From 3c4a9a05a0bee8ae1f19c8632a57d7fe69f88c4f Mon Sep 17 00:00:00 2001 From: qianlifeng Date: Mon, 3 Nov 2014 18:49:18 +0800 Subject: [PATCH] Add search monitor --- .../MFTSearch/MFTSearcher.cs | 14 +++-- .../MFTSearch/MFTSearcherCache.cs | 11 ++-- .../MFTSearch/VolumeMonitor.cs | 59 ++++++++----------- Wox/MainWindow.xaml.cs | 7 ++- 4 files changed, 42 insertions(+), 49 deletions(-) diff --git a/Plugins/Wox.Plugin.FindFile/MFTSearch/MFTSearcher.cs b/Plugins/Wox.Plugin.FindFile/MFTSearch/MFTSearcher.cs index 6ce6f51e69..39198c4d64 100644 --- a/Plugins/Wox.Plugin.FindFile/MFTSearch/MFTSearcher.cs +++ b/Plugins/Wox.Plugin.FindFile/MFTSearch/MFTSearcher.cs @@ -15,11 +15,13 @@ namespace Wox.Plugin.FindFile.MFTSearch public class MFTSearcher { private static MFTSearcherCache cache = new MFTSearcherCache(); + private static VolumeMonitor monitor = new VolumeMonitor(); private static void IndexVolume(string volume) { - cache.CheckHashTableKey(volume); - EnumerateVolume(volume,cache.VolumeRecords[volume]); + cache.EnsureVolumeExistInHashTable(volume); + EnumerateVolume(volume, cache.VolumeRecords[volume]); + monitor.Monitor(volume,cache); } public static void IndexAllVolumes() @@ -39,7 +41,7 @@ namespace Wox.Plugin.FindFile.MFTSearch { if (string.IsNullOrEmpty(item)) return new List(); - List found = cache.FindByName(item,100); + List found = cache.FindByName(item, 100); found.ForEach(x => FillPath(x.VolumeName, x, cache)); return found.ConvertAll(o => new MFTSearchRecord(o)); } @@ -65,7 +67,7 @@ namespace Wox.Plugin.FindFile.MFTSearch UInt64 fileIndexHigh = (UInt64)fi.FileIndexHigh; UInt64 indexRoot = (fileIndexHigh << 32) | fi.FileIndexLow; - files.Add(indexRoot,new USNRecord + files.Add(indexRoot, new USNRecord { FRN = indexRoot, Name = volumeName, @@ -94,7 +96,7 @@ namespace Wox.Plugin.FindFile.MFTSearch IntPtr pVolume = IntPtr.Zero; try { - AddVolumeRootRecord(volumeName,files); + AddVolumeRootRecord(volumeName, files); pVolume = GetVolumeJournalHandle(volumeName); EnableVomuleJournal(pVolume); @@ -217,7 +219,7 @@ namespace Wox.Plugin.FindFile.MFTSearch { PInvokeWin32.USN_RECORD usn = new PInvokeWin32.USN_RECORD(pUsnRecord); - files.Add(usn.FRN,new USNRecord + files.Add(usn.FRN, new USNRecord { Name = usn.FileName, ParentFrn = usn.ParentFRN, diff --git a/Plugins/Wox.Plugin.FindFile/MFTSearch/MFTSearcherCache.cs b/Plugins/Wox.Plugin.FindFile/MFTSearch/MFTSearcherCache.cs index 1e1f4e65fe..5353573366 100644 --- a/Plugins/Wox.Plugin.FindFile/MFTSearch/MFTSearcherCache.cs +++ b/Plugins/Wox.Plugin.FindFile/MFTSearch/MFTSearcherCache.cs @@ -17,17 +17,20 @@ namespace Wox.Plugin.FindFile.MFTSearch public void AddRecord(string volume, List r) { - CheckHashTableKey(volume); + EnsureVolumeExistInHashTable(volume); r.ForEach(x => VolumeRecords[volume].Add(x.FRN, x)); } public void AddRecord(string volume, USNRecord record) { - CheckHashTableKey(volume); - VolumeRecords[volume].Add(record.FRN, record); + EnsureVolumeExistInHashTable(volume); + if (!VolumeRecords[volume].ContainsKey(record.FRN)) + { + VolumeRecords[volume].Add(record.FRN, record); + } } - public void CheckHashTableKey(string volume) + public void EnsureVolumeExistInHashTable(string volume) { if (!VolumeRecords.ContainsKey(volume)) VolumeRecords.Add(volume, new Dictionary()); diff --git a/Plugins/Wox.Plugin.FindFile/MFTSearch/VolumeMonitor.cs b/Plugins/Wox.Plugin.FindFile/MFTSearch/VolumeMonitor.cs index a29aa05afa..6048bacf75 100644 --- a/Plugins/Wox.Plugin.FindFile/MFTSearch/VolumeMonitor.cs +++ b/Plugins/Wox.Plugin.FindFile/MFTSearch/VolumeMonitor.cs @@ -16,12 +16,18 @@ namespace Wox.Plugin.FindFile.MFTSearch { foreach (var volume in volumes) { - if (string.IsNullOrEmpty(volume)) throw new InvalidOperationException("Volume cant't be null or empty string."); - if (!db.ContainsVolume(volume)) throw new InvalidOperationException(string.Format("Volume {0} must be scaned first.")); - Thread th = new Thread(new ParameterizedThreadStart(MonitorThread)); - th.Start(new Dictionary { { "Volume", volume }, { "MFTSearcherCache", db } }); + Monitor(volume, db); } } + + public void Monitor(string volume, MFTSearcherCache db) + { + if (string.IsNullOrEmpty(volume)) throw new InvalidOperationException("Volume cant't be null or empty string."); + if (!db.ContainsVolume(volume)) throw new InvalidOperationException(string.Format("Volume {0} must be scaned first.")); + + ThreadPool.QueueUserWorkItem(o => MonitorThread(volume, db)); + } + private PInvokeWin32.READ_USN_JOURNAL_DATA SetupInputData4JournalRead(string volume, uint reason) { IntPtr pMonitorVolume = MFTSearcher.GetVolumeJournalHandle(volume); @@ -40,11 +46,9 @@ namespace Wox.Plugin.FindFile.MFTSearch return rujd; } - private void MonitorThread(object param) - { - MFTSearcherCache db = (param as Dictionary)["MFTSearcherCache"] as MFTSearcherCache; - string volume = (param as Dictionary)["Volume"] as string; + private void MonitorThread(string volume, MFTSearcherCache db) + { IntPtr pbuffer = Marshal.AllocHGlobal(0x1000); PInvokeWin32.READ_USN_JOURNAL_DATA rujd = SetupInputData4JournalRead(volume, 0xFFFFFFFF); UInt32 cbRead; @@ -56,7 +60,6 @@ namespace Wox.Plugin.FindFile.MFTSearch PInvokeWin32.ZeroMemory(prujd, Marshal.SizeOf(rujd)); Marshal.StructureToPtr(rujd, prujd, true); - Debug.WriteLine(string.Format("\nMoniting on {0}......", volume)); IntPtr pVolume = MFTSearcher.GetVolumeJournalHandle(volume); bool fok = PInvokeWin32.DeviceIoControl(pVolume, @@ -81,15 +84,9 @@ namespace Wox.Plugin.FindFile.MFTSearch rujd.StartUsn = Marshal.ReadInt64(pbuffer); } } + private void ProcessUSN(PInvokeWin32.USN_RECORD usn, string volume, MFTSearcherCache db) { - var dbCached = db.FindByFrn(volume, usn.FRN); - MFTSearcher.FillPath(volume, dbCached, db); - Debug.WriteLine(string.Format("------USN[frn={0}]------", usn.FRN)); - Debug.WriteLine(string.Format("FileName={0}, USNChangeReason={1}", usn.FileName, USNChangeReason.ReasonPrettyFormat(usn.Reason))); - Debug.WriteLine(string.Format("FileName[Cached]={0}", dbCached == null ? "NoCache" : dbCached.FullPath)); - Debug.WriteLine("--------------------------------------"); - if (MaskEqual(usn.Reason, USNChangeReason.USN_REASONS["USN_REASON_RENAME_NEW_NAME"])) ProcessRenameNewName(usn, volume, db); if ((usn.Reason & USNChangeReason.USN_REASONS["USN_REASON_FILE_CREATE"]) != 0) @@ -97,47 +94,37 @@ namespace Wox.Plugin.FindFile.MFTSearch if (MaskEqual(usn.Reason, USNChangeReason.USN_REASONS["USN_REASON_FILE_DELETE"])) ProcessFileDelete(usn, volume, db); } + private void ProcessFileDelete(PInvokeWin32.USN_RECORD usn, string volume, MFTSearcherCache db) { var cached = db.FindByFrn(volume, usn.FRN); - if (cached == null) - { - return; - } - else + if (cached != null) { MFTSearcher.FillPath(volume, cached, db); var deleteok = db.DeleteRecord(volume, usn.FRN); - Debug.WriteLine(string.Format(">>>> File {0} deleted {1}.", cached.FullPath, deleteok ? "successful" : "fail")); + Debug.WriteLine(string.Format(">>>> DeleteFIle {0} {1}.", cached.FullPath, deleteok ? "successful" : "fail")); if (RecordDeletedEvent != null) RecordDeletedEvent(cached); } } + private void ProcessRenameNewName(PInvokeWin32.USN_RECORD usn, string volume, MFTSearcherCache db) { USNRecord newRecord = USNRecord.ParseUSN(volume, usn); - //string fullpath = newRecord.Name; - //db.FindRecordPath(newRecord, ref fullpath, db.GetVolumeRecords(volume)); - //newRecord.FullPath = fullpath; - var oldRecord = db.FindByFrn(volume, usn.FRN); - MFTSearcher.FillPath(volume, oldRecord, db); - MFTSearcher.FillPath(volume, newRecord, db); - Debug.WriteLine(string.Format(">>>> RenameFile {0} to {1}", oldRecord.FullPath, newRecord.FullPath)); db.UpdateRecord(volume, newRecord); - if (RecordRenameEvent != null) RecordRenameEvent(oldRecord, newRecord); - if (newRecord.FullPath.Contains("$RECYCLE.BIN")) + + var oldRecord = db.FindByFrn(volume, usn.FRN); + if (oldRecord != null) { - Debug.WriteLine(string.Format(">>>> Means {0} moved to recycle.", oldRecord.FullPath)); + Debug.WriteLine(string.Format(">>>> RenameFile {0} to {1}", oldRecord.FullPath, newRecord.FullPath)); + if (RecordRenameEvent != null) RecordRenameEvent(oldRecord, newRecord); } } + private void ProcessFileCreate(PInvokeWin32.USN_RECORD usn, string volume, MFTSearcherCache db) { USNRecord record = USNRecord.ParseUSN(volume, usn); - //string fullpath = record.Name; - //db.FindRecordPath(record, ref fullpath, db.GetVolumeRecords(volume)); - //record.FullPath = fullpath; db.AddRecord(volume, record); - MFTSearcher.FillPath(volume, record, db); Debug.WriteLine(string.Format(">>>> NewFile: {0}", record.FullPath)); if (RecordAddedEvent != null) RecordAddedEvent(record); diff --git a/Wox/MainWindow.xaml.cs b/Wox/MainWindow.xaml.cs index bfca9c5f6d..3ed2fbbeb0 100644 --- a/Wox/MainWindow.xaml.cs +++ b/Wox/MainWindow.xaml.cs @@ -184,7 +184,10 @@ namespace Wox globalHotkey.hookedKeyboardCallback += KListener_hookedKeyboardCallback; - this.Closing += MainWindow_Closing; + Closing += MainWindow_Closing; + //since MainWIndow implement IPublicAPI, so we need to finish ctor MainWindow object before + //PublicAPI invoke in plugin init methods. E.g FolderPlugin + ThreadPool.QueueUserWorkItem(o => Plugins.Init()); } void pnlResult_RightMouseClickEvent(Result result) @@ -217,8 +220,6 @@ namespace Wox Top = UserSettingStorage.Instance.WindowTop; } - Plugins.Init(); - InitProgressbarAnimation(); //only works for win7+