Skip to content

Commit

Permalink
Batch block connection during IBD
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
sipa committed Oct 20, 2012
1 parent 450cbb0 commit ae8bfd1
Show file tree
Hide file tree
Showing 10 changed files with 181 additions and 169 deletions.
89 changes: 65 additions & 24 deletions src/db.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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;
Expand All @@ -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);
Expand Down Expand Up @@ -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)
Expand All @@ -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;
Expand Down Expand Up @@ -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,
Expand Down
20 changes: 19 additions & 1 deletion src/db.h
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@ class CDB
explicit CDB(const char* pszFile, const char* pszMode="r+");
~CDB() { Close(); }
public:
void Flush();
void Close();
private:
CDB(const CDB&);
Expand Down Expand Up @@ -330,6 +331,23 @@ class CCoinsDB : public CDB
bool WriteHashBestChain(uint256 hashBestChain);
};


/** CCoinsView backed by a CCoinsDB */
class CCoinsViewDB : public CCoinsView
{
protected:
CCoinsDB db;
public:
CCoinsViewDB();
bool GetCoins(uint256 txid, CCoins &coins);
bool SetCoins(uint256 txid, const CCoins &coins);
bool HaveCoins(uint256 txid);
CBlockIndex *GetBestBlock();
bool SetBestBlock(CBlockIndex *pindex);
bool BatchWrite(const std::map<uint256, CCoins> &mapCoins, CBlockIndex *pindex);
};


/** Access to the block database (chain.dat) */
class CChainDB : public CDB
{
Expand All @@ -350,7 +368,7 @@ class CChainDB : public CDB
};


bool LoadBlockIndex(CCoinsDB &coinsdb, CChainDB &chaindb);
bool LoadBlockIndex(CChainDB &chaindb);


/** Access to the (IP) address database (peers.dat) */
Expand Down
12 changes: 12 additions & 0 deletions src/init.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,8 @@ void StartShutdown()
#endif
}

static CCoinsViewDB *pcoinsdbview;

void Shutdown(void* parg)
{
static CCriticalSection cs_Shutdown;
Expand All @@ -74,6 +76,12 @@ void Shutdown(void* parg)
nTransactionsUpdated++;
bitdb.Flush(false);
StopNode();
{
LOCK(cs_main);
pcoinsTip->Flush();
delete pcoinsTip;
delete pcoinsdbview;
}
bitdb.Flush(true);
boost::filesystem::remove(GetPidFile());
UnregisterWallet(pwalletMain);
Expand Down Expand Up @@ -298,6 +306,7 @@ std::string HelpMessage()
return strUsage;
}


/** Initialize bitcoin.
* @pre Parameters should be parsed and config file should be read.
*/
Expand Down Expand Up @@ -641,6 +650,9 @@ bool AppInit2()
uiInterface.InitMessage(_("Loading block index..."));
printf("Loading block index...\n");
nStart = GetTimeMillis();
pcoinsdbview = new CCoinsViewDB();
pcoinsTip = new CCoinsViewCache(*pcoinsdbview);

if (!LoadBlockIndex())
return InitError(_("Error loading blkindex.dat"));

Expand Down
Loading

0 comments on commit ae8bfd1

Please sign in to comment.