ソースを参照

Usn读取,存储到Sqlite数据库

yuzhengyang 8 年 前
コミット
07feee6dd3
22 ファイル変更687 行追加226 行削除
  1. 23 14
      Fork.Net/Fork.Net.SpeciallyTools/Y.FileQueryEngine/QueryEngine/FileQueryEngine.cs
  2. 8 8
      Fork.Net/Fork.Net.SpeciallyTools/Y.FileQueryEngine/UsnOperation/UsnEntry.cs
  3. 1 1
      Fork.Net/Fork.Net.SpeciallyTools/Y.FileQueryEngine/UsnOperation/UsnJournalData.cs
  4. 100 1
      Fork.Net/Fork.Net.SpeciallyTools/Y.FileQueryEngine/UsnOperation/UsnOperator.cs
  5. 1 1
      Fork.Net/Fork.Net.SpeciallyTools/Y.FileQueryEngine/Win32/Structures/USN_JOURNAL_DATA.cs
  6. 1 0
      Fork.Net/Fork.Net.SpeciallyTools/Y.FileQueryEngine/Y.FileQueryEngine.csproj
  7. 1 1
      Fork.Net/Oreo.Plugins/Oreo.FileMan/App.config
  8. 0 1
      Fork.Net/Oreo.Plugins/Oreo.FileMan/Commons/R.cs
  9. 7 0
      Fork.Net/Oreo.Plugins/Oreo.FileMan/DatabaseEngine/Mapping.cs
  10. 156 24
      Fork.Net/Oreo.Plugins/Oreo.FileMan/DatabaseEngine/Muse.cs
  11. 42 0
      Fork.Net/Oreo.Plugins/Oreo.FileMan/DatabaseEngine/SuperDb.cs
  12. 0 58
      Fork.Net/Oreo.Plugins/Oreo.FileMan/Helpers/FileHelper.cs
  13. 15 0
      Fork.Net/Oreo.Plugins/Oreo.FileMan/Models/Drives.cs
  14. 8 4
      Fork.Net/Oreo.Plugins/Oreo.FileMan/Models/Files.cs
  15. 3 1
      Fork.Net/Oreo.Plugins/Oreo.FileMan/Oreo.FileMan.csproj
  16. 4 4
      Fork.Net/Oreo.Plugins/Oreo.FileMan/Partial/FileTypePartial.Designer.cs
  17. 224 89
      Fork.Net/Oreo.Plugins/Oreo.FileMan/Partial/FileTypePartial.cs
  18. 5 5
      Fork.Net/Y.DB/DAO/IDbContext.cs
  19. 31 14
      Fork.Net/Y.DB/DAO/Muse.cs
  20. 23 0
      Fork.Net/Y.Utils/DataUtils/Collections/ListTool.cs
  21. 33 0
      Fork.Net/Y.Utils/IOUtils/DriveUtils/DriveTool.cs
  22. 1 0
      Fork.Net/Y.Utils/Y.Utils.csproj

+ 23 - 14
Fork.Net/Fork.Net.SpeciallyTools/Y.FileQueryEngine/QueryEngine/FileQueryEngine.cs

@@ -11,7 +11,7 @@ namespace Y.FileQueryEngine.QueryEngine
         /// <summary>
         /// When its values is 1407374883553285(0x5000000000005L), it means this file/folder is under drive root
         /// </summary>
-        protected const UInt64 ROOT_FILE_REFERENCE_NUMBER = 0x5000000000005L;
+        public const UInt64 ROOT_FILE_REFERENCE_NUMBER = 0x5000000000005L;
 
         protected static readonly string excludeFolders = string.Join("|",
             new string[]
@@ -49,22 +49,31 @@ namespace Y.FileQueryEngine.QueryEngine
             return DriveInfo.GetDrives()
                 .Where(d => d.IsReady && d.DriveFormat.ToUpper() == "NTFS");
         }
-
-        public static List<string> GetAllFiles(DriveInfo drive)
+        /// <summary>
+        /// 查询磁盘的所有文件
+        /// </summary>
+        /// <param name="drive"></param>
+        /// <returns></returns>
+        public static List<UsnEntry> GetAllFiles(DriveInfo drive)
         {
-            List<string> result = new List<string>();
             var usnOperator = new UsnOperator(drive);
-            var usnEntries = usnOperator.GetEntries().Where(e => !excludeFolders.Contains(e.FileName.ToUpper()));
-            var folders = usnEntries.Where(e => e.IsFolder).ToArray();
-            List<FrnFilePath> paths = GetFolderPath(folders, drive);
-            var range = usnEntries.Join(
-               paths,
-               usn => usn.ParentFileReferenceNumber,
-               path => path.FileReferenceNumber,
-               (usn, path) => string.Concat(path.Path + "\\" + usn.FileName));
-            result.AddRange(range);
-            return result;
+            return usnOperator.GetEntries().Where(e => !excludeFolders.Contains(e.FileName.ToUpper())).ToList();
+        }
+        public static bool FileIsExist(string drive, long usn)
+        {
+            var d = DriveInfo.GetDrives().FirstOrDefault(x => x.Name == drive);
+            if (d != null)
+            {
+                var usnOperator = new UsnOperator(d);
+                return usnOperator.UsnIsExist(usn);
+            }
+            return false;
         }
