1
/* Copyright (C) 2003 MySQL AB
3
This program is free software; you can redistribute it and/or modify
4
it under the terms of the GNU General Public License as published by
5
the Free Software Foundation; version 2 of the License.
7
This program is distributed in the hope that it will be useful,
8
but WITHOUT ANY WARRANTY; without even the implied warranty of
9
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10
GNU General Public License for more details.
12
You should have received a copy of the GNU General Public License
13
along with this program; if not, write to the Free Software
14
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
19
#include <UtilTransactions.hpp>
21
Bank::Bank(Ndb_cluster_connection& con, bool _init, const char * dbase):
32
if (m_initialized == true)
35
myRandom48Init(NdbTick_CurrentMillisecond());
38
if (m_ndb.waitUntilReady(30) != 0)
40
ndbout << "Ndb not ready" << endl;
44
if (getNumAccounts() != NDBT_OK)
51
int Bank::performTransactions(int maxSleepBetweenTrans, int yield){
55
while(performTransaction() == NDBT_OK)
59
if (maxSleepBetweenTrans > 0){
60
int val = myRandom48(maxSleepBetweenTrans);
61
NdbSleep_MilliSleep(val);
64
if((transactions % 100) == 0)
65
g_info << transactions << endl;
67
if (yield != 0 && transactions >= yield)
75
int Bank::performTransaction(){
78
if (m_maxAccount <= 0){
79
g_err << "No accounts in bank" << endl;
83
int fromAccount = myRandom48(m_maxAccount);
84
int toAccount = myRandom48(m_maxAccount);
86
if (fromAccount == toAccount){
87
// Increase toAccount with 1
88
toAccount = (toAccount+1)%m_maxAccount;
91
int maxAmount = getMaxAmount();
93
int amount = myRandom48(maxAmount);
96
int res = performTransaction(fromAccount, toAccount, amount);
100
g_err << "performTransaction returned NDBT_FAILED" << endl
101
<< " fromAccount = " << fromAccount << endl
102
<< " toAccount = " << toAccount << endl
103
<< " amount = " << amount << endl;
104
result = NDBT_FAILED;
106
case NOT_ENOUGH_FUNDS:
107
// ndbout << "performTransaction returned NOT_ENOUGH_FUNDS" << endl;
110
g_err << "TEMPORARY_ERRROR retrying" << endl;
111
NdbSleep_MilliSleep(50);
112
goto retry_transaction;
115
g_info << "performTransaction returned "<<res << endl;
123
* Perform a transaction in the bank.
124
* Ie. transfer money from one account to another.
127
* @return 0 if successful or an error code
129
int Bank::performTransaction(int fromAccountId,
133
* 1. Start transaction
134
* 2. Check balance on from account, if there is
135
* not enough funds abort transaction
136
* 3. Update ACCOUNT set balance = balance - amount on
138
* 4. Insert withdrawal in TRANSACTION
139
* 5. Insert deposit in transaction
140
* 6. Update ACCOUNT set balance = balance + amount on
142
* 7. Commit transaction
144
// g_info << "performTransaction " << fromAccountId
145
// << ", "<<toAccountId<<", "<<amount << endl;
147
// Call the first implementation of this trans
148
// In the future we can have several different versions of this trans
149
// and call them randomly
150
return performTransactionImpl1(fromAccountId, toAccountId, amount);
154
int Bank::performTransactionImpl1(int fromAccountId,
160
// Ok, all clear to do the transaction
162
int result = NDBT_OK;
163
if ((result= getNextTransactionId(transId)) != NDBT_OK){
167
NdbConnection* pTrans = m_ndb.startTransaction();
169
if( pTrans == NULL ) {
170
const NdbError err = m_ndb.getNdbError();
171
if (err.status == NdbError::TemporaryError){
173
return NDBT_TEMPORARY;
180
if (prepareGetCurrTimeOp(pTrans, currTime) != NDBT_OK){
181
ERR(pTrans->getNdbError());
182
m_ndb.closeTransaction(pTrans);
187
* Check balance on from account
189
NdbOperation* pOp = pTrans->getNdbOperation("ACCOUNT");
191
ERR(pTrans->getNdbError());
192
m_ndb.closeTransaction(pTrans);
196
check = pOp->readTupleExclusive();
198
ERR(pTrans->getNdbError());
199
m_ndb.closeTransaction(pTrans);
203
check = pOp->equal("ACCOUNT_ID", fromAccountId);
205
ERR(pTrans->getNdbError());
206
m_ndb.closeTransaction(pTrans);
210
NdbRecAttr* balanceFromRec = pOp->getValue("BALANCE");
211
if( balanceFromRec ==NULL ) {
212
ERR(pTrans->getNdbError());
213
m_ndb.closeTransaction(pTrans);
217
NdbRecAttr* fromAccountTypeRec = pOp->getValue("ACCOUNT_TYPE");
218
if( fromAccountTypeRec == NULL ) {
219
ERR(pTrans->getNdbError());
220
m_ndb.closeTransaction(pTrans);
225
* Read balance on to account
227
NdbOperation* pOp6 = pTrans->getNdbOperation("ACCOUNT");
229
ERR(pTrans->getNdbError());
230
m_ndb.closeTransaction(pTrans);
234
check = pOp6->readTupleExclusive();
236
ERR(pTrans->getNdbError());
237
m_ndb.closeTransaction(pTrans);
241
check = pOp6->equal("ACCOUNT_ID", toAccountId);
243
ERR(pTrans->getNdbError());
244
m_ndb.closeTransaction(pTrans);
248
NdbRecAttr* balanceToRec = pOp6->getValue("BALANCE");
249
if( balanceToRec == NULL ) {
250
ERR(pTrans->getNdbError());
251
m_ndb.closeTransaction(pTrans);
255
NdbRecAttr* toAccountTypeRec = pOp6->getValue("ACCOUNT_TYPE");
256
if( toAccountTypeRec == NULL ) {
257
ERR(pTrans->getNdbError());
258
m_ndb.closeTransaction(pTrans);
262
check = pTrans->execute(NoCommit);
264
const NdbError err = pTrans->getNdbError();
265
m_ndb.closeTransaction(pTrans);
266
if (err.status == NdbError::TemporaryError){
268
return NDBT_TEMPORARY;
275
Uint32 balanceFrom = balanceFromRec->u_32_value();
276
// ndbout << "balanceFrom: " << balanceFrom << endl;
278
if (((Int64)balanceFrom - amount) < 0){
279
m_ndb.closeTransaction(pTrans);
280
//ndbout << "Not enough funds" << endl;
281
return NOT_ENOUGH_FUNDS;
284
Uint32 fromAccountType = fromAccountTypeRec->u_32_value();
286
Uint32 balanceTo = balanceToRec->u_32_value();
287
// ndbout << "balanceTo: " << balanceTo << endl;
288
Uint32 toAccountType = toAccountTypeRec->u_32_value();
291
* Update balance on from account
293
NdbOperation* pOp2 = pTrans->getNdbOperation("ACCOUNT");
295
ERR(pTrans->getNdbError());
296
m_ndb.closeTransaction(pTrans);
300
check = pOp2->updateTuple();
302
ERR(pTrans->getNdbError());
303
m_ndb.closeTransaction(pTrans);
307
check = pOp2->equal("ACCOUNT_ID", fromAccountId);
309
ERR(pTrans->getNdbError());
310
m_ndb.closeTransaction(pTrans);
314
check = pOp2->setValue("BALANCE", balanceFrom - amount);
316
ERR(pTrans->getNdbError());
317
m_ndb.closeTransaction(pTrans);
322
* Update balance on to account
324
NdbOperation* pOp3 = pTrans->getNdbOperation("ACCOUNT");
326
ERR(pTrans->getNdbError());
327
m_ndb.closeTransaction(pTrans);
331
check = pOp3->updateTuple();
333
ERR(pTrans->getNdbError());
334
m_ndb.closeTransaction(pTrans);
338
check = pOp3->equal("ACCOUNT_ID", toAccountId);
340
ERR(pTrans->getNdbError());
341
m_ndb.closeTransaction(pTrans);
345
check = pOp3->setValue("BALANCE", balanceTo + amount);
347
ERR(pTrans->getNdbError());
348
m_ndb.closeTransaction(pTrans);
353
* Insert withdrawal transaction
355
NdbOperation* pOp4 = pTrans->getNdbOperation("TRANSACTION");
357
ERR(pTrans->getNdbError());
358
m_ndb.closeTransaction(pTrans);
362
check = pOp4->insertTuple();
364
ERR(pTrans->getNdbError());
365
m_ndb.closeTransaction(pTrans);
369
check = pOp4->equal("TRANSACTION_ID", transId);
371
ERR(pTrans->getNdbError());
372
m_ndb.closeTransaction(pTrans);
376
check = pOp4->equal("ACCOUNT", fromAccountId);
378
ERR(pTrans->getNdbError());
379
m_ndb.closeTransaction(pTrans);
383
check = pOp4->setValue("ACCOUNT_TYPE", fromAccountType);
385
ERR(pTrans->getNdbError());
386
m_ndb.closeTransaction(pTrans);
390
check = pOp4->setValue("OTHER_ACCOUNT", toAccountId);
392
ERR(pTrans->getNdbError());
393
m_ndb.closeTransaction(pTrans);
397
check = pOp4->setValue("TRANSACTION_TYPE", WithDrawal);
399
ERR(pTrans->getNdbError());
400
m_ndb.closeTransaction(pTrans);
404
check = pOp4->setValue("TIME", currTime);
406
ERR(pTrans->getNdbError());
407
m_ndb.closeTransaction(pTrans);
411
check = pOp4->setValue("AMOUNT", amount);
413
ERR(pTrans->getNdbError());
414
m_ndb.closeTransaction(pTrans);
419
* Insert deposit transaction
421
NdbOperation* pOp5 = pTrans->getNdbOperation("TRANSACTION");
423
ERR(pTrans->getNdbError());
424
m_ndb.closeTransaction(pTrans);
428
check = pOp5->insertTuple();
430
ERR(pTrans->getNdbError());
431
m_ndb.closeTransaction(pTrans);
435
check = pOp5->equal("TRANSACTION_ID", transId);
437
ERR(pTrans->getNdbError());
438
m_ndb.closeTransaction(pTrans);
442
check = pOp5->equal("ACCOUNT", toAccountId);
444
ERR(pTrans->getNdbError());
445
m_ndb.closeTransaction(pTrans);
449
check = pOp5->setValue("ACCOUNT_TYPE", toAccountType);
451
ERR(pTrans->getNdbError());
452
m_ndb.closeTransaction(pTrans);
456
check = pOp5->setValue("OTHER_ACCOUNT", fromAccountId);
458
ERR(pTrans->getNdbError());
459
m_ndb.closeTransaction(pTrans);
463
check = pOp5->setValue("TRANSACTION_TYPE", Deposit);
465
ERR(pTrans->getNdbError());
466
m_ndb.closeTransaction(pTrans);
470
check = pOp5->setValue("TIME", currTime);
472
ERR(pTrans->getNdbError());
473
m_ndb.closeTransaction(pTrans);
477
check = pOp5->setValue("AMOUNT", amount);
479
ERR(pTrans->getNdbError());
480
m_ndb.closeTransaction(pTrans);
484
check = pTrans->execute(Commit);
486
const NdbError err = pTrans->getNdbError();
487
m_ndb.closeTransaction(pTrans);
488
if (err.status == NdbError::TemporaryError){
490
return NDBT_TEMPORARY;
496
m_ndb.closeTransaction(pTrans);
503
int Bank::performMakeGLs(int yield){
506
int counter, maxCounter;
507
int yieldCounter = 0;
510
// Counters to keep tracck of how many
511
// GLs should be made before performing a validation
513
maxCounter = 50 + myRandom48(100);
516
* Validate GLs and Transactions for previous days
519
result = performValidateGLs();
520
if (result != NDBT_OK){
521
if (result == VERIFICATION_FAILED){
522
g_err << "performValidateGLs verification failed" << endl;
525
g_info << "performValidateGLs failed" << endl;
530
result = performValidatePurged();
531
if (result != NDBT_OK){
532
if (result == VERIFICATION_FAILED){
533
g_err << "performValidatePurged verification failed" << endl;
536
g_info << "performValidatePurged failed" << endl;
543
if (yield != 0 && yieldCounter >= yield)
548
* ( GL record with highest time value)
551
if (findLastGL(lastGLTime) != NDBT_OK){
552
g_info << "findLastGL failed" << endl;
553
// Break out of inner while loop
560
* If last GL time + 1 is smaller than current time
561
* perform a GL for that time
564
if (getCurrTime(currTime) != NDBT_OK){
565
g_info << "getCurrTime failed" << endl;
566
// Break out of inner while loop
569
if (lastGLTime < currTime){
571
if (performMakeGL(lastGLTime) != NDBT_OK){
572
g_info << "performMakeGL failed" << endl;
573
// Break out of inner while loop
577
if (counter > maxCounter){
578
// Break out of inner while loop and
579
// validatePreviousGLs
580
g_info << "counter("<<counter<<") > maxCounter("<<maxCounter<<")" << endl;
585
;//ndbout << "It's not time to make GL yet" << endl;
587
// ndbout << "Sleeping 1 second" << endl;
588
NdbSleep_SecSleep(1);
593
if (purgeOldGLTransactions(currTime, age) != NDBT_OK){
594
g_info << "purgeOldGLTransactions failed" << endl;
595
// Break out of inner while loop
606
int Bank::performValidateAllGLs(){
612
* Validate GLs and Transactions for previous days
613
* Set age so that ALL GL's are validated
616
result = performValidateGLs(age);
617
if (result != NDBT_OK){
618
if (result == VERIFICATION_FAILED){
619
g_err << "performValidateGLs verification failed" << endl;
622
g_err << "performValidateGLs failed" << endl;
630
result = performValidatePurged();
631
if (result != NDBT_OK){
632
if (result == VERIFICATION_FAILED){
633
g_err << "performValidatePurged verification failed" << endl;
636
g_err << "performValidatePurged failed" << endl;
646
int Bank::findLastGL(Uint64 &lastTime){
650
* SELECT MAX(time) FROM GL
652
NdbConnection* pScanTrans = m_ndb.startTransaction();
653
if (pScanTrans == NULL) {
654
ERR(m_ndb.getNdbError());
658
NdbScanOperation* pOp = pScanTrans->getNdbScanOperation("GL");
660
ERR(pScanTrans->getNdbError());
661
m_ndb.closeTransaction(pScanTrans);
665
if( pOp->readTuples() ) {
666
ERR(pScanTrans->getNdbError());
667
m_ndb.closeTransaction(pScanTrans);
671
check = pOp->interpret_exit_ok();
673
ERR(pScanTrans->getNdbError());
674
m_ndb.closeTransaction(pScanTrans);
678
NdbRecAttr* timeRec = pOp->getValue("TIME");
679
if( timeRec ==NULL ) {
680
ERR(pScanTrans->getNdbError());
681
m_ndb.closeTransaction(pScanTrans);
685
check = pScanTrans->execute(NoCommit);
687
ERR(pScanTrans->getNdbError());
688
m_ndb.closeTransaction(pScanTrans);
694
eof = pOp->nextResult();
699
Uint64 t = timeRec->u_32_value();
704
eof = pOp->nextResult();
707
ERR(pScanTrans->getNdbError());
708
m_ndb.closeTransaction(pScanTrans);
712
m_ndb.closeTransaction(pScanTrans);
718
int Bank::performMakeGL(int time){
719
g_info << "performMakeGL: " << time << endl;
721
* Create one GL record for each account type.
722
* All in the same transaction
725
NdbConnection* pTrans = m_ndb.startTransaction();
727
ERR(m_ndb.getNdbError());
730
for (int i = 0; i < getNumAccountTypes(); i++){
732
if (performMakeGLForAccountType(pTrans, time, i) != NDBT_OK){
733
g_err << "performMakeGLForAccountType returned NDBT_FAILED"<<endl;
734
m_ndb.closeTransaction(pTrans);
738
// Execute transaction
739
if( pTrans->execute(Commit) == -1 ) {
740
ERR(pTrans->getNdbError());
741
m_ndb.closeTransaction(pTrans);
744
m_ndb.closeTransaction(pTrans);
749
int Bank::performMakeGLForAccountType(NdbConnection* pTrans,
751
Uint32 accountTypeId){
755
Uint32 withdrawalCount = 0;
756
Uint32 withdrawalSum = 0;
757
Uint32 depositSum = 0;
758
Uint32 depositCount = 0;
759
Uint32 countTransactions = 0;
762
// Insert record in GL so that we know
763
// that no one else is performing the same task
764
// Set purged = 0 to indicate that TRANSACTION
765
// records still exist
766
NdbOperation* pOp = pTrans->getNdbOperation("GL");
768
ERR(pTrans->getNdbError());
772
check = pOp->insertTuple();
774
ERR(pTrans->getNdbError());
778
check = pOp->equal("TIME", glTime);
780
ERR(pTrans->getNdbError());
784
check = pOp->equal("ACCOUNT_TYPE", accountTypeId);
786
ERR(pTrans->getNdbError());
790
check = pOp->setValue("BALANCE", balance);
792
ERR(pTrans->getNdbError());
796
check = pOp->setValue("DEPOSIT_COUNT", depositCount);
798
ERR(pTrans->getNdbError());
802
check = pOp->setValue("DEPOSIT_SUM", depositSum);
804
ERR(pTrans->getNdbError());
808
check = pOp->setValue("WITHDRAWAL_COUNT", withdrawalCount);
810
ERR(pTrans->getNdbError());
814
check = pOp->setValue("WITHDRAWAL_SUM", withdrawalSum);
816
ERR(pTrans->getNdbError());
820
check = pOp->setValue("PURGED", purged);
822
ERR(pTrans->getNdbError());
826
check = pTrans->execute(NoCommit);
828
ERR(pOp->getNdbError());
832
// Read previous GL record to get old balance
833
NdbOperation* pOp2 = pTrans->getNdbOperation("GL");
835
ERR(pTrans->getNdbError());
839
check = pOp2->readTuple();
841
ERR(pTrans->getNdbError());
845
check = pOp2->equal("TIME", glTime-1);
847
ERR(pTrans->getNdbError());
851
check = pOp2->equal("ACCOUNT_TYPE", accountTypeId);
853
ERR(pTrans->getNdbError());
857
NdbRecAttr* oldBalanceRec = pOp2->getValue("BALANCE");
858
if( oldBalanceRec == NULL ) {
859
ERR(pTrans->getNdbError());
863
check = pTrans->execute(NoCommit);
865
ERR(pOp2->getNdbError());
869
Uint32 oldBalance = oldBalanceRec->u_32_value();
870
// ndbout << "oldBalance = "<<oldBalance<<endl;
871
balance = oldBalance;
872
// Start a scan transaction to search
873
// for TRANSACTION records with TIME = time
874
// and ACCOUNT_TYPE = accountTypeId
875
// Build sum of all found transactions
877
if (sumTransactionsForGL(glTime,
888
// ndbout << "sumTransactionsForGL completed" << endl;
889
// ndbout << "balance="<<balance<<endl
890
// << "withdrawalCount="<<withdrawalCount<<endl
891
// << "withdrawalSum="<<withdrawalSum<<endl
892
// << "depositCount="<<depositCount<<endl
893
// << "depositSum="<<depositSum<<endl;
897
NdbOperation* pOp3 = pTrans->getNdbOperation("GL");
899
ERR(pTrans->getNdbError());
903
check = pOp3->updateTuple();
905
ERR(pTrans->getNdbError());
909
check = pOp3->equal("TIME", glTime);
911
ERR(pTrans->getNdbError());
915
check = pOp3->equal("ACCOUNT_TYPE", accountTypeId);
917
ERR(pTrans->getNdbError());
921
check = pOp3->setValue("BALANCE", balance);
923
ERR(pTrans->getNdbError());
927
check = pOp3->setValue("DEPOSIT_COUNT", depositCount);
929
ERR(pTrans->getNdbError());
933
check = pOp3->setValue("DEPOSIT_SUM", depositSum);
935
ERR(pTrans->getNdbError());
939
check = pOp3->setValue("WITHDRAWAL_COUNT", withdrawalCount);
941
ERR(pTrans->getNdbError());
945
check = pOp3->setValue("WITHDRAWAL_SUM", withdrawalSum);
947
ERR(pTrans->getNdbError());
951
check = pOp3->setValue("PURGED", purged);
953
ERR(pTrans->getNdbError());
957
// Execute transaction
958
check = pTrans->execute(NoCommit);
960
ERR(pTrans->getNdbError());
970
int Bank::sumTransactionsForGL(const Uint64 glTime,
971
const Uint32 accountType,
973
Uint32& withdrawalCount,
974
Uint32& withdrawalSum,
976
Uint32& depositCount,
977
Uint32& transactionsCount,
978
NdbConnection* pTrans){
981
// g_info << "sumTransactionsForGL: " << glTime << ", " << accountType << endl;
983
NdbConnection* pScanTrans = m_ndb.startTransaction();
984
if (pScanTrans == NULL) {
985
ERR(m_ndb.getNdbError());
989
NdbScanOperation* pOp = pScanTrans->getNdbScanOperation("TRANSACTION");
991
ERR(pScanTrans->getNdbError());
992
m_ndb.closeTransaction(pScanTrans);
996
if( pOp->readTuplesExclusive()) {
997
ERR(pScanTrans->getNdbError());
998
m_ndb.closeTransaction(pScanTrans);
1002
check = pOp->interpret_exit_ok();
1004
ERR(pScanTrans->getNdbError());
1005
m_ndb.closeTransaction(pScanTrans);
1009
NdbRecAttr* accountTypeRec = pOp->getValue("ACCOUNT_TYPE");
1010
if( accountTypeRec ==NULL ) {
1011
ERR(pScanTrans->getNdbError());
1012
m_ndb.closeTransaction(pScanTrans);
1016
NdbRecAttr* timeRec = pOp->getValue("TIME");
1017
if( timeRec ==NULL ) {
1018
ERR(pScanTrans->getNdbError());
1019
m_ndb.closeTransaction(pScanTrans);
1023
NdbRecAttr* transTypeRec = pOp->getValue("TRANSACTION_TYPE");
1024
if( transTypeRec ==NULL ) {
1025
ERR(pScanTrans->getNdbError());
1026
m_ndb.closeTransaction(pScanTrans);
1030
NdbRecAttr* amountRec = pOp->getValue("AMOUNT");
1031
if( amountRec ==NULL ) {
1032
ERR(pScanTrans->getNdbError());
1033
m_ndb.closeTransaction(pScanTrans);
1037
check = pScanTrans->execute(NoCommit);
1039
ERR(pScanTrans->getNdbError());
1040
m_ndb.closeTransaction(pScanTrans);
1047
eof = pOp->nextResult();
1051
Uint32 a = accountTypeRec->u_32_value();
1052
Uint64 t = timeRec->u_64_value();
1054
if (a == accountType && t == glTime){
1057
int transType = transTypeRec->u_32_value();
1058
int amount = amountRec->u_32_value();
1059
if (transType == WithDrawal){
1061
withdrawalSum += amount;
1064
assert(transType == Deposit);
1066
depositSum += amount;
1071
eof = pOp->nextResult();
1073
if ((rows % 100) == 0){
1074
// "refresh" ownner transaction every 100th row
1075
if (pTrans->refresh() == -1) {
1076
ERR(pTrans->getNdbError());
1083
ERR(pScanTrans->getNdbError());
1084
m_ndb.closeTransaction(pScanTrans);
1088
m_ndb.closeTransaction(pScanTrans);
1089
// ndbout << rows << " TRANSACTIONS have been read" << endl;
1090
transactionsCount = rowsFound;
1096
int Bank::performValidateGLs(Uint64 age){
1099
if (getCurrTime(currTime) != NDBT_OK){
1102
Uint64 glTime = currTime - 1;
1103
while((glTime > 0) && ((glTime + age) >= currTime)){
1105
int result = performValidateGL(glTime);
1106
if (result != NDBT_OK){
1107
g_err << "performValidateGL failed" << endl;
1117
int Bank::performValidateGL(Uint64 glTime){
1119
ndbout << "performValidateGL: " << glTime << endl;
1122
* - There should be zero or NoAccountTypes GL records for each glTime
1123
* - If purged == 0, then the TRANSACTION table should be checked
1124
* to see that there are:
1125
* + DEPOSIT_COUNT deposit transactions with account_type == ACCOUNT_TYPE
1126
* and TIME == glTime. The sum of these transactions should be
1128
* + WITHDRAWAL_COUNT withdrawal transactions with account_type ==
1129
* ACCOUNT_TYPE and TIME == glTime. The sum of these transactions
1130
* should be WITHDRAWAL_SUM
1131
* + BALANCE should be equal to the sum of all transactions plus
1132
* the balance of the previous GL record
1133
* - If purged == 1 then there should be NO transactions with TIME == glTime
1134
* and ACCOUNT_TYPE == account_type
1140
* SELECT * FROM GL WHERE account_type = @accountType and time = @time
1142
NdbConnection* pScanTrans = m_ndb.startTransaction();
1143
if (pScanTrans == NULL) {
1144
ERR(m_ndb.getNdbError());
1148
NdbScanOperation* pOp = pScanTrans->getNdbScanOperation("GL");
1150
ERR(pScanTrans->getNdbError());
1151
m_ndb.closeTransaction(pScanTrans);
1155
if( pOp->readTuples() ) {
1156
ERR(pScanTrans->getNdbError());
1157
m_ndb.closeTransaction(pScanTrans);
1161
check = pOp->interpret_exit_ok();
1163
ERR(pScanTrans->getNdbError());
1164
m_ndb.closeTransaction(pScanTrans);
1168
NdbRecAttr* accountTypeRec = pOp->getValue("ACCOUNT_TYPE");
1169
if( accountTypeRec ==NULL ) {
1170
ERR(pScanTrans->getNdbError());
1171
m_ndb.closeTransaction(pScanTrans);
1175
NdbRecAttr* timeRec = pOp->getValue("TIME");
1176
if( timeRec ==NULL ) {
1177
ERR(pScanTrans->getNdbError());
1178
m_ndb.closeTransaction(pScanTrans);
1182
NdbRecAttr* purgedRec = pOp->getValue("PURGED");
1183
if( purgedRec ==NULL ) {
1184
ERR(pScanTrans->getNdbError());
1185
m_ndb.closeTransaction(pScanTrans);
1189
NdbRecAttr* balanceRec = pOp->getValue("BALANCE");
1190
if( balanceRec ==NULL ) {
1191
ERR(pScanTrans->getNdbError());
1192
m_ndb.closeTransaction(pScanTrans);
1196
NdbRecAttr* depositSumRec = pOp->getValue("DEPOSIT_SUM");
1197
if( depositSumRec ==NULL ) {
1198
ERR(pScanTrans->getNdbError());
1199
m_ndb.closeTransaction(pScanTrans);
1203
NdbRecAttr* depositCountRec = pOp->getValue("DEPOSIT_COUNT");
1204
if( depositCountRec ==NULL ) {
1205
ERR(pScanTrans->getNdbError());
1206
m_ndb.closeTransaction(pScanTrans);
1210
NdbRecAttr* withdrawalSumRec = pOp->getValue("WITHDRAWAL_SUM");
1211
if( withdrawalSumRec ==NULL ) {
1212
ERR(pScanTrans->getNdbError());
1213
m_ndb.closeTransaction(pScanTrans);
1216
NdbRecAttr* withdrawalCountRec = pOp->getValue("WITHDRAWAL_COUNT");
1217
if( withdrawalCountRec ==NULL ) {
1218
ERR(pScanTrans->getNdbError());
1219
m_ndb.closeTransaction(pScanTrans);
1223
check = pScanTrans->execute(NoCommit);
1225
ERR(pScanTrans->getNdbError());
1226
m_ndb.closeTransaction(pScanTrans);
1232
int countGlRecords = 0;
1233
int result = NDBT_OK;
1234
eof = pOp->nextResult();
1238
Uint64 t = timeRec->u_64_value();
1242
Uint32 a = accountTypeRec->u_32_value();
1243
Uint32 purged = purgedRec->u_32_value();
1244
Uint32 wsum = withdrawalSumRec->u_32_value();
1245
Uint32 wcount = withdrawalCountRec->u_32_value();
1246
Uint32 dsum = depositSumRec->u_32_value();
1247
Uint32 dcount = depositCountRec->u_32_value();
1248
Uint32 b = balanceRec->u_32_value();
1251
Uint32 withdrawalSum = 0;
1252
Uint32 withdrawalCount = 0;
1253
Uint32 depositSum = 0;
1254
Uint32 depositCount = 0;
1255
Uint32 countTransactions = 0;
1257
// If purged == 0, then the TRANSACTION table should be checked
1258
// to see that there are:
1259
// + DEPOSIT_COUNT deposit transactions with account_type == ACCOUNT_TYPE
1260
// and TIME == glTime. The sum of these transactions should be
1262
// + WITHDRAWAL_COUNT withdrawal transactions with account_type ==
1263
// ACCOUNT_TYPE and TIME == glTime. The sum of these transactions
1264
// should be WITHDRAWAL_SUM
1265
// + BALANCE should be equal to the sum of all transactions plus
1266
// the balance of the previous GL record
1267
if (sumTransactionsForGL(t,
1275
pScanTrans) != NDBT_OK){
1276
result = NDBT_FAILED;
1278
Uint32 prevBalance = 0;
1279
if (getBalanceForGL(t-1, a, prevBalance) != NDBT_OK){
1280
result = NDBT_FAILED;
1282
if (((prevBalance + balance) != b) ||
1283
(wsum != withdrawalSum) ||
1284
(wcount != withdrawalCount) ||
1285
(dsum != depositSum) ||
1286
(dcount != depositCount)){
1287
g_err << "performValidateGL, sums and counts failed" << endl
1288
<< "balance : " << balance+prevBalance << "!="<<b<<endl
1289
<< "with sum : " << withdrawalSum << "!="<<wsum<<endl
1290
<< "with count: " << withdrawalCount << "!="<<wcount<<endl
1291
<< "dep sum : " << depositSum << "!="<<dsum<<endl
1292
<< "dep count : " << depositCount << "!="<<dcount<<endl;
1293
result = VERIFICATION_FAILED;
1298
assert(purged == 1);
1299
// If purged == 1 then there should be NO transactions with
1300
// TIME == glTime and ACCOUNT_TYPE == account_type
1302
if (sumTransactionsForGL(t,
1310
pScanTrans) != NDBT_OK){
1311
result = NDBT_FAILED;
1313
if (countTransactions != 0){
1314
g_err << "performValidateGL, countTransactions("<<countTransactions<<") != 0" << endl;
1315
result = VERIFICATION_FAILED;
1321
eof = pOp->nextResult();
1324
ERR(pScanTrans->getNdbError());
1325
m_ndb.closeTransaction(pScanTrans);
1329
m_ndb.closeTransaction(pScanTrans);
1331
// - There should be zero or NoAccountTypes GL records for each glTime
1332
if ((countGlRecords != 0) && (countGlRecords != getNumAccountTypes())){
1333
g_err << "performValidateGL: " << endl
1334
<< "countGlRecords = " << countGlRecords << endl;
1335
result = VERIFICATION_FAILED;
1343
int Bank::getBalanceForGL(const Uint64 glTime,
1344
const Uint32 accountTypeId,
1348
NdbConnection* pTrans = m_ndb.startTransaction();
1349
if (pTrans == NULL) {
1350
ERR(m_ndb.getNdbError());
1354
NdbOperation* pOp = pTrans->getNdbOperation("GL");
1356
ERR(pTrans->getNdbError());
1360
check = pOp->readTuple();
1362
ERR(pTrans->getNdbError());
1366
check = pOp->equal("TIME", glTime);
1368
ERR(pTrans->getNdbError());
1372
check = pOp->equal("ACCOUNT_TYPE", accountTypeId);
1374
ERR(pTrans->getNdbError());
1378
NdbRecAttr* balanceRec = pOp->getValue("BALANCE");
1379
if( balanceRec == NULL ) {
1380
ERR(pTrans->getNdbError());
1384
check = pTrans->execute(Commit);
1386
ERR(pTrans->getNdbError());
1390
m_ndb.closeTransaction(pTrans);
1392
balance = balanceRec->u_32_value();
1399
int Bank::getOldestPurgedGL(const Uint32 accountType,
1403
* SELECT MAX(time) FROM GL WHERE account_type = @accountType and purged=1
1405
NdbConnection* pScanTrans = 0;
1408
pScanTrans = m_ndb.startTransaction();
1409
if (pScanTrans == NULL) {
1410
ERR(m_ndb.getNdbError());
1414
NdbScanOperation* pOp = pScanTrans->getNdbScanOperation("GL");
1416
ERR(pScanTrans->getNdbError());
1417
m_ndb.closeTransaction(pScanTrans);
1421
if( pOp->readTuples() ) {
1422
ERR(pScanTrans->getNdbError());
1423
m_ndb.closeTransaction(pScanTrans);
1427
check = pOp->interpret_exit_ok();
1429
ERR(pScanTrans->getNdbError());
1430
m_ndb.closeTransaction(pScanTrans);
1434
NdbRecAttr* accountTypeRec = pOp->getValue("ACCOUNT_TYPE");
1435
if( accountTypeRec ==NULL ) {
1436
ERR(pScanTrans->getNdbError());
1437
m_ndb.closeTransaction(pScanTrans);
1441
NdbRecAttr* timeRec = pOp->getValue("TIME");
1442
if( timeRec ==NULL ) {
1443
ERR(pScanTrans->getNdbError());
1444
m_ndb.closeTransaction(pScanTrans);
1448
NdbRecAttr* purgedRec = pOp->getValue("PURGED");
1449
if( purgedRec ==NULL ) {
1450
ERR(pScanTrans->getNdbError());
1451
m_ndb.closeTransaction(pScanTrans);
1455
check = pScanTrans->execute(NoCommit);
1457
NdbError err = pScanTrans->getNdbError();
1459
m_ndb.closeTransaction(pScanTrans);
1460
if (err.status == NdbError::TemporaryError)
1462
NdbSleep_MilliSleep(50);
1470
eof = pOp->nextResult();
1475
Uint32 a = accountTypeRec->u_32_value();
1476
Uint32 p = purgedRec->u_32_value();
1478
if (a == accountType && p == 1){
1480
Uint64 t = timeRec->u_64_value();
1484
eof = pOp->nextResult();
1488
NdbError err = pScanTrans->getNdbError();
1490
m_ndb.closeTransaction(pScanTrans);
1492
if (err.status == NdbError::TemporaryError)
1494
NdbSleep_MilliSleep(50);
1502
m_ndb.closeTransaction(pScanTrans);
1507
int Bank::getOldestNotPurgedGL(Uint64 &oldest,
1508
Uint32 &accountTypeId,
1512
* SELECT time, accountTypeId FROM GL
1513
* WHERE purged=0 order by time asc
1515
NdbConnection* pScanTrans = m_ndb.startTransaction();
1516
if (pScanTrans == NULL) {
1517
ERR(m_ndb.getNdbError());
1521
NdbScanOperation* pOp = pScanTrans->getNdbScanOperation("GL");
1523
ERR(pScanTrans->getNdbError());
1524
m_ndb.closeTransaction(pScanTrans);
1528
if( pOp->readTuples() ) {
1529
ERR(pScanTrans->getNdbError());
1530
m_ndb.closeTransaction(pScanTrans);
1534
check = pOp->interpret_exit_ok();
1536
ERR(pScanTrans->getNdbError());
1537
m_ndb.closeTransaction(pScanTrans);
1541
NdbRecAttr* accountTypeRec = pOp->getValue("ACCOUNT_TYPE");
1542
if( accountTypeRec ==NULL ) {
1543
ERR(pScanTrans->getNdbError());
1544
m_ndb.closeTransaction(pScanTrans);
1548
NdbRecAttr* timeRec = pOp->getValue("TIME");
1549
if( timeRec ==NULL ) {
1550
ERR(pScanTrans->getNdbError());
1551
m_ndb.closeTransaction(pScanTrans);
1555
NdbRecAttr* purgedRec = pOp->getValue("PURGED");
1556
if( purgedRec ==NULL ) {
1557
ERR(pScanTrans->getNdbError());
1558
m_ndb.closeTransaction(pScanTrans);
1562
check = pScanTrans->execute(NoCommit);
1564
ERR(pScanTrans->getNdbError());
1565
m_ndb.closeTransaction(pScanTrans);
1571
eof = pOp->nextResult();
1572
oldest = (Uint64)-1;
1577
Uint32 p = purgedRec->u_32_value();
1581
Uint32 a = accountTypeRec->u_32_value();
1582
Uint64 t = timeRec->u_64_value();
1588
eof = pOp->nextResult();
1591
ERR(pScanTrans->getNdbError());
1592
m_ndb.closeTransaction(pScanTrans);
1596
m_ndb.closeTransaction(pScanTrans);
1602
int Bank::checkNoTransactionsOlderThan(const Uint32 accountType,
1603
const Uint64 oldest){
1605
* SELECT COUNT(transaction_id) FROM TRANSACTION
1606
* WHERE account_type = @accountType and time <= @oldest
1612
NdbConnection* pScanTrans = 0;
1616
pScanTrans = m_ndb.startTransaction();
1617
if (pScanTrans == NULL) {
1618
ERR(m_ndb.getNdbError());
1622
NdbScanOperation* pOp = pScanTrans->getNdbScanOperation("TRANSACTION");
1624
ERR(pScanTrans->getNdbError());
1625
m_ndb.closeTransaction(pScanTrans);
1629
if( pOp->readTuples() ) {
1630
ERR(pScanTrans->getNdbError());
1631
m_ndb.closeTransaction(pScanTrans);
1635
check = pOp->interpret_exit_ok();
1637
ERR(pScanTrans->getNdbError());
1638
m_ndb.closeTransaction(pScanTrans);
1642
NdbRecAttr* accountTypeRec = pOp->getValue("ACCOUNT_TYPE");
1643
if( accountTypeRec ==NULL ) {
1644
ERR(pScanTrans->getNdbError());
1645
m_ndb.closeTransaction(pScanTrans);
1649
NdbRecAttr* timeRec = pOp->getValue("TIME");
1650
if( timeRec ==NULL ) {
1651
ERR(pScanTrans->getNdbError());
1652
m_ndb.closeTransaction(pScanTrans);
1656
NdbRecAttr* transactionIdRec = pOp->getValue("TRANSACTION_ID");
1657
if( transactionIdRec ==NULL ) {
1658
ERR(pScanTrans->getNdbError());
1659
m_ndb.closeTransaction(pScanTrans);
1663
check = pScanTrans->execute(NoCommit);
1665
NdbError err = pScanTrans->getNdbError();
1667
m_ndb.closeTransaction(pScanTrans);
1669
if (err.status == NdbError::TemporaryError)
1671
NdbSleep_MilliSleep(50);
1680
eof = pOp->nextResult();
1684
Uint32 a = accountTypeRec->u_32_value();
1685
Uint32 t = timeRec->u_32_value();
1687
if (a == accountType && t <= oldest){
1689
Uint64 ti = transactionIdRec->u_64_value();
1690
g_err << "checkNoTransactionsOlderThan found one record" << endl
1691
<< " t = " << t << endl
1692
<< " a = " << a << endl
1693
<< " ti = " << ti << endl;
1696
eof = pOp->nextResult();
1699
NdbError err = pScanTrans->getNdbError();
1701
m_ndb.closeTransaction(pScanTrans);
1703
if (err.status == NdbError::TemporaryError)
1705
NdbSleep_MilliSleep(50);
1715
m_ndb.closeTransaction(pScanTrans);
1720
return VERIFICATION_FAILED;
1724
int Bank::performValidatePurged(){
1726
* Make sure there are no TRANSACTIONS older than the oldest
1731
for (int i = 0; i < getNumAccountTypes(); i++){
1732
ndbout << "performValidatePurged: " << i << endl;
1733
Uint64 oldestGlTime;
1734
if (getOldestPurgedGL(i, oldestGlTime) != NDBT_OK){
1735
g_err << "getOldestPurgedGL failed" << endl;
1738
int result = checkNoTransactionsOlderThan(i, oldestGlTime);
1739
if (result != NDBT_OK){
1740
g_err << "checkNoTransactionsOlderThan failed" << endl;
1749
int Bank::purgeOldGLTransactions(Uint64 currTime, Uint32 age){
1751
* For each GL record that are older than age and have purged == 0
1752
* - delete all TRANSACTIONS belonging to the GL and set purged = 1
1764
// Search for the oldest GL record with purged == 0
1765
Uint64 oldestGlTime;
1766
Uint32 accountTypeId;
1767
if (getOldestNotPurgedGL(oldestGlTime, accountTypeId, found) != NDBT_OK){
1768
g_err << "getOldestNotPurgedGL failed" << endl;
1773
if (found == false){
1774
// ndbout << "not found" << endl;
1779
// ndbout << "purgeOldGLTransactions" << endl
1780
// << " oldestGlTime = " << oldestGlTime << endl
1781
// << " currTime = " << currTime << endl
1782
// << " age = " << age << endl;
1783
// Check if this GL is old enough to be purged
1784
if ((currTime < age) || (oldestGlTime > (currTime-age))){
1785
// ndbout << "is not old enough" << endl;
1789
if (purgeTransactions(oldestGlTime, accountTypeId) != NDBT_OK){
1790
g_err << "purgeTransactions failed" << endl;
1794
g_err << "abnormal return" << endl;
1799
int Bank::purgeTransactions(const Uint64 glTime,
1800
const Uint32 accountTypeId)
1803
g_info << "purgeTransactions: " << glTime << ", "<<accountTypeId<<endl;
1804
NdbConnection* pTrans = m_ndb.startTransaction();
1805
if (pTrans == NULL){
1806
ERR(m_ndb.getNdbError());
1810
// Start by updating the GL record with purged = 1, use NoCommit
1811
NdbOperation* pOp = pTrans->getNdbOperation("GL");
1813
ERR(pTrans->getNdbError());
1817
check = pOp->updateTuple();
1819
ERR(pTrans->getNdbError());
1823
check = pOp->equal("TIME", glTime);
1825
ERR(pTrans->getNdbError());
1829
check = pOp->equal("ACCOUNT_TYPE", accountTypeId);
1831
ERR(pTrans->getNdbError());
1836
check = pOp->setValue("PURGED", purged);
1838
ERR(pTrans->getNdbError());
1842
// Execute transaction
1843
check = pTrans->execute(NoCommit);
1845
ERR(pTrans->getNdbError());
1849
// Find all transactions and take over them for delete
1851
if(findTransactionsToPurge(glTime,
1853
pTrans) != NDBT_OK){
1854
g_err << "findTransactionToPurge failed" << endl;
1855
m_ndb.closeTransaction(pTrans);
1861
check = pTrans->execute(Commit);
1863
ERR(pTrans->getNdbError());
1867
m_ndb.closeTransaction(pTrans);
1872
int Bank::findTransactionsToPurge(const Uint64 glTime,
1873
const Uint32 accountType,
1874
NdbConnection* pTrans){
1877
NdbConnection* pScanTrans = m_ndb.startTransaction();
1878
if (pScanTrans == NULL) {
1879
ERR(m_ndb.getNdbError());
1883
NdbScanOperation* pOp = pScanTrans->getNdbScanOperation("TRANSACTION");
1885
ERR(pScanTrans->getNdbError());
1886
m_ndb.closeTransaction(pScanTrans);
1890
if( pOp->readTuplesExclusive() ) {
1891
ERR(pScanTrans->getNdbError());
1892
m_ndb.closeTransaction(pScanTrans);
1896
check = pOp->interpret_exit_ok();
1898
ERR(pScanTrans->getNdbError());
1899
m_ndb.closeTransaction(pScanTrans);
1903
NdbRecAttr* timeRec = pOp->getValue("TIME");
1904
if( timeRec ==NULL ) {
1905
ERR(pScanTrans->getNdbError());
1906
m_ndb.closeTransaction(pScanTrans);
1910
NdbRecAttr* accountTypeRec = pOp->getValue("ACCOUNT_TYPE");
1911
if( accountTypeRec ==NULL ) {
1912
ERR(pScanTrans->getNdbError());
1913
m_ndb.closeTransaction(pScanTrans);
1917
check = pScanTrans->execute(NoCommit);
1919
ERR(pScanTrans->getNdbError());
1920
m_ndb.closeTransaction(pScanTrans);
1927
eof = pOp->nextResult();
1931
Uint64 t = timeRec->u_64_value();
1932
Uint32 a = accountTypeRec->u_32_value();
1934
if (a == accountType && t == glTime){
1937
check = pOp->deleteCurrentTuple(pTrans);
1939
ERR(m_ndb.getNdbError());
1940
m_ndb.closeTransaction(pScanTrans);
1944
// Execute transaction
1945
check = pTrans->execute(NoCommit);
1947
ERR(pTrans->getNdbError());
1948
m_ndb.closeTransaction(pScanTrans);
1952
eof = pOp->nextResult();
1955
ERR(pScanTrans->getNdbError());
1956
m_ndb.closeTransaction(pScanTrans);
1960
m_ndb.closeTransaction(pScanTrans);
1961
// ndbout << rowsFound << " TRANSACTIONS have been deleted" << endl;
1968
int Bank::performIncreaseTime(int maxSleepBetweenDays, int yield)
1970
int yieldCounter = 0;
1975
if (incCurrTime(currTime) != NDBT_OK)
1978
g_info << "Current time is " << currTime << endl;
1979
if (maxSleepBetweenDays > 0){
1980
int val = myRandom48(maxSleepBetweenDays);
1981
NdbSleep_SecSleep(val);
1985
if (yield != 0 && yieldCounter >= yield)
1992
int Bank::readSystemValue(SystemValueId sysValId, Uint64 & value){
1995
NdbConnection* pTrans = 0;
1998
pTrans = m_ndb.startTransaction();
2001
ERR(m_ndb.getNdbError());
2002
if(m_ndb.getNdbError().status == NdbError::TemporaryError)
2004
NdbSleep_MilliSleep(50);
2011
if ((result= prepareReadSystemValueOp(pTrans, sysValId, value)) != NDBT_OK)
2013
ERR(pTrans->getNdbError());
2014
m_ndb.closeTransaction(pTrans);
2018
check = pTrans->execute(Commit);
2020
NdbError err = pTrans->getNdbError();
2021
m_ndb.closeTransaction(pTrans);
2023
if(err.status == NdbError::TemporaryError)
2025
NdbSleep_MilliSleep(50);
2034
m_ndb.closeTransaction(pTrans);
2039
int Bank::prepareReadSystemValueOp(NdbConnection* pTrans, SystemValueId sysValId, Uint64 & value){
2043
NdbOperation* pOp = pTrans->getNdbOperation("SYSTEM_VALUES");
2048
check = pOp->readTuple();
2053
check = pOp->equal("SYSTEM_VALUES_ID", sysValId);
2058
NdbRecAttr* valueRec = pOp->getValue("VALUE", (char *)&value);
2059
if( valueRec == NULL ) {
2066
int Bank::writeSystemValue(SystemValueId sysValId, Uint64 value){
2070
NdbConnection* pTrans = m_ndb.startTransaction();
2071
if (pTrans == NULL){
2072
ERR(m_ndb.getNdbError());
2076
NdbOperation* pOp = pTrans->getNdbOperation("SYSTEM_VALUES");
2078
ERR(pTrans->getNdbError());
2079
m_ndb.closeTransaction(pTrans);
2083
check = pOp->insertTuple();
2085
ERR(pTrans->getNdbError());
2086
m_ndb.closeTransaction(pTrans);
2090
check = pOp->equal("SYSTEM_VALUES_ID", sysValId);
2092
ERR(pTrans->getNdbError());
2093
m_ndb.closeTransaction(pTrans);
2097
check = pOp->setValue("VALUE", value);
2099
ERR(pTrans->getNdbError());
2100
m_ndb.closeTransaction(pTrans);
2104
check = pTrans->execute(Commit);
2106
ERR(pTrans->getNdbError());
2107
m_ndb.closeTransaction(pTrans);
2111
m_ndb.closeTransaction(pTrans);
2116
int Bank::getNextTransactionId(Uint64 &value){
2117
return increaseSystemValue2(LastTransactionId, value);
2120
int Bank::incCurrTime(Uint64 &value){
2121
return increaseSystemValue(CurrentTime, value);
2125
int Bank::increaseSystemValue(SystemValueId sysValId, Uint64 &value){
2127
* Increase value with one and return
2132
DBUG_ENTER("Bank::increaseSystemValue");
2136
NdbConnection* pTrans = m_ndb.startTransaction();
2137
if (pTrans == NULL){
2138
ERR(m_ndb.getNdbError());
2139
if (m_ndb.getNdbError().status == NdbError::TemporaryError)
2140
DBUG_RETURN(NDBT_TEMPORARY);
2141
DBUG_RETURN(NDBT_FAILED);
2144
NdbOperation* pOp = pTrans->getNdbOperation("SYSTEM_VALUES");
2146
ERR(pTrans->getNdbError());
2147
m_ndb.closeTransaction(pTrans);
2148
DBUG_RETURN(NDBT_FAILED);
2151
check = pOp->readTupleExclusive();
2152
// check = pOp->readTuple();
2154
ERR(pTrans->getNdbError());
2155
m_ndb.closeTransaction(pTrans);
2156
DBUG_RETURN(NDBT_FAILED);
2159
check = pOp->equal("SYSTEM_VALUES_ID", sysValId);
2161
ERR(pTrans->getNdbError());
2162
m_ndb.closeTransaction(pTrans);
2163
DBUG_RETURN(NDBT_FAILED);
2166
NdbRecAttr* valueRec = pOp->getValue("VALUE");
2167
if( valueRec ==NULL ) {
2168
ERR(pTrans->getNdbError());
2169
m_ndb.closeTransaction(pTrans);
2170
DBUG_RETURN(NDBT_FAILED);
2173
check = pTrans->execute(NoCommit);
2175
ERR(pTrans->getNdbError());
2176
if (pTrans->getNdbError().status == NdbError::TemporaryError)
2178
m_ndb.closeTransaction(pTrans);
2179
DBUG_RETURN(NDBT_TEMPORARY);
2181
m_ndb.closeTransaction(pTrans);
2182
DBUG_RETURN(NDBT_FAILED);
2185
value = valueRec->u_64_value();
2188
NdbOperation* pOp2 = pTrans->getNdbOperation("SYSTEM_VALUES");
2190
ERR(pTrans->getNdbError());
2191
m_ndb.closeTransaction(pTrans);
2192
DBUG_RETURN(NDBT_FAILED);
2195
check = pOp2->updateTuple();
2197
ERR(pTrans->getNdbError());
2198
m_ndb.closeTransaction(pTrans);
2199
DBUG_RETURN(NDBT_FAILED);
2202
check = pOp2->equal("SYSTEM_VALUES_ID", sysValId);
2204
ERR(pTrans->getNdbError());
2205
m_ndb.closeTransaction(pTrans);
2206
DBUG_RETURN(NDBT_FAILED);
2209
check = pOp2->setValue("VALUE", value);
2211
ERR(pTrans->getNdbError());
2212
m_ndb.closeTransaction(pTrans);
2213
DBUG_RETURN(NDBT_FAILED);
2216
check = pTrans->execute(NoCommit);
2218
ERR(pTrans->getNdbError());
2219
m_ndb.closeTransaction(pTrans);
2220
DBUG_RETURN(NDBT_FAILED);
2223
NdbOperation* pOp3 = pTrans->getNdbOperation("SYSTEM_VALUES");
2225
ERR(pTrans->getNdbError());
2226
m_ndb.closeTransaction(pTrans);
2227
DBUG_RETURN(NDBT_FAILED);
2230
check = pOp3->readTuple();
2232
ERR(pTrans->getNdbError());
2233
m_ndb.closeTransaction(pTrans);
2234
DBUG_RETURN(NDBT_FAILED);
2237
check = pOp3->equal("SYSTEM_VALUES_ID", sysValId);
2239
ERR(pTrans->getNdbError());
2240
m_ndb.closeTransaction(pTrans);
2241
DBUG_RETURN(NDBT_FAILED);
2245
NdbRecAttr* valueNewRec = pOp3->getValue("VALUE");
2246
if( valueNewRec ==NULL ) {
2247
ERR(pTrans->getNdbError());
2248
m_ndb.closeTransaction(pTrans);
2249
DBUG_RETURN(NDBT_FAILED);
2252
check = pTrans->execute(Commit);
2254
ERR(pTrans->getNdbError());
2255
if (pTrans->getNdbError().status == NdbError::TemporaryError)
2257
m_ndb.closeTransaction(pTrans);
2258
DBUG_RETURN(NDBT_TEMPORARY);
2260
m_ndb.closeTransaction(pTrans);
2261
DBUG_RETURN(NDBT_FAILED);
2264
// Check that value updated equals the value we read after the update
2265
if (valueNewRec->u_64_value() != value){
2267
printf("value actual=%lld\n", valueNewRec->u_64_value());
2268
printf("value expected=%lld actual=%lld\n", value, valueNewRec->u_64_value());
2270
DBUG_PRINT("info", ("value expected=%ld actual=%ld", value, valueNewRec->u_64_value()));
2271
g_err << "getNextTransactionId: value was not updated" << endl;
2272
m_ndb.closeTransaction(pTrans);
2273
DBUG_RETURN(NDBT_FAILED);
2276
m_ndb.closeTransaction(pTrans);
2281
int Bank::increaseSystemValue2(SystemValueId sysValId, Uint64 &value){
2283
* Increase value with one and return
2285
* A more optimized version using interpreted update!
2291
NdbConnection* pTrans = m_ndb.startTransaction();
2292
if (pTrans == NULL){
2293
ERR(m_ndb.getNdbError());
2294
if(m_ndb.getNdbError().status == NdbError::TemporaryError)
2295
return NDBT_TEMPORARY;
2299
NdbOperation* pOp = pTrans->getNdbOperation("SYSTEM_VALUES");
2301
ERR(pTrans->getNdbError());
2302
m_ndb.closeTransaction(pTrans);
2306
check = pOp->interpretedUpdateTuple();
2308
ERR(pTrans->getNdbError());
2309
m_ndb.closeTransaction(pTrans);
2313
check = pOp->equal("SYSTEM_VALUES_ID", sysValId );
2315
ERR(pTrans->getNdbError());
2316
m_ndb.closeTransaction(pTrans);
2320
Uint32 valToIncWith = 1;
2321
check = pOp->incValue("VALUE", valToIncWith);
2323
ERR(pTrans->getNdbError());
2324
m_ndb.closeTransaction(pTrans);
2328
NdbRecAttr* valueRec = pOp->getValue("VALUE");
2329
if( valueRec == NULL ) {
2330
ERR(pTrans->getNdbError());
2331
m_ndb.closeTransaction(pTrans);
2335
check = pTrans->execute(Commit);
2337
ERR(pTrans->getNdbError());
2338
if(pTrans->getNdbError().status == NdbError::TemporaryError)
2340
m_ndb.closeTransaction(pTrans);
2341
return NDBT_TEMPORARY;
2343
m_ndb.closeTransaction(pTrans);
2347
value = valueRec->u_64_value();
2349
m_ndb.closeTransaction(pTrans);
2357
int Bank::getCurrTime(Uint64 &time){
2358
return readSystemValue(CurrentTime, time);
2361
int Bank::prepareGetCurrTimeOp(NdbConnection *pTrans, Uint64 &time){
2362
return prepareReadSystemValueOp(pTrans, CurrentTime, time);
2366
int Bank::performSumAccounts(int maxSleepBetweenSums, int yield){
2368
int yieldCounter = 0;
2372
Uint32 sumAccounts = 0;
2373
Uint32 numAccounts = 0;
2374
if (getSumAccounts(sumAccounts, numAccounts) != NDBT_OK){
2375
g_err << "getSumAccounts FAILED" << endl;
2378
g_info << "num="<<numAccounts<<", sum=" << sumAccounts << endl;
2380
if (sumAccounts != (10000000 + (10000*(numAccounts-1)))){
2381
g_err << "performSumAccounts FAILED" << endl
2382
<< " sumAccounts="<<sumAccounts<<endl
2383
<< " expected ="<<(10000000 + (10000*(numAccounts-1)))<<endl
2384
<< " numAccounts="<<numAccounts<<endl;
2388
if (maxSleepBetweenSums > 0){
2389
int val = myRandom48(maxSleepBetweenSums);
2390
NdbSleep_MilliSleep(val);
2395
if (yield != 0 && yieldCounter >= yield)
2402
int Bank::getSumAccounts(Uint32 &sumAccounts,
2403
Uint32 &numAccounts){
2405
// SELECT SUM(balance) FROM ACCOUNT
2408
NdbConnection* pScanTrans = m_ndb.startTransaction();
2409
if (pScanTrans == NULL) {
2410
ERR(m_ndb.getNdbError());
2414
NdbScanOperation* pOp = pScanTrans->getNdbScanOperation("ACCOUNT");
2416
ERR(pScanTrans->getNdbError());
2417
m_ndb.closeTransaction(pScanTrans);
2421
if( pOp->readTuplesExclusive() ) {
2422
ERR(pScanTrans->getNdbError());
2423
m_ndb.closeTransaction(pScanTrans);
2427
check = pOp->interpret_exit_ok();
2429
ERR(pScanTrans->getNdbError());
2430
m_ndb.closeTransaction(pScanTrans);
2434
NdbRecAttr* balanceRec = pOp->getValue("BALANCE");
2435
if( balanceRec ==NULL ) {
2436
ERR(pScanTrans->getNdbError());
2437
m_ndb.closeTransaction(pScanTrans);
2441
check = pScanTrans->execute(NoCommit);
2443
ERR(pScanTrans->getNdbError());
2444
m_ndb.closeTransaction(pScanTrans);
2448
NdbConnection* pTrans = m_ndb.startTransaction();
2449
if (pTrans == NULL) {
2450
ERR(m_ndb.getNdbError());
2451
m_ndb.closeTransaction(pScanTrans);
2456
eof = pOp->nextResult();
2459
Uint32 b = balanceRec->u_32_value();
2464
// ndbout << numAccounts << ": balance =" << b
2465
// << ", sum="<< sumAccounts << endl;
2467
// Take over the operation so that the lock is kept in db
2468
NdbOperation* pLockOp = pOp->updateCurrentTuple(pTrans);
2469
if (pLockOp == NULL){
2470
ERR(m_ndb.getNdbError());
2471
m_ndb.closeTransaction(pScanTrans);
2472
m_ndb.closeTransaction(pTrans);
2476
Uint32 illegalBalance = 99;
2477
check = pLockOp->setValue("BALANCE", illegalBalance);
2479
ERR(pTrans->getNdbError());
2480
m_ndb.closeTransaction(pTrans);
2481
m_ndb.closeTransaction(pScanTrans);
2485
// Execute transaction
2486
check = pTrans->execute(NoCommit);
2488
ERR(pTrans->getNdbError());
2489
m_ndb.closeTransaction(pScanTrans);
2490
m_ndb.closeTransaction(pTrans);
2494
eof = pOp->nextResult();
2497
ERR(pScanTrans->getNdbError());
2498
m_ndb.closeTransaction(pScanTrans);
2499
m_ndb.closeTransaction(pTrans);
2503
// TODO Forget about rolling back, just close pTrans!!
2505
// Rollback transaction
2506
check = pTrans->execute(Rollback);
2508
ERR(pTrans->getNdbError());
2509
m_ndb.closeTransaction(pScanTrans);
2510
m_ndb.closeTransaction(pTrans);
2514
m_ndb.closeTransaction(pScanTrans);
2515
m_ndb.closeTransaction(pTrans);