mysql_isolated_server 0.2.2 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/bin/boot_isolated_server +30 -0
- data/lib/mysql_isolated_server.rb +60 -14
- data/lib/mysql_isolated_server/jdbc_connection.rb +49 -0
- data/lib/mysql_isolated_server/mysql2_connection.rb +8 -0
- data/lib/mysql_isolated_server/version.rb +1 -1
- data/mysql_isolated_server.gemspec +0 -1
- metadata +8 -18
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5d8abd30d623ca6de6dc2bffdbda2a4a7b0bbbb5
|
4
|
+
data.tar.gz: 390239042496260846019bf0ee3ca7289b8c293c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 14b04cc5b22b42c6b9020a3d991483871a67b19e4339ae71762e278e751352432080afce395f722ebbb639edd19f55c93d8dae7e18d5a2ff7de3bd11f6963aef
|
7
|
+
data.tar.gz: dc810674507fa907e24595314a238a150e7c05906c2d1a5d2b684e0c415170bf400f73d9df927ad948a81c43330962c1928db7b44f3e8330d4b2b2b59b15560e
|
@@ -0,0 +1,30 @@
|
|
1
|
+
#!/usr/bin/ruby
|
2
|
+
require 'rubygems'
|
3
|
+
$LOAD_PATH << File.dirname(__FILE__) + "/../lib"
|
4
|
+
require 'mysql_isolated_server'
|
5
|
+
require 'getoptlong'
|
6
|
+
|
7
|
+
$stderr.puts ENV.inspect
|
8
|
+
opts = GetoptLong.new(
|
9
|
+
[ '--log-bin', GetoptLong::REQUIRED_ARGUMENT ],
|
10
|
+
[ '--pid', GetoptLong::REQUIRED_ARGUMENT ]
|
11
|
+
)
|
12
|
+
|
13
|
+
options = {}
|
14
|
+
opts.each do |opt, arg|
|
15
|
+
case opt
|
16
|
+
when '--log-bin'
|
17
|
+
options[:log_bin] = arg
|
18
|
+
when '--pid'
|
19
|
+
options[:pid] = arg.to_i
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
options[:params] = ARGV.join(' ')
|
24
|
+
|
25
|
+
mysql_isolated_server = MysqlIsolatedServer.new(options)
|
26
|
+
mysql_isolated_server.boot!
|
27
|
+
|
28
|
+
puts "dir: " + mysql_isolated_server.base
|
29
|
+
puts "port: " + mysql_isolated_server.port.to_s
|
30
|
+
STDOUT.flush
|
@@ -1,23 +1,56 @@
|
|
1
1
|
require 'tmpdir'
|
2
2
|
require 'socket'
|
3
|
-
|
3
|
+
|
4
|
+
if RUBY_PLATFORM == "java"
|
5
|
+
require 'mysql_isolated_server/jdbc_connection'
|
6
|
+
else
|
7
|
+
require 'mysql_isolated_server/mysql2_connection'
|
8
|
+
end
|
4
9
|
|
5
10
|
class MysqlIsolatedServer
|
11
|
+
include DBConnection
|
6
12
|
attr_reader :pid, :base, :port
|
7
13
|
attr_accessor :params
|
8
14
|
MYSQL_BASE_DIR="/usr"
|
9
15
|
|
10
16
|
def initialize(options = {})
|
11
|
-
@base = Dir.mktmpdir("mysql_isolated", "/tmp")
|
17
|
+
@base = options[:base] || Dir.mktmpdir("mysql_isolated", "/tmp")
|
12
18
|
@mysql_data_dir="#{@base}/mysqld"
|
13
19
|
@mysql_socket="#{@mysql_data_dir}/mysqld.sock"
|
14
20
|
@params = options[:params]
|
15
21
|
@load_data_path = options[:data_path]
|
16
22
|
@port = options[:port]
|
17
23
|
@allow_output = options[:allow_output]
|
24
|
+
@log_bin = options[:log_bin] || "--log-bin"
|
25
|
+
@parent_pid = options[:pid]
|
18
26
|
@server_id = rand(2**31)
|
19
27
|
end
|
20
28
|
|
29
|
+
def self.thread_boot(*params)
|
30
|
+
bin = File.dirname(__FILE__) + "/../bin/boot_isolated_server"
|
31
|
+
mysql_dir, mysql_port = nil, nil
|
32
|
+
restore_env = {}
|
33
|
+
|
34
|
+
Thread.abort_on_exception = true
|
35
|
+
Thread.new do
|
36
|
+
ENV.keys.grep(/GEM|BUNDLE|RUBYOPT/).each do |k|
|
37
|
+
restore_env[k] = ENV.delete(k)
|
38
|
+
end
|
39
|
+
params = ["--pid", $$.to_s] + params
|
40
|
+
|
41
|
+
pipe = IO.popen(["#{bin}"].concat(params), "r") do |pipe|
|
42
|
+
mysql_dir = pipe.readline.split(' ').last
|
43
|
+
mysql_port = pipe.readline.split(' ').last.to_i
|
44
|
+
sleep
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
while mysql_port.nil?
|
49
|
+
sleep 1
|
50
|
+
end
|
51
|
+
new(:port => mysql_port, :base => mysql_dir)
|
52
|
+
end
|
53
|
+
|
21
54
|
def make_slave_of(master)
|
22
55
|
master_binlog_info = master.connection.query("show master status").first
|
23
56
|
connection.query(<<-EOL
|
@@ -32,10 +65,6 @@ class MysqlIsolatedServer
|
|
32
65
|
connection.query("SET GLOBAL READ_ONLY=1")
|
33
66
|
end
|
34
67
|
|
35
|
-
def connection
|
36
|
-
@cx ||= Mysql2::Client.new(:host => "127.0.0.1", :port => @port, :username => "root", :password => "", :database => "mysql")
|
37
|
-
end
|
38
|
-
|
39
68
|
def set_rw(rw)
|
40
69
|
ro = rw ? 0 : 1
|
41
70
|
connection.query("SET GLOBAL READ_ONLY=#{ro}")
|
@@ -54,7 +83,7 @@ class MysqlIsolatedServer
|
|
54
83
|
exec_server <<-EOL
|
55
84
|
#{mysqld} --no-defaults --default-storage-engine=innodb \
|
56
85
|
--datadir=#{@mysql_data_dir} --pid-file=#{@base}/mysqld.pid --port=#{@port} \
|
57
|
-
#{@params} --socket=#{@mysql_data_dir}/mysql.sock
|
86
|
+
#{@params} --socket=#{@mysql_data_dir}/mysql.sock #{@log_bin} --log-slave-updates
|
58
87
|
EOL
|
59
88
|
|
60
89
|
while !system("mysql -h127.0.0.1 --port=#{@port} --database=mysql -u root -e 'select 1' >/dev/null 2>&1")
|
@@ -85,6 +114,19 @@ class MysqlIsolatedServer
|
|
85
114
|
system("cp #{File.expand_path(File.dirname(__FILE__))}/tables/user.* #{@mysql_data_dir}/mysql")
|
86
115
|
end
|
87
116
|
|
117
|
+
if !@log_bin
|
118
|
+
@log_bin = "--log-bin"
|
119
|
+
else
|
120
|
+
if @log_bin[0] != '/'
|
121
|
+
binlog_dir = "#{@mysql_data_dir}/#{@log_bin}"
|
122
|
+
else
|
123
|
+
binlog_dir = @log_bin
|
124
|
+
end
|
125
|
+
|
126
|
+
system("mkdir -p #{binlog_dir}")
|
127
|
+
@log_bin = "--log-bin=#{binlog_dir}"
|
128
|
+
end
|
129
|
+
|
88
130
|
up!
|
89
131
|
|
90
132
|
tzinfo_to_sql = locate_executable("mysql_tzinfo_to_sql5", "mysql_tzinfo_to_sql")
|
@@ -100,7 +142,7 @@ class MysqlIsolatedServer
|
|
100
142
|
|
101
143
|
begin
|
102
144
|
socket = Socket.new(:INET, :STREAM, 0)
|
103
|
-
socket.bind(
|
145
|
+
socket.bind(Socket.pack_sockaddr_in(candidate, '127.0.0.1'))
|
104
146
|
socket.close
|
105
147
|
return candidate
|
106
148
|
rescue Exception => e
|
@@ -117,9 +159,10 @@ class MysqlIsolatedServer
|
|
117
159
|
system("mkdir -p #{base}/tmp")
|
118
160
|
system("chmod 0777 #{base}/tmp")
|
119
161
|
|
120
|
-
|
162
|
+
parent_pid = @parent_pid || $$
|
121
163
|
mysql_pid = nil
|
122
164
|
|
165
|
+
$stderr.puts cmd
|
123
166
|
middle_pid = fork do
|
124
167
|
mysql_pid = fork do
|
125
168
|
ENV["TMPDIR"] = "#{base}/tmp"
|
@@ -134,15 +177,18 @@ class MysqlIsolatedServer
|
|
134
177
|
# begin waiting for the parent (or mysql) to die; at_exit is hard to control when interacting with test/unit
|
135
178
|
# we can also be killed by our parent with down! and up!
|
136
179
|
#
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
180
|
+
["TERM", "INT"].each do |sig|
|
181
|
+
trap(sig) do
|
182
|
+
Process.kill("KILL", mysql_pid) rescue nil
|
183
|
+
cleanup!
|
184
|
+
exit!
|
185
|
+
end
|
141
186
|
end
|
142
187
|
|
188
|
+
|
143
189
|
while true
|
144
190
|
begin
|
145
|
-
Process.kill(0,
|
191
|
+
Process.kill(0, parent_pid)
|
146
192
|
Process.kill(0, mysql_pid)
|
147
193
|
rescue Exception => e
|
148
194
|
Process.kill("KILL", mysql_pid) rescue nil
|
@@ -0,0 +1,49 @@
|
|
1
|
+
require "java"
|
2
|
+
java_import "java.sql.DriverManager"
|
3
|
+
java_import "org.apache.commons.lang.StringEscapeUtils"
|
4
|
+
|
5
|
+
class MysqlIsolatedServer
|
6
|
+
class WrappedJDBCConnection
|
7
|
+
def initialize(port)
|
8
|
+
@cx ||= DriverManager.get_connection("jdbc:mysql://127.0.0.1:#{port}/mysql", "root", "")
|
9
|
+
end
|
10
|
+
|
11
|
+
def query(sql)
|
12
|
+
stmt = @cx.create_statement
|
13
|
+
if sql !~ /^select/i && sql !~ /^show/i
|
14
|
+
return stmt.execute(sql)
|
15
|
+
end
|
16
|
+
|
17
|
+
rs = stmt.execute_query(sql)
|
18
|
+
while (rs.next)
|
19
|
+
rows = []
|
20
|
+
meta_data = rs.get_meta_data
|
21
|
+
num_cols = meta_data.get_column_count
|
22
|
+
|
23
|
+
row = {}
|
24
|
+
1.upto(num_cols) do |col|
|
25
|
+
col_name = meta_data.get_column_label(col)
|
26
|
+
col_value = rs.get_object(col) # of meta_data.get_column_type(col)
|
27
|
+
|
28
|
+
row[col_name] = col_value if col_value # skip if nil
|
29
|
+
end
|
30
|
+
|
31
|
+
rows << row
|
32
|
+
end
|
33
|
+
rows
|
34
|
+
ensure
|
35
|
+
stmt.close if stmt
|
36
|
+
rs.close if rs
|
37
|
+
end
|
38
|
+
|
39
|
+
def escape(str)
|
40
|
+
StringEscapeUtils.escapeSql(str)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
module DBConnection
|
45
|
+
def connection
|
46
|
+
@connection ||= WrappedJDBCConnection.new(@port)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -15,6 +15,5 @@ Gem::Specification.new do |gem|
|
|
15
15
|
gem.files = `git ls-files`.split($/)
|
16
16
|
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
17
17
|
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
18
|
-
gem.add_dependency "mysql2"
|
19
18
|
gem.require_paths = ["lib"]
|
20
19
|
end
|
metadata
CHANGED
@@ -1,34 +1,21 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: mysql_isolated_server
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ben Osheroff
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-
|
12
|
-
dependencies:
|
13
|
-
- !ruby/object:Gem::Dependency
|
14
|
-
name: mysql2
|
15
|
-
requirement: !ruby/object:Gem::Requirement
|
16
|
-
requirements:
|
17
|
-
- - ">="
|
18
|
-
- !ruby/object:Gem::Version
|
19
|
-
version: '0'
|
20
|
-
type: :runtime
|
21
|
-
prerelease: false
|
22
|
-
version_requirements: !ruby/object:Gem::Requirement
|
23
|
-
requirements:
|
24
|
-
- - ">="
|
25
|
-
- !ruby/object:Gem::Version
|
26
|
-
version: '0'
|
11
|
+
date: 2014-06-16 00:00:00.000000000 Z
|
12
|
+
dependencies: []
|
27
13
|
description: A small library that allows you to easily spin up new local mysql servers
|
28
14
|
for testing purposes.
|
29
15
|
email:
|
30
16
|
- ben@zendesk.com
|
31
|
-
executables:
|
17
|
+
executables:
|
18
|
+
- boot_isolated_server
|
32
19
|
extensions: []
|
33
20
|
extra_rdoc_files: []
|
34
21
|
files:
|
@@ -37,7 +24,10 @@ files:
|
|
37
24
|
- LICENSE.txt
|
38
25
|
- README.md
|
39
26
|
- Rakefile
|
27
|
+
- bin/boot_isolated_server
|
40
28
|
- lib/mysql_isolated_server.rb
|
29
|
+
- lib/mysql_isolated_server/jdbc_connection.rb
|
30
|
+
- lib/mysql_isolated_server/mysql2_connection.rb
|
41
31
|
- lib/mysql_isolated_server/version.rb
|
42
32
|
- lib/tables/user.MYD
|
43
33
|
- lib/tables/user.MYI
|