Exemple #1
0
static void createIndex(Ndb &myNdb, bool includePrimary, unsigned int noOfIndexes)
{
  Uint64 before, after;
  NdbDictionary::Dictionary* dict = myNdb.getDictionary();
  char indexName[] = "PNUMINDEX0000";
  int res;

  for(unsigned int indexNum = 0; indexNum < noOfIndexes; indexNum++) {
    sprintf(indexName, "PNUMINDEX%.4u", indexNum);
    NdbDictionary::Index index(indexName);
    index.setTable("PERSON");
    index.setType(NdbDictionary::Index::UniqueHashIndex);
    if (includePrimary) {
      const char* attr_arr[] = {"NAME", "PNUM1", "PNUM3"};
      index.addIndexColumns(3, attr_arr);
    }
    else {
      const char* attr_arr[] = {"PNUM1", "PNUM3"};
      index.addIndexColumns(2, attr_arr);
    }
    before = NdbTick_CurrentMillisecond();
    if ((res = dict->createIndex(index)) == -1) {
      error_handler(dict->getNdbError());
    }    
    after = NdbTick_CurrentMillisecond();
    ndbout << "Created index " << indexName << ", " << after - before << " msec" << endl;
  }
}
void doCopyLap(Uint32 laps, const char * title){

  Uint64 ms1, ms2;
  const Uint32 count = g_count;
  for(Uint32 i = 0; i<count; i++)
    C(i, g_signal);
  laps--;
  for(Uint32 i = 0; i<count; i++)
    C(i, g_signal);
  laps--;
  
  Uint32 div = laps;
  
  ms1 = NdbTick_CurrentMillisecond();
  while(laps > 0){
    for(Uint32 i = 0; i<count; i++){
#if (__GNUC__ == 3 && __GNUC_MINOR >= 1)
      _builtin_prefetch(&g_jobBuffer[i], 1, 0);
#endif
      C(i, g_signal);
    }
    laps--;
  }
  ms2 = NdbTick_CurrentMillisecond();
  
  ms2 -= ms1;
  Uint32 diff = ms2;
  ndbout_c("%s : %d laps in %d millis => %d copies/sec",
	   title, div, diff, (1000*div*g_count+(diff/2))/diff);
}
Exemple #3
0
int InsertInitialRecords(Ndb* pNdb, long nInsert, long nSeed)
{
    int iRes = -1;
    char szMsg[100];
    for(long i=0; i<nInsert; ++i) 
    {
        int iContextID = i+nSeed;
        int nRetry = 0;
        NdbError err;
        memset(&err, 0, sizeof(err));
        NDB_TICKS tStartTrans = NdbTick_CurrentMillisecond();
        iRes = RetryInsertTransaction(pNdb, iContextID, nSeed, iContextID,
            (long)(tStartTrans/1000), (long)((tStartTrans%1000)*1000), 
            STATUS_DATA, err, nRetry);
        NDB_TICKS tEndTrans = NdbTick_CurrentMillisecond();
        long lMillisecForThisTrans = (long)(tEndTrans-tStartTrans);
        if(nRetry>0)
        {
            sprintf(szMsg, "insert retried %d times, time %ld msec.", 
                nRetry, lMillisecForThisTrans);
            ReportNdbError(szMsg, err);
        }
        if(iRes)
        {
            ReportNdbError("Insert initial record failed", err);
            return iRes;
        }
        InterlockedIncrement(&g_nNumberOfInitialInsert);
    }
    return iRes;
}
Exemple #4
0
int VerifyInitialRecords(Ndb* pNdb, long nVerify, long nSeed)
{
    int iRes = -1;
    char* pchContextData = new char[g_nStatusDataSize];
    char szMsg[100];
    long iPrevLockTime = -1;
    long iPrevLockTimeUSec = -1;
    for(long i=0; i<nVerify; ++i) 
    {
        int iContextID = i+nSeed;
        long iVersion = 0;
        long iLockFlag = 0;
        long iLockTime = 0;
        long iLockTimeUSec = 0;
        int nRetry = 0;
        NdbError err;
        memset(&err, 0, sizeof(err));
        NDB_TICKS tStartTrans = NdbTick_CurrentMillisecond();
        iRes = RetryQueryTransaction(pNdb, iContextID, &iVersion, &iLockFlag, 
                    &iLockTime, &iLockTimeUSec, pchContextData, err, nRetry);
        NDB_TICKS tEndTrans = NdbTick_CurrentMillisecond();
        long lMillisecForThisTrans = (long)(tEndTrans-tStartTrans);
        if(nRetry>0)
        {
            sprintf(szMsg, "verify retried %d times, time %ld msec.", 
                nRetry, lMillisecForThisTrans);
            ReportNdbError(szMsg, err);
        }
        if(iRes)
        {
            ReportNdbError("Read initial record failed", err);
            delete[] pchContextData;
            return iRes;
        }
        if(memcmp(pchContextData, STATUS_DATA, g_nStatusDataSize))
        {
            sprintf(szMsg, "wrong context data in tuple %d", iContextID);
            ReportNdbError(szMsg, err);
            delete[] pchContextData;
            return -1;
        }
        if(iVersion!=nSeed 
            || iLockFlag!=iContextID 
            || iLockTime<iPrevLockTime 
            || (iLockTime==iPrevLockTime && iLockTimeUSec<iPrevLockTimeUSec))
        {
            sprintf(szMsg, "wrong call data in tuple %d", iContextID);
            ReportNdbError(szMsg, err);
            delete[] pchContextData;
            return -1;
        }
        iPrevLockTime = iLockTime;
        iPrevLockTimeUSec = iLockTimeUSec;
        InterlockedIncrement(&g_nNumberOfInitialVerify);
    }
    delete[] pchContextData;
    return iRes;
}
Exemple #5
0
void
Ndb::check_send_timeout()
{
  Uint32 timeout = theImpl->get_ndbapi_config_parameters().m_waitfor_timeout;
  NDB_TICKS current_time = NdbTick_CurrentMillisecond();
  assert(current_time >= the_last_check_time);
  if (current_time - the_last_check_time > 1000) {
    the_last_check_time = current_time;
    Uint32 no_of_sent = theNoOfSentTransactions;
    for (Uint32 i = 0; i < no_of_sent; i++) {
      NdbTransaction* a_con = theSentTransactionsArray[i];
      if ((current_time - a_con->theStartTransTime) > timeout)
      {
#ifdef VM_TRACE
        a_con->printState();
	Uint32 t1 = (Uint32) a_con->theTransactionId;
	Uint32 t2 = a_con->theTransactionId >> 32;
	ndbout_c("4012 [%.8x %.8x]", t1, t2);
	//abort();
#endif
        a_con->theReleaseOnClose = true;
	a_con->theError.code = 4012;
        a_con->setOperationErrorCodeAbort(4012);
	a_con->theCommitStatus = NdbTransaction::NeedAbort;
        a_con->theCompletionStatus = NdbTransaction::CompletedFailure;
        a_con->handleExecuteCompletion();
        remove_sent_list(i);
        insert_completed_list(a_con);
        no_of_sent--;
        i--;
      }//if
    }//for
int stopOnError(F_ARGS){

  myRandom48Init((long)NdbTick_CurrentMillisecond());

  int randomId = myRandom48(_restarter.getNumDbNodes());
  int nodeId = _restarter.getDbNodeId(randomId);
  
  do {
    g_info << _restart->m_name << ": node = " << nodeId 
	   << endl;
    
    CHECK(_restarter.waitClusterStarted(300) == 0,
	  "waitClusterStarted failed");
    
    int val = DumpStateOrd::NdbcntrTestStopOnError;
    CHECK(_restarter.dumpStateOneNode(nodeId, &val, 1) == 0,
	  "failed to set NdbcntrTestStopOnError");
    
    NdbSleep_SecSleep(3);
    
    CHECK(_restarter.waitClusterStarted(300) == 0,
	  "waitClusterStarted failed");
  } while (false);
  
  return NDBT_OK;
}
Exemple #7
0
//--------------------------------------------------------------------
// ipControlLoop -- The main loop of ndb.
// Handles the scheduling of signal execution and input/output
// One lap in the loop should take approximately 10 milli seconds
// If the jobbuffer is empty and the laptime is less than 10 milliseconds
// at the end of the loop
// the TransporterRegistry is called in order to sleep on the IO ports
// waiting for another incoming signal to wake us up.
// The timeout value in this call is calculated as (10 ms - laptime)
// This would make ndb use less cpu while improving response time.
//--------------------------------------------------------------------
void ThreadConfig::ipControlLoop()
{

//--------------------------------------------------------------------
// initialise the counter that keeps track of the current millisecond
//--------------------------------------------------------------------
  globalData.internalMillisecCounter = NdbTick_CurrentMillisecond();
  Uint32 i = 0;
  while (globalData.theRestartFlag != perform_stop)  { 

    Uint32 timeOutMillis = 0;
    if (LEVEL_IDLE == globalData.highestAvailablePrio) {
//--------------------------------------------------------------------
// The buffers are empty, we need to wait for a while until we continue.
// We cannot wait forever since we can also have timed events.
//--------------------------------------------------------------------
//--------------------------------------------------------------------
// Set the time we will sleep on the sockets before waking up
// unconditionally to 10 ms. Will never sleep more than 10 milliseconds
// on a socket.
//--------------------------------------------------------------------
      timeOutMillis = 10;
    }//if
//--------------------------------------------------------------------
// Now it is time to check all interfaces. We will send all buffers
// plus checking for any received messages.
//--------------------------------------------------------------------
    if (i++ >= 20) {
      globalTransporterRegistry.update_connections();
      globalData.incrementWatchDogCounter(5);
      i = 0;
    }//if

    globalData.incrementWatchDogCounter(6);
    globalTransporterRegistry.performSend();
    
    globalData.incrementWatchDogCounter(7);
    if (globalTransporterRegistry.pollReceive(timeOutMillis)) {
      globalData.incrementWatchDogCounter(8);
      globalTransporterRegistry.performReceive();
    }

//--------------------------------------------------------------------
// We scan the time queue to see if there are any timed signals that
// is now ready to be executed.
//--------------------------------------------------------------------
    globalData.incrementWatchDogCounter(2);
    scanTimeQueue(); 

//--------------------------------------------------------------------
// This is where the actual execution of signals occur. We execute
// until all buffers are empty or until we have executed 2048 signals.
//--------------------------------------------------------------------
    globalScheduler.doJob();
  }//while

  globalData.incrementWatchDogCounter(6);
  globalTransporterRegistry.performSend();

}//ThreadConfig::ipControlLoop()
/**
 * For each millisecond that has passed since this function was last called:
 *   Scan the job buffer and increment the internalMillisecCounter 
 *      with 1 to keep track of where we are
 */
inline
void 
ThreadConfig::scanTimeQueue()
{
  unsigned int maxCounter;
  Uint64 currMilliSecond;
  maxCounter = 0;
  currMilliSecond = NdbTick_CurrentMillisecond();
  if (currMilliSecond < globalData.internalMillisecCounter) {
//--------------------------------------------------------------------
// This could occur around 2036 or if the operator decides to change
// time backwards. We cannot know how long time has past since last
// time and we make a best try with 0 milliseconds.
//--------------------------------------------------------------------
    g_eventLogger->warning("Time moved backwards with %llu ms",
                           globalData.internalMillisecCounter-currMilliSecond);
    globalData.internalMillisecCounter = currMilliSecond;
  }//if
  if (currMilliSecond > (globalData.internalMillisecCounter + 1500)) {
//--------------------------------------------------------------------
// Time has moved forward more than a second. Either it could happen
// if operator changed the time or if the OS has misbehaved badly.
// We set the new time to one second from the past.
//--------------------------------------------------------------------
    g_eventLogger->warning("Time moved forward with %llu ms",
                           currMilliSecond-globalData.internalMillisecCounter);
    globalData.internalMillisecCounter = currMilliSecond - 1000;
  }//if
  while (((currMilliSecond - globalData.internalMillisecCounter) > 0) &&
         (maxCounter < 20)){
    globalData.internalMillisecCounter++;
    maxCounter++;
    globalTimeQueue.scanTable();
  }//while
}//ThreadConfig::scanTimeQueue()
int getRandomNodeId(NdbRestarter& _restarter) {
  myRandom48Init((long)NdbTick_CurrentMillisecond());
  int randomId = myRandom48(_restarter.getNumDbNodes());
  int nodeId = _restarter.getDbNodeId(randomId);

  return nodeId;
}
Exemple #10
0
bool
NDBT_Context::closeToTimeout(int safety)
{
  if (safety == 0)
    return false;

  if (m_env_timeout == 0)
  {
    char buf[1024];
    const char * p = NdbEnv_GetEnv("ATRT_TIMEOUT", buf, sizeof(buf));
    if (p)
    {
      m_env_timeout = atoi(p);
      ndbout_c("FOUND ATRT_TIMEOUT: %d", m_env_timeout);
    }
    else
    {
      m_env_timeout = -1;
    }
  }

  if (m_env_timeout < 0)
    return false;

  Uint64 to = (1000 * m_env_timeout * (100 - safety)) / 100;
  Uint64 now = NdbTick_CurrentMillisecond();
  if (now >= m_test_start_time + to)
  {
    ndbout_c("closeToTimeout(%d) => true env(timeout): %d",
             safety, m_env_timeout);
    return true;
  }

  return false;
}
Exemple #11
0
int
write_socket(NDB_SOCKET_TYPE socket, int timeout_millis, int *time,
	     const char buf[], int len){
  fd_set writeset;
  FD_ZERO(&writeset);
  FD_SET(socket, &writeset);
  struct timeval timeout;
  timeout.tv_sec  = (timeout_millis / 1000);
  timeout.tv_usec = (timeout_millis % 1000) * 1000;


  Uint64 tick= NdbTick_CurrentMillisecond();
  const int selectRes = select(socket + 1, 0, &writeset, 0, &timeout);
  *time= NdbTick_CurrentMillisecond() - tick;

  if(selectRes != 1){
    return -1;
  }

  const char * tmp = &buf[0];
  while(len > 0){
    const int w = send(socket, tmp, len, 0);
    if(w == -1){
      return -1;
    }
    len -= w;
    tmp += w;
    
    if(len == 0)
      break;
    
    FD_ZERO(&writeset);
    FD_SET(socket, &writeset);
    timeout.tv_sec  = ((timeout_millis - *time) / 1000);
    timeout.tv_usec = ((timeout_millis - *time) % 1000) * 1000;

    Uint64 tick= NdbTick_CurrentMillisecond();
    const int selectRes2 = select(socket + 1, 0, &writeset, 0, &timeout);
    *time= NdbTick_CurrentMillisecond() - tick;

    if(selectRes2 != 1){
      return -1;
    }
  }
  
  return 0;
}
Exemple #12
0
static void dropIndex(Ndb &myNdb, unsigned int noOfIndexes)
{
  for(unsigned int indexNum = 0; indexNum < noOfIndexes; indexNum++) {
    char indexName[255];
    sprintf(indexName, "PNUMINDEX%.4u", indexNum);
    const Uint64 before = NdbTick_CurrentMillisecond();
    const int retVal = myNdb.getDictionary()->dropIndex(indexName, "PERSON");
    const Uint64 after = NdbTick_CurrentMillisecond();
    
    if(retVal == 0){
      ndbout << "Dropped index " << indexName << ", " 
	     << after - before << " msec" << endl;
    } else {
      ndbout << "Failed to drop index " << indexName << endl;
      ndbout << myNdb.getDictionary()->getNdbError() << endl;
    }
  }
}
Exemple #13
0
int
main(void){
  
  srand(NdbTick_CurrentMillisecond());

  //test( 1, 1000, 1000);
  test(54, 1000, 1000);
  test(59, 1000, 1000);
  test(60, 1000, 1000);
  test(61, 1000, 1000);
  return 0;
}
SimpleSignal *
SignalSender::waitFor(Uint32 timeOutMillis, T & t)
{
  SimpleSignal * s = t.check(m_jobBuffer);
  if(s != 0){
    if (m_usedBuffer.push_back(s))
    {
      return 0;
    }
    assert(s->header.theLength > 0);
    return s;
  }

  /* Remove old signals from usedBuffer */
  for (unsigned i= 0; i < m_usedBuffer.size(); i++)
    delete m_usedBuffer[i];
  m_usedBuffer.clear();

  NDB_TICKS now = NdbTick_CurrentMillisecond();
  NDB_TICKS stop = now + timeOutMillis;
  Uint32 wait = (timeOutMillis == 0 ? 10 : timeOutMillis);
  do {
    do_poll(wait);
    
    SimpleSignal * s = t.check(m_jobBuffer);
    if(s != 0){
      if (m_usedBuffer.push_back(s))
      {
        return 0;
      }
      assert(s->header.theLength > 0);
      return s;
    }
    
    now = NdbTick_CurrentMillisecond();
    wait = (Uint32)(timeOutMillis == 0 ? 10 : stop - now);
  } while(stop > now || timeOutMillis == 0);
  
  return 0;
} 
Exemple #15
0
extern "C" void* NdbThreadFuncUpdate(void* pArg)
{
    myRandom48Init((long int)NdbTick_CurrentMillisecond());
    unsigned nSucc = 0;
    unsigned nFail = 0;
    Ndb* pNdb = NULL ;
    pNdb = new Ndb("TEST_DB");
    VerifyMethodInt(pNdb, init());
    VerifyMethodInt(pNdb, waitUntilReady());

    while(NdbMutex_Trylock(g_pNdbMutex)) {
        Uint32 nWarehouse = myRandom48(g_nWarehouseCount);
        NdbConnection* pNdbConnection = NULL ;
        VerifyMethodPtr(pNdbConnection, pNdb, startTransaction());
        CHK_TR(pNdbConnection) ; // epaulsa
        NdbOperation* pNdbOperationW = NULL ;
        VerifyMethodPtr(pNdbOperationW, pNdbConnection, getNdbOperation(c_szWarehouse));
        VerifyMethodInt(pNdbOperationW, interpretedUpdateTuple());
        VerifyMethodInt(pNdbOperationW, equal(c_szWarehouseNumber, nWarehouse));
        VerifyMethodInt(pNdbOperationW, incValue(c_szWarehouseCount, Uint32(1)));
        Uint32 nWarehouseSum = 0;
        for(Uint32 nDistrict=0; nDistrict<g_nDistrictPerWarehouse; ++nDistrict) {
            NdbOperation* pNdbOperationD = NULL ;
            VerifyMethodPtr(pNdbOperationD, pNdbConnection, getNdbOperation(c_szDistrict));
            VerifyMethodInt(pNdbOperationD, interpretedUpdateTuple());
            VerifyMethodInt(pNdbOperationD, equal(c_szDistrictWarehouseNumber, nWarehouse));
            VerifyMethodInt(pNdbOperationD, equal(c_szDistrictNumber, nDistrict));
            VerifyMethodInt(pNdbOperationD, incValue(c_szDistrictCount, Uint32(1)));
            Uint32 nDistrictSum = myRandom48(100);
            nWarehouseSum += nDistrictSum;
            VerifyMethodInt(pNdbOperationD, setValue(c_szDistrictSum, nDistrictSum));
        }
        VerifyMethodInt(pNdbOperationW, setValue(c_szWarehouseSum, nWarehouseSum));
        int iExec = pNdbConnection->execute(Commit);
        int iError = pNdbConnection->getNdbError().code;

        if(iExec<0 && iError!=0 && iError!=266 && iError!=626) {
            ReportMethodInt(iExec, pNdbConnection, "pNdbConnection", "execute(Commit)", __FILE__, __LINE__);
        }
        if(iExec==0) {
            ++nSucc;
        } else {
            ++nFail;
        }
        VerifyMethodVoid(pNdb, closeTransaction(pNdbConnection));
    }
    ndbout << "update: " << nSucc << " succeeded, " << nFail << " failed " << endl;
    NdbMutex_Unlock(g_pNdbMutex);
    delete pNdb;
    pNdb = NULL ;
    return NULL;
}
int restartRandomNodeInitial(F_ARGS){

  myRandom48Init((long)NdbTick_CurrentMillisecond());
  int randomId = myRandom48(_restarter.getNumDbNodes());
  int nodeId = _restarter.getDbNodeId(randomId);
  
  g_info << _restart->m_name << ": node = "<<nodeId << endl;

  CHECK(_restarter.restartOneDbNode(nodeId, true) == 0,
	"Could not restart node "<<nodeId);

  return NDBT_OK;
}
int restartRandomNodeError(F_ARGS){

  myRandom48Init((long)NdbTick_CurrentMillisecond());
  int randomId = myRandom48(_restarter.getNumDbNodes());
  int nodeId = _restarter.getDbNodeId(randomId);
  
  ndbout << _restart->m_name << ": node = "<<nodeId << endl;

  CHECK(_restarter.insertErrorInNode(nodeId, 9999) == 0, 
	"Could not restart node "<<nodeId);

  return NDBT_OK;
}
Exemple #18
0
void InterlockedIncrementAndReport(void)
{
    NdbMutex_Lock(g_pNdbMutexIncrement);
    ++g_nNumCallsProcessed;
    if((g_nNumCallsProcessed%1000)==0) 
    {
        g_tEndTime = NdbTick_CurrentMillisecond();
        if(g_tStartTime) 
            ReportCallsPerSecond(1000, g_tStartTime, g_tEndTime);

        g_tStartTime = g_tEndTime;
    }
    NdbMutex_Unlock(g_pNdbMutexIncrement);
}
Exemple #19
0
NDBT_Context::NDBT_Context(Ndb_cluster_connection& con)
  : m_cluster_connection(con)
{
  suite = NULL;
  testcase = NULL;
  ndb = NULL;
  records = 1;
  loops = 1;
  stopped = false;
  propertyMutexPtr = NdbMutex_Create();
  propertyCondPtr = NdbCondition_Create();
  m_env_timeout = 0;
  m_test_start_time = NdbTick_CurrentMillisecond();
}
int 
doTime(Uint32 ms){
  
  Uint64 ms1, ms2;
  const Uint32 count = g_count;
  for(Uint32 i = 0; i<count; i++)
    C(i, g_signal);
  for(Uint32 i = 0; i<count; i++)
    C(i, g_signal);
  
  Uint32 laps = 0;
  
  ms1 = NdbTick_CurrentMillisecond();
  do {
    for(int j = 100; j>= 0; j--)
      for(Uint32 i = 0; i<count; i++){
	C(i, g_signal);
      }
    ms2 = NdbTick_CurrentMillisecond();
    laps += 100;
  } while((ms2 - ms1) < ms);
  
  return laps;
}
void
Restore::release_file(FilePtr file_ptr)
{
  LocalDataBuffer<15> pages(m_databuffer_pool, file_ptr.p->m_pages);
  LocalDataBuffer<15> columns(m_databuffer_pool, file_ptr.p->m_columns);

  List::Iterator it;
  for (pages.first(it); !it.isNull(); pages.next(it))
  {
    if (* it.data == RNIL)
      continue;
    m_global_page_pool.release(* it.data);
  }

  {
    Uint64 millis = NdbTick_CurrentMillisecond() -
                   file_ptr.p->m_restore_start_time;
    if (millis == 0)
      millis = 1;
    Uint64 bps = file_ptr.p->m_bytes_restored * 1000 / millis;

    g_eventLogger->info("LDM instance %u: Restored T%dF%u LCP %llu rows, "
                        "%llu bytes, %llu millis, %llu bytes/s)", 
                        instance(),
                        file_ptr.p->m_table_id,
                        file_ptr.p->m_fragment_id,
                        file_ptr.p->m_rows_restored,
                        file_ptr.p->m_bytes_restored,
                        millis,
                        bps);

    m_rows_restored+= file_ptr.p->m_rows_restored;
    m_bytes_restored+= file_ptr.p->m_bytes_restored;
    m_millis_spent+= millis;
    m_frags_restored++;
  }
  
  columns.release();
  pages.release();
  m_file_list.release(file_ptr);
}
/**
 * Report connection established
 */
void
reportConnect(void* callbackObj, NodeId nodeId){
  char buf[255];
  sprintf(buf, "reportConnect(%d)", nodeId);
  ndbout << buf << endl;
  tReg->setPerformState(nodeId, PerformIO);
  
  if(!isStarted){
    isStarted = true;
    startTime = NdbTick_CurrentMillisecond();
    if(isClient){
      reportHeader();
      allPhases[0].startTime = startTime;
    }
  }
  else{
    // Resend signals that were lost when connection failed
    TestPhase * current = &allPhases[currentPhase];
    current->noOfSignalSent = current->noOfSignalReceived;
  }
}
int twoNodeFailure(F_ARGS){

  myRandom48Init((long)NdbTick_CurrentMillisecond());
  int randomId = myRandom48(_restarter.getNumDbNodes());
  int n[2];
  n[0] = _restarter.getDbNodeId(randomId);  
  n[1] = _restarter.getRandomNodeOtherNodeGroup(n[0], rand());
  g_info << _restart->m_name << ": node = "<< n[0] << endl;

  int val2[] = { DumpStateOrd::CmvmiSetRestartOnErrorInsert, 1 };
  CHECK(_restarter.dumpStateOneNode(n[0], val2, 2) == 0,
        "Failed to dump");
  CHECK(_restarter.dumpStateOneNode(n[1], val2, 2) == 0,
        "Failed to dump");
  
  CHECK(_restarter.insertErrorInNode(n[0], 9999) == 0,
	"Could not restart node "<< n[0]);

    // Create random value, max 3 secs
  int max = 3000;
  int ms = (myRandom48(max)) + 1;   
  g_info << "Waiting for " << ms << "(" << max 
	 << ") ms " << endl;
  NdbSleep_MilliSleep(ms);

  g_info << _restart->m_name << ": node = "<< n[1] << endl;
  CHECK(_restarter.insertErrorInNode(n[1], 9999) == 0,
	"Could not restart node "<< n[1]);

  CHECK(_restarter.waitNodesNoStart(n, 2) == 0,
        "Failed to wait nostart");

  _restarter.startNodes(n, 2);
  
  return NDBT_OK;
}
int
main(int argc, const char** argv) {
    ndb_init();
    int verbose = 1;
    int optind = 0;

    struct getargs args[1+P_MAX] = {
        { "verbose", 'v', arg_flag, &verbose, "Print verbose status", "verbose" }
    };
    const int num_args = 1 + P_MAX;
    int i;
    for(i = 0; i<P_MAX; i++) {
        args[i+1].long_name = g_paramters[i].name;
        args[i+1].short_name = * g_paramters[i].name;
        args[i+1].type = arg_integer;
        args[i+1].value = &g_paramters[i].value;
        BaseString tmp;
        tmp.assfmt("min: %d max: %d", g_paramters[i].min, g_paramters[i].max);
        args[i+1].help = strdup(tmp.c_str());
        args[i+1].arg_help = 0;
    }

    if(getarg(args, num_args, argc, argv, &optind)) {
        arg_printusage(args, num_args, argv[0], "tabname1 tabname2 ...");
        return NDBT_WRONGARGS;
    }

    myRandom48Init(NdbTick_CurrentMillisecond());
    memset(g_times, 0, sizeof(g_times));

    Ndb_cluster_connection con;
    if(con.connect(12, 5, 1))
    {
        return NDBT_ProgramExit(NDBT_FAILED);
    }

    g_ndb = new Ndb(&con, "TEST_DB");
    if(g_ndb->init() != 0) {
        g_err << "init() failed" << endl;
        goto error;
    }
    if(g_ndb->waitUntilReady() != 0) {
        g_err << "Wait until ready failed" << endl;
        goto error;
    }
    for(i = optind; i<argc; i++) {
        const char * T = argv[i];
        g_info << "Testing " << T << endl;
        BaseString::snprintf(g_table, sizeof(g_table), T);
        BaseString::snprintf(g_ordered, sizeof(g_ordered), "IDX_O_%s", T);
        BaseString::snprintf(g_unique, sizeof(g_unique), "IDX_U_%s", T);
        if(create_table())
            goto error;
        if(load_table())
            goto error;
        for(int l = 0; l<g_paramters[P_LOOPS].value; l++) {
            for(int j = 0; j<P_OP_TYPES; j++) {
                g_paramters[P_OPER].value = j;
                if(run_read())
                    goto error;
            }
        }
        print_result();
    }

    if(g_ndb) delete g_ndb;
    return NDBT_OK;
error:
    if(g_ndb) delete g_ndb;
    return NDBT_FAILED;
}
int
run_read() {
    int iter = g_paramters[P_LOOPS].value;
    NDB_TICKS start1, stop;
    int sum_time= 0;

    const Uint32 rows = g_paramters[P_ROWS].value;
    const Uint32 range = g_paramters[P_RANGE].value;

    start1 = NdbTick_CurrentMillisecond();
    NdbConnection * pTrans = g_ndb->startTransaction();
    if(!pTrans) {
        g_err << "Failed to start transaction" << endl;
        err(g_ndb->getNdbError());
        return -1;
    }

    NdbOperation * pOp;
    NdbScanOperation * pSp;
    NdbIndexOperation * pUp;
    NdbIndexScanOperation * pIp;

    Uint32 start_row = rand() % (rows - range);
    Uint32 stop_row = start_row + range;

    /**
     * 0 - serial pk
     * 1 - batch pk
     * 2 - serial uniq
     * 3 - batch uniq
     * 4 - index eq
     * 5 - range scan
     * 6 - interpreted scan
     */
    int check = 0;
    void* res = (void*)~0;
    const Uint32 pk = 0;
    Uint32 cnt = 0;
    for(; start_row < stop_row; start_row++) {
        switch(g_paramters[P_OPER].value) {
        case 0:
            pOp = pTrans->getNdbOperation(g_table);
            check = pOp->readTuple();
            check = pOp->equal(pk, start_row);
            break;
        case 1:
            for(; start_row<stop_row; start_row++) {
                pOp = pTrans->getNdbOperation(g_table);
                check = pOp->readTuple();
                check = pOp->equal(pk, start_row);
                for(int j = 0; j<g_tab->getNoOfColumns(); j++) {
                    res = pOp->getValue(j);
                    assert(res);
                }
            }
            break;
        case 2:
            pOp = pTrans->getNdbIndexOperation(g_unique, g_table);
            check = pOp->readTuple();
            check = pOp->equal(pk, start_row);
            break;
        case 3:
            for(; start_row<stop_row; start_row++) {
                pOp = pTrans->getNdbIndexOperation(g_unique, g_table);
                check = pOp->readTuple();
                check = pOp->equal(pk, start_row);
                for(int j = 0; j<g_tab->getNoOfColumns(); j++) {
                    res = pOp->getValue(j);
                    assert(res);
                }
            }
            break;
        case 4:
            pOp = pSp = pIp = pTrans->getNdbIndexScanOperation(g_ordered,g_table);
            pIp->readTuples(NdbScanOperation::LM_CommittedRead, 0, 0);
            check = pIp->setBound(pk, NdbIndexScanOperation::BoundEQ, &start_row);
            break;
        case 5:
            pOp = pSp = pIp = pTrans->getNdbIndexScanOperation(g_ordered,g_table);
            pIp->readTuples(NdbScanOperation::LM_CommittedRead, 0, 0);
            check = pIp->setBound(pk, NdbIndexScanOperation::BoundLE, &start_row);
            check = pIp->setBound(pk, NdbIndexScanOperation::BoundGT, &stop_row);
            start_row = stop_row;
            break;
        case 6:
            pOp = pSp = pIp = pTrans->getNdbIndexScanOperation(g_ordered,g_table);
            pIp->readTuples(NdbScanOperation::LM_CommittedRead, 0, 0, true);
            check = pIp->setBound(pk, NdbIndexScanOperation::BoundLE, &start_row);
            check = pIp->setBound(pk, NdbIndexScanOperation::BoundGT, &stop_row);
            start_row = stop_row;
            break;
        case 7:
            pOp = pSp = pTrans->getNdbScanOperation(g_table);
            pSp->readTuples(NdbScanOperation::LM_CommittedRead, 0, 0);
            NdbScanFilter filter(pOp) ;
            filter.begin(NdbScanFilter::AND);
            filter.ge(pk, start_row);
            filter.lt(pk, stop_row);
            filter.end();
            start_row = stop_row;
            break;
        }

        assert(res);
        if(check != 0) {
            ndbout << pOp->getNdbError() << endl;
            ndbout << pTrans->getNdbError() << endl;
        }
        assert(check == 0);

        for(int j = 0; j<g_tab->getNoOfColumns(); j++) {
            res = pOp->getValue(j);
            assert(res);
        }

        check = pTrans->execute(NoCommit);
        if(check != 0) {
            ndbout << pTrans->getNdbError() << endl;
        }
        assert(check == 0);
        if(g_paramters[P_OPER].value >= 4) {
            while((check = pSp->nextResult(true)) == 0) {
                cnt++;
            }

            if(check == -1) {
                err(pTrans->getNdbError());
                return -1;
            }
            assert(check == 1);
            pSp->close();
        }
    }
    assert(g_paramters[P_OPER].value < 4 || (cnt == range));

    pTrans->close();

    stop = NdbTick_CurrentMillisecond();
    g_times[g_paramters[P_OPER].value] += (stop - start1);
    return 0;
}
void
client(NodeId remoteNodeId){
  isClient = true;

  currentPhase = 0;
  memcpy(allPhases, testSpec, sizeof(testSpec));

  int counter = 0;
  int sigCounter = 0;

  while(true){
    TestPhase * current = &allPhases[currentPhase];
    if(current->noOfSignals == current->noOfSignalSent &&
       current->noOfSignals == current->noOfSignalReceived){

      /**
       * Test phase done
       */
      current->stopTime  = NdbTick_CurrentMillisecond();
      current->accTime  += (current->stopTime - current->startTime);

      NdbSleep_MilliSleep(500 / loopCount);
      
      current->startTime = NdbTick_CurrentMillisecond();
      
      current->noOfSignalSent     = 0;
      current->noOfSignalReceived = 0;

      current->loopCount ++;
      if(current->loopCount == loopCount){

	printReport(allPhases[currentPhase]);

	currentPhase ++;
	if(currentPhase == noOfTests){
	  /**
	   * Now we are done
	   */
	  break;
	}
	NdbSleep_MilliSleep(500);
	current = &allPhases[currentPhase];
	current->startTime = NdbTick_CurrentMillisecond();
      }
    } 
    
    int signalsLeft = current->noOfSignals - current->noOfSignalSent;
    if(signalsLeft > 0){
      for(; signalsLeft > 0; signalsLeft--){
	if(sendSignalTo(remoteNodeId,current->signalSize,sigCounter)== SEND_OK){
	  current->noOfSignalSent++;
	  sigCounter++;
	} else {
	  ndbout << "Failed to send: " << sigCounter << endl;
	  tReg->external_IO(10);
	  break;
	}
      }
    }
    if(counter % 10 == 0)
      tReg->checkConnections();
    tReg->external_IO(0);
    counter++;
  }
}
Exemple #27
0
int NDBT_TestSuite::execute(int argc, const char** argv){
  int res = NDBT_FAILED;
  /* Arguments:
       Run only a subset of tests
       -n testname Which test to run
       Recommendations to test functions:
       --records Number of records to use(default: 10000)
       --loops Number of loops to execute in the test(default: 100)

       Other parameters should:
       * be calculated from the above two parameters 
       * be divided into different test cases, ex. one testcase runs
         with FragmentType = Single and another perfoms the same 
         test with FragmentType = Large
       * let the test case iterate over all/subset of appropriate parameters
         ex. iterate over FragmentType = Single to FragmentType = AllLarge

       Remeber that the intention is that it should be _easy_ to run 
       a complete test suite without any greater knowledge of what 
       should be tested ie. keep arguments at a minimum
  */

  char **_argv= (char **)argv;

  if (!my_progname)
    my_progname= _argv[0];

  ndb_opt_set_usage_funcs(short_usage_sub, usage);

  ndb_load_defaults(NULL, load_default_groups,&argc,&_argv);
  // Save pointer to memory allocated by 'ndb_load_defaults'
  char** defaults_argv= _argv;

  int ho_error;
#ifndef DBUG_OFF
  opt_debug= "d:t:i:F:L";
#endif
  if ((ho_error=handle_options(&argc, &_argv, my_long_options,
			       ndb_std_get_one_option)))
  {
    usage();
    ndb_free_defaults(defaults_argv);
    return NDBT_ProgramExit(NDBT_WRONGARGS);
  }

  if (opt_verbose)
    setOutputLevel(2); // Show g_info
  else 
    setOutputLevel(0); // Show only g_err ?

  records = opt_records;
  loops = opt_loops;
  timer = opt_timer;
  if (opt_nologging)
    setLogging(false);
  temporaryTables = opt_temporary;
  m_noddl = opt_noddl;
  m_forceShort = opt_forceShort;

  if (opt_seed == 0)
  {
    opt_seed = (unsigned)NdbTick_CurrentMillisecond();
  }
  ndbout_c("random seed: %u", opt_seed);
  srand(opt_seed);
  srandom(opt_seed);

  global_flag_skip_invalidate_cache = 1;

  int num_tables= argc;
  if (argc == 0)
    num_tables = NDBT_Tables::getNumTables();

  for(int i = 0; i<num_tables; i++)
  {
    if (argc == 0)
      m_tables_in_test.push_back(NDBT_Tables::getTable(i)->getName());
    else
      m_tables_in_test.push_back(_argv[i]);
  }

  if (m_createTable)
  {
    for (unsigned t = 0; t < tests.size(); t++)
    {
      const char* createFuncName= NULL;
      NDBT_TESTFUNC* createFunc= NULL;
      const char* dropFuncName= NULL;
      NDBT_TESTFUNC* dropFunc= NULL;

      if (!m_noddl)
      {
        createFuncName= m_createAll ? "runCreateTable" : "runCreateTable";
        createFunc=   m_createAll ? &runCreateTables : &runCreateTable;
        dropFuncName= m_createAll ? "runDropTables" : "runDropTable";
        dropFunc= m_createAll ? &runDropTables : &runDropTable;
      }
      else
      {
        /* No DDL allowed, so we substitute 'do nothing' variants
         * of the create + drop table test procs
         */
        createFuncName= "runCheckTableExists";
        createFunc= &runCheckTableExists;
        dropFuncName= "runEmptyDropTable";
        dropFunc= &runEmptyDropTable;
      }

      NDBT_TestCaseImpl1* pt= (NDBT_TestCaseImpl1*)tests[t];
      NDBT_Initializer* pti =
        new NDBT_Initializer(pt,
                             createFuncName,
                             *createFunc);
      pt->addInitializer(pti, true);
      NDBT_Finalizer* ptf =
        new NDBT_Finalizer(pt,
                           dropFuncName,
                           *dropFunc);
      pt->addFinalizer(ptf);
    }

    for (unsigned t = 0; t < explicitTests.size(); t++)
    {
      const char* createFuncName= NULL;
      NDBT_TESTFUNC* createFunc= NULL;
      const char* dropFuncName= NULL;
      NDBT_TESTFUNC* dropFunc= NULL;

      if (!m_noddl)
      {
        createFuncName= m_createAll ? "runCreateTable" : "runCreateTable";
        createFunc=   m_createAll ? &runCreateTables : &runCreateTable;
        dropFuncName= m_createAll ? "runDropTables" : "runDropTable";
        dropFunc= m_createAll ? &runDropTables : &runDropTable;
      }
      else
      {
        /* No DDL allowed, so we substitute 'do nothing' variants
         * of the create + drop table test procs
         */
        createFuncName= "runCheckTableExists";
        createFunc= &runCheckTableExists;
        dropFuncName= "runEmptyDropTable";
        dropFunc= &runEmptyDropTable;
      }

      NDBT_TestCaseImpl1* pt= (NDBT_TestCaseImpl1*)explicitTests[t];
      NDBT_Initializer* pti =
        new NDBT_Initializer(pt,
                             createFuncName,
                             *createFunc);
      pt->addInitializer(pti, true);
      NDBT_Finalizer* ptf =
        new NDBT_Finalizer(pt,
                           dropFuncName,
                           *dropFunc);
      pt->addFinalizer(ptf);
    }
  }

  if (opt_print == true){
    printExecutionTree();
    ndb_free_defaults(defaults_argv);
    return 0;
  }

  if (opt_print_html == true){
    printExecutionTreeHTML();
    ndb_free_defaults(defaults_argv);
    return 0;
  }

  if (opt_print_cases == true){
    printCases();
    ndb_free_defaults(defaults_argv);
    return 0;
  }

  Ndb_cluster_connection con(opt_ndb_connectstring, opt_ndb_nodeid);
  if(m_connect_cluster && con.connect(12, 5, 1))
  {
    ndb_free_defaults(defaults_argv);
    return NDBT_ProgramExit(NDBT_FAILED);
  }

  if(argc == 0){
    // No table specified
    res = executeAll(con, opt_testname);
  } else {
    testSuiteTimer.doStart(); 
    for(int i = 0; i<argc; i++){
      executeOne(con, _argv[i], opt_testname);
    }
    testSuiteTimer.doStop();
    res = report(opt_testname);
  }

  ndb_free_defaults(defaults_argv);
  return NDBT_ProgramExit(res);
}
void
MgmApiSession::get_nodeid(Parser_t::Context &,
			  const class Properties &args)
{
  const char *cmd= "get nodeid reply";
  Uint32 version, nodeid= 0, nodetype= 0xff;
  Uint32 timeout= 20;  // default seconds timeout
  const char * transporter;
  const char * user;
  const char * password;
  const char * public_key;
  const char * endian= NULL;
  const char * name= NULL;
  Uint32 log_event= 1;
  bool log_event_version;
  union { long l; char c[sizeof(long)]; } endian_check;

  args.get("version", &version);
  args.get("nodetype", &nodetype);
  args.get("transporter", &transporter);
  args.get("nodeid", &nodeid);
  args.get("user", &user);
  args.get("password", &password);
  args.get("public key", &public_key);
  args.get("endian", &endian);
  args.get("name", &name);
  args.get("timeout", &timeout);
  /* for backwards compatability keep track if client uses new protocol */
  log_event_version= args.get("log_event", &log_event);

  endian_check.l = 1;
  if(endian 
     && strcmp(endian,(endian_check.c[sizeof(long)-1])?"big":"little")!=0) {
    m_output->println(cmd);
    m_output->println("result: Node does not have the same endianness as the management server.");
    m_output->println("");
    return;
  }

  bool compatible;
  switch (nodetype) {
  case NODE_TYPE_MGM:
  case NODE_TYPE_API:
    compatible = ndbCompatible_mgmt_api(NDB_VERSION, version);
    break;
  case NODE_TYPE_DB:
    compatible = ndbCompatible_mgmt_ndb(NDB_VERSION, version);
    break;
  default:
    m_output->println(cmd);
    m_output->println("result: unknown nodetype %d", nodetype);
    m_output->println("");
    return;
  }

  struct sockaddr_in addr;
  SOCKET_SIZE_TYPE addrlen= sizeof(addr);
  int r = getpeername(m_socket, (struct sockaddr*)&addr, &addrlen);
  if (r != 0 ) {
    m_output->println(cmd);
    m_output->println("result: getpeername(%d) failed, err= %d", m_socket, r);
    m_output->println("");
    return;
  }

  NodeId tmp= nodeid;
  if(tmp == 0 || !m_allocated_resources->is_reserved(tmp)){
    BaseString error_string;
    int error_code;
    NDB_TICKS tick= 0;
    /* only report error on second attempt as not to clog the cluster log */
    while (!m_mgmsrv.alloc_node_id(&tmp, (enum ndb_mgm_node_type)nodetype, 
                                   (struct sockaddr*)&addr, &addrlen,
                                   error_code, error_string,
                                   tick == 0 ? 0 : log_event))
    {
      /* NDB_MGM_ALLOCID_CONFIG_MISMATCH is a non retriable error */
      if (tick == 0 && error_code != NDB_MGM_ALLOCID_CONFIG_MISMATCH)
      {
        // attempt to free any timed out reservations
        tick= NdbTick_CurrentMillisecond();
        struct PurgeStruct ps;
        m_mgmsrv.get_connected_nodes(ps.free_nodes);
        // invert connected_nodes to get free nodes
        ps.free_nodes.bitXORC(NodeBitmask());
        ps.str= 0;
        ps.tick= tick;
        m_mgmsrv.get_socket_server()->
          foreachSession(stop_session_if_timed_out,&ps);
	m_mgmsrv.get_socket_server()->checkSessions();
        error_string = "";
        continue;
      }
      const char *alias;
      const char *str;
      alias= ndb_mgm_get_node_type_alias_string((enum ndb_mgm_node_type)
						nodetype, &str);
      m_output->println(cmd);
      m_output->println("result: %s", error_string.c_str());
      /* only use error_code protocol if client knows about it */
      if (log_event_version)
        m_output->println("error_code: %d", error_code);
      m_output->println("");
      return;
    }
  }    
  
#if 0
  if (!compatible){
    m_output->println(cmd);
    m_output->println("result: incompatible version mgmt 0x%x and node 0x%x",
		      NDB_VERSION, version);
    m_output->println("");
    return;
  }
#endif
  
  m_output->println(cmd);
  m_output->println("nodeid: %u", tmp);
  m_output->println("result: Ok");
  m_output->println("");
  m_allocated_resources->reserve_node(tmp, timeout*1000);
  
  if (name)
    g_eventLogger.info("Node %d: %s", tmp, name);

  return;
}
 NdbRestarts(const char* _addr = 0): 
   m_restarter(_addr)
 {
   myRandom48Init((long)NdbTick_CurrentMillisecond());
 }
Exemple #30
0
int
main(void){

  srand(NdbTick_CurrentMillisecond());
#if 0
  for(int i = 0; i<100; i++)
    ndbout_c("randRange(0, 3) = %d", randRange(0, 3));
  return 0;
#endif
  SignalSender ss;
  
  ndbout << "Connecting...";
  if(!ss.connect(30)){
    ndbout << "failed" << endl << "Exiting" << endl;
    return 0;
  }
  ndbout << "done" << endl;
  ndbout_c("Connected as block=%d node=%d",
	   refToBlock(ss.getOwnRef()), refToNode(ss.getOwnRef()));
  
  Uint32 data[25];
  Uint32 sec0[70];
  Uint32 sec1[123];
  Uint32 sec2[10];
  
  data[0] = ss.getOwnRef();
  data[1] = 1;
  data[2] = 76; 
  data[3] = 1;
  data[4] = 1;
  data[5] = 70;
  data[6] = 123;
  data[7] = 10;
  const Uint32 theDataLen = 18;

  for(Uint32 i = 0; i<70; i++)
    sec0[i] = i;
  
  for(Uint32 i = 0; i<123; i++)
    sec1[i] = 70+i;

  for(Uint32 i = 0; i<10; i++)
    sec2[i] = (i + 1)*(i + 1);
  
  SimpleSignal signal1;
  signal1.set(ss, 0, CMVMI, GSN_TESTSIG, theDataLen + 2);  
  signal1.header.m_noOfSections = 1;
  signal1.header.m_fragmentInfo = 1;

  memcpy(&signal1.theData[0], data, 4 * theDataLen );
  signal1.theData[theDataLen + 0] = 0;
  signal1.theData[theDataLen + 1] = 7; // FragmentId
  
  signal1.ptr[0].sz = 60;
  signal1.ptr[0].p = &sec0[0];
  
  SimpleSignal signal2;
  
  Uint32 idx = 0;
  memcpy(&signal2.theData[0], data, 4 * theDataLen );
  signal2.theData[theDataLen + idx] = 0; idx++;
  signal2.theData[theDataLen + idx] = 1; idx++;
  //signal2.theData[theDataLen + idx] = 2; idx++;
  signal2.theData[theDataLen + idx] = 7; idx++; // FragmentId

  signal2.set(ss, 0, CMVMI, GSN_TESTSIG, theDataLen + idx);
  signal2.header.m_fragmentInfo = 3;
  signal2.header.m_noOfSections = idx - 1;
  
  signal2.ptr[0].sz = 10;
  signal2.ptr[0].p = &sec0[60];
  
  signal2.ptr[1].sz = 123;
  signal2.ptr[1].p = &sec1[0];
  
  signal2.ptr[2].sz = 10;
  signal2.ptr[2].p = &sec2[0];
  
  char * buf;
  while((buf = readline("Enter command: "))){
    add_history(buf);
    data[1] = atoi(buf);
    if(strcmp(buf, "r") == 0){
      SimpleSignal * ret1 = ss.waitFor();
      (* ret1).print();
      delete ret1;
      continue;
    }
    if(strcmp(buf, "a") == 0){
      runTest(ss, 10, true);
      print_help();
      continue;
    }
    if(strcmp(buf, "b") == 0){
      runTest(ss, 100, false);
      print_help();
      continue;
    }
    if(strcmp(buf, "c") == 0){
      runTest(ss, 1000000, false);
      print_help();
      continue;
    }
    
    if(data[1] >= 1 && data[1] <= 12){
      Uint32 nodeId = ss.getAliveNode();
      ndbout_c("Sending 2 fragmented to node %d", nodeId);
      ss.sendSignal(nodeId, &signal1);
      ss.sendSignal(nodeId, &signal2);

      if(data[1] >= 5){
	continue;
      }
      ndbout_c("Waiting for signal from %d", nodeId);
      
      SimpleSignal * ret1 = ss.waitFor((Uint16)nodeId);
      (* ret1).print();
      Uint32 count = ret1->theData[4] - 1;
      delete ret1;
      while(count > 0){
	ndbout << "Waiting for " << count << " signals... ";
	SimpleSignal * ret1 = ss.waitFor();
	ndbout_c("received from node %d", 
		 refToNode(ret1->header.theSendersBlockRef));
	(* ret1).print();
	delete ret1;
	count--;
      }
    } else if (data[1] == 13) {
      const Uint32 count = 3500;
      const Uint32 loop = 1000;

      signal1.set(ss, 0, CMVMI, GSN_TESTSIG, 25);
      signal1.header.m_fragmentInfo = 0;
      signal1.header.m_noOfSections = 0;
      signal1.theData[1] = 14; 
      signal1.theData[3] = 0;   // Print
      signal1.theData[8] = count;
      signal1.theData[9] = loop;
      Uint32 nodeId = ss.getAliveNode();
      ndbout_c("Sending 25 len signal to node %d", nodeId);
      ss.sendSignal(nodeId, &signal1);

      Uint32 total;
      {
	SimpleSignal * ret1 = ss.waitFor((Uint16)nodeId);
	ndbout_c("received from node %d", 
		 refToNode(ret1->header.theSendersBlockRef));
	total = ret1->theData[10] - 1;
	delete ret1;
      }

      do {
	ndbout << "Waiting for " << total << " signals... " << flush;
	SimpleSignal * ret1 = ss.waitFor((Uint16)nodeId);
	ndbout_c("received from node %d", 
		 refToNode(ret1->header.theSendersBlockRef));
	delete ret1;
	total --;
      } while(total > 0);
    } else {
      print_help();
    }
  }
  ndbout << "Exiting" << endl;
};