Beispiel #1
0
        public async Task <object> SendBtcAsync(
            ITransactionInfo info,
            CancellationToken ct
            )
        {
            var wallet = await _context
                         .Wallets
                         .FirstOrDefaultAsync(e => e.Balance > info.Amount, ct);

            if (wallet == null)
            {
                throw new Exception("Wallet not found for the transaction");
            }

            var transaction = new TransactionEntity
            {
                Address        = info.Address,
                Amount         = info.Amount,
                IdempotencyKey = info.IdempotencyKey,
                Data           = DateTime.UtcNow,
                WalletId       = wallet.Id,
                Type           = TransactionType.Send
            };

            await _context
            .Transactions
            .AddAsync(transaction, ct);

            await _context
            .SaveChangesAsync(ct);

            return(Transaction.FromDbo(transaction));
        }
Beispiel #2
0
        public Task <TransactionalStatus> Commit(ITransactionInfo info)
        {
            var transactionInfo = (TransactionInfo)info;

            transactionInfo.TimeStamp = this.clock.MergeUtcNow(transactionInfo.TimeStamp);

            if (logger.IsEnabled(LogLevel.Trace))
            {
                logger.Trace($"{stopwatch.Elapsed.TotalMilliseconds:f2} prepare {transactionInfo}");
            }

            List <ITransactionParticipant> writeParticipants = null;

            foreach (var p in transactionInfo.Participants)
            {
                if (p.Value.Writes > 0)
                {
                    if (writeParticipants == null)
                    {
                        writeParticipants = new List <ITransactionParticipant>();
                    }
                    writeParticipants.Add(p.Key);
                }
            }

            if (writeParticipants == null)
            {
                return(CommitReadOnlyTransaction(transactionInfo));
            }
            else
            {
                return(CommitReadWriteTransaction(transactionInfo, writeParticipants));
            }
        }
        public Message CreateMessage(InvokeMethodRequest request, InvokeMethodOptions options)
        {
            var direction = (options & InvokeMethodOptions.OneWay) != 0 ? Message.Directions.OneWay : Message.Directions.Request;
            var message   = new Message
            {
                Category                 = Message.Categories.Application,
                Direction                = direction,
                Id                       = CorrelationId.GetNext(),
                IsReadOnly               = (options & InvokeMethodOptions.ReadOnly) != 0,
                IsUnordered              = (options & InvokeMethodOptions.Unordered) != 0,
                IsTransactionRequired    = (options & InvokeMethodOptions.TransactionRequiresNew) != 0 || (options & InvokeMethodOptions.TransactionRequired) != 0,
                BodyObject               = request,
                IsUsingInterfaceVersions = request.InterfaceVersion > 0,
            };

            ITransactionInfo transactionInfo = message.IsTransactionRequired ? TransactionContext.GetTransactionInfo() : null;

            if (transactionInfo != null)
            {
                message.TransactionInfo = transactionInfo.Fork();
            }

            if ((options & InvokeMethodOptions.AlwaysInterleave) != 0)
            {
                message.IsAlwaysInterleave = true;
            }

            message.RequestContextData = RequestContextExtensions.Export(this.serializationManager);
            return(message);
        }
        public async Task Commit(ITransactionInfo info)
        {
            var transactionInfo = (TransactionInfo)info;

            transactionInfo.TimeStamp = MergeAndReadClock(transactionInfo.TimeStamp);

            if (logger.IsEnabled(LogLevel.Trace))
            {
                logger.Trace($"{stopwatch.Elapsed.TotalMilliseconds:f2} prepare {transactionInfo}");
            }

            List <ITransactionParticipant> writeParticipants = null;

            foreach (var p in transactionInfo.Participants)
            {
                if (p.Value.Writes > 0)
                {
                    if (writeParticipants == null)
                    {
                        writeParticipants = new List <ITransactionParticipant>();
                    }
                    writeParticipants.Add(p.Key);
                }
            }

            if (writeParticipants == null)
            {
                await CommitReadOnlyTransaction(transactionInfo);
            }
            else
            {
                await CommitReadWriteTransaction(transactionInfo, writeParticipants);
            }
        }
Beispiel #5
0
        internal static void SetTransactionInfo(ITransactionInfo info)
        {
            Dictionary <string, object> values = GetContextData();

            values = values == null ? new Dictionary <string, object>() : new Dictionary <string, object>(values);
            values[TransactionInfoHeader] = info;
            SetContextData(values);
        }
