int
Match::eval(const Iter& iter)
{
  Uint32 val32;
  Uint64 val64;
  const char* valc;
  if (iter.get(m_key, &val32) == 0)
  {
    if(atoi(m_value.c_str()) != (int)val32)
      return 0;
  } 
  else if(iter.get(m_key, &val64) == 0)
  {
    if(strtoll(m_value.c_str(), (char **)NULL, 10) != (long long)val64)
      return 0;
  }
  else if(iter.get(m_key, &valc) == 0)
  {
    if(strcmp(m_value.c_str(), valc) != 0)
      return 0;
  }
  else
  {
    return 0;
  }
  return 1;
}
char *
find_bin_path(const char * prefix, const char * exe)
{
  if (exe == 0)
    return 0;

  if (exe[0] == '/')
  {
    /**
     * Trust that path is correct...
     */
    return strdup(exe);
  }

  for (int i = 0; g_search_path[i] != 0; i++)
  {
    BaseString p;
    p.assfmt("%s/%s/%s", prefix, g_search_path[i], exe);
    if (File_class::exists(p.c_str()))
    {
      return strdup(p.c_str());
    }
  }
  return 0;
}
bool
verifySlaveLoad(BaseString &table)
{
  //BaseString  sqlStm;
  BaseString  db;
  unsigned int masterCount = 0;
  unsigned int slaveCount  = 0;
 
  db.assign("TEST_DB");
  //sqlStm.assfmt("SELECT COUNT(*) FROM %s", table);

  //First thing to do is sync slave
  printf("Calling syncSlave\n");
  if(!syncSlaveWithMaster())
  {
    g_err << "Verify Load -> Syncing with slave failed" << endl;
    return false;
  }

  //Now that slave is sync we can verify load
  DbUtil master(db.c_str());

  //Login to Master
  if (!master.connect())
  {
    g_err << "Verify Load -> connect to master failed" << endl;
    return false;
  }

  if((masterCount = master.selectCountTable(table.c_str())) == 0 )
  {
    g_err << "Verify Load -> masterCount == ZERO!" << endl;
    return false;
  }
  
  //Create a DB Object for slave
  DbUtil slave(db.c_str(), ".1.slave");

  //Login to slave
  if (!slave.connect())
  {
    g_err << "Verify Load -> connect to master failed" << endl;
    return false;
  }

  if((slaveCount = slave.selectCountTable(table.c_str())) == 0 )
  {
    g_err << "Verify Load -> slaveCount == ZERO" << endl;
    return false;
  }
  
  if(slaveCount != masterCount)
  {
    g_err << "Verify Load -> Slave Count != Master Count "
          << endl;
    return false;
  }
  return true;
}
Beispiel #4
0
 int update_prefix()
 {
   if (!m_prefix.assfmt("%s%c%s%c", m_dbname.c_str(), table_name_separator,
                        m_schemaname.c_str(), table_name_separator))
   {
     return -1;
   }
   return 0;
 }
Beispiel #5
0
  bool connect(const Properties& config,
               int num_retries = 60, int retry_delay_in_seconds = 1)
  {
    BaseString constr = connectstring(config);
    g_info << "Connecting to " << name() << " @ " << constr.c_str() << endl;

    return m_mgmd_client.connect(constr.c_str(),
                                 num_retries,
                                 retry_delay_in_seconds);
  }
bool
FileLogHandler::setMaxFiles(const BaseString &files) {
  char *end;
  long val = strtol(files.c_str(), &end, 0);
  if(files.c_str() == end || val < 1)
  {
    setErrorStr("Invalid maximum number of files");
    return false;
  }
  m_maxNoFiles = val;

  return true;
}
  NDBT_Workingdir(const char* dirname)
  {
    const char* tmp_path = m_temp.path();
    char* ndbt_tmp = getenv("NDBT_TMP_DIR");
    if (ndbt_tmp)
      tmp_path = ndbt_tmp;
    require(tmp_path);

    m_wd.assfmt("%s%s%s%d", tmp_path, DIR_SEPARATOR, dirname,
                (int)NdbProcess::getpid());
    if (access(m_wd.c_str(), F_OK) == 0)
      NdbDir::remove_recursive(m_wd.c_str());
    if (!NdbDir::create(m_wd.c_str()))
      abort();
  }
  static bool
  create_directories(const char* path, Properties & config)
  {
    Properties::Iterator it(&config);

    while (const char* name = it.next())
    {
      BaseString dir;
      dir.assfmt("%s/%s", path, name);
      printf("Creating %s...\n", dir.c_str());
      if (!NdbDir::create(dir.c_str()))
        return false;
    }
    return true;
  }
