1 /*
2 Copyright (c) 2005, 2021, Oracle and/or its affiliates.
3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License, version 2.0,
6 as published by the Free Software Foundation.
7
8 This program is also distributed with certain software (including
9 but not limited to OpenSSL) that is licensed under separate terms,
10 as designated in a particular file or component or in included license
11 documentation. The authors of MySQL hereby grant you an additional
12 permission to link the program and your derivative works with the
13 separately licensed software that they have included with MySQL.
14
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License, version 2.0, for more details.
19
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
23 */
24
25 #include <NDBT.hpp>
26 #include <NDBT_Test.hpp>
27 #include <HugoTransactions.hpp>
28 #include <UtilTransactions.hpp>
29 #include <NdbBackup.hpp>
30
31 #include "bank/Bank.hpp"
32 #include <NdbMixRestarter.hpp>
33
34 bool disk = false;
35
runCreateBank(NDBT_Context * ctx,NDBT_Step * step)36 int runCreateBank(NDBT_Context* ctx, NDBT_Step* step){
37 Bank bank(ctx->m_cluster_connection);
38 int overWriteExisting = true;
39 if (bank.createAndLoadBank(overWriteExisting, disk, 10) != NDBT_OK)
40 return NDBT_FAILED;
41 return NDBT_OK;
42 }
43
44 /**
45 *
46 * SR_RUNNING (0) - Normal, no failures are allowed.
47 * SR_STOPPING (1) - Shutdown in progress, failures should
48 * be expected/ignored, and operations retried.
49 * SR_STOPPED (2) - restart in progress, halt operations
50 * until we are SR_RUNNING.
51 */
52 int
runBankTimer(NDBT_Context * ctx,NDBT_Step * step)53 runBankTimer(NDBT_Context* ctx, NDBT_Step* step){
54 int wait = 5; // Max seconds between each "day"
55 int yield = 1; // Loops before bank returns
56
57 while (!ctx->isTestStopped())
58 {
59 Bank bank(ctx->m_cluster_connection);
60 ctx->incProperty(NMR_SR_THREADS_ACTIVE);
61 while(!ctx->isTestStopped() &&
62 ctx->getProperty(NMR_SR) <= NdbMixRestarter::SR_STOPPING)
63 {
64 if(bank.performIncreaseTime(wait, yield) == NDBT_FAILED)
65 {
66 ndbout << "performIncreaseTime FAILED" << endl;
67 if (ctx->getProperty(NMR_SR) == NdbMixRestarter::SR_RUNNING)
68 return NDBT_FAILED;
69 else
70 break; // Possibly retry
71 }
72 }
73
74 ndbout_c("runBankTimer is stopped");
75 ctx->decProperty(NMR_SR_THREADS_ACTIVE);
76 if(ctx->getPropertyWait(NMR_SR, NdbMixRestarter::SR_RUNNING))
77 break;
78 }
79 return NDBT_OK;
80 }
81
runBankTransactions(NDBT_Context * ctx,NDBT_Step * step)82 int runBankTransactions(NDBT_Context* ctx, NDBT_Step* step){
83 int wait = 0; // Max ms between each transaction
84 int yield = 1; // Loops before bank returns
85
86 while (!ctx->isTestStopped())
87 {
88 Bank bank(ctx->m_cluster_connection);
89 ctx->incProperty(NMR_SR_THREADS_ACTIVE);
90 while(!ctx->isTestStopped() &&
91 ctx->getProperty(NMR_SR) <= NdbMixRestarter::SR_STOPPING)
92 {
93 if(bank.performTransactions(wait, yield) == NDBT_FAILED)
94 {
95 ndbout << "performTransactions FAILED" << endl;
96 if (ctx->getProperty(NMR_SR) == NdbMixRestarter::SR_RUNNING)
97 return NDBT_FAILED;
98 else
99 break; // Possibly retry
100 }
101 }
102 ndbout_c("runBankTransactions is stopped");
103 ctx->decProperty(NMR_SR_THREADS_ACTIVE);
104 if(ctx->getPropertyWait(NMR_SR, NdbMixRestarter::SR_RUNNING))
105 break;
106 }
107 return NDBT_OK;
108 }
109
runBankGL(NDBT_Context * ctx,NDBT_Step * step)110 int runBankGL(NDBT_Context* ctx, NDBT_Step* step){
111 int yield = 1; // Loops before bank returns
112
113 while (ctx->isTestStopped() == false)
114 {
115 Bank bank(ctx->m_cluster_connection);
116 ctx->incProperty(NMR_SR_THREADS_ACTIVE);
117 while(!ctx->isTestStopped() &&
118 ctx->getProperty(NMR_SR) <= NdbMixRestarter::SR_STOPPING)
119 {
120 if (bank.performMakeGLs(yield) == NDBT_FAILED)
121 {
122 ndbout << "bank.performMakeGLs FAILED" << endl;
123 if (ctx->getProperty(NMR_SR) == NdbMixRestarter::SR_RUNNING)
124 return NDBT_FAILED;
125 else
126 break; // Possibly retry
127 }
128 }
129 ndbout_c("runBankGL is stopped");
130 ctx->decProperty(NMR_SR_THREADS_ACTIVE);
131 if(ctx->getPropertyWait(NMR_SR, NdbMixRestarter::SR_RUNNING))
132 break;
133 }
134 return NDBT_OK;
135 }
136
137 int
runBankSrValidator(NDBT_Context * ctx,NDBT_Step * step)138 runBankSrValidator(NDBT_Context* ctx, NDBT_Step* step)
139 {
140 ctx->incProperty(NMR_SR_VALIDATE_THREADS);
141
142 while(!ctx->isTestStopped())
143 {
144 if (ctx->getPropertyWait(NMR_SR, NdbMixRestarter::SR_VALIDATING))
145 break;
146
147 int wait = 0;
148 int yield = 1;
149 Bank bank(ctx->m_cluster_connection);
150 if (bank.performSumAccounts(wait, yield) != 0)
151 {
152 ndbout << "bank.performSumAccounts FAILED" << endl;
153 return NDBT_FAILED;
154 }
155
156 if (bank.performValidateAllGLs() != 0)
157 {
158 ndbout << "bank.performValidateAllGLs FAILED" << endl;
159 return NDBT_FAILED;
160 }
161
162 ndbout_c("runBankSrValidator is stopped");
163 ctx->decProperty(NMR_SR_VALIDATE_THREADS_ACTIVE);
164
165 if (ctx->getPropertyWait(NMR_SR, NdbMixRestarter::SR_RUNNING))
166 break;
167 }
168
169 ctx->decProperty(NMR_SR_VALIDATE_THREADS);
170 return NDBT_OK;
171 }
172
runBankSum(NDBT_Context * ctx,NDBT_Step * step)173 int runBankSum(NDBT_Context* ctx, NDBT_Step* step)
174 {
175 int wait = 2000; // Max ms between each sum of accounts
176 int yield = 1; // Loops before bank returns
177
178 while (!ctx->isTestStopped())
179 {
180 Bank bank(ctx->m_cluster_connection);
181 ctx->incProperty(NMR_SR_THREADS_ACTIVE);
182 while(!ctx->isTestStopped() &&
183 ctx->getProperty(NMR_SR) <= NdbMixRestarter::SR_STOPPING)
184 {
185 if (bank.performSumAccounts(wait, yield) == NDBT_FAILED)
186 {
187 ndbout << "bank.performSumAccounts FAILED" << endl;
188 if (ctx->getProperty(NMR_SR) == NdbMixRestarter::SR_RUNNING)
189 return NDBT_FAILED;
190 else
191 break; // Possibly retry
192 }
193 }
194 ndbout_c("performSumAccounts is stopped");
195 ctx->decProperty(NMR_SR_THREADS_ACTIVE);
196 if(ctx->getPropertyWait(NMR_SR, NdbMixRestarter::SR_RUNNING))
197 break;
198 }
199 return NDBT_OK;
200 }
201
202 int
runMixRestart(NDBT_Context * ctx,NDBT_Step * step)203 runMixRestart(NDBT_Context* ctx, NDBT_Step* step)
204 {
205 NdbMixRestarter res;
206 int runtime = ctx->getNumLoops();
207 int sleeptime = ctx->getNumRecords();
208 Uint32 mask = ctx->getProperty("Type", ~(Uint32)0);
209 res.setRestartTypeMask(mask);
210
211 if (res.runPeriod(ctx, step, runtime, sleeptime))
212 {
213 return NDBT_FAILED;
214 }
215
216 ctx->stopTest();
217 return NDBT_OK;
218 }
219
220 /**
221 * Verify Bank consisteny after load has been stopped.
222 * Then, unconditionaly drop the Bank-DB
223 */
224 int
runVerifyAndDropBank(NDBT_Context * ctx,NDBT_Step * step)225 runVerifyAndDropBank(NDBT_Context* ctx, NDBT_Step* step)
226 {
227 int wait = 0;
228 int yield = 1;
229 int result = NDBT_OK;
230 Bank bank(ctx->m_cluster_connection);
231
232 if (bank.performSumAccounts(wait, yield) == NDBT_FAILED)
233 {
234 ndbout << "runVerifyAndDropBank: bank.performSumAccounts FAILED" << endl;
235 result = NDBT_FAILED;
236 }
237 if (bank.performValidateAllGLs() == NDBT_FAILED)
238 {
239 ndbout << "runVerifyAndDropBank: bank.performValidateAllGLs FAILED" << endl;
240 result = NDBT_FAILED;
241 }
242
243 if (bank.dropBank() != NDBT_OK)
244 return NDBT_FAILED;
245 return result;
246 }
247
248
249 NDBT_TESTSUITE(testSRBank);
250 TESTCASE("SR",
251 " Test that a consistent bank is restored after graceful shutdown\n"
252 "1. Create bank\n"
253 "2. Start bank and let it run\n"
254 "3. Restart ndb and verify consistency\n"
255 "4. Drop bank\n")
256 {
257 TC_PROPERTY("Type", NdbMixRestarter::RTM_SR);
258 INITIALIZER(runCreateBank);
259 STEP(runBankTimer);
260 STEPS(runBankTransactions, 10);
261 STEP(runBankGL);
262 STEP(runBankSum);
263 STEP(runBankSrValidator);
264 STEP(runMixRestart);
265 FINALIZER(runVerifyAndDropBank);
266 }
267 TESTCASE("NR",
268 " Test that a consistent bank is restored after graceful shutdown\n"
269 "1. Create bank\n"
270 "2. Start bank and let it run\n"
271 "3. Restart ndb and verify consistency\n"
272 "4. Drop bank\n")
273 {
274 TC_PROPERTY("Type", NdbMixRestarter::RTM_NR);
275 INITIALIZER(runCreateBank);
276 STEP(runBankTimer);
277 STEPS(runBankTransactions, 10);
278 STEP(runBankGL);
279 STEP(runBankSum);
280 STEP(runMixRestart);
281 FINALIZER(runVerifyAndDropBank);
282 }
283 TESTCASE("Mix",
284 " Test that a consistent bank is restored after graceful shutdown\n"
285 "1. Create bank\n"
286 "2. Start bank and let it run\n"
287 "3. Restart ndb and verify consistency\n"
288 "4. Drop bank\n")
289 {
290 TC_PROPERTY("Type", NdbMixRestarter::RTM_ALL);
291 INITIALIZER(runCreateBank);
292 STEP(runBankTimer);
293 STEPS(runBankTransactions, 10);
294 STEP(runBankGL);
295 STEP(runBankSum);
296 STEP(runMixRestart);
297 STEP(runBankSrValidator);
298 FINALIZER(runVerifyAndDropBank);
299 }
300 NDBT_TESTSUITE_END(testSRBank);
301
302 int
main(int argc,const char ** argv)303 main(int argc, const char** argv){
304 ndb_init();
305 for (int i = 0; i<argc; i++)
306 {
307 if (strcmp(argv[i], "--disk") == 0)
308 {
309 argc--;
310 disk = true;
311 for (; i<argc; i++)
312 argv[i] = argv[i+1];
313 break;
314 }
315 }
316 NDBT_TESTSUITE_INSTANCE(testSRBank);
317 return testSRBank.execute(argc, argv);
318 }
319
320