Browse Source

Use singleton block tree database instance

miguelfreitas
Pieter Wuille 12 years ago
parent
commit
d979e6e36a
  1. 30
      src/db.cpp
  2. 12
      src/db.h
  3. 3
      src/init.cpp
  4. 61
      src/main.cpp
  5. 6
      src/main.h
  6. 8
      src/test/test_bitcoin.cpp

30
src/db.cpp

@ -273,7 +273,7 @@ CDB::CDB(const char *pszFile, const char* pszMode) :
static bool IsChainFile(std::string strFile) static bool IsChainFile(std::string strFile)
{ {
if (strFile == "coins.dat" || strFile == "chain.dat") if (strFile == "coins.dat" || strFile == "blktree.dat")
return true; return true;
return false; return false;
@ -483,7 +483,7 @@ void CDBEnv::Flush(bool fShutdown)
// //
// CChainDB and CCoinsDB // CBlockTreeDB and CCoinsDB
// //
bool CCoinsDB::HaveCoins(uint256 hash) { bool CCoinsDB::HaveCoins(uint256 hash) {
@ -504,7 +504,7 @@ bool CCoinsDB::WriteCoins(uint256 hash, const CCoins &coins) {
return Write(make_pair('c', hash), coins); return Write(make_pair('c', hash), coins);
} }
bool CChainDB::WriteBlockIndex(const CDiskBlockIndex& blockindex) bool CBlockTreeDB::WriteBlockIndex(const CDiskBlockIndex& blockindex)
{ {
return Write(make_pair('b', blockindex.GetBlockHash()), blockindex); return Write(make_pair('b', blockindex.GetBlockHash()), blockindex);
} }
@ -519,29 +519,29 @@ bool CCoinsDB::WriteHashBestChain(uint256 hashBestChain)
return Write('B', hashBestChain); return Write('B', hashBestChain);
} }
bool CChainDB::ReadBestInvalidWork(CBigNum& bnBestInvalidWork) bool CBlockTreeDB::ReadBestInvalidWork(CBigNum& bnBestInvalidWork)
{ {
return Read('I', bnBestInvalidWork); return Read('I', bnBestInvalidWork);
} }
bool CChainDB::WriteBestInvalidWork(CBigNum bnBestInvalidWork) bool CBlockTreeDB::WriteBestInvalidWork(CBigNum bnBestInvalidWork)
{ {
return Write('I', bnBestInvalidWork); return Write('I', bnBestInvalidWork);
} }
bool CChainDB::WriteBlockFileInfo(int nFile, const CBlockFileInfo &info) { bool CBlockTreeDB::WriteBlockFileInfo(int nFile, const CBlockFileInfo &info) {
return Write(make_pair('f', nFile), info); return Write(make_pair('f', nFile), info);
} }
bool CChainDB::ReadBlockFileInfo(int nFile, CBlockFileInfo &info) { bool CBlockTreeDB::ReadBlockFileInfo(int nFile, CBlockFileInfo &info) {
return Read(make_pair('f', nFile), info); return Read(make_pair('f', nFile), info);
} }
bool CChainDB::WriteLastBlockFile(int nFile) { bool CBlockTreeDB::WriteLastBlockFile(int nFile) {
return Write('l', nFile); return Write('l', nFile);
} }
bool CChainDB::ReadLastBlockFile(int &nFile) { bool CBlockTreeDB::ReadLastBlockFile(int &nFile) {
return Read('l', nFile); return Read('l', nFile);
} }
@ -601,9 +601,9 @@ CBlockIndex static * InsertBlockIndex(uint256 hash)
return pindexNew; return pindexNew;
} }
bool LoadBlockIndex(CChainDB &chaindb) bool LoadBlockIndexDB()
{ {
if (!chaindb.LoadBlockIndexGuts()) if (!pblocktree->LoadBlockIndexGuts())
return false; return false;
if (fRequestShutdown) if (fRequestShutdown)
@ -628,9 +628,9 @@ bool LoadBlockIndex(CChainDB &chaindb)
} }
// Load block file info // Load block file info
chaindb.ReadLastBlockFile(nLastBlockFile); pblocktree->ReadLastBlockFile(nLastBlockFile);
printf("LoadBlockIndex(): last block file = %i\n", nLastBlockFile); printf("LoadBlockIndex(): last block file = %i\n", nLastBlockFile);
if (chaindb.ReadBlockFileInfo(nLastBlockFile, infoLastBlockFile)) if (pblocktree->ReadBlockFileInfo(nLastBlockFile, infoLastBlockFile))
printf("LoadBlockIndex(): last block file: %s\n", infoLastBlockFile.ToString().c_str()); printf("LoadBlockIndex(): last block file: %s\n", infoLastBlockFile.ToString().c_str());
// Load hashBestChain pointer to end of best chain // Load hashBestChain pointer to end of best chain
@ -656,7 +656,7 @@ bool LoadBlockIndex(CChainDB &chaindb)
DateTimeStrFormat("%x %H:%M:%S", pindexBest->GetBlockTime()).c_str()); DateTimeStrFormat("%x %H:%M:%S", pindexBest->GetBlockTime()).c_str());
// Load bnBestInvalidWork, OK if it doesn't exist // Load bnBestInvalidWork, OK if it doesn't exist
chaindb.ReadBestInvalidWork(bnBestInvalidWork); pblocktree->ReadBestInvalidWork(bnBestInvalidWork);
// Verify blocks in the best chain // Verify blocks in the best chain
int nCheckLevel = GetArg("-checklevel", 1); int nCheckLevel = GetArg("-checklevel", 1);
@ -693,7 +693,7 @@ bool LoadBlockIndex(CChainDB &chaindb)
bool CChainDB::LoadBlockIndexGuts() bool CBlockTreeDB::LoadBlockIndexGuts()
{ {
// Get database cursor // Get database cursor
Dbc* pcursor = GetCursor(); Dbc* pcursor = GetCursor();

12
src/db.h

@ -348,14 +348,14 @@ public:
}; };
/** Access to the block database (chain.dat) */ /** Access to the block database (blktree.dat) */
class CChainDB : public CDB class CBlockTreeDB : public CDB
{ {
public: public:
CChainDB(const char* pszMode="r+") : CDB("chain.dat", pszMode) { } CBlockTreeDB(const char* pszMode="r+") : CDB("blktree.dat", pszMode) { }
private: private:
CChainDB(const CChainDB&); CBlockTreeDB(const CBlockTreeDB&);
void operator=(const CChainDB&); void operator=(const CBlockTreeDB&);
public: public:
bool WriteBlockIndex(const CDiskBlockIndex& blockindex); bool WriteBlockIndex(const CDiskBlockIndex& blockindex);
bool ReadBestInvalidWork(CBigNum& bnBestInvalidWork); bool ReadBestInvalidWork(CBigNum& bnBestInvalidWork);
@ -368,7 +368,7 @@ public:
}; };
bool LoadBlockIndex(CChainDB &chaindb); bool LoadBlockIndexDB();
/** Access to the (IP) address database (peers.dat) */ /** Access to the (IP) address database (peers.dat) */

