OSDN Git Service

Added support for setting the number threads in the GUI + some improvements applicati...
authorLoRd_MuldeR <mulder2@gmx.de>
Sun, 3 Apr 2022 12:58:59 +0000 (14:58 +0200)
committerLoRd_MuldeR <mulder2@gmx.de>
Sun, 3 Apr 2022 17:23:58 +0000 (19:23 +0200)
README.md
gui/App.config
gui/Process/SlunkCryptRunner.cs
gui/SlunkCryptGUI.xaml.cs
gui/Utilities/ApplicationConfig.cs
gui/Utilities/ProcessRunner.cs
libslunkcrypt/src/thread.c

index fb0f434..4c3d6b9 100644 (file)
--- 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 &mdash; default value: `false`.
 
+- **`ThreadCount`:**  
+  Specifies the number of worker threads to use &mdash; 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 &mdash; default value: `false`.
 
 Command-line Usage
 ==================
index 58e53ce..4e4ea08 100644 (file)
@@ -1,9 +1,11 @@
 <?xml version="1.0" encoding="utf-8"?>
 <configuration>
-    <startup> 
+    <startup>
         <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5.2"/>
     </startup>
     <appSettings>
         <add key="DisableBusyIndicator" value="false"/>
+        <add key="ThreadCount" value="0"/>
+        <add key="KeepIncompleteFiles" value="false"/>
     </appSettings>
 </configuration>
index af78ccd..5229f7f 100644 (file)
@@ -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<int> ExecuteAsync(Mode mode, string inputFile, string outputFile, string password)
+        public async Task<int> ExecuteAsync(Mode mode, string inputFile, string outputFile, string password, SlunkOptions? options = null)
         {
             Dictionary<string, string> environmentVariables = new Dictionary<string, string>();
             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)
             {
index fdf593c..5d8249f 100644 (file)
@@ -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)
index 6706b13..02fb722 100644 (file)
 /******************************************************************************/
 
 using System;
+using System.Collections.Concurrent;
 using System.Configuration;
+using System.Threading;
 
 namespace com.muldersoft.slunkcrypt.gui.utils
 {
     class ApplicationConfig
     {
-        private readonly Lazy<KeyValueConfigurationCollection> m_settings = new Lazy<KeyValueConfigurationCollection>(InitializeSettings);
+        private readonly ConcurrentDictionary<string, int> m_cache = new ConcurrentDictionary<string, int>();
 
         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<string, int> valueFactory)
         {
-            string value;
-            if (!string.IsNullOrWhiteSpace(value = GetConfigValue(name)))
+            return m_cache.GetOrAdd(name, valueFactory);
+        }
+
+        protected bool ComputeIfAbsent(string name, Func<string, bool> valueFactory)
+        {
+            return Convert.ToBoolean(m_cache.GetOrAdd(name, (key) => Convert.ToInt32(valueFactory(key))));
+        }
+
+        // =============================================================================
+        // Helper class
+        // =============================================================================
+
+        private static class AppConfHelper
+        {
+            private static readonly Lazy<KeyValueConfigurationCollection> m_settings = new Lazy<KeyValueConfigurationCollection>(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<object>(ref m_syncRoot, new object(), null);
+                    }
+                    return m_syncRoot;
+                }
+            }
         }
     }
 }
index ea55985..7ffd8e3 100644 (file)
@@ -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<string, string> environmentVariables)
+        private static void SetupEnvironment(StringDictionary dictionary, string executablePath, IReadOnlyDictionary<string, string> environmentVariables)
         {
+            string baseDirectory = Path.GetDirectoryName(executablePath);
+            dictionary["PATH"] = string.IsNullOrEmpty(baseDirectory) ? Environment.SystemDirectory : baseDirectory;
             if (!ReferenceEquals(environmentVariables, null))
             {
                 foreach (KeyValuePair<string, string> entry in environmentVariables)
                 {
-                    dictionary.Add(entry.Key, entry.Value);
+                    dictionary[entry.Key] = entry.Value;
                 }
             }
         }
index cda59b9..89ac88e 100644 (file)
@@ -15,6 +15,7 @@
 
 /* CRT */
 #include <stdlib.h>
+#include <errno.h>
 #include <string.h>
 
 /* 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)