From e818fa32b98dfd148e2a4e31dbf17400f5b7c655 Mon Sep 17 00:00:00 2001 From: Rob Reynolds Date: Fri, 16 Sep 2016 11:09:59 -0500 Subject: [PATCH] (GH-943) Lock Pending File Until Operation Completes Open and hold the pending file exclusively open until install is finished. Then remove the file lock. This allows for better concurrent operations when running multiple choco processes at the same time (which isn't necessarily recommended). --- .../services/ChocolateyPackageService.cs | 12 ++++++++++++ .../infrastructure.app/services/FilesService.cs | 3 ++- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/src/chocolatey/infrastructure.app/services/ChocolateyPackageService.cs b/src/chocolatey/infrastructure.app/services/ChocolateyPackageService.cs index c7726d21fa..8ccb1a4a58 100644 --- a/src/chocolatey/infrastructure.app/services/ChocolateyPackageService.cs +++ b/src/chocolatey/infrastructure.app/services/ChocolateyPackageService.cs @@ -50,6 +50,8 @@ public class ChocolateyPackageService : IChocolateyPackageService private readonly IAutomaticUninstallerService _autoUninstallerService; private readonly IXmlService _xmlService; private readonly IConfigTransformService _configTransformService; + private readonly IDictionary _pendingLocks = new Dictionary(); + private readonly IList _proBusinessMessages = new List { @" Are you ready for the ultimate experience? Check out Pro / Business! @@ -1158,6 +1160,7 @@ public void set_pending(PackageResult packageResult, ChocolateyConfiguration con var pendingFile = _fileSystem.combine_paths(packageDirectory, ApplicationParameters.PackagePendingFileName); _fileSystem.write_file(pendingFile, "{0}".format_with(packageResult.Name)); + _pendingLocks.Add(packageResult.Name.to_lower(), _fileSystem.open_file_exclusive(pendingFile)); } public void remove_pending(PackageResult packageResult, ChocolateyConfiguration config) @@ -1177,6 +1180,15 @@ public void remove_pending(PackageResult packageResult, ChocolateyConfiguration } var pendingFile = _fileSystem.combine_paths(packageDirectory, ApplicationParameters.PackagePendingFileName); + var lockName = packageResult.Name.to_lower(); + if (_pendingLocks.ContainsKey(lockName)) + { + var fileLock = _pendingLocks[lockName]; + _pendingLocks.Remove(lockName); + fileLock.Close(); + fileLock.Dispose(); + } + if (_fileSystem.file_exists(pendingFile)) _fileSystem.delete_file(pendingFile); } diff --git a/src/chocolatey/infrastructure.app/services/FilesService.cs b/src/chocolatey/infrastructure.app/services/FilesService.cs index e2dc6cea6c..8f2b40127c 100644 --- a/src/chocolatey/infrastructure.app/services/FilesService.cs +++ b/src/chocolatey/infrastructure.app/services/FilesService.cs @@ -17,6 +17,7 @@ namespace chocolatey.infrastructure.app.services { using System; using System.IO; + using System.Linq; using configuration; using cryptography; using domain; @@ -117,7 +118,7 @@ public PackageFiles capture_package_files(string directory, ChocolateyConfigurat this.Log().Debug(() => "Capturing package files in '{0}'".format_with(directory)); //gather all files in the folder var files = _fileSystem.get_files(directory, pattern: "*.*", option: SearchOption.AllDirectories); - foreach (string file in files.or_empty_list_if_null()) + foreach (string file in files.or_empty_list_if_null().Where(f => !f.EndsWith(ApplicationParameters.PackagePendingFileName))) { packageFiles.Files.Add(get_package_file(file)); }