static inline int wrapper_single_mysql_send_query(const db_con_t *conn, const str *query) { int code, error; if (CON_DISCON(conn)) return -1; code = mysql_send_query(CON_CONNECTION(conn), query->s, query->len); if (code == 0) return 0; error = mysql_errno(CON_CONNECTION(conn)); switch (error) { case CR_SERVER_GONE_ERROR: case CR_SERVER_LOST: case CR_COMMANDS_OUT_OF_SYNC: return -1; /* reconnection error -> <0 */ default: LM_CRIT("driver error (%i): %s\n", error, mysql_error(CON_CONNECTION(conn))); /* do not rely on libmysqlclient implementation * specification says non-zero code on error, not positive code */ return 1; } }
/* * mysql_send_query is unlikely to block since most queries are small * enough to fit in a socket buffer, but sometimes large UPDATE and * INSERTs will cause the process to block */ static void *nogvl_send_query(void *ptr) { struct nogvl_send_query_args *args = ptr; int rv; rv = mysql_send_query(args->mysql, args->sql_ptr, args->sql_len); return (void*)(rv == 0 ? Qtrue : Qfalse); }
/* * mysql_send_query is unlikely to block since most queries are small * enough to fit in a socket buffer, but sometimes large UPDATE and * INSERTs will cause the process to block */ static VALUE nogvl_send_query(void *ptr) { struct nogvl_send_query_args *args = ptr; int rv; const char *sql = StringValuePtr(args->sql); long sql_len = RSTRING_LEN(args->sql); rv = mysql_send_query(args->mysql, sql, sql_len); return rv == 0 ? Qtrue : Qfalse; }
MYSQL_RES *do_mysql_cCommand_execute_async(VALUE self, VALUE connection, MYSQL *db, VALUE query) { int retval; if ((retval = mysql_ping(db)) && mysql_errno(db) == CR_SERVER_GONE_ERROR) { do_mysql_full_connect(connection, db); } struct timeval start; const char *str = rb_str_ptr_readonly(query); long len = rb_str_len(query); gettimeofday(&start, NULL); retval = mysql_send_query(db, str, len); CHECK_AND_RAISE(retval, query); int socket_fd = db->net.fd; fd_set rset; while (1) { FD_ZERO(&rset); FD_SET(socket_fd, &rset); retval = rb_thread_select(socket_fd + 1, &rset, NULL, NULL, NULL); if (retval < 0) { rb_sys_fail(0); } if (retval == 0) { continue; } if (db->status == MYSQL_STATUS_READY) { break; } } retval = mysql_read_query_result(db); CHECK_AND_RAISE(retval, query); data_objects_debug(connection, query, &start); MYSQL_RES *result = mysql_store_result(db); if (!result) { CHECK_AND_RAISE(mysql_errno(db), query); } return result; }
static MYSQL_RES* cCommand_execute_async(VALUE self, MYSQL* db, VALUE query) { int socket_fd; int retval; fd_set rset; char* str = RSTRING_PTR(query); int len = RSTRING_LEN(query); VALUE connection = rb_iv_get(self, "@connection"); retval = mysql_ping(db); if(retval == CR_SERVER_GONE_ERROR) { CHECK_AND_RAISE(retval, "Mysql server has gone away. \ Please report this issue to the Datamapper project. \ Specify your at least your MySQL version when filing a ticket"); } retval = mysql_send_query(db, str, len); data_objects_debug(query); CHECK_AND_RAISE(retval, str); socket_fd = db->net.fd; for(;;) { FD_ZERO(&rset); FD_SET(socket_fd, &rset); retval = rb_thread_select(socket_fd + 1, &rset, NULL, NULL, NULL); if (retval < 0) { rb_sys_fail(0); }