void getRestartAction(Uint32 action, BaseString &str)
{
  if (action == 0)
    return;
  str.appfmt(", restarting");
  if (action & 2)
    str.appfmt(", no start");
  if (action & 4)
    str.appfmt(", initial");
}
Beispiel #2
0
int
AtrtClient::writeCommand(AtrtCommandType _type,
                         const Properties& args){
  if (!isConnected())
    return false;

  BaseString sql;
  sql.assfmt("INSERT  command ( ");

  const char* name;
  {
    Properties::Iterator iter(&args);
    while((name= iter.next())){
      sql.appfmt("%s, ", name);
    }
  }

  sql.appfmt(" state, cmd) VALUES (");

  {
    Properties::Iterator iter(&args);
    while((name= iter.next())){
      PropertiesType t;
      Uint32 val_i;
      BaseString val_s;
      args.getTypeOf(name, &t);
      switch(t) {
      case PropertiesType_Uint32:
        args.get(name, &val_i);
        sql.appfmt("%d, ", val_i);
        break;
      case PropertiesType_char:
        args.get(name, val_s);
        sql.appfmt("'%s', ", val_s.c_str());
        break;
      default:
        assert(false);
        break;
      }
    }
  }

  sql.appfmt("'new', %d)", _type);
  if (!doQuery(sql)){
    return -1;
  }

  return mysql_insert_id(m_mysql);
}
Beispiel #3
0
BaseString replace_tags(const char* str)
{
  BaseString result(str);
  for (size_t i = 0; i < num_replaces; i++)
  {
    Vector<BaseString> parts;
    const char* p = result.c_str();
    const char* tag = replaces[i].tag;

    /* Split on <tag> */
    const char* first;
    while((first = strstr(p, tag)))
    {
      BaseString part;
      part.assign(p, first - p);
      parts.push_back(part);
      p = first + strlen(tag);
    }
    parts.push_back(p);

    /* Put back together */
    BaseString res;
    const char* separator = "";
    for (unsigned j = 0; j < parts.size(); j++)
    {
      res.appfmt("%s%s", separator, parts[j].c_str());
      separator = replaces[i].string;
    }

    /* Save result from this loop */
    result = res;
  }
  return result;
}
Beispiel #4
0
 BaseString str() const {
   BaseString tmp;
   const char* sep="";
   for (unsigned i = 0; i<m_vec.size(); i++)
   {
     tmp.appfmt("%s%u", sep, m_vec[i]);
     sep=",";
   }
   return tmp;
 }
