Beispiel #1
0
static rw_status_t bootstrap_rwproc(struct rwmain_gi * rwmain)
{
  rw_status_t status;
  char * self_id = NULL;

  RWTRACE_INFO(
      rwmain->rwvx->rwtrace,
      RWTRACE_CATEGORY_RWMAIN,
      "Performing bootstrap of RWPROC %s",
      rwmain->component_name);

  status = RW_STATUS_SUCCESS;
  if (!rwmain->rwvx->rwvcs->pb_rwmanifest->bootstrap_phase->rwproc)
    goto done;

  self_id = to_instance_name(rwmain->component_name, rwmain->instance_id);

  for (size_t i = 0; i < rwmain->rwvx->rwvcs->pb_rwmanifest->bootstrap_phase->rwproc->n_instances; ++i) {
    vcs_manifest_action action;
    vcs_manifest_action_start start;

    vcs_manifest_action__init(&action);
    vcs_manifest_action_start__init(&start);

    action.start = &start;
    start.component_name = rwmain->rwvx->rwvcs->pb_rwmanifest->bootstrap_phase->rwproc->instances[i]->component_name;
    start.has_config_ready = rwmain->rwvx->rwvcs->pb_rwmanifest->bootstrap_phase->rwproc->instances[i]->has_config_ready;
    start.config_ready = rwmain->rwvx->rwvcs->pb_rwmanifest->bootstrap_phase->rwproc->instances[i]->config_ready;
#if 0
    start.has_recovery_action = true;
    start.recovery_action = RWVCS_TYPES_RECOVERY_TYPE_RESTART;
#else
    start.has_recovery_action = rwmain->rwvx->rwvcs->pb_rwmanifest->bootstrap_phase->rwproc->instances[i]->has_recovery_action;
    start.recovery_action = rwmain->rwvx->rwvcs->pb_rwmanifest->bootstrap_phase->rwproc->instances[i]->recovery_action;
#endif

    status = rwmain_action_run(rwmain, self_id, &action);

    action.start = NULL;
    start.component_name = NULL;
    protobuf_free_stack(action);
    protobuf_free_stack(start);
  }

done:
  if (self_id)
    free(self_id);

  RWTRACE_INFO(
      rwmain->rwvx->rwtrace,
      RWTRACE_CATEGORY_RWMAIN,
      "Bootstrap of RWPROC complete");

  return status;
}
Beispiel #2
0
rw_status_t process_init_phase(struct rwmain_gi * rwmain)
{
  rw_status_t status;
  rwvcs_instance_ptr_t rwvcs;

  rwvcs = rwmain->rwvx->rwvcs;

  if (rwvcs->pb_rwmanifest->init_phase->settings->rwvcs->no_autostart == false) {
    vcs_manifest_component *m_component;
    char * instance_name = NULL;

    instance_name = to_instance_name(rwmain->component_name, rwmain->instance_id);
    RW_ASSERT(*instance_name);

    // Lookup the component to start
    status = rwvcs_manifest_component_lookup(rwvcs, rwmain->component_name, &m_component);
    rwmain_trace_info(rwmain, "rwvcs_manifest_component_lookup %s", rwmain->component_name);
    RW_ASSERT(status == RW_STATUS_SUCCESS);

    if (m_component->component_type == RWVCS_TYPES_COMPONENT_TYPE_RWVM) {
      RWVCS_LATENCY_CHK_PRE(rwmain->rwvx->rwsched);
      rwmain_rwvm_init(
          rwmain,
          m_component->rwvm,
          rwmain->component_name,
          rwmain->instance_id,
          instance_name,
          rwmain->parent_id);
      RWVCS_LATENCY_CHK_POST(rwmain->rwvx->rwtrace, RWTRACE_CATEGORY_RWMAIN,
                             rwmain_rwvm_init, "rwmain_rwvm_init:%s", instance_name);
    } else if (m_component->component_type == RWVCS_TYPES_COMPONENT_TYPE_RWPROC) {
      RWVCS_LATENCY_CHK_PRE(rwmain->rwvx->rwsched);
      rwmain_rwproc_init(
          rwmain,
          m_component->rwproc,
          rwmain->component_name,
          rwmain->instance_id,
          instance_name,
          rwmain->parent_id);
      RWVCS_LATENCY_CHK_POST(rwmain->rwvx->rwtrace, RWTRACE_CATEGORY_RWMAIN,
                             rwmain_rwproc_init, "rwmain_rwproc_init:%s", instance_name);
    } else {
      rwmain_trace_crit(
          rwmain,
          "rwmain cannot start a component which is not a vm or process (%s)",
          m_component->component_name);
      RW_CRASH();
    }
  }

  return RW_STATUS_SUCCESS;
}
Beispiel #3
0
struct rwmain_gi * rwmain_alloc(
    rwvx_instance_ptr_t rwvx,
    const char * component_name,
    uint32_t instance_id,
    const char * component_type,
    const char * parent_id,
    const char * vm_ip_address,
    uint32_t vm_instance_id)
{
  rw_status_t status;
  int r;
  rwtasklet_info_ptr_t info = NULL;
  rwdts_api_t * dts = NULL;
  struct rwmain_gi * rwmain = NULL;
  char * instance_name = NULL;


  rwmain = (struct rwmain_gi *)malloc(sizeof(struct rwmain_gi));
  if (!rwmain) {
    RW_CRASH();
    goto err;
  }
  bzero(rwmain, sizeof(struct rwmain_gi));

  /* If the component name wasn't specified on the command line, pull it
   * from the manifest init-phase.
   */
  if (!component_name) {
    char cn[1024];

    status = rwvcs_variable_evaluate_str(
        rwvx->rwvcs,
        "$rw_component_name",
        cn,
        sizeof(cn));
    if (status != RW_STATUS_SUCCESS) {
      RW_CRASH();
      goto err;
    }

    rwmain->component_name = strdup(cn);
  } else {
    rwmain->component_name = strdup(component_name);
  }

  if (!rwmain->component_name) {
    RW_CRASH();
    goto err;
  }


  /* If the instance id wasn't specified on the command line pull it from
   * the manifest init-phase if it is there, otherwise autoassign one.
   */
  if (instance_id == 0) {
    int id;

    status = rwvcs_variable_evaluate_int(
        rwvx->rwvcs,
        "$instance_id",
        &id);
    if ((status == RW_STATUS_SUCCESS) && id) {
      rwmain->instance_id = (uint32_t)id;
    } else {
      status = rwvcs_rwzk_next_instance_id(rwvx->rwvcs, &rwmain->instance_id, NULL);
      if (status != RW_STATUS_SUCCESS) {
        RW_CRASH();
        goto err;
      }
    }
  } else {
    rwmain->instance_id = instance_id;
  }

  if (component_type) {
    rwmain->component_type = component_type_str_to_enum(component_type);
  } else {
    char ctype[64];
    status = rwvcs_variable_evaluate_str(
        rwvx->rwvcs,
        "$component_type",
        ctype,
        sizeof(ctype));
    if (status != RW_STATUS_SUCCESS) {
      RW_CRASH();
      goto err;
    }
    rwmain->component_type = component_type_str_to_enum(ctype);
  }

  if (vm_instance_id > 0)
    rwmain->vm_instance_id = vm_instance_id;
  else if (rwmain->component_type == RWVCS_TYPES_COMPONENT_TYPE_RWVM)
    rwmain->vm_instance_id = rwmain->instance_id;
  else {
    int vm_instance_id;
    status = rwvcs_variable_evaluate_int(
        rwvx->rwvcs,
        "$vm_instance_id",
        &vm_instance_id);
    if (status == RW_STATUS_SUCCESS) {
      rwmain->vm_instance_id = (uint32_t)vm_instance_id;
    }
  }
  RW_ASSERT(rwmain->vm_instance_id);


  // 10 hz with tolerance 600
  // TODO: Must take from YANG. These are currently defined as the defaults in rw-base.yang
  rwmain->rwproc_heartbeat = rwproc_heartbeat_alloc(10, 600);
  if (!rwmain->rwproc_heartbeat) {
    RW_CRASH();
    goto err;
  }

  bzero(&rwmain->sys, sizeof(rwmain->sys));

  if (parent_id) {
    rwmain->parent_id = strdup(parent_id);
    if (!rwmain->parent_id) {
      RW_CRASH();
      goto err;
    }
  }
  else {
    char ctype[64];
    status = rwvcs_variable_evaluate_str(
        rwvx->rwvcs,
        "$parent_id",
        ctype,
        sizeof(ctype));
    if (status == RW_STATUS_SUCCESS) {
      rwmain->parent_id = strdup(ctype);
    }
  }


  if (rwvx->rwvcs->pb_rwmanifest->init_phase->settings->rwvcs->collapse_each_rwvm) {
    r = asprintf(&rwmain->vm_ip_address, "127.%u.%u.1", rwmain->instance_id / 256, rwmain->instance_id % 256);
    if (r == -1) {
      RW_CRASH();
      goto err;
    }
  } else if (vm_ip_address) {
    rwmain->vm_ip_address = strdup(vm_ip_address);
    if (!rwmain->vm_ip_address) {
      RW_CRASH();
      goto err;
    }
    char *variable[0];
    r = asprintf(&variable[0], "vm_ip_address = '%s'", vm_ip_address);
    if (r == -1) {
      RW_CRASH();
      goto err;
    }
    status = rwvcs_variable_list_evaluate(
        rwvx->rwvcs,
        1,
        variable);
    if (status != RW_STATUS_SUCCESS) {
      RW_CRASH();
      goto err;
    }
    free(variable[0]);
  } else {
    char buf[32];

    status = rwvcs_variable_evaluate_str(
        rwvx->rwvcs,
        "$vm_ip_address",
        buf,
        sizeof(buf));
    if (status != RW_STATUS_SUCCESS) {
      RW_CRASH();
      goto err;
    }

    rwmain->vm_ip_address = strdup(buf);
    if (!rwmain->vm_ip_address) {
      RW_CRASH();
      goto err;
    }
  }


  rwvx->rwvcs->identity.vm_ip_address = strdup(rwmain->vm_ip_address);
  if (!rwvx->rwvcs->identity.vm_ip_address) {
    RW_CRASH();
    goto err;
  }
  rwvx->rwvcs->identity.rwvm_instance_id = rwmain->vm_instance_id;

  instance_name = to_instance_name(rwmain->component_name, rwmain->instance_id);
  RW_ASSERT(instance_name!=NULL);
  if (rwmain->component_type == RWVCS_TYPES_COMPONENT_TYPE_RWVM) {
    rwvx->rwvcs->identity.rwvm_name = instance_name;
  }
  else if (rwmain->component_type == RWVCS_TYPES_COMPONENT_TYPE_RWPROC) {
    RW_ASSERT(rwmain->parent_id);
    rwvx->rwvcs->identity.rwvm_name = strdup(rwmain->parent_id);
  }

  char rift_var_vm[255];
  if (rwvx->rwvcs->identity.rwvm_name) {
    snprintf(rift_var_vm, 255, "%s%c%s", rwvx->rwvcs->pb_rwmanifest->bootstrap_phase->test_name,
             '-', rwvx->rwvcs->identity.rwvm_name);
  } else {
    snprintf(rift_var_vm, 255, "%s", rwvx->rwvcs->pb_rwmanifest->bootstrap_phase->test_name);
  }

  setenv("RIFT_VAR_VM", rift_var_vm, true);
  info = get_rwmain_tasklet_info(
      rwvx,
      rwmain->component_name,
      rwmain->instance_id,
      rwmain->vm_instance_id);
  if (!info) {
    RW_CRASH();
    goto err;
  }

  if (rwvx->rwsched) {
    if (!rwvx->rwsched->rwlog_instance) {
      rwvx->rwsched->rwlog_instance = rwlog_init("RW.Sched");
    }
  }
  if (!rwvx->rwlog) {
    rwvx->rwlog = rwlog_init("Logging");
  }

  dts = rwdts_api_new(
      info,
      (rw_yang_pb_schema_t *)RWPB_G_SCHEMA_YPBCSD(RwVcs),
      rwmain_dts_handle_state_change,
      NULL,
      NULL);

  if (!dts) {
    RW_CRASH();
    goto err;
  }

  RW_SKLIST_PARAMS_DECL(
      procs_sklist_params,
      struct rwmain_proc,
      instance_name,
      rw_sklist_comp_charptr,
      _sklist);
  RW_SKLIST_INIT(&(rwmain->procs), &procs_sklist_params);

  RW_SKLIST_PARAMS_DECL(
      tasklets_sklist_params,
      struct rwmain_tasklet,
      instance_name,
      rw_sklist_comp_charptr,
      _sklist);
  RW_SKLIST_INIT(&(rwmain->tasklets), &tasklets_sklist_params);

  RW_SKLIST_PARAMS_DECL(
      multivms_sklist_params,
      struct rwmain_multivm,
      key,
      rw_sklist_comp_charbuf,
      _sklist);
  RW_SKLIST_INIT(&(rwmain->multivms), &multivms_sklist_params);


  rwmain->dts = dts;
  rwmain->tasklet_info = info;
  rwmain->rwvx = rwvx;
  r = asprintf(&VCS_GET(rwmain)->vcs_instance_xpath,
               VCS_INSTANCE_XPATH_FMT,
               instance_name);
  if (r == -1) {
    RW_CRASH();
    goto err;
  }
  VCS_GET(rwmain)->instance_name = instance_name;

  goto done;

err:
  if (info) {
    rwsched_tasklet_free(info->rwsched_tasklet_info);
    free(info->identity.rwtasklet_name);
    rwmsg_endpoint_halt(info->rwmsg_endpoint);
    free(info);
  }

  if (dts)
    rwdts_api_deinit(dts);

  if (rwmain->component_name)
    free(rwmain->component_name);

  if (rwmain->parent_id)
    free(rwmain->parent_id);

  if (rwmain)
    free(rwmain);

done:

  return rwmain;
}
Beispiel #4
0
static rwtasklet_info_ptr_t get_rwmain_tasklet_info(
    rwvx_instance_ptr_t rwvx,
    const char * component_name,
    int instance_id,
    uint32_t vm_instance_id)
{
  rwtasklet_info_ptr_t info;
  char * instance_name = NULL;
  int broker_instance_id;

  info = (rwtasklet_info_ptr_t)RW_MALLOC0(sizeof(struct rwtasklet_info_s));
  if (!info) {
    RW_CRASH();
    goto err;
  }

  instance_name = to_instance_name(component_name, instance_id);
  if (!instance_name) {
    RW_CRASH();
    goto err;
  }

  info->rwsched_instance = rwvx->rwsched;
  info->rwsched_tasklet_info = rwsched_tasklet_new(rwvx->rwsched);
  info->rwtrace_instance = rwvx->rwtrace;
  info->rwvx = rwvx;
  info->rwvcs = rwvx->rwvcs;

  info->identity.rwtasklet_instance_id = instance_id;
  info->identity.rwtasklet_name = strdup(component_name);
  char *rift_var_root = rwtasklet_info_get_rift_var_root(info);
  RW_ASSERT(rift_var_root);

  rw_status_t status = rw_setenv("RIFT_VAR_ROOT", rift_var_root);
  RW_ASSERT(status == RW_STATUS_SUCCESS);
  setenv("RIFT_VAR_ROOT", rift_var_root, true);

  info->rwlog_instance = rwlog_init(instance_name);

  broker_instance_id = 0;
  if (rwvx->rwvcs->pb_rwmanifest->init_phase->settings->rwmsg->multi_broker
      && rwvx->rwvcs->pb_rwmanifest->init_phase->settings->rwmsg->multi_broker->has_enable
      && rwvx->rwvcs->pb_rwmanifest->init_phase->settings->rwmsg->multi_broker->enable) {
    broker_instance_id = vm_instance_id ? vm_instance_id : 1;
  }

  info->rwmsg_endpoint = rwmsg_endpoint_create(
    1,
    instance_id,
    broker_instance_id,
    info->rwsched_instance,
    info->rwsched_tasklet_info,
    info->rwtrace_instance,
    rwvx->rwvcs->pb_rwmanifest->init_phase->settings->rwmsg);

  rwtasklet_info_ref(info);
  free(instance_name);

  return info;

err:
  if (info)
    free(info);

  if (instance_name)
    free(instance_name);

  return NULL;
}
Beispiel #5
0
struct rwmain_gi * rwmain_gi_new(rwpb_gi_RwManifest_Manifest * manifest_box) 
{
  rw_status_t status;
  struct rwmain_gi * rwmain;
  struct rwvx_instance_s * rwvx;
  vcs_manifest * manifest;
  extern char **environ;
  char *s;
  int i;
  char * parent = NULL;
  char * ip_address = NULL;

