add some comments to the C code. take out come compiler warnings, add some notes.
This commit is contained in:
parent
d40d8ff323
commit
c5042772b5
3
README
3
README
@ -38,3 +38,6 @@ Lourens Naude for 1.9 integration help.
|
|||||||
|
|
||||||
=== License
|
=== License
|
||||||
Ruby License, http://www.ruby-lang.org/en/LICENSE.txt.
|
Ruby License, http://www.ruby-lang.org/en/LICENSE.txt.
|
||||||
|
|
||||||
|
== Mailing list
|
||||||
|
http://groups.google.com/group/never-block?hl=en
|
||||||
|
@ -3,3 +3,10 @@ TODO list:
|
|||||||
Is there a quick, cheap, easy way to test for writability so we don't have to use select itself? Does select take any time that it's worth looking into this?
|
Is there a quick, cheap, easy way to test for writability so we don't have to use select itself? Does select take any time that it's worth looking into this?
|
||||||
|
|
||||||
Some of the tests currently might "think" they are using the ruby select but in reality be using the C select.
|
Some of the tests currently might "think" they are using the ruby select but in reality be using the C select.
|
||||||
|
|
||||||
|
gc_disabled is unused
|
||||||
|
|
||||||
|
if they call get_result twice consecutively it should blow (and maybe already does).
|
||||||
|
|
||||||
|
mingw support
|
||||||
|
add slim attributes right in there :)
|
||||||
|
89
ext/mysql.c
89
ext/mysql.c
@ -67,6 +67,7 @@ struct mysql {
|
|||||||
char busy;
|
char busy;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// a wrapper for mysql_res's so we can detect double frees
|
||||||
struct mysql_res {
|
struct mysql_res {
|
||||||
MYSQL_RES* res;
|
MYSQL_RES* res;
|
||||||
char freed;
|
char freed;
|
||||||
@ -233,11 +234,12 @@ static VALUE init(VALUE klass)
|
|||||||
mysql_init(&myp->handler);
|
mysql_init(&myp->handler);
|
||||||
myp->connection = Qfalse;
|
myp->connection = Qfalse;
|
||||||
myp->query_with_result = Qtrue;
|
myp->query_with_result = Qtrue;
|
||||||
myp->gc_disabled = Qfalse;
|
myp->gc_disabled = Qtrue;
|
||||||
rb_obj_call_init(obj, 0, NULL);
|
rb_obj_call_init(obj, 0, NULL);
|
||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// =========== a 1.9 rb_thread_blocking_region simplifier attempt
|
||||||
#ifdef HAVE_TBR
|
#ifdef HAVE_TBR
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
@ -247,17 +249,16 @@ typedef struct
|
|||||||
void *args[10];
|
void *args[10];
|
||||||
} arg_holder, *arg_holder2;
|
} arg_holder, *arg_holder2;
|
||||||
|
|
||||||
|
// here's how to make rb_thread_blocking_region much cleaner and easier
|
||||||
// here's the call to make rb_thread_blocking_region much cleaner and easier
|
|
||||||
// syntax: param_count+2, func_pointer to call, [RUBY_UBF_IO or RUBY_UBF_PROCESS], param1, param2...
|
// syntax: param_count+2, func_pointer to call, [RUBY_UBF_IO or RUBY_UBF_PROCESS], param1, param2...
|
||||||
// the third parameter is the interuptor--possible values appear to be RUBY_UBF_IO or RUBY_UBF_PROCESS http://groups.google.com/group/comp.lang.ruby/browse_thread/thread/ad8c1326b2a8e404/00447b9aa15979be?lnk=raot
|
// the third parameter is the interuptor--possible values appear to be RUBY_UBF_IO or RUBY_UBF_PROCESS http://groups.google.com/group/comp.lang.ruby/browse_thread/thread/ad8c1326b2a8e404/00447b9aa15979be?lnk=raot
|
||||||
// ex: (int) returned_this = rb_thread_blocking_region_variable_params(10, &method_name, RUBY_UBF_IO, param1, param2, param3, param4, param5, param6, param7, param8)
|
// ex: (int) returned_this = rb_thread_blocking_region_variable_params(10, &method_name, RUBY_UBF_IO, param1, param2, param3, param4, param5, param6, param7, param8)
|
||||||
|
|
||||||
static void call_single_function_rb_thread_blocking_region(void *arg_holder_in);
|
static void *call_single_function_rb_thread_blocking_region(void *arg_holder_in);
|
||||||
|
|
||||||
void *rb_thread_blocking_region_variable_params(int number, ...)
|
void *rb_thread_blocking_region_variable_params(int number, ...)
|
||||||
{
|
{
|
||||||
va_list param_pt; // TODO handle all the way through 10 args
|
va_list param_pt;
|
||||||
va_start(param_pt, number);
|
va_start(param_pt, number);
|
||||||
int index;
|
int index;
|
||||||
arg_holder param_storer;
|
arg_holder param_storer;
|
||||||
@ -274,31 +275,33 @@ void *rb_thread_blocking_region_variable_params(int number, ...)
|
|||||||
}
|
}
|
||||||
va_end(param_pt);
|
va_end(param_pt);
|
||||||
|
|
||||||
return rb_thread_blocking_region((rb_blocking_function_t *)call_single_function_rb_thread_blocking_region, (void *) ¶m_storer, interrupter, 0);
|
return (void *) rb_thread_blocking_region((rb_blocking_function_t *)call_single_function_rb_thread_blocking_region, (void *) ¶m_storer, interrupter, 0);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void call_single_function_rb_thread_blocking_region(void *arg_holder_in)
|
// used internally
|
||||||
|
static void * call_single_function_rb_thread_blocking_region(void *arg_holder_in)
|
||||||
{
|
{
|
||||||
arg_holder *params_and_func = (arg_holder *) arg_holder_in;
|
arg_holder *params_and_func = (arg_holder *) arg_holder_in;
|
||||||
int param_count = params_and_func->param_count;
|
int param_count = params_and_func->param_count;
|
||||||
void *result;
|
void *result;
|
||||||
if(param_count == 3)
|
switch(param_count)
|
||||||
{
|
{
|
||||||
void * (*pt2Func)(void *, void *, void *) = params_and_func->func_pointer;
|
case 3:;
|
||||||
result = (*pt2Func)(params_and_func->args[0], params_and_func->args[1], params_and_func->args[2]);
|
void * (*pt3Func)(void *, void *, void *) = params_and_func->func_pointer;
|
||||||
}else if(param_count == 6)
|
result = (*pt3Func)(params_and_func->args[0], params_and_func->args[1], params_and_func->args[2]);
|
||||||
{
|
break;
|
||||||
void * (*pt2Func)(void *, void *, void *, void *, void *, void *) = params_and_func->func_pointer;
|
case 6:;
|
||||||
result = (*pt2Func)(params_and_func->args[0], params_and_func->args[1], params_and_func->args[2], params_and_func->args[3], params_and_func->args[4], params_and_func->args[5]);
|
void * (*pt6Func)(void *, void *, void *, void *, void *, void *) = params_and_func->func_pointer;
|
||||||
}else if(param_count == 8)
|
result = (*pt6Func)(params_and_func->args[0], params_and_func->args[1], params_and_func->args[2], params_and_func->args[3], params_and_func->args[4], params_and_func->args[5]);
|
||||||
{
|
break;
|
||||||
void * (*pt2Func)(void *, void *, void *, void *, void *, void *, void *, void *) = params_and_func->func_pointer;
|
case 8:;
|
||||||
result = (*pt2Func)(params_and_func->args[0], params_and_func->args[1], params_and_func->args[2], params_and_func->args[3], params_and_func->args[4], params_and_func->args[5], params_and_func->args[6], params_and_func->args[7]);
|
void * (*pt8Func)(void *, void *, void *, void *, void *, void *, void *, void *) = params_and_func->func_pointer;
|
||||||
}else
|
result = (*pt8Func)(params_and_func->args[0], params_and_func->args[1], params_and_func->args[2], params_and_func->args[3], params_and_func->args[4], params_and_func->args[5], params_and_func->args[6], params_and_func->args[7]);
|
||||||
{
|
break;
|
||||||
printf("UN nonwn param count--please add it! %d\n", param_count);
|
default:;
|
||||||
result = Qnil;
|
printf("UNknown param count--please add it! %d\n", param_count);
|
||||||
|
result = (void *) Qnil;
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
@ -337,14 +340,14 @@ static void optimize_for_async( VALUE obj )
|
|||||||
async_in_progress_set( obj, Qfalse );
|
async_in_progress_set( obj, Qfalse );
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO what should this do?
|
// TODO does nothing currently
|
||||||
static void schedule_connect(VALUE obj )
|
static void schedule_connect(VALUE obj )
|
||||||
{
|
{
|
||||||
|
/* TODO is this old?
|
||||||
MYSQL* m = GetHandler(obj);
|
MYSQL* m = GetHandler(obj);
|
||||||
fd_set read;
|
fd_set read;
|
||||||
|
|
||||||
struct timeval tv = { tv_sec: m->options.connect_timeout, tv_usec: 0 };
|
struct timeval tv = { tv_sec: m->options.connect_timeout, tv_usec: 0 };
|
||||||
/* TODO is this old?
|
|
||||||
if (rb_thread_select(0, NULL, NULL, NULL, &tv) < 0) {
|
if (rb_thread_select(0, NULL, NULL, NULL, &tv) < 0) {
|
||||||
rb_raise(eMysql, "connect: timeout");
|
rb_raise(eMysql, "connect: timeout");
|
||||||
}
|
}
|
||||||
@ -361,7 +364,7 @@ static void schedule_connect(VALUE obj )
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* real_connect(host=nil, user=nil, passwd=nil, db=nil, port=nil, sock=nil, flag=nil) */
|
/* real_connect(host=nil, user=nil, passwd=nil, db=nil, port=nil, sock=nil, flag=nil) */
|
||||||
static VALUE real_connect(int argc, VALUE* argv, VALUE klass) /* actually gets run */
|
static VALUE real_connect(int argc, VALUE* argv, VALUE klass)
|
||||||
{
|
{
|
||||||
VALUE host, user, passwd, db, port, sock, flag;
|
VALUE host, user, passwd, db, port, sock, flag;
|
||||||
char *h, *u, *p, *d, *s;
|
char *h, *u, *p, *d, *s;
|
||||||
@ -389,7 +392,7 @@ static VALUE real_connect(int argc, VALUE* argv, VALUE klass) /* actually gets r
|
|||||||
#if MYSQL_VERSION_ID >= 32200
|
#if MYSQL_VERSION_ID >= 32200
|
||||||
mysql_init(&myp->handler); /* we get here */
|
mysql_init(&myp->handler); /* we get here */
|
||||||
# ifdef HAVE_TBR
|
# ifdef HAVE_TBR
|
||||||
if( (int) rb_thread_blocking_region_variable_params(10, &mysql_real_connect, RUBY_UBF_IO, &myp->handler, h, u, p, d, pp, s, f) == NULL)
|
if( (MYSQL *) rb_thread_blocking_region_variable_params(10, &mysql_real_connect, RUBY_UBF_IO, &myp->handler, h, u, p, d, pp, s, f) == NULL)
|
||||||
# else
|
# else
|
||||||
if(mysql_real_connect(&myp->handler, h, u, p, d, pp, s, f) == NULL)
|
if(mysql_real_connect(&myp->handler, h, u, p, d, pp, s, f) == NULL)
|
||||||
# endif
|
# endif
|
||||||
@ -408,7 +411,7 @@ static VALUE real_connect(int argc, VALUE* argv, VALUE klass) /* actually gets r
|
|||||||
myp->query_with_result = Qtrue;
|
myp->query_with_result = Qtrue;
|
||||||
rb_obj_call_init(obj, argc, argv);
|
rb_obj_call_init(obj, argc, argv);
|
||||||
|
|
||||||
schedule_connect(obj);
|
//schedule_connect(obj);
|
||||||
|
|
||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
@ -473,7 +476,7 @@ static VALUE real_connect2(int argc, VALUE* argv, VALUE obj)
|
|||||||
GetMysqlStruct(obj)->connection = Qtrue;
|
GetMysqlStruct(obj)->connection = Qtrue;
|
||||||
|
|
||||||
optimize_for_async(obj);
|
optimize_for_async(obj);
|
||||||
schedule_connect(obj);
|
//schedule_connect(obj);
|
||||||
|
|
||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
@ -825,6 +828,7 @@ static VALUE my_stat(VALUE obj)
|
|||||||
return rb_tainted_str_new2(s);
|
return rb_tainted_str_new2(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 1.9 friendly
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
MYSQL *mysql_instance;
|
MYSQL *mysql_instance;
|
||||||
@ -836,7 +840,7 @@ typedef struct
|
|||||||
static VALUE store_result_to_location(void *settings_in)
|
static VALUE store_result_to_location(void *settings_in)
|
||||||
{
|
{
|
||||||
mysql_result_to_here_t *settings = (mysql_result_to_here_t *) settings_in;
|
mysql_result_to_here_t *settings = (mysql_result_to_here_t *) settings_in;
|
||||||
*(settings->store_it_here) = mysql_store_result(settings->mysql_instance); // this one runs a good long while for very large queries
|
*(settings->store_it_here) = mysql_store_result(settings->mysql_instance); // this one line runs a good long while for very large queries
|
||||||
return Qnil;
|
return Qnil;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -851,7 +855,7 @@ static VALUE store_result(VALUE obj)
|
|||||||
mysql_result_to_here_t linker;
|
mysql_result_to_here_t linker;
|
||||||
linker.mysql_instance = m;
|
linker.mysql_instance = m;
|
||||||
linker.store_it_here = &res;
|
linker.store_it_here = &res;
|
||||||
rb_thread_blocking_region(store_result_to_location, (void *) &linker, RUBY_UBF_IO, 0); /* not sure if this should be RUBY_UBF_IO or RUBY_UBF_PROCESS here -- see Ruby 1.9 ChangeLog */
|
rb_thread_blocking_region(store_result_to_location, (void *) &linker, RUBY_UBF_IO, 0);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (res == NULL)
|
if (res == NULL)
|
||||||
@ -956,14 +960,12 @@ static VALUE socket(VALUE obj)
|
|||||||
MYSQL* m = GetHandler(obj);
|
MYSQL* m = GetHandler(obj);
|
||||||
return INT2NUM(m->net.fd);
|
return INT2NUM(m->net.fd);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* socket_type --currently returns true or false, needs some work */
|
/* socket_type --currently returns true or false, needs some work */
|
||||||
static VALUE socket_type(VALUE obj)
|
static VALUE socket_type(VALUE obj)
|
||||||
{
|
{
|
||||||
MYSQL* m = GetHandler(obj);
|
MYSQL* m = GetHandler(obj);
|
||||||
char *answer;
|
if(vio_description(m->net.vio))
|
||||||
VALUE description = vio_description( m->net.vio );
|
|
||||||
answer = NILorSTRING( description );
|
|
||||||
if(answer)
|
|
||||||
return Qtrue; // TODO return a ruby string
|
return Qtrue; // TODO return a ruby string
|
||||||
else
|
else
|
||||||
return Qnil;
|
return Qnil;
|
||||||
@ -1012,7 +1014,7 @@ static VALUE readable( int argc, VALUE* argv, VALUE obj )
|
|||||||
if ( NIL_P( timeout ) ){
|
if ( NIL_P( timeout ) ){
|
||||||
timeout = m->net.read_timeout;
|
timeout = m->net.read_timeout;
|
||||||
}
|
}
|
||||||
|
// todo could do a rb_blocking_region here
|
||||||
return ( vio_poll_read( m->net.vio, INT2NUM(timeout) ) == 0 ? Qtrue : Qfalse );
|
return ( vio_poll_read( m->net.vio, INT2NUM(timeout) ) == 0 ? Qtrue : Qfalse );
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1054,14 +1056,13 @@ static VALUE gc_disabled( VALUE obj ){
|
|||||||
|
|
||||||
static void validate_async_query( VALUE obj )
|
static void validate_async_query( VALUE obj )
|
||||||
{
|
{
|
||||||
MYSQL* m = GetHandler(obj);
|
|
||||||
|
|
||||||
if( async_in_progress(obj) == Qtrue ){
|
if( async_in_progress(obj) == Qtrue ){
|
||||||
async_in_progress_set(obj, Qfalse);
|
async_in_progress_set(obj, Qfalse);
|
||||||
rb_raise(eMysql, "Query out of sequence: Each call to Mysql#send_query requires a successive Mysql#get_result.");
|
rb_raise(eMysql, "Query out of sequence: Each call to Mysql#send_query requires a successive Mysql#get_result.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* for testing */
|
||||||
static VALUE simulate_disconnect( VALUE obj )
|
static VALUE simulate_disconnect( VALUE obj )
|
||||||
{
|
{
|
||||||
MYSQL* m = GetHandler(obj);
|
MYSQL* m = GetHandler(obj);
|
||||||
@ -1093,7 +1094,11 @@ static VALUE send_query(VALUE obj, VALUE sql)
|
|||||||
return Qnil;
|
return Qnil;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* get_result */
|
/*
|
||||||
|
get_result
|
||||||
|
returns the mysql_result set (default) [i.e. all rows in said said]
|
||||||
|
or nil if query_with_result == false
|
||||||
|
*/
|
||||||
static VALUE get_result(VALUE obj)
|
static VALUE get_result(VALUE obj)
|
||||||
{
|
{
|
||||||
MYSQL* m = GetHandler(obj);
|
MYSQL* m = GetHandler(obj);
|
||||||
@ -1111,8 +1116,10 @@ static VALUE get_result(VALUE obj)
|
|||||||
|
|
||||||
if (GetMysqlStruct(obj)->query_with_result == Qfalse)
|
if (GetMysqlStruct(obj)->query_with_result == Qfalse)
|
||||||
return obj;
|
return obj;
|
||||||
|
|
||||||
if (mysql_field_count(m) == 0)
|
if (mysql_field_count(m) == 0)
|
||||||
return Qnil;
|
return Qnil;
|
||||||
|
|
||||||
return store_result(obj);
|
return store_result(obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1150,7 +1157,9 @@ static int should_schedule_query(){
|
|||||||
return rb_thread_alone() != 1;
|
return rb_thread_alone() != 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* async_query(sql,timeout=nil) */
|
/* async_query(sql,timeout=nil)
|
||||||
|
optionally take a block
|
||||||
|
*/
|
||||||
static VALUE async_query(int argc, VALUE* argv, VALUE obj)
|
static VALUE async_query(int argc, VALUE* argv, VALUE obj)
|
||||||
{
|
{
|
||||||
MYSQL* m = GetHandler(obj);
|
MYSQL* m = GetHandler(obj);
|
||||||
@ -1445,7 +1454,7 @@ static VALUE fetch_row(VALUE obj)
|
|||||||
return ary;
|
return ary;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* process_all_hashes (internal) */
|
/* process_all_hashes (internal helper) */
|
||||||
static VALUE process_all_hashes(VALUE obj, VALUE with_table, int build_array, int yield)
|
static VALUE process_all_hashes(VALUE obj, VALUE with_table, int build_array, int yield)
|
||||||
{
|
{
|
||||||
MYSQL_RES* res = GetMysqlRes(obj);
|
MYSQL_RES* res = GetMysqlRes(obj);
|
||||||
|
Loading…
Reference in New Issue
Block a user