flydata 0.6.3 → 0.6.4
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/Rakefile +2 -2
- data/VERSION +1 -1
- data/bin/fdredshift +78 -0
- data/circle.yml +1 -1
- data/ext/flydata/{parser/mysql → source_mysql/parser}/.gitignore +0 -0
- data/ext/flydata/{parser/mysql → source_mysql/parser}/dump_parser_ext.cpp +3 -3
- data/ext/flydata/source_mysql/parser/extconf.rb +3 -0
- data/ext/flydata/{parser/mysql → source_mysql/parser}/parser.txt +0 -0
- data/ext/flydata/{parser/mysql → source_mysql/parser}/sql_parser.cpp +0 -0
- data/ext/flydata/{parser/mysql → source_mysql/parser}/sql_parser.h +0 -0
- data/flydata-core/lib/flydata-core/mysql/binlog_pos.rb +34 -32
- data/flydata-core/lib/flydata-core/mysql/compatibility_checker.rb +20 -0
- data/flydata-core/lib/flydata-core/table_def/mysql_table_def.rb +12 -4
- data/flydata-core/lib/flydata-core/table_def/redshift_table_def.rb +60 -6
- data/flydata-core/spec/mysql/binlog_pos_spec.rb +474 -0
- data/flydata-core/spec/table_def/mysql_table_def_spec.rb +57 -0
- data/flydata-core/spec/table_def/mysql_to_redshift_table_def_spec.rb +174 -20
- data/flydata-core/spec/table_def/mysqldump_test_col_comment_with_AUTO_INCREMENT_keyword.dump +43 -0
- data/flydata-core/spec/table_def/mysqldump_test_col_comment_with_not_null_keyword.dump +43 -0
- data/flydata-core/spec/table_def/mysqldump_test_col_comment_with_unique_keyword.dump +43 -0
- data/flydata-core/spec/table_def/mysqldump_test_col_comment_with_unsigned_keyword.dump +43 -0
- data/flydata-core/spec/table_def/redshift_table_def_spec.rb +41 -8
- data/flydata.gemspec +0 -0
- data/lib/flydata/cli.rb +11 -5
- data/lib/flydata/command/base.rb +14 -1
- data/lib/flydata/command/exclusive_runnable.rb +42 -12
- data/lib/flydata/command/helper.rb +6 -6
- data/lib/flydata/command/sender.rb +4 -3
- data/lib/flydata/command/setup.rb +30 -381
- data/lib/flydata/command/stop.rb +1 -0
- data/lib/flydata/command/sync.rb +273 -301
- data/lib/flydata/compatibility_check.rb +24 -117
- data/lib/flydata/fluent-plugins/in_mysql_binlog_flydata.rb +3 -3
- data/lib/flydata/fluent-plugins/mysql/alter_table_query_handler.rb +2 -2
- data/lib/flydata/fluent-plugins/mysql/binlog_record_handler.rb +6 -6
- data/lib/flydata/fluent-plugins/mysql/truncate_table_query_handler.rb +0 -1
- data/lib/flydata/parser.rb +14 -0
- data/lib/flydata/{parser_provider.rb → parser/parser_provider.rb} +6 -4
- data/lib/flydata/parser/source_table.rb +33 -0
- data/lib/flydata/source.rb +105 -0
- data/lib/flydata/source/component.rb +21 -0
- data/lib/flydata/source/errors.rb +7 -0
- data/lib/flydata/source/generate_source_dump.rb +72 -0
- data/lib/flydata/source/parse_dump_and_send.rb +52 -0
- data/lib/flydata/source/setup.rb +31 -0
- data/lib/flydata/source/source_pos.rb +45 -0
- data/lib/flydata/source/sync.rb +56 -0
- data/lib/flydata/source/sync_generate_table_ddl.rb +43 -0
- data/lib/flydata/source_file/setup.rb +17 -0
- data/lib/flydata/source_file/sync.rb +14 -0
- data/lib/flydata/{command → source_mysql/command}/mysql.rb +2 -1
- data/lib/flydata/{command → source_mysql/command}/mysql_command_base.rb +2 -4
- data/lib/flydata/{command → source_mysql/command}/mysqlbinlog.rb +2 -1
- data/lib/flydata/{command → source_mysql/command}/mysqldump.rb +2 -1
- data/lib/flydata/source_mysql/generate_source_dump.rb +53 -0
- data/lib/flydata/source_mysql/mysql_compatibility_check.rb +114 -0
- data/lib/flydata/source_mysql/parse_dump_and_send.rb +28 -0
- data/lib/flydata/{parser/mysql → source_mysql/parser}/.gitignore +0 -0
- data/lib/flydata/{parser/mysql → source_mysql/parser}/dump_parser.rb +32 -67
- data/lib/flydata/{parser/mysql → source_mysql/parser}/mysql_alter_table.treetop +0 -0
- data/lib/flydata/source_mysql/setup.rb +24 -0
- data/lib/flydata/source_mysql/source_pos.rb +21 -0
- data/lib/flydata/source_mysql/sync.rb +45 -0
- data/lib/flydata/source_mysql/sync_generate_table_ddl.rb +40 -0
- data/lib/flydata/{mysql → source_mysql}/table_ddl.rb +6 -17
- data/lib/flydata/source_zendesk/sync_generate_table_ddl.rb +30 -0
- data/lib/flydata/source_zendesk/zendesk_flydata_tabledefs.rb +133 -0
- data/lib/flydata/sync_file_manager.rb +132 -73
- data/lib/flydata/table_ddl.rb +18 -0
- data/spec/flydata/cli_spec.rb +1 -0
- data/spec/flydata/command/exclusive_runnable_spec.rb +19 -8
- data/spec/flydata/command/sender_spec.rb +1 -1
- data/spec/flydata/command/setup_spec.rb +4 -4
- data/spec/flydata/command/sync_spec.rb +97 -134
- data/spec/flydata/compatibility_check_spec.rb +16 -289
- data/spec/flydata/fluent-plugins/mysql/alter_table_query_handler_spec.rb +3 -3
- data/spec/flydata/fluent-plugins/mysql/dml_record_handler_spec.rb +1 -1
- data/spec/flydata/fluent-plugins/mysql/shared_query_handler_context.rb +4 -2
- data/spec/flydata/fluent-plugins/mysql/truncate_query_handler_spec.rb +1 -1
- data/spec/flydata/source_mysql/generate_source_dump_spec.rb +69 -0
- data/spec/flydata/source_mysql/mysql_compatibility_check_spec.rb +280 -0
- data/spec/flydata/{parser/mysql → source_mysql/parser}/alter_table_parser_spec.rb +2 -2
- data/spec/flydata/{parser/mysql → source_mysql/parser}/dump_parser_spec.rb +75 -70
- data/spec/flydata/source_mysql/sync_generate_table_ddl_spec.rb +137 -0
- data/spec/flydata/{mysql → source_mysql}/table_ddl_spec.rb +2 -2
- data/spec/flydata/source_spec.rb +140 -0
- data/spec/flydata/source_zendesk/sync_generate_table_ddl_spec.rb +33 -0
- data/spec/flydata/sync_file_manager_spec.rb +157 -77
- data/tmpl/redshift_mysql_data_entry.conf.tmpl +1 -1
- metadata +56 -23
- data/ext/flydata/parser/mysql/extconf.rb +0 -3
- data/lib/flydata/mysql/binlog_position.rb +0 -22
- data/spec/flydata/mysql/binlog_position_spec.rb +0 -35
|
@@ -1,22 +1,11 @@
|
|
|
1
|
-
require 'flydata/
|
|
1
|
+
require 'flydata/table_ddl'
|
|
2
2
|
require 'flydata-core/mysql/command_generator'
|
|
3
|
+
require 'flydata-core/mysql/binlog_pos'
|
|
3
4
|
|
|
4
5
|
module Flydata
|
|
5
|
-
module
|
|
6
|
+
module SourceMysql
|
|
6
7
|
|
|
7
8
|
class TableDdl
|
|
8
|
-
VERSION0 = 0 # the version where no .generated_ddl file was generated.
|
|
9
|
-
# Therefore, this version never shows up in anywhere.
|
|
10
|
-
VERSION1 = 1 # the version which doesn't handle server side encoding support.
|
|
11
|
-
VERSION2 = 2 # the version with server side encoding support, migrated from
|
|
12
|
-
# the previous versions. Format/functionality-wise, it's the
|
|
13
|
-
# same as Version 3.
|
|
14
|
-
VERSION3 = 3 # the version with server side encoding support, generated by
|
|
15
|
-
# sync:generated_table_ddl command.
|
|
16
|
-
VERSION4 = 4 # the version with server side encoding support, generated by
|
|
17
|
-
# the auto-generated CREATE TABLE event.
|
|
18
|
-
VERSION = VERSION3
|
|
19
|
-
|
|
20
9
|
def self.migrate_tables(tables, mysql_opts, sync_fm, position_file, context,
|
|
21
10
|
&block)
|
|
22
11
|
migrate_to_v2(tables, mysql_opts, sync_fm, position_file, context, &block)
|
|
@@ -24,7 +13,7 @@ class TableDdl
|
|
|
24
13
|
|
|
25
14
|
private
|
|
26
15
|
|
|
27
|
-
V2_TARGET_VERSION = VERSION2
|
|
16
|
+
V2_TARGET_VERSION = Flydata::TableDdl::VERSION2
|
|
28
17
|
EVENT_TYPE = 'Query'
|
|
29
18
|
ALTER_TABLE_CHARSET_SQL = <<EOS.strip
|
|
30
19
|
ALTER TABLE `%s`.`%s` CHARACTER SET = %s;
|
|
@@ -60,9 +49,9 @@ EOS
|
|
|
60
49
|
mysql_tabledef = mysql_tabledefs[table]
|
|
61
50
|
if binlog_pos.nil?
|
|
62
51
|
# get binlog position
|
|
63
|
-
binlog_pos =
|
|
52
|
+
binlog_pos = FlydataCore::Mysql::BinlogPos.new(File.open(position_file){|f| f.read })
|
|
64
53
|
original_binlog_file = context.current_binlog_file
|
|
65
|
-
context.current_binlog_file = binlog_pos.
|
|
54
|
+
context.current_binlog_file = binlog_pos.filename
|
|
66
55
|
end
|
|
67
56
|
# get charset
|
|
68
57
|
charset = mysql_tabledef.default_charset_mysql
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
require 'flydata/source/sync_generate_table_ddl'
|
|
2
|
+
require 'flydata/source_zendesk/zendesk_flydata_tabledefs'
|
|
3
|
+
|
|
4
|
+
module Flydata
|
|
5
|
+
module SourceZendesk
|
|
6
|
+
|
|
7
|
+
class SyncGenerateTableDdl < Source::SyncGenerateTableDdl
|
|
8
|
+
def run_compatibility_check
|
|
9
|
+
#TODO Check version "Zendesk v2 API"
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def generate_flydata_tabledef(tables, options)
|
|
13
|
+
flydata_tabledefs = []
|
|
14
|
+
error_list = []
|
|
15
|
+
zendesk_resource_names = ZENDESK_FLYDATA_TABLEDEFS.keys.join(" ")
|
|
16
|
+
|
|
17
|
+
tables.each do |tablename|
|
|
18
|
+
flydata_tabledef = ZENDESK_FLYDATA_TABLEDEFS[tablename]
|
|
19
|
+
if !flydata_tabledef
|
|
20
|
+
error_list << { error: "Invalid Zendesk resource name specified. Flydata supports following Zendesk resources: #{zendesk_resource_names}", table: tablename }
|
|
21
|
+
next
|
|
22
|
+
end
|
|
23
|
+
flydata_tabledefs << flydata_tabledef
|
|
24
|
+
end
|
|
25
|
+
[flydata_tabledefs, error_list]
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
end
|
|
30
|
+
end
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
module Flydata
|
|
2
|
+
module SourceZendesk
|
|
3
|
+
|
|
4
|
+
class SyncGenerateTableDdl < Source::SyncGenerateTableDdl
|
|
5
|
+
ZENDESK_FLYDATA_TABLEDEFS =
|
|
6
|
+
{"tickets"=>
|
|
7
|
+
{:table_name=>"tickets",
|
|
8
|
+
:columns=>
|
|
9
|
+
[{:column=>"id", :type=>"int8(20)", :not_null=>true, :primary_key=>true},
|
|
10
|
+
{:column=>"url", :type=>"varchar(8000)", :default=>nil},#RFC7231 8000 octets
|
|
11
|
+
{:column=>"external_id", :type=>"varchar(2047)", :default=>nil},
|
|
12
|
+
{:column=>"type", :type=>"varchar(24)", :default=>nil},
|
|
13
|
+
{:column=>"subject", :type=>"text"},
|
|
14
|
+
{:column=>"raw_subject", :type=>"text"},
|
|
15
|
+
{:column=>"description", :type=>"text"},
|
|
16
|
+
{:column=>"priority", :type=>"varchar(24)", :default=>nil},
|
|
17
|
+
{:column=>"status", :type=>"varchar(24)", :default=>nil},
|
|
18
|
+
{:column=>"recipient", :type=>"varchar(762)", :default=>nil},#email
|
|
19
|
+
{:column=>"requester_id", :type=>"int8(20)", :default=>nil},
|
|
20
|
+
{:column=>"submitter_id", :type=>"int8(20)", :default=>nil},
|
|
21
|
+
{:column=>"assignee_id", :type=>"int8(20)", :default=>nil},
|
|
22
|
+
{:column=>"organization_id", :type=>"int8(20)", :default=>nil},
|
|
23
|
+
{:column=>"group_id", :type=>"int8(20)", :default=>nil},
|
|
24
|
+
{:column=>"collaborator_ids", :type=>"text"},
|
|
25
|
+
{:column=>"forum_topic_id", :type=>"int8(20)", :default=>nil},
|
|
26
|
+
{:column=>"problem_id", :type=>"int8(20)", :default=>nil},
|
|
27
|
+
{:column=>"has_incidents", :type=>"int1(1)", :default=>nil},
|
|
28
|
+
{:column=>"due_at", :type=>"datetime", :default=>nil},
|
|
29
|
+
{:column=>"tags", :type=>"text"},
|
|
30
|
+
{:column=>"via", :type=>"text"},
|
|
31
|
+
{:column=>"custom_fields", :type=>"text"},
|
|
32
|
+
{:column=>"satisfaction_rating", :type=>"text"},
|
|
33
|
+
{:column=>"sharing_agreement_ids", :type=>"text"},
|
|
34
|
+
{:column=>"followup_ids", :type=>"text"},
|
|
35
|
+
{:column=>"ticket_form_id", :type=>"int8(20)", :default=>nil},
|
|
36
|
+
{:column=>"brand_id", :type=>"int8(20)", :default=>nil},
|
|
37
|
+
{:column=>"created_at", :type=>"datetime", :default=>nil},
|
|
38
|
+
{:column=>"updated_at", :type=>"datetime", :default=>nil}],
|
|
39
|
+
:default_charset=>"UTF_8",
|
|
40
|
+
:src_ddl=> '{"version":"Zendesk v2 API","url":"https://developer.zendesk.com/rest_api/docs/core/tickets”}'
|
|
41
|
+
},
|
|
42
|
+
"ticket_comments"=>
|
|
43
|
+
{:table_name=>"ticket_comments",
|
|
44
|
+
:columns=>
|
|
45
|
+
[{:column=>"id", :type=>"int8(20)", :not_null=>true, :primary_key=>true},
|
|
46
|
+
{:column=>"type", :type=>"varchar(24)", :default=>nil},
|
|
47
|
+
{:column=>"body", :type=>"text"},
|
|
48
|
+
{:column=>"html_body", :type=>"text"},
|
|
49
|
+
{:column=>"public", :type=>"int1(1)", :default=>nil},
|
|
50
|
+
{:column=>"author_id", :type=>"int8(20)", :default=>nil},
|
|
51
|
+
{:column=>"attachments", :type=>"text"},
|
|
52
|
+
{:column=>"via", :type=>"text"},
|
|
53
|
+
{:column=>"metadata", :type=>"text"},
|
|
54
|
+
{:column=>"created_at", :type=>"datetime", :default=>nil}],
|
|
55
|
+
:default_charset=>"UTF_8",
|
|
56
|
+
:src_ddl=> '{"version":"Zendesk v2 API","url":"https://developer.zendesk.com/rest_api/docs/core/ticket_comments”}'
|
|
57
|
+
},
|
|
58
|
+
"ticket_audits"=>
|
|
59
|
+
{:table_name=>"ticket_audits",
|
|
60
|
+
:columns=>
|
|
61
|
+
[{:column=>"id", :type=>"int8(20)", :not_null=>true, :primary_key=>true},
|
|
62
|
+
{:column=>"ticket_id", :type=>"int8(20)", :default=>nil},
|
|
63
|
+
{:column=>"metadata", :type=>"text"},
|
|
64
|
+
{:column=>"via", :type=>"text"},
|
|
65
|
+
{:column=>"created_at", :type=>"datetime", :default=>nil},
|
|
66
|
+
{:column=>"author_id", :type=>"int8(20)", :default=>nil},
|
|
67
|
+
{:column=>"events", :type=>"text"}],
|
|
68
|
+
:default_charset=>"UTF_8",
|
|
69
|
+
:src_ddl=> '{"version":"Zendesk v2 API","url":"https://developer.zendesk.com/rest_api/docs/core/ticket_audits”}'
|
|
70
|
+
},
|
|
71
|
+
"users"=>
|
|
72
|
+
{:table_name=>"users",
|
|
73
|
+
:columns=>
|
|
74
|
+
[{:column=>"id", :type=>"int8(20)", :not_null=>true, :primary_key=>true},
|
|
75
|
+
{:column=>"url", :type=>"varchar(8000)", :default=>nil},#RFC 7230 recommendation (8000 octets)
|
|
76
|
+
{:column=>"name", :type=>"varchar(6141)", :default=>nil},
|
|
77
|
+
{:column=>"external_id", :type=>"varchar(2047)", :default=>nil},
|
|
78
|
+
{:column=>"alias", :type=>"varchar(6141)", :default=>nil},
|
|
79
|
+
{:column=>"created_at", :type=>"datetime", :default=>nil},
|
|
80
|
+
{:column=>"updated_at", :type=>"datetime", :default=>nil},
|
|
81
|
+
{:column=>"active", :type=>"int1(1)", :default=>nil},
|
|
82
|
+
{:column=>"verified", :type=>"int1(1)", :default=>nil},
|
|
83
|
+
{:column=>"shared", :type=>"int1(1)", :default=>nil},
|
|
84
|
+
{:column=>"shared_agent", :type=>"int1(1)", :default=>nil},
|
|
85
|
+
{:column=>"locale", :type=>"varchar(765)", :default=>nil},
|
|
86
|
+
{:column=>"locale_id", :type=>"int4(11)", :default=>nil},
|
|
87
|
+
{:column=>"time_zone", :type=>"varchar(765)", :default=>nil},
|
|
88
|
+
{:column=>"last_login_at", :type=>"datetime", :default=>nil},
|
|
89
|
+
{:column=>"two_factor_auth_enabled", :type=>"int1(1)", :default=>nil},
|
|
90
|
+
{:column=>"email", :type=>"varchar(762)", :default=>nil},
|
|
91
|
+
{:column=>"phone", :type=>"varchar(765)", :default=>nil},
|
|
92
|
+
{:column=>"signature", :type=>"text"},
|
|
93
|
+
{:column=>"details", :type=>"text"},
|
|
94
|
+
{:column=>"notes", :type=>"text"},
|
|
95
|
+
{:column=>"organization_id", :type=>"int8(20)", :default=>nil},
|
|
96
|
+
{:column=>"role", :type=>"varchar(24)", :default=>nil},
|
|
97
|
+
{:column=>"custom_role_id", :type=>"int8(20)", :default=>nil},
|
|
98
|
+
{:column=>"moderator", :type=>"int1(1)", :default=>nil},
|
|
99
|
+
{:column=>"ticket_restriction", :type=>"varchar(24)", :default=>nil},
|
|
100
|
+
{:column=>"only_private_comments", :type=>"int1(1)", :default=>nil},
|
|
101
|
+
{:column=>"tags", :type=>"text"},
|
|
102
|
+
{:column=>"suspended", :type=>"int1(1)", :default=>nil},
|
|
103
|
+
{:column=>"restricted_agent", :type=>"int1(1)", :default=>nil},
|
|
104
|
+
{:column=>"photo", :type=>"text"},
|
|
105
|
+
{:column=>"user_fields", :type=>"text"}],
|
|
106
|
+
:default_charset=>"UTF_8",
|
|
107
|
+
:src_ddl=> '{"version":"Zendesk v2 API","url":"https://developer.zendesk.com/rest_api/docs/core/users”}'
|
|
108
|
+
},
|
|
109
|
+
"organizations"=>
|
|
110
|
+
{:table_name=>"organizations",
|
|
111
|
+
:columns=>
|
|
112
|
+
[{:column=>"id", :type=>"int8(20)", :not_null=>true, :primary_key=>true},
|
|
113
|
+
{:column=>"url", :type=>"varchar(8000)", :default=>nil},
|
|
114
|
+
{:column=>"external_id", :type=>"varchar(2047)", :default=>nil},
|
|
115
|
+
{:column=>"name", :type=>"varchar(6141)", :default=>nil},
|
|
116
|
+
{:column=>"created_at", :type=>"datetime", :default=>nil},
|
|
117
|
+
{:column=>"updated_at", :type=>"datetime", :default=>nil},
|
|
118
|
+
{:column=>"domain_names", :type=>"text"},
|
|
119
|
+
{:column=>"details", :type=>"text"},
|
|
120
|
+
{:column=>"notes", :type=>"text"},
|
|
121
|
+
{:column=>"group_id", :type=>"int8(20)", :default=>nil},
|
|
122
|
+
{:column=>"shared_tickets", :type=>"int1(1)", :default=>nil},
|
|
123
|
+
{:column=>"shared_comments", :type=>"int1(1)", :default=>nil},
|
|
124
|
+
{:column=>"tags", :type=>"text"},
|
|
125
|
+
{:column=>"organization_fields", :type=>"text"}],
|
|
126
|
+
:default_charset=>"UTF_8",
|
|
127
|
+
:src_ddl=> '{"version":"Zendesk v2 API","url":"https://developer.zendesk.com/rest_api/docs/core/organizations”}'
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
end
|
|
133
|
+
end
|
|
@@ -1,6 +1,9 @@
|
|
|
1
|
-
require 'mysql2'
|
|
2
1
|
require 'flydata-core/query_job'
|
|
2
|
+
require 'flydata/parser/source_table' # Required for Marshal.load
|
|
3
|
+
require 'flydata/parser'
|
|
3
4
|
require 'set'
|
|
5
|
+
require 'flydata/source'
|
|
6
|
+
require 'flydata/source/source_pos'
|
|
4
7
|
|
|
5
8
|
module Flydata
|
|
6
9
|
class SyncFileManager
|
|
@@ -9,12 +12,17 @@ module Flydata
|
|
|
9
12
|
TABLE_POSITIONS_DIR = ENV['FLYDATA_TABLE_POSITIONS'] || File.join(FLYDATA_HOME, 'positions')
|
|
10
13
|
SYNC_TABLE_POSITIONS = 0
|
|
11
14
|
|
|
12
|
-
def initialize(data_entry)
|
|
15
|
+
def initialize(data_entry, source = nil)
|
|
13
16
|
@data_entry = data_entry
|
|
17
|
+
@source = source #for Source dependent objects
|
|
14
18
|
@table_position_files = {} # File objects keyed by table name
|
|
15
19
|
@sync_table_positions_count = SYNC_TABLE_POSITIONS
|
|
16
20
|
end
|
|
17
21
|
|
|
22
|
+
def source
|
|
23
|
+
@source
|
|
24
|
+
end
|
|
25
|
+
|
|
18
26
|
def close
|
|
19
27
|
@table_position_files.values.each {|f| f.close }
|
|
20
28
|
@table_position_files = {}
|
|
@@ -29,21 +37,19 @@ module Flydata
|
|
|
29
37
|
dump_file_path + ".pos"
|
|
30
38
|
end
|
|
31
39
|
|
|
32
|
-
def save_dump_pos(status, table_name, last_pos,
|
|
40
|
+
def save_dump_pos(status, table_name, last_pos, source_pos, state = nil, substate = nil)
|
|
33
41
|
File.open(dump_pos_path, 'w') do |f|
|
|
34
|
-
f.write(dump_pos_content(status, table_name, last_pos,
|
|
42
|
+
f.write(dump_pos_content(status, table_name, last_pos, source_pos, state, substate))
|
|
35
43
|
end
|
|
36
44
|
end
|
|
37
45
|
|
|
38
46
|
def load_dump_pos
|
|
39
47
|
path = dump_pos_path
|
|
40
48
|
return {} unless File.exists?(path)
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
{
|
|
45
|
-
binlog_pos: {binfile: items[3], pos: items[4].to_i},
|
|
46
|
-
state: items[5], substate: items[6], mysql_table: mysql_table}
|
|
49
|
+
content = File.open(path, 'r').readline
|
|
50
|
+
source_table = load_source_table_marshal_dump
|
|
51
|
+
|
|
52
|
+
dump_pos_content_to_hash(content).merge( { source_table: source_table} )
|
|
47
53
|
end
|
|
48
54
|
|
|
49
55
|
def load_generated_ddl(tables)
|
|
@@ -79,60 +85,73 @@ module Flydata
|
|
|
79
85
|
new_tables
|
|
80
86
|
end
|
|
81
87
|
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
88
|
+
SOURCE_TABLE_EXT = "mysql_table"
|
|
89
|
+
|
|
90
|
+
# SourceTable marshal file
|
|
91
|
+
def source_table_marshal_dump_path
|
|
92
|
+
dump_file_path + ".#{SOURCE_TABLE_EXT}"
|
|
85
93
|
end
|
|
86
94
|
|
|
87
|
-
def
|
|
88
|
-
File.open(
|
|
89
|
-
f.write Marshal.dump(
|
|
95
|
+
def save_source_table_marshal_dump(source_table)
|
|
96
|
+
File.open(source_table_marshal_dump_path, 'w') do |f|
|
|
97
|
+
f.write Marshal.dump(source_table)
|
|
90
98
|
end
|
|
91
99
|
end
|
|
92
100
|
|
|
93
101
|
# master binlog.pos file
|
|
94
|
-
def
|
|
95
|
-
path =
|
|
102
|
+
def save_source_pos(source_pos)
|
|
103
|
+
path = source_pos_path
|
|
96
104
|
File.open(path, 'w') do |f|
|
|
97
|
-
f.write(
|
|
105
|
+
f.write(source_pos.to_s)
|
|
98
106
|
end
|
|
99
107
|
end
|
|
100
108
|
|
|
101
|
-
def
|
|
109
|
+
def load_source_pos(file_path = source_pos_path)
|
|
102
110
|
return nil unless File.exists?(file_path)
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
111
|
+
|
|
112
|
+
source_pos_str = IO.read(file_path).strip
|
|
113
|
+
begin
|
|
114
|
+
context = source.source_pos
|
|
115
|
+
source_pos = context.create_source_pos(source_pos_str)
|
|
116
|
+
rescue RuntimeError
|
|
117
|
+
return nil
|
|
118
|
+
end
|
|
119
|
+
source_pos
|
|
106
120
|
end
|
|
107
121
|
|
|
108
|
-
def
|
|
122
|
+
def source_pos_path
|
|
109
123
|
File.join(FLYDATA_HOME, @data_entry['name'] + ".binlog.pos")
|
|
110
124
|
end
|
|
111
125
|
|
|
112
|
-
# sent binlog.pos
|
|
113
|
-
def
|
|
114
|
-
File.open(
|
|
115
|
-
f.write(
|
|
126
|
+
# sent source pos file (binlog.pos)
|
|
127
|
+
def save_sent_source_pos(source_pos)
|
|
128
|
+
File.open(sent_source_pos_path, 'w') do |f|
|
|
129
|
+
f.write(source_pos.to_s)
|
|
116
130
|
end
|
|
117
131
|
end
|
|
118
132
|
|
|
119
|
-
def
|
|
133
|
+
def load_sent_source_pos(file_path = sent_source_pos_path)
|
|
120
134
|
return nil unless File.exists?(file_path)
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
135
|
+
|
|
136
|
+
source_pos_str = IO.read(file_path).strip
|
|
137
|
+
begin
|
|
138
|
+
source_pos = source.source_pos.create_source_pos(source_pos_str)
|
|
139
|
+
rescue RuntimeError
|
|
140
|
+
return nil
|
|
141
|
+
end
|
|
142
|
+
source_pos
|
|
124
143
|
end
|
|
125
144
|
|
|
126
|
-
def
|
|
127
|
-
|
|
128
|
-
"#{
|
|
145
|
+
def sent_source_pos_path(master_source_pos_path = source_pos_path)
|
|
146
|
+
validate_master_source_pos_path(master_source_pos_path)
|
|
147
|
+
"#{master_source_pos_path[0..-5]}.sent.pos"
|
|
129
148
|
end
|
|
130
149
|
|
|
131
150
|
# ssl_ca file path
|
|
132
|
-
def ssl_ca_path(
|
|
133
|
-
|
|
151
|
+
def ssl_ca_path(master_source_pos_path = source_pos_path)
|
|
152
|
+
validate_master_source_pos_path(master_source_pos_path)
|
|
134
153
|
# <data-entry-name>.ssl_ca.pem
|
|
135
|
-
"#{
|
|
154
|
+
"#{master_source_pos_path[0..-12]}.ssl_ca.pem"
|
|
136
155
|
end
|
|
137
156
|
|
|
138
157
|
def save_ssl_ca(ssl_ca_content, path = ssl_ca_path)
|
|
@@ -142,10 +161,10 @@ module Flydata
|
|
|
142
161
|
end
|
|
143
162
|
|
|
144
163
|
# ssl_cipher file path
|
|
145
|
-
def ssl_cipher_path(
|
|
146
|
-
|
|
164
|
+
def ssl_cipher_path(master_source_pos_path = source_pos_path)
|
|
165
|
+
validate_master_source_pos_path(master_source_pos_path)
|
|
147
166
|
# <data-entry-name>.ssl_cipher
|
|
148
|
-
"#{
|
|
167
|
+
"#{master_source_pos_path[0..-12]}.ssl_cipher"
|
|
149
168
|
end
|
|
150
169
|
|
|
151
170
|
def save_ssl_cipher(ssl_cipher_content, path = ssl_cipher_path)
|
|
@@ -176,12 +195,12 @@ module Flydata
|
|
|
176
195
|
tables.map{|table| File.join(table_positions_dir_path, table + '.generated_ddl')}
|
|
177
196
|
end
|
|
178
197
|
|
|
179
|
-
def
|
|
198
|
+
def table_source_pos_paths(*tables)
|
|
180
199
|
tables.empty? ? Dir.glob(File.join(table_positions_dir_path, '*.binlog.pos')) :
|
|
181
200
|
tables.map{|table| File.join(table_positions_dir_path, table + '.binlog.pos')}
|
|
182
201
|
end
|
|
183
202
|
|
|
184
|
-
def
|
|
203
|
+
def table_source_pos_init_paths(*tables)
|
|
185
204
|
tables.empty? ? Dir.glob(File.join(table_positions_dir_path, '*.binlog.pos.init')) :
|
|
186
205
|
tables.map{|table| File.join(table_positions_dir_path, table + '.binlog.pos.init')}
|
|
187
206
|
end
|
|
@@ -262,10 +281,11 @@ module Flydata
|
|
|
262
281
|
tables: items[1].split(" ") }
|
|
263
282
|
end
|
|
264
283
|
|
|
265
|
-
def
|
|
284
|
+
def get_table_source_pos_init(table_name)
|
|
266
285
|
file = File.join(table_positions_dir_path, table_name + ".binlog.pos.init")
|
|
267
286
|
return nil unless File.exists?(file)
|
|
268
|
-
|
|
287
|
+
|
|
288
|
+
source.source_pos.create_source_pos( File.open(file, 'r').readline )
|
|
269
289
|
end
|
|
270
290
|
|
|
271
291
|
def table_rev_file_path(table_name)
|
|
@@ -302,8 +322,8 @@ module Flydata
|
|
|
302
322
|
def delete_table_control_files(*tables)
|
|
303
323
|
files_to_delete = [
|
|
304
324
|
table_position_file_paths(*tables),
|
|
305
|
-
|
|
306
|
-
|
|
325
|
+
table_source_pos_paths(*tables),
|
|
326
|
+
table_source_pos_init_paths(*tables),
|
|
307
327
|
table_rev_file_paths(*tables),
|
|
308
328
|
table_ddl_file_paths(*tables)
|
|
309
329
|
]
|
|
@@ -327,7 +347,7 @@ module Flydata
|
|
|
327
347
|
files_to_delete = [
|
|
328
348
|
dump_file_path,
|
|
329
349
|
dump_pos_path,
|
|
330
|
-
|
|
350
|
+
source_table_marshal_dump_path,
|
|
331
351
|
sync_info_file,
|
|
332
352
|
stats_path
|
|
333
353
|
]
|
|
@@ -338,8 +358,8 @@ module Flydata
|
|
|
338
358
|
|
|
339
359
|
def delete_master_position_files
|
|
340
360
|
files_to_delete = [
|
|
341
|
-
|
|
342
|
-
|
|
361
|
+
source_pos_path,
|
|
362
|
+
sent_source_pos_path,
|
|
343
363
|
lock_pid_file,
|
|
344
364
|
]
|
|
345
365
|
files_to_delete.flatten.each do |file_to_delete|
|
|
@@ -348,7 +368,7 @@ module Flydata
|
|
|
348
368
|
end
|
|
349
369
|
|
|
350
370
|
|
|
351
|
-
def
|
|
371
|
+
def delete_table_source_pos(table_name)
|
|
352
372
|
file = File.join(table_positions_dir_path, table_name + ".binlog.pos")
|
|
353
373
|
if File.exists?(file)
|
|
354
374
|
FileUtils.rm(file, :force => true)
|
|
@@ -357,7 +377,7 @@ module Flydata
|
|
|
357
377
|
end
|
|
358
378
|
end
|
|
359
379
|
|
|
360
|
-
def
|
|
380
|
+
def save_table_source_pos(tables, source_pos, options = {})
|
|
361
381
|
dest_dir = case options[:destination]
|
|
362
382
|
when :positions; table_positions_dir_path
|
|
363
383
|
when :dump; dump_dir
|
|
@@ -368,18 +388,28 @@ module Flydata
|
|
|
368
388
|
tables.each do |table_name|
|
|
369
389
|
file = File.join(dest_dir, table_name + ".binlog.pos")
|
|
370
390
|
File.open(file, "w") do |f|
|
|
371
|
-
f.write(
|
|
391
|
+
f.write(source_pos.to_s)
|
|
372
392
|
end
|
|
373
393
|
end
|
|
374
394
|
end
|
|
375
395
|
|
|
376
|
-
def
|
|
396
|
+
def get_table_source_pos(table_name)
|
|
397
|
+
source_pos_str = get_table_source_raw_pos(table_name)
|
|
398
|
+
return nil unless source_pos_str
|
|
399
|
+
|
|
400
|
+
source.source_pos.create_source_pos( source_pos_str )
|
|
401
|
+
end
|
|
402
|
+
|
|
403
|
+
def get_table_source_raw_pos(table_name) #returns String. interface for fluentd
|
|
377
404
|
file = File.join(table_positions_dir_path, table_name + ".binlog.pos")
|
|
378
405
|
return nil unless File.exists?(file)
|
|
406
|
+
|
|
379
407
|
File.open(file, 'r').readline
|
|
380
408
|
end
|
|
381
409
|
|
|
382
|
-
|
|
410
|
+
|
|
411
|
+
|
|
412
|
+
def install_table_source_pos_files(tables)
|
|
383
413
|
FileUtils.mkdir_p(table_positions_dir_path) unless Dir.exists?(table_positions_dir_path)
|
|
384
414
|
tables.each do |table_name|
|
|
385
415
|
file_name = table_name + ".binlog.pos"
|
|
@@ -403,7 +433,7 @@ module Flydata
|
|
|
403
433
|
FileUtils.mkdir_p(backup_dir) unless Dir.exists?(backup_dir)
|
|
404
434
|
dest_dir = File.join(backup_dir, Time.now.strftime("%Y%m%d%H%M%S"))
|
|
405
435
|
FileUtils.mkdir(dest_dir)
|
|
406
|
-
|
|
436
|
+
['info', 'pos', 'stats', SOURCE_TABLE_EXT].each do |ext|
|
|
407
437
|
FileUtils.mv(Dir.glob("#{dump_dir}/*.#{ext}"), dest_dir)
|
|
408
438
|
end
|
|
409
439
|
end
|
|
@@ -435,29 +465,58 @@ module Flydata
|
|
|
435
465
|
end
|
|
436
466
|
end
|
|
437
467
|
|
|
438
|
-
def dump_pos_content(status, table_name, last_pos,
|
|
439
|
-
[status, table_name, last_pos,
|
|
468
|
+
def dump_pos_content(status, table_name, last_pos, source_pos, state = nil, substate = nil)
|
|
469
|
+
[status, table_name, last_pos, source_pos.to_s, state, substate].join("\t")
|
|
440
470
|
end
|
|
441
471
|
|
|
442
|
-
def
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
472
|
+
def dump_pos_content_to_hash(content)
|
|
473
|
+
items = content.split("\t",-1) # -1 means,(1) there is no limit to the number of fields returned
|
|
474
|
+
# (2) trailing null fields are not suppressed.
|
|
475
|
+
raise "Invalid dump.pos file: #{path}" unless items.length >= 6
|
|
476
|
+
|
|
477
|
+
status = items[0]
|
|
478
|
+
table_name = items[1]
|
|
479
|
+
last_pos = items[2].to_i
|
|
480
|
+
|
|
481
|
+
source_pos_str = items[3..-3].join("\t")
|
|
482
|
+
context = source.source_pos
|
|
483
|
+
source_pos = context.create_source_pos(source_pos_str)
|
|
484
|
+
|
|
485
|
+
state = get_parse_state(items[-2])
|
|
486
|
+
substate = get_parse_state(items[-1])
|
|
487
|
+
|
|
488
|
+
{ status: status, table_name: table_name, last_pos: last_pos,
|
|
489
|
+
source_pos: source_pos,
|
|
490
|
+
state: state, substate: substate }
|
|
491
|
+
end
|
|
492
|
+
|
|
493
|
+
def get_parse_state(state)
|
|
494
|
+
state.empty? ? nil : state
|
|
446
495
|
end
|
|
447
496
|
|
|
448
|
-
def
|
|
449
|
-
path =
|
|
497
|
+
def load_source_table_marshal_dump
|
|
498
|
+
path = source_table_marshal_dump_path
|
|
450
499
|
return nil unless File.exists?(path)
|
|
451
500
|
Marshal.load(File.open(path, 'r'))
|
|
452
501
|
end
|
|
453
502
|
|
|
503
|
+
OLD_DUMP_DIR_PROPERTY = 'mysqldump_dir'
|
|
504
|
+
DUMP_DIR_PROPERTY = 'dump_dir'
|
|
454
505
|
def dump_dir
|
|
455
506
|
pref = @data_entry['mysql_data_entry_preference']
|
|
456
|
-
dump_dir =
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
507
|
+
dump_dir = nil
|
|
508
|
+
dump_dir_property = DUMP_DIR_PROPERTY
|
|
509
|
+
|
|
510
|
+
if pref
|
|
511
|
+
# check the old property for backward compatibility
|
|
512
|
+
[DUMP_DIR_PROPERTY, OLD_DUMP_DIR_PROPERTY].each do |prop|
|
|
513
|
+
if pref[prop]
|
|
514
|
+
dump_dir_property = prop
|
|
515
|
+
dump_dir = pref[prop]
|
|
516
|
+
break
|
|
517
|
+
end
|
|
518
|
+
end
|
|
519
|
+
end
|
|
461
520
|
if dump_dir
|
|
462
521
|
dump_dir = dump_dir.dup
|
|
463
522
|
dump_dir[0] = ENV['HOME'] if dump_dir.match(/^~$|^~\//)
|
|
@@ -465,15 +524,15 @@ module Flydata
|
|
|
465
524
|
dump_dir = DUMP_DIR.dup
|
|
466
525
|
end
|
|
467
526
|
if File.exists?(dump_dir) and not Dir.exists?(dump_dir)
|
|
468
|
-
raise "'
|
|
527
|
+
raise "'#{dump_dir_property}'(#{dump_dir}) must be a directory."
|
|
469
528
|
end
|
|
470
529
|
FileUtils.mkdir_p(dump_dir) unless Dir.exists?(dump_dir)
|
|
471
530
|
dump_dir
|
|
472
531
|
end
|
|
473
532
|
|
|
474
|
-
def
|
|
475
|
-
unless
|
|
476
|
-
raise ArgumentError.new("Invalid
|
|
533
|
+
def validate_master_source_pos_path(master_source_pos_path)
|
|
534
|
+
unless master_source_pos_path && master_source_pos_path.end_with?('binlog.pos')
|
|
535
|
+
raise ArgumentError.new("Invalid source position path. Source position path needs to end with 'binlog.pos'")
|
|
477
536
|
end
|
|
478
537
|
end
|
|
479
538
|
end
|