Commit 5e03357b authored by Bharath Radhakrishnan's avatar Bharath Radhakrishnan

fixed compilation issues and general housekeeping

parent 40cf442d
package handler
package connhandler
import (
"bufio"
"bytes"
"encoding/gob"
"kvstore"
"net"
"raft"
"strconv"
"strings"
"time"
"utils"
)
/*
*Helper function to read value or cause timeout after READ_TIMEOUT seconds
......@@ -13,7 +26,7 @@ func readValue(ch chan []byte, n uint64) ([]byte, bool) {
up := make(chan bool, 1)
//after 5 seconds passed reading value, we'll just send err to client
go func() {
time.Sleep(READ_TIMEOUT * time.Second)
time.Sleep(kvstore.READ_TIMEOUT * time.Second)
up <- true
}()
......@@ -100,21 +113,52 @@ func MyRead(ch chan []byte, conn net.Conn) {
*/
func Write(conn net.Conn, msg string) {
buf := []byte(msg)
buf = append(buf, []byte(CRLF)...)
buf = append(buf, []byte(kvstore.CRLF)...)
conn.Write(buf)
}
func handleClient(conn net.Conn) {
func HandleClient(conn net.Conn, rft *raft.Raft) {
defer conn.Close()
//channel for every connection for every client
ch := make(chan []byte)
go myRead(ch, conn)
go MyRead(ch, conn)
for {
command := new(utils.Command)
msg := <-ch
if len(msg) == 0 {
continue
}
//kvstore.ParseInput(conn, string(msg), table, ch)
command.Cmd = msg
flag := false
nr := uint64(0)
tokens := strings.Fields(string(msg))
if kvstore.IsCas(tokens[0]) {
n, _ := strconv.ParseUint(tokens[3], 10, 64)
nr = n
flag = true
} else if kvstore.IsSet(tokens[0]) {
n, _ := strconv.ParseUint(tokens[2], 10, 64)
nr = n
flag = true
}
if flag {
if v, err := readValue(ch, nr); err {
Write(conn, kvstore.ERR_CMD_ERR)
} else {
command.Val = v
//command.isVal = true
}
}
buffer := new(bytes.Buffer)
// writing
enc := gob.NewEncoder(buffer)
err := enc.Encode(command)
if err != nil {
//log.Fatal("encode error:", err)
}
rft.Append(buffer.Bytes())
}
}
package kvstore
import (
"bufio"
"bytes"
"fmt"
"io/ioutil"
"log"
"net"
......@@ -107,16 +105,16 @@ var table *KeyValueStore
// }
//}
///*Simple write function to send information to the client
// *arguments: client connection, msg to send to the client
// *return: none
// */
//func write(conn net.Conn, msg string) {
// buf := []byte(msg)
// buf = append(buf, []byte(CRLF)...)
// logger.Println(buf, len(buf))
// conn.Write(buf)
//}
/*Simple write function to send information to the client
*arguments: client connection, msg to send to the client
*return: none
*/
func write(conn net.Conn, msg string) {
buf := []byte(msg)
buf = append(buf, []byte(CRLF)...)
//logger.Println(buf, len(buf))
conn.Write(buf)
}
/*After initial establishment of the connection with the client, this go routine handles further interaction
*arguments: client connection
......@@ -268,7 +266,7 @@ func ParseInput(conn net.Conn, msg string, ch chan []byte) {
if isValid(SET, tokens, conn) != 0 {
return
}
if ver, ok, r := performSet(conn, tokens[1:len(tokens)], table, ch); ok {
if ver, ok, r := performSet(conn, tokens[1:len(tokens)], ch); ok {
//debug(table)
logger.Println(ver)
if r {
......@@ -284,7 +282,7 @@ func ParseInput(conn net.Conn, msg string, ch chan []byte) {
if isValid(GET, tokens, conn) != 0 {
return
}
if data, ok := performGet(conn, tokens[1:len(tokens)], table); ok {
if data, ok := performGet(conn, tokens[1:len(tokens)]); ok {
logger.Println("sending", tokens[1], "data")
buffer.Reset()
buffer.WriteString(VALUE)
......@@ -305,7 +303,7 @@ func ParseInput(conn net.Conn, msg string, ch chan []byte) {
if isValid(GETM, tokens, conn) != 0 {
return
}
if data, ok := performGetm(conn, tokens[1:len(tokens)], table); ok {
if data, ok := performGetm(conn, tokens[1:len(tokens)]); ok {
logger.Println("sending", tokens[1], "metadata")
buffer.Reset()
buffer.WriteString(VALUE)
......@@ -334,7 +332,7 @@ func ParseInput(conn net.Conn, msg string, ch chan []byte) {
if isValid(CAS, tokens, conn) != 0 {
return
}
if ver, ok, r := performCas(conn, tokens[1:len(tokens)], table, ch); r {
if ver, ok, r := performCas(conn, tokens[1:len(tokens)], ch); r {
if r {
switch ok {
case 0:
......@@ -365,7 +363,7 @@ func ParseInput(conn net.Conn, msg string, ch chan []byte) {
if isValid(DELETE, tokens, conn) != 0 {
return
}
if ok := performDelete(conn, tokens[1:len(tokens)], table); ok == 0 {
if ok := performDelete(conn, tokens[1:len(tokens)]); ok == 0 {
write(conn, DELETED)
} else {
write(conn, ERR_NOT_FOUND)
......@@ -384,11 +382,11 @@ func ParseInput(conn net.Conn, msg string, ch chan []byte) {
*return: version of inserted key (if successful, 0 otherwise), success or failure, whether to send reply to client
*/
func performSet(conn net.Conn, tokens []string, ch chan []byte) (uint64, bool, bool) {
k := tokens[0]
//-k := tokens[0]
//expiry time offset
e, _ := strconv.ParseUint(tokens[1], 10, 64)
//-e, _ := strconv.ParseUint(tokens[1], 10, 64)
//numbytes
n, _ := strconv.ParseUint(tokens[2], 10, 64)
//-n, _ := strconv.ParseUint(tokens[2], 10, 64)
r := true
if len(tokens) == 4 && tokens[3] == NOREPLY {
......@@ -397,32 +395,33 @@ func performSet(conn net.Conn, tokens []string, ch chan []byte) (uint64, bool, b
logger.Println(r)
if v, err := readValue(ch, n); err {
write(conn, ERR_CMD_ERR)
return 0, false, r
} else {
defer table.Unlock()
table.Lock()
//critical section start
var val *Data
if _, ok := table.dictionary[k]; ok {
val = table.dictionary[k]
} else {
val = new(Data)
table.dictionary[k] = val
}
val.numBytes = n
val.version++
if e == 0 {
val.isPerpetual = true
val.expTime = 0
} else {
val.isPerpetual = false
val.expTime = e + uint64(time.Now().Unix())
}
val.value = v
return val.version, true, r
}
//if v, err := readValue(ch, n); err {
// write(conn, ERR_CMD_ERR)
// return 0, false, r
//} else {
// defer table.Unlock()
// table.Lock()
// //critical section start
// var val *Data
// if _, ok := table.dictionary[k]; ok {
// val = table.dictionary[k]
// } else {
// val = new(Data)
// table.dictionary[k] = val
// }
// val.numBytes = n
// val.version++
// if e == 0 {
// val.isPerpetual = true
// val.expTime = 0
// } else {
// val.isPerpetual = false
// val.expTime = e + uint64(time.Now().Unix())
// }
// val.value = v
// return val.version, true, r
//}
return 2, true, true
}
/*Delegate function reponsible for activities related to the GET command sent by the client.
......@@ -496,40 +495,41 @@ func performCas(conn net.Conn, tokens []string, ch chan []byte) (uint64, int, bo
}
//read value
if v, err := readValue(ch, n); err {
return 0, 1, r
} else {
defer table.Unlock()
table.Lock()
if val, ok := table.dictionary[k]; ok {
if val.version == ve {
if val.isPerpetual || val.expTime >= uint64(time.Now().Unix()) {
//if expiry time is zero, key should not be deleted
if e == 0 {
val.isPerpetual = true
val.expTime = 0
} else {
val.isPerpetual = false
val.expTime = e + uint64(time.Now().Unix())
}
val.numBytes = n
val.version++
val.value = v
//key found and changed
return val.version, 0, r
} else {
logger.Println("expired key found!")
//version found but key expired, can delete key safely and tell client that it does not exist
delete(table.dictionary, k)
return 0, 3, r
}
}
//version mismatch
return 0, 2, r
}
//key not found
return 0, 3, r
}
//if v, err := readValue(ch, n); err {
// return 0, 1, r
//} else {
// defer table.Unlock()
// table.Lock()
// if val, ok := table.dictionary[k]; ok {
// if val.version == ve {
// if val.isPerpetual || val.expTime >= uint64(time.Now().Unix()) {
// //if expiry time is zero, key should not be deleted
// if e == 0 {
// val.isPerpetual = true
// val.expTime = 0
// } else {
// val.isPerpetual = false
// val.expTime = e + uint64(time.Now().Unix())
// }
// val.numBytes = n
// val.version++
// val.value = v
// //key found and changed
// return val.version, 0, r
// } else {
// logger.Println("expired key found!")
// //version found but key expired, can delete key safely and tell client that it does not exist
// delete(table.dictionary, k)
// return 0, 3, r
// }
// }
// //version mismatch
// return 0, 2, r
// }
// //key not found
// return 0, 3, r
//}
return 1, 1, true
}
/*Delegate function reponsible for activities related to the DELETE command sent by the client.
......@@ -613,11 +613,12 @@ func InitKVStore() {
table = &KeyValueStore{dictionary: make(map[string]*Data)}
}
func IsCasOrSet(msg string) bool {
tokens := strings.Fields(msg)
if len(tokens) >= 1 {
return tokens[0] == SET || tokens[0] == CAS
}
func IsCas(msg string) bool {
return msg == CAS
}
func IsSet(msg string) bool {
return msg == SET
}
//server will not call this, we'll call it from test cases to clear the map
......
package raft
import (
"fmt"
"io/ioutil"
"log"
"net"
"net/rpc"
"os"
"reflect"
"strconv"
"time"
)
......@@ -201,81 +196,3 @@ func NewClusterConfig(num_servers int) (*ClusterConfig, error) {
func (e ErrRedirect) Error() string {
return "Redirect to server " + strconv.Itoa(0)
}
//func start_rpc(this_server *ServerConfig) {
// //rpc.Register()
//}
func (t *AppendEntries) AppendEntriesRPC(args *Args, reply *Reply) error {
reply.X = args.X
return nil
}
func initInterServerCommunication(this_server *ServerConfig) {
appendRpc := new(AppendEntries)
rpc.Register(appendRpc)
listener, e := net.Listen("tcp", ":"+strconv.Itoa(this_server.LogPort))
if e != nil {
Info.Fatal("listen error:", e)
}
for {
if conn, err := listener.Accept(); err != nil {
Info.Fatal("accept error: " + err.Error())
} else {
Info.Printf("new connection established\n")
go rpc.ServeConn(conn)
}
}
}
// Initialize Logger
func initLogger(serverId int) {
// Logger Initializaion
if !DEBUG {
Info = log.New(ioutil.Discard, "INFO: ", log.Ldate|log.Ltime|log.Lshortfile)
} else {
Info = log.New(os.Stdout, "INFO: ", log.Ldate|log.Ltime|log.Lshortfile)
}
Info.Println("Initialized server")
}
func initClientCommunication(server) {
listener, e := net.Listen("tcp", ":"+strconv.Itoa(server.ClientPort))
if e != nil {
Info.Fatal("client listen error:", e)
}
for {
if conn, err := listener.Accept(); err != nil {
Info.Fatal("client accept error: " + err.Error())
} else {
Info.Printf("client new connection established\n")
go handleClient(conn)
}
}
}
func main() {
sid, err := strconv.Atoi(os.Args[1])
if err != nil {
Info.Println("argument ", os.Args[1], "is not string")
}
initLogger(sid)
Info.Println("Start")
server, _ := NewServerConfig(sid)
serverCount, err2 := strconv.Atoi((os.Args[2]))
if err2 != nil {
Info.Println("argument ", os.Args[2], "is not string")
}
cluster_config, _ := NewClusterConfig(serverCount)
initClientCommunication(server)
initInterServerCommunication(server)
var dummy string
fmt.Scanln(&dummy)
}
......@@ -3,10 +3,8 @@ package main
import (
"fmt"
"os"
//"log"
"os/exec"
"strconv"
//"syscall"
)
//constant values used
......@@ -15,7 +13,7 @@ const (
)
func TestServersCommunic(i int) {
cmd := exec.Command("go", "run", "replic_kvstore.go", strconv.Itoa(i+1), strconv.Itoa(NUM_SERVERS))
cmd := exec.Command("go", "run", "server.go", strconv.Itoa(i+1), strconv.Itoa(NUM_SERVERS))
f, err := os.OpenFile(strconv.Itoa(i), os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0666)
if err != nil {
fmt.Println("error opening file: %v", err)
......@@ -25,11 +23,6 @@ func TestServersCommunic(i int) {
cmd.Stdout = f
cmd.Stderr = f
cmd.Run()
/*if err != nil {
fmt.Println(err)
}
fmt.Println(string(out))*/
}
func main() {
......
......@@ -2,18 +2,15 @@
package main
import (
"cs733/assignment2/handler"
"cs733/assignment2/kvstore"
"cs733/assignment2/raft"
"connhandler"
"fmt"
"io/ioutil"
"log"
"net"
"net/rpc"
"os"
"reflect"
"raft"
"strconv"
"time"
)
// Logger
......@@ -22,6 +19,8 @@ var Info *log.Logger
// Flag for enabling/disabling logging functionality
var DEBUG = true
type AppendEntries struct{}
type Args struct {
X int
}
......@@ -30,17 +29,15 @@ type Reply struct {
X int
}
type AppendEntries struct{}
func (t *AppendEntries) AppendEntriesRPC(args *Args, reply *Reply) error {
reply.X = args.X
return nil
}
func initInterServerCommunication(server *raft.ServerConfig, rft *raft.SharedLog) {
func initInterServerCommunication(server *raft.ServerConfig, rft *raft.Raft) {
appendRpc := new(AppendEntries)
rpc.Register(appendRpc)
listener, e := net.Listen("tcp", ":"+strconv.Itoa(this_server.LogPort))
listener, e := net.Listen("tcp", ":"+strconv.Itoa(server.LogPort))
if e != nil {
Info.Fatal("listen error:", e)
}
......@@ -67,7 +64,7 @@ func initLogger(serverId int) {
Info.Println("Initialized server")
}
func initClientCommunication(server *raft.ServerConfig, rft *raft.SharedLog) {
func initClientCommunication(server *raft.ServerConfig, rft *raft.Raft) {
listener, e := net.Listen("tcp", ":"+strconv.Itoa(server.ClientPort))
if e != nil {
Info.Fatal("client listen error:", e)
......@@ -77,7 +74,7 @@ func initClientCommunication(server *raft.ServerConfig, rft *raft.SharedLog) {
Info.Fatal("client accept error: " + err.Error())
} else {
Info.Printf("client new connection established\n")
go handler.HandleClient(conn, rft)
go connhandler.HandleClient(conn, rft)
}
}
}
......@@ -100,7 +97,7 @@ func main() {
clusterConfig, _ := raft.NewClusterConfig(serverCount)
commitCh := make(chan raft.LogEntry)
rft := raft.NewRaft(clusterConfig, sid, commitCh)
rft, _ := raft.NewRaft(clusterConfig, sid, commitCh)
initClientCommunication(server, rft)
initInterServerCommunication(server, rft)
......
......@@ -2,23 +2,23 @@
package utils
import (
"bytes"
"encoding/gob"
"fmt"
)
type Command struct {
cmd []byte
val []byte
Cmd []byte
Val []byte
}
func (d *Command) GobEncode() ([]byte, error) {
w := new(bytes.Buffer)
encoder := gob.NewEncoder(w)
err := encoder.Encode(d.cmd)
err := encoder.Encode(d.Cmd)
if err != nil {
return nil, err
}
err = encoder.Encode(d.val)
err = encoder.Encode(d.Val)
if err != nil {
return nil, err
}
......@@ -28,9 +28,9 @@ func (d *Command) GobEncode() ([]byte, error) {
func (d *Command) GobDecode(buf []byte) error {
r := bytes.NewBuffer(buf)
decoder := gob.NewDecoder(r)
err := decoder.Decode(&d.cmd)
err := decoder.Decode(&d.Cmd)
if err != nil {
return err
}
return decoder.Decode(&d.val)
return decoder.Decode(&d.Val)
}
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