+        /// <summary>
+        /// 查询磁盘的所有文件
+        /// </summary>
+        /// <param name="drive"></param>
+        /// <returns></returns>
         public static List<FileAndDirectoryEntry> GetAllFileEntrys(DriveInfo drive)
         {
             List<FileAndDirectoryEntry> result = new List<FileAndDirectoryEntry>();

+ 8 - 8
Fork.Net/Fork.Net.SpeciallyTools/Y.FileQueryEngine/UsnOperation/UsnEntry.cs

@@ -9,8 +9,8 @@ namespace Y.FileQueryEngine.UsnOperation
     /// </summary>
     public class UsnEntry
     {
-        public UInt32 RecordLength { get; private set; }
-        public UInt64 FileReferenceNumber { get; private set; }
+        public uint RecordLength { get; private set; }
+        public ulong FileReferenceNumber { get; private set; }
 
         /// <summary>
         /// Gets the parent file reference number.
@@ -19,12 +19,12 @@ namespace Y.FileQueryEngine.UsnOperation
         /// <value>
         /// The parent file reference number.
         /// </value>
-        public UInt64 ParentFileReferenceNumber { get; private set; }
-        public Int64 Usn { get; private set; }
-        public UInt32 Reason { get; private set; }
-        public UInt32 FileAttributes { get; private set; }
-        public Int32 FileNameLength { get; private set; }
-        public Int32 FileNameOffset { get; private set; }
+        public ulong ParentFileReferenceNumber { get; private set; }
+        public long Usn { get; private set; }
+        public uint Reason { get; private set; }
+        public uint FileAttributes { get; private set; }
+        public int FileNameLength { get; private set; }
+        public int FileNameOffset { get; private set; }
         public string FileName { get; private set; }
         public bool IsFolder
         {

+ 1 - 1
Fork.Net/Fork.Net.SpeciallyTools/Y.FileQueryEngine/UsnOperation/UsnJournalData.cs

@@ -4,7 +4,7 @@ using Y.FileQueryEngine.Win32.Structures;
 
 namespace Y.FileQueryEngine.UsnOperation
 {
-    internal class UsnJournalData
+    public class UsnJournalData
     {
         public DriveInfo Drive { get; private set; }
         public UInt64 UsnJournalID { get; private set; }

+ 100 - 1
Fork.Net/Fork.Net.SpeciallyTools/Y.FileQueryEngine/UsnOperation/UsnOperator.cs

@@ -9,8 +9,10 @@ using Y.FileQueryEngine.Win32.Constants;
 
 namespace Y.FileQueryEngine.UsnOperation
 {
-    internal class UsnOperator : IDisposable
+    public class UsnOperator : IDisposable
     {
+        public delegate void GetEntriesHandler(DriveInfo drive, List<UsnEntry> data);
+
         protected USN_JOURNAL_DATA ntfsUsnJournalData;
 
         public DriveInfo Drive
@@ -141,7 +143,104 @@ namespace Y.FileQueryEngine.UsnOperation
 
             return result;
         }
+        public void GetEntries(long usn, GetEntriesHandler handler, int count)
+        {
+            List<UsnEntry> result = new List<UsnEntry>();
+            UsnErrorCode usnErrorCode = this.QueryUSNJournal();
+            if (usnErrorCode == UsnErrorCode.SUCCESS)
+            {
+                MFT_ENUM_DATA mftEnumData = new MFT_ENUM_DATA();
+                mftEnumData.StartFileReferenceNumber = 0;
+                mftEnumData.LowUsn = usn;
+                mftEnumData.HighUsn = this.ntfsUsnJournalData.NextUsn;
+                int sizeMftEnumData = Marshal.SizeOf(mftEnumData);
+                IntPtr ptrMftEnumData = GetHeapGlobalPtr(sizeMftEnumData);
+                Marshal.StructureToPtr(mftEnumData, ptrMftEnumData, true);
+                int ptrDataSize = sizeof(UInt64) + 10000;
+                IntPtr ptrData = GetHeapGlobalPtr(ptrDataSize);
+                uint outBytesCount;
 
+                while (false != Win32Api.DeviceIoControl(
+                    this.DriveRootHandle,
+                    UsnControlCode.FSCTL_ENUM_USN_DATA,
+                    ptrMftEnumData,
+                    sizeMftEnumData,
+                    ptrData,
+                    ptrDataSize,
+                    out outBytesCount,
+                    IntPtr.Zero))
+                {
+
+                    IntPtr ptrUsnRecord = new IntPtr(ptrData.ToInt32() + sizeof(Int64));
+
+                    while (outBytesCount > 60)
+                    {
+                        var usnRecord = new USN_RECORD_V2(ptrUsnRecord);
+                        result.Add(new UsnEntry(usnRecord));
+                        ptrUsnRecord = new IntPtr(ptrUsnRecord.ToInt32() + usnRecord.RecordLength);
+                        outBytesCount -= usnRecord.RecordLength;
+
+                        if (result.Count >= count)
+                        {
+                            handler?.Invoke(Drive, result);
+                            result = new List<UsnEntry>();
+                        }
+                    }
+                    Marshal.WriteInt64(ptrMftEnumData, Marshal.ReadInt64(ptrData, 0));
+                }
+
+                Marshal.FreeHGlobal(ptrData);
+                Marshal.FreeHGlobal(ptrMftEnumData);
+            }
+            handler?.Invoke(Drive, result);
+        }
+
+        public bool UsnIsExist(long usn)
+        {
+            bool rs = false;
+            UsnErrorCode usnErrorCode = QueryUSNJournal();
+            if (ntfsUsnJournalData.NextUsn < usn) return rs;
+
+            if (usnErrorCode == UsnErrorCode.SUCCESS)
+            {
+                MFT_ENUM_DATA mftEnumData = new MFT_ENUM_DATA();
+                mftEnumData.StartFileReferenceNumber = 0;
+                mftEnumData.LowUsn = usn;
+                mftEnumData.HighUsn = usn;
+                int sizeMftEnumData = Marshal.SizeOf(mftEnumData);
+                IntPtr ptrMftEnumData = GetHeapGlobalPtr(sizeMftEnumData);
+                Marshal.StructureToPtr(mftEnumData, ptrMftEnumData, true);
+                int ptrDataSize = sizeof(UInt64) + 10000;
+                IntPtr ptrData = GetHeapGlobalPtr(ptrDataSize);
+                uint outBytesCount;
+
+                while (false != Win32Api.DeviceIoControl(
+                    this.DriveRootHandle,
+                    UsnControlCode.FSCTL_ENUM_USN_DATA,
+                    ptrMftEnumData,
+                    sizeMftEnumData,
+                    ptrData,
+                    ptrDataSize,
+                    out outBytesCount,
+                    IntPtr.Zero))
+                {
+                    IntPtr ptrUsnRecord = new IntPtr(ptrData.ToInt32() + sizeof(Int64));
+
+                    while (outBytesCount > 60)
+                    {
+                        var usnRecord = new USN_RECORD_V2(ptrUsnRecord);
+                        ptrUsnRecord = new IntPtr(ptrUsnRecord.ToInt32() + usnRecord.RecordLength);
+                        outBytesCount -= usnRecord.RecordLength;
+                        rs = true;
+                    }
+                    Marshal.WriteInt64(ptrMftEnumData, Marshal.ReadInt64(ptrData, 0));
+                }
+
+                Marshal.FreeHGlobal(ptrData);
+                Marshal.FreeHGlobal(ptrMftEnumData);
+            }
+            return rs;
+        }
         private static IntPtr GetHeapGlobalPtr(int size)
         {
             IntPtr buffer = Marshal.AllocHGlobal(size);

+ 1 - 1
Fork.Net/Fork.Net.SpeciallyTools/Y.FileQueryEngine/Win32/Structures/USN_JOURNAL_DATA.cs

@@ -8,7 +8,7 @@ namespace Y.FileQueryEngine.Win32.Structures
     /// Lowest Valid USN(64bits), Max USN(64bits), Maximum Size(64bits) and Allocation Delta(64bits).
     /// </summary>
     [StructLayout(LayoutKind.Sequential, Pack = 1)]
-    internal struct USN_JOURNAL_DATA
+    public struct USN_JOURNAL_DATA
     {
         public UInt64 UsnJournalID;
         public Int64 FirstUsn;

+ 1 - 0
Fork.Net/Fork.Net.SpeciallyTools/Y.FileQueryEngine/Y.FileQueryEngine.csproj

@@ -20,6 +20,7 @@
     <DefineConstants>DEBUG;TRACE</DefineConstants>
     <ErrorReport>prompt</ErrorReport>
     <WarningLevel>4</WarningLevel>
+    <DocumentationFile>bin\Debug\Y.FileQueryEngine.XML</DocumentationFile>
   </PropertyGroup>
   <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
     <DebugType>pdbonly</DebugType>

+ 1 - 1
Fork.Net/Oreo.Plugins/Oreo.FileMan/App.config

@@ -8,7 +8,7 @@
     <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.1" />
   </startup>
   <connectionStrings>
-    <add name="DefaultConnection" connectionString="data source=|DataDirectory|\db.sqlite;password=123456;" providerName="System.Data.SQLite" />
+    <add name="DefaultConnection" connectionString="data source=|DataDirectory|\files.db" providerName="System.Data.SQLite" />
   </connectionStrings>
   <entityFramework>
     <defaultConnectionFactory type="System.Data.Entity.Infrastructure.LocalDbConnectionFactory, EntityFramework">

+ 0 - 1
Fork.Net/Oreo.Plugins/Oreo.FileMan/Commons/R.cs

@@ -30,7 +30,6 @@ namespace Oreo.FileMan.Commons
             public static string App = Application.ExecutablePath;
             //public static string Settings = Paths.Root + "\\Settings.ini";//应用配置信息目录
             public static string Frisbee = Paths.App + "\\Frisbee.ini";
-            public static string Db = Paths.App + "db.sqlite";
         }
     }
 }

+ 7 - 0
Fork.Net/Oreo.Plugins/Oreo.FileMan/DatabaseEngine/Mapping.cs

@@ -17,4 +17,11 @@ namespace Oreo.FileMan.DatabaseEngine
             this.Property(o => o.Id).HasColumnAnnotation("Index", new IndexAnnotation(new IndexAttribute() { IsUnique = true }));
         }
     }
+    public class DrivesMap : EntityTypeConfiguration<Drives>
+    {
+        public DrivesMap()
+        {
+            this.Property(o => o.Id).HasColumnAnnotation("Index", new IndexAnnotation(new IndexAttribute() { IsUnique = true }));
+        }
+    }
 }

+ 156 - 24
Fork.Net/Oreo.Plugins/Oreo.FileMan/DatabaseEngine/Muse.cs

@@ -1,46 +1,178 @@
-using Oreo.FileMan.Commons;
-using Oreo.FileMan.Models;
-using SQLite.CodeFirst;
-using System;
+using System;
 using System.Collections.Generic;
 using System.Data.Entity;
-using System.Data.Entity.ModelConfiguration.Conventions;
-using System.IO;
+using System.Data.Entity.Infrastructure;
 using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
+using System.Linq.Expressions;
 
 namespace Oreo.FileMan.DatabaseEngine
 {
-    public class Muse : DbContext
+    class Muse : IDisposable
     {
+        SuperDb db;
         public Muse()
-            : base("DefaultConnection")
         {
+            db = new SuperDb();
         }
 
-        protected override void OnModelCreating(DbModelBuilder modelBuilder)
+        public int Add<T>(T EntityObj, bool isSave = true) where T : class
         {
-            modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
-            modelBuilder.Configurations.AddFromAssembly(typeof(Muse).Assembly);
-            if (!File.Exists(R.Files.Db))
+            try
             {
-                Database.SetInitializer(new MyDbInitializer(Database.Connection.ConnectionString, modelBuilder));
-                //var sqliteConnectionInitializer = new SqliteCreateDatabaseIfNotExists<Muse>(modelBuilder);
-                //Database.SetInitializer(sqliteConnectionInitializer);}
+                this.db.Set<T>().Add(EntityObj);
+                if (isSave)
+                {
+                    return Save();
+                }
             }
+            catch (Exception e) { }
+            return 0;
+        }
+        public int Adds<T>(IEnumerable<T> EntityObjs) where T : class
+        {
+            try
+            {
+                db.Set<T>().AddRange(EntityObjs);
+                return Save();
+            }
+            catch (Exception e)
+            {
+                return 0;
+            }
+        }
+        public int Del<T>(T EntityObj, bool isSave) where T : class
+        {
+            try
+            {
+                this.db.Set<T>().Remove(EntityObj);
+                if (isSave)
+                {
+                    return Save();
+                }
+            }
+            catch (Exception e) { }
+            return 0;
+        }
+        public int Dels<T>(IEnumerable<T> EntityObjs) where T : class
+        {
+            try
+            {
+                this.db.Set<T>().RemoveRange(EntityObjs);
+                return Save();
+            }
+            catch (Exception e) { }
+            return 0;
+        }
+        public int Update<T>(T EntityObj, bool isSave) where T : class
+        {
+            try
+            {
+                this.db.Entry(EntityObj).State = EntityState.Modified;
+                if (isSave)
+                {
+                    return Save();
+                }
+            }
+            catch (Exception e) { }
+            return 0;
+        }
+        public int Save()
+        {
+            return db.SaveChanges();
         }
 
-        public class MyDbInitializer : SqliteDropCreateDatabaseAlways<Muse>
+        public T Get<T>(Expression<Func<T, bool>> expression, string[] include) where T : class
+        {
+            try
+            {
+                if (include != null && include.Count() > 0)
+                {
+                    DbQuery<T> query = GetInclude<T>(include);
+                    if (query != null)
+                        return query.FirstOrDefault(expression);
+                }
+                return this.db.Set<T>().FirstOrDefault(expression);
+            }
+            catch (Exception e)
+            {
+            }
+            return null;
+        }
+        public IEnumerable<T> Gets<T>(Expression<Func<T, bool>> expression, string[] include) where T : class
+        {
+            try
+            {
+                if (include != null && include.Count() > 0)
+                {
+                    DbQuery<T> query = GetInclude<T>(include);
+                    if (query != null)
+                        return query.Where(expression).ToList();
+                }
+            }
+            catch (Exception)
+            {
+                throw;
+            }
+            return db.Set<T>().Where(expression).ToList();
+        }
+        public IEnumerable<T> GetAll<T>(string[] include, bool track) where T : class
+        {
+            if (include != null && include.Count() > 0)
+            {
+                DbQuery<T> query = GetInclude<T>(include);
+                if (query != null)
+                    if (track)
+                        return query.ToList();
+                    else
+                        return query.AsNoTracking().ToList();
+            }
+            if (!track)
+                db.Set<T>().AsNoTracking().ToList();
+            return db.Set<T>().ToList();
+        }
+        private DbQuery<T> GetInclude<T>(string[] include) where T : class
         {
-            public MyDbInitializer(string connectionString, DbModelBuilder modelBuilder)
-                : base(modelBuilder) { }
+            DbQuery<T> searchCondition = null;
+            foreach (var item in include)
+            {
+                if (searchCondition == null)
+                    searchCondition = this.db.Set<T>().Include(item);
+                else
+                    searchCondition = searchCondition.Include(item);
+            }
+            return searchCondition;
+        }
 
-            protected override void Seed(Muse context)
+        public bool Any<T>(Expression<Func<T, bool>> expression, string[] include) where T : class
+        {
+            try
+            {
+                if (include != null && include.Count() > 0)
+                {
+                    DbQuery<T> query = GetInclude<T>(include);
+                    if (query != null)
+                        return query.Any(expression);
+                }
+                return this.db.Set<T>().Any(expression);
+            }
+            catch (Exception e)
             {
-                //context.Set<Files>().Add(new Files { FileName = "123" });
-                base.Seed(context);
             }
+            return false;
+        }
+        public DbSet<T> Do<T>() where T : class
+        {
+            return db.Set<T>();
+        }
+        public IEnumerable<T> ExecuteSqlCom<T, U>(string sql, U paramObjs)
+            where U : class
+            where T : class
+        {
+            return db.Set<T>().SqlQuery(sql, paramObjs);
+        }
+        public void Dispose()
+        {
+            db.Dispose();
         }
     }
-}
+}

+ 42 - 0
Fork.Net/Oreo.Plugins/Oreo.FileMan/DatabaseEngine/SuperDb.cs

@@ -0,0 +1,42 @@
+using Oreo.FileMan.Commons;
+using Oreo.FileMan.Models;
+using SQLite.CodeFirst;
+using System;
+using System.Collections.Generic;
+using System.Data.Entity;
+using System.Data.Entity.ModelConfiguration.Conventions;
+using System.IO;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Oreo.FileMan.DatabaseEngine
+{
+    public class SuperDb : DbContext
+    {
+        public SuperDb()
+            : base(@"DefaultConnection")
+        {
+        }
+
+        protected override void OnModelCreating(DbModelBuilder modelBuilder)
+        {
+            modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
+            modelBuilder.Configurations.AddFromAssembly(typeof(SuperDb).Assembly);
+
+            Database.SetInitializer(new MyDbInitializer(Database.Connection.ConnectionString, modelBuilder));
+        }
+
+        public class MyDbInitializer : SqliteDropCreateDatabaseWhenModelChanges<SuperDb>//SqliteDropCreateDatabaseAlways
+        {
+            public MyDbInitializer(string connectionString, DbModelBuilder modelBuilder)
+                : base(modelBuilder) { }
+
+            protected override void Seed(SuperDb context)
+            {
+                //context.Set<Files>().Add(new Files { FileName = "123" });
+                base.Seed(context);
+            }
+        }
+    }
+}

+ 0 - 58
Fork.Net/Oreo.Plugins/Oreo.FileMan/Helpers/FileHelper.cs

@@ -1,58 +0,0 @@
-using Oreo.FileMan.DatabaseEngine;
-using Oreo.FileMan.Models;
-using System;
-using System.Collections.Generic;
-using System.IO;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-using Y.FileQueryEngine.QueryEngine;
-using Y.Utils.DataUtils.Collections;
-using Y.Utils.IOUtils.FileUtils;
-using Y.Utils.IOUtils.PathUtils;
-
-namespace Oreo.FileMan.Helpers
-{
-    public class FileHelper
-    {
-        public static void GetAllFileToDb()
-        {
-            var drives = FileQueryEngine.GetReadyNtfsDrives().OrderByDescending(x => x.Name);
-            if (ListTool.HasElements(drives))
-            {
-                foreach (var drive in drives)
-                {
-                    var allFiles = FileQueryEngine.GetAllFiles(drive);
-                    if (ListTool.HasElements(allFiles))
-                    {
-                        using (var db = new Muse())
-                        {
-                            int addcount = 0;
-                            foreach (var file in allFiles)
-                            {
-                                if (!db.Set<Files>().Any(x => x.FullPath == file))
-                                {
-                                    var a = db.Set<Files>().Add(
-                                        new Files()
-                                        {
-                                            FullPath = file,
-                                            FileName = Path.GetFileName(file),
-                                            ExtName = Path.GetExtension(file),
-                                            Size = FileTool.Size(file),
-                                        });
-                                    addcount++;
-                                }
-                                if (addcount >= 500)
-                                {
-                                    addcount = 0;
-                                    db.SaveChanges();
-                                }
-                            }
-                            int count = db.SaveChanges();
-                        }
-                    }
-                }
-            }
-        }
-    }
-}

+ 15 - 0
Fork.Net/Oreo.Plugins/Oreo.FileMan/Models/Drives.cs

@@ -0,0 +1,15 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Oreo.FileMan.Models
+{
+    public class Drives
+    {
+        public int Id { get; set; }
+        public string Name { get; set; }
+        public string LastFormatTime { get; set; }
+    }
+}

+ 8 - 4
Fork.Net/Oreo.Plugins/Oreo.FileMan/Models/Files.cs

@@ -1,17 +1,21 @@
 using System;
 using System.Collections.Generic;
+using System.IO;
 using System.Linq;
 using System.Text;
 using System.Threading.Tasks;
+using Y.Utils.IOUtils.FileUtils;
 
 namespace Oreo.FileMan.Models
 {
     public class Files
     {
         public int Id { get; set; }
-        public string FullPath { get; set; }
-        public string FileName { get; set; }
-        public string ExtName { get; set; }
-        public long Size { get; set; }
+        public string Name { get; set; }
+        public bool IsFolder { get; set; }
+        public string Number { get; set; }
+        public string ParentNumber { get; set; }
+        public string Drive { get; set; }
+        public long Usn { get; set; }
     }
 }

+ 3 - 1
Fork.Net/Oreo.Plugins/Oreo.FileMan/Oreo.FileMan.csproj

@@ -88,7 +88,8 @@
     <Compile Include="Commons\R.cs" />
     <Compile Include="DatabaseEngine\Mapping.cs" />
     <Compile Include="DatabaseEngine\Muse.cs" />
-    <Compile Include="Helpers\FileHelper.cs" />
+    <Compile Include="DatabaseEngine\SuperDb.cs" />
+    <Compile Include="Models\Drives.cs" />
     <Compile Include="Models\Files.cs" />
     <Compile Include="Partial\FileBackupPartial.cs">
       <SubType>UserControl</SubType>
@@ -171,6 +172,7 @@
     <None Include="App.config" />
   </ItemGroup>
   <ItemGroup>
+    <Folder Include="Helpers\" />
     <Folder Include="Services\" />
   </ItemGroup>
   <ItemGroup>

+ 4 - 4
Fork.Net/Oreo.Plugins/Oreo.FileMan/Partial/FileTypePartial.Designer.cs

@@ -355,11 +355,11 @@
             // LbFileCount
             // 
             this.LbFileCount.ForeColor = System.Drawing.Color.Gray;
-            this.LbFileCount.Location = new System.Drawing.Point(297, 7);
+            this.LbFileCount.Location = new System.Drawing.Point(250, 7);
             this.LbFileCount.Name = "LbFileCount";
-            this.LbFileCount.Size = new System.Drawing.Size(152, 14);
+            this.LbFileCount.Size = new System.Drawing.Size(199, 14);
             this.LbFileCount.TabIndex = 60;
-            this.LbFileCount.Text = "已整理/总文件";
+            this.LbFileCount.Text = "暂无新增项目";
             this.LbFileCount.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
             // 
             // panel1
@@ -377,7 +377,7 @@
             this.label1.ForeColor = System.Drawing.Color.Gray;
             this.label1.Location = new System.Drawing.Point(14, 7);
             this.label1.Name = "label1";
-            this.label1.Size = new System.Drawing.Size(284, 14);
+            this.label1.Size = new System.Drawing.Size(230, 14);
             this.label1.TabIndex = 61;
             this.label1.Text = "搜索";
             // 

+ 224 - 89
Fork.Net/Oreo.Plugins/Oreo.FileMan/Partial/FileTypePartial.cs

@@ -1,26 +1,29 @@
 using System;
 using System.Collections.Generic;
-using System.ComponentModel;
-using System.Drawing;
 using System.Data;
 using System.Linq;
-using System.Text;
 using System.Threading.Tasks;
 using System.Windows.Forms;
-using System.IO;
 using Y.Utils.DataUtils.Collections;
-using Y.Utils.IOUtils.FileUtils;
 using System.Threading;
-using Y.Utils.IOUtils.PathUtils;
 using Oreo.FileMan.Models;
 using Oreo.FileMan.DatabaseEngine;
-using Oreo.FileMan.Helpers;
 using Y.FileQueryEngine.QueryEngine;
+using Y.FileQueryEngine.UsnOperation;
+using System.IO;
+using Y.Utils.IOUtils.DriveUtils;
+using System.Data.SqlClient;
 
 namespace Oreo.FileMan.Partial
 {
     public partial class FileTypePartial : UserControl
     {
+        int GetTypeFileCountInterval = 60 * 1000;
+        int GetTypeFileCountDetailInterval = 1000;
+        int GetFileToDatabaseInterval = 60 * 1000;
+
+        int NewFileCount = 0;
+
         string[] TypeVideo = new string[] { ".mp4", ".rmvb", ".wma" };
         string[] TypeDoc = new string[] { ".doc", ".docx", ".xls", ".xlsx", ".ppt", ".pptx", ".txt" };
         string[] TypePicture = new string[] { ".jpg", ".bmp", ".png", ".icon", ".ico" };
@@ -34,122 +37,246 @@ namespace Oreo.FileMan.Partial
 
         private void FileTypePartial_Load(object sender, EventArgs e)
         {
-            Start();
+            TaskOfGetFileToDatabase();//获取磁盘所有文件到文件索引数据库
         }
 
-        void Start()
+        private void TaskOfGetFileToDatabase()
         {
-            if (true)
-            {
-                Task.Factory.StartNew(() => { GetAllFileToDb(); });
-            }
-
-            if (false)
+            Task.Factory.StartNew(() =>
             {
-                Task.Factory.StartNew(() =>
+                while (!IsDisposed)
                 {
-                    while (!IsDisposed)
-                    {
-                        Thread.Sleep(30 * 1000);
-
-                        //视频
-                        UISearchFileWaiting(LbVideoCount);
-                        Thread.Sleep(2000);
-                        int ctv = GetTypeFileCount(TypeVideo);
-                        UISetFileCount(LbVideoCount, ctv);
-                        //文档
-                        UISearchFileWaiting(LbDocCount);
-                        Thread.Sleep(2000);
-                        int ctd = GetTypeFileCount(TypeDoc);
-                        UISetFileCount(LbDocCount, ctd);
-                        //图片
-                        UISearchFileWaiting(LbPictureCount);
-                        Thread.Sleep(2000);
-                        int ctp = GetTypeFileCount(TypePicture);
-                        UISetFileCount(LbPictureCount, ctp);
-                        //音乐
-                        UISearchFileWaiting(LbMusicCount);
-                        Thread.Sleep(2000);
-                        int ctm = GetTypeFileCount(TypeMusic);
-                        UISetFileCount(LbMusicCount, ctm);
-                        //安装包
-                        UISearchFileWaiting(LbSetupCount);
-                        Thread.Sleep(2000);
-                        int cts = GetTypeFileCount(TypeSetup);
-                        UISetFileCount(LbSetupCount, cts);
-                        //压缩包
-                        UISearchFileWaiting(LbZipCount);
-                        Thread.Sleep(2000);
-                        int ctz = GetTypeFileCount(TypeZip);
-                        UISetFileCount(LbZipCount, ctz);
-
-                        UISearchFileWaiting(LbZipCount, false);
-                    }
-                });
-            }
+                    GetFileToDatabase2();
+                    GetTypeFileCount();
+                    Thread.Sleep(GetFileToDatabaseInterval);
+                }
+            });
         }
-
-        private int GetTypeFileCount(string[] type)
+        private void GetFileToDatabase()
         {
-            int result = 0;
-            try
+            var drives = FileQueryEngine.GetReadyNtfsDrives().OrderByDescending(x => x.Name);
+            if (ListTool.HasElements(drives))
             {
-                using (var db = new Muse())
+                foreach (var drive in drives)
                 {
-                    if (ListTool.HasElements(type))
+                    var usnList = FileQueryEngine.GetAllFiles(drive);
+                    if (ListTool.HasElements(usnList))
                     {
-                        foreach (var t in type)
+                        using (var db = new Muse())
                         {
-                            result += db.Set<Files>().Count(x => x.ExtName == t);
+                            //检测磁盘是否格式化,如果格式化则清空USN记录
+                            DateTime dt1 = DriveTool.GetLastFormatTime(drive.Name);
+                            var ds = db.Get<Drives>(x => x.Name == drive.Name, null);
+                            if ((ds == null) || (ds != null && ds.LastFormatTime != dt1.ToString()))
+                            {
+                                var fs = db.Gets<Files>(x => x.Drive == drive.Name, null);
+                                if (ListTool.HasElements(fs)) db.Dels(fs);
+
+                                if (ds == null)
+                                {
+                                    db.Add(new Drives() { Name = drive.Name, LastFormatTime = dt1.ToString() });
+                                }
+                                else
+                                {
+                                    ds.LastFormatTime = dt1.ToString();
+                                    db.Update(ds, true);
+                                }
+                            }
+
+                            //查询上次读取到的位置并读取USN
+                            if (db.Any<Files>(x => x.Drive == drive.Name, null))
+                            {
+                                long currentUsn = db.Do<Files>().Where(x => x.Drive == drive.Name).Max(x => x.Usn);
+                                usnList = usnList.Where(x => x.Usn > currentUsn).ToList();
+                            }
+                            //将记录存储到数据库中
+                            if (ListTool.HasElements(usnList))
+                            {
+                                //List<Files> temp = new List<Files>();
+                                for (int i = 0; i < usnList.Count; i++)
+                                {
+                                    UISetFileCount(i + 1, usnList.Count());
+
+                                    //temp.Add(new Files()
+                                    //{
+                                    //    Name = usnList[i].FileName,
+                                    //    IsFolder = usnList[i].IsFolder,
+                                    //    Number = usnList[i].FileReferenceNumber.ToString(),
+                                    //    ParentNumber = usnList[i].ParentFileReferenceNumber.ToString(),
+                                    //    Drive = drive.Name,
+                                    //    Usn = usnList[i].Usn,
+                                    //});
+                                    //if (temp.Count > 100)
+                                    //{
+                                    //    db.Adds(temp);
+                                    //    temp = new List<Files>();
+                                    //    Thread.Sleep(100);
+                                    //}
+                                    db.Add(new Files()
+                                    {
+                                        Name = usnList[i].FileName,
+                                        IsFolder = usnList[i].IsFolder,
+                                        Number = usnList[i].FileReferenceNumber.ToString(),
+                                        ParentNumber = usnList[i].ParentFileReferenceNumber.ToString(),
+                                        Drive = drive.Name,
+                                        Usn = usnList[i].Usn,
+                                    });
+                                }
+                                //db.Adds(temp);
+                            }
                         }
                     }
                 }
             }
-            catch (Exception e) { }
-            return result;
         }
-
-        private void GetAllFileToDb()
+        private void GetFileToDatabase2()
         {
+            using (var db = new Muse())
+            {
+                var a = db.Get(x=>x.);
+                //var a = db.Database.SqlQuery<Drives>("delete from drives where name = 'C:\\'", new SqlParameter("@name", @"C:\"));
+
+            }
+
             var drives = FileQueryEngine.GetReadyNtfsDrives().OrderByDescending(x => x.Name);
             if (ListTool.HasElements(drives))
             {
                 foreach (var drive in drives)
                 {
-                    var allFiles = FileQueryEngine.GetAllFiles(drive);
-                    int current = 0, total = allFiles.Count();
+                    NewFileCount = 0;
+                    //if (drive.Name.Contains("C")) continue;//测试时跳过C盘
+                    //if (drive.Name.Contains("D")) continue;//测试时跳过D盘
+
                     using (var db = new Muse())
                     {
-                        List<Files> temp = new List<Files>();
-                        while (ListTool.HasElements(allFiles))
+                        //检测磁盘是否格式化,如果格式化则清空USN记录
+                        DateTime dt1 = DriveTool.GetLastFormatTime(drive.Name);
+                        var ds = db.Get<Drives>(x => x.Name == drive.Name, null);
+                        if ((ds == null) || (ds != null && ds.LastFormatTime != dt1.ToString()))
                         {
-                            //if (!db.Set<Files>().Any(x => x.FullPath == file))
+                            var fs = db.Gets<Files>(x => x.Drive == drive.Name, null);
+                            if (ListTool.HasElements(fs))
+                            {
+                                //db.Dels(fs);
+                            }
 
-                            temp.Add(new Files()
+                            if (ds == null)
                             {
-                                FullPath = allFiles[0],
-                                FileName = Path.GetFileName(allFiles[0]),
-                                ExtName = Path.GetExtension(allFiles[0]),
-                                Size = FileTool.Size(allFiles[0]),
-                            });
-                            allFiles.RemoveAt(0);
-
-                            if (temp.Count() % 100 == 0)
+                                db.Add(new Drives() { Name = drive.Name, LastFormatTime = dt1.ToString() });
+                            }
+                            else
                             {
-                                UISetFileCount(current, total);
+                                ds.LastFormatTime = dt1.ToString();
+                                db.Update(ds, true);
                             }
-                            current++;
                         }
-                        UISetFileCount(current, total);
-                        db.Set<Files>().AddRange(temp);
-                        int count = db.SaveChanges();
-                        UISetFileCount(count, total);
+
+                        //查询上次读取到的位置
+                        long currentUsn = 0;
+                        if (db.Any<Files>(x => x.Drive == drive.Name, null))
+                        {
+                            currentUsn = db.Do<Files>().Where(x => x.Drive == drive.Name).Max(x => x.Usn) + 1;
+                        }
+                        //从上次Usn记录开始读取
+                        var usnOperator = new UsnOperator(drive);
+                        usnOperator.GetEntries(currentUsn, GetFileToDatabaseEvent, 1000);
+                    }
+                }
+            }
+        }
+        private void GetFileToDatabaseEvent(DriveInfo drive, List<UsnEntry> data)
+        {
+            List<Files> temp = new List<Files>();
+            if (ListTool.HasElements(data))
+            {
+                for (int i = 0; i < data.Count; i++)
+                {
+                    temp.Add(new Files()
+                    {
+                        Name = data[i].FileName,
+                        IsFolder = data[i].IsFolder,
+                        Number = data[i].FileReferenceNumber.ToString(),
+                        ParentNumber = data[i].ParentFileReferenceNumber.ToString(),
+                        Drive = drive.Name,
+                        Usn = data[i].Usn,
+                    });
+                    NewFileCount++;
+                }
+            }
+            using (var db = new Muse())
+            {
+                db.Adds(temp);
+            }
+            UISetFileCount(drive.Name, NewFileCount);
+        }
+        private void GetTypeFileCount()
+        {
+            //视频
+            UISearchFileWaiting(LbVideoCount);
+            Thread.Sleep(GetTypeFileCountDetailInterval);
+            int ctv = GetTypeFileCount(TypeVideo);
+            UISetFileCount(LbVideoCount, ctv);
+            //文档
+            UISearchFileWaiting(LbDocCount);
+            Thread.Sleep(GetTypeFileCountDetailInterval);
+            int ctd = GetTypeFileCount(TypeDoc);
+            UISetFileCount(LbDocCount, ctd);
+            //图片
+            UISearchFileWaiting(LbPictureCount);
+            Thread.Sleep(GetTypeFileCountDetailInterval);
+            int ctp = GetTypeFileCount(TypePicture);
+            UISetFileCount(LbPictureCount, ctp);
+            //音乐
+            UISearchFileWaiting(LbMusicCount);
+            Thread.Sleep(GetTypeFileCountDetailInterval);
+            int ctm = GetTypeFileCount(TypeMusic);
+            UISetFileCount(LbMusicCount, ctm);
+            //安装包
+            UISearchFileWaiting(LbSetupCount);
+            Thread.Sleep(GetTypeFileCountDetailInterval);
+            int cts = GetTypeFileCount(TypeSetup);
+            UISetFileCount(LbSetupCount, cts);
+            //压缩包
+            UISearchFileWaiting(LbZipCount);
+            Thread.Sleep(GetTypeFileCountDetailInterval);
+            int ctz = GetTypeFileCount(TypeZip);
+            UISetFileCount(LbZipCount, ctz);
+
+            UISearchFileWaiting(LbZipCount, false);
+            Thread.Sleep(GetTypeFileCountInterval);
+        }
+        private int GetTypeFileCount(string[] type)
+        {
+            int result = 0;
+            try
+            {
+                using (var db = new Muse())
+                {
+                    if (ListTool.HasElements(type))
+                    {
+                        foreach (var t in type)
+                        {
+                            var count = db.Do<Files>().Count(x => !x.IsFolder && x.Name.EndsWith(t));
+                            result += count;
+                            //foreach (var l in list)
+                            //{
+                            //    bool flag = FileQueryEngine.FileIsExist(l.Drive, l.Usn);
+                            //    if (flag) { result++; }
+                            //    else
+                            //    {
+                            //        db.Del(l, true);
+                            //    }
+                            //}
+                        }
                     }
                 }
-                //GC.Collect();
             }
+            catch (Exception e) { }
+            return result;
         }
 
