flydata 0.3.10 → 0.3.11

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 478d29c0767a534808dea15674528d5b5442bbed
4
- data.tar.gz: c6536fb66fedffbdcc52069cb28f32f74fe3465d
3
+ metadata.gz: c81a2a245fd400366aa535123cd4bcfa009aa29f
4
+ data.tar.gz: 6762cefccdabfd09f5e7034bbf32aa9fb6d6262b
5
5
  SHA512:
6
- metadata.gz: 6b97f3acc0e763fcff4f2d4a18dcc4d9625d736db229b00554aee36da0ff8e68a189324a46abb3d985dfd1e2d4964ec6963a9299d475170e759485cb1e07faec
7
- data.tar.gz: fdee03e1c1bf32699f8c5157aa51f48ecf6f1c023d2160a63b996ca7ac0599fa952de02b55045715b4a66283083b204860201a31a157b9cbf92d2413aebc77d5
6
+ metadata.gz: cd9983b914ef12e36f39248dfe4fde7c49e321b17df7ad476155061d84da62dde5a0cd78ed94c17b23c55bebd5b3b591adccafb45c5c4036305702e8cd5bab44
7
+ data.tar.gz: 18e24eb120bc7d0aa61d7e9819c4d59593a07645703ffcb627d8ede58deb6e43953a20318006a5c4fcf562cc4decac586d34ec4b697373cbc7dde0faea63a7f4
data/Gemfile CHANGED
@@ -14,6 +14,7 @@ gem "slop", '~> 3.4', '>= 3.4.6'
14
14
  gem "treetop", '~> 1.5', '>= 1.5.3'
15
15
  gem "sys-filesystem", '~> 1.1', '>= 1.1.3'
16
16
  gem "io-console", '~> 0.4.2', '>= 0.4.2'
17
+ gem "kodama", '~> 0.1.2', '>= 0.1.2'
17
18
 
18
19
  group :development do
19
20
  gem "jeweler", '~> 1.8', '>= 1.8.8'
data/Gemfile.lock CHANGED
@@ -61,7 +61,7 @@ GEM
61
61
  rdoc
62
62
  json (1.8.1)
63
63
  jwt (1.0.0)
64
- kodama (0.1.1)
64
+ kodama (0.1.2)
65
65
  ruby-binlog (>= 0.1.9)
66
66
  method_source (0.8.2)
67
67
  mime-types (2.3)
@@ -133,6 +133,7 @@ DEPENDENCIES
133
133
  io-console (~> 0.4.2, >= 0.4.2)
134
134
  jeweler (~> 1.8, >= 1.8.8)
135
135
  json (~> 1.8, >= 1.8.0)
136
+ kodama (~> 0.1.2, >= 0.1.2)
136
137
  mysql2 (~> 0.3, >= 0.3.11)
137
138
  protected_attributes (~> 1.0, >= 1.0.8)
138
139
  pry
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.3.10
1
+ 0.3.11
data/flydata.gemspec CHANGED
@@ -2,16 +2,14 @@
2
2
  # DO NOT EDIT THIS FILE DIRECTLY
3
3
  # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
4
4
  # -*- encoding: utf-8 -*-
5
- # stub: flydata 0.3.10 ruby lib
6
5
 
7
6
  Gem::Specification.new do |s|
8
7
  s.name = "flydata"
9
- s.version = "0.3.10"
8
+ s.version = "0.3.11"
10
9
 
11
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
12
- s.require_paths = ["lib"]
13
11
  s.authors = ["Koichi Fujikawa", "Masashi Miyazaki", "Matthew Luu", "Mak Inada", "Sriram NS"]
14
- s.date = "2015-03-31"
12
+ s.date = "2015-04-03"
15
13
  s.description = "FlyData Agent"
16
14
  s.email = "sysadmin@flydata.com"
17
15
  s.executables = ["fdmysqldump", "flydata", "serverinfo"]
