Exemplo n.º 1
0
        /// <summary>
        /// Cleans files that failed to be deleted during previous delete or clean operations. If another thread/process is currently running a clean
        /// operation on the folder assigned to this image host, an <see cref="IOException"/> is thrown.
        /// </summary>
        /// <param name="cancellationToken">An optional cancellation token to cancel the operation.</param>
        /// <exception cref="InvalidOperationException">
        /// This image host does not support cleanup.
        /// </exception>
        /// <exception cref="IOException">
        /// Another thread/process is already running a cleaning operation on the base directory.
        /// </exception>
        public void Clean(CancellationToken cancellationToken = default)
        {
            if (CleanupDirectory == null)
            {
                throw new InvalidOperationException(CleanupNotSupportedMessage);
            }

            var        cleanLockFile = CleanupDirectory.CombineFile(".lock", PathOptions.None);
            FileStream cleanLock;

            try {
                cleanLock = cleanLockFile.OpenStream(FileMode.OpenOrCreate, options: FileOptions.DeleteOnClose);
            }
            catch (IOException ex) {
                throw new IOException($"Could not obtain a lock on '{cleanLockFile.PathDisplay}'. Another thread or process may be cleaning right now.", ex);
            }

            using (cleanLock)
            {
                foreach (var cleanupRecord in CleanupDirectory.GetChildFiles("*.delete"))
                {
                    if (cancellationToken.IsCancellationRequested)
                    {
                        throw new OperationCanceledException(cancellationToken);
                    }

                    var imageId = Guid.Parse(cleanupRecord.NameWithoutExtension);

                    try {
                        DeleteWithAggregateThrow(imageId);
                    }
                    catch (AggregateException ex) {
                        using var fs = cleanupRecord.OpenStream(FileMode.Truncate);
                        using var sw = new StreamWriter(fs);

                        WriteCleanupRecord(sw, "IMAGE FILE CLEANUP FAILED", ex);
                        continue;
                    }

                    try {
                        cleanupRecord.Delete();
                    }
                    catch (FileNotFoundException) { }
                    catch (Exception ex) {
                        try {
                            const string header = "CLEANUP RECORD REMOVAL FAILED";

                            using var fs = cleanupRecord.OpenStream(FileMode.Truncate);
                            using var sw = new StreamWriter(fs);

                            WriteCleanupRecord(sw, header, ex);
                        }
                        catch (FileNotFoundException) { }
                    }
                }
            }
        }
Exemplo n.º 2
0
        private CleanupDirectory ReadCleanupDirectory(XElement item)
        {
            CleanupDirectory result = new CleanupDirectory
            {
                LocalDirectory = XElementExtender.ReadPath(item)
            };

            OutputConsole.PrintVerbose(result, 5);
            return(result);
        }
Exemplo n.º 3
0
        /// <summary>
        /// Initializes a new instance of the <see cref="ImageHost"/> class.
        /// </summary>
        /// <param name="baseDirectory">The base directory path where images are stored. Multiple image host instances (either in the same process or in
        /// different processes) can safely share the same directory but it should not be used by anything other than image hosts.</param>
        /// <param name="options">Options for configuring the image host.</param>
        public ImageHost(IAbsoluteDirectoryPath baseDirectory, ImageHostOptions options)
        {
            if (_jpegEncoder == null)
            {
                throw new InvalidOperationException("JPEG encoder was not found.");
            }

            BaseDirectory     = baseDirectory;
            DeleteFailureMode = options.DeleteFailureMode;

            BaseDirectory.Create();

            if (options.DeleteFailureMode == DeleteFailureMode.WriteCleanupRecord)
            {
                CleanupDirectory = baseDirectory.CombineDirectory(".cleanup", PathOptions.None);
                CleanupDirectory.Create();
            }
        }
Exemplo n.º 4
0
 /// <summary>
 /// Gets a value indicating whether there are files that need to be cleaned up. This method is thread-safe.
 /// </summary>
 public bool NeedsCleaning()
 {
     return(CleanupDirectory != null?
            CleanupDirectory.GetChildFiles("*.delete").Any() :
                throw new InvalidOperationException("Cleanup is not supported."));
 }