protected override async Task SaveImplAsync(string dataName, ReadOnlyMemory <byte> data, bool doNotOverwrite, CancellationToken cancel = default) { string filename = MakeFileName(dataName, Options.FileExtension); string newFilename = filename + Options.TmpFileExtension; string directoryName = PathParser.GetDirectoryName(filename); Mutant?mutant = null; if (this.Options.GlobalLock) { mutant = new Mutant("Hive_GlobalLock_" + filename, false, false); } try { if (mutant != null) { await mutant.LockAsync(); } if (data.IsEmpty == false) { if (doNotOverwrite) { if (await FileSystem.IsFileExistsAsync(filename, cancel)) { throw new ApplicationException($"The file \"{filename}\" exists while doNotOverwrite flag is set."); } } try { await FileSystem.CreateDirectoryAsync(directoryName, Options.Flags, cancel); if (Options.PutGitIgnore) { Util.PutGitIgnoreFileOnDirectory(Options.RootDirectoryPath.Value); } await FileSystem.WriteDataToFileAsync(newFilename, data, Options.Flags | FileFlags.ForceClearReadOnlyOrHiddenBitsOnNeed, false, cancel); try { await FileSystem.DeleteFileAsync(filename, Options.Flags | FileFlags.ForceClearReadOnlyOrHiddenBitsOnNeed, cancel); } catch { } await FileSystem.MoveFileAsync(newFilename, filename, cancel); } finally { await FileSystem.DeleteFileAsync(newFilename, Options.Flags | FileFlags.ForceClearReadOnlyOrHiddenBitsOnNeed, cancel); } } else { if (doNotOverwrite) { throw new ApplicationException($"The file {filename} exists while doNotOverwrite flag is set."); } try { await FileSystem.DeleteFileAsync(filename, FileFlags.ForceClearReadOnlyOrHiddenBitsOnNeed, cancel); } catch { } try { await FileSystem.DeleteFileAsync(newFilename, FileFlags.ForceClearReadOnlyOrHiddenBitsOnNeed, cancel); } catch { } } } finally { if (mutant != null) { await mutant.UnlockAsync(); mutant._DisposeSafe(); } } }