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 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))); }