Пример #1
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;
}
Пример #2
0
static
inline
bool
setSignalLog(){
  signalLogger.flushSignalLog();

  const char * tmp = NdbEnv_GetEnv(API_SIGNAL_LOG, (char *)0, 0);
  if(tmp != 0 && apiSignalLog != 0 && strcmp(tmp,apiSignalLog) == 0){
    return true;
  } else if(tmp == 0 && apiSignalLog == 0){
    return false;
  } else if(tmp == 0 && apiSignalLog != 0){
    signalLogger.setOutputStream(0);
    apiSignalLog = tmp;
    return false;
  } else if(tmp !=0){
    if (strcmp(tmp, "-") == 0)
        signalLogger.setOutputStream(stdout);
#ifndef DBUG_OFF
    else if (strcmp(tmp, "+") == 0)
        signalLogger.setOutputStream(DBUG_FILE);
#endif
    else
        signalLogger.setOutputStream(fopen(tmp, "w"));
    apiSignalLog = tmp;
    return true;
  }
  return false;
}
 static Uint32 get_ndbt_base_port(void)
 {
   Uint32 port = 0;
   const char* base_port_str = NdbEnv_GetEnv("NDBT_BASE_PORT", (char*)0, 0);
   if (base_port_str)
     port = atoi(base_port_str);
   if (!port)
     port = 11000; // default
   return port;
 }
