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 #ifndef OMIT_MULTI_VER
17 #include "kv_store_delegate_impl.h"
18
19 #include <functional>
20 #include <string>
21
22 #include "platform_specific.h"
23 #include "log_print.h"
24 #include "param_check_utils.h"
25 #include "db_constant.h"
26 #include "db_errno.h"
27 #include "db_types.h"
28 #include "kv_store_errno.h"
29 #include "kvdb_pragma.h"
30 #include "kv_store_observer.h"
31 #include "kvdb_manager.h"
32 #include "kv_store_snapshot_delegate_impl.h"
33 #include "kv_store_changed_data_impl.h"
34
35 namespace DistributedDB {
36 namespace {
37 const std::string INVALID_CONNECTION = "[KvStoreDelegate] Invalid connection for operation";
38 }
KvStoreDelegateImpl(IKvDBConnection * conn,const std::string & storeId)39 KvStoreDelegateImpl::KvStoreDelegateImpl(IKvDBConnection *conn, const std::string &storeId)
40 : conn_(conn),
41 storeId_(storeId),
42 releaseFlag_(false)
43 {}
44
~KvStoreDelegateImpl()45 KvStoreDelegateImpl::~KvStoreDelegateImpl()
46 {
47 if (!releaseFlag_) {
48 LOGF("[KvStoreDelegate] can not release object directly");
49 return;
50 }
51
52 LOGI("[KvStoreDelegate] deconstruct");
53 conn_ = nullptr;
54 }
55
Put(const Key & key,const Value & value)56 DBStatus KvStoreDelegateImpl::Put(const Key &key, const Value &value)
57 {
58 if (conn_ != nullptr) {
59 IOption option;
60 int errCode = conn_->Put(option, key, value);
61 if (errCode == E_OK) {
62 return OK;
63 }
64
65 LOGE("[KvStoreDelegate] Put data failed:%d", errCode);
66 return TransferDBErrno(errCode);
67 }
68
69 LOGE("%s", INVALID_CONNECTION.c_str());
70 return DB_ERROR;
71 }
72
PutBatch(const std::vector<Entry> & entries)73 DBStatus KvStoreDelegateImpl::PutBatch(const std::vector<Entry> &entries)
74 {
75 if (conn_ != nullptr) {
76 IOption option;
77 int errCode = conn_->PutBatch(option, entries);
78 if (errCode == E_OK) {
79 return OK;
80 }
81
82 LOGE("[KvStoreDelegate] Put batch data failed:%d", errCode);
83 return TransferDBErrno(errCode);
84 }
85
86 LOGE("%s", INVALID_CONNECTION.c_str());
87 return DB_ERROR;
88 }
89
Delete(const Key & key)90 DBStatus KvStoreDelegateImpl::Delete(const Key &key)
91 {
92 if (conn_ != nullptr) {
93 IOption option;
94 int errCode = conn_->Delete(option, key);
95 if (errCode == E_OK || errCode == -E_NOT_FOUND) {
96 return OK;
97 }
98
99 LOGE("[KvStoreDelegate] Delete data failed:%d", errCode);
100 return TransferDBErrno(errCode);
101 }
102
103 LOGE("%s", INVALID_CONNECTION.c_str());
104 return DB_ERROR;
105 }
106
DeleteBatch(const std::vector<Key> & keys)107 DBStatus KvStoreDelegateImpl::DeleteBatch(const std::vector<Key> &keys)
108 {
109 if (conn_ != nullptr) {
110 IOption option;
111 int errCode = conn_->DeleteBatch(option, keys);
112 if (errCode == E_OK || errCode == -E_NOT_FOUND) {
113 return OK;
114 }
115
116 LOGE("[KvStoreDelegate] Delete batch data failed:%d", errCode);
117 return TransferDBErrno(errCode);
118 }
119
120 LOGE("%s", INVALID_CONNECTION.c_str());
121 return DB_ERROR;
122 }
123
Clear()124 DBStatus KvStoreDelegateImpl::Clear()
125 {
126 if (conn_ != nullptr) {
127 IOption option;
128 int errCode = conn_->Clear(option);
129 if (errCode == E_OK) {
130 return OK;
131 }
132
133 LOGE("[KvStoreDelegate] Clear data failed:%d", errCode);
134 return TransferDBErrno(errCode);
135 }
136
137 LOGE("%s", INVALID_CONNECTION.c_str());
138 return DB_ERROR;
139 }
140
GetStoreId() const141 std::string KvStoreDelegateImpl::GetStoreId() const
142 {
143 return storeId_;
144 }
145
GetKvStoreSnapshot(KvStoreObserver * observer,const std::function<void (DBStatus,KvStoreSnapshotDelegate *)> & callback)146 void KvStoreDelegateImpl::GetKvStoreSnapshot(KvStoreObserver *observer,
147 const std::function<void(DBStatus, KvStoreSnapshotDelegate *)> &callback)
148 {
149 if (!callback) {
150 LOGE("[KvStoreDelegate] Invalid callback for snapshot!");
151 return;
152 }
153
154 if (conn_ != nullptr) {
155 if (observer != nullptr && RegisterObserver(observer) != E_OK) {
156 LOGE("[KvStoreDelegate][GetSnapshot] Register observer failed!");
157 callback(DB_ERROR, nullptr);
158 return;
159 }
160
161 IKvDBSnapshot *snapshot = nullptr;
162 int errCode = conn_->GetSnapshot(snapshot);
163 if (errCode == E_OK) {
164 auto snapshotDelegate = new (std::nothrow) KvStoreSnapshotDelegateImpl(snapshot, observer);
165 if (snapshotDelegate != nullptr) {
166 callback(OK, snapshotDelegate);
167 return;
168 }
169 conn_->ReleaseSnapshot(snapshot);
170 snapshot = nullptr;
171 }
172
173 // UnRegister the registered observer.
174 errCode = UnRegisterObserver(observer);
175 if (errCode != E_OK) {
176 LOGE("[KvStoreDelegate][GetSnapshot] UnRegister observer failed:%d!", errCode);
177 }
178 }
179
180 LOGE("%s", INVALID_CONNECTION.c_str());
181 callback(DB_ERROR, nullptr);
182 }
183
ReleaseKvStoreSnapshot(KvStoreSnapshotDelegate * & snapshotDelegate)184 DBStatus KvStoreDelegateImpl::ReleaseKvStoreSnapshot(KvStoreSnapshotDelegate *&snapshotDelegate)
185 {
186 if (conn_ != nullptr && snapshotDelegate != nullptr) {
187 KvStoreObserver *observer = nullptr;
188 (static_cast<KvStoreSnapshotDelegateImpl *>(snapshotDelegate))->GetObserver(observer);
189 if (observer != nullptr && UnRegisterObserver(observer) != E_OK) {
190 LOGE("[KvStoreDelegate][ReleaseSnapshot] UnRegistObserver failed!");
191 return DB_ERROR;
192 }
193
194 IKvDBSnapshot *snapshot = nullptr;
195 (static_cast<KvStoreSnapshotDelegateImpl *>(snapshotDelegate))->GetSnapshot(snapshot);
196 conn_->ReleaseSnapshot(snapshot);
197 snapshot = nullptr;
198 delete snapshotDelegate;
199 snapshotDelegate = nullptr;
200 return OK;
201 }
202
203 return DB_ERROR;
204 }
205
RegisterObserver(KvStoreObserver * observer)206 DBStatus KvStoreDelegateImpl::RegisterObserver(KvStoreObserver *observer)
207 {
208 if (observer == nullptr) {
209 return INVALID_ARGS;
210 }
211
212 if (conn_ == nullptr) {
213 LOGE("%s", INVALID_CONNECTION.c_str());
214 return DB_ERROR;
215 }
216
217 std::lock_guard<std::mutex> lockGuard(observerMapLock_);
218 if (observerMap_.find(observer) != observerMap_.end()) {
219 LOGE("[KvStoreDelegate] Observer has been already registered!");
220 return DB_ERROR;
221 }
222
223 Key key;
224 int errCode = E_OK;
225 KvDBObserverHandle *observerHandle = conn_->RegisterObserver(
226 static_cast<unsigned int>(DATABASE_COMMIT_EVENT),
227 key,
228 [observer](const KvDBCommitNotifyData &ptr) {
229 KvStoreChangedDataImpl data(&ptr);
230 observer->OnChange(data);
231 },
232 errCode);
233
234 if (errCode != E_OK || observerHandle == nullptr) {
235 LOGE("[KvStoreDelegate] Register listener failed:%d!", errCode);
236 return DB_ERROR;
237 }
238
239 observerMap_.insert(std::pair<const KvStoreObserver *, const KvDBObserverHandle *>(observer, observerHandle));
240 return OK;
241 }
242
243 // Unregister a data change observer
UnRegisterObserver(const KvStoreObserver * observer)244 DBStatus KvStoreDelegateImpl::UnRegisterObserver(const KvStoreObserver *observer)
245 {
246 if (observer == nullptr) {
247 return INVALID_ARGS;
248 }
249
250 if (conn_ == nullptr) {
251 LOGE("%s", INVALID_CONNECTION.c_str());
252 return DB_ERROR;
253 }
254
255 std::lock_guard<std::mutex> lockGuard(observerMapLock_);
256 auto iter = observerMap_.find(observer);
257 if (iter == observerMap_.end()) {
258 LOGE("[KvStoreDelegate] observer has not been registered!");
259 return NOT_FOUND;
260 }
261
262 const KvDBObserverHandle *observerHandle = iter->second;
263 int errCode = conn_->UnRegisterObserver(observerHandle);
264 if (errCode != E_OK) {
265 LOGE("[KvStoreDelegate] UnRegister observer failed:%d!", errCode);
266 return DB_ERROR;
267 }
268 observerMap_.erase(iter);
269 return OK;
270 }
271
StartTransaction()272 DBStatus KvStoreDelegateImpl::StartTransaction()
273 {
274 if (conn_ == nullptr) {
275 LOGE("%s", INVALID_CONNECTION.c_str());
276 return DB_ERROR;
277 }
278
279 int errCode = conn_->StartTransaction();
280 if (errCode != E_OK) {
281 LOGE("[KvStoreDelegate] StartTransaction failed:%d", errCode);
282 return TransferDBErrno(errCode);
283 }
284 return OK;
285 }
286
Commit()287 DBStatus KvStoreDelegateImpl::Commit()
288 {
289 if (conn_ == nullptr) {
290 LOGE("%s", INVALID_CONNECTION.c_str());
291 return DB_ERROR;
292 }
293
294 int errCode = conn_->Commit();
295 if (errCode != E_OK) {
296 LOGE("[KvStoreDelegate] Commit failed:%d", errCode);
297 return TransferDBErrno(errCode);
298 }
299 return OK;
300 }
301
Rollback()302 DBStatus KvStoreDelegateImpl::Rollback()
303 {
304 if (conn_ == nullptr) {
305 LOGE("%s", INVALID_CONNECTION.c_str());
306 return DB_ERROR;
307 }
308
309 int errCode = conn_->RollBack();
310 if (errCode != E_OK) {
311 LOGE("[KvStoreDelegate] Rollback failed:%d", errCode);
312 return TransferDBErrno(errCode);
313 }
314 return OK;
315 }
316
SetConflictResolutionPolicy(ResolutionPolicyType type,const ConflictResolution & resolution)317 DBStatus KvStoreDelegateImpl::SetConflictResolutionPolicy(ResolutionPolicyType type,
318 const ConflictResolution &resolution)
319 {
320 if (type == AUTO_LAST_WIN) {
321 return OK;
322 }
323
324 if (type == CUSTOMER_RESOLUTION && resolution != nullptr) {
325 return OK;
326 }
327 LOGE("[KvStoreDelegate] Invalid conflict resolution policy:%d", type);
328 return DB_ERROR;
329 }
330
Rekey(const CipherPassword & password)331 DBStatus KvStoreDelegateImpl::Rekey(const CipherPassword &password)
332 {
333 if (conn_ != nullptr) {
334 int errCode = conn_->Rekey(password);
335 if (errCode == E_OK) {
336 return OK;
337 }
338
339 LOGE("[KvStoreDelegate] rekey failed:%d", errCode);
340 return TransferDBErrno(errCode);
341 }
342
343 LOGE("%s", INVALID_CONNECTION.c_str());
344 return DB_ERROR;
345 }
346
Export(const std::string & filePath,const CipherPassword & passwd)347 DBStatus KvStoreDelegateImpl::Export(const std::string &filePath, const CipherPassword &passwd)
348 {
349 std::string fileDir;
350 std::string fileName;
351 OS::SplitFilePath(filePath, fileDir, fileName);
352
353 std::string canonicalUrl;
354 if (!ParamCheckUtils::CheckDataDir(fileDir, canonicalUrl)) {
355 return INVALID_ARGS;
356 }
357
358 if (!OS::CheckPathExistence(canonicalUrl)) {
359 return NO_PERMISSION;
360 }
361
362 canonicalUrl = canonicalUrl + "/" + fileName;
363 if (OS::CheckPathExistence(canonicalUrl)) {
364 LOGE("[KvStoreDelegate] The exported file has already been existed");
365 return FILE_ALREADY_EXISTED;
366 }
367
368 if (conn_ != nullptr) {
369 int errCode = conn_->Export(canonicalUrl, passwd);
370 if (errCode == E_OK) {
371 return OK;
372 }
373 LOGE("[KvStoreDelegate] Export failed:%d", errCode);
374 return TransferDBErrno(errCode);
375 }
376
377 LOGE("%s", INVALID_CONNECTION.c_str());
378 return DB_ERROR;
379 }
380
Import(const std::string & filePath,const CipherPassword & passwd)381 DBStatus KvStoreDelegateImpl::Import(const std::string &filePath, const CipherPassword &passwd)
382 {
383 std::string fileDir;
384 std::string fileName;
385 OS::SplitFilePath(filePath, fileDir, fileName);
386
387 std::string canonicalUrl;
388 if (!ParamCheckUtils::CheckDataDir(fileDir, canonicalUrl)) {
389 return INVALID_ARGS;
390 }
391
392 canonicalUrl = canonicalUrl + "/" + fileName;
393 if (!OS::CheckPathExistence(canonicalUrl)) {
394 LOGE("[KvStoreDelegate] The imported file not existed:%d", errno);
395 return INVALID_FILE;
396 }
397
398 if (conn_ != nullptr) {
399 int errCode = conn_->Import(canonicalUrl, passwd);
400 if (errCode == E_OK) {
401 return OK;
402 }
403 LOGE("[KvStoreDelegate] Import failed:%d", errCode);
404 return TransferDBErrno(errCode);
405 }
406
407 LOGE("%s", INVALID_CONNECTION.c_str());
408 return DB_ERROR;
409 }
410
SetReleaseFlag(bool flag)411 void KvStoreDelegateImpl::SetReleaseFlag(bool flag)
412 {
413 releaseFlag_ = flag;
414 }
415
Close()416 DBStatus KvStoreDelegateImpl::Close()
417 {
418 if (conn_ != nullptr) {
419 int errCode = KvDBManager::ReleaseDatabaseConnection(conn_);
420 if (errCode == -E_BUSY) {
421 LOGW("[KvStoreDelegate] busy for close");
422 return BUSY;
423 }
424
425 LOGI("[KvStoreDelegate] Close");
426 conn_ = nullptr;
427 }
428 return OK;
429 }
430
Pragma(PragmaCmd cmd,PragmaData & paramData)431 DBStatus KvStoreDelegateImpl::Pragma(PragmaCmd cmd, PragmaData ¶mData)
432 {
433 if (conn_ == nullptr) {
434 LOGE("%s", INVALID_CONNECTION.c_str());
435 return DB_ERROR;
436 }
437 int errCode;
438 switch (cmd) {
439 case PERFORMANCE_ANALYSIS_GET_REPORT:
440 errCode = conn_->Pragma(PRAGMA_PERFORMANCE_ANALYSIS_GET_REPORT, paramData);
441 break;
442 case PERFORMANCE_ANALYSIS_OPEN:
443 errCode = conn_->Pragma(PRAGMA_PERFORMANCE_ANALYSIS_OPEN, paramData);
444 break;
445 case PERFORMANCE_ANALYSIS_CLOSE:
446 errCode = conn_->Pragma(PRAGMA_PERFORMANCE_ANALYSIS_CLOSE, paramData);
447 break;
448 case PERFORMANCE_ANALYSIS_SET_REPORTFILENAME:
449 errCode = conn_->Pragma(PRAGMA_PERFORMANCE_ANALYSIS_SET_REPORTFILENAME, paramData);
450 break;
451 default:
452 errCode = -E_NOT_SUPPORT;
453 break;
454 }
455
456 if (errCode != E_OK) {
457 LOGE("[KvStoreDelegate] Pragma failed:%d", errCode);
458 return TransferDBErrno(errCode);
459 }
460 return OK;
461 }
462 } // namespace DistributedDB
463 #endif
464