diff --git a/app/lib/dal/drivers/SQLiteDriver.ts b/app/lib/dal/drivers/SQLiteDriver.ts index 404371634614543f04bee34812528d961a5ee043..15a437ef500e699b64ba20d8f7e953d9d3844734 100644 --- a/app/lib/dal/drivers/SQLiteDriver.ts +++ b/app/lib/dal/drivers/SQLiteDriver.ts @@ -103,8 +103,8 @@ export class SQLiteDriver { this.logger.debug('Database "%s" removed', this.path); } - get closed() { - return this.dbPromise; + isClosed() { + return !this.dbPromise; } async closeConnection(): Promise<void> { diff --git a/app/lib/dal/fileDAL.ts b/app/lib/dal/fileDAL.ts index 2d7915db8d508ca3ab8014d3ef4129a454ff1cb8..b680bf9f40fe7f2320b7e4b5d63114fab3eab7e2 100644 --- a/app/lib/dal/fileDAL.ts +++ b/app/lib/dal/fileDAL.ts @@ -129,8 +129,7 @@ export class FileDAL implements ServerDAO { sindexDAL: SIndexDAO; cindexDAL: CIndexDAO; dividendDAL: DividendDAO; - newDals: { [k: string]: Initiable }; - private dals: (PeerDAO | WalletDAO | GenericDAO<any>)[]; + dals: { [k: string]: Initiable }; loadConfHook: (conf: ConfDTO) => Promise<void>; saveConfHook: (conf: ConfDTO) => Promise<ConfDTO>; @@ -174,7 +173,7 @@ export class FileDAL implements ServerDAO { this.cindexDAL = new LevelDBCindex(getLevelDB); this.dividendDAL = new LevelDBDividend(getLevelDB); - this.newDals = { + this.dals = { powDAL: this.powDAL, metaDAL: this.metaDAL, blockDAL: this.blockDAL, @@ -196,24 +195,9 @@ export class FileDAL implements ServerDAO { async init(conf: ConfDTO) { this.wotb = this.params.wotbf(); - this.dals = [ - this.blockDAL, - this.txsDAL, - this.peerDAL, - this.walletDAL, - this.bindexDAL, - this.mindexDAL, - this.iindexDAL, - this.sindexDAL, - this.cindexDAL, - this.dividendDAL, - ]; - for (const indexDAL of this.dals) { - indexDAL.triggerInit(); - } - const dalNames = Underscore.keys(this.newDals); + const dalNames = Underscore.keys(this.dals); for (const dalName of dalNames) { - const dal = this.newDals[dalName]; + const dal = this.dals[dalName]; await dal.init(); } logger.debug("Upgrade database..."); @@ -229,6 +213,23 @@ export class FileDAL implements ServerDAO { } } + generateUpgradeSql() { + // Make sure to always renable constraints (a.g. if the last sync failed, it can be still disabled) + return "PRAGMA ignore_check_constraints = true;"; + } + + async disableCheckConstraints() { + logger.info("Disabling database check constraints..."); + await this.metaDAL.exec("PRAGMA ignore_check_constraints = true;"); + await this.txsDAL.disableCheckConstraints(); + } + + async enableCheckConstraints() { + logger.info("Enabling database check constraints..."); + await this.metaDAL.exec("PRAGMA ignore_check_constraints = false;"); + await this.txsDAL.enableCheckConstraints(); + } + getDBVersion() { return this.metaDAL.getVersion(); } @@ -1583,14 +1584,14 @@ export class FileDAL implements ServerDAO { } async cleanCaches() { - await Underscore.values(this.newDals).map( + await Underscore.values(this.dals).map( (dal: Initiable) => dal.cleanCache && dal.cleanCache() ); } async close() { await Promise.all( - Underscore.values(this.newDals).map(async (dal: Initiable) => { + Underscore.values(this.dals).map(async (dal: Initiable) => { dal.cleanCache(); await dal.close(); }) diff --git a/app/lib/dal/indexDAL/abstract/GenericDAO.ts b/app/lib/dal/indexDAL/abstract/GenericDAO.ts index b7df7ad288e7130df8bfee6d5f89bd0ffc7a9f69..e9057917c6cedc1f84d6e2601afb260ddbb6f930 100644 --- a/app/lib/dal/indexDAL/abstract/GenericDAO.ts +++ b/app/lib/dal/indexDAL/abstract/GenericDAO.ts @@ -1,10 +1,6 @@ import { Initiable } from "../../sqliteDAL/Initiable"; export interface GenericDAO<T> extends Initiable { - /** - * Trigger the initialization of the DAO. Called when the underlying DB is ready. - */ - triggerInit(): void; /** * Make a generic find with some ordering. diff --git a/app/lib/dal/indexDAL/abstract/PeerDAO.ts b/app/lib/dal/indexDAL/abstract/PeerDAO.ts index 0432e2c15d551ab0944e7cd8e18aaec610915470..a3f6e3f239ec8a87933efe449b17c493bda76331 100644 --- a/app/lib/dal/indexDAL/abstract/PeerDAO.ts +++ b/app/lib/dal/indexDAL/abstract/PeerDAO.ts @@ -2,10 +2,6 @@ import { DBPeer } from "../../../db/DBPeer"; import { Initiable } from "../../sqliteDAL/Initiable"; export interface PeerDAO extends Initiable { - /** - * Trigger the initialization of the DAO. Called when the underlying DB is ready. - */ - triggerInit(): void; listAll(): Promise<DBPeer[]>; diff --git a/app/lib/dal/indexDAL/abstract/TxsDAO.ts b/app/lib/dal/indexDAL/abstract/TxsDAO.ts index 93854de3e21bfd08ad732f1fba4731ad7b88975f..fc91a739d5f7e2959a8dbac1256c7b4521db6e11 100644 --- a/app/lib/dal/indexDAL/abstract/TxsDAO.ts +++ b/app/lib/dal/indexDAL/abstract/TxsDAO.ts @@ -4,6 +4,11 @@ import { SandBox } from "../../sqliteDAL/SandBox"; import { DBTx } from "../../../db/DBTx"; export interface TxsDAO extends GenericDAO<DBTx> { + + disableCheckConstraints(): Promise<void>; + + enableCheckConstraints(): Promise<void>; + trimExpiredNonWrittenTxs(limitTime: number): Promise<void>; getAllPending(versionMin: number): Promise<DBTx[]>; diff --git a/app/lib/dal/indexDAL/abstract/WalletDAO.ts b/app/lib/dal/indexDAL/abstract/WalletDAO.ts index 3e076f2ebcffe622680cf1654d32bbf0ee120d3d..4b9f7e96bf0f3cde09b3db4762ecb813f08e3268 100644 --- a/app/lib/dal/indexDAL/abstract/WalletDAO.ts +++ b/app/lib/dal/indexDAL/abstract/WalletDAO.ts @@ -2,10 +2,6 @@ import { Initiable } from "../../sqliteDAL/Initiable"; import { DBWallet } from "../../../db/DBWallet"; export interface WalletDAO extends Initiable { - /** - * Trigger the initialization of the DAO. Called when the underlying DB is ready. - */ - triggerInit(): void; /** * Saves a wallet. diff --git a/app/lib/dal/indexDAL/leveldb/LevelDBDividend.ts b/app/lib/dal/indexDAL/leveldb/LevelDBDividend.ts index 4d1afc8e8beab4867fc4c5287da5e7b156854a72..161ddca3883413a691077d090b03296ac9d21493 100644 --- a/app/lib/dal/indexDAL/leveldb/LevelDBDividend.ts +++ b/app/lib/dal/indexDAL/leveldb/LevelDBDividend.ts @@ -32,9 +32,6 @@ export class LevelDBDividend extends LevelDBTable<DividendEntry> */ cleanCache(): void {} - - triggerInit(): void {} - async init(): Promise<void> { await super.init(); this.indexForTrimming = new LevelDBTable<string[]>( diff --git a/app/lib/dal/indexDAL/leveldb/LevelDBTable.ts b/app/lib/dal/indexDAL/leveldb/LevelDBTable.ts index c6b1f6de2c9dab34d2780dae2bc64ce8af44d1af..9b23982b1b2418570651dc3cf30934e9ebb35a38 100644 --- a/app/lib/dal/indexDAL/leveldb/LevelDBTable.ts +++ b/app/lib/dal/indexDAL/leveldb/LevelDBTable.ts @@ -12,7 +12,6 @@ export class LevelDBTable<T> { cleanCache(): void {} - triggerInit(): void {} async close() { await this.db.close(); diff --git a/app/lib/dal/indexDAL/sqlite/SqliteDividend.ts b/app/lib/dal/indexDAL/sqlite/SqliteDividend.ts index 3152d1174b3ee7d3aeb8d19d5ed10aec0804a024..d64cc48b342ad5194c37e5d23a6e0948abc06c0d 100644 --- a/app/lib/dal/indexDAL/sqlite/SqliteDividend.ts +++ b/app/lib/dal/indexDAL/sqlite/SqliteDividend.ts @@ -35,8 +35,6 @@ export class SqliteDividend extends SqliteTable<DividendEntry> cleanCache(): void {} - triggerInit(): void {} - /** * INSERT */ diff --git a/app/lib/dal/indexDAL/sqlite/SqliteIIndex.ts b/app/lib/dal/indexDAL/sqlite/SqliteIIndex.ts index d31696ed60b5d813473e917c8148051c948abdd0..a50fdb0416792dc09621fd0459c942a2364ae0cd 100644 --- a/app/lib/dal/indexDAL/sqlite/SqliteIIndex.ts +++ b/app/lib/dal/indexDAL/sqlite/SqliteIIndex.ts @@ -44,8 +44,6 @@ export class SqliteIIndex extends SqliteTable<IindexEntry> cleanCache(): void {} - triggerInit(): void {} - /** * INSERT */ diff --git a/app/lib/dal/indexDAL/sqlite/SqliteMIndex.ts b/app/lib/dal/indexDAL/sqlite/SqliteMIndex.ts index 6fe3b6230a545088d50a2cdcb03099cfdb1f80bb..0d8b60d2bb4768e50ddbd91490cf6ec222449d10 100644 --- a/app/lib/dal/indexDAL/sqlite/SqliteMIndex.ts +++ b/app/lib/dal/indexDAL/sqlite/SqliteMIndex.ts @@ -74,8 +74,6 @@ export class SqliteMIndex extends SqliteTable<MindexEntry> `); } - triggerInit(): void {} - /** * INSERT */ diff --git a/app/lib/dal/indexDAL/sqlite/SqlitePeers.ts b/app/lib/dal/indexDAL/sqlite/SqlitePeers.ts index 3b67bd9feb95686c3f779ef43d067718bd8b653b..50ce4109382fa961e2a42531fbd6b8cbdfd7c525 100644 --- a/app/lib/dal/indexDAL/sqlite/SqlitePeers.ts +++ b/app/lib/dal/indexDAL/sqlite/SqlitePeers.ts @@ -95,8 +95,6 @@ export class SqlitePeers extends SqliteTable<DBPeer> implements PeerDAO { return peer; } - triggerInit(): void {} - withUPStatus(): Promise<DBPeer[]> { return this.findEntities("SELECT * FROM peers WHERE status = ?", ["UP"]); } diff --git a/app/lib/dal/indexDAL/sqlite/SqliteSIndex.ts b/app/lib/dal/indexDAL/sqlite/SqliteSIndex.ts index c208fa380f3395ae3980d39f7e977582e019bd3f..fd27cead17b768e804bc1404007b5ccde535e813 100644 --- a/app/lib/dal/indexDAL/sqlite/SqliteSIndex.ts +++ b/app/lib/dal/indexDAL/sqlite/SqliteSIndex.ts @@ -46,8 +46,6 @@ export class SqliteSIndex extends SqliteTable<SindexEntry> cleanCache(): void {} - triggerInit(): void {} - /** * INSERT */ diff --git a/app/lib/dal/indexDAL/sqlite/SqliteTable.ts b/app/lib/dal/indexDAL/sqlite/SqliteTable.ts index 756d367c5df96461a44543f3b6def81e66b3cf24..d2c39b33bbcd3a8341bc2033ebeb54a311031173 100644 --- a/app/lib/dal/indexDAL/sqlite/SqliteTable.ts +++ b/app/lib/dal/indexDAL/sqlite/SqliteTable.ts @@ -4,7 +4,7 @@ import { SqliteNodeIOManager } from "./SqliteNodeIOManager"; import { SQLiteDriver } from "../../drivers/SQLiteDriver"; export class SqliteTable<T> { - private readonly pdriver: Promise<SQLiteDriver>; + private readonly _driverPromise: Promise<SQLiteDriver>; protected driver: SqliteNodeIOManager<T>; protected constructor( @@ -14,11 +14,11 @@ export class SqliteTable<T> { }, getSqliteDB: (dbName: string) => Promise<SQLiteDriver> ) { - this.pdriver = getSqliteDB(`${name}.db`); + this._driverPromise = getSqliteDB(`${name}.db`); } async init(): Promise<void> { - this.driver = new SqliteNodeIOManager(await this.pdriver, "sindex"); + this.driver = new SqliteNodeIOManager(await this._driverPromise, this.name); await this.driver.sqlExec(` BEGIN; ${this.generateCreateTable()}; @@ -32,6 +32,14 @@ export class SqliteTable<T> { await this.driver.close(); } + async disableCheckConstraints(): Promise<void> { + await this.driver.sqlExec("PRAGMA ignore_check_constraints = true;"); + } + + async enableCheckConstraints(): Promise<void> { + await this.driver.sqlExec("PRAGMA ignore_check_constraints = false;"); + } + generateCreateTable() { let sql = `CREATE TABLE IF NOT EXISTS ${this.name} (`; const fields = this.keys() diff --git a/app/lib/dal/indexDAL/sqlite/SqliteTransactions.ts b/app/lib/dal/indexDAL/sqlite/SqliteTransactions.ts index c7a90a92f98e4432ce4327ed7336025f3e484990..f739136e5e47d3bdb3f1927a26c41038b140dbbb 100644 --- a/app/lib/dal/indexDAL/sqlite/SqliteTransactions.ts +++ b/app/lib/dal/indexDAL/sqlite/SqliteTransactions.ts @@ -368,8 +368,6 @@ export class SqliteTransactions extends SqliteTable<DBTx> implements TxsDAO { return this.driver.sqlWrite("DELETE FROM txs WHERE hash = ?", [hash]); } - triggerInit(): void {} - trimExpiredNonWrittenTxs(limitTime: number): Promise<void> { return this.driver.sqlWrite( "DELETE FROM txs WHERE NOT written AND blockstampTime <= ?", diff --git a/app/lib/dal/indexDAL/sqlite/SqliteWallet.ts b/app/lib/dal/indexDAL/sqlite/SqliteWallet.ts index 3b70811fe3ee3a6106ee3898fec4f5a6d6413536..a9f8fb03134194958ea298b49f64411ba686e6ed 100644 --- a/app/lib/dal/indexDAL/sqlite/SqliteWallet.ts +++ b/app/lib/dal/indexDAL/sqlite/SqliteWallet.ts @@ -23,8 +23,6 @@ export class SqliteWallet extends SqliteTable<DBWallet> implements WalletDAO { cleanCache(): void {} - triggerInit(): void {} - /** * INSERT */ diff --git a/app/modules/crawler/lib/sync.ts b/app/modules/crawler/lib/sync.ts index 69d073a23e107ee909aad9db96dbb52f4246cae0..de68f7920f66b4794460522b6804b20cda907d3f 100644 --- a/app/modules/crawler/lib/sync.ts +++ b/app/modules/crawler/lib/sync.ts @@ -183,6 +183,9 @@ export class Synchroniser extends stream.Duplex { // We use cautious mode if it is asked, or not particulary asked but blockchain has been started const cautious = askedCautious === true || localNumber >= 0; + // Disable constraints + if (!cautious) await this.server.dal.disableCheckConstraints(); + const milestonesStream = new ValidatorStream( localNumber, to, @@ -241,6 +244,9 @@ export class Synchroniser extends stream.Duplex { await this.syncStrategy.syncPeers(fullSync, to); } + // Enable constraints + if (!cautious) await this.server.dal.enableCheckConstraints(); + const syncDuration = Date.now() - syncStartTime; this.watcher.end(syncDuration); this.push({ sync: true }); diff --git a/app/modules/crawler/lib/sync/v2/GlobalIndexStream.ts b/app/modules/crawler/lib/sync/v2/GlobalIndexStream.ts index 242ecf2b1ea0fef3d543b7e43e4eeb2ee2e5a7b3..120578daa16ede72927bdef3cdae5fcc4e290a5d 100644 --- a/app/modules/crawler/lib/sync/v2/GlobalIndexStream.ts +++ b/app/modules/crawler/lib/sync/v2/GlobalIndexStream.ts @@ -124,12 +124,6 @@ export class GlobalIndexStream extends Duplex { })(); } - private async injectLoki<T, K extends keyof T>(dal: T, f: K, obj: T[K]) { - // this.mapInjection[f] = dal[f] - // dal[f] = obj - // await (obj as any).triggerInit() - } - readChunk(i: number) {} _read(size: number) { diff --git a/app/modules/prover/lib/proof.ts b/app/modules/prover/lib/proof.ts index f24d30571026488f51a3e663b20fdb2c9a5546c7..2ce2942c51901f026805da07fcc708fbcfd71732 100644 --- a/app/modules/prover/lib/proof.ts +++ b/app/modules/prover/lib/proof.ts @@ -53,7 +53,7 @@ export function createPowWorker() { process.exit(ExitCodes.OK); }); - process.on("message", async (message) => { + process.on("message", async (message: any) => { switch (message.command) { case "newPoW": (async () => { diff --git a/app/modules/upnp-provider.ts b/app/modules/upnp-provider.ts index 776453de15c99ea4e34140a4926da2146ec1c0a8..7631e3196e8abab074502f30396e248843a5cd2e 100644 --- a/app/modules/upnp-provider.ts +++ b/app/modules/upnp-provider.ts @@ -200,7 +200,7 @@ export class UpnpProvider { let keys = Underscore.keys(netInterfaces); let res = []; for (const name of keys) { - let addresses = netInterfaces[name]; + let addresses = netInterfaces[name] || []; for (const addr of addresses) { if (!family || addr.family == family) { res.push({ diff --git a/server.ts b/server.ts index d5c4b7e5d30a25d83bfa321c83c52afc8afd2cbd..97f067ffa985d39c9d2af94c82cab73fa37ad81a 100644 --- a/server.ts +++ b/server.ts @@ -167,9 +167,9 @@ export class Server extends stream.Duplex implements HookableServer { async getSQLiteDB(dbName: string, home: string) { // Check in cach (useful to avoid migration task to create a new driver on the same DB file) let driver: SQLiteDriver = this.sqliteDBs[dbName]; - if (!driver || driver.closed) { + if (!driver || driver.isClosed()) { driver = await Directory.getHomeDB(this.memoryOnly, dbName, home); - this.sqliteDBs[dbName] = driver; + if (!this.memoryOnly) this.sqliteDBs[dbName] = driver; } return driver; } @@ -179,7 +179,7 @@ export class Server extends stream.Duplex implements HookableServer { let driver: LevelUp = this.levelDBs[dbName]; if (!driver || driver.isClosed()) { driver = await Directory.getHomeLevelDB(this.memoryOnly, dbName, home); - this.levelDBs[dbName] = driver; + if (!this.memoryOnly) this.levelDBs[dbName] = driver; } return driver; } @@ -514,6 +514,12 @@ export class Server extends stream.Duplex implements HookableServer { if (this.dal) { await this.dal.close() } + await Promise.all(Object.values(this.sqliteDBs) + .filter(db => db && !db.isClosed()) + .map(db => db.closeConnection())); + await Promise.all(Object.values(this.levelDBs) + .filter(db => db && !db.isClosed()) + .map(db => db.close())); } revert() { diff --git a/test/dal/basic-dal-tests.ts b/test/dal/basic-dal-tests.ts index ccc4ffd264927a573939c862e8688d930d80ffd4..6696c74c3f5b8348931f0ad8b204f702aefe8a48 100644 --- a/test/dal/basic-dal-tests.ts +++ b/test/dal/basic-dal-tests.ts @@ -113,6 +113,10 @@ describe("DAL", function(){ return fileDAL.saveConf({ currency: "meta_brouzouf" } as any); }) + after(() => { + return fileDAL.close(); + }) + it('should have last DB version', async () => { let version = await fileDAL.getDBVersion(); should.exist(version);