示例#1
0
        public void ExecuteTransaction(IList <CachedObject> itemsToPut, IList <OrQuery> conditions,
                                       IList <CachedObject> itemsToDelete = null)
        {
            var locksOk = false;

            var iteration = 0;


            while (!locksOk)
            {
                var delay = ThreadLocalRandom.Instance.Next(10 * iteration);

                TransactionStatistics.Retries(iteration + 1);


                Dbg.Trace(
                    $"C: delay = {delay} for iteration {iteration} single stage transaction connector {GetHashCode()}");

                if (delay > 0)
                {
                    Thread.Sleep(delay);
                }


                if (itemsToPut == null)
                {
                    throw new ArgumentNullException(nameof(itemsToPut));
                }

                var request = new TransactionRequest(itemsToPut, conditions, itemsToDelete)
                {
                    IsSingleStage = true
                };

                TransactionStatistics.ExecutedAsSingleStage();


                var response = Channel.SendRequest(request);

                if (response is NullResponse)
                {
                    locksOk = true;
                }
                else if (response is ExceptionResponse exResponse)
                {
                    if (exResponse.ExceptionType != ExceptionType.FailedToAcquireLock)
                    {
                        throw new CacheException(exResponse.Message, exResponse.ExceptionType);
                    }
                }
            }

            TransactionStatistics.NewTransactionCompleted();
        }
示例#2
0
        private void SendRequestsAndWaitForLock <TRequest>(List <CacheClient> clients,
                                                           ConcurrentDictionary <int, TRequest> requestByServer, ConcurrentDictionary <int, Session> sessions,
                                                           string transactionId, ConcurrentDictionary <int, bool> serverStatus) where TRequest : Request
        {
            var locksOk = false;

            var iteration = 0;


            while (!locksOk)
            {
                try
                {
                    var delay = ThreadLocalRandom.Instance.Next(10 * iteration);

                    TransactionStatistics.Retries(iteration + 1);


                    Dbg.Trace(
                        $"C: delay = {delay} for iteration {iteration} transaction {transactionId} connector {GetHashCode()}");

                    if (delay > 0)
                    {
                        Thread.Sleep(delay);
                    }

                    // send transaction requests
                    Parallel.ForEach(clients, client =>
                    {
                        var request = requestByServer[client.ShardIndex];


                        try
                        {
                            var session = client.Channel.BeginSession();
                            sessions[client.ShardIndex] = session;

                            Dbg.Trace(
                                $"C: Sending transaction request to server {client.ShardIndex} transaction {transactionId} connector {GetHashCode()}");
                            client.Channel.PushRequest(session, request);
                        }
                        catch (Exception e)
                        {
                            // here if communication exception
                            serverStatus[client.ShardIndex] = false;

                            Dbg.Trace($"C: Exception while sending request to server {client.ShardIndex}:{e.Message}");
                        }
                    });

                    // wait for servers to acquire lock
                    Parallel.ForEach(clients, client =>
                    {
                        try
                        {
                            var session = sessions[client.ShardIndex];

                            var answer = client.Channel.GetResponse(session);
                            if (answer is ReadyResponse)
                            {
                                serverStatus[client.ShardIndex] = true;
                            }
                            else
                            {
                                serverStatus[client.ShardIndex] = false;
                            }
                        }
                        catch (Exception e)
                        {
                            // here if communication exception
                            serverStatus[client.ShardIndex] = false;

                            Dbg.Trace($"C: Exception while sending request to server {client.ShardIndex}:{e.Message}");
                        }
                    });
                }
                catch (AggregateException e)
                {
                    // this code should never be reached
                    throw new CacheException(
                              $"Error in the first stage of a two stage transaction:{e.InnerExceptions.First()}");
                }

                locksOk = serverStatus.Values.All(s => s);

                Dbg.Trace(!locksOk
                    ? $"C: Failed to acquire lock for transaction {transactionId}. retrying "
                    : $"C: Lock acquired for all servers: transaction {transactionId} ");

                if (locksOk == false)
                {
                    Parallel.ForEach(clients, client =>
                    {
                        if (serverStatus[client.ShardIndex])
                        {
                            var session = sessions[client.ShardIndex];
                            client.Channel.PushRequest(session, new ContinueRequest {
                                Rollback = true
                            });
                        }
                    });
                }
                else
                {
                    Parallel.ForEach(clients, client =>
                    {
                        var session = sessions[client.ShardIndex];
                        client.Channel.PushRequest(session, new ContinueRequest {
                            Rollback = false
                        });
                    });
                }

                iteration++;

                TransactionStatistics.NewAttemptToLock();
            }
        }