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 "multi_ver_natural_store.h"
18 
19 #include <cstdio>
20 #include <openssl/rand.h>
21 
22 #include "securec.h"
23 
24 #include "db_constant.h"
25 #include "ikvdb_factory.h"
26 #include "db_common.h"
27 #include "endian_convert.h"
28 #include "log_print.h"
29 #include "db_errno.h"
30 #include "multi_ver_storage_engine.h"
31 #include "multi_ver_natural_store_connection.h"
32 #include "generic_multi_ver_kv_entry.h"
33 #include "sqlite_multi_ver_data_storage.h"
34 #include "multi_ver_natural_store_commit_storage.h"
35 #include "multi_ver_vacuum_executor_impl.h"
36 #include "kvdb_utils.h"
37 #include "sqlite_utils.h"
38 #include "platform_specific.h"
39 #include "package_file.h"
40 #include "multi_ver_database_oper.h"
41 
42 namespace DistributedDB {
43 namespace {
44     // file block doesn't support the atomic of the upgrade temporarily.
45     struct VersionFileBlock {
46         static const uint64_t MAGIC_NUMBER = 0x37F8C35AULL;
47         uint64_t magic = MAGIC_NUMBER; // magic number.
48         uint32_t fileVersion = VERSION_FILE_VERSION_CURRENT; // file format version.
49         uint32_t version = 0U; // version of the database.
50         uint8_t tag[MULTI_VER_TAG_SIZE] = {0}; // tag of the multi ver branch.
51         uint8_t reserved[72] = {0}; // reserved data.
52         uint8_t checkSum[32] = {0}; // check sum
53     };
54 
TransferHostFileBlockToNet(VersionFileBlock & block)55     void TransferHostFileBlockToNet(VersionFileBlock &block)
56     {
57         block.magic = HostToNet(block.magic);
58         block.fileVersion = HostToNet(block.fileVersion);
59         block.version = HostToNet(block.version);
60     }
61 
TransferNetFileBlockToHost(VersionFileBlock & block)62     void TransferNetFileBlockToHost(VersionFileBlock &block)
63     {
64         block.magic = NetToHost(block.magic);
65         block.fileVersion = NetToHost(block.fileVersion);
66         block.version = NetToHost(block.version);
67     }
68 
CalcFileBlockCheckSum(VersionFileBlock & block)69     int CalcFileBlockCheckSum(VersionFileBlock &block)
70     {
71         std::vector<uint8_t> vect(reinterpret_cast<uint8_t *>(&block),
72             reinterpret_cast<uint8_t *>(&block) + sizeof(block) - sizeof(block.checkSum));
73         std::vector<uint8_t> hashVect;
74         int errCode = DBCommon::CalcValueHash(vect, hashVect);
75         if (errCode != E_OK) {
76             return errCode;
77         }
78         errCode = memcpy_s(block.checkSum, sizeof(block.checkSum), hashVect.data(), hashVect.size());
79         if (errCode != EOK) {
80             return -E_SECUREC_ERROR;
81         }
82         return E_OK;
83     }
84 
CheckFileBlock(VersionFileBlock & block)85     int CheckFileBlock(VersionFileBlock &block)
86     {
87         uint64_t readMagic = NetToHost(block.magic);
88         if (readMagic != block.MAGIC_NUMBER) {
89             LOGE("Invalid file head");
90             return -E_UNEXPECTED_DATA;
91         }
92 
93         std::vector<uint8_t> vect(reinterpret_cast<uint8_t *>(&block),
94             reinterpret_cast<uint8_t *>(&block) + sizeof(block) - sizeof(block.checkSum));
95         std::vector<uint8_t> hashVect;
96         int errCode = DBCommon::CalcValueHash(vect, hashVect);
97         if (errCode != E_OK) {
98             return errCode;
99         }
100         if (memcmp(hashVect.data(), block.checkSum, sizeof(block.checkSum)) != 0) {
101             LOGE("Check block error");
102             return -E_UNEXPECTED_DATA;
103         }
104 
105         return E_OK;
106     }
107 
CreateNewVersionFile(const std::string & versionFileDir,uint32_t version,std::vector<uint8_t> & tag)108     int CreateNewVersionFile(const std::string &versionFileDir, uint32_t version, std::vector<uint8_t> &tag)
109     {
110         VersionFileBlock block;
111         block.version = version;
112     #ifdef SQLITE_HAS_CODEC
113         RAND_bytes(block.tag, sizeof(block.tag));
114     #endif
115         int errCode = memset_s(block.reserved, sizeof(block.reserved), 0, sizeof(block.reserved));
116         if (errCode != EOK) {
117             return -E_SECUREC_ERROR;
118         }
119 
120         TransferHostFileBlockToNet(block);
121         errCode = CalcFileBlockCheckSum(block);
122         if (errCode != E_OK) {
123             return errCode;
124         }
125         FILE *versionFile = fopen(versionFileDir.c_str(), "wb+");
126         if (versionFile == nullptr) {
127             LOGE("Open the version file error:%d", errno);
128             return -E_SYSTEM_API_FAIL;
129         }
130         size_t writeSize = fwrite(static_cast<void *>(&block), 1, sizeof(VersionFileBlock), versionFile);
131         if (writeSize != sizeof(VersionFileBlock)) {
132             LOGE("Write version file head error:%d", errno);
133             errCode = -E_SYSTEM_API_FAIL;
134         } else {
135             errCode = E_OK;
136             tag.assign(block.tag, block.tag + sizeof(block.tag));
137         }
138 
139         fclose(versionFile);
140         versionFile = nullptr;
141         return errCode;
142     }
143 
ChangeVersionFile(const std::string & versionFileDir,uint32_t version,std::vector<uint8_t> & tag,bool isChangeTag)144     int ChangeVersionFile(const std::string &versionFileDir, uint32_t version, std::vector<uint8_t> &tag,
145         bool isChangeTag)
146     {
147         FILE *versionFile = fopen(versionFileDir.c_str(), "rb+");
148         if (versionFile == nullptr) {
149             LOGE("Open the version file error:%d", errno);
150             return -E_SYSTEM_API_FAIL;
151         }
152         VersionFileBlock block;
153         size_t operateSize = fread(static_cast<void *>(&block), 1, sizeof(VersionFileBlock), versionFile);
154         if (operateSize != sizeof(VersionFileBlock)) {
155             fclose(versionFile);
156             LOGE("Read file error:%d", errno);
157             return -E_SYSTEM_API_FAIL;
158         };
159         int errCode = CheckFileBlock(block);
160         if (errCode != E_OK) {
161             goto END;
162         }
163         TransferHostFileBlockToNet(block);
164         block.version = version;
165 
166         if (isChangeTag) {
167             RAND_bytes(block.tag, sizeof(block.tag));
168             tag.assign(block.tag, block.tag + sizeof(block.tag));
169         }
170 
171         TransferHostFileBlockToNet(block);
172         errCode = CalcFileBlockCheckSum(block);
173         if (errCode != E_OK) {
174             goto END;
175         }
176 #ifdef OS_TYPE_MAC
177         fseeko(versionFile, 0LL, SEEK_SET);
178 #else
179         fseeko64(versionFile, 0LL, SEEK_SET);
180 #endif
181         operateSize = fwrite(&block, 1, sizeof(VersionFileBlock), versionFile);
182         if (operateSize != sizeof(VersionFileBlock)) {
183             LOGE("write the file error:%d", errno);
184             errCode = -E_SYSTEM_API_FAIL;
185             goto END;
186         }
187     END:
188         fclose(versionFile);
189         versionFile = nullptr;
190         return errCode;
191     }
192 
GetVersionAndTag(const std::string & versionFileDir,uint32_t & version,std::vector<uint8_t> & tag)193     int GetVersionAndTag(const std::string &versionFileDir, uint32_t &version, std::vector<uint8_t> &tag)
194     {
195         FILE *versionFile = fopen(versionFileDir.c_str(), "rb+");
196         if (versionFile == nullptr) {
197             LOGE("Open the version file error:%d", errno);
198             return -E_SYSTEM_API_FAIL;
199         }
200         int errCode = E_OK;
201         VersionFileBlock block;
202         size_t readSize = fread(static_cast<void *>(&block), 1, sizeof(VersionFileBlock), versionFile);
203         if (readSize != sizeof(VersionFileBlock)) {
204             LOGE("read the file error:%d", errno);
205             errCode = -E_SYSTEM_API_FAIL;
206             goto END;
207         };
208         errCode = CheckFileBlock(block);
209         if (errCode != E_OK) {
210             LOGE("Check the file block error");
211             goto END;
212         }
213         TransferNetFileBlockToHost(block);
214         version = block.version;
215         tag.assign(block.tag, block.tag + sizeof(block.tag));
216     END:
217         fclose(versionFile);
218         versionFile = nullptr;
219         return errCode;
220     }
221 }
222 
223 MultiVerVacuum MultiVerNaturalStore::shadowTrimmer_;
MultiVerNaturalStore()224 MultiVerNaturalStore::MultiVerNaturalStore()
225     : multiVerData_(nullptr),
226       commitHistory_(nullptr),
227       multiVerKvStorage_(nullptr),
228       multiVerEngine_(nullptr),
229       trimmerImpl_(nullptr),
230       maxRecordTimestamp_(0),
231       maxCommitVersion_(0)
232 {}
233 
~MultiVerNaturalStore()234 MultiVerNaturalStore::~MultiVerNaturalStore()
235 {
236     Clear();
237     UnRegisterNotificationEventType(NATURAL_STORE_COMMIT_EVENT);
238 }
239 
Clear()240 void MultiVerNaturalStore::Clear()
241 {
242     if (trimmerImpl_ != nullptr) {
243         shadowTrimmer_.Abort(GetStringIdentifier());
244         delete trimmerImpl_;
245         trimmerImpl_ = nullptr;
246     }
247     {
248         std::lock_guard<std::mutex> lock(commitHistMutex_);
249         if (commitHistory_ != nullptr) {
250             commitHistory_->Close();
251             delete commitHistory_;
252             commitHistory_ = nullptr;
253         }
254     }
255     {
256         std::lock_guard<std::mutex> lock(multiDataMutex_);
257         if (multiVerData_ != nullptr) {
258             multiVerData_->Close();
259             delete multiVerData_;
260             multiVerData_ = nullptr;
261         }
262     }
263 
264     {
265         std::lock_guard<std::mutex> lock(syncerKvMutex_);
266         if (multiVerKvStorage_ != nullptr) {
267             multiVerKvStorage_->Close();
268             delete multiVerKvStorage_;
269             multiVerKvStorage_ = nullptr;
270         }
271     }
272     multiVerEngine_ = nullptr;
273 }
274 
InitStorages(const KvDBProperties & kvDBProp,bool isChangeTag)275 int MultiVerNaturalStore::InitStorages(const KvDBProperties &kvDBProp, bool isChangeTag)
276 {
277     std::string dataDir = kvDBProp.GetStringProp(KvDBProperties::DATA_DIR, "");
278     std::string identifierDir = kvDBProp.GetStringProp(KvDBProperties::IDENTIFIER_DIR, "");
279     bool isNeedCreate = kvDBProp.GetBoolProp(KvDBProperties::CREATE_IF_NECESSARY, true);
280     CipherType cipherType;
281     CipherPassword passwd;
282     kvDBProp.GetPassword(cipherType, passwd);
283 
284     IKvDBMultiVerDataStorage::Property multiVerProp = {dataDir, identifierDir, isNeedCreate, cipherType, passwd};
285     IKvDBCommitStorage::Property commitProp = {dataDir, identifierDir, isNeedCreate, cipherType, passwd};
286     MultiVerKvDataStorage::Property multiVerKvProp = {dataDir, identifierDir, isNeedCreate, cipherType, passwd};
287 
288     int errCode = DBCommon::CreateStoreDirectory(dataDir, identifierDir, DBConstant::MULTI_SUB_DIR, isNeedCreate);
289     if (errCode != E_OK) {
290         return errCode;
291     }
292 
293     errCode = CheckVersion(kvDBProp);
294     if (errCode != E_OK) {
295         LOGE("Upgrade multi ver failed:%d", errCode);
296         return errCode;
297     }
298 
299     errCode = multiVerData_->Open(multiVerProp);
300     if (errCode != E_OK) {
301         LOGE("MultiVer::InitStorages open  multiVerData fail! errCode[%d]", errCode);
302         return errCode;
303     }
304 
305     errCode = commitHistory_->Open(commitProp);
306     if (errCode != E_OK) {
307         LOGE("MultiVer::InitStorages open  commitHistory fail! errCode[%d]", errCode);
308         return errCode;
309     }
310 
311     errCode = multiVerKvStorage_->Open(multiVerKvProp);
312     if (errCode != E_OK) {
313         LOGE("Open multi ver kv storage failed:%d", errCode);
314         return errCode;
315     }
316 
317     errCode = RecoverFromException();
318     if (errCode != E_OK) {
319         LOGE("Recover multi version storage failed:%d", errCode);
320         return errCode;
321     }
322     return InitStorageContext(isChangeTag);
323 }
324 
CheckSubStorageVersion(const KvDBProperties & kvDBProp,bool & isSubStorageAllExist) const325 int MultiVerNaturalStore::CheckSubStorageVersion(const KvDBProperties &kvDBProp, bool &isSubStorageAllExist) const
326 {
327     std::string dataDir = kvDBProp.GetStringProp(KvDBProperties::DATA_DIR, "");
328     std::string identifierDir = kvDBProp.GetStringProp(KvDBProperties::IDENTIFIER_DIR, "");
329     bool isNeedCreate = kvDBProp.GetBoolProp(KvDBProperties::CREATE_IF_NECESSARY, true);
330     CipherType cipherType;
331     CipherPassword passwd;
332     kvDBProp.GetPassword(cipherType, passwd);
333 
334     IKvDBMultiVerDataStorage::Property multiVerProp = {dataDir, identifierDir, isNeedCreate, cipherType, passwd};
335     IKvDBCommitStorage::Property commitProp = {dataDir, identifierDir, isNeedCreate, cipherType, passwd};
336     MultiVerKvDataStorage::Property multiVerKvProp = {dataDir, identifierDir, true, cipherType, passwd};
337 
338     bool isDataStorageExist = false;
339     bool isCommitStorageExist = false;
340     bool isKvStorageAllExist = false;
341     int errCode = multiVerData_->CheckVersion(multiVerProp, isDataStorageExist);
342     if (errCode != E_OK) {
343         return errCode;
344     }
345     errCode = commitHistory_->CheckVersion(commitProp, isCommitStorageExist);
346     if (errCode != E_OK) {
347         return errCode;
348     }
349     errCode = multiVerKvStorage_->CheckVersion(multiVerKvProp, isKvStorageAllExist);
350     if (errCode != E_OK) {
351         return errCode;
352     }
353     if ((isDataStorageExist != isCommitStorageExist) || (isCommitStorageExist != isKvStorageAllExist)) {
354         // In case failure happens during open progress, some dbFile will not exist, we should recover from this
355         LOGW("[MultiVerStore][CheckSubVer] Detect File Lost, isDataExist=%d, isCommitExist=%d, isKvAllExist=%d.",
356             isDataStorageExist, isCommitStorageExist, isKvStorageAllExist);
357     }
358     isSubStorageAllExist = isDataStorageExist && isCommitStorageExist && isKvStorageAllExist;
359     return E_OK;
360 }
361 
CreateStorages()362 int MultiVerNaturalStore::CreateStorages()
363 {
364     int errCode = E_OK;
365     IKvDBFactory *factory = IKvDBFactory::GetCurrent();
366     if (factory == nullptr) {
367         return -E_INVALID_DB;
368     }
369     multiVerData_ = factory->CreateMultiVerStorage(errCode);
370     if (multiVerData_ == nullptr) {
371         return errCode;
372     }
373 
374     commitHistory_ = factory->CreateMultiVerCommitStorage(errCode);
375     if (commitHistory_ == nullptr) {
376         return errCode;
377     }
378 
379     multiVerKvStorage_ = new (std::nothrow) MultiVerKvDataStorage;
380     if (multiVerKvStorage_ == nullptr) {
381         return -E_OUT_OF_MEMORY;
382     }
383     return E_OK;
384 }
385 
ClearTempFile(const KvDBProperties & kvDBProp)386 int MultiVerNaturalStore::ClearTempFile(const KvDBProperties &kvDBProp)
387 {
388     std::unique_ptr<MultiVerDatabaseOper> operation = std::make_unique<MultiVerDatabaseOper>(this, multiVerData_,
389         commitHistory_, multiVerKvStorage_);
390     (void)operation->ClearExportedTempFiles(kvDBProp);
391     int errCode = operation->RekeyRecover(kvDBProp);
392     if (errCode != E_OK) {
393         LOGE("Recover for open db failed in multi version:%d", errCode);
394         return errCode;
395     }
396 
397     errCode = operation->ClearImportTempFile(kvDBProp);
398     if (errCode != E_OK) {
399         LOGE("Recover import temp file for open db failed in multi version:%d", errCode);
400     }
401     return errCode;
402 }
403 
404 // Open the database
Open(const KvDBProperties & kvDBProp)405 int MultiVerNaturalStore::Open(const KvDBProperties &kvDBProp)
406 {
407     StorageEngineAttr poolSize = {0, 1, 0, 16}; // 1 write 16 read at most.
408     int errCode = CreateStorages();
409     if (errCode != E_OK) {
410         goto ERROR;
411     }
412 
413     MyProp() = kvDBProp;
414     errCode = ClearTempFile(kvDBProp);
415     if (errCode != E_OK) {
416         goto ERROR;
417     }
418 
419     errCode = InitStorages(kvDBProp);
420     if (errCode != E_OK) {
421         goto ERROR;
422     }
423 
424     errCode = RegisterNotificationEventType(NATURAL_STORE_COMMIT_EVENT);
425     if (errCode != E_OK) {
426         LOGE("RegisterEventType failed!");
427         goto ERROR;
428     }
429 
430     multiVerEngine_ = std::make_unique<MultiVerStorageEngine>();
431     errCode = multiVerEngine_->InitDatabases(this, multiVerData_, commitHistory_, multiVerKvStorage_, poolSize);
432     if (errCode != E_OK) {
433         goto ERROR;
434     }
435     // Start the trimming;
436     trimmerImpl_ = new (std::nothrow) MultiVerVacuumExecutorImpl(this);
437     if (trimmerImpl_ == nullptr) {
438         errCode = -E_OUT_OF_MEMORY;
439         goto ERROR;
440     }
441 
442     shadowTrimmer_.Launch(GetStringIdentifier(), trimmerImpl_);
443     StartSyncer();
444     return E_OK;
445 ERROR:
446     Clear();
447     return errCode;
448 }
449 
Close()450 void MultiVerNaturalStore::Close()
451 {
452     // Abort the trimming;
453     SyncAbleKvDB::Close();
454     Clear();
455 }
456 
NewConnection(int & errCode)457 GenericKvDBConnection *MultiVerNaturalStore::NewConnection(int &errCode)
458 {
459     auto connection = new (std::nothrow) MultiVerNaturalStoreConnection(this);
460     if (connection == nullptr) {
461         errCode = -E_OUT_OF_MEMORY;
462         return nullptr;
463     }
464 
465     errCode = E_OK;
466     return connection;
467 }
468 
469 // Get interface for syncer.
GetSyncInterface()470 IKvDBSyncInterface *MultiVerNaturalStore::GetSyncInterface()
471 {
472     return this;
473 }
474 
475 // Get interface type of this kvdb.
GetInterfaceType() const476 int MultiVerNaturalStore::GetInterfaceType() const
477 {
478     return SYNC_MVD;
479 }
480 
481 // Get the interface ref-count, in order to access asynchronously.
IncRefCount()482 void MultiVerNaturalStore::IncRefCount()
483 {
484     IncObjRef(this);
485 }
486 
487 // Drop the interface ref-count.
DecRefCount()488 void MultiVerNaturalStore::DecRefCount()
489 {
490     DecObjRef(this);
491 }
492 
493 // Get the identifier of this kvdb.
GetIdentifier() const494 std::vector<uint8_t> MultiVerNaturalStore::GetIdentifier() const
495 {
496     std::string identifier = MyProp().GetStringProp(KvDBProperties::IDENTIFIER_DATA, "");
497     std::vector<uint8_t> identifierVect(identifier.begin(), identifier.end());
498     return identifierVect;
499 }
500 
GetStringIdentifier() const501 std::string MultiVerNaturalStore::GetStringIdentifier() const
502 {
503     std::string identifier = MyProp().GetStringProp(KvDBProperties::IDENTIFIER_DATA, "");
504     std::vector<uint8_t> idVect(identifier.begin(), identifier.end());
505     return VEC_TO_STR(idVect);
506 }
507 
508 // Get the max timestamp of all entries in database.
GetMaxTimestamp(Timestamp & stamp) const509 void MultiVerNaturalStore::GetMaxTimestamp(Timestamp &stamp) const
510 {
511     std::lock_guard<std::mutex> lock(maxTimeMutex_);
512     stamp = maxRecordTimestamp_;
513 }
514 
SetMaxTimestamp(Timestamp stamp)515 void MultiVerNaturalStore::SetMaxTimestamp(Timestamp stamp)
516 {
517     std::lock_guard<std::mutex> lock(maxTimeMutex_);
518     maxRecordTimestamp_ = (stamp > maxRecordTimestamp_) ? stamp : maxRecordTimestamp_;
519 }
520 
521 // Get meta data associated with the given key.
GetMetaData(const Key & key,Value & value) const522 int MultiVerNaturalStore::GetMetaData(const Key &key, Value &value) const
523 {
524     int errCode = E_OK;
525     auto handle = GetHandle(false, errCode);
526     if (handle == nullptr) {
527         return errCode;
528     }
529 
530     errCode = handle->GetMetaData(key, value);
531     ReleaseHandle(handle);
532     return errCode;
533 }
534 
535 // Put meta data as a key-value entry.
PutMetaData(const Key & key,const Value & value,bool isInTransaction)536 int MultiVerNaturalStore::PutMetaData(const Key &key, const Value &value, bool isInTransaction)
537 {
538     (void)isInTransaction;
539     int errCode = E_OK;
540     auto handle = GetHandle(true, errCode);
541     if (handle == nullptr) {
542         return errCode;
543     }
544 
545     errCode = handle->PutMetaData(key, value);
546     ReleaseHandle(handle);
547     return errCode;
548 }
549 
DeleteMetaData(const std::vector<Key> & keys)550 int MultiVerNaturalStore::DeleteMetaData(const std::vector<Key> &keys)
551 {
552     return -E_NOT_SUPPORT;
553 }
554 
555 // Get all meta data keys.
GetAllMetaKeys(std::vector<Key> & keys) const556 int MultiVerNaturalStore::GetAllMetaKeys(std::vector<Key> &keys) const
557 {
558     return E_OK;
559 }
560 
IsCommitExisted(const MultiVerCommitNode & commit) const561 bool MultiVerNaturalStore::IsCommitExisted(const MultiVerCommitNode &commit) const
562 {
563     int errCode = E_OK;
564     auto handle = GetHandle(false, errCode);
565     if (handle == nullptr) {
566         return false;
567     }
568 
569     bool result = handle->IsCommitExisted(commit, errCode);
570     ReleaseHandle(handle);
571     return result;
572 }
573 
GetDeviceLatestCommit(std::map<std::string,MultiVerCommitNode> & commitMap) const574 int MultiVerNaturalStore::GetDeviceLatestCommit(std::map<std::string, MultiVerCommitNode> &commitMap) const
575 {
576     int errCode = E_OK;
577     auto handle = GetHandle(false, errCode);
578     if (handle == nullptr) {
579         return -E_BUSY;
580     }
581 
582     errCode = handle->GetDeviceLatestCommit(commitMap);
583     ReleaseHandle(handle);
584     return errCode;
585 }
586 
GetCommitTree(const std::map<std::string,MultiVerCommitNode> & commitMap,std::vector<MultiVerCommitNode> & commits) const587 int MultiVerNaturalStore::GetCommitTree(const std::map<std::string, MultiVerCommitNode> &commitMap,
588     std::vector<MultiVerCommitNode> &commits) const
589 {
590     int errCode = E_OK;
591     auto handle = GetHandle(false, errCode);
592     if (handle == nullptr) {
593         return -E_BUSY;
594     }
595 
596     errCode = handle->GetCommitTree(commitMap, commits);
597     ReleaseHandle(handle);
598     return errCode;
599 }
600 
GetCommitData(const MultiVerCommitNode & commit,std::vector<MultiVerKvEntry * > & entries) const601 int MultiVerNaturalStore::GetCommitData(const MultiVerCommitNode &commit, std::vector<MultiVerKvEntry *> &entries) const
602 {
603     int errCode = E_OK;
604     auto handle = GetHandle(false, errCode);
605     if (handle == nullptr) {
606         return -E_BUSY;
607     }
608 
609     errCode = handle->GetCommitData(commit, entries);
610     ReleaseHandle(handle);
611     return errCode;
612 }
613 
CreateKvEntry(const std::vector<uint8_t> & data)614 MultiVerKvEntry *MultiVerNaturalStore::CreateKvEntry(const std::vector<uint8_t> &data)
615 {
616     auto kvEntry = new (std::nothrow) GenericMultiVerKvEntry;
617     if (kvEntry == nullptr) {
618         return nullptr;
619     }
620 
621     int errCode = kvEntry->DeSerialData(data);
622     if (errCode != E_OK) {
623         LOGE("deserialize data into kv entry failed:%d", errCode);
624         delete kvEntry;
625         kvEntry = nullptr;
626     }
627     return kvEntry;
628 }
629 
ReleaseKvEntry(const MultiVerKvEntry * entry)630 void MultiVerNaturalStore::ReleaseKvEntry(const MultiVerKvEntry *entry)
631 {
632     if (entry != nullptr) {
633         delete entry;
634         entry = nullptr;
635     }
636 }
637 
IsValueSliceExisted(const ValueSliceHash & value) const638 bool MultiVerNaturalStore::IsValueSliceExisted(const ValueSliceHash &value) const
639 {
640     int errCode = E_OK;
641     auto handle = GetHandle(false, errCode);
642     if (handle == nullptr) {
643         return false;
644     }
645 
646     bool result = handle->IsValueSliceExisted(value, errCode);
647     ReleaseHandle(handle);
648     return result;
649 }
650 
GetValueSlice(const ValueSliceHash & hashValue,ValueSlice & sliceValue) const651 int MultiVerNaturalStore::GetValueSlice(const ValueSliceHash &hashValue, ValueSlice &sliceValue) const
652 {
653     int errCode = E_OK;
654     auto handle = GetHandle(false, errCode);
655     if (handle == nullptr) {
656         return -E_BUSY;
657     }
658 
659     errCode = handle->GetValueSlice(hashValue, sliceValue);
660     ReleaseHandle(handle);
661     return errCode;
662 }
663 
PutValueSlice(const ValueSliceHash & hashValue,const ValueSlice & sliceValue) const664 int MultiVerNaturalStore::PutValueSlice(const ValueSliceHash &hashValue, const ValueSlice &sliceValue) const
665 {
666     int errCode = E_OK;
667     auto handle = GetHandle(true, errCode);
668     if (handle == nullptr) {
669         return -E_BUSY;
670     }
671 
672     errCode = handle->PutValueSlice(hashValue, sliceValue, false);
673     ReleaseHandle(handle);
674     return errCode;
675 }
676 
PutCommitData(const MultiVerCommitNode & commit,const std::vector<MultiVerKvEntry * > & entries,const std::string & deviceName)677 int MultiVerNaturalStore::PutCommitData(const MultiVerCommitNode &commit, const std::vector<MultiVerKvEntry *> &entries,
678     const std::string &deviceName)
679 {
680     int errCode = E_OK;
681     auto handle = GetHandle(true, errCode);
682     if (handle == nullptr) {
683         return -E_BUSY;
684     }
685 
686     errCode = handle->PutCommitData(commit, entries, deviceName);
687     ReleaseHandle(handle);
688     return errCode;
689 }
690 
MergeSyncCommit(const MultiVerCommitNode & commit,const std::vector<MultiVerCommitNode> & commits)691 int MultiVerNaturalStore::MergeSyncCommit(const MultiVerCommitNode &commit,
692     const std::vector<MultiVerCommitNode> &commits)
693 {
694     int errCode = E_OK;
695     auto handle = GetHandle(true, errCode);
696     if (handle == nullptr) {
697         return -E_BUSY;
698     }
699 
700     errCode = handle->MergeSyncCommit(commit, commits);
701     ReleaseHandle(handle);
702     return errCode;
703 }
704 
NotifyStartSyncOperation()705 void MultiVerNaturalStore::NotifyStartSyncOperation()
706 {
707     shadowTrimmer_.Pause(GetStringIdentifier());
708 }
709 
NotifyFinishSyncOperation()710 void MultiVerNaturalStore::NotifyFinishSyncOperation()
711 {
712     shadowTrimmer_.Continue(GetStringIdentifier(), true);
713 }
714 
TransferSyncCommitDevInfo(MultiVerCommitNode & commit,const std::string & devId,bool isSyncedIn) const715 int MultiVerNaturalStore::TransferSyncCommitDevInfo(MultiVerCommitNode &commit, const std::string &devId,
716     bool isSyncedIn) const
717 {
718     std::string hashDevId = DBCommon::TransferHashString(devId);
719     if (isSyncedIn) {
720         // The size of the device info must be hash_size + tag_size;
721         if (commit.deviceInfo.size() == hashDevId.size() + MULTI_VER_TAG_SIZE) {
722             // If the hash device info is matched with the local, just remove the hash device info.
723             if (commit.deviceInfo.compare(0, hashDevId.size(), hashDevId) == 0) {
724                 commit.deviceInfo = commit.deviceInfo.substr(hashDevId.size(), MULTI_VER_TAG_SIZE);
725             }
726             return E_OK;
727         }
728         LOGE("Unexpected dev info for sync in:%zu", commit.deviceInfo.size());
729         return -E_UNEXPECTED_DATA;
730     } else {
731         // If the device info only contains the tag info, it must be local node.
732         if (commit.deviceInfo.size() == MULTI_VER_TAG_SIZE) {
733             commit.deviceInfo.insert(0, hashDevId);
734         } else if (commit.deviceInfo.size() != hashDevId.size() + MULTI_VER_TAG_SIZE) {
735             LOGE("Unexpected dev info for sync out:%zu", commit.deviceInfo.size());
736             return -E_UNEXPECTED_DATA;
737         }
738         return E_OK;
739     }
740 }
741 
Rekey(const CipherPassword & passwd)742 int MultiVerNaturalStore::Rekey(const CipherPassword &passwd)
743 {
744     if (multiVerEngine_ == nullptr) {
745         return -E_INVALID_DB;
746     }
747     int errCode = multiVerEngine_->TryToDisable(false, OperatePerm::REKEY_MONOPOLIZE_PERM);
748     if (errCode != E_OK) {
749         return errCode;
750     }
751     StopSyncer();
752     shadowTrimmer_.Pause(GetStringIdentifier());
753     errCode = multiVerEngine_->TryToDisable(true, OperatePerm::REKEY_MONOPOLIZE_PERM);
754     if (errCode != E_OK) {
755         multiVerEngine_->Enable(OperatePerm::REKEY_MONOPOLIZE_PERM);
756         shadowTrimmer_.Continue(GetStringIdentifier(), true);
757         StartSyncer();
758         return errCode;
759     }
760 
761     std::unique_ptr<MultiVerDatabaseOper> operation = std::make_unique<MultiVerDatabaseOper>(this, multiVerData_,
762         commitHistory_, multiVerKvStorage_);
763     errCode = operation->Rekey(passwd);
764 
765     multiVerEngine_->Enable(OperatePerm::REKEY_MONOPOLIZE_PERM);
766     shadowTrimmer_.Continue(GetStringIdentifier(), true);
767     StartSyncer();
768 
769     return errCode;
770 }
771 
Export(const std::string & filePath,const CipherPassword & passwd)772 int MultiVerNaturalStore::Export(const std::string &filePath, const CipherPassword &passwd)
773 {
774     if (multiVerEngine_ == nullptr) {
775         return -E_INVALID_DB;
776     }
777     std::string localDev;
778     int errCode = GetLocalIdentity(localDev);
779     if (errCode != E_OK) {
780         LOGE("Failed to GetLocalIdentity!");
781     }
782     // Exclusively write resources
783     auto handle = GetHandle(true, errCode);
784     if (handle == nullptr) {
785         return errCode;
786     }
787 
788     std::unique_ptr<MultiVerDatabaseOper> operation = std::make_unique<MultiVerDatabaseOper>(this, multiVerData_,
789         commitHistory_, multiVerKvStorage_);
790     operation->SetLocalDevId(localDev);
791     errCode = operation->Export(filePath, passwd);
792 
793     ReleaseHandle(handle);
794 
795     return errCode;
796 }
797 
Import(const std::string & filePath,const CipherPassword & passwd)798 int MultiVerNaturalStore::Import(const std::string &filePath, const CipherPassword &passwd)
799 {
800     if (multiVerEngine_ == nullptr) {
801         return -E_INVALID_DB;
802     }
803     std::string localDev;
804     int errCode = GetLocalIdentity(localDev);
805     if (errCode != E_OK) {
806         LOGE("Failed to get the local identity!");
807         localDev.resize(0);
808     }
809     errCode = multiVerEngine_->TryToDisable(false, OperatePerm::IMPORT_MONOPOLIZE_PERM);
810     if (errCode != E_OK) {
811         return errCode;
812     }
813     StopSyncer();
814     shadowTrimmer_.Abort(GetStringIdentifier());
815     std::unique_ptr<MultiVerDatabaseOper> operation;
816     errCode = multiVerEngine_->TryToDisable(true, OperatePerm::IMPORT_MONOPOLIZE_PERM);
817     if (errCode != E_OK) {
818         goto END;
819     }
820     operation = std::make_unique<MultiVerDatabaseOper>(this, multiVerData_, commitHistory_, multiVerKvStorage_);
821     operation->SetLocalDevId(localDev);
822     errCode = operation->Import(filePath, passwd);
823 END:
824     multiVerEngine_->Enable(OperatePerm::IMPORT_MONOPOLIZE_PERM);
825     shadowTrimmer_.Launch(GetStringIdentifier(), trimmerImpl_);
826     StartSyncer();
827     return errCode;
828 }
829 
GetCurrentTimestamp()830 uint64_t MultiVerNaturalStore::GetCurrentTimestamp()
831 {
832     return GetTimestamp();
833 }
834 
GetDiffEntries(const CommitID & begin,const CommitID & end,MultiVerDiffData & data) const835 int MultiVerNaturalStore::GetDiffEntries(const CommitID &begin, const CommitID &end, MultiVerDiffData &data) const
836 {
837     // Get one connection.
838     int errCode = E_OK;
839     auto handle = GetHandle(false, errCode);
840     if (handle == nullptr) {
841         return errCode;
842     }
843 
844     errCode = handle->GetDiffEntries(begin, end, data);
845     ReleaseHandle(handle);
846     return errCode;
847 }
848 
RecoverFromException()849 int MultiVerNaturalStore::RecoverFromException()
850 {
851     // Get the latest local version and the head node.
852     if (multiVerData_ == nullptr || commitHistory_ == nullptr) {
853         return -E_INVALID_DB;
854     }
855 
856     IKvDBMultiVerTransaction *transaction = nullptr;
857     int errCode = multiVerData_->StartWrite(KvDataType::KV_DATA_SYNC_P2P, transaction);
858     if (transaction == nullptr) {
859         goto END;
860     }
861     errCode = transaction->StartTransaction();
862     if (errCode != E_OK) {
863         goto END;
864     }
865 
866     errCode = CompareVerDataAndLog(transaction);
867     if (errCode != E_OK) {
868         LOGE("Compare the version data and log failed:%d", errCode);
869         transaction->RollBackTransaction();
870         goto END;
871     }
872     errCode = transaction->CommitTransaction();
873 END:
874     if (transaction != nullptr) {
875         multiVerData_->ReleaseTransaction(transaction);
876         transaction = nullptr;
877     }
878     return errCode;
879 }
880 
CompareVerDataAndLog(IKvDBMultiVerTransaction * transaction) const881 int MultiVerNaturalStore::CompareVerDataAndLog(IKvDBMultiVerTransaction *transaction) const
882 {
883     // Get the latest local version, we only care the local data.
884     Version maxLocalVersion = 0;
885     int errCode = transaction->GetMaxVersion(MultiVerDataType::NATIVE_TYPE, maxLocalVersion);
886     if (errCode != E_OK) {
887         return errCode;
888     }
889 
890     CommitID headerId = commitHistory_->GetHeader(errCode);
891     if (errCode != E_OK) {
892         return errCode;
893     }
894 
895     if (headerId.empty()) {
896         if (maxLocalVersion != 0) {
897             return transaction->ClearEntriesByVersion(maxLocalVersion);
898         }
899         return E_OK;
900     }
901 
902     IKvDBCommit *commitHead = commitHistory_->GetCommit(headerId, errCode);
903     if (commitHead == nullptr) {
904         return errCode;
905     }
906 
907     // compare the version
908     if (commitHead->GetCommitVersion() < maxLocalVersion) {
909         LOGD("Delete entries");
910         errCode = transaction->ClearEntriesByVersion(maxLocalVersion);
911     } else {
912         errCode = E_OK;
913     }
914 
915     commitHistory_->ReleaseCommit(commitHead);
916     commitHead = nullptr;
917     return errCode;
918 }
919 
GetMaxCommitVersion() const920 Version MultiVerNaturalStore::GetMaxCommitVersion() const
921 {
922     return maxCommitVersion_;
923 }
924 
SetMaxCommitVersion(const Version & version)925 void MultiVerNaturalStore::SetMaxCommitVersion(const Version &version)
926 {
927     maxCommitVersion_ = (version > maxCommitVersion_) ? version : maxCommitVersion_;
928 }
929 
GetHandle(bool isWrite,int & errCode,bool isTrimming,OperatePerm perm) const930 MultiVerStorageExecutor *MultiVerNaturalStore::GetHandle(bool isWrite, int &errCode,
931     bool isTrimming, OperatePerm perm) const
932 {
933     if (multiVerEngine_ == nullptr) {
934         errCode = -E_INVALID_DB;
935         return nullptr;
936     }
937 
938     if (isWrite && !isTrimming) {
939         // stop the trimming
940         shadowTrimmer_.Pause(GetStringIdentifier());
941     }
942     StorageExecutor *handle = nullptr;
943     if (isTrimming) {
944         handle = multiVerEngine_->FindExecutor(isWrite, OperatePerm::NORMAL_PERM, errCode, 0);
945     } else {
946         handle = multiVerEngine_->FindExecutor(isWrite, perm, errCode);
947     }
948 
949     if (handle == nullptr) {
950         if (isWrite && !isTrimming) {
951             // restart the trimming
952             shadowTrimmer_.Continue(GetStringIdentifier(), false);
953         }
954     } else {
955         if (!handle->GetWritable() && isTrimming) {
956             static_cast<MultiVerStorageExecutor *>(handle)->InitCurrentReadVersion();
957         }
958     }
959     return static_cast<MultiVerStorageExecutor *>(handle);
960 }
961 
ReleaseHandle(MultiVerStorageExecutor * & handle,bool isTrimming) const962 void MultiVerNaturalStore::ReleaseHandle(MultiVerStorageExecutor *&handle, bool isTrimming) const
963 {
964     if (multiVerEngine_ == nullptr || handle == nullptr) {
965         return;
966     }
967     bool isCorrupted = handle->GetCorruptedStatus();
968     bool isWrite = handle->GetWritable();
969     StorageExecutor *databaseHandle = handle;
970     multiVerEngine_->Recycle(databaseHandle);
971     handle = nullptr;
972     if (isCorrupted) {
973         CorruptNotify();
974     }
975     if (isWrite && !isTrimming) {
976         // restart the trimming.
977         LOGI("Release handle and continue vacuum data!");
978         shadowTrimmer_.Continue(GetStringIdentifier(), true);
979     }
980 }
981 
InitStorageContext(bool isChangeTag)982 int MultiVerNaturalStore::InitStorageContext(bool isChangeTag)
983 {
984     int errCode = InitStorageContextVersion(isChangeTag);
985     if (errCode != E_OK) {
986         return errCode;
987     }
988 
989     maxCommitVersion_ = commitHistory_->GetMaxCommitVersion(errCode);
990     if (errCode != E_OK) {
991         LOGE("Get the max commit version failed:%d", errCode);
992     }
993     return errCode;
994 }
995 
InitStorageContextVersion(bool isChangeTag)996 int MultiVerNaturalStore::InitStorageContextVersion(bool isChangeTag)
997 {
998     std::string verFilePath;
999     int errCode = GetVersionFilePath(MyProp(), verFilePath);
1000     if (errCode != E_OK) {
1001         return errCode;
1002     }
1003 
1004     if (!OS::CheckPathExistence(verFilePath)) {
1005         return CreateNewVersionFile(verFilePath, MULTI_VER_STORE_VERSION_CURRENT, branchTag_);
1006     }
1007     if (isChangeTag) {
1008         return ChangeVersionFile(verFilePath, MULTI_VER_STORE_VERSION_CURRENT, branchTag_, isChangeTag);
1009     }
1010     uint32_t version = 0;
1011     return GetVersionAndTag(verFilePath, version, branchTag_);
1012 }
1013 
GetCurrentTag(std::vector<uint8_t> & tag) const1014 void MultiVerNaturalStore::GetCurrentTag(std::vector<uint8_t> &tag) const
1015 {
1016     tag = branchTag_;
1017 }
1018 
AddVersionConstraintToList(Version version)1019 void MultiVerNaturalStore::AddVersionConstraintToList(Version version)
1020 {
1021     std::lock_guard<std::mutex> lock(versionConstraintMutex_);
1022     versionConstraints_.insert(version);
1023 }
1024 
RemoveVersionConstraintFromList(Version version)1025 void MultiVerNaturalStore::RemoveVersionConstraintFromList(Version version)
1026 {
1027     std::lock_guard<std::mutex> lock(versionConstraintMutex_);
1028     auto iter = versionConstraints_.find(version);
1029     if (iter != versionConstraints_.end()) {
1030         versionConstraints_.erase(iter);
1031         // Auto launch the vacuum.
1032         shadowTrimmer_.AutoRelaunchOnce(GetStringIdentifier());
1033     }
1034 }
1035 
GetMaxTrimmableVersion() const1036 Version MultiVerNaturalStore::GetMaxTrimmableVersion() const
1037 {
1038     std::lock_guard<std::mutex> lock(versionConstraintMutex_);
1039     if (versionConstraints_.empty()) {
1040         return UINT64_MAX;
1041     }
1042     return *(versionConstraints_.begin());
1043 }
1044 
TransObserverTypeToRegisterFunctionType(int observerType,RegisterFuncType & type) const1045 int MultiVerNaturalStore::TransObserverTypeToRegisterFunctionType(int observerType, RegisterFuncType &type) const
1046 {
1047     if (observerType == static_cast<uint32_t>(NATURAL_STORE_COMMIT_EVENT)) {
1048         type = RegisterFuncType::OBSERVER_MULTI_VERSION_NS_COMMIT_EVENT;
1049         return E_OK;
1050     }
1051     return -E_NOT_SUPPORT;
1052 }
1053 
GetDbProperties() const1054 const KvDBProperties &MultiVerNaturalStore::GetDbProperties() const
1055 {
1056     return GetMyProperties();
1057 }
1058 
RemoveKvDB(const KvDBProperties & properties)1059 int MultiVerNaturalStore::RemoveKvDB(const KvDBProperties &properties)
1060 {
1061     std::string storeOnlyDir;
1062     std::string storeDir;
1063     GenericKvDB::GetStoreDirectory(properties, KvDBProperties::MULTI_VER_TYPE_SQLITE, storeDir, storeOnlyDir);
1064     int errCodeVersion = KvDBUtils::RemoveKvDB(storeDir, storeOnlyDir, DBConstant::MULTI_VER_DATA_STORE);
1065     int errCodeCommit = KvDBUtils::RemoveKvDB(storeDir, storeOnlyDir, DBConstant::MULTI_VER_COMMIT_STORE);
1066     int errCodeValue = KvDBUtils::RemoveKvDB(storeDir, storeOnlyDir, DBConstant::MULTI_VER_VALUE_STORE);
1067     int errCodeMeta = KvDBUtils::RemoveKvDB(storeDir, storeOnlyDir, DBConstant::MULTI_VER_META_STORE);
1068     LOGD("Delete the versionStorage:%d, commitStorage:%d, valueStorage:%d, metaStorage:%d",
1069         errCodeVersion, errCodeCommit, errCodeValue, errCodeMeta);
1070     DBCommon::RemoveAllFilesOfDirectory(storeDir, true);
1071     DBCommon::RemoveAllFilesOfDirectory(storeOnlyDir, true);
1072     if (errCodeVersion == E_OK && errCodeCommit == E_OK) {
1073         return E_OK;
1074     }
1075     if (errCodeVersion == -E_NOT_FOUND && errCodeCommit == -E_NOT_FOUND) {
1076         return -E_NOT_FOUND;
1077     }
1078     if (errCodeVersion == E_OK && errCodeCommit == -E_NOT_FOUND) {
1079         return E_OK;
1080     }
1081     if (errCodeVersion == -E_NOT_FOUND && errCodeCommit == E_OK) {
1082         return E_OK;
1083     }
1084     return errCodeCommit;
1085 }
1086 
GetKvDBSize(const KvDBProperties & properties,uint64_t & size) const1087 int MultiVerNaturalStore::GetKvDBSize(const KvDBProperties &properties, uint64_t &size) const
1088 {
1089     std::string storeOnlyDir;
1090     std::string storeDir;
1091     GenericKvDB::GetStoreDirectory(properties, KvDBProperties::MULTI_VER_TYPE_SQLITE, storeDir, storeOnlyDir);
1092 
1093     std::vector<std::string> storageNames = {
1094         DBConstant::MULTI_VER_DATA_STORE,
1095         DBConstant::MULTI_VER_COMMIT_STORE,
1096         DBConstant::MULTI_VER_VALUE_STORE,
1097         DBConstant::MULTI_VER_META_STORE
1098     };
1099 
1100     // there only calculate db related file size
1101     for (const auto &storageName : storageNames) {
1102         uint64_t dbSize = 0;
1103         int errCode = KvDBUtils::GetKvDbSize(storeDir, storeOnlyDir, storageName, dbSize);
1104         if (errCode == E_OK) {
1105             size += dbSize;
1106             continue;
1107         }
1108 
1109         if (errCode == -E_NOT_FOUND) {
1110             return -E_NOT_FOUND;
1111         }
1112 
1113         size = 0;
1114         return errCode;
1115     }
1116     return E_OK;
1117 }
1118 
GetDbPropertyForUpdate()1119 KvDBProperties &MultiVerNaturalStore::GetDbPropertyForUpdate()
1120 {
1121     return MyProp();
1122 }
1123 
CheckVersion(const KvDBProperties & kvDBProp) const1124 int MultiVerNaturalStore::CheckVersion(const KvDBProperties &kvDBProp) const
1125 {
1126     LOGD("[MultiVerStore][CheckVer] Current Overall Version: %u.", MULTI_VER_STORE_VERSION_CURRENT);
1127     bool isVerFileExist = false;
1128     int errCode = CheckOverallVersionViaVersionFile(kvDBProp, isVerFileExist);
1129     if (errCode != E_OK) {
1130         return errCode;
1131     }
1132     bool isSubStorageExist = false;
1133     errCode = CheckSubStorageVersion(kvDBProp, isSubStorageExist);
1134     if (errCode != E_OK) {
1135         return errCode;
1136     }
1137     if (isVerFileExist != isSubStorageExist) {
1138         LOGW("[MultiVerStore][CheckVer] Detect File Lost, isVerFileExist=%d, isSubStorageExist=%d.",
1139             isVerFileExist, isSubStorageExist);
1140     }
1141     return E_OK;
1142 }
1143 
CheckOverallVersionViaVersionFile(const KvDBProperties & kvDBProp,bool & isVerFileExist) const1144 int MultiVerNaturalStore::CheckOverallVersionViaVersionFile(const KvDBProperties &kvDBProp, bool &isVerFileExist) const
1145 {
1146     std::string verFilePath;
1147     int errCode = GetVersionFilePath(kvDBProp, verFilePath);
1148     if (errCode != E_OK) {
1149         return errCode;
1150     }
1151     // Absent of version file may because: 1: Newly created database; 2: An already created database lost version file.
1152     // In both case, we returned E_OK here. After each sub storage be successfully open and upgrade, create verFile.
1153     if (!OS::CheckPathExistence(verFilePath)) {
1154         LOGD("[MultiVerStore][CheckOverVer] No Version File.");
1155         isVerFileExist = false;
1156         return E_OK;
1157     }
1158     isVerFileExist = true;
1159 
1160     uint32_t overallVersion = 0;
1161     std::vector<uint8_t> branchTagInVerFile;
1162     errCode = GetVersionAndTag(verFilePath, overallVersion, branchTagInVerFile);
1163     if (errCode != E_OK) {
1164         LOGE("[MultiVerStore][CheckOverVer] GetVersionAndTag fail, errCode=%d.", errCode);
1165         return errCode;
1166     }
1167     LOGD("[MultiVerStore][CheckOverVer] overallVersion=%u, tag=%s.", overallVersion, VEC_TO_STR(branchTagInVerFile));
1168     if (overallVersion > MULTI_VER_STORE_VERSION_CURRENT) {
1169         LOGE("[MultiVerStore][CheckOverVer] Version Not Support!");
1170         return -E_VERSION_NOT_SUPPORT;
1171     }
1172     return E_OK;
1173 }
1174 
GetVersionFilePath(const KvDBProperties & kvDBProp,std::string & outPath) const1175 int MultiVerNaturalStore::GetVersionFilePath(const KvDBProperties &kvDBProp, std::string &outPath) const
1176 {
1177     std::string verFiledir;
1178     int errCode = GetWorkDir(kvDBProp, verFiledir);
1179     if (errCode != E_OK) {
1180         LOGE("[MultiVerStore][GetVerFilePath] GetWorkDir fail, errCode=%d", errCode);
1181         return errCode;
1182     }
1183     outPath = verFiledir + "/" + DBConstant::MULTI_SUB_DIR + "/version";
1184     return E_OK;
1185 }
1186 
DeleteMetaDataByPrefixKey(const Key & keyPrefix) const1187 int MultiVerNaturalStore::DeleteMetaDataByPrefixKey(const Key &keyPrefix) const
1188 {
1189     (void)keyPrefix;
1190     return -E_NOT_SUPPORT;
1191 }
1192 
SetSendDataInterceptor(const PushDataInterceptor & interceptor)1193 void MultiVerNaturalStore::SetSendDataInterceptor(const PushDataInterceptor &interceptor)
1194 {
1195     (void)interceptor;
1196     return;
1197 }
1198 
SetReceiveDataInterceptor(const DataInterceptor & interceptor)1199 void MultiVerNaturalStore::SetReceiveDataInterceptor(const DataInterceptor &interceptor)
1200 {
1201     (void)interceptor;
1202     return;
1203 }
1204 
1205 DEFINE_OBJECT_TAG_FACILITIES(MultiVerNaturalStore)
1206 } // namespace DistributedDB
1207 #endif
1208