Beispiel #6
0
        public async Task Commit(ITransactionInfo info)
        {
            var transactionInfo = (TransactionInfo)info;

            TransactionsStatisticsGroup.OnTransactionCommitRequest();

            if (transactionInfo.IsReadOnly)
            {
                return;
            }

            var  completion = new TaskCompletionSource <bool>();
            bool canCommit  = true;

            List <Task <bool> > prepareTasks = new List <Task <bool> >(transactionInfo.WriteSet.Count);

            foreach (var g in transactionInfo.WriteSet.Keys)
            {
                TransactionalResourceVersion write = TransactionalResourceVersion.Create(transactionInfo.TransactionId, transactionInfo.WriteSet[g]);
                TransactionalResourceVersion?read  = null;
                if (transactionInfo.ReadSet.ContainsKey(g))
                {
                    read = transactionInfo.ReadSet[g];
                    transactionInfo.ReadSet.Remove(g);
                }
                prepareTasks.Add(g.Prepare(transactionInfo.TransactionId, write, read));
            }

            foreach (var g in transactionInfo.ReadSet.Keys)
            {
                TransactionalResourceVersion read = transactionInfo.ReadSet[g];
                prepareTasks.Add(g.Prepare(transactionInfo.TransactionId, null, read));
            }

            await Task.WhenAll(prepareTasks);

            foreach (var t in prepareTasks)
            {
                if (!t.Result)
                {
                    canCommit = false;
                }
            }

            if (!canCommit)
            {
                TransactionsStatisticsGroup.OnTransactionAborted();
                abortedTransactions.TryAdd(transactionInfo.TransactionId, 0);
                throw new OrleansPrepareFailedException(transactionInfo.TransactionId);
            }
            commitCompletions.TryAdd(transactionInfo.TransactionId, completion);
            transactionCommitQueue.Enqueue(transactionInfo);
            await completion.Task;
        }
 private static TransactionResponseModel MakeResponseObject(ITransactionInfo transactionInfo)
 {
     return(new TransactionResponseModel
     {
         Id = transactionInfo.Id,
         JobId = transactionInfo.JobId,
         StoreName = transactionInfo.StoreName,
         StartTime = transactionInfo.StartTime,
         Status = transactionInfo.Status.ToString(),
         TransactionType = transactionInfo.TransactionType.ToString()
     });
 }
 private static TransactionResponseModel MakeResponseObject(ITransactionInfo transactionInfo)
 {
     return new TransactionResponseModel
         {
             Id = transactionInfo.Id,
             JobId = transactionInfo.JobId,
             StoreName = transactionInfo.StoreName,
             StartTime = transactionInfo.StartTime,
             Status = transactionInfo.Status.ToString(),
             TransactionType = transactionInfo.TransactionType.ToString()
         };
 }
        public async Task Abort(ITransactionInfo info)
        {
            this.statistics.TrackTransactionFailed();
            var transactionInfo = (TransactionInfo)info;

            List <ParticipantId> participants = transactionInfo.Participants.Keys.ToList();

            if (logger.IsEnabled(LogLevel.Trace))
            {
                logger.Trace($"abort {transactionInfo} {string.Join(",", participants.Select(p => p.ToString()))}");
            }

            // send one-way abort messages to release the locks and roll back any updates
            await Task.WhenAll(participants.Select(p => p.Reference.AsReference <ITransactionalResourceExtension>()
                                                   .Abort(p.Name, transactionInfo.TransactionId)));
        }
Beispiel #10
0
        public async Task <TransactionalStatus> Commit(ITransactionInfo info)
        {
            var transactionInfo = (TransactionInfo)info;

            transactionInfo.TimeStamp = this.clock.MergeUtcNow(transactionInfo.TimeStamp);

            if (logger.IsEnabled(LogLevel.Trace))
            {
                logger.Trace($"{stopwatch.Elapsed.TotalMilliseconds:f2} prepare {transactionInfo}");
            }

            List <ParticipantId> writeParticipants = null;

            foreach (var p in transactionInfo.Participants)
            {
                if (p.Value.Writes > 0)
                {
                    if (writeParticipants == null)
                    {
                        writeParticipants = new List <ParticipantId>();
                    }
                    writeParticipants.Add(p.Key);
                }
            }

            try
            {
                TransactionalStatus status = (writeParticipants == null)
                    ? await CommitReadOnlyTransaction(transactionInfo)
                    : await CommitReadWriteTransaction(transactionInfo, writeParticipants);

                if (status == TransactionalStatus.Ok)
                {
                    this.statistics.TrackTransactionSucceeded();
                }
                else
                {
                    this.statistics.TrackTransactionFailed();
                }
                return(status);
            }
            catch (Exception)
            {
                this.statistics.TrackTransactionFailed();
                throw;
            }
        }
Beispiel #11
0
        public void Abort(ITransactionInfo info, OrleansTransactionAbortedException reason)
        {
            var transactionInfo = (TransactionInfo)info;

            abortedTransactions.TryAdd(transactionInfo.TransactionId, 0);
            foreach (var g in transactionInfo.WriteSet.Keys)
            {
                g.Abort(transactionInfo.TransactionId).Ignore();
            }

            // TODO: should we wait for the abort tasks to complete before returning?
            // If so, how do we handle exceptions?

            // There is no guarantee that the WriteSet is complete and has all the grains.
            // Notify the TM of the abort as well.
            this.tmService.AbortTransaction(transactionInfo.TransactionId, reason).Ignore();
        }
