1/*
2 * Copyright (c) 2020 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 *     http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15#include "client_factory.h"
16#include <ohos_errno.h>
17#include "registry.h"
18#include "memory_adapter.h"
19#include "thread_adapter.h"
20#include "default_client.h"
21
22typedef struct Factory Factory;
23struct Factory {
24    SaName key;
25    Creator creator;
26    Destroyer destroyer;
27};
28
29static Vector g_factories;
30static MutexId g_mutex;
31static Factory *GetFactory(const char *service, const char *feature);
32
33void *SAMGR_CreateIClient(const char *service, const char *feature, uint32 size)
34{
35    if (service == NULL) {
36        return NULL;
37    }
38
39    if (g_mutex == NULL) {
40        return NULL;
41    }
42
43    Factory *factory = GetFactory(service, feature);
44    if (factory == NULL) {
45        return NULL;
46    }
47
48    return factory->creator(service, feature, size);
49}
50
51int SAMGR_ReleaseIClient(const char *service, const char *feature, void *iClient)
52{
53    if (service == NULL || iClient == NULL) {
54        return EC_INVALID;
55    }
56
57    if (g_mutex == NULL) {
58        return EC_NOHANDLER;
59    }
60
61    Factory *factory = GetFactory(service, feature);
62    if (factory == NULL) {
63        return EC_NOHANDLER;
64    }
65    factory->destroyer(service, feature, iClient);
66    return EC_SUCCESS;
67}
68
69int SAMGR_RegisterFactory(const char *service, const char *feature, Creator creator, Destroyer destroyer)
70{
71    if (service == NULL || creator == NULL || destroyer == NULL) {
72        return EC_INVALID;
73    }
74
75    if (g_mutex == NULL) {
76        g_factories = VECTOR_Make(NULL, (VECTOR_Compare)SAMGR_CompareSAName);
77        g_mutex = MUTEX_InitValue();
78        if (g_mutex == NULL) {
79            return EC_NOMEMORY;
80        }
81    }
82
83    Factory *factory = GetFactory(service, feature);
84    if (factory != NULL) {
85        return EC_SUCCESS;
86    }
87
88    MUTEX_Lock(g_mutex);
89    factory = SAMGR_Malloc(sizeof(Factory));
90    if (factory == NULL) {
91        MUTEX_Unlock(g_mutex);
92        return EC_NOMEMORY;
93    }
94    factory->key.service = service;
95    factory->key.feature = feature;
96    factory->creator = creator;
97    factory->destroyer = destroyer;
98    int ret = VECTOR_Add(&g_factories, factory);
99    MUTEX_Unlock(g_mutex);
100    if (ret == INVALID_INDEX) {
101        SAMGR_Free(factory);
102        return EC_NOMEMORY;
103    }
104    return EC_SUCCESS;
105}
106
107static Factory *GetFactory(const char *service, const char *feature)
108{
109    SaName key = {service, feature};
110    Factory *factory = NULL;
111    MUTEX_Lock(g_mutex);
112    int16 index = VECTOR_FindByKey(&g_factories, &key);
113    if (index != INVALID_INDEX) {
114        factory = VECTOR_At(&g_factories, index);
115    }
116    MUTEX_Unlock(g_mutex);
117    return factory;
118}
119