Esempio n. 1
0
void TableTailer::waitForEvents() {
    NdbEventOperation* op;
    LOG_INFO("create EventOperation for [" << mEventName << "]");
    if ((op = mNdbConnection->createEventOperation(mEventName.c_str())) == NULL)
        LOG_NDB_API_ERROR(mNdbConnection->getNdbError());

    NdbRecAttr * recAttr[mTable.mNoColumns];
    NdbRecAttr * recAttrPre[mTable.mNoColumns];

    // primary keys should always be a part of the result
    for (int i = 0; i < mTable.mNoColumns; i++) {
        recAttr[i] = op->getValue(mTable.mColumnNames[i].c_str());
        recAttrPre[i] = op->getPreValue(mTable.mColumnNames[i].c_str());
    }

    LOG_INFO("Execute");
    // This starts changes to "start flowing"
    if (op->execute())
        LOG_NDB_API_ERROR(op->getNdbError());
    while (true) {
        int r = mNdbConnection->pollEvents2(mPollMaxTimeToWait);
        if (r > 0) {
            while ((op = mNdbConnection->nextEvent2())) {
                NdbDictionary::Event::TableEvent event = op->getEventType2();
                if(event != NdbDictionary::Event::TE_EMPTY){
                    LOG_TRACE("Got Event [" << event << ","  << getEventName(event) << "] Epoch " << op->getEpoch());
                }
                switch (event) {
                    case NdbDictionary::Event::TE_INSERT:
                    case NdbDictionary::Event::TE_DELETE:
                    case NdbDictionary::Event::TE_UPDATE:
                        handleEvent(event, recAttrPre, recAttr);
                        break;
                    default:
                        break;
                }

            }
        }
        //boost::this_thread::sleep(boost::posix_time::milliseconds(mPollMaxTimeToWait));
    }

}
Esempio n. 2
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;
#ifndef DBUG_OFF
  opt_debug= "d:t:O,/tmp/ndb_desc.trace";