Beispiel #12
0
        public void Abort(ITransactionInfo info, OrleansTransactionAbortedException reason)
        {
            var transactionInfo = (TransactionInfo)info;

            var participants = transactionInfo.Participants.Keys.ToList();

            if (logger.IsEnabled(LogLevel.Trace))
            {
                logger.Trace($"abort {transactionInfo} {string.Join(",", participants.Select(p => p.ToString()))} {reason}");
            }

            // send one-way abort messages to release the locks and roll back any updates
            foreach (var p in participants)
            {
                p.Abort(transactionInfo.TransactionId);
            }
        }
Beispiel #13
0
        public async Task <(TransactionalStatus, Exception)> Resolve(ITransactionInfo info)
        {
            var transactionInfo = (TransactionInfo)info;

            transactionInfo.TimeStamp = this.clock.MergeUtcNow(transactionInfo.TimeStamp);

            if (logger.IsEnabled(LogLevel.Trace))
            {
                logger.Trace($"{stopwatch.Elapsed.TotalMilliseconds:f2} prepare {transactionInfo}");
            }

            if (transactionInfo.Participants.Count == 0)
            {
                this.statistics.TrackTransactionSucceeded();
                return(TransactionalStatus.Ok, null);
            }

            KeyValuePair <ParticipantId, AccessCounter>?manager;

            List <ParticipantId> writeParticipants;
            List <KeyValuePair <ParticipantId, AccessCounter> > resources;

            CollateParticipants(transactionInfo.Participants, out writeParticipants, out resources, out manager);
            try
            {
                var(status, exception) = (writeParticipants == null)
                    ? await CommitReadOnlyTransaction(transactionInfo, resources)
                    : await CommitReadWriteTransaction(transactionInfo, writeParticipants, resources, manager.Value);

                if (status == TransactionalStatus.Ok)
                {
                    this.statistics.TrackTransactionSucceeded();
                }
                else
                {
                    this.statistics.TrackTransactionFailed();
                }
                return(status, exception);
            }
            catch (Exception)
            {
                this.statistics.TrackTransactionFailed();
                throw;
            }
        }
Beispiel #14
0
        public void Abort(ITransactionInfo info, OrleansTransactionAbortedException reason)
        {
            this.statistics.TrackTransactionFailed();
            var transactionInfo = (TransactionInfo)info;

            List <ParticipantId> participants = transactionInfo.Participants.Keys.ToList();

            if (logger.IsEnabled(LogLevel.Trace))
            {
                logger.Trace($"abort {transactionInfo} {string.Join(",", participants.Select(p => p.ToString()))} {reason}");
            }

            // send one-way abort messages to release the locks and roll back any updates
            foreach (var p in participants)
            {
                p.Reference.AsReference <ITransactionalResourceExtension>()
                .Abort(p.Name, transactionInfo.TransactionId)
                .Ignore();
            }
        }
Beispiel #15
0
        public void Abort(ITransactionInfo info, OrleansTransactionAbortedException reason)
        {
            var transactionInfo = (TransactionInfo)info;

            if (logger.IsEnabled(LogLevel.Trace))
            {
                logger.Trace($"abort {transactionInfo} {reason}");
            }

            var participants = transactionInfo.Participants.Keys.ToList();

            if (!transactionInfo.PrepareMessagesSent)
            {
                // send one-way abort messages to release the locks and roll back any updates
                foreach (var p in participants)
                {
                    p.Abort(transactionInfo.TransactionId);
                }
            }
        }
Beispiel #16
0
        public static async Task <List <string>[]> GetNestedTransactionIds(int tier, List <ITransactionAttributionGrain>[] tiers)
        {
            ITransactionInfo ti = TransactionContext.GetTransactionInfo();

            List <string>[] results = new List <string> [tier + 1 + tiers.Length];
            results[tier] = new List <string>(new[] { ti?.Id });

            if (tiers.Length == 0)
            {
                return(results);
            }

            List <ITransactionAttributionGrain> nextTier = tiers.FirstOrDefault();

            List <ITransactionAttributionGrain>[] nextTiers = tiers.Skip(1).ToArray();
            List <string>[][] tiersResults = await Task.WhenAll(nextTier.Select(g => g.GetNestedTransactionIds(tier + 1, nextTiers)));

            foreach (List <string>[] result in tiersResults)
            {
                if (result.Length != results.Length)
                {
                    throw new ApplicationException("Invalid result length");
                }
                for (int i = tier + 1; i < results.Length; i++)
                {
                    if (results[i] != null)
                    {
                        results[i].AddRange(result[i]);
                    }
                    else
                    {
                        results[i] = result[i];
                    }
                }
            }

            return(results);
        }
 /// <summary>
 /// Executes a previous transaction
 /// </summary>
 /// <param name="storeName"></param>
 /// <param name="transactionInfo"></param>
 public IJobInfo ReExecuteTransaction(string storeName, ITransactionInfo transactionInfo)
 {
     ValidateStoreName(storeName);
     if (transactionInfo == null)
     {
         throw  new ArgumentNullException("transactionInfo");
     }
     if (!(transactionInfo is TransactionInfoWrapper))
     {
         throw new ArgumentException(Strings.BrightstarServiceClient_InvalidTransactionInfoObject, "transactionInfo");
     }
     try
     {
         return
             (new JobInfoWrapper(_service.ReExecuteTransaction(storeName,
                                                               (transactionInfo as TransactionInfoWrapper).
                                                               TransactionInfo)));
     }
     catch (FaultException <ExceptionDetail> fault)
     {
         throw new BrightstarClientException(fault);
     }
 }
