diff --git a/app/lib/dal/indexDAL/abstract/GenericDAO.ts b/app/lib/dal/indexDAL/abstract/GenericDAO.ts index 64382b3f0b677fecfeacc3c16b3263fecee9458d..500899136bffbaf86ff136b4b8c2c3dc342d3704 100644 --- a/app/lib/dal/indexDAL/abstract/GenericDAO.ts +++ b/app/lib/dal/indexDAL/abstract/GenericDAO.ts @@ -14,6 +14,14 @@ export interface GenericDAO<T> extends Initiable { */ findRaw(criterion: any): Promise<any> + /** + * Make a generic find with some ordering. + * @param criterion Criterion object, LokiJS's find object format. + * @param sort A LokiJS's compunded sort object. + * @returns {Promise<any>} A set of records. + */ + findRawWithOrder(criterion: any, sort:((string|((string|boolean)[]))[])): Promise<any> + /** * Make a single insert. * @param record The record to insert. diff --git a/app/lib/dal/indexDAL/loki/LokiIndex.ts b/app/lib/dal/indexDAL/loki/LokiIndex.ts index 1197d56c766bca32eba38bb2ea1239bd7585ec57..6283a831244c629ed2057cf9e28589e064a51279 100644 --- a/app/lib/dal/indexDAL/loki/LokiIndex.ts +++ b/app/lib/dal/indexDAL/loki/LokiIndex.ts @@ -28,6 +28,16 @@ export abstract class LokiIndex<T extends IndexData> extends LokiCollectionManag return res } + async findRawWithOrder(criterion:any, sort:((string|((string|boolean)[]))[])) { + const now = getMicrosecondsTime() + const res = this.collection + .chain() + .find(criterion) + .compoundsort(sort) + logger.trace('[loki][%s][findRaw] => %sµs', this.collectionName, (getMicrosecondsTime() - now), criterion) + return res.data() + } + async insertBatch(records: T[]): Promise<void> { const now = getMicrosecondsTime() records.map(r => this.insert(r)) diff --git a/app/modules/dump.ts b/app/modules/dump.ts new file mode 100644 index 0000000000000000000000000000000000000000..3ebba35e3057b43b2834c7d11db43810f96a5641 --- /dev/null +++ b/app/modules/dump.ts @@ -0,0 +1,93 @@ +// Source file from duniter: Crypto-currency software to manage libre currency such as Ğ1 +// Copyright (C) 2018 Cedric Moreau <cem.moreau@gmail.com> +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. + +import {ConfDTO} from "../lib/dto/ConfDTO" +import {Server} from "../../server" + +const Table = require('cli-table'); + +module.exports = { + duniter: { + cli: [{ + name: 'dump [what] [name]', + desc: 'Dumps data of the blockchain.', + logs: false, + preventIfRunning: true, + + onDatabaseExecute: async (server:Server, conf:ConfDTO, program:any, params:any) => { + const what: string = params[0] || '' + const name: string = params[1] || '' + switch (what) { + + case 'table': + let rows: any[] + switch (name) { + case 'i_index': + rows = await server.dal.iindexDAL.findRawWithOrder({}, [['writtenOn', false], ['wotb_id', false]]) + dump(rows, (program.dbgOmitCols || "").split(',').concat('index', 'meta', '$loki', 'writtenOn', 'age')) + break + case 'm_index': + rows = await server.dal.mindexDAL.findRawWithOrder({}, [['writtenOn', false], ['pub', false]]) + dump(rows, ['op','pub','created_on','written_on','expires_on','expired_on','revokes_on','revoked_on','leaving','revocation','chainable_on']) + break + case 'c_index': + rows = await server.dal.cindexDAL.findRawWithOrder({}, [['writtenOn', false], ['issuer', false], ['receiver', false]]) + dump(rows, ['op','issuer','receiver','created_on','written_on','sig','expires_on','expired_on','chainable_on','from_wid','to_wid']) + break + case 's_index': + rows = await server.dal.sindexDAL.findRawWithOrder({}, [['writtenOn', false], ['identifier', false], ['pos', false]]) + dump(rows, ['op','tx','identifier','pos','created_on','written_on','written_time','amount','base','locktime','consumed','conditions']) + break + default: + console.error(`Unknown dump table ${name}`) + break + } + break + + default: + console.error(`Unknown dump ${what}`) + break + } + // Save DB + await server.disconnect(); + } + }] + } +} + +function dump(rows: any[], columns: string[]) { + // Table columns + const t = new Table({ + head: columns + }); + for (const row of rows) { + t.push(columns.map((c) => { + if (row[c] === null) { + return "NULL" + } + else if (row[c] === undefined) { + return 'NULL' + } + else if (typeof row[c] === 'boolean') { + return row[c] ? 1 : 0 + } + return row[c] + })); + } + try { + const dumped = t.toString() + console.log(dumped) + } catch (e) { + console.error(e) + } +} diff --git a/index.ts b/index.ts index a19e14c527b0860666f606b871654c7140538983..92ff49b31faacd701a135bab1ea812a0498244be 100644 --- a/index.ts +++ b/index.ts @@ -41,6 +41,7 @@ const revertDependency = require('./app/modules/revert'); const daemonDependency = require('./app/modules/daemon'); const pSignalDependency = require('./app/modules/peersignal'); const pluginDependency = require('./app/modules/plugin'); +const dumpDependency = require('./app/modules/dump'); let sigintListening = false @@ -130,7 +131,8 @@ const DEFAULT_DEPENDENCIES = MINIMAL_DEPENDENCIES.concat([ { name: 'duniter-keypair', required: KeypairDependency }, { name: 'duniter-crawler', required: CrawlerDependency }, { name: 'duniter-bma', required: BmaDependency }, - { name: 'duniter-ws2p', required: WS2PDependency } + { name: 'duniter-ws2p', required: WS2PDependency }, + { name: 'duniter-dump', required: dumpDependency }, ]); const PRODUCTION_DEPENDENCIES = DEFAULT_DEPENDENCIES.concat([ diff --git a/package.json b/package.json index f2c94cf428af1a75ee9b4a8f3a23af00f790696e..838fbfbda1da3b132dd1af511b32198f69f091ac 100644 --- a/package.json +++ b/package.json @@ -62,6 +62,7 @@ "bindings": "1.2.1", "body-parser": "1.17.1", "bs58": "^4.0.1", + "cli-table": "^0.3.1", "colors": "1.1.2", "commander": "2.9.0", "cors": "2.8.2", diff --git a/yarn.lock b/yarn.lock index 34e53e44cafcbe2b311dcde003efe4e072b92324..ee9288bed5e6ff4ce680da78f4a2c6381c2f3839 100644 --- a/yarn.lock +++ b/yarn.lock @@ -610,6 +610,12 @@ cli-cursor@^2.1.0: dependencies: restore-cursor "^2.0.0" +cli-table@^0.3.1: + version "0.3.1" + resolved "https://registry.yarnpkg.com/cli-table/-/cli-table-0.3.1.tgz#f53b05266a8b1a0b934b3d0821e6e2dc5914ae23" + dependencies: + colors "1.0.3" + cli-width@^1.0.1: version "1.1.1" resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-1.1.1.tgz#a4d293ef67ebb7b88d4a4d42c0ccf00c4d1e366d" @@ -662,7 +668,7 @@ colors@0.5.x: version "0.5.1" resolved "https://registry.yarnpkg.com/colors/-/colors-0.5.1.tgz#7d0023eaeb154e8ee9fce75dcb923d0ed1667774" -colors@1.0.x: +colors@1.0.3, colors@1.0.x: version "1.0.3" resolved "https://registry.yarnpkg.com/colors/-/colors-1.0.3.tgz#0433f44d809680fdeb60ed260f1b0c262e82a40b"