searchSessionFile function

Future<SessionSearchOutcome> searchSessionFile(
  1. FileSystem fs,
  2. String sessionPath,
  3. SessionSearchQuery query, {
  4. Duration timeBudget = sessionSearchTimeBudget,
  5. int blockBytes = sessionSearchScanBlockBytes,
})

Searches a whole session file chain — the production path behind the session_search tool. Streams every segment (rotations included, per listSessionSegmentPaths) under the query's continuation token and a wall-clock timeBudget (E4/E5); never loads the file into memory. Map mode and branch scope pay one extra read-only census pass first (structure only — see searchRecords): the real pass then keeps its ordinal table bounded and caps true branch hits with full knowledge.

Implementation

Future<SessionSearchOutcome> searchSessionFile(
  FileSystem fs,
  String sessionPath,
  SessionSearchQuery query, {
  Duration timeBudget = sessionSearchTimeBudget,
  int blockBytes = sessionSearchScanBlockBytes,
}) async {
  final deadline = DateTime.now().add(timeBudget);
  final segments = await listSessionSegmentPaths(fs, sessionPath);
  final needsCensus =
      query.mode == SessionSearchMode.map ||
      (query.mode == SessionSearchMode.search &&
          query.scope == SessionSearchScope.branch);
  var ordinalWanted = const <String>{};
  var branchIds = const <String>{};
  if (needsCensus) {
    final census = _ScanAccumulator(
      query,
      deadline: deadline,
      censusOnly: true,
    );
    for (final segment in segments) {
      await _scanSessionSegment(fs, segment, census, blockBytes: blockBytes);
      if (census.stopped) break;
    }
    ordinalWanted = census._ordinalWanted;
    branchIds = census._walkChain(census._activeLeaf);
  }
  final accumulator = _ScanAccumulator(
    query,
    deadline: deadline,
    ordinalWanted: ordinalWanted,
    branchIds: branchIds,
  );
  for (final segment in segments) {
    await _scanSessionSegment(fs, segment, accumulator, blockBytes: blockBytes);
    if (accumulator.stopped) break;
  }
  return accumulator.finish();
}