diff --git a/ext/mysql.c b/ext/mysql.c index 79480f5..d9bb6fa 100644 --- a/ext/mysql.c +++ b/ext/mysql.c @@ -756,13 +756,32 @@ static VALUE socket(VALUE obj) return INT2NUM(m->net.fd); } -/* send_query(sql,timeout=nil) */ -static VALUE send_query(int argc, VALUE* argv, VALUE obj) +/* readable(timeout=nil) */ +static VALUE readable( int argc, VALUE* argv, VALUE obj ) { MYSQL* m = GetHandler(obj); - VALUE sql, timeout; - rb_scan_args(argc, argv, "11", &sql, &timeout); + VALUE timeout; + + rb_scan_args(argc, argv, "01", &timeout); + + if ( NIL_P( timeout ) ){ + timeout = m->net.read_timeout; + } + + if( vio_poll_read( m->net.vio, INT2NUM(timeout) ) == 0 ){ + rb_warn( "Socket readable" ); + return Qtrue; + }else{ + rb_warn( "Socket not readable" ); + return Qfalse; + } +} + +/* send_query(sql) */ +static VALUE send_query(VALUE obj, VALUE sql) +{ + MYSQL* m = GetHandler(obj); Check_Type(sql, T_STRING); if (GetMysqlStruct(obj)->connection == Qfalse) { @@ -789,17 +808,17 @@ static VALUE get_result(VALUE obj) return store_result(obj); } -/* async_query */ -/* -comment it out until I figure out how it works -static VALUE async_query(VALUE obj, VALUE sql) +/* async_query(sql,timeout=nil) */ +static VALUE async_query(int argc, VALUE* argv, VALUE obj) { + VALUE sql, timeout; + + rb_scan_args(argc, argv, "11", &sql, &timeout); + send_query(obj,sql); rb_io_wait_readable(socket(obj)); return get_result(obj); } -*/ - #if MYSQL_VERSION_ID >= 40100 /* server_version() */ @@ -2090,9 +2109,10 @@ void Init_mysql(void) #endif rb_define_method(cMysql, "query", query, 1); rb_define_method(cMysql, "real_query", query, 1); - /*rb_define_method(cMysql, "async_query", async_query, 1);*/ - rb_define_method(cMysql, "send_query", send_query, -1); + rb_define_method(cMysql, "async_query", async_query, -1); + rb_define_method(cMysql, "send_query", send_query, 1); rb_define_method(cMysql, "get_result", get_result, 0); + rb_define_method(cMysql, "readable?", readable, -1); rb_define_method(cMysql, "socket", socket, 0); rb_define_method(cMysql, "refresh", refresh, 1); rb_define_method(cMysql, "reload", reload, 0); diff --git a/lib/mysqlplus.rb b/lib/mysqlplus.rb index 474eeb3..66a4b83 100644 --- a/lib/mysqlplus.rb +++ b/lib/mysqlplus.rb @@ -1,11 +1,15 @@ require 'mysql' class Mysql - def async_query(sql) + alias_method :c_async_query, :async_query + + def async_query(sql, timeout = nil) + c_async_query(sql, timeout) if ENV['MYSQL_C_ASYNC_QUERY'] == '1' send_query(sql) select [ (@sockets ||= {})[socket] ||= IO.new(socket) ], nil, nil, nil get_result end + end class Mysql::Result diff --git a/test/evented_test.rb b/test/evented_test.rb index ec8ad3d..c2a89e1 100644 --- a/test/evented_test.rb +++ b/test/evented_test.rb @@ -1,6 +1,12 @@ require File.dirname(__FILE__) + '/test_helper' EventedMysqlTest.new( 10 ) do |test| - test.setup{ Mysql.real_connect('localhost','root') } + test.setup{ Mysql.real_connect('localhost','root','3421260') } + test.run! +end + +EventedMysqlTest.new( 10 ) do |test| + test.setup{ Mysql.real_connect('localhost','root','3421260') } + test.c_async_query = true test.run! end \ No newline at end of file diff --git a/test/test_helper.rb b/test/test_helper.rb index 3f5078c..3466411 100644 --- a/test/test_helper.rb +++ b/test/test_helper.rb @@ -10,11 +10,13 @@ class MysqlTest :connections, :connection_signature, :start, - :done + :done, + :c_async_query def initialize( queries ) @queries = queries @done = [] + @c_async_query = false yield self if block_given? end @@ -24,7 +26,10 @@ class MysqlTest end def run! - raise NotImplemented + c_or_native_ruby_async_query do + prepare + yield + end end def prepare @@ -49,6 +54,19 @@ class MysqlTest Time.now - @start end + protected + + def c_or_native_ruby_async_query + if @c_async_query + ENV['MYSQL_C_ASYNC_QUERY'] = '1' + log "** using C based async_query" + else + ENV['MYSQL_C_ASYNC_QUERY'] = '0' + log "** using native Ruby async_query" + end + yield + end + end class EventedMysqlTest < MysqlTest @@ -73,18 +91,22 @@ class EventedMysqlTest < MysqlTest end def run! - prepare - - loop do - result = select( @sockets,nil,nil,nil ) - if result - result.first.each do |conn| - @connections[conn].get_result.each{|res| log( "Result for socket #{conn.fileno} : #{res}" ) } - @done << nil - teardown if done? - end + super do + catch :END_EVENT_LOOP do + loop do + result = select( @sockets,nil,nil,nil ) + if result + result.first.each do |conn| + @connections[conn].get_result.each{|res| log( "Result for socket #{conn.fileno} : #{res}" ) } + @done << nil + if done? + teardown + end + end + end + end end - end + end end def prepare @@ -95,7 +117,7 @@ class EventedMysqlTest < MysqlTest def teardown log "done" - exit + throw :END_EVENT_LOOP end protected @@ -126,11 +148,11 @@ class ThreadedMysqlTest < MysqlTest end def run! - prepare - - with_logging "waiting on threads" do - @threads.each{|t| t.join } - end + super do + with_logging "waiting on threads" do + @threads.each{|t| t.join } + end + end end def prepare diff --git a/test/threaded_test.rb b/test/threaded_test.rb index 7a18a26..0db4682 100644 --- a/test/threaded_test.rb +++ b/test/threaded_test.rb @@ -1,6 +1,12 @@ require File.dirname(__FILE__) + '/test_helper' ThreadedMysqlTest.new( 10 ) do |test| - test.setup{ Mysql.real_connect('localhost','root') } + test.setup{ Mysql.real_connect('localhost','root','3421260') } + test.run! +end + +ThreadedMysqlTest.new( 10 ) do |test| + test.setup{ Mysql.real_connect('localhost','root','3421260') } + test.c_async_query = true test.run! end \ No newline at end of file