  if (!getenv("TEST_ENVIRON")) {
    return rwmain_gi_old(manifest_box);
  }

  rwvx = rwvx_instance_alloc();
   
  RW_ASSERT(rwvx);

  s = *environ;
  for (i=0; s; i++) {
    rwvx->rwvcs->envp = realloc(rwvx->rwvcs->envp, (i+1)*sizeof(char*));
    rwvx->rwvcs->envp[i] = strdup(s);
    s = *(environ+i+1);
  }
  rwvx->rwvcs->envp = realloc(rwvx->rwvcs->envp, (i+1)*sizeof(char*));
  rwvx->rwvcs->envp[i] = NULL;

 
  RW_ASSERT(manifest_box->box.message->descriptor == RWPB_G_MSG_PBCMD(RwManifest_Manifest));
  manifest = (vcs_manifest *)manifest_box->box.message;
  sanitize_manifest(manifest);
  char *manifest_file = getenv("RW_MANIFEST");
  if (!manifest_file) {
    rwvx->rwvcs->pb_rwmanifest = (vcs_manifest *)protobuf_c_message_duplicate(
      NULL,
      &manifest->base,
      manifest->base.descriptor);
  }
  if (g_pb_rwmanifest) {
    protobuf_c_message_free_unpacked(NULL, &g_pb_rwmanifest->base);
  }
  g_pb_rwmanifest = (vcs_manifest *)protobuf_c_message_duplicate(
                    NULL, &manifest->base,
                    manifest->base.descriptor); /* used for module / unit test hack */

