Commit f18eef0f authored by Sushant Mahajan's avatar Sushant Mahajan

leader election working

parent cbd36253
#! /bin/bash #! /bin/bash
rm {1..5} currentTerm* votedFor* log* rm {0..4} currentTerm* votedFor* log*
This diff is collapsed.
// server.go
package raft
import (
"fmt"
"io/ioutil"
"log"
"os"
"strconv"
)
var rafts map[int]*Raft
func getLogger(serverId int, toDebug bool) (l *log.Logger) {
if !toDebug {
l = log.New(ioutil.Discard, "INFO: ", log.Ltime|log.Lshortfile)
} else {
logf, _ := os.OpenFile(strconv.Itoa(serverId), os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0666)
l = log.New(logf, "INFO: ", log.Ltime|log.Lmicroseconds|log.Lshortfile)
}
l.Println("Initialized server.")
return l
}
func Start(serverId int, toDebug bool) {
eventCh := make(chan RaftEvent)
commitCh := make(chan LogEntry)
monitorVotesCh := make(chan bool)
clusterConfig, _ := NewClusterConfig(5)
rft, _ := NewRaft(clusterConfig, serverId, commitCh, eventCh, monitorVotesCh, true)
if rafts == nil {
rafts = make(map[int]*Raft)
}
rafts[serverId] = rft
fmt.Println(len(rafts))
rft.loop()
}
...@@ -11,6 +11,7 @@ import ( ...@@ -11,6 +11,7 @@ import (
"os" "os"
"raft" "raft"
"strconv" "strconv"
"time"
) )
// Logger // Logger
...@@ -20,10 +21,10 @@ var Info *log.Logger ...@@ -20,10 +21,10 @@ var Info *log.Logger
var rft *raft.Raft var rft *raft.Raft
//Receiver for RPC //Receiver for RPC
type AppendEntries struct{} type RaftRPCService struct{}
//Receiver for voting related RPC //Receiver for voting related RPC
type Voting struct{} //type Voting struct{}
//receiver for testing RPC //receiver for testing RPC
//only for testing purpose //only for testing purpose
...@@ -72,7 +73,7 @@ type Reply struct { ...@@ -72,7 +73,7 @@ type Reply struct {
//arguments: pointer to argument struct (has LogEntryData), pointer to reply struct //arguments: pointer to argument struct (has LogEntryData), pointer to reply struct
//returns: error //returns: error
//receiver: pointer to AppendEntries //receiver: pointer to AppendEntries
func (t *AppendEntries) AppendRPC(args *raft.AppendRPC, reply *Reply) error { func (t *RaftRPCService) AppendRPC(args *raft.AppendRPC, reply *Reply) error {
Info.Println("append RPC invoked") Info.Println("append RPC invoked")
rft.AddToEventChannel(args) rft.AddToEventChannel(args)
reply.X = 1 reply.X = 1
...@@ -83,7 +84,7 @@ func (t *AppendEntries) AppendRPC(args *raft.AppendRPC, reply *Reply) error { ...@@ -83,7 +84,7 @@ func (t *AppendEntries) AppendRPC(args *raft.AppendRPC, reply *Reply) error {
return nil*/ return nil*/
} }
func (t *AppendEntries) AppendReplyRPC(args *raft.AppendReplyRPC, reply *Reply) error { func (t *RaftRPCService) AppendReplyRPC(args *raft.AppendReply, reply *Reply) error {
Info.Println("append reply to leader RPC invoked") Info.Println("append reply to leader RPC invoked")
rft.AddToEventChannel(args) rft.AddToEventChannel(args)
reply.X = 1 reply.X = 1
...@@ -98,7 +99,7 @@ func (t *AppendEntries) AppendReplyRPC(args *raft.AppendReplyRPC, reply *Reply) ...@@ -98,7 +99,7 @@ func (t *AppendEntries) AppendReplyRPC(args *raft.AppendReplyRPC, reply *Reply)
//arguments: pointer to argument struct (has LogEntry), pointer to reply struct //arguments: pointer to argument struct (has LogEntry), pointer to reply struct
//returns: error //returns: error
//receiver: pointer to AppendEntries //receiver: pointer to AppendEntries
func (t *AppendEntries) CommitRPC(args *raft.CommitData, reply *Reply) error { func (t *RaftRPCService) CommitRPC(args *raft.CommitData, reply *Reply) error {
Info.Println("Commit RPC invoked") Info.Println("Commit RPC invoked")
rft.LogArray[(*args).Id].SetCommitted(true) rft.LogArray[(*args).Id].SetCommitted(true)
rft.AddToChannel(rft.LogArray[(*args).Id]) rft.AddToChannel(rft.LogArray[(*args).Id])
...@@ -106,29 +107,30 @@ func (t *AppendEntries) CommitRPC(args *raft.CommitData, reply *Reply) error { ...@@ -106,29 +107,30 @@ func (t *AppendEntries) CommitRPC(args *raft.CommitData, reply *Reply) error {
return nil return nil
} }
func (t *Voting) VoteRequestRPC(args *raft.VoteRequest, reply *Reply) { func (t *RaftRPCService) VoteRequestRPC(args *raft.VoteRequest, reply *Reply) error {
Info.Println("Request Vote RPC received from server", id) Info.Println("Request Vote RPC received")
rft.AddToEventChannel(args) rft.AddToEventChannel(args)
reply.X = 1 reply.X = 1
return nil return nil
} }
func (t *Voting) CastVoteRPC(args *raft.VoteRequestReply, reply *Reply) { func (t *RaftRPCService) CastVoteRPC(args *raft.VoteRequestReply, reply *Reply) error {
Info.Println("Request Vote RPC received from server", id) Info.Println("Cast Vote RPC received")
rft.AddToMonitorVotesChannel(args) rft.AddToMonitorVotesChannel(args)
reply.X = 1 reply.X = 1
return nil return nil
} }
//Initialize all the things necessary for start the server for inter raft communication. //Initialize all the things necessary for start the server for inter raft communication.
//The servers are running on ports 20000+serverId. {1..5} //The servers are running on ports 20000+serverId. {0..4}
//arguments: pointer to current server config, pointer to raft object, a bool channel to set to true to let //arguments: pointer to current server config, pointer to raft object, a bool channel to set to true to let
//the invoker know that the proc ended. //the invoker know that the proc ended.
//returns: none //returns: none
//receiver: none //receiver: none
func initInterServerCommunication(server *raft.ServerConfig, rft *raft.Raft, ch chan bool) { func initInterServerCommunication(server *raft.ServerConfig, rft *raft.Raft, ch chan bool) {
appendRpc := new(AppendEntries) raftRPC := new(RaftRPCService)
rpc.Register(appendRpc) rpc.Register(raftRPC)
listener, e := net.Listen("tcp", ":"+strconv.Itoa(server.LogPort)) listener, e := net.Listen("tcp", ":"+strconv.Itoa(server.LogPort))
if e != nil { if e != nil {
Info.Fatal("listen error:", e) Info.Fatal("listen error:", e)
...@@ -152,9 +154,9 @@ func initInterServerCommunication(server *raft.ServerConfig, rft *raft.Raft, ch ...@@ -152,9 +154,9 @@ func initInterServerCommunication(server *raft.ServerConfig, rft *raft.Raft, ch
func initLogger(serverId int, toDebug bool) { func initLogger(serverId int, toDebug bool) {
// Logger Initializaion // Logger Initializaion
if !toDebug { if !toDebug {
Info = log.New(ioutil.Discard, "INFO: ", log.Ldate|log.Ltime|log.Lshortfile) Info = log.New(ioutil.Discard, "INFO: ", log.Ldate|log.Lmicroseconds|log.Lshortfile)
} else { } else {
Info = log.New(os.Stdout, "INFO: ", log.Ldate|log.Ltime|log.Lshortfile) Info = log.New(os.Stdout, "INFO: ", log.Ldate|log.Lmicroseconds|log.Lshortfile)
} }
Info.Println("Initialized server.") Info.Println("Initialized server.")
...@@ -184,12 +186,9 @@ func initClientCommunication(server *raft.ServerConfig, rft *raft.Raft, ch chan ...@@ -184,12 +186,9 @@ func initClientCommunication(server *raft.ServerConfig, rft *raft.Raft, ch chan
//Entry point for application. Starts all major server go routines and then waits for ever //Entry point for application. Starts all major server go routines and then waits for ever
func main() { func main() {
sid, err := strconv.Atoi(os.Args[1]) sid, _ := strconv.Atoi(os.Args[1])
ch1 := make(chan bool) ch1 := make(chan bool)
ch2 := make(chan bool) ch2 := make(chan bool)
if err != nil {
Info.Println("argument ", os.Args[1], "is not string")
}
if len(os.Args) > 3 { if len(os.Args) > 3 {
initLogger(sid, true) initLogger(sid, true)
...@@ -214,6 +213,9 @@ func main() { ...@@ -214,6 +213,9 @@ func main() {
go initClientCommunication(server, rft, ch1) go initClientCommunication(server, rft, ch1)
go initInterServerCommunication(server, rft, ch2) go initInterServerCommunication(server, rft, ch2)
time.Sleep(100 * time.Millisecond)
raft.StartRaft(rft)
for <-ch1 && <-ch2 { for <-ch1 && <-ch2 {
} }
......
...@@ -3,13 +3,9 @@ ...@@ -3,13 +3,9 @@
package main package main
import ( import (
"bytes"
//"fmt" //"fmt"
"net"
"net/rpc"
"os" "os"
"os/exec" "os/exec"
"raft"
"strconv" "strconv"
"testing" "testing"
"time" "time"
...@@ -27,16 +23,21 @@ type Testpair struct { ...@@ -27,16 +23,21 @@ type Testpair struct {
// //
func TestAll(t *testing.T) { func TestAll(t *testing.T) {
dummy := make(chan bool)
//start the servers //start the servers
for i := 1; i <= NUM_SERVERS; i++ { for i := 0; i < NUM_SERVERS; i++ {
go startServers(i, t) go startServers(i, t, dummy)
} }
//wait for some time so that servers are ready //wait for some time so that servers are ready
time.Sleep(4 * time.Second)
time.Sleep(1 * time.Second)
if <-dummy {
}
} }
//run servers //run servers
func startServers(i int, t *testing.T) { func startServers(i int, t *testing.T, dummy chan bool) {
cmd := exec.Command("go", "run", "server.go", strconv.Itoa(i), strconv.Itoa(NUM_SERVERS), "x") cmd := exec.Command("go", "run", "server.go", strconv.Itoa(i), strconv.Itoa(NUM_SERVERS), "x")
f, err := os.OpenFile(strconv.Itoa(i), os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0666) f, err := os.OpenFile(strconv.Itoa(i), os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0666)
if err != nil { if err != nil {
......
Markdown is supported
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