/** * Delete an item from the cache * @param key the key of the item to delete * @param nkey the length of the key * @return true if the item was deleted from the cache */ bool delete_item(const void* key, size_t nkey) { ib_trx_t transaction= ib_trx_begin(IB_TRX_REPEATABLE_READ); bool ret= do_delete_item(transaction, key, nkey); if (ret) { /* object found. commit transaction */ ib_err_t error= ib_trx_commit(transaction); if (error != DB_SUCCESS) { fprintf(stderr, "Failed to delete key:\n\t%s\n", ib_strerror(error)); ret= false; } } else { ib_err_t error= ib_trx_rollback(transaction); if (error != DB_SUCCESS) fprintf(stderr, "Failed to roll back the transaction:\n\t%s\n", ib_strerror(error)); } return ret; }
static void innostore_drv_stop(ErlDrvData handle) { PortState* state = (PortState*)handle; // Grab the worker lock, in case we have an job running erl_drv_mutex_lock(state->worker_lock); // Signal the shutdown and wait until the current operation has completed state->shutdown_flag = 1; erl_drv_cond_signal(state->worker_cv); while (state->op) { erl_drv_cond_wait(state->worker_cv, state->worker_lock); } // If the port state is not marked as READY, close the cursor and abort the txn if (state->port_state != STATE_READY) { ib_cursor_close(state->cursor); ib_trx_rollback(state->txn); } // No pending jobs and we have the lock again -- join our worker thread erl_drv_cond_signal(state->worker_cv); erl_drv_mutex_unlock(state->worker_lock); erl_drv_thread_join(state->worker, 0); // Cleanup erl_drv_cond_destroy(state->worker_cv); erl_drv_mutex_destroy(state->worker_lock); driver_free(handle); }
/** * Flush the entire cache * @param when when the cache should be flushed (0 == immediately) */ void flush(uint32_t when __attribute__((unused))) { /* @TODO implement support for when != 0 */ ib_trx_t transaction= ib_trx_begin(IB_TRX_REPEATABLE_READ); ib_crsr_t cursor= NULL; ib_err_t err= DB_SUCCESS; checked(ib_cursor_open_table(tablename, transaction, &cursor)); checked(ib_cursor_first(cursor)); checked(ib_cursor_lock(cursor, IB_LOCK_X)); do { checked(ib_cursor_delete_row(cursor)); } while ((err= ib_cursor_next(cursor)) == DB_SUCCESS); if (err != DB_END_OF_INDEX) { fprintf(stderr, "Failed to flush the cache: %s\n", ib_strerror(err)); goto error_exit; } ib_cursor_close(cursor); cursor= NULL; checked(ib_trx_commit(transaction)); return; error_exit: if (cursor != NULL) ib_cursor_close(cursor); ib_err_t error= ib_trx_rollback(transaction); if (error != DB_SUCCESS) fprintf(stderr, "Failed to roll back the transaction:\n\t%s\n", ib_strerror(error)); }
/********************************************************************* CREATE TABLE T(C1 INT, C2 VARCHAR(10), C3 BLOB); */ static ib_err_t create_table( /*=========*/ const char* dbname, /*!< in: database name */ const char* name) /*!< in: table name */ { ib_trx_t ib_trx; ib_id_t table_id = 0; ib_err_t err = DB_SUCCESS; ib_tbl_sch_t ib_tbl_sch = NULL; char table_name[IB_MAX_TABLE_NAME_LEN]; #ifdef __WIN__ sprintf(table_name, "%s/%s", dbname, name); #else snprintf(table_name, sizeof(table_name), "%s/%s", dbname, name); #endif /* Pass a table page size of 0, ie., use default page size. */ err = ib_table_schema_create( table_name, &ib_tbl_sch, IB_TBL_COMPACT, 0); assert(err == DB_SUCCESS); err = ib_table_schema_add_col( ib_tbl_sch, "c1", IB_INT, IB_COL_NONE, 0, sizeof(ib_i32_t)); assert(err == DB_SUCCESS); err = ib_tbl_sch_add_varchar_col(ib_tbl_sch, "c2", 10); assert(err == DB_SUCCESS); err = ib_tbl_sch_add_blob_col(ib_tbl_sch, "c3"); assert(err == DB_SUCCESS); /* create table */ ib_trx = ib_trx_begin(IB_TRX_REPEATABLE_READ); err = ib_schema_lock_exclusive(ib_trx); assert(err == DB_SUCCESS); err = ib_table_create(ib_trx, ib_tbl_sch, &table_id); if (err == DB_SUCCESS) { err = ib_trx_commit(ib_trx); } else { fprintf(stderr, "Table: %s create failed: %s\n", table_name, ib_strerror(err)); err = ib_trx_rollback(ib_trx); } assert(err == DB_SUCCESS); if (ib_tbl_sch != NULL) { ib_table_schema_delete(ib_tbl_sch); } return(err); }
/** * Get an item from the engine * @param key the key to grab * @param nkey number of bytes in the key * @return pointer to the item if found */ struct item* get_item(const void* key, size_t nkey) { ib_trx_t transaction= ib_trx_begin(IB_TRX_SERIALIZABLE); struct item* ret= do_get_item(transaction, key, nkey); ib_err_t error= ib_trx_rollback(transaction); if (error != DB_SUCCESS) fprintf(stderr, "Failed to roll back the transaction:\n\t%s\n", ib_strerror(error)); return ret; }
/********************************************************************* Tests creating a index with a name that InnoDB uses for temporary indexs @return DB_SUCCESS or error code */ static ib_err_t test_create_temp_index( /*=============*/ const char* dbname, const char* name, /*!< in: table name */ const char* col_name) /*!< in: column name */ { ib_err_t err; ib_trx_t ib_trx; ib_id_t index_id = 0; ib_idx_sch_t ib_idx_sch = NULL; char index_name[IB_MAX_TABLE_NAME_LEN]; char table_name[IB_MAX_TABLE_NAME_LEN]; #ifdef __WIN__ sprintf(table_name, "%s/%s", dbname, name); #else snprintf(table_name, sizeof(table_name), "%s/%s", dbname, name); #endif ib_trx = ib_trx_begin(IB_TRX_REPEATABLE_READ); err = ib_schema_lock_exclusive(ib_trx); assert(err == DB_SUCCESS); #ifdef __WIN__ sprintf(index_name, "%c%s_%s", TEMP_INDEX_PREFIX, table_name, col_name); #else snprintf(index_name, sizeof(index_name), "%c%s_%s", TEMP_INDEX_PREFIX, table_name, col_name); #endif err = ib_index_schema_create( ib_trx, index_name, table_name, &ib_idx_sch); assert(err == DB_INVALID_INPUT); if (ib_idx_sch != NULL) { ib_index_schema_delete(ib_idx_sch); ib_idx_sch = NULL; } if (err == DB_SUCCESS) { err = ib_trx_commit(ib_trx); } else { err = ib_trx_rollback(ib_trx); } assert(err == DB_SUCCESS); return(err); }
/********************************************************************* Create a secondary indexes on a table. @return DB_SUCCESS or error code */ static ib_err_t create_sec_index( /*=============*/ const char* table_name, /*!< in: table name */ const char* col_name, /*!< in: column name */ int prefix_len) /*!< in: prefix index length */ { ib_err_t err; ib_trx_t ib_trx; ib_id_t index_id = 0; ib_idx_sch_t ib_idx_sch = NULL; char index_name[IB_MAX_TABLE_NAME_LEN]; ib_trx = ib_trx_begin(IB_TRX_REPEATABLE_READ); err = ib_schema_lock_exclusive(ib_trx); assert(err == DB_SUCCESS); #ifdef __WIN__ sprintf(index_name, "%s_%s", table_name, col_name); #else snprintf(index_name, sizeof(index_name), "%s_%s", table_name, col_name); #endif err = ib_index_schema_create( ib_trx, index_name, table_name, &ib_idx_sch); assert(err == DB_SUCCESS); err = ib_index_schema_add_col(ib_idx_sch, col_name, prefix_len); assert(err == DB_SUCCESS); err = ib_index_create(ib_idx_sch, &index_id); if (ib_idx_sch != NULL) { ib_index_schema_delete(ib_idx_sch); ib_idx_sch = NULL; } if (err == DB_SUCCESS) { err = ib_trx_commit(ib_trx); } else { err = ib_trx_rollback(ib_trx); } assert(err == DB_SUCCESS); return(err); }
/** * Create the database schema. * @return true if the database schema was created without any problems * false otherwise. */ static bool create_schema(void) { ib_tbl_sch_t schema= NULL; ib_idx_sch_t dbindex= NULL; if (ib_database_create("memcached") != IB_TRUE) { fprintf(stderr, "Failed to create database\n"); return false; } ib_trx_t transaction= ib_trx_begin(IB_TRX_SERIALIZABLE); ib_id_t table_id; checked(ib_table_schema_create(tablename, &schema, IB_TBL_COMPACT, 0)); checked(ib_table_schema_add_col(schema, "key", IB_BLOB, IB_COL_NOT_NULL, 0, 32767)); checked(ib_table_schema_add_col(schema, "data", IB_BLOB, IB_COL_NONE, 0, 1024*1024)); checked(ib_table_schema_add_col(schema, "flags", IB_INT, IB_COL_UNSIGNED, 0, 4)); checked(ib_table_schema_add_col(schema, "cas", IB_INT, IB_COL_UNSIGNED, 0, 8)); checked(ib_table_schema_add_col(schema, "exp", IB_INT, IB_COL_UNSIGNED, 0, 4)); checked(ib_table_schema_add_index(schema, "PRIMARY_KEY", &dbindex)); checked(ib_index_schema_add_col(dbindex, "key", 0)); checked(ib_index_schema_set_clustered(dbindex)); checked(ib_schema_lock_exclusive(transaction)); checked(ib_table_create(transaction, schema, &table_id)); checked(ib_trx_commit(transaction)); ib_table_schema_delete(schema); return true; error_exit: /* @todo release resources! */ { ib_err_t error= ib_trx_rollback(transaction); if (error != DB_SUCCESS) fprintf(stderr, "Failed to roll back the transaction:\n\t%s\n", ib_strerror(error)); } return false; }
/** * Store an item in the databse * * @param item the item to store */ void put_item(struct item* item) { ib_trx_t transaction= ib_trx_begin(IB_TRX_SERIALIZABLE); if (do_put_item(transaction, item)) { ib_err_t error= ib_trx_commit(transaction); if (error != DB_SUCCESS) { fprintf(stderr, "Failed to store key:\n\t%s\n", ib_strerror(error)); } } else { ib_err_t error= ib_trx_rollback(transaction); if (error != DB_SUCCESS) fprintf(stderr, "Failed to roll back the transaction:\n\t%s\n", ib_strerror(error)); } }
/********************************************************************* CREATE TABLE T( vchar VARCHAR(128), blob VARCHAR(n), count INT, PRIMARY KEY(vchar); */ static ib_err_t create_table( /*=========*/ const char* dbname, /*!< in: database name */ const char* name) /*!< in: table name */ { ib_trx_t ib_trx; ib_id_t table_id = 0; ib_err_t err = DB_SUCCESS; ib_tbl_sch_t ib_tbl_sch = NULL; ib_idx_sch_t ib_idx_sch = NULL; ib_tbl_fmt_t tbl_fmt = IB_TBL_COMPACT; char table_name[IB_MAX_TABLE_NAME_LEN]; #ifdef __WIN__ sprintf(table_name, "%s/%s", dbname, name); #else snprintf(table_name, sizeof(table_name), "%s/%s", dbname, name); #endif if (page_size > 0) { tbl_fmt = IB_TBL_COMPRESSED; printf("Creating compressed table with page size %d\n", page_size); } err = ib_table_schema_create( table_name, &ib_tbl_sch, tbl_fmt, page_size); assert(err == DB_SUCCESS); err = ib_table_schema_add_col( ib_tbl_sch, "vchar", IB_VARCHAR, IB_COL_NONE, 0, 128); assert(err == DB_SUCCESS); err = ib_table_schema_add_col( ib_tbl_sch, "blob", IB_BLOB, IB_COL_NONE, 0, 0); assert(err == DB_SUCCESS); err = ib_table_schema_add_col( ib_tbl_sch, "count", IB_INT, IB_COL_UNSIGNED, 0, 4); assert(err == DB_SUCCESS); err = ib_table_schema_add_index(ib_tbl_sch, "PRIMARY", &ib_idx_sch); assert(err == DB_SUCCESS); /* Set prefix length to 0. */ err = ib_index_schema_add_col( ib_idx_sch, "vchar", 0); assert(err == DB_SUCCESS); err = ib_index_schema_set_clustered(ib_idx_sch); assert(err == DB_SUCCESS); err = ib_index_schema_set_unique(ib_idx_sch); assert(err == DB_SUCCESS); /* create table */ ib_trx = ib_trx_begin(IB_TRX_REPEATABLE_READ); err = ib_schema_lock_exclusive(ib_trx); assert(err == DB_SUCCESS); err = ib_table_create(ib_trx, ib_tbl_sch, &table_id); if (err != DB_SUCCESS) { fprintf(stderr, "Warning: table create failed: %s\n", ib_strerror(err)); err = ib_trx_rollback(ib_trx); } else { err = ib_trx_commit(ib_trx); } assert(err == DB_SUCCESS); if (ib_tbl_sch != NULL) { ib_table_schema_delete(ib_tbl_sch); } return(err); }
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])); }