"use strict";
// SPDX-License-Identifier: AGPL-3.0-or-later
// Copyright (C) 2024-2026 Gracker (Chris)
// This file is part of SmartPerfetto. See LICENSE for details.
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.computeTraceContentHash = computeTraceContentHash;
exports.isFileBackedTrace = isFileBackedTrace;
/**
 * traceHash — content addressing for file-backed traces.
 *
 * The Scene Story disk cache keys reports by sha256 of the trace file
 * contents, so reopening the same trace produces the same lookup key
 * regardless of which `traceId` the upload was assigned. External RPC
 * traces (registered via TraceProcessorService.registerExternalRpc) have
 * no file on disk and therefore no content hash — those flow into the
 * memory cache instead, see `SceneReportMemoryCache`.
 */
const crypto_1 = __importDefault(require("crypto"));
const fs_1 = __importDefault(require("fs"));
/**
 * Compute the sha256 hex digest of the on-disk trace file.
 *
 * Returns `null` when:
 *  - The trace is external RPC (no file on disk to hash).
 *  - The file is missing (e.g. trace was deleted between cache check and hash).
 *  - The stream errors out mid-read.
 *
 * Streams the read in chunks so multi-GB traces don't blow up memory.
 * Tradeoff: hashing 1 GB on a fast SSD takes ~5-10s, so callers must
 * `await` this off any latency-sensitive code path.
 */
async function computeTraceContentHash(tps, traceId) {
    const filePath = tps.getTraceFilePath(traceId);
    // Skip the pre-check `existsSync` — the stream error handler already
    // covers ENOENT (file deleted between check and open is a classic TOCTOU
    // race). This saves one syscall per call.
    return new Promise((resolve) => {
        const hash = crypto_1.default.createHash('sha256');
        const stream = fs_1.default.createReadStream(filePath);
        stream.on('data', (chunk) => hash.update(chunk));
        stream.on('end', () => resolve(hash.digest('hex')));
        stream.on('error', (err) => {
            // ENOENT is expected for external-RPC traces (no file on disk) —
            // resolve null silently. Other errors get a warning.
            if (err.code !== 'ENOENT') {
                console.warn(`[traceHash] Failed to stream-hash trace ${traceId}:`, err?.message ?? err);
            }
            resolve(null);
        });
    });
}
/**
 * Quick boolean: does this trace have a backing file on disk?
 *
 * Used by callers that only need to pick a cache strategy (disk vs memory)
 * and don't actually need the hash. Cheaper than `computeTraceContentHash`
 * because it doesn't read the file.
 */
function isFileBackedTrace(tps, traceId) {
    return fs_1.default.existsSync(tps.getTraceFilePath(traceId));
}
//# sourceMappingURL=traceHash.js.map