Quellcode durchsuchen

MK2: Folder scan

HOME vor 7 Monaten
Ursprung
Commit
970b091650

FNZCM2/FNZCM2.Abstractions/ideas/ASPNET-HTTP/RangeRequest.md → FNZCM2/FNZCM2.Abstractions/@Ideas/ASPNET-HTTP/RangeRequest.md


FNZCM2/FNZCM2.Abstractions/ideas/MediaLib/FolderStructure.md → FNZCM2/FNZCM2.Abstractions/@Ideas/MediaLib/FolderStructure.md


FNZCM2/FNZCM2.Abstractions/ideas/MediaLib/ModelAlbumMetadata.md → FNZCM2/FNZCM2.Abstractions/@Ideas/MediaLib/ModelAlbumMetadata.md


FNZCM2/FNZCM2.Abstractions/ideas/MediaLib/ModelCacheMeta.md → FNZCM2/FNZCM2.Abstractions/@Ideas/MediaLib/ModelCacheMeta.md


FNZCM2/FNZCM2.Abstractions/ideas/ScanExistedFolder/ExistedAlbumFolder.md → FNZCM2/FNZCM2.Abstractions/@Ideas/ScanExistedFolder/ExistedAlbumFolder.md


FNZCM2/FNZCM2.Abstractions/ideas/ScanExistedFolder/ExistedLibraryFolder.md → FNZCM2/FNZCM2.Abstractions/@Ideas/ScanExistedFolder/ExistedLibraryFolder.md


FNZCM2/FNZCM2.Abstractions/ideas/ScanExistedFolder/IOAPI.md → FNZCM2/FNZCM2.Abstractions/@Ideas/ScanExistedFolder/IOAPI.md


+ 21 - 0
FNZCM2/FNZCM2.Abstractions/Models/Fs/FileEntry.cs

@@ -0,0 +1,21 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace FNZCM2.Abstractions.Models.Fs;
+
+[DebuggerDisplay("F {Id} # {Name} # {Size}")]
+public class FileEntry : IFsEntry
+{
+    public required long Id { get; init; }
+
+    /// <summary> zero for root </summary>
+    public required long FolderId { get; init; }
+
+    public required string Name { get; init; }
+    public required long Size { get; init; }
+    public required DateTimeOffset LastChangedTime { get; init; }
+}

+ 15 - 0
FNZCM2/FNZCM2.Abstractions/Models/Fs/FolderEntry.cs

@@ -0,0 +1,15 @@
+using System.Diagnostics;
+
+namespace FNZCM2.Abstractions.Models.Fs;
+
+[DebuggerDisplay("D {Id} # {Name}")]
+public class FolderEntry : IFsEntry
+{
+    public required long Id { get; init; }
+    
+    /// <summary> zero for root </summary>
+    public required long FolderId { get; init; }
+
+    public required string Name { get; init; }
+    public required DateTimeOffset LastChangedTime { get; init; }
+}

+ 12 - 0
FNZCM2/FNZCM2.Abstractions/Models/Fs/IFsEntry.cs

@@ -0,0 +1,12 @@
+namespace FNZCM2.Abstractions.Models.Fs;
+
+public interface IFsEntry
+{
+    public long Id { get;  }
+
+    /// <summary> zero for root </summary>
+    public long FolderId { get;  }
+
+    public string Name { get; }
+    public DateTimeOffset LastChangedTime { get; }
+}

+ 132 - 0
FNZCM2/FNZCM2.Abstractions/Utility/FolderScan.cs

