@@ -7,6 +7,7 @@ package binlog
7
7
8
8
import (
9
9
"fmt"
10
+ "sync"
10
11
11
12
"github.com/github/gh-ost/go/mysql"
12
13
"github.com/github/gh-ost/go/sql"
@@ -23,20 +24,21 @@ const (
23
24
)
24
25
25
26
type GoMySQLReader struct {
26
- connectionConfig * mysql.ConnectionConfig
27
- binlogSyncer * replication.BinlogSyncer
28
- binlogStreamer * replication.BinlogStreamer
29
- tableMap map [ uint64 ] string
30
- currentCoordinates mysql. BinlogCoordinates
31
- lastHandledCoordinates mysql.BinlogCoordinates
27
+ connectionConfig * mysql.ConnectionConfig
28
+ binlogSyncer * replication.BinlogSyncer
29
+ binlogStreamer * replication.BinlogStreamer
30
+ currentCoordinates mysql. BinlogCoordinates
31
+ currentCoordinatesMutex * sync. Mutex
32
+ LastAppliedRowsEventHint mysql.BinlogCoordinates
32
33
}
33
34
34
35
func NewGoMySQLReader (connectionConfig * mysql.ConnectionConfig ) (binlogReader * GoMySQLReader , err error ) {
35
36
binlogReader = & GoMySQLReader {
36
- connectionConfig : connectionConfig ,
37
- tableMap : make (map [uint64 ]string ),
38
- currentCoordinates : mysql.BinlogCoordinates {},
39
- binlogStreamer : nil ,
37
+ connectionConfig : connectionConfig ,
38
+ currentCoordinates : mysql.BinlogCoordinates {},
39
+ currentCoordinatesMutex : & sync.Mutex {},
40
+ binlogSyncer : nil ,
41
+ binlogStreamer : nil ,
40
42
}
41
43
binlogReader .binlogSyncer = replication .NewBinlogSyncer (serverId , "mysql" )
42
44
@@ -63,25 +65,24 @@ func (this *GoMySQLReader) ConnectBinlogStreamer(coordinates mysql.BinlogCoordin
63
65
64
66
func (this * GoMySQLReader ) Reconnect () error {
65
67
this .binlogSyncer .Close ()
66
-
67
- connectCoordinates := & this .lastHandledCoordinates
68
- if connectCoordinates .IsEmpty () {
69
- connectCoordinates = & this .currentCoordinates
70
- }
68
+ connectCoordinates := & mysql.BinlogCoordinates {LogFile : this .currentCoordinates .LogFile , LogPos : 4 }
71
69
if err := this .ConnectBinlogStreamer (* connectCoordinates ); err != nil {
72
70
return err
73
71
}
74
72
return nil
75
73
}
76
74
77
75
func (this * GoMySQLReader ) GetCurrentBinlogCoordinates () * mysql.BinlogCoordinates {
78
- return & this .currentCoordinates
76
+ this .currentCoordinatesMutex .Lock ()
77
+ defer this .currentCoordinatesMutex .Unlock ()
78
+ returnCoordinates := this .currentCoordinates
79
+ return & returnCoordinates
79
80
}
80
81
81
82
// StreamEvents
82
83
func (this * GoMySQLReader ) handleRowsEvent (ev * replication.BinlogEvent , rowsEvent * replication.RowsEvent , entriesChannel chan <- * BinlogEntry ) error {
83
- if this .currentCoordinates .SmallerThanOrEquals (& this .lastHandledCoordinates ) && ! this . lastHandledCoordinates . IsEmpty ( ) {
84
- log .Infof ("Skipping handled query at %+v" , this .currentCoordinates )
84
+ if this .currentCoordinates .SmallerThanOrEquals (& this .LastAppliedRowsEventHint ) {
85
+ log .Debugf ("Skipping handled query at %+v" , this .currentCoordinates )
85
86
return nil
86
87
}
87
88
@@ -122,6 +123,7 @@ func (this *GoMySQLReader) handleRowsEvent(ev *replication.BinlogEvent, rowsEven
122
123
// In reality, reads will be synchronous
123
124
entriesChannel <- binlogEntry
124
125
}
126
+ this .LastAppliedRowsEventHint = this .currentCoordinates
125
127
return nil
126
128
}
127
129
@@ -135,21 +137,33 @@ func (this *GoMySQLReader) StreamEvents(canStopStreaming func() bool, entriesCha
135
137
if err != nil {
136
138
return err
137
139
}
138
- this .currentCoordinates .LogPos = int64 (ev .Header .LogPos )
140
+ // if rand.Intn(1000) == 0 {
141
+ // this.binlogSyncer.Close()
142
+ // log.Debugf("current: %+v, hint: %+v", this.currentCoordinates, this.LastAppliedRowsEventHint)
143
+ // return log.Errorf(".............haha got random error")
144
+ // }
145
+ // log.Debugf("0001 ........ currentCoordinates: %+v", this.currentCoordinates) //TODO
146
+ func () {
147
+ this .currentCoordinatesMutex .Lock ()
148
+ defer this .currentCoordinatesMutex .Unlock ()
149
+ this .currentCoordinates .LogPos = int64 (ev .Header .LogPos )
150
+ }()
139
151
if rotateEvent , ok := ev .Event .(* replication.RotateEvent ); ok {
140
- this .currentCoordinates .LogFile = string (rotateEvent .NextLogName )
152
+ // log.Debugf("0008 ........ currentCoordinates: %+v", this.currentCoordinates) //TODO
153
+ // ev.Dump(os.Stdout)
154
+ func () {
155
+ this .currentCoordinatesMutex .Lock ()
156
+ defer this .currentCoordinatesMutex .Unlock ()
157
+ this .currentCoordinates .LogFile = string (rotateEvent .NextLogName )
158
+ }()
159
+ // log.Debugf("0001 ........ currentCoordinates: %+v", this.currentCoordinates) //TODO
141
160
log .Infof ("rotate to next log name: %s" , rotateEvent .NextLogName )
142
- } else if tableMapEvent , ok := ev .Event .(* replication.TableMapEvent ); ok {
143
- // Actually not being used, since Table is available in RowsEvent.
144
- // Keeping this here in case I'm wrong about this. Sometime in the near
145
- // future I should remove this.
146
- this .tableMap [tableMapEvent .TableID ] = string (tableMapEvent .Table )
147
161
} else if rowsEvent , ok := ev .Event .(* replication.RowsEvent ); ok {
148
162
if err := this .handleRowsEvent (ev , rowsEvent , entriesChannel ); err != nil {
149
163
return err
150
164
}
151
165
}
152
- this . lastHandledCoordinates = this .currentCoordinates
166
+ // log.Debugf("TODO ........ currentCoordinates: %+v", this.currentCoordinates) //TODO
153
167
}
154
168
log .Debugf ("done streaming events" )
155
169
0 commit comments