github.com/pingcap/tiflow@v0.0.0-20240520035814-5bf52d54e205/dm/pkg/binlog/file.go (about)

     1  // Copyright 2021 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 binlog
    15  
    16  import (
    17  	"os"
    18  	"sort"
    19  
    20  	"github.com/pingcap/tiflow/dm/pkg/log"
    21  	"github.com/pingcap/tiflow/dm/pkg/terror"
    22  	"github.com/pingcap/tiflow/dm/pkg/utils"
    23  	"go.uber.org/zap"
    24  )
    25  
    26  // ReadSortedBinlogFromDir reads and returns all binlog files (sorted ascending by binlog filename and sequence number).
    27  func ReadSortedBinlogFromDir(dirpath string) ([]string, error) {
    28  	dir, err := os.Open(dirpath)
    29  	if err != nil {
    30  		return nil, terror.ErrReadDir.Delegate(err, dirpath)
    31  	}
    32  	defer dir.Close()
    33  
    34  	names, err := dir.Readdirnames(-1)
    35  	if err != nil {
    36  		return nil, terror.ErrReadDir.Delegate(err, dirpath)
    37  	}
    38  	if len(names) == 0 {
    39  		return nil, nil
    40  	}
    41  
    42  	// sorting bin.100000, ..., bin.1000000, ..., bin.999999
    43  	type tuple struct {
    44  		filename string
    45  		parsed   utils.Filename
    46  	}
    47  	tmp := make([]tuple, 0, len(names)-1)
    48  
    49  	for _, f := range names {
    50  		p, err2 := utils.ParseFilename(f)
    51  		if err2 != nil {
    52  			// may contain some file that can't be parsed, like relay meta. ignore them
    53  			log.L().Info("collecting binlog file, ignore invalid file", zap.String("file", f))
    54  			continue
    55  		}
    56  		tmp = append(tmp, tuple{
    57  			filename: f,
    58  			parsed:   p,
    59  		})
    60  	}
    61  
    62  	sort.Slice(tmp, func(i, j int) bool {
    63  		if tmp[i].parsed.BaseName != tmp[j].parsed.BaseName {
    64  			return tmp[i].parsed.BaseName < tmp[j].parsed.BaseName
    65  		}
    66  		return tmp[i].parsed.LessThan(tmp[j].parsed)
    67  	})
    68  
    69  	ret := make([]string, len(tmp))
    70  	for i := range tmp {
    71  		ret[i] = tmp[i].filename
    72  	}
    73  
    74  	return ret, nil
    75  }