@@ -168,7 +166,8 @@ Gem::Specification.new do |s|
168
166
  ]
169
167
  s.homepage = "http://flydata.com/"
170
168
  s.licenses = ["All right reserved."]
171
- s.rubygems_version = "2.4.3"
169
+ s.require_paths = ["lib"]
170
+ s.rubygems_version = "2.0.14"
172
171
  s.summary = "FlyData Agent"
173
172
 
174
173
  if s.respond_to? :specification_version then
@@ -188,6 +187,7 @@ Gem::Specification.new do |s|
188
187
  s.add_runtime_dependency(%q<treetop>, [">= 1.5.3", "~> 1.5"])
189
188
  s.add_runtime_dependency(%q<sys-filesystem>, [">= 1.1.3", "~> 1.1"])
190
189
  s.add_runtime_dependency(%q<io-console>, [">= 0.4.2", "~> 0.4.2"])
190
+ s.add_runtime_dependency(%q<kodama>, [">= 0.1.2", "~> 0.1.2"])
191
191
  s.add_development_dependency(%q<jeweler>, [">= 1.8.8", "~> 1.8"])
192
192
  s.add_development_dependency(%q<rspec>, ["~> 3.0"])
193
193
  s.add_development_dependency(%q<timecop>, [">= 0.7.1", "~> 0.7"])
@@ -211,6 +211,7 @@ Gem::Specification.new do |s|
211
211
  s.add_dependency(%q<treetop>, [">= 1.5.3", "~> 1.5"])
212
212
  s.add_dependency(%q<sys-filesystem>, [">= 1.1.3", "~> 1.1"])
213
213
  s.add_dependency(%q<io-console>, [">= 0.4.2", "~> 0.4.2"])
214
+ s.add_dependency(%q<kodama>, [">= 0.1.2", "~> 0.1.2"])
214
215
  s.add_dependency(%q<jeweler>, [">= 1.8.8", "~> 1.8"])
215
216
  s.add_dependency(%q<rspec>, ["~> 3.0"])
216
217
  s.add_dependency(%q<timecop>, [">= 0.7.1", "~> 0.7"])
@@ -235,6 +236,7 @@ Gem::Specification.new do |s|
235
236
  s.add_dependency(%q<treetop>, [">= 1.5.3", "~> 1.5"])
236
237
  s.add_dependency(%q<sys-filesystem>, [">= 1.1.3", "~> 1.1"])
237
238
  s.add_dependency(%q<io-console>, [">= 0.4.2", "~> 0.4.2"])
239
+ s.add_dependency(%q<kodama>, [">= 0.1.2", "~> 0.1.2"])
238
240
  s.add_dependency(%q<jeweler>, [">= 1.8.8", "~> 1.8"])
239
241
  s.add_dependency(%q<rspec>, ["~> 3.0"])
240
242
  s.add_dependency(%q<timecop>, [">= 0.7.1", "~> 0.7"])
@@ -182,6 +182,7 @@ EOS
182
182
  new_tables_after_reset = @new_tables + @input_tables
183
183
  if @input_tables.empty? or @full_tables.empty? or @full_tables.all?{|ft| new_tables_after_reset.include?(ft)}
184
184
  delete_files << sync_fm.binlog_path
185
+ delete_files << sync_fm.sent_binlog_path
185
186
  end
186
187
  delete_files.flatten.each do |path|
187
188
  FileUtils.rm(path) if File.exists?(path)
@@ -228,6 +229,54 @@ EOS
228
229
  do_generate_table_ddl(de)
229
230
  end
230
231
 
