func (chordNode *ChordNode) checkPredecessor() { chordNode.Logger.Println("Chord : In checkPredecessor") //RPC call to check predecessor jsonMessage := "{\"method\":\"CheckPredecessor\",\"params\":[]}" chordNode.Logger.Println("Predecessor:", chordNode.Predecessor) chordNode.Logger.Println("Predecessor serverInfo:", chordNode.FtServerMapping[chordNode.Predecessor]) clientServerInfo := rpcclient.ServerInfo{} clientServerInfo.ServerID = chordNode.FtServerMapping[chordNode.Predecessor].ServerID clientServerInfo.Protocol = chordNode.FtServerMapping[chordNode.Predecessor].Protocol clientServerInfo.IpAddress = chordNode.FtServerMapping[chordNode.Predecessor].IpAddress clientServerInfo.Port = chordNode.FtServerMapping[chordNode.Predecessor].Port chordNode.Logger.Println("RPC call to:", clientServerInfo) client := &rpcclient.RPCClient{} err, response := client.RpcCall(clientServerInfo, jsonMessage) chordNode.Logger.Println("Response:", response) if err != nil { chordNode.Logger.Println(err) return } chordNode.Logger.Println("response.Result=", response.(*(rpcclient.ResponseParameters)).Result) // Set the predecessor to nil if empty response if response.(*(rpcclient.ResponseParameters)).Result == nil { chordNode.Logger.Println("SETTING PREDECESSOR TO NIL") chordNode.SetPredecessor(true, 0) } }
// initially FingerTableIndex = 0 func (chordNode *ChordNode) fixFingers(FingerTableIndex int) { chordNode.Logger.Println("Chord : In fixFingers") //find the successor of (p+2^(i-1)) by initiaing the find_successor call from the current node nextNodeId := chordNode.Id + uint32(math.Pow(2, float64(FingerTableIndex-1))) jsonMessage := "{\"method\":\"findSuccessor\",\"params\":[" + fmt.Sprint(nextNodeId) + "]}" clientServerInfo := rpcclient.ServerInfo{} clientServerInfo.ServerID = chordNode.MyServerInfo.ServerID clientServerInfo.Protocol = chordNode.MyServerInfo.Protocol clientServerInfo.IpAddress = chordNode.MyServerInfo.IpAddress clientServerInfo.Port = chordNode.MyServerInfo.Port client := &rpcclient.RPCClient{} err, response := client.RpcCall(clientServerInfo, jsonMessage) if err != nil { chordNode.Logger.Println(err) return } // process only if response is present if response.(*(rpcclient.ResponseParameters)).Result != nil { chordNode.FingerTable[FingerTableIndex] = uint32((response.(*(rpcclient.ResponseParameters)).Result[0]).(float64)) resultServerInfo := rpcclient.ServerInfo{} for key, value := range response.(*(rpcclient.ResponseParameters)).Result[1].(map[string]interface{}) { switch key { case "serverID": resultServerInfo.ServerID = value.(string) break case "protocol": resultServerInfo.Protocol = value.(string) break case "IpAddress": resultServerInfo.IpAddress = value.(string) break case "Port": resultServerInfo.Port = int(value.(float64)) } } chordNode.FtServerMapping[chordNode.FingerTable[FingerTableIndex]] = resultServerInfo chordNode.Successor = chordNode.FingerTable[1] } chordNode.Logger.Println("FingerTable=", chordNode.FingerTable) }
func getDefaultServerInfo() rpcclient.ServerInfo { serverInfo := rpcclient.ServerInfo{} serverInfo.ServerID = "mainserver" serverInfo.Protocol = "tcp" serverInfo.IpAddress = "127.0.0.1" serverInfo.Port = 1234 return serverInfo }
func (chordNode *ChordNode) join(serverInfo rpcclient.ServerInfo) { chordNode.Logger.Println("Chord : In Join") jsonMessage := "{\"method\":\"findSuccessor\",\"params\":[" + fmt.Sprint(chordNode.Id) + "]}" clientServerInfo := rpcclient.ServerInfo{} clientServerInfo.ServerID = serverInfo.ServerID clientServerInfo.Protocol = serverInfo.Protocol clientServerInfo.IpAddress = serverInfo.IpAddress clientServerInfo.Port = serverInfo.Port client := &rpcclient.RPCClient{} err, response := client.RpcCall(clientServerInfo, jsonMessage) if err != nil { chordNode.Logger.Println(err) return } chordNode.Predecessor = 0 chordNode.Successor = uint32((response.(*(rpcclient.ResponseParameters)).Result[0]).(float64)) resultServerInfo := rpcclient.ServerInfo{} for key, value := range response.(*(rpcclient.ResponseParameters)).Result[1].(map[string]interface{}) { switch key { case "serverID": resultServerInfo.ServerID = value.(string) break case "protocol": resultServerInfo.Protocol = value.(string) break case "IpAddress": resultServerInfo.IpAddress = value.(string) break case "Port": resultServerInfo.Port = int(value.(float64)) } } chordNode.FtServerMapping[chordNode.Successor] = resultServerInfo }
func (chordNode *ChordNode) updateFtServerMapping(id uint32, serverInfo rpcclient.ServerInfo) { if _, ok := chordNode.FtServerMapping[id]; !ok { clientServerInfo := rpcclient.ServerInfo{} clientServerInfo.ServerID = serverInfo.ServerID clientServerInfo.Protocol = serverInfo.Protocol clientServerInfo.IpAddress = serverInfo.IpAddress clientServerInfo.Port = serverInfo.Port chordNode.FtServerMapping[id] = clientServerInfo } }
/* Use this function to create server info to whom RPCcall is going to be made Input: Chord Id of the server */ func (chordNode *ChordNode) PrepareClientServerInfo(chordID uint32) (rpcclient.ServerInfo, error) { clientServerInfo := rpcclient.ServerInfo{} if _, ok := chordNode.FtServerMapping[chordID]; ok { clientServerInfo.ServerID = chordNode.FtServerMapping[chordID].ServerID clientServerInfo.Protocol = chordNode.FtServerMapping[chordID].Protocol clientServerInfo.IpAddress = chordNode.FtServerMapping[chordID].IpAddress clientServerInfo.Port = chordNode.FtServerMapping[chordID].Port return clientServerInfo, nil } else { customError := errors.New("Entry not found in FTServerMapping") chordNode.Logger.Println(customError) return rpcclient.ServerInfo{}, customError } }
/* request <-"{"method":"Notify","params":[10,{"ServerID":"9999","Protocol":"tcp","IpAddress":"127.0.0.1","Port":1235}]}" response <- "{"result":[],"id":,"error":null }" */ func (rpcMethod *RPCMethod) Notify(jsonInput RequestParameters, jsonOutput *ResponseParameters) error { //Initialize rpcserver var err error err, rpcMethod.rpcServer = GetRPCServerInstance() var customError error if err != nil { customError = errors.New("Getting Server Instance error :" + err.Error()) rpcMethod.rpcServer.logger.Println(customError) return customError } rpcMethod.rpcServer.logger.Println("RPCCall: In Notify") rpcMethod.rpcServer.logger.Println("Input=", jsonInput) var probablePredecessorId uint32 probablePredecessorServerInfo := rpcclient.ServerInfo{} var parameters []interface{} parameters = jsonInput.Params //get inputId from the []interface for k, v := range parameters { if k == 0 { probablePredecessorId = uint32(v.(float64)) } else if k == 1 { resultServerInfo := rpcclient.ServerInfo{} for key, value := range v.(map[string]interface{}) { switch key { case "serverID": resultServerInfo.ServerID = value.(string) break case "protocol": resultServerInfo.Protocol = value.(string) break case "IpAddress": resultServerInfo.IpAddress = value.(string) break case "Port": resultServerInfo.Port = int(value.(float64)) } } probablePredecessorServerInfo = resultServerInfo } } //probablePredecessor ∈ (predecessor, chordNode) isPredecessorNil, predecessor := rpcMethod.rpcServer.chordNode.GetPredecessor() //predecessor == chordNode.Id refers to the case where the ActualNodesInRing = 1 i.e. predecessor is the node itself nodeId := rpcMethod.rpcServer.chordNode.Id if isPredecessorNil || (probablePredecessorId > predecessor && probablePredecessorId < nodeId) || predecessor == nodeId || (probablePredecessorId < nodeId && predecessor > probablePredecessorId && predecessor > nodeId) || (probablePredecessorId > nodeId && predecessor < probablePredecessorId && predecessor > nodeId) { rpcMethod.rpcServer.chordNode.SetPredecessor(false, probablePredecessorId) rpcMethod.rpcServer.chordNode.FtServerMapping[rpcMethod.rpcServer.chordNode.Predecessor] = probablePredecessorServerInfo //transfer keys to predecessor whose hash is less than predecessor chord ID rpcMethod.rpcServer.transferKeysToPredecessor() } return nil }
func (rpcMethod *RPCMethod) FindSuccessor(jsonInput RequestParameters, jsonOutput *ResponseParameters) error { //Initialize rpcserver var err error err, rpcMethod.rpcServer = GetRPCServerInstance() var customError error if err != nil { customError = errors.New("Getting Server Instance error :" + err.Error()) rpcMethod.rpcServer.logger.Println(customError) return customError } rpcMethod.rpcServer.logger.Println("RPCCall: In FindSuccessor ") rpcMethod.rpcServer.logger.Println("Input=", jsonInput) defer rpcMethod.rpcServer.logger.Println("Exited FindSuccssor=") var inputId uint32 var succId uint32 var interId uint32 succServerInfo := rpcclient.ServerInfo{} var parameters []interface{} parameters = jsonInput.Params //get inputId from the []interface for k, v := range parameters { if k == 0 { inputId = uint32(v.(float64)) } } /* if (id ∈ (n, successor]) return successor; */ rpcMethod.rpcServer.logger.Println("Find Successor of (id)" + fmt.Sprint(inputId)) rpcMethod.rpcServer.logger.Println("Current Node (n):" + fmt.Sprint(rpcMethod.rpcServer.chordNode.Id)) rpcMethod.rpcServer.logger.Println("Current Node Successor (successor):" + fmt.Sprint(rpcMethod.rpcServer.chordNode.Successor)) //case when only 1 node in chord ring - that node will be the successor if rpcMethod.rpcServer.chordNode.Id == rpcMethod.rpcServer.chordNode.Successor { succId = rpcMethod.rpcServer.chordNode.Id //basic condition } else if rpcMethod.rpcServer.chordNode.Id < inputId && inputId <= rpcMethod.rpcServer.chordNode.Successor { succId = rpcMethod.rpcServer.chordNode.Successor //successor id is less than node id - check whether inputId falls between (n,sucessor + 2^m) } else if rpcMethod.rpcServer.chordNode.Successor < rpcMethod.rpcServer.chordNode.Id && (inputId > rpcMethod.rpcServer.chordNode.Id || inputId < rpcMethod.rpcServer.chordNode.Successor) { succId = rpcMethod.rpcServer.chordNode.Successor } else { interId = rpcMethod.rpcServer.chordNode.ClosestPrecedingNode(inputId) // if call is being forwarded to the current node itself, that means current node itself is the successor if interId == rpcMethod.rpcServer.chordNode.Id { succId = rpcMethod.rpcServer.chordNode.Id } else { //create rpc call "{"method":"findSuccessor","params":[inputId]}" jsonMessage := "{\"method\":\"findSuccessor\",\"params\":[" + fmt.Sprint(inputId) + "]}" clientServerInfo := rpcclient.ServerInfo{} clientServerInfo.ServerID = rpcMethod.rpcServer.chordNode.FtServerMapping[interId].ServerID clientServerInfo.Protocol = rpcMethod.rpcServer.chordNode.FtServerMapping[interId].Protocol clientServerInfo.IpAddress = rpcMethod.rpcServer.chordNode.FtServerMapping[interId].IpAddress clientServerInfo.Port = rpcMethod.rpcServer.chordNode.FtServerMapping[interId].Port client := &rpcclient.RPCClient{} err, response := client.RpcCall(clientServerInfo, jsonMessage) if err != nil { fmt.Println(err) return nil } jsonOutput.Result = make([]interface{}, 2) // process only if response is present if response.(*(rpcclient.ResponseParameters)).Result != nil { succId = uint32(response.(*(rpcclient.ResponseParameters)).Result[0].(float64)) resultServerInfo := rpcclient.ServerInfo{} for key, value := range response.(*(rpcclient.ResponseParameters)).Result[1].(map[string]interface{}) { switch key { case "serverID": resultServerInfo.ServerID = value.(string) break case "protocol": resultServerInfo.Protocol = value.(string) break case "IpAddress": resultServerInfo.IpAddress = value.(string) break case "Port": resultServerInfo.Port = int(value.(float64)) } } succServerInfo = resultServerInfo //insert successor ID into jsonOutput jsonOutput.Result[0] = succId //insert succId's serverInfo into jsonOutput jsonOutput.Result[1] = succServerInfo } rpcMethod.rpcServer.logger.Println("Result from findSucc=", jsonOutput.Result) return nil } // END-ELSE } jsonOutput.Result = make([]interface{}, 2) //insert successor ID into jsonOutput jsonOutput.Result[0] = succId //insert succId's serverInfo into jsonOutput if rpcMethod.rpcServer.chordNode.Id == succId { jsonOutput.Result[1] = rpcMethod.rpcServer.chordNode.MyServerInfo } else { jsonOutput.Result[1] = rpcMethod.rpcServer.chordNode.FtServerMapping[succId] } return nil }
func (chordNode *ChordNode) stabilize() { chordNode.Logger.Println("Chord : In Stabilize") //RPC call to get predecessor of successor jsonMessage := "{\"method\":\"GetPredecessor\",\"params\":[]}" clientServerInfo := rpcclient.ServerInfo{} clientServerInfo.ServerID = chordNode.FtServerMapping[chordNode.FingerTable[1]].ServerID clientServerInfo.Protocol = chordNode.FtServerMapping[chordNode.FingerTable[1]].Protocol clientServerInfo.IpAddress = chordNode.FtServerMapping[chordNode.FingerTable[1]].IpAddress clientServerInfo.Port = chordNode.FtServerMapping[chordNode.FingerTable[1]].Port client := &rpcclient.RPCClient{} err, response := client.RpcCall(clientServerInfo, jsonMessage) if err != nil { chordNode.Logger.Println(err) return } // process only if response is present -- CASE WHERE SUCCESSOR LEAVES ABRUPTLY if response.(*(rpcclient.ResponseParameters)).Result != nil { isPredecessorOfSuccessorNil := (response.(*(rpcclient.ResponseParameters)).Result[0]).(bool) predecessorOfSuccessor := uint32((response.(*(rpcclient.ResponseParameters)).Result[1]).(float64)) resultServerInfo := rpcclient.ServerInfo{} for key, value := range response.(*(rpcclient.ResponseParameters)).Result[2].(map[string]interface{}) { switch key { case "serverID": resultServerInfo.ServerID = value.(string) break case "protocol": resultServerInfo.Protocol = value.(string) break case "IpAddress": resultServerInfo.IpAddress = value.(string) break case "Port": resultServerInfo.Port = int(value.(float64)) } } predecessorOfSuccessorServerInfo := resultServerInfo //update the successor if !isPredecessorOfSuccessorNil { isPredecessorNil, _ := chordNode.GetPredecessor() //predecessor == chordNode.Id refers to the case where the ActualNodesInRing = 1 i.e. predecessor is the node itself if (predecessorOfSuccessor > chordNode.Id && predecessorOfSuccessor < chordNode.Successor) || (!isPredecessorNil && chordNode.Successor == chordNode.Id) || (chordNode.Successor < chordNode.Id && predecessorOfSuccessor < chordNode.Successor) || (chordNode.Successor < chordNode.Id && predecessorOfSuccessor > chordNode.Successor && predecessorOfSuccessor > chordNode.Id) { chordNode.Successor = predecessorOfSuccessor chordNode.FtServerMapping[chordNode.Successor] = predecessorOfSuccessorServerInfo } } } chordNode.Logger.Println("About to make RPC call: Notify") //RPC call to notify the successor about the predecessor(i.e. current node) jsonMessage = "{\"method\":\"Notify\",\"params\":[" + fmt.Sprint(chordNode.Id) + ", {\"serverID\":\"" + chordNode.MyServerInfo.ServerID + "\", \"protocol\":\"" + chordNode.MyServerInfo.Protocol + "\",\"IpAddress\":\"" + chordNode.MyServerInfo.IpAddress + "\",\"Port\":" + fmt.Sprint(chordNode.MyServerInfo.Port) + "}]}" clientServerInfo = rpcclient.ServerInfo{} clientServerInfo.ServerID = chordNode.FtServerMapping[chordNode.FingerTable[1]].ServerID clientServerInfo.Protocol = chordNode.FtServerMapping[chordNode.FingerTable[1]].Protocol clientServerInfo.IpAddress = chordNode.FtServerMapping[chordNode.FingerTable[1]].IpAddress clientServerInfo.Port = chordNode.FtServerMapping[chordNode.FingerTable[1]].Port client = &rpcclient.RPCClient{} err, _ = client.RpcCall(clientServerInfo, jsonMessage) if err != nil { chordNode.Logger.Println(err) return } }