Exemplo n.º 1
0
/* Helper function: This handles the PUT state action using an
 * <b>obj_type</b> and <b>data</b> needed for the action.
 * PUT frees the previous data before replacing it, if needed. */
static void
state_query_put_(sr_state_object_t obj_type, void *data)
{
  if (BUG(!sr_state))
    return;

  switch (obj_type) {
  case SR_STATE_OBJ_COMMIT:
  {
    sr_commit_t *commit = data;
    tor_assert(commit);
    /* commit_add_to_state() frees the old commit, if there is one */
    commit_add_to_state(commit, sr_state);
    break;
  }
  case SR_STATE_OBJ_CURSRV:
      /* Check if the new pointer is the same as the old one: if it is, it's
       * probably a bug. The caller may have confused current and previous,
       * or they may have forgotten to sr_srv_dup().
       * Putting NULL multiple times is allowed. */
    if (!BUG(data && sr_state->current_srv == (sr_srv_t *) data)) {
      /* We own the old SRV, so we need to free it.  */
      state_query_del_(SR_STATE_OBJ_CURSRV, NULL);
      sr_state->current_srv = (sr_srv_t *) data;
    }
    break;
  case SR_STATE_OBJ_PREVSRV:
      /* Check if the new pointer is the same as the old one: if it is, it's
       * probably a bug. The caller may have confused current and previous,
       * or they may have forgotten to sr_srv_dup().
       * Putting NULL multiple times is allowed. */
    if (!BUG(data && sr_state->previous_srv == (sr_srv_t *) data)) {
      /* We own the old SRV, so we need to free it.  */
      state_query_del_(SR_STATE_OBJ_PREVSRV, NULL);
      sr_state->previous_srv = (sr_srv_t *) data;
    }
    break;
  case SR_STATE_OBJ_VALID_AFTER:
    sr_state->valid_after = *((time_t *) data);
    break;
  /* It's not allowed to change the phase nor the full commitments map from
   * the state. The phase is decided during a strict process post voting and
   * the commits should be put individually. */
  case SR_STATE_OBJ_PHASE:
  case SR_STATE_OBJ_COMMITS:
  default:
    tor_assert(0);
  }
}
Exemplo n.º 2
0
/* Query state using an <b>action</b> for an object type <b>obj_type</b>.
 * The <b>data</b> pointer needs to point to an object that the action needs
 * to use and if anything is required to be returned, it is stored in
 * <b>out</b>.
 *
 * This mechanism exists so we have one single point where we synchronized
 * our memory state with our disk state for every actions that changes it.
 * We then trigger a write on disk immediately.
 *
 * This should be the only entry point to our memory state. It's used by all
 * our state accessors and should be in the future. */
static void
state_query(sr_state_action_t action, sr_state_object_t obj_type,
            void *data, void **out)
{
  switch (action) {
  case SR_STATE_ACTION_GET:
    *out = state_query_get_(obj_type, data);
    break;
  case SR_STATE_ACTION_PUT:
    state_query_put_(obj_type, data);
    break;
  case SR_STATE_ACTION_DEL:
    state_query_del_(obj_type, data);
    break;
  case SR_STATE_ACTION_DEL_ALL:
    state_query_del_all_(obj_type);
    break;
  case SR_STATE_ACTION_SAVE:
    /* Only trigger a disk state save. */
    break;
  default:
    tor_assert(0);
  }

  /* If the action actually changes the state, immediately save it to disk.
   * The following will sync the state -> disk state and then save it. */
  if (action != SR_STATE_ACTION_GET) {
    disk_state_save_to_disk();
  }
}