/*!
 * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
 * Licensed under the MIT License.
 */
import { readAndParse } from "@fluidframework/driver-utils/internal";
import { SummaryTreeBuilder } from "@fluidframework/runtime-utils/internal";
export const redirectTableBlobName = ".redirectTable";
/**
 * @internal
 */
export const blobsTreeName = ".blobs";
/**
 * Reads blobs needed to load BlobManager from storage.
 *
 */
export const loadBlobManagerLoadInfo = async (context) => loadV1(context);
const loadV1 = async (context) => {
    const blobsTree = context.baseSnapshot?.trees[blobsTreeName];
    if (!blobsTree) {
        return {};
    }
    let redirectTableEntries = [];
    const tableId = blobsTree.blobs[redirectTableBlobName];
    if (tableId) {
        redirectTableEntries = await readAndParse(context.storage, tableId);
    }
    const ids = Object.entries(blobsTree.blobs)
        .filter(([k, _]) => k !== redirectTableBlobName)
        .map(([_, v]) => v);
    return { ids, redirectTable: redirectTableEntries };
};
export 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;
};
export const summarizeBlobManagerState = (redirectTable) => summarizeV1(redirectTable);
const summarizeV1 = (redirectTable) => {
    const builder = new SummaryTreeBuilder();
    const storageIds = 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(redirectTableBlobName, JSON.stringify(nonIdentityRedirectTableEntries));
    }
    return builder.getSummaryTree();
};
export const getStorageIds = (redirectTable) => {
    return new Set(redirectTable.values());
};
//# sourceMappingURL=blobManagerSnapSum.js.map