flydata 0.3.5 → 0.3.6

Sign up to get free protection for your applications and to get access to all the features.
Files changed (68) hide show
  1. checksums.yaml +4 -4
  2. data/VERSION +1 -1
  3. data/bin/flydata +1 -0
  4. data/flydata-core/lib/flydata-core/core_ext/module.rb +1 -1
  5. data/flydata-core/lib/flydata-core/core_ext/object.rb +1 -1
  6. data/flydata.gemspec +21 -5
  7. data/lib/flydata.rb +5 -8
  8. data/lib/flydata/api/data_entry.rb +2 -0
  9. data/lib/flydata/api/data_port.rb +2 -0
  10. data/lib/flydata/api/redshift_cluster.rb +2 -0
  11. data/lib/flydata/api_client.rb +3 -0
  12. data/lib/flydata/cli.rb +13 -2
  13. data/lib/flydata/command/base.rb +6 -0
  14. data/lib/flydata/command/conf.rb +3 -0
  15. data/lib/flydata/command/crontab.rb +3 -0
  16. data/lib/flydata/command/encrypt.rb +3 -0
  17. data/lib/flydata/command/kill_all.rb +3 -0
  18. data/lib/flydata/command/login.rb +2 -0
  19. data/lib/flydata/command/restart.rb +3 -0
  20. data/lib/flydata/command/routine.rb +3 -0
  21. data/lib/flydata/command/sender.rb +2 -0
  22. data/lib/flydata/command/setlogdel.rb +4 -1
  23. data/lib/flydata/command/setup.rb +7 -2
  24. data/lib/flydata/command/start.rb +3 -0
  25. data/lib/flydata/command/status.rb +3 -0
  26. data/lib/flydata/command/stop.rb +3 -0
  27. data/lib/flydata/command/sync.rb +10 -3
  28. data/lib/flydata/command/version.rb +2 -0
  29. data/lib/flydata/{command_logger.rb → command_loggable.rb} +0 -0
  30. data/lib/flydata/compatibility_check.rb +1 -1
  31. data/lib/flydata/credentials.rb +2 -0
  32. data/lib/flydata/fluent-plugins/in_mysql_binlog_flydata.rb +8 -9
  33. data/lib/flydata/fluent-plugins/mysql/alter_table_query_handler.rb +1 -1
  34. data/lib/flydata/fluent-plugins/mysql/binlog_query_dispatcher.rb +1 -1
  35. data/lib/flydata/fluent-plugins/mysql/binlog_query_handler.rb +1 -1
  36. data/lib/flydata/fluent-plugins/mysql/binlog_record_dispatcher.rb +2 -2
  37. data/lib/flydata/fluent-plugins/mysql/binlog_record_handler.rb +1 -1
  38. data/lib/flydata/fluent-plugins/mysql/ddl_query_handler.rb +1 -1
  39. data/lib/flydata/fluent-plugins/mysql/dml_record_handler.rb +1 -1
  40. data/lib/flydata/helpers.rb +0 -10
  41. data/lib/flydata/heroku.rb +3 -0
  42. data/lib/flydata/output/forwarder.rb +1 -1
  43. data/lib/flydata/parser/mysql/dump_parser.rb +29 -31
  44. data/lib/flydata/sync_file_manager.rb +230 -232
  45. data/spec/fly_data_model_spec.rb +1 -0
  46. data/spec/flydata/api/data_entry_spec.rb +1 -0
  47. data/spec/flydata/api_client_spec.rb +18 -0
  48. data/spec/flydata/cli_spec.rb +1 -0
  49. data/spec/flydata/command/base_spec.rb +44 -0
  50. data/spec/flydata/command/conf_spec.rb +21 -0
  51. data/spec/flydata/command/crontab_spec.rb +17 -0
  52. data/spec/flydata/command/encrypt_spec.rb +28 -0
  53. data/spec/flydata/command/kill_all_spec.rb +17 -0
  54. data/spec/flydata/command/login_spec.rb +21 -0
  55. data/spec/flydata/command/restart_spec.rb +17 -0
  56. data/spec/flydata/command/routine_spec.rb +29 -0
  57. data/spec/flydata/command/sender_spec.rb +7 -2
  58. data/spec/flydata/command/setlogdel_spec.rb +18 -0
  59. data/spec/flydata/command/setup_spec.rb +44 -0
  60. data/spec/flydata/command/start_spec.rb +17 -0
  61. data/spec/flydata/command/status_spec.rb +17 -0
  62. data/spec/flydata/command/stop_spec.rb +17 -0
  63. data/spec/flydata/command/sync_spec.rb +1 -0
  64. data/spec/flydata/command/version_spec.rb +14 -0
  65. data/spec/flydata/fluent-plugins/in_mysql_binlog_flydata_spec.rb +1 -1
  66. data/spec/flydata/parser/mysql/dump_parser_spec.rb +23 -73
  67. data/spec/flydata/sync_file_manager_spec.rb +150 -152
  68. metadata +19 -4
