• 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 #include "distributed_test_tools.h"
16 
17 #include <algorithm>
18 #include <chrono>
19 #include <cmath>
20 #include <cstdio>
21 #include <cstring>
22 #include <dirent.h>
23 #include <fcntl.h>
24 #include <functional>
25 #include <openssl/sha.h>
26 #include <random>
27 #include <string>
28 #include <sys/stat.h>
29 #include <unistd.h>
30 
31 #ifndef USE_SQLITE_SYMBOLS
32 #include "sqlite3.h"
33 #else
34 #include "sqlite3sym.h"
35 #endif
36 #include "delegate_callback.h"
37 #include "delegate_kv_mgr_callback.h"
38 #include "distributeddb_data_generator.h"
39 #include "distributed_test_sysinfo.h"
40 #include "kv_store_delegate.h"
41 #include "kv_store_delegate_manager.h"
42 #include "platform_specific.h"
43 #include "securec.h"
44 
45 using namespace std;
46 using namespace chrono;
47 using namespace std::placeholders;
48 using namespace DistributedDB;
49 using namespace DistributedDBDataGenerator;
50 
51 namespace {
52 #ifndef USE_SQLITE_CODEC_CIPHER
53     const std::string CIPHER_CONFIG_SQL = "PRAGMA cipher='aes-256-gcm';";
54     const std::string KDF_ITER_CONFIG_SQL = "PRAGMA kdf_iter=5000;";
55 #else
56     const std::string CIPHER_CONFIG_SQL = "PRAGMA codec_cipher='aes-256-gcm';";
57     const std::string KDF_ITER_CONFIG_SQL = "PRAGMA codec_kdf_iter=5000;";
58 #endif
59     const int RAND_BOOL_MIN = 0;
60     const int RAND_BOOL_MAX = 1;
61 }
62 
CompareVector(const std::vector<uint8_t> & first,const std::vector<uint8_t> & second)63 bool CompareVector(const std::vector<uint8_t>& first, const std::vector<uint8_t>& second)
64 {
65     if (first.size() != second.size()) {
66         MST_LOG("[CompareVector] first.size[%zu] != second.size[%zu]", first.size(), second.size());
67         return false;
68     }
69     return first == second;
70 }
71 
CompareEntriesVector(std::vector<DistributedDB::Entry> & retVec,std::vector<DistributedDB::Entry> & expectVec)72 bool CompareEntriesVector(std::vector<DistributedDB::Entry>& retVec,
73     std::vector<DistributedDB::Entry>& expectVec)
74 {
75     if (retVec.size() != expectVec.size()) {
76         MST_LOG("retVec.size() = %zd, expectVec.size() = %zd", retVec.size(), expectVec.size());
77         return false;
78     }
79 
80     // for retVec and expectVec are reference, don't want to change the value of them
81     vector<std::reference_wrapper<Entry>> retVector(retVec.begin(), retVec.end());
82     vector<std::reference_wrapper<Entry>> expVec(expectVec.begin(), expectVec.end());
83     sort(retVector.begin(), retVector.end(), DistributedTestTools::CompareKey);
84     sort(expVec.begin(), expVec.end(), DistributedTestTools::CompareKey);
85     bool result = true;
86     for (uint64_t at = 0; at < retVector.size(); at++) {
87         result = ((retVector[at].get().key == expVec[at].get().key) &&
88             (retVector[at].get().value == expVec[at].get().value));
89         if (!result) {
90             MST_LOG("[CompareEntriesVector] compare list failed at the position: %llu", ULL(at));
91             string retKey(retVector[at].get().key.begin(), retVector[at].get().key.end());
92             string retValue(retVector[at].get().value.begin(), retVector[at].get().value.end());
93             string expKey(expVec[at].get().key.begin(), expVec[at].get().key.end());
94             string expValue(expVec[at].get().value.begin(), expVec[at].get().value.end());
95             MST_LOG("[CompareEntriesVector] the actual Key: %s\n", retKey.c_str());
96             MST_LOG("[CompareEntriesVector] the expect key: %s\n", expKey.c_str());
97             // retValue num lessThan 10, expValue num lessThan 10,
98             if (retValue.size() > 10 && expValue.size() > 10) {
99                 MST_LOG("[CompareEntriesVector] the actual value: %s...%s\n",
100                     // retValue substr num as 10, the index of retKey.size() - 10
101                     retValue.substr(0, 10).c_str(), retValue.substr((retValue.size() - 10), 10).c_str());
102                 MST_LOG("[CompareEntriesVector] the expect value: %s...%s\n",
103                     // expValue substr num as 10, the index of retKey.size() - 10
104                     expValue.substr(0, 10).c_str(), expValue.substr((expValue.size() - 10), 10).c_str());
105             } else {
106                 MST_LOG("[CompareEntriesVector] the actual value: %s\n", retValue.c_str());
107                 MST_LOG("[CompareEntriesVector] the expect value: %s\n", expValue.c_str());
108             }
109             return result;
110         }
111     }
112     return true;
113 }
114 
PutUniqueKey(vector<Entry> & entryVec,const Key & putKey,const Value & putValue)115 void PutUniqueKey(vector<Entry> &entryVec, const Key &putKey, const Value &putValue)
116 {
117     bool findEachEntry = false;
118     for (unsigned int idxEntry = 0; idxEntry < entryVec.size(); ++idxEntry) {
119         if (CompareVector(entryVec[idxEntry].key, putKey)) {
120             findEachEntry = true;
121             entryVec[idxEntry].value = putValue;
122             break;
123         }
124     }
125     Entry entry = { putKey, putValue };
126     if (!findEachEntry) {
127         entryVec.push_back(entry);
128     }
129 }
130 
Uint8VecToString(std::vector<uint8_t> & vec,std::string & str)131 int Uint8VecToString(std::vector<uint8_t> &vec, std::string &str)
132 {
133     int len = 0;
134     str.clear();
135 
136     for (auto vecIt = vec.begin(); vecIt != vec.end(); ++vecIt) {
137         str.push_back(static_cast<char>(*vecIt));
138         ++len;
139     }
140 
141     return len;
142 }
143 
GenRanKeyVal(int putGetTimes,int keyLength,int valueLength,char val)144 vector<Entry> GenRanKeyVal(int putGetTimes, int keyLength, int valueLength, char val)
145 {
146     // random gen the key
147     std::random_device randDevKeyNo;
148     std::mt19937 genRandKeyNo(randDevKeyNo());
149     std::uniform_int_distribution<uint8_t> disRandKeyNo(CHAR_SPAN_MIN, CHAR_SPAN_MAX);
150 
151     DistributedDB::Entry entryCurrent;
152     vector<Entry> entriesBatch;
153 
154     for (int cnt = 0; cnt < putGetTimes; ++cnt) {
155         DistributedDB::Key tempKey = PERFORMANCEKEY;
156         for (int kIndex = 0; kIndex < keyLength; ++kIndex) {
157             tempKey.push_back(disRandKeyNo(genRandKeyNo));
158         }
159         entryCurrent.key = tempKey;
160         entryCurrent.value.assign(valueLength, val);
161 
162         entriesBatch.push_back(entryCurrent);
163     }
164     return entriesBatch;
165 }
166 
GetRandBool()167 bool GetRandBool()
168 {
169     std::random_device randDev;
170     std::mt19937 genRand(randDev());
171     std::uniform_int_distribution<int> disRand(RAND_BOOL_MIN, RAND_BOOL_MAX);
172     return disRand(genRand);
173 }
174 
PutEntries(KvStoreNbDelegate * & delegate,vector<Entry> & entries)175 bool PutEntries(KvStoreNbDelegate *&delegate, vector<Entry> &entries)
176 {
177     for (const auto &entry : entries) {
178         if (delegate->Put(entry.key, entry.value) != OK) {
179             return false;
180         }
181     }
182     return true;
183 }
184 
GetKeysFromEntries(std::vector<DistributedDB::Entry> entries,bool random)185 vector<Key> GetKeysFromEntries(std::vector < DistributedDB::Entry > entries, bool random)
186 {
187     vector<Key> result;
188     vector<Entry> old;
189     old.assign(entries.begin(), entries.end());
190     if (random) {
191         for (int i = entries.size(); i > 0; i--) {
192             int index = GetRandInt(0, ONE_HUNDRED_SECONDS * MILLSECONDS_PER_SECOND) % i;
193             result.push_back(old[index].key);
194             old.erase(old.begin() + index);
195         }
196     } else {
197         for (auto entry = entries.begin(); entry != entries.end(); ++entry) {
198             result.push_back(entry->key);
199         }
200     }
201     return result;
202 }
203 
GetIntValue(Value & value)204 int GetIntValue(Value &value)
205 {
206     if (value.size() == 0) {
207         return 0;
208     }
209     string strVal;
210     Uint8VecToString(value, strVal);
211     int number;
212     if (sscanf_s(strVal.c_str(), "%d", &number) != 1) {
213         return 0;
214     }
215     return number;
216 }
217 
GetValueWithInt(int val)218 Value GetValueWithInt(int val)
219 {
220     string strVal = std::to_string(val);
221     Value result;
222     result.assign(strVal.begin(), strVal.end());
223     return result;
224 }
225 
GetGroupEntries(vector<Entry> entries,int pageSize,int valueLength,uint8_t c)226 vector< vector<Entry> > GetGroupEntries(vector<Entry> entries, int pageSize, int valueLength, uint8_t c)
227 {
228     vector< vector<Entry> > result;
229     if (pageSize <= 0) {
230         MST_LOG("pageSize can't be zero or negative number!");
231     } else {
232         int pages = (entries.size() - 1) / pageSize + 1;
233         for (int pageIndex = 0; pageIndex < pages; ++pageIndex) {
234             vector<Entry> temp;
235             int pageStart = pageSize * pageIndex;
236             int pageEnd = (pageSize * (pageIndex + 1)) - 1;
237             if (pageEnd + 1 > static_cast<int>(entries.size())) {
238                 pageEnd = entries.size() - 1;
239             }
240             MST_LOG("The %d page start position: %d, end position: %d", pageIndex, pageStart, pageEnd);
241             temp.assign(entries.begin() + pageStart, entries.begin() + pageEnd);
242             result.push_back(temp);
243         }
244         for (auto iter = result.begin(); iter != result.end(); ++iter) {
245             for (auto entry = iter->begin(); entry != iter->end(); ++entry) {
246                 entry->value.assign(valueLength, c);
247             }
248         }
249     }
250     return result;
251 }
252 
253 // KvCallback conclude the Callback of function <void(DBStatus, Value)> and <void(DBStatus, vector<Entry>)>
254 class KvCallback {
255 public:
KvCallback()256     KvCallback() {}
~KvCallback()257     ~KvCallback() {}
258 
259     // Delete the copy and assign constructors
260     KvCallback(const KvCallback &callback) = delete;
261     KvCallback& operator=(const KvCallback &callback) = delete;
262     KvCallback(KvCallback &&callback) = delete;
263     KvCallback& operator=(KvCallback &&callback) = delete;
264 
Callback(DBStatus status,const Value & value)265     void Callback(DBStatus status, const Value &value)
266     {
267         this->status_ = status;
268         this->value_ = value;
269     }
270 
CallbackPrefix(DBStatus status,const vector<Entry> & entries)271     void CallbackPrefix(DBStatus status, const vector<Entry> &entries)
272     {
273         this->status_ = status;
274         this->entries_ = entries;
275     }
276 
GetStatus()277     DBStatus GetStatus()
278     {
279         return status_;
280     }
281 
GetValue()282     const Value &GetValue()
283     {
284         return value_;
285     }
286 
GetValueVector()287     const vector<Entry> &GetValueVector()
288     {
289         return entries_;
290     }
291 
292 private:
293     DBStatus status_ = DBStatus::INVALID_ARGS;
294     Value value_ = { };
295     vector<Entry> entries_ = {};
296 };
297 
GetDirStat(const char * dir,struct stat & dirStat)298 static int GetDirStat(const char *dir, struct stat &dirStat)
299 {
300     // getting dir attribution fails
301     if (stat(dir, &dirStat) < 0) {
302         perror("get directory stat error");
303         return -1;
304     }
305     return 0;
306 }
307 
308 // delete dir(directory) recursively
RemoveDir(const std::string & dirSrc)309 int RemoveDir(const std::string &dirSrc)
310 {
311     string directory = dirSrc;
312     char curDir[] = ".";
313     char upDir[] = "..";
314     char dirName[MAX_DIR_LENGTH] = { 0 };
315     DIR *dirp = nullptr;
316     struct dirent *dp = nullptr;
317     struct stat dirStat;
318 
319     while (directory.at(directory.length() - 1) == '/') {
320         directory.pop_back();
321     }
322 
323     const char *dir = directory.c_str();
324     // if dir is not existed
325     if (access(dir, F_OK) != 0) {
326         return 0;
327     }
328     GetDirStat(dir, dirStat);
329     // if dir is a common file
330     if (S_ISREG(dirStat.st_mode)) {
331 #ifdef DB_DEBUG_ENV
332     MST_LOG("---> remove db directory: %s", dir);
333 #endif
334         remove(dir);
335     } else if (S_ISDIR(dirStat.st_mode)) {
336         // if dir is directory, delete it recursively
337         dirp = opendir(dir);
338         if (dirp == nullptr) {
339             perror("open directory error");
340             return -1;
341         }
342         while ((dp = readdir(dirp)) != nullptr) {
343             // ignore . and ..
344             if ((strcmp(curDir, dp->d_name) == 0) || (strcmp(upDir, dp->d_name)) == 0) {
345                 continue;
346             }
347             int result = sprintf_s(dirName, sizeof(dirName) - 1, "%s/%s", dir, dp->d_name);
348             if (result < 0) {
349                 closedir(dirp);
350                 return -1;
351             }
352             MST_LOG("delete dirName = %s", dirName);
353             RemoveDir(std::string(dirName));
354         }
355         closedir(dirp);
356 #ifdef DB_DEBUG_ENV
357         MST_LOG("---> remove db directory: %s", directory.c_str());
358 #endif
359         remove(directory.c_str());
360     } else {
361         perror("unknown file type!");
362     }
363     return 0;
364 }
365 
366 // If the test cases' related dir in system is not exist, create it.
SetDir(const std::string & directory,const int authRight)367 int SetDir(const std::string &directory, const int authRight)
368 {
369     MST_LOG("create directory: %s", directory.c_str());
370     char dir[MAX_DIR_LENGTH] = { 0 };
371 
372     errno_t ret = strcpy_s(dir, MAX_DIR_LENGTH, directory.c_str());
373     if (ret != E_OK) {
374         MST_LOG("strcpy_s failed(%d)!", ret);
375         return -1;
376     }
377     int len = strlen(dir);
378     if (dir[len - 1] != '/') {
379         ret = strcat_s(dir, sizeof(dir) - strlen(dir) - 1, "/");
380         if (ret != E_OK) {
381             MST_LOG("strcat_s failed(%d)!", ret);
382             return -1;
383         }
384         len++;
385     }
386 
387     for (int i = 1; i < len; i++) {
388         if (dir[i] != '/') {
389             continue;
390         }
391         dir[i] = '\0';
392         if (access(dir, F_OK) == E_OK) {
393             dir[i] = '/';
394             continue;
395         }
396         mode_t mode = umask(0);
397 #if defined(RUNNING_ON_LINUX)
398         if (mkdir(dir, authRight) == E_ERROR) {
399 #else
400         std::string stringDir = dir;
401         if (OS::MakeDBDirectory(stringDir) == E_ERROR) {
402 #endif
403             MST_LOG("mkdir(%s) failed(%d)!", dir, errno);
404             return -1;
405         }
406         if (chdir(dir) == E_ERROR) {
407             MST_LOG("chdir(%s) failed(%d)!", dir, errno);
408         }
409         umask(mode);
410         dir[i] = '/';
411     }
412     MST_LOG("check dir = %s", dir);
413     return 0;
414 }
415 
416 void CopyFile(const string &srcFile, const string &destFile)
417 {
418     int len = 0;
419     char buff[BUF_LEN] = { 0 };
420 
421     FILE *pIn = fopen(srcFile.c_str(), "r");
422     if (pIn == nullptr) {
423         perror("pIn");
424         return;
425     }
426 
427     FILE *pOut = fopen(destFile.c_str(), "w");
428     if (pOut == nullptr) {
429         perror("pOut");
430         fclose(pIn);
431         return;
432     }
433 
434     while ((len = fread(buff, sizeof(char), sizeof(buff), pIn)) > 0) {
435         fwrite(buff, sizeof(char), len, pOut);
436     }
437     fclose(pOut);
438     fclose(pIn);
439 }
440 
441 void CopyDir(const string &srcDir, const string &destDir, const int authRight)
442 {
443     string srcFullDir = srcDir;
444     string destFullDir = destDir;
445     struct dirent *filename = nullptr;
446     DIR *dpDest = opendir(destFullDir.c_str());
447     if (dpDest == nullptr) {
448         if (SetDir(destFullDir.c_str(), authRight)) {
449             MST_LOG("[CopyDir] SetDir(%s) failed(%d)!", destFullDir.c_str(), errno);
450             return;
451         }
452     } else {
453         closedir(dpDest);
454     }
455     string path = srcFullDir;
456     if (srcFullDir.back() != '/') {
457         srcFullDir += "/";
458     }
459     if (destFullDir.back() != '/') {
460         destFullDir += "/";
461     }
462 
463     DIR *dpSrc = opendir(path.c_str());
464     if (dpSrc == nullptr) {
465         MST_LOG("[CopyDir] please make sure srcDir(%s) is valid.", srcDir.c_str());
466         return;
467     }
468     while ((filename = readdir(dpSrc)) != nullptr) {
469         string fileSourceDir = srcFullDir;
470         string fileDestDir = destFullDir;
471 
472         fileSourceDir += filename->d_name;
473         fileDestDir += filename->d_name;
474         if (filename->d_type == DT_DIR) {
475             if ((string(filename->d_name).compare(0, strlen("."), ".") != 0) &&
476                 (string(filename->d_name).compare(0, strlen(".."), "..") != 0)) {
477                 CopyDir(fileSourceDir, fileDestDir);
478             }
479         } else {
480             CopyFile(fileSourceDir, fileDestDir);
481         }
482     }
483     closedir(dpSrc);
484     MST_LOG("[CopyDir] copy file from %s to %s successfully.", srcDir.c_str(), destDir.c_str());
485 }
486 
487 void CheckFileNumber(const string &filePath, int &fileCount)
488 {
489     std::string cmd = "cd " + filePath + ";ls -l |grep " + "^-" + "|wc -l";
490     FILE *pipe = popen(cmd.c_str(), "r");
491     if (pipe == nullptr) {
492         MST_LOG("Check file number filed.");
493         return;
494     }
495 
496     char buffer[128]; // set pipe buffer length as 128B
497     std::string result = "";
498     while (!feof(pipe)) {
499         if (fgets(buffer, 128, pipe) != nullptr) { // set pipe buffer length as 128B
500             result += buffer;
501         }
502     }
503     pclose(pipe);
504     fileCount = std::stoi(result);
505     MST_LOG("Check file number is %d", fileCount);
506 }
507 
508 // this static method is to compare if the two Value has the same data.
509 bool DistributedTestTools::IsValueEquals(const DistributedDB::Value &v1, const DistributedDB::Value &v2)
510 {
511     // just return false if the sizes are not the same.
512     if (v1.size() != v2.size()) {
513         return false;
514     }
515 
516     // compare two Values char by char.
517     return v1 == v2;
518 }
519 
520 // This static method is for moduleTest of distributed to get KvStoreDelegate with valid ids.
521 KvStoreDelegate* DistributedTestTools::GetDelegateSuccess(KvStoreDelegateManager *&outManager,
522     const KvDBParameters &param, const KvOption &optionParam)
523 {
524     MST_LOG("GetDelegateSuccess isEncryptedDb= %d", optionParam.isEncryptedDb);
525     SetDir(DIRECTOR);
526     if (param.storeId.empty() || param.appId.empty() || param.userId.empty()) {
527         return nullptr;
528     }
529 
530     // define a Callback to hold the kvStoreDelegate and status.
531     DelegateKvMgrCallback delegateKvMgrCallback;
532     function<void(DBStatus, KvStoreDelegate*)> callFunction
533         = bind(&DelegateKvMgrCallback::Callback, &delegateKvMgrCallback, _1, _2);
534 
535     // use appid and userid to initialize a kvStoreDelegateManager, and set the default cfg.
536     if (outManager != nullptr) {
537         delete outManager;
538         outManager = nullptr;
539     }
540     KvStoreDelegateManager *manager = new (std::nothrow) KvStoreDelegateManager(param.appId, param.userId);
541     if (manager == nullptr) {
542         MST_LOG("new delegate failed nullptr.");
543         return nullptr;
544     }
545     DBStatus status = manager->SetKvStoreConfig(KV_CONFIG);
546     if (status != DBStatus::OK) {
547         MST_LOG("%s SetConfig failed! Status= %d", TAG.c_str(), status);
548         delete manager;
549         manager = nullptr;
550         return nullptr;
551     }
552 
553     KvStoreDelegate::Option option = TransferKvOptionType(optionParam);
554     // get kv store, then the Callback will save the status and delegate.
555     manager->GetKvStore(param.storeId, option, callFunction);
556     status = delegateKvMgrCallback.GetStatus();
557     if (status != DBStatus::OK) {
558         MST_LOG("%s GetKvStore failed! Status= %d", TAG.c_str(), status);
559         delete manager;
560         manager = nullptr;
561         return nullptr;
562     }
563     const KvStoreDelegate* delegate = const_cast<KvStoreDelegate*>(delegateKvMgrCallback.GetKvStore());
564     if (delegate == nullptr) {
565         MST_LOG("%s GetKvStore failed! delegate nullptr.", TAG.c_str());
566         delete manager;
567         manager = nullptr;
568         return nullptr;
569     }
570 
571     MST_LOG("%s GetKvStore success: %s %s %s %d %d", TAG.c_str(),
572         param.storeId.c_str(), param.appId.c_str(), param.userId.c_str(), option.createIfNecessary, option.localOnly);
573     outManager = manager;
574     return const_cast<KvStoreDelegate*>(delegate);
575 }
576 
577 KvStoreDelegate* DistributedTestTools::GetDelegateStatus(KvStoreDelegateManager *&outManager, DBStatus &statusReturn,
578     const KvDBParameters &param, const KvOption &optionParam)
579 {
580     MST_LOG("Delegate isEncryptedDb : %s", (optionParam.isEncryptedDb ? "true" : "false"));
581     SetDir(DIRECTOR);
582     if (param.storeId.empty() || param.appId.empty() || param.userId.empty()) {
583         return nullptr;
584     }
585 
586     // define a Callback to hold the kvStoreDelegate and status.
587     DelegateKvMgrCallback delegateKvMgrCallback;
588     function<void(DBStatus, KvStoreDelegate*)> functionCallback
589         = bind(&DelegateKvMgrCallback::Callback, &delegateKvMgrCallback, _1, _2);
590 
591     // use appid and userid to initialize a kvStoreDelegateManager, and set the default cfg.
592     if (outManager != nullptr) {
593         delete outManager;
594         outManager = nullptr;
595     }
596     KvStoreDelegateManager *manager = new (std::nothrow) KvStoreDelegateManager(param.appId, param.userId);
597     if (manager == nullptr) {
598         MST_LOG("new delegate failed nullptr.");
599         return nullptr;
600     }
601     DBStatus status = manager->SetKvStoreConfig(KV_CONFIG);
602     if (status != DBStatus::OK) {
603         MST_LOG("%s SetConfig failed! Status= %d", TAG.c_str(), status);
604         delete manager;
605         manager = nullptr;
606         return nullptr;
607     }
608 
609     KvStoreDelegate::Option option = TransferKvOptionType(optionParam);
610     // get kv store, then the Callback will save the status and delegate.
611     manager->GetKvStore(param.storeId, option, functionCallback);
612     statusReturn = delegateKvMgrCallback.GetStatus();
613     if (statusReturn != DBStatus::OK) {
614         MST_LOG("%s GetKvStore failed! Status= %d", TAG.c_str(), statusReturn);
615         delete manager;
616         manager = nullptr;
617         return nullptr;
618     }
619     const KvStoreDelegate* delegate = const_cast<KvStoreDelegate*>(delegateKvMgrCallback.GetKvStore());
620     if (delegate == nullptr) {
621         MST_LOG("%s GetDelegate failed! delegate is nullptr.", TAG.c_str());
622         delete manager;
623         manager = nullptr;
624         return nullptr;
625     }
626 
627     MST_LOG("%s GetKvStore success : %s %s %s %d %d", TAG.c_str(), param.storeId.c_str(), param.appId.c_str(),
628         param.userId.c_str(), option.createIfNecessary, option.localOnly);
629     outManager = manager;
630     return const_cast<KvStoreDelegate*>(delegate);
631 }
632 
633 // This static method is for moduleTest of distributed to try-get KvStoreDelegate with invalid params.
634 DBStatus DistributedTestTools::GetDelegateNotGood(KvStoreDelegateManager *&manager, KvStoreDelegate *&outDelegate,
635     const string &storeId, const KvOption &optionParam)
636 {
637     SetDir(DIRECTOR);
638 
639     // define a Callback to hold the kvStoreDelegate and status.
640     DelegateKvMgrCallback delegateKvMgrCallback;
641     function<void(DBStatus, KvStoreDelegate*)> callFunction
642         = bind(&DelegateKvMgrCallback::Callback, &delegateKvMgrCallback, _1, _2);
643 
644     DBStatus status = manager->SetKvStoreConfig(KV_CONFIG);
645     if (status != DBStatus::OK) {
646         MST_LOG("%s SetConfig failed! Status= %d", TAG.c_str(), status);
647         status = DBStatus::INVALID_ARGS;
648         delete manager;
649         manager = nullptr;
650         return status;
651     }
652 
653     KvStoreDelegate::Option option = TransferKvOptionType(optionParam);
654     // get kv store, then the Callback will save the status and delegate.
655     manager->GetKvStore(storeId, option, callFunction);
656     status = delegateKvMgrCallback.GetStatus();
657     outDelegate = const_cast<KvStoreDelegate*>(delegateKvMgrCallback.GetKvStore());
658     if (outDelegate != nullptr) {
659         MST_LOG("%s GetKvStore failed! delegate nullptr.", TAG.c_str());
660         delete manager;
661         manager = nullptr;
662         return status;
663     }
664     if (status == DBStatus::NOT_FOUND) {
665         MST_LOG("%s GetKvStore failed! Status= %d", TAG.c_str(), status);
666         delete manager;
667         manager = nullptr;
668         return status;
669     }
670 
671     MST_LOG("%s GetKvStore failed, Status = %d", TAG.c_str(), status);
672     return status;
673 }
674 
675 // This static method is for moduleTest to put value with kvStoreDelegate.
676 DBStatus DistributedTestTools::Put(KvStoreDelegate &kvStoreDelegate, const Key &key, const Value &value)
677 {
678     return kvStoreDelegate.Put(key, value);
679 }
680 
681 // This static method is for moduleTest to putBatch value with kvStoreDelegate.
682 DBStatus DistributedTestTools::PutBatch(KvStoreDelegate &kvStoreDelegate, const vector<Entry> &entries)
683 {
684     DistributedDB::DBStatus status;
685     unsigned int cnt = entries.size();
686     int index = 0;
687     while (cnt > BATCH_RECORDS) {
688         cnt -= BATCH_RECORDS;
689         std::vector<DistributedDB::Entry> entriesBatch(entries.begin() + index * BATCH_RECORDS,
690             entries.begin() + (index + 1) * BATCH_RECORDS);
691         status = kvStoreDelegate.PutBatch(entriesBatch);
692         index++;
693         if (status != DBStatus::OK) {
694             return status;
695         }
696     }
697     std::vector<DistributedDB::Entry> entriesBatch(entries.begin() + index * BATCH_RECORDS, entries.end());
698     status = kvStoreDelegate.PutBatch(entriesBatch);
699 
700     return status;
701 }
702 
703 // This static method is for moduleTest to delete value with kvStoreDelegate.
704 DBStatus DistributedTestTools::Delete(KvStoreDelegate &kvStoreDelegate, const Key &key)
705 {
706     return kvStoreDelegate.Delete(key);
707 }
708 
709 // This static method is for moduleTest to deleteBatch value with kvStoreDelegate.
710 DBStatus DistributedTestTools::DeleteBatch(KvStoreDelegate &kvStoreDelegate, const vector<Key> &keys)
711 {
712     if (keys.size() > BATCH_RECORDS) {
713         int cnt = 0;
714         std::vector<DistributedDB::Key> keyBatch;
715         DistributedDB::DBStatus status;
716         for (const auto &iter : keys) {
717             keyBatch.push_back(iter);
718             cnt++;
719             if (cnt % BATCH_RECORDS != 0 && cnt != static_cast<int>(keys.size())) {
720                 continue;
721             }
722             status = kvStoreDelegate.DeleteBatch(keyBatch);
723             if (status != DBStatus::OK) {
724                 return status;
725             }
726             keyBatch.clear();
727         }
728         return status;
729     } else {
730         return kvStoreDelegate.DeleteBatch(keys);
731     }
732 }
733 
734 // This static method is for moduleTest to clear value with kvStoreDelegate.
735 DBStatus DistributedTestTools::Clear(KvStoreDelegate &kvStoreDelegate)
736 {
737     return kvStoreDelegate.Clear();
738 }
739 
740 // This static method is for moduleTest to try-get snapshot with kvStoreDelegate.
741 KvStoreSnapshotDelegate *DistributedTestTools::GetKvStoreSnapshot(KvStoreDelegate &kvStoreDelegate)
742 {
743     DelegateCallback delegateCallback;
744     function<void(DBStatus, KvStoreSnapshotDelegate *)> callFunction
745         = bind(&DelegateCallback::Callback, &delegateCallback, _1, _2);
746 
747     // no need to use obsever, so param1 is nullptr;
748     kvStoreDelegate.GetKvStoreSnapshot(nullptr, callFunction);
749     DBStatus status = delegateCallback.GetStatus();
750     if (status != DBStatus::OK) {
751         MST_LOG("%s Get Callback failed! Status= %d", TAG.c_str(), status);
752         return nullptr;
753     }
754     KvStoreSnapshotDelegate *snapshot
755         = const_cast<KvStoreSnapshotDelegate *>(delegateCallback.GetKvStoreSnapshot());
756     if (snapshot == nullptr) {
757         MST_LOG("%s Get KvStoreSnapshot null! Status= %d", TAG.c_str(), status);
758         return nullptr;
759     }
760     return snapshot;
761 }
762 
763 // This static method is for moduleTest to get value with kvStoreDelegate.
764 Value DistributedTestTools::Get(KvStoreDelegate &kvStoreDelegate, const Key &key)
765 {
766     // initialize the result value.
767     Value result = { };
768     DelegateCallback delegateCallback;
769     function<void(DBStatus, KvStoreSnapshotDelegate *)> callFunction
770         = bind(&DelegateCallback::Callback, &delegateCallback, _1, _2);
771     kvStoreDelegate.GetKvStoreSnapshot(nullptr, callFunction);
772     DBStatus status = delegateCallback.GetStatus();
773     if (status != DBStatus::OK) {
774         MST_LOG("%s Get failed! Status= %d", TAG.c_str(), status);
775         return result;
776     }
777 
778     // the first Callback's kvStoreDelegate is used to get snapshot.
779     KvStoreSnapshotDelegate *snapshot
780         = const_cast<KvStoreSnapshotDelegate*>(delegateCallback.GetKvStoreSnapshot());
781     if (snapshot == nullptr) {
782         MST_LOG("%s Get snapshot null! Status= %d", TAG.c_str(), status);
783         return result;
784     }
785 
786     // the second Callback is used in Snapshot.
787     KvCallback kvCallback;
788     function < void(DBStatus, Value) > function2
789         = bind(&KvCallback::Callback, &kvCallback, _1, _2);
790     snapshot->Get(key, function2);
791     status = kvCallback.GetStatus();
792     if (status != DBStatus::OK) {
793         kvStoreDelegate.ReleaseKvStoreSnapshot(snapshot);
794         snapshot = nullptr;
795         MST_LOG("%s Get value failed! Status= %d", TAG.c_str(), status);
796         return result;
797     }
798     result = kvCallback.GetValue();
799     kvStoreDelegate.ReleaseKvStoreSnapshot(snapshot);
800     snapshot = nullptr;
801     return result;
802 }
803 
804 Value DistributedTestTools::Get(KvStoreSnapshotDelegate &kvStoreSnapshotDelegate, const Key &key)
805 {
806     KvCallback kvCallback;
807     function < void(DBStatus, Value) > function2
808         = bind(&KvCallback::Callback, &kvCallback, _1, _2);
809     kvStoreSnapshotDelegate.Get(key, function2);
810     return kvCallback.GetValue();
811 }
812 
813 vector<Entry> DistributedTestTools::GetEntries(KvStoreSnapshotDelegate &kvStoreSnapshotDelegate, const Key &key)
814 {
815     KvCallback kvCallback;
816     function<void(DBStatus, vector<Entry>)> function2
817         = bind(&KvCallback::CallbackPrefix, &kvCallback, _1, _2);
818     kvStoreSnapshotDelegate.GetEntries(key, function2);
819     return kvCallback.GetValueVector();
820 }
821 
822 // This static method is for moduleTest to get values with kvStoreDelegate and keyPrefix.
823 vector<Entry> DistributedTestTools::GetEntries(KvStoreDelegate &kvStoreDelegate, const Key &keyPrefix)
824 {
825     DelegateCallback delegateCallback;
826     function<void(DBStatus, KvStoreSnapshotDelegate *)> callFunction
827         = bind(&DelegateCallback::Callback, &delegateCallback, _1, _2);
828     kvStoreDelegate.GetKvStoreSnapshot(nullptr, callFunction);
829     DBStatus status = delegateCallback.GetStatus();
830     if (status != DBStatus::OK) {
831         MST_LOG("%s Get failed! Status= %d", TAG.c_str(), status);
832         return {};
833     }
834 
835     KvStoreSnapshotDelegate *snapshot
836         = const_cast<KvStoreSnapshotDelegate*>(delegateCallback.GetKvStoreSnapshot());
837     if (snapshot == nullptr) {
838         MST_LOG("%s Get snapshot null! Status= %d", TAG.c_str(), status);
839         return {};
840     }
841 
842     KvCallback kvCallback;
843     function<void(DBStatus, vector<Entry>)> function2 = bind(&KvCallback::CallbackPrefix, &kvCallback, _1, _2);
844     snapshot->GetEntries(keyPrefix, function2);
845     status = kvCallback.GetStatus();
846     if (status != DBStatus::OK) {
847         kvStoreDelegate.ReleaseKvStoreSnapshot(snapshot);
848         snapshot = nullptr;
849         MST_LOG("%s GetEntries failed! Status= %d", TAG.c_str(), status);
850         return {};
851     }
852     kvStoreDelegate.ReleaseKvStoreSnapshot(snapshot);
853     snapshot = nullptr;
854     return kvCallback.GetValueVector();
855 }
856 
857 void TickTock(steady_clock::time_point &tick, double &duration)
858 {
859     steady_clock::time_point tock = steady_clock::now();
860     auto durate = duration_cast<microseconds>(tock - tick);
861     tick = tock;
862     duration = static_cast<double>(durate.count());
863 }
864 
865 bool TickTock1(steady_clock::time_point &tick, int putGetTimes, double &duration)
866 {
867     if (putGetTimes <= 0) {
868         MST_LOG("putGetTimes is 0!");
869         return false;
870     }
871     TickTock(tick, duration);
872     duration /= putGetTimes;
873     return true;
874 }
875 
876 void GetSysInfo(DistributedTestSysInfo &si, SeqNo seqNo)
877 {
878     si.GetSysMemOccpy(seqNo);
879     si.GetSysCpuUsage(seqNo, DEFAULT_INTEVAL);
880     si.GetSysCurrentPower(seqNo, DEFAULT_COUNT, DEFAULT_INTEVAL);
881 }
882 
883 void CheckBeforeOpenDB(bool getSysInfo, steady_clock::time_point &tick,
884     vector<Entry> data1, vector<Key> keys, DistributedTestSysInfo &si)
885 {
886     if (!getSysInfo) {
887         MST_LOG("[gen data]:%zu, %zu.", data1.size(), keys.size());
888         tick = time_point_cast<microseconds>(steady_clock::now());
889     } else {
890         MST_LOG("System info before opening a db:");
891         GetSysInfo(si, FIRST);
892     }
893 }
894 
895 void CheckAfterOperateDB(bool getSysInfo, steady_clock::time_point &tick,
896     double &duration, DistributedTestSysInfo &si)
897 {
898     if (!getSysInfo) {
899         TickTock(tick, duration);
900         MST_LOG("[time calculator]this operate cost %f us.", duration);
901     } else {
902         MST_LOG("System info after opening db, or before inserting records:");
903         GetSysInfo(si, SECOND);
904         si.SaveSecondToFirst();
905     }
906 }
907 
908 void PutDuration(steady_clock::time_point &tick, PerformanceData &performanceData,
909     int keyLength, DistributedTestSysInfo &si)
910 {
911     bool getSysInfo = performanceData.getSysInfo;
912     int putGetTimes = performanceData.putGetTimes;
913     double duration;
914     if (!getSysInfo) {
915         TickTock(tick, duration);
916         performanceData.putDuration = duration / putGetTimes;
917         MST_LOG("[time calculator]put first [%d]keys,\tvalue[%dB-length],\tcost[%fus],\tper[%fus].",
918             putGetTimes, keyLength, duration, performanceData.putDuration);
919         TickTock(tick, duration);
920     } else {
921         MST_LOG("System info after inserting records, or before querying records:");
922         GetSysInfo(si, SECOND);
923         si.SaveSecondToFirst();
924     }
925 }
926 
927 void ReadDuration(steady_clock::time_point &tick, PerformanceData &performanceData,
928     int keyLength, DistributedTestSysInfo &si)
929 {
930     bool getSysInfo = performanceData.getSysInfo;
931     int putGetTimes = performanceData.putGetTimes;
932     double duration;
933     if (!getSysInfo) {
934         TickTock(tick, duration);
935         performanceData.readPutDuration = duration / putGetTimes;
936         MST_LOG("[time calculator]get first [%d]keys,\tvalue[%dB-length],\tcost[%fus],\tper[%fus].",
937             putGetTimes, keyLength, duration, performanceData.readPutDuration);
938         TickTock(tick, duration);
939     } else {
940         MST_LOG("System info after querying records, or before updating records:");
941         GetSysInfo(si, SECOND);
942         si.SaveSecondToFirst();
943     }
944 }
945 
946 void UpdateDuration(steady_clock::time_point &tick, PerformanceData &performanceData,
947     int keyLength, DistributedTestSysInfo &si)
948 {
949     bool getSysInfo = performanceData.getSysInfo;
950     int putGetTimes = performanceData.putGetTimes;
951     double duration;
952     if (!getSysInfo) {
953         TickTock(tick, duration);
954         performanceData.updateDuration = duration / putGetTimes;
955         MST_LOG("[time calculator]put second [%d]keys,\tvalue[%dB-length],\tcost[%fus],\tper[%fus].",
956             putGetTimes, keyLength, duration, performanceData.updateDuration);
957         TickTock(tick, duration);
958     } else {
959         MST_LOG("System info after updating records, or before querying records one by one:");
960         GetSysInfo(si, SECOND);
961         si.SaveSecondToFirst();
962     }
963 }
964 
965 void ReadUpdateDuration(steady_clock::time_point &tick, PerformanceData &performanceData,
966     int keyLength, DistributedTestSysInfo &si)
967 {
968     bool getSysInfo = performanceData.getSysInfo;
969     int putGetTimes = performanceData.putGetTimes;
970     double duration;
971     if (!getSysInfo) {
972         TickTock(tick, duration);
973         performanceData.readUpdateDuration = duration / putGetTimes;
974         MST_LOG("[time calculator]get second [%d]keys,\tvalue[%dB-length],\tcost[%fus],\tper[%fus].",
975             putGetTimes, keyLength, duration, performanceData.readUpdateDuration);
976         TickTock(tick, duration);
977     } else {
978         MST_LOG("System info after querying records one by one, or before deleting records one by one:");
979         GetSysInfo(si, SECOND);
980         si.SaveSecondToFirst();
981     }
982 }
983 
984 void ClearDuration(steady_clock::time_point &tick, PerformanceData &performanceData,
985     int keyLength, DistributedTestSysInfo &si)
986 {
987     bool getSysInfo = performanceData.getSysInfo;
988     int putGetTimes = performanceData.putGetTimes;
989     double duration;
990     if (!getSysInfo) {
991         TickTock(tick, duration);
992         performanceData.deleteDuration = duration / putGetTimes;
993         MST_LOG("[time calculator]delete [%d]keys,\tvalue[%dB-length],\tcost[%fus],\tper[%fus].",
994             putGetTimes, keyLength, duration, performanceData.deleteDuration);
995         TickTock(tick, duration);
996     } else {
997         MST_LOG("System info after deleting records one by one, or before closing a db:");
998         GetSysInfo(si, SECOND);
999         si.SaveSecondToFirst();
1000     }
1001 }
1002 
1003 bool DistributedTestTools::CalculateOpenPerformance(PerformanceData &performanceData)
1004 {
1005     int putGetTimes = performanceData.putGetTimes;
1006     int keyLength = performanceData.keyLength;
1007     int valueLength = performanceData.valueLength;
1008     bool getSysInfo = performanceData.getSysInfo;
1009     DistributedTestSysInfo si;
1010     steady_clock::time_point tick;
1011 
1012     vector<Entry> data1 = GenRanKeyVal(putGetTimes, keyLength, valueLength, 'a');
1013     vector<Key> keys = GetKeysFromEntries(data1, false);
1014 
1015     CheckBeforeOpenDB(getSysInfo, tick, data1, keys, si);
1016     // print the opened time.
1017     KvStoreDelegate *store1 = nullptr;
1018     KvStoreDelegateManager *manager = nullptr;
1019 
1020     KvOption option = g_kvOption;
1021     option.localOnly = performanceData.isLocal;
1022     store1 = DistributedTestTools::GetDelegateSuccess(manager, KVDB_PARAMETER_PERFORM, option);
1023     if (store1 == nullptr) {
1024         return false;
1025     }
1026     CheckAfterOperateDB(getSysInfo, tick, performanceData.closeDuration, si);
1027 
1028     // close the base db
1029     if (manager->CloseKvStore(store1) != DistributedDB::DBStatus::OK) {
1030         return false;
1031     }
1032     if (manager->DeleteKvStore(STORE_ID_PERFORM) != OK) {
1033         return false;
1034     }
1035     store1 = nullptr;
1036     delete manager;
1037     manager = nullptr;
1038     CheckAfterOperateDB(getSysInfo, tick, performanceData.closeDuration, si);
1039 
1040     return true;
1041 }
1042 
1043 bool DistributedTestTools::CalculateInsertPerformance(PerformanceData &performanceData)
1044 {
1045     int putGetTimes = performanceData.putGetTimes;
1046     int keyLength = performanceData.keyLength;
1047     int valueLength = performanceData.valueLength;
1048     bool putBatch = performanceData.putBatch;
1049     bool getSysInfo = performanceData.getSysInfo;
1050     DistributedTestSysInfo si;
1051     steady_clock::time_point tick;
1052 
1053     vector<Entry> data1 = GenRanKeyVal(putGetTimes, keyLength, valueLength, 'a');
1054     vector<Key> keys = GetKeysFromEntries(data1, false);
1055     vector< vector<Entry> > groupEntries = GetGroupEntries(data1, BATCH_RECORDS, valueLength, 'a');
1056     CheckBeforeOpenDB(getSysInfo, tick, data1, keys, si);
1057 
1058     KvStoreDelegate *store1 = nullptr;
1059     KvStoreDelegateManager *manager = nullptr;
1060 
1061     KvOption option = g_kvOption;
1062     option.localOnly = performanceData.isLocal;
1063     store1 = DistributedTestTools::GetDelegateSuccess(manager, KVDB_PARAMETER_PERFORM, option);
1064     if (store1 == nullptr) {
1065         return false;
1066     }
1067     // print the insert time.
1068     if (putBatch) {
1069         for (auto entries = groupEntries.begin(); entries != groupEntries.end(); ++entries) {
1070             DistributedTestTools::PutBatch(*store1, *entries);
1071         }
1072     } else {
1073         for (auto entry = data1.begin(); entry != data1.end(); ++entry) {
1074             DistributedTestTools::Put(*store1, entry->key, entry->value);
1075         }
1076     }
1077 
1078     PutDuration(tick, performanceData, keyLength, si);
1079 
1080     // close the base db
1081     if (manager->CloseKvStore(store1) != DistributedDB::DBStatus::OK) {
1082         return false;
1083     }
1084     if (manager->DeleteKvStore(STORE_ID_PERFORM) != OK) {
1085         return false;
1086     }
1087     store1 = nullptr;
1088     delete manager;
1089     manager = nullptr;
1090     CheckAfterOperateDB(getSysInfo, tick, performanceData.closeDuration, si);
1091 
1092     return true;
1093 }
1094 
1095 bool DistributedTestTools::CalculateGetPutPerformance(PerformanceData &performanceData)
1096 {
1097     int putGetTimes = performanceData.putGetTimes;
1098     int keyLength = performanceData.keyLength;
1099     int valueLength = performanceData.valueLength;
1100     bool getBatch = performanceData.getBatch;
1101     bool getSysInfo = performanceData.getSysInfo;
1102     DistributedTestSysInfo si;
1103     steady_clock::time_point tick;
1104 
1105     vector<Entry> data1 = GenRanKeyVal(putGetTimes, keyLength, valueLength, 'a');
1106     vector<Key> keys = GetKeysFromEntries(data1, false);
1107 
1108     CheckBeforeOpenDB(getSysInfo, tick, data1, keys, si);
1109 
1110     // print the get put time.
1111     KvStoreDelegate *store1 = nullptr;
1112     KvStoreDelegateManager *manager = nullptr;
1113 
1114     KvOption option = g_kvOption;
1115     option.localOnly = performanceData.isLocal;
1116     store1 = DistributedTestTools::GetDelegateSuccess(manager, KVDB_PARAMETER_PERFORM, option);
1117     if (store1 == nullptr) {
1118         return false;
1119     }
1120     KvStoreSnapshotDelegate *snapShot = DistributedTestTools::GetKvStoreSnapshot(*store1);
1121     if (snapShot == nullptr)  {
1122         return false;
1123     }
1124     if (getBatch) {
1125         std::vector<Entry> ev = DistributedTestTools::GetEntries(*snapShot, PERFORMANCEKEY);
1126     } else {
1127         for (auto key = keys.begin(); key != keys.end(); ++key) {
1128             Value valueResult = DistributedTestTools::Get(*snapShot, *key);
1129         }
1130     }
1131     store1->ReleaseKvStoreSnapshot(snapShot);
1132     snapShot = nullptr;
1133     ReadDuration(tick, performanceData, keyLength, si);
1134 
1135     // close the base db
1136     if (manager->CloseKvStore(store1) != DistributedDB::DBStatus::OK) {
1137         return false;
1138     }
1139     if (manager->DeleteKvStore(STORE_ID_PERFORM) != OK) {
1140         return false;
1141     }
1142     store1 = nullptr;
1143     delete manager;
1144     manager = nullptr;
1145     CheckAfterOperateDB(getSysInfo, tick, performanceData.closeDuration, si);
1146 
1147     return true;
1148 }
1149 
1150 bool DistributedTestTools::CalculateUpdatePerformance(PerformanceData &performanceData)
1151 {
1152     int putGetTimes = performanceData.putGetTimes;
1153     int keyLength = performanceData.keyLength;
1154     int valueLength = performanceData.valueLength;
1155     bool putBatch = performanceData.putBatch;
1156     bool getSysInfo = performanceData.getSysInfo;
1157     DistributedTestSysInfo si;
1158     steady_clock::time_point tick;
1159 
1160     vector<Entry> data1 = GenRanKeyVal(putGetTimes, keyLength, valueLength, 'a');
1161     vector<Key> keys = GetKeysFromEntries(data1, false);
1162     Value updateVal;
1163     updateVal.assign(valueLength, 'b');
1164     vector< vector<Entry> > groupEntriesUp = GetGroupEntries(data1, BATCH_RECORDS, valueLength, 'b');
1165     CheckBeforeOpenDB(getSysInfo, tick, data1, keys, si);
1166 
1167     // print the update time.
1168     KvStoreDelegate *store1 = nullptr;
1169     KvStoreDelegateManager *manager = nullptr;
1170 
1171     KvOption option = g_kvOption;
1172     option.localOnly = performanceData.isLocal;
1173     store1 = DistributedTestTools::GetDelegateSuccess(manager, KVDB_PARAMETER_PERFORM, option);
1174     if (store1 == nullptr) {
1175         return false;
1176     }
1177     if (putBatch) {
1178         for (auto entries = groupEntriesUp.begin(); entries != groupEntriesUp.end(); ++entries) {
1179             DistributedTestTools::PutBatch(*store1, *entries);
1180         }
1181     } else {
1182         for (auto entry = data1.begin(); entry != data1.end(); ++entry) {
1183             DistributedTestTools::Put(*store1, entry->key, updateVal);
1184         }
1185     }
1186     UpdateDuration(tick, performanceData, keyLength, si);
1187 
1188     // close the base db
1189     if (manager->CloseKvStore(store1) != DistributedDB::DBStatus::OK) {
1190         return false;
1191     }
1192     if (manager->DeleteKvStore(STORE_ID_PERFORM) != OK) {
1193         return false;
1194     }
1195     store1 = nullptr;
1196     delete manager;
1197     manager = nullptr;
1198     CheckAfterOperateDB(getSysInfo, tick, performanceData.closeDuration, si);
1199 
1200     return true;
1201 }
1202 
1203 bool DistributedTestTools::CalculateGetUpdatePerformance(PerformanceData &performanceData)
1204 {
1205     int putGetTimes = performanceData.putGetTimes;
1206     int keyLength = performanceData.keyLength;
1207     int valueLength = performanceData.valueLength;
1208     bool getSysInfo = performanceData.getSysInfo;
1209     DistributedTestSysInfo si;
1210     steady_clock::time_point tick;
1211 
1212     vector<Entry> data1 = GenRanKeyVal(putGetTimes, keyLength, valueLength, 'a');
1213     vector<Key> keys = GetKeysFromEntries(data1, false);
1214 
1215     CheckBeforeOpenDB(getSysInfo, tick, data1, keys, si);
1216 
1217     // print the get update time.
1218     KvStoreDelegate *store1 = nullptr;
1219     KvStoreDelegateManager *manager = nullptr;
1220 
1221     KvOption option = g_kvOption;
1222     option.localOnly = performanceData.isLocal;
1223     store1 = DistributedTestTools::GetDelegateSuccess(manager, KVDB_PARAMETER_PERFORM, option);
1224     if (store1 == nullptr) {
1225         return false;
1226     }
1227     KvStoreSnapshotDelegate *snapShot = DistributedTestTools::GetKvStoreSnapshot(*store1);
1228     if (snapShot == nullptr)  {
1229         return false;
1230     }
1231     for (auto key = keys.begin(); key != keys.end(); ++key) {
1232         Value valueResult = DistributedTestTools::Get(*snapShot, *key);
1233     }
1234     store1->ReleaseKvStoreSnapshot(snapShot);
1235     snapShot = nullptr;
1236     ReadUpdateDuration(tick, performanceData, keyLength, si);
1237 
1238     // close the base db
1239     if (manager->CloseKvStore(store1) != DistributedDB::DBStatus::OK) {
1240         return false;
1241     }
1242     if (manager->DeleteKvStore(STORE_ID_PERFORM) != OK) {
1243         return false;
1244     }
1245     store1 = nullptr;
1246     delete manager;
1247     manager = nullptr;
1248     CheckAfterOperateDB(getSysInfo, tick, performanceData.closeDuration, si);
1249     return true;
1250 }
1251 
1252 bool DistributedTestTools::CalculateUseClearPerformance(PerformanceData &performanceData)
1253 {
1254     int putGetTimes = performanceData.putGetTimes;
1255     int keyLength = performanceData.keyLength;
1256     int valueLength = performanceData.valueLength;
1257     bool useClear = performanceData.useClear;
1258     bool getSysInfo = performanceData.getSysInfo;
1259     DistributedTestSysInfo si;
1260     steady_clock::time_point tick;
1261 
1262     vector<Entry> data1 = GenRanKeyVal(putGetTimes, keyLength, valueLength, 'a');
1263     vector<Key> keys = GetKeysFromEntries(data1, false);
1264 
1265     CheckBeforeOpenDB(getSysInfo, tick, data1, keys, si);
1266 
1267     // print the get update time.
1268     KvStoreDelegate *store1 = nullptr;
1269     KvStoreDelegateManager *manager = nullptr;
1270 
1271     KvOption option = g_kvOption;
1272     option.localOnly = performanceData.isLocal;
1273     store1 = DistributedTestTools::GetDelegateSuccess(manager, KVDB_PARAMETER_PERFORM, option);
1274     if (store1 == nullptr) {
1275         return false;
1276     }
1277     if (useClear) {
1278         DistributedTestTools::Clear(*store1);
1279     } else {
1280         for (auto key = keys.begin(); key != keys.end(); ++key) {
1281             DistributedTestTools::Delete(*store1, *key);
1282         }
1283     }
1284     ClearDuration(tick, performanceData, keyLength, si);
1285 
1286     // close the base db
1287     if (manager->CloseKvStore(store1) != DistributedDB::DBStatus::OK) {
1288         return false;
1289     }
1290     if (manager->DeleteKvStore(STORE_ID_PERFORM) != OK) {
1291         return false;
1292     }
1293     store1 = nullptr;
1294     delete manager;
1295     manager = nullptr;
1296     CheckAfterOperateDB(getSysInfo, tick, performanceData.closeDuration, si);
1297     return true;
1298 }
1299 
1300 bool DistributedTestTools::CloseAndRelease(KvStoreDelegateManager *&manager, KvStoreDelegate *&delegate)
1301 {
1302     bool result = true;
1303     DBStatus status;
1304     if (delegate != nullptr && manager != nullptr) {
1305         status = manager->CloseKvStore(delegate);
1306         MST_LOG("[CloseAndRelease] status = %d", status);
1307         result = (status == OK);
1308         delegate = nullptr;
1309         delete manager;
1310         manager = nullptr;
1311     } else {
1312         MST_LOG("Close Failed");
1313         return false;
1314     }
1315     return result;
1316 }
1317 
1318 bool DistributedTestTools::CloseAndRelease(KvStoreDelegateManager *&manager, KvStoreNbDelegate *&delegate)
1319 {
1320     bool result = true;
1321     if (delegate != nullptr && manager != nullptr) {
1322         result = (manager->CloseKvStore(delegate) == OK);
1323         delegate = nullptr;
1324         delete manager;
1325         manager = nullptr;
1326     } else {
1327         MST_LOG("Close Failed");
1328         return false;
1329     }
1330     return result;
1331 }
1332 
1333 bool DistributedTestTools::VerifyDbRecordCnt(KvStoreNbDelegate *&delegate, unsigned int recordCnt, bool isLocal)
1334 {
1335     if (delegate == nullptr) {
1336         MST_LOG("The delegate is nullptr!");
1337         return false;
1338     }
1339     DBStatus status = OK;
1340     vector<Entry> entries;
1341     if (isLocal) {
1342 #ifdef RELEASE_MODE_V2
1343         status = delegate->GetLocalEntries(KEY_EMPTY, entries);
1344 #endif // end of RELEASE_MODE_V2
1345     } else {
1346         status = delegate->GetEntries(KEY_EMPTY, entries);
1347     }
1348 
1349     if (status == OK && entries.size() == recordCnt) {
1350         return true;
1351     } else {
1352         MST_LOG("The real status is %d, real recordCnt is %zu", status, entries.size());
1353         return false;
1354     }
1355 }
1356 
1357 bool DistributedTestTools::VerifyRecordsInDb(DistributedDB::KvStoreNbDelegate *&delegate,
1358     std::vector<DistributedDB::Entry> &entriesExpected, const std::vector<uint8_t> &keyPrefix, bool isLocal)
1359 {
1360     DBStatus status = OK;
1361     vector<Entry> entries;
1362     if (isLocal) {
1363 #ifdef RELEASE_MODE_V2
1364         status = delegate->GetLocalEntries(keyPrefix, entries);
1365 #endif // end of RELEASE_MODE_V2
1366     } else {
1367         status = delegate->GetEntries(keyPrefix, entries);
1368     }
1369     if (status == OK && CompareEntriesVector(entries, entriesExpected)) {
1370         return true;
1371     }
1372     MST_LOG("[VerifyRecordsInDb] status = %d, entries.size() = %zu\n", status, entries.size());
1373     return false;
1374 }
1375 
1376 void ReleaseSqliteResource(sqlite3_stmt *&statement, sqlite3 *&db)
1377 {
1378     sqlite3_finalize(statement);
1379     statement = nullptr;
1380     sqlite3_close(db);
1381 }
1382 
1383 bool SqliteBindToStatement(sqlite3_stmt *&statement, sqlite3 *&db, std::vector<DistributedDB::Key> &sqlParam)
1384 {
1385     int errCode = 0;
1386     for (unsigned int index = 0; index < sqlParam.size(); index++) {
1387         if (sqlParam[index].empty()) {
1388             errCode = sqlite3_bind_zeroblob(statement, index, -1); // -1 for zero-length blob.
1389         } else {
1390             errCode = sqlite3_bind_blob(statement, index + 1, static_cast<const void*>(sqlParam[index].data()),
1391                 sqlParam[index].size(), SQLITE_TRANSIENT);
1392         }
1393         if (errCode != SQLITE_OK) {
1394             MST_LOG("[SqliteBindToStatement] Failed to bind the SQLite blob: %d", errCode);
1395             ReleaseSqliteResource(statement, db);
1396             return false;
1397         }
1398     }
1399     return true;
1400 }
1401 
1402 static bool SetSQLiteKey(sqlite3 *db, const std::vector<uint8_t> &passwd)
1403 {
1404     int errCode = sqlite3_key(db, static_cast<const void *>(passwd.data()),
1405                               static_cast<int>(passwd.size()));
1406     if (errCode != SQLITE_OK) {
1407         MST_LOG("[DistributedTestTools::SetSQLiteKey] sqlite3_key failed: %d", errCode);
1408         return false;
1409     }
1410     char *errMsg = nullptr;
1411     bool result = false;
1412     errCode = sqlite3_exec(db, CIPHER_CONFIG_SQL.c_str(), nullptr, nullptr, &errMsg);
1413     if (errCode != SQLITE_OK) {
1414         MST_LOG("[DistributedTestTools::SetSQLiteKey] config cipher failed: %d", errCode);
1415         goto END;
1416     }
1417 
1418     errCode = sqlite3_exec(db, KDF_ITER_CONFIG_SQL.c_str(), nullptr, nullptr, &errMsg);
1419     if (errCode != SQLITE_OK) {
1420         MST_LOG("[DistributedTestTools::SetSQLiteKey] config kdf iter failed: %d", errCode);
1421         goto END;
1422     }
1423     result = true;
1424 END:
1425     if (errMsg != nullptr) {
1426         sqlite3_free(errMsg);
1427         errMsg = nullptr;
1428     }
1429     return result;
1430 }
1431 
1432 bool DistributedTestTools::GetRecordCntByKey(const std::string &dbName,
1433     const std::string &strSql, std::vector<DistributedDB::Key> &sqlParam, KvOption &option, int &count)
1434 {
1435     sqlite3 *db = nullptr;
1436     std::string dbOpenName = dbName;
1437     uint64_t flag = SQLITE_OPEN_URI | SQLITE_OPEN_READWRITE;
1438     int errCode = sqlite3_open_v2(dbOpenName.c_str(), &db, flag, nullptr);
1439     if (errCode != SQLITE_OK) {
1440         MST_LOG("[DistributedTestTools::GetRecordCntByKey] sqlite3_open failed: %d", errCode);
1441         return false;
1442     }
1443 
1444     if (option.isEncryptedDb) {
1445         if (SetSQLiteKey(db, option.passwd) != true) {
1446             MST_LOG("[DistributedTestTools::GetRecordCntByKey] sqlite3 set key failed");
1447             sqlite3_close(db);
1448             return false;
1449         }
1450     }
1451 
1452     sqlite3_stmt *statement = nullptr;
1453     errCode = sqlite3_prepare(db, strSql.c_str(), -1, &statement, nullptr);
1454     if (errCode != SQLITE_OK) {
1455         MST_LOG("[DistributedTestTools::GetRecordCntByKey] sqlite3_prepare failed: %d", errCode);
1456         ReleaseSqliteResource(statement, db);
1457         return false;
1458     }
1459     if (!SqliteBindToStatement(statement, db, sqlParam)) {
1460         return false;
1461     }
1462     errCode = sqlite3_step(statement);
1463     if (errCode == SQLITE_ROW) {
1464         count = static_cast<uint64_t>(sqlite3_column_int64(statement, 0));
1465     } else {
1466         MST_LOG("[DistributedTestTools::GetRecordCntByKey] sqlite3_step failed: %d", errCode);
1467         ReleaseSqliteResource(statement, db);
1468         count = 0;
1469         return false;
1470     }
1471 
1472     ReleaseSqliteResource(statement, db);
1473     return true;
1474 }
1475 
1476 bool DistributedTestTools::QuerySpecifiedData(const std::string &dbName,
1477     const std::string &strSql, EncrypteAttribute &attribute, int &count)
1478 {
1479     sqlite3 *db = nullptr;
1480     std::string dbOpenName = dbName;
1481     uint64_t flag = SQLITE_OPEN_URI | SQLITE_OPEN_READWRITE;
1482     int nResult = sqlite3_open_v2(dbOpenName.c_str(), &db, flag, nullptr);
1483     if (nResult != SQLITE_OK) {
1484         MST_LOG("[sqlite3_open] failed: %d.", nResult);
1485         return false;
1486     }
1487 
1488     if (attribute.isEncryptedDb) {
1489         if (SetSQLiteKey(db, attribute.passwd) != true) {
1490             MST_LOG("[DistributedTestTools::QuerySpecifiedData] sqlite3 set key failed");
1491             sqlite3_close(db);
1492             return false;
1493         }
1494     }
1495 
1496     sqlite3_stmt *statement = nullptr;
1497     nResult = sqlite3_prepare(db, strSql.c_str(), -1, &statement, nullptr);
1498     if (nResult != SQLITE_OK) {
1499         MST_LOG("[sqlite3_prepare] failed %d.", nResult);
1500         sqlite3_finalize(statement);
1501         statement = nullptr;
1502         sqlite3_close(db);
1503         return false;
1504     }
1505     int errCode = sqlite3_step(statement);
1506     if (errCode != SQLITE_ROW) {
1507         MST_LOG("[sqlite3_step] failed, errCode: %d.", errCode);
1508         sqlite3_finalize(statement);
1509         statement = nullptr;
1510         sqlite3_close(db);
1511         return false;
1512     }
1513     count = static_cast<uint64_t>(sqlite3_column_int64(statement, 0));
1514     MST_LOG("The query count is %d\n.", count);
1515     sqlite3_finalize(statement);
1516     statement = nullptr;
1517     sqlite3_close(db);
1518     return true;
1519 }
1520 
1521 bool DistributedTestTools::RepeatCheckAsyncResult(const std::function<bool(void)> &inPred, int repeatLimit,
1522     uint32_t repeatInterval)
1523 {
1524     int limit = repeatLimit;
1525     while (limit != 0) {
1526         if (inPred()) {
1527             return true;
1528         }
1529         if (--limit <= 0) {
1530             MST_LOG("BREAK RepeatCheckAsyncResult :: limit %d\n", limit);
1531             break;
1532         }
1533         std::this_thread::sleep_for(std::chrono::milliseconds(repeatInterval));
1534     }
1535     return false;
1536 }
1537 
1538 bool DistributedTestTools::CompareKey(const Entry &entry1, const Entry &entry2)
1539 {
1540     return entry1.key < entry2.key;
1541 }
1542 void DistributedTestTools::CopyFile(const string &srcFile, const string &destFile)
1543 {
1544     int len = 0;
1545     char buff[BUF_LEN] = { 0 };
1546 
1547     FILE *pIn = fopen(srcFile.c_str(), "r");
1548     if (pIn == nullptr) {
1549         MST_LOG("Open srcFile failed!");
1550         return;
1551     }
1552     FILE *pOut = fopen(destFile.c_str(), "w");
1553     if (pOut == nullptr) {
1554         MST_LOG("Open destFile failed!");
1555         fclose(pIn);
1556         return;
1557     }
1558 
1559     while ((len = fread(buff, sizeof(char), sizeof(buff), pIn)) > 0) {
1560         fwrite(buff, sizeof(char), len, pOut);
1561     }
1562     fclose(pOut);
1563     fclose(pIn);
1564 }
1565 
1566 void TransactionBeforOpenDB(bool getSysInfo, steady_clock::time_point &tick,
1567     vector<Entry> &data1, vector<Key> &keys, DistributedTestSysInfo &si)
1568 {
1569     if (!getSysInfo) {
1570         MST_LOG("[gen data]:%zu, %zu.", data1.size(), keys.size());
1571         tick = time_point_cast<microseconds>(steady_clock::now());
1572     } else {
1573         MST_LOG("System info before opening a db:");
1574         GetSysInfo(si, FIRST);
1575     }
1576 }
1577 
1578 void TransactionAfterOpenDB(bool getSysInfo, steady_clock::time_point &tick,
1579     PerformanceData &performanceData, DistributedTestSysInfo &si)
1580 {
1581     if (!getSysInfo) {
1582         TickTock(tick, performanceData.openDuration);
1583         MST_LOG("[time calculator]open a new db cost %f us.", static_cast<double>(performanceData.openDuration));
1584     } else {
1585         MST_LOG("System info after opening db, or before inserting records of a transaction:");
1586         GetSysInfo(si, SECOND);
1587         si.SaveSecondToFirst();
1588     }
1589 }
1590 
1591 void TransactionAfterPutData(steady_clock::time_point &tick, PerformanceData &performanceData,
1592     int keyLength, DistributedTestSysInfo &si)
1593 {
1594     bool getSysInfo = performanceData.getSysInfo;
1595     int putGetTimes = performanceData.putGetTimes;
1596     if (!getSysInfo) {
1597         if (!TickTock1(tick, putGetTimes, performanceData.putDuration)) {
1598             MST_LOG("[time calculator]put first [%d]keys,\tvalue[%dB-length],\tcost[%fus],\tper[%fus].",
1599                 putGetTimes, keyLength, (performanceData.putDuration) * putGetTimes,
1600                 performanceData.putDuration);
1601         }
1602     } else {
1603         MST_LOG("System info after inserting records of a transaction, or before querying records one by one:");
1604         GetSysInfo(si, SECOND);
1605         si.SaveSecondToFirst();
1606     }
1607 }
1608 
1609 void TransactionAfterQueryPutData(steady_clock::time_point &tick, PerformanceData &performanceData,
1610     int keyLength, DistributedTestSysInfo &si)
1611 {
1612     bool getSysInfo = performanceData.getSysInfo;
1613     int putGetTimes = performanceData.putGetTimes;
1614     if (!getSysInfo) {
1615         if (!TickTock1(tick, putGetTimes, performanceData.readPutDuration)) {
1616             MST_LOG("[time calculator]get first [%d]keys,\tvalue[%dB-length],\tcost[%fus],\tper[%fus].",
1617                 putGetTimes, keyLength, (performanceData.readPutDuration) * putGetTimes,
1618                 performanceData.readPutDuration);
1619         }
1620     } else {
1621         MST_LOG("System info after querying records one by one, or before updating records in a transaction:");
1622         GetSysInfo(si, SECOND);
1623         si.SaveSecondToFirst();
1624     }
1625 }
1626 
1627 void TransactionAfterUpdateData(steady_clock::time_point &tick, PerformanceData &performanceData,
1628     int keyLength, DistributedTestSysInfo &si)
1629 {
1630     bool getSysInfo = performanceData.getSysInfo;
1631     int putGetTimes = performanceData.putGetTimes;
1632     if (!getSysInfo) {
1633         if (!TickTock1(tick, putGetTimes, performanceData.updateDuration)) {
1634             MST_LOG("[time calculator]put second [%d]keys,\tvalue[%dB-length],\tcost[%fus],\tper[%fus].",
1635                 putGetTimes, keyLength, (performanceData.updateDuration) * putGetTimes,
1636                 performanceData.updateDuration);
1637         }
1638     } else {
1639         MST_LOG("System info after updating records in a transaction, or before updating records one by one:");
1640         GetSysInfo(si, SECOND);
1641         si.SaveSecondToFirst();
1642     }
1643 }
1644 
1645 void TransactionAfterQueryUpdateData(steady_clock::time_point &tick, PerformanceData &performanceData,
1646     int keyLength, DistributedTestSysInfo &si)
1647 {
1648     bool getSysInfo = performanceData.getSysInfo;
1649     int putGetTimes = performanceData.putGetTimes;
1650     if (!getSysInfo) {
1651         if (!TickTock1(tick, putGetTimes, performanceData.readUpdateDuration)) {
1652             MST_LOG("[time calculator]get second [%d]keys,\tvalue[%dB-length],\tcost[%fus],\tper[%fus].",
1653                 putGetTimes, keyLength, (performanceData.readUpdateDuration) * putGetTimes,
1654                 performanceData.readUpdateDuration);
1655         }
1656     } else {
1657         MST_LOG("System info after updating records one by one, or before deleting records in a transaction:");
1658         GetSysInfo(si, SECOND);
1659         si.SaveSecondToFirst();
1660     }
1661 }
1662 
1663 void TransactionAfterDeleteData(steady_clock::time_point &tick, PerformanceData &performanceData,
1664     int keyLength, DistributedTestSysInfo &si)
1665 {
1666     bool getSysInfo = performanceData.getSysInfo;
1667     int putGetTimes = performanceData.putGetTimes;
1668     if (!getSysInfo) {
1669         if (!TickTock1(tick, putGetTimes, performanceData.deleteDuration)) {
1670             MST_LOG("[time calculator]delete [%d]keys,\tvalue[%dB-length],\tcost[%fus],\tper[%fus].",
1671                 putGetTimes, keyLength, (performanceData.deleteDuration) * putGetTimes,
1672                 performanceData.deleteDuration);
1673         }
1674     } else {
1675         MST_LOG("System info after deleting records in a transaction, or before closing a db:");
1676         GetSysInfo(si, SECOND);
1677         si.SaveSecondToFirst();
1678     }
1679 }
1680 
1681 void TransactionAfterCloseDB(steady_clock::time_point &tick, PerformanceData &performanceData,
1682     DistributedTestSysInfo &si)
1683 {
1684     bool getSysInfo = performanceData.getSysInfo;
1685     int putGetTimes = performanceData.putGetTimes;
1686     if (!getSysInfo) {
1687         if (!TickTock1(tick, putGetTimes, performanceData.closeDuration)) {
1688             MST_LOG("[time calculator]close a db cost %f us.", static_cast<double>(performanceData.closeDuration));
1689         }
1690     } else {
1691         MST_LOG("System info after closing a db:");
1692         GetSysInfo(si, SECOND);
1693         si.SaveSecondToFirst();
1694     }
1695 }
1696 
1697 bool BeginTransaction1(vector<Entry> &data1, KvStoreDelegate *store1)
1698 {
1699     bool result = true;
1700     result = result && (store1->StartTransaction() == DBStatus::OK);
1701     for (auto entry = data1.begin(); entry != data1.end(); ++entry) {
1702         result = result && (DistributedTestTools::Put(*store1, entry->key, entry->value) == DBStatus::OK);
1703     }
1704     result = result && (store1->Commit() == DBStatus::OK);
1705     return result;
1706 }
1707 
1708 bool BeginTransaction2(vector<Entry> &data1, KvStoreDelegate *store1, Value updateVal)
1709 {
1710     bool result = true;
1711     result = result && (store1->StartTransaction() == DBStatus::OK);
1712     for (auto entry = data1.begin(); entry != data1.end(); ++entry) {
1713         result = result && (DistributedTestTools::Put(*store1, entry->key, updateVal) == DBStatus::OK);
1714     }
1715     result = result && (store1->Commit() == DBStatus::OK);
1716     return result;
1717 }
1718 
1719 bool BeginTransaction3(KvStoreDelegate *store1, vector<Key> &keys)
1720 {
1721     bool result = true;
1722     result = result && (store1->StartTransaction() == DBStatus::OK);
1723     for (auto key = keys.begin(); key != keys.end(); ++key) {
1724         result = result && (DistributedTestTools::Delete(*store1, *key) == DBStatus::OK);
1725     }
1726     result = result && (store1->Commit() == DBStatus::OK);
1727     return result;
1728 }
1729 
1730 bool CheckSnapShot1(KvStoreSnapshotDelegate *snapShot, KvStoreDelegate *store1, vector<Key> &keys)
1731 {
1732     if (snapShot == nullptr) {
1733         return false;
1734     }
1735     for (auto key = keys.begin(); key != keys.end(); ++key) {
1736         Value valueResult = DistributedTestTools::Get(*snapShot, *key);
1737     }
1738     store1->ReleaseKvStoreSnapshot(snapShot);
1739     snapShot = nullptr;
1740     return true;
1741 }
1742 
1743 bool CheckSnapShot2(KvStoreSnapshotDelegate *snapShot, KvStoreDelegate *store1, vector<Key> &keys)
1744 {
1745     snapShot = DistributedTestTools::GetKvStoreSnapshot(*store1);
1746     if (snapShot == nullptr)  {
1747         return false;
1748     }
1749     for (auto key = keys.begin(); key != keys.end(); ++key) {
1750         Value valueResult = DistributedTestTools::Get(*snapShot, *key);
1751     }
1752     store1->ReleaseKvStoreSnapshot(snapShot);
1753     snapShot = nullptr;
1754     return true;
1755 }
1756 
1757 bool CloseDB(KvStoreDelegateManager *manager, KvStoreDelegate *store1)
1758 {
1759     DBStatus status = manager->CloseKvStore(store1);
1760     if (status != DistributedDB::DBStatus::OK) {
1761         return false;
1762     }
1763     store1 = nullptr;
1764     status = manager->DeleteKvStore(STORE_ID_PERFORM);
1765     if (status != DistributedDB::DBStatus::OK) {
1766         return false;
1767     }
1768     delete manager;
1769     manager = nullptr;
1770     return true;
1771 }
1772 
1773 bool DistributedTestTools::CalculateTransactionPerformance(PerformanceData &performanceData)
1774 {
1775     int putGetTimes = performanceData.putGetTimes;
1776     int keyLength = performanceData.keyLength;
1777     int valueLength = performanceData.valueLength;
1778     bool getSysInfo = performanceData.getSysInfo;
1779     DistributedTestSysInfo si;
1780     steady_clock::time_point tick;
1781     vector<Entry> data1 = GenRanKeyVal(putGetTimes, keyLength, valueLength, 'a');
1782     vector<Key> keys = GetKeysFromEntries(data1, false);
1783     Value updateVal;
1784     updateVal.assign(valueLength, 'b');
1785     TransactionBeforOpenDB(getSysInfo, tick, data1, keys, si);
1786     // print the opened time.
1787     KvStoreDelegate *store1 = nullptr;
1788     KvStoreDelegateManager *manager = nullptr;
1789     KvOption option = g_kvOption;
1790     option.localOnly = performanceData.isLocal;
1791     store1 = GetDelegateSuccess(manager, KVDB_PARAMETER_PERFORM, option);
1792     if (store1 == nullptr) {
1793         return false;
1794     }
1795     TransactionAfterOpenDB(getSysInfo, tick, performanceData, si);
1796     // print the insert time.
1797     BeginTransaction1(data1, store1);
1798     TransactionAfterPutData(tick, performanceData, keyLength, si);
1799     // print the get time.
1800     KvStoreSnapshotDelegate *snapShot;
1801     snapShot = DistributedTestTools::GetKvStoreSnapshot(*store1);
1802     if (!(CheckSnapShot1(snapShot, store1, keys))) {
1803         return false;
1804     }
1805     TransactionAfterQueryPutData(tick, performanceData, keyLength, si);
1806     // print the update time.
1807     BeginTransaction2(data1, store1, updateVal);
1808     TransactionAfterUpdateData(tick, performanceData, keyLength, si);
1809     // print the get time.
1810     if (!(CheckSnapShot2(snapShot, store1, keys))) {
1811         return false;
1812     }
1813     TransactionAfterQueryUpdateData(tick, performanceData, keyLength, si);
1814     BeginTransaction3(store1, keys);
1815     TransactionAfterDeleteData(tick, performanceData, keyLength, si);
1816     // close the base db
1817     if (!(CloseDB(manager, store1))) {
1818         return false;
1819     }
1820     TransactionAfterCloseDB(tick, performanceData, si);
1821     return true;
1822 }
1823 
1824 KvStoreSnapshotDelegate *DistributedTestTools::RegisterSnapObserver(KvStoreDelegate *delegate,
1825     KvStoreObserver *observer)
1826 {
1827     DelegateCallback delegateCallback;
1828     function<void(DBStatus, KvStoreSnapshotDelegate *)> callFunction
1829         = bind(&DelegateCallback::Callback, &delegateCallback, _1, _2);
1830 
1831     delegate->GetKvStoreSnapshot(observer, callFunction);
1832     DBStatus status = delegateCallback.GetStatus();
1833     if (status != DBStatus::OK) {
1834         MST_LOG("%s Get failed! Status= %d", TAG.c_str(), status);
1835         return nullptr;
1836     }
1837 
1838     KvStoreSnapshotDelegate *snapshot
1839         = const_cast<KvStoreSnapshotDelegate *>(delegateCallback.GetKvStoreSnapshot());
1840     if (snapshot == nullptr) {
1841         MST_LOG("%s Get snapshot null! Status= %d", TAG.c_str(), status);
1842         return nullptr;
1843     }
1844     return snapshot;
1845 }
1846 
1847 DBStatus DistributedTestTools::RegisterObserver(KvStoreDelegate *delegate, KvStoreObserver *observer)
1848 {
1849     return delegate->RegisterObserver(observer);
1850 }
1851 
1852 DBStatus DistributedTestTools::UnRegisterObserver(KvStoreDelegate *delegate, KvStoreObserver *observer)
1853 {
1854     return delegate->UnRegisterObserver(observer);
1855 }
1856 
1857 KvStoreDelegate::Option DistributedTestTools::TransferKvOptionType(const KvOption &optionParam)
1858 {
1859     KvStoreDelegate::Option option;
1860     option.createIfNecessary = optionParam.createIfNecessary;
1861     option.localOnly = optionParam.localOnly;
1862     option.isEncryptedDb = optionParam.isEncryptedDb;
1863     option.cipher = optionParam.cipher;
1864     (void)option.passwd.SetValue(optionParam.passwd.data(), optionParam.passwd.size());
1865     return option;
1866 }
1867 
1868 std::string TransferStringToHashHexString(const std::string &origStr)
1869 {
1870     SHA256_CTX context;
1871     SHA256_Init(&context);
1872     SHA256_Update(&context, origStr.data(), origStr.size());
1873     std::vector<uint8_t> hashVect(SHA256_DIGEST_LENGTH, 0);
1874     SHA256_Final(hashVect.data(), &context);
1875 
1876     const char *hex = "0123456789abcdef";
1877     std::string tmp;
1878     for (size_t i = 0; i < SHA256_DIGEST_LENGTH; i++) {
1879         tmp.push_back(hex[hashVect[i] >> 4]); // high 4 bit to one hex.
1880         tmp.push_back(hex[hashVect[i] & 0x0F]); // low 4 bit to one hex.
1881     }
1882     return tmp;
1883 }
1884 
1885 #if defined(RUNNING_ON_LINUX)
1886 int RemoveDatabaseDirectory(const std::string &directory)
1887 {
1888 #ifdef DB_DEBUG_ENV
1889     MST_LOG("---> remove db directory: %s", directory.c_str());
1890 #endif
1891     return remove(directory.c_str());
1892 }
1893 #else
1894 int RemoveDatabaseDirectory(const std::string &directory)
1895 {
1896     return rmdir(directory.c_str());
1897 }
1898 #endif
1899 
1900 bool VerifyObserverResult(const KvStoreObserverImpl &pObserver,
1901     int changedTimes, ListType type, const list<Entry> &lst, uint32_t timeout)
1902 {
1903     MST_LOG("[VerifyObserverResult] pObserver.GetCumulatedFlag() = %d, pObserver.GetChanged() = %d, type = %d",
1904         pObserver.GetCumulatedFlag(), pObserver.GetChanged(), type);
1905     if (pObserver.GetCumulatedFlag()) {
1906         int expectListSize = lst.size();
1907         pObserver.WaitUntilReachRecordCount(expectListSize, type, timeout);
1908     } else {
1909         pObserver.WaitUntilReachChangeCount(changedTimes, timeout);
1910     }
1911 
1912     list<Entry> retLst;
1913     if (pObserver.GetCumulatedFlag()) {
1914         if (type == INSERT_LIST) {
1915             MST_LOG("type == INSERT_LIST");
1916             retLst = pObserver.GetCumulatedInsertList();
1917         } else if (type == UPDATE_LIST) {
1918             MST_LOG("type == UPDATE_LIST");
1919             retLst = pObserver.GetCumulatedUpdateList();
1920         } else {
1921             MST_LOG("type == DELETE_LIST");
1922             retLst = pObserver.GetCumulatedDeleteList();
1923         }
1924     } else {
1925         if (type == INSERT_LIST) {
1926             MST_LOG("type == INSERT_LIST");
1927             retLst = pObserver.GetInsertList();
1928         } else if (type == UPDATE_LIST) {
1929             MST_LOG("type == UPDATE_LIST");
1930             retLst = pObserver.GetUpdateList();
1931         } else {
1932             MST_LOG("type == DELETE_LIST");
1933             retLst = pObserver.GetDeleteList();
1934         }
1935     }
1936 
1937     bool result = true;
1938     vector<Entry> retVec(retLst.begin(), retLst.end());
1939     vector<Entry> expectVec(lst.begin(), lst.end());
1940     result = CompareEntriesVector(retVec, expectVec);
1941     MST_LOG("VerifyObserverResult CompareEntriesVector result is %d", result);
1942     return result;
1943 }
1944 
1945 bool VerifyObserverResult(const KvStoreObserverImpl &pObserver, int changedTimes, ListType type,
1946     const vector<Entry> &vec, uint32_t timeout)
1947 {
1948     list<Entry> entriesList(vec.begin(), vec.end());
1949     return VerifyObserverResult(pObserver, changedTimes, type, entriesList, timeout);
1950 }
1951 
1952 bool VerifyObserverForSchema(const KvStoreObserverImpl &pObserver,
1953     int changedTimes, ListType type, const vector<Entry> &expectEntry, uint32_t timeout)
1954 {
1955     MST_LOG("[VerifyObserverForSchema] pObserver.GetCumulatedFlag() = %d, pObserver.GetChanged() = %d, type = %d",
1956         pObserver.GetCumulatedFlag(), pObserver.GetChanged(), type);
1957     if (pObserver.GetCumulatedFlag()) {
1958         int expectListSize = expectEntry.size();
1959         pObserver.WaitUntilReachRecordCount(expectListSize, type, timeout);
1960     } else {
1961         pObserver.WaitUntilReachChangeCount(changedTimes, timeout);
1962     }
1963 
1964     list<Entry> retLst;
1965     if (pObserver.GetCumulatedFlag()) {
1966         if (type == INSERT_LIST) {
1967             MST_LOG("type == INSERT_LIST");
1968             retLst = pObserver.GetCumulatedInsertList();
1969         } else if (type == UPDATE_LIST) {
1970             MST_LOG("type == UPDATE_LIST");
1971             retLst = pObserver.GetCumulatedUpdateList();
1972         } else {
1973             MST_LOG("type == DELETE_LIST");
1974             retLst = pObserver.GetCumulatedDeleteList();
1975         }
1976     } else {
1977         if (type == INSERT_LIST) {
1978             MST_LOG("type == INSERT_LIST");
1979             retLst = pObserver.GetInsertList();
1980         } else if (type == UPDATE_LIST) {
1981             MST_LOG("type == UPDATE_LIST");
1982             retLst = pObserver.GetUpdateList();
1983         } else {
1984             MST_LOG("type == DELETE_LIST");
1985             retLst = pObserver.GetDeleteList();
1986         }
1987     }
1988 
1989     vector<Entry> retVec(retLst.begin(), retLst.end());
1990     if (retVec.size() != expectEntry.size()) {
1991         MST_LOG("[VerifyObserverForSchema] the expect value size is not equal to the retVec size and return");
1992         return false;
1993     }
1994 
1995     for (uint64_t index = 0; index < expectEntry.size(); index++) {
1996         bool result = ((retVec[index].key == expectEntry[index].key) &&
1997             (retVec[index].value == expectEntry[index].value));
1998         if (!result) {
1999             MST_LOG("[VerifyObserverForSchema] compare list failed at the position: %llu", ULL(index));
2000             return false;
2001         }
2002     }
2003     return true;
2004 }