  char cn[1024];

  status = rwvcs_variable_evaluate_str(
      rwvx->rwvcs,
      "$rw_component_name",
      cn,
      sizeof(cn));

  rwvcs_process_manifest_file (rwvx->rwvcs, getenv("RW_MANIFEST"));
  if(!(cn[0])) {
    ip_address = rwvcs_manifest_get_local_mgmt_addr(rwvx->rwvcs->pb_rwmanifest->bootstrap_phase);
    RW_ASSERT(ip_address);
  }
  rwvcs_manifest_setup_mgmt_info (rwvx->rwvcs, !(cn[0]), ip_address);
  if (manifest_file) {
     status = rwvcs_instance_init(rwvx->rwvcs, 
                               getenv("RW_MANIFEST"), 
                               ip_address, 
                               NULL,
                               main_function);
  }
  else {
    status = rwvcs_instance_init(rwvx->rwvcs, NULL, ip_address, NULL, rwmain_gi_function);
  }
  RW_ASSERT(status == RW_STATUS_SUCCESS);

  char *component_name = NULL;
  char *component_type = NULL;
  uint32_t instance_id = 0;
  uint32_t vm_instance_id = 0;
  rwmain = rwmain_alloc(rwvx, component_name, instance_id, component_type, parent, ip_address, vm_instance_id);
  RW_ASSERT(rwmain);
  {
    rwmain->rwvx->rwvcs->apih = rwmain->dts;
    RW_SKLIST_PARAMS_DECL(
        config_ready_entries_,
        rwvcs_config_ready_entry_t,
        instance_name,
        rw_sklist_comp_charptr,
        config_ready_elem);
    RW_SKLIST_INIT(
        &(rwmain->rwvx->rwvcs->config_ready_entries), 
        &config_ready_entries_);
    rwmain->rwvx->rwvcs->config_ready_fn = rwmain_dts_config_ready_process;
  }
    

