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 #ifndef OMIT_MULTI_VER
16 #include "distributed_crud_transaction_tools.h"
17 #include <gtest/gtest.h>
18 #include <dirent.h>
19 #include <string>
20 #include <sys/stat.h>
21 #include <random>
22 #include <algorithm>
23 #include <thread>
24 #include <cstdio>
25 #include <chrono>
26 #include <cmath>
27
28 #include "distributed_test_tools.h"
29 #include "distributeddb_data_generator.h"
30 #include "kv_store_delegate.h"
31 #include "kv_store_delegate_manager.h"
32
33 using namespace std;
34 using namespace chrono;
35 using namespace std::placeholders;
36 using namespace DistributedDB;
37 using namespace DistributedDBDataGenerator;
38
DistributedCrudTransactionTools(KvStoreDelegate & delegate,CrudMode first,CrudMode second,bool preset,bool isLocal)39 DistributedCrudTransactionTools::DistributedCrudTransactionTools(KvStoreDelegate &delegate,
40 CrudMode first, CrudMode second, bool preset, bool isLocal)
41 {
42 this->storeDelegate_ = &delegate,
43 this->firstMode_ = first;
44 this->secondMode_ = second;
45 this->needPresetData_ = preset;
46 this->isLocal_ = isLocal;
47 }
48
PresetValue()49 bool DistributedCrudTransactionTools::PresetValue()
50 {
51 vector<Entry> entriesBatch;
52 vector<Key> allKeys;
53 GenerateRecords(this->presetCount_, DEFAULT_START, allKeys, entriesBatch);
54
55 for (unsigned long i = 0; i < this->presetCount_; ++i) {
56 entriesBatch[i].value = GetValueWithInt(this->presetValue_);
57 }
58 DBStatus status = DistributedTestTools::PutBatch(*storeDelegate_, entriesBatch);
59 if (status != DistributedDB::OK) {
60 MST_LOG("PresetValue failed, status %d", status);
61 return false;
62 }
63 return true;
64 }
65
CheckFirst()66 bool DistributedCrudTransactionTools::CheckFirst()
67 {
68 vector<Entry> values = DistributedTestTools::GetEntries(*storeDelegate_, KEY_SEARCH_4);
69 if (firstMode_ == CrudMode::PUT_BATCH) {
70 MST_LOG("[CHECK LOG]putbatch first %zu", values.size());
71 if (needPresetData_) {
72 if (values.size() != 0) {
73 return GetIntValue(values[0].value) == presetValue_;
74 } else {
75 return true;
76 }
77 } else {
78 return (values.size() == NO_RECORD) || (values.size() == presetCount_);
79 }
80 }
81 if (firstMode_ == CrudMode::UPDATE_BATCH) {
82 if (values.size() != presetCount_) {
83 return false;
84 }
85 for (unsigned long index = 0; index < values.size(); ++index) {
86 if (GetIntValue(values[index].value) != presetValue_) {
87 return false;
88 }
89 }
90 return true;
91 }
92 if (firstMode_ == CrudMode::DELETE_BATCH || firstMode_ == CrudMode::CLEAR) {
93 MST_LOG("[CHECK LOG]check clear first %zu", values.size());
94 if ((values.size() > NO_RECORD) && (values.size() < presetCount_)) {
95 return false;
96 }
97 return (values.size() == NO_RECORD) ||
98 ((values.size() == presetCount_ && GetIntValue(values[0].value) == presetValue_));
99 }
100 return false;
101 }
102
CheckSecond()103 bool DistributedCrudTransactionTools::CheckSecond()
104 {
105 if (secondMode_ == CrudMode::PUT) {
106 vector<Entry> values = DistributedTestTools::GetEntries(*storeDelegate_, KEY_SEARCH_4);
107 return values.size() == NO_RECORD || GetIntValue(values[0].value) == SMALL_VALUE_SIZE ||
108 GetIntValue(values[0].value) == presetValue_;
109 }
110 if (secondMode_ == CrudMode::DELETE) {
111 Key key0 = { 'k', '0' };
112 Value value = DistributedTestTools::Get(*storeDelegate_, key0);
113 return value.size() == NO_RECORD || GetIntValue(value) == presetValue_;
114 }
115 if (secondMode_ == CrudMode::PUT_BATCH) {
116 vector<Entry> values = DistributedTestTools::GetEntries(*storeDelegate_, KEY_SEARCH_4);
117 if ((values.size() != NO_RECORD) && (values.size() != presetCount_)) {
118 return false;
119 }
120 for (unsigned long index = 0; index < values.size(); ++index) {
121 if (GetIntValue(values[0].value) != presetValue_) {
122 return false;
123 }
124 }
125 return true;
126 }
127 if (secondMode_ == CrudMode::DELETE_BATCH || secondMode_ == CrudMode::CLEAR) {
128 vector<Entry> values = DistributedTestTools::GetEntries(*storeDelegate_, KEY_SEARCH_4);
129 if ((values.size() != NO_RECORD) && (values.size() != presetCount_)) {
130 return false;
131 }
132 for (unsigned long index = 0; index < values.size(); ++index) {
133 if (GetIntValue(values[0].value) != presetValue_) {
134 return false;
135 }
136 }
137 return true;
138 }
139 return false;
140 }
141
Check()142 void DistributedCrudTransactionTools::Check()
143 {
144 while (!secondComplete_) {
145 if (!firstComplete_) {
146 bool result = CheckFirst();
147 if (!result) {
148 MST_LOG("[CHECK LOG]check first failed;%d", success_);
149 }
150 MST_LOG("[CHECK LOG]firstComplete_ failed %d;", success_);
151 success_ = result;
152 } else if (firstComplete_ && !secondComplete_) {
153 bool result = CheckSecond();
154 if (!result) {
155 MST_LOG("[CHECK LOG]check second failed;%d", success_);
156 }
157 MST_LOG("[CHECK LOG]secondComplete_ failed %d;", success_);
158 success_ = result;
159 }
160 }
161 }
162
Action1(KvStoreDelegate & delegate)163 bool DistributedCrudTransactionTools::Action1(KvStoreDelegate &delegate)
164 {
165 MST_LOG("firstmode %d", static_cast<int>(firstMode_));
166 if (firstMode_ == CrudMode::PUT_BATCH) {
167 return DBStatus::OK == delegate.PutBatch(entriesBatch_);
168 } else if (firstMode_ == CrudMode::DELETE_BATCH) {
169 return DBStatus::OK == delegate.DeleteBatch(allKeys_) ||
170 DBStatus::NOT_FOUND == delegate.DeleteBatch(allKeys_);
171 } else if (firstMode_ == CrudMode::CLEAR) {
172 return DBStatus::OK == delegate.Clear();
173 } else {
174 MST_LOG("unknown first %d", static_cast<int>(firstMode_));
175 return false;
176 }
177 }
178
Action2(KvStoreDelegate & delegate)179 bool DistributedCrudTransactionTools::Action2(KvStoreDelegate &delegate)
180 {
181 MST_LOG("secondmode %d", static_cast<int>(secondMode_));
182 if (secondMode_ == CrudMode::PUT) {
183 entriesBatch_[0].value = GetValueWithInt(SMALL_VALUE_SIZE);
184 return DBStatus::OK == delegate.Put(entriesBatch_[0].key, entriesBatch_[0].value);
185 } else if (secondMode_ == CrudMode::DELETE) {
186 return DBStatus::OK == delegate.Delete(entriesBatch_[0].key) ||
187 DBStatus::NOT_FOUND == delegate.DeleteBatch(allKeys_);
188 } else if (secondMode_ == CrudMode::CLEAR) {
189 return DBStatus::OK == delegate.Clear();
190 } else if (secondMode_ == CrudMode::PUT_BATCH) {
191 return DBStatus::OK == delegate.PutBatch(entriesBatch_);
192 } else {
193 MST_LOG("unknown secondmode %d", static_cast<int>(secondMode_));
194 return false;
195 }
196 }
197
SleepOneSecond()198 void SleepOneSecond()
199 {
200 std::this_thread::sleep_for(std::chrono::duration<int>(1));
201 }
202
DeleteDataBase(bool success_,KvStoreDelegate * & delegate1,KvStoreDelegate * & delegate2,KvStoreDelegateManager * & delegateManager1,KvStoreDelegateManager * & delegateManager2)203 bool DeleteDataBase(bool success_, KvStoreDelegate *&delegate1, KvStoreDelegate *&delegate2,
204 KvStoreDelegateManager *&delegateManager1, KvStoreDelegateManager *&delegateManager2)
205 {
206 SleepOneSecond();
207 if ((delegateManager1->CloseKvStore(delegate1) != OK) ||
208 (delegateManager2->CloseKvStore(delegate2) != OK)) {
209 MST_LOG("closed failed!");
210 }
211 delegate1 = nullptr;
212 delegate2 = nullptr;
213 delete delegateManager1;
214 delegateManager1 = nullptr;
215 delete delegateManager2;
216 delegateManager2 = nullptr;
217 MST_LOG("[CHECK LOG]check result %d", success_);
218 return success_;
219 }
220
testCrudTransaction()221 bool DistributedCrudTransactionTools::testCrudTransaction()
222 {
223 if (storeDelegate_ == nullptr) {
224 return false;
225 }
226
227 DistributedTestTools::Clear(*storeDelegate_);
228 if (this->needPresetData_) {
229 if (!PresetValue()) {
230 return false;
231 }
232 }
233 GenerateRecords(this->presetCount_, DEFAULT_START, allKeys_, entriesBatch_);
234 for (unsigned long i = 0; i < this->presetCount_; ++i) {
235 entriesBatch_[i].value = GetValueWithInt(this->presetValue_);
236 }
237
238 KvStoreDelegate *delegate1 = nullptr;
239 KvStoreDelegateManager *delegateManager1 = nullptr;
240 delegate1 = DistributedTestTools::GetDelegateSuccess(delegateManager1,
241 g_kvdbParameter1, g_kvOption);
242 if (delegateManager1 == nullptr || delegate1 == nullptr) {
243 MST_LOG("[testCrudTransaction] delegateManager1 or delegate1 is nullptr");
244 return false;
245 }
246
247 KvStoreDelegate *delegate2 = nullptr;
248 KvStoreDelegateManager *delegateManager2 = nullptr;
249 delegate2 = DistributedTestTools::GetDelegateSuccess(delegateManager2,
250 g_kvdbParameter1, g_kvOption);
251 if (delegateManager2 == nullptr || delegate2 == nullptr) {
252 MST_LOG("[testCrudTransaction] delegateManager2 or delegate2 is nullptr");
253 return false;
254 }
255
256 std::thread th(&DistributedCrudTransactionTools::Check, this);
257 th.detach();
258
259 if (!Action1(*delegate1)) {
260 MST_LOG("action1 failed");
261 goto ERROR;
262 }
263 firstComplete_ = true;
264 MST_LOG("firstComplete_");
265
266 if (!Action2(*delegate2)) {
267 MST_LOG("action2 failed");
268 goto ERROR;
269 }
270 secondComplete_ = true;
271 return DeleteDataBase(success_, delegate1, delegate2, delegateManager1, delegateManager2);
272 ERROR:
273 secondComplete_ = true;
274 return false;
275 }
276 #endif // OMIT_MULTI_VER