From 5bedff1e636cb2112f53cf147787d6782a13119c Mon Sep 17 00:00:00 2001 From: cgeek <cem.moreau@gmail.com> Date: Sat, 21 Jul 2018 11:27:03 +0200 Subject: [PATCH] [fix] dal: `getBlocks` function was broken if the chunk was targeting the archives --- app/lib/dal/fileDAL.ts | 21 +++++++- app/lib/dal/indexDAL/CFSBlockchainArchive.ts | 53 ++++++++++++++++--- .../indexDAL/abstract/BlockchainArchiveDAO.ts | 8 +++ 3 files changed, 73 insertions(+), 9 deletions(-) diff --git a/app/lib/dal/fileDAL.ts b/app/lib/dal/fileDAL.ts index 62e3799da..d4c0bb389 100644 --- a/app/lib/dal/fileDAL.ts +++ b/app/lib/dal/fileDAL.ts @@ -412,8 +412,25 @@ export class FileDAL { return this.blockDAL.getCountOfBlocksIssuedBy(issuer) } - getBlocksBetween (start:number, end:number) { - return this.blockDAL.getBlocks(Math.max(0, start), end) + async getBlocksBetween (start:number, end:number) { + start = Math.max(0, start) + end= Math.max(0, end) + const blocks = await this.blockDAL.getBlocks(Math.max(0, start), end) + if (blocks[0] && blocks[0].number === start) { + // OK: we have all the blocks from memory + return blocks + } + // Else: we have to pick them from archives + const last = blocks[0] ? blocks[0].number - 1 : end + const archiveBlocks = await this.blockchainArchiveDAL.getBlocks(start, last) + const lastInArchives = archiveBlocks[archiveBlocks.length - 1] ? archiveBlocks[archiveBlocks.length - 1].number - 1 : end + if (lastInArchives === end) { + // OK: we have all the blocks from archives + return archiveBlocks + } + // Otherwise: what is not taken in the archives are in memory + const memBlocks = await this.blockDAL.getBlocks(archiveBlocks[archiveBlocks.length - 1].number + 1, end) + return archiveBlocks.concat(memBlocks) } getForkBlocksFollowing(current:DBBlock) { diff --git a/app/lib/dal/indexDAL/CFSBlockchainArchive.ts b/app/lib/dal/indexDAL/CFSBlockchainArchive.ts index 361315590..44fb159e3 100644 --- a/app/lib/dal/indexDAL/CFSBlockchainArchive.ts +++ b/app/lib/dal/indexDAL/CFSBlockchainArchive.ts @@ -1,5 +1,6 @@ import {BlockchainArchiveDAO, BlockLike} from "./abstract/BlockchainArchiveDAO" import {CFSCore} from "../fileDALs/CFSCore" +import {Underscore} from "../../common-libs/underscore" export class CFSBlockchainArchive<T extends BlockLike> implements BlockchainArchiveDAO<T> { @@ -15,7 +16,7 @@ export class CFSBlockchainArchive<T extends BlockLike> implements BlockchainArch } const chunks = this.splitIntoChunks(records) for (const c of chunks) { - const fileName = this.getFileName(c[0].number) + const fileName = this.getFileNameForBlock(c[0].number) await this.cfs.writeJSON(fileName, c) } return chunks.length @@ -62,7 +63,7 @@ export class CFSBlockchainArchive<T extends BlockLike> implements BlockchainArch if (number < 0) { return null } - const content = await this.getChunk(number) + const content = await this.getChunkForBlock(number) if (!content) { // The block's chunk is not archived return null @@ -70,8 +71,38 @@ export class CFSBlockchainArchive<T extends BlockLike> implements BlockchainArch return content[this.getPositionInChunk(number)] } + async getBlocks(start: number, end: number): Promise<T[]> { + const chunkStart = this.getChunkNumber(start) + const chunkLast = this.getChunkNumber(end) + const chunkRange = Underscore.range(chunkStart, chunkLast + 1) + const chunks = await Promise.all(chunkRange.map(c => this.getChunk(c))) + const startInFirst = start - chunkStart * this._chunkSize + const endInLast = end % this._chunkSize + 1 + let blocks: T[] = [] + for (let i = 0; i < chunks.length; i++) { + let toConcat: T[]Â = [] + const chunk = chunks[i] + if (chunk) { + if (i === 0) { + toConcat = chunk.slice(startInFirst, chunkStart === chunkLast ? endInLast : this._chunkSize) + } else if (i === chunks.length - 1) { + toConcat = chunk.slice(0, endInLast) + } else { + toConcat = chunk.slice() + } + } + blocks = blocks.concat(toConcat) + } + return blocks + } + async getChunk(number:number): Promise<(T[])|null> { - const file = this.getFileName(number) + const file = this.getFileNameForChunk(number) + return this.cfs.readJSON(file) + } + + async getChunkForBlock(number:number): Promise<(T[])|null> { + const file = this.getFileNameForBlock(number) return this.cfs.readJSON(file) } @@ -84,19 +115,27 @@ export class CFSBlockchainArchive<T extends BlockLike> implements BlockchainArch .reduce((v, max) => { return Math.max(v, max) }, 0) - const content = await this.getChunk(max * this._chunkSize) + const content = await this.getChunkForBlock(max * this._chunkSize) if (!content) { return null } return this.getBlock(content[content.length - 1].number, content[content.length - 1].hash) } - private getFileName(number:number) { - const rest = number % this._chunkSize - const chunk = (number - rest) / this._chunkSize + private getFileNameForChunk(number:number) { + return CFSBlockchainArchive.getChunkName(number, this._chunkSize) + } + + private getFileNameForBlock(number:number) { + const chunk = this.getChunkNumber(number) return CFSBlockchainArchive.getChunkName(chunk, this._chunkSize) } + private getChunkNumber(number:number) { + const rest = number % this._chunkSize + return (number - rest) / this._chunkSize + } + private static getChunkName(chunkNumber:number, chunkSize:number) { return `chunk_${chunkNumber}-${chunkSize}.json` } diff --git a/app/lib/dal/indexDAL/abstract/BlockchainArchiveDAO.ts b/app/lib/dal/indexDAL/abstract/BlockchainArchiveDAO.ts index 123c169ea..59e655c36 100644 --- a/app/lib/dal/indexDAL/abstract/BlockchainArchiveDAO.ts +++ b/app/lib/dal/indexDAL/abstract/BlockchainArchiveDAO.ts @@ -29,6 +29,14 @@ export interface BlockchainArchiveDAO<T extends BlockLike> extends Initiable { */ getBlockByNumber(number:number): Promise<T|null> + /** + * Get the blocks whose number is between [start ; end]. + * @param {number} start Starting number to be included. + * @param {number} end Ending number to be included. + * @returns {Promise<T[]>} The corresponding blocks. + */ + getBlocks(start: number, end: number): Promise<T[]> + /** * Archives a suite of blocks. * -- GitLab