示例#1
0
        public void Prepare(long sequenceNumber, Guid transactionId, DateTime timestamp,
                            ITransactionParticipant transactionManager, TState state)
        {
            prepare++;
            total++;

            if (MetaData.TimeStamp < timestamp)
            {
                MetaData.TimeStamp = timestamp;
            }

            if (prepares == null)
            {
                prepares = new SortedDictionary <long, PendingTransactionState <TState> >();
            }

            var tmstring = (transactionManager == null) ? null :
                           JsonConvert.SerializeObject(transactionManager, MetaData.SerializerSettings);

            prepares[sequenceNumber] = new PendingTransactionState <TState>
            {
                SequenceId         = sequenceNumber,
                TransactionId      = transactionId.ToString(),
                TimeStamp          = timestamp,
                TransactionManager = tmstring,
                State = state
            };

            if (cancelAbove < sequenceNumber)
            {
                cancelAbove = sequenceNumber;
            }
        }
示例#2
0
        private async Task OnSetupState(CancellationToken ct)
        {
            if (ct.IsCancellationRequested)
            {
                return;
            }

            var boundExtension = await this.runtime.BindExtension <TransactionParticipantExtension, ITransactionParticipantExtension>(() => new TransactionParticipantExtension());

            boundExtension.Item1.Register(this.config.StateName, this);
            this.thisParticipant = boundExtension.Item2.AsTransactionParticipant(this.config.StateName);

            this.logger = loggerFactory.CreateLogger($"{context.GrainType.Name}.{this.config.StateName}.{this.thisParticipant.ToShortString()}");

            var storageFactory = this.context.ActivationServices.GetRequiredService <INamedTransactionalStateStorageFactory>();
            ITransactionalStateStorage <TState> storage = storageFactory.Create <TState>(this.config.StorageName, this.config.StateName);

            Action deactivate = () => grainRuntime.DeactivateOnIdle(context.GrainInstance);
            var    options    = this.context.ActivationServices.GetRequiredService <IOptions <TransactionalStateOptions> >();
            var    clock      = this.context.ActivationServices.GetRequiredService <IClock>();

            this.queue              = new TransactionQueue <TState>(options, this.thisParticipant, deactivate, storage, this.serializerSettings, clock, logger);
            this.resource           = new TransactionalResource <TState>(this.queue);
            this.transactionManager = new TransactionManager <TState>(this.queue);

            // recover state
            await this.queue.NotifyOfRestore();
        }
示例#3
0
        public Task Ping(Guid transactionId, DateTime timeStamp, ITransactionParticipant participant)
        {
            if (commitQueue.Find(transactionId, timeStamp) != -1)
            {
                // no need to take special action now - the transaction is still
                // in the commit queue and its status is not yet determined.
                // confirmation or cancellation will be sent after committing or aborting.

                storageWorker.Notify(); // just in case the worker fell asleep or something
            }
            else
            {
                if (confirmationTasks.TryGetValue(transactionId, out var record))
                {
                    // re-send now
                    record.LastSent = null;
                    confirmationWorker.Notify();
                }
                else
                {
                    // we never heard of this transaction - so it must have aborted
                    participant.Cancel(transactionId, timeStamp, TransactionalStatus.PresumedAbort);
                }
            }
            return(Task.CompletedTask); // one-way, no response
        }
        /// <summary>
        /// Enlists the specified <paramref name="transactionParticipant"/> in the current transaction handled by the specified <paramref name="transactionManager" />.
        /// </summary>
        /// <param name="transactionParticipant">The participant to enlist.</param>
        /// <param name="transactionManager">The transaction manager that provides the transaction to enlist in.</param>
        /// <returns>The enlistment returned from the transaction when enlisting.</returns>
        public static IEnlistment EnlistVolatile(this ITransactionParticipant transactionParticipant, ITransactionManager transactionManager)
        {
            Ensure.IsNotNull(transactionParticipant, "transactionParticipant");
            Ensure.IsNotNull(transactionManager, "transactionManager");

            return(transactionManager.CurrentTransaction.EnlistVolatile(
                       transactionParticipant, EnlistmentOptions.None));
        }
示例#5
0
        public void SetUp()
        {
            this.participant        = MockRepository.GenerateMock <ITransactionParticipant>();
            this.transactionManager = MockRepository.GenerateMock <ITransactionManager>();
            this.transaction        = MockRepository.GenerateMock <ITransaction>();

            this.transactionManager.Stub(x => x.CurrentTransaction).Return(this.transaction);
        }
示例#6
0
 public void Add(ITransactionParticipant data)
 {
     if (_dataReferences == null)
     {
         _dataReferences = new List <ITransactionParticipant>();
     }
     _dataReferences.Add(data);
 }
