flydata 0.2.20 → 0.2.21
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/VERSION +1 -1
- data/flydata.gemspec +7 -4
- data/lib/flydata/command/base.rb +3 -0
- data/lib/flydata/command_logger.rb +1 -1
- data/lib/flydata/fluent-plugins/in_mysql_binlog_flydata.rb +7 -1
- data/lib/flydata/fluent-plugins/mysql/binlog_record_handler.rb +1 -0
- data/lib/flydata/fluent-plugins/mysql/context.rb +1 -1
- data/lib/flydata/fluent-plugins/mysql/dml_record_handler.rb +12 -3
- data/lib/flydata/fluent-plugins/mysql/table_meta.rb +83 -0
- data/spec/fluent_plugins_spec_helper.rb +3 -1
- data/spec/flydata/cli_spec.rb +1 -1
- data/spec/flydata/fluent-plugins/in_mysql_binlog_flydata_spec.rb +1 -0
- data/spec/flydata/fluent-plugins/mysql/alter_table_query_handler_spec.rb +5 -2
- data/spec/flydata/fluent-plugins/mysql/binlog_position_spec.rb +2 -1
- data/spec/flydata/fluent-plugins/mysql/binlog_query_dispatcher_spec.rb +1 -1
- data/spec/flydata/fluent-plugins/mysql/table_meta_spec.rb +61 -0
- data/spec/flydata/parser/mysql/alter_table_parser_spec.rb +1 -0
- data/spec/flydata/sync_file_manager_spec.rb +2 -0
- data/spec/spec_helper.rb +3 -0
- metadata +5 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b2bb40962e8bd93a3daf20cee2de578c4abc1788
|
4
|
+
data.tar.gz: 266ca371867bd725c6721bae7d23fbea9fd4a0e6
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: daaa7f5468f4f334ef0b7d0cea6cfd672c0a816fd119ca4b54c4f6fa5619987ff37c5df587b11c734d4a29fd2518072277c98a810755d0f0db8008fc719a0ec1
|
7
|
+
data.tar.gz: 3140aea09a5fad9977f1a0bf9d60f317f71637129e0b7ac423198e43e84159534f1715d49d28db28ddc135e522bcbdc32f3ed1415904d2f6cffeffc1f46066c3
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.2.
|
1
|
+
0.2.21
|
data/flydata.gemspec
CHANGED
@@ -2,14 +2,16 @@
|
|
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.2.21 ruby lib
|
5
6
|
|
6
7
|
Gem::Specification.new do |s|
|
7
8
|
s.name = "flydata"
|
8
|
-
s.version = "0.2.
|
9
|
+
s.version = "0.2.21"
|
9
10
|
|
10
11
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
12
|
+
s.require_paths = ["lib"]
|
11
13
|
s.authors = ["Koichi Fujikawa", "Masashi Miyazaki", "Matthew Luu", "Mak Inada", "Sriram NS"]
|
12
|
-
s.date = "2014-12-
|
14
|
+
s.date = "2014-12-12"
|
13
15
|
s.description = "FlyData Agent"
|
14
16
|
s.email = "sysadmin@flydata.com"
|
15
17
|
s.executables = ["fdmysqldump", "flydata", "serverinfo"]
|
@@ -100,6 +102,7 @@ Gem::Specification.new do |s|
|
|
100
102
|
"lib/flydata/fluent-plugins/mysql/context.rb",
|
101
103
|
"lib/flydata/fluent-plugins/mysql/ddl_query_handler.rb",
|
102
104
|
"lib/flydata/fluent-plugins/mysql/dml_record_handler.rb",
|
105
|
+
"lib/flydata/fluent-plugins/mysql/table_meta.rb",
|
103
106
|
"lib/flydata/fluent-plugins/out_forward_ssl.rb",
|
104
107
|
"lib/flydata/fluent-plugins/preference.rb",
|
105
108
|
"lib/flydata/flydata_crontab.sh",
|
@@ -127,6 +130,7 @@ Gem::Specification.new do |s|
|
|
127
130
|
"spec/flydata/fluent-plugins/mysql/alter_table_query_handler_spec.rb",
|
128
131
|
"spec/flydata/fluent-plugins/mysql/binlog_position_spec.rb",
|
129
132
|
"spec/flydata/fluent-plugins/mysql/binlog_query_dispatcher_spec.rb",
|
133
|
+
"spec/flydata/fluent-plugins/mysql/table_meta_spec.rb",
|
130
134
|
"spec/flydata/heroku_spec.rb",
|
131
135
|
"spec/flydata/output/forwarder_spec.rb",
|
132
136
|
"spec/flydata/parser/mysql/alter_table_parser_spec.rb",
|
@@ -139,8 +143,7 @@ Gem::Specification.new do |s|
|
|
139
143
|
]
|
140
144
|
s.homepage = "http://flydata.com/"
|
141
145
|
s.licenses = ["All right reserved."]
|
142
|
-
s.
|
143
|
-
s.rubygems_version = "2.0.14"
|
146
|
+
s.rubygems_version = "2.2.2"
|
144
147
|
s.summary = "FlyData Agent"
|
145
148
|
|
146
149
|
if s.respond_to? :specification_version then
|
data/lib/flydata/command/base.rb
CHANGED
@@ -14,6 +14,7 @@ require_relative 'preference'
|
|
14
14
|
require_relative 'mysql/binlog_position_file'
|
15
15
|
require_relative 'mysql/binlog_record_dispatcher'
|
16
16
|
require_relative 'mysql/context'
|
17
|
+
require_relative 'mysql/table_meta'
|
17
18
|
|
18
19
|
#Monkey-patch fluentd class (EngineClass) to support shutdown for input plugin.
|
19
20
|
#This will be called when USR1 signal is received
|
@@ -69,9 +70,14 @@ class MysqlBinlogFlydataInput < MysqlBinlogInput
|
|
69
70
|
end
|
70
71
|
sync_fm = Flydata::FileUtil::SyncFileManager.new(nil) # Passing nil for data_entry as this class does not use methods which require data_entry
|
71
72
|
|
73
|
+
table_meta = Mysql::TableMeta.new(
|
74
|
+
mysql_url: mysql_url, database: @database, tables: @tables)
|
75
|
+
table_meta.update
|
76
|
+
|
72
77
|
@context = Mysql::Context.new(
|
73
78
|
database: @database, tables: @tables,
|
74
|
-
tag: @tag, sync_fm: sync_fm, omit_events: @omit_events
|
79
|
+
tag: @tag, sync_fm: sync_fm, omit_events: @omit_events,
|
80
|
+
table_meta: table_meta,
|
75
81
|
)
|
76
82
|
@record_dispatcher = Mysql::FlydataBinlogRecordDispatcher.new(@context)
|
77
83
|
end
|
@@ -42,25 +42,34 @@ module Mysql
|
|
42
42
|
|
43
43
|
def emit_rows(type, record)
|
44
44
|
emit_record(type, record) do |opt|
|
45
|
+
table_name = record['table_name']
|
45
46
|
records = record["rows"].collect do |row|
|
46
47
|
row = yield(row) if block_given? # Give the caller a chance to generate the correct row
|
47
|
-
{ ROW => convert_to_flydata_row_format(row) }
|
48
|
+
{ ROW => convert_to_flydata_row_format(table_name, row) }
|
48
49
|
end
|
49
50
|
encode_signless_integer(records, record["columns"])
|
50
51
|
records
|
51
52
|
end
|
52
53
|
end
|
53
54
|
|
54
|
-
def convert_to_flydata_row_format(row)
|
55
|
+
def convert_to_flydata_row_format(table_name, row)
|
55
56
|
row.each.with_index(1).inject({}) do |h, (v, i)|
|
56
57
|
if v.kind_of?(String)
|
57
|
-
v =
|
58
|
+
v = encode_row_value(table_name, v)
|
58
59
|
end
|
59
60
|
h[i.to_s] = v
|
60
61
|
h
|
61
62
|
end
|
62
63
|
end
|
63
64
|
|
65
|
+
def encode_row_value(table_name, value)
|
66
|
+
if src_encoding = @table_meta[table_name][:encoding]
|
67
|
+
value.encode('utf-8', src_encoding, :undef => :replace, :invalid => :replace)
|
68
|
+
else
|
69
|
+
value.encode('utf-16', :undef => :replace, :invalid => :replace).encode('utf-8')
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
64
73
|
def encode_signless_integer(records, column_types)
|
65
74
|
records.each do |record|
|
66
75
|
record[ROW].keys.each do |position|
|
@@ -0,0 +1,83 @@
|
|
1
|
+
require 'mysql2'
|
2
|
+
|
3
|
+
module Mysql
|
4
|
+
class TableMeta
|
5
|
+
MANDATORY_OPTS = [
|
6
|
+
:mysql_url, :database, :tables
|
7
|
+
]
|
8
|
+
OPTIONAL_OPTS = [
|
9
|
+
]
|
10
|
+
|
11
|
+
GET_TABLE_META_SQL = <<EOT
|
12
|
+
SELECT
|
13
|
+
T.table_name as table_name,
|
14
|
+
CCSA.character_set_name as character_set_name
|
15
|
+
FROM
|
16
|
+
information_schema.`TABLES` T,
|
17
|
+
information_schema.`COLLATION_CHARACTER_SET_APPLICABILITY` CCSA
|
18
|
+
WHERE
|
19
|
+
CCSA.collation_name = T.table_collation
|
20
|
+
AND T.table_schema = '%{database}'
|
21
|
+
AND T.table_name in (%{tables});
|
22
|
+
EOT
|
23
|
+
|
24
|
+
def initialize(opts)
|
25
|
+
missing_opts = MANDATORY_OPTS - opts.keys
|
26
|
+
raise "Mandatory option(s) are missing: #{missing_opts.join(', ')}" unless (missing_opts.empty?)
|
27
|
+
@mysql_url = opts[:mysql_url]
|
28
|
+
@database = opts[:database]
|
29
|
+
@tables = opts[:tables]
|
30
|
+
@table_meta = Hash.new{|h, k| h[k] = {}}
|
31
|
+
end
|
32
|
+
|
33
|
+
def update
|
34
|
+
conn = Mysql2::Client.new(@mysql_url)
|
35
|
+
sql = GET_TABLE_META_SQL % {
|
36
|
+
database: @database, tables: @tables.collect{|t| "'#{t}'"}.join(',') }
|
37
|
+
columns = conn.query(sql)
|
38
|
+
columns.collect do |col|
|
39
|
+
@table_meta[col['table_name'].to_sym][:encoding] = get_ruby_charset_name(col['character_set_name'])
|
40
|
+
end
|
41
|
+
ensure
|
42
|
+
conn.close rescue nil if conn
|
43
|
+
end
|
44
|
+
|
45
|
+
# Charset naming conversion rule. mysql => ruby
|
46
|
+
#
|
47
|
+
# mysql
|
48
|
+
# http://dev.mysql.com/doc/refman/5.6/en/charset-charsets.html
|
49
|
+
# mysql(supported CJK character sets)
|
50
|
+
# http://dev.mysql.com/doc/refman/5.6/en/faqs-cjk.html#qandaitem-A-11-1-1
|
51
|
+
# For ruby, you can see encoding list with "Encoding.list"
|
52
|
+
CHARSET_ENCODE_RULE = {
|
53
|
+
'ascii' => nil, # 'ASCII-8BIT', (not need to be encoded)
|
54
|
+
'utf8' => nil, # 'UTF-8', (not need to be encoded)
|
55
|
+
'utf16' => 'UTF-16',
|
56
|
+
'utf32' => 'UTF-32',
|
57
|
+
'latin1' => 'ISO-8859-1',
|
58
|
+
'latin2' => 'ISO-8859-2',
|
59
|
+
'big5' => 'Big5',
|
60
|
+
'cp932' => 'CP932',
|
61
|
+
'eucjpms' => 'eucJP-ms',
|
62
|
+
'euckr' => 'EUC-KR',
|
63
|
+
'gb18030' => 'GB18030',
|
64
|
+
'gb2312' => 'GB2312',
|
65
|
+
'gbk' => 'GBK',
|
66
|
+
'sjis' => 'Shift_JIS',
|
67
|
+
'ujis' => 'EUC-JP',
|
68
|
+
}
|
69
|
+
|
70
|
+
def get_ruby_charset_name(mysql_charset)
|
71
|
+
return nil if mysql_charset.to_s.empty?
|
72
|
+
raise "Unsupported charset:#{mysql_charset}." unless CHARSET_ENCODE_RULE.has_key?(mysql_charset)
|
73
|
+
charset = CHARSET_ENCODE_RULE[mysql_charset]
|
74
|
+
return charset
|
75
|
+
end
|
76
|
+
|
77
|
+
# Return table meta
|
78
|
+
# :character_set_name
|
79
|
+
def [](table_name)
|
80
|
+
@table_meta[table_name.to_sym]
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
data/spec/flydata/cli_spec.rb
CHANGED
@@ -225,6 +225,7 @@ EOT
|
|
225
225
|
setup_initial_flydata_files
|
226
226
|
allow(MysqlBinlogInput::BinlogUtil).to receive(:to_hash) {|e| e}
|
227
227
|
allow(Mysql::BinLogPositionFile).to receive(:new).with(TEST_POSITION_FILE).and_return(binlog_position_file)
|
228
|
+
allow(Mysql::TableMeta).to receive(:update)
|
228
229
|
allow(plugin).to receive(:`).with("mysql -V").and_return("mysql Ver 14.14 Distrib 5.5.40")
|
229
230
|
allow(plugin).to receive(:`).with(/^echo 'select version\(\);'/).and_return("version()\n5.5.40-0ubuntu0.12.04.1-log")
|
230
231
|
Timecop.freeze(now)
|
@@ -1,4 +1,4 @@
|
|
1
|
-
|
1
|
+
require 'fluent_plugins_spec_helper'
|
2
2
|
require 'flydata/fluent-plugins/mysql/alter_table_query_handler'
|
3
3
|
|
4
4
|
module Mysql
|
@@ -10,11 +10,13 @@ module Mysql
|
|
10
10
|
end
|
11
11
|
let(:database) { "testdb" }
|
12
12
|
let(:table) { "foo" }
|
13
|
+
let(:table_meta) { double'table_meta' }
|
13
14
|
let(:context) do
|
14
15
|
r = double('context')
|
15
16
|
allow(r).to receive(:sync_fm).and_return(sync_fm)
|
16
17
|
allow(r).to receive(:database).and_return([database])
|
17
18
|
allow(r).to receive(:tables).and_return([table])
|
19
|
+
allow(r).to receive(:table_meta).and_return(table_meta)
|
18
20
|
r
|
19
21
|
end
|
20
22
|
subject { described_class.new(context) }
|
@@ -38,7 +40,8 @@ module Mysql
|
|
38
40
|
r
|
39
41
|
end
|
40
42
|
before do
|
41
|
-
|
43
|
+
parser_class = ParserProvider.parser(:mysql, :mysql_alter_table)
|
44
|
+
allow(parser_class).to receive(:new).and_return(parser)
|
42
45
|
allow(subject).to receive(:acceptable_table?).and_return(true)
|
43
46
|
allow(subject).to receive(:acceptable_db?).and_return(true)
|
44
47
|
allow(subject).to receive(:check_empty_binlog)
|
@@ -0,0 +1,61 @@
|
|
1
|
+
require 'fluent_plugins_spec_helper'
|
2
|
+
require 'flydata/fluent-plugins/mysql/table_meta'
|
3
|
+
|
4
|
+
module Mysql
|
5
|
+
describe TableMeta do
|
6
|
+
let(:mysql_url) { double('mysql_url') }
|
7
|
+
let(:database) { 'test-db' }
|
8
|
+
let(:tables) { %w(a_table b_table c_table) }
|
9
|
+
|
10
|
+
let(:conn) { double('conn') }
|
11
|
+
let(:table_meta) { TableMeta.new(
|
12
|
+
mysql_url: mysql_url, database: database, tables: tables) }
|
13
|
+
|
14
|
+
before do
|
15
|
+
allow(conn).to receive(:close)
|
16
|
+
allow(Mysql2::Client).to receive(:new).and_return(conn)
|
17
|
+
end
|
18
|
+
|
19
|
+
describe '.update' do
|
20
|
+
let(:query_result) {[]}
|
21
|
+
before do
|
22
|
+
allow(conn).to receive(:query).and_return(query_result)
|
23
|
+
end
|
24
|
+
|
25
|
+
context 'when character_set_name is supported' do
|
26
|
+
context 'when encoding is not necessary' do
|
27
|
+
let(:query_result) {[
|
28
|
+
{'table_name' => 'a_table', 'character_set_name' => 'utf8' }
|
29
|
+
]}
|
30
|
+
it 'set nil for encoding' do
|
31
|
+
table_meta.update
|
32
|
+
expect(table_meta['a_table'][:encoding]).to be_nil
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
context 'when encoding is needed' do
|
37
|
+
let(:query_result) {[
|
38
|
+
{'table_name' => 'a_table', 'character_set_name' => 'latin1' },
|
39
|
+
{'table_name' => 'b_table', 'character_set_name' => 'cp932' }
|
40
|
+
]}
|
41
|
+
it 'set ruby encoding encoding' do
|
42
|
+
table_meta.update
|
43
|
+
expect(table_meta['a_table'][:encoding]).to eq('ISO-8859-1')
|
44
|
+
expect(table_meta['b_table'][:encoding]).to eq('CP932')
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
context 'when character_set_name is not supported' do
|
50
|
+
let(:query_result) {[
|
51
|
+
{'table_name' => 'a_table', 'character_set_name' => 'xxxx' }
|
52
|
+
]}
|
53
|
+
it 'raise an error' do
|
54
|
+
expect{table_meta.update}.to raise_error('Unsupported charset:xxxx.')
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
|
data/spec/spec_helper.rb
CHANGED
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.2.
|
4
|
+
version: 0.2.21
|
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: 2014-12-
|
15
|
+
date: 2014-12-12 00:00:00.000000000 Z
|
16
16
|
dependencies:
|
17
17
|
- !ruby/object:Gem::Dependency
|
18
18
|
name: rest-client
|
@@ -485,6 +485,7 @@ files:
|
|
485
485
|
- lib/flydata/fluent-plugins/mysql/context.rb
|
486
486
|
- lib/flydata/fluent-plugins/mysql/ddl_query_handler.rb
|
487
487
|
- lib/flydata/fluent-plugins/mysql/dml_record_handler.rb
|
488
|
+
- lib/flydata/fluent-plugins/mysql/table_meta.rb
|
488
489
|
- lib/flydata/fluent-plugins/out_forward_ssl.rb
|
489
490
|
- lib/flydata/fluent-plugins/preference.rb
|
490
491
|
- lib/flydata/flydata_crontab.sh
|
@@ -512,6 +513,7 @@ files:
|
|
512
513
|
- spec/flydata/fluent-plugins/mysql/alter_table_query_handler_spec.rb
|
513
514
|
- spec/flydata/fluent-plugins/mysql/binlog_position_spec.rb
|
514
515
|
- spec/flydata/fluent-plugins/mysql/binlog_query_dispatcher_spec.rb
|
516
|
+
- spec/flydata/fluent-plugins/mysql/table_meta_spec.rb
|
515
517
|
- spec/flydata/heroku_spec.rb
|
516
518
|
- spec/flydata/output/forwarder_spec.rb
|
517
519
|
- spec/flydata/parser/mysql/alter_table_parser_spec.rb
|
@@ -541,7 +543,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
541
543
|
version: '0'
|
542
544
|
requirements: []
|
543
545
|
rubyforge_project:
|
544
|
-
rubygems_version: 2.
|
546
|
+
rubygems_version: 2.2.2
|
545
547
|
signing_key:
|
546
548
|
specification_version: 4
|
547
549
|
summary: FlyData Agent
|