MySQL 5.6.14 Source Code Document
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
Bank.cpp
1 /*
2  Copyright (C) 2003-2006, 2008 MySQL AB, 2008, 2009 Sun Microsystems, Inc.
3  All rights reserved. Use is subject to license terms.
4 
5  This program is free software; you can redistribute it and/or modify
6  it under the terms of the GNU General Public License as published by
7  the Free Software Foundation; version 2 of the License.
8 
9  This program is distributed in the hope that it will be useful,
10  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  GNU General Public License for more details.
13 
14  You should have received a copy of the GNU General Public License
15  along with this program; if not, write to the Free Software
16  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
17 */
18 
19 #include "Bank.hpp"
20 #include <time.h>
21 #include <NdbSleep.h>
22 #include <UtilTransactions.hpp>
23 
24 Bank::Bank(Ndb_cluster_connection& con, bool _init, const char * dbase):
25  m_ndb(&con, dbase),
26  m_maxAccount(-1),
27  m_initialized(false),
28  m_skip_create(false)
29 {
30  if(_init)
31  init();
32 }
33 
34 int Bank::init(){
35  if (m_initialized == true)
36  return NDBT_OK;
37 
38  myRandom48Init((long)NdbTick_CurrentMillisecond());
39 
40  m_ndb.init();
41  if (m_ndb.waitUntilReady(30) != 0)
42  {
43  ndbout << "Ndb not ready" << endl;
44  return NDBT_FAILED;
45  }
46 
47  if (getNumAccounts() != NDBT_OK)
48  return NDBT_FAILED;
49 
50  m_initialized = true;
51  return NDBT_OK;
52 }
53 
54 int Bank::performTransactions(int maxSleepBetweenTrans, int yield){
55 
56  int transactions = 0;
57 
58  while(performTransaction() == NDBT_OK)
59  {
60  transactions++;
61 
62  if (maxSleepBetweenTrans > 0){
63  int val = myRandom48(maxSleepBetweenTrans);
64  NdbSleep_MilliSleep(val);
65  }
66 
67  if((transactions % 100) == 0)
68  g_info << transactions << endl;
69 
70  if (yield != 0 && transactions >= yield)
71  return NDBT_OK;
72  }
73 
74  return NDBT_FAILED;
75 
76 }
77 
78 int Bank::performTransaction(){
79  int result = NDBT_OK;
80 
81  if (m_maxAccount <= 0){
82  g_err << "No accounts in bank" << endl;
83  return NDBT_FAILED;
84  }
85 
86  int fromAccount = myRandom48(m_maxAccount);
87  int toAccount = myRandom48(m_maxAccount);
88 
89  if (fromAccount == toAccount){
90  // Increase toAccount with 1
91  toAccount = (toAccount+1)%m_maxAccount;
92  }
93 
94  int maxAmount = getMaxAmount();
95 
96  int amount = myRandom48(maxAmount);
97 
98 retry_transaction:
99  int res = performTransaction(fromAccount, toAccount, amount);
100  if (res != 0){
101  switch (res){
102  case NDBT_FAILED:
103  g_err << "performTransaction returned NDBT_FAILED" << endl
104  << " fromAccount = " << fromAccount << endl
105  << " toAccount = " << toAccount << endl
106  << " amount = " << amount << endl;
107  result = NDBT_FAILED;
108  break;
109  case NOT_ENOUGH_FUNDS:
110  // ndbout << "performTransaction returned NOT_ENOUGH_FUNDS" << endl;
111  break;
112  case NDBT_TEMPORARY:
113  g_err << "TEMPORARY_ERRROR retrying" << endl;
114  NdbSleep_MilliSleep(50);
115  goto retry_transaction;
116  break;
117  default:
118  g_info << "performTransaction returned "<<res << endl;
119  break;
120  }
121  }
122  return result;
123 }
124 
132 int Bank::performTransaction(int fromAccountId,
133  int toAccountId,
134  int amount ){
147  // g_info << "performTransaction " << fromAccountId
148  // << ", "<<toAccountId<<", "<<amount << endl;
149 
150  // Call the first implementation of this trans
151  // In the future we can have several different versions of this trans
152  // and call them randomly
153  return performTransactionImpl1(fromAccountId, toAccountId, amount);
154 }
155 
156 
157 int Bank::performTransactionImpl1(int fromAccountId,
158  int toAccountId,
159  int amount ){
160 
161  int check;
162 
163  // Ok, all clear to do the transaction
164  Uint64 transId;
165  int result = NDBT_OK;
166  if ((result= getNextTransactionId(transId)) != NDBT_OK){
167  return result;
168  }
169 
170  NdbConnection* pTrans = m_ndb.startTransaction();
171 
172  if( pTrans == NULL ) {
173  const NdbError err = m_ndb.getNdbError();
174  if (err.status == NdbError::TemporaryError){
175  ERR(err);
176  return NDBT_TEMPORARY;
177  }
178  ERR(err);
179  return NDBT_FAILED;
180  }
181 
182  Uint64 currTime;
183  if (prepareGetCurrTimeOp(pTrans, currTime) != NDBT_OK){
184  ERR(pTrans->getNdbError());
185  m_ndb.closeTransaction(pTrans);
186  return NDBT_FAILED;
187  }
188 
192  NdbOperation* pOp = pTrans->getNdbOperation("ACCOUNT");
193  if (pOp == NULL) {
194  ERR(pTrans->getNdbError());
195  m_ndb.closeTransaction(pTrans);
196  return NDBT_FAILED;
197  }
198 
199  check = pOp->readTupleExclusive();
200  if( check == -1 ) {
201  ERR(pTrans->getNdbError());
202  m_ndb.closeTransaction(pTrans);
203  return NDBT_FAILED;
204  }
205 
206  check = pOp->equal("ACCOUNT_ID", fromAccountId);
207  if( check == -1 ) {
208  ERR(pTrans->getNdbError());
209  m_ndb.closeTransaction(pTrans);
210  return NDBT_FAILED;
211  }
212 
213  NdbRecAttr* balanceFromRec = pOp->getValue("BALANCE");
214  if( balanceFromRec ==NULL ) {
215  ERR(pTrans->getNdbError());
216  m_ndb.closeTransaction(pTrans);
217  return NDBT_FAILED;
218  }
219 
220  NdbRecAttr* fromAccountTypeRec = pOp->getValue("ACCOUNT_TYPE");
221  if( fromAccountTypeRec == NULL ) {
222  ERR(pTrans->getNdbError());
223  m_ndb.closeTransaction(pTrans);
224  return NDBT_FAILED;
225  }
226 
230  NdbOperation* pOp6 = pTrans->getNdbOperation("ACCOUNT");
231  if (pOp6 == NULL) {
232  ERR(pTrans->getNdbError());
233  m_ndb.closeTransaction(pTrans);
234  return NDBT_FAILED;
235  }
236 
237  check = pOp6->readTupleExclusive();
238  if( check == -1 ) {
239  ERR(pTrans->getNdbError());
240  m_ndb.closeTransaction(pTrans);
241  return NDBT_FAILED;
242  }
243 
244  check = pOp6->equal("ACCOUNT_ID", toAccountId);
245  if( check == -1 ) {
246  ERR(pTrans->getNdbError());
247  m_ndb.closeTransaction(pTrans);
248  return NDBT_FAILED;
249  }
250 
251  NdbRecAttr* balanceToRec = pOp6->getValue("BALANCE");
252  if( balanceToRec == NULL ) {
253  ERR(pTrans->getNdbError());
254  m_ndb.closeTransaction(pTrans);
255  return NDBT_FAILED;
256  }
257 
258  NdbRecAttr* toAccountTypeRec = pOp6->getValue("ACCOUNT_TYPE");
259  if( toAccountTypeRec == NULL ) {
260  ERR(pTrans->getNdbError());
261  m_ndb.closeTransaction(pTrans);
262  return NDBT_FAILED;
263  }
264 
265  check = pTrans->execute(NoCommit);
266  if( check == -1 ) {
267  const NdbError err = pTrans->getNdbError();
268  m_ndb.closeTransaction(pTrans);
269  if (err.status == NdbError::TemporaryError){
270  ERR(err);
271  return NDBT_TEMPORARY;
272  }
273  ERR(err);
274  return NDBT_FAILED;
275  }
276 
277 
278  Uint32 balanceFrom = balanceFromRec->u_32_value();
279  // ndbout << "balanceFrom: " << balanceFrom << endl;
280 
281  if (((Int64)balanceFrom - amount) < 0){
282  m_ndb.closeTransaction(pTrans);
283  //ndbout << "Not enough funds" << endl;
284  return NOT_ENOUGH_FUNDS;
285  }
286 
287  Uint32 fromAccountType = fromAccountTypeRec->u_32_value();
288 
289  Uint32 balanceTo = balanceToRec->u_32_value();
290  // ndbout << "balanceTo: " << balanceTo << endl;
291  Uint32 toAccountType = toAccountTypeRec->u_32_value();
292 
296  NdbOperation* pOp2 = pTrans->getNdbOperation("ACCOUNT");
297  if (pOp2 == NULL) {
298  ERR(pTrans->getNdbError());
299  m_ndb.closeTransaction(pTrans);
300  return NDBT_FAILED;
301  }
302 
303  check = pOp2->updateTuple();
304  if( check == -1 ) {
305  ERR(pTrans->getNdbError());
306  m_ndb.closeTransaction(pTrans);
307  return NDBT_FAILED;
308  }
309 
310  check = pOp2->equal("ACCOUNT_ID", fromAccountId);
311  if( check == -1 ) {
312  ERR(pTrans->getNdbError());
313  m_ndb.closeTransaction(pTrans);
314  return NDBT_FAILED;
315  }
316 
317  check = pOp2->setValue("BALANCE", balanceFrom - amount);
318  if( check == -1 ) {
319  ERR(pTrans->getNdbError());
320  m_ndb.closeTransaction(pTrans);
321  return NDBT_FAILED;
322  }
323 
327  NdbOperation* pOp3 = pTrans->getNdbOperation("ACCOUNT");
328  if (pOp3 == NULL) {
329  ERR(pTrans->getNdbError());
330  m_ndb.closeTransaction(pTrans);
331  return NDBT_FAILED;
332  }
333 
334  check = pOp3->updateTuple();
335  if( check == -1 ) {
336  ERR(pTrans->getNdbError());
337  m_ndb.closeTransaction(pTrans);
338  return NDBT_FAILED;
339  }
340 
341  check = pOp3->equal("ACCOUNT_ID", toAccountId);
342  if( check == -1 ) {
343  ERR(pTrans->getNdbError());
344  m_ndb.closeTransaction(pTrans);
345  return NDBT_FAILED;
346  }
347 
348  check = pOp3->setValue("BALANCE", balanceTo + amount);
349  if( check == -1 ) {
350  ERR(pTrans->getNdbError());
351  m_ndb.closeTransaction(pTrans);
352  return NDBT_FAILED;
353  }
354 
358  NdbOperation* pOp4 = pTrans->getNdbOperation("TRANSACTION");
359  if (pOp4 == NULL) {
360  ERR(pTrans->getNdbError());
361  m_ndb.closeTransaction(pTrans);
362  return NDBT_FAILED;
363  }
364 
365  check = pOp4->insertTuple();
366  if( check == -1 ) {
367  ERR(pTrans->getNdbError());
368  m_ndb.closeTransaction(pTrans);
369  return NDBT_FAILED;
370  }
371 
372  check = pOp4->equal("TRANSACTION_ID", transId);
373  if( check == -1 ) {
374  ERR(pTrans->getNdbError());
375  m_ndb.closeTransaction(pTrans);
376  return NDBT_FAILED;
377  }
378 
379  check = pOp4->equal("ACCOUNT", fromAccountId);
380  if( check == -1 ) {
381  ERR(pTrans->getNdbError());
382  m_ndb.closeTransaction(pTrans);
383  return NDBT_FAILED;
384  }
385 
386  check = pOp4->setValue("ACCOUNT_TYPE", fromAccountType);
387  if( check == -1 ) {
388  ERR(pTrans->getNdbError());
389  m_ndb.closeTransaction(pTrans);
390  return NDBT_FAILED;
391  }
392 
393  check = pOp4->setValue("OTHER_ACCOUNT", toAccountId);
394  if( check == -1 ) {
395  ERR(pTrans->getNdbError());
396  m_ndb.closeTransaction(pTrans);
397  return NDBT_FAILED;
398  }
399 
400  check = pOp4->setValue("TRANSACTION_TYPE", WithDrawal);
401  if( check == -1 ) {
402  ERR(pTrans->getNdbError());
403  m_ndb.closeTransaction(pTrans);
404  return NDBT_FAILED;
405  }
406 
407  check = pOp4->setValue("TIME", currTime);
408  if( check == -1 ) {
409  ERR(pTrans->getNdbError());
410  m_ndb.closeTransaction(pTrans);
411  return NDBT_FAILED;
412  }
413 
414  check = pOp4->setValue("AMOUNT", amount);
415  if( check == -1 ) {
416  ERR(pTrans->getNdbError());
417  m_ndb.closeTransaction(pTrans);
418  return NDBT_FAILED;
419  }
420 
424  NdbOperation* pOp5 = pTrans->getNdbOperation("TRANSACTION");
425  if (pOp5 == NULL) {
426  ERR(pTrans->getNdbError());
427  m_ndb.closeTransaction(pTrans);
428  return NDBT_FAILED;
429  }
430 
431  check = pOp5->insertTuple();
432  if( check == -1 ) {
433  ERR(pTrans->getNdbError());
434  m_ndb.closeTransaction(pTrans);
435  return NDBT_FAILED;
436  }
437 
438  check = pOp5->equal("TRANSACTION_ID", transId);
439  if( check == -1 ) {
440  ERR(pTrans->getNdbError());
441  m_ndb.closeTransaction(pTrans);
442  return NDBT_FAILED;
443  }
444 
445  check = pOp5->equal("ACCOUNT", toAccountId);
446  if( check == -1 ) {
447  ERR(pTrans->getNdbError());
448  m_ndb.closeTransaction(pTrans);
449  return NDBT_FAILED;
450  }
451 
452  check = pOp5->setValue("ACCOUNT_TYPE", toAccountType);
453  if( check == -1 ) {
454  ERR(pTrans->getNdbError());
455  m_ndb.closeTransaction(pTrans);
456  return NDBT_FAILED;
457  }
458 
459  check = pOp5->setValue("OTHER_ACCOUNT", fromAccountId);
460  if( check == -1 ) {
461  ERR(pTrans->getNdbError());
462  m_ndb.closeTransaction(pTrans);
463  return NDBT_FAILED;
464  }
465 
466  check = pOp5->setValue("TRANSACTION_TYPE", Deposit);
467  if( check == -1 ) {
468  ERR(pTrans->getNdbError());
469  m_ndb.closeTransaction(pTrans);
470  return NDBT_FAILED;
471  }
472 
473  check = pOp5->setValue("TIME", currTime);
474  if( check == -1 ) {
475  ERR(pTrans->getNdbError());
476  m_ndb.closeTransaction(pTrans);
477  return NDBT_FAILED;
478  }
479 
480  check = pOp5->setValue("AMOUNT", amount);
481  if( check == -1 ) {
482  ERR(pTrans->getNdbError());
483  m_ndb.closeTransaction(pTrans);
484  return NDBT_FAILED;
485  }
486 
487  check = pTrans->execute(Commit);
488  if( check == -1 ) {
489  const NdbError err = pTrans->getNdbError();
490  m_ndb.closeTransaction(pTrans);
491  if (err.status == NdbError::TemporaryError){
492  ERR(err);
493  return NDBT_TEMPORARY;
494  }
495  ERR(err);
496  return NDBT_FAILED;
497  }
498 
499  m_ndb.closeTransaction(pTrans);
500  return NDBT_OK;
501 }
502 
503 
504 
505 
506 int Bank::performMakeGLs(int yield){
507  int result;
508 
509  int counter, maxCounter;
510  int yieldCounter = 0;
511 
512  while (1){
513  // Counters to keep tracck of how many
514  // GLs should be made before performing a validation
515  counter = 0;
516  maxCounter = 50 + myRandom48(100);
517 
522  result = performValidateGLs();
523  if (result != NDBT_OK){
524  if (result == VERIFICATION_FAILED){
525  g_err << "performValidateGLs verification failed" << endl;
526  return NDBT_FAILED;
527  }
528  g_info << "performValidateGLs failed: " << result << endl;
529  return NDBT_FAILED;
530  continue;
531  }
532 
533  result = performValidatePurged();
534  if (result != NDBT_OK){
535  if (result == VERIFICATION_FAILED){
536  g_err << "performValidatePurged verification failed" << endl;
537  return NDBT_FAILED;
538  }
539  g_info << "performValidatePurged failed" << endl;
540  return NDBT_FAILED;
541  }
542 
543  while (1){
544 
545  yieldCounter++;
546  if (yield != 0 && yieldCounter >= yield)
547  return NDBT_OK;
548 
553  Uint64 lastGLTime;
554  if (findLastGL(lastGLTime) != NDBT_OK){
555  g_info << "findLastGL failed" << endl;
556  // Break out of inner while loop
557  break;
558  }
559 
560  lastGLTime++;
561 
566  Uint64 currTime;
567  if (getCurrTime(currTime) != NDBT_OK){
568  g_info << "getCurrTime failed" << endl;
569  // Break out of inner while loop
570  break;
571  }
572  if (lastGLTime < currTime){
573  counter++;
574  if (performMakeGL(lastGLTime) != NDBT_OK){
575  g_info << "performMakeGL failed" << endl;
576  // Break out of inner while loop
577  break;
578  }
579 
580  if (counter > maxCounter){
581  // Break out of inner while loop and
582  // validatePreviousGLs
583  g_info << "counter("<<counter<<") > maxCounter("<<maxCounter<<")" << endl;
584  break;
585  }
586 
587  } else {
588  ;//ndbout << "It's not time to make GL yet" << endl;
589 
590  // ndbout << "Sleeping 1 second" << endl;
591  NdbSleep_SecSleep(1);
592 
593  }
594 
595  Uint32 age = 3;
596  if (purgeOldGLTransactions(currTime, age) != NDBT_OK){
597  g_info << "purgeOldGLTransactions failed" << endl;
598  // Break out of inner while loop
599  break;
600  }
601 
602  }
603  }
604 
605  return NDBT_FAILED;
606 
607 }
608 
610  int result;
611 
612  while (1){
613 
618  int age = 100000;
619  result = performValidateGLs(age);
620  if (result != NDBT_OK){
621  if (result == VERIFICATION_FAILED){
622  g_err << "performValidateGLs verification failed" << endl;
623  return NDBT_FAILED;
624  }
625  g_err << "performValidateGLs failed: " << result << endl;
626  return NDBT_FAILED;
627  }
628 
633  result = performValidatePurged();
634  if (result != NDBT_OK){
635  if (result == VERIFICATION_FAILED){
636  g_err << "performValidatePurged verification failed" << endl;
637  return NDBT_FAILED;
638  }
639  g_err << "performValidatePurged failed" << endl;
640  return NDBT_FAILED;
641  }
642  return NDBT_OK;
643  }
644 
645  return NDBT_FAILED;
646 
647 }
648 
649 int Bank::findLastGL(Uint64 &lastTime){
650 
651  int check;
655  NdbConnection* pScanTrans = m_ndb.startTransaction();
656  if (pScanTrans == NULL) {
657  ERR(m_ndb.getNdbError());
658  return NDBT_FAILED;
659  }
660 
661  NdbScanOperation* pOp = pScanTrans->getNdbScanOperation("GL");
662  if (pOp == NULL) {
663  ERR(pScanTrans->getNdbError());
664  m_ndb.closeTransaction(pScanTrans);
665  return NDBT_FAILED;
666  }
667 
668  if( pOp->readTuples() ) {
669  ERR(pScanTrans->getNdbError());
670  m_ndb.closeTransaction(pScanTrans);
671  return NDBT_FAILED;
672  }
673 
674  NdbRecAttr* timeRec = pOp->getValue("TIME");
675  if( timeRec ==NULL ) {
676  ERR(pScanTrans->getNdbError());
677  m_ndb.closeTransaction(pScanTrans);
678  return NDBT_FAILED;
679  }
680 
681  check = pScanTrans->execute(NoCommit);
682  if( check == -1 ) {
683  ERR(pScanTrans->getNdbError());
684  m_ndb.closeTransaction(pScanTrans);
685  return NDBT_FAILED;
686  }
687 
688  int eof;
689  int rows = 0;
690  eof = pOp->nextResult();
691  lastTime = 0;
692 
693  while(eof == 0){
694  rows++;
695  Uint64 t = timeRec->u_32_value();
696 
697  if (t > lastTime)
698  lastTime = t;
699 
700  eof = pOp->nextResult();
701  }
702  if (eof == -1) {
703  ERR(pScanTrans->getNdbError());
704  m_ndb.closeTransaction(pScanTrans);
705  return NDBT_FAILED;
706  }
707 
708  m_ndb.closeTransaction(pScanTrans);
709 
710  return NDBT_OK;
711 }
712 
713 
714 int Bank::performMakeGL(Uint64 time){
715  g_info << "performMakeGL: " << time << endl;
720  // Start transaction
721  NdbConnection* pTrans = m_ndb.startTransaction();
722  if (pTrans == NULL){
723  ERR(m_ndb.getNdbError());
724  return NDBT_FAILED;
725  }
726  for (int i = 0; i < getNumAccountTypes(); i++){
727 
728  if (performMakeGLForAccountType(pTrans, time, i) != NDBT_OK){
729  g_err << "performMakeGLForAccountType returned NDBT_FAILED"<<endl;
730  m_ndb.closeTransaction(pTrans);
731  return NDBT_FAILED;
732  }
733  }
734  // Execute transaction
735  if( pTrans->execute(Commit) == -1 ) {
736  ERR(pTrans->getNdbError());
737  m_ndb.closeTransaction(pTrans);
738  return NDBT_FAILED;
739  }
740  m_ndb.closeTransaction(pTrans);
741 
742  return NDBT_OK;
743 }
744 
745 int Bank::performMakeGLForAccountType(NdbConnection* pTrans,
746  Uint64 glTime,
747  Uint32 accountTypeId){
748  int check;
749 
750  Uint32 balance = 0;
751  Uint32 withdrawalCount = 0;
752  Uint32 withdrawalSum = 0;
753  Uint32 depositSum = 0;
754  Uint32 depositCount = 0;
755  Uint32 countTransactions = 0;
756  Uint32 purged = 0;
757 
758  // Insert record in GL so that we know
759  // that no one else is performing the same task
760  // Set purged = 0 to indicate that TRANSACTION
761  // records still exist
762  NdbOperation* pOp = pTrans->getNdbOperation("GL");
763  if (pOp == NULL) {
764  ERR(pTrans->getNdbError());
765  return NDBT_FAILED;
766  }
767 
768  check = pOp->insertTuple();
769  if( check == -1 ) {
770  ERR(pTrans->getNdbError());
771  return NDBT_FAILED;
772  }
773 
774  check = pOp->equal("TIME", glTime);
775  if( check == -1 ) {
776  ERR(pTrans->getNdbError());
777  return NDBT_FAILED;
778  }
779 
780  check = pOp->equal("ACCOUNT_TYPE", accountTypeId);
781  if( check == -1 ) {
782  ERR(pTrans->getNdbError());
783  return NDBT_FAILED;
784  }
785 
786  check = pOp->setValue("BALANCE", balance);
787  if( check == -1 ) {
788  ERR(pTrans->getNdbError());
789  return NDBT_FAILED;
790  }
791 
792  check = pOp->setValue("DEPOSIT_COUNT", depositCount);
793  if( check == -1 ) {
794  ERR(pTrans->getNdbError());
795  return NDBT_FAILED;
796  }
797 
798  check = pOp->setValue("DEPOSIT_SUM", depositSum);
799  if( check == -1 ) {
800  ERR(pTrans->getNdbError());
801  return NDBT_FAILED;
802  }
803 
804  check = pOp->setValue("WITHDRAWAL_COUNT", withdrawalCount);
805  if( check == -1 ) {
806  ERR(pTrans->getNdbError());
807  return NDBT_FAILED;
808  }
809 
810  check = pOp->setValue("WITHDRAWAL_SUM", withdrawalSum);
811  if( check == -1 ) {
812  ERR(pTrans->getNdbError());
813  return NDBT_FAILED;
814  }
815 
816  check = pOp->setValue("PURGED", purged);
817  if( check == -1 ) {
818  ERR(pTrans->getNdbError());
819  return NDBT_FAILED;
820  }
821 
822  check = pTrans->execute(NoCommit);
823  if( check == -1 ) {
824  ERR(pOp->getNdbError());
825  return NDBT_FAILED;
826  }
827 
828  // Read previous GL record to get old balance
829  NdbOperation* pOp2 = pTrans->getNdbOperation("GL");
830  if (pOp2 == NULL) {
831  ERR(pTrans->getNdbError());
832  return NDBT_FAILED;
833  }
834 
835  check = pOp2->readTuple();
836  if( check == -1 ) {
837  ERR(pTrans->getNdbError());
838  return NDBT_FAILED;
839  }
840 
841  check = pOp2->equal("TIME", glTime-1);
842  if( check == -1 ) {
843  ERR(pTrans->getNdbError());
844  return NDBT_FAILED;
845  }
846 
847  check = pOp2->equal("ACCOUNT_TYPE", accountTypeId);
848  if( check == -1 ) {
849  ERR(pTrans->getNdbError());
850  return NDBT_FAILED;
851  }
852 
853  NdbRecAttr* oldBalanceRec = pOp2->getValue("BALANCE");
854  if( oldBalanceRec == NULL ) {
855  ERR(pTrans->getNdbError());
856  return NDBT_FAILED;
857  }
858 
859  check = pTrans->execute(NoCommit);
860  if( check == -1 ) {
861  ERR(pOp2->getNdbError());
862  return NDBT_FAILED;
863  }
864 
865  Uint32 oldBalance = oldBalanceRec->u_32_value();
866  // ndbout << "oldBalance = "<<oldBalance<<endl;
867  balance = oldBalance;
868  // Start a scan transaction to search
869  // for TRANSACTION records with TIME = time
870  // and ACCOUNT_TYPE = accountTypeId
871  // Build sum of all found transactions
872 
873  if (sumTransactionsForGL(glTime,
874  accountTypeId,
875  balance,
876  withdrawalCount,
877  withdrawalSum,
878  depositSum,
879  depositCount,
880  countTransactions,
881  pTrans) != NDBT_OK){
882  return NDBT_FAILED;
883  }
884  // ndbout << "sumTransactionsForGL completed" << endl;
885  // ndbout << "balance="<<balance<<endl
886  // << "withdrawalCount="<<withdrawalCount<<endl
887  // << "withdrawalSum="<<withdrawalSum<<endl
888  // << "depositCount="<<depositCount<<endl
889  // << "depositSum="<<depositSum<<endl;
890 
891 
892 
893  NdbOperation* pOp3 = pTrans->getNdbOperation("GL");
894  if (pOp3 == NULL) {
895  ERR(pTrans->getNdbError());
896  return NDBT_FAILED;
897  }
898 
899  check = pOp3->updateTuple();
900  if( check == -1 ) {
901  ERR(pTrans->getNdbError());
902  return NDBT_FAILED;
903  }
904 
905  check = pOp3->equal("TIME", glTime);
906  if( check == -1 ) {
907  ERR(pTrans->getNdbError());
908  return NDBT_FAILED;
909  }
910 
911  check = pOp3->equal("ACCOUNT_TYPE", accountTypeId);
912  if( check == -1 ) {
913  ERR(pTrans->getNdbError());
914  return NDBT_FAILED;
915  }
916 
917  check = pOp3->setValue("BALANCE", balance);
918  if( check == -1 ) {
919  ERR(pTrans->getNdbError());
920  return NDBT_FAILED;
921  }
922 
923  check = pOp3->setValue("DEPOSIT_COUNT", depositCount);
924  if( check == -1 ) {
925  ERR(pTrans->getNdbError());
926  return NDBT_FAILED;
927  }
928 
929  check = pOp3->setValue("DEPOSIT_SUM", depositSum);
930  if( check == -1 ) {
931  ERR(pTrans->getNdbError());
932  return NDBT_FAILED;
933  }
934 
935  check = pOp3->setValue("WITHDRAWAL_COUNT", withdrawalCount);
936  if( check == -1 ) {
937  ERR(pTrans->getNdbError());
938  return NDBT_FAILED;
939  }
940 
941  check = pOp3->setValue("WITHDRAWAL_SUM", withdrawalSum);
942  if( check == -1 ) {
943  ERR(pTrans->getNdbError());
944  return NDBT_FAILED;
945  }
946 
947  check = pOp3->setValue("PURGED", purged);
948  if( check == -1 ) {
949  ERR(pTrans->getNdbError());
950  return NDBT_FAILED;
951  }
952 
953  // Execute transaction
954  check = pTrans->execute(NoCommit);
955  if( check == -1 ) {
956  ERR(pTrans->getNdbError());
957  return NDBT_FAILED;
958  }
959 
960  return NDBT_OK;
961 }
962 
963 
964 
965 
966 int Bank::sumTransactionsForGL(const Uint64 glTime,
967  const Uint32 accountType,
968  Uint32& balance,
969  Uint32& withdrawalCount,
970  Uint32& withdrawalSum,
971  Uint32& depositSum,
972  Uint32& depositCount,
973  Uint32& transactionsCount,
974  NdbConnection* pTrans){
975  int check;
976 
977  // g_info << "sumTransactionsForGL: " << glTime << ", " << accountType << endl;
978 
979  NdbConnection* pScanTrans = m_ndb.startTransaction();
980  if (pScanTrans == NULL) {
981  ERR(m_ndb.getNdbError());
982  return NDBT_FAILED;
983  }
984 
985  NdbScanOperation* pOp = pScanTrans->getNdbScanOperation("TRANSACTION");
986  if (pOp == NULL) {
987  ERR(pScanTrans->getNdbError());
988  m_ndb.closeTransaction(pScanTrans);
989  return NDBT_FAILED;
990  }
991 
992  if( pOp->readTuplesExclusive()) {
993  ERR(pScanTrans->getNdbError());
994  m_ndb.closeTransaction(pScanTrans);
995  return NDBT_FAILED;
996  }
997 
998  NdbRecAttr* accountTypeRec = pOp->getValue("ACCOUNT_TYPE");
999  if( accountTypeRec ==NULL ) {
1000  ERR(pScanTrans->getNdbError());
1001  m_ndb.closeTransaction(pScanTrans);
1002  return NDBT_FAILED;
1003  }
1004 
1005  NdbRecAttr* timeRec = pOp->getValue("TIME");
1006  if( timeRec ==NULL ) {
1007  ERR(pScanTrans->getNdbError());
1008  m_ndb.closeTransaction(pScanTrans);
1009  return NDBT_FAILED;
1010  }
1011 
1012  NdbRecAttr* transTypeRec = pOp->getValue("TRANSACTION_TYPE");
1013  if( transTypeRec ==NULL ) {
1014  ERR(pScanTrans->getNdbError());
1015  m_ndb.closeTransaction(pScanTrans);
1016  return NDBT_FAILED;
1017  }
1018 
1019  NdbRecAttr* amountRec = pOp->getValue("AMOUNT");
1020  if( amountRec ==NULL ) {
1021  ERR(pScanTrans->getNdbError());
1022  m_ndb.closeTransaction(pScanTrans);
1023  return NDBT_FAILED;
1024  }
1025 
1026  check = pScanTrans->execute(NoCommit);
1027  if( check == -1 ) {
1028  ERR(pScanTrans->getNdbError());
1029  m_ndb.closeTransaction(pScanTrans);
1030  return NDBT_FAILED;
1031  }
1032 
1033  int eof;
1034  int rows = 0;
1035  int rowsFound = 0;
1036  eof = pOp->nextResult();
1037 
1038  while(eof == 0){
1039  rows++;
1040  Uint32 a = accountTypeRec->u_32_value();
1041  Uint64 t = timeRec->u_64_value();
1042 
1043  if (a == accountType && t == glTime){
1044  rowsFound++;
1045  // One record found
1046  int transType = transTypeRec->u_32_value();
1047  int amount = amountRec->u_32_value();
1048  if (transType == WithDrawal){
1049  withdrawalCount++;
1050  withdrawalSum += amount;
1051  balance -= amount;
1052  } else {
1053  assert(transType == Deposit);
1054  depositCount++;
1055  depositSum += amount;
1056  balance += amount;
1057  }
1058  }
1059 
1060  eof = pOp->nextResult();
1061 
1062  if ((rows % 100) == 0){
1063  // "refresh" ownner transaction every 100th row
1064  if (pTrans->refresh() == -1) {
1065  ERR(pTrans->getNdbError());
1066  return NDBT_FAILED;
1067  }
1068  }
1069 
1070  }
1071  if (eof == -1) {
1072  ERR(pScanTrans->getNdbError());
1073  m_ndb.closeTransaction(pScanTrans);
1074  return NDBT_FAILED;
1075  }
1076 
1077  m_ndb.closeTransaction(pScanTrans);
1078  // ndbout << rows << " TRANSACTIONS have been read" << endl;
1079  transactionsCount = rowsFound;
1080 
1081  return NDBT_OK;
1082 
1083 }
1084 
1085  int Bank::performValidateGLs(Uint64 age){
1086 
1087  Uint64 currTime;
1088  if (getCurrTime(currTime) != NDBT_OK){
1089  return NDBT_FAILED;
1090  }
1091  Uint64 glTime = currTime - 1;
1092  while((glTime > 0) && ((glTime + age) >= currTime)){
1093 
1094  int result = performValidateGL(glTime);
1095  if (result != NDBT_OK){
1096  g_err << "performValidateGL failed: " << result << endl;
1097  return result;
1098  }
1099 
1100  glTime--;
1101  }
1102 
1103  return NDBT_OK;
1104  }
1105 
1106 int Bank::performValidateGL(Uint64 glTime){
1107 
1108  ndbout << "performValidateGL: " << glTime << endl;
1127  int check;
1131  NdbConnection* pScanTrans = m_ndb.startTransaction();
1132  if (pScanTrans == NULL) {
1133  ERR(m_ndb.getNdbError());
1134  return NDBT_FAILED;
1135  }
1136 
1137  NdbScanOperation* pOp = pScanTrans->getNdbScanOperation("GL");
1138  if (pOp == NULL) {
1139  ERR(pScanTrans->getNdbError());
1140  m_ndb.closeTransaction(pScanTrans);
1141  return NDBT_FAILED;
1142  }
1143 
1144  if( pOp->readTuples() ) {
1145  ERR(pScanTrans->getNdbError());
1146  m_ndb.closeTransaction(pScanTrans);
1147  return NDBT_FAILED;
1148  }
1149 
1150  NdbRecAttr* accountTypeRec = pOp->getValue("ACCOUNT_TYPE");
1151  if( accountTypeRec ==NULL ) {
1152  ERR(pScanTrans->getNdbError());
1153  m_ndb.closeTransaction(pScanTrans);
1154  return NDBT_FAILED;
1155  }
1156 
1157  NdbRecAttr* timeRec = pOp->getValue("TIME");
1158  if( timeRec ==NULL ) {
1159  ERR(pScanTrans->getNdbError());
1160  m_ndb.closeTransaction(pScanTrans);
1161  return NDBT_FAILED;
1162  }
1163 
1164  NdbRecAttr* purgedRec = pOp->getValue("PURGED");
1165  if( purgedRec ==NULL ) {
1166  ERR(pScanTrans->getNdbError());
1167  m_ndb.closeTransaction(pScanTrans);
1168  return NDBT_FAILED;
1169  }
1170 
1171  NdbRecAttr* balanceRec = pOp->getValue("BALANCE");
1172  if( balanceRec ==NULL ) {
1173  ERR(pScanTrans->getNdbError());
1174  m_ndb.closeTransaction(pScanTrans);
1175  return NDBT_FAILED;
1176  }
1177 
1178  NdbRecAttr* depositSumRec = pOp->getValue("DEPOSIT_SUM");
1179  if( depositSumRec ==NULL ) {
1180  ERR(pScanTrans->getNdbError());
1181  m_ndb.closeTransaction(pScanTrans);
1182  return NDBT_FAILED;
1183  }
1184 
1185  NdbRecAttr* depositCountRec = pOp->getValue("DEPOSIT_COUNT");
1186  if( depositCountRec ==NULL ) {
1187  ERR(pScanTrans->getNdbError());
1188  m_ndb.closeTransaction(pScanTrans);
1189  return NDBT_FAILED;
1190  }
1191 
1192  NdbRecAttr* withdrawalSumRec = pOp->getValue("WITHDRAWAL_SUM");
1193  if( withdrawalSumRec ==NULL ) {
1194  ERR(pScanTrans->getNdbError());
1195  m_ndb.closeTransaction(pScanTrans);
1196  return NDBT_FAILED;
1197  }
1198  NdbRecAttr* withdrawalCountRec = pOp->getValue("WITHDRAWAL_COUNT");
1199  if( withdrawalCountRec ==NULL ) {
1200  ERR(pScanTrans->getNdbError());
1201  m_ndb.closeTransaction(pScanTrans);
1202  return NDBT_FAILED;
1203  }
1204 
1205  check = pScanTrans->execute(NoCommit);
1206  if( check == -1 ) {
1207  ERR(pScanTrans->getNdbError());
1208  m_ndb.closeTransaction(pScanTrans);
1209  return NDBT_FAILED;
1210  }
1211 
1212  int eof;
1213  int rows = 0;
1214  int countGlRecords = 0;
1215  int result = NDBT_OK;
1216  eof = pOp->nextResult();
1217 
1218  while(eof == 0){
1219  rows++;
1220  Uint64 t = timeRec->u_64_value();
1221 
1222  if (t == glTime){
1223  countGlRecords++;
1224  Uint32 a = accountTypeRec->u_32_value();
1225  Uint32 purged = purgedRec->u_32_value();
1226  Uint32 wsum = withdrawalSumRec->u_32_value();
1227  Uint32 wcount = withdrawalCountRec->u_32_value();
1228  Uint32 dsum = depositSumRec->u_32_value();
1229  Uint32 dcount = depositCountRec->u_32_value();
1230  Uint32 b = balanceRec->u_32_value();
1231 
1232  Uint32 balance = 0;
1233  Uint32 withdrawalSum = 0;
1234  Uint32 withdrawalCount = 0;
1235  Uint32 depositSum = 0;
1236  Uint32 depositCount = 0;
1237  Uint32 countTransactions = 0;
1238  if (purged == 0){
1239  // If purged == 0, then the TRANSACTION table should be checked
1240  // to see that there are:
1241  // + DEPOSIT_COUNT deposit transactions with account_type == ACCOUNT_TYPE
1242  // and TIME == glTime. The sum of these transactions should be
1243  // DEPOSIT_SUM
1244  // + WITHDRAWAL_COUNT withdrawal transactions with account_type ==
1245  // ACCOUNT_TYPE and TIME == glTime. The sum of these transactions
1246  // should be WITHDRAWAL_SUM
1247  // + BALANCE should be equal to the sum of all transactions plus
1248  // the balance of the previous GL record
1249  if (sumTransactionsForGL(t,
1250  a,
1251  balance,
1252  withdrawalCount,
1253  withdrawalSum,
1254  depositSum,
1255  depositCount,
1256  countTransactions,
1257  pScanTrans) != NDBT_OK){
1258  result = NDBT_FAILED;
1259  } else {
1260  Uint32 prevBalance = 0;
1261  if (getBalanceForGL(t-1, a, prevBalance) != NDBT_OK){
1262  result = NDBT_FAILED;
1263  } else
1264  if (((prevBalance + balance) != b) ||
1265  (wsum != withdrawalSum) ||
1266  (wcount != withdrawalCount) ||
1267  (dsum != depositSum) ||
1268  (dcount != depositCount)){
1269  g_err << "performValidateGL, sums and counts failed" << endl
1270  << "balance : " << balance+prevBalance << "!="<<b<<endl
1271  << "with sum : " << withdrawalSum << "!="<<wsum<<endl
1272  << "with count: " << withdrawalCount << "!="<<wcount<<endl
1273  << "dep sum : " << depositSum << "!="<<dsum<<endl
1274  << "dep count : " << depositCount << "!="<<dcount<<endl;
1275  result = VERIFICATION_FAILED;
1276  }
1277  }
1278 
1279  } else {
1280  assert(purged == 1);
1281  // If purged == 1 then there should be NO transactions with
1282  // TIME == glTime and ACCOUNT_TYPE == account_type
1283 
1284  if (sumTransactionsForGL(t,
1285  a,
1286  balance,
1287  withdrawalCount,
1288  withdrawalSum,
1289  depositSum,
1290  depositCount,
1291  countTransactions,
1292  pScanTrans) != NDBT_OK){
1293  result = NDBT_FAILED;
1294  } else {
1295  if (countTransactions != 0){
1296  g_err << "performValidateGL, countTransactions("<<countTransactions<<") != 0" << endl;
1297  result = VERIFICATION_FAILED;
1298  }
1299  }
1300  }
1301 
1302  }
1303  eof = pOp->nextResult();
1304  }
1305  if (eof == -1) {
1306  ERR(pScanTrans->getNdbError());
1307  m_ndb.closeTransaction(pScanTrans);
1308  return NDBT_FAILED;
1309  }
1310 
1311  m_ndb.closeTransaction(pScanTrans);
1312 
1313  // - There should be zero or NoAccountTypes GL records for each glTime
1314  if ((countGlRecords != 0) && (countGlRecords != getNumAccountTypes())){
1315  g_err << "performValidateGL: " << endl
1316  << "countGlRecords = " << countGlRecords << endl;
1317  result = VERIFICATION_FAILED;
1318  }
1319 
1320  return result;
1321 
1322 
1323  }
1324 
1325 int Bank::getBalanceForGL(const Uint64 glTime,
1326  const Uint32 accountTypeId,
1327  Uint32 &balance){
1328  int check;
1329 
1330  NdbConnection* pTrans = m_ndb.startTransaction();
1331  if (pTrans == NULL) {
1332  ERR(m_ndb.getNdbError());
1333  return NDBT_FAILED;
1334  }
1335 
1336  NdbOperation* pOp = pTrans->getNdbOperation("GL");
1337  if (pOp == NULL) {
1338  ERR(pTrans->getNdbError());
1339  return NDBT_FAILED;
1340  }
1341 
1342  check = pOp->readTuple();
1343  if( check == -1 ) {
1344  ERR(pTrans->getNdbError());
1345  return NDBT_FAILED;
1346  }
1347 
1348  check = pOp->equal("TIME", glTime);
1349  if( check == -1 ) {
1350  ERR(pTrans->getNdbError());
1351  return NDBT_FAILED;
1352  }
1353 
1354  check = pOp->equal("ACCOUNT_TYPE", accountTypeId);
1355  if( check == -1 ) {
1356  ERR(pTrans->getNdbError());
1357  return NDBT_FAILED;
1358  }
1359 
1360  NdbRecAttr* balanceRec = pOp->getValue("BALANCE");
1361  if( balanceRec == NULL ) {
1362  ERR(pTrans->getNdbError());
1363  return NDBT_FAILED;
1364  }
1365 
1366  check = pTrans->execute(Commit);
1367  if( check == -1 ) {
1368  ERR(pTrans->getNdbError());
1369  return NDBT_FAILED;
1370  }
1371 
1372  m_ndb.closeTransaction(pTrans);
1373 
1374  balance = balanceRec->u_32_value();
1375 
1376  return NDBT_OK;
1377 }
1378 
1379 
1380 
1381 int Bank::getOldestPurgedGL(const Uint32 accountType,
1382  Uint64 &oldest){
1383  int check;
1387  NdbConnection* pScanTrans = 0;
1388  do
1389  {
1390  pScanTrans = m_ndb.startTransaction();
1391  if (pScanTrans == NULL) {
1392  ERR(m_ndb.getNdbError());
1393  return NDBT_FAILED;
1394  }
1395 
1396  NdbScanOperation* pOp = pScanTrans->getNdbScanOperation("GL");
1397  if (pOp == NULL) {
1398  ERR(pScanTrans->getNdbError());
1399  m_ndb.closeTransaction(pScanTrans);
1400  return NDBT_FAILED;
1401  }
1402 
1403  if( pOp->readTuples() ) {
1404  ERR(pScanTrans->getNdbError());
1405  m_ndb.closeTransaction(pScanTrans);
1406  return NDBT_FAILED;
1407  }
1408 
1409  NdbRecAttr* accountTypeRec = pOp->getValue("ACCOUNT_TYPE");
1410  if( accountTypeRec ==NULL ) {
1411  ERR(pScanTrans->getNdbError());
1412  m_ndb.closeTransaction(pScanTrans);
1413  return NDBT_FAILED;
1414  }
1415 
1416  NdbRecAttr* timeRec = pOp->getValue("TIME");
1417  if( timeRec ==NULL ) {
1418  ERR(pScanTrans->getNdbError());
1419  m_ndb.closeTransaction(pScanTrans);
1420  return NDBT_FAILED;
1421  }
1422 
1423  NdbRecAttr* purgedRec = pOp->getValue("PURGED");
1424  if( purgedRec ==NULL ) {
1425  ERR(pScanTrans->getNdbError());
1426  m_ndb.closeTransaction(pScanTrans);
1427  return NDBT_FAILED;
1428  }
1429 
1430  check = pScanTrans->execute(NoCommit);
1431  if( check == -1 ) {
1432  NdbError err = pScanTrans->getNdbError();
1433  ERR(err);
1434  m_ndb.closeTransaction(pScanTrans);
1435  if (err.status == NdbError::TemporaryError)
1436  {
1437  NdbSleep_MilliSleep(50);
1438  continue;
1439  }
1440  return NDBT_FAILED;
1441  }
1442 
1443  int eof;
1444  int rows = 0;
1445  eof = pOp->nextResult();
1446  oldest = 0;
1447 
1448  while(eof == 0){
1449  rows++;
1450  Uint32 a = accountTypeRec->u_32_value();
1451  Uint32 p = purgedRec->u_32_value();
1452 
1453  if (a == accountType && p == 1){
1454  // One record found
1455  Uint64 t = timeRec->u_64_value();
1456  if (t > oldest)
1457  oldest = t;
1458  }
1459  eof = pOp->nextResult();
1460  }
1461  if (eof == -1)
1462  {
1463  NdbError err = pScanTrans->getNdbError();
1464  ERR(err);
1465  m_ndb.closeTransaction(pScanTrans);
1466 
1467  if (err.status == NdbError::TemporaryError)
1468  {
1469  NdbSleep_MilliSleep(50);
1470  continue;
1471  }
1472  return NDBT_FAILED;
1473  }
1474  break;
1475  } while(true);
1476 
1477  m_ndb.closeTransaction(pScanTrans);
1478 
1479  return NDBT_OK;
1480 }
1481 
1482 int Bank::getOldestNotPurgedGL(Uint64 &oldest,
1483  Uint32 &accountTypeId,
1484  bool &found){
1485  int check;
1490  NdbConnection* pScanTrans = m_ndb.startTransaction();
1491  if (pScanTrans == NULL) {
1492  ERR(m_ndb.getNdbError());
1493  return NDBT_FAILED;
1494  }
1495 
1496  NdbScanOperation* pOp = pScanTrans->getNdbScanOperation("GL");
1497  if (pOp == NULL) {
1498  ERR(pScanTrans->getNdbError());
1499  m_ndb.closeTransaction(pScanTrans);
1500  return NDBT_FAILED;
1501  }
1502 
1503  if( pOp->readTuples() ) {
1504  ERR(pScanTrans->getNdbError());
1505  m_ndb.closeTransaction(pScanTrans);
1506  return NDBT_FAILED;
1507  }
1508 
1509  NdbRecAttr* accountTypeRec = pOp->getValue("ACCOUNT_TYPE");
1510  if( accountTypeRec ==NULL ) {
1511  ERR(pScanTrans->getNdbError());
1512  m_ndb.closeTransaction(pScanTrans);
1513  return NDBT_FAILED;
1514  }
1515 
1516  NdbRecAttr* timeRec = pOp->getValue("TIME");
1517  if( timeRec ==NULL ) {
1518  ERR(pScanTrans->getNdbError());
1519  m_ndb.closeTransaction(pScanTrans);
1520  return NDBT_FAILED;
1521  }
1522 
1523  NdbRecAttr* purgedRec = pOp->getValue("PURGED");
1524  if( purgedRec ==NULL ) {
1525  ERR(pScanTrans->getNdbError());
1526  m_ndb.closeTransaction(pScanTrans);
1527  return NDBT_FAILED;
1528  }
1529 
1530  check = pScanTrans->execute(NoCommit);
1531  if( check == -1 ) {
1532  ERR(pScanTrans->getNdbError());
1533  m_ndb.closeTransaction(pScanTrans);
1534  return NDBT_FAILED;
1535  }
1536 
1537  int eof;
1538  int rows = 0;
1539  eof = pOp->nextResult();
1540  oldest = (Uint64)-1;
1541  found = false;
1542 
1543  while(eof == 0){
1544  rows++;
1545  Uint32 p = purgedRec->u_32_value();
1546  if (p == 0){
1547  found = true;
1548  // One record found
1549  Uint32 a = accountTypeRec->u_32_value();
1550  Uint64 t = timeRec->u_64_value();
1551  if (t < oldest){
1552  oldest = t;
1553  accountTypeId = a;
1554  }
1555  }
1556  eof = pOp->nextResult();
1557  }
1558  if (eof == -1) {
1559  ERR(pScanTrans->getNdbError());
1560  m_ndb.closeTransaction(pScanTrans);
1561  return NDBT_FAILED;
1562  }
1563 
1564  m_ndb.closeTransaction(pScanTrans);
1565 
1566  return NDBT_OK;
1567 }
1568 
1569 
1570 int Bank::checkNoTransactionsOlderThan(const Uint32 accountType,
1571  const Uint64 oldest){
1578  int loop = 0;
1579  int found = 0;
1580  NdbConnection* pScanTrans = 0;
1581  do {
1582  int check;
1583  loop++;
1584  pScanTrans = m_ndb.startTransaction();
1585  if (pScanTrans == NULL) {
1586  ERR(m_ndb.getNdbError());
1587  return NDBT_FAILED;
1588  }
1589 
1590  NdbScanOperation* pOp = pScanTrans->getNdbScanOperation("TRANSACTION");
1591  if (pOp == NULL) {
1592  ERR(pScanTrans->getNdbError());
1593  m_ndb.closeTransaction(pScanTrans);
1594  return NDBT_FAILED;
1595  }
1596 
1597  if( pOp->readTuples() ) {
1598  ERR(pScanTrans->getNdbError());
1599  m_ndb.closeTransaction(pScanTrans);
1600  return NDBT_FAILED;
1601  }
1602 
1603  NdbRecAttr* accountTypeRec = pOp->getValue("ACCOUNT_TYPE");
1604  if( accountTypeRec ==NULL ) {
1605  ERR(pScanTrans->getNdbError());
1606  m_ndb.closeTransaction(pScanTrans);
1607  return NDBT_FAILED;
1608  }
1609 
1610  NdbRecAttr* timeRec = pOp->getValue("TIME");
1611  if( timeRec ==NULL ) {
1612  ERR(pScanTrans->getNdbError());
1613  m_ndb.closeTransaction(pScanTrans);
1614  return NDBT_FAILED;
1615  }
1616 
1617  NdbRecAttr* transactionIdRec = pOp->getValue("TRANSACTION_ID");
1618  if( transactionIdRec ==NULL ) {
1619  ERR(pScanTrans->getNdbError());
1620  m_ndb.closeTransaction(pScanTrans);
1621  return NDBT_FAILED;
1622  }
1623 
1624  check = pScanTrans->execute(NoCommit);
1625  if( check == -1 ) {
1626  NdbError err = pScanTrans->getNdbError();
1627  ERR(err);
1628  m_ndb.closeTransaction(pScanTrans);
1629 
1630  if (err.status == NdbError::TemporaryError)
1631  {
1632  NdbSleep_MilliSleep(50);
1633  continue;
1634  }
1635  return NDBT_FAILED;
1636  }
1637 
1638  int eof;
1639  int rows = 0;
1640  found = 0;
1641  eof = pOp->nextResult();
1642 
1643  while(eof == 0){
1644  rows++;
1645  Uint32 a = accountTypeRec->u_32_value();
1646  Uint32 t = timeRec->u_32_value();
1647 
1648  if (a == accountType && t <= oldest){
1649  // One record found
1650  Uint64 ti = transactionIdRec->u_64_value();
1651  g_err << "checkNoTransactionsOlderThan found one record" << endl
1652  << " t = " << t << endl
1653  << " a = " << a << endl
1654  << " ti = " << ti << endl;
1655  found++;
1656  }
1657  eof = pOp->nextResult();
1658  }
1659  if (eof == -1) {
1660  NdbError err = pScanTrans->getNdbError();
1661  ERR(err);
1662  m_ndb.closeTransaction(pScanTrans);
1663 
1664  if (err.status == NdbError::TemporaryError)
1665  {
1666  NdbSleep_MilliSleep(50);
1667  continue;
1668  }
1669 
1670  return NDBT_FAILED;
1671  }
1672 
1673  break;
1674  } while(true);
1675 
1676  m_ndb.closeTransaction(pScanTrans);
1677 
1678  if (found == 0)
1679  return NDBT_OK;
1680  else
1681  return VERIFICATION_FAILED;
1682 }
1683 
1684 
1685  int Bank::performValidatePurged(){
1692  for (int i = 0; i < getNumAccountTypes(); i++){
1693  ndbout << "performValidatePurged: " << i << endl;
1694  Uint64 oldestGlTime;
1695  if (getOldestPurgedGL(i, oldestGlTime) != NDBT_OK){
1696  g_err << "getOldestPurgedGL failed" << endl;
1697  return NDBT_FAILED;
1698  }
1699  int result = checkNoTransactionsOlderThan(i, oldestGlTime);
1700  if (result != NDBT_OK){
1701  g_err << "checkNoTransactionsOlderThan failed" << endl;
1702  return result;
1703  }
1704 
1705  }
1706 
1707  return NDBT_OK;
1708  }
1709 
1710  int Bank::purgeOldGLTransactions(Uint64 currTime, Uint32 age){
1717  bool found;
1718  int count = 0;
1719 
1720  while(1){
1721  count++;
1722  if (count > 100)
1723  return NDBT_OK;
1724 
1725  // Search for the oldest GL record with purged == 0
1726  Uint64 oldestGlTime;
1727  Uint32 accountTypeId;
1728  if (getOldestNotPurgedGL(oldestGlTime, accountTypeId, found) != NDBT_OK){
1729  g_err << "getOldestNotPurgedGL failed" << endl;
1730  return NDBT_FAILED;
1731  }
1732 
1733 
1734  if (found == false){
1735  // ndbout << "not found" << endl;
1736  return NDBT_OK;
1737  }
1738 
1739 
1740 // ndbout << "purgeOldGLTransactions" << endl
1741 // << " oldestGlTime = " << oldestGlTime << endl
1742 // << " currTime = " << currTime << endl
1743 // << " age = " << age << endl;
1744  // Check if this GL is old enough to be purged
1745  if ((currTime < age) || (oldestGlTime > (currTime-age))){
1746  // ndbout << "is not old enough" << endl;
1747  return NDBT_OK;
1748  }
1749 
1750  if (purgeTransactions(oldestGlTime, accountTypeId) != NDBT_OK){
1751  g_err << "purgeTransactions failed" << endl;
1752  return NDBT_FAILED;
1753  }
1754  }
1755  g_err << "abnormal return" << endl;
1756  return NDBT_FAILED;
1757  }
1758 
1759 
1760 int Bank::purgeTransactions(const Uint64 glTime,
1761  const Uint32 accountTypeId)
1762 {
1763  int check;
1764  g_info << "purgeTransactions: " << glTime << ", "<<accountTypeId<<endl;
1765  NdbConnection* pTrans = m_ndb.startTransaction();
1766  if (pTrans == NULL){
1767  ERR(m_ndb.getNdbError());
1768  return NDBT_FAILED;
1769  }
1770 
1771  // Start by updating the GL record with purged = 1, use NoCommit
1772  NdbOperation* pOp = pTrans->getNdbOperation("GL");
1773  if (pOp == NULL) {
1774  ERR(pTrans->getNdbError());
1775  return NDBT_FAILED;
1776  }
1777 
1778  check = pOp->updateTuple();
1779  if( check == -1 ) {
1780  ERR(pTrans->getNdbError());
1781  return NDBT_FAILED;
1782  }
1783 
1784  check = pOp->equal("TIME", glTime);
1785  if( check == -1 ) {
1786  ERR(pTrans->getNdbError());
1787  return NDBT_FAILED;
1788  }
1789 
1790  check = pOp->equal("ACCOUNT_TYPE", accountTypeId);
1791  if( check == -1 ) {
1792  ERR(pTrans->getNdbError());
1793  return NDBT_FAILED;
1794  }
1795 
1796  Uint32 purged = 1;
1797  check = pOp->setValue("PURGED", purged);
1798  if( check == -1 ) {
1799  ERR(pTrans->getNdbError());
1800  return NDBT_FAILED;
1801  }
1802 
1803  // Execute transaction
1804  check = pTrans->execute(NoCommit);
1805  if( check == -1 ) {
1806  ERR(pTrans->getNdbError());
1807  return NDBT_FAILED;
1808  }
1809 
1810  // Find all transactions and take over them for delete
1811 
1812  if(findTransactionsToPurge(glTime,
1813  accountTypeId,
1814  pTrans) != NDBT_OK){
1815  g_err << "findTransactionToPurge failed" << endl;
1816  m_ndb.closeTransaction(pTrans);
1817  return NDBT_FAILED;
1818  }
1819 
1820 
1821 
1822  check = pTrans->execute(Commit);
1823  if( check == -1 ) {
1824  ERR(pTrans->getNdbError());
1825  return NDBT_FAILED;
1826  }
1827 
1828  m_ndb.closeTransaction(pTrans);
1829  return NDBT_OK;
1830 }
1831 
1832 
1833 int Bank::findTransactionsToPurge(const Uint64 glTime,
1834  const Uint32 accountType,
1835  NdbConnection* pTrans){
1836  int check;
1837 
1838  NdbConnection* pScanTrans = m_ndb.startTransaction();
1839  if (pScanTrans == NULL) {
1840  ERR(m_ndb.getNdbError());
1841  return NDBT_FAILED;
1842  }
1843 
1844  NdbScanOperation* pOp = pScanTrans->getNdbScanOperation("TRANSACTION");
1845  if (pOp == NULL) {
1846  ERR(pScanTrans->getNdbError());
1847  m_ndb.closeTransaction(pScanTrans);
1848  return NDBT_FAILED;
1849  }
1850 
1851  if( pOp->readTuplesExclusive() ) {
1852  ERR(pScanTrans->getNdbError());
1853  m_ndb.closeTransaction(pScanTrans);
1854  return NDBT_FAILED;
1855  }
1856 
1857  NdbRecAttr* timeRec = pOp->getValue("TIME");
1858  if( timeRec ==NULL ) {
1859  ERR(pScanTrans->getNdbError());
1860  m_ndb.closeTransaction(pScanTrans);
1861  return NDBT_FAILED;
1862  }
1863 
1864  NdbRecAttr* accountTypeRec = pOp->getValue("ACCOUNT_TYPE");
1865  if( accountTypeRec ==NULL ) {
1866  ERR(pScanTrans->getNdbError());
1867  m_ndb.closeTransaction(pScanTrans);
1868  return NDBT_FAILED;
1869  }
1870 
1871  check = pScanTrans->execute(NoCommit);
1872  if( check == -1 ) {
1873  ERR(pScanTrans->getNdbError());
1874  m_ndb.closeTransaction(pScanTrans);
1875  return NDBT_FAILED;
1876  }
1877 
1878  int eof;
1879  int rows = 0;
1880  int rowsFound = 0;
1881  eof = pOp->nextResult();
1882 
1883  while(eof == 0){
1884  rows++;
1885  Uint64 t = timeRec->u_64_value();
1886  Uint32 a = accountTypeRec->u_32_value();
1887 
1888  if (a == accountType && t == glTime){
1889  rowsFound++;
1890  // One record found
1891  check = pOp->deleteCurrentTuple(pTrans);
1892  if (check == -1){
1893  ERR(m_ndb.getNdbError());
1894  m_ndb.closeTransaction(pScanTrans);
1895  return NDBT_FAILED;
1896  }
1897 
1898  // Execute transaction
1899  check = pTrans->execute(NoCommit);
1900  if( check == -1 ) {
1901  ERR(pTrans->getNdbError());
1902  m_ndb.closeTransaction(pScanTrans);
1903  return NDBT_FAILED;
1904  }
1905  }
1906  eof = pOp->nextResult();
1907  }
1908  if (eof == -1) {
1909  ERR(pScanTrans->getNdbError());
1910  m_ndb.closeTransaction(pScanTrans);
1911  return NDBT_FAILED;
1912  }
1913 
1914  m_ndb.closeTransaction(pScanTrans);
1915  // ndbout << rowsFound << " TRANSACTIONS have been deleted" << endl;
1916 
1917  return NDBT_OK;
1918 
1919 }
1920 
1921 
1922 int Bank::performIncreaseTime(int maxSleepBetweenDays, int yield)
1923 {
1924  int yieldCounter = 0;
1925 
1926  while(1){
1927 
1928  Uint64 currTime;
1929  if (incCurrTime(currTime) != NDBT_OK)
1930  break;
1931 
1932  g_info << "Current time is " << currTime << endl;
1933  if (maxSleepBetweenDays > 0){
1934  int val = myRandom48(maxSleepBetweenDays);
1935  NdbSleep_SecSleep(val);
1936  }
1937 
1938  yieldCounter++;
1939  if (yield != 0 && yieldCounter >= yield)
1940  return NDBT_OK;
1941 
1942  }
1943  return NDBT_FAILED;
1944 }
1945 
1946 int Bank::readSystemValue(SystemValueId sysValId, Uint64 & value){
1947 
1948  int check;
1949  NdbConnection* pTrans = 0;
1950  while (true)
1951  {
1952  pTrans = m_ndb.startTransaction();
1953  if (pTrans == NULL)
1954  {
1955  ERR(m_ndb.getNdbError());
1957  {
1958  NdbSleep_MilliSleep(50);
1959  continue;
1960  }
1961  return NDBT_FAILED;
1962  }
1963 
1964  int result;
1965  if ((result= prepareReadSystemValueOp(pTrans, sysValId, value)) != NDBT_OK)
1966  {
1967  ERR(pTrans->getNdbError());
1968  m_ndb.closeTransaction(pTrans);
1969  return result;
1970  }
1971 
1972  check = pTrans->execute(Commit);
1973  if( check == -1 ) {
1974  NdbError err = pTrans->getNdbError();
1975  m_ndb.closeTransaction(pTrans);
1976  ERR(err);
1977  if(err.status == NdbError::TemporaryError)
1978  {
1979  NdbSleep_MilliSleep(50);
1980  continue;
1981  }
1982  return NDBT_FAILED;
1983  }
1984 
1985  break;
1986  }
1987 
1988  m_ndb.closeTransaction(pTrans);
1989  return NDBT_OK;
1990 
1991 }
1992 
1993 int Bank::prepareReadSystemValueOp(NdbConnection* pTrans, SystemValueId sysValId, Uint64 & value){
1994 
1995  int check;
1996 
1997  NdbOperation* pOp = pTrans->getNdbOperation("SYSTEM_VALUES");
1998  if (pOp == NULL) {
1999  return NDBT_FAILED;
2000  }
2001 
2002  check = pOp->readTuple();
2003  if( check == -1 ) {
2004  return NDBT_FAILED;
2005  }
2006 
2007  check = pOp->equal("SYSTEM_VALUES_ID", sysValId);
2008  if( check == -1 ) {
2009  return NDBT_FAILED;
2010  }
2011 
2012  NdbRecAttr* valueRec = pOp->getValue("VALUE", (char *)&value);
2013  if( valueRec == NULL ) {
2014  return NDBT_FAILED;
2015  }
2016 
2017  return NDBT_OK;
2018 }
2019 
2020 int Bank::writeSystemValue(SystemValueId sysValId, Uint64 value){
2021 
2022  int check;
2023 
2024  NdbConnection* pTrans = m_ndb.startTransaction();
2025  if (pTrans == NULL){
2026  ERR(m_ndb.getNdbError());
2027  return NDBT_FAILED;
2028  }
2029 
2030  NdbOperation* pOp = pTrans->getNdbOperation("SYSTEM_VALUES");
2031  if (pOp == NULL) {
2032  ERR(pTrans->getNdbError());
2033  m_ndb.closeTransaction(pTrans);
2034  return NDBT_FAILED;
2035  }
2036 
2037  check = pOp->insertTuple();
2038  if( check == -1 ) {
2039  ERR(pTrans->getNdbError());
2040  m_ndb.closeTransaction(pTrans);
2041  return NDBT_FAILED;
2042  }
2043 
2044  check = pOp->equal("SYSTEM_VALUES_ID", sysValId);
2045  if( check == -1 ) {
2046  ERR(pTrans->getNdbError());
2047  m_ndb.closeTransaction(pTrans);
2048  return NDBT_FAILED;
2049  }
2050 
2051  check = pOp->setValue("VALUE", value);
2052  if( check == -1 ) {
2053  ERR(pTrans->getNdbError());
2054  m_ndb.closeTransaction(pTrans);
2055  return NDBT_FAILED;
2056  }
2057 
2058  check = pTrans->execute(Commit);
2059  if( check == -1 ) {
2060  ERR(pTrans->getNdbError());
2061  m_ndb.closeTransaction(pTrans);
2062  return NDBT_FAILED;
2063  }
2064 
2065  m_ndb.closeTransaction(pTrans);
2066  return NDBT_OK;
2067 
2068 }
2069 
2070 int Bank::getNextTransactionId(Uint64 &value){
2071  return increaseSystemValue2(LastTransactionId, value);
2072 }
2073 
2074 int Bank::incCurrTime(Uint64 &value){
2075  return increaseSystemValue(CurrentTime, value);
2076 }
2077 
2078 
2079 int Bank::increaseSystemValue(SystemValueId sysValId, Uint64 &value){
2086  DBUG_ENTER("Bank::increaseSystemValue");
2087 
2088  int check;
2089 
2090  NdbConnection* pTrans = m_ndb.startTransaction();
2091  if (pTrans == NULL){
2092  ERR(m_ndb.getNdbError());
2094  DBUG_RETURN(NDBT_TEMPORARY);
2095  DBUG_RETURN(NDBT_FAILED);
2096  }
2097 
2098  NdbOperation* pOp = pTrans->getNdbOperation("SYSTEM_VALUES");
2099  if (pOp == NULL) {
2100  ERR(pTrans->getNdbError());
2101  m_ndb.closeTransaction(pTrans);
2102  DBUG_RETURN(NDBT_FAILED);
2103  }
2104 
2105  check = pOp->readTupleExclusive();
2106  // check = pOp->readTuple();
2107  if( check == -1 ) {
2108  ERR(pTrans->getNdbError());
2109  m_ndb.closeTransaction(pTrans);
2110  DBUG_RETURN(NDBT_FAILED);
2111  }
2112 
2113  check = pOp->equal("SYSTEM_VALUES_ID", sysValId);
2114  if( check == -1 ) {
2115  ERR(pTrans->getNdbError());
2116  m_ndb.closeTransaction(pTrans);
2117  DBUG_RETURN(NDBT_FAILED);
2118  }
2119 
2120  NdbRecAttr* valueRec = pOp->getValue("VALUE");
2121  if( valueRec ==NULL ) {
2122  ERR(pTrans->getNdbError());
2123  m_ndb.closeTransaction(pTrans);
2124  DBUG_RETURN(NDBT_FAILED);
2125  }
2126 
2127  check = pTrans->execute(NoCommit);
2128  if( check == -1 ) {
2129  ERR(pTrans->getNdbError());
2130  if (pTrans->getNdbError().status == NdbError::TemporaryError)
2131  {
2132  m_ndb.closeTransaction(pTrans);
2133  DBUG_RETURN(NDBT_TEMPORARY);
2134  }
2135  m_ndb.closeTransaction(pTrans);
2136  DBUG_RETURN(NDBT_FAILED);
2137  }
2138 
2139  value = valueRec->u_64_value();
2140  value++;
2141 
2142  NdbOperation* pOp2 = pTrans->getNdbOperation("SYSTEM_VALUES");
2143  if (pOp2 == NULL) {
2144  ERR(pTrans->getNdbError());
2145  m_ndb.closeTransaction(pTrans);
2146  DBUG_RETURN(NDBT_FAILED);
2147  }
2148 
2149  check = pOp2->updateTuple();
2150  if( check == -1 ) {
2151  ERR(pTrans->getNdbError());
2152  m_ndb.closeTransaction(pTrans);
2153  DBUG_RETURN(NDBT_FAILED);
2154  }
2155 
2156  check = pOp2->equal("SYSTEM_VALUES_ID", sysValId);
2157  if( check == -1 ) {
2158  ERR(pTrans->getNdbError());
2159  m_ndb.closeTransaction(pTrans);
2160  DBUG_RETURN(NDBT_FAILED);
2161  }
2162 
2163  check = pOp2->setValue("VALUE", value);
2164  if( check == -1 ) {
2165  ERR(pTrans->getNdbError());
2166  m_ndb.closeTransaction(pTrans);
2167  DBUG_RETURN(NDBT_FAILED);
2168  }
2169 
2170  check = pTrans->execute(NoCommit);
2171  if( check == -1 ) {
2172  ERR(pTrans->getNdbError());
2173  m_ndb.closeTransaction(pTrans);
2174  DBUG_RETURN(NDBT_FAILED);
2175  }
2176 
2177  NdbOperation* pOp3 = pTrans->getNdbOperation("SYSTEM_VALUES");
2178  if (pOp3 == NULL) {
2179  ERR(pTrans->getNdbError());
2180  m_ndb.closeTransaction(pTrans);
2181  DBUG_RETURN(NDBT_FAILED);
2182  }
2183 
2184  check = pOp3->readTuple();
2185  if( check == -1 ) {
2186  ERR(pTrans->getNdbError());
2187  m_ndb.closeTransaction(pTrans);
2188  DBUG_RETURN(NDBT_FAILED);
2189  }
2190 
2191  check = pOp3->equal("SYSTEM_VALUES_ID", sysValId);
2192  if( check == -1 ) {
2193  ERR(pTrans->getNdbError());
2194  m_ndb.closeTransaction(pTrans);
2195  DBUG_RETURN(NDBT_FAILED);
2196  }
2197 
2198  // Read new value
2199  NdbRecAttr* valueNewRec = pOp3->getValue("VALUE");
2200  if( valueNewRec ==NULL ) {
2201  ERR(pTrans->getNdbError());
2202  m_ndb.closeTransaction(pTrans);
2203  DBUG_RETURN(NDBT_FAILED);
2204  }
2205 
2206  check = pTrans->execute(Commit);
2207  if( check == -1 ) {
2208  ERR(pTrans->getNdbError());
2209  if (pTrans->getNdbError().status == NdbError::TemporaryError)
2210  {
2211  m_ndb.closeTransaction(pTrans);
2212  DBUG_RETURN(NDBT_TEMPORARY);
2213  }
2214  m_ndb.closeTransaction(pTrans);
2215  DBUG_RETURN(NDBT_FAILED);
2216  }
2217 
2218  // Check that value updated equals the value we read after the update
2219  if (valueNewRec->u_64_value() != value){
2220 
2221  printf("value actual=%lld\n", valueNewRec->u_64_value());
2222  printf("value expected=%lld actual=%lld\n", value, valueNewRec->u_64_value());
2223 
2224  DBUG_PRINT("info", ("value expected=%ld actual=%ld", (long)value, (long)valueNewRec->u_64_value()));
2225  g_err << "getNextTransactionId: value was not updated" << endl;
2226  m_ndb.closeTransaction(pTrans);
2227  DBUG_RETURN(NDBT_FAILED);
2228  }
2229 
2230  m_ndb.closeTransaction(pTrans);
2231 
2232  DBUG_RETURN(0);
2233 }
2234 
2235 int Bank::increaseSystemValue2(SystemValueId sysValId, Uint64 &value){
2243  int check;
2244 
2245  NdbConnection* pTrans = m_ndb.startTransaction();
2246  if (pTrans == NULL){
2247  ERR(m_ndb.getNdbError());
2249  return NDBT_TEMPORARY;
2250  return NDBT_FAILED;
2251  }
2252 
2253  NdbOperation* pOp = pTrans->getNdbOperation("SYSTEM_VALUES");
2254  if (pOp == NULL) {
2255  ERR(pTrans->getNdbError());
2256  m_ndb.closeTransaction(pTrans);
2257  return NDBT_FAILED;
2258  }
2259 
2260  check = pOp->interpretedUpdateTuple();
2261  if( check == -1 ) {
2262  ERR(pTrans->getNdbError());
2263  m_ndb.closeTransaction(pTrans);
2264  return NDBT_FAILED;
2265  }
2266 
2267  check = pOp->equal("SYSTEM_VALUES_ID", sysValId );
2268  if( check == -1 ) {
2269  ERR(pTrans->getNdbError());
2270  m_ndb.closeTransaction(pTrans);
2271  return NDBT_FAILED;
2272  }
2273 
2274  Uint32 valToIncWith = 1;
2275  check = pOp->incValue("VALUE", valToIncWith);
2276  if( check == -1 ) {
2277  ERR(pTrans->getNdbError());
2278  m_ndb.closeTransaction(pTrans);
2279  return NDBT_FAILED;
2280  }
2281 
2282  NdbRecAttr* valueRec = pOp->getValue("VALUE");
2283  if( valueRec == NULL ) {
2284  ERR(pTrans->getNdbError());
2285  m_ndb.closeTransaction(pTrans);
2286  return NDBT_FAILED;
2287  }
2288 
2289  check = pTrans->execute(Commit);
2290  if( check == -1 ) {
2291  ERR(pTrans->getNdbError());
2293  {
2294  m_ndb.closeTransaction(pTrans);
2295  return NDBT_TEMPORARY;
2296  }
2297  m_ndb.closeTransaction(pTrans);
2298  return NDBT_FAILED;
2299  }
2300 
2301  value = valueRec->u_64_value();
2302 
2303  m_ndb.closeTransaction(pTrans);
2304 
2305  return 0;
2306 
2307 }
2308 
2309 
2310 
2311 int Bank::getCurrTime(Uint64 &time){
2312  return readSystemValue(CurrentTime, time);
2313 }
2314 
2315 int Bank::prepareGetCurrTimeOp(NdbConnection *pTrans, Uint64 &time){
2316  return prepareReadSystemValueOp(pTrans, CurrentTime, time);
2317 }
2318 
2319 
2320 int Bank::performSumAccounts(int maxSleepBetweenSums, int yield){
2321 
2322  int yieldCounter = 0;
2323 
2324  while (1){
2325 
2326  Uint32 sumAccounts = 0;
2327  Uint32 numAccounts = 0;
2328  if (getSumAccounts(sumAccounts, numAccounts) != NDBT_OK){
2329  g_err << "getSumAccounts FAILED" << endl;
2330  } else {
2331 
2332  g_info << "num="<<numAccounts<<", sum=" << sumAccounts << endl;
2333 
2334  if (sumAccounts != (10000000 + (10000*(numAccounts-1)))){
2335  g_err << "performSumAccounts FAILED" << endl
2336  << " sumAccounts="<<sumAccounts<<endl
2337  << " expected ="<<(10000000 + (10000*(numAccounts-1)))<<endl
2338  << " numAccounts="<<numAccounts<<endl;
2339  return NDBT_FAILED;
2340  }
2341 
2342  if (maxSleepBetweenSums > 0){
2343  int val = myRandom48(maxSleepBetweenSums);
2344  NdbSleep_MilliSleep(val);
2345  }
2346  }
2347 
2348  yieldCounter++;
2349  if (yield != 0 && yieldCounter >= yield)
2350  return NDBT_OK;
2351  }
2352  return NDBT_FAILED;
2353 }
2354 
2355 
2356 int Bank::getSumAccounts(Uint32 &sumAccounts,
2357  Uint32 &numAccounts){
2358 
2359  // SELECT SUM(balance) FROM ACCOUNT
2360 
2361  int check;
2362  NdbConnection* pScanTrans = m_ndb.startTransaction();
2363  if (pScanTrans == NULL) {
2364  ERR(m_ndb.getNdbError());
2365  return NDBT_FAILED;
2366  }
2367 
2368  NdbScanOperation* pOp = pScanTrans->getNdbScanOperation("ACCOUNT");
2369  if (pOp == NULL) {
2370  ERR(pScanTrans->getNdbError());
2371  m_ndb.closeTransaction(pScanTrans);
2372  return NDBT_FAILED;
2373  }
2374 
2375  if( pOp->readTuplesExclusive() ) {
2376  ERR(pScanTrans->getNdbError());
2377  m_ndb.closeTransaction(pScanTrans);
2378  return NDBT_FAILED;
2379  }
2380 
2381  NdbRecAttr* balanceRec = pOp->getValue("BALANCE");
2382  if( balanceRec ==NULL ) {
2383  ERR(pScanTrans->getNdbError());
2384  m_ndb.closeTransaction(pScanTrans);
2385  return NDBT_FAILED;
2386  }
2387 
2388  check = pScanTrans->execute(NoCommit);
2389  if( check == -1 ) {
2390  ERR(pScanTrans->getNdbError());
2391  m_ndb.closeTransaction(pScanTrans);
2392  return NDBT_FAILED;
2393  }
2394 
2395  NdbConnection* pTrans = m_ndb.startTransaction();
2396  if (pTrans == NULL) {
2397  ERR(m_ndb.getNdbError());
2398  m_ndb.closeTransaction(pScanTrans);
2399  return NDBT_FAILED;
2400  }
2401 
2402  int eof;
2403  eof = pOp->nextResult();
2404 
2405  while(eof == 0){
2406  Uint32 b = balanceRec->u_32_value();
2407 
2408  sumAccounts += b;
2409  numAccounts++;
2410 
2411  // ndbout << numAccounts << ": balance =" << b
2412  // << ", sum="<< sumAccounts << endl;
2413 
2414  // Take over the operation so that the lock is kept in db
2415  NdbOperation* pLockOp = pOp->updateCurrentTuple(pTrans);
2416  if (pLockOp == NULL){
2417  ERR(m_ndb.getNdbError());
2418  m_ndb.closeTransaction(pScanTrans);
2419  m_ndb.closeTransaction(pTrans);
2420  return NDBT_FAILED;
2421  }
2422 
2423  Uint32 illegalBalance = 99;
2424  check = pLockOp->setValue("BALANCE", illegalBalance);
2425  if( check == -1 ) {
2426  ERR(pTrans->getNdbError());
2427  m_ndb.closeTransaction(pTrans);
2428  m_ndb.closeTransaction(pScanTrans);
2429  return NDBT_FAILED;
2430  }
2431 
2432  // Execute transaction
2433  check = pTrans->execute(NoCommit);
2434  if( check == -1 ) {
2435  ERR(pTrans->getNdbError());
2436  m_ndb.closeTransaction(pScanTrans);
2437  m_ndb.closeTransaction(pTrans);
2438  return NDBT_FAILED;
2439  }
2440 
2441  eof = pOp->nextResult();
2442  }
2443  if (eof == -1) {
2444  ERR(pScanTrans->getNdbError());
2445  m_ndb.closeTransaction(pScanTrans);
2446  m_ndb.closeTransaction(pTrans);
2447  return NDBT_FAILED;
2448  }
2449 
2450  // TODO Forget about rolling back, just close pTrans!!
2451 
2452  // Rollback transaction
2453  check = pTrans->execute(Rollback);
2454  if( check == -1 ) {
2455  ERR(pTrans->getNdbError());
2456  m_ndb.closeTransaction(pScanTrans);
2457  m_ndb.closeTransaction(pTrans);
2458  return NDBT_FAILED;
2459  }
2460 
2461  m_ndb.closeTransaction(pScanTrans);
2462  m_ndb.closeTransaction(pTrans);
2463 
2464 
2465  return NDBT_OK;
2466 
2467 }