namespace FluidExplorer.Services.Search; public enum IndexState { NotStarted, RequiresElevation, Building, Ready, Watching, Failed, Stopped } /// 索引里的一条记录(NTFS USN 数据的最小集合)。 public readonly record struct IndexedEntry( ulong Frn, ulong ParentFrn, string Name, bool IsDirectory, long Size, DateTime ModifiedUtc, uint Attributes) { /// 非 NTFS / 非索引来源(例如回退扫描器)可直接携带完整路径。 public string? FullPath { get; init; } public string Extension { get { if (IsDirectory) return string.Empty; var i = Name.LastIndexOf('.'); return i > 0 && i < Name.Length - 1 ? Name[(i + 1)..] : string.Empty; } } } public sealed class IndexStateChangedEventArgs(IndexState state, string? message = null) : EventArgs { public IndexState State { get; } = state; public string? Message { get; } = message; } /// /// 单卷文件索引:Everything 式体验的核心。 /// 实现必须做到:构建阶段不阻塞调用线程(内部自行使用线程池)、 /// 支持增量更新(USN 日志)、查询使用并行扫描并在毫秒级返回。 /// public interface IFileIndex { /// 卷根,例如 "C:\"。 string VolumeRoot { get; } IndexState State { get; } long EntryCount { get; } event EventHandler? StateChanged; /// 建立初始索引(枚举 MFT / 扫描)。可重复调用,完成后自动转入 Watching。 Task BuildAsync(IProgress? progress, CancellationToken cancellationToken); /// 启动增量监听(USN journal),保持索引实时。 void StartWatching(); void Stop(); /// /// 查询。实现约定: /// 1) 先按 IncludeTerms/Extensions/大小/时间/属性过滤(纯内存操作,必须并行化); /// 2) 仅当 不为空时,才对已命中的候选调用路径解析; /// 3) 命中数达到 maxResults 即可提前返回,但不要漏掉更"好"的匹配(短名优先)。 /// IEnumerable Query(SearchQuery query, int maxResults, CancellationToken cancellationToken); /// 把 FRN 解析为完整路径(内部要缓存父链解析结果)。失败返回 false。 bool TryResolvePath(ulong frn, out string fullPath); }