@@ -1,5 +1,5 @@
1
1
  require 'flydata/parser_provider'
2
- require_relative 'ddl_query_handler'
2
+ require 'flydata/fluent-plugins/mysql/ddl_query_handler'
3
3
 
4
4
  module Mysql
5
5
  class AlterTableQueryHandler < DdlQueryHandler
@@ -1,4 +1,4 @@
1
- require_relative 'alter_table_query_handler'
1
+ require 'flydata/fluent-plugins/mysql/alter_table_query_handler'
2
2
 
3
3
  module Mysql
4
4
  class BinlogQueryDispatcher
@@ -1,4 +1,4 @@
1
- require_relative 'binlog_record_handler'
1
+ require 'flydata/fluent-plugins/mysql/binlog_record_handler'
2
2
 
3
3
  module Mysql
4
4
  class BinlogQueryHandler < BinlogRecordHandler
@@ -1,7 +1,7 @@
1
1
  require 'fluent/plugin/in_mysql_binlog'
2
2
  require 'binlog'
3
- require_relative 'dml_record_handler'
4
- require_relative 'binlog_query_dispatcher'
3
+ require 'flydata/fluent-plugins/mysql/dml_record_handler'
4
+ require 'flydata/fluent-plugins/mysql/binlog_query_dispatcher'
5
5
 
6
6
  module Mysql
7
7
  class BinlogRecordDispatcher
@@ -1,6 +1,6 @@
1
1
  require 'fluent/plugin/in_mysql_binlog'
2
2
  require 'binlog'
3
- require_relative 'binlog_position'
3
+ require 'flydata/fluent-plugins/mysql/binlog_position'
4
4
 
5
5
  module Mysql
6
6
  class BinlogRecordHandler
@@ -1,4 +1,4 @@
1
- require_relative 'binlog_query_handler'
1
+ require 'flydata/fluent-plugins/mysql/binlog_query_handler'
2
2
 
3
3
  module Mysql
4
4
 
@@ -1,4 +1,4 @@
1
- require_relative 'binlog_record_handler'
1
+ require 'flydata/fluent-plugins/mysql/binlog_record_handler'
2
2
 
3
3
  module Mysql
4
4
  class DmlRecordHandler < BinlogRecordHandler
@@ -2,16 +2,6 @@ module Flydata
2
2
  module Helpers
3
3
  @@development_mode = nil
4
4
  module_function
5
- def parse_command(cmd)
6
- klass = Flydata::Command::Base
7
- method = cmd
8
- if cmd.include?(':')
9
- class_name, method = cmd.split(':')
10
- klass = to_command_class(class_name)
11
- end
12
- [klass, method]
13
- end
14
-
15
5
  def usage_text
16
6
  text = ""
17
7
 
@@ -1,3 +1,6 @@
1
+ require 'flydata/heroku/instance_methods'
2
+ require 'flydata/heroku/configuration_methods'
3
+
1
4
  module Flydata
2
5
  module Heroku
3
6
  extend ActiveSupport::Concern
@@ -1,6 +1,6 @@
1
1
  require 'socket'
2
2
  require 'msgpack'
3
- require 'flydata/command_logger'
3
+ require 'flydata/command_loggable'
4
4
 
5
5
  module Flydata
6
6
  module Output
@@ -12,7 +12,7 @@ module Flydata
12
12
 
13
13
  def mysql_cli(conf = nil)
14
14
  mysql_conf(conf) if conf
15
- return Mysql2::Client.new(@mysql_conf) if @mysql_conf
15
+ return FdMysqlClient.new(@mysql_conf) if @mysql_conf
16
16
  nil
17
17
  end
18
18
  end
@@ -53,32 +53,6 @@ module Flydata
53
53
  end
54
54
  end
55
55
 