示例#7
0
        public Task Prepared(Guid transactionId, DateTime timeStamp, ITransactionParticipant participant, TransactionalStatus status)
        {
            var pos = commitQueue.Find(transactionId, timeStamp);

            if (pos != -1)
            {
                var localEntry = commitQueue[pos];

                if (localEntry.Role != CommitRole.LocalCommit)
                {
                    logger.Error(666, $"transaction abort due to internal error in {nameof(Prepared)}: Wrong commit type");
                    throw new InvalidOperationException($"Wrong commit type: {localEntry.Role}");
                }

                if (status == TransactionalStatus.Ok)
                {
                    localEntry.WaitCount--;

                    storageWorker.Notify();
                }
                else
                {
                    AbortCommits(status, pos);

                    lockWorker.Notify();
                }
            }
            else
            {
                // this message has arrived ahead of the commit request - we need to remember it

                if (unprocessedPreparedMessages == null)
                {
                    unprocessedPreparedMessages = new Dictionary <DateTime, PMessages>();
                }

                PMessages info;
                if (!unprocessedPreparedMessages.TryGetValue(timeStamp, out info))
                {
                    unprocessedPreparedMessages[timeStamp] = info = new PMessages();
                }
                if (status == TransactionalStatus.Ok)
                {
                    info.Count++;
                }
                else
                {
                    info.Status = status;
                }

                // TODO fix memory leak if corresponding commit messages never arrive
            }

            return(Task.CompletedTask); // one-way, no response
        }
示例#8
0
 public virtual void Enlist(ITransactionParticipant participant)
 {
     if (null == participant)
     {
         throw new ArgumentNullException();
     }
     CheckSynchronization();
     if (!_participants.Contains(participant))
     {
         _participants.Add(participant);
     }
 }
示例#9
0
        public void RecordWrite(ITransactionParticipant transactionalResource, DateTime minTime)
        {
            Participants.TryGetValue(transactionalResource, out var count);

            count.Writes++;

            Participants[transactionalResource] = count;

            if (minTime > TimeStamp)
            {
                TimeStamp = minTime;
            }
        }
示例#10
0
        internal static void Participate(ITransactionParticipant participant)
        {
            if (!IsActive)
            {
                return;
            }

            TransactionQueue queue = ContextHandler.GetTransactionQueue();

            if (queue == null)
            {
                queue = new TransactionQueue();
                ContextHandler.SetTransactionQueue(queue);
            }
            queue.Add(participant);
        }
示例#11
0
 private void InternRollback(ITransactionParticipant participant)
 {
     try
     {
         participant.Rollback();
     }
     catch (ObjectDisposedException ex)
     {
         // Tolerate the fact that the transaction has already been disposed.
         Log.Debug(ex, $"{nameof(participant)} Transaction already disposed.");
     }
     catch (TransactionException txEx)
     {
         // Tolerate transaction exceptions
         Log.Debug(txEx, $"{nameof(participant)} Rollback failed.");
         Log.Trace(Outer.TraceTransaction());
     }
 }
 public TransactionQueue(
     IOptions <TransactionalStateOptions> options,
     ITransactionParticipant resource,
     Action deactivate,
     ITransactionalStateStorage <TState> storage,
     JsonSerializerSettings serializerSettings,
     IClock clock,
     ILogger logger)
 {
     this.options            = options.Value;
     this.resource           = resource;
     this.deactivate         = deactivate;
     this.storage            = storage;
     this.serializerSettings = serializerSettings;
     this.Clock              = new CausalClock(clock);
     this.logger             = logger;
     this.confirmationTasks  = new Dictionary <Guid, TransactionRecord <TState> >();
     this.storageWorker      = new BatchWorkerFromDelegate(StorageWork);
     this.confirmationWorker = new BatchWorkerFromDelegate(ConfirmationWork);
     this.RWLock             = new ReadWriteLock <TState>(options, this, this.storageWorker, logger);
 }
示例#13
0
        private async Task OnSetupState(CancellationToken ct)
        {
            if (ct.IsCancellationRequested)
            {
                return;
            }

            var boundExtension = await this.runtime.BindExtension <TransactionParticipantExtension, ITransactionParticipantExtension>(() => new TransactionParticipantExtension());

            boundExtension.Item1.Register(this.config.StateName, this);
            this.thisParticipant = boundExtension.Item2.AsTransactionParticipant(this.config.StateName);

            this.logger = loggerFactory.CreateLogger($"{context.GrainType.Name}.{this.config.StateName}.{this.thisParticipant.ToShortString()}");

            var storageFactory = this.context.ActivationServices.GetRequiredService <INamedTransactionalStateStorageFactory>();

            this.storage = storageFactory.Create <TState>(this.config.StorageName, this.config.StateName);

            // recover state
            await Restore();

            storageWorker.Notify();
        }
 public Task Prepared(Guid transactionId, DateTime timeStamp, ITransactionParticipant participant, TransactionalStatus status)
 {
     return(extension.Prepared(resourceId, transactionId, timeStamp, participant, status));
 }
 public Task Prepare(Guid transactionId, AccessCounter accessCount, DateTime timeStamp, ITransactionParticipant transactionManager)
 {
     return(extension.Prepare(resourceId, transactionId, accessCount, timeStamp, transactionManager));
 }
 public Task Ping(Guid transactionId, DateTime timeStamp, ITransactionParticipant participant)
 {
     return(extension.Ping(resourceId, transactionId, timeStamp, participant));
 }
 public static IEnlistmentNotification Cast(this ITransactionParticipant participant)
 {
     return(new EnlistmentNotificationAdapter(participant));
 }
