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); }
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(); }
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"); } }
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); }
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." }); }
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(); }
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); }
public ActionResult Show() { AccessCounter.Increase(); ViewBag.PodIP = Environment.GetEnvironmentVariable("POD_IP"); ViewBag.HostIP = Environment.GetEnvironmentVariable("HOST_IP"); ViewBag.AccessCounter = AccessCounter.Value(); return(View()); }
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))); }
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"); } }
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); }
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); }
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); }
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); }
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; } } } } }
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 }
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); }
public void NotifyUsed(CacheEntry cacheEntry) { AccessCounter.Increment(cacheEntry.Hash); }
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)); }
public void Metrics() { Response.ContentType = "text/plain"; Response.Write(string.Format("winaspnet_access_total {0}", AccessCounter.Value())); Response.End(); }
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 }
public Task <TransactionalStatus> CommitReadOnly(Guid transactionId, AccessCounter accessCount, DateTime timeStamp) { return(extension.CommitReadOnly(resourceId, transactionId, accessCount, timeStamp)); }
public Task <TransactionalStatus> PrepareAndCommit(Guid transactionId, AccessCounter accessCount, DateTime timeStamp, List <ITransactionParticipant> writeParticipants, int totalParticipants) { return(extension.PrepareAndCommit(resourceId, transactionId, accessCount, timeStamp, writeParticipants, totalParticipants)); }
public Task Prepare(Guid transactionId, AccessCounter accessCount, DateTime timeStamp, ITransactionParticipant transactionManager) { return(extension.Prepare(resourceId, transactionId, accessCount, timeStamp, transactionManager)); }
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 }); }
public Task Prepare(string resourceId, Guid transactionId, AccessCounter accessCount, DateTime timeStamp, ITransactionParticipant transactionManager) { return(localParticipants[resourceId].Prepare(transactionId, accessCount, timeStamp, transactionManager)); }
public async Task Prepare(Guid transactionId, AccessCounter accessCount, DateTime timeStamp, ParticipantId transactionManager) { await this.queue.NotifyOfPrepare(transactionId, accessCount, timeStamp, transactionManager); }
public Task <TransactionalStatus> CommitReadOnly(string resourceId, Guid transactionId, AccessCounter accessCount, DateTime timeStamp) { return(localParticipants[resourceId].CommitReadOnly(transactionId, accessCount, timeStamp)); }