diff options
Diffstat (limited to 'ndb/test/ndbapi/acid2.cpp')
-rw-r--r-- | ndb/test/ndbapi/acid2.cpp | 692 |
1 files changed, 692 insertions, 0 deletions
diff --git a/ndb/test/ndbapi/acid2.cpp b/ndb/test/ndbapi/acid2.cpp new file mode 100644 index 00000000000..434a0450daa --- /dev/null +++ b/ndb/test/ndbapi/acid2.cpp @@ -0,0 +1,692 @@ +/* Copyright (C) 2003 MySQL AB + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + + +#include <NdbApi.hpp> +#include <NdbOut.hpp> +#include <NdbThread.h> +#include <NdbSleep.h> +#include <NdbMutex.h> + +#include "TraceNdbApi.hpp" +#include "VerifyNdbApi.hpp" + + +#define Ndb CTraceNdb +#define NdbSchemaCon CTraceNdbSchemaCon +#define NdbSchemaOp CTraceNdbSchemaOp +#define NdbConnection CTraceNdbConnection +#define NdbOperation CTraceNdbOperation +#define NdbIndexOperation CTraceNdbIndexOperation +#define NdbRecAttr CTraceNdbRecAttr +#define Table CTraceTable +#define Index CTraceIndex +#define Column CTraceColumn +#define NdbDictionary CTraceNdbDictionary + +/* +#define Ndb CVerifyNdb +#define NdbSchemaCon CVerifyNdbSchemaCon +#define NdbSchemaOp CVerifyNdbSchemaOp +#define NdbConnection CVerifyNdbConnection +#define NdbOperation CVerifyNdbOperation +#define NdbIndexOperation CVerifyNdbIndexOperation +#define NdbRecAttr CVerifyNdbRecAttr +#define Table CVerifyTable +#define Index CVerifyIndex +#define Column CVerifyColumn +#define NdbDictionary CVerifyNdbDictionary +*/ + +NdbMutex* g_pNdbMutexStop = 0; +Uint32 g_nPart = 1; +Uint32 g_nTable = 1; +Uint32 g_nTuple = 1; +Uint32 g_nAttribute = 1; +char* g_szTable = 0; +char* g_szIndex = 0; +char* g_szAttribute = 0; +bool g_bVerify = false; +bool g_bUseIndex = false; + + + +#define N 624 +#define M 397 +#define MATRIX_A 0x9908b0df +#define UPPER_MASK 0x80000000 +#define LOWER_MASK 0x7fffffff + +#define TEMPERING_MASK_B 0x9d2c5680 +#define TEMPERING_MASK_C 0xefc60000 +#define TEMPERING_SHIFT_U(y) (y >> 11) +#define TEMPERING_SHIFT_S(y) (y << 7) +#define TEMPERING_SHIFT_T(y) (y << 15) +#define TEMPERING_SHIFT_L(y) (y >> 18) + + +class MT19937 +{ +public: + MT19937(void); + void sgenrand(unsigned long seed); + unsigned long genrand(void); + +private: + unsigned long mt[N]; + int mti; + unsigned long mag01[2]; +}; + + +MT19937::MT19937(void) +{ + mti = N+1; + mag01[0] = 0x0; + mag01[1] = MATRIX_A; + sgenrand(4357); +} + + +void MT19937::sgenrand(unsigned long seed) +{ + mt[0]= seed & 0xffffffff; + for (mti=1; mti<N; mti++) + mt[mti] = (69069 * mt[mti-1]) & 0xffffffff; +} + + +unsigned long MT19937::genrand(void) +{ + unsigned long y; + if (mti >= N) { + int kk; + if (mti == N+1) + { + sgenrand(4357); + } + for (kk=0;kk<N-M;kk++) { + y = (mt[kk]&UPPER_MASK)|(mt[kk+1]&LOWER_MASK); + mt[kk] = mt[kk+M] ^ (y >> 1) ^ mag01[y & 0x1]; + } + for (;kk<N-1;kk++) { + y = (mt[kk]&UPPER_MASK)|(mt[kk+1]&LOWER_MASK); + mt[kk] = mt[kk+(M-N)] ^ (y >> 1) ^ mag01[y & 0x1]; + } + y = (mt[N-1]&UPPER_MASK)|(mt[0]&LOWER_MASK); + mt[N-1] = mt[M-1] ^ (y >> 1) ^ mag01[y & 0x1]; + mti = 0; + } + y = mt[mti++]; + y ^= TEMPERING_SHIFT_U(y); + y ^= TEMPERING_SHIFT_S(y) & TEMPERING_MASK_B; + y ^= TEMPERING_SHIFT_T(y) & TEMPERING_MASK_C; + y ^= TEMPERING_SHIFT_L(y); + return y; +} + + + + + +void CreateTables(Ndb* pNdb) +{ + for(Uint32 iTable=0; iTable<g_nTable; ++iTable) + { + NdbDictionary::Dictionary* pDictionary = pNdb->getDictionary(); + + NdbDictionary::Table table; + table.setName(g_szTable+iTable*4); + + NdbDictionary::Index index; + index.setName(g_szIndex+iTable*4); + index.setTable(table.getName()); + index.setType(NdbDictionary::Index::UniqueHashIndex); + + NdbDictionary::Column columnPK; + columnPK.setName("PK"); + columnPK.setTupleKey(true); + table.addColumn(columnPK); + index.addIndexColumn(columnPK.getName()); + + for(Uint32 iAttr=0; iAttr<g_nAttribute; ++iAttr) + { + NdbDictionary::Column columnAttr; + columnAttr.setName(g_szAttribute+iAttr*4); + columnAttr.setTupleKey(false); + table.addColumn(columnAttr); + } + + pDictionary->createTable(table); + pDictionary->createIndex(index); + + /* + NdbSchemaCon* pNdbSchemaCon = pNdb->startSchemaTransaction(); + NdbSchemaOp* pNdbSchemaOp = pNdbSchemaCon->getNdbSchemaOp(); + pNdbSchemaOp->createTable(g_szTable+iTable*4); + pNdbSchemaOp->createAttribute("PK", TupleKey); + for(Uint32 iAttr=0; iAttr<g_nAttribute; ++iAttr) + { + pNdbSchemaOp->createAttribute(g_szAttribute+iAttr*4, NoKey); + } + + pNdbSchemaCon->execute(); + pNdb->closeSchemaTransaction(pNdbSchemaCon); + */ + } +} + + +int InsertTransaction(Ndb* pNdb, const Uint32 iPart, const bool bIndex) +{ + int iExec = -1; + int iCode = -1; + NdbConnection* pNdbConnection = pNdb->startTransaction(); + if(pNdbConnection) + { + for(Uint32 iTable=0; iTable<g_nTable; ++iTable) + { + for(Uint32 iTuple=0; iTuple<g_nTuple; ++iTuple) + { + if(bIndex) + { + NdbIndexOperation* pNdbIndexOperation = pNdbConnection->getNdbIndexOperation(g_szIndex+iTable*4, g_szTable+iTable*4); + pNdbIndexOperation->insertTuple(); + Uint32 nPK = iPart*g_nTuple + iTuple; + pNdbIndexOperation->equal("PK", nPK); + for(Uint32 iAttr=0; iAttr<g_nAttribute; ++iAttr) + { + Uint32 nValue = ((iPart*g_nTable+iTable)*g_nTuple+iTuple)*g_nAttribute+iAttr; + pNdbIndexOperation->setValue(g_szAttribute+iAttr*4, nValue); + } + } + else + { + NdbOperation* pNdbOperation = pNdbConnection->getNdbOperation(g_szTable+iTable*4); + pNdbOperation->insertTuple(); + Uint32 nPK = iPart*g_nTuple + iTuple; + pNdbOperation->equal("PK", nPK); + for(Uint32 iAttr=0; iAttr<g_nAttribute; ++iAttr) + { + Uint32 nValue = ((iPart*g_nTable+iTable)*g_nTuple+iTuple)*g_nAttribute+iAttr; + pNdbOperation->setValue(g_szAttribute+iAttr*4, nValue); + } + } + } + } + iExec = pNdbConnection->execute_ok(Commit); + if (iExec == -1) + { + ndbout << pNdbConnection->getNdbError() << endl; + } + pNdb->closeTransaction(pNdbConnection); + } + return 0; +} + + +int UpdateGetAndSetTransaction(Ndb* pNdb, const Uint32 iPart, const bool bIndex) +{ + int iExec = -1; + int iCode = -1; + NdbRecAttr** ppNdbRecAttr = new NdbRecAttr*[g_nTable*g_nTuple*g_nAttribute]; + NdbConnection* pNdbConnection = pNdb->startTransaction(); + if(pNdbConnection) + { + for(Uint32 iTable=0; iTable<g_nTable; ++iTable) + { + for(Uint32 iTuple=0; iTuple<g_nTuple; ++iTuple) + { + if(bIndex) + { + NdbIndexOperation* pNdbIndexOperation = pNdbConnection->getNdbIndexOperation(g_szIndex+iTable*4, g_szTable+iTable*4); + pNdbIndexOperation->readTupleExclusive(); + Uint32 nPK = iPart*g_nTuple + iTuple; + pNdbIndexOperation->equal("PK", nPK); + for(Uint32 iAttr=0; iAttr<g_nAttribute; ++iAttr) + { + ppNdbRecAttr[(iTable*g_nTuple+iTuple)*g_nAttribute+iAttr] + = pNdbIndexOperation->getValue(g_szAttribute+iAttr*4); + } + } + else + { + NdbOperation* pNdbOperation = pNdbConnection->getNdbOperation(g_szTable+iTable*4); + pNdbOperation->readTupleExclusive(); + Uint32 nPK = iPart*g_nTuple + iTuple; + pNdbOperation->equal("PK", nPK); + for(Uint32 iAttr=0; iAttr<g_nAttribute; ++iAttr) + { + ppNdbRecAttr[(iTable*g_nTuple+iTuple)*g_nAttribute+iAttr] + = pNdbOperation->getValue(g_szAttribute+iAttr*4); + } + } + } + } + iExec = pNdbConnection->execute_ok(NoCommit); + if( iExec == -1) + { + ndbout << pNdbConnection->getNdbError() << endl; + } + } + iCode = pNdbConnection->getNdbError().code; + if(iExec==0) + { + for(Uint32 iTable=0; iTable<g_nTable; ++iTable) + { + for(Uint32 iTuple=0; iTuple<g_nTuple; ++iTuple) + { + if(bIndex) + { + NdbIndexOperation* pNdbIndexOperation = pNdbConnection->getNdbIndexOperation(g_szIndex+iTable*4, g_szTable+iTable*4); + pNdbIndexOperation->updateTuple(); + Uint32 nPK = iPart*g_nTuple + iTuple; + pNdbIndexOperation->equal("PK", nPK); + for(Uint32 iAttr=0; iAttr<g_nAttribute; ++iAttr) + { + NdbRecAttr* pNdbRecAttr + = ppNdbRecAttr[(iTable*g_nTuple+iTuple)*g_nAttribute+iAttr]; + Uint32 nValue = pNdbRecAttr->u_32_value() + 1; + pNdbIndexOperation->setValue(g_szAttribute+iAttr*4, nValue); + } + } + else + { + NdbOperation* pNdbOperation = pNdbConnection->getNdbOperation(g_szTable+iTable*4); + pNdbOperation->updateTuple(); + Uint32 nPK = iPart*g_nTuple + iTuple; + pNdbOperation->equal("PK", nPK); + for(Uint32 iAttr=0; iAttr<g_nAttribute; ++iAttr) + { + NdbRecAttr* pNdbRecAttr + = ppNdbRecAttr[(iTable*g_nTuple+iTuple)*g_nAttribute+iAttr]; + Uint32 nValue = pNdbRecAttr->u_32_value() + 1; + pNdbOperation->setValue(g_szAttribute+iAttr*4, nValue); + } + } + } + } + iExec = pNdbConnection->execute(Commit); + if (iExec == -1) + { + ndbout << pNdbConnection->getNdbError() << endl; + } + pNdb->closeTransaction(pNdbConnection); + } + delete[] ppNdbRecAttr; + return 0; +} + + +int UpdateInterpretedTransaction(Ndb* pNdb, const Uint32 iPart, const bool bIndex) +{ + int iExec = -1; + int iCode = -1; + NdbConnection* pNdbConnection = pNdb->startTransaction(); + if(pNdbConnection) + { + for(Uint32 iTable=0; iTable<g_nTable; ++iTable) + { + for(Uint32 iTuple=0; iTuple<g_nTuple; ++iTuple) + { + if(bIndex) + { + NdbIndexOperation* pNdbIndexOperation = pNdbConnection->getNdbIndexOperation(g_szIndex+iTable*4, g_szTable+iTable*4); + pNdbIndexOperation->interpretedUpdateTuple(); + Uint32 nPK = iPart*g_nTuple + iTuple; + pNdbIndexOperation->equal("PK", nPK); + for(Uint32 iAttr=0; iAttr<g_nAttribute; ++iAttr) + { + pNdbIndexOperation->incValue(g_szAttribute+iAttr*4, (Uint32)1); + } + } + else + { + NdbOperation* pNdbOperation = pNdbConnection->getNdbOperation(g_szTable+iTable*4); + pNdbOperation->interpretedUpdateTuple(); + Uint32 nPK = iPart*g_nTuple + iTuple; + pNdbOperation->equal("PK", nPK); + for(Uint32 iAttr=0; iAttr<g_nAttribute; ++iAttr) + { + pNdbOperation->incValue(g_szAttribute+iAttr*4, (Uint32)1); + } + } + } + } + iExec = pNdbConnection->execute_ok(Commit); + + if (iExec == -1) + { + ndbout << pNdbConnection->getNdbError() << endl; + } + pNdb->closeTransaction(pNdbConnection); + } + return 0; +} + + +void ReportInconsistency (const Uint32 iPart, + const Uint32 iTable, + const Uint32 iTuple, + const Uint32 iAttr, + const Uint32 nValue, + const Uint32 nExpected ) +{ + ndbout << "INCONSISTENCY: "; + ndbout << "Part " << iPart; + ndbout << ", Table " << iTable; + ndbout << ", Tuple " << iTuple; + ndbout << ", Attr " << iAttr; + ndbout << ", Value " << nValue; + ndbout << ", Expected " << nExpected; + ndbout << endl; +} + + +int ReadTransaction(Ndb* pNdb, const Uint32 iPart, const bool bIndex) +{ + int iExec = -1; + int iCode = -1; + NdbRecAttr** ppNdbRecAttr = new NdbRecAttr*[g_nTable*g_nTuple*g_nAttribute]; + NdbConnection* pNdbConnection = pNdb->startTransaction(); + if(pNdbConnection) + { + for(Uint32 iTable=0; iTable<g_nTable; ++iTable) + { + for(Uint32 iTuple=0; iTuple<g_nTuple; ++iTuple) + { + if(bIndex) + { + NdbIndexOperation* pNdbIndexOperation = pNdbConnection->getNdbIndexOperation(g_szIndex+iTable*4, g_szTable+iTable*4); + pNdbIndexOperation->readTuple(); + Uint32 nPK = iPart*g_nTuple + iTuple; + pNdbIndexOperation->equal("PK", nPK); + for(Uint32 iAttr=0; iAttr<g_nAttribute; ++iAttr) + { + ppNdbRecAttr[(iTable*g_nTuple+iTuple)*g_nAttribute+iAttr] + = pNdbIndexOperation->getValue(g_szAttribute+iAttr*4); + } + } + else + { + NdbOperation* pNdbOperation = pNdbConnection->getNdbOperation(g_szTable+iTable*4); + pNdbOperation->readTuple(); + Uint32 nPK = iPart*g_nTuple + iTuple; + pNdbOperation->equal("PK", nPK); + for(Uint32 iAttr=0; iAttr<g_nAttribute; ++iAttr) + { + ppNdbRecAttr[(iTable*g_nTuple+iTuple)*g_nAttribute+iAttr] + = pNdbOperation->getValue(g_szAttribute+iAttr*4); + } + } + } + } + iExec = pNdbConnection->execute_ok(Commit); + if (iExec == -1) + { + ndbout << pNdbConnection->getNdbError() << endl; + } + if(iExec==0) + { + Uint32 nValue0 = ppNdbRecAttr[0]->u_32_value(); + for(Uint32 iTable=0; iTable<g_nTable; ++iTable) + { + for(Uint32 iTuple=0; iTuple<g_nTuple; ++iTuple) + { + for(Uint32 iAttr=0; iAttr<g_nAttribute; ++iAttr) + { + Uint32 nValue = ppNdbRecAttr[(iTable*g_nTuple+iTuple)*g_nAttribute+iAttr]->u_32_value(); + Uint32 nExpected = nValue0 + (iTable*g_nTuple+iTuple)*g_nAttribute+iAttr; + if(nValue!=nExpected) + { + ReportInconsistency(iPart, iTable, iTuple, iAttr, nValue, nExpected); + } + } + } + } + } + pNdb->closeTransaction(pNdbConnection); + } + return 0; +} + + +int DeleteTransaction(Ndb* pNdb, const Uint32 iPart, const bool bIndex) +{ + int iExec = -1; + int iCode = -1; + NdbConnection* pNdbConnection = pNdb->startTransaction(); + if(pNdbConnection) + { + for(Uint32 iTable=0; iTable<g_nTable; ++iTable) + { + for(Uint32 iTuple=0; iTuple<g_nTuple; ++iTuple) + { + if(bIndex) + { + NdbIndexOperation* pNdbIndexOperation = pNdbConnection->getNdbIndexOperation(g_szIndex+iTable*4, g_szTable+iTable*4); + pNdbIndexOperation->deleteTuple(); + Uint32 nPK = iPart*g_nTuple + iTuple; + pNdbIndexOperation->equal("PK", nPK); + } + else + { + NdbOperation* pNdbOperation = pNdbConnection->getNdbOperation(g_szTable+iTable*4); + pNdbOperation->deleteTuple(); + Uint32 nPK = iPart*g_nTuple + iTuple; + pNdbOperation->equal("PK", nPK); + } + } + } + iExec = pNdbConnection->execute_ok(Commit); + + if (iExec == -1) + { + ndbout << pNdbConnection->getNdbError() << endl; + } + pNdb->closeTransaction(pNdbConnection); + } + return 0; +} + + +extern "C" void* ThreadFunc(void*) +{ + Ndb* pNdb = new Ndb("TEST_DB"); + pNdb->init(); + pNdb->waitUntilReady(); + + MT19937 rndgen; + rndgen.sgenrand((unsigned long)pNdb); + + Uint32 nInsertError = 0; + Uint32 nInsertCommit = 0; + Uint32 nInsertRollback = 0; + Uint32 nUpdateGetAndSetError = 0; + Uint32 nUpdateGetAndSetCommit = 0; + Uint32 nUpdateGetAndSetRollback = 0; + Uint32 nReadError = 0; + Uint32 nReadCommit = 0; + Uint32 nReadRollback = 0; + Uint32 nUpdateInterpretedError = 0; + Uint32 nUpdateInterpretedCommit = 0; + Uint32 nUpdateInterpretedRollback = 0; + Uint32 nDeleteError = 0; + Uint32 nDeleteCommit = 0; + Uint32 nDeleteRollback = 0; + + if (g_bVerify) + { + for (Uint32 iPart = 0; iPart < g_nPart; iPart++) + { + switch(ReadTransaction(pNdb, iPart, false)) + { + case -1: ++nReadError; break; + case 0: ++nReadCommit; break; + case 1: ++nReadRollback; break; + } + } + } + else + while(NdbMutex_Trylock(g_pNdbMutexStop)) + { + Uint32 iPart = rndgen.genrand() % g_nPart; + Uint32 iTrans = rndgen.genrand() % 5; + bool bIndex = ((rndgen.genrand() & 1) ? true : false); + switch(iTrans) + { + case 0: + switch(InsertTransaction(pNdb, iPart, bIndex)) + { + case -1: ++nInsertError; break; + case 0: ++nInsertCommit; break; + case 1: ++nInsertRollback; break; + } + break; + + case 1: + switch(UpdateGetAndSetTransaction(pNdb, iPart, bIndex)) + { + case -1: ++nUpdateGetAndSetError; break; + case 0: ++nUpdateGetAndSetCommit; break; + case 1: ++nUpdateGetAndSetRollback; break; + } + break; + + case 2: + switch(ReadTransaction(pNdb, iPart, bIndex)) + { + case -1: ++nReadError; break; + case 0: ++nReadCommit; break; + case 1: ++nReadRollback; break; + } + break; + + case 3: + switch(UpdateInterpretedTransaction(pNdb, iPart, bIndex)) + { + case -1: ++nUpdateInterpretedError; break; + case 0: ++nUpdateInterpretedCommit; break; + case 1: ++nUpdateInterpretedRollback; break; + } + break; + + case 4: + switch(DeleteTransaction(pNdb, iPart, bIndex)) + { + case -1: ++nDeleteError; break; + case 0: ++nDeleteCommit; break; + case 1: ++nDeleteRollback; break; + } + break; + } + } + + ndbout << "I:" << nInsertError << ":" << nInsertCommit << ":" << nInsertRollback; + ndbout << " UG:" << nUpdateGetAndSetError << ":" << nUpdateGetAndSetCommit << ":" << nUpdateGetAndSetRollback; + ndbout << " R:" << nReadError << ":" << nReadCommit << ":" << nReadRollback; + ndbout << " UI:" << nUpdateInterpretedError << ":" << nUpdateInterpretedCommit << ":" << nUpdateInterpretedRollback; + ndbout << " D:" << nDeleteError << ":" << nDeleteCommit << ":" << nDeleteRollback << endl; + ndbout << endl; + + NdbMutex_Unlock(g_pNdbMutexStop); + delete pNdb; + return 0; +} + + +int main(int argc, char* argv[]) +{ + Uint32 nSeconds = 1; + Uint32 nThread = 1; + + for(int iArg=1; iArg<argc; ++iArg) + { + if(argv[iArg][0]=='-') + { + switch(argv[iArg][1]) + { + case 'p': g_nPart = atol(argv[iArg]+2); break; + case 'b': g_nTable = atol(argv[iArg]+2); break; + case 'u': g_nTuple = atol(argv[iArg]+2); break; + case 'a': g_nAttribute = atol(argv[iArg]+2); break; + case 'v': g_bVerify = true; break; + case 't': nThread = atol(argv[iArg]+2); break; + case 's': nSeconds = atol(argv[iArg]+2); break; + case 'i': g_bUseIndex = true; break; + } + } + } + ndbout << argv[0]; + ndbout << " -p" << g_nPart; + ndbout << " -b" << g_nTable; + ndbout << " -u" << g_nTuple; + ndbout << " -a" << g_nAttribute; + if (g_bVerify) + ndbout << " -v"; + ndbout << " -t" << nThread; + ndbout << " -s" << nSeconds; + ndbout << endl; + + g_szTable = new char[g_nTable*4]; + for(Uint32 iTable=0; iTable<g_nTable; ++iTable) + { + sprintf(g_szTable+iTable*4, "T%02d", iTable); + } + + g_szIndex = new char[g_nTable*4]; + for(Uint32 iIndex=0; iIndex<g_nTable; ++iIndex) + { + sprintf(g_szIndex+iIndex*4, "I%02d", iIndex); + } + + g_szAttribute = new char[g_nAttribute*4]; + for(Uint32 iAttr=0; iAttr<g_nAttribute; ++iAttr) + { + sprintf(g_szAttribute+iAttr*4, "A%02d", iAttr); + } + + + Ndb* pNdb = new Ndb("TEST_DB"); + pNdb->init(); + pNdb->waitUntilReady(); + + if (!g_bVerify) CreateTables(pNdb); + g_pNdbMutexStop = NdbMutex_Create(); + NdbMutex_Lock(g_pNdbMutexStop); + + NdbThread_SetConcurrencyLevel(nThread+1); + NdbThread** ppNdbThread = new NdbThread*[nThread]; + for(Uint32 iThread=0; iThread<nThread; ++iThread) + { + ppNdbThread[iThread] = NdbThread_Create(ThreadFunc, 0, 0, "ThreadFunc", NDB_THREAD_PRIO_MEAN); + } + + NdbSleep_SecSleep(nSeconds); + NdbMutex_Unlock(g_pNdbMutexStop); + + for(Uint32 iThread=0; iThread<nThread; ++iThread) + { + void* status; + NdbThread_WaitFor(ppNdbThread[iThread], &status); + } + + NdbMutex_Destroy(g_pNdbMutexStop); + g_pNdbMutexStop = 0; + delete pNdb; +} + + |