Commit ec90437b authored by Moul's avatar Moul

[mod] #1358: Remove Loki related code

parent f061b73a
......@@ -69,7 +69,6 @@ import {cliprogram} from "../common-libs/programOptions"
import {DividendDAO, UDSource} from "./indexDAL/abstract/DividendDAO"
import {HttpSource, HttpUD} from "../../modules/bma/lib/dtos"
import {GenericDAO} from "./indexDAL/abstract/GenericDAO"
import {LokiDAO} from "./indexDAL/loki/LokiDAO"
import {MonitorExecutionTime} from "../debug/MonitorExecutionTime"
import {LevelDBDividend} from "./indexDAL/leveldb/LevelDBDividend"
import {LevelDBBindex} from "./indexDAL/leveldb/LevelDBBindex"
......@@ -136,7 +135,6 @@ export class FileDAL {
dividendDAL:DividendDAO
newDals:{ [k:string]: Initiable }
private dals:(BlockchainArchiveDAO<any>|PeerDAO|WalletDAO|GenericDAO<any>)[]
private lokiDaos:LokiDAO[] = []
loadConfHook: (conf:ConfDTO) => Promise<void>
saveConfHook: (conf:ConfDTO) => Promise<ConfDTO>
......
import {DBHead} from "../../../db/DBHead"
import {BIndexDAO} from "../abstract/BIndexDAO"
import {NewLogger} from "../../../logger"
import {MonitorLokiExecutionTime} from "../../../debug/MonitorLokiExecutionTime"
import {LokiProtocolIndex} from "./LokiProtocolIndex"
import {MonitorExecutionTime} from "../../../debug/MonitorExecutionTime"
const logger = NewLogger()
export class LokiBIndex extends LokiProtocolIndex<DBHead> implements BIndexDAO {
private HEAD:DBHead|null = null
constructor(loki:any) {
super(loki, 'bindex', ['number', 'hash'])
}
@MonitorExecutionTime()
async insert(record: DBHead): Promise<void> {
this.HEAD = record
return super.insert(record);
}
@MonitorExecutionTime()
async removeBlock(blockstamp: string): Promise<void> {
this.HEAD = await this.head(2)
return super.removeBlock(blockstamp);
}
@MonitorExecutionTime()
async head(n: number): Promise<DBHead> {
if (!n) {
throw "Cannot read HEAD~0, which is the incoming block"
}
if (n === 1 && this.HEAD) {
// Cached
return this.HEAD
} else if (this.HEAD) {
// Another than HEAD
return this.collection
.find({ number: this.HEAD.number - n + 1 })[0]
} else {
// Costly method, as a fallback
return this.collection
.chain()
.find({})
.simplesort('number', true)
.data()[n - 1]
}
}
@MonitorExecutionTime()
async range(n: number, m: number): Promise<DBHead[]> {
if (!n) {
throw "Cannot read HEAD~0, which is the incoming block"
}
const HEAD = await this.head(1)
if (!HEAD) {
return []
}
return this.collection
.chain()
.find({
$and: [
{ number: { $lte: HEAD.number - n + 1 } },
{ number: { $gte: HEAD.number - m + 1 } },
]
})
.simplesort('number', true)
.data().slice(n - 1, m)
}
@MonitorExecutionTime()
async tail(): Promise<DBHead> {
const HEAD = await this.head(1)
if (!HEAD) {
return HEAD
}
const nbHEADs = this.collection.length()
return this.collection
.find({ number: HEAD.number - nbHEADs + 1 })[0]
}
@MonitorExecutionTime()
@MonitorLokiExecutionTime(true)
async trimBlocks(maxnumber: number): Promise<void> {
this.collection
.chain()
.find({ number: { $lt: maxnumber }})
.remove()
}
@MonitorExecutionTime()
@MonitorLokiExecutionTime(true)
async getWrittenOn(blockstamp: string): Promise<DBHead[]> {
const criterion:any = { number: parseInt(blockstamp) }
return this.collection.find(criterion)
}
}
import {BlockchainDAO} from "../abstract/BlockchainDAO"
import {DBBlock} from "../../../db/DBBlock"
import {MonitorLokiExecutionTime} from "../../../debug/MonitorLokiExecutionTime"
import {LokiProtocolIndex} from "./LokiProtocolIndex"
import {MonitorExecutionTime} from "../../../debug/MonitorExecutionTime"
export class LokiBlockchain extends LokiProtocolIndex<DBBlock> implements BlockchainDAO {
private current:DBBlock|null = null
constructor(loki:any) {
super(loki, 'blockchain', ['number', 'hash', 'fork'])
}
cleanCache(): void {
super.cleanCache()
this.current = null
}
@MonitorExecutionTime()
async getCurrent() {
if (this.current) {
// Cached
return this.current
} else {
// Costly method, as a fallback
return this.collection
.chain()
.find({
fork: false
})
.simplesort('number', true)
.data()[0]
}
}
@MonitorExecutionTime()
@MonitorLokiExecutionTime(true)
async getBlock(number:string | number) {
return this.collection
.chain()
.find({
number: parseInt(String(number)),
fork: false
})
.data()[0]
}
@MonitorExecutionTime()
async getPotentialRoots() {
return this.collection
.chain()
.find({ number: 0, fork: true })
.data()
}
@MonitorExecutionTime()
async saveBunch(blocks:DBBlock[]) {
return this.insertBatch(blocks)
}
@MonitorExecutionTime()
async insertBatch(records: DBBlock[]): Promise<void> {
const lastInBatch = records[records.length - 1]
if (!this.current || this.current.number < lastInBatch.number) {
this.current = lastInBatch
}
return super.insertBatch(records)
}
@MonitorExecutionTime()
async removeBlock(blockstamp: string): Promise<void> {
// Never remove blocks
}
@MonitorExecutionTime()
async removeForkBlock(number:number): Promise<void> {
await this.collection
.chain()
.find({
fork: true,
number
})
.remove()
}
@MonitorExecutionTime()
async removeForkBlockAboveOrEqual(number:number): Promise<void> {
await this.collection
.chain()
.find({
fork: true,
number: { $gte: number }
})
.remove()
}
@MonitorExecutionTime()
async trimBlocks(number:number): Promise<void> {
await this.collection
.chain()
.find({
number: { $lte: number }
})
.remove()
}
@MonitorExecutionTime()
async getAbsoluteBlock(number: number, hash: string): Promise<DBBlock | null> {
return this.collection
.chain()
.find({
number,
hash
})
.data()[0]
}
@MonitorExecutionTime()
async getBlocks(start: number, end: number): Promise<DBBlock[]> {
return this.collection
.chain()
.find({
number: { $between: [start, end] },
fork: false
})
.simplesort('number')
.data()
}
@MonitorExecutionTime()
async getCountOfBlocksIssuedBy(issuer: string): Promise<number> {
return this.collection
.chain()
.find({
issuer,
fork: false
})
.data()
.length
}
@MonitorExecutionTime()
async getNextForkBlocks(number: number, hash: string): Promise<DBBlock[]> {
return this.collection
.chain()
.find({
fork: true,
number: number + 1,
previousHash: hash
})
.simplesort('number')
.data()
}
@MonitorExecutionTime()
async getPotentialForkBlocks(numberStart: number, medianTimeStart: number, maxNumber: number): Promise<DBBlock[]> {
return this.collection
.chain()
.find({
fork: true,
number: { $between: [numberStart, maxNumber] },
medianTime: { $gte: medianTimeStart }
})
.simplesort('number', true)
.data()
}
@MonitorExecutionTime()
async lastBlockOfIssuer(issuer: string): Promise<DBBlock | null> {
return this.collection
.chain()
.find({
fork: false,
issuer
})
.simplesort('number', true)
.data()[0]
}
@MonitorExecutionTime()
async lastBlockWithDividend(): Promise<DBBlock | null> {
return this.collection
.chain()
.find({
fork: false,
dividend: { $gt: 0 }
})
.simplesort('number', true)
.data()[0]
}
@MonitorExecutionTime()
async saveBlock(block: DBBlock): Promise<DBBlock> {
if (!this.current || this.current.number < block.number) {
this.current = block;
}
return this.insertOrUpdate(block, false)
}
@MonitorExecutionTime()
async saveSideBlock(block: DBBlock): Promise<DBBlock> {
return this.insertOrUpdate(block, true)
}
@MonitorExecutionTime()
async insertOrUpdate(block: DBBlock, isFork:boolean): Promise<DBBlock> {
block.fork = isFork
const conditions = { number: block.number, hash: block.hash }
const existing = (await this.findRaw(conditions))[0]
if (existing && existing.fork !== isFork) {
// Existing block: we only allow to change the fork flag
this.collection
.chain()
.find(conditions)
.update(b => {
b.fork = isFork
b.monetaryMass = block.monetaryMass
b.dividend = block.dividend
})
}
else if (!existing) {
await this.insert(block)
}
return block
}
@MonitorExecutionTime()
async dropNonForkBlocksAbove(number: number): Promise<void> {
this.collection
.chain()
.find({
fork: false,
number: { $gt: number }
})
.remove()
}
@MonitorExecutionTime()
async setSideBlock(number: number, previousBlock: DBBlock | null): Promise<void> {
this.collection
.chain()
.find({
number
})
.update((b:DBBlock) => {
b.fork = true
})
// Also update the cache if concerned
if (this.current && this.current.number === number) {
if (previousBlock && this.current.previousHash === previousBlock.hash) {
this.current = previousBlock
} else {
this.current = null
}
}
}
@MonitorExecutionTime()
async getNonForkChunk(start: number, end: number): Promise<DBBlock[]> {
return this.collection
.chain()
.find({
fork: false,
number: { $between: [start, end ]}
})
.simplesort('number')
.data()
}
}
import {LokiChainableFind, LokiCollection} from "./LokiTypes"
import {NewLogger} from "../../../logger"
import {getMicrosecondsTime} from "../../../../ProcessCpuProfiler"
const logger = NewLogger()
export class LokiProxyCollection<T> implements LokiCollection<T> {
constructor(public collection:LokiCollection<T>, private collectionName:string) {
}
get data() {
return this.collection.data
}
length(): number {
return this.collection.data.length
}
insert(entity:T) {
this.collection.insert(entity)
}
remove(entity:T) {
this.collection.remove(entity)
}
find(criterion:{ [t in keyof T|'$or'|'$and']?: any }) {
const now = getMicrosecondsTime()
const res = this.collection.find(criterion)
// logger.trace('[loki][%s][find] %sµs', this.collectionName, getDurationInMicroSeconds(now), criterion)
return res
}
chain(): LokiChainableFind<T> {
return this.collection.chain()
}
setChangesApi(enabled: boolean) {
this.collection.setChangesApi(enabled)
// This is a Loki bug: `disableDeltaChangesApi` should be impacted just like `disableChangesApi`:
;(this.collection as any).disableDeltaChangesApi = !enabled
}
// Returns the real Loki property
get disableChangesApi() {
return this.collection.disableChangesApi
}
// Returns the real Loki property
get disableDeltaChangesApi() {
return this.collection.disableDeltaChangesApi
}
get changes() {
return this.collection.changes
}
}
import {LokiCollection} from "./LokiTypes"
import {LokiProxyCollection} from "./LokiCollection"
import {NewLogger} from "../../../logger"
import {LokiDAO} from "./LokiDAO"
import {cliprogram} from "../../../common-libs/programOptions"
import {Initiable} from "../../sqliteDAL/Initiable"
const logger = NewLogger()
export abstract class LokiCollectionManager<T> implements LokiDAO, Initiable {
protected collection:LokiCollection<T>
protected collectionIsInitialized: Promise<void>
protected resolveCollection: () => void
public constructor(
protected loki:any,
protected collectionName:'iindex'|'mindex'|'cindex'|'sindex'|'bindex'|'blockchain'|'txs'|'wallet'|'peer'|'dividend',
protected indices: (keyof T)[]) {
this.collectionIsInitialized = new Promise<void>(res => this.resolveCollection = res)
}
get lokiCollection(): LokiCollection<T> {
return this.collection
}
public triggerInit() {
const coll = this.loki.addCollection(this.collectionName, {
indices: this.indices,
disableChangesApi: cliprogram.isSync
})
this.collection = new LokiProxyCollection(coll, this.collectionName)
this.resolveCollection()
}
public enableChangesAPI() {
this.collection.setChangesApi(true)
}
public disableChangesAPI() {
this.collection.setChangesApi(false)
}
async init(): Promise<void> {
await this.collectionIsInitialized
logger.info('Collection %s ready', this.collectionName)
}
async close(): Promise<void> {
}
cleanCache(): void {
}
}
import {LokiCollection} from "./LokiTypes"
export interface LokiDAO {
enableChangesAPI(): void
disableChangesAPI(): void
lokiCollection: LokiCollection<any>
}
import {LokiIndex} from "./LokiIndex"
import {DividendDAO, DividendEntry, UDSource} from "../abstract/DividendDAO"
import {IindexEntry, SimpleTxInput, SimpleUdEntryForWallet, SindexEntry} from "../../../indexer"
import {DataErrors} from "../../../common-libs/errors"
import {MonitorExecutionTime} from "../../../debug/MonitorExecutionTime"
import {DividendDaoHandler} from "../common/DividendDaoHandler"
export class LokiDividend extends LokiIndex<DividendEntry> implements DividendDAO {
constructor(loki:any) {
super(loki, 'dividend', ['pub'])
}
@MonitorExecutionTime()
async createMember(pub: string): Promise<void> {
const existing = this.collection.find({ pub })[0]
if (!existing) {
await this.insert(DividendDaoHandler.getNewDividendEntry(pub))
} else {
await this.setMember(true, pub)
}
}
@MonitorExecutionTime()
async setMember(member: boolean, pub: string) {
await this.collection
.chain()
.find({ pub })
.update(r => {
r.member = member
})
}
@MonitorExecutionTime()
async deleteMember(pub: string): Promise<void> {
this.collection
.chain()
.find({ pub })
.remove()
}
@MonitorExecutionTime()
async produceDividend(blockNumber: number, dividend: number, unitbase: number, local_iindex: IindexEntry[]): Promise<SimpleUdEntryForWallet[]> {
const dividends: SimpleUdEntryForWallet[] = []
// Then produce the UD
this.collection
.chain()
.find({ member: true })
.update(r => DividendDaoHandler.produceDividend(r, blockNumber, dividend, unitbase, dividends))
return dividends
}
@MonitorExecutionTime()
async consume(filter: SindexEntry[]): Promise<void> {
for (const dividendToConsume of filter) {
this.collection
.chain()
// We look at the dividends of this member
.find({
pub: dividendToConsume.identifier
})
// Then we try to consume the dividend being spent
.update(m => DividendDaoHandler.consume(m, dividendToConsume))
}
}
@MonitorExecutionTime()
async getUDSources(pub: string): Promise<UDSource[]> {
const member = this.collection
.chain()
.find({ pub })
.data()[0]
if (!member) {
return []
}
return DividendDaoHandler.udSources(member)
}
@MonitorExecutionTime()