+
+        #region UI操作
         /// <summary>
         /// 读取文件分类的加载动画
         /// </summary>
@@ -187,8 +314,16 @@ namespace Oreo.FileMan.Partial
         {
             BeginInvoke(new Action(() =>
             {
-                LbFileCount.Text = string.Format("{0} / {1}", current, total);
+                LbFileCount.Text = string.Format("已处理 {0} / 新增 {1} 项", current, total);
+            }));
+        }
+        void UISetFileCount(string drive, int number)
+        {
+            BeginInvoke(new Action(() =>
+            {
+                LbFileCount.Text = string.Format("磁盘 {0} 新增 {1} 项", drive, number);
             }));
         }
+        #endregion
     }
 }

+ 5 - 5
Fork.Net/Y.DB/DAO/IDbContext.cs

@@ -12,13 +12,13 @@ namespace Y.DB.DAO
     /// </summary>
     public interface IDbContext : IDisposable
     {
-        bool Add<T>(T EntityObj, bool isSave) where T : class;
-        bool Del<T>(T EntityObj, bool isSave) where T : class;
-        bool Update<T>(T EntityObj, bool isSave) where T : class;
-        bool Save();
+        int Add<T>(T EntityObj, bool isSave) where T : class;
+        int Del<T>(T EntityObj, bool isSave) where T : class;
+        int Update<T>(T EntityObj, bool isSave) where T : class;
+        int Save();
         T Get<T>(Expression<Func<T, bool>> expression, string[] include) where T : class;
         IEnumerable<T> Gets<T>(Expression<Func<T, bool>> expression, string[] include) where T : class;
-        IEnumerable<T> GetAll<T>(string[] include,bool track) where T : class;
+        IEnumerable<T> GetAll<T>(string[] include, bool track) where T : class;
         IEnumerable<T> ExecuteSqlCom<T, U>(string sql, U paramObjs) where T : class where U : class;
     }
 }

