1 /*
2 * Copyright (c) 2025 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
16 #define LOG_TAG "RdbObsManager"
17
18 #include "rdb_obs_manager.h"
19
20 #include <dlfcn.h>
21
22 #include "global_resource.h"
23 #include "logger.h"
24 #include "obs_mgr_adapter.h"
25 #include "rdb_errno.h"
26 #include "sqlite_utils.h"
27
28 namespace OHOS::NativeRdb {
29 using RdbStoreObserver = DistributedRdb::RdbStoreObserver;
30 using namespace OHOS::Rdb;
31 std::mutex RdbObsManager::mutex_;
32 RdbObsManager::ObsAPIInfo RdbObsManager::apiInfo_;
33 void *RdbObsManager::handle_ = nullptr;
~RdbObsManager()34 RdbObsManager::~RdbObsManager()
35 {
36 if (obs_.Empty()) {
37 return;
38 }
39 auto handle = GetApiInfo();
40 if (handle.unregisterFunc == nullptr) {
41 LOG_ERROR("dlsym(Unregister) failed");
42 return;
43 }
44 obs_.ForEach([handle](const auto &key, auto &value) {
45 for (auto &obs : value) {
46 handle.unregisterFunc(key, obs);
47 }
48 return false;
49 });
50 }
51
GetApiInfo()52 RdbObsManager::ObsAPIInfo RdbObsManager::GetApiInfo()
53 {
54 std::lock_guard<decltype(mutex_)> lock(mutex_);
55 if (handle_ != nullptr) {
56 return apiInfo_;
57 }
58 handle_ = dlopen("librdb_obs_mgr_adapter.z.so", RTLD_LAZY);
59 if (handle_ == nullptr) {
60 LOG_ERROR("dlopen(librdb_obs_mgr_adapter) failed(%{public}d)!", errno);
61 return apiInfo_;
62 }
63 GlobalResource::RegisterClean(GlobalResource::OBS, CleanUp);
64 apiInfo_.registerFunc = reinterpret_cast<RegisterFunc>(dlsym(handle_, "Register"));
65 apiInfo_.unregisterFunc = reinterpret_cast<UnregisterFunc>(dlsym(handle_, "Unregister"));
66 apiInfo_.notifyFunc = reinterpret_cast<NotifyFunc>(dlsym(handle_, "NotifyChange"));
67 apiInfo_.cleanFunc = reinterpret_cast<CleanFunc>(dlsym(handle_, "CleanUp"));
68 return apiInfo_;
69 }
70
CleanUp()71 int32_t RdbObsManager::CleanUp()
72 {
73 auto handle = GetApiInfo();
74 if (handle.cleanFunc == nullptr) {
75 LOG_ERROR("dlsym(CleanUp) fail!");
76 return E_ERROR;
77 }
78 if (!handle.cleanFunc()) {
79 return E_ERROR;
80 }
81 std::lock_guard<decltype(mutex_)> lock(mutex_);
82 dlclose(handle_);
83 handle_ = nullptr;
84 apiInfo_.registerFunc = nullptr;
85 apiInfo_.unregisterFunc = nullptr;
86 apiInfo_.notifyFunc = nullptr;
87 apiInfo_.cleanFunc = nullptr;
88 return E_OK;
89 }
90
Register(const std::string & uri,std::shared_ptr<RdbStoreObserver> obs)91 int32_t RdbObsManager::Register(const std::string &uri, std::shared_ptr<RdbStoreObserver> obs)
92 {
93 auto handle = GetApiInfo();
94 if (handle.registerFunc == nullptr) {
95 LOG_ERROR("dlsym(Register) fail!, uri:%{public}s", SqliteUtils::Anonymous(uri).c_str());
96 return E_ERROR;
97 }
98 auto code = handle.registerFunc(uri, obs);
99 if (code == E_OK) {
100 obs_.Compute(uri, [obs](const auto &key, auto &value) {
101 value.push_back(obs);
102 return !value.empty();
103 });
104 return E_OK;
105 }
106 return code == RDB_OBS_DUPLICATE_SUB ? E_OK : code;
107 }
108
Unregister(const std::string & uri,std::shared_ptr<RdbStoreObserver> obs)109 int32_t RdbObsManager::Unregister(const std::string &uri, std::shared_ptr<RdbStoreObserver> obs)
110 {
111 auto handle = GetApiInfo();
112 if (handle.unregisterFunc == nullptr) {
113 LOG_ERROR("dlsym(Unregister) fail!, uri:%{public}s", SqliteUtils::Anonymous(uri).c_str());
114 return E_ERROR;
115 }
116 auto code = handle.unregisterFunc(uri, obs);
117 if (code != E_OK) {
118 return code;
119 }
120 obs_.Compute(uri, [obs](const auto &key, auto &value) {
121 if (obs == nullptr) {
122 value.clear();
123 }
124 for (auto it = value.begin(); it != value.end();) {
125 if (*it == obs) {
126 value.erase(it);
127 break;
128 }
129 ++it;
130 }
131 return !value.empty();
132 });
133 return code;
134 }
135
Notify(const std::string & uri)136 int32_t RdbObsManager::Notify(const std::string &uri)
137 {
138 auto handle = GetApiInfo();
139 if (handle.notifyFunc == nullptr) {
140 LOG_ERROR("dlsym(NotifyChange) fail! uri:%{public}s", SqliteUtils::Anonymous(uri).c_str());
141 return E_ERROR;
142 }
143 return handle.notifyFunc(uri);
144 }
145
146 } // namespace OHOS::NativeRdb