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 ¶m, 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 ¶m, 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 }