Beispiel #18
0
        private void SetTransaction(Message message, InvokeMethodOptions options)
        {
            // clear transaction info if transaction operation requires new transaction.
            ITransactionInfo transactionInfo = TransactionContext.GetTransactionInfo();

            // enforce join transaction calls
            if (options.IsTransactionOption(InvokeMethodOptions.TransactionJoin) && transactionInfo == null)
            {
                throw new NotSupportedException("Call cannot be made outside of a transaction.");
            }

            // enforce not allowed transaction calls
            if (options.IsTransactionOption(InvokeMethodOptions.TransactionNotAllowed) && transactionInfo != null)
            {
                throw new NotSupportedException("Call cannot be made within a transaction.");
            }

            // clear transaction context if creating a transaction or transaction is suppressed
            if (options.IsTransactionOption(InvokeMethodOptions.TransactionCreate) ||
                options.IsTransactionOption(InvokeMethodOptions.TransactionSuppress))
            {
                transactionInfo = null;
            }

            bool isTransactionRequired = options.IsTransactionOption(InvokeMethodOptions.TransactionCreate) ||
                                         options.IsTransactionOption(InvokeMethodOptions.TransactionCreateOrJoin) ||
                                         options.IsTransactionOption(InvokeMethodOptions.TransactionJoin);

            message.TransactionInfo       = transactionInfo?.Fork();
            message.IsTransactionRequired = isTransactionRequired;
            if (transactionInfo == null)
            {
                // if we're leaving a transaction context, make sure it's been cleared from the request context.
                message.RequestContextData?.Remove(TransactionContext.Orleans_TransactionContext_Key);
            }
        }
 public Task <TransactionalStatus> Resolve(ITransactionInfo transactionInfo)
 {
     throw new OrleansTransactionsDisabledException();
 }
