blob: fe2f86503e0851ec425db8a074c7bbe6099f3cca [file] [log] [blame]
khenaidood948f772021-08-11 17:49:24 -04001// Copyright 2017 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 etcdserver
16
17import (
18 "fmt"
19 "os"
20 "time"
21
22 "github.com/coreos/etcd/lease"
23 "github.com/coreos/etcd/mvcc"
24 "github.com/coreos/etcd/mvcc/backend"
25 "github.com/coreos/etcd/raft/raftpb"
26 "github.com/coreos/etcd/snap"
27)
28
29func newBackend(cfg ServerConfig) backend.Backend {
30 bcfg := backend.DefaultBackendConfig()
31 bcfg.Path = cfg.backendPath()
32 if cfg.QuotaBackendBytes > 0 && cfg.QuotaBackendBytes != DefaultQuotaBytes {
33 // permit 10% excess over quota for disarm
34 bcfg.MmapSize = uint64(cfg.QuotaBackendBytes + cfg.QuotaBackendBytes/10)
35 }
36 return backend.New(bcfg)
37}
38
39// openSnapshotBackend renames a snapshot db to the current etcd db and opens it.
40func openSnapshotBackend(cfg ServerConfig, ss *snap.Snapshotter, snapshot raftpb.Snapshot) (backend.Backend, error) {
41 snapPath, err := ss.DBFilePath(snapshot.Metadata.Index)
42 if err != nil {
43 return nil, fmt.Errorf("database snapshot file path error: %v", err)
44 }
45 if err := os.Rename(snapPath, cfg.backendPath()); err != nil {
46 return nil, fmt.Errorf("rename snapshot file error: %v", err)
47 }
48 return openBackend(cfg), nil
49}
50
51// openBackend returns a backend using the current etcd db.
52func openBackend(cfg ServerConfig) backend.Backend {
53 fn := cfg.backendPath()
54 beOpened := make(chan backend.Backend)
55 go func() {
56 beOpened <- newBackend(cfg)
57 }()
58 select {
59 case be := <-beOpened:
60 return be
61 case <-time.After(10 * time.Second):
62 plog.Warningf("another etcd process is using %q and holds the file lock, or loading backend file is taking >10 seconds", fn)
63 plog.Warningf("waiting for it to exit before starting...")
64 }
65 return <-beOpened
66}
67
68// recoverBackendSnapshot recovers the DB from a snapshot in case etcd crashes
69// before updating the backend db after persisting raft snapshot to disk,
70// violating the invariant snapshot.Metadata.Index < db.consistentIndex. In this
71// case, replace the db with the snapshot db sent by the leader.
72func recoverSnapshotBackend(cfg ServerConfig, oldbe backend.Backend, snapshot raftpb.Snapshot) (backend.Backend, error) {
73 var cIndex consistentIndex
74 kv := mvcc.New(oldbe, &lease.FakeLessor{}, nil, &cIndex)
75 defer kv.Close()
76 if snapshot.Metadata.Index <= kv.ConsistentIndex() {
77 return oldbe, nil
78 }
79 oldbe.Close()
80 return openSnapshotBackend(cfg, snap.New(cfg.SnapDir()), snapshot)
81}