"use strict";
/*!
 * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
 * Licensed under the MIT License.
 */
Object.defineProperty(exports, "__esModule", { value: true });
exports.getStorageIds = exports.summarizeBlobManagerState = exports.toRedirectTable = exports.loadBlobManagerLoadInfo = exports.blobsTreeName = exports.redirectTableBlobName = void 0;
const internal_1 = require("@fluidframework/driver-utils/internal");
const internal_2 = require("@fluidframework/runtime-utils/internal");
exports.redirectTableBlobName = ".redirectTable";
/**
 * @internal
 */
exports.blobsTreeName = ".blobs";
/**
 * Reads blobs needed to load BlobManager from storage.
 *
 */
const loadBlobManagerLoadInfo = async (context) => loadV1(context);
exports.loadBlobManagerLoadInfo = loadBlobManagerLoadInfo;
const loadV1 = async (context) => {
    const blobsTree = context.baseSnapshot?.trees[exports.blobsTreeName];
    if (!blobsTree) {
        return {};
    }
    let redirectTableEntries = [];
    const tableId = blobsTree.blobs[exports.redirectTableBlobName];
    if (tableId) {
        redirectTableEntries = await (0, internal_1.readAndParse)(context.storage, tableId);
    }
    const ids = Object.entries(blobsTree.blobs)
        .filter(([k, _]) => k !== exports.redirectTableBlobName)
        .map(([_, v]) => v);
    return { ids, redirectTable: redirectTableEntries };
};
const toRedirectTable = (blobManagerLoadInfo, logger) => {
    logger.sendTelemetryEvent({
        eventName: "AttachmentBlobsLoaded",
        count: blobManagerLoadInfo.ids?.length ?? 0,
        redirectTable: blobManagerLoadInfo.redirectTable?.length,
    });
    const redirectTable = new Map(blobManagerLoadInfo.redirectTable);
    if (blobManagerLoadInfo.ids !== undefined) {
        for (const storageId of blobManagerLoadInfo.ids) {
            // Older versions of the runtime used the storage ID directly in the handle,
            // rather than routing through the redirectTable. To support old handles that
            // were created in this way but unify handling through the redirectTable, we
            // add identity mappings to the redirect table at load. These identity entries
            // will be excluded during summarization.
            redirectTable.set(storageId, storageId);
        }
    }
    return redirectTable;
};
exports.toRedirectTable = toRedirectTable;
const summarizeBlobManagerState = (redirectTable) => summarizeV1(redirectTable);
exports.summarizeBlobManagerState = summarizeBlobManagerState;
const summarizeV1 = (redirectTable) => {
    const builder = new internal_2.SummaryTreeBuilder();
    const storageIds = (0, exports.getStorageIds)(redirectTable);
    for (const storageId of storageIds) {
        // The Attachment is inspectable by storage, which lets it detect that the blob is referenced
        // and therefore should not be GC'd.
        builder.addAttachment(storageId);
    }
    // Exclude identity mappings from the redirectTable summary. Note that
    // the storageIds of the identity mappings are still included in the Attachments
    // above, so we expect these identity mappings will be recreated at load
    // time in toRedirectTable even if there is no non-identity mapping in
    // the redirectTable.
    const nonIdentityRedirectTableEntries = [...redirectTable.entries()].filter(([localId, storageId]) => localId !== storageId);
    if (nonIdentityRedirectTableEntries.length > 0) {
        builder.addBlob(exports.redirectTableBlobName, JSON.stringify(nonIdentityRedirectTableEntries));
    }
    return builder.getSummaryTree();
};
const getStorageIds = (redirectTable) => {
    return new Set(redirectTable.values());
};
exports.getStorageIds = getStorageIds;
//# sourceMappingURL=blobManagerSnapSum.js.map