mySQL 5.0.11 sources for tomato
[tomato.git] / release / src / router / mysql / storage / ndb / test / ndbapi / bank / Bank.cpp
blob1ee8e24a57d4b74a76a008719e8983987792bd72
1 /* Copyright (c) 2003-2006 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
16 #include "Bank.hpp"
17 #include <time.h>
18 #include <NdbSleep.h>
19 #include <UtilTransactions.hpp>
21 Bank::Bank(Ndb_cluster_connection& con, bool _init, const char * dbase):
22 m_ndb(&con, dbase),
23 m_maxAccount(-1),
24 m_initialized(false),
25 m_skip_create(false)
27 if(_init)
28 init();
31 int Bank::init(){
32 if (m_initialized == true)
33 return NDBT_OK;
35 myRandom48Init(NdbTick_CurrentMillisecond());
37 m_ndb.init();
38 if (m_ndb.waitUntilReady(30) != 0)
40 ndbout << "Ndb not ready" << endl;
41 return NDBT_FAILED;
44 if (getNumAccounts() != NDBT_OK)
45 return NDBT_FAILED;
47 m_initialized = true;
48 return NDBT_OK;
51 int Bank::performTransactions(int maxSleepBetweenTrans, int yield){
53 int transactions = 0;
55 while(performTransaction() == NDBT_OK)
57 transactions++;
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)
68 return NDBT_OK;
71 return NDBT_FAILED;
75 int Bank::performTransaction(){
76 int result = NDBT_OK;
78 if (m_maxAccount <= 0){
79 g_err << "No accounts in bank" << endl;
80 return NDBT_FAILED;
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);
95 retry_transaction:
96 int res = performTransaction(fromAccount, toAccount, amount);
97 if (res != 0){
98 switch (res){
99 case NDBT_FAILED:
100 g_err << "performTransaction returned NDBT_FAILED" << endl
101 << " fromAccount = " << fromAccount << endl
102 << " toAccount = " << toAccount << endl
103 << " amount = " << amount << endl;
104 result = NDBT_FAILED;
105 break;
106 case NOT_ENOUGH_FUNDS:
107 // ndbout << "performTransaction returned NOT_ENOUGH_FUNDS" << endl;
108 break;
109 case NDBT_TEMPORARY:
110 g_err << "TEMPORARY_ERRROR retrying" << endl;
111 NdbSleep_MilliSleep(50);
112 goto retry_transaction;
113 break;
114 default:
115 g_info << "performTransaction returned "<<res << endl;
116 break;
119 return result;
123 * Perform a transaction in the bank.
124 * Ie. transfer money from one account to another.
126 * @param
127 * @return 0 if successful or an error code
129 int Bank::performTransaction(int fromAccountId,
130 int toAccountId,
131 int amount ){
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
137 * from account
138 * 4. Insert withdrawal in TRANSACTION
139 * 5. Insert deposit in transaction
140 * 6. Update ACCOUNT set balance = balance + amount on
141 * to account
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,
155 int toAccountId,
156 int amount ){
158 int check;
160 // Ok, all clear to do the transaction
161 Uint64 transId;
162 int result = NDBT_OK;
163 if ((result= getNextTransactionId(transId)) != NDBT_OK){
164 return result;
167 NdbConnection* pTrans = m_ndb.startTransaction();
169 if( pTrans == NULL ) {
170 const NdbError err = m_ndb.getNdbError();
171 if (err.status == NdbError::TemporaryError){
172 ERR(err);
173 return NDBT_TEMPORARY;
175 ERR(err);
176 return NDBT_FAILED;
179 Uint64 currTime;
180 if (prepareGetCurrTimeOp(pTrans, currTime) != NDBT_OK){
181 ERR(pTrans->getNdbError());
182 m_ndb.closeTransaction(pTrans);
183 return NDBT_FAILED;
186 /**
187 * Check balance on from account
189 NdbOperation* pOp = pTrans->getNdbOperation("ACCOUNT");
190 if (pOp == NULL) {
191 ERR(pTrans->getNdbError());
192 m_ndb.closeTransaction(pTrans);
193 return NDBT_FAILED;
196 check = pOp->readTupleExclusive();
197 if( check == -1 ) {
198 ERR(pTrans->getNdbError());
199 m_ndb.closeTransaction(pTrans);
200 return NDBT_FAILED;
203 check = pOp->equal("ACCOUNT_ID", fromAccountId);
204 if( check == -1 ) {
205 ERR(pTrans->getNdbError());
206 m_ndb.closeTransaction(pTrans);
207 return NDBT_FAILED;
210 NdbRecAttr* balanceFromRec = pOp->getValue("BALANCE");
211 if( balanceFromRec ==NULL ) {
212 ERR(pTrans->getNdbError());
213 m_ndb.closeTransaction(pTrans);
214 return NDBT_FAILED;
217 NdbRecAttr* fromAccountTypeRec = pOp->getValue("ACCOUNT_TYPE");
218 if( fromAccountTypeRec == NULL ) {
219 ERR(pTrans->getNdbError());
220 m_ndb.closeTransaction(pTrans);
221 return NDBT_FAILED;
224 /**
225 * Read balance on to account
227 NdbOperation* pOp6 = pTrans->getNdbOperation("ACCOUNT");
228 if (pOp6 == NULL) {
229 ERR(pTrans->getNdbError());
230 m_ndb.closeTransaction(pTrans);
231 return NDBT_FAILED;
234 check = pOp6->readTupleExclusive();
235 if( check == -1 ) {
236 ERR(pTrans->getNdbError());
237 m_ndb.closeTransaction(pTrans);
238 return NDBT_FAILED;
241 check = pOp6->equal("ACCOUNT_ID", toAccountId);
242 if( check == -1 ) {
243 ERR(pTrans->getNdbError());
244 m_ndb.closeTransaction(pTrans);
245 return NDBT_FAILED;
248 NdbRecAttr* balanceToRec = pOp6->getValue("BALANCE");
249 if( balanceToRec == NULL ) {
250 ERR(pTrans->getNdbError());
251 m_ndb.closeTransaction(pTrans);
252 return NDBT_FAILED;
255 NdbRecAttr* toAccountTypeRec = pOp6->getValue("ACCOUNT_TYPE");
256 if( toAccountTypeRec == NULL ) {
257 ERR(pTrans->getNdbError());
258 m_ndb.closeTransaction(pTrans);
259 return NDBT_FAILED;
262 check = pTrans->execute(NoCommit);
263 if( check == -1 ) {
264 const NdbError err = pTrans->getNdbError();
265 m_ndb.closeTransaction(pTrans);
266 if (err.status == NdbError::TemporaryError){
267 ERR(err);
268 return NDBT_TEMPORARY;
270 ERR(err);
271 return NDBT_FAILED;
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");
294 if (pOp2 == NULL) {
295 ERR(pTrans->getNdbError());
296 m_ndb.closeTransaction(pTrans);
297 return NDBT_FAILED;
300 check = pOp2->updateTuple();
301 if( check == -1 ) {
302 ERR(pTrans->getNdbError());
303 m_ndb.closeTransaction(pTrans);
304 return NDBT_FAILED;
307 check = pOp2->equal("ACCOUNT_ID", fromAccountId);
308 if( check == -1 ) {
309 ERR(pTrans->getNdbError());
310 m_ndb.closeTransaction(pTrans);
311 return NDBT_FAILED;
314 check = pOp2->setValue("BALANCE", balanceFrom - amount);
315 if( check == -1 ) {
316 ERR(pTrans->getNdbError());
317 m_ndb.closeTransaction(pTrans);
318 return NDBT_FAILED;
322 * Update balance on to account
324 NdbOperation* pOp3 = pTrans->getNdbOperation("ACCOUNT");
325 if (pOp3 == NULL) {
326 ERR(pTrans->getNdbError());
327 m_ndb.closeTransaction(pTrans);
328 return NDBT_FAILED;
331 check = pOp3->updateTuple();
332 if( check == -1 ) {
333 ERR(pTrans->getNdbError());
334 m_ndb.closeTransaction(pTrans);
335 return NDBT_FAILED;
338 check = pOp3->equal("ACCOUNT_ID", toAccountId);
339 if( check == -1 ) {
340 ERR(pTrans->getNdbError());
341 m_ndb.closeTransaction(pTrans);
342 return NDBT_FAILED;
345 check = pOp3->setValue("BALANCE", balanceTo + amount);
346 if( check == -1 ) {
347 ERR(pTrans->getNdbError());
348 m_ndb.closeTransaction(pTrans);
349 return NDBT_FAILED;
353 * Insert withdrawal transaction
355 NdbOperation* pOp4 = pTrans->getNdbOperation("TRANSACTION");
356 if (pOp4 == NULL) {
357 ERR(pTrans->getNdbError());
358 m_ndb.closeTransaction(pTrans);
359 return NDBT_FAILED;
362 check = pOp4->insertTuple();
363 if( check == -1 ) {
364 ERR(pTrans->getNdbError());
365 m_ndb.closeTransaction(pTrans);
366 return NDBT_FAILED;
369 check = pOp4->equal("TRANSACTION_ID", transId);
370 if( check == -1 ) {
371 ERR(pTrans->getNdbError());
372 m_ndb.closeTransaction(pTrans);
373 return NDBT_FAILED;
376 check = pOp4->equal("ACCOUNT", fromAccountId);
377 if( check == -1 ) {
378 ERR(pTrans->getNdbError());
379 m_ndb.closeTransaction(pTrans);
380 return NDBT_FAILED;
383 check = pOp4->setValue("ACCOUNT_TYPE", fromAccountType);
384 if( check == -1 ) {
385 ERR(pTrans->getNdbError());
386 m_ndb.closeTransaction(pTrans);
387 return NDBT_FAILED;
390 check = pOp4->setValue("OTHER_ACCOUNT", toAccountId);
391 if( check == -1 ) {
392 ERR(pTrans->getNdbError());
393 m_ndb.closeTransaction(pTrans);
394 return NDBT_FAILED;
397 check = pOp4->setValue("TRANSACTION_TYPE", WithDrawal);
398 if( check == -1 ) {
399 ERR(pTrans->getNdbError());
400 m_ndb.closeTransaction(pTrans);
401 return NDBT_FAILED;
404 check = pOp4->setValue("TIME", currTime);
405 if( check == -1 ) {
406 ERR(pTrans->getNdbError());
407 m_ndb.closeTransaction(pTrans);
408 return NDBT_FAILED;
411 check = pOp4->setValue("AMOUNT", amount);
412 if( check == -1 ) {
413 ERR(pTrans->getNdbError());
414 m_ndb.closeTransaction(pTrans);
415 return NDBT_FAILED;
419 * Insert deposit transaction
421 NdbOperation* pOp5 = pTrans->getNdbOperation("TRANSACTION");
422 if (pOp5 == NULL) {
423 ERR(pTrans->getNdbError());
424 m_ndb.closeTransaction(pTrans);
425 return NDBT_FAILED;
428 check = pOp5->insertTuple();
429 if( check == -1 ) {
430 ERR(pTrans->getNdbError());
431 m_ndb.closeTransaction(pTrans);
432 return NDBT_FAILED;
435 check = pOp5->equal("TRANSACTION_ID", transId);
436 if( check == -1 ) {
437 ERR(pTrans->getNdbError());
438 m_ndb.closeTransaction(pTrans);
439 return NDBT_FAILED;
442 check = pOp5->equal("ACCOUNT", toAccountId);
443 if( check == -1 ) {
444 ERR(pTrans->getNdbError());
445 m_ndb.closeTransaction(pTrans);
446 return NDBT_FAILED;
449 check = pOp5->setValue("ACCOUNT_TYPE", toAccountType);
450 if( check == -1 ) {
451 ERR(pTrans->getNdbError());
452 m_ndb.closeTransaction(pTrans);
453 return NDBT_FAILED;
456 check = pOp5->setValue("OTHER_ACCOUNT", fromAccountId);
457 if( check == -1 ) {
458 ERR(pTrans->getNdbError());
459 m_ndb.closeTransaction(pTrans);
460 return NDBT_FAILED;
463 check = pOp5->setValue("TRANSACTION_TYPE", Deposit);
464 if( check == -1 ) {
465 ERR(pTrans->getNdbError());
466 m_ndb.closeTransaction(pTrans);
467 return NDBT_FAILED;
470 check = pOp5->setValue("TIME", currTime);
471 if( check == -1 ) {
472 ERR(pTrans->getNdbError());
473 m_ndb.closeTransaction(pTrans);
474 return NDBT_FAILED;
477 check = pOp5->setValue("AMOUNT", amount);
478 if( check == -1 ) {
479 ERR(pTrans->getNdbError());
480 m_ndb.closeTransaction(pTrans);
481 return NDBT_FAILED;
484 check = pTrans->execute(Commit);
485 if( check == -1 ) {
486 const NdbError err = pTrans->getNdbError();
487 m_ndb.closeTransaction(pTrans);
488 if (err.status == NdbError::TemporaryError){
489 ERR(err);
490 return NDBT_TEMPORARY;
492 ERR(err);
493 return NDBT_FAILED;
496 m_ndb.closeTransaction(pTrans);
497 return NDBT_OK;
503 int Bank::performMakeGLs(int yield){
504 int result;
506 int counter, maxCounter;
507 int yieldCounter = 0;
509 while (1){
510 // Counters to keep tracck of how many
511 // GLs should be made before performing a validation
512 counter = 0;
513 maxCounter = 50 + myRandom48(100);
515 /**
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;
523 return NDBT_FAILED;
525 g_info << "performValidateGLs failed" << endl;
526 return NDBT_FAILED;
527 continue;
530 result = performValidatePurged();
531 if (result != NDBT_OK){
532 if (result == VERIFICATION_FAILED){
533 g_err << "performValidatePurged verification failed" << endl;
534 return NDBT_FAILED;
536 g_info << "performValidatePurged failed" << endl;
537 return NDBT_FAILED;
540 while (1){
542 yieldCounter++;
543 if (yield != 0 && yieldCounter >= yield)
544 return NDBT_OK;
547 * Find last GL time.
548 * ( GL record with highest time value)
550 Uint64 lastGLTime;
551 if (findLastGL(lastGLTime) != NDBT_OK){
552 g_info << "findLastGL failed" << endl;
553 // Break out of inner while loop
554 break;
557 lastGLTime++;
559 /**
560 * If last GL time + 1 is smaller than current time
561 * perform a GL for that time
563 Uint64 currTime;
564 if (getCurrTime(currTime) != NDBT_OK){
565 g_info << "getCurrTime failed" << endl;
566 // Break out of inner while loop
567 break;
569 if (lastGLTime < currTime){
570 counter++;
571 if (performMakeGL(lastGLTime) != NDBT_OK){
572 g_info << "performMakeGL failed" << endl;
573 // Break out of inner while loop
574 break;
577 if (counter > maxCounter){
578 // Break out of inner while loop and
579 // validatePreviousGLs
580 g_info << "counter("<<counter<<") > maxCounter("<<maxCounter<<")" << endl;
581 break;
584 } else {
585 ;//ndbout << "It's not time to make GL yet" << endl;
587 // ndbout << "Sleeping 1 second" << endl;
588 NdbSleep_SecSleep(1);
592 Uint32 age = 3;
593 if (purgeOldGLTransactions(currTime, age) != NDBT_OK){
594 g_info << "purgeOldGLTransactions failed" << endl;
595 // Break out of inner while loop
596 break;
602 return NDBT_FAILED;
606 int Bank::performValidateAllGLs(){
607 int result;
609 while (1){
611 /**
612 * Validate GLs and Transactions for previous days
613 * Set age so that ALL GL's are validated
615 int age = 100000;
616 result = performValidateGLs(age);
617 if (result != NDBT_OK){
618 if (result == VERIFICATION_FAILED){
619 g_err << "performValidateGLs verification failed" << endl;
620 return NDBT_FAILED;
622 g_err << "performValidateGLs failed" << endl;
623 return NDBT_FAILED;
630 result = performValidatePurged();
631 if (result != NDBT_OK){
632 if (result == VERIFICATION_FAILED){
633 g_err << "performValidatePurged verification failed" << endl;
634 return NDBT_FAILED;
636 g_err << "performValidatePurged failed" << endl;
637 return NDBT_FAILED;
639 return NDBT_OK;
642 return NDBT_FAILED;
646 int Bank::findLastGL(Uint64 &lastTime){
648 int check;
650 * SELECT MAX(time) FROM GL
652 NdbConnection* pScanTrans = m_ndb.startTransaction();
653 if (pScanTrans == NULL) {
654 ERR(m_ndb.getNdbError());
655 return NDBT_FAILED;
658 NdbScanOperation* pOp = pScanTrans->getNdbScanOperation("GL");
659 if (pOp == NULL) {
660 ERR(pScanTrans->getNdbError());
661 m_ndb.closeTransaction(pScanTrans);
662 return NDBT_FAILED;
665 if( pOp->readTuples() ) {
666 ERR(pScanTrans->getNdbError());
667 m_ndb.closeTransaction(pScanTrans);
668 return NDBT_FAILED;
671 check = pOp->interpret_exit_ok();
672 if( check == -1 ) {
673 ERR(pScanTrans->getNdbError());
674 m_ndb.closeTransaction(pScanTrans);
675 return NDBT_FAILED;
678 NdbRecAttr* timeRec = pOp->getValue("TIME");
679 if( timeRec ==NULL ) {
680 ERR(pScanTrans->getNdbError());
681 m_ndb.closeTransaction(pScanTrans);
682 return NDBT_FAILED;
685 check = pScanTrans->execute(NoCommit);
686 if( check == -1 ) {
687 ERR(pScanTrans->getNdbError());
688 m_ndb.closeTransaction(pScanTrans);
689 return NDBT_FAILED;
692 int eof;
693 int rows = 0;
694 eof = pOp->nextResult();
695 lastTime = 0;
697 while(eof == 0){
698 rows++;
699 Uint64 t = timeRec->u_32_value();
701 if (t > lastTime)
702 lastTime = t;
704 eof = pOp->nextResult();
706 if (eof == -1) {
707 ERR(pScanTrans->getNdbError());
708 m_ndb.closeTransaction(pScanTrans);
709 return NDBT_FAILED;
712 m_ndb.closeTransaction(pScanTrans);
714 return NDBT_OK;
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
724 // Start transaction
725 NdbConnection* pTrans = m_ndb.startTransaction();
726 if (pTrans == NULL){
727 ERR(m_ndb.getNdbError());
728 return NDBT_FAILED;
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);
735 return NDBT_FAILED;
738 // Execute transaction
739 if( pTrans->execute(Commit) == -1 ) {
740 ERR(pTrans->getNdbError());
741 m_ndb.closeTransaction(pTrans);
742 return NDBT_FAILED;
744 m_ndb.closeTransaction(pTrans);
746 return NDBT_OK;
749 int Bank::performMakeGLForAccountType(NdbConnection* pTrans,
750 Uint64 glTime,
751 Uint32 accountTypeId){
752 int check;
754 Uint32 balance = 0;
755 Uint32 withdrawalCount = 0;
756 Uint32 withdrawalSum = 0;
757 Uint32 depositSum = 0;
758 Uint32 depositCount = 0;
759 Uint32 countTransactions = 0;
760 Uint32 purged = 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");
767 if (pOp == NULL) {
768 ERR(pTrans->getNdbError());
769 return NDBT_FAILED;
772 check = pOp->insertTuple();
773 if( check == -1 ) {
774 ERR(pTrans->getNdbError());
775 return NDBT_FAILED;
778 check = pOp->equal("TIME", glTime);
779 if( check == -1 ) {
780 ERR(pTrans->getNdbError());
781 return NDBT_FAILED;
784 check = pOp->equal("ACCOUNT_TYPE", accountTypeId);
785 if( check == -1 ) {
786 ERR(pTrans->getNdbError());
787 return NDBT_FAILED;
790 check = pOp->setValue("BALANCE", balance);
791 if( check == -1 ) {
792 ERR(pTrans->getNdbError());
793 return NDBT_FAILED;
796 check = pOp->setValue("DEPOSIT_COUNT", depositCount);
797 if( check == -1 ) {
798 ERR(pTrans->getNdbError());
799 return NDBT_FAILED;
802 check = pOp->setValue("DEPOSIT_SUM", depositSum);
803 if( check == -1 ) {
804 ERR(pTrans->getNdbError());
805 return NDBT_FAILED;
808 check = pOp->setValue("WITHDRAWAL_COUNT", withdrawalCount);
809 if( check == -1 ) {
810 ERR(pTrans->getNdbError());
811 return NDBT_FAILED;
814 check = pOp->setValue("WITHDRAWAL_SUM", withdrawalSum);
815 if( check == -1 ) {
816 ERR(pTrans->getNdbError());
817 return NDBT_FAILED;
820 check = pOp->setValue("PURGED", purged);
821 if( check == -1 ) {
822 ERR(pTrans->getNdbError());
823 return NDBT_FAILED;
826 check = pTrans->execute(NoCommit);
827 if( check == -1 ) {
828 ERR(pOp->getNdbError());
829 return NDBT_FAILED;
832 // Read previous GL record to get old balance
833 NdbOperation* pOp2 = pTrans->getNdbOperation("GL");
834 if (pOp2 == NULL) {
835 ERR(pTrans->getNdbError());
836 return NDBT_FAILED;
839 check = pOp2->readTuple();
840 if( check == -1 ) {
841 ERR(pTrans->getNdbError());
842 return NDBT_FAILED;
845 check = pOp2->equal("TIME", glTime-1);
846 if( check == -1 ) {
847 ERR(pTrans->getNdbError());
848 return NDBT_FAILED;
851 check = pOp2->equal("ACCOUNT_TYPE", accountTypeId);
852 if( check == -1 ) {
853 ERR(pTrans->getNdbError());
854 return NDBT_FAILED;
857 NdbRecAttr* oldBalanceRec = pOp2->getValue("BALANCE");
858 if( oldBalanceRec == NULL ) {
859 ERR(pTrans->getNdbError());
860 return NDBT_FAILED;
863 check = pTrans->execute(NoCommit);
864 if( check == -1 ) {
865 ERR(pOp2->getNdbError());
866 return NDBT_FAILED;
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,
878 accountTypeId,
879 balance,
880 withdrawalCount,
881 withdrawalSum,
882 depositSum,
883 depositCount,
884 countTransactions,
885 pTrans) != NDBT_OK){
886 return NDBT_FAILED;
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");
898 if (pOp3 == NULL) {
899 ERR(pTrans->getNdbError());
900 return NDBT_FAILED;
903 check = pOp3->updateTuple();
904 if( check == -1 ) {
905 ERR(pTrans->getNdbError());
906 return NDBT_FAILED;
909 check = pOp3->equal("TIME", glTime);
910 if( check == -1 ) {
911 ERR(pTrans->getNdbError());
912 return NDBT_FAILED;
915 check = pOp3->equal("ACCOUNT_TYPE", accountTypeId);
916 if( check == -1 ) {
917 ERR(pTrans->getNdbError());
918 return NDBT_FAILED;
921 check = pOp3->setValue("BALANCE", balance);
922 if( check == -1 ) {
923 ERR(pTrans->getNdbError());
924 return NDBT_FAILED;
927 check = pOp3->setValue("DEPOSIT_COUNT", depositCount);
928 if( check == -1 ) {
929 ERR(pTrans->getNdbError());
930 return NDBT_FAILED;
933 check = pOp3->setValue("DEPOSIT_SUM", depositSum);
934 if( check == -1 ) {
935 ERR(pTrans->getNdbError());
936 return NDBT_FAILED;
939 check = pOp3->setValue("WITHDRAWAL_COUNT", withdrawalCount);
940 if( check == -1 ) {
941 ERR(pTrans->getNdbError());
942 return NDBT_FAILED;
945 check = pOp3->setValue("WITHDRAWAL_SUM", withdrawalSum);
946 if( check == -1 ) {
947 ERR(pTrans->getNdbError());
948 return NDBT_FAILED;
951 check = pOp3->setValue("PURGED", purged);
952 if( check == -1 ) {
953 ERR(pTrans->getNdbError());
954 return NDBT_FAILED;
957 // Execute transaction
958 check = pTrans->execute(NoCommit);
959 if( check == -1 ) {
960 ERR(pTrans->getNdbError());
961 return NDBT_FAILED;
964 return NDBT_OK;
970 int Bank::sumTransactionsForGL(const Uint64 glTime,
971 const Uint32 accountType,
972 Uint32& balance,
973 Uint32& withdrawalCount,
974 Uint32& withdrawalSum,
975 Uint32& depositSum,
976 Uint32& depositCount,
977 Uint32& transactionsCount,
978 NdbConnection* pTrans){
979 int check;
981 // g_info << "sumTransactionsForGL: " << glTime << ", " << accountType << endl;
983 NdbConnection* pScanTrans = m_ndb.startTransaction();
984 if (pScanTrans == NULL) {
985 ERR(m_ndb.getNdbError());
986 return NDBT_FAILED;
989 NdbScanOperation* pOp = pScanTrans->getNdbScanOperation("TRANSACTION");
990 if (pOp == NULL) {
991 ERR(pScanTrans->getNdbError());
992 m_ndb.closeTransaction(pScanTrans);
993 return NDBT_FAILED;
996 if( pOp->readTuplesExclusive()) {
997 ERR(pScanTrans->getNdbError());
998 m_ndb.closeTransaction(pScanTrans);
999 return NDBT_FAILED;
1002 check = pOp->interpret_exit_ok();
1003 if( check == -1 ) {
1004 ERR(pScanTrans->getNdbError());
1005 m_ndb.closeTransaction(pScanTrans);
1006 return NDBT_FAILED;
1009 NdbRecAttr* accountTypeRec = pOp->getValue("ACCOUNT_TYPE");
1010 if( accountTypeRec ==NULL ) {
1011 ERR(pScanTrans->getNdbError());
1012 m_ndb.closeTransaction(pScanTrans);
1013 return NDBT_FAILED;
1016 NdbRecAttr* timeRec = pOp->getValue("TIME");
1017 if( timeRec ==NULL ) {
1018 ERR(pScanTrans->getNdbError());
1019 m_ndb.closeTransaction(pScanTrans);
1020 return NDBT_FAILED;
1023 NdbRecAttr* transTypeRec = pOp->getValue("TRANSACTION_TYPE");
1024 if( transTypeRec ==NULL ) {
1025 ERR(pScanTrans->getNdbError());
1026 m_ndb.closeTransaction(pScanTrans);
1027 return NDBT_FAILED;
1030 NdbRecAttr* amountRec = pOp->getValue("AMOUNT");
1031 if( amountRec ==NULL ) {
1032 ERR(pScanTrans->getNdbError());
1033 m_ndb.closeTransaction(pScanTrans);
1034 return NDBT_FAILED;
1037 check = pScanTrans->execute(NoCommit);
1038 if( check == -1 ) {
1039 ERR(pScanTrans->getNdbError());
1040 m_ndb.closeTransaction(pScanTrans);
1041 return NDBT_FAILED;
1044 int eof;
1045 int rows = 0;
1046 int rowsFound = 0;
1047 eof = pOp->nextResult();
1049 while(eof == 0){
1050 rows++;
1051 Uint32 a = accountTypeRec->u_32_value();
1052 Uint64 t = timeRec->u_64_value();
1054 if (a == accountType && t == glTime){
1055 rowsFound++;
1056 // One record found
1057 int transType = transTypeRec->u_32_value();
1058 int amount = amountRec->u_32_value();
1059 if (transType == WithDrawal){
1060 withdrawalCount++;
1061 withdrawalSum += amount;
1062 balance -= amount;
1063 } else {
1064 assert(transType == Deposit);
1065 depositCount++;
1066 depositSum += amount;
1067 balance += 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());
1077 return NDBT_FAILED;
1082 if (eof == -1) {
1083 ERR(pScanTrans->getNdbError());
1084 m_ndb.closeTransaction(pScanTrans);
1085 return NDBT_FAILED;
1088 m_ndb.closeTransaction(pScanTrans);
1089 // ndbout << rows << " TRANSACTIONS have been read" << endl;
1090 transactionsCount = rowsFound;
1092 return NDBT_OK;
1096 int Bank::performValidateGLs(Uint64 age){
1098 Uint64 currTime;
1099 if (getCurrTime(currTime) != NDBT_OK){
1100 return NDBT_FAILED;
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;
1108 return result;
1111 glTime--;
1114 return NDBT_OK;
1117 int Bank::performValidateGL(Uint64 glTime){
1119 ndbout << "performValidateGL: " << glTime << endl;
1121 * Rules:
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
1127 * DEPOSIT_SUM
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
1138 int check;
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());
1145 return NDBT_FAILED;
1148 NdbScanOperation* pOp = pScanTrans->getNdbScanOperation("GL");
1149 if (pOp == NULL) {
1150 ERR(pScanTrans->getNdbError());
1151 m_ndb.closeTransaction(pScanTrans);
1152 return NDBT_FAILED;
1155 if( pOp->readTuples() ) {
1156 ERR(pScanTrans->getNdbError());
1157 m_ndb.closeTransaction(pScanTrans);
1158 return NDBT_FAILED;
1161 check = pOp->interpret_exit_ok();
1162 if( check == -1 ) {
1163 ERR(pScanTrans->getNdbError());
1164 m_ndb.closeTransaction(pScanTrans);
1165 return NDBT_FAILED;
1168 NdbRecAttr* accountTypeRec = pOp->getValue("ACCOUNT_TYPE");
1169 if( accountTypeRec ==NULL ) {
1170 ERR(pScanTrans->getNdbError());
1171 m_ndb.closeTransaction(pScanTrans);
1172 return NDBT_FAILED;
1175 NdbRecAttr* timeRec = pOp->getValue("TIME");
1176 if( timeRec ==NULL ) {
1177 ERR(pScanTrans->getNdbError());
1178 m_ndb.closeTransaction(pScanTrans);
1179 return NDBT_FAILED;
1182 NdbRecAttr* purgedRec = pOp->getValue("PURGED");
1183 if( purgedRec ==NULL ) {
1184 ERR(pScanTrans->getNdbError());
1185 m_ndb.closeTransaction(pScanTrans);
1186 return NDBT_FAILED;
1189 NdbRecAttr* balanceRec = pOp->getValue("BALANCE");
1190 if( balanceRec ==NULL ) {
1191 ERR(pScanTrans->getNdbError());
1192 m_ndb.closeTransaction(pScanTrans);
1193 return NDBT_FAILED;
1196 NdbRecAttr* depositSumRec = pOp->getValue("DEPOSIT_SUM");
1197 if( depositSumRec ==NULL ) {
1198 ERR(pScanTrans->getNdbError());
1199 m_ndb.closeTransaction(pScanTrans);
1200 return NDBT_FAILED;
1203 NdbRecAttr* depositCountRec = pOp->getValue("DEPOSIT_COUNT");
1204 if( depositCountRec ==NULL ) {
1205 ERR(pScanTrans->getNdbError());
1206 m_ndb.closeTransaction(pScanTrans);
1207 return NDBT_FAILED;
1210 NdbRecAttr* withdrawalSumRec = pOp->getValue("WITHDRAWAL_SUM");
1211 if( withdrawalSumRec ==NULL ) {
1212 ERR(pScanTrans->getNdbError());
1213 m_ndb.closeTransaction(pScanTrans);
1214 return NDBT_FAILED;
1216 NdbRecAttr* withdrawalCountRec = pOp->getValue("WITHDRAWAL_COUNT");
1217 if( withdrawalCountRec ==NULL ) {
1218 ERR(pScanTrans->getNdbError());
1219 m_ndb.closeTransaction(pScanTrans);
1220 return NDBT_FAILED;
1223 check = pScanTrans->execute(NoCommit);
1224 if( check == -1 ) {
1225 ERR(pScanTrans->getNdbError());
1226 m_ndb.closeTransaction(pScanTrans);
1227 return NDBT_FAILED;
1230 int eof;
1231 int rows = 0;
1232 int countGlRecords = 0;
1233 int result = NDBT_OK;
1234 eof = pOp->nextResult();
1236 while(eof == 0){
1237 rows++;
1238 Uint64 t = timeRec->u_64_value();
1240 if (t == glTime){
1241 countGlRecords++;
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();
1250 Uint32 balance = 0;
1251 Uint32 withdrawalSum = 0;
1252 Uint32 withdrawalCount = 0;
1253 Uint32 depositSum = 0;
1254 Uint32 depositCount = 0;
1255 Uint32 countTransactions = 0;
1256 if (purged == 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
1261 // DEPOSIT_SUM
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,
1269 balance,
1270 withdrawalCount,
1271 withdrawalSum,
1272 depositSum,
1273 depositCount,
1274 countTransactions,
1275 pScanTrans) != NDBT_OK){
1276 result = NDBT_FAILED;
1277 } else {
1278 Uint32 prevBalance = 0;
1279 if (getBalanceForGL(t-1, a, prevBalance) != NDBT_OK){
1280 result = NDBT_FAILED;
1281 } else
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;
1297 } else {
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,
1304 balance,
1305 withdrawalCount,
1306 withdrawalSum,
1307 depositSum,
1308 depositCount,
1309 countTransactions,
1310 pScanTrans) != NDBT_OK){
1311 result = NDBT_FAILED;
1312 } else {
1313 if (countTransactions != 0){
1314 g_err << "performValidateGL, countTransactions("<<countTransactions<<") != 0" << endl;
1315 result = VERIFICATION_FAILED;
1321 eof = pOp->nextResult();
1323 if (eof == -1) {
1324 ERR(pScanTrans->getNdbError());
1325 m_ndb.closeTransaction(pScanTrans);
1326 return NDBT_FAILED;
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;
1338 return result;
1343 int Bank::getBalanceForGL(const Uint64 glTime,
1344 const Uint32 accountTypeId,
1345 Uint32 &balance){
1346 int check;
1348 NdbConnection* pTrans = m_ndb.startTransaction();
1349 if (pTrans == NULL) {
1350 ERR(m_ndb.getNdbError());
1351 return NDBT_FAILED;
1354 NdbOperation* pOp = pTrans->getNdbOperation("GL");
1355 if (pOp == NULL) {
1356 ERR(pTrans->getNdbError());
1357 return NDBT_FAILED;
1360 check = pOp->readTuple();
1361 if( check == -1 ) {
1362 ERR(pTrans->getNdbError());
1363 return NDBT_FAILED;
1366 check = pOp->equal("TIME", glTime);
1367 if( check == -1 ) {
1368 ERR(pTrans->getNdbError());
1369 return NDBT_FAILED;
1372 check = pOp->equal("ACCOUNT_TYPE", accountTypeId);
1373 if( check == -1 ) {
1374 ERR(pTrans->getNdbError());
1375 return NDBT_FAILED;
1378 NdbRecAttr* balanceRec = pOp->getValue("BALANCE");
1379 if( balanceRec == NULL ) {
1380 ERR(pTrans->getNdbError());
1381 return NDBT_FAILED;
1384 check = pTrans->execute(Commit);
1385 if( check == -1 ) {
1386 ERR(pTrans->getNdbError());
1387 return NDBT_FAILED;
1390 m_ndb.closeTransaction(pTrans);
1392 balance = balanceRec->u_32_value();
1394 return NDBT_OK;
1399 int Bank::getOldestPurgedGL(const Uint32 accountType,
1400 Uint64 &oldest){
1401 int check;
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());
1411 return NDBT_FAILED;
1414 NdbScanOperation* pOp = pScanTrans->getNdbScanOperation("GL");
1415 if (pOp == NULL) {
1416 ERR(pScanTrans->getNdbError());
1417 m_ndb.closeTransaction(pScanTrans);
1418 return NDBT_FAILED;
1421 if( pOp->readTuples() ) {
1422 ERR(pScanTrans->getNdbError());
1423 m_ndb.closeTransaction(pScanTrans);
1424 return NDBT_FAILED;
1427 check = pOp->interpret_exit_ok();
1428 if( check == -1 ) {
1429 ERR(pScanTrans->getNdbError());
1430 m_ndb.closeTransaction(pScanTrans);
1431 return NDBT_FAILED;
1434 NdbRecAttr* accountTypeRec = pOp->getValue("ACCOUNT_TYPE");
1435 if( accountTypeRec ==NULL ) {
1436 ERR(pScanTrans->getNdbError());
1437 m_ndb.closeTransaction(pScanTrans);
1438 return NDBT_FAILED;
1441 NdbRecAttr* timeRec = pOp->getValue("TIME");
1442 if( timeRec ==NULL ) {
1443 ERR(pScanTrans->getNdbError());
1444 m_ndb.closeTransaction(pScanTrans);
1445 return NDBT_FAILED;
1448 NdbRecAttr* purgedRec = pOp->getValue("PURGED");
1449 if( purgedRec ==NULL ) {
1450 ERR(pScanTrans->getNdbError());
1451 m_ndb.closeTransaction(pScanTrans);
1452 return NDBT_FAILED;
1455 check = pScanTrans->execute(NoCommit);
1456 if( check == -1 ) {
1457 NdbError err = pScanTrans->getNdbError();
1458 ERR(err);
1459 m_ndb.closeTransaction(pScanTrans);
1460 if (err.status == NdbError::TemporaryError)
1462 NdbSleep_MilliSleep(50);
1463 continue;
1465 return NDBT_FAILED;
1468 int eof;
1469 int rows = 0;
1470 eof = pOp->nextResult();
1471 oldest = 0;
1473 while(eof == 0){
1474 rows++;
1475 Uint32 a = accountTypeRec->u_32_value();
1476 Uint32 p = purgedRec->u_32_value();
1478 if (a == accountType && p == 1){
1479 // One record found
1480 Uint64 t = timeRec->u_64_value();
1481 if (t > oldest)
1482 oldest = t;
1484 eof = pOp->nextResult();
1486 if (eof == -1)
1488 NdbError err = pScanTrans->getNdbError();
1489 ERR(err);
1490 m_ndb.closeTransaction(pScanTrans);
1492 if (err.status == NdbError::TemporaryError)
1494 NdbSleep_MilliSleep(50);
1495 continue;
1497 return NDBT_FAILED;
1499 break;
1500 } while(true);
1502 m_ndb.closeTransaction(pScanTrans);
1504 return NDBT_OK;
1507 int Bank::getOldestNotPurgedGL(Uint64 &oldest,
1508 Uint32 &accountTypeId,
1509 bool &found){
1510 int check;
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());
1518 return NDBT_FAILED;
1521 NdbScanOperation* pOp = pScanTrans->getNdbScanOperation("GL");
1522 if (pOp == NULL) {
1523 ERR(pScanTrans->getNdbError());
1524 m_ndb.closeTransaction(pScanTrans);
1525 return NDBT_FAILED;
1528 if( pOp->readTuples() ) {
1529 ERR(pScanTrans->getNdbError());
1530 m_ndb.closeTransaction(pScanTrans);
1531 return NDBT_FAILED;
1534 check = pOp->interpret_exit_ok();
1535 if( check == -1 ) {
1536 ERR(pScanTrans->getNdbError());
1537 m_ndb.closeTransaction(pScanTrans);
1538 return NDBT_FAILED;
1541 NdbRecAttr* accountTypeRec = pOp->getValue("ACCOUNT_TYPE");
1542 if( accountTypeRec ==NULL ) {
1543 ERR(pScanTrans->getNdbError());
1544 m_ndb.closeTransaction(pScanTrans);
1545 return NDBT_FAILED;
1548 NdbRecAttr* timeRec = pOp->getValue("TIME");
1549 if( timeRec ==NULL ) {
1550 ERR(pScanTrans->getNdbError());
1551 m_ndb.closeTransaction(pScanTrans);
1552 return NDBT_FAILED;
1555 NdbRecAttr* purgedRec = pOp->getValue("PURGED");
1556 if( purgedRec ==NULL ) {
1557 ERR(pScanTrans->getNdbError());
1558 m_ndb.closeTransaction(pScanTrans);
1559 return NDBT_FAILED;
1562 check = pScanTrans->execute(NoCommit);
1563 if( check == -1 ) {
1564 ERR(pScanTrans->getNdbError());
1565 m_ndb.closeTransaction(pScanTrans);
1566 return NDBT_FAILED;
1569 int eof;
1570 int rows = 0;
1571 eof = pOp->nextResult();
1572 oldest = (Uint64)-1;
1573 found = false;
1575 while(eof == 0){
1576 rows++;
1577 Uint32 p = purgedRec->u_32_value();
1578 if (p == 0){
1579 found = true;
1580 // One record found
1581 Uint32 a = accountTypeRec->u_32_value();
1582 Uint64 t = timeRec->u_64_value();
1583 if (t < oldest){
1584 oldest = t;
1585 accountTypeId = a;
1588 eof = pOp->nextResult();
1590 if (eof == -1) {
1591 ERR(pScanTrans->getNdbError());
1592 m_ndb.closeTransaction(pScanTrans);
1593 return NDBT_FAILED;
1596 m_ndb.closeTransaction(pScanTrans);
1598 return NDBT_OK;
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
1610 int loop = 0;
1611 int found = 0;
1612 NdbConnection* pScanTrans = 0;
1613 do {
1614 int check;
1615 loop++;
1616 pScanTrans = m_ndb.startTransaction();
1617 if (pScanTrans == NULL) {
1618 ERR(m_ndb.getNdbError());
1619 return NDBT_FAILED;
1622 NdbScanOperation* pOp = pScanTrans->getNdbScanOperation("TRANSACTION");
1623 if (pOp == NULL) {
1624 ERR(pScanTrans->getNdbError());
1625 m_ndb.closeTransaction(pScanTrans);
1626 return NDBT_FAILED;
1629 if( pOp->readTuples() ) {
1630 ERR(pScanTrans->getNdbError());
1631 m_ndb.closeTransaction(pScanTrans);
1632 return NDBT_FAILED;
1635 check = pOp->interpret_exit_ok();
1636 if( check == -1 ) {
1637 ERR(pScanTrans->getNdbError());
1638 m_ndb.closeTransaction(pScanTrans);
1639 return NDBT_FAILED;
1642 NdbRecAttr* accountTypeRec = pOp->getValue("ACCOUNT_TYPE");
1643 if( accountTypeRec ==NULL ) {
1644 ERR(pScanTrans->getNdbError());
1645 m_ndb.closeTransaction(pScanTrans);
1646 return NDBT_FAILED;
1649 NdbRecAttr* timeRec = pOp->getValue("TIME");
1650 if( timeRec ==NULL ) {
1651 ERR(pScanTrans->getNdbError());
1652 m_ndb.closeTransaction(pScanTrans);
1653 return NDBT_FAILED;
1656 NdbRecAttr* transactionIdRec = pOp->getValue("TRANSACTION_ID");
1657 if( transactionIdRec ==NULL ) {
1658 ERR(pScanTrans->getNdbError());
1659 m_ndb.closeTransaction(pScanTrans);
1660 return NDBT_FAILED;
1663 check = pScanTrans->execute(NoCommit);
1664 if( check == -1 ) {
1665 NdbError err = pScanTrans->getNdbError();
1666 ERR(err);
1667 m_ndb.closeTransaction(pScanTrans);
1669 if (err.status == NdbError::TemporaryError)
1671 NdbSleep_MilliSleep(50);
1672 continue;
1674 return NDBT_FAILED;
1677 int eof;
1678 int rows = 0;
1679 found = 0;
1680 eof = pOp->nextResult();
1682 while(eof == 0){
1683 rows++;
1684 Uint32 a = accountTypeRec->u_32_value();
1685 Uint32 t = timeRec->u_32_value();
1687 if (a == accountType && t <= oldest){
1688 // One record found
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;
1694 found++;
1696 eof = pOp->nextResult();
1698 if (eof == -1) {
1699 NdbError err = pScanTrans->getNdbError();
1700 ERR(err);
1701 m_ndb.closeTransaction(pScanTrans);
1703 if (err.status == NdbError::TemporaryError)
1705 NdbSleep_MilliSleep(50);
1706 continue;
1709 return NDBT_FAILED;
1712 break;
1713 } while(true);
1715 m_ndb.closeTransaction(pScanTrans);
1717 if (found == 0)
1718 return NDBT_OK;
1719 else
1720 return VERIFICATION_FAILED;
1724 int Bank::performValidatePurged(){
1726 * Make sure there are no TRANSACTIONS older than the oldest
1727 * purged GL record
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;
1736 return NDBT_FAILED;
1738 int result = checkNoTransactionsOlderThan(i, oldestGlTime);
1739 if (result != NDBT_OK){
1740 g_err << "checkNoTransactionsOlderThan failed" << endl;
1741 return result;
1746 return NDBT_OK;
1749 int Bank::purgeOldGLTransactions(Uint64 currTime, Uint32 age){
1750 /**
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
1756 bool found;
1757 int count = 0;
1759 while(1){
1760 count++;
1761 if (count > 100)
1762 return NDBT_OK;
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;
1769 return NDBT_FAILED;
1773 if (found == false){
1774 // ndbout << "not found" << endl;
1775 return NDBT_OK;
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;
1786 return NDBT_OK;
1789 if (purgeTransactions(oldestGlTime, accountTypeId) != NDBT_OK){
1790 g_err << "purgeTransactions failed" << endl;
1791 return NDBT_FAILED;
1794 g_err << "abnormal return" << endl;
1795 return NDBT_FAILED;
1799 int Bank::purgeTransactions(const Uint64 glTime,
1800 const Uint32 accountTypeId)
1802 int check;
1803 g_info << "purgeTransactions: " << glTime << ", "<<accountTypeId<<endl;
1804 NdbConnection* pTrans = m_ndb.startTransaction();
1805 if (pTrans == NULL){
1806 ERR(m_ndb.getNdbError());
1807 return NDBT_FAILED;
1810 // Start by updating the GL record with purged = 1, use NoCommit
1811 NdbOperation* pOp = pTrans->getNdbOperation("GL");
1812 if (pOp == NULL) {
1813 ERR(pTrans->getNdbError());
1814 return NDBT_FAILED;
1817 check = pOp->updateTuple();
1818 if( check == -1 ) {
1819 ERR(pTrans->getNdbError());
1820 return NDBT_FAILED;
1823 check = pOp->equal("TIME", glTime);
1824 if( check == -1 ) {
1825 ERR(pTrans->getNdbError());
1826 return NDBT_FAILED;
1829 check = pOp->equal("ACCOUNT_TYPE", accountTypeId);
1830 if( check == -1 ) {
1831 ERR(pTrans->getNdbError());
1832 return NDBT_FAILED;
1835 Uint32 purged = 1;
1836 check = pOp->setValue("PURGED", purged);
1837 if( check == -1 ) {
1838 ERR(pTrans->getNdbError());
1839 return NDBT_FAILED;
1842 // Execute transaction
1843 check = pTrans->execute(NoCommit);
1844 if( check == -1 ) {
1845 ERR(pTrans->getNdbError());
1846 return NDBT_FAILED;
1849 // Find all transactions and take over them for delete
1851 if(findTransactionsToPurge(glTime,
1852 accountTypeId,
1853 pTrans) != NDBT_OK){
1854 g_err << "findTransactionToPurge failed" << endl;
1855 m_ndb.closeTransaction(pTrans);
1856 return NDBT_FAILED;
1861 check = pTrans->execute(Commit);
1862 if( check == -1 ) {
1863 ERR(pTrans->getNdbError());
1864 return NDBT_FAILED;
1867 m_ndb.closeTransaction(pTrans);
1868 return NDBT_OK;
1872 int Bank::findTransactionsToPurge(const Uint64 glTime,
1873 const Uint32 accountType,
1874 NdbConnection* pTrans){
1875 int check;
1877 NdbConnection* pScanTrans = m_ndb.startTransaction();
1878 if (pScanTrans == NULL) {
1879 ERR(m_ndb.getNdbError());
1880 return NDBT_FAILED;
1883 NdbScanOperation* pOp = pScanTrans->getNdbScanOperation("TRANSACTION");
1884 if (pOp == NULL) {
1885 ERR(pScanTrans->getNdbError());
1886 m_ndb.closeTransaction(pScanTrans);
1887 return NDBT_FAILED;
1890 if( pOp->readTuplesExclusive() ) {
1891 ERR(pScanTrans->getNdbError());
1892 m_ndb.closeTransaction(pScanTrans);
1893 return NDBT_FAILED;
1896 check = pOp->interpret_exit_ok();
1897 if( check == -1 ) {
1898 ERR(pScanTrans->getNdbError());
1899 m_ndb.closeTransaction(pScanTrans);
1900 return NDBT_FAILED;
1903 NdbRecAttr* timeRec = pOp->getValue("TIME");
1904 if( timeRec ==NULL ) {
1905 ERR(pScanTrans->getNdbError());
1906 m_ndb.closeTransaction(pScanTrans);
1907 return NDBT_FAILED;
1910 NdbRecAttr* accountTypeRec = pOp->getValue("ACCOUNT_TYPE");
1911 if( accountTypeRec ==NULL ) {
1912 ERR(pScanTrans->getNdbError());
1913 m_ndb.closeTransaction(pScanTrans);
1914 return NDBT_FAILED;
1917 check = pScanTrans->execute(NoCommit);
1918 if( check == -1 ) {
1919 ERR(pScanTrans->getNdbError());
1920 m_ndb.closeTransaction(pScanTrans);
1921 return NDBT_FAILED;
1924 int eof;
1925 int rows = 0;
1926 int rowsFound = 0;
1927 eof = pOp->nextResult();
1929 while(eof == 0){
1930 rows++;
1931 Uint64 t = timeRec->u_64_value();
1932 Uint32 a = accountTypeRec->u_32_value();
1934 if (a == accountType && t == glTime){
1935 rowsFound++;
1936 // One record found
1937 check = pOp->deleteCurrentTuple(pTrans);
1938 if (check == -1){
1939 ERR(m_ndb.getNdbError());
1940 m_ndb.closeTransaction(pScanTrans);
1941 return NDBT_FAILED;
1944 // Execute transaction
1945 check = pTrans->execute(NoCommit);
1946 if( check == -1 ) {
1947 ERR(pTrans->getNdbError());
1948 m_ndb.closeTransaction(pScanTrans);
1949 return NDBT_FAILED;
1952 eof = pOp->nextResult();
1954 if (eof == -1) {
1955 ERR(pScanTrans->getNdbError());
1956 m_ndb.closeTransaction(pScanTrans);
1957 return NDBT_FAILED;
1960 m_ndb.closeTransaction(pScanTrans);
1961 // ndbout << rowsFound << " TRANSACTIONS have been deleted" << endl;
1963 return NDBT_OK;
1968 int Bank::performIncreaseTime(int maxSleepBetweenDays, int yield)
1970 int yieldCounter = 0;
1972 while(1){
1974 Uint64 currTime;
1975 if (incCurrTime(currTime) != NDBT_OK)
1976 break;
1978 g_info << "Current time is " << currTime << endl;
1979 if (maxSleepBetweenDays > 0){
1980 int val = myRandom48(maxSleepBetweenDays);
1981 NdbSleep_SecSleep(val);
1984 yieldCounter++;
1985 if (yield != 0 && yieldCounter >= yield)
1986 return NDBT_OK;
1989 return NDBT_FAILED;
1992 int Bank::readSystemValue(SystemValueId sysValId, Uint64 & value){
1994 int check;
1995 NdbConnection* pTrans = 0;
1996 while (true)
1998 pTrans = m_ndb.startTransaction();
1999 if (pTrans == NULL)
2001 ERR(m_ndb.getNdbError());
2002 if(m_ndb.getNdbError().status == NdbError::TemporaryError)
2004 NdbSleep_MilliSleep(50);
2005 continue;
2007 return NDBT_FAILED;
2010 int result;
2011 if ((result= prepareReadSystemValueOp(pTrans, sysValId, value)) != NDBT_OK)
2013 ERR(pTrans->getNdbError());
2014 m_ndb.closeTransaction(pTrans);
2015 return result;
2018 check = pTrans->execute(Commit);
2019 if( check == -1 ) {
2020 NdbError err = pTrans->getNdbError();
2021 m_ndb.closeTransaction(pTrans);
2022 ERR(err);
2023 if(err.status == NdbError::TemporaryError)
2025 NdbSleep_MilliSleep(50);
2026 continue;
2028 return NDBT_FAILED;
2031 break;
2034 m_ndb.closeTransaction(pTrans);
2035 return NDBT_OK;
2039 int Bank::prepareReadSystemValueOp(NdbConnection* pTrans, SystemValueId sysValId, Uint64 & value){
2041 int check;
2043 NdbOperation* pOp = pTrans->getNdbOperation("SYSTEM_VALUES");
2044 if (pOp == NULL) {
2045 return NDBT_FAILED;
2048 check = pOp->readTuple();
2049 if( check == -1 ) {
2050 return NDBT_FAILED;
2053 check = pOp->equal("SYSTEM_VALUES_ID", sysValId);
2054 if( check == -1 ) {
2055 return NDBT_FAILED;
2058 NdbRecAttr* valueRec = pOp->getValue("VALUE", (char *)&value);
2059 if( valueRec == NULL ) {
2060 return NDBT_FAILED;
2063 return NDBT_OK;
2066 int Bank::writeSystemValue(SystemValueId sysValId, Uint64 value){
2068 int check;
2070 NdbConnection* pTrans = m_ndb.startTransaction();
2071 if (pTrans == NULL){
2072 ERR(m_ndb.getNdbError());
2073 return NDBT_FAILED;
2076 NdbOperation* pOp = pTrans->getNdbOperation("SYSTEM_VALUES");
2077 if (pOp == NULL) {
2078 ERR(pTrans->getNdbError());
2079 m_ndb.closeTransaction(pTrans);
2080 return NDBT_FAILED;
2083 check = pOp->insertTuple();
2084 if( check == -1 ) {
2085 ERR(pTrans->getNdbError());
2086 m_ndb.closeTransaction(pTrans);
2087 return NDBT_FAILED;
2090 check = pOp->equal("SYSTEM_VALUES_ID", sysValId);
2091 if( check == -1 ) {
2092 ERR(pTrans->getNdbError());
2093 m_ndb.closeTransaction(pTrans);
2094 return NDBT_FAILED;
2097 check = pOp->setValue("VALUE", value);
2098 if( check == -1 ) {
2099 ERR(pTrans->getNdbError());
2100 m_ndb.closeTransaction(pTrans);
2101 return NDBT_FAILED;
2104 check = pTrans->execute(Commit);
2105 if( check == -1 ) {
2106 ERR(pTrans->getNdbError());
2107 m_ndb.closeTransaction(pTrans);
2108 return NDBT_FAILED;
2111 m_ndb.closeTransaction(pTrans);
2112 return NDBT_OK;
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
2128 * updated value
2132 DBUG_ENTER("Bank::increaseSystemValue");
2134 int check;
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");
2145 if (pOp == NULL) {
2146 ERR(pTrans->getNdbError());
2147 m_ndb.closeTransaction(pTrans);
2148 DBUG_RETURN(NDBT_FAILED);
2151 check = pOp->readTupleExclusive();
2152 // check = pOp->readTuple();
2153 if( check == -1 ) {
2154 ERR(pTrans->getNdbError());
2155 m_ndb.closeTransaction(pTrans);
2156 DBUG_RETURN(NDBT_FAILED);
2159 check = pOp->equal("SYSTEM_VALUES_ID", sysValId);
2160 if( check == -1 ) {
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);
2174 if( check == -1 ) {
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();
2186 value++;
2188 NdbOperation* pOp2 = pTrans->getNdbOperation("SYSTEM_VALUES");
2189 if (pOp2 == NULL) {
2190 ERR(pTrans->getNdbError());
2191 m_ndb.closeTransaction(pTrans);
2192 DBUG_RETURN(NDBT_FAILED);
2195 check = pOp2->updateTuple();
2196 if( check == -1 ) {
2197 ERR(pTrans->getNdbError());
2198 m_ndb.closeTransaction(pTrans);
2199 DBUG_RETURN(NDBT_FAILED);
2202 check = pOp2->equal("SYSTEM_VALUES_ID", sysValId);
2203 if( check == -1 ) {
2204 ERR(pTrans->getNdbError());
2205 m_ndb.closeTransaction(pTrans);
2206 DBUG_RETURN(NDBT_FAILED);
2209 check = pOp2->setValue("VALUE", value);
2210 if( check == -1 ) {
2211 ERR(pTrans->getNdbError());
2212 m_ndb.closeTransaction(pTrans);
2213 DBUG_RETURN(NDBT_FAILED);
2216 check = pTrans->execute(NoCommit);
2217 if( check == -1 ) {
2218 ERR(pTrans->getNdbError());
2219 m_ndb.closeTransaction(pTrans);
2220 DBUG_RETURN(NDBT_FAILED);
2223 NdbOperation* pOp3 = pTrans->getNdbOperation("SYSTEM_VALUES");
2224 if (pOp3 == NULL) {
2225 ERR(pTrans->getNdbError());
2226 m_ndb.closeTransaction(pTrans);
2227 DBUG_RETURN(NDBT_FAILED);
2230 check = pOp3->readTuple();
2231 if( check == -1 ) {
2232 ERR(pTrans->getNdbError());
2233 m_ndb.closeTransaction(pTrans);
2234 DBUG_RETURN(NDBT_FAILED);
2237 check = pOp3->equal("SYSTEM_VALUES_ID", sysValId);
2238 if( check == -1 ) {
2239 ERR(pTrans->getNdbError());
2240 m_ndb.closeTransaction(pTrans);
2241 DBUG_RETURN(NDBT_FAILED);
2244 // Read new value
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);
2253 if( check == -1 ) {
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);
2278 DBUG_RETURN(0);
2281 int Bank::increaseSystemValue2(SystemValueId sysValId, Uint64 &value){
2283 * Increase value with one and return
2284 * updated value
2285 * A more optimized version using interpreted update!
2289 int check;
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;
2296 return NDBT_FAILED;
2299 NdbOperation* pOp = pTrans->getNdbOperation("SYSTEM_VALUES");
2300 if (pOp == NULL) {
2301 ERR(pTrans->getNdbError());
2302 m_ndb.closeTransaction(pTrans);
2303 return NDBT_FAILED;
2306 check = pOp->interpretedUpdateTuple();
2307 if( check == -1 ) {
2308 ERR(pTrans->getNdbError());
2309 m_ndb.closeTransaction(pTrans);
2310 return NDBT_FAILED;
2313 check = pOp->equal("SYSTEM_VALUES_ID", sysValId );
2314 if( check == -1 ) {
2315 ERR(pTrans->getNdbError());
2316 m_ndb.closeTransaction(pTrans);
2317 return NDBT_FAILED;
2320 Uint32 valToIncWith = 1;
2321 check = pOp->incValue("VALUE", valToIncWith);
2322 if( check == -1 ) {
2323 ERR(pTrans->getNdbError());
2324 m_ndb.closeTransaction(pTrans);
2325 return NDBT_FAILED;
2328 NdbRecAttr* valueRec = pOp->getValue("VALUE");
2329 if( valueRec == NULL ) {
2330 ERR(pTrans->getNdbError());
2331 m_ndb.closeTransaction(pTrans);
2332 return NDBT_FAILED;
2335 check = pTrans->execute(Commit);
2336 if( check == -1 ) {
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);
2344 return NDBT_FAILED;
2347 value = valueRec->u_64_value();
2349 m_ndb.closeTransaction(pTrans);
2351 return 0;
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;
2370 while (1){
2372 Uint32 sumAccounts = 0;
2373 Uint32 numAccounts = 0;
2374 if (getSumAccounts(sumAccounts, numAccounts) != NDBT_OK){
2375 g_err << "getSumAccounts FAILED" << endl;
2376 } else {
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;
2385 return NDBT_FAILED;
2388 if (maxSleepBetweenSums > 0){
2389 int val = myRandom48(maxSleepBetweenSums);
2390 NdbSleep_MilliSleep(val);
2394 yieldCounter++;
2395 if (yield != 0 && yieldCounter >= yield)
2396 return NDBT_OK;
2398 return NDBT_FAILED;
2402 int Bank::getSumAccounts(Uint32 &sumAccounts,
2403 Uint32 &numAccounts){
2405 // SELECT SUM(balance) FROM ACCOUNT
2407 int check;
2408 NdbConnection* pScanTrans = m_ndb.startTransaction();
2409 if (pScanTrans == NULL) {
2410 ERR(m_ndb.getNdbError());
2411 return NDBT_FAILED;
2414 NdbScanOperation* pOp = pScanTrans->getNdbScanOperation("ACCOUNT");
2415 if (pOp == NULL) {
2416 ERR(pScanTrans->getNdbError());
2417 m_ndb.closeTransaction(pScanTrans);
2418 return NDBT_FAILED;
2421 if( pOp->readTuplesExclusive() ) {
2422 ERR(pScanTrans->getNdbError());
2423 m_ndb.closeTransaction(pScanTrans);
2424 return NDBT_FAILED;
2427 check = pOp->interpret_exit_ok();
2428 if( check == -1 ) {
2429 ERR(pScanTrans->getNdbError());
2430 m_ndb.closeTransaction(pScanTrans);
2431 return NDBT_FAILED;
2434 NdbRecAttr* balanceRec = pOp->getValue("BALANCE");
2435 if( balanceRec ==NULL ) {
2436 ERR(pScanTrans->getNdbError());
2437 m_ndb.closeTransaction(pScanTrans);
2438 return NDBT_FAILED;
2441 check = pScanTrans->execute(NoCommit);
2442 if( check == -1 ) {
2443 ERR(pScanTrans->getNdbError());
2444 m_ndb.closeTransaction(pScanTrans);
2445 return NDBT_FAILED;
2448 NdbConnection* pTrans = m_ndb.startTransaction();
2449 if (pTrans == NULL) {
2450 ERR(m_ndb.getNdbError());
2451 m_ndb.closeTransaction(pScanTrans);
2452 return NDBT_FAILED;
2455 int eof;
2456 eof = pOp->nextResult();
2458 while(eof == 0){
2459 Uint32 b = balanceRec->u_32_value();
2461 sumAccounts += b;
2462 numAccounts++;
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);
2473 return NDBT_FAILED;
2476 Uint32 illegalBalance = 99;
2477 check = pLockOp->setValue("BALANCE", illegalBalance);
2478 if( check == -1 ) {
2479 ERR(pTrans->getNdbError());
2480 m_ndb.closeTransaction(pTrans);
2481 m_ndb.closeTransaction(pScanTrans);
2482 return NDBT_FAILED;
2485 // Execute transaction
2486 check = pTrans->execute(NoCommit);
2487 if( check == -1 ) {
2488 ERR(pTrans->getNdbError());
2489 m_ndb.closeTransaction(pScanTrans);
2490 m_ndb.closeTransaction(pTrans);
2491 return NDBT_FAILED;
2494 eof = pOp->nextResult();
2496 if (eof == -1) {
2497 ERR(pScanTrans->getNdbError());
2498 m_ndb.closeTransaction(pScanTrans);
2499 m_ndb.closeTransaction(pTrans);
2500 return NDBT_FAILED;
2503 // TODO Forget about rolling back, just close pTrans!!
2505 // Rollback transaction
2506 check = pTrans->execute(Rollback);
2507 if( check == -1 ) {
2508 ERR(pTrans->getNdbError());
2509 m_ndb.closeTransaction(pScanTrans);
2510 m_ndb.closeTransaction(pTrans);
2511 return NDBT_FAILED;
2514 m_ndb.closeTransaction(pScanTrans);
2515 m_ndb.closeTransaction(pTrans);
2518 return NDBT_OK;