github.com/pingcap/tiflow@v0.0.0-20240520035814-5bf52d54e205/dm/syncer/relay.go (about) 1 // Copyright 2019 PingCAP, Inc. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // See the License for the specific language governing permissions and 12 // limitations under the License. 13 14 package syncer 15 16 import ( 17 "context" 18 "path/filepath" 19 "strings" 20 21 "github.com/go-mysql-org/go-mysql/mysql" 22 "github.com/pingcap/tiflow/dm/config" 23 "github.com/pingcap/tiflow/dm/pkg/binlog" 24 "github.com/pingcap/tiflow/dm/pkg/log" 25 "github.com/pingcap/tiflow/dm/pkg/terror" 26 "github.com/pingcap/tiflow/dm/pkg/utils" 27 "github.com/pingcap/tiflow/dm/syncer/binlogstream" 28 ) 29 30 func (s *Syncer) setInitActiveRelayLog(ctx context.Context) error { 31 if s.binlogType != binlogstream.LocalBinlog { 32 return nil 33 } 34 35 var ( 36 pos mysql.Position 37 activeSubDir string 38 extractPos bool 39 err error 40 ) 41 42 indexPath := filepath.Join(s.cfg.RelayDir, utils.UUIDIndexFilename) 43 subDirs, err := utils.ParseUUIDIndex(indexPath) 44 if err != nil { 45 return terror.Annotatef(err, "UUID index file path %s", indexPath) 46 } 47 if len(subDirs) == 0 { 48 return terror.ErrRelayNoValidRelaySubDir.Generate(s.cfg.RelayDir) 49 } 50 51 checkLocation := s.checkpoint.GlobalPoint() 52 switch { 53 case binlog.ComparePosition(checkLocation.Position, binlog.MinPosition) > 0: 54 // continue from previous checkpoint 55 pos = checkLocation.Position 56 extractPos = true 57 case s.cfg.Mode == config.ModeIncrement: 58 // fresh start for task-mode increment 59 pos = mysql.Position{ 60 Name: s.cfg.Meta.BinLogName, 61 Pos: s.cfg.Meta.BinLogPos, 62 } 63 default: 64 // start from dumper or loader, get current pos from master 65 pos, _, err = s.fromDB.GetMasterStatus(s.tctx.WithContext(ctx), s.cfg.Flavor) 66 if err != nil { 67 return terror.Annotatef(err, "get master status") 68 } 69 } 70 71 if extractPos { 72 activeSubDir, _, pos, err = binlog.ExtractPos(pos, subDirs) 73 if err != nil { 74 return err 75 } 76 } else { 77 var uuid string 78 latestSubDir := subDirs[len(subDirs)-1] 79 uuid, err = s.fromDB.GetServerUUID(ctx, s.cfg.Flavor) 80 if err != nil { 81 return terror.WithScope(terror.Annotatef(err, "get server UUID"), terror.ScopeUpstream) 82 } 83 // latest should be the current 84 if !strings.HasPrefix(latestSubDir, uuid) { 85 return terror.ErrSyncerUnitUUIDNotLatest.Generate(uuid, subDirs) 86 } 87 activeSubDir = latestSubDir 88 } 89 90 if len(pos.Name) == 0 { 91 s.tctx.Logger.Warn("empty position, may because only specify GTID and hasn't saved according binlog position") 92 return nil 93 } 94 err = s.readerHub.UpdateActiveRelayLog(s.cfg.Name, activeSubDir, pos.Name) 95 s.recordedActiveRelayLog = true 96 s.tctx.L().Info("current earliest active relay log", log.WrapStringerField("active relay log", s.readerHub.EarliestActiveRelayLog())) 97 return err 98 } 99 100 func (s *Syncer) updateActiveRelayLog(pos mysql.Position) error { 101 if s.binlogType != binlogstream.LocalBinlog { 102 return nil 103 } 104 105 if len(pos.Name) == 0 { 106 s.tctx.Logger.Warn("empty position, may because only specify GTID and hasn't saved according binlog position") 107 return nil 108 } 109 110 indexPath := filepath.Join(s.cfg.RelayDir, utils.UUIDIndexFilename) 111 uuids, err := utils.ParseUUIDIndex(indexPath) 112 if err != nil { 113 return terror.Annotatef(err, "UUID index file path %s", indexPath) 114 } 115 if len(uuids) == 0 { 116 return terror.ErrRelayNoValidRelaySubDir.Generate(s.cfg.RelayDir) 117 } 118 119 activeSubDir, _, pos, err := binlog.ExtractPos(pos, uuids) 120 if err != nil { 121 return err 122 } 123 124 err = s.readerHub.UpdateActiveRelayLog(s.cfg.Name, activeSubDir, pos.Name) 125 s.tctx.L().Info("current earliest active relay log", log.WrapStringerField("active relay log", s.readerHub.EarliestActiveRelayLog())) 126 return err 127 } 128 129 func (s *Syncer) removeActiveRelayLog() { 130 if s.binlogType != binlogstream.LocalBinlog { 131 return 132 } 133 134 s.readerHub.RemoveActiveRelayLog(s.cfg.Name) 135 s.tctx.L().Info("current earliest active relay log", log.WrapStringerField("active relay log", s.readerHub.EarliestActiveRelayLog())) 136 }