232
+ # Command: flydata sync:fix_binlogpos
233
+ # - Arguments
234
+ def self.slop_fix_binlogpos
235
+ Slop.new do
236
+ on 'f', 'force', 'update sent binlog position file forcibly'
237
+ end
238
+ end
239
+
240
+ # Command: flydata sync:fix_binlogpos
241
+ # Set binlog path
242
+ # - Entry method
243
+ def fix_binlogpos
244
+ de = data_entry
245
+ sync_fm = create_sync_file_manager(de)
246
+
247
+ if File.exists?(sync_fm.sent_binlog_path) && !opts.force?
248
+ log_info_stdout("Skip creating sent binlogpos because sent position file is exist already. (#{sync_fm.sent_binlog_path})")
249
+ return
250
+ end
251
+
252
+ if Flydata::Command::Sender.new.process_exist?
253
+ log_warn_stderr("flydata is running. flydata process needs to be stopped with 'flydata stop'.")
254
+ return
255
+ end
256
+
257
+ binlog_info = sync_fm.load_binlog
258
+ if binlog_info.nil?
259
+ log_info_stdout("Skip creating sent binlogpos because binlog position file is empty or invalid. (#{sync_fm.sent_binlog_path})")
260
+ return
261
+ end
262
+
263
+ say("Updating binlog position files...")
264
+ log_info("Updating binlog position files... Original binlog_info:#{binlog_info}")
265
+
266
+ # Update binlog.sent.pos file
267
+ # -1 is because the position in binlog.pos is the next event's position.
268
+ # on the other hand the position in sent position indicates already processed.
269
+ binlog_info[:pos] -= 1
270
+ log_info("Updating sent position file. #{binlog_info} -> #{sync_fm.sent_binlog_path}")
271
+ sync_fm.save_sent_binlog(binlog_info)
272
+
273
+ # Update binlog.pos file to start from head of the current binlog file
274
+ new_binlog_info = binlog_info.dup.tap{|h| h[:pos] = 4} # 4 is the first position of binlog file.
275
+ log_info("Updating original position file. #{new_binlog_info} -> #{sync_fm.binlog_path}")
276
+ sync_fm.save_binlog(new_binlog_info)
277
+ log_info_stdout("Done!")
278
+ end
279
+
231
280
  private
232
281
 
233
282
  # Initial sync
@@ -60,6 +60,10 @@ class MysqlBinlogFlydataInput < MysqlBinlogInput
60
60
  unless @binlog_position_file.exists?
61
61
  raise "No position file(#{@position_file}). Initial synchronization is required before starting."
62
62
  end
63
+
64
+ @sync_fm = Flydata::SyncFileManager.new(nil) # Passing nil for data_entry as this class does not use methods which require data_entry
65
+ @sent_position_file_path = @sync_fm.sent_binlog_path(@position_file)
66
+
63
67
  load_custom_conf
64
68
  $log.info "mysql host:\"#{@host}\" port:\"#{@port}\" username:\"#{@username}\" database:\"#{@database}\" tables:\"#{@tables}\" tables_append_only:\"#{tables_append_only}\""
65
69
  $log.info "mysql client version: #{`mysql -V`}"
@@ -72,7 +76,6 @@ class MysqlBinlogFlydataInput < MysqlBinlogInput
72
76
  @tables << table unless @tables.include?(table)
73
77
  @omit_events[table] = [:delete]
74
78
  end
75
- @sync_fm = Flydata::SyncFileManager.new(nil) # Passing nil for data_entry as this class does not use methods which require data_entry
76
79
 
77
80
  #Remove tables that do not have pos files
78
81
  new_tables = @sync_fm.get_new_table_list(@tables, "pos")
@@ -131,6 +134,10 @@ EOS
131
134
  @context.table_meta.update
132
135
  start_kodama(mysql_url) do |c|
133
136
  c.binlog_position_file = @position_file
137
+ if c.respond_to?(:sent_binlog_position_file=)
138
+ $log.info "Sent position feature is enabled. sent_position_file:#{@sent_position_file_path}"
139
+ c.sent_binlog_position_file = @sent_position_file_path
140
+ end
134
141
  c.connection_retry_limit = @retry_limit