Beispiel #5
0
static void fill_blocks(BaseString& sql)
{
  const char* separator = "";
  for (BlockNumber i = 0; i < NO_OF_BLOCK_NAMES; i++)
  {
    const BlockName& bn = BlockNames[i];
    sql.appfmt("%s(%u, \"%s\")", separator, bn.number, bn.name);
    separator = ", ";
  }
}
Beispiel #6
0
static void fill_dblqh_tcconnect_state(BaseString& sql)
{
  const char* separator = "";
  for (unsigned i = 0; g_dblqh_tcconnect_state_desc[i].name != 0; i++)
  {
    sql.appfmt("%s(%u, \"%s\", \"%s\", \"%s\")",
               separator,
               g_dblqh_tcconnect_state_desc[i].value,
               g_dblqh_tcconnect_state_desc[i].name,
               g_dblqh_tcconnect_state_desc[i].friendly_name,
               g_dblqh_tcconnect_state_desc[i].description);
    separator = ", ";
  }
}
Beispiel #7
0
static BaseString path(const char* first, ...)
{
  BaseString path;
  path.assign(first);

  const char* str;
  va_list args;
  va_start(args, first);
  while ((str = va_arg(args, const char*)) != NULL)
  {
    path.appfmt("%s%s", DIR_SEPARATOR, str);
  }
  va_end(args);
  return path;
}
Beispiel #8
0
static void fill_config_params(BaseString& sql)
{
  const char* separator = "";
  const ConfigInfo::ParamInfo* pinfo= NULL;
  ConfigInfo::ParamInfoIter param_iter(g_info,
                                       CFG_SECTION_NODE,
                                       NODE_TYPE_DB);
  while((pinfo= param_iter.next())) {
    if (pinfo->_paramId == 0 || // KEY_INTERNAL
        pinfo->_status != ConfigInfo::CI_USED)
      continue;
    sql.appfmt("%s(%u, \"%s\")", separator, pinfo->_paramId, pinfo->_fname);
    separator = ", ";
  }
}
static
atrt_process*
find(atrt_config& config, int type, const char * name)
{
  BaseString tmp(name);
  Vector<BaseString> src;
  Vector<BaseString> dst;
  tmp.split(src, ".");
  
  if (src.size() != 2)
  {
    return 0;
  }
  atrt_cluster* cluster = 0;
  BaseString cl;
  cl.appfmt(".%s", src[1].c_str());
  for (unsigned i = 0; i<config.m_clusters.size(); i++)
  {
    if (config.m_clusters[i]->m_name == cl)
    {
      cluster = config.m_clusters[i];
      break;
    }
  }   
  
  if (cluster == 0)
  {
    return 0;
  }
  
  int idx = atoi(src[0].c_str()) - 1;
  for (unsigned i = 0; i<cluster->m_processes.size(); i++)
  {
    if (cluster->m_processes[i]->m_type & type)
    {
      if (idx == 0)
	return cluster->m_processes[i];
      else
	idx --;
    }
  }
  
  return 0;
}
Beispiel #10
0
static 
bool 
pr_fix_ndb_connectstring(Properties& props, proc_rule_ctx& ctx, int)
{
  const char * val;
  atrt_cluster& cluster = *ctx.m_cluster;

  if (cluster.m_options.m_features & atrt_options::AO_NDBCLUSTER)
  {
    if (!cluster.m_options.m_loaded.get(ndbcs, &val))
    {
      /**
       * Construct connect string for this cluster
     */
      BaseString str;
      for (unsigned i = 0; i<cluster.m_processes.size(); i++)
      {
	atrt_process* tmp = cluster.m_processes[i];
	if (tmp->m_type == atrt_process::AP_NDB_MGMD)
	{
	  if (str.length())
	  {
	    str.append(";");
	  }
	  const char * port;
	  require(tmp->m_options.m_loaded.get("--PortNumber=", &port));
	  str.appfmt("%s:%s", tmp->m_host->m_hostname.c_str(), port);
	}
      }
      cluster.m_options.m_loaded.put(ndbcs, str.c_str());
      cluster.m_options.m_generated.put(ndbcs, str.c_str());
      cluster.m_options.m_loaded.get(ndbcs, &val);
    }
    
    for (unsigned i = 0; i<cluster.m_processes.size(); i++)
    {
      cluster.m_processes[i]->m_proc.m_env.appfmt(" NDB_CONNECTSTRING=%s", 
						  val);
    }
  }
  return true;
}
Beispiel #11
0
void
MgmApiSession::listen_event(Parser<MgmApiSession>::Context & ctx,
			    Properties const & args) {
  Uint32 parsable= 0;
  BaseString node, param, value;
  args.get("node", node);
  args.get("filter", param);
  args.get("parsable", &parsable);

  int result = 0;
  BaseString msg;

  Ndb_mgmd_event_service::Event_listener le;
  le.m_parsable = parsable;
  le.m_socket = m_socket;

  Vector<BaseString> list;
  param.trim();
  param.split(list, " ,");
  for(size_t i = 0; i<list.size(); i++){
    Vector<BaseString> spec;
    list[i].trim();
    list[i].split(spec, "=:");
    if(spec.size() != 2){
      msg.appfmt("Invalid filter specification: >%s< >%s< %d", 
		 param.c_str(), list[i].c_str(), spec.size());
      result = -1;
      goto done;
    }

    spec[0].trim().ndb_toupper();
    int category = ndb_mgm_match_event_category(spec[0].c_str());
    if(category == NDB_MGM_ILLEGAL_EVENT_CATEGORY){
      category = atoi(spec[0].c_str());
      if(category < NDB_MGM_MIN_EVENT_CATEGORY ||
	 category > NDB_MGM_MAX_EVENT_CATEGORY){
	msg.appfmt("Unknown category: >%s<", spec[0].c_str());
	result = -1;
	goto done;
      }
    }
    
    int level = atoi(spec[1].c_str());
    if(level < 0 || level > NDB_MGM_MAX_LOGLEVEL){
      msg.appfmt("Invalid level: >%s<", spec[1].c_str());
      result = -1;
      goto done;
    }
    category -= CFG_MIN_LOGLEVEL;
    le.m_logLevel.setLogLevel((LogLevel::EventCategory)category, level);
  }
  
  if(list.size() == 0){
    msg.appfmt("Empty filter specification");
    result = -1;
    goto done;
  }

done:
  m_output->println("listen event");
  m_output->println("result: %d", result);
  if(result != 0)
    m_output->println("msg: %s", msg.c_str());
  m_output->println("");

  if(result==0)
  {
    m_mgmsrv.m_event_listner.add_listener(le);
    m_stop = true;
    m_socket = NDB_INVALID_SOCKET;
  }
}
Beispiel #12
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);
}
Beispiel #13
0
int main(int argc, char** argv){

  BaseString sql;
  if ((handle_options(&argc, &argv, my_long_options, NULL)))
    return 2;

  printf("#\n");
  printf("# SQL commands for creating the tables in MySQL Server which\n");
  printf("# are used by the NDBINFO storage engine to access system\n");
  printf("# information and statistics from MySQL Cluster\n");
  printf("#\n");

  printf("# Only create objects if NDBINFO is supported\n");
  printf("SELECT @have_ndbinfo:= COUNT(*) FROM "
                  "information_schema.engines WHERE engine='NDBINFO' "
                  "AND support IN ('YES', 'DEFAULT');\n\n");

  printf("# Only create objects if version >= 7.1\n");
  sql.assfmt("SELECT @have_ndbinfo:="
             " (@@ndbinfo_version >= (7 << 16) | (1 << 8)) || @ndbinfo_skip_version_check");
  print_conditional_sql(sql);

  sql.assfmt("CREATE DATABASE IF NOT EXISTS `%s`", opt_ndbinfo_db);
  print_conditional_sql(sql);

  printf("# Set NDBINFO in offline mode during (re)create of tables\n");
  printf("# and views to avoid errors caused by no such table or\n");
  printf("# different table definition in NDB\n");
  sql.assfmt("SET @@global.ndbinfo_offline=TRUE");
  print_conditional_sql(sql);

  {
    // Lookup tables which existed in other engine before
    // they were hardcoded into ha_ndbinfo. Drop to allow
    // the new ndbinfo tables(and in some cases views) to
    // be created
    const char* old_lookups[] =
    {
      "blocks",
      "dict_obj_types",
      "config_params",
      "ndb$dbtc_apiconnect_state",
      "ndb$dblqh_tcconnect_state"
    };
    printf("# Drop obsolete lookups in %s\n", opt_ndbinfo_db);
    for (size_t i = 0; i < sizeof(old_lookups)/sizeof(old_lookups[0]); i++)
    {
      sql.assfmt("DROP TABLE IF EXISTS `%s`.`%s`",
                 opt_ndbinfo_db, old_lookups[i]);
      print_conditional_sql(sql);
    }
  }

  printf("# Drop any old views in %s\n", opt_ndbinfo_db);
  for (size_t i = 0; i < num_views; i++)
  {
    sql.assfmt("DROP VIEW IF EXISTS `%s`.`%s`",
               opt_ndbinfo_db, views[i].name);
    print_conditional_sql(sql);
  }

  printf("# Drop any old lookup tables in %s\n", opt_ndbinfo_db);
  for (size_t i = 0; i < num_lookups; i++)
  {
    BaseString table_name = replace_tags(lookups[i].name);

    sql.assfmt("DROP TABLE IF EXISTS `%s`.`%s`",
               opt_ndbinfo_db, table_name.c_str());
    print_conditional_sql(sql);
  }

  for (int i = 0; i < Ndbinfo::getNumTables(); i++)
  {
    const Ndbinfo::Table& table = Ndbinfo::getTable(i);

    printf("# %s.%s%s\n",
            opt_ndbinfo_db, opt_table_prefix, table.m.name);

    /* Drop the table if it exists */
    sql.assfmt("DROP TABLE IF EXISTS `%s`.`%s%s`",
               opt_ndbinfo_db, opt_table_prefix, table.m.name);
    print_conditional_sql(sql);

    /* Create the table */
    sql.assfmt("CREATE TABLE `%s`.`%s%s` (",
               opt_ndbinfo_db, opt_table_prefix, table.m.name);

    const char* separator = "";
    for(int j = 0; j < table.m.ncols ; j++)
    {
      const Ndbinfo::Column& col = table.col[j];

      sql.appfmt("%s", separator);
      separator = ",";

      sql.appfmt("`%s` ", col.name);

      switch(col.coltype)
      {
      case Ndbinfo::Number:
        sql.appfmt("INT UNSIGNED");
        break;
      case Ndbinfo:: Number64:
        sql.appfmt("BIGINT UNSIGNED");
        break;
      case Ndbinfo::String:
        sql.appfmt("VARCHAR(512)");
        break;
      default:
        fprintf(stderr, "unknown coltype: %d\n", col.coltype);
        abort();
        break;
      }

      if (col.comment[0] != '\0')
        sql.appfmt(" COMMENT \"%s\"", col.comment);

    }

    sql.appfmt(") COMMENT=\"%s\" ENGINE=NDBINFO", table.m.comment);

    print_conditional_sql(sql);

  }

  for (size_t i = 0; i < num_lookups; i++)
  {
    lookup l = lookups[i];
    BaseString table_name = replace_tags(l.name);
    printf("# %s.%s\n", opt_ndbinfo_db, table_name.c_str());

    /* Drop the table if it exists */
    sql.assfmt("DROP TABLE IF EXISTS `%s`.`%s`",
               opt_ndbinfo_db, table_name.c_str());
    print_conditional_sql(sql);

    /* Create lookup table */
    sql.assfmt("CREATE TABLE `%s`.`%s` (%s) ENGINE=NDBINFO",
               opt_ndbinfo_db, table_name.c_str(), l.columns);
    print_conditional_sql(sql);
  }

  for (size_t i = 0; i < num_views; i++)
  {
    view v = views[i];

    printf("# %s.%s\n", opt_ndbinfo_db, v.name);

    BaseString view_sql = replace_tags(v.sql);

    /* Create or replace the view */
    BaseString sql;
    sql.assfmt("CREATE OR REPLACE DEFINER=`root`@`localhost` "
               "SQL SECURITY INVOKER VIEW `%s`.`%s` AS %s",
               opt_ndbinfo_db, v.name, view_sql.c_str());
    print_conditional_sql(sql);
  }

  printf("# Finally turn off offline mode\n");
  sql.assfmt("SET @@global.ndbinfo_offline=FALSE");
  print_conditional_sql(sql);

  return 0;
}
Beispiel #14
0
int main(int argc, char** argv){

  BaseString sql;
  if ((handle_options(&argc, &argv, my_long_options, NULL)))
    return 2;

  printf("#\n");
  printf("# SQL commands for creating the tables in MySQL Server which\n");
  printf("# are used by the NDBINFO storage engine to access system\n");
  printf("# information and statistics from MySQL Cluster\n");
  printf("#\n");

  printf("# Only create objects if NDBINFO is supported\n");
  printf("SELECT @have_ndbinfo:= COUNT(*) FROM "
                  "information_schema.engines WHERE engine='NDBINFO' "
                  "AND support IN ('YES', 'DEFAULT');\n\n");

  printf("# Only create objects if version >= 7.1\n");
  sql.assfmt("SELECT @have_ndbinfo:="
             " (@@ndbinfo_version >= (7 << 16) | (1 << 8)) || @ndbinfo_skip_version_check");
  print_conditional_sql(sql);

  printf("# Only create objects if ndbinfo namespace is free\n");
  sql.assfmt("SET @@ndbinfo_show_hidden=TRUE");
  print_conditional_sql(sql);
  sql.assfmt("SELECT @have_ndbinfo:= COUNT(*) = 0"
             " FROM information_schema.tables WHERE"
             " table_schema = @@ndbinfo_database AND"
             " LEFT(table_name, LENGTH(@@ndbinfo_table_prefix)) ="
             " @@ndbinfo_table_prefix AND"
             " engine != \"ndbinfo\"");
  print_conditional_sql(sql);
  sql.assfmt("SET @@ndbinfo_show_hidden=default");
  print_conditional_sql(sql);

  sql.assfmt("CREATE DATABASE IF NOT EXISTS `%s`", opt_ndbinfo_db);
  print_conditional_sql(sql);

  printf("# Set NDBINFO in offline mode during (re)create of tables\n");
  printf("# and views to avoid errors caused by no such table or\n");
  printf("# different table definition in NDB\n");
  sql.assfmt("SET @@global.ndbinfo_offline=TRUE");
  print_conditional_sql(sql);

  printf("# Drop any old views in %s\n", opt_ndbinfo_db);
  for (size_t i = 0; i < num_views; i++)
  {
    sql.assfmt("DROP VIEW IF EXISTS `%s`.`%s`",
               opt_ndbinfo_db, views[i].name);
    print_conditional_sql(sql);
  }

  printf("# Drop any old lookup tables in %s\n", opt_ndbinfo_db);
  for (size_t i = 0; i < num_lookups; i++)
  {
    BaseString table_name = replace_tags(lookups[i].name);

    sql.assfmt("DROP TABLE IF EXISTS `%s`.`%s`",
               opt_ndbinfo_db, table_name.c_str());
    print_conditional_sql(sql);
  }

  for (int i = 0; i < Ndbinfo::getNumTables(); i++)
  {
    const Ndbinfo::Table& table = Ndbinfo::getTable(i);

    printf("# %s.%s%s\n",
            opt_ndbinfo_db, opt_table_prefix, table.m.name);

    /* Drop the table if it exists */
    sql.assfmt("DROP TABLE IF EXISTS `%s`.`%s%s`",
               opt_ndbinfo_db, opt_table_prefix, table.m.name);
    print_conditional_sql(sql);

    /* Create the table */
    sql.assfmt("CREATE TABLE `%s`.`%s%s` (",
               opt_ndbinfo_db, opt_table_prefix, table.m.name);

    const char* separator = "";
    for(int j = 0; j < table.m.ncols ; j++)
    {
      const Ndbinfo::Column& col = table.col[j];

      sql.appfmt("%s", separator);
      separator = ",";

      sql.appfmt("`%s` ", col.name);

      switch(col.coltype)
      {
      case Ndbinfo::Number:
        sql.appfmt("INT UNSIGNED");
        break;
      case Ndbinfo:: Number64:
        sql.appfmt("BIGINT UNSIGNED");
        break;
      case Ndbinfo::String:
        sql.appfmt("VARCHAR(512)");
        break;
      default:
        fprintf(stderr, "unknown coltype: %d\n", col.coltype);
        abort();
        break;
      }

      if (col.comment[0] != '\0')
        sql.appfmt(" COMMENT \"%s\"", col.comment);

    }

    sql.appfmt(") COMMENT=\"%s\" ENGINE=NDBINFO", table.m.comment);

    print_conditional_sql(sql);

  }

  for (size_t i = 0; i < num_lookups; i++)
  {
    lookup l = lookups[i];
    BaseString table_name = replace_tags(l.name);
    printf("# %s.%s\n", opt_ndbinfo_db, table_name.c_str());

    /* Create lookup table */
    sql.assfmt("CREATE TABLE `%s`.`%s` (%s)",
               opt_ndbinfo_db, table_name.c_str(), l.columns);
    print_conditional_sql(sql);

    /* Insert data */
    sql.assfmt("INSERT INTO `%s`.`%s` VALUES ",
               opt_ndbinfo_db, table_name.c_str());
    l.fill(sql);
    print_conditional_sql(sql);
  }

  for (size_t i = 0; i < num_views; i++)
  {
    view v = views[i];

    printf("# %s.%s\n", opt_ndbinfo_db, v.name);

    BaseString view_sql = replace_tags(v.sql);

    /* Create or replace the view */
    BaseString sql;
    sql.assfmt("CREATE OR REPLACE DEFINER=`root@localhost` "
               "SQL SECURITY INVOKER VIEW `%s`.`%s` AS %s",
               opt_ndbinfo_db, v.name, view_sql.c_str());
    print_conditional_sql(sql);
  }

  printf("# Finally turn off offline mode\n");
  sql.assfmt("SET @@global.ndbinfo_offline=FALSE");
  print_conditional_sql(sql);

  return 0;
}
Beispiel #15
0
int 
main(int argc, const char** argv){
  ndb_init();

  
  int _help = 0;
  const char* db = 0;
  const char* connectstring1 = 0;
  const char* connectstring2 = 0;

  struct getargs args[] = {
    { "connectstring1", 'c',
      arg_string, &connectstring1, "connectstring1", "" },
    { "connectstring2", 'C',
      arg_string, &connectstring2, "connectstring2", "" },
    { "database", 'd', arg_string, &db, "Database", "" },
    { "usage", '?', arg_flag, &_help, "Print help", "" }
  };
  int num_args = sizeof(args) / sizeof(args[0]);
  int optind = 0, i;
  char desc[] = 
    "<tabname>+ \nThis program listen to events on specified tables\n";
  
  if(getarg(args, num_args, argc, argv, &optind) ||
     argv[optind] == NULL || _help) {
    arg_printusage(args, num_args, argv[0], desc);
    return NDBT_ProgramExit(NDBT_WRONGARGS);
  }

  // Connect to Ndb
  Ndb_cluster_connection con(connectstring1);
  if(con.connect(12, 5, 1) != 0)
  {
    return NDBT_ProgramExit(NDBT_FAILED);
  }
  Ndb MyNdb( &con, db ? db : "TEST_DB" );

  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;

  Ndb_cluster_connection *con2 = NULL;
  Ndb *ndb2 =  NULL;
  if (connectstring2)
  {
    con2 = new Ndb_cluster_connection(connectstring2);

    if(con2->connect(12, 5, 1) != 0)
    {
      return NDBT_ProgramExit(NDBT_FAILED);
    }
    ndb2 = new Ndb( con2, db ? db : "TEST_DB" );

    if(ndb2->init() != 0){
      ERR(ndb2->getNdbError());
      return NDBT_ProgramExit(NDBT_FAILED);
    }

    // Connect to Ndb and wait for it to become ready
    while(ndb2->waitUntilReady() != 0)
      ndbout << "Waiting for ndb to become ready..." << endl;
  }

  int result = 0;
  
  NdbDictionary::Dictionary *myDict = MyNdb.getDictionary();
  Vector<NdbDictionary::Event*> events;
  Vector<NdbEventOperation*> event_ops;
  int sz = 0;
  for(i= optind; i<argc; i++)
  {
    const NdbDictionary::Table* table= myDict->getTable(argv[i]);
    if(!table)
    {
      ndbout_c("Could not find table: %s, skipping", argv[i]);
      continue;
    }

    BaseString name;
    name.appfmt("EV-%s", argv[i]);
    NdbDictionary::Event *myEvent= new NdbDictionary::Event(name.c_str());
    myEvent->setTable(table->getName());
    myEvent->addTableEvent(NdbDictionary::Event::TE_ALL); 
    for(int a = 0; a < table->getNoOfColumns(); a++){
      myEvent->addEventColumn(a);
    }

    if (myDict->createEvent(* myEvent))
    {
      if(myDict->getNdbError().classification == NdbError::SchemaObjectExists) 
      {
	g_info << "Event creation failed event exists. Removing...\n";
	if (myDict->dropEvent(name.c_str()))
	{
	  g_err << "Failed to drop event: " << myDict->getNdbError() << endl;
	  result = 1;
	  goto end;
	}
	// try again
	if (myDict->createEvent(* myEvent)) 
	{
	  g_err << "Failed to create event: " << myDict->getNdbError() << endl;
	  result = 1;
	  goto end;
	}
      }
      else
      {
	g_err << "Failed to create event: " << myDict->getNdbError() << endl;
	result = 1;
	goto end;
      }
    }
    
    events.push_back(myEvent);

    NdbEventOperation* pOp = MyNdb.createEventOperation(name.c_str());
    if ( pOp == NULL ) {
      g_err << "Event operation creation failed" << endl;
      result = 1;
      goto end;
    }

    event_values.push_back(Vector<NdbRecAttr *>());
    event_pre_values.push_back(Vector<NdbRecAttr *>());
    for (int a = 0; a < table->getNoOfColumns(); a++) 
    {
      event_values[sz].
        push_back(pOp->getValue(table->getColumn(a)->getName()));
      event_pre_values[sz].
        push_back(pOp->getPreValue(table->getColumn(a)->getName()));
    }
    event_ops.push_back(pOp);
    {
      struct Table_info ti;
      ti.id = sz;
      table_infos.push_back(ti);
    }
    pOp->setCustomData((void *)&table_infos[sz]);
    sz++;
  }

  for(i= 0; i<(int)event_ops.size(); i++)
  {
    if (event_ops[i]->execute())
    { 
      g_err << "operation execution failed: " << event_ops[i]->getNdbError()
	    << endl;
      result = 1;
      goto end;
    }
  }

  struct Trans_arg trans_arg;
  while(true)
  {
    while(MyNdb.pollEvents(100) == 0);
    
    NdbEventOperation* pOp= MyNdb.nextEvent();
    while(pOp)
    {
      Uint64 gci= pOp->getGCI();
      Uint64 cnt_i= 0, cnt_u= 0, cnt_d= 0;
      if (ndb2)
        do_begin(ndb2, trans_arg);
      do
      {
	switch(pOp->getEventType())
	{
	case NdbDictionary::Event::TE_INSERT:
	  cnt_i++;
          if (ndb2)
            do_insert(trans_arg, pOp);
	  break;
	case NdbDictionary::Event::TE_DELETE:
	  cnt_d++;
          if (ndb2)
            do_delete(trans_arg, pOp);
	  break;
	case NdbDictionary::Event::TE_UPDATE:
	  cnt_u++;
          if (ndb2)
            do_update(trans_arg, pOp);
	  break;
	case NdbDictionary::Event::TE_CLUSTER_FAILURE:
	  break;
	case NdbDictionary::Event::TE_ALTER:
	  break;
	case NdbDictionary::Event::TE_DROP:
	  break;
	case NdbDictionary::Event::TE_NODE_FAILURE:
	  break;
	case NdbDictionary::Event::TE_SUBSCRIBE:
	case NdbDictionary::Event::TE_UNSUBSCRIBE:
	  break;
	default:
	  /* We should REALLY never get here. */
	  ndbout_c("Error: unknown event type: %u", 
		   (Uint32)pOp->getEventType());
	  abort();
	}
      } while ((pOp= MyNdb.nextEvent()) && gci == pOp->getGCI());
      if (ndb2)
        do_commit(trans_arg);
      ndbout_c("GCI: %lld events: %lld(I) %lld(U) %lld(D)", gci, cnt_i, cnt_u, cnt_d);
    }
  }
end:
  for(i= 0; i<(int)event_ops.size(); i++)
    MyNdb.dropEventOperation(event_ops[i]);

  if (ndb2)
    delete ndb2;
  if (con2)
    delete con2;
  return NDBT_ProgramExit(NDBT_OK);
}