Merge branch 'master' of git@github.com:oldmoe/mysqlplus
This commit is contained in:
commit
c695d4d842
1
README
1
README
@ -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
|
||||
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 :)
|
||||
Lourens Naude for 1.9 integration help.
|
||||
|
||||
=== License
|
||||
Ruby License, http://www.ruby-lang.org/en/LICENSE.txt.
|
||||
|
52
Rakefile
Normal file
52
Rakefile
Normal 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
|
12
ext/mysql.c
12
ext/mysql.c
@ -753,13 +753,17 @@ static VALUE query(VALUE obj, VALUE sql)
|
||||
static VALUE socket(VALUE obj)
|
||||
{
|
||||
MYSQL* m = GetHandler(obj);
|
||||
return INT2NUM(vio_fd(m->net.vio));
|
||||
return INT2NUM(m->net.fd);
|
||||
}
|
||||
|
||||
/* send_query */
|
||||
static VALUE send_query(VALUE obj, VALUE sql)
|
||||
/* send_query(sql,timeout=nil) */
|
||||
static VALUE send_query(int argc, VALUE* argv, VALUE obj)
|
||||
{
|
||||
MYSQL* m = GetHandler(obj);
|
||||
VALUE sql, timeout;
|
||||
|
||||
rb_scan_args(argc, argv, "11", &sql, &timeout);
|
||||
|
||||
Check_Type(sql, T_STRING);
|
||||
if (GetMysqlStruct(obj)->connection == Qfalse) {
|
||||
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, "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, "send_query", send_query, -1);
|
||||
rb_define_method(cMysql, "get_result", get_result, 0);
|
||||
rb_define_method(cMysql, "socket", socket, 0);
|
||||
rb_define_method(cMysql, "refresh", refresh, 1);
|
||||
|
@ -12,9 +12,12 @@ Gem::Specification.new do |s|
|
||||
s.files = [
|
||||
"mysqlplus.gemspec",
|
||||
"README",
|
||||
"Rakefile",
|
||||
"lib/mysqlplus.rb",
|
||||
"test/test_threaded.rb",
|
||||
"test/test_evented.rb",
|
||||
"test/test_helper.rb",
|
||||
"test/threaded_test.rb",
|
||||
"test/evented_test.rb",
|
||||
"ext/error_const.h",
|
||||
"ext/extconf.rb",
|
||||
"ext/mysql.c"
|
||||
]
|
||||
|
6
test/evented_test.rb
Normal file
6
test/evented_test.rb
Normal 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
|
@ -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
152
test/test_helper.rb
Normal 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
|
@ -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
6
test/threaded_test.rb
Normal 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
|
Loading…
Reference in New Issue
Block a user