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  }