Пример #4
0
void
ndbSetOwnVersion() {
  char buf[256];
  if (NdbEnv_GetEnv("NDB_SETVERSION", buf, sizeof(buf))) {
    Uint32 _v1,_v2,_v3;
    if (sscanf(buf, "%u.%u.%u", &_v1, &_v2, &_v3) == 3) {
      ndbOwnVersionTesting = MAKE_VERSION(_v1,_v2,_v3);
      ndbout_c("Testing: Version set to 0x%x",  ndbOwnVersionTesting);
    }
  }
}
Пример #5
0
const char *
NdbConfig_get_path(int *_len)
{
  const char *path= NdbEnv_GetEnv("NDB_HOME", 0, 0);
  int path_len= 0;
  if (path)
    path_len= strlen(path);
  if (path_len == 0 && datadir_path) {
    path= datadir_path;
    path_len= strlen(path);
  }
  if (path_len == 0) {
    path= ".";
    path_len= strlen(path);
  }
  if (_len)
    *_len= path_len;
  return path;
}
Пример #6
0
int restartNFDuringNR(F_ARGS safety){

  myRandom48Init((long)NdbTick_CurrentMillisecond());
  int i;
  const int sz = sizeof(NFDuringNR_codes)/sizeof(NFDuringNR_codes[0]);
  for(i = 0; i<sz && !ctx->closeToTimeout(safety); i++){
    int randomId = myRandom48(_restarter.getNumDbNodes());
    int nodeId = _restarter.getDbNodeId(randomId);
    int error = NFDuringNR_codes[i];
    
    g_err << _restart->m_name << ": node = " << nodeId 
	  << " error code = " << error << endl;
    
    CHECK(_restarter.restartOneDbNode(nodeId, false, true, true) == 0,
	  "Could not restart node "<< nodeId);
    
    CHECK(_restarter.waitNodesNoStart(&nodeId, 1) == 0,
	  "waitNodesNoStart failed");
    
    int val[] = { DumpStateOrd::CmvmiSetRestartOnErrorInsert, 1 } ;
    CHECK(_restarter.dumpStateOneNode(nodeId, val, 2) == 0,
	  "failed to set RestartOnErrorInsert");
    
    CHECK(_restarter.insertErrorInNode(nodeId, error) == 0,
	  "failed to set error insert");
   
    CHECK(_restarter.startNodes(&nodeId, 1) == 0,
	  "failed to start node");

    NdbSleep_SecSleep(3);

    CHECK(_restarter.waitNodesNoStart(&nodeId, 1) == 0,
          "waitNodesNoStart failed");

    CHECK(_restarter.startNodes(&nodeId, 1) == 0,
	  "failed to start node");
    
    CHECK(_restarter.waitNodesStarted(&nodeId, 1) == 0,
	  "waitNodesStarted failed");
  }

  return NDBT_OK;
  
  if(_restarter.getNumDbNodes() < 4)
    return NDBT_OK;

#ifdef NDB_USE_GET_ENV
  char buf[256];
  if(NdbEnv_GetEnv("USER", buf, 256) == 0 || strcmp(buf, "ejonore") != 0)
    return NDBT_OK;
  
  for(i = 0; i<sz && !ctx->isTestStopped() && !ctx->closeToTimeout(safety);i++){
    const int randomId = myRandom48(_restarter.getNumDbNodes());
    int nodeId = _restarter.getDbNodeId(randomId);
    const int error = NFDuringNR_codes[i];
    
    const int masterNodeId = _restarter.getMasterNodeId();
    CHECK(masterNodeId > 0, "getMasterNodeId failed");
    int crashNodeId = 0;
    do {
      int rand = myRandom48(1000);
      crashNodeId = _restarter.getRandomNodeOtherNodeGroup(nodeId, rand);
    } while(crashNodeId == masterNodeId);

    CHECK(crashNodeId > 0, "getMasterNodeId failed");

    g_info << _restart->m_name << " restarting node = " << nodeId 
	   << " error code = " << error 
	   << " crash node = " << crashNodeId << endl;
    
    CHECK(_restarter.restartOneDbNode(nodeId, false, true, true) == 0,
	  "Could not restart node "<< nodeId);
    
    CHECK(_restarter.waitNodesNoStart(&nodeId, 1) == 0,
	  "waitNodesNoStart failed");
        
    int val[] = { DumpStateOrd::CmvmiSetRestartOnErrorInsert, 1 };
    CHECK(_restarter.dumpStateOneNode(crashNodeId, val, 2) == 0,
	  "failed to set RestartOnErrorInsert");
    
    CHECK(_restarter.insertErrorInNode(crashNodeId, error) == 0,
	  "failed to set error insert");
   
    CHECK(_restarter.startNodes(&nodeId, 1) == 0,
	  "failed to start node");

    CHECK(_restarter.waitClusterStarted() == 0,
	  "waitClusterStarted failed");
  }
#endif
  return NDBT_OK;
}
Пример #7
0
bool
LocalConfig::init(const char *connectString,
		  const char *fileName)
{
  DBUG_ENTER("LocalConfig::init");
  /** 
   * Escalation:
   *  1. Check connectString
   *  2. Check given filename
   *  3. Check environment variable NDB_CONNECTSTRING
   *  4. Check Ndb.cfg in NDB_HOME
   *  5. Check Ndb.cfg in cwd
   *  6. Check defaultConnectString
   */
  
  _ownNodeId= 0;

  //1. Check connectString
  if(connectString != 0 && connectString[0] != 0){
    if(readConnectString(connectString, "connect string")){
      if (ids.size())
	DBUG_RETURN(true);
      // only nodeid given, continue to find hosts
    } else
      DBUG_RETURN(false);
  }

  //2. Check given filename
  if (fileName && strlen(fileName) > 0) {
    bool fopenError;
    if(readFile(fileName, fopenError)){
      DBUG_RETURN(true);
    }
    DBUG_RETURN(false);
  }

  //3. Check environment variable
  char buf[255];  
  if(NdbEnv_GetEnv("NDB_CONNECTSTRING", buf, sizeof(buf)) &&
     strlen(buf) != 0){
    if(readConnectString(buf, "NDB_CONNECTSTRING")){
      DBUG_RETURN(true);
    }
    DBUG_RETURN(false);
  }
  
  //4. Check Ndb.cfg in NDB_HOME
  {
    bool fopenError;
    char *buf2= NdbConfig_NdbCfgName(1 /*true*/);
    NdbAutoPtr<char> tmp_aptr(buf2);
    if(readFile(buf2, fopenError))
      DBUG_RETURN(true);
    if (!fopenError)
      DBUG_RETURN(false);
  }

  //5. Check Ndb.cfg in cwd
  {
    bool fopenError;
    char *buf2= NdbConfig_NdbCfgName(0 /*false*/);
    NdbAutoPtr<char> tmp_aptr(buf2);
    if(readFile(buf2, fopenError))
      DBUG_RETURN(true);
    if (!fopenError)
      DBUG_RETURN(false);
  }

  //7. Check
  {
    char buf2[256];
    BaseString::snprintf(buf2, sizeof(buf2), "host=localhost:%s", NDB_PORT);
    if(readConnectString(buf2, "default connect string"))
      DBUG_RETURN(true);
  }

  setError(0, "");

  DBUG_RETURN(false);
}
Пример #8
0
void
ndbd_run(bool foreground, int report_fd,
         const char* connect_str, int force_nodeid, const char* bind_address,
         bool no_start, bool initial, bool initialstart,
         unsigned allocated_nodeid)
{
#ifdef _WIN32
  {
    char shutdown_event_name[32];
    _snprintf(shutdown_event_name, sizeof(shutdown_event_name),
              "ndbd_shutdown_%d", GetCurrentProcessId());

    g_shutdown_event = CreateEvent(NULL, TRUE, FALSE, shutdown_event_name);
    if (g_shutdown_event == NULL)
    {
      g_eventLogger->error("Failed to create shutdown event, error: %d",
                           GetLastError());
     ndbd_exit(1);
    }

    HANDLE thread = CreateThread(NULL, 0, &shutdown_thread, NULL, 0, NULL);
    if (thread == NULL)
    {
      g_eventLogger->error("couldn't start shutdown thread, error: %d",
                           GetLastError());
      ndbd_exit(1);
    }
  }
#endif

  if (foreground)
    g_eventLogger->info("Ndb started in foreground");

  if (report_fd)
  {
    g_eventLogger->debug("Opening report stream on fd: %d", report_fd);
    // Open a stream for sending extra status to angel
    if (!(angel_info_w = fdopen(report_fd, "w")))
    {
      g_eventLogger->error("Failed to open stream for reporting "
                           "to angel, error: %d (%s)", errno, strerror(errno));
      ndbd_exit(-1);
    }
  }
  else
  {
    // No reporting requested, open /dev/null
    const char* dev_null = IF_WIN("nul", "/dev/null");
    if (!(angel_info_w = fopen(dev_null, "w")))
    {
      g_eventLogger->error("Failed to open stream for reporting to "
                           "'%s', error: %d (%s)", dev_null, errno,
                           strerror(errno));
      ndbd_exit(-1);
    }
  }

  globalEmulatorData.create();

  Configuration* theConfig = globalEmulatorData.theConfiguration;
  if(!theConfig->init(no_start, initial, initialstart))
  {
    g_eventLogger->error("Failed to init Configuration");
    ndbd_exit(-1);
  }

  theConfig->fetch_configuration(connect_str, force_nodeid, bind_address,
                                 allocated_nodeid);

  if (NdbDir::chdir(NdbConfig_get_path(NULL)) != 0)
  {
    g_eventLogger->warning("Cannot change directory to '%s', error: %d",
                           NdbConfig_get_path(NULL), errno);
    // Ignore error
  }

  theConfig->setupConfiguration();

  if (get_multithreaded_config(globalEmulatorData))
    ndbd_exit(-1);

  systemInfo(* theConfig, * theConfig->m_logLevel);

  NdbThread* pWatchdog = globalEmulatorData.theWatchDog->doStart();

  {
    /*
     * Memory allocation can take a long time for large memory.
     *
     * So we want the watchdog to monitor the process of initial allocation.
     */
    Uint32 watchCounter;
    watchCounter = 9;           //  Means "doing allocation"
    globalEmulatorData.theWatchDog->registerWatchedThread(&watchCounter, 0);
    if (init_global_memory_manager(globalEmulatorData, &watchCounter))
      ndbd_exit(1);
    globalEmulatorData.theWatchDog->unregisterWatchedThread(0);
  }

  globalEmulatorData.theThreadConfig->init();

#ifdef VM_TRACE
  // Create a signal logger before block constructors
  char *buf= NdbConfig_SignalLogFileName(globalData.ownId);
  NdbAutoPtr<char> tmp_aptr(buf);
  FILE * signalLog = fopen(buf, "a");
  globalSignalLoggers.setOwnNodeId(globalData.ownId);
  globalSignalLoggers.setOutputStream(signalLog);
#if 1 // to log startup
  { const char* p = NdbEnv_GetEnv("NDB_SIGNAL_LOG", (char*)0, 0);
    if (p != 0) {
      char buf[200];
      BaseString::snprintf(buf, sizeof(buf), "BLOCK=%s", p);
      for (char* q = buf; *q != 0; q++) *q = toupper(toascii(*q));
      globalSignalLoggers.log(SignalLoggerManager::LogInOut, buf);
      globalData.testOn = 1;
      assert(signalLog != 0);
      fprintf(signalLog, "START\n");
      fflush(signalLog);
    }
  }
#endif
#endif

  // Load blocks (both main and workers)
  globalEmulatorData.theSimBlockList->load(globalEmulatorData);

  // Set thread concurrency for Solaris' light weight processes
  int status;
  status = NdbThread_SetConcurrencyLevel(30);
  assert(status == 0);

  catchsigs(foreground);

  /**
   * Do startup
   */
  switch(globalData.theRestartFlag){
  case initial_state:
    globalEmulatorData.theThreadConfig->doStart(NodeState::SL_CMVMI);
    break;
  case perform_start:
    globalEmulatorData.theThreadConfig->doStart(NodeState::SL_CMVMI);
    globalEmulatorData.theThreadConfig->doStart(NodeState::SL_STARTING);
    break;
  default:
    assert("Illegal state globalData.theRestartFlag" == 0);
  }

  globalTransporterRegistry.startSending();
  globalTransporterRegistry.startReceiving();
  if (!globalTransporterRegistry.start_service(*globalEmulatorData.m_socket_server)){
    ndbout_c("globalTransporterRegistry.start_service() failed");
    ndbd_exit(-1);
  }

  // Re-use the mgm handle as a transporter
  if(!globalTransporterRegistry.connect_client(
		 theConfig->get_config_retriever()->get_mgmHandlePtr()))
      ERROR_SET(fatal, NDBD_EXIT_CONNECTION_SETUP_FAILED,
                "Failed to convert mgm connection to a transporter",
                __FILE__);

  NdbThread* pTrp = globalTransporterRegistry.start_clients();
  if (pTrp == 0)
  {
    ndbout_c("globalTransporterRegistry.start_clients() failed");
    ndbd_exit(-1);
  }

  NdbThread* pSockServ = globalEmulatorData.m_socket_server->startServer();

  globalEmulatorData.theConfiguration->addThread(pTrp, SocketClientThread);
  globalEmulatorData.theConfiguration->addThread(pWatchdog, WatchDogThread);
  globalEmulatorData.theConfiguration->addThread(pSockServ, SocketServerThread);

  //  theConfig->closeConfiguration();
  {
    NdbThread *pThis = NdbThread_CreateObject(0);
    Uint32 inx = globalEmulatorData.theConfiguration->addThread(pThis,
                                                                MainThread);
    globalEmulatorData.theThreadConfig->ipControlLoop(pThis, inx);
    globalEmulatorData.theConfiguration->removeThreadId(inx);
  }
  NdbShutdown(0, NST_Normal);

  ndbd_exit(0);
}
Пример #9
0
static int
get_multithreaded_config(EmulatorData& ed)
{
  // multithreaded is compiled in ndbd/ndbmtd for now
  globalData.isNdbMt = SimulatedBlock::isMultiThreaded();
  if (!globalData.isNdbMt)
  {
    ndbout << "NDBMT: non-mt" << endl;
    return 0;
  }

  THRConfig & conf = ed.theConfiguration->m_thr_config;

  Uint32 threadcount = conf.getThreadCount();
  ndbout << "NDBMT: MaxNoOfExecutionThreads=" << threadcount << endl;

  globalData.isNdbMtLqh = true;

  {
    if (conf.getMtClassic())
    {
      globalData.isNdbMtLqh = false;
    }
  }

  if (!globalData.isNdbMtLqh)
    return 0;

  Uint32 threads = conf.getThreadCount(THRConfig::T_LDM);
  Uint32 workers = threads;
  {
    ndb_mgm_configuration * conf = ed.theConfiguration->getClusterConfig();
    if (conf == 0)
    {
      abort();
    }
    ndb_mgm_configuration_iterator * p =
      ndb_mgm_create_configuration_iterator(conf, CFG_SECTION_NODE);
    if (ndb_mgm_find(p, CFG_NODE_ID, globalData.ownId))
    {
      abort();
    }
    ndb_mgm_get_int_parameter(p, CFG_NDBMT_LQH_WORKERS, &workers);
  }

#ifdef VM_TRACE
  // testing
  {
    const char* p;
    p = NdbEnv_GetEnv("NDBMT_LQH_WORKERS", (char*)0, 0);
    if (p != 0)
      workers = atoi(p);
  }
#endif

  ndbout << "NDBMT: workers=" << workers
         << " threads=" << threads << endl;

  assert(workers != 0 && workers <= MAX_NDBMT_LQH_WORKERS);
  assert(threads != 0 && threads <= MAX_NDBMT_LQH_THREADS);
  assert(workers % threads == 0);

  globalData.ndbMtLqhWorkers = workers;
  globalData.ndbMtLqhThreads = threads;
  return 0;
}
Пример #10
0
int 
main(int argc, const char** argv){
  ndb_init();
  int help = 0;
  const char *cmd=0, *name=0, *group=0, *owner=0;
  int list = 0, start = 0, stop = 0, rm = 0;
  struct getargs args[] = {
    { "cmd", 'c', arg_string, &cmd, "command", "command to run (default ls)" }
    ,{ "name", 'n', arg_string, &name, 
       "apply command for all processes with name" }
    ,{ "group", 'g', arg_string, &group, 
       "apply command for all processes in group" }
    ,{ "owner", 'g', arg_string, &owner,
       "apply command for all processes with owner" }
    ,{ "long", 'l', arg_flag, &g_settings.m_longl, "long", "long listing"}
    ,{ "usage", '?', arg_flag, &help, "Print help", "" }
    ,{ "ls",  0, arg_flag, &list, "-c list", "list process(es)" }
    ,{ "start", 0, arg_flag, &start, "-c start", "start process(es)" }
    ,{ "stop",  0, arg_flag, &stop, "-c stop", "stop process(es)" }
    ,{ "rm",    0, arg_flag, &rm, "-c rm", "undefine process(es)" }
  };
  const int num_args = 10;
  int i; 
  int optind = 0;
  char desc[] = "[host:[port]]\n";
  
  if(getarg(args, num_args, argc, argv, &optind) || help) {
    arg_printusage(args, num_args, argv[0], desc);
    return 1;
  }

  if(list + start + stop + rm > 1){
    ndbout_c("Can only specify one command");
    arg_printusage(args, num_args, argv[0], desc);
    return 1;
  }
  
  if(list) cmd = "list";
  if(start) cmd = "start";
  if(stop) cmd = "stop";
  if(rm) cmd = "rm";
  if(!cmd) cmd = "list";
  
  Expression * m_expr = 0;

  for(i = optind; i<argc; i++){
    add_host(g_hosts, argv[i]);
  }

  OrExpr * orE = new OrExpr(new Operate(cmd, g_settings), true);
  m_expr = orE;
  for(i = optind; i<argc; i++){
    BaseString tmp(argv[i]);
    Vector<BaseString> split;
    tmp.split(split, ":");
    
    if(split.size() > 2){
      Uint32 id = atoi(split[2].c_str());
      orE->push_back(new ProcEQ(g_hosts[i-optind], id));	
    }
  }

  if(g_hosts.size() == 0){
    char buf[1024];
    if(NdbEnv_GetEnv(ENV_HOSTS, buf, sizeof(buf))){
      add_hosts(g_hosts, BaseString(buf));
    }
  }
  
  if(g_hosts.size() == 0){
    g_hosts.push_back(new SimpleCpcClient("localhost", g_settings.m_port));
  }
  
  if(group != 0){
    Expression * tmp = new FieldEQ("group", group);
    m_expr = new Match(* tmp, * m_expr);
  }
  
  if(name != 0){
    Expression * tmp = new FieldEQ("name", name);
    m_expr = new Match(* tmp, * m_expr);
  }

  if(owner != 0){
    Expression * tmp = new FieldEQ("owner", owner);
    m_expr = new Match(* tmp, * m_expr);
  }

  connect(g_hosts);
  for_each(g_hosts, * m_expr);
  
  return 0;
}
Пример #11
0
void
Dbtux::execTUX_ADD_ATTRREQ(Signal* signal)
{
  jamEntry();
  const TuxAddAttrReq reqCopy = *(const TuxAddAttrReq*)signal->getDataPtr();
  const TuxAddAttrReq* const req = &reqCopy;
  // get the records
  FragOpPtr fragOpPtr;
  IndexPtr indexPtr;
  c_fragOpPool.getPtr(fragOpPtr, req->tuxConnectPtr);
  c_indexPool.getPtr(indexPtr, fragOpPtr.p->m_indexId);
  TuxAddAttrRef::ErrorCode errorCode = TuxAddAttrRef::NoError;
  do {
    // expected attribute id
    const unsigned attrId = fragOpPtr.p->m_numAttrsRecvd++;
    ndbrequire(
        indexPtr.p->m_state == Index::Defining &&
        attrId < indexPtr.p->m_numAttrs &&
        attrId == req->attrId);
    const Uint32 ad = req->attrDescriptor;
    const Uint32 typeId = AttributeDescriptor::getType(ad);
    const Uint32 sizeInBytes = AttributeDescriptor::getSizeInBytes(ad);
    const Uint32 nullable = AttributeDescriptor::getNullable(ad);
    const Uint32 csNumber = req->extTypeInfo >> 16;
    const Uint32 primaryAttrId = req->primaryAttrId;

    DescHead& descHead = getDescHead(*indexPtr.p);
    // add type to spec
    KeySpec& keySpec = indexPtr.p->m_keySpec;
    KeyType keyType(typeId, sizeInBytes, nullable, csNumber);
    if (keySpec.add(keyType) == -1) {
      jam();
      errorCode = TuxAddAttrRef::InvalidAttributeType;
      break;
    }
    // add primary attr to read keys array
    AttributeHeader* keyAttrs = getKeyAttrs(descHead);
    AttributeHeader& keyAttr = keyAttrs[attrId];
    new (&keyAttr) AttributeHeader(primaryAttrId, sizeInBytes);
#ifdef VM_TRACE
    if (debugFlags & DebugMeta) {
      debugOut << "attr " << attrId << " " << keyType << endl;
    }
#endif
    if (csNumber != 0) {
      unsigned err;
      CHARSET_INFO *cs = all_charsets[csNumber];
      ndbrequire(cs != 0);
      if ((err = NdbSqlUtil::check_column_for_ordered_index(typeId, cs))) {
        jam();
        errorCode = (TuxAddAttrRef::ErrorCode) err;
        break;
      }
    }
    const bool lastAttr = (indexPtr.p->m_numAttrs == fragOpPtr.p->m_numAttrsRecvd);
    if ((ERROR_INSERTED(12003) && attrId == 0) ||
        (ERROR_INSERTED(12004) && lastAttr))
    {
      errorCode = (TuxAddAttrRef::ErrorCode)1;
      CLEAR_ERROR_INSERT_VALUE;
      break;
    }
    if (lastAttr) {
      // compute min prefix
      const KeySpec& keySpec = indexPtr.p->m_keySpec;
      unsigned attrs = 0;
      unsigned bytes = keySpec.get_nullmask_len(false);
      unsigned maxAttrs = indexPtr.p->m_numAttrs;
#ifdef VM_TRACE
#ifdef NDB_USE_GET_ENV
      {
        const char* p = NdbEnv_GetEnv("MAX_TTREE_PREF_ATTRS", (char*)0, 0);
        if (p != 0 && p[0] != 0 && maxAttrs > (unsigned)atoi(p))
          maxAttrs = atoi(p);
      }
#endif
#endif
      while (attrs < maxAttrs) {
        const KeyType& keyType = keySpec.get_type(attrs);
        const unsigned newbytes = bytes + keyType.get_byte_size();
        if (newbytes > (MAX_TTREE_PREF_SIZE << 2))
          break;
        attrs++;
        bytes = newbytes;
      }
      if (attrs == 0)
        bytes = 0;
      indexPtr.p->m_prefAttrs = attrs;
      indexPtr.p->m_prefBytes = bytes;
      // fragment is defined
#ifdef VM_TRACE
      if (debugFlags & DebugMeta) {
        debugOut << "Release frag op " << fragOpPtr.i << " " << *fragOpPtr.p << endl;
      }
#endif
      c_fragOpPool.release(fragOpPtr);
    }
    // success
    TuxAddAttrConf* conf = (TuxAddAttrConf*)signal->getDataPtrSend();
    conf->userPtr = fragOpPtr.p->m_userPtr;
    conf->lastAttr = lastAttr;
    sendSignal(fragOpPtr.p->m_userRef, GSN_TUX_ADD_ATTRCONF,
        signal, TuxAddAttrConf::SignalLength, JBB);
    return;
  } while (0);
  // error
  TuxAddAttrRef* ref = (TuxAddAttrRef*)signal->getDataPtrSend();
  ref->userPtr = fragOpPtr.p->m_userPtr;
  ref->errorCode = errorCode;
  sendSignal(fragOpPtr.p->m_userRef, GSN_TUX_ADD_ATTRREF,
      signal, TuxAddAttrRef::SignalLength, JBB);
#ifdef VM_TRACE
    if (debugFlags & DebugMeta) {
      debugOut << "Release on attr error frag op " << fragOpPtr.i << " " << *fragOpPtr.p << endl;
    }
#endif
  // let DICT drop the unfinished index
}