135
142
  c.connection_retry_wait = @retry_wait
136
143
  c.log_level = @log_level.to_sym
@@ -13,13 +13,13 @@ module Mysql
13
13
  PATTERN
14
14
  end
15
15
 
16
- def process(record, normalized_query)
16
+ def process(record)
17
17
  emit_record(:alter_table, record) do |opt|
18
18
  ret = nil
19
19
  begin
20
- result = ParserProvider.parser(:mysql, :mysql_alter_table).new.parse(normalized_query)
20
+ result = ParserProvider.parser(:mysql, :mysql_alter_table).new.parse(record["normalized_query"])
21
21
  if result.nil?
22
- $log.error("Received unsupported alter table query. normalized query:'#{normalized_query}', raw query: '#{record['query']}'")
22
+ $log.error("Received unsupported alter table query. normalized query:'#{record['normalized_query']}', raw query: '#{record['query']}'")
23
23
  else
24
24
  ret = result.tree
25
25
  breaking_query = ret[:actions].any?{|action| !action.has_key?(:support_level) || action[:support_level] != :nonbreaking}
@@ -27,7 +27,7 @@ module Mysql
27
27
  end
28
28
  rescue => e
29
29
  msg = <<EOS
30
- Received unsupported alter table query. normalized query:'#{normalized_query}', raw query: '#{record['query']}' Caused by error '#{e.to_s}'
30
+ Received unsupported alter table query. normalized query:'#{record['normalized_query']}', raw query: '#{record['query']}' Caused by error '#{e.to_s}'
31
31
  Stacktrace :
32
32
  #{e.backtrace.join("\n")}
33
33
  EOS
@@ -10,7 +10,7 @@ module Mysql
10
10
  normalize_query(record["query"]) do |query|
11
11
  @handlers.each do |handler|
12
12
  if (handler.pattern.match(query))
13
- handler.process(record, query)
13
+ handler.process(record.merge({"normalized_query" => query}))
14
14
  break
15
15
  end
16
16
  end
@@ -7,7 +7,7 @@ class DdlQueryHandler < BinlogQueryHandler
7
7
 
8
8
  def acceptable_db?(record)
9
9
  db_name = record["db_name"]
10
- if DDL_TABLE_QUERY =~ record["query"]
10
+ if DDL_TABLE_QUERY =~ record["normalized_query"]
11
11
  table_name_in_query = $1 ? $1 : $2
12
12
 
13
13
  if (idx = table_name_in_query.index("."))
@@ -1,3 +1,5 @@
1
+ require 'mysql2'
2
+
1
3
  module Flydata
2
4
  class SyncFileManager
3
5
  DUMP_DIR = ENV['FLYDATA_DUMP'] || File.join(FLYDATA_HOME, 'dump')
@@ -70,7 +72,7 @@ module Flydata
70
72
  end
71
73
  end
72
74
 
73
- # binlog.pos file
75
+ # master binlog.pos file
74
76
  def save_binlog(binlog_pos)
75
77
  path = binlog_path
76
78
  File.open(path, 'w') do |f|
@@ -78,10 +80,32 @@ module Flydata
78
80
  end
79
81
  end
80
82
 
83
+ def load_binlog(file_path = binlog_path)
84
+ return nil unless File.exists?(file_path)
85
+ f, pos = IO.read(file_path).strip.split("\t")
86
+ return nil if f.nil? || f.empty? || pos.nil?
87
+ { binfile: f, pos: pos.to_i }
88
+ end
89
+
81
90
  def binlog_path
82
91
  File.join(FLYDATA_HOME, @data_entry['name'] + ".binlog.pos")
83
92
  end
84
93
 
