go.etcd.io/etcd@v3.3.27+incompatible/wal/util.go (about) 1 // Copyright 2015 The etcd Authors 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 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package wal 16 17 import ( 18 "errors" 19 "fmt" 20 "strings" 21 22 "github.com/coreos/etcd/pkg/fileutil" 23 ) 24 25 var ( 26 badWalName = errors.New("bad wal name") 27 ) 28 29 func Exist(dirpath string) bool { 30 names, err := fileutil.ReadDir(dirpath) 31 if err != nil { 32 return false 33 } 34 return len(names) != 0 35 } 36 37 // searchIndex returns the last array index of names whose raft index section is 38 // equal to or smaller than the given index. 39 // The given names MUST be sorted. 40 func searchIndex(names []string, index uint64) (int, bool) { 41 for i := len(names) - 1; i >= 0; i-- { 42 name := names[i] 43 _, curIndex, err := parseWalName(name) 44 if err != nil { 45 plog.Panicf("parse correct name should never fail: %v", err) 46 } 47 if index >= curIndex { 48 return i, true 49 } 50 } 51 return -1, false 52 } 53 54 // names should have been sorted based on sequence number. 55 // isValidSeq checks whether seq increases continuously. 56 func isValidSeq(names []string) bool { 57 var lastSeq uint64 58 for _, name := range names { 59 curSeq, _, err := parseWalName(name) 60 if err != nil { 61 plog.Panicf("parse correct name should never fail: %v", err) 62 } 63 if lastSeq != 0 && lastSeq != curSeq-1 { 64 return false 65 } 66 lastSeq = curSeq 67 } 68 return true 69 } 70 func readWalNames(dirpath string) ([]string, error) { 71 names, err := fileutil.ReadDir(dirpath) 72 if err != nil { 73 return nil, err 74 } 75 wnames := checkWalNames(names) 76 if len(wnames) == 0 { 77 return nil, ErrFileNotFound 78 } 79 return wnames, nil 80 } 81 82 func checkWalNames(names []string) []string { 83 wnames := make([]string, 0) 84 for _, name := range names { 85 if _, _, err := parseWalName(name); err != nil { 86 // don't complain about left over tmp files 87 if !strings.HasSuffix(name, ".tmp") { 88 plog.Warningf("ignored file %v in wal", name) 89 } 90 continue 91 } 92 wnames = append(wnames, name) 93 } 94 return wnames 95 } 96 97 func parseWalName(str string) (seq, index uint64, err error) { 98 if !strings.HasSuffix(str, ".wal") { 99 return 0, 0, badWalName 100 } 101 _, err = fmt.Sscanf(str, "%016x-%016x.wal", &seq, &index) 102 return seq, index, err 103 } 104 105 func walName(seq, index uint64) string { 106 return fmt.Sprintf("%016x-%016x.wal", seq, index) 107 }