Beispiel #20
0
        public async Task Invoke(IGrainContext target, Message message)
        {
            try
            {
                // Don't process messages that have already timed out
                if (message.IsExpired)
                {
                    this.messagingTrace.OnDropExpiredMessage(message, MessagingStatisticsGroup.Phase.Invoke);
                    return;
                }

                RequestContextExtensions.Import(message.RequestContextData);

                bool             startNewTransaction = false;
                ITransactionInfo transactionInfo     = message.TransactionInfo;

                if (message.IsTransactionRequired && transactionInfo == null)
                {
                    // TODO: this should be a configurable parameter
                    var transactionTimeout = Debugger.IsAttached ? TimeSpan.FromMinutes(30) : TimeSpan.FromSeconds(10);

                    // Start a new transaction
                    transactionInfo = await this.transactionAgent.StartTransaction(message.IsReadOnly, transactionTimeout);

                    startNewTransaction = true;
                }

                if (transactionInfo != null)
                {
                    TransactionContext.SetTransactionInfo(transactionInfo);
                }

                object resultObject;
                try
                {
                    var request = (InvokeMethodRequest)message.BodyObject;
                    if (request.Arguments != null)
                    {
                        CancellationSourcesExtension.RegisterCancellationTokens(target, request);
                    }

                    if (!this.invokers.TryGet(message.InterfaceType, out var invoker))
                    {
                        throw new KeyNotFoundException($"Could not find an invoker for interface {message.InterfaceType}");
                    }

                    messagingTrace.OnInvokeMessage(message);
                    var requestInvoker = new GrainMethodInvoker(target, request, invoker, GrainCallFilters, interfaceToImplementationMapping);
                    await requestInvoker.Invoke();

                    resultObject = requestInvoker.Result;
                }
                catch (Exception exc1)
                {
                    if (message.Direction == Message.Directions.OneWay)
                    {
                        this.invokeExceptionLogger.Warn(ErrorCode.GrainInvokeException,
                                                        "Exception during Grain method call of message: " + message + ": " + LogFormatter.PrintException(exc1), exc1);
                    }
                    else if (invokeExceptionLogger.IsEnabled(LogLevel.Debug))
                    {
                        this.invokeExceptionLogger.Debug(ErrorCode.GrainInvokeException,
                                                         "Exception during Grain method call of message: " + message + ": " + LogFormatter.PrintException(exc1), exc1);
                    }

                    if (transactionInfo != null)
                    {
                        transactionInfo.ReconcilePending();

                        // Record reason for abort, if not already set.
                        transactionInfo.RecordException(exc1, serializationManager);

                        if (startNewTransaction)
                        {
                            exc1 = transactionInfo.MustAbort(serializationManager);
                            await this.transactionAgent.Abort(transactionInfo);

                            TransactionContext.Clear();
                        }
                    }

                    // If a grain allowed an inconsistent state exception to escape and the exception originated from
                    // this activation, then deactivate it.
                    var ise = exc1 as InconsistentStateException;
                    if (ise != null && ise.IsSourceActivation)
                    {
                        // Mark the exception so that it doesn't deactivate any other activations.
                        ise.IsSourceActivation = false;

                        this.invokeExceptionLogger.Info($"Deactivating {target} due to inconsistent state.");
                        this.DeactivateOnIdle(target.ActivationId);
                    }

                    if (message.Direction != Message.Directions.OneWay)
                    {
                        SafeSendExceptionResponse(message, exc1);
                    }
                    return;
                }

                OrleansTransactionException transactionException = null;

                if (transactionInfo != null)
                {
                    try
                    {
                        transactionInfo.ReconcilePending();
                        transactionException = transactionInfo.MustAbort(serializationManager);

                        // This request started the transaction, so we try to commit before returning,
                        // or if it must abort, tell participants that it aborted
                        if (startNewTransaction)
                        {
                            try
                            {
                                if (transactionException is null)
                                {
                                    var(status, exception) = await this.transactionAgent.Resolve(transactionInfo);

                                    if (status != TransactionalStatus.Ok)
                                    {
                                        transactionException = status.ConvertToUserException(transactionInfo.Id, exception);
                                    }
                                }
                                else
                                {
                                    await this.transactionAgent.Abort(transactionInfo);
                                }
                            }
                            finally
                            {
                                TransactionContext.Clear();
                            }
                        }
                    }
                    catch (Exception e)
                    {
                        // we should never hit this, but if we do, the following message will help us diagnose
                        this.logger.LogError(e, "Error in transaction post-grain-method-invocation code");
                        throw;
                    }
                }

                if (message.Direction != Message.Directions.OneWay)
                {
                    if (transactionException != null)
                    {
                        SafeSendExceptionResponse(message, transactionException);
                    }
                    else
                    {
                        SafeSendResponse(message, resultObject);
                    }
                }
                return;
            }
            catch (Exception exc2)
            {
                this.logger.Warn(ErrorCode.Runtime_Error_100329, "Exception during Invoke of message: " + message, exc2);

                TransactionContext.Clear();

                if (message.Direction != Message.Directions.OneWay)
                {
                    SafeSendExceptionResponse(message, exc2);
                }
            }
            finally
            {
                RequestContext.Clear();
            }
        }
 /// <summary>
 /// Executes a previous transaction
 /// </summary>
 /// <param name="storeName"></param>
 /// <param name="transactionInfo"></param>
 public IJobInfo ReExecuteTransaction(string storeName, ITransactionInfo transactionInfo)
 {
     ValidateStoreName(storeName);
     if(transactionInfo == null) throw  new ArgumentNullException("transactionInfo");
     if (!(transactionInfo is TransactionInfoWrapper)) throw new ArgumentException(Strings.BrightstarServiceClient_InvalidTransactionInfoObject, "transactionInfo");
     try
     {
         return
             new JobInfoWrapper(_service.ReExecuteTransaction(storeName,
                                                              (transactionInfo as TransactionInfoWrapper).
                                                                  TransactionInfo));
     }
     catch (FaultException<ExceptionDetail> fault)
     {
         throw new BrightstarClientException(fault);
     }
 }
 /// <summary>
 /// Executes a previous transaction
 /// </summary>
 /// <param name="storeName">Name of the store</param>
 /// <param name="transactionInfo">Transaction to execute.</param>
 /// <param name="label">Optional user-friendly label for the job.</param>
 public IJobInfo ReExecuteTransaction(string storeName, ITransactionInfo transactionInfo, string label = null)
 {
     if (storeName == null) throw new ArgumentNullException("storeName");
     if (transactionInfo == null) throw new ArgumentNullException("transactionInfo");
     try
     {
         var jobId = _serverCore.ReExecuteTransaction(storeName, transactionInfo.Id,
                                                      transactionInfo.TransactionType,
                                                      label);
         return GetJobInfo(storeName, jobId.ToString());
     }
     catch (Exception ex)
     {
         Logging.LogError(BrightstarEventId.ServerCoreException, "Error rexecuting transaction with JobId {0} for store {1}", transactionInfo.JobId, storeName);
         throw new BrightstarClientException(String.Format("Error rexecuting transaction with JobId {0} for store {1}. {2}", transactionInfo.JobId, storeName, ex.Message), ex);
     }
 }
