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; } }
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(); }
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)); }
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); }
public void Add(ITransactionParticipant data) { if (_dataReferences == null) { _dataReferences = new List <ITransactionParticipant>(); } _dataReferences.Add(data); }
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 }
public virtual void Enlist(ITransactionParticipant participant) { if (null == participant) { throw new ArgumentNullException(); } CheckSynchronization(); if (!_participants.Contains(participant)) { _participants.Add(participant); } }
public void RecordWrite(ITransactionParticipant transactionalResource, DateTime minTime) { Participants.TryGetValue(transactionalResource, out var count); count.Writes++; Participants[transactionalResource] = count; if (minTime > TimeStamp) { TimeStamp = minTime; } }
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); }
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); }
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)); }
public bool Equals(ITransactionParticipant other) { return(thisParticipant.Equals(other)); }
public void Add(ITransactionParticipant data) { if (_dataReferences == null) _dataReferences = new List<ITransactionParticipant>(); _dataReferences.Add(data); }
public Task Prepared(string resourceId, Guid transactionId, DateTime timestamp, ITransactionParticipant participant, TransactionalStatus status) { return(localParticipants[resourceId].Prepared(transactionId, timestamp, participant, status)); }
public Task Prepare(string resourceId, Guid transactionId, AccessCounter accessCount, DateTime timeStamp, ITransactionParticipant transactionManager) { return(localParticipants[resourceId].Prepare(transactionId, accessCount, timeStamp, transactionManager)); }
public Task Ping(string resourceId, Guid transactionId, DateTime timeStamp, ITransactionParticipant participant) { return(localParticipants[resourceId].Ping(transactionId, timeStamp, participant)); }
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); }
public Task Ping(Guid transactionId, DateTime timeStamp, ITransactionParticipant participant) { return(this.transactionManager.Ping(transactionId, timeStamp, participant)); }
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()); }
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()); }
public void Register(string resourceId, ITransactionParticipant localTransactionParticipant) { this.localParticipants.Add(resourceId, localTransactionParticipant); }
public void AddTransactionParticipant(ITransactionParticipant participant) { Participants.Add(participant); }