コード例 #1
0
ファイル: TransactionManager.cs プロジェクト: n00j/orleans
        public async Task <TransactionalStatus> PrepareAndCommit(Guid transactionId, AccessCounter accessCount, DateTime timeStamp, List <ParticipantId> writeResources, int totalResources)
        {
            // validate the lock
            var locked = await this.queue.RWLock.ValidateLock(transactionId, accessCount);

            var status = locked.Item1;
            var record = locked.Item2;
            var valid  = status == TransactionalStatus.Ok;

            record.Timestamp         = timeStamp;
            record.Role              = CommitRole.LocalCommit; // we are the TM
            record.WaitCount         = totalResources - 1;
            record.WaitingSince      = DateTime.UtcNow;
            record.WriteParticipants = writeResources;
            record.PromiseForTA      = new TaskCompletionSource <TransactionalStatus>(TaskCreationOptions.RunContinuationsAsynchronously);

            if (!valid)
            {
                await this.queue.NotifyOfAbort(record, status);
            }
            else
            {
                this.queue.Clock.Merge(record.Timestamp);
            }

            this.queue.RWLock.Notify();
            return(await record.PromiseForTA.Task);
        }
コード例 #2
0
        public async Task NotifyOfPrepare(Guid transactionId, AccessCounter accessCount, DateTime timeStamp, ParticipantId transactionManager)
        {
            var locked = await this.RWLock.ValidateLock(transactionId, accessCount);

            var status = locked.Item1;
            var record = locked.Item2;
            var valid  = status == TransactionalStatus.Ok;

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

            if (!valid)
            {
                await this.NotifyOfAbort(record, status);
            }
            else
            {
                this.Clock.Merge(record.Timestamp);
            }

            this.RWLock.Notify();
        }
コード例 #3
0
        public async Task Prepare(Guid transactionId, AccessCounter accessCount, DateTime timeStamp, ParticipantId transactionManager)
        {
            this.logger.Info($"Grain {this.context.GrainInstance} started Prepare transaction {transactionId}");

            if (this.faultInjectionControl?.FaultInjectionPhase == TransactionFaultInjectPhase.BeforePrepare)
            {
                if (this.faultInjectionControl.FaultInjectionType == FaultInjectionType.ExceptionBeforeStore)
                {
                    this.faultInjector.InjectBeforeStore = true;
                }
                if (this.faultInjectionControl.FaultInjectionType == FaultInjectionType.ExceptionAfterStore)
                {
                    this.faultInjector.InjectAfterStore = true;
                }
                this.logger.Info($"Grain {this.context.GrainInstance} injected fault before transaction {transactionId} Prepare, " +
                                 $"with fault type {this.faultInjectionControl.FaultInjectionType}");
            }

            await this.tResource.Prepare(transactionId, accessCount, timeStamp, transactionManager);

            if (this.faultInjectionControl?.FaultInjectionPhase == TransactionFaultInjectPhase.AfterPrepare &&
                this.faultInjectionControl.FaultInjectionType == FaultInjectionType.Deactivation)
            {
                this.grainRuntime.DeactivateOnIdle((context.GrainInstance));
                this.faultInjectionControl.FaultInjectionPhase = TransactionFaultInjectPhase.None;
                this.logger.Info($"Grain {this.context.GrainInstance} deactivating after transaction {transactionId} Prepare");
            }
        }
コード例 #4
0
        public async Task <TransactionalStatus> PrepareAndCommit(Guid transactionId, AccessCounter accessCount, DateTime timeStamp, List <ParticipantId> writeParticipants, int totalParticipants)
        {
            this.logger.Info($"Grain {this.context.GrainInstance} started PrepareAndCommit transaction {transactionId}");
            if (this.faultInjectionControl?.FaultInjectionPhase == TransactionFaultInjectPhase.BeforePrepareAndCommit)
            {
                if (this.faultInjectionControl.FaultInjectionType == FaultInjectionType.ExceptionBeforeStore)
                {
                    this.faultInjector.InjectBeforeStore = true;
                }
                if (this.faultInjectionControl.FaultInjectionType == FaultInjectionType.ExceptionAfterStore)
                {
                    this.faultInjector.InjectAfterStore = true;
                }
                this.logger.Info($"Grain {this.context.GrainInstance} injected fault before transaction {transactionId} PrepareAndCommit, " +
                                 $"with fault type {this.faultInjectionControl.FaultInjectionType}");
            }
            var result = await this.tm.PrepareAndCommit(transactionId, accessCount, timeStamp, writeParticipants, totalParticipants);

            if (this.faultInjectionControl?.FaultInjectionPhase == TransactionFaultInjectPhase.AfterPrepareAndCommit && this.faultInjectionControl.FaultInjectionType == FaultInjectionType.Deactivation)
            {
                this.grainRuntime.DeactivateOnIdle((context.GrainInstance));
                this.faultInjectionControl.FaultInjectionPhase = TransactionFaultInjectPhase.None;
                this.logger.Info($"Grain {this.context.GrainInstance} deactivating after transaction {transactionId} PrepareAndCommit");
            }
            return(result);
        }
