"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.computeOperations = computeOperations; exports.OperationKind = void 0; var OperationKind; exports.OperationKind = OperationKind; (function (OperationKind) { OperationKind[OperationKind["COPY"] = 0] = "COPY"; OperationKind[OperationKind["DOWNLOAD"] = 1] = "DOWNLOAD"; })(OperationKind || (exports.OperationKind = OperationKind = {})); function computeOperations(oldBlockMap, newBlockMap, logger) { const nameToOldBlocks = buildBlockFileMap(oldBlockMap.files); const nameToNewBlocks = buildBlockFileMap(newBlockMap.files); const oldEntryMap = buildEntryMap(oldBlockMap.files); let lastOperation = null; const operations = []; for (const blockMapFile of newBlockMap.files) { const name = blockMapFile.name; const oldEntry = oldEntryMap.get(name); if (oldEntry == null) { // new file operations.push({ kind: OperationKind.DOWNLOAD, start: blockMapFile.offset, end: blockMapFile.offset + blockMapFile.sizes.reduce((accumulator, currentValue) => accumulator + currentValue) }); continue; } const newFile = nameToNewBlocks.get(name); let changedBlockCount = 0; const { checksumToOffset: checksumToOldOffset, checksumToOldSize } = buildChecksumMap(nameToOldBlocks.get(name), oldEntry.offset); let newOffset = blockMapFile.offset; for (let i = 0; i < newFile.checksums.length; newOffset += newFile.sizes[i], i++) { const blockSize = newFile.sizes[i]; const checksum = newFile.checksums[i]; let oldOffset = checksumToOldOffset.get(checksum); if (oldOffset != null && checksumToOldSize.get(checksum) !== blockSize) { logger.warn(`Checksum ("${checksum}") matches, but size differs (old: ${checksumToOldSize.get(checksum)}, new: ${blockSize})`); oldOffset = null; } if (oldOffset == null) { changedBlockCount++; if (lastOperation == null || lastOperation.kind !== OperationKind.DOWNLOAD || lastOperation.end !== newOffset) { lastOperation = { kind: OperationKind.DOWNLOAD, start: newOffset, end: newOffset + blockSize }; operations.push(lastOperation); } else { lastOperation.end += blockSize; } } else if (lastOperation == null || lastOperation.kind !== OperationKind.COPY || lastOperation.end !== oldOffset) { lastOperation = { kind: OperationKind.COPY, start: oldOffset, end: oldOffset + blockSize }; operations.push(lastOperation); } else { lastOperation.end += blockSize; } } if (changedBlockCount > 0) { logger.info(`File${blockMapFile.name === "file" ? "" : " " + blockMapFile.name} has ${changedBlockCount} changed blocks`); } } return operations; } function buildChecksumMap(file, fileOffset) { const checksumToOffset = new Map(); const checksumToSize = new Map(); let offset = fileOffset; for (let i = 0; i < file.checksums.length; i++) { const checksum = file.checksums[i]; const size = file.sizes[i]; checksumToOffset.set(checksum, offset); checksumToSize.set(checksum, size); offset += size; } return { checksumToOffset, checksumToOldSize: checksumToSize }; } function buildEntryMap(list) { const result = new Map(); for (const item of list) { result.set(item.name, item); } return result; } function buildBlockFileMap(list) { const result = new Map(); for (const item of list) { result.set(item.name, item); } return result; } //# sourceMappingURL=downloadPlanBuilder.js.map