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