static void do_get(void* arg) { PortState* state = (PortState*)arg; // Unpack key from work buffer // table - 8 bytes // keysz - 1 byte // key - variable ib_id_t table ; UNPACK_INT(state->work_buffer, 0, &table); unsigned char keysz = UNPACK_BYTE(state->work_buffer, sizeof(table)); char* key = UNPACK_BLOB(state->work_buffer, sizeof(table)+1); ib_trx_t txn = ib_trx_begin(IB_TRX_REPEATABLE_READ); ib_crsr_t cursor; FAIL_ON_ERROR(ib_cursor_open_table_using_id(table, txn, &cursor), ROLLBACK_RETURN(txn)); ib_tpl_t key_tuple = ib_clust_search_tuple_create(cursor); ib_col_set_value(key_tuple, KEY_COL, key, keysz); int searchloc; ib_err_t error = ib_cursor_moveto(cursor, key_tuple, IB_CUR_GE, &searchloc); // Drop the key tuple -- cursor is at desired location ib_tuple_delete(key_tuple); // If we encountered an error, bail if (error != DB_SUCCESS && error != DB_RECORD_NOT_FOUND && error != DB_END_OF_INDEX) { ib_cursor_close(cursor); send_error_str(state, ib_strerror(error)); ROLLBACK_RETURN(txn); } // Found it, read the value and send back to caller if (searchloc == 0) { ib_tpl_t tuple = ib_clust_read_tuple_create(cursor); // TODO: May need better error handling here FAIL_ON_ERROR(ib_cursor_read_row(cursor, tuple), { ib_tuple_delete(tuple); ib_cursor_close(cursor); ROLLBACK_RETURN(txn); });
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); }
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])); }