예제 #1
0
        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 }!");
            }
        }
예제 #2
0
 private async Task <IChordResponseMessage> processHealthCheck(
     IChordRequestMessage request)
 {
     // just send back the local endpoint containing the health state
     return(new ChordResponseMessage()
     {
         Responder = local
     });
 }
예제 #3
0
        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
            });
        }
예제 #4
0
        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
            });
        }
예제 #5
0
        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
            });
        }
예제 #6
0
        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
            });
        }
예제 #7
0
        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
            });
        }
예제 #8
0
        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
            });
        }
예제 #9
0
        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.
        }