merging in latest from master
This commit is contained in:
commit
6c4fd8a9ca
44
Rakefile
44
Rakefile
@ -1,49 +1,5 @@
|
|||||||
# encoding: UTF-8
|
# encoding: UTF-8
|
||||||
begin
|
|
||||||
require 'rubygems'
|
|
||||||
require 'jeweler'
|
|
||||||
JEWELER = Jeweler::Tasks.new do |gem|
|
|
||||||
gem.name = "mysql2"
|
|
||||||
gem.summary = "A simple, fast Mysql library for Ruby, binding to libmysql"
|
|
||||||
gem.email = "seniorlopez@gmail.com"
|
|
||||||
gem.homepage = "http://github.com/brianmario/mysql2"
|
|
||||||
gem.authors = ["Brian Lopez"]
|
|
||||||
gem.require_paths = ["lib", "ext"]
|
|
||||||
gem.extra_rdoc_files = `git ls-files *.rdoc`.split("\n")
|
|
||||||
gem.files = `git ls-files`.split("\n")
|
|
||||||
gem.extensions = ["ext/mysql2/extconf.rb"]
|
|
||||||
gem.files.include %w(lib/jeweler/templates/.document lib/jeweler/templates/.gitignore)
|
|
||||||
# gem.rubyforge_project = "mysql2"
|
|
||||||
end
|
|
||||||
rescue LoadError
|
|
||||||
puts "Jeweler, or one of its dependencies, is not available. Install it with: sudo gem install jeweler -s http://gems.github.com"
|
|
||||||
end
|
|
||||||
|
|
||||||
require 'rake'
|
require 'rake'
|
||||||
require 'spec/rake/spectask'
|
|
||||||
|
|
||||||
desc "Run all examples with RCov"
|
|
||||||
Spec::Rake::SpecTask.new('spec:rcov') do |t|
|
|
||||||
t.spec_files = FileList['spec/']
|
|
||||||
t.rcov = true
|
|
||||||
t.rcov_opts = lambda do
|
|
||||||
IO.readlines("spec/rcov.opts").map {|l| l.chomp.split " "}.flatten
|
|
||||||
end
|
|
||||||
end
|
|
||||||
Spec::Rake::SpecTask.new('spec') do |t|
|
|
||||||
t.spec_files = FileList['spec/']
|
|
||||||
t.spec_opts << '--options' << 'spec/spec.opts'
|
|
||||||
t.verbose = true
|
|
||||||
t.warning = true
|
|
||||||
end
|
|
||||||
|
|
||||||
Spec::Rake::SpecTask.new('spec:gdb') do |t|
|
|
||||||
t.spec_files = FileList['spec/']
|
|
||||||
t.spec_opts << '--options' << 'spec/spec.opts'
|
|
||||||
t.ruby_cmd = "gdb --args #{RUBY}"
|
|
||||||
end
|
|
||||||
|
|
||||||
task :default => :spec
|
|
||||||
|
|
||||||
# Load custom tasks
|
# Load custom tasks
|
||||||
Dir['tasks/*.rake'].sort.each { |f| load f }
|
Dir['tasks/*.rake'].sort.each { |f| load f }
|
||||||
|
@ -1,20 +0,0 @@
|
|||||||
# encoding: UTF-8
|
|
||||||
$LOAD_PATH.unshift File.expand_path(File.dirname(__FILE__) + '/../lib')
|
|
||||||
|
|
||||||
require 'rubygems'
|
|
||||||
require 'benchmark'
|
|
||||||
require 'mysql2'
|
|
||||||
|
|
||||||
iterations = 1000
|
|
||||||
client = Mysql2::Client.new(:host => "localhost", :username => "root", :database => "test")
|
|
||||||
query = lambda{ iterations.times{ client.query("SELECT mysql2_test.* FROM mysql2_test") } }
|
|
||||||
Benchmark.bmbm do |x|
|
|
||||||
x.report('select') do
|
|
||||||
query.call
|
|
||||||
end
|
|
||||||
x.report('rb_thread_select') do
|
|
||||||
thread = Thread.new{ sleep(10) }
|
|
||||||
query.call
|
|
||||||
thread.kill
|
|
||||||
end
|
|
||||||
end
|
|
@ -104,62 +104,56 @@ static VALUE nogvl_connect(void *ptr) {
|
|||||||
return client ? Qtrue : Qfalse;
|
return client ? Qtrue : Qfalse;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void rb_mysql_client_free(void * ptr) {
|
static VALUE nogvl_close(void *ptr) {
|
||||||
mysql_client_wrapper *wrapper = (mysql_client_wrapper *)ptr;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* we'll send a QUIT message to the server, but that message is more of a
|
|
||||||
* formality than a hard requirement since the socket is getting shutdown
|
|
||||||
* anyways, so ensure the socket write does not block our interpreter
|
|
||||||
*/
|
|
||||||
int fd = wrapper->client->net.fd;
|
|
||||||
|
|
||||||
if (fd >= 0) {
|
|
||||||
/*
|
|
||||||
* if the socket is dead we have no chance of blocking,
|
|
||||||
* so ignore any potential fcntl errors since they don't matter
|
|
||||||
*/
|
|
||||||
#ifndef _WIN32
|
|
||||||
int flags = fcntl(fd, F_GETFL);
|
|
||||||
if (flags > 0 && !(flags & O_NONBLOCK))
|
|
||||||
fcntl(fd, F_SETFL, flags | O_NONBLOCK);
|
|
||||||
#else
|
|
||||||
u_long iMode = 1;
|
|
||||||
ioctlsocket(fd, FIONBIO, &iMode);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
/* It's safe to call mysql_close() on an already closed connection. */
|
|
||||||
if (!wrapper->closed) {
|
|
||||||
mysql_close(wrapper->client);
|
|
||||||
if (!wrapper->freed) {
|
|
||||||
free(wrapper->client);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
xfree(ptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
static VALUE nogvl_close(void * ptr) {
|
|
||||||
mysql_client_wrapper *wrapper = ptr;
|
mysql_client_wrapper *wrapper = ptr;
|
||||||
if (!wrapper->closed) {
|
if (!wrapper->closed) {
|
||||||
wrapper->closed = 1;
|
wrapper->closed = 1;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* we'll send a QUIT message to the server, but that message is more of a
|
||||||
|
* formality than a hard requirement since the socket is getting shutdown
|
||||||
|
* anyways, so ensure the socket write does not block our interpreter
|
||||||
|
*/
|
||||||
|
int fd = wrapper->client->net.fd;
|
||||||
|
|
||||||
|
if (fd >= 0) {
|
||||||
|
/*
|
||||||
|
* if the socket is dead we have no chance of blocking,
|
||||||
|
* so ignore any potential fcntl errors since they don't matter
|
||||||
|
*/
|
||||||
|
#ifndef _WIN32
|
||||||
|
int flags = fcntl(fd, F_GETFL);
|
||||||
|
if (flags > 0 && !(flags & O_NONBLOCK))
|
||||||
|
fcntl(fd, F_SETFL, flags | O_NONBLOCK);
|
||||||
|
#else
|
||||||
|
u_long iMode = 1;
|
||||||
|
ioctlsocket(fd, FIONBIO, &iMode);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
mysql_close(wrapper->client);
|
mysql_close(wrapper->client);
|
||||||
wrapper->client->net.fd = -1;
|
wrapper->client->net.fd = -1;
|
||||||
if (!wrapper->freed) {
|
free(wrapper->client);
|
||||||
free(wrapper->client);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return Qnil;
|
return Qnil;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void rb_mysql_client_free(void * ptr) {
|
||||||
|
mysql_client_wrapper *wrapper = (mysql_client_wrapper *)ptr;
|
||||||
|
|
||||||
|
nogvl_close(wrapper);
|
||||||
|
|
||||||
|
xfree(ptr);
|
||||||
|
}
|
||||||
|
|
||||||
static VALUE allocate(VALUE klass) {
|
static VALUE allocate(VALUE klass) {
|
||||||
VALUE obj;
|
VALUE obj;
|
||||||
mysql_client_wrapper * wrapper;
|
mysql_client_wrapper * wrapper;
|
||||||
obj = Data_Make_Struct(klass, mysql_client_wrapper, rb_mysql_client_mark, rb_mysql_client_free, wrapper);
|
obj = Data_Make_Struct(klass, mysql_client_wrapper, rb_mysql_client_mark, rb_mysql_client_free, wrapper);
|
||||||
wrapper->encoding = Qnil;
|
wrapper->encoding = Qnil;
|
||||||
wrapper->active = 0;
|
wrapper->active = 0;
|
||||||
wrapper->closed = 0;
|
wrapper->closed = 1;
|
||||||
wrapper->freed = 0;
|
|
||||||
wrapper->client = (MYSQL*)malloc(sizeof(MYSQL));
|
wrapper->client = (MYSQL*)malloc(sizeof(MYSQL));
|
||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
@ -523,6 +517,7 @@ static VALUE init_connection(VALUE self) {
|
|||||||
return rb_raise_mysql2_error(wrapper->client);
|
return rb_raise_mysql2_error(wrapper->client);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
wrapper->closed = 0;
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -35,7 +35,6 @@ typedef struct {
|
|||||||
VALUE encoding;
|
VALUE encoding;
|
||||||
short int active;
|
short int active;
|
||||||
short int closed;
|
short int closed;
|
||||||
short int freed;
|
|
||||||
MYSQL *client;
|
MYSQL *client;
|
||||||
} mysql_client_wrapper;
|
} mysql_client_wrapper;
|
||||||
|
|
||||||
|
@ -1,45 +1,49 @@
|
|||||||
# encoding: UTF-8
|
# encoding: UTF-8
|
||||||
require 'spec_helper'
|
if defined? EventMachine
|
||||||
require 'mysql2/em'
|
require 'spec_helper'
|
||||||
|
require 'mysql2/em'
|
||||||
|
|
||||||
describe Mysql2::EM::Client do
|
describe Mysql2::EM::Client do
|
||||||
it "should support async queries" do
|
it "should support async queries" do
|
||||||
results = []
|
results = []
|
||||||
EM.run do
|
EM.run do
|
||||||
client1 = Mysql2::EM::Client.new
|
client1 = Mysql2::EM::Client.new
|
||||||
defer1 = client1.query "SELECT sleep(0.1) as first_query"
|
defer1 = client1.query "SELECT sleep(0.1) as first_query"
|
||||||
defer1.callback do |result|
|
defer1.callback do |result|
|
||||||
results << result.first
|
|
||||||
EM.stop_event_loop
|
|
||||||
end
|
|
||||||
|
|
||||||
client2 = Mysql2::EM::Client.new
|
|
||||||
defer2 = client2.query "SELECT sleep(0.025) second_query"
|
|
||||||
defer2.callback do |result|
|
|
||||||
results << result.first
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
results[0].keys.should include("second_query")
|
|
||||||
results[1].keys.should include("first_query")
|
|
||||||
end
|
|
||||||
|
|
||||||
it "should support queries in callbacks" do
|
|
||||||
results = []
|
|
||||||
EM.run do
|
|
||||||
client = Mysql2::EM::Client.new
|
|
||||||
defer1 = client.query "SELECT sleep(0.025) as first_query"
|
|
||||||
defer1.callback do |result|
|
|
||||||
results << result.first
|
|
||||||
defer2 = client.query "SELECT sleep(0.025) as second_query"
|
|
||||||
defer2.callback do |result|
|
|
||||||
results << result.first
|
results << result.first
|
||||||
EM.stop_event_loop
|
EM.stop_event_loop
|
||||||
end
|
end
|
||||||
|
|
||||||
|
client2 = Mysql2::EM::Client.new
|
||||||
|
defer2 = client2.query "SELECT sleep(0.025) second_query"
|
||||||
|
defer2.callback do |result|
|
||||||
|
results << result.first
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
results[0].keys.should include("second_query")
|
||||||
|
results[1].keys.should include("first_query")
|
||||||
end
|
end
|
||||||
|
|
||||||
results[0].keys.should include("first_query")
|
it "should support queries in callbacks" do
|
||||||
results[1].keys.should include("second_query")
|
results = []
|
||||||
|
EM.run do
|
||||||
|
client = Mysql2::EM::Client.new
|
||||||
|
defer1 = client.query "SELECT sleep(0.025) as first_query"
|
||||||
|
defer1.callback do |result|
|
||||||
|
results << result.first
|
||||||
|
defer2 = client.query "SELECT sleep(0.025) as second_query"
|
||||||
|
defer2.callback do |result|
|
||||||
|
results << result.first
|
||||||
|
EM.stop_event_loop
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
results[0].keys.should include("first_query")
|
||||||
|
results[1].keys.should include("second_query")
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
else
|
||||||
|
puts "EventMachine not installed, skipping the specs that use it"
|
||||||
|
end
|
@ -1,2 +0,0 @@
|
|||||||
--format specdoc
|
|
||||||
--colour
|
|
@ -1,10 +1,11 @@
|
|||||||
# encoding: UTF-8
|
# encoding: UTF-8
|
||||||
|
|
||||||
require 'rubygems'
|
$LOAD_PATH.unshift File.expand_path("../../lib", __FILE__)
|
||||||
|
require 'rspec'
|
||||||
require 'mysql2'
|
require 'mysql2'
|
||||||
require 'timeout'
|
require 'timeout'
|
||||||
|
|
||||||
Spec::Runner.configure do |config|
|
RSpec.configure do |config|
|
||||||
config.before(:all) do
|
config.before(:all) do
|
||||||
client = Mysql2::Client.new :database => 'test'
|
client = Mysql2::Client.new :database => 'test'
|
||||||
client.query %[
|
client.query %[
|
||||||
|
17
tasks/jeweler.rake
Normal file
17
tasks/jeweler.rake
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
begin
|
||||||
|
require 'jeweler'
|
||||||
|
JEWELER = Jeweler::Tasks.new do |gem|
|
||||||
|
gem.name = "mysql2"
|
||||||
|
gem.summary = "A simple, fast Mysql library for Ruby, binding to libmysql"
|
||||||
|
gem.email = "seniorlopez@gmail.com"
|
||||||
|
gem.homepage = "http://github.com/brianmario/mysql2"
|
||||||
|
gem.authors = ["Brian Lopez"]
|
||||||
|
gem.require_paths = ["lib", "ext"]
|
||||||
|
gem.extra_rdoc_files = `git ls-files *.rdoc`.split("\n")
|
||||||
|
gem.files = `git ls-files`.split("\n")
|
||||||
|
gem.extensions = ["ext/mysql2/extconf.rb"]
|
||||||
|
gem.files.include %w(lib/jeweler/templates/.document lib/jeweler/templates/.gitignore)
|
||||||
|
end
|
||||||
|
rescue LoadError
|
||||||
|
puts "jeweler, or one of its dependencies, is not available. Install it with: sudo gem install jeweler"
|
||||||
|
end
|
16
tasks/rspec.rake
Normal file
16
tasks/rspec.rake
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
begin
|
||||||
|
require 'rspec'
|
||||||
|
require 'rspec/core/rake_task'
|
||||||
|
|
||||||
|
desc "Run all examples with RCov"
|
||||||
|
RSpec::Core::RakeTask.new('spec:rcov') do |t|
|
||||||
|
t.rcov = true
|
||||||
|
end
|
||||||
|
RSpec::Core::RakeTask.new('spec') do |t|
|
||||||
|
t.verbose = true
|
||||||
|
end
|
||||||
|
|
||||||
|
task :default => :spec
|
||||||
|
rescue LoadError
|
||||||
|
puts "rspec, or one of its dependencies, is not available. Install it with: sudo gem install rspec"
|
||||||
|
end
|
Loading…
Reference in New Issue
Block a user