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