  if (rwmain->vm_ip_address) {
    rwmain->rwvx->rwvcs->identity.vm_ip_address = strdup(rwmain->vm_ip_address);
    RW_ASSERT(rwmain->rwvx->rwvcs->identity.vm_ip_address);
  }
  rwmain->rwvx->rwvcs->identity.rwvm_instance_id = rwmain->vm_instance_id;

  if (rwmain->component_type == RWVCS_TYPES_COMPONENT_TYPE_RWVM) {
    RW_ASSERT(VCS_GET(rwmain)->instance_name);
    rwmain->rwvx->rwvcs->identity.rwvm_name = strdup(VCS_GET(rwmain)->instance_name);
  }
  else if (rwmain->component_type == RWVCS_TYPES_COMPONENT_TYPE_RWPROC) {
    RW_ASSERT(rwmain->parent_id);
    rwmain->rwvx->rwvcs->identity.rwvm_name = strdup(rwmain->parent_id);
  }

  {
    char instance_id_str[256];
    snprintf(instance_id_str, 256, "%u", rwmain->vm_instance_id);
  }

  if (rwmain->component_type == RWVCS_TYPES_COMPONENT_TYPE_RWVM && parent!=NULL) {
    rwvcs_instance_ptr_t rwvcs = rwvx->rwvcs;
    struct timeval timeout = { .tv_sec = RWVCS_RWZK_TIMEOUT_S, .tv_usec = 0 };
    rw_component_info rwvm_info;
    char * instance_name = NULL;
    instance_name = to_instance_name(component_name, instance_id);
    RW_ASSERT(instance_name!=NULL);
    // Lock so that the parent can initialize the zk data before the child updates it
    status = rwvcs_rwzk_lock(rwvcs, instance_name, &timeout);
    RW_ASSERT(status == RW_STATUS_SUCCESS);
    printf("instance_nameinstance_nameinstance_nameinstance_nameinstance_name=%s\n", instance_name);
    status = rwvcs_rwzk_lookup_component(rwvcs, instance_name, &rwvm_info);
    RW_ASSERT(status == RW_STATUS_SUCCESS);
    RW_ASSERT(rwvm_info.vm_info!=NULL);
    rwvm_info.vm_info->has_pid = true;
    rwvm_info.vm_info->pid = getpid();
    status = rwvcs_rwzk_node_update(rwvcs, &rwvm_info);
    RW_ASSERT(status == RW_STATUS_SUCCESS);
    status = rwvcs_rwzk_unlock(rwvcs, instance_name);
    RW_ASSERT(status == RW_STATUS_SUCCESS);
    free(instance_name);
  } else if (rwmain->component_type == RWVCS_TYPES_COMPONENT_TYPE_RWVM && parent == NULL) {
Beispiel #6
0
/*
 * Initialize the zookeeper with a node for this component.  Used when the
 * component does not have a parent and therefore no one created the zookeeper
 * node yet.
 */
rw_status_t update_zk(struct rwmain_gi * rwmain)
{
  rw_status_t status;
  vcs_manifest_component * mdef;
  rwvcs_instance_ptr_t rwvcs;
  char * id = NULL;
  rw_component_info * ci = NULL;


  rwvcs = rwmain->rwvx->rwvcs;

  RW_ASSERT(!rwmain->parent_id);
  id = to_instance_name(rwmain->component_name, rwmain->instance_id);

  // As we only hit this point when the parent_id is NULL, we are pretty much
  // guaranteed that the definition has to be in the static manifest.
  status = rwvcs_manifest_component_lookup(rwvcs, rwmain->component_name, &mdef);
  if (status != RW_STATUS_SUCCESS) {
    RW_CRASH();
    goto done;
  }


  if (mdef->component_type == RWVCS_TYPES_COMPONENT_TYPE_RWVM) {
    ci = rwvcs_rwvm_alloc(
        rwmain->rwvx->rwvcs,
        rwmain->parent_id,
        rwmain->component_name,
        rwmain->instance_id,
        id);
    if (!ci) {
      RW_CRASH();
      status = RW_STATUS_FAILURE;
      goto done;
    }

    ci->vm_info->vm_ip_address = strdup(rwmain->vm_ip_address);
    ci->vm_info->has_pid = true;
    ci->vm_info->pid = getpid();
    ci->has_state = true;
    ci->state = RW_BASE_STATE_TYPE_STARTING;

    if (mdef->rwvm && mdef->rwvm->has_leader) {
      ci->vm_info->has_leader = true;
      ci->vm_info->leader= mdef->rwvm->leader;
    }
  } else if (mdef->component_type == RWVCS_TYPES_COMPONENT_TYPE_RWPROC) {
    ci = rwvcs_rwproc_alloc(
        rwvcs,
        rwmain->parent_id,
        rwmain->component_name,
        rwmain->instance_id,
        id);
    if (!ci) {
      RW_CRASH();
      status = RW_STATUS_FAILURE;
      goto done;
    }

    ci->proc_info->has_pid = true;
    ci->proc_info->pid = getpid();
    ci->has_state = true;
    ci->proc_info->has_native = true;
    ci->proc_info->native = false;
    ci->state = RW_BASE_STATE_TYPE_STARTING;
  } else {
    RW_CRASH();
    status = RW_STATUS_FAILURE;
    goto done;
  }

  status = rwvcs_rwzk_node_update(rwmain->rwvx->rwvcs, ci);
  if (status != RW_STATUS_SUCCESS) {
    RW_CRASH();
    goto done;
  }


done:
  if (id)
    free(id);

  if (ci)
    protobuf_free(ci);

  return status;
}