From 82106c1c8b8b02d39ab43d3245b1b5cabefa8f39 Mon Sep 17 00:00:00 2001 From: qianlifeng Date: Mon, 15 Dec 2014 22:58:49 +0800 Subject: [PATCH] fix #185. Loading index cache on startup. --- Wox.Infrastructure/Storage/BaseStorage.cs | 86 ++++++++++--------- Wox.Infrastructure/Storage/BinaryStorage.cs | 45 ++++++++++ Wox.Infrastructure/Storage/IStorage.cs | 13 +++ Wox.Infrastructure/Storage/JsonStrorage.cs | 46 ++++++++++ .../Storage/UserSelectedRecordStorage.cs | 2 +- .../Storage/UserSettings/FolderLink.cs | 16 ++-- .../UserSettings/UserSettingStorage.cs | 6 +- Wox.Infrastructure/Timeit.cs | 26 ++++++ Wox.Infrastructure/Wox.Infrastructure.csproj | 4 + Wox.Plugin.SystemPlugins/CMD/CMDStorage.cs | 2 +- .../Program/IProgramSource.cs | 1 + Wox.Plugin.SystemPlugins/Program/Program.cs | 2 + .../Program/ProgramCacheStorage.cs | 18 ++++ .../ProgramSources/AppPathsProgramSource.cs | 4 +- .../CommonStartMenuProgramSource.cs | 1 + .../ProgramSources/FileSystemProgramSource.cs | 1 + .../UserStartMenuProgramSource.cs | 1 + Wox.Plugin.SystemPlugins/Program/Programs.cs | 12 +++ .../Wox.Plugin.SystemPlugins.csproj | 1 + Wox.sln | 2 +- 20 files changed, 233 insertions(+), 56 deletions(-) create mode 100644 Wox.Infrastructure/Storage/BinaryStorage.cs create mode 100644 Wox.Infrastructure/Storage/IStorage.cs create mode 100644 Wox.Infrastructure/Storage/JsonStrorage.cs create mode 100644 Wox.Infrastructure/Timeit.cs create mode 100644 Wox.Plugin.SystemPlugins/Program/ProgramCacheStorage.cs diff --git a/Wox.Infrastructure/Storage/BaseStorage.cs b/Wox.Infrastructure/Storage/BaseStorage.cs index f19065c44..d899cb690 100644 --- a/Wox.Infrastructure/Storage/BaseStorage.cs +++ b/Wox.Infrastructure/Storage/BaseStorage.cs @@ -2,90 +2,92 @@ using System.Collections.Generic; using System.IO; using System.Linq; +using System.Runtime.InteropServices.ComTypes; using System.Text; using System.Windows.Forms; using Newtonsoft.Json; namespace Wox.Infrastructure.Storage { - public abstract class BaseStorage where T : class, new() + [Serializable] + public abstract class BaseStorage : IStorage where T : class,IStorage,new() { - private string configFolder = Path.Combine(Path.GetDirectoryName(Application.ExecutablePath), "Config"); - private string fileSuffix = ".json"; - private static object locker = new object(); - private static T storage; + private readonly string configFolder = Path.Combine(Path.GetDirectoryName(Application.ExecutablePath), "Config"); - public event Action AfterLoadConfig; - - protected virtual void OnAfterLoadConfig(T obj) + protected string ConfigPath { - Action handler = AfterLoadConfig; - if (handler != null) handler(obj); + get + { + return Path.Combine(configFolder, ConfigName + FileSuffix); + } } + + protected abstract string FileSuffix { get; } protected abstract string ConfigName { get; } + private static object locker = new object(); + protected static T serializedObject; + + public event Action AfterLoad; + + protected virtual void OnAfterLoad(T obj) + { + Action handler = AfterLoad; + if (handler != null) handler(obj); + } + public static T Instance { get { - if (storage == null) + if (serializedObject == null) { lock (locker) { - if (storage == null) + if (serializedObject == null) { - storage = new T(); - (storage as BaseStorage).Load(); + serializedObject = new T(); + serializedObject.Load(); } } } - return storage; + return serializedObject; } } - protected virtual T LoadDefaultConfig() + /// + /// if loading storage failed, we will try to load default + /// + /// + protected virtual T LoadDefault() { - return storage; + return serializedObject; } - private void Load() + protected abstract void LoadInternal(); + protected abstract void SaveInternal(); + + public void Load() { - string configPath = Path.Combine(configFolder, ConfigName + fileSuffix); - if (!File.Exists(configPath)) + if (!File.Exists(ConfigPath)) { if (!Directory.Exists(configFolder)) + { Directory.CreateDirectory(configFolder); - File.Create(configPath).Close(); - } - string json = File.ReadAllText(configPath); - if (!string.IsNullOrEmpty(json)) - { - try - { - storage = JsonConvert.DeserializeObject(json); - } - catch (Exception) - { - storage = LoadDefaultConfig(); } + File.Create(ConfigPath).Close(); } - else - { - storage = LoadDefaultConfig(); - } - OnAfterLoadConfig(storage); + LoadInternal(); + OnAfterLoad(serializedObject); } public void Save() { lock (locker) { - //json is a good choise, readable and flexiable - string configPath = Path.Combine(configFolder, ConfigName + fileSuffix); - string json = JsonConvert.SerializeObject(storage, Formatting.Indented); - File.WriteAllText(configPath, json); + SaveInternal(); } } } -} +} \ No newline at end of file diff --git a/Wox.Infrastructure/Storage/BinaryStorage.cs b/Wox.Infrastructure/Storage/BinaryStorage.cs new file mode 100644 index 000000000..a04434c80 --- /dev/null +++ b/Wox.Infrastructure/Storage/BinaryStorage.cs @@ -0,0 +1,45 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Runtime.Serialization.Formatters.Binary; +using System.Text; + +namespace Wox.Infrastructure.Storage +{ + /// + /// Stroage object using binary data + /// Normally, it has better performance, but not readable + /// + [Serializable] + public abstract class BinaryStorage : BaseStorage where T : class, IStorage, new() + { + protected override string FileSuffix + { + get { return ".dat"; } + } + + protected override void LoadInternal() + { + try + { + FileStream fileStream = new FileStream(ConfigPath, FileMode.Open, FileAccess.Read, FileShare.Read); + BinaryFormatter binaryFormatter = new BinaryFormatter(); + serializedObject = binaryFormatter.Deserialize(fileStream) as T; + fileStream.Close(); + } + catch (Exception) + { + serializedObject = LoadDefault(); + } + } + + protected override void SaveInternal() + { + FileStream fileStream = new FileStream(ConfigPath, FileMode.Create); + BinaryFormatter binaryFormatter = new BinaryFormatter(); + binaryFormatter.Serialize(fileStream, serializedObject); + fileStream.Close(); + } + } +} diff --git a/Wox.Infrastructure/Storage/IStorage.cs b/Wox.Infrastructure/Storage/IStorage.cs new file mode 100644 index 000000000..bb94306f1 --- /dev/null +++ b/Wox.Infrastructure/Storage/IStorage.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace Wox.Infrastructure.Storage +{ + public interface IStorage + { + void Load(); + void Save(); + } +} diff --git a/Wox.Infrastructure/Storage/JsonStrorage.cs b/Wox.Infrastructure/Storage/JsonStrorage.cs new file mode 100644 index 000000000..4a4525bd3 --- /dev/null +++ b/Wox.Infrastructure/Storage/JsonStrorage.cs @@ -0,0 +1,46 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using Newtonsoft.Json; + +namespace Wox.Infrastructure.Storage +{ + /// + /// Serialize object using json format. + /// + public abstract class JsonStrorage : BaseStorage where T : class, IStorage, new() + { + protected override string FileSuffix + { + get { return ".json"; } + } + + protected override void LoadInternal() + { + string json = File.ReadAllText(ConfigPath); + if (!string.IsNullOrEmpty(json)) + { + try + { + serializedObject = JsonConvert.DeserializeObject(json); + } + catch (Exception) + { + serializedObject = LoadDefault(); + } + } + else + { + serializedObject = LoadDefault(); + } + } + + protected override void SaveInternal() + { + string json = JsonConvert.SerializeObject(serializedObject, Formatting.Indented); + File.WriteAllText(ConfigPath, json); + } + } +} diff --git a/Wox.Infrastructure/Storage/UserSelectedRecordStorage.cs b/Wox.Infrastructure/Storage/UserSelectedRecordStorage.cs index 9c0c77d40..0b21e320e 100644 --- a/Wox.Infrastructure/Storage/UserSelectedRecordStorage.cs +++ b/Wox.Infrastructure/Storage/UserSelectedRecordStorage.cs @@ -8,7 +8,7 @@ using Wox.Plugin; namespace Wox.Infrastructure.Storage { - public class UserSelectedRecordStorage : BaseStorage + public class UserSelectedRecordStorage : JsonStrorage { [JsonProperty] private Dictionary records = new Dictionary(); diff --git a/Wox.Infrastructure/Storage/UserSettings/FolderLink.cs b/Wox.Infrastructure/Storage/UserSettings/FolderLink.cs index a31151750..69bb68b87 100644 --- a/Wox.Infrastructure/Storage/UserSettings/FolderLink.cs +++ b/Wox.Infrastructure/Storage/UserSettings/FolderLink.cs @@ -4,14 +4,16 @@ using System.Linq; using System.Text; using Newtonsoft.Json; -namespace Wox.Infrastructure.Storage.UserSettings { - public class FolderLink { +namespace Wox.Infrastructure.Storage.UserSettings +{ + public class FolderLink + { [JsonProperty] - public string Path { get; set; } + public string Path { get; set; } - public string Nickname - { - get { return Path.Split(new char[] { System.IO.Path.DirectorySeparatorChar }, StringSplitOptions.None).Last(); } - } + public string Nickname + { + get { return Path.Split(new char[] { System.IO.Path.DirectorySeparatorChar }, StringSplitOptions.None).Last(); } + } } } diff --git a/Wox.Infrastructure/Storage/UserSettings/UserSettingStorage.cs b/Wox.Infrastructure/Storage/UserSettings/UserSettingStorage.cs index dbef1b084..6f82703e1 100644 --- a/Wox.Infrastructure/Storage/UserSettings/UserSettingStorage.cs +++ b/Wox.Infrastructure/Storage/UserSettings/UserSettingStorage.cs @@ -6,7 +6,7 @@ using Newtonsoft.Json; namespace Wox.Infrastructure.Storage.UserSettings { - public class UserSettingStorage : BaseStorage + public class UserSettingStorage : JsonStrorage { [JsonProperty] public bool DontPromptUpdateMsg { get; set; } @@ -146,7 +146,7 @@ namespace Wox.Infrastructure.Storage.UserSettings get { return "config"; } } - protected override UserSettingStorage LoadDefaultConfig() + protected override UserSettingStorage LoadDefault() { DontPromptUpdateMsg = false; Theme = "Dark"; @@ -165,7 +165,7 @@ namespace Wox.Infrastructure.Storage.UserSettings return this; } - protected override void OnAfterLoadConfig(UserSettingStorage storage) + protected override void OnAfterLoad(UserSettingStorage storage) { if (storage.CustomizedPluginConfigs == null) { diff --git a/Wox.Infrastructure/Timeit.cs b/Wox.Infrastructure/Timeit.cs new file mode 100644 index 000000000..5b020ac8c --- /dev/null +++ b/Wox.Infrastructure/Timeit.cs @@ -0,0 +1,26 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Text; + +namespace Wox.Infrastructure +{ + public class Timeit : IDisposable + { + private Stopwatch stopwatch = new Stopwatch(); + private string name; + + public Timeit(string name) + { + this.name = name; + stopwatch.Start(); + } + + public void Dispose() + { + stopwatch.Stop(); + Debug.WriteLine(name + ":" + stopwatch.ElapsedMilliseconds + "ms"); + } + } +} diff --git a/Wox.Infrastructure/Wox.Infrastructure.csproj b/Wox.Infrastructure/Wox.Infrastructure.csproj index df363b742..442f0561a 100644 --- a/Wox.Infrastructure/Wox.Infrastructure.csproj +++ b/Wox.Infrastructure/Wox.Infrastructure.csproj @@ -58,8 +58,12 @@ + + + + diff --git a/Wox.Plugin.SystemPlugins/CMD/CMDStorage.cs b/Wox.Plugin.SystemPlugins/CMD/CMDStorage.cs index d76202755..cfb3a5ddc 100644 --- a/Wox.Plugin.SystemPlugins/CMD/CMDStorage.cs +++ b/Wox.Plugin.SystemPlugins/CMD/CMDStorage.cs @@ -7,7 +7,7 @@ using Wox.Infrastructure.Storage; namespace Wox.Plugin.SystemPlugins.CMD { - public class CMDStorage : BaseStorage + public class CMDStorage : JsonStrorage { [JsonProperty] public Dictionary CMDHistory = new Dictionary(); diff --git a/Wox.Plugin.SystemPlugins/Program/IProgramSource.cs b/Wox.Plugin.SystemPlugins/Program/IProgramSource.cs index f2443c46f..edaebc821 100644 --- a/Wox.Plugin.SystemPlugins/Program/IProgramSource.cs +++ b/Wox.Plugin.SystemPlugins/Program/IProgramSource.cs @@ -11,6 +11,7 @@ namespace Wox.Plugin.SystemPlugins.Program int BonusPoints { get; set; } } + [Serializable] public abstract class AbstractProgramSource : IProgramSource { public abstract List LoadPrograms(); diff --git a/Wox.Plugin.SystemPlugins/Program/Program.cs b/Wox.Plugin.SystemPlugins/Program/Program.cs index 8148e3cbb..bcef7c422 100644 --- a/Wox.Plugin.SystemPlugins/Program/Program.cs +++ b/Wox.Plugin.SystemPlugins/Program/Program.cs @@ -1,7 +1,9 @@ +using System; using Wox.Infrastructure; namespace Wox.Plugin.SystemPlugins.Program { + [Serializable] public class Program { private static readonly global::System.Text.RegularExpressions.Regex AbbrRegexp = new global::System.Text.RegularExpressions.Regex("[^A-Z0-9]", global::System.Text.RegularExpressions.RegexOptions.Compiled); diff --git a/Wox.Plugin.SystemPlugins/Program/ProgramCacheStorage.cs b/Wox.Plugin.SystemPlugins/Program/ProgramCacheStorage.cs new file mode 100644 index 000000000..8c28ab722 --- /dev/null +++ b/Wox.Plugin.SystemPlugins/Program/ProgramCacheStorage.cs @@ -0,0 +1,18 @@ +using System; +using System.Collections.Generic; +using Newtonsoft.Json; +using Wox.Infrastructure.Storage; + +namespace Wox.Plugin.SystemPlugins.Program +{ + [Serializable] + public class ProgramCacheStorage : BinaryStorage + { + public List Programs = new List(); + + protected override string ConfigName + { + get { return "ProgramIndexCache"; } + } + } +} \ No newline at end of file diff --git a/Wox.Plugin.SystemPlugins/Program/ProgramSources/AppPathsProgramSource.cs b/Wox.Plugin.SystemPlugins/Program/ProgramSources/AppPathsProgramSource.cs index 1cc37b874..e6c67cc70 100644 --- a/Wox.Plugin.SystemPlugins/Program/ProgramSources/AppPathsProgramSource.cs +++ b/Wox.Plugin.SystemPlugins/Program/ProgramSources/AppPathsProgramSource.cs @@ -1,8 +1,10 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; using Wox.Infrastructure.Storage.UserSettings; namespace Wox.Plugin.SystemPlugins.Program.ProgramSources { + [Serializable] [global::System.ComponentModel.Browsable(false)] public class AppPathsProgramSource: AbstractProgramSource { diff --git a/Wox.Plugin.SystemPlugins/Program/ProgramSources/CommonStartMenuProgramSource.cs b/Wox.Plugin.SystemPlugins/Program/ProgramSources/CommonStartMenuProgramSource.cs index 67910e262..bbad13756 100644 --- a/Wox.Plugin.SystemPlugins/Program/ProgramSources/CommonStartMenuProgramSource.cs +++ b/Wox.Plugin.SystemPlugins/Program/ProgramSources/CommonStartMenuProgramSource.cs @@ -5,6 +5,7 @@ using Wox.Infrastructure.Storage.UserSettings; namespace Wox.Plugin.SystemPlugins.Program.ProgramSources { + [Serializable] [global::System.ComponentModel.Browsable(false)] public class CommonStartMenuProgramSource : FileSystemProgramSource { diff --git a/Wox.Plugin.SystemPlugins/Program/ProgramSources/FileSystemProgramSource.cs b/Wox.Plugin.SystemPlugins/Program/ProgramSources/FileSystemProgramSource.cs index 5f127b8b2..831bb5db4 100644 --- a/Wox.Plugin.SystemPlugins/Program/ProgramSources/FileSystemProgramSource.cs +++ b/Wox.Plugin.SystemPlugins/Program/ProgramSources/FileSystemProgramSource.cs @@ -9,6 +9,7 @@ using Log = Wox.Infrastructure.Logger.Log; namespace Wox.Plugin.SystemPlugins.Program.ProgramSources { + [Serializable] public class FileSystemProgramSource : AbstractProgramSource { private string baseDirectory; diff --git a/Wox.Plugin.SystemPlugins/Program/ProgramSources/UserStartMenuProgramSource.cs b/Wox.Plugin.SystemPlugins/Program/ProgramSources/UserStartMenuProgramSource.cs index 5ee04c376..b467fc46b 100644 --- a/Wox.Plugin.SystemPlugins/Program/ProgramSources/UserStartMenuProgramSource.cs +++ b/Wox.Plugin.SystemPlugins/Program/ProgramSources/UserStartMenuProgramSource.cs @@ -3,6 +3,7 @@ using Wox.Infrastructure.Storage.UserSettings; namespace Wox.Plugin.SystemPlugins.Program.ProgramSources { + [Serializable] [global::System.ComponentModel.Browsable(false)] public class UserStartMenuProgramSource : FileSystemProgramSource { diff --git a/Wox.Plugin.SystemPlugins/Program/Programs.cs b/Wox.Plugin.SystemPlugins/Program/Programs.cs index 649ce9acd..9e0eb7ad4 100644 --- a/Wox.Plugin.SystemPlugins/Program/Programs.cs +++ b/Wox.Plugin.SystemPlugins/Program/Programs.cs @@ -1,7 +1,11 @@ using System; using System.Collections.Generic; +using System.Diagnostics; +using System.IO; using System.Linq; using System.Reflection; +using System.Runtime.Serialization.Formatters.Binary; +using System.Windows.Forms; using Wox.Infrastructure; using Wox.Infrastructure.Storage.UserSettings; using Wox.Plugin.SystemPlugins.Program.ProgramSources; @@ -73,6 +77,10 @@ namespace Wox.Plugin.SystemPlugins.Program protected override void InitInternal(PluginInitContext context) { this.context = context; + using (new Timeit("Loading Program Index Cache")) + { + programs = ProgramCacheStorage.Instance.Programs; + } IndexPrograms(); } @@ -82,6 +90,7 @@ namespace Wox.Plugin.SystemPlugins.Program { lock (lockObject) { + initing = true; List programSources = new List(); @@ -125,6 +134,9 @@ namespace Wox.Plugin.SystemPlugins.Program programs = tempPrograms; initing = false; + + ProgramCacheStorage.Instance.Programs = programs; + ProgramCacheStorage.Instance.Save(); } } } diff --git a/Wox.Plugin.SystemPlugins/Wox.Plugin.SystemPlugins.csproj b/Wox.Plugin.SystemPlugins/Wox.Plugin.SystemPlugins.csproj index d68e9e3a7..7fb13e044 100644 --- a/Wox.Plugin.SystemPlugins/Wox.Plugin.SystemPlugins.csproj +++ b/Wox.Plugin.SystemPlugins/Wox.Plugin.SystemPlugins.csproj @@ -70,6 +70,7 @@ FolderPluginSettings.xaml + diff --git a/Wox.sln b/Wox.sln index a8b3e304f..120076914 100644 --- a/Wox.sln +++ b/Wox.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 2013 -VisualStudioVersion = 12.0.21005.1 +VisualStudioVersion = 12.0.30723.0 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Wox.Test", "Wox.Test\Wox.Test.csproj", "{FF742965-9A80-41A5-B042-D6C7D3A21708}" EndProject