Beispiel #9
0
/**
 * Given a SocketClient, creates a NdbMgmHandle, turns it into a transporter
 * and returns the socket.
 */
NDB_SOCKET_TYPE TransporterRegistry::connect_ndb_mgmd(SocketClient *sc)
{
  NdbMgmHandle h= ndb_mgm_create_handle();

  if ( h == NULL )
  {
    return NDB_INVALID_SOCKET;
  }

  /**
   * Set connectstring
   */
  {
    BaseString cs;
    cs.assfmt("%s:%u",sc->get_server_name(),sc->get_port());
    ndb_mgm_set_connectstring(h, cs.c_str());
  }

  if(ndb_mgm_connect(h, 0, 0, 0)<0)
  {
    ndb_mgm_destroy_handle(&h);
    return NDB_INVALID_SOCKET;
  }

  return connect_ndb_mgmd(&h);
}
Beispiel #10
0
void
MgmApiSession::stopAll(Parser<MgmApiSession>::Context &,
                       Properties const &args) {
  int stopped[2] = {0,0};
  Uint32 abort;
  args.get("abort", &abort);

  BaseString stop;
  const char* tostop= "db";
  int ver=1;
  if (args.get("stop", stop))
  {
    tostop= stop.c_str();
    ver= 2;
  }

  int result= 0;
  if(strstr(tostop,"db"))
    result= m_mgmsrv.shutdownDB(&stopped[0], abort != 0);
  if(!result && strstr(tostop,"mgm"))
    result= m_mgmsrv.shutdownMGM(&stopped[1], abort!=0, &m_stopSelf);

  m_output->println("stop reply");
  if(result != 0)
    m_output->println("result: %s", get_error_text(result));
  else
    m_output->println("result: Ok");
  m_output->println("stopped: %d", stopped[0]+stopped[1]);
  if(ver >1)
    m_output->println("disconnect: %d", (m_stopSelf)?1:0);
  m_output->println("");
}
Beispiel #11
0
int
SimpleCpcClient::undefine_process(Uint32 id, Properties& reply){
  const ParserRow_t stop_reply[] = {
    CPC_CMD("undefine process", NULL, ""),
    CPC_ARG("status", Int, Mandatory, ""),
    CPC_ARG("id", Int, Optional, ""),
    CPC_ARG("errormessage", String, Optional, ""),
    
    CPC_END()
  };

  Properties args;
  args.put("id", id);
  
  const Properties* ret = cpc_call("undefine process", args, stop_reply);
  if(ret == 0){
    reply.put("status", (Uint32)0);
    reply.put("errormessage", "unknown error");
    return -1;
  }

  Uint32 status = 0;
  ret->get("status", &status);
  reply.put("status", status);
  if(status != 0) {
    BaseString msg;
    ret->get("errormessage", msg);
    reply.put("errormessage", msg.c_str());
  }

  return status;
}
//*****************************************************************************
inline bool OpenFiles::insert(AsyncFile* file, Uint16 id){
  // Check if file has already been opened
  for (unsigned i = 0; i < m_files.size(); i++){
    if(m_files[i].m_file == NULL)
      continue;

    if(strcmp(m_files[i].m_file->theFileName.c_str(), 
	      file->theFileName.c_str()) == 0)
    {
      BaseString names;
      names.assfmt("open: >%s< existing: >%s<",
		   file->theFileName.c_str(),
		   m_files[i].m_file->theFileName.c_str());
      ERROR_SET(fatal, NDBD_EXIT_AFS_ALREADY_OPEN, names.c_str(),
		"OpenFiles::insert()");    
    }
  }
  
  // Insert the file into vector
  OpenFileItem openFile;
  openFile.m_id = id;
  openFile.m_file = file;
  m_files.push_back(openFile);
  
  return true;
}
int
stressSQL_rep1(NDBT_Context* ctx, NDBT_Step* step)
{
  BaseString sqlStm;

  DbUtil master("TEST_DB");
  int loops = ctx->getNumLoops();
  uint record = 0;

  //Login to Master
  if (!master.connect())
  {
    ctx->stopTest();
    return NDBT_FAILED;
  }

  for (int j= 0; loops == 0 || j < loops; j++)
  {
    record = urandom(ctx->getNumRecords());
    sqlStm.assfmt("UPDATE TEST_DB.rep1 SET c2 = 33.3221 where c1 =  %u", record);
    if(!master.doQuery(sqlStm.c_str()))
    {
      return NDBT_FAILED;
    }
  }
  ctx->stopTest();
  return NDBT_OK;
}
Beispiel #14
0
void
MgmApiSession::setLogLevel(Parser<MgmApiSession>::Context &,
			   Properties const &args) {
  Uint32 node = 0, level = 0, cat;
  BaseString errorString;
  SetLogLevelOrd logLevel;
  logLevel.clear();
  args.get("node", &node);
  args.get("category", &cat);
  args.get("level", &level);

  if(level > NDB_MGM_MAX_LOGLEVEL) {
    m_output->println("set loglevel reply");
    m_output->println("result: Invalid loglevel", errorString.c_str());
    m_output->println("");
    return;
  }

  LogLevel::EventCategory category= 
    (LogLevel::EventCategory)(cat-(int)CFG_MIN_LOGLEVEL);

  {
    LogLevel ll;
    ll.setLogLevel(category,level);
    m_mgmsrv.m_event_listner.update_max_log_level(ll);
  }

  m_output->println("set loglevel reply");
  m_output->println("result: Ok");
  m_output->println("");
}
Beispiel #15
0
bool LocalConfig::readFile(const char * filename, bool &fopenError)
{
  char line[1024];
  
  fopenError = false;
  
  FILE * file = fopen(filename, "r");
  if(file == 0){
    BaseString::snprintf(line, sizeof(line),
	     "Unable to open local config file: %s", filename);
    setError(0, line);
    fopenError = true;
    return false;
  }

  BaseString theString;

  while(fgets(line, sizeof(line), file)){
    BaseString tmp(line);
    tmp.trim(" \t\n\r");
    if(tmp.length() > 0 && tmp.c_str()[0] != '#'){
      theString.append(tmp);
      break;
    }
  }
  while (fgets(line, sizeof(line), file)) {
    BaseString tmp(line);
    tmp.trim(" \t\n\r");
    if(tmp.length() > 0 && tmp.c_str()[0] != '#'){
      theString.append(";");
      theString.append(tmp);
    }
  }
  
  BaseString err;
  bool return_value = parseString(theString.c_str(), err);

  if (!return_value) {
    BaseString tmp;
    tmp.assfmt("Reading %s: %s", filename, err.c_str());
    setError(0, tmp.c_str());
  }

  fclose(file);
  return return_value;
}
bool
FileLogHandler::setFilename(const BaseString &filename) {
  close();
  if(m_pLogFile)
    delete m_pLogFile;
  m_pLogFile = new File_class(filename.c_str(), "a+");
  return open();
}
Beispiel #17
0
int
startPostUpgradeChecks(NDBT_Context* ctx, NDBT_Step* step)
{
    /**
     * This will restart *self* in new version
     */

    BaseString extraArgs;
    if (ctx->getProperty("RestartNoDDL", Uint32(0)))
    {
        /* Ask post-upgrade steps not to perform DDL
         * (e.g. for 6.3->7.0 upgrade)
         */
        extraArgs.append(" --noddl ");
    }

    /**
     * mysql-getopt works so that passing "-n X -n Y" is ok
     *   and is interpreted as "-n Y"
     *
     * so we restart ourselves with testcase-name and "--post-upgrade" appended
     * e.g if testcase is "testUpgrade -n X"
     *     this will restart it as "testUpgrade -n X -n X--post-upgrade"
     */
    BaseString tc;
    tc.assfmt("-n %s--post-upgrade %s",
              ctx->getCase()->getName(),
              extraArgs.c_str());

    ndbout << "About to restart self with extra arg: " << tc.c_str() << endl;

    AtrtClient atrt;
    int process_id = atrt.getOwnProcessId();
    if (process_id == -1)
    {
        g_err << "Failed to find own process id" << endl;
        return NDBT_FAILED;
    }

    if (!atrt.changeVersion(process_id, tc.c_str()))
        return NDBT_FAILED;

    // Will not be reached...

    return NDBT_OK;
}
static
int
set_ulimit(const BaseString & pair){
#ifdef HAVE_GETRLIMIT
  errno = 0;
  Vector<BaseString> list;
  pair.split(list, ":");
  if(list.size() != 2){
    logger.error("Unable to process ulimit: split >%s< list.size()=%d", 
		 pair.c_str(), list.size());
    return -1;
  }
  
  int res;
  rlim_t value = RLIM_INFINITY;
  if(!(list[1].trim() == "unlimited")){
    value = atoi(list[1].c_str());
  }

  struct rlimit rlp;
#define _RLIMIT_FIX(x) { res = getrlimit(x,&rlp); if(!res){ rlp.rlim_cur = value; res = setrlimit(x, &rlp); }}
  
  if(list[0].trim() == "c"){
    _RLIMIT_FIX(RLIMIT_CORE);
  } else if(list[0] == "d"){
    _RLIMIT_FIX(RLIMIT_DATA);
  } else if(list[0] == "f"){
    _RLIMIT_FIX(RLIMIT_FSIZE);
  } else if(list[0] == "n"){
    _RLIMIT_FIX(RLIMIT_NOFILE);
  } else if(list[0] == "s"){
    _RLIMIT_FIX(RLIMIT_STACK);
  } else if(list[0] == "t"){
    _RLIMIT_FIX(RLIMIT_CPU);
  } else {
    res= -11;
    errno = EINVAL;
  }
  if(res){
    logger.error("Unable to process ulimit: %s res=%d error=%d(%s)", 
		 pair.c_str(), res, errno, strerror(errno));
    return -1;
  }
#endif
  return 0;
}
Beispiel #19
0
int
DbUtil::createDb(BaseString& m_db)
{
  BaseString stm;
  {
    if(mysql_select_db(m_mysql, m_db.c_str()) == DBU_OK)
    {
      stm.assfmt("DROP DATABASE %s", m_db.c_str());
      if(doQuery(m_db.c_str()) == DBU_FAILED)
        return DBU_FAILED;
    }
    stm.assfmt("CREATE DATABASE %s", m_db.c_str());
    if(doQuery(m_db.c_str()) == DBU_FAILED)
      return DBU_FAILED;
    return DBU_OK;
  }
}
Beispiel #20
0
static void
print_conditional_sql(const BaseString& sql)
{
  printf("SET @str=IF(@have_ndbinfo,'%s','SET @dummy = 0');\n",
         sql.c_str());
  printf("PREPARE stmt FROM @str;\n");
  printf("EXECUTE stmt;\n");
  printf("DROP PREPARE stmt;\n\n");
}
bool
FileLogHandler::setMaxSize(const BaseString &size) {
  char *end;
  long val = strtol(size.c_str(), &end, 0); /* XXX */
  if(size.c_str() == end || val < 0)
  {
    setErrorStr("Invalid file size");
    return false;
  }
  if(end[0] == 'M')
    val *= 1024*1024;
  if(end[0] == 'k')
    val *= 1024;

  m_maxFileSize = val;

  return true;
}
Beispiel #22
0
static int drop_all_tables()
{
  NdbDictionary::Dictionary * dict = g_ndb->getDictionary();
  require(dict);

  BaseString db = g_ndb->getDatabaseName();
  BaseString schema = g_ndb->getSchemaName();

  NdbDictionary::Dictionary::List list;
  if (dict->listObjects(list, NdbDictionary::Object::TypeUndefined) == -1){
      g_err << "Failed to list tables: " << endl
	    << dict->getNdbError() << endl;
      return -1;
  }
  for (unsigned i = 0; i < list.count; i++) {
    NdbDictionary::Dictionary::List::Element& elt = list.elements[i];
    switch (elt.type) {
    case NdbDictionary::Object::SystemTable:
    case NdbDictionary::Object::UserTable:
      g_ndb->setDatabaseName(elt.database);
      g_ndb->setSchemaName(elt.schema);
      if(dict->dropTable(elt.name) != 0){
	g_err << "Failed to drop table: " 
	      << elt.database << "/" << elt.schema << "/" << elt.name <<endl;
	g_err << dict->getNdbError() << endl;
	return -1;
      }
      break;
    case NdbDictionary::Object::UniqueHashIndex:
    case NdbDictionary::Object::OrderedIndex:
    case NdbDictionary::Object::HashIndexTrigger:
    case NdbDictionary::Object::IndexTrigger:
    case NdbDictionary::Object::SubscriptionTrigger:
    case NdbDictionary::Object::ReadOnlyConstraint:
    default:
      break;
    }
  }
  
  g_ndb->setDatabaseName(db.c_str());
  g_ndb->setSchemaName(schema.c_str());
  
  return 0;
}
Beispiel #23
0
bool
DbUtil::createDb(BaseString& m_db)
{
  BaseString stm;
  setDbName(m_db.c_str());
  
  {
    if(selectDb())
    {
      stm.assfmt("DROP DATABASE %s", m_db.c_str());
      if(!doQuery(m_db.c_str()))
        return false;
    }
    stm.assfmt("CREATE DATABASE %s", m_db.c_str());
    if(!doQuery(m_db.c_str()))
      return false;
    return true;
  }
}
Beispiel #24
0
int
insert_file(FILE * f, class Properties& p, bool break_on_empty){
  if(f == 0)
    return -1;

  while(!feof(f)){
    char buf[1024];
    fgets(buf, 1024, f);
    BaseString tmp = buf;

    if(tmp.length() > 0 && tmp.c_str()[0] == '#')
      continue;

    if(insert(tmp.c_str(), p) != 0 && break_on_empty)
      break;
  }

  return 0;
}
Beispiel #25
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 #26
0
bool
LocalConfig::readConnectString(const char * connectString,
			       const char * info){
  BaseString err;
  bool return_value = parseString(connectString, err);
  if (!return_value) {
    BaseString err2;
    err2.assfmt("Reading %d \"%s\": %s", info, connectString, err.c_str());
    setError(0,err2.c_str());
  }
  return return_value;
}
Beispiel #27
0
bool
Operate::evaluate(SimpleCpcClient* c, const SimpleCpcClient::Process & pp){
  Uint32 id = pp.m_id;
  Properties p;
  int res;

  if(strcasecmp(cmd, "start") == 0)
    res = c->start_process(id, p);
  else if(strcasecmp(cmd, "stop") == 0)
    res = c->stop_process(id, p);
  else if(strcasecmp(cmd, "rm") == 0)
    res = c->undefine_process(id, p);
  else if(strcasecmp(cmd, "list") == 0){
    if(!sets.m_longl){
      if(host != c){
	ndbout_c("--- %s:%d", c->getHost(), c->getPort());
	host = c;
      }
    }
    
    char s = 0;
    const char * status = pp.m_status.c_str();
    if(strcmp(status, "stopped") == 0)  s = '-';
    if(strcmp(status, "starting") == 0) s = 's';
    if(strcmp(status, "running") == 0)  s = 'r';
    if(strcmp(status, "stopping") == 0)  s = 'k';    
    if(s == 0) s = '?';

    if(!sets.m_longl){
      ndbout_c("%c%c\t%d\t%s\t%s\t%s(%s)", 
	       s, 
	       pp.m_type.c_str()[0], id, pp.m_owner.c_str(), 
	       pp.m_group.c_str(), pp.m_name.c_str(), pp.m_path.c_str());
    } else {
      ndbout_c("%c%c %s:%d:%d %s %s %s(%s)", 
	       s, pp.m_type.c_str()[0], c->getHost(), c->getPort(),
	       id, pp.m_owner.c_str(), pp.m_group.c_str(), 
	       pp.m_name.c_str(), pp.m_path.c_str());
    }
    return true;
  }
  
  if(res != 0){
    BaseString msg;
    p.get("errormessage", msg);
    ndbout_c("Failed to %s %d on %s:%d - %s",
	     cmd, id, 
	     c->getHost(), c->getPort(), msg.c_str());
    return false;
  }
  
  return true;
}
Beispiel #28
0
static
bool
create_directory(const char * path)
{
  BaseString native(path);
  to_native(native);
  BaseString tmp(path);
  Vector<BaseString> list;

  if (tmp.split(list, "/") == 0)
  {
    g_logger.error("Failed to create directory: %s", tmp.c_str());
    return false;
  }
  
  BaseString cwd = IF_WIN("","/");
  for (unsigned i = 0; i < list.size(); i++)
  {
    cwd.append(list[i].c_str());
    cwd.append("/");
    NdbDir::create(cwd.c_str(),
                   NdbDir::u_rwx() | NdbDir::g_r() | NdbDir::g_x(),
                   true);
  }

  struct stat sbuf;
  if (lstat(native.c_str(), &sbuf) != 0 ||
      !S_ISDIR(sbuf.st_mode))
  {
    g_logger.error("Failed to create directory: %s (%s)", 
		   native.c_str(),
		   cwd.c_str());
    return false;
  }
  
  return true;
}
Beispiel #29
0
bool
BackupRestore::init()
{
  release();

  if (!m_restore && !m_restore_meta && !m_restore_epoch)
    return true;

  m_cluster_connection = new Ndb_cluster_connection(g_connect_string);
  m_cluster_connection->set_name(g_options.c_str());
  if(m_cluster_connection->connect(12, 5, 1) != 0)
  {
    return false;
  }

  m_ndb = new Ndb(m_cluster_connection);

  if (m_ndb == NULL)
    return false;
  
  m_ndb->init(1024);
  if (m_ndb->waitUntilReady(30) != 0)
  {
    err << "Failed to connect to ndb!!" << endl;
    return false;
  }
  info << "Connected to ndb!!" << endl;

  m_callback = new restore_callback_t[m_parallelism];

  if (m_callback == 0)
  {
    err << "Failed to allocate callback structs" << endl;
    return false;
  }

  m_free_callback= m_callback;
  for (Uint32 i= 0; i < m_parallelism; i++) {
    m_callback[i].restore= this;
    m_callback[i].connection= 0;
    if (i > 0)
      m_callback[i-1].next= &(m_callback[i]);
  }
  m_callback[m_parallelism-1].next = 0;

  return true;
}
Beispiel #30
0
void
MgmApiSession::logSignals(Parser<MgmApiSession>::Context &,
			   Properties const &args) {
  Uint32 node = 0, in = 0, out = 0;
  //  BaseString blocks;
  BaseString blockList;
  char * blockName;
  args.get("node", &node);
  args.get("in", &in);
  args.get("out", &out);
  args.get("blocks", blockList);
  // fast fix - pekka
  char buf[200];
  BaseString::snprintf(buf, 200, "%s", blockList.c_str());
  Vector<BaseString> blocks;  

  blockName=strtok(buf,"|");
  while( blockName != NULL)
    {
      blocks.push_back(blockName);
      blockName=strtok(NULL,"|");
    }
  

  if(in > 1 || out > 1)
    return; /* Invalid arguments */
  
  const MgmtSrvr::LogMode modes[] = {
    MgmtSrvr::Off,
    MgmtSrvr::Out,
    MgmtSrvr::In,
    MgmtSrvr::InOut,
  };
  MgmtSrvr::LogMode mode = modes[in<<1 | out];

  int result = m_mgmsrv.setSignalLoggingMode(node, mode, blocks);

  m_output->println("log signals reply");
  if(result != 0)
    m_output->println("result: %s", get_error_text(result));
  else
    m_output->println("result: Ok");
  m_output->println("");
}