コード例 #5
0
        public async Task <ReserveSpaceResult> TryReserveSpace(CacheEntry cacheEntry, string contentType, int byteCount,
                                                               bool allowEviction, AsyncLockProvider writeLocks,
                                                               CancellationToken cancellationToken)
        {
            var shard          = Database.GetShardForKey(cacheEntry.RelativePath);
            var shardSizeLimit = Options.MaxCacheBytes / Database.GetShardCount();

            // When we're okay with deleting the database entry even though the file isn't written
            var farFuture = DateTime.UtcNow.AddHours(1);

            var maxAttempts = 30;

            for (var attempts = 0; attempts < maxAttempts; attempts++)
            {
                var recordCreated =
                    await Database.CreateRecordIfSpace(shard, cacheEntry.RelativePath,
                                                       contentType,
                                                       EstimateEntryBytesWithOverhead(byteCount),
                                                       farFuture,
                                                       AccessCounter.GetHash(cacheEntry.Hash),
                                                       shardSizeLimit);

                // Return true if we created the record
                if (recordCreated)
                {
                    return new ReserveSpaceResult()
                           {
                               Success = true
                           }
                }
                ;

                // We need to evict but we are not permitted
                if (!allowEviction)
                {
                    return new ReserveSpaceResult()
                           {
                               Success = false, Message = "Eviction disabled in sync mode"
                           }
                }
                ;

                var entryDiskSpace = EstimateEntryBytesWithOverhead(byteCount) +
                                     Database.EstimateRecordDiskSpace(cacheEntry.RelativePath.Length + (contentType?.Length ?? 0));

                var missingSpace = Math.Max(0, await Database.GetShardSize(shard) + entryDiskSpace - shardSizeLimit);
                // Evict space
                var evictResult = await EvictSpace(shard, missingSpace, writeLocks, cancellationToken);

                if (!evictResult.Success)
                {
                    return(evictResult); //We failed to evict enough space from the cache
                }
            }

            return(new ReserveSpaceResult()
            {
                Success = false, Message = $"Eviction worked but CreateRecordIfSpace failed {maxAttempts} times."
            });
        }
コード例 #6
0
        public void NotifyOfPrepare(Guid transactionId, AccessCounter accessCount, DateTime timeStamp, ParticipantId transactionManager)
        {
            var valid = this.RWLock.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 (logger.IsEnabled(LogLevel.Trace))
            {
                logger.Trace("received prepare valid={Valid} {Record}", valid, record);
            }

            if (!valid)
            {
                this.NotifyOfAbort(record, status);
            }
            else
            {
                this.Clock.Merge(record.Timestamp);
            }

            this.RWLock.Notify();
        }
コード例 #7
0
        public async Task <TransactionalStatus> CommitReadOnly(Guid transactionId, AccessCounter accessCount, DateTime timeStamp)
        {
            // validate the lock
            var locked = await this.queue.RWLock.ValidateLock(transactionId, accessCount);

            var status = locked.Item1;
            var record = locked.Item2;
            var valid  = status == TransactionalStatus.Ok;

            record.Timestamp    = timeStamp;
            record.Role         = CommitRole.ReadOnly;
            record.PromiseForTA = new TaskCompletionSource <TransactionalStatus>(TaskCreationOptions.RunContinuationsAsynchronously);

            if (!valid)
            {
                await this.queue.NotifyOfAbort(record, status);
            }
            else
            {
                this.queue.Clock.Merge(record.Timestamp);
            }

            this.queue.RWLock.Notify();
            return(await record.PromiseForTA.Task);
        }
