ruby-binlog 0.1.4 → 0.1.5
Sign up to get free protection for your applications and to get access to all the features.
- data/README +26 -13
- data/ext/ruby_binlog.cpp +121 -7
- data/ext/ruby_binlog.h +7 -0
- data/ext/ruby_binlog_cast_to_tcp_driver.cpp +18 -0
- metadata +5 -4
data/README
CHANGED
@@ -14,19 +14,32 @@ gem install ruby-binlog
|
|
14
14
|
|
15
15
|
require "binlog"
|
16
16
|
|
17
|
-
|
18
|
-
|
19
|
-
client.position = 4
|
17
|
+
master_log_file = "mysql-bin.000001"
|
18
|
+
master_log_pos = 4
|
20
19
|
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
20
|
+
begin
|
21
|
+
client = Binlog::Client.new("mysql://repl:repl@example.com")
|
22
|
+
sleep 0.3 until client.connect
|
23
|
+
client.set_position(master_log_file, master_log_pos)
|
24
|
+
|
25
|
+
while event = client.wait_for_next_event
|
26
|
+
master_log_pos = event.next_position
|
27
|
+
|
28
|
+
case event
|
29
|
+
when Binlog::QueryEvent
|
30
|
+
puts event.query
|
31
|
+
when Binlog::RowEvent
|
32
|
+
puts event.event_type
|
33
|
+
p event.columns
|
34
|
+
p event.rows
|
35
|
+
when Binlog::RotateEvent
|
36
|
+
master_log_file = event.binlog_file
|
37
|
+
else
|
38
|
+
puts "(#{event.event_type})"
|
39
|
+
end
|
31
40
|
end
|
41
|
+
rescue Binlog::Error => e
|
42
|
+
puts e
|
43
|
+
retry if client.closed?
|
44
|
+
raise e
|
32
45
|
end
|
data/ext/ruby_binlog.cpp
CHANGED
@@ -58,22 +58,116 @@ struct Client {
|
|
58
58
|
int result;
|
59
59
|
|
60
60
|
Data_Get_Struct(self, Client, p);
|
61
|
+
TRAP_BEG;
|
61
62
|
result = p->m_binlog->connect();
|
63
|
+
TRAP_END;
|
62
64
|
|
63
65
|
return (result == 0) ? Qtrue : Qfalse;
|
64
66
|
}
|
65
67
|
|
68
|
+
// XXX: Don't use
|
69
|
+
/*
|
70
|
+
static VALUE disconnect(VALUE self) {
|
71
|
+
Client *p;
|
72
|
+
mysql::system::Binlog_tcp_driver *driver;
|
73
|
+
|
74
|
+
Data_Get_Struct(self, Client, p);
|
75
|
+
driver = cast_to_tcp_driver(p->m_binlog->m_driver);
|
76
|
+
|
77
|
+
if (driver) {
|
78
|
+
driver->disconnect();
|
79
|
+
}
|
80
|
+
|
81
|
+
return Qnil;
|
82
|
+
}
|
83
|
+
*/
|
84
|
+
|
85
|
+
// XXX: Don't use
|
86
|
+
/*
|
87
|
+
static VALUE reconnect(VALUE self) {
|
88
|
+
Client *p;
|
89
|
+
mysql::system::Binlog_tcp_driver *driver;
|
90
|
+
|
91
|
+
Data_Get_Struct(self, Client, p);
|
92
|
+
driver = cast_to_tcp_driver(p->m_binlog->m_driver);
|
93
|
+
|
94
|
+
if (driver) {
|
95
|
+
driver->reconnect();
|
96
|
+
}
|
97
|
+
|
98
|
+
return Qnil;
|
99
|
+
}
|
100
|
+
*/
|
101
|
+
|
102
|
+
static VALUE is_closed(VALUE self) {
|
103
|
+
Client *p;
|
104
|
+
mysql::system::Binlog_tcp_driver *driver;
|
105
|
+
|
106
|
+
Data_Get_Struct(self, Client, p);
|
107
|
+
driver = cast_to_tcp_driver(p->m_binlog->m_driver);
|
108
|
+
|
109
|
+
if (!driver) {
|
110
|
+
return Qfalse;
|
111
|
+
}
|
112
|
+
|
113
|
+
if (driver->m_socket) {
|
114
|
+
bool socket_is_open;
|
115
|
+
|
116
|
+
TRAP_BEG;
|
117
|
+
socket_is_open = driver->m_socket->is_open();
|
118
|
+
TRAP_END;
|
119
|
+
|
120
|
+
return socket_is_open ? Qfalse : Qtrue;
|
121
|
+
} else {
|
122
|
+
return Qtrue;
|
123
|
+
}
|
124
|
+
}
|
125
|
+
|
66
126
|
static VALUE wait_for_next_event(VALUE self) {
|
67
127
|
Client *p;
|
68
128
|
Binary_log_event *event;
|
69
|
-
int result;
|
129
|
+
int result = ERR_EOF;
|
70
130
|
VALUE retval = Qnil;
|
131
|
+
mysql::system::Binlog_tcp_driver *driver;
|
71
132
|
|
72
133
|
Data_Get_Struct(self, Client, p);
|
134
|
+
driver = cast_to_tcp_driver(p->m_binlog->m_driver);
|
135
|
+
|
136
|
+
if (driver) {
|
137
|
+
int closed = 0;
|
138
|
+
timeval interval = { 0, WAIT_INTERVAL };
|
139
|
+
|
140
|
+
TRAP_BEG;
|
141
|
+
while (1) {
|
142
|
+
if (driver->m_event_queue->is_not_empty()) {
|
143
|
+
result = p->m_binlog->wait_for_next_event(&event);
|
144
|
+
break;
|
145
|
+
} else {
|
146
|
+
if (driver->m_socket && driver->m_socket->is_open()) {
|
147
|
+
rb_thread_wait_for(interval);
|
148
|
+
} else {
|
149
|
+
closed = 1;
|
150
|
+
driver->shutdown();
|
151
|
+
rb_thread_wait_for(interval);
|
152
|
+
break;
|
153
|
+
}
|
154
|
+
}
|
155
|
+
}
|
156
|
+
TRAP_END;
|
157
|
+
|
158
|
+
if (closed) {
|
159
|
+
TRAP_BEG;
|
160
|
+
driver->disconnect();
|
161
|
+
TRAP_END;
|
162
|
+
|
163
|
+
rb_raise(rb_eBinlogError, "MySQL server has gone away");
|
164
|
+
}
|
165
|
+
} else {
|
166
|
+
TRAP_BEG;
|
167
|
+
result = p->m_binlog->wait_for_next_event(&event);
|
168
|
+
TRAP_END;
|
169
|
+
}
|
73
170
|
|
74
|
-
TRAP_BEG;
|
75
|
-
result = p->m_binlog->wait_for_next_event(&event);
|
76
|
-
TRAP_END;
|
77
171
|
|
78
172
|
if (result == ERR_EOF) {
|
79
173
|
return Qfalse;
|
@@ -152,13 +246,17 @@ struct Client {
|
|
152
246
|
if (NIL_P(position)) {
|
153
247
|
unsigned long i_position;
|
154
248
|
i_position = NUM2ULONG(filename);
|
249
|
+
TRAP_BEG;
|
155
250
|
result = p->m_binlog->set_position(i_position);
|
251
|
+
TRAP_END;
|
156
252
|
} else {
|
157
253
|
unsigned long i_position;
|
158
254
|
Check_Type(filename, T_STRING);
|
159
255
|
i_position = NUM2ULONG(position);
|
160
256
|
std::string s_filename(StringValuePtr(filename));
|
257
|
+
TRAP_BEG;
|
161
258
|
result = p->m_binlog->set_position(s_filename, i_position);
|
259
|
+
TRAP_END;
|
162
260
|
}
|
163
261
|
|
164
262
|
switch (result) {
|
@@ -168,7 +266,7 @@ struct Client {
|
|
168
266
|
case ERR_EOF:
|
169
267
|
retval = Qfalse;
|
170
268
|
default:
|
171
|
-
rb_raise(
|
269
|
+
rb_raise(rb_eBinlogError, "An unspecified error occurred (%d)", result);
|
172
270
|
break;
|
173
271
|
}
|
174
272
|
|
@@ -181,7 +279,9 @@ struct Client {
|
|
181
279
|
int result;
|
182
280
|
|
183
281
|
Data_Get_Struct(self, Client, p);
|
282
|
+
TRAP_BEG;
|
184
283
|
result = p->m_binlog->set_position(NUM2ULONG(position));
|
284
|
+
TRAP_END;
|
185
285
|
|
186
286
|
switch (result) {
|
187
287
|
case ERR_OK:
|
@@ -190,7 +290,7 @@ struct Client {
|
|
190
290
|
case ERR_EOF:
|
191
291
|
retval = Qfalse;
|
192
292
|
default:
|
193
|
-
rb_raise(
|
293
|
+
rb_raise(rb_eBinlogError, "An unspecified error occurred (%d)", result);
|
194
294
|
break;
|
195
295
|
}
|
196
296
|
|
@@ -210,7 +310,9 @@ struct Client {
|
|
210
310
|
} else {
|
211
311
|
Check_Type(filename, T_STRING);
|
212
312
|
std::string s_filename(StringValuePtr(filename));
|
313
|
+
TRAP_BEG;
|
213
314
|
position = p->m_binlog->get_position(s_filename);
|
315
|
+
TRAP_END;
|
214
316
|
}
|
215
317
|
|
216
318
|
return ULONG2NUM(position);
|
@@ -219,7 +321,13 @@ struct Client {
|
|
219
321
|
static VALUE get_position2(VALUE self) {
|
220
322
|
Client *p;
|
221
323
|
Data_Get_Struct(self, Client, p);
|
222
|
-
|
324
|
+
unsigned long position;
|
325
|
+
|
326
|
+
TRAP_BEG;
|
327
|
+
position = p->m_binlog->get_position();
|
328
|
+
TRAP_END;
|
329
|
+
|
330
|
+
return ULONG2NUM(position);
|
223
331
|
}
|
224
332
|
|
225
333
|
static void init() {
|
@@ -227,6 +335,10 @@ struct Client {
|
|
227
335
|
rb_define_alloc_func(rb_cBinlogClient, &alloc);
|
228
336
|
rb_define_private_method(rb_cBinlogClient, "initialize", __F(&initialize), 1);
|
229
337
|
rb_define_method(rb_cBinlogClient, "connect", __F(&connect), 0);
|
338
|
+
// XXX: Don't use
|
339
|
+
//rb_define_method(rb_cBinlogClient, "disconnect", __F(&disconnect), 0);
|
340
|
+
//rb_define_method(rb_cBinlogClient, "reconnect", __F(&reconnect), 0);
|
341
|
+
rb_define_method(rb_cBinlogClient, "closed?", __F(&is_closed), 0);
|
230
342
|
rb_define_method(rb_cBinlogClient, "wait_for_next_event", __F(&wait_for_next_event), 0);
|
231
343
|
rb_define_method(rb_cBinlogClient, "set_position", __F(&set_position), -1);
|
232
344
|
rb_define_method(rb_cBinlogClient, "position=", __F(&set_position2), 1);
|
@@ -240,10 +352,12 @@ struct Client {
|
|
240
352
|
|
241
353
|
VALUE rb_mBinlog;
|
242
354
|
VALUE rb_cBinlogEvent;
|
355
|
+
VALUE rb_eBinlogError;
|
243
356
|
|
244
357
|
void Init_binlog() {
|
245
358
|
rb_mBinlog = rb_define_module("Binlog");
|
246
359
|
rb_cBinlogEvent = rb_define_class_under(rb_mBinlog, "Event", rb_cObject);
|
360
|
+
rb_eBinlogError = rb_define_class_under(rb_mBinlog, "Error", rb_eRuntimeError);
|
247
361
|
|
248
362
|
rb_define_const(rb_cBinlogEvent, "UNKNOWN_EVENT", INT2NUM(0));
|
249
363
|
rb_define_const(rb_cBinlogEvent, "START_EVENT_V3", INT2NUM(1));
|
data/ext/ruby_binlog.h
CHANGED
@@ -1,6 +1,9 @@
|
|
1
1
|
#ifndef __RUBY_BINLOG_H__
|
2
2
|
#define __RUBY_BINLOG_H__
|
3
3
|
|
4
|
+
// XXX:
|
5
|
+
#define private public
|
6
|
+
|
4
7
|
#include <string>
|
5
8
|
#include <binlog_api.h>
|
6
9
|
#include <ruby.h>
|
@@ -21,11 +24,15 @@
|
|
21
24
|
#define __F(f) (reinterpret_cast<VALUE (*)(...)>(f))
|
22
25
|
#endif
|
23
26
|
|
27
|
+
#define WAIT_INTERVAL 300
|
28
|
+
|
24
29
|
extern VALUE rb_mBinlog;
|
30
|
+
extern VALUE rb_eBinlogError;
|
25
31
|
|
26
32
|
namespace ruby {
|
27
33
|
namespace binlog {
|
28
34
|
const char* get_field_type_str(mysql::system::enum_field_types type);
|
35
|
+
mysql::system::Binlog_tcp_driver *cast_to_tcp_driver(mysql::system::Binary_log_driver *driver);
|
29
36
|
} // namespace binlog
|
30
37
|
} // namespace ruby
|
31
38
|
|
@@ -0,0 +1,18 @@
|
|
1
|
+
#include "ruby_binlog.h"
|
2
|
+
|
3
|
+
namespace ruby {
|
4
|
+
namespace binlog {
|
5
|
+
|
6
|
+
mysql::system::Binlog_tcp_driver *cast_to_tcp_driver(mysql::system::Binary_log_driver *driver) {
|
7
|
+
const char *cname = typeid(*driver).name();
|
8
|
+
std::string name = cname;
|
9
|
+
|
10
|
+
if(name.find("tcp_driver") == std::string::npos) {
|
11
|
+
return 0;
|
12
|
+
}
|
13
|
+
|
14
|
+
return static_cast<mysql::system::Binlog_tcp_driver *>(driver);
|
15
|
+
}
|
16
|
+
|
17
|
+
} // namespace binlog
|
18
|
+
} // namespace ruby
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ruby-binlog
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 17
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 1
|
9
|
-
-
|
10
|
-
version: 0.1.
|
9
|
+
- 5
|
10
|
+
version: 0.1.5
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- winebarrel
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2012-08-
|
18
|
+
date: 2012-08-28 00:00:00 Z
|
19
19
|
dependencies: []
|
20
20
|
|
21
21
|
description: Ruby binding for MySQL Binary log API.
|
@@ -30,6 +30,7 @@ files:
|
|
30
30
|
- ext/ruby_binlog_xid_event.cpp
|
31
31
|
- ext/ruby_binlog_rotate_event.cpp
|
32
32
|
- ext/ruby_binlog_format_event.cpp
|
33
|
+
- ext/ruby_binlog_cast_to_tcp_driver.cpp
|
33
34
|
- ext/ruby_binlog_user_var_event.cpp
|
34
35
|
- ext/ruby_binlog.cpp
|
35
36
|
- ext/ruby_binlog_table_map_event.cpp
|