From: LoRd_MuldeR Date: Sun, 3 Apr 2022 12:58:59 +0000 (+0200) Subject: Added support for setting the number threads in the GUI + some improvements applicati... X-Git-Tag: 1.2.0~11 X-Git-Url: http://git.osdn.net/view?a=commitdiff_plain;h=45829c43170284e1de7b4338c56b985c4e22f51c;p=slunkcrypt%2FSlunkCrypt.git Added support for setting the number threads in the GUI + some improvements application configuration handling. --- diff --git a/README.md b/README.md index fb0f434..4c3d6b9 100644 --- a/README.md +++ b/README.md @@ -55,6 +55,11 @@ The following settings can be adjusted in the `slunkcrypt-gui.exe.config` config - **`DisableBusyIndicator`:** If set to `true`, the “busy indicator” animation will be *disabled* on application startup — default value: `false`. +- **`ThreadCount`:** + Specifies the number of worker threads to use — default value: `0` (i.e. detect the number of available processors and create one thread for each processor). + +- **`KeepIncompleteFiles`:** + If set to `true`, incomplete or corrupted output files will *not* be deleted — default value: `false`. Command-line Usage ================== diff --git a/gui/App.config b/gui/App.config index 58e53ce..4e4ea08 100644 --- a/gui/App.config +++ b/gui/App.config @@ -1,9 +1,11 @@ - + + + diff --git a/gui/Process/SlunkCryptRunner.cs b/gui/Process/SlunkCryptRunner.cs index af78ccd..5229f7f 100644 --- a/gui/Process/SlunkCryptRunner.cs +++ b/gui/Process/SlunkCryptRunner.cs @@ -19,6 +19,17 @@ namespace com.muldersoft.slunkcrypt.gui.process { public enum Mode { Encrypt, Decrypt } + public struct SlunkOptions + { + public SlunkOptions(bool keepIncompleteFiles, int threadCount) + { + this.keepIncompleteFiles = keepIncompleteFiles; + this.threadCount = threadCount; + } + public readonly bool keepIncompleteFiles; + public readonly int threadCount; + } + private const string COMMAND_ENCRYPT = "-e"; private const string COMMAND_DECRYPT = "-d"; @@ -39,12 +50,13 @@ namespace com.muldersoft.slunkcrypt.gui.process // Public methods // ============================================================================= - public async Task ExecuteAsync(Mode mode, string inputFile, string outputFile, string password) + public async Task ExecuteAsync(Mode mode, string inputFile, string outputFile, string password, SlunkOptions? options = null) { Dictionary environmentVariables = new Dictionary(); environmentVariables.Add("SLUNK_PASSPHRASE", password); - string[] arguments = new string[] { GetCommandString(mode), inputFile, outputFile }; - return await ExecAsnyc(m_executableFile.Name, arguments, environmentVariables); + environmentVariables.Add("SLUNK_KEEP_INCOMPLETE", Convert.ToInt32(options.HasValue ? options.Value.keepIncompleteFiles : false).ToString()); + environmentVariables.Add("SLUNK_THREADS", Math.Max(0, Math.Min(32, options.HasValue ? options.Value.threadCount : 0)).ToString()); + return await ExecAsnyc(m_executableFile.Name, new string[] { GetCommandLineModeString(mode), inputFile, outputFile }, environmentVariables); } public override void Dispose() @@ -94,7 +106,7 @@ namespace com.muldersoft.slunkcrypt.gui.process return false; } - private static string GetCommandString(Mode mode) + private static string GetCommandLineModeString(Mode mode) { switch(mode) { diff --git a/gui/SlunkCryptGUI.xaml.cs b/gui/SlunkCryptGUI.xaml.cs index fdf593c..5d8249f 100644 --- a/gui/SlunkCryptGUI.xaml.cs +++ b/gui/SlunkCryptGUI.xaml.cs @@ -556,8 +556,11 @@ namespace com.muldersoft.slunkcrypt.gui Button_Decrypt_Toggle.IsChecked = Button_Encrypt_Toggle.IsChecked = m_checksumError = m_processReceived = false; if (!await processor(inputFile, outputFile, password)) { + if (!m_config.KeepIncompleteFiles) + { + PathUtils.TryRemoveFile(outputFile); + } SetProgress(double.NaN, true); - PathUtils.TryRemoveFile(outputFile); } await Task.Yield(); } @@ -624,12 +627,13 @@ namespace com.muldersoft.slunkcrypt.gui } try { + SlunkCryptRunner.SlunkOptions options = new SlunkCryptRunner.SlunkOptions(m_config.KeepIncompleteFiles, m_config.ThreadCount); using (m_processRunner = new SlunkCryptRunner(Dispatcher)) { m_processRunner.OutputAvailable += Process_OutputAvailable; m_processRunner.ProgressChanged += Porcess_ProgressChanged; SetProcessPriority(ProcessPriorityClass.AboveNormal); - return await m_processRunner.ExecuteAsync(mode, inputFile, outputFile, password); + return await m_processRunner.ExecuteAsync(mode, inputFile, outputFile, password, options); } } catch (ProcessRunner.ProcessStartException err) diff --git a/gui/Utilities/ApplicationConfig.cs b/gui/Utilities/ApplicationConfig.cs index 6706b13..02fb722 100644 --- a/gui/Utilities/ApplicationConfig.cs +++ b/gui/Utilities/ApplicationConfig.cs @@ -4,62 +4,138 @@ /******************************************************************************/ using System; +using System.Collections.Concurrent; using System.Configuration; +using System.Threading; namespace com.muldersoft.slunkcrypt.gui.utils { class ApplicationConfig { - private readonly Lazy m_settings = new Lazy(InitializeSettings); + private readonly ConcurrentDictionary m_cache = new ConcurrentDictionary(); public bool DisableBusyIndicator { get { - return GetConfigValueAsBool("DisableBusyIndicator"); + return ComputeIfAbsent("DisableBusyIndicator", (key) => AppConfHelper.GetConfigValueAsBool(key).GetValueOrDefault(false)); + } + } + + public bool KeepIncompleteFiles + { + get + { + return ComputeIfAbsent("KeepIncompleteFiles", (key) => AppConfHelper.GetConfigValueAsBool(key).GetValueOrDefault(false)); } } - protected string GetConfigValue(string name) + public int ThreadCount { - KeyValueConfigurationCollection settings = m_settings.Value; - if (!ReferenceEquals(settings, null)) + get { - KeyValueConfigurationElement element = settings[name]; - if (!ReferenceEquals(element, null)) - { - string value = element.Value; - return string.IsNullOrWhiteSpace(value) ? string.Empty : value; - } + return ComputeIfAbsent("ThreadCount", (key) => AppConfHelper.GetConfigValueAsInt32(key).GetValueOrDefault(0)); } - return string.Empty; } - protected bool GetConfigValueAsBool(string name) + // ============================================================================= + // Internal methods + // ============================================================================= + + protected int ComputeIfAbsent(string name, Func valueFactory) { - string value; - if (!string.IsNullOrWhiteSpace(value = GetConfigValue(name))) + return m_cache.GetOrAdd(name, valueFactory); + } + + protected bool ComputeIfAbsent(string name, Func valueFactory) + { + return Convert.ToBoolean(m_cache.GetOrAdd(name, (key) => Convert.ToInt32(valueFactory(key)))); + } + + // ============================================================================= + // Helper class + // ============================================================================= + + private static class AppConfHelper + { + private static readonly Lazy m_settings = new Lazy(InitializeSettings, LazyThreadSafetyMode.ExecutionAndPublication); + + private static volatile object m_syncRoot; + + public static string GetConfigValue(string name) { - bool result; - if (bool.TryParse(value.Trim(), out result)) + KeyValueConfigurationCollection settings = m_settings.Value; + if (!ReferenceEquals(settings, null)) { - return result; + lock (settings.SyncRoot ?? SyncRootInstance) + { + try + { + KeyValueConfigurationElement element = settings[name]; + if (!ReferenceEquals(element, null)) + { + string value = element.Value; + return string.IsNullOrWhiteSpace(value) ? string.Empty : value; + } + } + catch { } + } } + return string.Empty; } - return false; - } - private static KeyValueConfigurationCollection InitializeSettings() - { - try + public static bool? GetConfigValueAsBool(string name) { - Configuration configuration = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None); - return configuration.AppSettings.Settings; + string value; + if (!string.IsNullOrWhiteSpace(value = GetConfigValue(name))) + { + bool result; + if (bool.TryParse(value.Trim(), out result)) + { + return result; + } + } + return null; } - catch + + public static int? GetConfigValueAsInt32(string name) { + string value; + if (!string.IsNullOrWhiteSpace(value = GetConfigValue(name))) + { + int result; + if (int.TryParse(value.Trim(), out result)) + { + return result; + } + } return null; } + + private static KeyValueConfigurationCollection InitializeSettings() + { + try + { + Configuration configuration = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None); + return configuration.AppSettings.Settings; + } + catch + { + return null; + } + } + + private static object SyncRootInstance + { + get + { + if (m_syncRoot == null) + { + Interlocked.CompareExchange(ref m_syncRoot, new object(), null); + } + return m_syncRoot; + } + } } } } diff --git a/gui/Utilities/ProcessRunner.cs b/gui/Utilities/ProcessRunner.cs index ea55985..7ffd8e3 100644 --- a/gui/Utilities/ProcessRunner.cs +++ b/gui/Utilities/ProcessRunner.cs @@ -226,7 +226,7 @@ namespace com.muldersoft.slunkcrypt.gui.utils { process.StartInfo.FileName = executablePath; process.StartInfo.Arguments = CreateArgumentList(arguments); - SetupEnvironment(process.StartInfo.EnvironmentVariables, environmentVariables); + SetupEnvironment(process.StartInfo.EnvironmentVariables, executablePath, environmentVariables); process.StartInfo.WorkingDirectory = AppDomain.CurrentDomain.BaseDirectory; process.Start(); SetProcessPriority(process, priorityClass); @@ -390,13 +390,15 @@ namespace com.muldersoft.slunkcrypt.gui.utils return false; } - private static void SetupEnvironment(StringDictionary dictionary, IReadOnlyDictionary environmentVariables) + private static void SetupEnvironment(StringDictionary dictionary, string executablePath, IReadOnlyDictionary environmentVariables) { + string baseDirectory = Path.GetDirectoryName(executablePath); + dictionary["PATH"] = string.IsNullOrEmpty(baseDirectory) ? Environment.SystemDirectory : baseDirectory; if (!ReferenceEquals(environmentVariables, null)) { foreach (KeyValuePair entry in environmentVariables) { - dictionary.Add(entry.Key, entry.Value); + dictionary[entry.Key] = entry.Value; } } } diff --git a/libslunkcrypt/src/thread.c b/libslunkcrypt/src/thread.c index cda59b9..89ac88e 100644 --- a/libslunkcrypt/src/thread.c +++ b/libslunkcrypt/src/thread.c @@ -15,6 +15,7 @@ /* CRT */ #include +#include #include /* PThread */ @@ -80,9 +81,10 @@ static INLINE size_t BOUND(const size_t min, const size_t value, const size_t ma #define PTHRD_MUTEX_ENTER(X) do \ { \ - if (pthread_mutex_lock((X)) != 0) \ + int _retval; \ + while ((_retval = pthread_mutex_trylock((X))) != 0) \ { \ - abort(); \ + if (_retval != EBUSY) { abort(); } \ } \ } \ while(0)