@@ -0,0 +1,132 @@
+using System.IO.Enumeration;
+using FNZCM2.Abstractions.Models.Fs;
+
+namespace FNZCM2.Abstractions.Utility;
+
+using FSE = (bool isDir, string path, long size, System.DateTimeOffset lastWrited);
+
+public static class FolderScan
+{
+    public static FolderScanResult Scan(string folderPath)
+    {
+        List<IFsEntry> allEntries = new();
+        List<FolderEntry> allFolders = new();
+        List<FileEntry> allFiles = new();
+
+        Dictionary<string, long> folderPathToIdCache = new();
+        long GetFolderId(string path)
+        {
+            if (folderPathToIdCache.TryGetValue(path, out var fid)) return fid;
+
+            var parts = path.Split(Path.DirectorySeparatorChar);
+
+            fid = 0;
+            foreach (var s in parts)
+            {
+                var d = allFolders.First(p => p.FolderId == fid && p.Name == s);
+                fid = d.Id;
+            }
+
+            folderPathToIdCache[path] = fid;
+            return fid;
+        }
+
+        var fullPath = Path.GetFullPath(folderPath);
+
+        var fse = new FileSystemEnumerable<FSE>(
+            fullPath,
+            (ref FileSystemEntry p) => new(
+                p.IsDirectory,
+                p.ToFullPath(),
+                p.Length,
+                p.LastWriteTimeUtc
+            ),
+            new()
+            {
+                RecurseSubdirectories = true,
+            });
+
+        var trimPathPrefixLength = fullPath.Length + 1;
+
+        foreach (var e in fse)
+        {
+            var rPath = e.path.Substring(trimPathPrefixLength);
+
+            var directoryName = Path.GetDirectoryName(rPath);
+            var fileName = Path.GetFileName(rPath);
+            var folderId = string.IsNullOrEmpty(directoryName) ? 0 : GetFolderId(directoryName!);
+
+            if (e.isDir)
+            {
+                var folderEntry = new FolderEntry
+                {
+                    Id = DateTime.Now.Ticks,
+                    FolderId = folderId,
+                    Name = fileName,
+                    LastChangedTime = e.lastWrited,
+                };
+
+                allEntries.Add(folderEntry);
+                allFolders.Add(folderEntry);
+            }
+            else
+            {
+                var fileEntry = new FileEntry
+                {
+                    Id = DateTime.Now.Ticks,
+                    FolderId = folderId,
+                    Name = fileName,
+                    LastChangedTime = e.lastWrited,
+                    Size = e.size,
+                };
+
+                allEntries.Add(fileEntry);
+                allFiles.Add(fileEntry);
+            }
+        }
+
+        var allById = allEntries.ToDictionary(e => e.Id);
+        var allInFolder = allEntries
+            .GroupBy(e => e.FolderId)
+            .ToDictionary(g => g.Key, g => (IReadOnlyList<IFsEntry>)g.ToArray());
+
+        var folderById = allFolders.ToDictionary(f => f.Id);
+        var foldersInFolder = allFolders
+            .GroupBy(f => f.FolderId)
+            .ToDictionary(g => g.Key, g => (IReadOnlyList<FolderEntry>)g.ToArray());
+
+        var fileById = allFiles.ToDictionary(f => f.Id);
+        var filesInFolder = allFiles
+            .GroupBy(f => f.FolderId)
+            .ToDictionary(g => g.Key, g => (IReadOnlyList<FileEntry>)g.ToArray());
+
+        return new FolderScanResult
+        {
+            All = allEntries,
+            AllById = allById,
+            AllInFolder = allInFolder,
+            Folders = allFolders,
+            FolderById = folderById,
+            FoldersInFolder = foldersInFolder,
+            Files = allFiles,
+            FileById = fileById,
+            FilesInFolder = filesInFolder,
+            //add folderPathToIdCache on demands
+        };
+    }
+}
+
+public class FolderScanResult
+{
+    public required IReadOnlyList<IFsEntry> All { get; init; }
+    public required IReadOnlyDictionary<long, IFsEntry> AllById { get; init; }
+    public required IReadOnlyDictionary<long, IReadOnlyList<IFsEntry>> AllInFolder { get; init; }
+
+    public required IReadOnlyList<FolderEntry> Folders { get; init; }
+    public required IReadOnlyDictionary<long, FolderEntry> FolderById { get; init; }
+    public required IReadOnlyDictionary<long, IReadOnlyList<FolderEntry>> FoldersInFolder { get; init; }
+
+    public required IReadOnlyList<FileEntry> Files { get; init; }
+    public required IReadOnlyDictionary<long, FileEntry> FileById { get; init; }
+    public required IReadOnlyDictionary<long, IReadOnlyList<FileEntry>> FilesInFolder { get; init; }
+}

+ 4 - 0
FNZCM2/FNZCM2.ProofOfConcept/FNZCM2.ProofOfConcept.csproj

@@ -7,4 +7,8 @@
     <Nullable>enable</Nullable>
   </PropertyGroup>
 
+  <ItemGroup>
+    <ProjectReference Include="..\FNZCM2.Abstractions\FNZCM2.Abstractions.csproj" />
+  </ItemGroup>
+
 </Project>

+ 1 - 1
FNZCM2/FNZCM2.ProofOfConcept/PocScanFolder.cs

@@ -3,7 +3,7 @@ using FSE = (bool isDir, string path, long size, System.DateTimeOffset lastWrite
 
 namespace FNZCM2.ProofOfConcept;
 
-internal static class PocScanFolder
+internal static class PocFolderScanByFileSystemEnumerable
 {
     public static void RunPoc()
     {

+ 12 - 0
FNZCM2/FNZCM2.ProofOfConcept/PocFolderScanImplement.cs

@@ -0,0 +1,12 @@
+using FNZCM2.Abstractions.Utility;
+
+namespace FNZCM2.ProofOfConcept;
+
+internal static class PocFolderScanImplement
+{
+    public static void RunPoc()
+    {
+        var r = FolderScan.Scan("library");
+        int bp = 0;
+    }
+}

+ 2 - 1
FNZCM2/FNZCM2.ProofOfConcept/Program.cs

@@ -5,6 +5,7 @@ using FNZCM2.ProofOfConcept;
 Console.WriteLine("Hello, World!");
 
 //PocTickAsUUID.RunPoc();
-PocScanFolder.RunPoc();
+//PocFolderScanByFileSystemEnumerable.RunPoc();
+PocFolderScanImplement.RunPoc();
 
 Console.WriteLine("Goodbye, World!");