Beispiel #23
0
        public async Task Invoke(IAddressable target, IInvokable invokable, Message message)
        {
            try
            {
                // Don't process messages that have already timed out
                if (message.IsExpired)
                {
                    this.messagingTrace.OnDropExpiredMessage(message, MessagingStatisticsGroup.Phase.Invoke);
                    return;
                }

                RequestContextExtensions.Import(message.RequestContextData);
                if (schedulingOptions.PerformDeadlockDetection && !message.TargetGrain.IsSystemTarget())
                {
                    UpdateDeadlockInfoInRequestContext(new RequestInvocationHistory(message.TargetGrain, message.TargetActivation));
                    // RequestContext is automatically saved in the msg upon send and propagated to the next hop
                    // in RuntimeClient.CreateMessage -> RequestContextExtensions.ExportToMessage(message);
                }

                bool             startNewTransaction = false;
                ITransactionInfo transactionInfo     = message.TransactionInfo;

                if (message.IsTransactionRequired && transactionInfo == null)
                {
                    // TODO: this should be a configurable parameter
                    var transactionTimeout = Debugger.IsAttached ? TimeSpan.FromMinutes(30) : TimeSpan.FromSeconds(10);

                    // Start a new transaction
                    transactionInfo = await this.transactionAgent.StartTransaction(message.IsReadOnly, transactionTimeout);

                    startNewTransaction = true;
                }

                if (transactionInfo != null)
                {
                    TransactionContext.SetTransactionInfo(transactionInfo);
                }

                object resultObject;
                try
                {
                    var request = (InvokeMethodRequest)message.BodyObject;
                    if (request.Arguments != null)
                    {
                        CancellationSourcesExtension.RegisterCancellationTokens(target, request, this.loggerFactory, logger, this, this.cancellationTokenRuntime);
                    }

                    var invoker = invokable.GetInvoker(typeManager, request.InterfaceId, message.GenericGrainType);

                    if (invoker is IGrainExtensionMethodInvoker &&
                        !(target is IGrainExtension) &&
                        !TryInstallExtension(request.InterfaceId, invokable, message.GenericGrainType, ref invoker))
                    {
                        // We are trying the invoke a grain extension method on a grain
                        // -- most likely reason is that the dynamic extension is not installed for this grain
                        // So throw a specific exception here rather than a general InvalidCastException
                        var error = String.Format(
                            "Extension not installed on grain {0} attempting to invoke type {1} from invokable {2}",
                            target.GetType().FullName, invoker.GetType().FullName, invokable.GetType().FullName);
                        var    exc            = new GrainExtensionNotInstalledException(error);
                        string extraDebugInfo = null;
#if DEBUG
                        extraDebugInfo = Utils.GetStackTrace();
#endif
                        this.logger.Warn(ErrorCode.Stream_ExtensionNotInstalled,
                                         string.Format("{0} for message {1} {2}", error, message, extraDebugInfo), exc);

                        throw exc;
                    }

                    messagingTrace.OnInvokeMessage(message);
                    var requestInvoker = new GrainMethodInvoker(target, request, invoker, GrainCallFilters, interfaceToImplementationMapping);
                    await requestInvoker.Invoke();

                    resultObject = requestInvoker.Result;
                }
                catch (Exception exc1)
                {
                    if (message.Direction == Message.Directions.OneWay)
                    {
                        this.invokeExceptionLogger.Warn(ErrorCode.GrainInvokeException,
                                                        "Exception during Grain method call of message: " + message + ": " + LogFormatter.PrintException(exc1), exc1);
                    }
                    else if (invokeExceptionLogger.IsEnabled(LogLevel.Debug))
                    {
                        this.invokeExceptionLogger.Debug(ErrorCode.GrainInvokeException,
                                                         "Exception during Grain method call of message: " + message + ": " + LogFormatter.PrintException(exc1), exc1);
                    }

                    if (transactionInfo != null)
                    {
                        transactionInfo.ReconcilePending();

                        // Record reason for abort, if not alread set
                        transactionInfo.RecordException(exc1, serializationManager);

                        if (startNewTransaction)
                        {
                            exc1 = transactionInfo.MustAbort(serializationManager);
                            await this.transactionAgent.Abort(transactionInfo);

                            TransactionContext.Clear();
                        }
                    }

                    // If a grain allowed an inconsistent state exception to escape and the exception originated from
                    // this activation, then deactivate it.
                    var ise = exc1 as InconsistentStateException;
                    if (ise != null && ise.IsSourceActivation)
                    {
                        // Mark the exception so that it doesn't deactivate any other activations.
                        ise.IsSourceActivation = false;

                        var activation = (target as Grain)?.Data;
                        if (activation != null)
                        {
                            this.invokeExceptionLogger.Info($"Deactivating {activation} due to inconsistent state.");
                            this.DeactivateOnIdle(activation.ActivationId);
                        }
                    }

                    if (message.Direction != Message.Directions.OneWay)
                    {
                        SafeSendExceptionResponse(message, exc1);
                    }
                    return;
                }

                OrleansTransactionException transactionException = null;

                if (transactionInfo != null)
                {
                    try
                    {
                        transactionInfo.ReconcilePending();
                        transactionException = transactionInfo.MustAbort(serializationManager);

                        // This request started the transaction, so we try to commit before returning,
                        // or if it must abort, tell participants that it aborted
                        if (startNewTransaction)
                        {
                            try
                            {
                                if (transactionException == null)
                                {
                                    var status = await this.transactionAgent.Resolve(transactionInfo);

                                    if (status != TransactionalStatus.Ok)
                                    {
                                        transactionException = status.ConvertToUserException(transactionInfo.Id);
                                    }
                                }
                                else
                                {
                                    await this.transactionAgent.Abort(transactionInfo);
                                }
                            }
                            finally
                            {
                                TransactionContext.Clear();
                            }
                        }
                    }
                    catch (Exception e)
                    {
                        // we should never hit this, but if we do, the following message will help us diagnose
                        this.logger.LogError(e, "Error in transaction post-grain-method-invocation code");
                        throw;
                    }
                }

                if (message.Direction != Message.Directions.OneWay)
                {
                    if (transactionException != null)
                    {
                        SafeSendExceptionResponse(message, transactionException);
                    }
                    else
                    {
                        SafeSendResponse(message, resultObject);
                    }
                }
                return;
            }
            catch (Exception exc2)
            {
                this.logger.Warn(ErrorCode.Runtime_Error_100329, "Exception during Invoke of message: " + message, exc2);

                TransactionContext.Clear();

                if (message.Direction != Message.Directions.OneWay)
                {
                    SafeSendExceptionResponse(message, exc2);
                }
            }
            finally
            {
                RequestContext.Clear();
            }
        }
