1 /*
2 * Copyright (c) 2021 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 #include "generic_kvdb_connection.h"
17
18 #include <algorithm>
19
20 #include "log_print.h"
21 #include "db_constant.h"
22 #include "db_errno.h"
23 #include "generic_kvdb.h"
24 #include "kvdb_observer_handle.h"
25 #include "kvdb_commit_notify_filterable_data.h"
26
27 namespace DistributedDB {
GenericKvDBConnection(GenericKvDB * kvDB)28 GenericKvDBConnection::GenericKvDBConnection(GenericKvDB *kvDB)
29 : kvDB_(kvDB),
30 isExclusive_(false),
31 isSafeDeleted_(false)
32 {
33 }
34
~GenericKvDBConnection()35 GenericKvDBConnection::~GenericKvDBConnection()
36 {
37 if (!isSafeDeleted_) {
38 LOGF("The connection is deleted directly by user.");
39 }
40
41 for (auto &observer : observerList_) {
42 delete observer;
43 observer = nullptr;
44 }
45 }
46
RegisterObserverForOneType(int type,const Key & key,const KvDBObserverAction & action,NotificationChain::Listener * & listener)47 int GenericKvDBConnection::RegisterObserverForOneType(int type, const Key &key, const KvDBObserverAction &action,
48 NotificationChain::Listener *&listener)
49 {
50 if (kvDB_ == nullptr) {
51 return -E_INVALID_CONNECTION;
52 }
53 RegisterFuncType funcType = REGISTER_FUNC_TYPE_MAX;
54 int errCode = kvDB_->TransObserverTypeToRegisterFunctionType(type, funcType);
55 if (errCode != E_OK) {
56 return errCode;
57 }
58 errCode = kvDB_->RegisterFunction(funcType);
59 if (errCode != E_OK) {
60 return errCode;
61 }
62 listener = RegisterSpecialListener(type, key, action, false, errCode);
63 if (listener == nullptr) {
64 (void)(kvDB_->UnregisterFunction(funcType));
65 return errCode;
66 }
67 return E_OK;
68 }
69
RegisterObserver(unsigned mode,const Key & key,const KvDBObserverAction & action,int & errCode)70 KvDBObserverHandle *GenericKvDBConnection::RegisterObserver(unsigned mode,
71 const Key &key, const KvDBObserverAction &action, int &errCode)
72 {
73 if (!action || key.size() > DBConstant::MAX_KEY_SIZE) {
74 errCode = -E_INVALID_ARGS;
75 return nullptr;
76 }
77 std::list<int> eventTypes;
78 errCode = GetEventType(mode, eventTypes);
79 if (errCode != E_OK) {
80 return nullptr;
81 }
82
83 std::lock_guard<std::mutex> lockGuard(observerListLock_);
84 if (observerList_.size() >= MAX_OBSERVER_COUNT) {
85 errCode = -E_MAX_LIMITS;
86 LOGE("The number of observers has been larger than 'MAX_OBSERVER_COUNT'!");
87 return nullptr;
88 }
89 if (isExclusive_.load()) {
90 errCode = -E_BUSY;
91 return nullptr;
92 }
93 auto observerHandle = new (std::nothrow) KvDBObserverHandle(mode);
94 if (observerHandle == nullptr) {
95 errCode = -E_OUT_OF_MEMORY;
96 return nullptr;
97 }
98
99 std::list<NotificationChain::Listener *> listenerList;
100 for (const auto &type : eventTypes) {
101 NotificationChain::Listener *listenerObj = nullptr;
102 // Register function count in db is also protected by observer list lock.
103 errCode = RegisterObserverForOneType(type, key, action, listenerObj);
104 if (errCode != E_OK) {
105 for (auto &listener : listenerList) {
106 listener->Drop();
107 }
108 LOGE("Register observer failed, register listener failed, err:'%d'.", errCode);
109 delete observerHandle;
110 observerHandle = nullptr;
111 return nullptr;
112 }
113 listenerList.push_back(listenerObj);
114 }
115
116 for (auto &listener : listenerList) {
117 observerHandle->InsertListener(listener);
118 }
119 observerList_.push_back(observerHandle);
120 errCode = E_OK;
121 return observerHandle;
122 }
123
UnRegisterObserver(const KvDBObserverHandle * observerHandle)124 int GenericKvDBConnection::UnRegisterObserver(const KvDBObserverHandle *observerHandle)
125 {
126 if (observerHandle == nullptr) {
127 return -E_INVALID_ARGS;
128 }
129
130 if (kvDB_ == nullptr) {
131 return -E_INVALID_CONNECTION;
132 }
133
134 std::list<int> eventTypes;
135 int errCode = GetEventType(observerHandle->GetObserverMode(), eventTypes);
136 if (errCode != E_OK) {
137 return errCode;
138 }
139
140 {
141 std::lock_guard<std::mutex> lockGuard(observerListLock_);
142 auto observerIter = std::find(observerList_.begin(), observerList_.end(), observerHandle);
143 if (observerIter == observerList_.end()) {
144 LOGE("Unregister observer failed, no such entry.");
145 return -E_NO_SUCH_ENTRY;
146 }
147 observerList_.erase(observerIter);
148 // Register function count in db is also protected by observer list lock.
149 RegisterFuncType funcType = REGISTER_FUNC_TYPE_MAX;
150 for (auto type : eventTypes) {
151 errCode = kvDB_->TransObserverTypeToRegisterFunctionType(type, funcType);
152 if (errCode != E_OK) {
153 LOGE("Get register function type failed, err:'%d'.", errCode);
154 continue;
155 }
156 errCode = kvDB_->UnregisterFunction(funcType);
157 if (errCode != E_OK) {
158 LOGE("Unregister function failed, err:'%d'.", errCode);
159 continue;
160 }
161 }
162 }
163
164 delete observerHandle;
165 observerHandle = nullptr;
166 return E_OK;
167 }
168
SetConflictNotifier(int conflictType,const KvDBConflictAction & action)169 int GenericKvDBConnection::SetConflictNotifier(int conflictType, const KvDBConflictAction &action)
170 {
171 (void)conflictType;
172 (void)action;
173 return -E_NOT_SUPPORT;
174 }
175
Close()176 int GenericKvDBConnection::Close()
177 {
178 if (kvDB_ == nullptr) {
179 return -E_INVALID_CONNECTION;
180 }
181
182 if (isExclusive_.load()) {
183 return -E_BUSY;
184 }
185 if (kvDB_->IsDataMigrating()) {
186 return -E_BUSY;
187 }
188
189 int errCode = PreClose();
190 if (errCode != E_OK) {
191 LOGE("Close connection failed, err:'%d'.", errCode);
192 return errCode;
193 }
194 kvDB_->ReleaseDBConnection(this);
195 return E_OK;
196 }
197
GetIdentifier() const198 std::string GenericKvDBConnection::GetIdentifier() const
199 {
200 if (kvDB_ == nullptr) {
201 return "";
202 }
203 return kvDB_->GetMyProperties().GetStringProp(KvDBProperties::IDENTIFIER_DATA, "");
204 }
205
Pragma(int cmd,void * parameter)206 int GenericKvDBConnection::Pragma(int cmd, void *parameter)
207 {
208 (void)cmd;
209 (void)parameter;
210 return -E_NOT_SUPPORT;
211 }
212
PreClose()213 int GenericKvDBConnection::PreClose()
214 {
215 return E_OK;
216 }
217
SetSafeDeleted()218 void GenericKvDBConnection::SetSafeDeleted()
219 {
220 isSafeDeleted_ = true;
221 }
222
GetEntries(const IOption & option,const Key & keyPrefix,std::vector<Entry> & entries) const223 int GenericKvDBConnection::GetEntries(const IOption &option, const Key &keyPrefix, std::vector<Entry> &entries) const
224 {
225 (void)option;
226 (void)keyPrefix;
227 (void)entries;
228 return -E_NOT_SUPPORT;
229 }
230
GetEntries(const IOption & option,const Query & query,std::vector<Entry> & entries) const231 int GenericKvDBConnection::GetEntries(const IOption &option, const Query &query, std::vector<Entry> &entries) const
232 {
233 (void)option;
234 (void)query;
235 (void)entries;
236 return -E_NOT_SUPPORT;
237 }
238
GetResultSet(const IOption & option,const Key & keyPrefix,IKvDBResultSet * & resultSet) const239 int GenericKvDBConnection::GetResultSet(const IOption &option, const Key &keyPrefix, IKvDBResultSet *&resultSet) const
240 {
241 (void)option;
242 (void)keyPrefix;
243 (void)resultSet;
244 return -E_NOT_SUPPORT;
245 }
246
GetResultSet(const IOption & option,const Query & query,IKvDBResultSet * & resultSet) const247 int GenericKvDBConnection::GetResultSet(const IOption &option, const Query &query, IKvDBResultSet *&resultSet) const
248 {
249 (void)option;
250 (void)query;
251 (void)resultSet;
252 return -E_NOT_SUPPORT;
253 }
254
GetCount(const IOption & option,const Query & query,int & count) const255 int GenericKvDBConnection::GetCount(const IOption &option, const Query &query, int &count) const
256 {
257 (void)option;
258 (void)query;
259 (void)count;
260 return -E_NOT_SUPPORT;
261 }
262
ReleaseResultSet(IKvDBResultSet * & resultSet)263 void GenericKvDBConnection::ReleaseResultSet(IKvDBResultSet *&resultSet)
264 {
265 (void)resultSet;
266 return;
267 }
268
RegisterLifeCycleCallback(const DatabaseLifeCycleNotifier & notifier)269 int GenericKvDBConnection::RegisterLifeCycleCallback(const DatabaseLifeCycleNotifier ¬ifier)
270 {
271 (void)notifier;
272 return -E_NOT_SUPPORT;
273 }
274
GetSecurityOption(int & securityLabel,int & securityFlag) const275 int GenericKvDBConnection::GetSecurityOption(int &securityLabel, int &securityFlag) const
276 {
277 if (kvDB_ == nullptr) {
278 return -E_INVALID_CONNECTION;
279 }
280 securityLabel = kvDB_->GetMyProperties().GetIntProp(KvDBProperties::SECURITY_LABEL, 0);
281 securityFlag = kvDB_->GetMyProperties().GetIntProp(KvDBProperties::SECURITY_FLAG, 0);
282 return E_OK;
283 }
284
RegisterSpecialListener(int type,const Key & key,const KvDBObserverAction & action,bool conflict,int & errCode)285 NotificationChain::Listener *GenericKvDBConnection::RegisterSpecialListener(int type,
286 const Key &key, const KvDBObserverAction &action, bool conflict, int &errCode)
287 {
288 if (!action) {
289 errCode = -E_INVALID_ARGS;
290 return nullptr;
291 }
292
293 if (kvDB_ == nullptr) {
294 errCode = -E_INVALID_CONNECTION;
295 return nullptr;
296 }
297
298 uint64_t notifyBarrier = kvDB_->GetEventNotifyCounter();
299 return kvDB_->RegisterEventListener(static_cast<EventType>(type),
300 [key, action, conflict, notifyBarrier](void *ptr) {
301 if (ptr == nullptr) {
302 return;
303 }
304 KvDBCommitNotifyFilterAbleData *data = static_cast<KvDBCommitNotifyFilterAbleData *>(ptr);
305 if (data->GetNotifyID() <= notifyBarrier) {
306 return;
307 }
308 data->SetFilterKey(key);
309 if (conflict) {
310 if (!data->IsConflictedDataEmpty()) {
311 action(*data);
312 }
313 } else {
314 if (!data->IsChangedDataEmpty()) {
315 action(*data);
316 }
317 }
318 }, nullptr, errCode);
319 }
320
PreCheckExclusiveStatus()321 int GenericKvDBConnection::PreCheckExclusiveStatus()
322 {
323 std::lock_guard<std::mutex> lockGuard(observerListLock_);
324 if (observerList_.empty()) {
325 isExclusive_.store(true);
326 return E_OK;
327 }
328 return -E_BUSY;
329 }
330
ResetExclusiveStatus()331 void GenericKvDBConnection::ResetExclusiveStatus()
332 {
333 isExclusive_.store(false);
334 }
335
GetEventType(unsigned mode,std::list<int> & eventTypes) const336 int GenericKvDBConnection::GetEventType(unsigned mode, std::list<int> &eventTypes) const
337 {
338 if (kvDB_ == nullptr) {
339 return -E_INVALID_CONNECTION;
340 }
341
342 return TranslateObserverModeToEventTypes(mode, eventTypes);
343 }
344
CheckIntegrity() const345 int GenericKvDBConnection::CheckIntegrity() const
346 {
347 return E_OK;
348 }
349 }