Пример #1
0
        public async Task ReplaceRelativePathAndUpdateLastDeletion(ICacheDatabaseRecord record,
                                                                   string movedRelativePath,
                                                                   DateTime lastDeletionAttempt)
        {
            var newRecord = new CacheDatabaseRecord()
            {
                AccessCountKey      = record.AccessCountKey,
                ContentType         = record.ContentType,
                CreatedAt           = record.CreatedAt,
                DiskSize            = record.DiskSize,
                LastDeletionAttempt = lastDeletionAttempt,
                RelativePath        = movedRelativePath
            };

            var loadedDict = await GetLoadedDict();

            if (loadedDict.TryAdd(movedRelativePath, newRecord))
            {
                await writeLog.LogCreated(newRecord);
            }
            else
            {
                throw new InvalidOperationException("Record already moved in database");
            }
            await DeleteRecord(record);
        }
Пример #2
0
 public Task DeleteRecord(int shard, ICacheDatabaseRecord record)
 {
     if (record.CreatedAt > DateTime.UtcNow)
     {
         throw new InvalidOperationException();
     }
     return(shards[shard].DeleteRecord(record));
 }
Пример #3
0
 public LogEntry(LogEntryType entryType, ICacheDatabaseRecord record)
 {
     EntryType           = entryType;
     AccessCountKey      = record.AccessCountKey;
     ContentType         = record.ContentType;
     RelativePath        = record.RelativePath;
     DiskSize            = record.DiskSize;
     LastDeletionAttempt = record.LastDeletionAttempt;
     CreatedAt           = record.CreatedAt;
 }
Пример #4
0
        /// <summary>
        /// Skips the record if there is delete contention for a file.
        /// Only counts bytes as deleted if the physical file is deleted successfully.
        /// Deletes db record whether file exists or not.
        /// </summary>
        /// <param name="shard"></param>
        /// <param name="record"></param>
        /// <param name="writeLocks"></param>
        /// <returns></returns>
        private async Task <long> TryDeleteRecord(int shard, ICacheDatabaseRecord record, AsyncLockProvider writeLocks)
        {
            long bytesDeleted = 0;
            var  unused       = await writeLocks.TryExecuteAsync(record.RelativePath, 0, CancellationToken.None, async() =>
            {
                var physicalPath = PathBuilder.GetPhysicalPathFromRelativePath(record.RelativePath);
                try
                {
                    if (File.Exists(physicalPath))
                    {
                        File.Delete(physicalPath);
                        await Database.DeleteRecord(shard, record);
                        bytesDeleted = record.DiskSize;
                    }
                    else
                    {
                        await Database.DeleteRecord(shard, record);
                    }
                }
                catch (IOException ioException)
                {
                    if (physicalPath.Contains(".moving_"))
                    {
                        // We already moved it. All we can do is update the last deletion attempt
                        await Database.UpdateLastDeletionAttempt(shard, record.RelativePath, DateTime.UtcNow);
                        return;
                    }

                    var movedRelativePath = record.RelativePath + ".moving_" +
                                            new Random().Next(int.MaxValue).ToString("x", CultureInfo.InvariantCulture);
                    var movedPath = PathBuilder.GetPhysicalPathFromRelativePath(movedRelativePath);
                    try
                    {
                        //Move it so it usage will decrease and it can be deleted later
                        //TODO: This is not transactional, as the db record is written *after* the file is moved
                        //This should be split up into create and delete
                        (Options.MoveFileOverwriteFunc ?? File.Move)(physicalPath, movedPath);
                        await Database.ReplaceRelativePathAndUpdateLastDeletion(shard, record, movedRelativePath,
                                                                                DateTime.UtcNow);
                        Logger?.LogError(ioException, "HybridCache: Error deleting file, moved for eventual deletion - {Path}", record.RelativePath);
                    }
                    catch (IOException ioException2)
                    {
                        await Database.UpdateLastDeletionAttempt(shard, record.RelativePath, DateTime.UtcNow);
                        Logger?.LogError(ioException2, "HybridCache: Failed to move file for eventual deletion - {Path}", record.RelativePath);
                    }
                }
            });

            return(bytesDeleted);
        }
Пример #5
0
 public async Task DeleteRecord(ICacheDatabaseRecord oldRecord)
 {
     using (await createLock.LockAsync())
     {
         if ((await GetLoadedDict()).TryRemove(oldRecord.RelativePath, out var currentRecord))
         {
             if (currentRecord != oldRecord)
             {
                 logger?.LogError(
                     "DeleteRecord tried to delete a different instance of the record than the one provided. Re-inserting in {ShardId}", shardId);
                 (await GetLoadedDict()).TryAdd(oldRecord.RelativePath, currentRecord);
             }
             else
             {
                 await writeLog.LogDeleted(oldRecord);
             }
         }
     }
 }
 public Task LogDeleted(ICacheDatabaseRecord deletedRecord)
 {
     return(WriteLogEntry(new LogEntry(LogEntryType.Delete, deletedRecord), false));
 }
Пример #7
0
 public Task ReplaceRelativePathAndUpdateLastDeletion(int shard, ICacheDatabaseRecord record, string movedRelativePath,
                                                      DateTime lastDeletionAttempt)
 {
     return(shards[shard].ReplaceRelativePathAndUpdateLastDeletion(record, movedRelativePath, lastDeletionAttempt));
 }