コード例 #1
0
        private void TakeWaitAll(Task <ReplyData>[] tasksArray, XuLiskovRequest request, CancellationToken cancellationToken, bool isTakeTwo = true)
        {
            int tasksCount = tasksArray.Length;

            try
            {
                Task.WaitAll(tasksArray, cancellationToken);
            }
            catch (OperationCanceledException)
            {
                RepeatOperation(EOperationType.Take, request, reason: "one or more servers timed out");
                return;
            }

            for (int tidx = 0; tidx < tasksCount; tidx++)
            {
                ReplyData replyData = tasksArray[tidx].Result;

                if (!Utils.IsValidRemoteReply(tasksArray[tidx], typeof(AckReply)))
                {
                    TryUpdateView(tasksArray[tidx]);
                    RepeatOperation(EOperationType.Take, request, $"at least a server failed to acknowledge <TAKE-{(isTakeTwo ? "PHASE2> commit" : "UNLOCK> request")}");
                    return;
                }
            }

            Utils.Print($" >> Success on <TAKE-{(isTakeTwo ? "PHASE2" : "UNLOCK> ")}>...");
        }
コード例 #2
0
        public void Take(XuLiskovRequest request, EXuLiskovOperation operation)
        {
            List <ServerData>       replicasList = backgroundClientView.ReplicasList;
            CancellationTokenSource tokenSource  = new CancellationTokenSource();

            tokenSource.CancelAfter(timeout);
            CancellationToken cancellationToken = tokenSource.Token;

            Utils.Print($" [*] Waiting servers for <TAKE - PHASE 1> Acknowledge...");

            Task <ReplyData>[] tasksArray = InitiateServerCalls(replicasList, request, cancellationToken);

            if (operation == EXuLiskovOperation.TakeOne)
            {
                TakeOne(tasksArray, request, cancellationToken);
            }
            else if (operation == EXuLiskovOperation.TakeTwo)
            {
                TakeTwo(tasksArray, request, cancellationToken);
            }
            else if (operation == EXuLiskovOperation.Unlock)
            {
                TakeUnlock(tasksArray, request, cancellationToken);
            }
            else
            {
                Utils.Print($" [x] Error: Unable to identify <TAKE> phase...");
            }
        }
コード例 #3
0
        public void ConsumeRequest(DIDATuple tuple, EXuLiskovOperation operation)
        {
            Utils.Print(" [*] Recieved new request...", verbose: Verbose);
            EOperationType  requestOperation = GetPrimitiveOperationType(operation);
            RequestData     requestData      = new RequestData(++requestCounter, backgroundClientView.ViewId, ClientId, $"tcp://localhost:{ClientPort}", tuple, requestOperation);
            XuLiskovRequest request          = new XuLiskovRequest(requestData, operation);

            ExecuteConsumption(request, operation);
        }
コード例 #4
0
        public void Read(XuLiskovRequest request)
        {
            int tidx;
            int tasksCount;

            List <ServerData>       replicasList = backgroundClientView.ReplicasList;
            CancellationTokenSource tokenSource  = new CancellationTokenSource();

            tokenSource.CancelAfter(timeout);
            CancellationToken cancellationToken = tokenSource.Token;

            Utils.Print($" [*] Waiting servers for <READ> Acknowledge...");

            Task <ReplyData>[] tasksArray = InitiateServerCalls(replicasList, request, cancellationToken);

            try
            {
                tasksCount = replicasList.Count;
                while (tasksCount > 0)
                {
                    tidx = Task.WaitAny(tasksArray, cancellationToken);

                    TryUpdateView(tasksArray[tidx]);

                    if (Utils.IsValidRemoteReply(tasksArray[tidx], typeof(TupleReply)))
                    {
                        Utils.Print($" >> Success");
                        Utils.Print($" >>> {JsonConvert.SerializeObject(((TupleReply)tasksArray[tidx].Result).Tuple, Formatting.Indented)}");
                        return;
                    }

                    tasksArray[tidx] = new Task <ReplyData>(NoAction);

                    tasksCount--;
                    if (tasksCount == 0)
                    {
                        RepeatOperation(EOperationType.Read, request, reason: "no match found");
                        return;
                    }
                }
            }
            catch (OperationCanceledException)
            {
                RepeatOperation(EOperationType.Read, request, "operation reached timeout");
                return;
            }
        }
コード例 #5
0
 private void RepeatOperation(EOperationType operationType, XuLiskovRequest request, string reason = "reason not specified")
 {
     if (operationType == EOperationType.Write)
     {
         Utils.Print($" >> Retrying <WRITE> operation, {reason}...");
         Write(request);
     }
     else if (operationType == EOperationType.Read)
     {
         Utils.Print($" >> Retrying <READ> operation, {reason}...");
         Read(request);
     }
     else
     {
         Utils.Print($" >> Retrying <TAKE> operation, {reason}...");
         EXuLiskovOperation concreteOperation = request.Operation;
         Take(request, concreteOperation);
     }
 }
コード例 #6
0
        private void ExecuteConsumption(XuLiskovRequest request, EXuLiskovOperation operation)
        {
            if (request == null)
            {
                return;
            }

            Utils.Print($" [*] Consuming operation of type: {operation}...", verbose: Verbose);

            if (operation == EXuLiskovOperation.Write)
            {
                Write(request);
            }
            else if (operation == EXuLiskovOperation.Read)
            {
                Read(request);
            }
            else
            {
                Take(request, operation);
            }
        }