コード例 #8
0
 public ActionResult Show()
 {
     AccessCounter.Increase();
     ViewBag.PodIP         = Environment.GetEnvironmentVariable("POD_IP");
     ViewBag.HostIP        = Environment.GetEnvironmentVariable("HOST_IP");
     ViewBag.AccessCounter = AccessCounter.Value();
     return(View());
 }
コード例 #9
0
 public Task MarkFileCreated(CacheEntry cacheEntry, string contentType, long recordDiskSpace, DateTime createdDate)
 {
     return(Database.UpdateCreatedDateAtomic(
                Database.GetShardForKey(cacheEntry.RelativePath),
                cacheEntry.RelativePath,
                contentType,
                EstimateEntryBytesWithOverhead(recordDiskSpace),
                createdDate,
                AccessCounter.GetHash(cacheEntry.Hash)));
 }
コード例 #10
0
        public async Task Prepare(Guid transactionId, AccessCounter accessCount, DateTime timeStamp, ParticipantId transactionManager)
        {
            this.logger.Info($"Grain {this.context.GrainInstance} started Prepare transaction {transactionId}");
            await this.tResource.Prepare(transactionId, accessCount, timeStamp, transactionManager);

            if (this.deactivationPhaseReference.DeactivationPhase == TransactionDeactivationPhase.AfterPrepare)
            {
                this.grainRuntime.DeactivateOnIdle((context.GrainInstance));
                this.deactivationPhaseReference.DeactivationPhase = TransactionDeactivationPhase.None;
                this.logger.Info($"Grain {this.context.GrainInstance} deactivating after transaction {transactionId} Prepare");
            }
        }
コード例 #11
0
        public async Task <TransactionalStatus> CommitReadOnly(Guid transactionId, AccessCounter accessCount, DateTime timeStamp)
        {
            this.logger.Info($"Grain {this.context.GrainInstance} started CommitReadOnly transaction {transactionId}");
            var result = await this.tResource.CommitReadOnly(transactionId, accessCount, timeStamp);

            if (this.deactivationPhaseReference.DeactivationPhase == TransactionDeactivationPhase.AfterCommitReadOnly)
            {
                this.grainRuntime.DeactivateOnIdle((context.GrainInstance));
                this.deactivationPhaseReference.DeactivationPhase = TransactionDeactivationPhase.None;
                this.logger.Info($"Grain {this.context.GrainInstance} deactivating after transaction {transactionId} CommitReadOnly");
            }
            return(result);
        }
コード例 #12
0
        public async Task <TransactionalStatus> PrepareAndCommit(Guid transactionId, AccessCounter accessCount, DateTime timeStamp, List <ParticipantId> writeParticipants, int totalParticipants)
        {
            this.logger.Info($"Grain {this.context.GrainInstance} started PrepareAndCommit transaction {transactionId}");
            var result = await this.tm.PrepareAndCommit(transactionId, accessCount, timeStamp, writeParticipants, totalParticipants);

            if (this.deactivationPhaseReference.DeactivationPhase == TransactionDeactivationPhase.AfterPrepareAndCommit)
            {
                this.grainRuntime.DeactivateOnIdle((context.GrainInstance));
                this.deactivationPhaseReference.DeactivationPhase = TransactionDeactivationPhase.None;
                this.logger.Info($"Grain {this.context.GrainInstance} deactivating after transaction {transactionId} PrepareAndCommit");
            }
            return(result);
        }
コード例 #13
0
        public async Task <TransactionalStatus> CommitReadOnly(Guid transactionId, AccessCounter accessCount, DateTime timeStamp)
        {
            this.logger.Info($"Grain {this.context.GrainInstance} started CommitReadOnly transaction {transactionId}");
            var result = await this.tResource.CommitReadOnly(transactionId, accessCount, timeStamp);

            if (this.faultInjectionControl.FaultInjectionPhase == TransactionFaultInjectPhase.AfterCommitReadOnly &&
                this.faultInjectionControl.FaultInjectionType == FaultInjectionType.Deactivation)
            {
                this.grainRuntime.DeactivateOnIdle((context.GrainInstance));
                this.logger.Info($"Grain {this.context.GrainInstance} deactivating after transaction {transactionId} CommitReadOnly");
            }

            this.faultInjectionControl.Reset();
            return(result);
        }