94
+ # sent binlog.pos file
95
+ def save_sent_binlog(binlog_pos)
96
+ File.open(sent_binlog_path, 'w') do |f|
97
+ f.write(binlog_content(binlog_pos))
98
+ end
99
+ end
100
+
101
+ def sent_binlog_path(master_binlog_path = binlog_path)
102
+ unless master_binlog_path && master_binlog_path.end_with?('binlog.pos')
103
+ raise ArgumentError.new("Invalid binlog path. binlog path needs to end with 'binlog.pos'")
104
+ end
105
+ "#{master_binlog_path[0..-5]}.sent.pos"
106
+ end
107
+
108
+ # table files
85
109
  def reset_table_position_files(tables)
86
110
  tables.each do |table_name|
87
111
  file = File.join(table_positions_dir_path, table_name + ".pos")
@@ -15,7 +15,7 @@ module Fluent
15
15
  TEST_SEQUENCE_NUM = 1
16
16
  TEST_TABLE_BINLOG_POS = File.join(FLYDATA_HOME, "positions/#{TEST_TABLE}.binlog.pos")
17
17
  TEST_TABLES = "#{TEST_TABLE},test_table_1,test_table_2,test_table_3"
18
- TEST_POSITION_FILE = "test_position.log"
18
+ TEST_POSITION_FILE = "test_position.binlog.pos"
19
19
  TEST_REVISION_FILE = File.join(FLYDATA_HOME, "positions/#{TEST_TABLE}.rev")
20
20
  TEST_TIMESTAMP = 1389214083
21
21
  TEST_TABLE_APPEND_ONLY = "test_table_4"
@@ -22,14 +22,15 @@ module Mysql
22
22
  subject { described_class.new(context) }
23
23
  describe '#process' do
24
24
  let(:query) { "a_query" }
25
+ let(:normalized_query) { double('normalized_query') }
25
26
  let(:record) do
26
27
  r = double('record')
27
28
  allow(r).to receive(:[]).with("db_name").and_return(database)
28
29
  allow(r).to receive(:[]).with("query").and_return(query)
29
30
  allow(r).to receive(:[]).with("table_name").and_return(table)
31
+ allow(r).to receive(:[]).with("normalized_query").and_return(normalized_query)
30
32
  r
31
33
  end
32
- let(:normalized_query) { double('normalized_query') }
33
34
  let(:parse_result) do
34
35
  r = double('parse_result')
35
36
  r
@@ -51,7 +52,7 @@ module Mysql
51
52
  it "returns nil with an error log" do
52
53
  expect($log).to receive(:error).with(/Received unsupported alter table query.*Caused by error '#{an_error}'/m)
53
54
 
54
- expect(subject.process(record, normalized_query)).to eq(nil)
55
+ expect(subject.process(record)).to eq(nil)
55
56
  end
56
57
  end
57
58
 
@@ -74,7 +75,7 @@ module Mysql
74
75
  it "returns nil with a warn log" do
75
76
  expect($log).to receive(:error).with(/Received unsupported alter table query\./)
76
77
 
77
- expect(subject.process(record, normalized_query)).to eq(nil)
78
+ expect(subject.process(record)).to eq(nil)
78
79
  end
79
80
  end
80
81
  end
@@ -46,12 +46,13 @@ EOT
46
46
  let(:record) do
47
47
  r = double('record')
48
48
  allow(r).to receive(:[]).with("query").and_return(query)
49
+ expect(r).to receive(:merge).with({"normalized_query" => normalized_query}).and_return(r)
49
50
  r
50
51
  end
51
52
  let(:query_handler) do
52
53
  r = double('query_handler')
53
54
  allow(r).to receive(:pattern).and_return(/^ALTER TABLE/i)
54
- expect(r).to receive(:process).with(record, normalized_query)
55
+ expect(r).to receive(:process).with(record)
55
56
  r
56
57
  end
57
58
  let(:context) { double('context') }
@@ -153,10 +153,47 @@ module Flydata
153
153
  end
154
154
  end
155
155
 