Beispiel #24
0
 public void Abort(ITransactionInfo transactionInfo, OrleansTransactionAbortedException reason)
 {
     throw new OrleansTransactionsDisabledException();
 }
Beispiel #25
0
 public void Join(ITransactionInfo x)
 {
     this.joined.Enqueue((TransactionInfo)x);
 }
 public Task Abort(ITransactionInfo transactionInfo)
 {
     throw new OrleansTransactionsDisabledException();
 }
        public async Task Invoke(IAddressable target, IInvokable invokable, Message message)
        {
            try
            {
                // Don't process messages that have already timed out
                if (message.IsExpired)
                {
                    message.DropExpiredMessage(MessagingStatisticsGroup.Phase.Invoke);
                    return;
                }

                RequestContextExtensions.Import(message.RequestContextData);
                if (schedulingOptions.PerformDeadlockDetection && !message.TargetGrain.IsSystemTarget)
                {
                    UpdateDeadlockInfoInRequestContext(new RequestInvocationHistory(message.TargetGrain, message.TargetActivation, message.DebugContext));
                    // RequestContext is automatically saved in the msg upon send and propagated to the next hop
                    // in RuntimeClient.CreateMessage -> RequestContextExtensions.ExportToMessage(message);
                }

                bool             startNewTransaction = false;
                ITransactionInfo transactionInfo     = message.TransactionInfo;

                if (message.IsTransactionRequired && transactionInfo == null)
                {
                    // TODO: this should be a configurable parameter
                    var transactionTimeout = Debugger.IsAttached ? TimeSpan.FromMinutes(30) : TimeSpan.FromSeconds(10);

                    // Start a new transaction
                    transactionInfo = await this.transactionAgent.Value.StartTransaction(message.IsReadOnly, transactionTimeout);

                    startNewTransaction = true;
                }

                if (transactionInfo != null)
                {
                    TransactionContext.SetTransactionInfo(transactionInfo);
                }

                object resultObject;
                try
                {
                    var request = (InvokeMethodRequest)message.GetDeserializedBody(this.serializationManager);
                    if (request.Arguments != null)
                    {
                        CancellationSourcesExtension.RegisterCancellationTokens(target, request, this.loggerFactory, logger, this, this.cancellationTokenRuntime);
                    }

                    var invoker = invokable.GetInvoker(typeManager, request.InterfaceId, message.GenericGrainType);

                    if (invoker is IGrainExtensionMethodInvoker &&
                        !(target is IGrainExtension))
                    {
                        // We are trying the invoke a grain extension method on a grain
                        // -- most likely reason is that the dynamic extension is not installed for this grain
                        // So throw a specific exception here rather than a general InvalidCastException
                        var error = String.Format(
                            "Extension not installed on grain {0} attempting to invoke type {1} from invokable {2}",
                            target.GetType().FullName, invoker.GetType().FullName, invokable.GetType().FullName);
                        var    exc            = new GrainExtensionNotInstalledException(error);
                        string extraDebugInfo = null;
#if DEBUG
                        extraDebugInfo = Utils.GetStackTrace();
#endif
                        logger.Warn(ErrorCode.Stream_ExtensionNotInstalled,
                                    string.Format("{0} for message {1} {2}", error, message, extraDebugInfo), exc);

                        throw exc;
                    }

                    var requestInvoker = new GrainMethodInvoker(target, request, invoker, GrainCallFilters, interfaceToImplementationMapping);
                    await requestInvoker.Invoke();

                    resultObject = requestInvoker.Result;
                }
                catch (Exception exc1)
                {
                    if (invokeExceptionLogger.IsEnabled(LogLevel.Debug) || message.Direction == Message.Directions.OneWay)
                    {
                        invokeExceptionLogger.Warn(ErrorCode.GrainInvokeException,
                                                   "Exception during Grain method call of message: " + message, exc1);
                    }

                    transactionInfo = TransactionContext.GetTransactionInfo();
                    if (transactionInfo != null)
                    {
                        // Must abort the transaction on exceptions
                        transactionInfo.IsAborted = true;
                        if (startNewTransaction)
                        {
                            var abortException = (exc1 as OrleansTransactionAbortedException) ??
                                                 new OrleansTransactionAbortedException(transactionInfo.TransactionId.ToString(), exc1);
                            this.transactionAgent.Value.Abort(transactionInfo, abortException);
                            exc1 = abortException;
                        }
                    }

                    // If a grain allowed an inconsistent state exception to escape and the exception originated from
                    // this activation, then deactivate it.
                    var ise = exc1 as InconsistentStateException;
                    if (ise != null && ise.IsSourceActivation)
                    {
                        // Mark the exception so that it doesn't deactivate any other activations.
                        ise.IsSourceActivation = false;

                        var activation = (target as Grain)?.Data;
                        if (activation != null)
                        {
                            invokeExceptionLogger.Info($"Deactivating {activation} due to inconsistent state.");
                            this.DeactivateOnIdle(activation.ActivationId);
                        }
                    }

                    if (message.Direction != Message.Directions.OneWay)
                    {
                        TransactionContext.Clear();
                        SafeSendExceptionResponse(message, exc1);
                    }
                    return;
                }

                transactionInfo = TransactionContext.GetTransactionInfo();
                if (transactionInfo != null && !transactionInfo.ReconcilePending(out var numberOrphans))
                {
                    var abortException = new OrleansOrphanCallException(transactionInfo.TransactionId.ToString(), numberOrphans);
                    // Can't exit before the transaction completes.
                    TransactionContext.GetTransactionInfo().IsAborted = true;
                    if (startNewTransaction)
                    {
                        this.transactionAgent.Value.Abort(TransactionContext.GetTransactionInfo(), abortException);
                    }


                    if (message.Direction != Message.Directions.OneWay)
                    {
                        TransactionContext.Clear();
                        SafeSendExceptionResponse(message, abortException);
                    }

                    return;
                }

                if (startNewTransaction)
                {
                    // This request started the transaction, so we try to commit before returning.
                    await this.transactionAgent.Value.Commit(transactionInfo);

                    TransactionContext.Clear();
                }

                if (message.Direction == Message.Directions.OneWay)
                {
                    return;
                }

                SafeSendResponse(message, resultObject);
            }
            catch (Exception exc2)
            {
                logger.Warn(ErrorCode.Runtime_Error_100329, "Exception during Invoke of message: " + message, exc2);

                try
                {
                    if (exc2 is OrleansTransactionInDoubtException)
                    {
                        this.logger.LogError(exc2, "Transaction failed due to in doubt transaction");
                    }
                    else if (TransactionContext.GetTransactionInfo() != null)
                    {
                        // Must abort the transaction on exceptions
                        TransactionContext.GetTransactionInfo().IsAborted = true;
                        var abortException = (exc2 as OrleansTransactionAbortedException) ??
                                             new OrleansTransactionAbortedException(TransactionContext.GetTransactionInfo().TransactionId.ToString(), exc2);
                        this.transactionAgent.Value.Abort(TransactionContext.GetTransactionInfo(), abortException);
                    }
                }
                finally
                {
                    TransactionContext.Clear();
                    if (message.Direction != Message.Directions.OneWay)
                    {
                        SafeSendExceptionResponse(message, exc2);
                    }
                }
            }
            finally
            {
                TransactionContext.Clear();
            }
        }
 /// <summary>
 /// Executes a previous transaction
 /// </summary>
 /// <param name="storeName">Name of the store</param>
 /// <param name="transactionInfo">Transaction to execute.</param>
 public IJobInfo ReExecuteTransaction(string storeName, ITransactionInfo transactionInfo)
 {
     try
     {
         var tInfoWrapper = transactionInfo as TransactionInfoWrapper;
         if (tInfoWrapper == null) throw new ArgumentException("Invalid TransactionInfo object received.", "transactionInfo");
         var tInfo = tInfoWrapper.TransactionInfo;
         var jobId = _serverCore.ReExecuteTransaction(storeName, tInfo.Id, (Storage.TransactionType)((int) tInfo.TransactionType));
         return new JobInfoWrapper(new JobInfo { JobId = jobId.ToString(), JobPending = true });
     }
     catch (Exception ex)
     {
         Logging.LogError(BrightstarEventId.ServerCoreException, "Error rexecuting transaction with JobId {0} for store {1}", transactionInfo.JobId, storeName);
         throw new BrightstarClientException(String.Format("Error rexecuting transaction with JobId {0} for store {1}. {2}", transactionInfo.JobId, storeName, ex.Message), ex);
     }
 }
Beispiel #29
0
 /// <summary>
 /// Executes a previous transaction
 /// </summary>
 /// <param name="storeName">The name of the store to re-apply the transaction to</param>
 /// <param name="transactionInfo">The transaction to be applied</param>
 public IJobInfo ReExecuteTransaction(string storeName, ITransactionInfo transactionInfo)
 {
     throw new NotImplementedException();
 }
Beispiel #30
0
 public void Join(ITransactionInfo other)
 {
     this.joined.Enqueue((TransactionInfo)other);
 }