Add search monitor

This commit is contained in:
qianlifeng
2014-11-03 18:49:18 +08:00
parent 9481d04a19
commit 3c4a9a05a0
4 changed files with 42 additions and 49 deletions

View File

@@ -15,11 +15,13 @@ namespace Wox.Plugin.FindFile.MFTSearch
public class MFTSearcher public class MFTSearcher
{ {
private static MFTSearcherCache cache = new MFTSearcherCache(); private static MFTSearcherCache cache = new MFTSearcherCache();
private static VolumeMonitor monitor = new VolumeMonitor();
private static void IndexVolume(string volume) private static void IndexVolume(string volume)
{ {
cache.CheckHashTableKey(volume); cache.EnsureVolumeExistInHashTable(volume);
EnumerateVolume(volume,cache.VolumeRecords[volume]); EnumerateVolume(volume, cache.VolumeRecords[volume]);
monitor.Monitor(volume,cache);
} }
public static void IndexAllVolumes() public static void IndexAllVolumes()
@@ -39,7 +41,7 @@ namespace Wox.Plugin.FindFile.MFTSearch
{ {
if (string.IsNullOrEmpty(item)) return new List<MFTSearchRecord>(); if (string.IsNullOrEmpty(item)) return new List<MFTSearchRecord>();
List<USNRecord> found = cache.FindByName(item,100); List<USNRecord> found = cache.FindByName(item, 100);
found.ForEach(x => FillPath(x.VolumeName, x, cache)); found.ForEach(x => FillPath(x.VolumeName, x, cache));
return found.ConvertAll(o => new MFTSearchRecord(o)); return found.ConvertAll(o => new MFTSearchRecord(o));
} }
@@ -65,7 +67,7 @@ namespace Wox.Plugin.FindFile.MFTSearch
UInt64 fileIndexHigh = (UInt64)fi.FileIndexHigh; UInt64 fileIndexHigh = (UInt64)fi.FileIndexHigh;
UInt64 indexRoot = (fileIndexHigh << 32) | fi.FileIndexLow; UInt64 indexRoot = (fileIndexHigh << 32) | fi.FileIndexLow;
files.Add(indexRoot,new USNRecord files.Add(indexRoot, new USNRecord
{ {
FRN = indexRoot, FRN = indexRoot,
Name = volumeName, Name = volumeName,
@@ -94,7 +96,7 @@ namespace Wox.Plugin.FindFile.MFTSearch
IntPtr pVolume = IntPtr.Zero; IntPtr pVolume = IntPtr.Zero;
try try
{ {
AddVolumeRootRecord(volumeName,files); AddVolumeRootRecord(volumeName, files);
pVolume = GetVolumeJournalHandle(volumeName); pVolume = GetVolumeJournalHandle(volumeName);
EnableVomuleJournal(pVolume); EnableVomuleJournal(pVolume);
@@ -217,7 +219,7 @@ namespace Wox.Plugin.FindFile.MFTSearch
{ {
PInvokeWin32.USN_RECORD usn = new PInvokeWin32.USN_RECORD(pUsnRecord); PInvokeWin32.USN_RECORD usn = new PInvokeWin32.USN_RECORD(pUsnRecord);
files.Add(usn.FRN,new USNRecord files.Add(usn.FRN, new USNRecord
{ {
Name = usn.FileName, Name = usn.FileName,
ParentFrn = usn.ParentFRN, ParentFrn = usn.ParentFRN,

View File

@@ -17,17 +17,20 @@ namespace Wox.Plugin.FindFile.MFTSearch
public void AddRecord(string volume, List<USNRecord> r) public void AddRecord(string volume, List<USNRecord> r)
{ {
CheckHashTableKey(volume); EnsureVolumeExistInHashTable(volume);
r.ForEach(x => VolumeRecords[volume].Add(x.FRN, x)); r.ForEach(x => VolumeRecords[volume].Add(x.FRN, x));
} }
public void AddRecord(string volume, USNRecord record) public void AddRecord(string volume, USNRecord record)
{ {
CheckHashTableKey(volume); EnsureVolumeExistInHashTable(volume);
VolumeRecords[volume].Add(record.FRN, record); 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)) if (!VolumeRecords.ContainsKey(volume))
VolumeRecords.Add(volume, new Dictionary<ulong, USNRecord>()); VolumeRecords.Add(volume, new Dictionary<ulong, USNRecord>());

View File

@@ -16,12 +16,18 @@ namespace Wox.Plugin.FindFile.MFTSearch
{ {
foreach (var volume in volumes) foreach (var volume in volumes)
{ {
if (string.IsNullOrEmpty(volume)) throw new InvalidOperationException("Volume cant't be null or empty string."); Monitor(volume, db);
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<string, object> { { "Volume", volume }, { "MFTSearcherCache", 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) private PInvokeWin32.READ_USN_JOURNAL_DATA SetupInputData4JournalRead(string volume, uint reason)
{ {
IntPtr pMonitorVolume = MFTSearcher.GetVolumeJournalHandle(volume); IntPtr pMonitorVolume = MFTSearcher.GetVolumeJournalHandle(volume);
@@ -40,11 +46,9 @@ namespace Wox.Plugin.FindFile.MFTSearch
return rujd; return rujd;
} }
private void MonitorThread(object param)
{
MFTSearcherCache db = (param as Dictionary<string, object>)["MFTSearcherCache"] as MFTSearcherCache; private void MonitorThread(string volume, MFTSearcherCache db)
string volume = (param as Dictionary<string, object>)["Volume"] as string; {
IntPtr pbuffer = Marshal.AllocHGlobal(0x1000); IntPtr pbuffer = Marshal.AllocHGlobal(0x1000);
PInvokeWin32.READ_USN_JOURNAL_DATA rujd = SetupInputData4JournalRead(volume, 0xFFFFFFFF); PInvokeWin32.READ_USN_JOURNAL_DATA rujd = SetupInputData4JournalRead(volume, 0xFFFFFFFF);
UInt32 cbRead; UInt32 cbRead;
@@ -56,7 +60,6 @@ namespace Wox.Plugin.FindFile.MFTSearch
PInvokeWin32.ZeroMemory(prujd, Marshal.SizeOf(rujd)); PInvokeWin32.ZeroMemory(prujd, Marshal.SizeOf(rujd));
Marshal.StructureToPtr(rujd, prujd, true); Marshal.StructureToPtr(rujd, prujd, true);
Debug.WriteLine(string.Format("\nMoniting on {0}......", volume));
IntPtr pVolume = MFTSearcher.GetVolumeJournalHandle(volume); IntPtr pVolume = MFTSearcher.GetVolumeJournalHandle(volume);
bool fok = PInvokeWin32.DeviceIoControl(pVolume, bool fok = PInvokeWin32.DeviceIoControl(pVolume,
@@ -81,15 +84,9 @@ namespace Wox.Plugin.FindFile.MFTSearch
rujd.StartUsn = Marshal.ReadInt64(pbuffer); rujd.StartUsn = Marshal.ReadInt64(pbuffer);
} }
} }
private void ProcessUSN(PInvokeWin32.USN_RECORD usn, string volume, MFTSearcherCache db) 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"])) if (MaskEqual(usn.Reason, USNChangeReason.USN_REASONS["USN_REASON_RENAME_NEW_NAME"]))
ProcessRenameNewName(usn, volume, db); ProcessRenameNewName(usn, volume, db);
if ((usn.Reason & USNChangeReason.USN_REASONS["USN_REASON_FILE_CREATE"]) != 0) 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"])) if (MaskEqual(usn.Reason, USNChangeReason.USN_REASONS["USN_REASON_FILE_DELETE"]))
ProcessFileDelete(usn, volume, db); ProcessFileDelete(usn, volume, db);
} }
private void ProcessFileDelete(PInvokeWin32.USN_RECORD usn, string volume, MFTSearcherCache db) private void ProcessFileDelete(PInvokeWin32.USN_RECORD usn, string volume, MFTSearcherCache db)
{ {
var cached = db.FindByFrn(volume, usn.FRN); var cached = db.FindByFrn(volume, usn.FRN);
if (cached == null) if (cached != null)
{
return;
}
else
{ {
MFTSearcher.FillPath(volume, cached, db); MFTSearcher.FillPath(volume, cached, db);
var deleteok = db.DeleteRecord(volume, usn.FRN); 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) if (RecordDeletedEvent != null)
RecordDeletedEvent(cached); RecordDeletedEvent(cached);
} }
} }
private void ProcessRenameNewName(PInvokeWin32.USN_RECORD usn, string volume, MFTSearcherCache db) private void ProcessRenameNewName(PInvokeWin32.USN_RECORD usn, string volume, MFTSearcherCache db)
{ {
USNRecord newRecord = USNRecord.ParseUSN(volume, usn); 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); 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) private void ProcessFileCreate(PInvokeWin32.USN_RECORD usn, string volume, MFTSearcherCache db)
{ {
USNRecord record = USNRecord.ParseUSN(volume, usn); 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); db.AddRecord(volume, record);
MFTSearcher.FillPath(volume, record, db);
Debug.WriteLine(string.Format(">>>> NewFile: {0}", record.FullPath)); Debug.WriteLine(string.Format(">>>> NewFile: {0}", record.FullPath));
if (RecordAddedEvent != null) if (RecordAddedEvent != null)
RecordAddedEvent(record); RecordAddedEvent(record);

View File

@@ -184,7 +184,10 @@ namespace Wox
globalHotkey.hookedKeyboardCallback += KListener_hookedKeyboardCallback; 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) void pnlResult_RightMouseClickEvent(Result result)
@@ -217,8 +220,6 @@ namespace Wox
Top = UserSettingStorage.Instance.WindowTop; Top = UserSettingStorage.Instance.WindowTop;
} }
Plugins.Init();
InitProgressbarAnimation(); InitProgressbarAnimation();
//only works for win7+ //only works for win7+