Merge branch 'master' of git@github.com:oldmoe/mysqlplus

This commit is contained in:
oldmoe 2008-09-06 03:59:41 +02:00
commit c695d4d842
9 changed files with 230 additions and 67 deletions

1
README
View File

@ -26,6 +26,7 @@ An enhanced MySQL database driver. With support for async operations and threade
Aman Gupta, for help in threading support and improved tests Aman Gupta, for help in threading support and improved tests
Tomita Masahiro--since this is a fork of his already excellent mysql lib [http://www.tmtm.org/en/mysql/ruby]. Tomita Masahiro--since this is a fork of his already excellent mysql lib [http://www.tmtm.org/en/mysql/ruby].
Roger Pack, for helping in the file descriptor hunt :) Roger Pack, for helping in the file descriptor hunt :)
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.

52
Rakefile Normal file
View File

@ -0,0 +1,52 @@
require 'rake'
require 'rake/testtask'
desc 'Default: build and install.'
task :default => :build
desc 'Run performance tests.'
Rake::TestTask.new(:test) do |t|
t.libs = [] #reference the installed gem instead
t.pattern = 'test/*_test.rb'
t.verbose = true
end
task :build do |t|
configure
install
end
def configure
puts "** building gem"
puts %x{gem build mysqlplus.gemspec}
end
def install
puts "** installing gem"
_mysql_config = mysql_config
puts "** using mysql_config: #{_mysql_config}"
puts %x{sudo gem install mysqlplus-#{version}.gem -- --with-mysql-config=#{_mysql_config}}
end
def gem_spec
@gem_spec ||= eval( IO.read( 'mysqlplus.gemspec') )
end
def version
gem_spec.version.to_s
end
def mysql_configs
%w(mysql_config mysql_config5)
end
def mysql_config
mysql_configs.each do |config|
path = mysql_config!( config )
return path unless path.empty?
end
end
def mysql_config!( config )
%x{which #{config}}
end

View File

@ -753,13 +753,17 @@ static VALUE query(VALUE obj, VALUE sql)
static VALUE socket(VALUE obj) static VALUE socket(VALUE obj)
{ {
MYSQL* m = GetHandler(obj); MYSQL* m = GetHandler(obj);
return INT2NUM(vio_fd(m->net.vio)); return INT2NUM(m->net.fd);
} }
/* send_query */ /* send_query(sql,timeout=nil) */
static VALUE send_query(VALUE obj, VALUE sql) static VALUE send_query(int argc, VALUE* argv, VALUE obj)
{ {
MYSQL* m = GetHandler(obj); MYSQL* m = GetHandler(obj);
VALUE sql, timeout;
rb_scan_args(argc, argv, "11", &sql, &timeout);
Check_Type(sql, T_STRING); Check_Type(sql, T_STRING);
if (GetMysqlStruct(obj)->connection == Qfalse) { if (GetMysqlStruct(obj)->connection == Qfalse) {
rb_raise(eMysql, "query: not connected"); rb_raise(eMysql, "query: not connected");
@ -2087,7 +2091,7 @@ void Init_mysql(void)
rb_define_method(cMysql, "query", query, 1); rb_define_method(cMysql, "query", query, 1);
rb_define_method(cMysql, "real_query", query, 1); rb_define_method(cMysql, "real_query", query, 1);
/*rb_define_method(cMysql, "async_query", async_query, 1);*/ /*rb_define_method(cMysql, "async_query", async_query, 1);*/
rb_define_method(cMysql, "send_query", send_query, 1); rb_define_method(cMysql, "send_query", send_query, -1);
rb_define_method(cMysql, "get_result", get_result, 0); rb_define_method(cMysql, "get_result", get_result, 0);
rb_define_method(cMysql, "socket", socket, 0); rb_define_method(cMysql, "socket", socket, 0);
rb_define_method(cMysql, "refresh", refresh, 1); rb_define_method(cMysql, "refresh", refresh, 1);

View File

@ -12,9 +12,12 @@ Gem::Specification.new do |s|
s.files = [ s.files = [
"mysqlplus.gemspec", "mysqlplus.gemspec",
"README", "README",
"Rakefile",
"lib/mysqlplus.rb", "lib/mysqlplus.rb",
"test/test_threaded.rb", "test/test_helper.rb",
"test/test_evented.rb", "test/threaded_test.rb",
"test/evented_test.rb",
"ext/error_const.h",
"ext/extconf.rb", "ext/extconf.rb",
"ext/mysql.c" "ext/mysql.c"
] ]

6
test/evented_test.rb Normal file
View File

@ -0,0 +1,6 @@
require File.dirname(__FILE__) + '/test_helper'
EventedMysqlTest.new( 10 ) do |test|
test.setup{ Mysql.real_connect('localhost','root') }
test.run!
end

View File

@ -1,31 +0,0 @@
require 'mysqlplus'
@count = 10
@connections = {}
@count.times do
c = Mysql.real_connect('localhost','root',nil)
@connections[IO.new(c.socket)] = c
end
@sockets = @connections.keys
@done = 0
@t = Time.now
@connections.each_value do |c|
c.send_query('select sleep(1)')
end
loop do
res = select(@sockets,nil,nil,nil)
if res
res.first.each do |c|
@connections[c].get_result.each{|r| p r}
@done = @done + 1
if @done == @count
puts Time.now - @t
exit
end
end
end
end

152
test/test_helper.rb Normal file
View File

@ -0,0 +1,152 @@
require 'rubygems'
require 'mysqlplus'
class MysqlTest
class NotImplemented < StandardError
end
attr_accessor :queries,
:connections,
:connection_signature,
:start,
:done
def initialize( queries )
@queries = queries
@done = []
yield self if block_given?
end
def setup( &block )
@start = Time.now
@connection_signature = block
end
def run!
raise NotImplemented
end
def prepare
raise NotImplemented
end
def teardown
raise NotImplemented
end
def log( message, prefix = '' )
puts "[#{timestamp}] #{prefix} #{message}"
end
def with_logging( message )
log( message, 'Start' )
yield
log( message, 'End' )
end
def timestamp
Time.now - @start
end
end
class EventedMysqlTest < MysqlTest
attr_accessor :sockets
def initialize( queries )
@sockets = []
@connections = {}
super( queries )
end
def setup( &block )
super( &block )
with_logging 'Setup connection pool' do
@queries.times do
connection = @connection_signature.call
@connections[ IO.new(connection.socket) ] = connection
@sockets = @connections.keys
end
end
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
end
end
end
def prepare
@connections.each_value do |conn|
conn.send_query( "select sleep(3)" )
end
end
def teardown
log "done"
exit
end
protected
def done?
@done.size == @queries
end
end
class ThreadedMysqlTest < MysqlTest
attr_accessor :threads
def initialize( queries )
@connections = []
@threads = []
super( queries )
end
def setup( &block )
super( &block )
with_logging "Setup connection pool" do
@queries.times do
@connections << @connection_signature.call
end
end
end
def run!
prepare
with_logging "waiting on threads" do
@threads.each{|t| t.join }
end
end
def prepare
with_logging "prepare" do
@queries.times do |conn|
@threads << Thread.new do
log "sending query on connection #{conn}"
@connections[conn].async_query( "select sleep(3)" ).each do |result|
log "connection #{conn} done"
end
end
end
end
end
end

View File

@ -1,30 +0,0 @@
require 'mysqlplus'
$count = 10
$start = Time.now
$connections = []
$count.times do
$connections << Mysql.real_connect('localhost','root')
end
puts 'connection pool ready'
$threads = []
$count.times do |i|
$threads << Thread.new do
puts "sending query on connection #{i}"
$connections[i].async_query("select sleep(3)").each{ |r|
puts "connection #{i} done"
}
end
end
puts 'waiting on threads'
$threads.each{|t| t.join }
puts Time.now - $start

6
test/threaded_test.rb Normal file
View File

@ -0,0 +1,6 @@
require File.dirname(__FILE__) + '/test_helper'
ThreadedMysqlTest.new( 10 ) do |test|
test.setup{ Mysql.real_connect('localhost','root') }
test.run!
end