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