Beispiel #1
0
        /// <summary>
        /// Saves the document's content to the given file path.
        /// </summary>
        public void Save(string path)
        {
            //On Windows:
            // Readers will prevent the file from being overwritten due to FileShare.Read.
            // Readers can read in parallel, but when there's contention with a writer, the retrying will kick in to resolve it.
            //On Unix:
            // FileShare.Read does nothing, but...
            // File.Replace is implemented with rename system call that will mean that even though writers can overwrite while
            // reading is happening, each reader will see file before or after overwrite, not in between

            EnsureContent();
            var tempPath = Path.Combine(Path.GetDirectoryName(path), Path.GetRandomFileName());

            using (var stream = File.Open(tempPath, FileMode.Create, FileAccess.ReadWrite, FileShare.None))
            {
                Save(stream);
            }

            ExponentialRetry.ExecuteWithRetryOnIOException(() =>
            {
                if (File.Exists(path))
                {
                    File.Replace(
                        sourceFileName: tempPath,
                        destinationFileName: path,
                        destinationBackupFileName: null,
                        ignoreMetadataErrors: true);
                }
                else
                {
                    File.Move(sourceFileName: tempPath, destFileName: path);
                }
            }, maxRetryCount: 3);
        }