示例#18
0
 public virtual void Enlist(ITransactionParticipant participant)
 {
     if (null == participant)
     {
         throw new ArgumentNullException();
     }
     CheckSynchronization();
     if (!_participants.Contains(participant))
     {
         _participants.Add(participant);
     }
 }
示例#19
0
 public bool Equals(ITransactionParticipant other)
 {
     return(thisParticipant.Equals(other));
 }
示例#20
0
 public void Add(ITransactionParticipant data)
 {
     if (_dataReferences == null)
         _dataReferences = new List<ITransactionParticipant>();
     _dataReferences.Add(data);
 }
示例#21
0
 public Task Prepared(string resourceId, Guid transactionId, DateTime timestamp, ITransactionParticipant participant, TransactionalStatus status)
 {
     return(localParticipants[resourceId].Prepared(transactionId, timestamp, participant, status));
 }
示例#22
0
 public Task Prepare(string resourceId, Guid transactionId, AccessCounter accessCount, DateTime timeStamp, ITransactionParticipant transactionManager)
 {
     return(localParticipants[resourceId].Prepare(transactionId, accessCount, timeStamp, transactionManager));
 }
示例#23
0
 public Task Ping(string resourceId, Guid transactionId, DateTime timeStamp, ITransactionParticipant participant)
 {
     return(localParticipants[resourceId].Ping(transactionId, timeStamp, participant));
 }
示例#24
0
        internal static void Participate(ITransactionParticipant participant)
		{
			if (!IsActive)
				return;

			TransactionQueue queue = ContextHandler.GetTransactionQueue();
			if (queue == null)
			{
				queue = new TransactionQueue();
				ContextHandler.SetTransactionQueue(queue);
			}
            queue.Add(participant);
		}
示例#25
0
 public Task Ping(Guid transactionId, DateTime timeStamp, ITransactionParticipant participant)
 {
     return(this.transactionManager.Ping(transactionId, timeStamp, participant));
 }
示例#26
0
 public Task Prepared(Guid transactionId, DateTime timeStamp, ITransactionParticipant participant, TransactionalStatus status)
 {
     return(this.transactionManager.Prepared(transactionId, timeStamp, participant, status));
 }
 public static string ToShortString(this ITransactionParticipant participant)
 {
     // Meant to help humans when debugging or reading traces
     return(participant.GetHashCode().ToString("x4").Substring(0, 4));
 }
 public bool Equals(ITransactionParticipant other)
 {
     return(Equals((object)other));
 }
 public IEnlistment EnlistVolatile(ITransactionParticipant enlistmentNotification, EnlistmentOptions enlistmentOptions)
 {
     return(this.Transaction.EnlistVolatile(enlistmentNotification.Cast(), enlistmentOptions).Cast());
 }
示例#30
0
        public Task Prepare(Guid transactionId, AccessCounter accessCount, DateTime timeStamp, ITransactionParticipant transactionManager)
        {
            var valid = ValidateLock(transactionId, accessCount, out var status, out var record);

            record.Timestamp          = timeStamp;
            record.Role               = CommitRole.RemoteCommit; // we are not the TM
            record.TransactionManager = transactionManager;
            record.LastSent           = null;
            record.PrepareIsPersisted = false;

            if (!valid)
            {
                NotifyOfAbort(record, status);
            }
            else
            {
                MergeClock(record.Timestamp);
            }

            lockWorker.Notify();
            return(Task.CompletedTask); // one-way, no response
        }
 public IEnlistment EnlistDurable(Guid resourceManagerIdentifier, ITransactionParticipant enlistmentNotification, EnlistmentOptions enlistmentOptions)
 {
     return(this.Transaction.EnlistDurable(resourceManagerIdentifier, enlistmentNotification.Cast(), enlistmentOptions).Cast());
 }
示例#32
0
 public void Register(string resourceId, ITransactionParticipant localTransactionParticipant)
 {
     this.localParticipants.Add(resourceId, localTransactionParticipant);
 }
示例#33
0
 public void AddTransactionParticipant(ITransactionParticipant participant)
 {
     Participants.Add(participant);
 }