public async Task <IChordResponseMessage> ProcessRequest( IChordRequestMessage request) { switch (request.Type) { // key lookup, health check and update successor case ChordRequestType.KeyLookup: return(await processKeyLookup(request)); case ChordRequestType.HealthCheck: return(await processHealthCheck(request)); case ChordRequestType.UpdateSuccessor: return(await processUpdateSuccessor(request)); // node join procedure (init/commit) case ChordRequestType.InitNodeJoin: return(await processInitNodeJoin(request)); case ChordRequestType.CommitNodeJoin: return(await processCommitNodeJoin(request)); // node leave procedure (init/commit) case ChordRequestType.InitNodeLeave: return(await processInitNodeLeave(request)); case ChordRequestType.CommitNodeLeave: return(await processCommitNodeLeave(request)); // handle unknown request types by throwing an error default: throw new ArgumentException( $"Invalid argument! Unknown request type { request.Type }!"); } }
private async Task <IChordResponseMessage> processHealthCheck( IChordRequestMessage request) { // just send back the local endpoint containing the health state return(new ChordResponseMessage() { Responder = local }); }
private async Task <IChordResponseMessage> processInitNodeLeave( IChordRequestMessage request) { // prepare for the predecessor leaving the network // inform the payload component that it will be sent payload data // currently nothing to do here ... return(new ChordResponseMessage() { Responder = local, ReadyForDataCopy = true }); }
private async Task <IChordResponseMessage> processInitNodeJoin( IChordRequestMessage request) { // prepare for a joining node as new predecessor // inform the payload component that it has to send the payload // data chunk to the joining node that it is now responsible for // currently nothing to do here ... // TODO: trigger copy process for payload data transmission return(new ChordResponseMessage() { Responder = local, ReadyForDataCopy = true }); }
private async Task <IChordResponseMessage> processCommitNodeLeave( IChordRequestMessage request) { // request updating the leaving node's prodecessor's successor // -> predecessor.successor = this node var response = await sendRequest( new ChordRequestMessage() { Type = ChordRequestType.UpdateSuccessor, RequesterId = local.NodeId, NewSuccessor = request.NewSuccessor }, predecessor); return(new ChordResponseMessage() { Responder = local, CommitSuccessful = response.CommitSuccessful }); }
private async Task <IChordResponseMessage> processCommitNodeJoin( IChordRequestMessage request) { // request the prodecessor's successor to be updated to the joining node // -> predecessor.successor = joining node // -> this.predecessor = joining node var response = await sendRequest( new ChordRequestMessage() { Type = ChordRequestType.UpdateSuccessor, RequesterId = local.NodeId, NewSuccessor = request.NewSuccessor }, predecessor); return(new ChordResponseMessage() { Responder = local, CommitSuccessful = response.CommitSuccessful }); }
private async Task <IChordResponseMessage> processKeyLookup( IChordRequestMessage request) { // handle the special case for being the initial node of the cluster // seving the first lookup request of a node join if (local.State == ChordHealthStatus.Starting) { // TODO: think of what else needs to be done here ... return(new ChordResponseMessage() { Responder = local }); } // perform key lookup and return the endpoint responsible for the key var responder = await LookupKey(request.RequestedResourceId); return(new ChordResponseMessage() { Responder = responder }); }
private async Task <IChordResponseMessage> processUpdateSuccessor( IChordRequestMessage request) { const int timeout = 10; // ping the new successor to make sure it is healthy var status = await CheckHealth(request.NewSuccessor, timeout, ChordHealthStatus.Dead); bool canUpdate = status != ChordHealthStatus.Dead; // update the successor if (canUpdate) { successor = request.NewSuccessor; } // respond whether the update was successful return(new ChordResponseMessage() { Responder = local, CommitSuccessful = canUpdate }); }
private static async Task <IChordResponseMessage> sendRequest( IChordRequestMessage request, IChordEndpoint receiver) { // create the request URL to the remote chord endpoint string url = $"http://{ receiver.IpAddress }:{ receiver.Port }/chord"; // serialize the request as JSON string requestJson = JsonSerializer.Serialize(request); // TODO: check if this works // open a HTTP connection to the remote endpoint using (var client = new HttpClient()) using (var content = new StringContent(requestJson)) { // send the request as JSON, parse the response from JSON var httpResponse = await client.PostAsync(url, content); var responseJson = await httpResponse.Content.ReadAsStringAsync(); return(JsonSerializer.Deserialize <ChordResponseMessage>(responseJson)); } // TODO: keep the TCP connections open as long as possible // TODO: add error handling for timeouts, etc. }