+ 31 - 14
Fork.Net/Y.DB/DAO/Muse.cs

@@ -17,7 +17,7 @@ namespace Y.DB.DAO
             db = new DbTable();
         }
 
-        public bool Add<T>(T EntityObj, bool isSave = true) where T : class
+        public int Add<T>(T EntityObj, bool isSave = true) where T : class
         {
             try
             {
@@ -28,9 +28,18 @@ namespace Y.DB.DAO
                 }
             }
             catch (Exception e) { }
-            return false;
+            return 0;
+        }
+        public int Adds<T>(IEnumerable<T> EntityObjs) where T : class
+        {
+            try
+            {
+                db.Set<T>().AddRange(EntityObjs);
+                return Save();
+            }
+            catch (Exception e) { return 0; }
         }
-        public bool Del<T>(T EntityObj, bool isSave) where T : class
+        public int Del<T>(T EntityObj, bool isSave) where T : class
         {
             try
             {
@@ -39,12 +48,21 @@ namespace Y.DB.DAO
                 {
                     return Save();
                 }
-                return false;
             }
             catch (Exception e) { }
-            return false;
+            return 0;
+        }
+        public int Dels<T>(IEnumerable<T> EntityObjs) where T : class
+        {
+            try
+            {
+                this.db.Set<T>().RemoveRange(EntityObjs);
+                return Save();
+            }
+            catch (Exception e) { }
+            return 0;
         }