56
- class MysqlDumpGeneratorMasterData < MysqlDumpGenerator
57
- def dump(file_path)
58
- cmd = "#{@dump_cmd} -r #{file_path}"
59
- o, e, s = Open3.capture3(cmd)
60
- e.to_s.each_line {|l| puts l unless /^Warning:/ =~ l } unless e.to_s.empty?
61
- unless s.exitstatus == 0
62
- if File.exists?(file_path)
63
- File.open(file_path, 'r') {|f| f.each_line{|l| puts l}}
64
- FileUtils.rm(file_path)
65
- end
66
- raise "Failed to run mysqldump command."
67
- end
68
- unless File.exists?(file_path)
69
- raise "mysqldump file does not exist. Something wrong..."
70
- end
71
- if File.size(file_path) == 0
72
- raise "mysqldump file is empty. Something wrong..."
73
- end
74
- true
75
- end
76
-
77
- def generate_dump_cmd(conf)
78
- Util::MysqlUtil.generate_mysqldump_with_master_data_cmd(conf)
79
- end
80
- end
81
-
82
56
  class MysqlDumpGeneratorNoMasterData < MysqlDumpGenerator
83
57
  CHANGE_MASTER_TEMPLATE = <<EOS
84
58
  --
@@ -100,7 +74,7 @@ EOS
100
74
 
101
75
  begin
102
76
  # create pipe for callback function
103
- rd_io, wr_io = IO.pipe
77
+ rd_io, wr_io = IO.pipe("utf-8")
104
78
  wr_io.sync = true
105
79
  wr_io.set_encoding("utf-8")
106
80
  rd_io.extend(DumpStreamIO)
@@ -119,7 +93,7 @@ EOS
119
93
  threads << Thread.new do
120
94
  begin
121
95
  wr_io.print(first_line) # write a first line
122
- fileter_dump_stream(cmd_out, wr_io, binlog_file, binlog_pos)
96
+ filter_dump_stream(cmd_out, wr_io, binlog_file, binlog_pos)
123
97
  ensure
124
98
  wr_io.close rescue nil
125
99
  end
@@ -187,7 +161,7 @@ EOS
187
161
 
188
162
  def create_table_locker
189
163
  Fiber.new do
190
- client = Mysql2::Client.new(@db_opts)
164
+ client = FdMysqlClient.new(@db_opts)
191
165
  # Lock tables
192
166
  client.query "FLUSH LOCAL TABLES;"
193
167
  q = flush_tables_with_read_lock_query(client)
@@ -227,7 +201,7 @@ EOS
227
201
  result.first['Value']
228
202
  end
229
203
 
230
- def fileter_dump_stream(cmd_out, w_io, binlog_file, binlog_pos)
204
+ def filter_dump_stream(cmd_out, w_io, binlog_file, binlog_pos)
231
205
  find_insert_pos = :not_started
232
206
  cmd_out.each_line do |line|
233
207
  if find_insert_pos == :not_started && /^-- Server version/ === line
@@ -248,6 +222,30 @@ EOS
248
222
 
249
223
  end
250
224
 
225
+ # Custom mysql client that sets config params (eg:-read_timeout) uniformly for all
226
+ # mysql access. Also, gives access to the last query that was executed using the client
227
+ # which can be helpful when handling exceptions
228
+ class FdMysqlClient < Mysql2::Client
229
+
230
+ attr_accessor :last_query
231
+
232
+ def initialize(db_opts)
233
+ super(db_opts.merge(read_timeout: 600))
234
+ end
235
+
236
+ def query(sql, options = {})
237
+ @last_query = sql
238
+ begin
239
+ super(sql, options)
240
+ rescue Mysql2::Error => e
241
+ if /^Timeout waiting for a response/ === e.to_s
242
+ raise "The below query timed out when running. Please check long running processes and locks in your database.\n#{last_query}"
243
+ end
244
+ raise e
245
+ end
246
+ end
247
+ end
248
+
251
249
  class MysqlDumpParser
252
250
 
253
251
  module State
@@ -1,290 +1,288 @@
1
1
  module Flydata
2
- module FileUtil
3
- class SyncFileManager
4
- DUMP_DIR = ENV['FLYDATA_DUMP'] || File.join(FLYDATA_HOME, 'dump')
5
- BACKUP_DIR = ENV['FLYDATA_BACKUP'] || File.join(FLYDATA_HOME, 'backup')
6
- TABLE_POSITIONS_DIR = ENV['FLYDATA_TABLE_POSITIONS'] || File.join(FLYDATA_HOME, 'positions')
7
- def initialize(data_entry)
8
- @data_entry = data_entry
9
- @table_position_files = {} # File objects keyed by table name
10
- end
2
+ class SyncFileManager
3
+ DUMP_DIR = ENV['FLYDATA_DUMP'] || File.join(FLYDATA_HOME, 'dump')
4
+ BACKUP_DIR = ENV['FLYDATA_BACKUP'] || File.join(FLYDATA_HOME, 'backup')
5
+ TABLE_POSITIONS_DIR = ENV['FLYDATA_TABLE_POSITIONS'] || File.join(FLYDATA_HOME, 'positions')
6
+ def initialize(data_entry)
7
+ @data_entry = data_entry
8
+ @table_position_files = {} # File objects keyed by table name
9
+ end
11
10
 
