14 736 Lab 2 raft go

package raft

// 14-736 Lab 2 Raft implementation in go

“raft/src/remote”

// LogEntry struct used to store log entries in the Raft node
type LogEntry struct {
Term int
Command int
// raft node structure
type RaftNode struct {
currentTerm int
votedFor int
log []LogEntry
commitIndex int
lastApplied int
nextIndex []int
matchIndex []int

// StatusReport struct sent from Raft node to Controller in response to command and status requests.
// this is needed by the Controller, so do not change it. make sure you give it to the Controller
// when requested
type StatusReport struct {
Index int
Term int
Leader bool
CallCount int

// RaftInterface — this is the “service interface” that is implemented by each Raft peer using the
// remote library from Lab 1. it supports five remote methods that you must define and implement.
// these methods are described as follows:
// 1. RequestVote — this is one of the remote calls defined in the Raft paper, and it should be
// supported as such. you will need to include whatever argument types are needed per the Raft
// algorithm, and you can package the return values however you like, as long as the last return
// type is `remote.RemoteObjectError`, since that is required for the remote library use.
// 2. AppendEntries — this is one of the remote calls defined in the Raft paper, and it should be
// supported as such and defined in a similar manner to RequestVote above.
// 3. GetCommittedCmd — this is a remote call that is used by the Controller in the test code. it
// allows the Controller to check the value of a commmitted log entry at a given index. the
// type of the function is given below, and it must be implemented as given, otherwise the test
// code will not function correctly. more detail about this method is available later in this
// starter code file.
// 4. GetStatus — this is a remote call that is used by the Controller to collect status information
// about the Raft peer. the struct type that it returns is defined above, and it must be implemented
// as given, or the Controller and test code will not function correctly. more detail below.
// 5. NewCommand — this is a remote call that is used by the Controller to emulate submission of
// a new command value by a Raft client. upon receipt, it will initiate processing of the command
// and reply back to the Controller with a StatusReport struct as defined above. it must be
// implemented as given, or the test code will not function correctly. more detail below
type RaftInterface struct {
RequestVote func() // TODO: define function type
AppendEntries func() // TODO: define function type
GetCommittedCmd func(int) (int, remote.RemoteObjectError)
GetStatus func() (StatusReport, remote.RemoteObjectError)
NewCommand func(int) (StatusReport, remote.RemoteObjectError)

// you will need to define a struct that contains the parameters/variables that define and
// explain the current status of each Raft peer. it doesn’t matter what you call this struct,
// and the test code doesn’t really care what state it contains, so this part is up to you.
// TODO: define a struct to maintain the local state of a single Raft peer

// `NewRaftPeer` — this method should create an instance of the above struct and return a pointer
// to it back to the Controller, which calls this method. this allows the Controller to create,
// interact with, and control the configuration as needed. this method takes three parameters:
// — port: this is the service port number where this Raft peer will listen for incoming messages
// — id: this is the ID (or index) of this Raft peer in the peer group, ranging from 0 to num-1
// — num: this is the number of Raft peers in the peer group (num > id)
func NewRaftPeer(port int, id int, num int) *struct{} { // TODO: <---- change the return type // TODO: create a new raft peer and return a pointer to it // when a new raft peer is created, its initial state should be populated into the corresponding // struct entries, and its `remote.Service` and `remote.StubFactory` components should be created, // but the Service should not be started (the Controller will do that when ready). // the `remote.Service` should be bound to port number `port`, as given in the input argument. // each `remote.StubFactory` will be used to interact with a different Raft peer, and different // port numbers are used for each Raft peer. the Controller assigns these port numbers sequentially // starting from peer with `id = 0` and ending with `id = num-1`, so any peer who knows its own // `id`, `port`, and `num` can determine the port number used by any other peer. remote.NewService(&RaftInterface{}, ) remote.StubFactory(port, &RaftInterface{}) return nil // `Activate` -- this method operates on your Raft peer struct and initiates functionality // to allow the Raft peer to interact with others. before the peer is activated, it can // have internal algorithm state, but it cannot make remote calls using its stubs or receive // remote calls using its underlying remote.Service interface. in essence, when not activated, // the Raft peer is "sleeping" from the perspective of any other Raft peer. // this method is used exclusively by the Controller whenever it needs to "wake up" the Raft // peer and allow it to start interacting with other Raft peers. this is used to emulate // connecting a new peer to the network or recovery of a previously failed peer. // when this method is called, the Raft peer should do whatever is necessary to enable its // remote.Service interface to support remote calls from other Raft peers as soon as the method // returns (i.e., if it takes time for the remote.Service to start, this method should not // return until that happens). the method should not otherwise block the Controller, so it may // be useful to spawn go routines from this method to handle the on-going operation of the Raft // peer until the remote.Service stops. // given an instance `rf` of your Raft peer struct, the Controller will call this method // as `rf.Activate()`, so you should define this method accordingly. NOTE: this is _not_ // a remote call using the `remote.Service` interface of the Raft peer. it uses direct // method calls from the Controller, and is used purely for the purposes of the test code. // you should not be using this method for any messaging between Raft peers. // TODO: implement the `Activate` method // `Deactivate` -- this method performs the "inverse" operation to `Activate`, namely to emulate // disconnection / failure of the Raft peer. when called, the Raft peer should effectively "go // to sleep", meaning it should stop its underlying remote.Service interface, including shutting // down the listening socket, causing any further remote calls to this Raft peer to fail due to // connection error. when deactivated, a Raft peer should not make or receive any remote calls, // and any execution of the Raft protocol should effectively pause. however, local state should // be maintained, meaning if a Raft node was the LEADER when it was deactivated, it should still // believe it is the leader when it reactivates. // given an instance `rf` of your Raft peer struct, the Controller will call this method // as `rf.Deactivate()`, so you should define this method accordingly. Similar notes / details // apply here as with `Activate` // TODO: implement the `Deactivate` method // TODO: implement remote method calls from other Raft peers: // RequestVote -- as described in the Raft paper, called by other Raft peers // AppendEntries -- as described in the Raft paper, called by other Raft peers // GetCommittedCmd -- called (only) by the Controller. this method provides an input argument // `index`. if the Raft peer has a log entry at the given `index`, and that log entry has been // committed (per the Raft algorithm), then the command stored in the log entry should be returned // to the Controller. otherwise, the Raft peer should return the value 0, which is not a valid // command number and indicates that no committed log entry exists at that index // GetStatus -- called (only) by the Controller. this method takes no arguments and is essentially // a "getter" for the state of the Raft peer, including the Raft peer's current term, current last // log index, role in the Raft algorithm, and total number of remote calls handled since starting. // the method returns a `StatusReport` struct as defined at the top of this file. // NewCommand -- called (only) by the Controller. this method emulates submission of a new command // by a Raft client to this Raft peer, which should be handled and processed according to the rules // of the Raft algorithm. once handled, the Raft peer should return a `StatusReport` struct with // the updated status after the new command was handled. // general notes: // - you are welcome to use additional helper to handle various aspects of the Raft algorithm logic // within the scope of a single Raft peer. you should not need to create any additional remote // calls between Raft peers or the Controller. if there is a desire to create additional remote // calls, please talk with the course staff before doing so. // - please make sure to read the Raft paper (https://raft.github.io/raft.pdf) before attempting // any coding for this lab. you will most likely need to refer to it many times during your // implementation and testing tasks, so please consult the paper for algorithm details. // - each Raft peer will accept a lot of remote calls from other Raft peers and the Controller, // so use of locks / mutexes is essential. you are expected to use locks correctly in order to // prevent race conditions in your implementation. the Makefile supports testing both without // and with go's race detector, and the final auto-grader will enable the race detector, which will // cause tests to fail if any race conditions are encountered.