@@ -14,6 +14,25 @@ import (
14
14
// StartBackup: Like mysqlbinlog remote raw backup
15
15
// Backup remote binlog from position (filename, offset) and write in backupDir
16
16
func (b * BinlogSyncer ) StartBackup (backupDir string , p Position , timeout time.Duration ) error {
17
+ err := os .MkdirAll (backupDir , 0755 )
18
+ if err != nil {
19
+ return errors .Trace (err )
20
+ }
21
+ return b .StartBackupWithHandler (p , timeout , func (filename string ) (io.WriteCloser , error ) {
22
+ return os .OpenFile (path .Join (backupDir , filename ), os .O_CREATE | os .O_WRONLY , 0644 )
23
+ })
24
+ }
25
+
26
+ // StartBackupWithHandler starts the backup process for the binary log using the specified position and handler.
27
+ // The process will continue until the timeout is reached or an error occurs.
28
+ //
29
+ // Parameters:
30
+ // - p: The starting position in the binlog from which to begin the backup.
31
+ // - timeout: The maximum duration to wait for new binlog events before stopping the backup process.
32
+ // If set to 0, a default very long timeout (30 days) is used instead.
33
+ // - handler: A function that takes a binlog filename and returns an WriteCloser for writing raw events to.
34
+ func (b * BinlogSyncer ) StartBackupWithHandler (p Position , timeout time.Duration ,
35
+ handler func (binlogFilename string ) (io.WriteCloser , error )) (retErr error ) {
17
36
if timeout == 0 {
18
37
// a very long timeout here
19
38
timeout = 30 * 3600 * 24 * time .Second
@@ -22,10 +41,6 @@ func (b *BinlogSyncer) StartBackup(backupDir string, p Position, timeout time.Du
22
41
// Force use raw mode
23
42
b .parser .SetRawMode (true )
24
43
25
- if err := os .MkdirAll (backupDir , 0755 ); err != nil {
26
- return errors .Trace (err )
27
- }
28
-
29
44
s , err := b .StartSync (p )
30
45
if err != nil {
31
46
return errors .Trace (err )
@@ -34,10 +49,14 @@ func (b *BinlogSyncer) StartBackup(backupDir string, p Position, timeout time.Du
34
49
var filename string
35
50
var offset uint32
36
51
37
- var f * os. File
52
+ var w io. WriteCloser
38
53
defer func () {
39
- if f != nil {
40
- f .Close ()
54
+ var closeErr error
55
+ if w != nil {
56
+ closeErr = w .Close ()
57
+ }
58
+ if retErr == nil {
59
+ retErr = closeErr
41
60
}
42
61
}()
43
62
@@ -67,26 +86,29 @@ func (b *BinlogSyncer) StartBackup(backupDir string, p Position, timeout time.Du
67
86
} else if e .Header .EventType == FORMAT_DESCRIPTION_EVENT {
68
87
// FormateDescriptionEvent is the first event in binlog, we will close old one and create a new
69
88
70
- if f != nil {
71
- f .Close ()
89
+ if w != nil {
90
+ if err = w .Close (); err != nil {
91
+ w = nil
92
+ return errors .Trace (err )
93
+ }
72
94
}
73
95
74
96
if len (filename ) == 0 {
75
97
return errors .Errorf ("empty binlog filename for FormateDescriptionEvent" )
76
98
}
77
99
78
- f , err = os . OpenFile ( path . Join ( backupDir , filename ), os . O_CREATE | os . O_WRONLY , 0644 )
100
+ w , err = handler ( filename )
79
101
if err != nil {
80
102
return errors .Trace (err )
81
103
}
82
104
83
105
// write binlog header fe'bin'
84
- if _ , err = f .Write (BinLogFileHeader ); err != nil {
106
+ if _ , err = w .Write (BinLogFileHeader ); err != nil {
85
107
return errors .Trace (err )
86
108
}
87
109
}
88
110
89
- if n , err := f .Write (e .RawData ); err != nil {
111
+ if n , err := w .Write (e .RawData ); err != nil {
90
112
return errors .Trace (err )
91
113
} else if n != len (e .RawData ) {
92
114
return errors .Trace (io .ErrShortWrite )
0 commit comments