etcd/raft/log_unstable.go

138 lines
3.8 KiB
Go
Raw Normal View History

// Copyright 2015 CoreOS, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package raft
2015-03-08 08:00:13 +03:00
import pb "github.com/coreos/etcd/raft/raftpb"
// unstable.entris[i] has raft log position i+unstable.offset.
// Note that unstable.offset may be less than the highest log
// position in storage; this means that the next write to storage
// might need to truncate the log before persisting unstable.entries.
type unstable struct {
// the incoming unstable snapshot, if any.
snapshot *pb.Snapshot
// all entries that have not yet been written to storage.
entries []pb.Entry
offset uint64
}
// maybeFirstIndex returns the index of the first possible entry in entries
// if it has a snapshot.
func (u *unstable) maybeFirstIndex() (uint64, bool) {
if u.snapshot != nil {
return u.snapshot.Metadata.Index + 1, true
}
return 0, false
}
// maybeLastIndex returns the last index if it has at least one
// unstable entry or snapshot.
func (u *unstable) maybeLastIndex() (uint64, bool) {
if l := len(u.entries); l != 0 {
return u.offset + uint64(l) - 1, true
}
if u.snapshot != nil {
return u.snapshot.Metadata.Index, true
}
return 0, false
}
// myabeTerm returns the term of the entry at index i, if there
// is any.
func (u *unstable) maybeTerm(i uint64) (uint64, bool) {
if i < u.offset {
if u.snapshot == nil {
return 0, false
}
if u.snapshot.Metadata.Index == i {
return u.snapshot.Metadata.Term, true
}
return 0, false
}
last, ok := u.maybeLastIndex()
if !ok {
return 0, false
}
if i > last {
return 0, false
}
return u.entries[i-u.offset].Term, true
}
func (u *unstable) stableTo(i, t uint64) {
2014-11-29 02:14:22 +03:00
gt, ok := u.maybeTerm(i)
if !ok {
return
}
// if i < offest, term is matched with the snapshot
// only update the unstalbe entries if term is matched with
// an unstable entry.
if gt == t && i >= u.offset {
u.entries = u.entries[i+1-u.offset:]
u.offset = i + 1
}
}
func (u *unstable) stableSnapTo(i uint64) {
if u.snapshot != nil && u.snapshot.Metadata.Index == i {
u.snapshot = nil
}
}
func (u *unstable) restore(s pb.Snapshot) {
u.offset = s.Metadata.Index + 1
u.entries = nil
u.snapshot = &s
}
2014-12-02 19:50:15 +03:00
func (u *unstable) truncateAndAppend(ents []pb.Entry) {
after := ents[0].Index - 1
switch {
case after == u.offset+uint64(len(u.entries))-1:
// after is the last index in the u.entries
// directly append
u.entries = append(u.entries, ents...)
case after < u.offset:
2015-06-02 01:06:38 +03:00
raftLogger.Infof("replace the unstable entries from index %d", after+1)
// The log is being truncated to before our current offset
// portion, so set the offset and replace the entries
u.offset = after + 1
u.entries = ents
default:
// truncate to after and copy to u.entries
// then append
2015-06-02 01:06:38 +03:00
raftLogger.Infof("truncate the unstable entries to index %d", after)
u.entries = append([]pb.Entry{}, u.slice(u.offset, after+1)...)
u.entries = append(u.entries, ents...)
}
}
func (u *unstable) slice(lo uint64, hi uint64) []pb.Entry {
2014-12-03 03:19:37 +03:00
u.mustCheckOutOfBounds(lo, hi)
return u.entries[lo-u.offset : hi-u.offset]
}
2014-12-03 03:19:37 +03:00
// u.offset <= lo <= hi <= u.offset+len(u.offset)
func (u *unstable) mustCheckOutOfBounds(lo, hi uint64) {
if lo > hi {
2015-06-02 01:06:38 +03:00
raftLogger.Panicf("invalid unstable.slice %d > %d", lo, hi)
}
2014-12-03 03:19:37 +03:00
upper := u.offset + uint64(len(u.entries))
if lo < u.offset || hi > upper {
2015-06-02 01:06:38 +03:00
raftLogger.Panicf("unstable.slice[%d,%d) out of bound [%d,%d]", lo, hi, u.offset, upper)
}
}