156
+ describe '#load_binlog' do
157
+ let(:binfile) { 'mysqlbinlog.000001' }
158
+ let(:pos) { 107 }
159
+ let(:binlog_pos) { {binfile: binfile, pos: pos} }
160
+
161
+ subject { default_sfm.load_binlog }
162
+
163
+ context 'when binlog pos does not exist' do
164
+ before do
165
+ File.delete(default_sfm.binlog_path) if File.exist?(default_sfm.binlog_path)
166
+ end
167
+ it { is_expected.to be_nil }
168
+ end
169
+
170
+ context 'when binlog pos exists' do
171
+ before do
172
+ default_sfm.save_binlog(binlog_pos)
173
+ end
174
+ it { is_expected.to eq(binlog_pos) }
175
+ end
176
+ end
177
+
156
178
  describe '#binlog_path' do
157
179
  it { expect(default_sfm.binlog_path).to eq("#{FLYDATA_HOME}/flydata_sync_mysql.binlog.pos") }
158
180
  end
159
181
 
182
+ describe '#sent_binlog_path' do
183
+ context 'with no args' do
184
+ subject { default_sfm.sent_binlog_path }
185
+ it { is_expected.to eq("#{FLYDATA_HOME}/flydata_sync_mysql.binlog.sent.pos") }
186
+ end
187
+ context 'with invalid args' do
188
+ subject { default_sfm.sent_binlog_path('/home/ec2-user/.flydata/flydata_sync.pos') }
189
+ it { expect{subject}.to raise_error(ArgumentError) }
190
+ end
191
+ context 'with valid args' do
192
+ subject { default_sfm.sent_binlog_path('/home/ec2-user/.flydata/flydata_sync.binlog.pos') }
193
+ it { is_expected.to eq('/home/ec2-user/.flydata/flydata_sync.binlog.sent.pos') }
194
+ end
195
+ end
196
+
160
197
  describe '#increment_and_save_table_position' do
161
198
  let(:test_table) { 'test_table' }
162
199
  before do
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: flydata
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.10
4
+ version: 0.3.11
5
5
  platform: ruby
6
6
  authors:
7
7
  - Koichi Fujikawa
@@ -12,7 +12,7 @@ authors:
12
12
  autorequire:
13
13
  bindir: bin
14
14
  cert_chain: []
15
- date: 2015-03-31 00:00:00.000000000 Z
15
+ date: 2015-04-03 00:00:00.000000000 Z
16
16
  dependencies:
17
17
  - !ruby/object:Gem::Dependency
18
18
  name: rest-client
@@ -262,6 +262,26 @@ dependencies:
262
262
  - - ~>
263
263
  - !ruby/object:Gem::Version
264
264
  version: 0.4.2
265
+ - !ruby/object:Gem::Dependency
266
+ name: kodama
267
+ requirement: !ruby/object:Gem::Requirement
268
+ requirements:
269
+ - - '>='
270
+ - !ruby/object:Gem::Version
271
+ version: 0.1.2
272
+ - - ~>
273
+ - !ruby/object:Gem::Version
274
+ version: 0.1.2
275
+ type: :runtime
276
+ prerelease: false
277
+ version_requirements: !ruby/object:Gem::Requirement
278
+ requirements:
279
+ - - '>='
280
+ - !ruby/object:Gem::Version
281
+ version: 0.1.2
282
+ - - ~>
283
+ - !ruby/object:Gem::Version
284
+ version: 0.1.2
265
285
  - !ruby/object:Gem::Dependency
266
286
  name: jeweler
267
287
  requirement: !ruby/object:Gem::Requirement
@@ -608,7 +628,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
608
628
  version: '0'
609
629
  requirements: []
610
630
  rubyforge_project:
611
- rubygems_version: 2.4.3
631
+ rubygems_version: 2.0.14
612
632
  signing_key:
613
633
  specification_version: 4
614
634
  summary: FlyData Agent