コード例 #14
0
ファイル: TransactionManager.cs プロジェクト: ymoon/orleans
        public Task <TransactionalStatus> CommitReadOnly(Guid transactionId, AccessCounter accessCount, DateTime timeStamp)
        {
            // validate the lock
            var valid = this.queue.RWLock.ValidateLock(transactionId, accessCount, out var status, out var record);

            record.Timestamp    = timeStamp;
            record.Role         = CommitRole.ReadOnly;
            record.PromiseForTA = new TaskCompletionSource <TransactionalStatus>();

            if (!valid)
            {
                this.queue.NotifyOfAbort(record, status);
            }
            else
            {
                this.queue.Clock.Merge(record.Timestamp);
            }

            this.queue.RWLock.Notify();
            return(record.PromiseForTA.Task);
        }
コード例 #15
0
ファイル: ReaderWriterLock.cs プロジェクト: zeus82/orleans
        public async Task <TResult> EnterLock <TResult>(Guid transactionId, DateTime priority,
                                                        AccessCounter counter, bool isRead, Func <TResult> task)
        {
            bool        rollbacksOccurred = false;
            List <Task> cleanup           = new List <Task>();

            await this.queue.Ready();

            // search active transactions
            if (Find(transactionId, isRead, out var group, out var record))
            {
                // check if we lost some reads or writes already
                if (counter.Reads > record.NumberReads || counter.Writes > record.NumberWrites)
                {
                    throw new OrleansBrokenTransactionLockException(transactionId.ToString(), "when re-entering lock");
                }

                // check if the operation conflicts with other transactions in the group
                if (HasConflict(isRead, priority, transactionId, group, out var resolvable))
                {
                    if (!resolvable)
                    {
                        throw new OrleansTransactionLockUpgradeException(transactionId.ToString());
                    }
                    else
                    {
                        // rollback all conflicts
                        var conflicts = Conflicts(transactionId, group).ToList();

                        if (conflicts.Count > 0)
                        {
                            foreach (var r in conflicts)
                            {
                                cleanup.Add(Rollback(r, true));
                                rollbacksOccurred = true;
                            }
                        }
                    }
                }
            }
コード例 #16
0
        public Task Prepare(Guid transactionId, AccessCounter accessCount, DateTime timeStamp, ITransactionParticipant transactionManager)
        {
            var valid = this.queue.RWLock.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)
            {
                this.queue.NotifyOfAbort(record, status);
            }
            else
            {
                this.queue.Clock.Merge(record.Timestamp);
            }

            this.queue.RWLock.Notify();
            return(Task.CompletedTask); // one-way, no response
        }
コード例 #17
0
ファイル: TransactionManager.cs プロジェクト: ymoon/orleans
        public Task <TransactionalStatus> PrepareAndCommit(Guid transactionId, AccessCounter accessCount, DateTime timeStamp, List <ParticipantId> writeResources, int totalResources)
        {
            // validate the lock
            var valid = this.queue.RWLock.ValidateLock(transactionId, accessCount, out var status, out var record);

            record.Timestamp         = timeStamp;
            record.Role              = CommitRole.LocalCommit; // we are the TM
            record.WaitCount         = totalResources - 1;
            record.WaitingSince      = DateTime.UtcNow;
            record.WriteParticipants = writeResources;
            record.PromiseForTA      = new TaskCompletionSource <TransactionalStatus>();

            if (!valid)
            {
                this.queue.NotifyOfAbort(record, status);
            }
            else
            {
                this.queue.Clock.Merge(record.Timestamp);
            }

            this.queue.RWLock.Notify();
            return(record.PromiseForTA.Task);
        }
コード例 #18
0
 public void NotifyUsed(CacheEntry cacheEntry)
 {
     AccessCounter.Increment(cacheEntry.Hash);
 }
コード例 #19
0
 public Task <TransactionalStatus> PrepareAndCommit(string resourceId, Guid transactionId, AccessCounter accessCount, DateTime timeStamp, List <ITransactionParticipant> writeParticipants, int totalParticipants)
 {
     return(localParticipants[resourceId].PrepareAndCommit(transactionId, accessCount, timeStamp, writeParticipants, totalParticipants));
 }
