diff --git a/.gitignore b/.gitignore index d6e6b2e..60eb957 100644 --- a/.gitignore +++ b/.gitignore @@ -74,3 +74,4 @@ third_party/luajit/lib/ third_party/luajit/share/ third_party/luajit/tmp/ sysbench/lua/internal/sysbench.lua.h +sysbench/lua/internal/sysbench.sql.lua.h diff --git a/configure.ac b/configure.ac index 3047483..1fbf2c3 100644 --- a/configure.ac +++ b/configure.ac @@ -306,6 +306,10 @@ AX_TLS([], # __attribute__((format...)) function attribute AX_GCC_FUNC_ATTRIBUTE(format) +# Define HAVE_FUNC_ATTRIBUTE_UNUSED if compiler supports the +# __attribute__((unused)) function attribute +AX_GCC_FUNC_ATTRIBUTE(unused) + if test "$enable_largefile" = yes; then AC_SYS_LARGEFILE fi diff --git a/sysbench/Makefile.am b/sysbench/Makefile.am index 27c6541..065886d 100644 --- a/sysbench/Makefile.am +++ b/sysbench/Makefile.am @@ -47,8 +47,9 @@ endif sysbench_SOURCES = sysbench.c sysbench.h sb_timer.c sb_timer.h \ sb_options.c sb_options.h sb_logger.c sb_logger.h sb_list.h db_driver.h \ db_driver.c sb_histogram.c sb_histogram.h sb_rand.c sb_rand.h \ -sb_thread.c sb_thread.h sb_barrier.c sb_barrier.h sb_global.h sb_lua.c \ -sb_lua.h lua/internal/sysbench.lua.h sb_util.h xoroshiro128plus.h +sb_thread.c sb_thread.h sb_barrier.c sb_barrier.h sb_lua.c \ +sb_lua.h lua/internal/sysbench.lua.h lua/internal/sysbench.sql.lua.h sb_util.h \ +xoroshiro128plus.h sysbench_LDADD = tests/fileio/libsbfileio.a tests/threads/libsbthreads.a \ tests/memory/libsbmemory.a tests/cpu/libsbcpu.a \ diff --git a/sysbench/db_driver.c b/sysbench/db_driver.c index 0c5ebbc..cff165e 100644 --- a/sysbench/db_driver.c +++ b/sysbench/db_driver.c @@ -25,6 +25,8 @@ #endif #ifdef STDC_HEADERS # include +# include +# include #endif #ifdef HAVE_STRING_H # include @@ -33,6 +35,8 @@ # include #endif +#include + #include "db_driver.h" #include "sb_list.h" #include "sb_histogram.h" @@ -44,42 +48,38 @@ /* How many rows to insert before COMMITs (used in bulk insert) */ #define ROWS_BEFORE_COMMIT 1000 -typedef struct { - uint64_t read_ops; - uint64_t write_ops; - uint64_t other_ops; - uint64_t transactions; - uint64_t errors; - uint64_t reconnects; - char pad[CK_MD_CACHELINE - sizeof(uint64_t) * 6]; -} db_thread_stat_t; - /* Global variables */ -db_globals_t db_globals; +db_globals_t db_globals CK_CC_CACHELINE; + +/* per-thread stats */ +db_stats_t *thread_stats CK_CC_CACHELINE; /* Used in intermediate reports */ -static unsigned long last_transactions; -static unsigned long last_read_ops; -static unsigned long last_write_ops; -static unsigned long last_errors; -static unsigned long last_reconnects; +static db_stats_t last_stats; /* Static variables */ static sb_list_t drivers; /* list of available DB drivers */ -static db_thread_stat_t *thread_stats; /* per-thread stats */ + +static uint8_t stats_enabled; + +static bool db_global_initialized; +static pthread_once_t db_global_once = PTHREAD_ONCE_INIT; /* Timers used in debug mode */ static sb_timer_t *exec_timers; static sb_timer_t *fetch_timers; +pthread_mutex_t print_stats_mutex; + /* Static functions */ static int db_parse_arguments(void); +#if 0 static void db_free_row(db_row_t *); +#endif static int db_bulk_do_insert(db_conn_t *, int); -static db_query_type_t db_get_query_type(const char *); -static void db_update_thread_stats(int, db_query_type_t); static void db_reset_stats(void); +static int db_free_results_int(db_conn_t *con); /* DB layer arguments */ @@ -101,10 +101,31 @@ static sb_arg_t db_args[] = {NULL, NULL, SB_ARG_TYPE_NULL, NULL} }; +static inline uint64_t db_stat_val(db_stats_t stats, db_stat_type_t type) +{ + return ck_pr_load_64(&stats[type]); +} + +static inline void db_stat_merge(db_stats_t dst, db_stats_t src) +{ + for (size_t i = 0; i < DB_STAT_MAX; i++) + ck_pr_add_64(&dst[i], db_stat_val(src, i)); +} + +static inline void db_stat_copy(db_stats_t dst, db_stats_t src) +{ + for (size_t i = 0; i < DB_STAT_MAX; i++) + ck_pr_store_64(&dst[i], db_stat_val(src, i)); +} + +static inline uint64_t db_stat_diff(db_stats_t a, db_stats_t b, + db_stat_type_t type) +{ + return db_stat_val(a, type) - db_stat_val(b, type); +} /* Register available database drivers and command line arguments */ - int db_register(void) { sb_list_item_t *pos; @@ -137,6 +158,8 @@ int db_register(void) drv = SB_LIST_ENTRY(pos, db_driver_t, listitem); if (drv->args != NULL) sb_register_arg_set(drv->args); + drv->initialized = false; + pthread_mutex_init(&drv->mutex, NULL); } /* Register general command line arguments for DB API */ sb_register_arg_set(db_args); @@ -173,27 +196,82 @@ void db_print_help(void) } +static void enable_print_stats(void) +{ + ck_pr_fence_store(); + ck_pr_store_8(&stats_enabled, 1); +} + +static void disable_print_stats(void) +{ + ck_pr_store_8(&stats_enabled, 0); + ck_pr_fence_store(); +} + + +static bool check_print_stats(void) +{ + bool rc = ck_pr_load_8(&stats_enabled) == 1; + ck_pr_fence_load(); + + return rc; +} + +/* Initialize per-thread stats */ + +int db_thread_stat_init(void) +{ + thread_stats = malloc(sb_globals.num_threads * sizeof(db_stats_t)); + + return thread_stats == NULL; +} + + +static void db_init(void) +{ + if (SB_LIST_IS_EMPTY(&drivers)) + { + log_text(LOG_FATAL, "No DB drivers available"); + return; + } + + if (db_parse_arguments()) + return; + + pthread_mutex_init(&print_stats_mutex, NULL); + + /* Initialize timers if in debug mode */ + if (db_globals.debug) + { + exec_timers = (sb_timer_t *) malloc(sb_globals.num_threads * + sizeof(sb_timer_t)); + fetch_timers = (sb_timer_t *) malloc(sb_globals.num_threads * + sizeof(sb_timer_t)); + } + + db_reset_stats(); + + enable_print_stats(); + + db_global_initialized = true; +} + /* Initialize a driver specified by 'name' and return a handle to it If NULL is passed as a name, then use the driver passed in --db-driver command line option */ - -db_driver_t *db_init(const char *name) +db_driver_t *db_create(const char *name) { db_driver_t *drv = NULL; db_driver_t *tmp; sb_list_item_t *pos; - if (SB_LIST_IS_EMPTY(&drivers)) - { - log_text(LOG_FATAL, "No DB drivers available"); - return NULL; - } + pthread_once(&db_global_once, db_init); - if (db_parse_arguments()) - return NULL; + if (!db_global_initialized) + goto err; if (name == NULL && db_globals.driver == NULL) { @@ -205,7 +283,7 @@ db_driver_t *db_init(const char *name) else { log_text(LOG_FATAL, "no database driver specified"); - return NULL; + goto err; } } else @@ -227,37 +305,46 @@ db_driver_t *db_init(const char *name) if (drv == NULL) { log_text(LOG_FATAL, "invalid database driver name: '%s'", name); - return NULL; + goto err; } - /* Initialize database driver */ - if (drv->ops.init()) - return NULL; - - /* Initialize per-thread stats */ - thread_stats = (db_thread_stat_t *)malloc(sb_globals.num_threads * - sizeof(db_thread_stat_t)); - if (thread_stats == NULL) - return NULL; - - /* Initialize timers if in debug mode */ - if (db_globals.debug) + /* Initialize database driver only once */ + pthread_mutex_lock(&drv->mutex); + if (!drv->initialized) { - exec_timers = (sb_timer_t *) malloc(sb_globals.num_threads * - sizeof(sb_timer_t)); - fetch_timers = (sb_timer_t *) malloc(sb_globals.num_threads * - sizeof(sb_timer_t)); + if (drv->ops.init()) + { + pthread_mutex_unlock(&drv->mutex); + goto err; + } + drv->initialized = true; } + pthread_mutex_unlock(&drv->mutex); - db_reset_stats(); + if (drv->ops.thread_init != NULL && drv->ops.thread_init(sb_tls_thread_id)) + { + log_text(LOG_FATAL, "thread-local driver initialization failed."); + return NULL; + } return drv; + +err: + return NULL; } +/* Deinitialize a driver object */ + +int db_destroy(db_driver_t *drv) +{ + if (drv->ops.thread_done != NULL) + return drv->ops.thread_done(sb_tls_thread_id); + + return 0; +} /* Describe database capabilities */ - int db_describe(db_driver_t *drv, drv_caps_t *caps) { if (drv->ops.describe == NULL) @@ -270,15 +357,21 @@ int db_describe(db_driver_t *drv, drv_caps_t *caps) /* Connect to database */ -db_conn_t *db_connect(db_driver_t *drv) +db_conn_t *db_connection_create(db_driver_t *drv) { db_conn_t *con; + SB_COMPILE_TIME_ASSERT(sizeof(db_conn_t) % CK_MD_CACHELINE == 0); + con = (db_conn_t *)calloc(1, sizeof(db_conn_t)); if (con == NULL) return NULL; - + con->driver = drv; + con->state = DB_CONN_READY; + + db_set_thread(con, sb_tls_thread_id); + if (drv->ops.connect(con)) { free(con); @@ -300,43 +393,62 @@ void db_set_thread(db_conn_t *con, int thread_id) /* Disconnect from database */ -int db_disconnect(db_conn_t *con) +int db_connection_close(db_conn_t *con) { int rc; - db_driver_t *drv; + db_driver_t *drv = con->driver; - drv = con->driver; - if (drv == NULL) - return 1; + if (con->state == DB_CONN_INVALID) + { + log_text(LOG_WARNING, "attempt to close an already closed connection"); + return 0; + } rc = drv->ops.disconnect(con); - free(con); + + con->state = DB_CONN_INVALID; return rc; } +/* Disconnect and release memory allocated by a connection object */ + + +void db_connection_free(db_conn_t *con) +{ + if (con->state != DB_CONN_INVALID) + db_connection_close(con); + + free(con); +} + + /* Prepare statement */ -db_stmt_t *db_prepare(db_conn_t *con, const char *query) +db_stmt_t *db_prepare(db_conn_t *con, const char *query, size_t len) { db_stmt_t *stmt; + if (con->state == DB_CONN_INVALID) + { + log_text(LOG_ALERT, "attempt to use an already closed connection"); + return NULL; + } + stmt = (db_stmt_t *)calloc(1, sizeof(db_stmt_t)); if (stmt == NULL) return NULL; stmt->connection = con; - if (con->driver->ops.prepare(stmt, query)) + if (con->driver->ops.prepare(stmt, query, len)) { free(stmt); return NULL; } - stmt->type = db_get_query_type(query); - return stmt; } @@ -344,12 +456,15 @@ db_stmt_t *db_prepare(db_conn_t *con, const char *query) /* Bind parameters for prepared statement */ -int db_bind_param(db_stmt_t *stmt, db_bind_t *params, unsigned int len) +int db_bind_param(db_stmt_t *stmt, db_bind_t *params, size_t len) { db_conn_t *con = stmt->connection; - if (con == NULL || con->driver == NULL) + if (con->state == DB_CONN_INVALID) + { + log_text(LOG_ALERT, "attempt to use an already closed connection"); return 1; + } return con->driver->ops.bind_param(stmt, params, len); } @@ -358,12 +473,15 @@ int db_bind_param(db_stmt_t *stmt, db_bind_t *params, unsigned int len) /* Bind results for prepared statement */ -int db_bind_result(db_stmt_t *stmt, db_bind_t *results, unsigned int len) +int db_bind_result(db_stmt_t *stmt, db_bind_t *results, size_t len) { db_conn_t *con = stmt->connection; - if (con == NULL || con->driver == NULL) + if (con->state == DB_CONN_INVALID) + { + log_text(LOG_ALERT, "attempt to use an already closed connection"); return 1; + } return con->driver->ops.bind_result(stmt, results, len); } @@ -372,72 +490,54 @@ int db_bind_result(db_stmt_t *stmt, db_bind_t *results, unsigned int len) /* Execute prepared statement */ -db_result_set_t *db_execute(db_stmt_t *stmt) +db_result_t *db_execute(db_stmt_t *stmt) { db_conn_t *con = stmt->connection; - db_result_set_t *rs = &con->rs; + db_result_t *rs = &con->rs; + int rc; - if (con == NULL || con->driver == NULL) + if (con->state == DB_CONN_INVALID) + { + log_text(LOG_ALERT, "attempt to use an already closed connection"); + return NULL; + } + else if (con->state == DB_CONN_RESULT_SET && + (rc = db_free_results_int(con)) != 0) { - log_text(LOG_DEBUG, "ERROR: exiting db_execute(), uninitialized connection"); return NULL; } - - memset(rs, 0, sizeof(db_result_set_t)); rs->statement = stmt; - rs->connection = con; con->db_errno = con->driver->ops.execute(stmt, rs); - if (con->db_errno != SB_DB_ERROR_NONE) - { - log_text(LOG_DEBUG, "ERROR: exiting db_execute(), driver's execute method failed"); - if (con->db_errno == SB_DB_ERROR_RECONNECTED) - { - thread_stats[con->thread_id].reconnects++; - con->db_errno = SB_DB_ERROR_RESTART_TRANSACTION; - } - else if (con->db_errno == SB_DB_ERROR_RESTART_TRANSACTION) - thread_stats[con->thread_id].errors++; + db_thread_stat_inc(con->thread_id, rs->stat_type); - return NULL; - } + con->state = DB_CONN_RESULT_SET; - db_update_thread_stats(con->thread_id, stmt->type); - return rs; } -/* Return the number of rows in a result set */ - - -unsigned long long db_num_rows(db_result_set_t *rs) -{ - db_conn_t *con = rs->connection; - - if (con == NULL || con->driver == NULL) - return 0; - - return con->driver->ops.num_rows(rs); -} - - /* Fetch row from result set of a query */ -db_row_t *db_fetch_row(db_result_set_t *rs) +db_row_t *db_fetch_row(db_result_t *rs) { - db_conn_t *con = rs->connection; + db_conn_t *con = SB_CONTAINER_OF(rs, db_conn_t, rs); - /* Is this a result set of a non-prepared statement? */ - if (rs->statement != NULL) + if (con->state == DB_CONN_INVALID) + { + log_text(LOG_ALERT, "attempt to use an already closed connection"); return NULL; - - if (con == NULL || con->driver == NULL) + } + else if (con->state != DB_CONN_RESULT_SET) + { + log_text(LOG_ALERT, "attempt to fetch row from an invalid result set"); return NULL; + } +#if 0 if (rs->row != NULL) db_free_row(rs->row); rs->row = (db_row_t *)calloc(1, sizeof(db_row_t)); @@ -451,39 +551,35 @@ db_row_t *db_fetch_row(db_result_set_t *rs) } return rs->row; +#endif + return NULL; } /* Execute non-prepared statement */ -db_result_set_t *db_query(db_conn_t *con, const char *query) +db_result_t *db_query(db_conn_t *con, const char *query, size_t len) { - db_result_set_t *rs = &con->rs; - - if (con->driver == NULL) - return NULL; + db_result_t *rs = &con->rs; + int rc; - memset(rs, 0, sizeof(db_result_set_t)); - - rs->connection = con; - - con->db_errno = con->driver->ops.query(con, query, rs); - - if (con->db_errno == SB_DB_ERROR_NONE) - db_update_thread_stats(con->thread_id, db_get_query_type(query)); - else + if (con->state == DB_CONN_INVALID) { - if (con->db_errno == SB_DB_ERROR_RECONNECTED) - { - thread_stats[con->thread_id].reconnects++; - con->db_errno = SB_DB_ERROR_RESTART_TRANSACTION; - } - else if (con->db_errno == SB_DB_ERROR_RESTART_TRANSACTION) - thread_stats[con->thread_id].errors++; - + log_text(LOG_ALERT, "attempt to use an already closed connection"); return NULL; } + else if (con->state == DB_CONN_RESULT_SET && + (rc = db_free_results_int(con)) != 0) + { + return NULL; + } + + con->db_errno = con->driver->ops.query(con, query, len, rs); + + db_thread_stat_inc(con->thread_id, rs->stat_type); + + con->state = DB_CONN_RESULT_SET; return rs; } @@ -492,22 +588,39 @@ db_result_set_t *db_query(db_conn_t *con, const char *query) /* Free result set */ -int db_free_results(db_result_set_t *rs) +static int db_free_results_int(db_conn_t *con) { int rc; - db_conn_t *con = rs->connection; - if (con == NULL || con->driver == NULL) - return 1; - - rc = con->driver->ops.free_results(rs); + rc = con->driver->ops.free_results(&con->rs); +#if 0 if (rs->row != NULL) db_free_row(rs->row); +#endif + + con->state = DB_CONN_READY; return rc; } +int db_free_results(db_result_t *rs) +{ + db_conn_t * const con = SB_CONTAINER_OF(rs, db_conn_t, rs); + + if (con->state == DB_CONN_INVALID) + { + log_text(LOG_ALERT, "attempt to use an already closed connection"); + return 0; + } + else if (con->state != DB_CONN_RESULT_SET) + { + log_text(LOG_ALERT, "attempt to free an invalid result set"); + return 0; + } + + return db_free_results_int(con); +} /* Close prepared statement */ @@ -517,13 +630,18 @@ int db_close(db_stmt_t *stmt) int rc; db_conn_t *con; - if (stmt == NULL) - return 1; - con = stmt->connection; - if (con == NULL || con->driver == NULL) - return 1; + if (con->state == DB_CONN_INVALID) + { + log_text(LOG_ALERT, "attempt to use an already closed connection"); + return 0; + } + else if (con->state == DB_CONN_RESULT_SET && con->rs.statement == stmt && + (rc = db_free_results_int(con)) != 0) + { + return 0; + } rc = con->driver->ops.close(stmt); @@ -542,47 +660,42 @@ int db_close(db_stmt_t *stmt) return rc; } +/* Uninitialize DB API */ -/* Store result set from last query */ - - -int db_store_results(db_result_set_t *rs) +void db_done(void) { - db_conn_t *con = rs->connection; + sb_list_item_t *pos; + db_driver_t *drv; - if (con == NULL || con->driver == NULL) - return SB_DB_ERROR_FAILED; + if (!db_global_initialized) + return; - return con->driver->ops.store_results(rs); -} + disable_print_stats(); - -/* Uninitialize driver */ - - -int db_done(db_driver_t *drv) -{ if (db_globals.debug) { free(exec_timers); free(fetch_timers); + + exec_timers = fetch_timers = NULL; } - - if (thread_stats != NULL) + + free(thread_stats); + thread_stats = NULL; + + pthread_mutex_destroy(&print_stats_mutex); + + SB_LIST_FOR_EACH(pos, &drivers) { - free(thread_stats); + drv = SB_LIST_ENTRY(pos, db_driver_t, listitem); + if (drv->initialized) + { + drv->ops.done(); + pthread_mutex_destroy(&drv->mutex); + } } - return drv->ops.done(); -} - - -/* Return the error code for the last function */ - - -db_error_t db_errno(db_conn_t *con) -{ - return con->db_errno; + return; } @@ -674,6 +787,7 @@ int db_print_value(db_bind_t *var, char *buf, int buflen) } +#if 0 /* Free row fetched by db_fetch_row() */ @@ -681,19 +795,27 @@ void db_free_row(db_row_t *row) { free(row); } - +#endif /* Initialize multi-row insert operation */ -int db_bulk_insert_init(db_conn_t *con, const char *query) +int db_bulk_insert_init(db_conn_t *con, const char *query, size_t query_len) { drv_caps_t driver_caps; - size_t query_len; + int rc; + + if (con->state == DB_CONN_INVALID) + { + log_text(LOG_ALERT, "attempt to use an already closed connection"); + return 0; + } + else if (con->state == DB_CONN_RESULT_SET && + (rc = db_free_results_int(con)) != 0) + { + return 0; + } - if (con->driver == NULL) - return 1; - /* Get database capabilites */ if (db_describe(con->driver, &driver_caps)) { @@ -702,7 +824,6 @@ int db_bulk_insert_init(db_conn_t *con, const char *query) } /* Allocate query buffer */ - query_len = strlen(query); if (query_len + 1 > BULK_PACKET_SIZE) { log_text(LOG_FATAL, @@ -720,7 +841,7 @@ int db_bulk_insert_init(db_conn_t *con, const char *query) con->bulk_commit_cnt = 0; strcpy(con->bulk_buffer, query); con->bulk_ptr = query_len; - con->bulk_ptr_orig = query_len; + con->bulk_values = query_len; con->bulk_cnt = 0; return 0; @@ -728,9 +849,20 @@ int db_bulk_insert_init(db_conn_t *con, const char *query) /* Add row to multi-row insert operation */ -int db_bulk_insert_next(db_conn_t *con, const char *query) +int db_bulk_insert_next(db_conn_t *con, const char *query, size_t query_len) { - unsigned int query_len = strlen(query); + int rc; + + if (con->state == DB_CONN_INVALID) + { + log_text(LOG_ALERT, "attempt to use an already closed connection"); + return 0; + } + else if (con->state == DB_CONN_RESULT_SET && + (rc = db_free_results_int(con)) != 0) + { + return 0; + } /* Reserve space for '\0' and ',' (if not the first chunk in @@ -766,14 +898,14 @@ int db_bulk_insert_next(db_conn_t *con, const char *query) /* Do the actual INSERT (and COMMIT, if necessary) */ -int db_bulk_do_insert(db_conn_t *con, int is_last) +static int db_bulk_do_insert(db_conn_t *con, int is_last) { if (!con->bulk_cnt) return 0; - - if (db_query(con, con->bulk_buffer) == NULL) + + if (db_query(con, con->bulk_buffer, con->bulk_ptr) == NULL) return 1; - + if (con->bulk_commit_max != 0) { @@ -781,13 +913,13 @@ int db_bulk_do_insert(db_conn_t *con, int is_last) if (is_last || con->bulk_commit_cnt >= con->bulk_commit_max) { - if (db_query(con, "COMMIT") == NULL) + if (db_query(con, "COMMIT", 6) == NULL) return 1; con->bulk_commit_cnt = 0; } } - con->bulk_ptr = con->bulk_ptr_orig; + con->bulk_ptr = con->bulk_values; con->bulk_cnt = 0; return 0; @@ -795,16 +927,19 @@ int db_bulk_do_insert(db_conn_t *con, int is_last) /* Finish multi-row insert operation */ -void db_bulk_insert_done(db_conn_t *con) +int db_bulk_insert_done(db_conn_t *con) { /* Flush remaining data in buffer, if any */ - db_bulk_do_insert(con, 1); - + if (db_bulk_do_insert(con, 1)) + return 1; + if (con->bulk_buffer != NULL) { free(con->bulk_buffer); con->bulk_buffer = NULL; } + + return 0; } /* Print database-specific test stats */ @@ -815,24 +950,24 @@ void db_print_stats(sb_stat_t type) unsigned int i; sb_timer_t exec_timer; sb_timer_t fetch_timer; - unsigned long read_ops; - unsigned long write_ops; - unsigned long other_ops; - unsigned long transactions; - unsigned long errors; - unsigned long reconnects; + db_stats_t stats; + + SB_COMPILE_TIME_ASSERT(sizeof(db_stats_t) % CK_MD_CACHELINE == 0); + + /* Don't print stats if no drivers are used */ + if (!check_print_stats()) + return; + + /* + Prevent interval and checkpoint reporting threads from using and updating + thread stats concurrently. + */ + pthread_mutex_lock(&print_stats_mutex); /* Summarize per-thread counters */ - read_ops = write_ops = other_ops = transactions = errors = reconnects = 0; + memset(&stats, 0, sizeof(db_stats_t)); for (i = 0; i < sb_globals.num_threads; i++) - { - read_ops += ck_pr_load_64(&thread_stats[i].read_ops); - write_ops += ck_pr_load_64(&thread_stats[i].write_ops); - other_ops += ck_pr_load_64(&thread_stats[i].other_ops); - transactions += ck_pr_load_64(&thread_stats[i].transactions); - errors += ck_pr_load_64(&thread_stats[i].errors); - reconnects += ck_pr_load_64(&thread_stats[i].reconnects); - } + db_stat_merge(stats, thread_stats[i]); if (type == SB_STAT_INTERMEDIATE) { @@ -841,19 +976,28 @@ void db_print_stats(sb_stat_t type) const double percentile_val = sb_histogram_get_pct_intermediate(&sb_latency_histogram, sb_globals.percentile); + const uint64_t reads = db_stat_diff(stats, last_stats, DB_STAT_READ); + const uint64_t writes = db_stat_diff(stats, last_stats, DB_STAT_WRITE); + const uint64_t others = db_stat_diff(stats, last_stats, DB_STAT_OTHER); + const uint64_t errors = db_stat_diff(stats, last_stats, DB_STAT_ERROR); + const uint64_t reconnects = db_stat_diff(stats, last_stats, + DB_STAT_RECONNECT); log_timestamp(LOG_NOTICE, NS2SEC(sb_timer_value(&sb_exec_timer)), - "threads: %d, tps: %4.2f, reads: %4.2f, writes: %4.2f, " - "response time: %4.2fms (%u%%), errors: %4.2f, " - "reconnects: %5.2f", + "threads: %d tps: %4.2f " + "qps: %4.2f (r/w/o: %4.2f/%4.2f/%4.2f) " + "latency: %4.2fms (%u%%) errors/s: %4.2f " + "reconnects/s: %4.2f", sb_globals.num_running, - (transactions - last_transactions) / seconds, - (read_ops - last_read_ops) / seconds, - (write_ops - last_write_ops) / seconds, + db_stat_diff(stats, last_stats, DB_STAT_TRX) / seconds, + (reads + writes + others) / seconds, + reads / seconds, + writes / seconds, + others / seconds, percentile_val, sb_globals.percentile, - (errors - last_errors) / seconds, - (reconnects - last_reconnects) / seconds); + errors / seconds, + reconnects / seconds); if (sb_globals.tx_rate > 0) { pthread_mutex_lock(&event_queue_mutex); @@ -865,41 +1009,40 @@ void db_print_stats(sb_stat_t type) pthread_mutex_unlock(&event_queue_mutex); } - SB_THREAD_MUTEX_LOCK(); - last_transactions = transactions; - last_read_ops = read_ops; - last_write_ops = write_ops; - last_errors = errors; - last_reconnects = reconnects; - SB_THREAD_MUTEX_UNLOCK(); + db_stat_copy(last_stats, stats); - return; + goto end; } else if (type != SB_STAT_CUMULATIVE) - return; + goto end; seconds = NS2SEC(sb_timer_checkpoint(&sb_checkpoint_timer1)); + const uint64_t reads = db_stat_val(stats, DB_STAT_READ); + const uint64_t writes = db_stat_val(stats, DB_STAT_WRITE); + const uint64_t others = db_stat_val(stats, DB_STAT_OTHER); + const uint64_t transactions = db_stat_val(stats, DB_STAT_TRX); + const uint64_t errors = db_stat_val(stats, DB_STAT_ERROR); + const uint64_t reconnects = db_stat_val(stats, DB_STAT_RECONNECT); + log_text(LOG_NOTICE, "OLTP test statistics:"); log_text(LOG_NOTICE, " queries performed:"); - log_text(LOG_NOTICE, " read: %lu", - read_ops); - log_text(LOG_NOTICE, " write: %lu", - write_ops); - log_text(LOG_NOTICE, " other: %lu", - other_ops); - log_text(LOG_NOTICE, " total: %lu", - read_ops + write_ops + other_ops); - log_text(LOG_NOTICE, " transactions: %-6lu" + log_text(LOG_NOTICE, " read: %" PRIu64, + reads); + log_text(LOG_NOTICE, " write: %" PRIu64, + writes); + log_text(LOG_NOTICE, " other: %" PRIu64, + others); + log_text(LOG_NOTICE, " total: %" PRIu64, + reads + writes + others); + log_text(LOG_NOTICE, " transactions: %-6" PRIu64 " (%.2f per sec.)", transactions, transactions / seconds); - log_text(LOG_NOTICE, " read/write requests: %-6lu" - " (%.2f per sec.)", read_ops + write_ops, - (read_ops + write_ops) / seconds); - log_text(LOG_NOTICE, " other operations: %-6lu" - " (%.2f per sec.)", other_ops, other_ops / seconds); - log_text(LOG_NOTICE, " ignored errors: %-6lu" + log_text(LOG_NOTICE, " queries: %-6" PRIu64 + " (%.2f per sec.)", reads + writes + others, + (reads + writes + others) / seconds); + log_text(LOG_NOTICE, " ignored errors: %-6" PRIu64 " (%.2f per sec.)", errors, errors / seconds); - log_text(LOG_NOTICE, " reconnects: %-6lu" + log_text(LOG_NOTICE, " reconnects: %-6" PRIu64 " (%.2f per sec.)", reconnects, reconnects / seconds); if (db_globals.debug) @@ -936,74 +1079,18 @@ void db_print_stats(sb_stat_t type) } db_reset_stats(); + +end: + pthread_mutex_unlock(&print_stats_mutex); } -/* Get query type */ - -db_query_type_t db_get_query_type(const char *query) -{ - while (isspace(*query)) - query++; - - if (!strncasecmp(query, "select", 6)) - return DB_QUERY_TYPE_READ; - - if (!strncasecmp(query, "insert", 6) || - !strncasecmp(query, "update", 6) || - !strncasecmp(query, "delete", 6)) - return DB_QUERY_TYPE_WRITE; - - if (!strncasecmp(query, "commit", 6) || - !strncasecmp(query, "unlock tables", 13)) - return DB_QUERY_TYPE_COMMIT; - - - return DB_QUERY_TYPE_OTHER; -} - -/* Update stats according to type */ - -void db_update_thread_stats(int id, db_query_type_t type) -{ - switch (type) - { - case DB_QUERY_TYPE_READ: - ck_pr_inc_64(&thread_stats[id].read_ops); - break; - case DB_QUERY_TYPE_WRITE: - ck_pr_inc_64(&thread_stats[id].write_ops); - break; - case DB_QUERY_TYPE_COMMIT: - ck_pr_inc_64(&thread_stats[id].other_ops); - ck_pr_inc_64(&thread_stats[id].transactions); - break; - case DB_QUERY_TYPE_OTHER: - ck_pr_inc_64(&thread_stats[id].other_ops); - break; - default: - log_text(LOG_WARNING, "Unknown query type: %d", type); - } -} static void db_reset_stats(void) { unsigned int i; - for(i = 0; i < sb_globals.num_threads; i++) - { - thread_stats[i].read_ops = 0; - thread_stats[i].write_ops = 0; - thread_stats[i].other_ops = 0; - thread_stats[i].transactions = 0; - thread_stats[i].errors = 0; - thread_stats[i].reconnects = 0; - } - - last_transactions = 0; - last_read_ops = 0; - last_write_ops = 0; - last_errors = 0; - last_reconnects = 0; + memset(thread_stats, 0, sb_globals.num_threads * sizeof(db_stats_t)); + memset(last_stats, 0, sizeof(db_stats_t)); /* So that intermediate stats are calculated from the current moment diff --git a/sysbench/db_driver.h b/sysbench/db_driver.h index 026e829..d4b66b1 100644 --- a/sysbench/db_driver.h +++ b/sysbench/db_driver.h @@ -1,5 +1,5 @@ /* Copyright (C) 2004 MySQL AB - Copyright (C) 2004-2016 Alexey Kopytov + Copyright (C) 2004-2017 Alexey Kopytov This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -26,7 +26,8 @@ #include "sysbench.h" #include "sb_list.h" #include "sb_histogram.h" - +#include "sb_util.h" +#include "ck_pr.h" /* Prepared statements usage modes */ @@ -45,8 +46,6 @@ typedef struct unsigned char debug; /* debug flag */ } db_globals_t; -extern db_globals_t db_globals; - /* Driver capabilities definition */ typedef struct @@ -63,10 +62,10 @@ typedef struct typedef enum { - SB_DB_ERROR_NONE, - SB_DB_ERROR_RESTART_TRANSACTION, - SB_DB_ERROR_RECONNECTED, - SB_DB_ERROR_FAILED + DB_ERROR_NONE, /* no error(s) */ + DB_ERROR_IGNORABLE, /* error should be ignored as defined by command + line arguments or a custom error handler */ + DB_ERROR_FATAL /* non-ignorable error */ } db_error_t; @@ -118,32 +117,33 @@ typedef struct struct db_conn; struct db_stmt; -struct db_result_set; +struct db_result; struct db_row; /* Driver operations definition */ typedef int drv_op_init(void); +typedef int drv_op_thread_init(int); typedef int drv_op_describe(drv_caps_t *); typedef int drv_op_connect(struct db_conn *); typedef int drv_op_disconnect(struct db_conn *); -typedef int drv_op_prepare(struct db_stmt *, const char *); -typedef int drv_op_bind_param(struct db_stmt *, db_bind_t *, unsigned int); -typedef int drv_op_bind_result(struct db_stmt *, db_bind_t *, unsigned int ); -typedef int drv_op_execute(struct db_stmt *, struct db_result_set *); -typedef int drv_op_fetch(struct db_result_set *); -typedef int drv_op_fetch_row(struct db_result_set *, struct db_row *); -typedef unsigned long long drv_op_num_rows(struct db_result_set *); -typedef int drv_op_query(struct db_conn *, const char *, - struct db_result_set *); -typedef int drv_op_free_results(struct db_result_set *); +typedef int drv_op_prepare(struct db_stmt *, const char *, size_t); +typedef int drv_op_bind_param(struct db_stmt *, db_bind_t *, size_t); +typedef int drv_op_bind_result(struct db_stmt *, db_bind_t *, size_t); +typedef db_error_t drv_op_execute(struct db_stmt *, struct db_result *); +typedef int drv_op_fetch(struct db_result *); +typedef int drv_op_fetch_row(struct db_result *, struct db_row *); +typedef db_error_t drv_op_query(struct db_conn *, const char *, size_t, + struct db_result *); +typedef int drv_op_free_results(struct db_result *); typedef int drv_op_close(struct db_stmt *); -typedef int drv_op_store_results(struct db_result_set *); +typedef int drv_op_thread_done(int); typedef int drv_op_done(void); typedef struct { drv_op_init *init; /* initializate driver */ + drv_op_thread_init *thread_init; /* thread-local driver initialization */ drv_op_describe *describe; /* describe database capabilities */ drv_op_connect *connect; /* connect to database */ drv_op_disconnect *disconnect; /* disconnect from database */ @@ -153,11 +153,10 @@ typedef struct drv_op_execute *execute; /* execute prepared statement */ drv_op_fetch *fetch; /* fetch row for prepared statement */ drv_op_fetch_row *fetch_row; /* fetch row for queries */ - drv_op_num_rows *num_rows; /* return number of rows in result set */ drv_op_free_results *free_results; /* free result set */ drv_op_close *close; /* close prepared statement */ drv_op_query *query; /* execute non-prepared statement */ - drv_op_store_results *store_results; /* store results from last query */ + drv_op_thread_done *thread_done; /* thread-local driver deinitialization */ drv_op_done *done; /* uninitialize driver */ } drv_ops_t; @@ -171,55 +170,65 @@ typedef struct drv_ops_t ops; /* driver operations */ sb_list_item_t listitem; /* can be linked in a list */ + bool initialized; + pthread_mutex_t mutex; } db_driver_t; -/* Connection types definition */ +/* Query type for statistics */ typedef enum { - DB_CONN_TYPE_UNUSED, - DB_CONN_TYPE_MYSQL -} db_conn_type_t; + DB_STAT_OTHER, + DB_STAT_READ, + DB_STAT_WRITE, + DB_STAT_TRX, + DB_STAT_ERROR, + DB_STAT_RECONNECT, + DB_STAT_MAX +} db_stat_type_t; /* Result set definition */ -typedef struct db_result_set +typedef struct db_result { - struct db_conn *connection; /* Connection which this result set belongs to */ - struct db_stmt *statement; /* Statement for this result set (if any) */ + db_stat_type_t stat_type; /* Statistical counter type */ + uint32_t nrows; /* Number of affected rows */ + struct db_stmt *statement; /* Pointer to prepared statement (if used) */ + void *ptr; /* Pointer to driver-specific data */ +} db_result_t; - struct db_row *row; /* Last row fetched by db_fetch_row */ - void *ptr; /* Pointer to driver-specific data */ - unsigned long long nrows; /* Number of rows in a result set */ -} db_result_set_t; +typedef enum { + DB_CONN_READY, + DB_CONN_RESULT_SET, + DB_CONN_INVALID +} db_conn_state_t; /* Database connection structure */ typedef struct db_conn { - db_driver_t *driver; /* DB driver for this connection */ - db_conn_type_t type; - void *ptr; - db_error_t db_errno; + db_driver_t *driver; /* DB driver for this connection */ + void *ptr; /* Driver-specific data */ + db_error_t db_errno; /* Driver-independent error code */ + db_conn_state_t state; /* Connection state */ + db_result_t rs; /* Result set */ + int thread_id; /* Assiciated thread id (required to + collect per-thread stats */ - /* Internal fields */ - char bulk_supported; /* 1, if multi-row inserts are supported by the driver */ + char bulk_supported; /* 1, if multi-row inserts are supported by + the driver */ unsigned int bulk_cnt; /* Current number of rows in bulk insert buffer */ - char * bulk_buffer; /* Bulk insert query buffer */ unsigned int bulk_buflen; /* Current length of bulk_buffer */ + char *bulk_buffer; /* Bulk insert query buffer */ unsigned int bulk_ptr; /* Current position in bulk_buffer */ - unsigned int bulk_ptr_orig; /* Save value of bulk_ptr */ + unsigned int bulk_values; /* Save value of bulk_ptr */ unsigned int bulk_commit_cnt; /* Current value of uncommitted rows */ unsigned int bulk_commit_max; /* Maximum value of uncommitted rows */ - int thread_id; /* Assiciated thread id (required to collect per-thread stats */ - db_result_set_t rs; /* Result set */ -} db_conn_t; -typedef enum { - DB_QUERY_TYPE_READ, - DB_QUERY_TYPE_WRITE, - DB_QUERY_TYPE_COMMIT, - DB_QUERY_TYPE_OTHER -} db_query_type_t; + char pad[SB_CACHELINE_PAD(sizeof(void *) * 3 + sizeof(db_error_t) + + sizeof(db_conn_state_t) + + sizeof(db_result_t) + + sizeof(int) * 8)]; +} db_conn_t; /* Prepared statement definition */ @@ -232,7 +241,7 @@ typedef struct db_stmt db_bind_t *bound_res; /* Array of bound results for emulated PS */ db_bind_t *bound_res_len; /* Length of the bound_res array */ char emulated; /* Should this statement be emulated? */ - db_query_type_t type; /* Query type */ + db_stat_type_t stat_type; /* Query type */ void *ptr; /* Pointer to driver-specific data structure */ } db_stmt_t; @@ -240,58 +249,69 @@ typedef struct db_stmt typedef struct db_row { - db_result_set_t *result_set; /* Result set which this row belongs to */ + db_result_t *result; /* Result set which this row belongs to */ void *ptr; /* Driver-specific row data */ } db_row_t; +/* + sizeof(db_stats_t) must be multiple of CK_MD_CACHELINE to avoid cache + line sharing. +*/ +typedef uint64_t +db_stats_t[SB_ALIGN(DB_STAT_MAX * sizeof(uint64_t), CK_MD_CACHELINE) / + sizeof(uint64_t)]; + +extern db_globals_t db_globals; +extern db_stats_t *thread_stats; + /* Database abstraction layer calls */ int db_register(void); void db_print_help(void); -db_driver_t *db_init(const char *); +db_driver_t *db_create(const char *); + +int db_destroy(db_driver_t *); int db_describe(db_driver_t *, drv_caps_t *); -db_conn_t *db_connect(db_driver_t *); +db_conn_t *db_connection_create(db_driver_t *); -int db_disconnect(db_conn_t *); +int db_connection_close(db_conn_t *); -db_stmt_t *db_prepare(db_conn_t *, const char *); +void db_connection_free(db_conn_t *con); -int db_bind_param(db_stmt_t *, db_bind_t *, unsigned int); +db_stmt_t *db_prepare(db_conn_t *, const char *, size_t); -int db_bind_result(db_stmt_t *, db_bind_t *, unsigned int); +int db_bind_param(db_stmt_t *, db_bind_t *, size_t); -db_result_set_t *db_execute(db_stmt_t *); +int db_bind_result(db_stmt_t *, db_bind_t *, size_t); -db_row_t *db_fetch_row(db_result_set_t *); +db_result_t *db_execute(db_stmt_t *); -unsigned long long db_num_rows(db_result_set_t *); +db_row_t *db_fetch_row(db_result_t *); -db_result_set_t *db_query(db_conn_t *, const char *); +db_result_t *db_query(db_conn_t *, const char *, size_t len); -int db_free_results(db_result_set_t *); +int db_free_results(db_result_t *); -int db_store_results(db_result_set_t *); +int db_store_results(db_result_t *); int db_close(db_stmt_t *); -int db_done(db_driver_t *); - -db_error_t db_errno(db_conn_t *); +void db_done(void); int db_print_value(db_bind_t *, char *, int); /* Initialize multi-row insert operation */ -int db_bulk_insert_init(db_conn_t *, const char *); +int db_bulk_insert_init(db_conn_t *, const char *, size_t); /* Add row to multi-row insert operation */ -int db_bulk_insert_next(db_conn_t *, const char *); +int db_bulk_insert_next(db_conn_t *, const char *, size_t); /* Finish multi-row insert operation */ -void db_bulk_insert_done(db_conn_t *); +int db_bulk_insert_done(db_conn_t *); /* Print database-specific test stats */ void db_print_stats(sb_stat_t type); @@ -299,6 +319,16 @@ void db_print_stats(sb_stat_t type); /* Associate connection with a thread (required only for statistics */ void db_set_thread(db_conn_t *, int); +/* Initialize per-thread stats */ +int db_thread_stat_init(void); + +/* Increment a given stat counter for a connection */ +static inline void db_thread_stat_inc(int id, db_stat_type_t type) +{ + ck_pr_inc_64(&thread_stats[id][type]); +} + + /* DB drivers registrars */ #ifdef USE_MYSQL diff --git a/sysbench/drivers/attachsql/drv_attachsql.c b/sysbench/drivers/attachsql/drv_attachsql.c index 0f55634..98ab626 100644 --- a/sysbench/drivers/attachsql/drv_attachsql.c +++ b/sysbench/drivers/attachsql/drv_attachsql.c @@ -86,17 +86,17 @@ static int attachsql_drv_init(void); static int attachsql_drv_describe(drv_caps_t *); static int attachsql_drv_connect(db_conn_t *); static int attachsql_drv_disconnect(db_conn_t *); -static int attachsql_drv_prepare(db_stmt_t *, const char *); -static int attachsql_drv_bind_param(db_stmt_t *, db_bind_t *, unsigned int); -static int attachsql_drv_bind_result(db_stmt_t *, db_bind_t *, unsigned int); -static int attachsql_drv_execute(db_stmt_t *, db_result_set_t *); -static int attachsql_drv_fetch(db_result_set_t *); -static int attachsql_drv_fetch_row(db_result_set_t *, db_row_t *); -static unsigned long long attachsql_drv_num_rows(db_result_set_t *); -static int attachsql_drv_query(db_conn_t *, const char *, db_result_set_t *); -static int attachsql_drv_free_results(db_result_set_t *); +static int attachsql_drv_prepare(db_stmt_t *, const char *, size_t); +static int attachsql_drv_bind_param(db_stmt_t *, db_bind_t *, size_t); +static int attachsql_drv_bind_result(db_stmt_t *, db_bind_t *, size_t); +static db_error_t attachsql_drv_execute(db_stmt_t *, db_result_t *); +static int attachsql_drv_fetch(db_result_t *); +static int attachsql_drv_fetch_row(db_result_t *, db_row_t *); +static db_error_t attachsql_drv_query(db_conn_t *, const char *, size_t, + db_result_t *); +static int attachsql_drv_free_results(db_result_t *); static int attachsql_drv_close(db_stmt_t *); -static int attachsql_drv_store_results(db_result_set_t *); +static int attachsql_drv_store_results(db_result_t *); static int attachsql_drv_done(void); /* libAttachSQL driver definition */ @@ -108,24 +108,22 @@ static db_driver_t attachsql_driver = .args = attachsql_drv_args, .ops = { - attachsql_drv_init, - attachsql_drv_describe, - attachsql_drv_connect, - attachsql_drv_disconnect, - attachsql_drv_prepare, - attachsql_drv_bind_param, - attachsql_drv_bind_result, - attachsql_drv_execute, - attachsql_drv_fetch, - attachsql_drv_fetch_row, - attachsql_drv_num_rows, - attachsql_drv_free_results, - attachsql_drv_close, - attachsql_drv_query, - attachsql_drv_store_results, - attachsql_drv_done - }, - .listitem = {NULL, NULL} + .init = attachsql_drv_init, + .describe = attachsql_drv_describe, + .connect = attachsql_drv_connect, + .disconnect = attachsql_drv_disconnect, + .prepare = attachsql_drv_prepare, + .bind_param = attachsql_drv_bind_param, + .bind_result = attachsql_drv_bind_result, + .execute = attachsql_drv_execute, + .fetch = attachsql_drv_fetch, + .fetch_row = attachsql_drv_fetch_row, + .free_results = attachsql_drv_free_results, + .close = attachsql_drv_close, + .query = attachsql_drv_query, + .store_results = attachsql_drv_store_results, + .done = attachsql_drv_done + } }; @@ -280,12 +278,12 @@ int attachsql_drv_disconnect(db_conn_t *sb_conn) /* Prepare statement */ -int attachsql_drv_prepare(db_stmt_t *stmt, const char *query) +int attachsql_drv_prepare(db_stmt_t *stmt, const char *query, size_t len) { attachsql_connect_t *con= (attachsql_connect_t *)stmt->connection->ptr; attachsql_error_t *error= NULL; attachsql_return_t aret= ATTACHSQL_RETURN_NONE; - attachsql_statement_prepare(con, strlen(query), query, &error); + attachsql_statement_prepare(con, len, query, &error); while(aret != ATTACHSQL_RETURN_EOF) { aret= attachsql_connect_poll(con, &error); @@ -302,7 +300,7 @@ int attachsql_drv_prepare(db_stmt_t *stmt, const char *query) /* Bind parameters for prepared statement */ -int attachsql_drv_bind_param(db_stmt_t *stmt, db_bind_t *params, unsigned int len) +int attachsql_drv_bind_param(db_stmt_t *stmt, db_bind_t *params, size_t len) { /* libAttachSQL doesn't do this, you do this during execute * this is because sysbench doesn't set the values until that time @@ -322,7 +320,7 @@ int attachsql_drv_bind_param(db_stmt_t *stmt, db_bind_t *params, unsigned int le /* Bind results for prepared statement */ -int attachsql_drv_bind_result(db_stmt_t *stmt, db_bind_t *params, unsigned int len) +int attachsql_drv_bind_result(db_stmt_t *stmt, db_bind_t *params, size_t len) { (void)stmt; (void)params; @@ -335,7 +333,7 @@ int attachsql_drv_bind_result(db_stmt_t *stmt, db_bind_t *params, unsigned int l /* Execute prepared statement */ -int attachsql_drv_execute(db_stmt_t *stmt, db_result_set_t *rs) +db_error_t attachsql_drv_execute(db_stmt_t *stmt, db_result_t *rs) { (void) rs; attachsql_connect_t *con= (attachsql_connect_t *)stmt->connection->ptr; @@ -426,8 +424,8 @@ int attachsql_drv_execute(db_stmt_t *stmt, db_result_set_t *rs) /* Execute SQL query */ -int attachsql_drv_query(db_conn_t *sb_conn, const char *query, - db_result_set_t *rs) +db_error_t attachsql_drv_query(db_conn_t *sb_conn, const char *query, + size_t len, db_result_t *rs) { (void) rs; attachsql_connect_t *con = sb_conn->ptr; @@ -441,8 +439,8 @@ int attachsql_drv_query(db_conn_t *sb_conn, const char *query, DEBUG("attachsql_query(%p, \"%s\", %u)", con, query, - strlen(query)); - attachsql_query(con, strlen(query), query, 0, NULL, &error); + len); + attachsql_query(con, len, query, 0, NULL, &error); while((aret != ATTACHSQL_RETURN_EOF) && (aret != ATTACHSQL_RETURN_ROW_READY)) { @@ -471,7 +469,7 @@ int attachsql_drv_query(db_conn_t *sb_conn, const char *query, /* Fetch row from result set of a prepared statement */ -int attachsql_drv_fetch(db_result_set_t *rs) +int attachsql_drv_fetch(db_result_t *rs) { /* NYI */ attachsql_connect_t *con = rs->connection->ptr; @@ -531,7 +529,7 @@ int attachsql_drv_fetch(db_result_set_t *rs) /* Fetch row from result set of a query */ -int attachsql_drv_fetch_row(db_result_set_t *rs, db_row_t *row) +int attachsql_drv_fetch_row(db_result_t *rs, db_row_t *row) { attachsql_error_t *error= NULL; attachsql_return_t aret= ATTACHSQL_RETURN_NONE; @@ -562,19 +560,10 @@ int attachsql_drv_fetch_row(db_result_set_t *rs, db_row_t *row) } -/* Return the number of rows in a result set */ - - -unsigned long long attachsql_drv_num_rows(db_result_set_t *rs) -{ - return rs->nrows; -} - - /* Store results from the last query */ -int attachsql_drv_store_results(db_result_set_t *rs) +int attachsql_drv_store_results(db_result_t *rs) { int ret= 0; db_row_t row; @@ -598,13 +587,14 @@ int attachsql_drv_store_results(db_result_set_t *rs) /* Free result set */ -int attachsql_drv_free_results(db_result_set_t *rs) +int attachsql_drv_free_results(db_result_t *rs) { if (rs->connection->ptr != NULL) { DEBUG("attachsql_query_close(%p)", rs->connection->ptr); attachsql_query_close(rs->connection->ptr); + rs->connection->ptr = NULL; return 0; } diff --git a/sysbench/drivers/drizzle/drv_drizzle.c b/sysbench/drivers/drizzle/drv_drizzle.c index 507dca5..4f5cd4f 100644 --- a/sysbench/drivers/drizzle/drv_drizzle.c +++ b/sysbench/drivers/drizzle/drv_drizzle.c @@ -96,17 +96,17 @@ static int drizzle_drv_init(void); static int drizzle_drv_describe(drv_caps_t *); static int drizzle_drv_connect(db_conn_t *); static int drizzle_drv_disconnect(db_conn_t *); -static int drizzle_drv_prepare(db_stmt_t *, const char *); -static int drizzle_drv_bind_param(db_stmt_t *, db_bind_t *, unsigned int); -static int drizzle_drv_bind_result(db_stmt_t *, db_bind_t *, unsigned int); -static int drizzle_drv_execute(db_stmt_t *, db_result_set_t *); -static int drizzle_drv_fetch(db_result_set_t *); -static int drizzle_drv_fetch_row(db_result_set_t *, db_row_t *); -static unsigned long long drizzle_drv_num_rows(db_result_set_t *); -static int drizzle_drv_query(db_conn_t *, const char *, db_result_set_t *); -static int drizzle_drv_free_results(db_result_set_t *); +static int drizzle_drv_prepare(db_stmt_t *, const char *, size_t); +static int drizzle_drv_bind_param(db_stmt_t *, db_bind_t *, size_t); +static int drizzle_drv_bind_result(db_stmt_t *, db_bind_t *, size_t); +static db_error_t drizzle_drv_execute(db_stmt_t *, db_result_t *); +static int drizzle_drv_fetch(db_result_t *); +static int drizzle_drv_fetch_row(db_result_t *, db_row_t *); +static db_error_t drizzle_drv_query(db_conn_t *, const char *, size_t, + db_result_t *); +static int drizzle_drv_free_results(db_result_t *); static int drizzle_drv_close(db_stmt_t *); -static int drizzle_drv_store_results(db_result_set_t *); +static int drizzle_drv_store_results(db_result_t *); static int drizzle_drv_done(void); /* Drizzle driver definition */ @@ -118,24 +118,22 @@ static db_driver_t drizzle_driver = .args = drizzle_drv_args, .ops = { - drizzle_drv_init, - drizzle_drv_describe, - drizzle_drv_connect, - drizzle_drv_disconnect, - drizzle_drv_prepare, - drizzle_drv_bind_param, - drizzle_drv_bind_result, - drizzle_drv_execute, - drizzle_drv_fetch, - drizzle_drv_fetch_row, - drizzle_drv_num_rows, - drizzle_drv_free_results, - drizzle_drv_close, - drizzle_drv_query, - drizzle_drv_store_results, - drizzle_drv_done + .init = drizzle_drv_init, + .describe = drizzle_drv_describe, + .connect = drizzle_drv_connect, + .disconnect = drizzle_drv_disconnect, + .prepare = drizzle_drv_prepare, + .bind_param = drizzle_drv_bind_param, + .bind_result = drizzle_drv_bind_result, + .execute = drizzle_drv_execute, + .fetch = drizzle_drv_fetch, + .fetch_row = drizzle_drv_fetch_row, + .free_results = drizzle_drv_free_results, + .close = drizzle_drv_close, + .query = drizzle_drv_query, + .store_results = drizzle_drv_store_results, + .done = drizzle_drv_done }, - .listitem = {NULL, NULL} }; @@ -299,9 +297,11 @@ int drizzle_drv_disconnect(db_conn_t *sb_conn) /* Prepare statement */ -int drizzle_drv_prepare(db_stmt_t *stmt, const char *query) +int drizzle_drv_prepare(db_stmt_t *stmt, const char *query, size_t len) { + (void) len; /* unused */ + /* Use client-side PS */ stmt->emulated = 1; stmt->query = strdup(query); @@ -311,7 +311,7 @@ int drizzle_drv_prepare(db_stmt_t *stmt, const char *query) /* Bind parameters for prepared statement */ -int drizzle_drv_bind_param(db_stmt_t *stmt, db_bind_t *params, unsigned int len) +int drizzle_drv_bind_param(db_stmt_t *stmt, db_bind_t *params, size_t len) { drizzle_con_st *con = (drizzle_con_st *)stmt->connection->ptr; @@ -333,7 +333,7 @@ int drizzle_drv_bind_param(db_stmt_t *stmt, db_bind_t *params, unsigned int len) /* Bind results for prepared statement */ -int drizzle_drv_bind_result(db_stmt_t *stmt, db_bind_t *params, unsigned int len) +int drizzle_drv_bind_result(db_stmt_t *stmt, db_bind_t *params, size_t len) { (void)stmt; (void)params; @@ -345,7 +345,7 @@ int drizzle_drv_bind_result(db_stmt_t *stmt, db_bind_t *params, unsigned int len /* Execute prepared statement */ -int drizzle_drv_execute(db_stmt_t *stmt, db_result_set_t *rs) +db_error_t drizzle_drv_execute(db_stmt_t *stmt, db_result_t *rs) { db_conn_t *con = stmt->connection; char *buf = NULL; @@ -390,7 +390,7 @@ int drizzle_drv_execute(db_stmt_t *stmt, db_result_set_t *rs) } buf[j] = '\0'; - con->db_errno = drizzle_drv_query(con, buf, rs); + con->db_errno = drizzle_drv_query(con, buf, j, rs); free(buf); if (con->db_errno != SB_DB_ERROR_NONE) { @@ -405,8 +405,8 @@ int drizzle_drv_execute(db_stmt_t *stmt, db_result_set_t *rs) /* Execute SQL query */ -int drizzle_drv_query(db_conn_t *sb_conn, const char *query, - db_result_set_t *rs) +db_error_t drizzle_drv_query(db_conn_t *sb_conn, const char *query, size_t len, + db_result_t *rs) { drizzle_con_st *con = sb_conn->ptr; unsigned int rc; @@ -417,9 +417,9 @@ int drizzle_drv_query(db_conn_t *sb_conn, const char *query, con, result, query, - strlen(query), + len, &ret); - result= drizzle_query(con, NULL, query, strlen(query), &ret); + result= drizzle_query(con, NULL, query, len, &ret); DEBUG("drizzle_query(%p) == %d", con, ret); if (ret == DRIZZLE_RETURN_ERROR_CODE) @@ -468,7 +468,7 @@ int drizzle_drv_query(db_conn_t *sb_conn, const char *query, /* Fetch row from result set of a prepared statement */ -int drizzle_drv_fetch(db_result_set_t *rs) +int drizzle_drv_fetch(db_result_t *rs) { /* NYI */ (void)rs; @@ -481,7 +481,7 @@ int drizzle_drv_fetch(db_result_set_t *rs) /* Fetch row from result set of a query */ -int drizzle_drv_fetch_row(db_result_set_t *rs, db_row_t *row) +int drizzle_drv_fetch_row(db_result_t *rs, db_row_t *row) { /* NYI */ printf("in drizzle_drv_fetch_row!\n"); @@ -492,19 +492,10 @@ int drizzle_drv_fetch_row(db_result_set_t *rs, db_row_t *row) } -/* Return the number of rows in a result set */ - - -unsigned long long drizzle_drv_num_rows(db_result_set_t *rs) -{ - return rs->nrows; -} - - /* Store results from the last query */ -int drizzle_drv_store_results(db_result_set_t *rs) +int drizzle_drv_store_results(db_result_t *rs) { drizzle_con_st *con = rs->connection->ptr; @@ -662,13 +653,14 @@ int drizzle_drv_store_results(db_result_set_t *rs) /* Free result set */ -int drizzle_drv_free_results(db_result_set_t *rs) +int drizzle_drv_free_results(db_result_t *rs) { if (rs->ptr != NULL) { DEBUG("drizzle_result_free(%p)", rs->ptr); drizzle_result_free(rs->ptr); + rs->ptr = NULL; return 0; } diff --git a/sysbench/drivers/mysql/drv_mysql.c b/sysbench/drivers/mysql/drv_mysql.c index 8835c07..b8c3842 100644 --- a/sysbench/drivers/mysql/drv_mysql.c +++ b/sysbench/drivers/mysql/drv_mysql.c @@ -1,5 +1,5 @@ /* Copyright (C) 2004 MySQL AB - Copyright (C) 2004-2015 Alexey Kopytov + Copyright (C) 2004-2017 Alexey Kopytov This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -41,19 +41,11 @@ #include "sb_options.h" #include "db_driver.h" -/* Check MySQL version for prepared statements availability */ -#if MYSQL_VERSION_ID >= 40103 -# define HAVE_PS -#endif - -/* Check if we should use the TYPE= (for 3.23) or ENGINE= syntax */ -#if MYSQL_VERSION_ID >= 40000 -# define ENGINE_CLAUSE "ENGINE" -#else -# define ENGINE_CLAUSE "TYPE" -#endif - -#define DEBUG(format, ...) do { if (args.debug) log_text(LOG_DEBUG, format, __VA_ARGS__); } while (0) +#define DEBUG(format, ...) \ + do { \ + if (SB_UNLIKELY(args.debug != 0)) \ + log_text(LOG_DEBUG, format, __VA_ARGS__); \ + } while (0) #define SAFESTR(s) ((s != NULL) ? (s) : "(null)") @@ -114,7 +106,6 @@ typedef struct char *socket; } db_mysql_conn_t; -#ifdef HAVE_PS /* Structure used for DB-to-MySQL bind types map */ typedef struct @@ -139,8 +130,6 @@ db_mysql_bind_map_t db_mysql_bind_map[] = {DB_TYPE_NONE, 0} }; -#endif /* HAVE_PS */ - /* MySQL driver capabilities */ static drv_caps_t mysql_drv_caps = @@ -169,56 +158,60 @@ static pthread_mutex_t pos_mutex; /* MySQL driver operations */ static int mysql_drv_init(void); +static int mysql_drv_thread_init(int); static int mysql_drv_describe(drv_caps_t *); static int mysql_drv_connect(db_conn_t *); static int mysql_drv_disconnect(db_conn_t *); -static int mysql_drv_prepare(db_stmt_t *, const char *); -static int mysql_drv_bind_param(db_stmt_t *, db_bind_t *, unsigned int); -static int mysql_drv_bind_result(db_stmt_t *, db_bind_t *, unsigned int); -static int mysql_drv_execute(db_stmt_t *, db_result_set_t *); -static int mysql_drv_fetch(db_result_set_t *); -static int mysql_drv_fetch_row(db_result_set_t *, db_row_t *); -static unsigned long long mysql_drv_num_rows(db_result_set_t *); -static int mysql_drv_query(db_conn_t *, const char *, db_result_set_t *); -static int mysql_drv_free_results(db_result_set_t *); +static int mysql_drv_prepare(db_stmt_t *, const char *, size_t); +static int mysql_drv_bind_param(db_stmt_t *, db_bind_t *, size_t); +static int mysql_drv_bind_result(db_stmt_t *, db_bind_t *, size_t); +static db_error_t mysql_drv_execute(db_stmt_t *, db_result_t *); +static int mysql_drv_fetch(db_result_t *); +#if 0 +static int mysql_drv_fetch_row(db_result_t *, db_row_t *); +#endif +static db_error_t mysql_drv_query(db_conn_t *, const char *, size_t, + db_result_t *); +static int mysql_drv_free_results(db_result_t *); static int mysql_drv_close(db_stmt_t *); -static int mysql_drv_store_results(db_result_set_t *); +static int mysql_drv_thread_done(int); static int mysql_drv_done(void); /* MySQL driver definition */ static db_driver_t mysql_driver = { - "mysql", - "MySQL driver", - mysql_drv_args, - { - mysql_drv_init, - mysql_drv_describe, - mysql_drv_connect, - mysql_drv_disconnect, - mysql_drv_prepare, - mysql_drv_bind_param, - mysql_drv_bind_result, - mysql_drv_execute, - mysql_drv_fetch, - mysql_drv_fetch_row, - mysql_drv_num_rows, - mysql_drv_free_results, - mysql_drv_close, - mysql_drv_query, - mysql_drv_store_results, - mysql_drv_done - }, - {0,0} + .sname = "mysql", + .lname = "MySQL driver", + .args = mysql_drv_args, + .ops = { + .init = mysql_drv_init, + .thread_init = mysql_drv_thread_init, + .describe = mysql_drv_describe, + .connect = mysql_drv_connect, + .disconnect = mysql_drv_disconnect, + .prepare = mysql_drv_prepare, + .bind_param = mysql_drv_bind_param, + .bind_result = mysql_drv_bind_result, + .execute = mysql_drv_execute, + .fetch = mysql_drv_fetch, +#if 0 + .fetch_row = mysql_drv_fetch_row, +#else + .fetch_row = NULL, +#endif + .free_results = mysql_drv_free_results, + .close = mysql_drv_close, + .query = mysql_drv_query, + .thread_done = mysql_drv_thread_done, + .done = mysql_drv_done + } }; /* Local functions */ -#ifdef HAVE_PS static int get_mysql_bind_type(db_bind_type_t); -#endif /* Register MySQL driver */ @@ -272,11 +265,9 @@ int mysql_drv_init(void) args.dry_run = sb_get_value_flag("mysql-dry-run"); use_ps = 0; -#ifdef HAVE_PS mysql_drv_caps.prepared_statements = 1; if (db_globals.ps_mode != DB_PS_MODE_DISABLE) use_ps = 1; -#endif DEBUG("mysql_library_init(%d, %p, %p)", 0, NULL, NULL); mysql_library_init(0, NULL, NULL); @@ -284,10 +275,28 @@ int mysql_drv_init(void) return 0; } +/* Thread-local driver initialization */ + +int mysql_drv_thread_init(int thread_id) +{ + (void) thread_id; /* unused */ + + return mysql_thread_init() != 0; +} + +/* Thread-local driver deinitialization */ + +int mysql_drv_thread_done(int thread_id) +{ + (void) thread_id; /* unused */ + + mysql_thread_end(); + + return 0; +} /* Describe database capabilities */ - int mysql_drv_describe(drv_caps_t *caps) { *caps = mysql_drv_caps; @@ -474,9 +483,8 @@ int mysql_drv_disconnect(db_conn_t *sb_conn) /* Prepare statement */ -int mysql_drv_prepare(db_stmt_t *stmt, const char *query) +int mysql_drv_prepare(db_stmt_t *stmt, const char *query, size_t len) { -#ifdef HAVE_PS db_mysql_conn_t *db_mysql_con = (db_mysql_conn_t *) stmt->connection->ptr; MYSQL *con = db_mysql_con->mysql; MYSQL_STMT *mystmt; @@ -499,8 +507,8 @@ int mysql_drv_prepare(db_stmt_t *stmt, const char *query) } stmt->ptr = (void *)mystmt; DEBUG("mysql_stmt_prepare(%p, \"%s\", %u) = %p", mystmt, query, - (unsigned int) strlen(query), stmt->ptr); - if (mysql_stmt_prepare(mystmt, query, strlen(query))) + (unsigned int) len, stmt->ptr); + if (mysql_stmt_prepare(mystmt, query, len)) { /* Check if this statement in not supported */ rc = mysql_errno(con); @@ -522,13 +530,15 @@ int mysql_drv_prepare(db_stmt_t *stmt, const char *query) return 1; } } + stmt->query = strdup(query); + stmt->stat_type = (mysql_stmt_field_count(mystmt) > 0) ? + DB_STAT_READ : DB_STAT_WRITE; return 0; } emulate: -#endif /* HAVE_PS */ /* Use client-side PS */ stmt->emulated = 1; @@ -541,16 +551,14 @@ int mysql_drv_prepare(db_stmt_t *stmt, const char *query) /* Bind parameters for prepared statement */ -int mysql_drv_bind_param(db_stmt_t *stmt, db_bind_t *params, unsigned int len) +int mysql_drv_bind_param(db_stmt_t *stmt, db_bind_t *params, size_t len) { db_mysql_conn_t *db_mysql_con = (db_mysql_conn_t *) stmt->connection->ptr; MYSQL *con = db_mysql_con->mysql; -#ifdef HAVE_PS MYSQL_BIND *bind; unsigned int i; my_bool rc; unsigned long param_count; -#endif if (args.dry_run) return 0; @@ -558,7 +566,6 @@ int mysql_drv_bind_param(db_stmt_t *stmt, db_bind_t *params, unsigned int len) if (con == NULL) return 1; -#ifdef HAVE_PS if (!stmt->emulated) { if (stmt->ptr == NULL) @@ -598,7 +605,6 @@ int mysql_drv_bind_param(db_stmt_t *stmt, db_bind_t *params, unsigned int len) return 0; } -#endif /* HAVE_PS */ /* Use emulation */ if (stmt->bound_param != NULL) @@ -617,16 +623,8 @@ int mysql_drv_bind_param(db_stmt_t *stmt, db_bind_t *params, unsigned int len) /* Bind results for prepared statement */ -int mysql_drv_bind_result(db_stmt_t *stmt, db_bind_t *params, unsigned int len) +int mysql_drv_bind_result(db_stmt_t *stmt, db_bind_t *params, size_t len) { -#ifndef HAVE_PS - /* No support for prepared statements */ - (void)stmt; /* unused */ - (void)params; /* unused */ - (void)len; /* unused */ - - return 1; -#else db_mysql_conn_t *db_mysql_con =(db_mysql_conn_t *) stmt->connection->ptr; MYSQL *con = db_mysql_con->mysql; MYSQL_BIND *bind; @@ -662,14 +660,9 @@ int mysql_drv_bind_result(db_stmt_t *stmt, db_bind_t *params, unsigned int len) free(bind); return 0; -#endif /* HAVE_PS */ } - -/* - Reset connection to the server by reconnecting with the same parameters. -*/ - +/* Reset connection to the server by reconnecting with the same parameters. */ static int mysql_drv_reconnect(db_conn_t *sb_con) { @@ -684,14 +677,14 @@ static int mysql_drv_reconnect(db_conn_t *sb_con) while (mysql_drv_real_connect(db_mysql_con)) { if (sb_globals.error) - return SB_DB_ERROR_FAILED; + return DB_ERROR_FATAL; usleep(1000); } log_text(LOG_DEBUG, "Reconnected"); - return SB_DB_ERROR_RECONNECTED; + return DB_ERROR_IGNORABLE; } @@ -701,7 +694,8 @@ static int mysql_drv_reconnect(db_conn_t *sb_con) */ -static int check_error(db_conn_t *sb_con, const char *func, const char *query) +static db_error_t check_error(db_conn_t *sb_con, const char *func, + const char *query, db_stat_type_t *type) { sb_list_item_t *pos; unsigned int tmp; @@ -734,6 +728,8 @@ static int check_error(db_conn_t *sb_con, const char *func, const char *query) case CR_TCP_CONNECTION: case CR_SERVER_LOST_EXTENDED: + *type = DB_STAT_RECONNECT; + return mysql_drv_reconnect(sb_con); default: @@ -741,7 +737,9 @@ static int check_error(db_conn_t *sb_con, const char *func, const char *query) break; } - return SB_DB_ERROR_RESTART_TRANSACTION; + *type = DB_STAT_ERROR; + + return DB_ERROR_IGNORABLE; } } @@ -752,13 +750,15 @@ static int check_error(db_conn_t *sb_con, const char *func, const char *query) log_text(LOG_ALERT, "%s returned error %u (%s)", func, error, mysql_error(con)); - return SB_DB_ERROR_FAILED; + *type = DB_STAT_ERROR; + + return DB_ERROR_FATAL; } /* Execute prepared statement */ -int mysql_drv_execute(db_stmt_t *stmt, db_result_set_t *rs) +db_error_t mysql_drv_execute(db_stmt_t *stmt, db_result_t *rs) { db_conn_t *con = stmt->connection; char *buf = NULL; @@ -766,32 +766,51 @@ int mysql_drv_execute(db_stmt_t *stmt, db_result_set_t *rs) unsigned int i, j, vcnt; char need_realloc; int n; - unsigned int rc; if (args.dry_run) - return 0; - -#ifdef HAVE_PS - (void)rs; /* unused */ + return DB_ERROR_NONE; if (!stmt->emulated) { if (stmt->ptr == NULL) { - log_text(LOG_DEBUG, "ERROR: exiting mysql_drv_execute(), uninitialized statement"); - return SB_DB_ERROR_FAILED; + log_text(LOG_DEBUG, + "ERROR: exiting mysql_drv_execute(), uninitialized statement"); + return DB_ERROR_FATAL; } - rc = (unsigned int)mysql_stmt_execute(stmt->ptr); - DEBUG("mysql_stmt_execute(%p) = %u", stmt->ptr, rc); - if (rc) - return check_error(con, "mysql_stmt_execute()", stmt->query); + int err = mysql_stmt_execute(stmt->ptr); + DEBUG("mysql_stmt_execute(%p) = %d", stmt->ptr, err); - return SB_DB_ERROR_NONE; + if (err) + return check_error(con, "mysql_stmt_execute()", stmt->query, + &rs->stat_type); + + if (stmt->stat_type != DB_STAT_READ) + { + rs->nrows = (uint32_t) mysql_stmt_affected_rows(stmt->ptr); + DEBUG("mysql_stmt_affected_rows(%p) = %u", stmt->ptr, + (unsigned) rs->nrows); + + rs->stat_type = (rs->nrows > 0) ? DB_STAT_WRITE : DB_STAT_OTHER; + + return DB_ERROR_NONE; + } + + err = mysql_stmt_store_result(stmt->ptr); + DEBUG("mysql_stmt_store_result(%p) = %d", stmt->ptr, err); + if (err) + { + return check_error(con, "mysql_stmt_store_result()", NULL, + &rs->stat_type); + } + + rs->nrows = (uint32_t) mysql_stmt_num_rows(stmt->ptr); + DEBUG("mysql_stmt_num_rows(%p) = %u", rs->statement->ptr, + (unsigned) (rs->nrows)); + + return DB_ERROR_NONE; } -#else - (void)rc; /* unused */ -#endif /* HAVE_PS */ /* Use emulation */ /* Build the actual query string from parameters list */ @@ -807,7 +826,7 @@ int mysql_drv_execute(db_stmt_t *stmt, db_result_set_t *rs) if (buf == NULL) { log_text(LOG_DEBUG, "ERROR: exiting mysql_drv_execute(), memory allocation failure"); - return SB_DB_ERROR_FAILED; + return DB_ERROR_FATAL; } need_realloc = 0; } @@ -829,51 +848,73 @@ int mysql_drv_execute(db_stmt_t *stmt, db_result_set_t *rs) } buf[j] = '\0'; - con->db_errno = mysql_drv_query(con, buf, rs); - free(buf); - if (con->db_errno != SB_DB_ERROR_NONE) - { - log_text(LOG_DEBUG, "ERROR: exiting mysql_drv_execute(), database error"); - return con->db_errno; - } + db_error_t rc = mysql_drv_query(con, buf, j, rs); - return SB_DB_ERROR_NONE; + free(buf); + + return rc; } /* Execute SQL query */ -int mysql_drv_query(db_conn_t *sb_conn, const char *query, - db_result_set_t *rs) +db_error_t mysql_drv_query(db_conn_t *sb_conn, const char *query, size_t len, + db_result_t *rs) { db_mysql_conn_t *db_mysql_con; MYSQL *con; - unsigned int rc; - - (void)rs; /* unused */ if (args.dry_run) - return 0; + return DB_ERROR_NONE; db_mysql_con = (db_mysql_conn_t *)sb_conn->ptr; con = db_mysql_con->mysql; - rc = (unsigned int)mysql_real_query(con, query, strlen(query)); - DEBUG("mysql_real_query(%p, \"%s\", %u) = %u", con, query, - (unsigned int) strlen(query), rc); + int err = mysql_real_query(con, query, len); + DEBUG("mysql_real_query(%p, \"%s\", %zd) = %d", con, query, len, err); - if (rc) - return check_error(sb_conn, "mysql_drv_query()", query); + if (SB_UNLIKELY(err != 0)) + return check_error(sb_conn, "mysql_drv_query()", query, &rs->stat_type); - return SB_DB_ERROR_NONE; + /* Store results and get query type */ + MYSQL_RES *res = mysql_store_result(con); + DEBUG("mysql_store_result(%p) = %p", con, res); + + if (res == NULL) + { + if (mysql_errno(con) == 0 && mysql_field_count(con) == 0) + { + /* Not a select. Check if it was a DML */ + uint32_t nrows = (uint32_t) mysql_affected_rows(con); + if (nrows > 0) + { + rs->stat_type = DB_STAT_WRITE; + rs->nrows = nrows; + } + else + rs->stat_type = DB_STAT_OTHER; + + return DB_ERROR_NONE; + } + + return check_error(sb_conn, "mysql_store_result()", NULL, &rs->stat_type); + } + + rs->stat_type = DB_STAT_READ; + rs->ptr = (void *)res; + + rs->nrows = mysql_num_rows(res); + DEBUG("mysql_num_rows(%p) = %u", res, (unsigned int)rs->nrows); + + return DB_ERROR_NONE; } /* Fetch row from result set of a prepared statement */ -int mysql_drv_fetch(db_result_set_t *rs) +int mysql_drv_fetch(db_result_t *rs) { /* NYI */ (void)rs; /* unused */ @@ -882,10 +923,11 @@ int mysql_drv_fetch(db_result_set_t *rs) } +#if 0 /* Fetch row from result set of a query */ -int mysql_drv_fetch_row(db_result_set_t *rs, db_row_t *row) +int mysql_drv_fetch_row(db_result_t *rs, db_row_t *row) { db_mysql_conn_t *db_mysql_con = (db_mysql_conn_t *) rs->connection->ptr; row->ptr = mysql_fetch_row(rs->ptr); @@ -899,110 +941,31 @@ int mysql_drv_fetch_row(db_result_set_t *rs, db_row_t *row) return 0; } - - -/* Return the number of rows in a result set */ - - -unsigned long long mysql_drv_num_rows(db_result_set_t *rs) -{ - return args.dry_run ? 0 : rs->nrows; -} - - -/* Store results from the last query */ - - -int mysql_drv_store_results(db_result_set_t *rs) -{ - db_mysql_conn_t *db_mysql_con = (db_mysql_conn_t *) rs->connection->ptr; - MYSQL *con; - MYSQL_RES *res; - MYSQL_ROW row; - unsigned int rc; - - if (args.dry_run) - return 0; - - con = db_mysql_con->mysql; - -#ifdef HAVE_PS - /* Is this result set from prepared statement? */ - if (rs->statement != NULL && rs->statement->emulated == 0) - { - if (rs->statement->ptr == NULL) - return 1; - - rc = (unsigned int)mysql_stmt_store_result(rs->statement->ptr); - DEBUG("mysql_stmt_store_result(%p) = %d", rs->statement->ptr, rc); - if (rc) - { - if (mysql_stmt_field_count(rs->statement->ptr) == 0) - return SB_DB_ERROR_NONE; - - return check_error(rs->connection, "mysql_stmt_store_result()", NULL); - } - rs->nrows = mysql_stmt_num_rows(rs->statement->ptr); - DEBUG("mysql_stmt_num_rows(%p) = %llu", rs->statement->ptr, rs->nrows); - do { - rc = (unsigned int)mysql_stmt_fetch(rs->statement->ptr); - DEBUG("mysql_stmt_fetch(%p) = %d", rs->statement->ptr, rc); - } while(rc == 0); - - return SB_DB_ERROR_NONE; - } #endif - if (con == NULL) - return SB_DB_ERROR_FAILED; - - /* using store results for speed will not work for large sets */ - res = mysql_store_result(con); - DEBUG("mysql_store_result(%p) = %p", con, res); - if (res == NULL) - { - if (mysql_field_count(con) == 0) - return SB_DB_ERROR_NONE; - - return check_error(rs->connection, "mysql_store_result()", NULL); - } - rs->ptr = (void *)res; - - rs->nrows = mysql_num_rows(res); - DEBUG("mysql_num_rows(%p) = %llu", res, rs->nrows); - - /* just fetch result */ - while((row = mysql_fetch_row(res))) - DEBUG("mysql_fetch_row(%p) = %p", res, row); - return SB_DB_ERROR_NONE; -} - - /* Free result set */ - -int mysql_drv_free_results(db_result_set_t *rs) +int mysql_drv_free_results(db_result_t *rs) { if (args.dry_run) return 0; -#ifdef HAVE_PS - /* Is this a result set of a prepared statement */ + /* Is this a result set of a prepared statement? */ if (rs->statement != NULL && rs->statement->emulated == 0) { DEBUG("mysql_stmt_free_result(%p)", rs->statement->ptr); - return mysql_stmt_free_result(rs->statement->ptr); + mysql_stmt_free_result(rs->statement->ptr); + rs->ptr = NULL; } -#endif if (rs->ptr != NULL) { DEBUG("mysql_free_result(%p)", rs->ptr); mysql_free_result((MYSQL_RES *)rs->ptr); - return 0; + rs->ptr = NULL; } - return 1; + return 0; } @@ -1020,16 +983,11 @@ int mysql_drv_close(db_stmt_t *stmt) stmt->query = NULL; } -#ifdef HAVE_PS if (stmt->ptr == NULL) return 1; DEBUG("mysql_stmt_close(%p)", stmt->ptr); return mysql_stmt_close(stmt->ptr); -#else - (void)stmt; /* unused */ - return 0; -#endif } @@ -1044,11 +1002,8 @@ int mysql_drv_done(void) return 0; } - -#ifdef HAVE_PS /* Map SQL data type to bind_type value in MYSQL_BIND */ - int get_mysql_bind_type(db_bind_type_t type) { unsigned int i; @@ -1059,5 +1014,3 @@ int get_mysql_bind_type(db_bind_type_t type) return -1; } - -#endif /* HAVE_PS */ diff --git a/sysbench/drivers/oracle/drv_oracle.c b/sysbench/drivers/oracle/drv_oracle.c index 445eba9..94b2fab 100644 --- a/sysbench/drivers/oracle/drv_oracle.c +++ b/sysbench/drivers/oracle/drv_oracle.c @@ -170,17 +170,17 @@ static int ora_drv_init(void); static int ora_drv_describe(drv_caps_t *); static int ora_drv_connect(db_conn_t *); static int ora_drv_disconnect(db_conn_t *); -static int ora_drv_prepare(db_stmt_t *, const char *); -static int ora_drv_bind_param(db_stmt_t *, db_bind_t *, unsigned int); -static int ora_drv_bind_result(db_stmt_t *, db_bind_t *, unsigned int); -static int ora_drv_execute(db_stmt_t *, db_result_set_t *); -static int ora_drv_fetch(db_result_set_t *); -static int ora_drv_fetch_row(db_result_set_t *, db_row_t *); -static unsigned long long ora_drv_num_rows(db_result_set_t *); -static int ora_drv_query(db_conn_t *, const char *, db_result_set_t *); -static int ora_drv_free_results(db_result_set_t *); +static int ora_drv_prepare(db_stmt_t *, const char *, size_t); +static int ora_drv_bind_param(db_stmt_t *, db_bind_t *, size_t); +static int ora_drv_bind_result(db_stmt_t *, db_bind_t *, size_t); +static db_error_t ora_drv_execute(db_stmt_t *, db_result_t *); +static int ora_drv_fetch(db_result_t *); +static int ora_drv_fetch_row(db_result_t *, db_row_t *); +static db_error_t ora_drv_query(db_conn_t *, const char *, size_t, + db_result_t *); +static int ora_drv_free_results(db_result_t *); static int ora_drv_close(db_stmt_t *); -static int ora_drv_store_results(db_result_set_t *); +static int ora_drv_store_results(db_result_t *); static int ora_drv_done(void); /* Oracle driver definition */ @@ -192,24 +192,22 @@ static db_driver_t oracle_driver = .args = ora_drv_args, .ops = { - ora_drv_init, - ora_drv_describe, - ora_drv_connect, - ora_drv_disconnect, - ora_drv_prepare, - ora_drv_bind_param, - ora_drv_bind_result, - ora_drv_execute, - ora_drv_fetch, - ora_drv_fetch_row, - ora_drv_num_rows, - ora_drv_free_results, - ora_drv_close, - ora_drv_query, - ora_drv_store_results, - ora_drv_done - }, - .listitem = {NULL, NULL} + .init = ora_drv_init, + .describe = ora_drv_describe, + .connect = ora_drv_connect, + .disconnect = ora_drv_disconnect, + .prepare = ora_drv_prepare, + .bind_param = ora_drv_bind_param, + .bind_result = ora_drv_bind_result, + .execute = ora_drv_execute, + .fetch = ora_drv_fetch, + .fetch_row = ora_drv_fetch_row, + .free_results = ora_drv_free_results, + .close = ora_drv_close, + .query = ora_drv_query, + .store_results = ora_drv_store_results, + .done = ora_drv_done + } }; @@ -402,7 +400,7 @@ int ora_drv_disconnect(db_conn_t *sb_conn) /* Prepare statement */ -int ora_drv_prepare(db_stmt_t *stmt, const char *query) +int ora_drv_prepare(db_stmt_t *stmt, const char *query, size_t len) { ora_conn_t *ora_con = (ora_conn_t *)stmt->connection->ptr; sword rc; @@ -468,7 +466,7 @@ int ora_drv_prepare(db_stmt_t *stmt, const char *query) if (ora_stmt->type != STMT_TYPE_BEGIN && ora_stmt->type != STMT_TYPE_COMMIT) { - rc = OCIStmtPrepare(ora_stmt->ptr, ora_con->errhp, buf, strlen(buf), + rc = OCIStmtPrepare(ora_stmt->ptr, ora_con->errhp, buf, j, OCI_NTV_SYNTAX, OCI_DEFAULT); CHECKERR("OCIStmtPrepare"); @@ -507,7 +505,7 @@ int ora_drv_prepare(db_stmt_t *stmt, const char *query) /* Bind parameters for prepared statement */ -int ora_drv_bind_param(db_stmt_t *stmt, db_bind_t *params, unsigned int len) +int ora_drv_bind_param(db_stmt_t *stmt, db_bind_t *params, size_t len) { ora_conn_t *con = (ora_conn_t *)stmt->connection->ptr; ora_stmt_t *ora_stmt = (ora_stmt_t *)stmt->ptr; @@ -574,7 +572,7 @@ int ora_drv_bind_param(db_stmt_t *stmt, db_bind_t *params, unsigned int len) /* Bind results for prepared statement */ -int ora_drv_bind_result(db_stmt_t *stmt, db_bind_t *params, unsigned int len) +int ora_drv_bind_result(db_stmt_t *stmt, db_bind_t *params, size_t len) { /* NYI */ @@ -589,7 +587,7 @@ int ora_drv_bind_result(db_stmt_t *stmt, db_bind_t *params, unsigned int len) /* Execute prepared statement */ -int ora_drv_execute(db_stmt_t *stmt, db_result_set_t *rs) +db_error_t ora_drv_execute(db_stmt_t *stmt, db_result_t *rs) { db_conn_t *db_con = stmt->connection; ora_stmt_t *ora_stmt = stmt->ptr; @@ -675,7 +673,7 @@ int ora_drv_execute(db_stmt_t *stmt, db_result_set_t *rs) } buf[j] = '\0'; - db_con->db_errno = ora_drv_query(db_con, buf, rs); + db_con->db_errno = ora_drv_query(db_con, buf, j, rs); free(buf); return SB_DB_ERROR_NONE; @@ -690,8 +688,8 @@ int ora_drv_execute(db_stmt_t *stmt, db_result_set_t *rs) /* Execute SQL query */ -int ora_drv_query(db_conn_t *sb_conn, const char *query, - db_result_set_t *rs) +db_error_t ora_drv_query(db_conn_t *sb_conn, const char *query, size_t len, + db_result_t *rs) { ora_conn_t *ora_con = sb_conn->ptr; sword rc = 0; @@ -728,7 +726,7 @@ int ora_drv_query(db_conn_t *sb_conn, const char *query, stmt = (OCIStmt *)tmp; - rc = OCIStmtPrepare(stmt, ora_con->errhp, (OraText *)query, strlen(query), + rc = OCIStmtPrepare(stmt, ora_con->errhp, (OraText *)query, len, OCI_NTV_SYNTAX, OCI_DEFAULT); CHECKERR("OCIStmtPrepare"); @@ -752,7 +750,7 @@ int ora_drv_query(db_conn_t *sb_conn, const char *query, /* Fetch row from result set of a prepared statement */ -int ora_drv_fetch(db_result_set_t *rs) +int ora_drv_fetch(db_result_t *rs) { /* NYI */ (void)rs; @@ -764,7 +762,7 @@ int ora_drv_fetch(db_result_set_t *rs) /* Fetch row from result set of a query */ -int ora_drv_fetch_row(db_result_set_t *rs, db_row_t *row) +int ora_drv_fetch_row(db_result_t *rs, db_row_t *row) { /* NYI */ (void)rs; /* unused */ @@ -774,25 +772,10 @@ int ora_drv_fetch_row(db_result_set_t *rs, db_row_t *row) } -/* Return the number of rows in a result set */ - - -unsigned long long ora_drv_num_rows(db_result_set_t *rs) -{ - ora_result_set_t *ora_rs = (ora_result_set_t *)rs->ptr; - - /* Check if the results are already fetched */ - if (ora_rs != NULL) - return ora_rs->nrows; - - return 0; -} - - /* Store results from the last query */ -int ora_drv_store_results(db_result_set_t *rs) +int ora_drv_store_results(db_result_t *rs) { unsigned int i; sword rc; @@ -935,7 +918,7 @@ int ora_drv_store_results(db_result_set_t *rs) /* Free result set */ -int ora_drv_free_results(db_result_set_t *rs) +int ora_drv_free_results(db_result_t *rs) { ora_result_set_t *ora_rs = (ora_result_set_t *)rs->ptr; ora_row_t *row; @@ -979,7 +962,9 @@ int ora_drv_free_results(db_result_set_t *rs) } free(ora_rs); - + + rs->ptr = NULL; + return 0; } diff --git a/sysbench/drivers/pgsql/drv_pgsql.c b/sysbench/drivers/pgsql/drv_pgsql.c index 24c20e2..cc4982f 100644 --- a/sysbench/drivers/pgsql/drv_pgsql.c +++ b/sysbench/drivers/pgsql/drv_pgsql.c @@ -114,17 +114,16 @@ static int pgsql_drv_init(void); static int pgsql_drv_describe(drv_caps_t *); static int pgsql_drv_connect(db_conn_t *); static int pgsql_drv_disconnect(db_conn_t *); -static int pgsql_drv_prepare(db_stmt_t *, const char *); -static int pgsql_drv_bind_param(db_stmt_t *, db_bind_t *, unsigned int); -static int pgsql_drv_bind_result(db_stmt_t *, db_bind_t *, unsigned int); -static int pgsql_drv_execute(db_stmt_t *, db_result_set_t *); -static int pgsql_drv_fetch(db_result_set_t *); -static int pgsql_drv_fetch_row(db_result_set_t *, db_row_t *); -static unsigned long long pgsql_drv_num_rows(db_result_set_t *); -static int pgsql_drv_query(db_conn_t *, const char *, db_result_set_t *); -static int pgsql_drv_free_results(db_result_set_t *); +static int pgsql_drv_prepare(db_stmt_t *, const char *, size_t); +static int pgsql_drv_bind_param(db_stmt_t *, db_bind_t *, size_t); +static int pgsql_drv_bind_result(db_stmt_t *, db_bind_t *, size_t); +static db_error_t pgsql_drv_execute(db_stmt_t *, db_result_t *); +static int pgsql_drv_fetch(db_result_t *); +static int pgsql_drv_fetch_row(db_result_t *, db_row_t *); +static db_error_t pgsql_drv_query(db_conn_t *, const char *, size_t, + db_result_t *); +static int pgsql_drv_free_results(db_result_t *); static int pgsql_drv_close(db_stmt_t *); -static int pgsql_drv_store_results(db_result_set_t *); static int pgsql_drv_done(void); /* PgSQL driver definition */ @@ -136,24 +135,21 @@ static db_driver_t pgsql_driver = .args = pgsql_drv_args, .ops = { - pgsql_drv_init, - pgsql_drv_describe, - pgsql_drv_connect, - pgsql_drv_disconnect, - pgsql_drv_prepare, - pgsql_drv_bind_param, - pgsql_drv_bind_result, - pgsql_drv_execute, - pgsql_drv_fetch, - pgsql_drv_fetch_row, - pgsql_drv_num_rows, - pgsql_drv_free_results, - pgsql_drv_close, - pgsql_drv_query, - pgsql_drv_store_results, - pgsql_drv_done - }, - .listitem = {NULL, NULL} + .init = pgsql_drv_init, + .describe = pgsql_drv_describe, + .connect = pgsql_drv_connect, + .disconnect = pgsql_drv_disconnect, + .prepare = pgsql_drv_prepare, + .bind_param = pgsql_drv_bind_param, + .bind_result = pgsql_drv_bind_result, + .execute = pgsql_drv_execute, + .fetch = pgsql_drv_fetch, + .fetch_row = pgsql_drv_fetch_row, + .free_results = pgsql_drv_free_results, + .close = pgsql_drv_close, + .query = pgsql_drv_query, + .done = pgsql_drv_done + } }; @@ -273,7 +269,7 @@ int pgsql_drv_disconnect(db_conn_t *sb_conn) /* Prepare statement */ -int pgsql_drv_prepare(db_stmt_t *stmt, const char *query) +int pgsql_drv_prepare(db_stmt_t *stmt, const char *query, size_t len) { PGconn *con = (PGconn *)stmt->connection->ptr; PGresult *pgres; @@ -285,7 +281,9 @@ int pgsql_drv_prepare(db_stmt_t *stmt, const char *query) unsigned int buflen; int n; char name[32]; - + + (void) len; /* unused */ + if (con == NULL) return 1; @@ -375,7 +373,7 @@ int pgsql_drv_prepare(db_stmt_t *stmt, const char *query) /* Bind parameters for prepared statement */ -int pgsql_drv_bind_param(db_stmt_t *stmt, db_bind_t *params, unsigned int len) +int pgsql_drv_bind_param(db_stmt_t *stmt, db_bind_t *params, size_t len) { PGconn *con = (PGconn *)stmt->connection->ptr; PGresult *pgres; @@ -405,7 +403,7 @@ int pgsql_drv_bind_param(db_stmt_t *stmt, db_bind_t *params, unsigned int len) if ((unsigned)pgstmt->nparams != len) { log_text(LOG_ALERT, "wrong number of parameters in prepared statement"); - log_text(LOG_DEBUG, "counted: %d, passed to bind_param(): %d", + log_text(LOG_DEBUG, "counted: %d, passed to bind_param(): %zd", pgstmt->nparams, len); return 1; } @@ -454,7 +452,7 @@ int pgsql_drv_bind_param(db_stmt_t *stmt, db_bind_t *params, unsigned int len) /* Bind results for prepared statement */ -int pgsql_drv_bind_result(db_stmt_t *stmt, db_bind_t *params, unsigned int len) +int pgsql_drv_bind_result(db_stmt_t *stmt, db_bind_t *params, size_t len) { /* unused */ (void)stmt; @@ -468,35 +466,67 @@ int pgsql_drv_bind_result(db_stmt_t *stmt, db_bind_t *params, unsigned int len) /* Check query execution status */ -static int pgsql_check_status(PGconn *pgcon, PGresult *pgres, - const char *funcname) +static db_error_t pgsql_check_status(PGconn *pgcon, PGresult *pgres, + const char *funcname, const char *query, + db_result_t *rs) { ExecStatusType status; + db_error_t rc; status = PQresultStatus(pgres); - if (status != PGRES_TUPLES_OK && status != PGRES_COMMAND_OK) - { + switch(status) { + case PGRES_TUPLES_OK: + rs->nrows = PQntuples(pgres); + rs->stat_type = DB_STAT_READ; + rc = DB_ERROR_NONE; + + break; + + case PGRES_COMMAND_OK: + rs->nrows = strtoul(PQcmdTuples(pgres), NULL, 10);; + rs->stat_type = (rs->nrows > 0) ? DB_STAT_WRITE : DB_STAT_OTHER; + rc = DB_ERROR_NONE; + + break; + + case PGRES_FATAL_ERROR: + rs->nrows = 0; + rs->stat_type = DB_STAT_ERROR; + const char * const errmsg = PQerrorMessage(pgcon); if (strstr(errmsg, "deadlock detected") || strstr(errmsg, "duplicate key value violates unique constraint")) { PQexec(pgcon, "ROLLBACK"); - return SB_DB_ERROR_RESTART_TRANSACTION; + rc = DB_ERROR_IGNORABLE; + } + else + { + log_text(LOG_FATAL, "%s() failed: %d %s", funcname, status, errmsg); + + if (query != NULL) + log_text(LOG_FATAL, "failed query was: %s", query); + + rc = DB_ERROR_FATAL; } - log_text(LOG_FATAL, "%s() failed: %d %s", funcname, status, errmsg); - return SB_DB_ERROR_FAILED; + break; + + default: + rs->nrows = 0; + rs->stat_type = DB_STAT_OTHER; + rc = DB_ERROR_NONE; } - return SB_DB_ERROR_NONE; + return rc; } /* Execute prepared statement */ -int pgsql_drv_execute(db_stmt_t *stmt, db_result_set_t *rs) +db_error_t pgsql_drv_execute(db_stmt_t *stmt, db_result_t *rs) { db_conn_t *con = stmt->connection; PGconn *pgcon = (PGconn *)con->ptr; @@ -507,15 +537,18 @@ int pgsql_drv_execute(db_stmt_t *stmt, db_result_set_t *rs) unsigned int i, j, vcnt; char need_realloc; int n; - int rc; + db_error_t rc; if (!stmt->emulated) { pgstmt = stmt->ptr; if (pgstmt == NULL) - return SB_DB_ERROR_FAILED; + { + log_text(LOG_DEBUG, + "ERROR: exiting mysql_drv_execute(), uninitialized statement"); + return DB_ERROR_FATAL; + } - /* Convert SysBench bind structures to PgSQL data */ for (i = 0; i < (unsigned)pgstmt->nparams; i++) { @@ -537,10 +570,9 @@ int pgsql_drv_execute(db_stmt_t *stmt, db_result_set_t *rs) pgres = PQexecPrepared(pgcon, pgstmt->name, pgstmt->nparams, (const char **)pgstmt->pvalues, NULL, NULL, 1); - rc = pgsql_check_status(pgcon, pgres, "PQexecPrepared"); + rc = pgsql_check_status(pgcon, pgres, "PQexecPrepared", NULL, rs); - if (rc == SB_DB_ERROR_NONE) - rs->ptr = (void *)pgres; + rs->ptr = (void *) pgres; return rc; } @@ -557,7 +589,7 @@ int pgsql_drv_execute(db_stmt_t *stmt, db_result_set_t *rs) buflen = (buflen > 0) ? buflen * 2 : 256; buf = realloc(buf, buflen); if (buf == NULL) - return SB_DB_ERROR_FAILED; + return DB_ERROR_FATAL; need_realloc = 0; } @@ -577,37 +609,31 @@ int pgsql_drv_execute(db_stmt_t *stmt, db_result_set_t *rs) vcnt++; } buf[j] = '\0'; - - con->db_errno = pgsql_drv_query(con, buf, rs); - free(buf); - if (con->db_errno != SB_DB_ERROR_NONE) - { - return con->db_errno; - } - return SB_DB_ERROR_NONE; + rc = pgsql_drv_query(con, buf, j, rs); + + free(buf); + + return rc; } /* Execute SQL query */ -int pgsql_drv_query(db_conn_t *sb_conn, const char *query, - db_result_set_t *rs) +db_error_t pgsql_drv_query(db_conn_t *sb_conn, const char *query, size_t len, + db_result_t *rs) { PGconn *con = sb_conn->ptr; PGresult *pgres; - int rc; + db_error_t rc; - (void)rs; /* unused */ + (void)len; /* unused */ pgres = PQexec(con, query); - rc = pgsql_check_status(con, pgres, "PQexec"); + rc = pgsql_check_status(con, pgres, "PQexec", query, rs); - if (rc == SB_DB_ERROR_NONE) - rs->ptr = pgres; - else if (rc == SB_DB_ERROR_FAILED) - log_text(LOG_FATAL, "failed query: %s", query); + rs->ptr = pgres; return rc; } @@ -616,7 +642,7 @@ int pgsql_drv_query(db_conn_t *sb_conn, const char *query, /* Fetch row from result set of a prepared statement */ -int pgsql_drv_fetch(db_result_set_t *rs) +int pgsql_drv_fetch(db_result_t *rs) { /* NYI */ (void)rs; @@ -628,7 +654,7 @@ int pgsql_drv_fetch(db_result_set_t *rs) /* Fetch row from result set of a query */ -int pgsql_drv_fetch_row(db_result_set_t *rs, db_row_t *row) +int pgsql_drv_fetch_row(db_result_t *rs, db_row_t *row) { /* NYI */ (void)rs; /* unused */ @@ -638,46 +664,15 @@ int pgsql_drv_fetch_row(db_result_set_t *rs, db_row_t *row) } -/* Return the number of rows in a result set */ - - -unsigned long long pgsql_drv_num_rows(db_result_set_t *rs) -{ - return rs->nrows; -} - - -/* Store results from the last query */ - - -int pgsql_drv_store_results(db_result_set_t *rs) -{ - PGresult *pgres; - unsigned long long i,j, ncolumns; - - pgres = (PGresult *)rs->ptr; - if (pgres == NULL) - return 1; - - rs->nrows = PQntuples(pgres); - ncolumns = PQnfields(pgres); - - for (i = 0; i < rs->nrows; i++) - for (j = 0; j < ncolumns; j++) - PQgetvalue(pgres, i, j); - - return 0; -} - - /* Free result set */ -int pgsql_drv_free_results(db_result_set_t *rs) +int pgsql_drv_free_results(db_result_t *rs) { if (rs->ptr != NULL) { PQclear((PGresult *)rs->ptr); + rs->ptr = NULL; return 0; } diff --git a/sysbench/lua/Makefile.am b/sysbench/lua/Makefile.am index bf76623..e52df34 100644 --- a/sysbench/lua/Makefile.am +++ b/sysbench/lua/Makefile.am @@ -15,3 +15,6 @@ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA SUBDIRS = internal + +dist_pkgdata_DATA = common.lua oltp.lua + diff --git a/sysbench/tests/db/common.lua b/sysbench/lua/common.lua similarity index 100% rename from sysbench/tests/db/common.lua rename to sysbench/lua/common.lua diff --git a/sysbench/lua/internal/Makefile.am b/sysbench/lua/internal/Makefile.am index 42e63ae..eba1db0 100644 --- a/sysbench/lua/internal/Makefile.am +++ b/sysbench/lua/internal/Makefile.am @@ -14,10 +14,10 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA -BUILT_SOURCES = sysbench.lua.h -CLEARFILES = sysbench.lua.h +BUILT_SOURCES = sysbench.lua.h sysbench.sql.lua.h +CLEARFILES = sysbench.lua.h sysbench.sql.lua.h -EXTRA_DIST = sysbench.lua +EXTRA_DIST = sysbench.lua sysbench.sql.lua SUFFIXES = .lua .lua.h diff --git a/sysbench/lua/internal/sysbench.lua b/sysbench/lua/internal/sysbench.lua index 19fcc33..10dacf4 100644 --- a/sysbench/lua/internal/sysbench.lua +++ b/sysbench/lua/internal/sysbench.lua @@ -1,4 +1,4 @@ --- Copyright (C) 2016 Alexey Kopytov +-- Copyright (C) 2016-2017 Alexey Kopytov -- This program is free software; you can redistribute it and/or modify -- it under the terms of the GNU General Public License as published by @@ -82,8 +82,7 @@ thread_id = sysbench.tid function sb_rnd() -- Keep lower 32 bits from sysbench.rand.uniform_uint64() and convert them to -- a Lua number - return tonumber(sysbench.rand.uniform_uint64() % - tonumber("100000000", 16)) + return tonumber(sysbench.rand.uniform_uint64() % 4294967296) end sb_rand = sysbench.rand.default @@ -106,7 +105,6 @@ function sb_rand_uniq(a, b) return res end - db_connect = sysbench.db.connect db_disconnect = sysbench.db.disconnect @@ -134,9 +132,6 @@ DB_ERROR_FAILED = sysbench.db.DB_ERROR_FAILED -- Main event loop. This is a Lua version of sysbench.c:thread_run() -- ---------------------------------------------------------------------- function thread_run(thread_id) - if (type(event) ~= "function") then - error("Cannot find the 'event' function in the script") - end while sysbench.more_events() do sysbench.event_start() event(thread_id) diff --git a/sysbench/lua/internal/sysbench.sql.lua b/sysbench/lua/internal/sysbench.sql.lua new file mode 100644 index 0000000..945c498 --- /dev/null +++ b/sysbench/lua/internal/sysbench.sql.lua @@ -0,0 +1,223 @@ +-- Copyright (C) 2017 Alexey Kopytov + +-- This program is free software; you can redistribute it and/or modify +-- it under the terms of the GNU General Public License as published by +-- the Free Software Foundation; either version 2 of the License, or +-- (at your option) any later version. + +-- This program is distributed in the hope that it will be useful, +-- but WITHOUT ANY WARRANTY; without even the implied warranty of +-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +-- GNU General Public License for more details. + +-- You should have received a copy of the GNU General Public License +-- along with this program; if not, write to the Free Software +-- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +-- ---------------------------------------------------------------------- +-- SQL API +-- ---------------------------------------------------------------------- + +ffi = require("ffi") + +sysbench.sql = {} + +ffi.cdef[[ +typedef enum +{ + DB_ERROR_NONE, /* no error(s) */ + DB_ERROR_IGNORABLE, /* error should be ignored as defined by command + line arguments or a custom error handler */ + DB_ERROR_FATAL /* non-ignorable error */ +} sql_error_t; + +typedef struct db_driver sql_driver; +typedef struct db_conn sql_connection; +typedef struct db_stmt sql_statement; +typedef struct db_result sql_result; + +typedef enum +{ + SQL_TYPE_NONE, + SQL_TYPE_TINYINT, + SQL_TYPE_SMALLINT, + SQL_TYPE_INT, + SQL_TYPE_BIGINT, + SQL_TYPE_FLOAT, + SQL_TYPE_DOUBLE, + SQL_TYPE_TIME, + SQL_TYPE_DATE, + SQL_TYPE_DATETIME, + SQL_TYPE_TIMESTAMP, + SQL_TYPE_CHAR, + SQL_TYPE_VARCHAR +} sql_bind_type_t; + +typedef struct +{ + sql_bind_type_t type; + void *buffer; + unsigned long *data_len; + unsigned long max_len; + char *is_null; +} sql_bind; + +sql_driver *db_create(const char *); +int db_destroy(sql_driver *drv); + +sql_connection *db_connection_create(sql_driver * drv); +int db_connection_close(sql_connection *con); +void db_connection_free(sql_connection *con); + +int db_bulk_insert_init(sql_connection *, const char *, size_t); +int db_bulk_insert_next(sql_connection *, const char *, size_t); +void db_bulk_insert_done(sql_connection *); + +sql_result *db_query(sql_connection *con, const char *query, size_t len); + +sql_statement *db_prepare(sql_connection *con, const char *query, size_t len); +int db_bind_param(sql_statement *stmt, sql_bind *params, size_t len); +int db_bind_result(sql_statement *stmt, sql_bind *results, size_t len); +sql_result db_execute(sql_statement *stmt); +int db_close(sql_statement *stmt); +]] + +local sql_driver = ffi.typeof('sql_driver *') +local sql_connection = ffi.typeof('sql_connection *') +local sql_statement = ffi.typeof('sql_statement *') +local sql_bind = ffi.typeof('sql_bind'); + +sysbench.sql.type = + { + NONE = ffi.C.SQL_TYPE_NONE, + TINYINT = ffi.C.SQL_TYPE_TINYINT, + SMALLINT = ffi.C.SQL_TYPE_SMALLINT, + INT = ffi.C.SQL_TYPE_INT, + BIGINT = ffi.C.SQL_TYPE_BIGINT, + FLOAT = ffi.C.SQL_TYPE_FLOAT, + DOUBLE = ffi.C.SQL_TYPE_DOUBLE, + TIME = ffi.C.SQL_TYPE_TIME, + DATE = ffi.C.SQL_TYPE_DATE, + DATETIME = ffi.C.SQL_TYPE_DATETIME, + TIMESTAMP = ffi.C.SQL_TYPE_TIMESTAMP, + CHAR = ffi.C.SQL_TYPE_CHAR, + VARCHAR = ffi.C.SQL_TYPE_VARCHAR + } + +local function check_type(type, var, func) + if var == nil or not ffi.istype(type, var) then + error(string.format("bad argument '%s' to %s() where a '%s' was expected", + var, func, type)) + end +end + +-- Initialize a given SQL driver and return a handle to it to create +-- connections. A nil driver name (i.e. no function argument) initializes the +-- default driver, i.e. the one specified with --db-driver on the command line. +function sysbench.sql.driver(driver_name) + local drv = ffi.C.db_create(driver_name) + if (drv == nil) then + error("failed to initialize the DB driver") + end + return ffi.gc(drv, ffi.C.db_destroy) +end + +function sysbench.sql.connect(driver) + check_type(sql_driver, driver, 'sysbench.sql.connect') + local con = ffi.C.db_connection_create(driver) + if con == nil then + error('connection creation failed') + end + return ffi.gc(con, ffi.C.db_connection_free) +end + +function sysbench.sql.disconnect(con) + check_type(sql_connection, con, 'sysbench.sql.disconnect') + return ffi.C.db_connection_close(con) == 0 +end + +function sysbench.sql.query(con, query) + check_type(sql_connection, con, 'sysbench.sql.query') + return ffi.C.db_query(con, query, #query) +end + +function sysbench.sql.bulk_insert_init(con, query) + check_type(sql_connection, con, 'sysbench.sql.bulk_insert_init') + return ffi.C.db_bulk_insert_init(con, query, #query) +end + +function sysbench.sql.bulk_insert_next(con, val) + check_type(sql_connection, con, 'sysbench.sql.bulk_insert_next') + return ffi.C.db_bulk_insert_next(con, val, #val) +end + +function sysbench.sql.bulk_insert_done(con) + check_type(sql_connection, con, 'sysbench.sql.bulk_insert_done') + return ffi.C.db_bulk_insert_done(con) +end + +function sysbench.sql.prepare(con, query) + check_type(sql_connection, con, 'sysbench.sql.prepare') + return ffi.C.db_prepare(con, query, #query) +end + +function sysbench.sql.bind_param(stmt, params) + local len = #params + local sql_params = {} + local i + + check_type(sql_statement, stmt, 'sysbench.sql.bind_param') + + error("NYI") + + return ffi.C.db_bind_param(stmt, + ffi.new("sql_bind[" .. len .."]", + sql_params), + len) +end + +-- sql_driver metatable +local driver_mt = { + __index = { + connect = sysbench.sql.connect, + }, + __gc = ffi.C.db_destroy, + __tostring = function() return '' end, +} +ffi.metatype("struct db_driver", driver_mt) + +-- sql_connection metatable +local connection_mt = { + __index = { + disconnect = sysbench.sql.disconnect, + query = sysbench.sql.query, + bulk_insert_init = sysbench.sql.bulk_insert_init, + bulk_insert_next = sysbench.sql.bulk_insert_next, + bulk_insert_done = sysbench.sql.bulk_insert_done, + prepare = sysbench.sql.prepare, + }, + __tostring = function() return '' end, + __gc = ffi.C.db_connection_free, +} +ffi.metatype("struct db_conn", connection_mt) + +-- sql_statement metatable +local statement_mt = { + __index = { + bind_param = sysbench.sql.bind_param, + }, + __tostring = function() return '' end, + __gc = ffi.C.db_close, +} +ffi.metatype("struct db_stmt", statement_mt) + +-- sql_bind metatable +local bind_mt = { + __tostring = function() return '' end, +} +ffi.metatype("sql_bind", bind_mt) + +-- error codes +sysbench.sql.ERROR_NONE = ffi.C.DB_ERROR_NONE +sysbench.sql.ERROR_IGNORABLE = ffi.C.DB_ERROR_IGNORABLE +sysbench.sql.ERROR_FATAL = ffi.C.DB_ERROR_FATAL diff --git a/sysbench/tests/db/oltp.lua b/sysbench/lua/oltp.lua similarity index 100% rename from sysbench/tests/db/oltp.lua rename to sysbench/lua/oltp.lua diff --git a/sysbench/sb_global.h b/sysbench/sb_global.h index edf855f..b0b0409 100644 --- a/sysbench/sb_global.h +++ b/sysbench/sb_global.h @@ -24,10 +24,4 @@ #include "config.h" #endif -#ifdef HAVE_FUNC_ATTRIBUTE_FORMAT -# define SB_ATTRIBUTE_FORMAT(style, m, n) __attribute__((format(style, m, n))) -#else -# define SB_ATTRIBUTE_FORMAT(style, m, n) -#endif - #endif /* SB_GLOBAL_H */ diff --git a/sysbench/sb_logger.h b/sysbench/sb_logger.h index 5b6ebb7..52c354c 100644 --- a/sysbench/sb_logger.h +++ b/sysbench/sb_logger.h @@ -27,7 +27,7 @@ # include #endif -#include "sb_global.h" +#include "sb_util.h" #include "sb_options.h" #include "sb_timer.h" #include "sb_histogram.h" diff --git a/sysbench/sb_lua.c b/sysbench/sb_lua.c index 04175e2..5cbbfe7 100644 --- a/sysbench/sb_lua.c +++ b/sysbench/sb_lua.c @@ -1,5 +1,5 @@ /* Copyright (C) 2006 MySQL AB - Copyright (C) 2006-2016 Alexey Kopytov + Copyright (C) 2006-2017 Alexey Kopytov This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -32,6 +32,7 @@ #include "ck_pr.h" /* Auto-generated headers */ #include "lua/internal/sysbench.lua.h" +#include "lua/internal/sysbench.sql.lua.h" #define EVENT_FUNC "event" #define PREPARE_FUNC "prepare" @@ -73,7 +74,7 @@ typedef struct { } sb_lua_bind_t; typedef struct { - db_result_set_t *ptr; + db_result_t *ptr; } sb_lua_db_rs_t; typedef struct { @@ -96,6 +97,8 @@ static unsigned int nevents; static sb_test_t sbtest; +static const char *sb_lua_script_path; + /* Lua test operations */ static int sb_lua_op_init(void); @@ -116,26 +119,23 @@ static sb_operations_t lua_ops = { static lua_State *gstate; /* Database driver */ -static db_driver_t *db_driver; +static TLS db_driver_t *db_driver; /* Variable with unique address to store per-state data */ static const char sb_lua_ctxt_key = 0; -/* Control variable for sb_lua_db_init_once() */ -static pthread_once_t db_init_control = PTHREAD_ONCE_INIT; - /* Lua test commands */ static int sb_lua_cmd_prepare(void); static int sb_lua_cmd_cleanup(void); static int sb_lua_cmd_help(void); /* Initialize interpreter state */ -static lua_State *sb_lua_new_state(const char *, int); +static lua_State *sb_lua_new_state(int); /* Close interpretet state */ static int sb_lua_close_state(lua_State *); -/* Exported C functions */ +/* Exported C functions for legacy Lua API */ static int sb_lua_db_connect(lua_State *); static int sb_lua_db_disconnect(lua_State *); static int sb_lua_db_query(lua_State *); @@ -165,14 +165,14 @@ unsigned int sb_lua_table_size(lua_State *, int); sb_test_t *sb_load_lua(const char *testname) { - unsigned int i; - #ifdef DATA_PATH setenv("LUA_PATH", DATA_PATH LUA_DIRSEP "?.lua", 0); #endif + sb_lua_script_path = testname; + /* Initialize global interpreter state */ - gstate = sb_lua_new_state(testname, -1); + gstate = sb_lua_new_state(-1); if (gstate == NULL) goto error; @@ -193,13 +193,9 @@ sb_test_t *sb_load_lua(const char *testname) /* Test operations */ sbtest.ops = lua_ops; - lua_getglobal(gstate, THREAD_INIT_FUNC); - if (!lua_isnil(gstate, -1)) - sbtest.ops.thread_init = &sb_lua_op_thread_init; + sbtest.ops.thread_init = &sb_lua_op_thread_init; - lua_getglobal(gstate, THREAD_DONE_FUNC); - if (!lua_isnil(gstate, -1)) - sbtest.ops.thread_done = &sb_lua_op_thread_done; + sbtest.ops.thread_done = &sb_lua_op_thread_done; lua_getglobal(gstate, THREAD_RUN_FUNC); if (!lua_isnil(gstate, -1)) @@ -207,30 +203,20 @@ sb_test_t *sb_load_lua(const char *testname) sbtest.ops.print_stats = &sb_lua_op_print_stats; - - /* Initialize per-thread interpreters */ + + /* Allocate per-thread interpreters array */ states = (lua_State **)calloc(sb_globals.num_threads, sizeof(lua_State *)); if (states == NULL) goto error; - for (i = 0; i < sb_globals.num_threads; i++) - { - states[i] = sb_lua_new_state(testname, i); - if (states[i] == NULL) - goto error; - } - + return &sbtest; error: sb_lua_close_state(gstate); if (states != NULL) - { - for (i = 0; i < sb_globals.num_threads; i++) - sb_lua_close_state(states[i]); free(states); - } - + return NULL; } @@ -271,15 +257,24 @@ sb_event_t sb_lua_next_event(int thread_id) int sb_lua_op_thread_init(int thread_id) { - lua_State * const L = states[thread_id]; + lua_State * L; + + L = sb_lua_new_state(thread_id); + if (L == NULL) + return 1; + + states[thread_id] = L; lua_getglobal(L, THREAD_INIT_FUNC); - lua_pushnumber(L, thread_id); - - if (lua_pcall(L, 1, 1, 0)) + if (!lua_isnil(L, -1)) { - CALL_ERROR(L, THREAD_INIT_FUNC); - return 1; + lua_pushnumber(L, thread_id); + + if (lua_pcall(L, 1, 1, 0)) + { + CALL_ERROR(L, THREAD_INIT_FUNC); + return 1; + } } return 0; @@ -304,34 +299,35 @@ int sb_lua_op_thread_run(int thread_id) int sb_lua_op_thread_done(int thread_id) { lua_State * const L = states[thread_id]; + int rc = 0; lua_getglobal(L, THREAD_DONE_FUNC); - lua_pushnumber(L, thread_id); - if (lua_pcall(L, 1, 1, 0)) + if (!lua_isnil(L, -1)) { - CALL_ERROR(L, THREAD_DONE_FUNC); - return 1; + lua_pushnumber(L, thread_id); + + if (lua_pcall(L, 1, 1, 0)) + { + CALL_ERROR(L, THREAD_DONE_FUNC); + rc = 1; + } } - - return 0; + + sb_lua_close_state(L); + + return rc; } void sb_lua_op_print_stats(sb_stat_t type) { - /* check if db driver has been initialized */ - if (db_driver != NULL) - db_print_stats(type); + db_print_stats(type); } int sb_lua_op_done(void) { - unsigned int i; - - for (i = 0; i < sb_globals.num_threads; i++) - lua_close(states[i]); - - free(states); + if (states != NULL) + free(states); lua_getglobal(gstate, DONE_FUNC); if (!lua_isnil(gstate, -1)) @@ -348,7 +344,7 @@ int sb_lua_op_done(void) /* Allocate and initialize new interpreter state */ -lua_State *sb_lua_new_state(const char *scriptname, int thread_id) +lua_State *sb_lua_new_state(int thread_id) { lua_State *L; sb_lua_ctxt_t *ctxt; @@ -447,9 +443,9 @@ lua_State *sb_lua_new_state(const char *scriptname, int thread_id) SB_LUA_FUNC("store_results", sb_lua_db_store_results); SB_LUA_FUNC("free_results", sb_lua_db_free_results); - SB_LUA_VAR("DB_ERROR_NONE", SB_DB_ERROR_NONE); - SB_LUA_VAR("DB_ERROR_RESTART_TRANSACTION", SB_DB_ERROR_RESTART_TRANSACTION); - SB_LUA_VAR("DB_ERROR_FAILED", SB_DB_ERROR_FAILED); + SB_LUA_VAR("DB_ERROR_NONE", DB_ERROR_NONE); + SB_LUA_VAR("DB_ERROR_RESTART_TRANSACTION", DB_ERROR_IGNORABLE); + SB_LUA_VAR("DB_ERROR_FAILED", DB_ERROR_FATAL); #undef SB_LUA_VAR #undef SB_LUA_FUNC @@ -467,18 +463,36 @@ lua_State *sb_lua_new_state(const char *scriptname, int thread_id) { log_text(LOG_FATAL, "failed to load internal module sysbench.lua: %s", lua_tostring(L, -1)); + return NULL; } lua_pushstring(L, "sysbench"); lua_call(L, 1, 0); - if (luaL_loadfile(L, scriptname)) + if (luaL_loadbuffer(L, (const char *) sysbench_sql_lua, sysbench_sql_lua_len, + "sysbench.sql.lua")) { + log_text(LOG_FATAL, "failed to load internal module sysbench.sql.lua: %s", + lua_tostring(L, -1)); + return NULL; + } + lua_pushstring(L, "sysbench.sql"); + lua_call(L, 1, 0); + + int rc; + + if ((rc = luaL_loadfile(L, sb_lua_script_path))) + { + if (rc != LUA_ERRFILE) + { + lua_error(L); + return NULL; + } #ifdef DATA_PATH /* first location failed - look in DATA_PATH */ char p[PATH_MAX + 1]; strncpy(p, DATA_PATH LUA_DIRSEP, sizeof(p)); - strncat(p, scriptname, sizeof(p)-strlen(p)-1); - if (!strrchr(scriptname, '.')) + strncat(p, sb_lua_script_path, sizeof(p)-strlen(p)-1); + if (!strrchr(sb_lua_script_path, '.')) { /* add .lua extension if there isn't one */ strncat(p, ".lua", sizeof(p)-strlen(p)-1); @@ -490,6 +504,7 @@ lua_State *sb_lua_new_state(const char *scriptname, int thread_id) return NULL; } #else + lua_error(L); return NULL; #endif } @@ -519,6 +534,12 @@ int sb_lua_close_state(lua_State *state) if (state != NULL) lua_close(state); + if (db_driver != NULL) + { + db_destroy(db_driver); + db_driver = NULL; + } + return 0; } @@ -571,29 +592,19 @@ int sb_lua_cmd_help(void) } -/* init_routine for pthread_once() */ - - -static void sb_lua_db_init_once(void) -{ - if (db_driver == NULL) - db_driver = db_init(NULL); -} - int sb_lua_db_connect(lua_State *L) { sb_lua_ctxt_t *ctxt; ctxt = sb_lua_get_context(L); - /* Initialize the DB driver once for all threads */ - pthread_once(&db_init_control, sb_lua_db_init_once); + db_driver = db_create(NULL); if (db_driver == NULL) luaL_error(L, "DB initialization failed"); lua_pushstring(L, db_driver->sname); lua_setglobal(L, "db_driver"); - ctxt->con = db_connect(db_driver); + ctxt->con = db_connection_create(db_driver); if (ctxt->con == NULL) luaL_error(L, "Failed to connect to the database"); db_set_thread(ctxt->con, ctxt->thread_id); @@ -608,7 +619,10 @@ int sb_lua_db_disconnect(lua_State *L) ctxt = sb_lua_get_context(L); if (ctxt->con) - db_disconnect(ctxt->con); + { + db_connection_close(ctxt->con); + db_connection_free(ctxt->con); + } ctxt->con = NULL; @@ -617,26 +631,26 @@ int sb_lua_db_disconnect(lua_State *L) int sb_lua_db_query(lua_State *L) { - sb_lua_ctxt_t *ctxt; - const char *query; - db_result_set_t *rs; + sb_lua_ctxt_t *ctxt; + const char *query; + db_result_t *rs; + size_t len; ctxt = sb_lua_get_context(L); if (ctxt->con == NULL) sb_lua_db_connect(L); - query = luaL_checkstring(L, 1); - rs = db_query(ctxt->con, query); + query = luaL_checklstring(L, 1, &len); + rs = db_query(ctxt->con, query, len); if (rs == NULL) { lua_pushnumber(L, ctxt->con->db_errno); lua_error(L); } - db_store_results(rs); db_free_results(rs); - + return 0; } @@ -644,16 +658,17 @@ int sb_lua_db_bulk_insert_init(lua_State *L) { sb_lua_ctxt_t *ctxt; const char *query; + size_t len; ctxt = sb_lua_get_context(L); if (ctxt->con == NULL) sb_lua_db_connect(L); - - query = luaL_checkstring(L, 1); - if (db_bulk_insert_init(ctxt->con, query)) + + query = luaL_checklstring(L, 1, &len); + if (db_bulk_insert_init(ctxt->con, query, len)) luaL_error(L, "db_bulk_insert_init() failed"); - + return 0; } @@ -661,13 +676,14 @@ int sb_lua_db_bulk_insert_next(lua_State *L) { sb_lua_ctxt_t *ctxt; const char *query; + size_t len; ctxt = sb_lua_get_context(L); CHECK_CONNECTION(L, ctxt); - query = luaL_checkstring(L, 1); - if (db_bulk_insert_next(ctxt->con, query)) + query = luaL_checklstring(L, 1, &len); + if (db_bulk_insert_next(ctxt->con, query, len)) luaL_error(L, "db_bulk_insert_next() failed"); return 0; @@ -688,23 +704,24 @@ int sb_lua_db_bulk_insert_done(lua_State *L) int sb_lua_db_prepare(lua_State *L) { - sb_lua_ctxt_t *ctxt; + sb_lua_ctxt_t *ctxt; sb_lua_db_stmt_t *stmt; - const char *query; + const char *query; + size_t len; ctxt = sb_lua_get_context(L); if (ctxt->con == NULL) sb_lua_db_connect(L); - query = luaL_checkstring(L, 1); - + query = luaL_checklstring(L, 1, &len); + stmt = (sb_lua_db_stmt_t *)lua_newuserdata(L, sizeof(sb_lua_db_stmt_t)); luaL_getmetatable(L, "sysbench.stmt"); lua_setmetatable(L, -2); memset(stmt, 0, sizeof(sb_lua_db_stmt_t)); - - stmt->ptr = db_prepare(ctxt->con, query); + + stmt->ptr = db_prepare(ctxt->con, query, len); if (stmt->ptr == NULL) luaL_error(L, "db_prepare() failed"); @@ -866,7 +883,7 @@ int sb_lua_db_execute(lua_State *L) { sb_lua_ctxt_t *ctxt; sb_lua_db_stmt_t *stmt; - db_result_set_t *ptr; + db_result_t *ptr; sb_lua_db_rs_t *rs; unsigned int i; char needs_rebind = 0; @@ -1014,8 +1031,8 @@ int sb_lua_db_store_results(lua_State *L) rs = (sb_lua_db_rs_t *)luaL_checkudata(L, 1, "sysbench.rs"); luaL_argcheck(L, rs != NULL, 1, "result set expected"); - db_store_results(rs->ptr); - + /* noop as db_store_results() is now performed automatically by db_query() */ + return 0; } diff --git a/sysbench/sb_timer.c b/sysbench/sb_timer.c index 39ee08d..e829a0f 100644 --- a/sysbench/sb_timer.c +++ b/sysbench/sb_timer.c @@ -30,6 +30,7 @@ #include "sb_logger.h" #include "sb_timer.h" +#include "sb_util.h" /* Some functions for simple time operations */ @@ -37,6 +38,8 @@ void sb_timer_init(sb_timer_t *t) { + SB_COMPILE_TIME_ASSERT(sizeof(sb_timer_t) % CK_MD_CACHELINE == 0); + memset(&t->time_start, 0, sizeof(struct timespec)); memset(&t->time_end, 0, sizeof(struct timespec)); sb_timer_reset(t); diff --git a/sysbench/sb_timer.h b/sysbench/sb_timer.h index aa2d540..a51d945 100644 --- a/sysbench/sb_timer.h +++ b/sysbench/sb_timer.h @@ -114,9 +114,9 @@ static inline uint64_t sb_timer_stop(sb_timer_t *t) t->events++; t->sum_time += elapsed; - if (CK_CC_UNLIKELY(elapsed < t->min_time)) + if (SB_UNLIKELY(elapsed < t->min_time)) t->min_time = elapsed; - if (CK_CC_UNLIKELY(elapsed > t->max_time)) + if (SB_UNLIKELY(elapsed > t->max_time)) t->max_time = elapsed; return elapsed; diff --git a/sysbench/sb_util.h b/sysbench/sb_util.h index cbeff74..49e81ed 100644 --- a/sysbench/sb_util.h +++ b/sysbench/sb_util.h @@ -30,6 +30,18 @@ #include "ck_md.h" #include "ck_cc.h" +#ifdef HAVE_FUNC_ATTRIBUTE_FORMAT +# define SB_ATTRIBUTE_FORMAT(style, m, n) __attribute__((format(style, m, n))) +#else +# define SB_ATTRIBUTE_FORMAT(style, m, n) +#endif + +#ifdef HAVE_FUNC_ATTRIBUTE_UNUSED +# define SB_ATTRIBUTE_UNUSED __attribute__((unused)) +#else +# define SB_ATTRIBUTE_UNUSED +#endif + /* Calculate the smallest multiple of m that is not smaller than n, when m is a power of 2. @@ -43,7 +55,7 @@ #define SB_PAD(n, m) (SB_ALIGN((n),(m)) - (n)) /* Calculate padding to cache line size. */ -#define SB_CACHELINE_PAD(n) (SB_PAD(n, CK_MD_CACHELINE)) +#define SB_CACHELINE_PAD(n) (SB_PAD((n), CK_MD_CACHELINE)) /* Minimum/maximum values */ #ifdef __GNUC__ @@ -63,4 +75,20 @@ #define SB_LIKELY(x) CK_CC_LIKELY(x) #define SB_UNLIKELY(x) CK_CC_UNLIKELY(x) +/* SB_CONTAINER_OF */ +#ifdef __GNUC__ +# define SB_MEMBER_TYPE(type, member) __typeof__ (((type *)0)->member) +#else +# define SB_MEMBER_TYPE(type, member) const void +#endif /* __GNUC__ */ + +#define SB_CONTAINER_OF(ptr, type, member) ((type *)(void *)( \ + (char *)(SB_MEMBER_TYPE(type, member) *){ ptr } - offsetof(type, member))) + +/* Compile-timer assertion */ +#define SB_COMPILE_TIME_ASSERT(expr) \ + do { \ + typedef char cta[(expr) ? 1 : -1] SB_ATTRIBUTE_UNUSED; \ + } while(0) + #endif /* SB_UTIL_H */ diff --git a/sysbench/sysbench.c b/sysbench/sysbench.c index 1ee089d..3d1c274 100644 --- a/sysbench/sysbench.c +++ b/sysbench/sysbench.c @@ -163,6 +163,8 @@ sb_timer_t sb_intermediate_timer CK_CC_CACHELINE; sb_timer_t sb_checkpoint_timer1 CK_CC_CACHELINE; sb_timer_t sb_checkpoint_timer2 CK_CC_CACHELINE; +TLS int sb_tls_thread_id; + static void print_header(void); static void print_help(void); static void print_run_mode(sb_test_t *); @@ -509,18 +511,21 @@ void sb_event_stop(int thread_id) if (sb_globals.percentile > 0) sb_histogram_update(&sb_latency_histogram, NS2MS(value)); + + db_thread_stat_inc(thread_id, DB_STAT_TRX); } /* Main event loop -- the default thread_run implementation */ -static void thread_run(sb_test_t *test, int thread_id) +static int thread_run(sb_test_t *test, int thread_id) { sb_event_t event; - int rc; + int rc = 0; - while ((event = sb_next_event(test, thread_id)).type != SB_REQ_TYPE_NULL) + while ((event = sb_next_event(test, thread_id)).type != SB_REQ_TYPE_NULL && + rc == 0) { sb_event_start(thread_id); @@ -534,10 +539,9 @@ static void thread_run(sb_test_t *test, int thread_id) sb_globals.concurrency--; pthread_mutex_unlock(&event_queue_mutex); } - - if (rc != 0) - break; } + + return rc; } @@ -549,10 +553,12 @@ static void *worker_thread(void *arg) sb_thread_ctxt_t *ctxt; sb_test_t *test; unsigned int thread_id; + int rc; ctxt = (sb_thread_ctxt_t *)arg; test = ctxt->test; - thread_id = ctxt->id; + + sb_tls_thread_id = thread_id = ctxt->id; /* Initialize thread-local RNG state */ sb_rand_thread_init(); @@ -577,15 +583,17 @@ static void *worker_thread(void *arg) if (test->ops.thread_run != NULL) { /* Use benchmark-provided thread_run implementation */ - test->ops.thread_run(thread_id); + rc = test->ops.thread_run(thread_id); } else { /* Use default thread_run implementation */ - thread_run(test, thread_id); + rc = thread_run(test, thread_id); } - if (test->ops.thread_done != NULL) + if (rc != 0) + sb_globals.error = 1; + else if (test->ops.thread_done != NULL) test->ops.thread_done(thread_id); return NULL; @@ -779,6 +787,8 @@ static int threads_started_callback(void *arg) sb_timer_copy(&sb_checkpoint_timer1, &sb_exec_timer); sb_timer_copy(&sb_checkpoint_timer2, &sb_exec_timer); + log_text(LOG_NOTICE, "Threads started!\n"); + return 0; } @@ -928,8 +938,6 @@ static int run_test(sb_test_t *test) } #endif - log_text(LOG_NOTICE, "Threads started!\n"); - for(i = 0; i < sb_globals.num_threads; i++) { if((err = sb_thread_join(threads[i].thread, NULL)) != 0) @@ -1177,9 +1185,9 @@ int main(int argc, char *argv[]) } /* Initialize global variables and logger */ - if (init() || log_init()) + if (init() || log_init() || db_thread_stat_init()) exit(1); - + print_header(); testname = sb_get_value_string("test"); @@ -1254,7 +1262,8 @@ int main(int argc, char *argv[]) if (run_test(test)) exit(1); - /* Uninitialize logger */ + db_done(); + log_done(); sb_options_done(); diff --git a/sysbench/sysbench.h b/sysbench/sysbench.h index c34dea1..6ffe276 100644 --- a/sysbench/sysbench.h +++ b/sysbench/sysbench.h @@ -218,6 +218,8 @@ extern sb_timer_t sb_intermediate_timer; extern sb_timer_t sb_checkpoint_timer1; extern sb_timer_t sb_checkpoint_timer2; +extern TLS int sb_tls_thread_id; + sb_event_t sb_next_event(sb_test_t *test, int thread_id); void sb_event_start(int thread_id); void sb_event_stop(int thread_id); diff --git a/sysbench/tests/db/Makefile.am b/sysbench/tests/db/Makefile.am index 3d6a7e4..42129d4 100644 --- a/sysbench/tests/db/Makefile.am +++ b/sysbench/tests/db/Makefile.am @@ -15,9 +15,10 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA -dist_pkgdata_DATA = common.lua delete.lua insert.lua bulk_insert.lua \ - oltp.lua \ - oltp_simple.lua \ +dist_pkgdata_DATA = delete.lua insert.lua bulk_insert.lua \ + oltp_read_write.lua oltp_read_only.lua \ + oltp_common.lua \ + oltp_point_select.lua \ parallel_prepare.lua \ select_random_points.lua \ select_random_ranges.lua \ diff --git a/sysbench/tests/db/bulk_insert.lua b/sysbench/tests/db/bulk_insert.lua index d203f78..e69de29 100644 --- a/sysbench/tests/db/bulk_insert.lua +++ b/sysbench/tests/db/bulk_insert.lua @@ -1,61 +0,0 @@ --- -------------------------------------------------------------------------- -- --- Bulk insert tests -- --- -------------------------------------------------------------------------- -- - -cursize=0 - -function prepare() - local i - - db_connect() - - for i = 0,num_threads-1 do - - if (db_driver == "pgsql") then - - db_query([[ -CREATE TABLE IF NOT EXISTS sbtest]] .. i .. [[ ( -id INTEGER NOT NULL, -k INTEGER DEFAULT '0' NOT NULL, -PRIMARY KEY (id) -)]]) - - else - - db_query([[ -CREATE TABLE IF NOT EXISTS sbtest]] .. i .. [[ ( -id INTEGER UNSIGNED NOT NULL, -k INTEGER UNSIGNED DEFAULT '0' NOT NULL, -PRIMARY KEY (id) -) ENGINE = InnoDB -]]) - - end - - end --for -end - -function event() - local i - - if (cursize == 0) then - db_bulk_insert_init("INSERT INTO sbtest" .. thread_id .. " VALUES") - end - - cursize = cursize + 1 - - db_bulk_insert_next("(" .. cursize .. "," .. cursize .. ")") -end - -function thread_done(thread_9d) - db_bulk_insert_done() -end - -function cleanup() - local i - - for i = 0,num_threads-1 do - print("Dropping table 'sbtest" .. i .. "'...") - db_query("DROP TABLE IF EXISTS sbtest".. i ) - end -end diff --git a/sysbench/tests/db/delete.lua b/sysbench/tests/db/delete.lua index 68a85a0..e69de29 100644 --- a/sysbench/tests/db/delete.lua +++ b/sysbench/tests/db/delete.lua @@ -1,17 +0,0 @@ -pathtest = string.match(test, "(.*/)") - -if pathtest then - dofile(pathtest .. "common.lua") -else - require("common") -end - -function thread_init() - set_vars() -end - -function event() - local table_name - table_name = "sbtest".. sb_rand_uniform(1, oltp_tables_count) - rs = db_query("DELETE FROM " .. table_name .. " WHERE id=" .. sb_rand(1, oltp_table_size)) -end diff --git a/sysbench/tests/db/insert.lua b/sysbench/tests/db/insert.lua index d2e5b98..e69de29 100644 --- a/sysbench/tests/db/insert.lua +++ b/sysbench/tests/db/insert.lua @@ -1,42 +0,0 @@ -pathtest = string.match(test, "(.*/)") - -if pathtest then - dofile(pathtest .. "common.lua") -else - require("common") -end - -function thread_init(thread_id) - set_vars() -end - -function event() - local table_name - local i - local c_val - local k_val - local pad_val - - table_name = "sbtest".. sb_rand_uniform(1, oltp_tables_count) - - k_val = sb_rand(1, oltp_table_size) - c_val = sb_rand_str([[ -###########-###########-###########-###########-###########-###########-###########-###########-###########-###########]]) - pad_val = sb_rand_str([[ -###########-###########-###########-###########-###########]]) - - if (db_driver == "pgsql" and oltp_auto_inc) then - rs = db_query("INSERT INTO " .. table_name .. " (k, c, pad) VALUES " .. - string.format("(%d, '%s', '%s')", k_val, c_val, pad_val)) - else - if (oltp_auto_inc) then - i = 0 - else - i = sb_rand_uniq() - end - rs = db_query("INSERT INTO " .. table_name .. - " (id, k, c, pad) VALUES " .. - string.format("(%d, %d, '%s', '%s')", i, k_val, c_val, - pad_val)) - end -end diff --git a/sysbench/tests/db/oltp_common.lua b/sysbench/tests/db/oltp_common.lua new file mode 100644 index 0000000..f2dac9c --- /dev/null +++ b/sysbench/tests/db/oltp_common.lua @@ -0,0 +1,204 @@ +-- Copyright (C) 2006-2017 Alexey Kopytov + +-- This program is free software; you can redistribute it and/or modify +-- it under the terms of the GNU General Public License as published by +-- the Free Software Foundation; either version 2 of the License, or +-- (at your option) any later version. + +-- This program is distributed in the hope that it will be useful, +-- but WITHOUT ANY WARRANTY; without even the implied warranty of +-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +-- GNU General Public License for more details. + +-- You should have received a copy of the GNU General Public License +-- along with this program; if not, write to the Free Software +-- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +-- ---------------------------------------------------------------------- +-- Common code for OLTP benchmarks +-- ---------------------------------------------------------------------- + +function create_insert(table_id) + + local index_name + local i + local j + local query + + if (oltp_secondary) then + index_name = "KEY xid" + else + index_name = "PRIMARY KEY" + end + + if (pgsql_variant == 'redshift') then + auto_inc_type = "INTEGER IDENTITY(1,1)" + else + auto_inc_type = "SERIAL" + end + + i = table_id + + print("Creating table 'sbtest" .. i .. "'...") + if ((db_driver == "mysql") or (db_driver == "attachsql")) then + query = [[ +CREATE TABLE sbtest]] .. i .. [[ ( +id INTEGER UNSIGNED NOT NULL ]] .. +((oltp_auto_inc and "AUTO_INCREMENT") or "") .. [[, +k INTEGER UNSIGNED DEFAULT '0' NOT NULL, +c CHAR(120) DEFAULT '' NOT NULL, +pad CHAR(60) DEFAULT '' NOT NULL, +]] .. index_name .. [[ (id) +) /*! ENGINE = ]] .. mysql_table_engine .. +" MAX_ROWS = " .. myisam_max_rows .. " */ " .. + (mysql_table_options or "") + + elseif (db_driver == "pgsql") then + query = [[ +CREATE TABLE sbtest]] .. i .. [[ ( +id ]] .. auto_inc_type .. [[ NOT NULL, +k INTEGER DEFAULT '0' NOT NULL, +c CHAR(120) DEFAULT '' NOT NULL, +pad CHAR(60) DEFAULT '' NOT NULL, +]] .. index_name .. [[ (id) +) ]] + + elseif (db_driver == "drizzle") then + query = [[ +CREATE TABLE sbtest ( +id INTEGER NOT NULL ]] .. ((oltp_auto_inc and "AUTO_INCREMENT") or "") .. [[, +k INTEGER DEFAULT '0' NOT NULL, +c CHAR(120) DEFAULT '' NOT NULL, +pad CHAR(60) DEFAULT '' NOT NULL, +]] .. index_name .. [[ (id) +) ]] + else + print("Unknown database driver: " .. db_driver) + return 1 + end + + db_query(query) + + print("Inserting " .. oltp_table_size .. " records into 'sbtest" .. i .. "'") + + if (oltp_auto_inc) then + db_bulk_insert_init("INSERT INTO sbtest" .. i .. "(k, c, pad) VALUES") + else + db_bulk_insert_init("INSERT INTO sbtest" .. i .. "(id, k, c, pad) VALUES") + end + + local c_val + local pad_val + + + for j = 1,oltp_table_size do + + c_val = sb_rand_str([[ +###########-###########-###########-###########-###########-###########-###########-###########-###########-###########]]) + pad_val = sb_rand_str([[ +###########-###########-###########-###########-###########]]) + + if (oltp_auto_inc) then + db_bulk_insert_next("(" .. sb_rand(1, oltp_table_size) .. ", '".. c_val .."', '" .. pad_val .. "')") + else + db_bulk_insert_next("("..j.."," .. sb_rand(1, oltp_table_size) .. ",'".. c_val .."', '" .. pad_val .. "' )") + end + end + + db_bulk_insert_done() + + if oltp_create_secondary then + print("Creating secondary indexes on 'sbtest" .. i .. "'...") + db_query("CREATE INDEX k_" .. i .. " on sbtest" .. i .. "(k)") + end + +end + + +function prepare() + local query + local i + local j + + set_vars() + + db_connect() + + + for i = 1,oltp_tables_count do + create_insert(i) + end + + return 0 +end + +function cleanup() + local i + + set_vars() + + for i = 1,oltp_tables_count do + print("Dropping table 'sbtest" .. i .. "'...") + db_query("DROP TABLE IF EXISTS sbtest".. i ) + end +end + +function set_vars() + oltp_table_size = tonumber(oltp_table_size) or 10000 + oltp_range_size = tonumber(oltp_range_size) or 100 + oltp_tables_count = tonumber(oltp_tables_count) or 1 + oltp_point_selects = tonumber(oltp_point_selects) or 10 + oltp_simple_ranges = tonumber(oltp_simple_ranges) or 1 + oltp_sum_ranges = tonumber(oltp_sum_ranges) or 1 + oltp_order_ranges = tonumber(oltp_order_ranges) or 1 + oltp_distinct_ranges = tonumber(oltp_distinct_ranges) or 1 + oltp_index_updates = tonumber(oltp_index_updates) or 1 + oltp_non_index_updates = tonumber(oltp_non_index_updates) or 1 + oltp_delete_inserts = tonumber(oltp_delete_inserts) or 1 + + if (oltp_range_selects == 'off') then + oltp_range_selects = false + else + oltp_range_selects = true + end + + if (oltp_auto_inc == 'off') then + oltp_auto_inc = false + else + oltp_auto_inc = true + end + + if (oltp_read_only == 'on') then + oltp_read_only = true + else + oltp_read_only = false + end + + if (oltp_write_only == 'on') then + oltp_write_only = true + else + oltp_write_only = false + end + + if (oltp_read_only and oltp_write_only) then + error("--oltp-read-only and --oltp-write-only are mutually exclusive") + end + + if (oltp_skip_trx == 'on') then + oltp_skip_trx = true + else + oltp_skip_trx = false + end + + if (oltp_create_secondary == 'off') then + oltp_create_secondary = false + else + oltp_create_secondary = true + end + + if (pgsql_variant == 'redshift') then + oltp_create_secondary = false + oltp_delete_inserts = 0 + end + +end diff --git a/sysbench/tests/db/oltp_point_select.lua b/sysbench/tests/db/oltp_point_select.lua new file mode 100644 index 0000000..e317d59 --- /dev/null +++ b/sysbench/tests/db/oltp_point_select.lua @@ -0,0 +1,39 @@ +-- Copyright (C) 2006-2017 Alexey Kopytov + +-- This program is free software; you can redistribute it and/or modify +-- it under the terms of the GNU General Public License as published by +-- the Free Software Foundation; either version 2 of the License, or +-- (at your option) any later version. + +-- This program is distributed in the hope that it will be useful, +-- but WITHOUT ANY WARRANTY; without even the implied warranty of +-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +-- GNU General Public License for more details. + +-- You should have received a copy of the GNU General Public License +-- along with this program; if not, write to the Free Software +-- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +-- ---------------------------------------------------------------------- +-- OLTP Point Select benchmark +-- ---------------------------------------------------------------------- + +pathtest = string.match(test, "(.*/)") + +if pathtest then + dofile(pathtest .. "oltp_common.lua") +else + require("oltp_common") +end + +function thread_init() + set_vars() + drv = sysbench.sql.driver() + con = drv:connect() +end + +function event() + con:query(string.format("SELECT c FROM sbtest%d WHERE id=%d", + sysbench.rand.uniform(1, oltp_tables_count), + sysbench.rand.default(1, oltp_table_size))) +end diff --git a/sysbench/tests/db/oltp_read_only.lua b/sysbench/tests/db/oltp_read_only.lua new file mode 100644 index 0000000..e69de29 diff --git a/sysbench/tests/db/oltp_read_write.lua b/sysbench/tests/db/oltp_read_write.lua new file mode 100644 index 0000000..e69de29 diff --git a/sysbench/tests/db/parallel_prepare.lua b/sysbench/tests/db/parallel_prepare.lua index b2cda7a..e69de29 100644 --- a/sysbench/tests/db/parallel_prepare.lua +++ b/sysbench/tests/db/parallel_prepare.lua @@ -1,30 +0,0 @@ --- for proper initialization use --max-requests = N, where N is --num-threads --- -pathtest = string.match(test, "(.*/)") - -if pathtest then - dofile(pathtest .. "common.lua") -else - require("common") -end - -function thread_init() - set_vars() -end - -function event() - local index_name - local i - print("thread prepare"..thread_id) - - if (oltp_secondary) then - index_name = "KEY xid" - else - index_name = "PRIMARY KEY" - end - - for i=thread_id+1, oltp_tables_count, num_threads do - create_insert(i) - end - -end diff --git a/sysbench/tests/db/select.lua b/sysbench/tests/db/select.lua index 571ef21..e69de29 100644 --- a/sysbench/tests/db/select.lua +++ b/sysbench/tests/db/select.lua @@ -1,18 +0,0 @@ -pathtest = string.match(test, "(.*/)") - -if pathtest then - dofile(pathtest .. "common.lua") -else - require("common") -end - -function thread_init() - set_vars() -end - -function event() - local table_name - table_name = "sbtest".. sb_rand_uniform(1, oltp_tables_count) - rs = db_query("SELECT pad FROM ".. table_name .." WHERE id=" .. sb_rand(1, oltp_table_size)) -end - diff --git a/sysbench/tests/db/select_random_points.lua b/sysbench/tests/db/select_random_points.lua index de18376..e69de29 100644 --- a/sysbench/tests/db/select_random_points.lua +++ b/sysbench/tests/db/select_random_points.lua @@ -1,61 +0,0 @@ --- This test is designed for testing MariaDB's key_cache_segments for MyISAM, --- and should work with other storage engines as well. --- --- For details about key_cache_segments please refer to: --- http://kb.askmonty.org/v/segmented-key-cache --- - --- Override oltp_tables_count, this test only supports a single table -oltp_tables_count = 1 - -pathtest = string.match(test, "(.*/)") - -if pathtest then - dofile(pathtest .. "common.lua") -else - require("common") -end - -function thread_init() - set_vars_points() - - points = "" - for i = 1,random_points do - points = points .. "?, " - end - - -- Get rid of last comma and space. - points = string.sub(points, 1, string.len(points) - 2) - - stmt = db_prepare([[ - SELECT id, k, c, pad - FROM sbtest1 - WHERE k IN (]] .. points .. [[) - ]]) - - params = {} - for j = 1,random_points do - params[j] = 1 - end - - db_bind_param(stmt, params) -end - -function event() - local rs - - -- To prevent overlapping of our range queries we need to partition the whole table - -- into num_threads segments and then make each thread work with its own segment. - for i = 1,random_points do - params[i] = sb_rand(oltp_table_size / num_threads * thread_id, oltp_table_size / num_threads * (thread_id + 1)) - end - - rs = db_execute(stmt) - db_store_results(rs) - db_free_results(rs) -end - -function set_vars_points() -set_vars() -random_points = random_points or 10 -end diff --git a/sysbench/tests/db/select_random_ranges.lua b/sysbench/tests/db/select_random_ranges.lua index 6185100..e69de29 100644 --- a/sysbench/tests/db/select_random_ranges.lua +++ b/sysbench/tests/db/select_random_ranges.lua @@ -1,64 +0,0 @@ --- This test is designed for testing MariaDB's key_cache_segments for MyISAM, --- and should work with other storage engines as well. --- --- For details about key_cache_segments please refer to: --- http://kb.askmonty.org/v/segmented-key-cache --- - -pathtest = string.match(test, "(.*/)") - -if pathtest then - dofile(pathtest .. "common.lua") -else - require("common") -end - --- Override oltp_tables_count, this test only supports a single table -oltp_tables_count = 1 - -function thread_init() - set_vars_ranges() - - ranges = "" - for i = 1,number_of_ranges do - ranges = ranges .. "k BETWEEN ? AND ? OR " - end - - -- Get rid of last OR and space. - ranges = string.sub(ranges, 1, string.len(ranges) - 3) - - stmt = db_prepare([[ - SELECT count(k) - FROM sbtest1 - WHERE ]] .. ranges .. [[ - ]]) - - params = {} - for j = 1,number_of_ranges * 2 do - params[j] = 1 - end - - db_bind_param(stmt, params) - -end - -function event() - local rs - - -- To prevent overlapping of our range queries we need to partition the whole table - -- into num_threads segments and then make each thread work with its own segment. - for i = 1,number_of_ranges * 2,2 do - params[i] = sb_rand(oltp_table_size / num_threads * thread_id, oltp_table_size / num_threads * (thread_id + 1)) - params[i + 1] = params[i] + delta - end - - rs = db_execute(stmt) - db_store_results(rs) - db_free_results(rs) -end - -function set_vars_ranges() - set_vars() - number_of_ranges = number_of_ranges or 10 - delta = random_ranges_delta or 5 -end diff --git a/sysbench/tests/db/update_index.lua b/sysbench/tests/db/update_index.lua index 5d1f20c..e69de29 100644 --- a/sysbench/tests/db/update_index.lua +++ b/sysbench/tests/db/update_index.lua @@ -1,17 +0,0 @@ -pathtest = string.match(test, "(.*/)") - -if pathtest then - dofile(pathtest .. "common.lua") -else - require("common") -end - -function thread_init() - set_vars() -end - -function event() - local table_name - table_name = "sbtest".. sb_rand_uniform(1, oltp_tables_count) - rs = db_query("UPDATE ".. table_name .." SET k=k+1 WHERE id=" .. sb_rand(1, oltp_table_size)) -end diff --git a/sysbench/tests/db/update_non_index.lua b/sysbench/tests/db/update_non_index.lua index d549add..e69de29 100644 --- a/sysbench/tests/db/update_non_index.lua +++ b/sysbench/tests/db/update_non_index.lua @@ -1,21 +0,0 @@ -pathtest = string.match(test, "(.*/)") - -if pathtest then - dofile(pathtest .. "common.lua") -else - require("common") -end - -function thread_init() - set_vars() -end - -function event() - local table_name - local c_val - local query - table_name = "sbtest".. sb_rand_uniform(1, oltp_tables_count) - c_val = sb_rand_str("###########-###########-###########-###########-###########-###########-###########-###########-###########-###########") - query = "UPDATE " .. table_name .. " SET c='" .. c_val .. "' WHERE id=" .. sb_rand(1, oltp_table_size) - rs = db_query(query) -end diff --git a/sysbench/tests/mutex/sb_mutex.c b/sysbench/tests/mutex/sb_mutex.c index a27e243..b66cfd9 100644 --- a/sysbench/tests/mutex/sb_mutex.c +++ b/sysbench/tests/mutex/sb_mutex.c @@ -76,6 +76,8 @@ static unsigned int mutex_loops; static unsigned int mutex_locks; static unsigned int global_var; +static TLS int tls_counter; + int register_test_mutex(sb_list_t *tests) { SB_LIST_ADD_TAIL(&mutex_test.listitem, tests); @@ -125,9 +127,15 @@ sb_event_t mutex_next_event(int thread_id) (void) thread_id; /* unused */ - sb_req.type = SB_REQ_TYPE_MUTEX; - mutex_req->nlocks = mutex_locks; - mutex_req->nloops = mutex_loops; + /* Perform only one request per thread */ + if (tls_counter++ > 0) + sb_req.type = SB_REQ_TYPE_NULL; + else + { + sb_req.type = SB_REQ_TYPE_MUTEX; + mutex_req->nlocks = mutex_locks; + mutex_req->nloops = mutex_loops; + } return sb_req; } @@ -154,8 +162,7 @@ int mutex_execute_event(sb_event_t *sb_req, int thread_id) } while (mutex_req->nlocks > 0); - /* Perform only one request per thread */ - return 1; + return 0; } diff --git a/tests/include/oltp_legacy/bulk_insert.lua b/tests/include/oltp_legacy/bulk_insert.lua new file mode 100644 index 0000000..d203f78 --- /dev/null +++ b/tests/include/oltp_legacy/bulk_insert.lua @@ -0,0 +1,61 @@ +-- -------------------------------------------------------------------------- -- +-- Bulk insert tests -- +-- -------------------------------------------------------------------------- -- + +cursize=0 + +function prepare() + local i + + db_connect() + + for i = 0,num_threads-1 do + + if (db_driver == "pgsql") then + + db_query([[ +CREATE TABLE IF NOT EXISTS sbtest]] .. i .. [[ ( +id INTEGER NOT NULL, +k INTEGER DEFAULT '0' NOT NULL, +PRIMARY KEY (id) +)]]) + + else + + db_query([[ +CREATE TABLE IF NOT EXISTS sbtest]] .. i .. [[ ( +id INTEGER UNSIGNED NOT NULL, +k INTEGER UNSIGNED DEFAULT '0' NOT NULL, +PRIMARY KEY (id) +) ENGINE = InnoDB +]]) + + end + + end --for +end + +function event() + local i + + if (cursize == 0) then + db_bulk_insert_init("INSERT INTO sbtest" .. thread_id .. " VALUES") + end + + cursize = cursize + 1 + + db_bulk_insert_next("(" .. cursize .. "," .. cursize .. ")") +end + +function thread_done(thread_9d) + db_bulk_insert_done() +end + +function cleanup() + local i + + for i = 0,num_threads-1 do + print("Dropping table 'sbtest" .. i .. "'...") + db_query("DROP TABLE IF EXISTS sbtest".. i ) + end +end diff --git a/tests/include/oltp_legacy/common.lua b/tests/include/oltp_legacy/common.lua new file mode 100644 index 0000000..c7d1391 --- /dev/null +++ b/tests/include/oltp_legacy/common.lua @@ -0,0 +1,190 @@ +-- Input parameters +-- oltp-tables-count - number of tables to create +-- oltp-secondary - use secondary key instead PRIMARY key for id column +-- +-- + +function create_insert(table_id) + + local index_name + local i + local j + local query + + if (oltp_secondary) then + index_name = "KEY xid" + else + index_name = "PRIMARY KEY" + end + + if (pgsql_variant == 'redshift') then + auto_inc_type = "INTEGER IDENTITY(1,1)" + else + auto_inc_type = "SERIAL" + end + + i = table_id + + print("Creating table 'sbtest" .. i .. "'...") + if ((db_driver == "mysql") or (db_driver == "attachsql")) then + query = [[ +CREATE TABLE sbtest]] .. i .. [[ ( +id INTEGER UNSIGNED NOT NULL ]] .. +((oltp_auto_inc and "AUTO_INCREMENT") or "") .. [[, +k INTEGER UNSIGNED DEFAULT '0' NOT NULL, +c CHAR(120) DEFAULT '' NOT NULL, +pad CHAR(60) DEFAULT '' NOT NULL, +]] .. index_name .. [[ (id) +) /*! ENGINE = ]] .. mysql_table_engine .. +" MAX_ROWS = " .. myisam_max_rows .. " */ " .. + (mysql_table_options or "") + + elseif (db_driver == "pgsql") then + query = [[ +CREATE TABLE sbtest]] .. i .. [[ ( +id ]] .. auto_inc_type .. [[ NOT NULL, +k INTEGER DEFAULT '0' NOT NULL, +c CHAR(120) DEFAULT '' NOT NULL, +pad CHAR(60) DEFAULT '' NOT NULL, +]] .. index_name .. [[ (id) +) ]] + + elseif (db_driver == "drizzle") then + query = [[ +CREATE TABLE sbtest ( +id INTEGER NOT NULL ]] .. ((oltp_auto_inc and "AUTO_INCREMENT") or "") .. [[, +k INTEGER DEFAULT '0' NOT NULL, +c CHAR(120) DEFAULT '' NOT NULL, +pad CHAR(60) DEFAULT '' NOT NULL, +]] .. index_name .. [[ (id) +) ]] + else + print("Unknown database driver: " .. db_driver) + return 1 + end + + db_query(query) + + print("Inserting " .. oltp_table_size .. " records into 'sbtest" .. i .. "'") + + if (oltp_auto_inc) then + db_bulk_insert_init("INSERT INTO sbtest" .. i .. "(k, c, pad) VALUES") + else + db_bulk_insert_init("INSERT INTO sbtest" .. i .. "(id, k, c, pad) VALUES") + end + + local c_val + local pad_val + + + for j = 1,oltp_table_size do + + c_val = sb_rand_str([[ +###########-###########-###########-###########-###########-###########-###########-###########-###########-###########]]) + pad_val = sb_rand_str([[ +###########-###########-###########-###########-###########]]) + + if (oltp_auto_inc) then + db_bulk_insert_next("(" .. sb_rand(1, oltp_table_size) .. ", '".. c_val .."', '" .. pad_val .. "')") + else + db_bulk_insert_next("("..j.."," .. sb_rand(1, oltp_table_size) .. ",'".. c_val .."', '" .. pad_val .. "' )") + end + end + + db_bulk_insert_done() + + if oltp_create_secondary then + print("Creating secondary indexes on 'sbtest" .. i .. "'...") + db_query("CREATE INDEX k_" .. i .. " on sbtest" .. i .. "(k)") + end + +end + + +function prepare() + local query + local i + local j + + set_vars() + + db_connect() + + + for i = 1,oltp_tables_count do + create_insert(i) + end + + return 0 +end + +function cleanup() + local i + + set_vars() + + for i = 1,oltp_tables_count do + print("Dropping table 'sbtest" .. i .. "'...") + db_query("DROP TABLE IF EXISTS sbtest".. i ) + end +end + +function set_vars() + oltp_table_size = tonumber(oltp_table_size) or 10000 + oltp_range_size = tonumber(oltp_range_size) or 100 + oltp_tables_count = tonumber(oltp_tables_count) or 1 + oltp_point_selects = tonumber(oltp_point_selects) or 10 + oltp_simple_ranges = tonumber(oltp_simple_ranges) or 1 + oltp_sum_ranges = tonumber(oltp_sum_ranges) or 1 + oltp_order_ranges = tonumber(oltp_order_ranges) or 1 + oltp_distinct_ranges = tonumber(oltp_distinct_ranges) or 1 + oltp_index_updates = tonumber(oltp_index_updates) or 1 + oltp_non_index_updates = tonumber(oltp_non_index_updates) or 1 + oltp_delete_inserts = tonumber(oltp_delete_inserts) or 1 + + if (oltp_range_selects == 'off') then + oltp_range_selects = false + else + oltp_range_selects = true + end + + if (oltp_auto_inc == 'off') then + oltp_auto_inc = false + else + oltp_auto_inc = true + end + + if (oltp_read_only == 'on') then + oltp_read_only = true + else + oltp_read_only = false + end + + if (oltp_write_only == 'on') then + oltp_write_only = true + else + oltp_write_only = false + end + + if (oltp_read_only and oltp_write_only) then + error("--oltp-read-only and --oltp-write-only are mutually exclusive") + end + + if (oltp_skip_trx == 'on') then + oltp_skip_trx = true + else + oltp_skip_trx = false + end + + if (oltp_create_secondary == 'off') then + oltp_create_secondary = false + else + oltp_create_secondary = true + end + + if (pgsql_variant == 'redshift') then + oltp_create_secondary = false + oltp_delete_inserts = 0 + end + +end diff --git a/tests/include/oltp_legacy/delete.lua b/tests/include/oltp_legacy/delete.lua new file mode 100644 index 0000000..68a85a0 --- /dev/null +++ b/tests/include/oltp_legacy/delete.lua @@ -0,0 +1,17 @@ +pathtest = string.match(test, "(.*/)") + +if pathtest then + dofile(pathtest .. "common.lua") +else + require("common") +end + +function thread_init() + set_vars() +end + +function event() + local table_name + table_name = "sbtest".. sb_rand_uniform(1, oltp_tables_count) + rs = db_query("DELETE FROM " .. table_name .. " WHERE id=" .. sb_rand(1, oltp_table_size)) +end diff --git a/tests/include/oltp_legacy/insert.lua b/tests/include/oltp_legacy/insert.lua new file mode 100644 index 0000000..d2e5b98 --- /dev/null +++ b/tests/include/oltp_legacy/insert.lua @@ -0,0 +1,42 @@ +pathtest = string.match(test, "(.*/)") + +if pathtest then + dofile(pathtest .. "common.lua") +else + require("common") +end + +function thread_init(thread_id) + set_vars() +end + +function event() + local table_name + local i + local c_val + local k_val + local pad_val + + table_name = "sbtest".. sb_rand_uniform(1, oltp_tables_count) + + k_val = sb_rand(1, oltp_table_size) + c_val = sb_rand_str([[ +###########-###########-###########-###########-###########-###########-###########-###########-###########-###########]]) + pad_val = sb_rand_str([[ +###########-###########-###########-###########-###########]]) + + if (db_driver == "pgsql" and oltp_auto_inc) then + rs = db_query("INSERT INTO " .. table_name .. " (k, c, pad) VALUES " .. + string.format("(%d, '%s', '%s')", k_val, c_val, pad_val)) + else + if (oltp_auto_inc) then + i = 0 + else + i = sb_rand_uniq() + end + rs = db_query("INSERT INTO " .. table_name .. + " (id, k, c, pad) VALUES " .. + string.format("(%d, %d, '%s', '%s')", i, k_val, c_val, + pad_val)) + end +end diff --git a/tests/include/oltp_legacy/oltp.lua b/tests/include/oltp_legacy/oltp.lua new file mode 100644 index 0000000..66ef667 --- /dev/null +++ b/tests/include/oltp_legacy/oltp.lua @@ -0,0 +1,114 @@ +pathtest = string.match(test, "(.*/)") + +if pathtest then + dofile(pathtest .. "common.lua") +else + require("common") +end + +function thread_init() + set_vars() + + if (((db_driver == "mysql") or (db_driver == "attachsql")) and mysql_table_engine == "myisam") then + local i + local tables = {} + for i=1, oltp_tables_count do + tables[i] = string.format("sbtest%i WRITE", i) + end + begin_query = "LOCK TABLES " .. table.concat(tables, " ,") + commit_query = "UNLOCK TABLES" + else + begin_query = "BEGIN" + commit_query = "COMMIT" + end + +end + +function get_range_str() + local start = sb_rand(1, oltp_table_size) + return string.format(" WHERE id BETWEEN %u AND %u", + start, start + oltp_range_size - 1) +end + +function event() + local rs + local i + local table_name + local c_val + local pad_val + local query + + table_name = "sbtest".. sb_rand_uniform(1, oltp_tables_count) + if not oltp_skip_trx then + db_query(begin_query) + end + + if not oltp_write_only then + + for i=1, oltp_point_selects do + rs = db_query("SELECT c FROM ".. table_name .." WHERE id=" .. + sb_rand(1, oltp_table_size)) + end + + if oltp_range_selects then + + for i=1, oltp_simple_ranges do + rs = db_query("SELECT c FROM ".. table_name .. get_range_str()) + end + + for i=1, oltp_sum_ranges do + rs = db_query("SELECT SUM(K) FROM ".. table_name .. get_range_str()) + end + + for i=1, oltp_order_ranges do + rs = db_query("SELECT c FROM ".. table_name .. get_range_str() .. + " ORDER BY c") + end + + for i=1, oltp_distinct_ranges do + rs = db_query("SELECT DISTINCT c FROM ".. table_name .. get_range_str() .. + " ORDER BY c") + end + + end + + end + + if not oltp_read_only then + + for i=1, oltp_index_updates do + rs = db_query("UPDATE " .. table_name .. " SET k=k+1 WHERE id=" .. sb_rand(1, oltp_table_size)) + end + + for i=1, oltp_non_index_updates do + c_val = sb_rand_str("###########-###########-###########-###########-###########-###########-###########-###########-###########-###########") + query = "UPDATE " .. table_name .. " SET c='" .. c_val .. "' WHERE id=" .. sb_rand(1, oltp_table_size) + rs = db_query(query) + if rs then + print(query) + end + end + + for i=1, oltp_delete_inserts do + + i = sb_rand(1, oltp_table_size) + + rs = db_query("DELETE FROM " .. table_name .. " WHERE id=" .. i) + + c_val = sb_rand_str([[ +###########-###########-###########-###########-###########-###########-###########-###########-###########-###########]]) + pad_val = sb_rand_str([[ +###########-###########-###########-###########-###########]]) + + rs = db_query("INSERT INTO " .. table_name .. " (id, k, c, pad) VALUES " .. string.format("(%d, %d, '%s', '%s')",i, sb_rand(1, oltp_table_size) , c_val, pad_val)) + + end + + end -- oltp_read_only + + if not oltp_skip_trx then + db_query(commit_query) + end + +end + diff --git a/sysbench/tests/db/oltp_simple.lua b/tests/include/oltp_legacy/oltp_simple.lua similarity index 100% rename from sysbench/tests/db/oltp_simple.lua rename to tests/include/oltp_legacy/oltp_simple.lua diff --git a/tests/include/oltp_legacy/parallel_prepare.lua b/tests/include/oltp_legacy/parallel_prepare.lua new file mode 100644 index 0000000..b2cda7a --- /dev/null +++ b/tests/include/oltp_legacy/parallel_prepare.lua @@ -0,0 +1,30 @@ +-- for proper initialization use --max-requests = N, where N is --num-threads +-- +pathtest = string.match(test, "(.*/)") + +if pathtest then + dofile(pathtest .. "common.lua") +else + require("common") +end + +function thread_init() + set_vars() +end + +function event() + local index_name + local i + print("thread prepare"..thread_id) + + if (oltp_secondary) then + index_name = "KEY xid" + else + index_name = "PRIMARY KEY" + end + + for i=thread_id+1, oltp_tables_count, num_threads do + create_insert(i) + end + +end diff --git a/tests/include/oltp_legacy/select.lua b/tests/include/oltp_legacy/select.lua new file mode 100644 index 0000000..571ef21 --- /dev/null +++ b/tests/include/oltp_legacy/select.lua @@ -0,0 +1,18 @@ +pathtest = string.match(test, "(.*/)") + +if pathtest then + dofile(pathtest .. "common.lua") +else + require("common") +end + +function thread_init() + set_vars() +end + +function event() + local table_name + table_name = "sbtest".. sb_rand_uniform(1, oltp_tables_count) + rs = db_query("SELECT pad FROM ".. table_name .." WHERE id=" .. sb_rand(1, oltp_table_size)) +end + diff --git a/tests/include/oltp_legacy/select_random_points.lua b/tests/include/oltp_legacy/select_random_points.lua new file mode 100644 index 0000000..de18376 --- /dev/null +++ b/tests/include/oltp_legacy/select_random_points.lua @@ -0,0 +1,61 @@ +-- This test is designed for testing MariaDB's key_cache_segments for MyISAM, +-- and should work with other storage engines as well. +-- +-- For details about key_cache_segments please refer to: +-- http://kb.askmonty.org/v/segmented-key-cache +-- + +-- Override oltp_tables_count, this test only supports a single table +oltp_tables_count = 1 + +pathtest = string.match(test, "(.*/)") + +if pathtest then + dofile(pathtest .. "common.lua") +else + require("common") +end + +function thread_init() + set_vars_points() + + points = "" + for i = 1,random_points do + points = points .. "?, " + end + + -- Get rid of last comma and space. + points = string.sub(points, 1, string.len(points) - 2) + + stmt = db_prepare([[ + SELECT id, k, c, pad + FROM sbtest1 + WHERE k IN (]] .. points .. [[) + ]]) + + params = {} + for j = 1,random_points do + params[j] = 1 + end + + db_bind_param(stmt, params) +end + +function event() + local rs + + -- To prevent overlapping of our range queries we need to partition the whole table + -- into num_threads segments and then make each thread work with its own segment. + for i = 1,random_points do + params[i] = sb_rand(oltp_table_size / num_threads * thread_id, oltp_table_size / num_threads * (thread_id + 1)) + end + + rs = db_execute(stmt) + db_store_results(rs) + db_free_results(rs) +end + +function set_vars_points() +set_vars() +random_points = random_points or 10 +end diff --git a/tests/include/oltp_legacy/select_random_ranges.lua b/tests/include/oltp_legacy/select_random_ranges.lua new file mode 100644 index 0000000..6185100 --- /dev/null +++ b/tests/include/oltp_legacy/select_random_ranges.lua @@ -0,0 +1,64 @@ +-- This test is designed for testing MariaDB's key_cache_segments for MyISAM, +-- and should work with other storage engines as well. +-- +-- For details about key_cache_segments please refer to: +-- http://kb.askmonty.org/v/segmented-key-cache +-- + +pathtest = string.match(test, "(.*/)") + +if pathtest then + dofile(pathtest .. "common.lua") +else + require("common") +end + +-- Override oltp_tables_count, this test only supports a single table +oltp_tables_count = 1 + +function thread_init() + set_vars_ranges() + + ranges = "" + for i = 1,number_of_ranges do + ranges = ranges .. "k BETWEEN ? AND ? OR " + end + + -- Get rid of last OR and space. + ranges = string.sub(ranges, 1, string.len(ranges) - 3) + + stmt = db_prepare([[ + SELECT count(k) + FROM sbtest1 + WHERE ]] .. ranges .. [[ + ]]) + + params = {} + for j = 1,number_of_ranges * 2 do + params[j] = 1 + end + + db_bind_param(stmt, params) + +end + +function event() + local rs + + -- To prevent overlapping of our range queries we need to partition the whole table + -- into num_threads segments and then make each thread work with its own segment. + for i = 1,number_of_ranges * 2,2 do + params[i] = sb_rand(oltp_table_size / num_threads * thread_id, oltp_table_size / num_threads * (thread_id + 1)) + params[i + 1] = params[i] + delta + end + + rs = db_execute(stmt) + db_store_results(rs) + db_free_results(rs) +end + +function set_vars_ranges() + set_vars() + number_of_ranges = number_of_ranges or 10 + delta = random_ranges_delta or 5 +end diff --git a/tests/include/oltp_legacy/update_index.lua b/tests/include/oltp_legacy/update_index.lua new file mode 100644 index 0000000..5d1f20c --- /dev/null +++ b/tests/include/oltp_legacy/update_index.lua @@ -0,0 +1,17 @@ +pathtest = string.match(test, "(.*/)") + +if pathtest then + dofile(pathtest .. "common.lua") +else + require("common") +end + +function thread_init() + set_vars() +end + +function event() + local table_name + table_name = "sbtest".. sb_rand_uniform(1, oltp_tables_count) + rs = db_query("UPDATE ".. table_name .." SET k=k+1 WHERE id=" .. sb_rand(1, oltp_table_size)) +end diff --git a/tests/include/oltp_legacy/update_non_index.lua b/tests/include/oltp_legacy/update_non_index.lua new file mode 100644 index 0000000..d549add --- /dev/null +++ b/tests/include/oltp_legacy/update_non_index.lua @@ -0,0 +1,21 @@ +pathtest = string.match(test, "(.*/)") + +if pathtest then + dofile(pathtest .. "common.lua") +else + require("common") +end + +function thread_init() + set_vars() +end + +function event() + local table_name + local c_val + local query + table_name = "sbtest".. sb_rand_uniform(1, oltp_tables_count) + c_val = sb_rand_str("###########-###########-###########-###########-###########-###########-###########-###########-###########-###########") + query = "UPDATE " .. table_name .. " SET c='" .. c_val .. "' WHERE id=" .. sb_rand(1, oltp_table_size) + rs = db_query(query) +end diff --git a/tests/include/script_oltp_common.sh b/tests/include/script_oltp_common.sh index 21ead7e..f3769fe 100644 --- a/tests/include/script_oltp_common.sh +++ b/tests/include/script_oltp_common.sh @@ -1,7 +1,7 @@ #!/usr/bin/env bash # ################################################################################ -# Common code for OLTP tests +# Common code for legacy OLTP tests # # Expects the following variables and callback functions to be defined by the # caller: @@ -14,7 +14,7 @@ set -eu -ARGS="--test=${SBTEST_SCRIPTDIR}/oltp.lua $DB_DRIVER_ARGS --oltp-tables-count=8" +ARGS="--test=${SBTEST_INCDIR}/oltp_legacy/oltp.lua $DB_DRIVER_ARGS --oltp-tables-count=8" sysbench $ARGS prepare @@ -42,7 +42,7 @@ db_show_table sbtest7 || true # Error on non-existing table db_show_table sbtest8 || true # Error on non-existing table # Test --oltp-create-secondary=off -ARGS="--test=${SBTEST_SCRIPTDIR}/oltp.lua $DB_DRIVER_ARGS --oltp-tables-count=1" +ARGS="--test=${SBTEST_INCDIR}/oltp_legacy/oltp.lua $DB_DRIVER_ARGS --oltp-tables-count=1" sysbench $ARGS --oltp-create-secondary=off prepare diff --git a/tests/include/script_oltp_legacy_common.sh b/tests/include/script_oltp_legacy_common.sh new file mode 100644 index 0000000..f3769fe --- /dev/null +++ b/tests/include/script_oltp_legacy_common.sh @@ -0,0 +1,51 @@ +#!/usr/bin/env bash +# +################################################################################ +# Common code for legacy OLTP tests +# +# Expects the following variables and callback functions to be defined by the +# caller: +# +# DB_DRIVER_ARGS -- extra driver-specific arguments to pass to sysbench +# +# db_show_table() -- called with a single argument to dump a specified table +# schema +################################################################################ + +set -eu + +ARGS="--test=${SBTEST_INCDIR}/oltp_legacy/oltp.lua $DB_DRIVER_ARGS --oltp-tables-count=8" + +sysbench $ARGS prepare + +db_show_table sbtest1 +db_show_table sbtest2 +db_show_table sbtest3 +db_show_table sbtest4 +db_show_table sbtest5 +db_show_table sbtest6 +db_show_table sbtest7 +db_show_table sbtest8 +db_show_table sbtest9 || true # Error on non-existing table + +sysbench $ARGS --max-requests=100 --num-threads=2 run + +sysbench $ARGS cleanup + +db_show_table sbtest1 || true # Error on non-existing table +db_show_table sbtest2 || true # Error on non-existing table +db_show_table sbtest3 || true # Error on non-existing table +db_show_table sbtest4 || true # Error on non-existing table +db_show_table sbtest5 || true # Error on non-existing table +db_show_table sbtest6 || true # Error on non-existing table +db_show_table sbtest7 || true # Error on non-existing table +db_show_table sbtest8 || true # Error on non-existing table + +# Test --oltp-create-secondary=off +ARGS="--test=${SBTEST_INCDIR}/oltp_legacy/oltp.lua $DB_DRIVER_ARGS --oltp-tables-count=1" + +sysbench $ARGS --oltp-create-secondary=off prepare + +db_show_table sbtest1 + +sysbench $ARGS cleanup diff --git a/tests/include/script_select_random_legacy_common.sh b/tests/include/script_select_random_legacy_common.sh new file mode 100644 index 0000000..b4dcdcc --- /dev/null +++ b/tests/include/script_select_random_legacy_common.sh @@ -0,0 +1,40 @@ +#!/usr/bin/env bash +# +################################################################################ +# Common code for select_random_* tests +# +# Expects the following variables and callback functions to be defined by the +# caller: +# +# DB_DRIVER_ARGS -- extra driver-specific arguments to pass to sysbench +# +# db_show_table() -- called with a single argument to dump a specified table +# schema +################################################################################ + +set -eu + +for test in select_random_points select_random_ranges +do + ARGS="--test=${SBTEST_INCDIR}/oltp_legacy/${test}.lua $DB_DRIVER_ARGS --oltp-tables-count=8" + + sysbench $ARGS prepare + + db_show_table sbtest1 + + for i in $(seq 2 8) + do + db_show_table sbtest${i} || true # Error on non-existing table + done + + sysbench $ARGS --max-requests=100 --num-threads=1 run + + sysbench $ARGS cleanup + + for i in $(seq 1 8) + do + db_show_table sbtest${i} || true # Error on non-existing table + done + + ARGS="--test=${SBTEST_INCDIR}/oltp_legacy/select_random_points.lua $DB_DRIVER_ARGS --oltp-tables-count=8" +done diff --git a/tests/t/api_legacy_basic.t b/tests/t/api_legacy_basic.t index a545221..f129308 100644 --- a/tests/t/api_legacy_basic.t +++ b/tests/t/api_legacy_basic.t @@ -1,5 +1,5 @@ ######################################################################## -Basic Lua API tests +Legacy basic Lua API tests ######################################################################## $ if [ -z "${SBTEST_MYSQL_ARGS:-}" ] diff --git a/tests/t/api_legacy_rand.t b/tests/t/api_legacy_rand.t index 96020b0..b762dc2 100644 --- a/tests/t/api_legacy_rand.t +++ b/tests/t/api_legacy_rand.t @@ -1,5 +1,5 @@ ######################################################################## -PRNG Lua API tests +Legacy PRNG Lua API tests ######################################################################## $ SB_ARGS="--verbosity=0 --test=$CRAMTMP/api_legacy_rand.lua --max-requests=1 --num-threads=1" diff --git a/tests/t/api_legacy_sql.t b/tests/t/api_legacy_sql.t index 2e4d33e..7abf4a0 100644 --- a/tests/t/api_legacy_sql.t +++ b/tests/t/api_legacy_sql.t @@ -1,5 +1,5 @@ ######################################################################## -SQL Lua API tests +Legacy SQL Lua API tests ######################################################################## $ if [ -z "${SBTEST_MYSQL_ARGS:-}" ] @@ -40,9 +40,9 @@ SQL Lua API tests $ mysql -uroot sbtest -Nse "DROP TABLE IF EXISTS t" $ sysbench $SB_ARGS run - DB_ERROR_NONE = 0 - DB_ERROR_RESTART_TRANSACTION = 1 - DB_ERROR_FAILED = 3 + DB_ERROR_NONE = [0-9] (re) + DB_ERROR_RESTART_TRANSACTION = [0-9] (re) + DB_ERROR_FAILED = [0-9] (re) $ mysql -uroot sbtest -Nse "SHOW CREATE TABLE t\G" *************************** 1. row *************************** @@ -60,3 +60,370 @@ SQL Lua API tests 200 $ mysql -uroot sbtest -Nse "DROP TABLE t" + + $ function db_show_table() { + > mysql -uroot sbtest -Nse "SHOW CREATE TABLE $1\G" + > } + + $ DB_DRIVER_ARGS="--db-driver=mysql --mysql-table-engine=myisam $SBTEST_MYSQL_ARGS" + $ . $SBTEST_INCDIR/script_oltp_legacy_common.sh + sysbench *.* * (glob) + + Creating table 'sbtest1'... + Inserting 10000 records into 'sbtest1' + Creating secondary indexes on 'sbtest1'... + Creating table 'sbtest2'... + Inserting 10000 records into 'sbtest2' + Creating secondary indexes on 'sbtest2'... + Creating table 'sbtest3'... + Inserting 10000 records into 'sbtest3' + Creating secondary indexes on 'sbtest3'... + Creating table 'sbtest4'... + Inserting 10000 records into 'sbtest4' + Creating secondary indexes on 'sbtest4'... + Creating table 'sbtest5'... + Inserting 10000 records into 'sbtest5' + Creating secondary indexes on 'sbtest5'... + Creating table 'sbtest6'... + Inserting 10000 records into 'sbtest6' + Creating secondary indexes on 'sbtest6'... + Creating table 'sbtest7'... + Inserting 10000 records into 'sbtest7' + Creating secondary indexes on 'sbtest7'... + Creating table 'sbtest8'... + Inserting 10000 records into 'sbtest8' + Creating secondary indexes on 'sbtest8'... + *************************** 1. row *************************** + sbtest1 + CREATE TABLE `sbtest1` ( + `id` int(10) unsigned NOT NULL AUTO_INCREMENT, + `k` int(10) unsigned NOT NULL DEFAULT '0', + `c` char(120)* NOT NULL DEFAULT '', (glob) + `pad` char(60)* NOT NULL DEFAULT '', (glob) + PRIMARY KEY (`id`), + KEY `k_1` (`k`) + ) ENGINE=MyISAM AUTO_INCREMENT=10001 DEFAULT CHARSET=* MAX_ROWS=1000000 (glob) + *************************** 1. row *************************** + sbtest2 + CREATE TABLE `sbtest2` ( + `id` int(10) unsigned NOT NULL AUTO_INCREMENT, + `k` int(10) unsigned NOT NULL DEFAULT '0', + `c` char(120)* NOT NULL DEFAULT '', (glob) + `pad` char(60)* NOT NULL DEFAULT '', (glob) + PRIMARY KEY (`id`), + KEY `k_2` (`k`) + ) ENGINE=MyISAM AUTO_INCREMENT=10001 DEFAULT CHARSET=* MAX_ROWS=1000000 (glob) + *************************** 1. row *************************** + sbtest3 + CREATE TABLE `sbtest3` ( + `id` int(10) unsigned NOT NULL AUTO_INCREMENT, + `k` int(10) unsigned NOT NULL DEFAULT '0', + `c` char(120)* NOT NULL DEFAULT '', (glob) + `pad` char(60)* NOT NULL DEFAULT '', (glob) + PRIMARY KEY (`id`), + KEY `k_3` (`k`) + ) ENGINE=MyISAM AUTO_INCREMENT=10001 DEFAULT CHARSET=* MAX_ROWS=1000000 (glob) + *************************** 1. row *************************** + sbtest4 + CREATE TABLE `sbtest4` ( + `id` int(10) unsigned NOT NULL AUTO_INCREMENT, + `k` int(10) unsigned NOT NULL DEFAULT '0', + `c` char(120)* NOT NULL DEFAULT '', (glob) + `pad` char(60)* NOT NULL DEFAULT '', (glob) + PRIMARY KEY (`id`), + KEY `k_4` (`k`) + ) ENGINE=MyISAM AUTO_INCREMENT=10001 DEFAULT CHARSET=* MAX_ROWS=1000000 (glob) + *************************** 1. row *************************** + sbtest5 + CREATE TABLE `sbtest5` ( + `id` int(10) unsigned NOT NULL AUTO_INCREMENT, + `k` int(10) unsigned NOT NULL DEFAULT '0', + `c` char(120)* NOT NULL DEFAULT '', (glob) + `pad` char(60)* NOT NULL DEFAULT '', (glob) + PRIMARY KEY (`id`), + KEY `k_5` (`k`) + ) ENGINE=MyISAM AUTO_INCREMENT=10001 DEFAULT CHARSET=* MAX_ROWS=1000000 (glob) + *************************** 1. row *************************** + sbtest6 + CREATE TABLE `sbtest6` ( + `id` int(10) unsigned NOT NULL AUTO_INCREMENT, + `k` int(10) unsigned NOT NULL DEFAULT '0', + `c` char(120)* NOT NULL DEFAULT '', (glob) + `pad` char(60)* NOT NULL DEFAULT '', (glob) + PRIMARY KEY (`id`), + KEY `k_6` (`k`) + ) ENGINE=MyISAM AUTO_INCREMENT=10001 DEFAULT CHARSET=* MAX_ROWS=1000000 (glob) + *************************** 1. row *************************** + sbtest7 + CREATE TABLE `sbtest7` ( + `id` int(10) unsigned NOT NULL AUTO_INCREMENT, + `k` int(10) unsigned NOT NULL DEFAULT '0', + `c` char(120)* NOT NULL DEFAULT '', (glob) + `pad` char(60)* NOT NULL DEFAULT '', (glob) + PRIMARY KEY (`id`), + KEY `k_7` (`k`) + ) ENGINE=MyISAM AUTO_INCREMENT=10001 DEFAULT CHARSET=* MAX_ROWS=1000000 (glob) + *************************** 1. row *************************** + sbtest8 + CREATE TABLE `sbtest8` ( + `id` int(10) unsigned NOT NULL AUTO_INCREMENT, + `k` int(10) unsigned NOT NULL DEFAULT '0', + `c` char(120)* NOT NULL DEFAULT '', (glob) + `pad` char(60)* NOT NULL DEFAULT '', (glob) + PRIMARY KEY (`id`), + KEY `k_8` (`k`) + ) ENGINE=MyISAM AUTO_INCREMENT=10001 DEFAULT CHARSET=* MAX_ROWS=1000000 (glob) + ERROR 1146 (42S02) at line 1: Table 'sbtest.sbtest9' doesn't exist + sysbench *.* * (glob) + + Running the test with following options: + Number of threads: 2 + Initializing random number generator from current time + + + Initializing worker threads... + + Threads started! + + OLTP test statistics: + queries performed: + read: 1400 + write: 400 + other: 200 + total: 2000 + transactions: 100 (* per sec.) (glob) + queries: 2000 (* per sec.) (glob) + ignored errors: 0 (* per sec.) (glob) + reconnects: 0 (* per sec.) (glob) + + General statistics: + total time: *s (glob) + total number of events: 100 + total time taken by event execution: *s (glob) + + Latency statistics: + min: *.*ms (glob) + avg: *.*ms (glob) + max: *.*ms (glob) + approx. 95th percentile: *.*ms (glob) + + Threads fairness: + events (avg/stddev): */* (glob) + execution time (avg/stddev): */* (glob) + + sysbench *.* * (glob) + + Dropping table 'sbtest1'... + Dropping table 'sbtest2'... + Dropping table 'sbtest3'... + Dropping table 'sbtest4'... + Dropping table 'sbtest5'... + Dropping table 'sbtest6'... + Dropping table 'sbtest7'... + Dropping table 'sbtest8'... + ERROR 1146 (42S02) at line 1: Table 'sbtest.sbtest1' doesn't exist + ERROR 1146 (42S02) at line 1: Table 'sbtest.sbtest2' doesn't exist + ERROR 1146 (42S02) at line 1: Table 'sbtest.sbtest3' doesn't exist + ERROR 1146 (42S02) at line 1: Table 'sbtest.sbtest4' doesn't exist + ERROR 1146 (42S02) at line 1: Table 'sbtest.sbtest5' doesn't exist + ERROR 1146 (42S02) at line 1: Table 'sbtest.sbtest6' doesn't exist + ERROR 1146 (42S02) at line 1: Table 'sbtest.sbtest7' doesn't exist + ERROR 1146 (42S02) at line 1: Table 'sbtest.sbtest8' doesn't exist + sysbench * (glob) + + Creating table 'sbtest1'... + Inserting 10000 records into 'sbtest1' + *************************** 1. row *************************** + sbtest1 + CREATE TABLE `sbtest1` ( + `id` int(10) unsigned NOT NULL AUTO_INCREMENT, + `k` int(10) unsigned NOT NULL DEFAULT '0', + `c` char(120)* NOT NULL DEFAULT '', (glob) + `pad` char(60)* NOT NULL DEFAULT '', (glob) + PRIMARY KEY (`id`) + ) ENGINE=MyISAM AUTO_INCREMENT=10001 DEFAULT CHARSET=* MAX_ROWS=1000000 (glob) + sysbench * (glob) + + Dropping table 'sbtest1'... + + $ DB_DRIVER_ARGS="--db-driver=mysql --mysql-table-engine=innodb $SBTEST_MYSQL_ARGS" + $ . $SBTEST_INCDIR/script_oltp_legacy_common.sh + sysbench *.* * (glob) + + Creating table 'sbtest1'... + Inserting 10000 records into 'sbtest1' + Creating secondary indexes on 'sbtest1'... + Creating table 'sbtest2'... + Inserting 10000 records into 'sbtest2' + Creating secondary indexes on 'sbtest2'... + Creating table 'sbtest3'... + Inserting 10000 records into 'sbtest3' + Creating secondary indexes on 'sbtest3'... + Creating table 'sbtest4'... + Inserting 10000 records into 'sbtest4' + Creating secondary indexes on 'sbtest4'... + Creating table 'sbtest5'... + Inserting 10000 records into 'sbtest5' + Creating secondary indexes on 'sbtest5'... + Creating table 'sbtest6'... + Inserting 10000 records into 'sbtest6' + Creating secondary indexes on 'sbtest6'... + Creating table 'sbtest7'... + Inserting 10000 records into 'sbtest7' + Creating secondary indexes on 'sbtest7'... + Creating table 'sbtest8'... + Inserting 10000 records into 'sbtest8' + Creating secondary indexes on 'sbtest8'... + *************************** 1. row *************************** + sbtest1 + CREATE TABLE `sbtest1` ( + `id` int(10) unsigned NOT NULL AUTO_INCREMENT, + `k` int(10) unsigned NOT NULL DEFAULT '0', + `c` char(120)* NOT NULL DEFAULT '', (glob) + `pad` char(60)* NOT NULL DEFAULT '', (glob) + PRIMARY KEY (`id`), + KEY `k_1` (`k`) + ) ENGINE=InnoDB AUTO_INCREMENT=10001 DEFAULT CHARSET=* MAX_ROWS=1000000 (glob) + *************************** 1. row *************************** + sbtest2 + CREATE TABLE `sbtest2` ( + `id` int(10) unsigned NOT NULL AUTO_INCREMENT, + `k` int(10) unsigned NOT NULL DEFAULT '0', + `c` char(120)* NOT NULL DEFAULT '', (glob) + `pad` char(60)* NOT NULL DEFAULT '', (glob) + PRIMARY KEY (`id`), + KEY `k_2` (`k`) + ) ENGINE=InnoDB AUTO_INCREMENT=10001 DEFAULT CHARSET=* MAX_ROWS=1000000 (glob) + *************************** 1. row *************************** + sbtest3 + CREATE TABLE `sbtest3` ( + `id` int(10) unsigned NOT NULL AUTO_INCREMENT, + `k` int(10) unsigned NOT NULL DEFAULT '0', + `c` char(120)* NOT NULL DEFAULT '', (glob) + `pad` char(60)* NOT NULL DEFAULT '', (glob) + PRIMARY KEY (`id`), + KEY `k_3` (`k`) + ) ENGINE=InnoDB AUTO_INCREMENT=10001 DEFAULT CHARSET=* MAX_ROWS=1000000 (glob) + *************************** 1. row *************************** + sbtest4 + CREATE TABLE `sbtest4` ( + `id` int(10) unsigned NOT NULL AUTO_INCREMENT, + `k` int(10) unsigned NOT NULL DEFAULT '0', + `c` char(120)* NOT NULL DEFAULT '', (glob) + `pad` char(60)* NOT NULL DEFAULT '', (glob) + PRIMARY KEY (`id`), + KEY `k_4` (`k`) + ) ENGINE=InnoDB AUTO_INCREMENT=10001 DEFAULT CHARSET=* MAX_ROWS=1000000 (glob) + *************************** 1. row *************************** + sbtest5 + CREATE TABLE `sbtest5` ( + `id` int(10) unsigned NOT NULL AUTO_INCREMENT, + `k` int(10) unsigned NOT NULL DEFAULT '0', + `c` char(120)* NOT NULL DEFAULT '', (glob) + `pad` char(60)* NOT NULL DEFAULT '', (glob) + PRIMARY KEY (`id`), + KEY `k_5` (`k`) + ) ENGINE=InnoDB AUTO_INCREMENT=10001 DEFAULT CHARSET=* MAX_ROWS=1000000 (glob) + *************************** 1. row *************************** + sbtest6 + CREATE TABLE `sbtest6` ( + `id` int(10) unsigned NOT NULL AUTO_INCREMENT, + `k` int(10) unsigned NOT NULL DEFAULT '0', + `c` char(120)* NOT NULL DEFAULT '', (glob) + `pad` char(60)* NOT NULL DEFAULT '', (glob) + PRIMARY KEY (`id`), + KEY `k_6` (`k`) + ) ENGINE=InnoDB AUTO_INCREMENT=10001 DEFAULT CHARSET=* MAX_ROWS=1000000 (glob) + *************************** 1. row *************************** + sbtest7 + CREATE TABLE `sbtest7` ( + `id` int(10) unsigned NOT NULL AUTO_INCREMENT, + `k` int(10) unsigned NOT NULL DEFAULT '0', + `c` char(120)* NOT NULL DEFAULT '', (glob) + `pad` char(60)* NOT NULL DEFAULT '', (glob) + PRIMARY KEY (`id`), + KEY `k_7` (`k`) + ) ENGINE=InnoDB AUTO_INCREMENT=10001 DEFAULT CHARSET=* MAX_ROWS=1000000 (glob) + *************************** 1. row *************************** + sbtest8 + CREATE TABLE `sbtest8` ( + `id` int(10) unsigned NOT NULL AUTO_INCREMENT, + `k` int(10) unsigned NOT NULL DEFAULT '0', + `c` char(120)* NOT NULL DEFAULT '', (glob) + `pad` char(60)* NOT NULL DEFAULT '', (glob) + PRIMARY KEY (`id`), + KEY `k_8` (`k`) + ) ENGINE=InnoDB AUTO_INCREMENT=10001 DEFAULT CHARSET=* MAX_ROWS=1000000 (glob) + ERROR 1146 (42S02) at line 1: Table 'sbtest.sbtest9' doesn't exist + sysbench *.* * (glob) + + Running the test with following options: + Number of threads: 2 + Initializing random number generator from current time + + + Initializing worker threads... + + Threads started! + + OLTP test statistics: + queries performed: + read: 1400 + write: 400 + other: 200 + total: 2000 + transactions: 100 (* per sec.) (glob) + queries: 2000 (* per sec.) (glob) + ignored errors: 0 (* per sec.) (glob) + reconnects: 0 (* per sec.) (glob) + + General statistics: + total time: *s (glob) + total number of events: 100 + total time taken by event execution: *s (glob) + + Latency statistics: + min: *.*ms (glob) + avg: *.*ms (glob) + max: *.*ms (glob) + approx. 95th percentile: *.*ms (glob) + + Threads fairness: + events (avg/stddev): */* (glob) + execution time (avg/stddev): */* (glob) + + sysbench *.* * (glob) + + Dropping table 'sbtest1'... + Dropping table 'sbtest2'... + Dropping table 'sbtest3'... + Dropping table 'sbtest4'... + Dropping table 'sbtest5'... + Dropping table 'sbtest6'... + Dropping table 'sbtest7'... + Dropping table 'sbtest8'... + ERROR 1146 (42S02) at line 1: Table 'sbtest.sbtest1' doesn't exist + ERROR 1146 (42S02) at line 1: Table 'sbtest.sbtest2' doesn't exist + ERROR 1146 (42S02) at line 1: Table 'sbtest.sbtest3' doesn't exist + ERROR 1146 (42S02) at line 1: Table 'sbtest.sbtest4' doesn't exist + ERROR 1146 (42S02) at line 1: Table 'sbtest.sbtest5' doesn't exist + ERROR 1146 (42S02) at line 1: Table 'sbtest.sbtest6' doesn't exist + ERROR 1146 (42S02) at line 1: Table 'sbtest.sbtest7' doesn't exist + ERROR 1146 (42S02) at line 1: Table 'sbtest.sbtest8' doesn't exist + sysbench * (glob) + + Creating table 'sbtest1'... + Inserting 10000 records into 'sbtest1' + *************************** 1. row *************************** + sbtest1 + CREATE TABLE `sbtest1` ( + `id` int(10) unsigned NOT NULL AUTO_INCREMENT, + `k` int(10) unsigned NOT NULL DEFAULT '0', + `c` char(120)* NOT NULL DEFAULT '', (glob) + `pad` char(60)* NOT NULL DEFAULT '', (glob) + PRIMARY KEY (`id`) + ) ENGINE=InnoDB AUTO_INCREMENT=10001 DEFAULT CHARSET=* MAX_ROWS=1000000 (glob) + sysbench * (glob) + + Dropping table 'sbtest1'... + diff --git a/tests/t/api_sql.t b/tests/t/api_sql.t index 68dff37..27698d5 100644 --- a/tests/t/api_sql.t +++ b/tests/t/api_sql.t @@ -9,40 +9,61 @@ SQL Lua API tests $ SB_ARGS="--verbosity=1 --test=$CRAMTMP/api_sql.lua --max-requests=1 --num-threads=1 --db-driver=mysql $SBTEST_MYSQL_ARGS" $ cat >$CRAMTMP/api_sql.lua < function event(thread_id) - > db_query("CREATE TABLE t(a INT)") + > function thread_init() + > drv = sysbench.sql.driver() + > con = drv:connect() + > end > - > db_bulk_insert_init("INSERT INTO t VALUES") + > function event() + > for k,v in pairs(sysbench.sql.type) do print(k .. " = " .. v) end + > print() + > + > con:query("DROP TABLE IF EXISTS t") + > con:query("CREATE TABLE t(a INT)") + > con:bulk_insert_init("INSERT INTO t VALUES") > for i = 1,100 do - > db_bulk_insert_next(string.format("(%d)", i)) + > con:bulk_insert_next(string.format("(%d)", i)) > end - > db_bulk_insert_done() + > con:bulk_insert_done() > - > db_connect() - > db_query("SELECT 1") - > db_disconnect() - > db_query("SELECT 1") - > db_connect() + > con2 = drv:connect() + > con:query("SELECT CONNECTION_ID()") + > con2:query("SELECT CONNECTION_ID()") + > con2:disconnect() > - > local stmt = db_prepare("UPDATE t SET a = a + ?") - > db_bind_param(stmt, {100}) - > rs = db_execute(stmt) - > db_store_results(rs) - > db_free_results(rs) - > db_close(stmt) - > - > print("DB_ERROR_NONE = " .. DB_ERROR_NONE) - > print("DB_ERROR_RESTART_TRANSACTION = " .. DB_ERROR_RESTART_TRANSACTION) - > print("DB_ERROR_FAILED = " .. DB_ERROR_FAILED) + > con:query("SELECT 1") + > con:disconnect() + > con:query("SELECT 1") + > + > con = drv:connect() + > con:query[[UPDATE t SET a = a + 100]] + > + > -- local stmt = con:prepare("UPDATE t SET a = a + ?") + > -- stmt:bind_param({{sysbench.sql.type.INT}}) + > -- rs = stmt:execute() + > -- rs:free_results() + > -- stmt:close() > end > EOF $ mysql -uroot sbtest -Nse "DROP TABLE IF EXISTS t" $ sysbench $SB_ARGS run - DB_ERROR_NONE = 0 - DB_ERROR_RESTART_TRANSACTION = 1 - DB_ERROR_FAILED = 3 + NONE = 0 + INT = 3 + CHAR = 11 + VARCHAR = 12 + TIMESTAMP = 10 + TIME = 7 + FLOAT = 5 + TINYINT = 1 + BIGINT = 4 + SMALLINT = 2 + DATE = 8 + DATETIME = 9 + DOUBLE = 6 + + ALERT: attempt to use an already closed connection $ mysql -uroot sbtest -Nse "SHOW CREATE TABLE t\G" *************************** 1. row *************************** diff --git a/tests/t/drv_mysql.t b/tests/t/drv_mysql.t index 86bea89..5f4ef0b 100644 --- a/tests/t/drv_mysql.t +++ b/tests/t/drv_mysql.t @@ -25,9 +25,8 @@ MySQL driver tests write: 0 other: 0 total: 10 - transactions: 0 (0.00 per sec.) - read/write requests: 10 (*.* per sec.) (glob) - other operations: 0 (0.00 per sec.) + transactions: 10 (*.* per sec.) (glob) + queries: 10 (*.* per sec.) (glob) ignored errors: 0 (0.00 per sec.) reconnects: 0 (0.00 per sec.) diff --git a/tests/t/drv_pgsql.t b/tests/t/drv_pgsql.t index 79876ea..034808f 100644 --- a/tests/t/drv_pgsql.t +++ b/tests/t/drv_pgsql.t @@ -25,9 +25,8 @@ PostgreSQL driver tests write: 0 other: 0 total: 10 - transactions: 0 (0.00 per sec.) - read/write requests: 10 (*.* per sec.) (glob) - other operations: 0 (0.00 per sec.) + transactions: 10 (*.* per sec.) (glob) + queries: 10 (*.* per sec.) (glob) ignored errors: 0 (0.00 per sec.) reconnects: 0 (0.00 per sec.) diff --git a/tests/t/opt_report_interval.t b/tests/t/opt_report_interval.t index c079d36..a9ecde2 100644 --- a/tests/t/opt_report_interval.t +++ b/tests/t/opt_report_interval.t @@ -8,7 +8,7 @@ > fi $ sysbench --test=${SBTEST_SCRIPTDIR}/oltp.lua --db-driver=mysql --mysql-dry-run --max-time=3 --max-requests=0 --report-interval=1 run | grep '\[ 2s\]' - [ 2s] threads: 1, tps: *, reads: *, writes: *, response time: *ms (95%), errors: 0.00, reconnects: 0.00 (glob) + [ 2s] threads: 1 tps: * qps: * (r/w/o: */*/*) latency: *ms (95%) errors/s: 0.00 reconnects/s: 0.00 (glob) # Run a test that does not support intermediate reports diff --git a/tests/t/script_oltp_mysql.t b/tests/t/script_oltp_mysql.t index 14702bf..52a46e6 100644 --- a/tests/t/script_oltp_mysql.t +++ b/tests/t/script_oltp_mysql.t @@ -138,8 +138,7 @@ oltp.lua + MySQL tests other: 200 total: 2000 transactions: 100 (* per sec.) (glob) - read/write requests: 1800 (* per sec.) (glob) - other operations: 200 (* per sec.) (glob) + queries: 2000 (* per sec.) (glob) ignored errors: 0 (* per sec.) (glob) reconnects: 0 (* per sec.) (glob) @@ -320,8 +319,7 @@ oltp.lua + MySQL tests other: 200 total: 2000 transactions: 100 (* per sec.) (glob) - read/write requests: 1800 (* per sec.) (glob) - other operations: 200 (* per sec.) (glob) + queries: 2000 (* per sec.) (glob) ignored errors: 0 (* per sec.) (glob) reconnects: 0 (* per sec.) (glob) diff --git a/tests/t/script_oltp_pgsql.t b/tests/t/script_oltp_pgsql.t index 3ae47bf..e11261c 100644 --- a/tests/t/script_oltp_pgsql.t +++ b/tests/t/script_oltp_pgsql.t @@ -147,8 +147,7 @@ oltp.lua + PostgreSQL tests other: 200 total: 2000 transactions: 100 (* per sec.) (glob) - read/write requests: 1800 (* per sec.) (glob) - other operations: 200 (* per sec.) (glob) + queries: 2000 (* per sec.) (glob) ignored errors: 0 (* per sec.) (glob) reconnects: 0 (* per sec.) (glob) diff --git a/tests/t/script_select_random_mysql.t b/tests/t/script_select_random_mysql.t.disabled similarity index 95% rename from tests/t/script_select_random_mysql.t rename to tests/t/script_select_random_mysql.t.disabled index 7d78a1f..dbb75d0 100644 --- a/tests/t/script_select_random_mysql.t +++ b/tests/t/script_select_random_mysql.t.disabled @@ -53,8 +53,7 @@ select_random_*.lua + MySQL tests other: 0 total: 100 transactions: 0 (0.00 per sec.) - read/write requests: 100 (* per sec.) (glob) - other operations: 0 (0.00 per sec.) + queries: 100 (* per sec.) (glob) ignored errors: 0 (0.00 per sec.) reconnects: 0 (0.00 per sec.) @@ -124,8 +123,7 @@ select_random_*.lua + MySQL tests other: 0 total: 100 transactions: 0 (0.00 per sec.) - read/write requests: 100 (* per sec.) (glob) - other operations: 0 (0.00 per sec.) + queries: 100 (* per sec.) (glob) ignored errors: 0 (0.00 per sec.) reconnects: 0 (0.00 per sec.) diff --git a/tests/t/script_select_random_pgsql.t b/tests/t/script_select_random_pgsql.t.disabled similarity index 95% rename from tests/t/script_select_random_pgsql.t rename to tests/t/script_select_random_pgsql.t.disabled index 05552aa..8dcc87f 100644 --- a/tests/t/script_select_random_pgsql.t +++ b/tests/t/script_select_random_pgsql.t.disabled @@ -54,8 +54,7 @@ select_random_*.lua + PostgreSQL tests other: 0 total: 100 transactions: 0 (0.00 per sec.) - read/write requests: 100 (* per sec.) (glob) - other operations: 0 (0.00 per sec.) + queries: 100 (* per sec.) (glob) ignored errors: 0 (0.00 per sec.) reconnects: 0 (0.00 per sec.) @@ -126,8 +125,7 @@ select_random_*.lua + PostgreSQL tests other: 0 total: 100 transactions: 0 (0.00 per sec.) - read/write requests: 100 (* per sec.) (glob) - other operations: 0 (0.00 per sec.) + queries: 100 (* per sec.) (glob) ignored errors: 0 (0.00 per sec.) reconnects: 0 (0.00 per sec.) diff --git a/tests/test_run.sh b/tests/test_run.sh index b58dd05..fddf0ab 100755 --- a/tests/test_run.sh +++ b/tests/test_run.sh @@ -65,7 +65,7 @@ else fi export SBTEST_ROOTDIR="$testroot" -export SBTEST_SCRIPTDIR="$testroot/../sysbench/tests/db" +export SBTEST_SCRIPTDIR="$testroot/../sysbench/lua" export SBTEST_SUITEDIR="$testroot/t" export SBTEST_INCDIR="$PWD/include" export SBTEST_CONFIG="$SBTEST_INCDIR/config.sh"