12
- def close
13
- @table_position_files.values.each {|f| f.close }
14
- @table_position_files = {}
15
- end
11
+ def close
12
+ @table_position_files.values.each {|f| f.close }
13
+ @table_position_files = {}
14
+ end
16
15
 
17
- def dump_file_path
18
- File.join(dump_dir, @data_entry['name']) + ".dump"
19
- end
16
+ def dump_file_path
17
+ File.join(dump_dir, @data_entry['name']) + ".dump"
18
+ end
20
19
 
21
- # dump pos file for resume
22
- def dump_pos_path
23
- dump_file_path + ".pos"
24
- end
20
+ # dump pos file for resume
21
+ def dump_pos_path
22
+ dump_file_path + ".pos"
23
+ end
25
24
 
26
- def save_dump_pos(status, table_name, last_pos, binlog_pos, state = nil, substate = nil)
27
- File.open(dump_pos_path, 'w') do |f|
28
- f.write(dump_pos_content(status, table_name, last_pos, binlog_pos, state, substate))
29
- end
25
+ def save_dump_pos(status, table_name, last_pos, binlog_pos, state = nil, substate = nil)
26
+ File.open(dump_pos_path, 'w') do |f|
27
+ f.write(dump_pos_content(status, table_name, last_pos, binlog_pos, state, substate))
30
28
  end
29
+ end
31
30
 
32
- def load_dump_pos
33
- path = dump_pos_path
34
- return {} unless File.exists?(path)
35
- items = File.open(path, 'r').readline.split("\t")
36
- raise "Invalid dump.pos file: #{path}" unless items.length >= 5 && items.length <= 7
37
- mysql_table = load_mysql_table_marshal_dump
38
- { status: items[0], table_name: items[1], last_pos: items[2].to_i,
39
- binlog_pos: {binfile: items[3], pos: items[4].to_i},
40
- state: items[5], substate: items[6], mysql_table: mysql_table}
41
- end
31
+ def load_dump_pos
32
+ path = dump_pos_path
33
+ return {} unless File.exists?(path)
34
+ items = File.open(path, 'r').readline.split("\t")
35
+ raise "Invalid dump.pos file: #{path}" unless items.length >= 5 && items.length <= 7
36
+ mysql_table = load_mysql_table_marshal_dump
37
+ { status: items[0], table_name: items[1], last_pos: items[2].to_i,
38
+ binlog_pos: {binfile: items[3], pos: items[4].to_i},
39
+ state: items[5], substate: items[6], mysql_table: mysql_table}
40
+ end
42
41
 
43
- def mark_generated_tables(tables)
44
- table_positions_dir_path = ENV['FLYDATA_TABLE_POSITIONS'] || File.join(FLYDATA_HOME, 'positions')
45
- #Create positions if dir does not exist
46
- unless File.directory?(table_positions_dir_path)
47
- FileUtils.mkdir_p(table_positions_dir_path)
48
- end
49
- tables.each do |tab|
50
- File.open(File.join(table_positions_dir_path, "#{tab}.generated_ddl"), 'w') {|f| f.write("1") }
51
- end
42
+ def mark_generated_tables(tables)
43
+ table_positions_dir_path = ENV['FLYDATA_TABLE_POSITIONS'] || File.join(FLYDATA_HOME, 'positions')
44
+ #Create positions if dir does not exist
45
+ unless File.directory?(table_positions_dir_path)
46
+ FileUtils.mkdir_p(table_positions_dir_path)
52
47
  end
53
-
54
- def get_new_table_list(tables, file_type)
55
- table_positions_dir_path = ENV['FLYDATA_TABLE_POSITIONS'] || File.join(FLYDATA_HOME, 'positions')
56
- new_tables = []
57
- tables.each do |table|
58
- new_tables << table unless File.exists?(File.join(table_positions_dir_path, "#{table}.#{file_type}"))
59
- end
60
- new_tables
48
+ tables.each do |tab|
49
+ File.open(File.join(table_positions_dir_path, "#{tab}.generated_ddl"), 'w') {|f| f.write("1") }
61
50
  end
