static NEOERR *unpack_row (WDB *wdb, void *rdata, int dlen, WDBRow *row)
{
  unsigned char *data = rdata;
  int version, n;
  int count, x, ondisk_index, type, d_int, inmem_index;
  char *s;

  n = 0;

  UNPACK_UB4(data, dlen, n, version);

  switch (version)
  {
    case PACK_VERSION_1:
      UNPACK_UB4(data, dlen, n, count);
      for (x = 0; x<count; x++)
      {
	UNPACK_UB4 (data, dlen, n, ondisk_index);
	UNPACK_BYTE (data, dlen, n, type);
	inmem_index = (int) skipSearch (wdb->ondisk, ondisk_index, NULL);

	switch (type)
	{
	  case WDB_TYPE_INT:
	    UNPACK_UB4 (data, dlen, n, d_int);
	    if (inmem_index != 0)
	      row->data[inmem_index-1] = (void *) d_int;
	    break;
	  case WDB_TYPE_STR:
	    UNPACK_STRING (data, dlen, n, s);
	    if (inmem_index != 0)
	      row->data[inmem_index-1] = s;
	    break;
	  default:
	    return nerr_raise (NERR_ASSERT, "Unknown type %d for col %d", type, ondisk_index);
	}
      }
      break;
    default:
      return nerr_raise (NERR_ASSERT, "Unknown version %d", version);
  }
      
  return STATUS_OK;
pack_err:
  return nerr_raise(NERR_PARSE, "Unable to unpack row %s", row->key_value);
}
Exemple #2
0
static void do_init_table(void* arg)
{
    PortState* state = (PortState*)arg;

    unsigned char fmt_code = UNPACK_BYTE(state->work_buffer, 0);
    // Unpack the table name (pre-formatted to be Database/TableName)
    char* table = UNPACK_STRING(state->work_buffer, 1);
    ib_id_t table_id;
    ib_tbl_fmt_t table_fmt;
    
    switch(fmt_code)
    {
      case FORMAT_REDUNDANT:
        table_fmt = IB_TBL_REDUNDANT;
        break;
      case FORMAT_COMPACT:
        table_fmt = IB_TBL_COMPACT;
        break;
      case FORMAT_DYNAMIC:
        table_fmt = IB_TBL_DYNAMIC;
        break;
      case FORMAT_COMPRESSED:
        table_fmt = IB_TBL_COMPRESSED;
        break;
      default:
        send_error_atom(state, "bad_format");
        return;
    }

    // If the table doesn't exist, create it
    if (ib_table_get_id(table, &table_id) != DB_SUCCESS)
    {
        // Start a txn for schema access and be sure to make it serializable
        ib_trx_t txn = ib_trx_begin(IB_TRX_SERIALIZABLE);
        ib_schema_lock_exclusive(txn);

        // Create the table schema
        ib_tbl_sch_t schema;
        ib_table_schema_create(table, &schema, table_fmt, 0);
        ib_table_schema_add_col(schema, "key", IB_VARBINARY, IB_COL_NONE, 0, 255);
        ib_table_schema_add_col(schema, "value", IB_BLOB, IB_COL_NONE, 0, 0);

        // Create primary index on key
        ib_idx_sch_t index;
        ib_table_schema_add_index(schema, "PRIMARY_KEY", &index);
        ib_index_schema_add_col(index, "key", 0);
        ib_index_schema_set_clustered(index);

        // Create the actual table
        ib_err_t rc = ib_table_create(txn, schema, &table_id);

        // Release the schema -- doesn't matter if table was created or not at this point
        ib_schema_unlock(txn);

        if (rc == DB_SUCCESS)
        {
            // Commit changes to schema (if any)
            ib_trx_commit(txn);
        }
        else
        {
            // Failed to create table -- rollback and exit
            ib_trx_rollback(txn);
            send_error_str(state, ib_strerror(rc));
            return;
        }
    }

    // Guaranteed at this point to have a valid table_id
    ErlDrvTermData response[] = { ERL_DRV_ATOM,   driver_mk_atom("innostore_ok"),
                                  ERL_DRV_BUF2BINARY, (ErlDrvTermData)&table_id,
                                                      (ErlDrvUInt)sizeof(table_id),
                                  ERL_DRV_TUPLE, 2};
    driver_send_term(state->port, state->port_owner, response,
                     sizeof(response) / sizeof(response[0]));
}
Exemple #3
0
static void do_set_cfg(void* arg)
{
    PortState* state = (PortState*)arg;

    erl_drv_mutex_lock(G_ENGINE_STATE_LOCK);
    if (G_ENGINE_STATE == ENGINE_STOPPED)
    {
        char* key   = UNPACK_STRING(state->work_buffer, 0);
        const char* value = UNPACK_STRING(state->work_buffer, strlen(key)+1);

        if (strcmp(key, "error_log") == 0)
        {
            if (set_log_file(value) == 0)
            {
                send_ok(state);
            }
            else
            {
                send_error_atom(state, "einval");
            }
        }
        else
        {
            // Check the expected type of the provided key so as to 1. validate it's a good key
            // and 2. know what setter to use.
            ib_cfg_type_t key_type;
            ib_err_t error = ib_cfg_var_get_type(key, &key_type);
            if (error == DB_SUCCESS)
            {
                if (key_type == IB_CFG_TEXT)
                {
                    // HACK: Semantics of setting a text configuration value for innodb changed
                    // to be pointer assignment (from copy) for vsn 1.0.6.6750. So, we strdup the
                    // value to ensure everything works as expected.
                    // TODO: Setup some sort of list of strdup'd values to ensure they all get
                    // cleaned up properly. In typical usage, this isn't going to be a problem
                    // as you only initialize once per run, but it bothers me just the same.
                    error = ib_cfg_set(key, strdup(value));
                }
                else
                {
                    ErlDrvUInt value_i;
                    UNPACK_INT(state->work_buffer, strlen(key)+1, &value_i);
                    error = ib_cfg_set(key, value_i);
                }

            }

            if (error == DB_SUCCESS)
            {
                send_ok(state);
            }
            else
            {
                send_error_str(state, ib_strerror(error));
            }
        }
    }
    else
    {
        send_error_atom(state, "starting");
    }

    erl_drv_mutex_unlock(G_ENGINE_STATE_LOCK);
}