コード例 #7
0
        public void Write(XuLiskovRequest request)
        {
            int tasksCount;

            List <ServerData>       replicasList = backgroundClientView.ReplicasList;
            CancellationTokenSource tokenSource  = new CancellationTokenSource();

            tokenSource.CancelAfter(timeout);
            CancellationToken cancellationToken = tokenSource.Token;

            Utils.Print($" [*] Waiting servers for <WRITE> Acknowledge...");

            Task <ReplyData>[] tasksArray = InitiateServerCalls(replicasList, request, cancellationToken);

            try
            {
                Task.WaitAll(tasksArray, cancellationToken);
            }
            catch (OperationCanceledException)
            {
                RepeatOperation(EOperationType.Write, request, reason: "failed to recieve at least one Acknowledge");
                return;
            }

            tasksCount = replicasList.Count;
            for (int tidx = 0; tidx < tasksCount; tidx++)
            {
                TryUpdateView(tasksArray[tidx]);

                if (!Utils.IsValidRemoteReply(tasksArray[tidx], typeof(AckReply)))
                {
                    RepeatOperation(EOperationType.Write, request, reason: "failed to recieve at least one Acknowledge");
                }
            }

            Utils.Print(" >> Success");
        }
コード例 #8
0
        private Task <ReplyData>[] InitiateServerCalls(List <ServerData> replicasList, XuLiskovRequest request, CancellationToken cancellationToken)
        {
            int replicasCount = replicasList.Count;

            Task <ReplyData>[] tasksArray = new Task <ReplyData> [replicasCount];

            for (int ridx = 0; ridx < replicasCount; ridx++)
            {
                Thread.Sleep(50);
                ServerData  serverData  = replicasList[ridx];
                RequestData requestData = request.RequestData;
                tasksArray[ridx] = Task.Run(() => CallServer(serverData, requestData, cancellationToken), cancellationToken);
            }

            return(tasksArray);
        }
コード例 #9
0
 private void TakeUnlock(Task <ReplyData>[] tasksArray, XuLiskovRequest request, CancellationToken cancellationToken)
 {
     TakeWaitAll(tasksArray, request, cancellationToken, isTakeTwo: false);
 }
コード例 #10
0
        private void TakeOne(Task <ReplyData>[] tasksArray, XuLiskovRequest request, CancellationToken cancellationToken)
        {
            IEnumerable <DIDATuple> tmpSet = new List <DIDATuple>();

            try
            {
                Task.WaitAll(tasksArray, cancellationToken);
            }
            catch (OperationCanceledException)
            {
                RepeatOperation(EOperationType.Take, request, reason: "one or more servers timed out");
                return;
            }

            int goodResponseCount = 0;
            int badResponseCount  = 0;
            int tasksCount        = tasksArray.Length;

            for (int tidx = 0; tidx < tasksCount; tidx++)
            {
                if (TryUpdateView(tasksArray[tidx]))
                {
                    RepeatOperation(EOperationType.Take, request, reason: "client in wrong view");
                }

                if (!Utils.IsValidRemoteReply(tasksArray[tidx], typeof(TupleSetReply)))
                {
                    badResponseCount++;
                }
                else
                {
                    ReplyData replyData = tasksArray[tidx].Result;
                    IEnumerable <DIDATuple> resultingSet = ((TupleSetReply)replyData).TupleSet;
                    List <DIDATuple>        intersectSet = new List <DIDATuple>();
                    if (tidx == 0)
                    {
                        tmpSet = resultingSet;
                    }
                    else
                    {
                        foreach (DIDATuple tupleRes in resultingSet)
                        {
                            foreach (DIDATuple tupleTmpSet in tmpSet)
                            {
                                if (tupleTmpSet.Equals(tupleRes))
                                {
                                    intersectSet.Add(tupleTmpSet);
                                }
                            }
                        }
                        tmpSet = intersectSet;
                    }
                    goodResponseCount++;
                }
            }

            DIDATuple[] setIntersection      = Enumerable.ToArray(tmpSet);
            int         setIntersectionCount = setIntersection.Length;
            bool        majorityAccepted     = Utils.MajorityHasAccepted(goodResponseCount, tasksCount);
            bool        everyoneAccepted     = Utils.EveryoneHasAccepted(goodResponseCount, tasksCount);

            if ((majorityAccepted && !everyoneAccepted) || (everyoneAccepted && setIntersectionCount == 0))
            {
                RepeatOperation(EOperationType.Take, request, reason: "at least a server failed to send a response set");
                return;
            }
            else if (!majorityAccepted)
            {
                Utils.Print($" >> failed locking on <TAKE-PHASE1>, initiating <TAKE-UNLOCK>...");

                request.Operation = EXuLiskovOperation.Unlock;
                Take(request, EXuLiskovOperation.Unlock);

                Thread.Sleep(randomGenerator.Next(500, 1000));

                request.Operation = EXuLiskovOperation.TakeOne;
                RepeatOperation(EOperationType.Take, request, reason: "only a minority of servers accepted <TAKE-ONE> request, retrying soon");
                return;
            }
            else
            {
                Utils.Print($" >> Success on <TAKE-PHASE1>, initiating <TAKE-PHASE2>...");
                DIDATuple selectedTuple = setIntersection[randomGenerator.Next(setIntersectionCount)];
                Utils.Print(" >> Locked:");
                Utils.Print(JsonConvert.SerializeObject(selectedTuple, Formatting.Indented));
                RequestData     requestData = new RequestData(++requestCounter, backgroundClientView.ViewId, ClientId, $"tcp://localhost:{ClientPort}", selectedTuple, EOperationType.Take);
                XuLiskovRequest requestTake = new XuLiskovRequest(requestData, EXuLiskovOperation.TakeTwo);

                Take(requestTake, EXuLiskovOperation.TakeTwo);
            }
        }