51
+ end
62
52
 
63
- # MysqlTable marshal file
64
- def mysql_table_marshal_dump_path
65
- dump_file_path + ".mysql_table"
53
+ def get_new_table_list(tables, file_type)
54
+ table_positions_dir_path = ENV['FLYDATA_TABLE_POSITIONS'] || File.join(FLYDATA_HOME, 'positions')
55
+ new_tables = []
56
+ tables.each do |table|
57
+ new_tables << table unless File.exists?(File.join(table_positions_dir_path, "#{table}.#{file_type}"))
66
58
  end
59
+ new_tables
60
+ end
67
61
 
68
- def save_mysql_table_marshal_dump(mysql_table)
69
- File.open(mysql_table_marshal_dump_path, 'w') do |f|
70
- f.write Marshal.dump(mysql_table)
71
- end
72
- end
62
+ # MysqlTable marshal file
63
+ def mysql_table_marshal_dump_path
64
+ dump_file_path + ".mysql_table"
65
+ end
73
66
 
74
- # binlog.pos file
75
- def save_binlog(binlog_pos)
76
- path = binlog_path
77
- File.open(path, 'w') do |f|
78
- f.write(binlog_content(binlog_pos))
79
- end
67
+ def save_mysql_table_marshal_dump(mysql_table)
68
+ File.open(mysql_table_marshal_dump_path, 'w') do |f|
69
+ f.write Marshal.dump(mysql_table)
80
70
  end
71
+ end
81
72
 
82
- def binlog_path
83
- File.join(FLYDATA_HOME, @data_entry['name'] + ".binlog.pos")
73
+ # binlog.pos file
74
+ def save_binlog(binlog_pos)
75
+ path = binlog_path
76
+ File.open(path, 'w') do |f|
77
+ f.write(binlog_content(binlog_pos))
84
78
  end
79
+ end
85
80
 
86
- def reset_table_position_files(tables)
87
- tables.each do |table_name|
88
- file = File.join(table_positions_dir_path, table_name + ".pos")
89
- File.open(file, "w") {|f| f.write('0') }
90
- end
91
- end
81
+ def binlog_path
82
+ File.join(FLYDATA_HOME, @data_entry['name'] + ".binlog.pos")
83
+ end
92
84
 
93
- def table_positions_dir_path
94
- TABLE_POSITIONS_DIR
85
+ def reset_table_position_files(tables)
86
+ tables.each do |table_name|
87
+ file = File.join(table_positions_dir_path, table_name + ".pos")
88
+ File.open(file, "w") {|f| f.write('0') }
95
89
  end
90
+ end
96
91
 
97
- def table_position_file_paths(*tables)
98
- tables.empty? ? Dir.glob(File.join(table_positions_dir_path, '*.pos')) :
99
- tables.map{|table| File.join(table_positions_dir_path, table + '.pos')}
100
- end
92
+ def table_positions_dir_path
93
+ TABLE_POSITIONS_DIR
94
+ end
101
95
 
102
- def table_ddl_file_paths(*tables)
103
- tables.empty? ? Dir.glob(File.join(table_positions_dir_path, '*.generated_ddl')) :
104
- tables.map{|table| File.join(table_positions_dir_path, table + '.generated_ddl')}
105
- end
96
+ def table_position_file_paths(*tables)
97
+ tables.empty? ? Dir.glob(File.join(table_positions_dir_path, '*.pos')) :
98
+ tables.map{|table| File.join(table_positions_dir_path, table + '.pos')}
99
+ end
106
100
 
107
- def table_binlog_pos_paths(*tables)
108
- tables.empty? ? Dir.glob(File.join(table_positions_dir_path, '*.binlog.pos')) :
109
- tables.map{|table| File.join(table_positions_dir_path, table + '.binlog.pos')}
110
- end
101
+ def table_ddl_file_paths(*tables)
102
+ tables.empty? ? Dir.glob(File.join(table_positions_dir_path, '*.generated_ddl')) :
103
+ tables.map{|table| File.join(table_positions_dir_path, table + '.generated_ddl')}
104
+ end
111
105
 
112
- def table_binlog_pos_init_paths(*tables)
113
- tables.empty? ? Dir.glob(File.join(table_positions_dir_path, '*.binlog.pos.init')) :
114
- tables.map{|table| File.join(table_positions_dir_path, table + '.binlog.pos.init')}
115
- end
106
+ def table_binlog_pos_paths(*tables)
107
+ tables.empty? ? Dir.glob(File.join(table_positions_dir_path, '*.binlog.pos')) :
108
+ tables.map{|table| File.join(table_positions_dir_path, table + '.binlog.pos')}
109
+ end
116
110
 