コード例 #20
0
 public void Metrics()
 {
     Response.ContentType = "text/plain";
     Response.Write(string.Format("winaspnet_access_total {0}", AccessCounter.Value()));
     Response.End();
 }
コード例 #21
0
 public Task Prepare(Guid transactionId, AccessCounter accessCount, DateTime timeStamp, ParticipantId transactionManager)
 {
     this.queue.NotifyOfPrepare(transactionId, accessCount, timeStamp, transactionManager);
     return(Task.CompletedTask); // one-way, no response
 }
コード例 #22
0
 public Task <TransactionalStatus> CommitReadOnly(Guid transactionId, AccessCounter accessCount, DateTime timeStamp)
 {
     return(extension.CommitReadOnly(resourceId, transactionId, accessCount, timeStamp));
 }
コード例 #23
0
 public Task <TransactionalStatus> PrepareAndCommit(Guid transactionId, AccessCounter accessCount, DateTime timeStamp, List <ITransactionParticipant> writeParticipants, int totalParticipants)
 {
     return(extension.PrepareAndCommit(resourceId, transactionId, accessCount, timeStamp, writeParticipants, totalParticipants));
 }
コード例 #24
0
 public Task Prepare(Guid transactionId, AccessCounter accessCount, DateTime timeStamp, ITransactionParticipant transactionManager)
 {
     return(extension.Prepare(resourceId, transactionId, accessCount, timeStamp, transactionManager));
 }
コード例 #25
0
        private async Task <ReserveSpaceResult> EvictSpace(int shard, long diskSpace, AsyncLockProvider writeLocks, CancellationToken cancellationToken)
        {
            var bytesToDeleteOptimally = Math.Max(Options.MinCleanupBytes, diskSpace);
            var bytesToDeleteMin       = diskSpace;

            long bytesDeleted = 0;

            while (bytesDeleted < bytesToDeleteOptimally)
            {
                var deletionCutoff = DateTime.UtcNow.Subtract(Options.RetryDeletionAfter);
                var creationCutoff = DateTime.UtcNow.Subtract(Options.MinAgeToDelete);

                var records =
                    (await Database.GetDeletionCandidates(shard, deletionCutoff, creationCutoff, Options.CleanupSelectBatchSize, AccessCounter.Get))
                    .Select(r =>
                            new Tuple <ushort, ICacheDatabaseRecord>(
                                AccessCounter.Get(r.AccessCountKey), r))
                    .OrderByDescending(r => r.Item1)
                    .Select(r => r.Item2).ToArray();

                foreach (var record in records)
                {
                    if (cancellationToken.IsCancellationRequested)
                    {
                        throw new OperationCanceledException(cancellationToken);
                    }

                    if (bytesDeleted >= bytesToDeleteOptimally)
                    {
                        break;
                    }

                    var deletedBytes = await TryDeleteRecord(shard, record, writeLocks);

                    bytesDeleted += deletedBytes;
                }

                // Unlikely to find more records in the next iteration
                if (records.Length < Options.CleanupSelectBatchSize)
                {
                    // If we hit the bare minimum, return OK
                    if (bytesDeleted >= bytesToDeleteMin)
                    {
                        return(new ReserveSpaceResult()
                        {
                            Success = true
                        });
                    }
                    else
                    {
                        return(new ReserveSpaceResult()
                        {
                            Success = false, Message = $"Failed to evict enough space using {records.Length} candidates"
                        });
                    }
                }
            }
            return(new ReserveSpaceResult()
            {
                Success = true
            });
        }
コード例 #26
0
 public Task Prepare(string resourceId, Guid transactionId, AccessCounter accessCount, DateTime timeStamp, ITransactionParticipant transactionManager)
 {
     return(localParticipants[resourceId].Prepare(transactionId, accessCount, timeStamp, transactionManager));
 }
コード例 #27
0
 public async Task Prepare(Guid transactionId, AccessCounter accessCount, DateTime timeStamp, ParticipantId transactionManager)
 {
     await this.queue.NotifyOfPrepare(transactionId, accessCount, timeStamp, transactionManager);
 }
コード例 #28
0
 public Task <TransactionalStatus> CommitReadOnly(string resourceId, Guid transactionId, AccessCounter accessCount, DateTime timeStamp)
 {
     return(localParticipants[resourceId].CommitReadOnly(transactionId, accessCount, timeStamp));
 }