#endif
  if ((ho_error=handle_options(&argc, &argv, my_long_options, 
			       ndb_std_get_one_option)))
    return NDBT_ProgramExit(NDBT_WRONGARGS);

  for (int i = 0; i<_loop; i++)
  {
    Ndb_cluster_connection con(opt_connect_str);
    if(con.connect(12, 5, 1) != 0)
    {
      ndbout << "Unable to connect to management server." << endl;
      return NDBT_ProgramExit(NDBT_FAILED);
    }
    if (con.wait_until_ready(30,30) != 0)
    {
      ndbout << "Cluster nodes not ready in 30 seconds." << endl;
      return NDBT_ProgramExit(NDBT_FAILED);
    }
    
    Ndb MyNdb(&con, "TEST_DB");
    if(MyNdb.init() != 0){
      ERR(MyNdb.getNdbError());
      return NDBT_ProgramExit(NDBT_FAILED);
    }

    Vector<NdbEventOperation*> ops;
    const NdbDictionary::Dictionary * dict= MyNdb.getDictionary();
    for (int j = 0; j < argc; j++) 
    {
      const NdbDictionary::Table * pTab = dict->getTable(argv[j]);
      if (pTab == 0)
      {
        ndbout_c("Failed to retreive table: \"%s\"", argv[j]);
      }

      BaseString tmp;
      tmp.appfmt("EV-%s", argv[j]);
      NdbEventOperation* pOp = MyNdb.createEventOperation(tmp.c_str());
      if ( pOp == NULL ) 
      {
        ndbout << "Event operation creation failed: " << 
          MyNdb.getNdbError() << endl;
        return NDBT_ProgramExit(NDBT_FAILED);
      }

      for (int a = 0; a < pTab->getNoOfColumns(); a++) 
      {
        pOp->getValue(pTab->getColumn(a)->getName());
        pOp->getPreValue(pTab->getColumn(a)->getName());
      }
      
      if (pOp->execute())
      { 
        ndbout << "operation execution failed: " << pOp->getNdbError()
               << endl;
        return NDBT_ProgramExit(NDBT_FAILED);
      }
      ops.push_back(pOp);
    }
    
    if (_sleep)
    {
      NdbSleep_MilliSleep(10 + rand() % _sleep);
    }
    
    for (Uint32 i = 0; i<ops.size(); i++)
    {
      switch(_drop){
      case 0:
        break;
      do_drop:
      case 1:
        if (MyNdb.dropEventOperation(ops[i]))
        {
          ndbout << "drop event operation failed " 
                 << MyNdb.getNdbError() << endl;
          return NDBT_ProgramExit(NDBT_FAILED);
        }
        break;
      default:
        if ((rand() % 100) > 50)
          goto do_drop;
      }
    }
  }
  
  return NDBT_ProgramExit(NDBT_OK);
}
Esempio n. 3
0
int runEventApplier(NDBT_Context* ctx, NDBT_Step* step)
{
  DBUG_ENTER("runEventApplier");

  int records = ctx->getNumRecords();
  int loops = ctx->getNumLoops();
  const NdbDictionary::Table * table= ctx->getTab();
  char buf[1024];

  sprintf(buf, "%s_SHADOW", table->getName());
  const NdbDictionary::Table * table_shadow;
  if ((table_shadow = GETNDB(step)->getDictionary()->getTable(buf)) == 0)
  {
    g_err << "Unable to get table " << buf << endl;
    DBUG_RETURN(NDBT_FAILED);
  }

  sprintf(buf, "%s_EVENT", table->getName());
  NdbEventOperation    *pOp;
  pOp = GETNDB(step)->createEventOperation(buf, 10*records);
  if ( pOp == NULL ) {
    g_err << "Event operation creation failed on %s" << buf << endl;
    DBUG_RETURN(NDBT_FAILED);
  }

  int i;
  int n_columns= table->getNoOfColumns();
  NdbRecAttr* recAttr[1024];
  NdbRecAttr* recAttrPre[1024];
  for (i = 0; i < n_columns; i++) {
    recAttr[i]    = pOp->getValue(table->getColumn(i)->getName());
    recAttrPre[i] = pOp->getPreValue(table->getColumn(i)->getName());
  }

  if (pOp->execute()) { // This starts changes to "start flowing"
    g_err << "execute operation execution failed: \n";
    g_err << pOp->getNdbError().code << " "
	  << pOp->getNdbError().message << endl;
    DBUG_RETURN(NDBT_FAILED);
  }

  int r= 0;
  int res;
  while (r < 10*records){
    //printf("now waiting for event...\n");
    res= GETNDB(step)->pollEvents(1000); // wait for event or 1000 ms
    if (res <= 0)
    {
      ndbout_c("********************");
      continue;
    }

    //printf("got data! %d\n", r);
    int overrun= 0;
    while (pOp->next(&overrun) > 0)
    {
      if (overrun)
      {
	g_err << "buffer overrun\n";
	DBUG_RETURN(NDBT_FAILED);
      }
      r++;

      Uint32 gci= pOp->getGCI();

      if (!pOp->isConsistent()) {
	g_err << "A node failure has occured and events might be missing\n";
	DBUG_RETURN(NDBT_FAILED);
      }

      int noRetries= 0;
      do
      {
	NdbTransaction *trans= GETNDB(step)->startTransaction();
	if (trans == 0)
	{
	  g_err << "startTransaction failed "
		<< GETNDB(step)->getNdbError().code << " "
		<< GETNDB(step)->getNdbError().message << endl;
	  DBUG_RETURN(NDBT_FAILED);
	}
	
	NdbOperation *op= trans->getNdbOperation(table_shadow);
	if (op == 0)
	{
	  g_err << "getNdbOperation failed "
		<< trans->getNdbError().code << " "
		<< trans->getNdbError().message << endl;
	  DBUG_RETURN(NDBT_FAILED);
	}
	
	switch (pOp->getEventType()) {
	case NdbDictionary::Event::TE_INSERT:
	  if (op->insertTuple())
	  {
	    g_err << "insertTuple "
		  << op->getNdbError().code << " "
		  << op->getNdbError().message << endl;
	    DBUG_RETURN(NDBT_FAILED);
	  }
	  break;
	case NdbDictionary::Event::TE_DELETE:
	  if (op->deleteTuple())
	  {
	    g_err << "deleteTuple "
		  << op->getNdbError().code << " "
		  << op->getNdbError().message << endl;
	    DBUG_RETURN(NDBT_FAILED);
	  }
	  break;
	case NdbDictionary::Event::TE_UPDATE:
	  if (op->updateTuple())
	  {
	    g_err << "updateTuple "
		  << op->getNdbError().code << " "
		  << op->getNdbError().message << endl;
	    DBUG_RETURN(NDBT_FAILED);
	  }
	  break;
	default:
	  abort();
	}

	for (i= 0; i < n_columns; i++)
	{
	  if (recAttr[i]->isNULL())
	  {
	    if (table->getColumn(i)->getPrimaryKey())
	    {
	      g_err << "internal error: primary key isNull()="
		    << recAttr[i]->isNULL() << endl;
	      DBUG_RETURN(NDBT_FAILED);
	    }
	    switch (pOp->getEventType()) {
	    case NdbDictionary::Event::TE_INSERT:
	      if (recAttr[i]->isNULL() < 0)
	      {
		g_err << "internal error: missing value for insert\n";
		DBUG_RETURN(NDBT_FAILED);
	      }
	      break;
	    case NdbDictionary::Event::TE_DELETE:
	      break;
	    case NdbDictionary::Event::TE_UPDATE:
	      break;
	    default:
	      abort();
	    }
	  }
	  if (table->getColumn(i)->getPrimaryKey() &&
	      op->equal(i,recAttr[i]->aRef()))
	  {
	    g_err << "equal " << i << " "
		  << op->getNdbError().code << " "
		  << op->getNdbError().message << endl;
	    DBUG_RETURN(NDBT_FAILED);
	  }
	}
	
	switch (pOp->getEventType()) {
	case NdbDictionary::Event::TE_INSERT:
	  for (i= 0; i < n_columns; i++)
	  {
	    if (!table->getColumn(i)->getPrimaryKey() &&
		op->setValue(i,recAttr[i]->isNULL() ? 0:recAttr[i]->aRef()))
	    {
	      g_err << "setValue(insert) " << i << " "
		    << op->getNdbError().code << " "
		    << op->getNdbError().message << endl;
	      DBUG_RETURN(NDBT_FAILED);
	    }
	  }
	  break;
	case NdbDictionary::Event::TE_DELETE:
	  break;
	case NdbDictionary::Event::TE_UPDATE:
	  for (i= 0; i < n_columns; i++)
	  {
	    if (!table->getColumn(i)->getPrimaryKey() &&
		recAttr[i]->isNULL() >= 0 &&
		op->setValue(i,recAttr[i]->isNULL() ? 0:recAttr[i]->aRef()))
	    {
	      g_err << "setValue(update) " << i << " "
		    << op->getNdbError().code << " "
		    << op->getNdbError().message << endl;
	      DBUG_RETURN(NDBT_FAILED);
	    }
	  }
	  break;
	case NdbDictionary::Event::TE_ALL:
	  abort();
	}
	if (trans->execute(Commit) == 0)
	{
	  trans->close();
	  // everything ok
	  break;
	}
	if (noRetries++ == 10 ||
	    trans->getNdbError().status != NdbError::TemporaryError)
	{
	  g_err << "execute " << r << " failed "
		<< trans->getNdbError().code << " "
		<< trans->getNdbError().message << endl;
	  trans->close();
	  DBUG_RETURN(NDBT_FAILED);
	}
	trans->close();
	NdbSleep_MilliSleep(100); // sleep before retying
      } while(1);
    }
  }

  if (GETNDB(step)->dropEventOperation(pOp)) {
    g_err << "dropEventOperation execution failed "
	  << GETNDB(step)->getNdbError().code << " "
	  << GETNDB(step)->getNdbError().message << endl;
    DBUG_RETURN(NDBT_FAILED);
  }
  
  DBUG_RETURN(NDBT_OK);
}
int main(int argc, char** argv)
{
  if (argc < 3)
  {
    std::cout << "Arguments are <connect_string cluster> <timeout> [m(merge events)|d(debug)].\n";
    exit(-1);
  }
  const char *connectstring = argv[1];
  int timeout = atoi(argv[2]);
  ndb_init();
  bool merge_events = argc > 3 && strchr(argv[3], 'm') != 0;
#ifdef VM_TRACE
  bool dbug = argc > 3 && strchr(argv[3], 'd') != 0;
  if (dbug) DBUG_PUSH("d:t:");
  if (dbug) putenv("API_SIGNAL_LOG=-");
#endif

  Ndb_cluster_connection *cluster_connection=
    new Ndb_cluster_connection(connectstring); // Object representing the cluster

  int r= cluster_connection->connect(5 /* retries               */,
				     3 /* delay between retries */,
				     1 /* verbose               */);
  if (r > 0)
  {
    std::cout
      << "Cluster connect failed, possibly resolved with more retries.\n";
    exit(-1);
  }
  else if (r < 0)
  {
    std::cout
      << "Cluster connect failed.\n";
    exit(-1);
  }
					   
  if (cluster_connection->wait_until_ready(30,30))
  {
    std::cout << "Cluster was not ready within 30 secs." << std::endl;
    exit(-1);
  }

  Ndb* myNdb= new Ndb(cluster_connection,
		      "TEST_DB");  // Object representing the database

  if (myNdb->init() == -1) APIERROR(myNdb->getNdbError());

  const char *eventName= "CHNG_IN_t0";
  const char *eventTableName= "t0";
  const int noEventColumnName= 5;
  const char *eventColumnName[noEventColumnName]=
    {"c0",
     "c1",
     "c2",
     "c3",
     "c4"
    };
  
  // Create events
  myCreateEvent(myNdb,
		eventName,
		eventTableName,
		eventColumnName,
		noEventColumnName,
                merge_events);

  // Normal values and blobs are unfortunately handled differently..
  typedef union { NdbRecAttr* ra; NdbBlob* bh; } RA_BH;

  int i, j, k, l;
  j = 0;
  while (j < timeout) {

    // Start "transaction" for handling events
    NdbEventOperation* op;
    printf("create EventOperation\n");
    if ((op = myNdb->createEventOperation(eventName)) == NULL)
      APIERROR(myNdb->getNdbError());
    op->mergeEvents(merge_events);

    printf("get values\n");
    RA_BH recAttr[noEventColumnName];
    RA_BH recAttrPre[noEventColumnName];
    // primary keys should always be a part of the result
    for (i = 0; i < noEventColumnName; i++) {
      if (i < 4) {
        recAttr[i].ra    = op->getValue(eventColumnName[i]);
        recAttrPre[i].ra = op->getPreValue(eventColumnName[i]);
      } else if (merge_events) {
        recAttr[i].bh    = op->getBlobHandle(eventColumnName[i]);
        recAttrPre[i].bh = op->getPreBlobHandle(eventColumnName[i]);
      }
    }

    // set up the callbacks
    printf("execute\n");
    // This starts changes to "start flowing"
    if (op->execute())
      APIERROR(op->getNdbError());

    NdbEventOperation* the_op = op;

    i= 0;
    while (i < timeout) {
      // printf("now waiting for event...\n");
      int r = myNdb->pollEvents(1000); // wait for event or 1000 ms
      if (r > 0) {
	// printf("got data! %d\n", r);
	while ((op= myNdb->nextEvent())) {
          assert(the_op == op);
	  i++;
	  switch (op->getEventType()) {
	  case NdbDictionary::Event::TE_INSERT:
	    printf("%u INSERT", i);
	    break;
	  case NdbDictionary::Event::TE_DELETE:
	    printf("%u DELETE", i);
	    break;
	  case NdbDictionary::Event::TE_UPDATE:
	    printf("%u UPDATE", i);
	    break;
	  default:
	    abort(); // should not happen
	  }
          printf(" gci=%d\n", (int)op->getGCI());
          for (k = 0; k <= 1; k++) {
            printf(k == 0 ? "post: " : "pre : ");
            for (l = 0; l < noEventColumnName; l++) {
              if (l < 4) {
                NdbRecAttr* ra = k == 0 ? recAttr[l].ra : recAttrPre[l].ra;
                if (ra->isNULL() >= 0) { // we have a value
                  if (ra->isNULL() == 0) { // we have a non-null value
                    if (l < 2)
                      printf("%-5u", ra->u_32_value());
                    else
                      printf("%-5.4s", ra->aRef());
                  } else
                    printf("%-5s", "NULL");
                } else
                  printf("%-5s", "-"); // no value
              } else if (merge_events) {
                int isNull;
                NdbBlob* bh = k == 0 ? recAttr[l].bh : recAttrPre[l].bh;
                bh->getDefined(isNull);
                if (isNull >= 0) { // we have a value
                  if (! isNull) { // we have a non-null value
                    Uint64 length = 0;
                    bh->getLength(length);
                    // read into buffer
                    unsigned char* buf = new unsigned char [length];
                    memset(buf, 'X', length);
                    Uint32 n = length;
                    bh->readData(buf, n); // n is in/out
                    assert(n == length);
                    // pretty-print
                    bool first = true;
                    Uint32 i = 0;
                    while (i < n) {
                      unsigned char c = buf[i++];
                      Uint32 m = 1;
                      while (i < n && buf[i] == c)
                        i++, m++;
                      if (! first)
                        printf("+");
                      printf("%u%c", m, c);
                      first = false;
                    }
                    printf("[%u]", n);
                    delete [] buf;
                  } else
                    printf("%-5s", "NULL");
                } else
                  printf("%-5s", "-"); // no value
              }
            }
            printf("\n");
          }
	}
      } else
	printf("timed out (%i)\n", timeout);
    }
    // don't want to listen to events anymore
    if (myNdb->dropEventOperation(the_op)) APIERROR(myNdb->getNdbError());
    the_op = 0;

    j++;
  }

  {
    NdbDictionary::Dictionary *myDict = myNdb->getDictionary();
    if (!myDict) APIERROR(myNdb->getNdbError());
    // remove event from database
    if (myDict->dropEvent(eventName)) APIERROR(myDict->getNdbError());
  }

  delete myNdb;
  delete cluster_connection;
  ndb_end(0);
  return 0;
}