117
- # Read a sequence number from the table's position file,
118
- # increment the number and pass the number to a block.
119
- # After executing the block, saves the value to the position
120
- # file.
121
- def increment_and_save_table_position(table_name)
122
- file = File.join(table_positions_dir_path, table_name + ".pos")
123
- retry_count = 0
124
- begin
125
- @table_position_files[table_name] ||= File.open(file, "r+")
126
- rescue Errno::ENOENT
127
- raise if retry_count > 0 # Already retried. Must be a differentfile causing the error
128
- # File not exist. Create one with initial value of '0'
129
- File.open(file, "w") {|f| f.write('0') }
130
- retry_count += 1
131
- retry
132
- end
133
- f = @table_position_files[table_name]
134
- seq = f.read
135
- seq = seq.to_i + 1
136
- begin
137
- yield(seq)
138
- ensure
139
- # when an error happened in yield, the sequence number should remain
140
- # as is. For the next call to read the value correctly, the position
141
- # must be rewound.
142
- f.rewind
143
- end
144
- f.truncate(0)
145
- f.write(seq)
146
- f.flush
111
+ def table_binlog_pos_init_paths(*tables)
112
+ tables.empty? ? Dir.glob(File.join(table_positions_dir_path, '*.binlog.pos.init')) :
113
+ tables.map{|table| File.join(table_positions_dir_path, table + '.binlog.pos.init')}
114
+ end
115
+
116
+ # Read a sequence number from the table's position file,
117
+ # increment the number and pass the number to a block.
118
+ # After executing the block, saves the value to the position
119
+ # file.
120
+ def increment_and_save_table_position(table_name)
121
+ file = File.join(table_positions_dir_path, table_name + ".pos")
122
+ retry_count = 0
123
+ begin
124
+ @table_position_files[table_name] ||= File.open(file, "r+")
125
+ rescue Errno::ENOENT
126
+ raise if retry_count > 0 # Already retried. Must be a differentfile causing the error
127
+ # File not exist. Create one with initial value of '0'
128
+ File.open(file, "w") {|f| f.write('0') }
129
+ retry_count += 1
130
+ retry
131
+ end
132
+ f = @table_position_files[table_name]
133
+ seq = f.read
134
+ seq = seq.to_i + 1
135
+ begin
136
+ yield(seq)
137
+ ensure
138
+ # when an error happened in yield, the sequence number should remain
139
+ # as is. For the next call to read the value correctly, the position
140
+ # must be rewound.
147
141
  f.rewind
148
142
  end
143
+ f.truncate(0)
144
+ f.write(seq)
145
+ f.flush
146
+ f.rewind
147
+ end
149
148
 
150
- def sync_info_file
151
- File.join(dump_dir, "sync.info")
152
- end
149
+ def sync_info_file
150
+ File.join(dump_dir, "sync.info")
151
+ end
153
152
 
154
- def save_sync_info(initial_sync, tables)
155
- File.open(sync_info_file, "w") do |f|
156
- f.write([initial_sync, tables.join(" ")].join("\t"))
157
- end
153
+ def save_sync_info(initial_sync, tables)
154
+ File.open(sync_info_file, "w") do |f|
155
+ f.write([initial_sync, tables.join(" ")].join("\t"))
158
156
  end
157
+ end
159
158
 
160
- def load_sync_info
161
- return nil unless File.exists?(sync_info_file)
162
- items = File.open(sync_info_file, 'r').readline.split("\t")
163
- { initial_sync: (items[0] == 'true'),
164
- tables: items[1].split(" ") }
165
- end
159
+ def load_sync_info
160
+ return nil unless File.exists?(sync_info_file)
161
+ items = File.open(sync_info_file, 'r').readline.split("\t")
162
+ { initial_sync: (items[0] == 'true'),
163
+ tables: items[1].split(" ") }
164
+ end
166
165
 
167
- def get_table_binlog_pos(table_name)
168
- file = File.join(table_positions_dir_path, table_name + ".binlog.pos")
169
- return nil unless File.exists?(file)
170
- File.open(file, 'r').readline
171
- end
166
+ def get_table_binlog_pos(table_name)
167
+ file = File.join(table_positions_dir_path, table_name + ".binlog.pos")
168
+ return nil unless File.exists?(file)
169
+ File.open(file, 'r').readline
170
+ end
172
171
 