-        public bool Update<T>(T EntityObj, bool isSave) where T : class
+        public int Update<T>(T EntityObj, bool isSave) where T : class
         {
             try
             {
@@ -53,14 +71,13 @@ namespace Y.DB.DAO
                 {
                     return Save();
                 }
-                return false;
             }
             catch (Exception e) { }
-            return false;
+            return 0;
         }
-        public bool Save()
+        public int Save()
         {
-            return db.SaveChanges() > 0;
+            return db.SaveChanges();
         }
 
         public T Get<T>(Expression<Func<T, bool>> expression, string[] include) where T : class
@@ -146,15 +163,15 @@ namespace Y.DB.DAO
         {
             return db.Set<T>();
         }
-        public void Dispose()
-        {
-            db.Dispose();
-        }
         public IEnumerable<T> ExecuteSqlCom<T, U>(string sql, U paramObjs)
             where U : class
             where T : class
         {
             return db.Set<T>().SqlQuery(sql, paramObjs);
         }
+        public void Dispose()
+        {
+            db.Dispose();
+        }
     }
 }

+ 23 - 0
Fork.Net/Y.Utils/DataUtils/Collections/ListTool.cs

@@ -9,24 +9,47 @@ namespace Y.Utils.DataUtils.Collections
 {
     public sealed class ListTool
     {
+        /// <summary>
+        /// 列表为空(null 或 count 等于 0)
+        /// </summary>
+        /// <param name="list"></param>
+        /// <returns></returns>
         public static bool IsNullOrEmpty(List<string> list)
         {
             if (list != null && list.Count() > 0)
                 return false;
             return true;
         }
+        /// <summary>
+        /// 列表为空(null 或 count 等于 0)
+        /// </summary>
+        /// <typeparam name="T"></typeparam>
+        /// <param name="list"></param>
+        /// <returns></returns>
         public static bool IsNullOrEmpty<T>(List<T> list)
         {
             if (list != null && list.Count() > 0)
                 return false;
             return true;
         }
+        /// <summary>
+        /// 列表为空(null 或 count 等于 0)
+        /// </summary>
+        /// <typeparam name="T"></typeparam>
+        /// <param name="list"></param>
+        /// <returns></returns>
         public static bool IsNullOrEmpty<T>(IEnumerable<T> list)
         {
             if (list != null && list.Count() > 0)
                 return false;
             return true;
         }
+        /// <summary>
+        /// 列表至少有一个元素
+        /// </summary>
+        /// <typeparam name="T"></typeparam>
+        /// <param name="list"></param>
+        /// <returns></returns>
         public static bool HasElements<T>(IEnumerable<T> list)
         {
             return !IsNullOrEmpty(list);

+ 33 - 0
Fork.Net/Y.Utils/IOUtils/DriveUtils/DriveTool.cs

@@ -0,0 +1,33 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Text;
+using Y.Utils.DataUtils.Collections;
+
+namespace Y.Utils.IOUtils.DriveUtils
+{
+    public class DriveTool
+    {
+        /// <summary>
+        /// 获取磁盘上次格式化时间
+        /// </summary>
+        /// <param name="dstr"></param>
+        /// <returns></returns>
+        public static DateTime GetLastFormatTime(string dstr)
+        {
+            string volInfo = dstr + "System Volume Information";
+            DateTime result = DateTime.Now;
+            if (Directory.Exists(volInfo))
+            {
+                try
+                {
+                    DirectoryInfo di = new DirectoryInfo(volInfo);
+                    result = di.CreationTime;
+                }
+                catch (Exception e) { }
+            }
+            return result;
+        }
+    }
+}

+ 1 - 0
Fork.Net/Y.Utils/Y.Utils.csproj

@@ -54,6 +54,7 @@
     <Compile Include="AppUtils\AppUnique.cs" />
     <Compile Include="DelegateUtils\ProgressDelegate.cs" />
     <Compile Include="DelegateUtils\ProgressEventArgs.cs" />
+    <Compile Include="IOUtils\DriveUtils\DriveTool.cs" />
     <Compile Include="IOUtils\FileUtils\FileCompressTool.cs" />
     <Compile Include="IOUtils\FileUtils\FilePackageModel.cs" />
     <Compile Include="IOUtils\FileUtils\FilePackageTool.cs" />