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