3
src/init.cpp

@ -79,8 +79,10 @@ void Shutdown(void* parg)
{ {
LOCK(cs_main); LOCK(cs_main);
pcoinsTip->Flush(); pcoinsTip->Flush();
pblocktree->Flush();
delete pcoinsTip; delete pcoinsTip;
delete pcoinsdbview; delete pcoinsdbview;
delete pblocktree;
} }
bitdb.Flush(true); bitdb.Flush(true);
boost::filesystem::remove(GetPidFile()); boost::filesystem::remove(GetPidFile());
@ -650,6 +652,7 @@ bool AppInit2()
uiInterface.InitMessage(_("Loading block index...")); uiInterface.InitMessage(_("Loading block index..."));
printf("Loading block index...\n"); printf("Loading block index...\n");
nStart = GetTimeMillis(); nStart = GetTimeMillis();
pblocktree = new CBlockTreeDB("cr+");
pcoinsdbview = new CCoinsViewDB(); pcoinsdbview = new CCoinsViewDB();
pcoinsTip = new CCoinsViewCache(*pcoinsdbview); pcoinsTip = new CCoinsViewCache(*pcoinsdbview);

61
src/main.cpp

@ -270,6 +270,7 @@ bool CCoinsViewMemPool::HaveCoins(uint256 txid) {
} }
CCoinsViewCache *pcoinsTip = NULL; CCoinsViewCache *pcoinsTip = NULL;
CBlockTreeDB *pblocktree = NULL;
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
// //
@ -1143,7 +1144,7 @@ void static InvalidChainFound(CBlockIndex* pindexNew)
if (pindexNew->bnChainWork > bnBestInvalidWork) if (pindexNew->bnChainWork > bnBestInvalidWork)
{ {
bnBestInvalidWork = pindexNew->bnChainWork; bnBestInvalidWork = pindexNew->bnChainWork;
CChainDB().WriteBestInvalidWork(bnBestInvalidWork); pblocktree->WriteBestInvalidWork(bnBestInvalidWork);
uiInterface.NotifyBlocksChanged(); uiInterface.NotifyBlocksChanged();
} }
printf("InvalidChainFound: invalid block=%s height=%d work=%s date=%s\n", printf("InvalidChainFound: invalid block=%s height=%d work=%s date=%s\n",
@ -1159,7 +1160,7 @@ void static InvalidChainFound(CBlockIndex* pindexNew)
void static InvalidBlockFound(CBlockIndex *pindex) { void static InvalidBlockFound(CBlockIndex *pindex) {
pindex->nStatus |= BLOCK_FAILED_VALID; pindex->nStatus |= BLOCK_FAILED_VALID;
CChainDB().WriteBlockIndex(CDiskBlockIndex(pindex)); pblocktree->WriteBlockIndex(CDiskBlockIndex(pindex));
setBlockIndexValid.erase(pindex); setBlockIndexValid.erase(pindex);
InvalidChainFound(pindex); InvalidChainFound(pindex);
if (pindex->pnext) if (pindex->pnext)
@ -1186,12 +1187,11 @@ bool ConnectBestBlock() {
do { do {
if (pindexTest->nStatus & BLOCK_FAILED_MASK) { if (pindexTest->nStatus & BLOCK_FAILED_MASK) {
// mark descendants failed // mark descendants failed
CChainDB chaindb;
CBlockIndex *pindexFailed = pindexNewBest; CBlockIndex *pindexFailed = pindexNewBest;
while (pindexTest != pindexFailed) { while (pindexTest != pindexFailed) {
pindexFailed->nStatus |= BLOCK_FAILED_CHILD; pindexFailed->nStatus |= BLOCK_FAILED_CHILD;
setBlockIndexValid.erase(pindexFailed); setBlockIndexValid.erase(pindexFailed);
chaindb.WriteBlockIndex(CDiskBlockIndex(pindexFailed)); pblocktree->WriteBlockIndex(CDiskBlockIndex(pindexFailed));
pindexFailed = pindexFailed->pprev; pindexFailed = pindexFailed->pprev;
} }
InvalidChainFound(pindexNewBest); InvalidChainFound(pindexNewBest);
@ -1498,7 +1498,7 @@ bool CBlock::DisconnectBlock(CBlockIndex *pindex, CCoinsViewCache &view)
return true; return true;
} }
bool FindUndoPos(CChainDB &chaindb, int nFile, CDiskBlockPos &pos, unsigned int nAddSize); bool FindUndoPos(int nFile, CDiskBlockPos &pos, unsigned int nAddSize);
bool CBlock::ConnectBlock(CBlockIndex* pindex, CCoinsViewCache &view, bool fJustCheck) bool CBlock::ConnectBlock(CBlockIndex* pindex, CCoinsViewCache &view, bool fJustCheck)
{ {
@ -1581,11 +1581,9 @@ bool CBlock::ConnectBlock(CBlockIndex* pindex, CCoinsViewCache &view, bool fJust
// Write undo information to disk // Write undo information to disk
if (pindex->GetUndoPos().IsNull() || (pindex->nStatus & BLOCK_VALID_MASK) < BLOCK_VALID_SCRIPTS) if (pindex->GetUndoPos().IsNull() || (pindex->nStatus & BLOCK_VALID_MASK) < BLOCK_VALID_SCRIPTS)
{ {
CChainDB chaindb;
if (pindex->GetUndoPos().IsNull()) { if (pindex->GetUndoPos().IsNull()) {
CDiskBlockPos pos; CDiskBlockPos pos;
if (!FindUndoPos(chaindb, pindex->nFile, pos, ::GetSerializeSize(blockundo, SER_DISK, CLIENT_VERSION) + 8)) if (!FindUndoPos(pindex->nFile, pos, ::GetSerializeSize(blockundo, SER_DISK, CLIENT_VERSION) + 8))
return error("ConnectBlock() : FindUndoPos failed"); return error("ConnectBlock() : FindUndoPos failed");
if (!blockundo.WriteToDisk(pos)) if (!blockundo.WriteToDisk(pos))
return error("ConnectBlock() : CBlockUndo::WriteToDisk failed"); return error("ConnectBlock() : CBlockUndo::WriteToDisk failed");
@ -1598,7 +1596,7 @@ bool CBlock::ConnectBlock(CBlockIndex* pindex, CCoinsViewCache &view, bool fJust
pindex->nStatus = (pindex->nStatus & ~BLOCK_VALID_MASK) | BLOCK_VALID_SCRIPTS; pindex->nStatus = (pindex->nStatus & ~BLOCK_VALID_MASK) | BLOCK_VALID_SCRIPTS;
CDiskBlockIndex blockindex(pindex); CDiskBlockIndex blockindex(pindex);
if (!chaindb.WriteBlockIndex(blockindex)) if (!pblocktree->WriteBlockIndex(blockindex))
return error("ConnectBlock() : WriteBlockIndex failed"); return error("ConnectBlock() : WriteBlockIndex failed");
} }
@ -1804,12 +1802,7 @@ bool CBlock::AddToBlockIndex(const CDiskBlockPos &pos)
pindexNew->nStatus = BLOCK_VALID_TRANSACTIONS | BLOCK_HAVE_DATA; pindexNew->nStatus = BLOCK_VALID_TRANSACTIONS | BLOCK_HAVE_DATA;
setBlockIndexValid.insert(pindexNew); setBlockIndexValid.insert(pindexNew);
CChainDB chaindb; pblocktree->WriteBlockIndex(CDiskBlockIndex(pindexNew));
if (!chaindb.TxnBegin())
return false;
chaindb.WriteBlockIndex(CDiskBlockIndex(pindexNew));
if (!chaindb.TxnCommit())
return false;
// New best? // New best?
if (!ConnectBestBlock()) if (!ConnectBestBlock())
@ -1823,13 +1816,15 @@ bool CBlock::AddToBlockIndex(const CDiskBlockPos &pos)
hashPrevBestCoinBase = GetTxHash(0); hashPrevBestCoinBase = GetTxHash(0);
} }
pblocktree->Flush();
uiInterface.NotifyBlocksChanged(); uiInterface.NotifyBlocksChanged();
return true; return true;
} }
bool FindBlockPos(CChainDB &chaindb, CDiskBlockPos &pos, unsigned int nAddSize, unsigned int nHeight, uint64 nTime) bool FindBlockPos(CDiskBlockPos &pos, unsigned int nAddSize, unsigned int nHeight, uint64 nTime)
{ {
bool fUpdatedLast = false; bool fUpdatedLast = false;
@ -1845,7 +1840,7 @@ bool FindBlockPos(CChainDB &chaindb, CDiskBlockPos &pos, unsigned int nAddSize,
fclose(file); fclose(file);
nLastBlockFile++; nLastBlockFile++;
infoLastBlockFile.SetNull(); infoLastBlockFile.SetNull();
chaindb.ReadBlockFileInfo(nLastBlockFile, infoLastBlockFile); // check whether data for the new file somehow already exist; can fail just fine pblocktree->ReadBlockFileInfo(nLastBlockFile, infoLastBlockFile); // check whether data for the new file somehow already exist; can fail just fine
fUpdatedLast = true; fUpdatedLast = true;
} }
@ -1865,15 +1860,15 @@ bool FindBlockPos(CChainDB &chaindb, CDiskBlockPos &pos, unsigned int nAddSize,
fclose(file); fclose(file);
} }
if (!chaindb.WriteBlockFileInfo(nLastBlockFile, infoLastBlockFile)) if (!pblocktree->WriteBlockFileInfo(nLastBlockFile, infoLastBlockFile))
return error("FindBlockPos() : cannot write updated block info"); return error("FindBlockPos() : cannot write updated block info");
if (fUpdatedLast) if (fUpdatedLast)
chaindb.WriteLastBlockFile(nLastBlockFile); pblocktree->WriteLastBlockFile(nLastBlockFile);
return true; return true;
} }
bool FindUndoPos(CChainDB &chaindb, int nFile, CDiskBlockPos &pos, unsigned int nAddSize) bool FindUndoPos(int nFile, CDiskBlockPos &pos, unsigned int nAddSize)
{ {
pos.nFile = nFile; pos.nFile = nFile;
@ -1883,15 +1878,15 @@ bool FindUndoPos(CChainDB &chaindb, int nFile, CDiskBlockPos &pos, unsigned int
if (nFile == nLastBlockFile) { if (nFile == nLastBlockFile) {
pos.nPos = infoLastBlockFile.nUndoSize; pos.nPos = infoLastBlockFile.nUndoSize;
nNewSize = (infoLastBlockFile.nUndoSize += nAddSize); nNewSize = (infoLastBlockFile.nUndoSize += nAddSize);
if (!chaindb.WriteBlockFileInfo(nLastBlockFile, infoLastBlockFile)) if (!pblocktree->WriteBlockFileInfo(nLastBlockFile, infoLastBlockFile))
return error("FindUndoPos() : cannot write updated block info"); return error("FindUndoPos() : cannot write updated block info");
} else { } else {
CBlockFileInfo info; CBlockFileInfo info;
if (!chaindb.ReadBlockFileInfo(nFile, info)) if (!pblocktree->ReadBlockFileInfo(nFile, info))
return error("FindUndoPos() : cannot read block info"); return error("FindUndoPos() : cannot read block info");
pos.nPos = info.nUndoSize; pos.nPos = info.nUndoSize;
nNewSize = (info.nUndoSize += nAddSize); nNewSize = (info.nUndoSize += nAddSize);
if (!chaindb.WriteBlockFileInfo(nFile, info)) if (!pblocktree->WriteBlockFileInfo(nFile, info))
return error("FindUndoPos() : cannot write updated block info"); return error("FindUndoPos() : cannot write updated block info");
} }
@ -2022,11 +2017,8 @@ bool CBlock::AcceptBlock()
if (!CheckDiskSpace(::GetSerializeSize(*this, SER_DISK, CLIENT_VERSION))) if (!CheckDiskSpace(::GetSerializeSize(*this, SER_DISK, CLIENT_VERSION)))
return error("AcceptBlock() : out of disk space"); return error("AcceptBlock() : out of disk space");
CDiskBlockPos blockPos; CDiskBlockPos blockPos;
{ if (!FindBlockPos(blockPos, nBlockSize+8, nHeight, nTime))
CChainDB chaindb; return error("AcceptBlock() : FindBlockPos failed");
if (!FindBlockPos(chaindb, blockPos, nBlockSize+8, nHeight, nTime))
return error("AcceptBlock() : FindBlockPos failed");
}
if (!WriteToDisk(blockPos)) if (!WriteToDisk(blockPos))
return error("AcceptBlock() : WriteToDisk failed"); return error("AcceptBlock() : WriteToDisk failed");
if (!AddToBlockIndex(blockPos)) if (!AddToBlockIndex(blockPos))
@ -2210,12 +2202,10 @@ bool LoadBlockIndex(bool fAllowNew)
} }
// //
// Load block index // Load block index from databases
// //
CChainDB chaindb("cr"); if (!LoadBlockIndexDB())
if (!LoadBlockIndex(chaindb))
return false; return false;
chaindb.Close();
// //
// Init with genesis block // Init with genesis block
@ -2267,11 +2257,8 @@ bool LoadBlockIndex(bool fAllowNew)
// Start new block file // Start new block file
unsigned int nBlockSize = ::GetSerializeSize(block, SER_DISK, CLIENT_VERSION); unsigned int nBlockSize = ::GetSerializeSize(block, SER_DISK, CLIENT_VERSION);
CDiskBlockPos blockPos; CDiskBlockPos blockPos;
{ if (!FindBlockPos(blockPos, nBlockSize+8, 0, block.nTime))
CChainDB chaindb; return error("AcceptBlock() : FindBlockPos failed");
if (!FindBlockPos(chaindb, blockPos, nBlockSize+8, 0, block.nTime))
return error("AcceptBlock() : FindBlockPos failed");
}
if (!block.WriteToDisk(blockPos)) if (!block.WriteToDisk(blockPos))
return error("LoadBlockIndex() : writing genesis block to disk failed"); return error("LoadBlockIndex() : writing genesis block to disk failed");
if (!block.AddToBlockIndex(blockPos)) if (!block.AddToBlockIndex(blockPos))

6
src/main.h

@ -86,7 +86,7 @@ static const uint64 nMinDiskSpace = 52428800;
class CReserveKey; class CReserveKey;
class CCoinsDB; class CCoinsDB;
class CChainDB; class CBlockTreeDB;
class CDiskBlockPos; class CDiskBlockPos;
class CCoins; class CCoins;
class CTxUndo; class CTxUndo;
@ -1865,6 +1865,10 @@ public:
bool HaveCoins(uint256 txid); bool HaveCoins(uint256 txid);
}; };
/** Global variable that points to the active CCoinsView (protected by cs_main) */
extern CCoinsViewCache *pcoinsTip; extern CCoinsViewCache *pcoinsTip;
/** Global variable that points to the active block tree (protected by cs_main) */
extern CBlockTreeDB *pblocktree;
#endif #endif

8
src/test/test_bitcoin.cpp

@ -12,10 +12,15 @@ extern bool fPrintToConsole;
extern void noui_connect(); extern void noui_connect();
struct TestingSetup { struct TestingSetup {
CCoinsViewDB *pcoinsdbview;
TestingSetup() { TestingSetup() {
fPrintToDebugger = true; // don't want to write to debug.log file fPrintToDebugger = true; // don't want to write to debug.log file
noui_connect(); noui_connect();
bitdb.MakeMock(); bitdb.MakeMock();
pblocktree = new CBlockTreeDB("cr+");
pcoinsdbview = new CCoinsViewDB();
pcoinsTip = new CCoinsViewCache(*pcoinsdbview);
LoadBlockIndex(true); LoadBlockIndex(true);
bool fFirstRun; bool fFirstRun;
pwalletMain = new CWallet("wallet.dat"); pwalletMain = new CWallet("wallet.dat");
@ -26,6 +31,9 @@ struct TestingSetup {
{ {
delete pwalletMain; delete pwalletMain;
pwalletMain = NULL; pwalletMain = NULL;
delete pcoinsTip;
delete pcoinsdbview;
delete pblocktree;
bitdb.Flush(true); bitdb.Flush(true);
} }
}; };

Loading…
Cancel
Save