private static (FullPath path, FullPath innerPath, Stream lockFile) CreateUniqueDirectory(FullPath folderPath) { /* * Structure * - temp/<folder>/lock => allows to detect concurrency * - temp/<folder>/<returned_value>/ */ var count = 1; while (true) { Stream?lockFileStream = null; try { var tempPath = folderPath.Value + "_"; while (Directory.Exists(folderPath)) { folderPath = FullPath.FromPath(tempPath + count.ToString(CultureInfo.InvariantCulture)); if (count == int.MaxValue) { throw new InvalidOperationException("Cannot create a temporary directory"); } count++; } Directory.CreateDirectory(folderPath); var lockFilePath = folderPath / LockFileName; lockFileStream = new FileStream(lockFilePath, FileMode.CreateNew, FileAccess.ReadWrite, FileShare.None); var innerFolderPath = folderPath / DirectoryName; if (Directory.Exists(innerFolderPath)) { lockFileStream.Dispose(); continue; } Directory.CreateDirectory(innerFolderPath); // Assert folder is empty if (Directory.EnumerateFileSystemEntries(innerFolderPath).Any()) { lockFileStream.Dispose(); continue; } return(folderPath, innerFolderPath, lockFileStream); } catch (IOException) { // The folder may already in use } catch { lockFileStream?.Dispose(); throw; } lockFileStream?.Dispose(); } }
private TemporaryDirectory(FullPath path, FullPath innerPath, Stream lockFile) { _path = path; FullPath = innerPath; _lockFile = lockFile; }