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