/* 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 <ndb_global.h> #include <ndb_opts.h> #include <NdbOut.hpp> #include <NdbApi.hpp> #include <NdbMain.h> #include <NDBT.hpp> #include <NdbSleep.h> #include <UtilTransactions.hpp> static int select_count(Ndb* pNdb, const NdbDictionary::Table* pTab, int parallelism, int* count_rows, NdbOperation::LockMode lock); static const char* opt_connect_str= 0; static const char* _dbname = "TEST_DB"; static int _parallelism = 240; static int _lock = 0; static struct my_option my_long_options[] = { NDB_STD_OPTS("ndb_desc"), { "database", 'd', "Name of database table is in", (gptr*) &_dbname, (gptr*) &_dbname, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 }, { "parallelism", 'p', "parallelism", (gptr*) &_parallelism, (gptr*) &_parallelism, 0, GET_INT, REQUIRED_ARG, 240, 0, 0, 0, 0, 0 }, { "lock", 'l', "Read(0), Read-hold(1), Exclusive(2)", (gptr*) &_lock, (gptr*) &_lock, 0, GET_INT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0} }; static void print_version() { printf("MySQL distrib %s, for %s (%s)\n",MYSQL_SERVER_VERSION,SYSTEM_TYPE,MACHINE_TYPE); } static void usage() { char desc[] = "tabname1 ... tabnameN\n"\ "This program will count the number of records in tables\n"; print_version(); my_print_help(my_long_options); my_print_variables(my_long_options); } static my_bool get_one_option(int optid, const struct my_option *opt __attribute__((unused)), char *argument) { switch (optid) { case '#': DBUG_PUSH(argument ? argument : "d:t:O,/tmp/ndb_select_count.trace"); break; case 'V': print_version(); exit(0); case '?': usage(); exit(0); } return 0; } int main(int argc, char** argv){ NDB_INIT(argv[0]); const char *load_default_groups[]= { "mysql_cluster",0 }; load_defaults("my",load_default_groups,&argc,&argv); int ho_error; if ((ho_error=handle_options(&argc, &argv, my_long_options, get_one_option))) return NDBT_ProgramExit(NDBT_WRONGARGS); if (argc < 1) { usage(); return NDBT_ProgramExit(NDBT_WRONGARGS); } Ndb::setConnectString(opt_connect_str); // Connect to Ndb Ndb MyNdb(_dbname); if(MyNdb.init() != 0){ ERR(MyNdb.getNdbError()); return NDBT_ProgramExit(NDBT_FAILED); } // Connect to Ndb and wait for it to become ready while(MyNdb.waitUntilReady() != 0) ndbout << "Waiting for ndb to become ready..." << endl; for(int i = 0; i<argc; i++){ // Check if table exists in db const NdbDictionary::Table * pTab = NDBT_Table::discoverTableFromDb(&MyNdb, argv[i]); if(pTab == NULL){ ndbout << " Table " << argv[i] << " does not exist!" << endl; continue; } int rows = 0; if (select_count(&MyNdb, pTab, _parallelism, &rows, (NdbOperation::LockMode)_lock) != 0){ return NDBT_ProgramExit(NDBT_FAILED); } ndbout << rows << " records in table " << argv[i] << endl; } return NDBT_ProgramExit(NDBT_OK); } int select_count(Ndb* pNdb, const NdbDictionary::Table* pTab, int parallelism, int* count_rows, NdbOperation::LockMode lock){ int retryAttempt = 0; const int retryMax = 100; int check; NdbConnection *pTrans; NdbScanOperation *pOp; while (true){ if (retryAttempt >= retryMax){ g_info << "ERROR: has retried this operation " << retryAttempt << " times, failing!" << endl; return NDBT_FAILED; } pTrans = pNdb->startTransaction(); if (pTrans == NULL) { const NdbError err = pNdb->getNdbError(); if (err.status == NdbError::TemporaryError){ NdbSleep_MilliSleep(50); retryAttempt++; continue; } ERR(err); return NDBT_FAILED; } pOp = pTrans->getNdbScanOperation(pTab->getName()); if (pOp == NULL) { ERR(pTrans->getNdbError()); pNdb->closeTransaction(pTrans); return NDBT_FAILED; } NdbResultSet * rs = pOp->readTuples(NdbScanOperation::LM_Dirty); if( rs == 0 ) { ERR(pTrans->getNdbError()); pNdb->closeTransaction(pTrans); return NDBT_FAILED; } check = pOp->interpret_exit_last_row(); if( check == -1 ) { ERR(pTrans->getNdbError()); pNdb->closeTransaction(pTrans); return NDBT_FAILED; } Uint64 tmp; Uint32 row_size; pOp->getValue(NdbDictionary::Column::ROW_COUNT, (char*)&tmp); pOp->getValue(NdbDictionary::Column::ROW_SIZE, (char*)&row_size); check = pTrans->execute(NoCommit); if( check == -1 ) { ERR(pTrans->getNdbError()); pNdb->closeTransaction(pTrans); return NDBT_FAILED; } Uint64 row_count = 0; int eof; while((eof = rs->nextResult(true)) == 0){ row_count += tmp; } if (eof == -1) { const NdbError err = pTrans->getNdbError(); if (err.status == NdbError::TemporaryError){ pNdb->closeTransaction(pTrans); NdbSleep_MilliSleep(50); retryAttempt++; continue; } ERR(err); pNdb->closeTransaction(pTrans); return NDBT_FAILED; } pNdb->closeTransaction(pTrans); if (count_rows != NULL){ *count_rows = row_count; } return NDBT_OK; } return NDBT_FAILED; }