• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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