173
- def table_rev_file_path(table_name)
174
- File.join(table_positions_dir_path, table_name + ".rev")
175
- end
172
+ def table_rev_file_path(table_name)
173
+ File.join(table_positions_dir_path, table_name + ".rev")
174
+ end
176
175
 
177
- def table_rev_file_paths(*tables)
178
- tables.empty? ? Dir.glob(File.join(table_positions_dir_path, "*.rev")) :
179
- tables.map{|table| table_rev_file_path(table)}
180
- end
176
+ def table_rev_file_paths(*tables)
177
+ tables.empty? ? Dir.glob(File.join(table_positions_dir_path, "*.rev")) :
178
+ tables.map{|table| table_rev_file_path(table)}
179
+ end
181
180
 
182
- def table_rev(table_name)
183
- file = table_rev_file_path(table_name)
184
- return 1 unless File.exists?(file) #default revision is 1
185
- File.open(file, "r+") do |f|
186
- seq = f.read
187
- if seq.empty?
188
- return 1
189
- else
190
- return seq.to_i
191
- end
181
+ def table_rev(table_name)
182
+ file = table_rev_file_path(table_name)
183
+ return 1 unless File.exists?(file) #default revision is 1
184
+ File.open(file, "r+") do |f|
185
+ seq = f.read
186
+ if seq.empty?
187
+ return 1
188
+ else
189
+ return seq.to_i
192
190
  end
193
191
  end
192
+ end
194
193
 
195
- def increment_table_rev(table_name, base_rev)
196
- file = table_rev_file_path(table_name)
197
- new_rev = base_rev + 1
198
- File.open(file, "w") do |f|
199
- f.write(new_rev)
200
- end
201
- new_rev
194
+ def increment_table_rev(table_name, base_rev)
195
+ file = table_rev_file_path(table_name)
196
+ new_rev = base_rev + 1
197
+ File.open(file, "w") do |f|
198
+ f.write(new_rev)
202
199
  end
200
+ new_rev
201
+ end
203
202
 
204
- def delete_table_binlog_pos(table_name)
205
- file = File.join(table_positions_dir_path, table_name + ".binlog.pos")
206
- if File.exists?(file)
207
- FileUtils.rm(file, :force => true)
208
- else
209
- puts "#{file} does not exist. Something is wrong. Did you delete the file manually when flydata was running?"
210
- end
203
+ def delete_table_binlog_pos(table_name)
204
+ file = File.join(table_positions_dir_path, table_name + ".binlog.pos")
205
+ if File.exists?(file)
206
+ FileUtils.rm(file, :force => true)
207
+ else
208
+ puts "#{file} does not exist. Something is wrong. Did you delete the file manually when flydata was running?"
211
209
  end
210
+ end
212
211
 
213
- def save_table_binlog_pos(tables, binlog_pos)
214
- tables.each do |table_name|
215
- file = File.join(dump_dir, table_name + ".binlog.pos")
216
- File.open(file, "w") do |f|
217
- f.write(binlog_content(binlog_pos))
218
- end
212
+ def save_table_binlog_pos(tables, binlog_pos)
213
+ tables.each do |table_name|
214
+ file = File.join(dump_dir, table_name + ".binlog.pos")
215
+ File.open(file, "w") do |f|
216
+ f.write(binlog_content(binlog_pos))
219
217
  end
220
218
  end
219
+ end
221
220
 
222
- def install_table_binlog_files(tables)
223
- FileUtils.mkdir_p(table_positions_dir_path) unless Dir.exists?(table_positions_dir_path)
224
- tables.each do |table_name|
225
- file_name = table_name + ".binlog.pos"
226
- src_file = File.join(dump_dir, file_name)
227
- if ! File.exists?(src_file)
228
- raise "#{src_file} does not exist. Error!!"
229
- end
230
- FileUtils.mv(src_file, table_positions_dir_path)
231
- # save the position at initial sync. this is used for repair if
232
- # necessary.
233
- FileUtils.cp(File.join(table_positions_dir_path, file_name), File.join(table_positions_dir_path, file_name + ".init"))
221
+ def install_table_binlog_files(tables)
222
+ FileUtils.mkdir_p(table_positions_dir_path) unless Dir.exists?(table_positions_dir_path)
223
+ tables.each do |table_name|
224
+ file_name = table_name + ".binlog.pos"
225
+ src_file = File.join(dump_dir, file_name)
226
+ if ! File.exists?(src_file)
227
+ raise "#{src_file} does not exist. Error!!"
234
228
  end
