5
5
from pymysql .constants .COMMAND import *
6
6
from pymysql .util import byte2int , int2byte
7
7
from .packet import BinLogPacketWrapper
8
- from .constants .BINLOG import TABLE_MAP_EVENT
8
+ from .constants .BINLOG import TABLE_MAP_EVENT , ROTATE_EVENT
9
9
10
10
11
11
class BinLogStreamReader (object ):
@@ -19,25 +19,32 @@ def __init__(self, connection_settings = {}, resume_stream = False, blocking = F
19
19
'''
20
20
self .__connection_settings = connection_settings
21
21
self .__connection_settings ['charset' ] = 'utf8'
22
- ctl_connection_settings = copy .copy (self .__connection_settings )
23
- ctl_connection_settings ['db' ] = 'information_schema'
24
- ctl_connection_settings ['cursorclass' ] = pymysql .cursors .DictCursor
25
- self .__ctl_connection = pymysql .connect (** ctl_connection_settings )
26
- self .__connected = False
22
+
23
+ self .__connected_stream = False
24
+ self .__connected_ctl = False
27
25
self .__resume_stream = resume_stream
28
26
self .__blocking = blocking
29
27
self .__only_events = only_events
30
28
self .__server_id = server_id
31
29
self .__log_pos = None
30
+ self .__log_file = None
32
31
33
32
#Store table meta informations
34
33
self .table_map = {}
35
34
36
35
def close (self ):
37
- if self .__connected :
36
+ if self .__connected_stream :
38
37
self ._stream_connection .close ()
39
- self .__connected = False
40
- self .__ctl_connection .close ()
38
+ self .__connected_stream = False
39
+ if self .__connected_ctl :
40
+ self ._ctl_connection .close ()
41
+ self .__connected_ctl = False
42
+
43
+ def __connect_to_ctl (self ):
44
+ self ._ctl_connection_settings = copy .copy (self .__connection_settings )
45
+ self ._ctl_connection_settings ['db' ] = 'information_schema'
46
+ self ._ctl_connection_settings ['cursorclass' ] = pymysql .cursors .DictCursor
47
+ self ._ctl_connection = pymysql .connect (** self ._ctl_connection_settings )
41
48
42
49
def __connect_to_stream (self ):
43
50
self ._stream_connection = pymysql .connect (** self .__connection_settings )
@@ -46,13 +53,14 @@ def __connect_to_stream(self):
46
53
(log_file , log_pos ) = cur .fetchone ()[:2 ]
47
54
cur .close ()
48
55
49
-
56
+ if self .__log_file is None :
57
+ self .__log_file = log_file
50
58
# binlog_pos (4) -- position in the binlog-file to start the stream with
51
59
# flags (2) BINLOG_DUMP_NON_BLOCK (0 or 1)
52
60
# server_id (4) -- server id of this slave
53
61
# binlog-filename (string.EOF) -- filename of the binlog on the master
54
62
command = COM_BINLOG_DUMP
55
- prelude = struct .pack ('<i' , len (log_file ) + 11 ) \
63
+ prelude = struct .pack ('<i' , len (self . __log_file ) + 11 ) \
56
64
+ int2byte (command )
57
65
if self .__log_pos is None :
58
66
if self .__resume_stream :
@@ -66,29 +74,35 @@ def __connect_to_stream(self):
66
74
else :
67
75
prelude += struct .pack ('<h' , 1 )
68
76
prelude += struct .pack ('<I' , self .__server_id )
69
- self ._stream_connection .wfile .write (prelude + log_file .encode ())
77
+ self ._stream_connection .wfile .write (prelude + self . __log_file .encode ())
70
78
self ._stream_connection .wfile .flush ()
71
- self .__connected = True
79
+ self .__connected_stream = True
72
80
73
81
def fetchone (self ):
74
82
while True :
75
- if self .__connected == False :
83
+ if self .__connected_stream == False :
76
84
self .__connect_to_stream ()
85
+ if self .__connected_ctl == False :
86
+ self .__connect_to_ctl ()
77
87
pkt = None
78
88
try :
79
89
pkt = self ._stream_connection .read_packet ()
80
90
except pymysql .OperationalError as (code , message ):
81
91
if code == 2013 : #2013: Connection Lost
82
- self .__connected = False
92
+ self .__connected_stream = False
83
93
continue
84
94
if not pkt .is_ok_packet ():
85
95
return None
86
- binlog_event = BinLogPacketWrapper (pkt , self .table_map , self .__ctl_connection )
96
+ binlog_event = BinLogPacketWrapper (pkt , self .table_map , self ._ctl_connection )
87
97
if binlog_event .event_type == TABLE_MAP_EVENT :
88
98
self .table_map [binlog_event .event .table_id ] = binlog_event .event
89
99
if self .__filter_event (binlog_event .event ):
90
100
continue
91
- self .__log_pos = binlog_event .log_pos
101
+ if binlog_event .event_type == ROTATE_EVENT :
102
+ self .__log_pos = binlog_event .event .position
103
+ self .__log_file = binlog_event .event .next_binlog
104
+ else :
105
+ self .__log_pos = binlog_event .log_pos
92
106
return binlog_event .event
93
107
94
108
def __filter_event (self , event ):
0 commit comments