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 isRebuild_(false)
33 {
34 }
35
~GenericKvDBConnection()36 GenericKvDBConnection::~GenericKvDBConnection()
37 {
38 if (!isSafeDeleted_) {
39 LOGF("The connection is deleted directly by user.");
40 }
41
42 for (auto &observer : observerList_) {
43 delete observer;
44 observer = nullptr;
45 }
46 }
47
RegisterObserverForOneType(int type,const Key & key,const KvDBObserverAction & action,NotificationChain::Listener * & listener)48 int GenericKvDBConnection::RegisterObserverForOneType(int type, const Key &key, const KvDBObserverAction &action,
49 NotificationChain::Listener *&listener)
50 {
51 if (kvDB_ == nullptr) {
52 return -E_INVALID_CONNECTION;
53 }
54 RegisterFuncType funcType = RegisterFuncType::REGISTER_FUNC_TYPE_MAX;
55 int errCode = kvDB_->TransObserverTypeToRegisterFunctionType(type, funcType);
56 if (errCode != E_OK) {
57 return errCode;
58 }
59 errCode = kvDB_->RegisterFunction(funcType);
60 if (errCode != E_OK) {
61 return errCode;
62 }
63 listener = RegisterSpecialListener(type, key, action, false, errCode);
64 if (listener == nullptr) {
65 (void)(kvDB_->UnregisterFunction(funcType));
66 return errCode;
67 }
68 return E_OK;
69 }
70
RegisterObserver(unsigned mode,const Key & key,const KvDBObserverAction & action,int & errCode)71 KvDBObserverHandle *GenericKvDBConnection::RegisterObserver(unsigned mode,
72 const Key &key, const KvDBObserverAction &action, int &errCode)
73 {
74 if (!action || key.size() > DBConstant::MAX_KEY_SIZE) {
75 errCode = -E_INVALID_ARGS;
76 return nullptr;
77 }
78 std::list<int> eventTypes;
79 errCode = GetEventType(mode, eventTypes);
80 if (errCode != E_OK) {
81 return nullptr;
82 }
83
84 std::lock_guard<std::mutex> lockGuard(observerListLock_);
85 if (observerList_.size() >= DBConstant::MAX_OBSERVER_COUNT) {
86 errCode = -E_MAX_LIMITS;
87 LOGE("The number of observers has been larger than 'MAX_OBSERVER_COUNT'!");
88 return nullptr;
89 }
90 if (isExclusive_.load()) {
91 errCode = -E_BUSY;
92 LOGE("Observer is exclusived %d", errCode);
93 return nullptr;
94 }
95 auto observerHandle = new (std::nothrow) KvDBObserverHandle(mode);
96 if (observerHandle == nullptr) {
97 errCode = -E_OUT_OF_MEMORY;
98 return nullptr;
99 }
100
101 std::list<NotificationChain::Listener *> listenerList;
102 for (const auto &type : eventTypes) {
103 NotificationChain::Listener *listenerObj = nullptr;
104 // Register function count in db is also protected by observer list lock.
105 errCode = RegisterObserverForOneType(type, key, action, listenerObj);
106 if (errCode != E_OK) {
107 for (auto &listener : listenerList) {
108 listener->Drop();
109 }
110 LOGE("Register observer failed, register listener failed, err:'%d'.", errCode);
111 delete observerHandle;
112 observerHandle = nullptr;
113 return nullptr;
114 }
115 listenerList.push_back(listenerObj);
116 }
117
118 for (auto &listener : listenerList) {
119 observerHandle->InsertListener(listener);
120 }
121 observerList_.push_back(observerHandle);
122 errCode = E_OK;
123 return observerHandle;
124 }
125
UnRegisterObserver(const KvDBObserverHandle * observerHandle)126 int GenericKvDBConnection::UnRegisterObserver(const KvDBObserverHandle *observerHandle)
127 {
128 if (observerHandle == nullptr) {
129 return -E_INVALID_ARGS;
130 }
131
132 if (kvDB_ == nullptr) {
133 return -E_INVALID_CONNECTION;
134 }
135
136 std::list<int> eventTypes;
137 int errCode = GetEventType(observerHandle->GetObserverMode(), eventTypes);
138 if (errCode != E_OK) {
139 return errCode;
140 }
141
142 {
143 std::lock_guard<std::mutex> lockGuard(observerListLock_);
144 auto observerIter = std::find(observerList_.begin(), observerList_.end(), observerHandle);
145 if (observerIter == observerList_.end()) {
146 LOGE("Unregister observer failed, no such entry.");
147 return -E_NO_SUCH_ENTRY;
148 }
149 observerList_.erase(observerIter);
150 // Register function count in db is also protected by observer list lock.
151 RegisterFuncType funcType = RegisterFuncType::REGISTER_FUNC_TYPE_MAX;
152 for (auto type : eventTypes) {
153 errCode = kvDB_->TransObserverTypeToRegisterFunctionType(type, funcType);
154 if (errCode != E_OK) {
155 LOGE("Get register function type failed, err:'%d'.", errCode);
156 continue;
157 }
158 errCode = kvDB_->UnregisterFunction(funcType);
159 if (errCode != E_OK) {
160 LOGE("Unregister function failed, err:'%d'.", errCode);
161 continue;
162 }
163 }
164 }
165
166 delete observerHandle;
167 observerHandle = nullptr;
168 return E_OK;
169 }
170
SetConflictNotifier(int conflictType,const KvDBConflictAction & action)171 int GenericKvDBConnection::SetConflictNotifier(int conflictType, const KvDBConflictAction &action)
172 {
173 (void)conflictType;
174 (void)action;
175 return -E_NOT_SUPPORT;
176 }
177
Close()178 int GenericKvDBConnection::Close()
179 {
180 if (kvDB_ == nullptr) {
181 return -E_INVALID_CONNECTION;
182 }
183
184 if (isExclusive_.load()) {
185 LOGE("Current connection is occupied by other connection");
186 return -E_BUSY;
187 }
188 if (kvDB_->IsDataMigrating()) {
189 LOGE("Data is migrating");
190 return -E_BUSY;
191 }
192
193 int errCode = PreClose();
194 if (errCode != E_OK) {
195 LOGE("Close connection failed, err:'%d'.", errCode);
196 return errCode;
197 }
198 kvDB_->ReleaseDBConnection(this);
199 return E_OK;
200 }
201
GetIdentifier() const202 std::string GenericKvDBConnection::GetIdentifier() const
203 {
204 if (kvDB_ == nullptr) {
205 return "";
206 }
207 return kvDB_->GetMyProperties().GetStringProp(KvDBProperties::IDENTIFIER_DATA, "");
208 }
209
Pragma(int cmd,void * parameter)210 int GenericKvDBConnection::Pragma(int cmd, void *parameter)
211 {
212 (void)cmd;
213 (void)parameter;
214 return -E_NOT_SUPPORT;
215 }
216
PreClose()217 int GenericKvDBConnection::PreClose()
218 {
219 return E_OK;
220 }
221
SetSafeDeleted()222 void GenericKvDBConnection::SetSafeDeleted()
223 {
224 isSafeDeleted_ = true;
225 }
226
GetEntries(const IOption & option,const Key & keyPrefix,std::vector<Entry> & entries) const227 int GenericKvDBConnection::GetEntries(const IOption &option, const Key &keyPrefix, std::vector<Entry> &entries) const
228 {
229 (void)option;
230 (void)keyPrefix;
231 (void)entries;
232 return -E_NOT_SUPPORT;
233 }
234
GetEntries(const IOption & option,const Query & query,std::vector<Entry> & entries) const235 int GenericKvDBConnection::GetEntries(const IOption &option, const Query &query, std::vector<Entry> &entries) const
236 {
237 (void)option;
238 (void)query;
239 (void)entries;
240 return -E_NOT_SUPPORT;
241 }
242
GetResultSet(const IOption & option,const Key & keyPrefix,IKvDBResultSet * & resultSet) const243 int GenericKvDBConnection::GetResultSet(const IOption &option, const Key &keyPrefix, IKvDBResultSet *&resultSet) const
244 {
245 (void)option;
246 (void)keyPrefix;
247 (void)resultSet;
248 return -E_NOT_SUPPORT;
249 }
250
GetResultSet(const IOption & option,const Query & query,IKvDBResultSet * & resultSet) const251 int GenericKvDBConnection::GetResultSet(const IOption &option, const Query &query, IKvDBResultSet *&resultSet) const
252 {
253 (void)option;
254 (void)query;
255 (void)resultSet;
256 return -E_NOT_SUPPORT;
257 }
258
GetCount(const IOption & option,const Query & query,int & count) const259 int GenericKvDBConnection::GetCount(const IOption &option, const Query &query, int &count) const
260 {
261 (void)option;
262 (void)query;
263 (void)count;
264 return -E_NOT_SUPPORT;
265 }
266
ReleaseResultSet(IKvDBResultSet * & resultSet)267 void GenericKvDBConnection::ReleaseResultSet(IKvDBResultSet *&resultSet)
268 {
269 (void)resultSet;
270 return;
271 }
272
RegisterLifeCycleCallback(const DatabaseLifeCycleNotifier & notifier)273 int GenericKvDBConnection::RegisterLifeCycleCallback(const DatabaseLifeCycleNotifier ¬ifier)
274 {
275 (void)notifier;
276 return -E_NOT_SUPPORT;
277 }
278
GetSecurityOption(int & securityLabel,int & securityFlag) const279 int GenericKvDBConnection::GetSecurityOption(int &securityLabel, int &securityFlag) const
280 {
281 if (kvDB_ == nullptr) {
282 return -E_INVALID_CONNECTION;
283 }
284 securityLabel = kvDB_->GetMyProperties().GetIntProp(KvDBProperties::SECURITY_LABEL, 0);
285 securityFlag = kvDB_->GetMyProperties().GetIntProp(KvDBProperties::SECURITY_FLAG, 0);
286 return E_OK;
287 }
288
RegisterSpecialListener(int type,const Key & key,const KvDBObserverAction & action,bool conflict,int & errCode)289 NotificationChain::Listener *GenericKvDBConnection::RegisterSpecialListener(int type,
290 const Key &key, const KvDBObserverAction &action, bool conflict, int &errCode)
291 {
292 if (!action) {
293 errCode = -E_INVALID_ARGS;
294 return nullptr;
295 }
296
297 if (kvDB_ == nullptr) {
298 errCode = -E_INVALID_CONNECTION;
299 return nullptr;
300 }
301
302 uint64_t notifyBarrier = kvDB_->GetEventNotifyCounter();
303 return kvDB_->RegisterEventListener(static_cast<EventType>(type),
304 [key, action, conflict, notifyBarrier](void *ptr) {
305 if (ptr == nullptr) {
306 return;
307 }
308 KvDBCommitNotifyFilterAbleData *data = static_cast<KvDBCommitNotifyFilterAbleData *>(ptr);
309 if (data->GetNotifyID() <= notifyBarrier) {
310 return;
311 }
312 data->SetFilterKey(key);
313 if (conflict) {
314 if (!data->IsConflictedDataEmpty()) {
315 action(*data);
316 }
317 } else {
318 if (!data->IsChangedDataEmpty()) {
319 action(*data);
320 }
321 }
322 }, nullptr, errCode);
323 }
324
PreCheckExclusiveStatus()325 int GenericKvDBConnection::PreCheckExclusiveStatus()
326 {
327 std::lock_guard<std::mutex> lockGuard(observerListLock_);
328 if (observerList_.empty()) {
329 isExclusive_.store(true);
330 return E_OK;
331 }
332 return -E_BUSY;
333 }
334
ResetExclusiveStatus()335 void GenericKvDBConnection::ResetExclusiveStatus()
336 {
337 isExclusive_.store(false);
338 }
339
GetEventType(unsigned mode,std::list<int> & eventTypes) const340 int GenericKvDBConnection::GetEventType(unsigned mode, std::list<int> &eventTypes) const
341 {
342 if (kvDB_ == nullptr) {
343 return -E_INVALID_CONNECTION;
344 }
345
346 return TranslateObserverModeToEventTypes(mode, eventTypes);
347 }
348
CheckIntegrity() const349 int GenericKvDBConnection::CheckIntegrity() const
350 {
351 return E_OK;
352 }
353
GetKeys(const IOption & option,const Key & keyPrefix,std::vector<Key> & keys) const354 int GenericKvDBConnection::GetKeys(const IOption &option, const Key &keyPrefix, std::vector<Key> &keys) const
355 {
356 return -E_NOT_SUPPORT;
357 }
358
GetSyncDataSize(const std::string & device,size_t & size) const359 int GenericKvDBConnection::GetSyncDataSize(const std::string &device, size_t &size) const
360 {
361 return -E_NOT_SUPPORT;
362 }
363
UpdateKey(const UpdateKeyCallback & callback)364 int GenericKvDBConnection::UpdateKey(const UpdateKeyCallback &callback)
365 {
366 return -E_NOT_SUPPORT;
367 }
368
369 int GenericKvDBConnection::GetWatermarkInfo([[gnu::unused]] const std::string &device,
370 [[gnu::unused]] WatermarkInfo &info)
371 {
372 return -E_NOT_SUPPORT;
373 }
374
IsObserverEmpty()375 bool GenericKvDBConnection::IsObserverEmpty()
376 {
377 std::lock_guard<std::mutex> lockGuard(observerListLock_);
378 return observerList_.empty();
379 }
380
381 int GenericKvDBConnection::Sync([[gnu::unused]] const CloudSyncOption &option,
382 [[gnu::unused]] const SyncProcessCallback &onProcess)
383 {
384 return -E_NOT_SUPPORT;
385 }
386
387 int GenericKvDBConnection::SetCloudDB([[gnu::unused]] const std::map<std::string, std::shared_ptr<ICloudDb>> &cloudDBs)
388 {
389 return -E_NOT_SUPPORT;
390 }
391
392 int GenericKvDBConnection::SetCloudDbSchema([[gnu::unused]] const std::map<std::string, DataBaseSchema> &schema)
393 {
394 return -E_NOT_SUPPORT;
395 }
396
397 int GenericKvDBConnection::RemoveDeviceData([[gnu::unused]] const std::string &device, [[gnu::unused]] ClearMode mode)
398 {
399 return -E_NOT_SUPPORT;
400 }
401
402 int GenericKvDBConnection::RemoveDeviceData([[gnu::unused]] const std::string &device,
403 [[gnu::unused]] const std::string &user, [[gnu::unused]] ClearMode mode)\
404 {
405 return -E_NOT_SUPPORT;
406 }
407
GetTaskCount()408 int32_t GenericKvDBConnection::GetTaskCount()
409 {
410 return 0;
411 }
412
413 int GenericKvDBConnection::RegisterObserverAction([[gnu::unused]] const KvStoreObserver *observer,
414 [[gnu::unused]] const ObserverAction &action)
415 {
416 return E_OK;
417 }
418
419 int GenericKvDBConnection::UnRegisterObserverAction([[gnu::unused]] const KvStoreObserver *observer)
420 {
421 return E_OK;
422 }
423
SetGenCloudVersionCallback(const GenerateCloudVersionCallback & callback)424 void GenericKvDBConnection::SetGenCloudVersionCallback(const GenerateCloudVersionCallback &callback)
425 {
426 (void)callback;
427 return;
428 }
429
GetCloudVersion(const std::string & device,std::map<std::string,std::string> & versionMap)430 int GenericKvDBConnection::GetCloudVersion(const std::string &device, std::map<std::string, std::string> &versionMap)
431 {
432 return -E_NOT_SUPPORT;
433 }
434
SetReceiveDataInterceptor(const DataInterceptor & interceptor)435 int GenericKvDBConnection::SetReceiveDataInterceptor(const DataInterceptor &interceptor)
436 {
437 return -E_NOT_SUPPORT;
438 }
439
SetCloudSyncConfig(const CloudSyncConfig & config)440 int GenericKvDBConnection::SetCloudSyncConfig(const CloudSyncConfig &config)
441 {
442 return -E_NOT_SUPPORT;
443 }
444
GetEntries(const std::string & device,std::vector<Entry> & entries) const445 int GenericKvDBConnection::GetEntries(const std::string &device, std::vector<Entry> &entries) const
446 {
447 return -E_NOT_SUPPORT;
448 }
449
MarkRebuild()450 void GenericKvDBConnection::MarkRebuild()
451 {
452 isRebuild_ = true;
453 }
454
IsRebuild() const455 bool GenericKvDBConnection::IsRebuild() const
456 {
457 return isRebuild_;
458 }
459 }