aboutsummaryrefslogtreecommitdiff
path: root/src/db.cpp
diff options
context:
space:
mode:
authorPieter Wuille <pieter.wuille@gmail.com>2012-07-06 16:33:34 +0200
committerPieter Wuille <pieter.wuille@gmail.com>2012-10-20 23:08:57 +0200
commitae8bfd12daa802d20791e69d3477e799d2b99f45 (patch)
tree848867135da5954b7155ebe98c09db66d09d5737 /src/db.cpp
parent450cbb0944cd20a06ce806e6679a1f4c83c50db2 (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.cpp89
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,