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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: c86a7be139488f4c7980f150cb2df8d998730c3a
4
- data.tar.gz: d90947e7b2e7bc90083bf7f63c93a00c56bfb661
3
+ metadata.gz: 5d8abd30d623ca6de6dc2bffdbda2a4a7b0bbbb5
4
+ data.tar.gz: 390239042496260846019bf0ee3ca7289b8c293c
5
5
  SHA512:
6
- metadata.gz: e15d257eab67513a552482f2b58eb86ad89a65f1dff1032d1b40a2108db393dc4f8fc0be8dee8c8f0a2f2c0045cb2d983bdac0a424cb7a40a0fd7cd2c6a7d154
7
- data.tar.gz: e15e5009dc2a940b3c547cfcb6bc817787d1d4b130c26f9510d3aa634c220efb5cfb41dedb95749bc95e6952c1806d8ceff6406c0a2cdbbb162f265147d445a5
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
- require 'mysql2'
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 --log-bin --log-slave-updates
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(Addrinfo.tcp("127.0.0.1", candidate))
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
- original_pid = $$
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
- trap("TERM") do
138
- Process.kill("KILL", mysql_pid) rescue nil
139
- cleanup!
140
- exit!
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, original_pid)
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
@@ -0,0 +1,8 @@
1
+ class MysqlIsolatedServer
2
+ module DBConnection
3
+ def connection
4
+ require 'mysql2'
5
+ @cx ||= Mysql2::Client.new(:host => "127.0.0.1", :port => @port, :username => "root", :password => "", :database => "mysql")
6
+ end
7
+ end
8
+ end
@@ -1,3 +1,3 @@
1
1
  class MysqlIsolatedServer
2
- VERSION = "0.2.2"
2
+ VERSION = "0.3.0"
3
3
  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.2.2
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-05-22 00:00:00.000000000 Z
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