229
+ FileUtils.mv(src_file, table_positions_dir_path)
230
+ # save the position at initial sync. this is used for repair if
231
+ # necessary.
232
+ FileUtils.cp(File.join(table_positions_dir_path, file_name), File.join(table_positions_dir_path, file_name + ".init"))
235
233
  end
234
+ end
236
235
 
237
- def delete_dump_file
238
- FileUtils.rm(dump_file_path) if File.exists?(dump_file_path)
239
- end
236
+ def delete_dump_file
237
+ FileUtils.rm(dump_file_path) if File.exists?(dump_file_path)
238
+ end
240
239
 
241
- def backup_dump_dir
242
- backup_dir = BACKUP_DIR.dup
243
- FileUtils.mkdir_p(backup_dir) unless Dir.exists?(backup_dir)
244
- dest_dir = File.join(backup_dir, Time.now.strftime("%Y%m%d%H%M%S"))
245
- FileUtils.mkdir(dest_dir)
246
- FileUtils.mv(Dir.glob("#{dump_dir}/*"), dest_dir)
247
- end
240
+ def backup_dump_dir
241
+ backup_dir = BACKUP_DIR.dup
242
+ FileUtils.mkdir_p(backup_dir) unless Dir.exists?(backup_dir)
243
+ dest_dir = File.join(backup_dir, Time.now.strftime("%Y%m%d%H%M%S"))
244
+ FileUtils.mkdir(dest_dir)
245
+ FileUtils.mv(Dir.glob("#{dump_dir}/*"), dest_dir)
246
+ end
248
247
 
249
- def backup_dir
250
- BACKUP_DIR
251
- end
248
+ def backup_dir
249
+ BACKUP_DIR
250
+ end
252
251
 
253
- private
252
+ private
254
253
 
255
- def dump_pos_content(status, table_name, last_pos, binlog_pos, state = nil, substate = nil)
256
- [status, table_name, last_pos, binlog_content(binlog_pos), state, substate].join("\t")
257
- end
254
+ def dump_pos_content(status, table_name, last_pos, binlog_pos, state = nil, substate = nil)
255
+ [status, table_name, last_pos, binlog_content(binlog_pos), state, substate].join("\t")
256
+ end
258
257
 
259
- def binlog_content(binlog_pos)
260
- [binlog_pos[:binfile], binlog_pos[:pos]].join("\t")
261
- end
258
+ def binlog_content(binlog_pos)
259
+ [binlog_pos[:binfile], binlog_pos[:pos]].join("\t")
260
+ end
262
261
 
263
- def load_mysql_table_marshal_dump
264
- path = mysql_table_marshal_dump_path
265
- return nil unless File.exists?(path)
266
- Marshal.load(File.open(path, 'r'))
267
- end
262
+ def load_mysql_table_marshal_dump
263
+ path = mysql_table_marshal_dump_path
264
+ return nil unless File.exists?(path)
265
+ Marshal.load(File.open(path, 'r'))
266
+ end
268
267
 
269
- def dump_dir
270
- pref = @data_entry['mysql_data_entry_preference']
271
- dump_dir = if pref and pref['mysqldump_dir']
272
- pref['mysqldump_dir']
273
- else
274
- nil
275
- end
276
- if dump_dir
277
- dump_dir = dump_dir.dup
278
- dump_dir[0] = ENV['HOME'] if dump_dir.match(/^~$|^~\//)
279
- else
280
- dump_dir = DUMP_DIR.dup
281
- end
282
- if File.exists?(dump_dir) and not Dir.exists?(dump_dir)
283
- raise "'mysqldump_dir'(#{dump_dir}) must be a directory."
284
- end
285
- FileUtils.mkdir_p(dump_dir) unless Dir.exists?(dump_dir)
286
- dump_dir
287
- end
268
+ def dump_dir
269
+ pref = @data_entry['mysql_data_entry_preference']
270
+ dump_dir = if pref and pref['mysqldump_dir']
271
+ pref['mysqldump_dir']
272
+ else
273
+ nil
274
+ end
275
+ if dump_dir
276
+ dump_dir = dump_dir.dup
277
+ dump_dir[0] = ENV['HOME'] if dump_dir.match(/^~$|^~\//)
278
+ else
279
+ dump_dir = DUMP_DIR.dup
280
+ end
281
+ if File.exists?(dump_dir) and not Dir.exists?(dump_dir)
282
+ raise "'mysqldump_dir'(#{dump_dir}) must be a directory."
283
+ end
284
+ FileUtils.mkdir_p(dump_dir) unless Dir.exists?(dump_dir)
285
+ dump_dir
288
286
  end
289
287
  end
290
288
  end