{"version":3,"file":"downloadPlanBuilder.js","sourceRoot":"","sources":["../../src/differentialDownloader/downloadPlanBuilder.ts"],"names":[],"mappings":"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","sourcesContent":["import { BlockMap, BlockMapFile } from \"builder-util-runtime/out/blockMapApi\"\nimport { Logger } from \"../types\"\n\nexport enum OperationKind {\n  COPY,\n  DOWNLOAD,\n}\n\nexport interface Operation {\n  kind: OperationKind\n\n  // inclusive\n  start: number\n  // exclusive\n  end: number\n\n  // debug only\n  // oldBlocks: Array<string> | null\n}\n\nexport function computeOperations(oldBlockMap: BlockMap, newBlockMap: BlockMap, logger: Logger): Array<Operation> {\n  const nameToOldBlocks = buildBlockFileMap(oldBlockMap.files)\n  const nameToNewBlocks = buildBlockFileMap(newBlockMap.files)\n\n  let lastOperation: Operation | null = null\n\n  // for now only one file is supported in block map\n  const blockMapFile: { name: string; offset: number } = newBlockMap.files[0]\n  const operations: Array<Operation> = []\n  const name = blockMapFile.name\n  const oldEntry = nameToOldBlocks.get(name)\n  if (oldEntry == null) {\n    // new file (unrealistic case for now, because in any case both blockmap contain the only file named as \"file\")\n    throw new Error(`no file ${name} in old blockmap`)\n  }\n\n  const newFile = nameToNewBlocks.get(name)!\n  let changedBlockCount = 0\n\n  const { checksumToOffset: checksumToOldOffset, checksumToOldSize } = buildChecksumMap(nameToOldBlocks.get(name)!, oldEntry.offset, logger)\n\n  let newOffset = blockMapFile.offset\n  for (let i = 0; i < newFile.checksums.length; newOffset += newFile.sizes[i], i++) {\n    const blockSize: number = newFile.sizes[i]\n    const checksum = newFile.checksums[i]\n    let oldOffset = checksumToOldOffset.get(checksum)\n    if (oldOffset != null && checksumToOldSize.get(checksum) !== blockSize) {\n      logger.warn(`Checksum (\"${checksum}\") matches, but size differs (old: ${checksumToOldSize.get(checksum)}, new: ${blockSize})`)\n      oldOffset = undefined\n    }\n\n    if (oldOffset === undefined) {\n      // download data from new file\n      changedBlockCount++\n\n      if (lastOperation != null && lastOperation.kind === OperationKind.DOWNLOAD && lastOperation.end === newOffset) {\n        lastOperation.end += blockSize\n      } else {\n        lastOperation = {\n          kind: OperationKind.DOWNLOAD,\n          start: newOffset,\n          end: newOffset + blockSize,\n          // oldBlocks: null,\n        }\n        validateAndAdd(lastOperation, operations, checksum, i)\n      }\n    } else {\n      // reuse data from old file\n      if (lastOperation != null && lastOperation.kind === OperationKind.COPY && lastOperation.end === oldOffset) {\n        lastOperation.end += blockSize\n        // lastOperation.oldBlocks!!.push(checksum)\n      } else {\n        lastOperation = {\n          kind: OperationKind.COPY,\n          start: oldOffset,\n          end: oldOffset + blockSize,\n          // oldBlocks: [checksum]\n        }\n        validateAndAdd(lastOperation, operations, checksum, i)\n      }\n    }\n  }\n\n  if (changedBlockCount > 0) {\n    logger.info(`File${blockMapFile.name === \"file\" ? \"\" : \" \" + blockMapFile.name} has ${changedBlockCount} changed blocks`)\n  }\n  return operations\n}\n\nconst isValidateOperationRange = process.env[\"DIFFERENTIAL_DOWNLOAD_PLAN_BUILDER_VALIDATE_RANGES\"] === \"true\"\n\nfunction validateAndAdd(operation: Operation, operations: Array<Operation>, checksum: string, index: number): void {\n  if (isValidateOperationRange && operations.length !== 0) {\n    const lastOperation = operations[operations.length - 1]\n    if (lastOperation.kind === operation.kind && operation.start < lastOperation.end && operation.start > lastOperation.start) {\n      const min = [lastOperation.start, lastOperation.end, operation.start, operation.end].reduce((p, v) => (p < v ? p : v))\n      throw new Error(\n        `operation (block index: ${index}, checksum: ${checksum}, kind: ${OperationKind[operation.kind]}) overlaps previous operation (checksum: ${checksum}):\\n` +\n          `abs: ${lastOperation.start} until ${lastOperation.end} and ${operation.start} until ${operation.end}\\n` +\n          `rel: ${lastOperation.start - min} until ${lastOperation.end - min} and ${operation.start - min} until ${operation.end - min}`\n      )\n    }\n  }\n  operations.push(operation)\n}\n\nfunction buildChecksumMap(file: BlockMapFile, fileOffset: number, logger: Logger) {\n  const checksumToOffset = new Map<string, number>()\n  const checksumToSize = new Map<string, number>()\n  let offset = fileOffset\n  for (let i = 0; i < file.checksums.length; i++) {\n    const checksum = file.checksums[i]\n    const size = file.sizes[i]\n\n    const existing = checksumToSize.get(checksum)\n    if (existing === undefined) {\n      checksumToOffset.set(checksum, offset)\n      checksumToSize.set(checksum, size)\n    } else if (logger.debug != null) {\n      const sizeExplanation = existing === size ? \"(same size)\" : `(size: ${existing}, this size: ${size})`\n      logger.debug(`${checksum} duplicated in blockmap ${sizeExplanation}, it doesn't lead to broken differential downloader, just corresponding block will be skipped)`)\n    }\n    offset += size\n  }\n  return { checksumToOffset, checksumToOldSize: checksumToSize }\n}\n\nfunction buildBlockFileMap(list: Array<BlockMapFile>): Map<string, BlockMapFile> {\n  const result = new Map<string, BlockMapFile>()\n  for (const item of list) {\n    result.set(item.name, item)\n  }\n  return result\n}\n"]}