diff options
author | Pieter Wuille <pieter.wuille@gmail.com> | 2012-07-06 16:33:34 +0200 |
---|---|---|
committer | Pieter Wuille <pieter.wuille@gmail.com> | 2012-10-20 23:08:57 +0200 |
commit | ae8bfd12daa802d20791e69d3477e799d2b99f45 (patch) | |
tree | 848867135da5954b7155ebe98c09db66d09d5737 /src/db.cpp | |
parent | 450cbb0944cd20a06ce806e6679a1f4c83c50db2 (diff) |
Batch block connection during IBD
During the initial block download (or -loadblock), delay connection
of new blocks a bit, and perform them in a single action. This reduces
the load on the database engine, as subsequent blocks often update an
earlier block's transaction already.
Diffstat (limited to 'src/db.cpp')
-rw-r--r-- | src/db.cpp | 89 |
1 files changed, 65 insertions, 24 deletions
diff --git a/src/db.cpp b/src/db.cpp index 0a6ba3fb39..06e5543b2e 100644 --- a/src/db.cpp +++ b/src/db.cpp @@ -79,8 +79,8 @@ bool CDBEnv::Open(boost::filesystem::path pathEnv_) dbenv.set_cachesize(nDbCache / 1024, (nDbCache % 1024)*1048576, 1); dbenv.set_lg_bsize(1048576); dbenv.set_lg_max(10485760); - dbenv.set_lk_max_locks(10000); - dbenv.set_lk_max_objects(10000); + dbenv.set_lk_max_locks(40000); + dbenv.set_lk_max_objects(40000); dbenv.set_errfile(fopen(pathErrorFile.string().c_str(), "a")); /// debug dbenv.set_flags(DB_AUTO_COMMIT, 1); dbenv.set_flags(DB_TXN_WRITE_NOSYNC, 1); @@ -279,14 +279,10 @@ static bool IsChainFile(std::string strFile) return false; } -void CDB::Close() +void CDB::Flush() { - if (!pdb) - return; if (activeTxn) - activeTxn->abort(); - activeTxn = NULL; - pdb = NULL; + return; // Flush database activity from memory pool to disk log unsigned int nMinutes = 0; @@ -298,6 +294,18 @@ void CDB::Close() nMinutes = 5; bitdb.dbenv.txn_checkpoint(nMinutes ? GetArg("-dblogsize", 100)*1024 : 0, nMinutes, 0); +} + +void CDB::Close() +{ + if (!pdb) + return; + if (activeTxn) + activeTxn->abort(); + activeTxn = NULL; + pdb = NULL; + + Flush(); { LOCK(bitdb.cs_db); @@ -537,6 +545,42 @@ bool CChainDB::ReadLastBlockFile(int &nFile) { return Read('l', nFile); } +CCoinsViewDB::CCoinsViewDB() : db("cr+") {} +bool CCoinsViewDB::GetCoins(uint256 txid, CCoins &coins) { return db.ReadCoins(txid, coins); } +bool CCoinsViewDB::SetCoins(uint256 txid, const CCoins &coins) { return db.WriteCoins(txid, coins); } +bool CCoinsViewDB::HaveCoins(uint256 txid) { return db.HaveCoins(txid); } +CBlockIndex *CCoinsViewDB::GetBestBlock() { + uint256 hashBestChain; + if (!db.ReadHashBestChain(hashBestChain)) + return NULL; + std::map<uint256, CBlockIndex*>::iterator it = mapBlockIndex.find(hashBestChain); + if (it == mapBlockIndex.end()) + return NULL; + return it->second; +} +bool CCoinsViewDB::SetBestBlock(CBlockIndex *pindex) { return db.WriteHashBestChain(pindex->GetBlockHash()); } +bool CCoinsViewDB::BatchWrite(const std::map<uint256, CCoins> &mapCoins, CBlockIndex *pindex) { + printf("Committing %u changed transactions to coin database...\n", (unsigned int)mapCoins.size()); + + if (!db.TxnBegin()) + return false; + bool fOk = true; + for (std::map<uint256, CCoins>::const_iterator it = mapCoins.begin(); it != mapCoins.end(); it++) { + fOk = db.WriteCoins(it->first, it->second); + if (!fOk) + break; + } + if (fOk) + fOk = db.WriteHashBestChain(pindex->GetBlockHash()); + + if (!fOk) + db.TxnAbort(); + else + fOk = db.TxnCommit(); + + return fOk; +} + CBlockIndex static * InsertBlockIndex(uint256 hash) { if (hash == 0) @@ -557,7 +601,7 @@ CBlockIndex static * InsertBlockIndex(uint256 hash) return pindexNew; } -bool LoadBlockIndex(CCoinsDB &coindb, CChainDB &chaindb) +bool LoadBlockIndex(CChainDB &chaindb) { if (!chaindb.LoadBlockIndexGuts()) return false; @@ -587,26 +631,23 @@ bool LoadBlockIndex(CCoinsDB &coindb, CChainDB &chaindb) printf("LoadBlockIndex(): last block file: %s\n", infoLastBlockFile.ToString().c_str()); // Load hashBestChain pointer to end of best chain - if (!coindb.ReadHashBestChain(hashBestChain)) + pindexBest = pcoinsTip->GetBestBlock(); + if (pindexBest == NULL) { if (pindexGenesisBlock == NULL) return true; return error("CTxDB::LoadBlockIndex() : hashBestChain not loaded"); } - std::map<uint256, CBlockIndex*>::iterator it = mapBlockIndex.find(hashBestChain); - if (it == mapBlockIndex.end()) { - return error("CTxDB::LoadBlockIndex() : hashBestChain not found in the block index"); - } else { - // set 'next' pointers in best chain - CBlockIndex *pindex = it->second; - while(pindex != NULL && pindex->pprev != NULL) { - CBlockIndex *pindexPrev = pindex->pprev; - pindexPrev->pnext = pindex; - pindex = pindexPrev; - } - pindexBest = it->second; - nBestHeight = pindexBest->nHeight; - bnBestChainWork = pindexBest->bnChainWork; + hashBestChain = pindexBest->GetBlockHash(); + nBestHeight = pindexBest->nHeight; + bnBestChainWork = pindexBest->bnChainWork; + + // set 'next' pointers in best chain + CBlockIndex *pindex = pindexBest; + while(pindex != NULL && pindex->pprev != NULL) { + CBlockIndex *pindexPrev = pindex->pprev; + pindexPrev->pnext = pindex; + pindex = pindexPrev; } printf("LoadBlockIndex(): hashBestChain=%s height=%d date=%s\n", hashBestChain.ToString().substr(0,20).c_str(), nBestHeight, |