talent-plan-tinykv/raft/rawnode.go

177 lines
5.2 KiB
Go
Raw Normal View History

// Copyright 2015 The etcd Authors
//
// 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
import (
"errors"
pb "github.com/pingcap-incubator/tinykv/proto/pkg/eraftpb"
)
// ErrStepLocalMsg is returned when try to step a local raft message
var ErrStepLocalMsg = errors.New("raft: cannot step raft local message")
// ErrStepPeerNotFound is returned when try to step a response message
// but there is no peer found in raft.Prs for that node.
var ErrStepPeerNotFound = errors.New("raft: cannot step as peer not found")
// SoftState provides state that is volatile and does not need to be persisted to the WAL.
type SoftState struct {
Lead uint64
RaftState StateType
}
// Ready encapsulates the entries and messages that are ready to read,
// be saved to stable storage, committed or sent to other peers.
// All fields in Ready are read-only.
type Ready struct {
// The current volatile state of a Node.
// SoftState will be nil if there is no update.
// It is not required to consume or store SoftState.
*SoftState
// The current state of a Node to be saved to stable storage BEFORE
// Messages are sent.
// HardState will be equal to empty state if there is no update.
pb.HardState
// Entries specifies entries to be saved to stable storage BEFORE
// Messages are sent.
Entries []pb.Entry
// Snapshot specifies the snapshot to be saved to stable storage.
Snapshot pb.Snapshot
// CommittedEntries specifies entries to be committed to a
// store/state-machine. These have previously been committed to stable
// store.
CommittedEntries []pb.Entry
// Messages specifies outbound messages to be sent AFTER Entries are
// committed to stable storage.
// If it contains a MessageType_MsgSnapshot message, the application MUST report back to raft
// when the snapshot has been received or has failed by calling ReportSnapshot.
Messages []pb.Message
}
// RawNode is a wrapper of Raft.
type RawNode struct {
Raft *Raft
// Your Data Here (2A).
}
// NewRawNode returns a new RawNode given configuration and a list of raft peers.
func NewRawNode(config *Config) (*RawNode, error) {
// Your Code Here (2A).
return nil, nil
}
// Tick advances the internal logical clock by a single tick.
func (rn *RawNode) Tick() {
rn.Raft.tick()
}
// Campaign causes this RawNode to transition to candidate state.
func (rn *RawNode) Campaign() error {
return rn.Raft.Step(pb.Message{
MsgType: pb.MessageType_MsgHup,
})
}
// Propose proposes data be appended to the raft log.
func (rn *RawNode) Propose(data []byte) error {
ent := pb.Entry{Data: data}
return rn.Raft.Step(pb.Message{
MsgType: pb.MessageType_MsgPropose,
From: rn.Raft.id,
Entries: []*pb.Entry{&ent}})
}
// ProposeConfChange proposes a config change.
func (rn *RawNode) ProposeConfChange(cc pb.ConfChange) error {
data, err := cc.Marshal()
if err != nil {
return err
}
ent := pb.Entry{EntryType: pb.EntryType_EntryConfChange, Data: data}
return rn.Raft.Step(pb.Message{
MsgType: pb.MessageType_MsgPropose,
Entries: []*pb.Entry{&ent},
})
}
// ApplyConfChange applies a config change to the local node.
func (rn *RawNode) ApplyConfChange(cc pb.ConfChange) *pb.ConfState {
if cc.NodeId == None {
return &pb.ConfState{Nodes: nodes(rn.Raft)}
}
switch cc.ChangeType {
case pb.ConfChangeType_AddNode:
rn.Raft.addNode(cc.NodeId)
case pb.ConfChangeType_RemoveNode:
rn.Raft.removeNode(cc.NodeId)
default:
panic("unexpected conf type")
}
return &pb.ConfState{Nodes: nodes(rn.Raft)}
}
// Step advances the state machine using the given message.
func (rn *RawNode) Step(m pb.Message) error {
// ignore unexpected local messages receiving over network
if IsLocalMsg(m.MsgType) {
return ErrStepLocalMsg
}
if pr := rn.Raft.Prs[m.From]; pr != nil || !IsResponseMsg(m.MsgType) {
return rn.Raft.Step(m)
}
return ErrStepPeerNotFound
}
// Ready returns the current point-in-time state of this RawNode.
func (rn *RawNode) Ready() Ready {
// Your Code Here (2A).
return Ready{}
}
// HasReady called when RawNode user need to check if any Ready pending.
func (rn *RawNode) HasReady() bool {
// Your Code Here (2A).
return false
}
// Advance notifies the RawNode that the application has applied and saved progress in the
// last Ready results.
func (rn *RawNode) Advance(rd Ready) {
// Your Code Here (2A).
}
2021-11-10 17:27:06 +08:00
// GetProgress return the Progress of this node and its peers, if this
// node is leader.
func (rn *RawNode) GetProgress() map[uint64]Progress {
prs := make(map[uint64]Progress)
if rn.Raft.State == StateLeader {
for id, p := range rn.Raft.Prs {
prs[id] = *p
}
}
return prs
}
// TransferLeader tries to transfer leadership to the given transferee.
func (rn *RawNode) TransferLeader(transferee uint64) {
_ = rn.Raft.Step(pb.Message{MsgType: pb.MessageType_MsgTransferLeader, From: transferee})
}