blob: 5c56e228872d47e195cd477643ca0ace2753703e [file] [log] [blame]
khenaidood948f772021-08-11 17:49:24 -04001// 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
15package wal
16
17import (
18 "errors"
19 "fmt"
20 "strings"
21
22 "github.com/coreos/etcd/pkg/fileutil"
23)
24
25var (
26 badWalName = errors.New("bad wal name")
27)
28
29func 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.
40func 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.
56func 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}
70func 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
82func 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
97func 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
105func walName(seq, index uint64) string {
106 return fmt.Sprintf("%016x-%016x.wal", seq, index)
107}