...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 package raft
16
17 import pb "go.etcd.io/etcd/raft/v3/raftpb"
18
19
20
21
22
23 type unstable struct {
24
25 snapshot *pb.Snapshot
26
27 entries []pb.Entry
28 offset uint64
29
30 logger Logger
31 }
32
33
34
35 func (u *unstable) maybeFirstIndex() (uint64, bool) {
36 if u.snapshot != nil {
37 return u.snapshot.Metadata.Index + 1, true
38 }
39 return 0, false
40 }
41
42
43
44 func (u *unstable) maybeLastIndex() (uint64, bool) {
45 if l := len(u.entries); l != 0 {
46 return u.offset + uint64(l) - 1, true
47 }
48 if u.snapshot != nil {
49 return u.snapshot.Metadata.Index, true
50 }
51 return 0, false
52 }
53
54
55
56 func (u *unstable) maybeTerm(i uint64) (uint64, bool) {
57 if i < u.offset {
58 if u.snapshot != nil && u.snapshot.Metadata.Index == i {
59 return u.snapshot.Metadata.Term, true
60 }
61 return 0, false
62 }
63
64 last, ok := u.maybeLastIndex()
65 if !ok {
66 return 0, false
67 }
68 if i > last {
69 return 0, false
70 }
71
72 return u.entries[i-u.offset].Term, true
73 }
74
75 func (u *unstable) stableTo(i, t uint64) {
76 gt, ok := u.maybeTerm(i)
77 if !ok {
78 return
79 }
80
81
82
83 if gt == t && i >= u.offset {
84 u.entries = u.entries[i+1-u.offset:]
85 u.offset = i + 1
86 u.shrinkEntriesArray()
87 }
88 }
89
90
91
92
93
94 func (u *unstable) shrinkEntriesArray() {
95
96
97
98
99 const lenMultiple = 2
100 if len(u.entries) == 0 {
101 u.entries = nil
102 } else if len(u.entries)*lenMultiple < cap(u.entries) {
103 newEntries := make([]pb.Entry, len(u.entries))
104 copy(newEntries, u.entries)
105 u.entries = newEntries
106 }
107 }
108
109 func (u *unstable) stableSnapTo(i uint64) {
110 if u.snapshot != nil && u.snapshot.Metadata.Index == i {
111 u.snapshot = nil
112 }
113 }
114
115 func (u *unstable) restore(s pb.Snapshot) {
116 u.offset = s.Metadata.Index + 1
117 u.entries = nil
118 u.snapshot = &s
119 }
120
121 func (u *unstable) truncateAndAppend(ents []pb.Entry) {
122 after := ents[0].Index
123 switch {
124 case after == u.offset+uint64(len(u.entries)):
125
126
127 u.entries = append(u.entries, ents...)
128 case after <= u.offset:
129 u.logger.Infof("replace the unstable entries from index %d", after)
130
131
132 u.offset = after
133 u.entries = ents
134 default:
135
136
137 u.logger.Infof("truncate the unstable entries before index %d", after)
138 u.entries = append([]pb.Entry{}, u.slice(u.offset, after)...)
139 u.entries = append(u.entries, ents...)
140 }
141 }
142
143 func (u *unstable) slice(lo uint64, hi uint64) []pb.Entry {
144 u.mustCheckOutOfBounds(lo, hi)
145 return u.entries[lo-u.offset : hi-u.offset]
146 }
147
148
149 func (u *unstable) mustCheckOutOfBounds(lo, hi uint64) {
150 if lo > hi {
151 u.logger.Panicf("invalid unstable.slice %d > %d", lo, hi)
152 }
153 upper := u.offset + uint64(len(u.entries))
154 if lo < u.offset || hi > upper {
155 u.logger.Panicf("unstable.slice[%d,%d) out of bound [%d,%d]", lo, hi, u.offset, upper)
156 }
157 }
158
View as plain text