Commit 25393c3f authored by djq2's avatar djq2
Browse files

Implementing structs and heartbeats

parent 9e261d40
......@@ -20,23 +20,27 @@ package raft
import "sync"
import "sync/atomic"
import "../labrpc"
import "rand"
import "time"
//
// as each Raft peer becomes aware that successive log entries are
// committed, the peer should send an ApplyMsg to the service (or
// tester) on the same server, via the applyCh passed to Make(). set
// CommandValid to true to indicate that the ApplyMsg contains a newly
// committed log entry.
//
type ApplyMsg struct {
CommandValid bool
Command interface{}
CommandIndex int
}
//
// Log entry
type Entry struct{
Command interface{}
Term int
}
// A Go object implementing a single Raft peer.
//
type Raft struct {
mu sync.Mutex // Lock to protect shared access to this peer's state
peers []*labrpc.ClientEnd // RPC end points of all peers
......@@ -47,45 +51,66 @@ type Raft struct {
// Look at the paper's Figure 2 for a description of what
// state a Raft server must maintain.
// You may also need to add other state, as per your implementation.
}
// return currentTerm and whether this server
// believes it is the leader.
func (rf *Raft) GetState() (int, bool) {
currentTerm int // Latest term seen by this process
votedFor interface{} // Id of candidate voted for, null if not voted
log[] Entry // List of received log entries
commitIndex int // Index of highest known committed log entry
lastApplied int // Index of highest entry applied to state machine
var term int
var isleader bool
// Your code here (2A).
return term, isleader
applyCh chan // Channel to send ApplyMsg given a successfully logged command
// For Leaders Only - Metadata on Followers
nextIndex[] int // Index of next log entry to send to server <i>
matchIndex[] int // Index of highest log entry known to be replicated on server <i>
}
//
// example RequestVote RPC arguments structure.
// field names must start with capital letters!
//
// Example RequestVote RPC arguments structure.
// Field names must start with capital letters!
type RequestVoteArgs struct {
// Your data here (2A, 2B).
Term int // Candidate's (Requestor) term
CandidateID interface{} // Id of requestor/candidate
LastLogIndex int // Index of requestor/candidate last log entry
LastLogTerm int // Term of requestor/candidate last log entry
}
type AppendEntriesArgs struct {
// Your data here (2A, 2B).
}
//
// example RequestVote RPC reply structure.
// field names must start with capital letters!
//
type RequestVoteReply struct {
// Your data here (2A).
Term int // Term to update to
VoteGranted bool // True if vote received
}
//
// example RequestVote RPC handler.
//
func (rf *Raft) RequestVote(args *RequestVoteArgs, reply *RequestVoteReply) {
type AppendEntriesReply struct {
// Your data here (2A).
}
// Example RequestVote RPC handler.
func (rf *Raft) RequestVote(args *AppendEntriesArgs, reply *AppendEntriesReply) {
// Your code here (2A, 2B).
// Read the fields in "args",
// and accordingly assign the values for fields in "reply".
}
// Append Entry RPC Handler
func (rf *Raft) HandleAppendEntries(args *AppendEntriesArgs, reply *AppendEntriesReply) {
}
//
// example code to send a RequestVote RPC to a server.
// server is the index of the target server in rf.peers[].
......@@ -115,13 +140,51 @@ func (rf *Raft) RequestVote(args *RequestVoteArgs, reply *RequestVoteReply) {
// that the caller passes the address of the reply struct with &, not
// the struct itself.
//
// Request Vote RPC
func (rf *Raft) sendRequestVote(server int, args *RequestVoteArgs, reply *RequestVoteReply) bool {
ok := rf.peers[server].Call("Raft.RequestVote", args, reply)
return ok
}
// Send Append Entry RPC
func (rf *Raft) sendAppendEntries(server int, args *RequestVoteArgs, reply *RequestVoteReply) bool {
ok := rf.peers[server].Call("Raft.AppendEntries", args, reply)
return ok
}
// Follower Protocol
func (rf *Raft) Follower() {
// Start listening
for {
// Handle timeout or RPC
select {
// RPC received
case received := <-rf.peers[me].ch
if received.svcMeth == "Raft.AppendEntries" {
rf.HandleAppendEntries()
}
else if received.svcMeth == "Raft.RequestVote" {
}
// Timeout
case <-time.After( (350 + (rand.Int() % 150)) * time.Millisecond)
}
}
}
// return currentTerm and whether this server believes it is the leader.
func (rf *Raft) GetState() (int, bool) {
var term int
var isleader bool
// Your code here (2A).
return term, isleader
}
//
// the service using Raft (e.g. a k/v server) wants to start
// agreement on the next command to be appended to Raft's log. if this
// server isn't the leader, returns false. otherwise start the
......@@ -134,7 +197,6 @@ func (rf *Raft) sendRequestVote(server int, args *RequestVoteArgs, reply *Reques
// if it's ever committed. the second return value is the current
// term. the third return value is true if this server believes it is
// the leader.
//
func (rf *Raft) Start(command interface{}) (int, int, bool) {
index := -1
term := -1
......@@ -183,6 +245,10 @@ func Make(peers []*labrpc.ClientEnd, me int,
rf.me = me
// Your initialization code here (2A, 2B).
rf.applyCh = applyCh
// Instantiate node as a follower
go Follower()
return rf
}
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment