From 4ca60bba5c3b8394c252715c71e8758d63c316ee Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Tue, 16 Oct 2012 22:23:39 +0200 Subject: Remove BDB block database support --- src/makefile.linux-mingw | 12 +-- src/makefile.mingw | 12 +-- src/makefile.osx | 12 +-- src/makefile.unix | 12 +-- src/test/test_bitcoin.cpp | 5 -- src/txdb-bdb.cpp | 171 ----------------------------------------- src/txdb-bdb.h | 61 --------------- src/txdb-leveldb.cpp | 189 ---------------------------------------------- src/txdb-leveldb.h | 47 ------------ src/txdb.cpp | 189 ++++++++++++++++++++++++++++++++++++++++++++++ src/txdb.h | 49 ++++++++++-- 11 files changed, 246 insertions(+), 513 deletions(-) delete mode 100644 src/txdb-bdb.cpp delete mode 100644 src/txdb-bdb.h delete mode 100644 src/txdb-leveldb.cpp delete mode 100644 src/txdb-leveldb.h create mode 100644 src/txdb.cpp (limited to 'src') diff --git a/src/makefile.linux-mingw b/src/makefile.linux-mingw index eee325d624..f4adbb2bff 100644 --- a/src/makefile.linux-mingw +++ b/src/makefile.linux-mingw @@ -6,7 +6,6 @@ DEPSDIR:=/usr/i586-mingw32msvc USE_UPNP:=0 USE_IPV6:=1 -USE_LEVELDB:=1 INCLUDEPATHS= \ -I"$(CURDIR)" \ @@ -83,21 +82,18 @@ OBJS= \ obj/util.o \ obj/wallet.o \ obj/walletdb.o \ - obj/noui.o + obj/noui.o \ + obj/leveldb.o \ + obj/txdb.o all: bitcoind.exe -ifdef USE_LEVELDB LIBS += $(CURDIR)/leveldb/libleveldb.a $(CURDIR)/leveldb/libmemenv.a -DEFS += -I"$(CURDIR)/leveldb/include" -DUSE_LEVELDB +DEFS += -I"$(CURDIR)/leveldb/include" DEFS += -I"$(CURDIR)/leveldb/helpers" -OBJS += obj/leveldb.o obj/txdb-leveldb.o leveldb/libleveldb.a: @echo "Building LevelDB ..."; cd leveldb; TARGET_OS=OS_WINDOWS_CROSSCOMPILE CXXFLAGS="-I$(INCLUDEPATHS)" LDFLAGS="-L$(LIBPATHS)" make libleveldb.a libmemenv.a; cd .. obj/leveldb.o: leveldb/libleveldb.a -else -OBJS += obj/txdb-bdb.o -endif obj/build.h: FORCE /bin/sh ../share/genbuild.sh obj/build.h diff --git a/src/makefile.mingw b/src/makefile.mingw index 4d95d1c038..89a4f372c5 100644 --- a/src/makefile.mingw +++ b/src/makefile.mingw @@ -4,7 +4,6 @@ USE_UPNP:=0 USE_IPV6:=1 -USE_LEVELDB:=1 INCLUDEPATHS= \ -I"C:\boost-1.50.0-mgw" \ @@ -79,7 +78,9 @@ OBJS= \ obj/util.o \ obj/wallet.o \ obj/walletdb.o \ - obj/noui.o + obj/noui.o \ + obj/leveldb.o \ + obj/txdb.o all: bitcoind.exe @@ -90,17 +91,12 @@ test check: test_bitcoin.exe FORCE # # LevelDB support # -ifdef USE_LEVELDB LIBS += $(CURDIR)/leveldb/libleveldb.a $(CURDIR)/leveldb/libmemenv.a -DEFS += $(addprefix -I,$(CURDIR)/leveldb/include) -DUSE_LEVELDB +DEFS += $(addprefix -I,$(CURDIR)/leveldb/include) DEFS += $(addprefix -I,$(CURDIR)/leveldb/helpers) -OBJS += obj/leveldb.o obj/txdb-leveldb.o leveldb/libleveldb.a: cd leveldb; make libleveldb.a libmemenv.a; cd .. obj/leveldb.o: leveldb/libleveldb.lib -else -OBJS += obj/txdb-bdb.o -endif obj/%.o: %.cpp $(HEADERS) g++ -c $(CFLAGS) -o $@ $< diff --git a/src/makefile.osx b/src/makefile.osx index 9a9296f412..f3e17d0d13 100644 --- a/src/makefile.osx +++ b/src/makefile.osx @@ -21,7 +21,6 @@ LIBPATHS= \ USE_UPNP:=1 USE_IPV6:=1 -USE_LEVELDB:=1 LIBS= -dead_strip @@ -97,7 +96,9 @@ OBJS= \ obj/util.o \ obj/wallet.o \ obj/walletdb.o \ - obj/noui.o + obj/noui.o \ + obj/leveldb.o \ + obj/txdb.o ifndef USE_UPNP override USE_UPNP = - @@ -123,17 +124,12 @@ test check: test_bitcoin FORCE # # LevelDB support # -ifdef USE_LEVELDB LIBS += $(CURDIR)/leveldb/libleveldb.a $(CURDIR)/leveldb/libmemenv.a -DEFS += $(addprefix -I,$(CURDIR)/leveldb/include) -DUSE_LEVELDB +DEFS += $(addprefix -I,$(CURDIR)/leveldb/include) DEFS += $(addprefix -I,$(CURDIR)/leveldb/helpers) -OBJS += obj/leveldb.o obj/txdb-leveldb.o leveldb/libleveldb.a: @echo "Building LevelDB ..."; cd leveldb; make libleveldb.a libmemenv.a; cd .. obj/leveldb.o: leveldb/libleveldb.a -else -OBJS += obj/txdb-bdb.o -endif # auto-generated dependencies: -include obj/*.P diff --git a/src/makefile.unix b/src/makefile.unix index 95234bae2a..df05f7990a 100644 --- a/src/makefile.unix +++ b/src/makefile.unix @@ -4,7 +4,6 @@ USE_UPNP:=0 USE_IPV6:=1 -USE_LEVELDB:=1 LINK:=$(CXX) @@ -128,7 +127,9 @@ OBJS= \ obj/util.o \ obj/wallet.o \ obj/walletdb.o \ - obj/noui.o + obj/noui.o \ + obj/leveldb.o \ + obj/txdb.o all: bitcoind @@ -139,17 +140,12 @@ test check: test_bitcoin FORCE # # LevelDB support # -ifdef USE_LEVELDB LIBS += $(CURDIR)/leveldb/libleveldb.a $(CURDIR)/leveldb/libmemenv.a -DEFS += $(addprefix -I,$(CURDIR)/leveldb/include) -DUSE_LEVELDB +DEFS += $(addprefix -I,$(CURDIR)/leveldb/include) DEFS += $(addprefix -I,$(CURDIR)/leveldb/helpers) -OBJS += obj/leveldb.o obj/txdb-leveldb.o leveldb/libleveldb.a: @echo "Building LevelDB ..."; cd leveldb; make libleveldb.a libmemenv.a; cd ..; obj/leveldb.o: leveldb/libleveldb.a -else -OBJS += obj/txdb-bdb.o -endif # auto-generated dependencies: -include obj/*.P diff --git a/src/test/test_bitcoin.cpp b/src/test/test_bitcoin.cpp index 0173c0064b..c1f47f786b 100644 --- a/src/test/test_bitcoin.cpp +++ b/src/test/test_bitcoin.cpp @@ -19,13 +19,8 @@ struct TestingSetup { fPrintToDebugger = true; // don't want to write to debug.log file noui_connect(); bitdb.MakeMock(); -#ifdef USE_LEVELDB pblocktree = new CBlockTreeDB(true); pcoinsdbview = new CCoinsViewDB(true); -#else - pblocktree = new CBlockTreeDB(); - pcoinsdbview = new CCoinsViewDB(); -#endif pcoinsTip = new CCoinsViewCache(*pcoinsdbview); LoadBlockIndex(true); bool fFirstRun; diff --git a/src/txdb-bdb.cpp b/src/txdb-bdb.cpp deleted file mode 100644 index 8954b8b30a..0000000000 --- a/src/txdb-bdb.cpp +++ /dev/null @@ -1,171 +0,0 @@ -// Copyright (c) 2009-2010 Satoshi Nakamoto -// Copyright (c) 2009-2012 The Bitcoin developers -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - -#include "txdb-bdb.h" - -bool CCoinsDB::HaveCoins(uint256 hash) { - assert(!fClient); - return Exists(make_pair('c', hash)); -} - -bool CCoinsDB::ReadCoins(uint256 hash, CCoins &coins) { - assert(!fClient); - return Read(make_pair('c', hash), coins); -} - -bool CCoinsDB::WriteCoins(uint256 hash, const CCoins &coins) { - assert(!fClient); - if (coins.IsPruned()) - return Erase(make_pair('c', hash)); - else - return Write(make_pair('c', hash), coins); -} - -bool CCoinsDB::ReadHashBestChain(uint256& hashBestChain) -{ - return Read('B', hashBestChain); -} - -bool CCoinsDB::WriteHashBestChain(uint256 hashBestChain) -{ - return Write('B', hashBestChain); -} - -bool CBlockTreeDB::WriteBlockIndex(const CDiskBlockIndex& blockindex) -{ - return Write(make_pair('b', blockindex.GetBlockHash()), blockindex); -} - -bool CBlockTreeDB::ReadBestInvalidWork(CBigNum& bnBestInvalidWork) -{ - return Read('I', bnBestInvalidWork); -} - -bool CBlockTreeDB::WriteBestInvalidWork(CBigNum bnBestInvalidWork) -{ - return Write('I', bnBestInvalidWork); -} - -bool CBlockTreeDB::WriteBlockFileInfo(int nFile, const CBlockFileInfo &info) { - return Write(make_pair('f', nFile), info); -} - -bool CBlockTreeDB::ReadBlockFileInfo(int nFile, CBlockFileInfo &info) { - return Read(make_pair('f', nFile), info); -} - -bool CBlockTreeDB::WriteLastBlockFile(int nFile) { - return Write('l', nFile); -} - -bool CBlockTreeDB::ReadLastBlockFile(int &nFile) { - return Read('l', nFile); -} - -CCoinsViewDB::CCoinsViewDB() : db() {} -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::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 &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::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; -} - - -bool CBlockTreeDB::LoadBlockIndexGuts() -{ - // Get database cursor - Dbc* pcursor = GetCursor(); - if (!pcursor) - return false; - - // Load mapBlockIndex - unsigned int fFlags = DB_SET_RANGE; - loop - { - // Read next record - CDataStream ssKey(SER_DISK, CLIENT_VERSION); - if (fFlags == DB_SET_RANGE) - ssKey << make_pair('b', uint256(0)); - CDataStream ssValue(SER_DISK, CLIENT_VERSION); - int ret = ReadAtCursor(pcursor, ssKey, ssValue, fFlags); - fFlags = DB_NEXT; - if (ret == DB_NOTFOUND) - break; - else if (ret != 0) - return false; - - // Unserialize - - try { - char chType; - ssKey >> chType; - if (chType == 'b' && !fRequestShutdown) - { - CDiskBlockIndex diskindex; - ssValue >> diskindex; - - // Construct block index object - CBlockIndex* pindexNew = InsertBlockIndex(diskindex.GetBlockHash()); - pindexNew->pprev = InsertBlockIndex(diskindex.hashPrev); - pindexNew->nHeight = diskindex.nHeight; - pindexNew->nFile = diskindex.nFile; - pindexNew->nDataPos = diskindex.nDataPos; - pindexNew->nUndoPos = diskindex.nUndoPos; - pindexNew->nVersion = diskindex.nVersion; - pindexNew->hashMerkleRoot = diskindex.hashMerkleRoot; - pindexNew->nTime = diskindex.nTime; - pindexNew->nBits = diskindex.nBits; - pindexNew->nNonce = diskindex.nNonce; - pindexNew->nStatus = diskindex.nStatus; - pindexNew->nTx = diskindex.nTx; - - // Watch for genesis block - if (pindexGenesisBlock == NULL && diskindex.GetBlockHash() == hashGenesisBlock) - pindexGenesisBlock = pindexNew; - - if (!pindexNew->CheckIndex()) - return error("LoadBlockIndex() : CheckIndex failed: %s", pindexNew->ToString().c_str()); - } - else - { - break; // if shutdown requested or finished loading block index - } - } // try - catch (std::exception &e) { - return error("%s() : deserialize error", __PRETTY_FUNCTION__); - } - } - pcursor->close(); - - return true; -} diff --git a/src/txdb-bdb.h b/src/txdb-bdb.h deleted file mode 100644 index 3e8d40c274..0000000000 --- a/src/txdb-bdb.h +++ /dev/null @@ -1,61 +0,0 @@ -// Copyright (c) 2009-2010 Satoshi Nakamoto -// Copyright (c) 2009-2012 The Bitcoin developers -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. -#ifndef BITCOIN_TXDB_BDB_H -#define BITCOIN_TXDB_BDB_H - -#include "db.h" - -/** Access to the transaction database (coins.dat) */ -class CCoinsDB : public CDB -{ -public: - CCoinsDB() : CDB("coins.dat", "cr+") { } -private: - CCoinsDB(const CCoinsDB&); - void operator=(const CCoinsDB&); -public: - bool ReadCoins(uint256 hash, CCoins &coins); - bool WriteCoins(uint256 hash, const CCoins& coins); - bool HaveCoins(uint256 hash); - bool ReadHashBestChain(uint256& hashBestChain); - 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 &mapCoins, CBlockIndex *pindex); -}; - -/** Access to the block database (blktree.dat) */ -class CBlockTreeDB : public CDB -{ -public: - CBlockTreeDB() : CDB("blktree.dat", "cr+") { } -private: - CBlockTreeDB(const CBlockTreeDB&); - void operator=(const CBlockTreeDB&); -public: - bool WriteBlockIndex(const CDiskBlockIndex& blockindex); - bool ReadBestInvalidWork(CBigNum& bnBestInvalidWork); - bool WriteBestInvalidWork(CBigNum bnBestInvalidWork); - bool ReadBlockFileInfo(int nFile, CBlockFileInfo &fileinfo); - bool WriteBlockFileInfo(int nFile, const CBlockFileInfo &fileinfo); - bool ReadLastBlockFile(int &nFile); - bool WriteLastBlockFile(int nFile); - bool LoadBlockIndexGuts(); -}; - -#endif // BITCOIN_TXDB_BDB_H diff --git a/src/txdb-leveldb.cpp b/src/txdb-leveldb.cpp deleted file mode 100644 index 7c72ccac02..0000000000 --- a/src/txdb-leveldb.cpp +++ /dev/null @@ -1,189 +0,0 @@ -// Copyright (c) 2009-2010 Satoshi Nakamoto -// Copyright (c) 2009-2012 The Bitcoin developers -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - -#include "txdb-leveldb.h" -#include "main.h" - -using namespace std; - -void static BatchWriteCoins(CLevelDBBatch &batch, const uint256 &hash, const CCoins &coins) { - if (coins.IsPruned()) - batch.Erase(make_pair('c', hash)); - else - batch.Write(make_pair('c', hash), coins); -} - -void static BatchWriteHashBestChain(CLevelDBBatch &batch, const uint256 &hash) { - batch.Write('B', hash); -} - -CCoinsViewDB::CCoinsViewDB(bool fMemory) : db(GetDataDir() / "coins", fMemory) { -} - -bool CCoinsViewDB::GetCoins(uint256 txid, CCoins &coins) { - return db.Read(make_pair('c', txid), coins); -} - -bool CCoinsViewDB::SetCoins(uint256 txid, const CCoins &coins) { - CLevelDBBatch batch; - BatchWriteCoins(batch, txid, coins); - return db.WriteBatch(batch); -} - -bool CCoinsViewDB::HaveCoins(uint256 txid) { - return db.Exists(make_pair('c', txid)); -} - -CBlockIndex *CCoinsViewDB::GetBestBlock() { - uint256 hashBestChain; - if (!db.Read('B', hashBestChain)) - return NULL; - std::map::iterator it = mapBlockIndex.find(hashBestChain); - if (it == mapBlockIndex.end()) - return NULL; - return it->second; -} - -bool CCoinsViewDB::SetBestBlock(CBlockIndex *pindex) { - CLevelDBBatch batch; - BatchWriteHashBestChain(batch, pindex->GetBlockHash()); - return db.WriteBatch(batch); -} - -bool CCoinsViewDB::BatchWrite(const std::map &mapCoins, CBlockIndex *pindex) { - printf("Committing %u changed transactions to coin database...\n", (unsigned int)mapCoins.size()); - - CLevelDBBatch batch; - for (std::map::const_iterator it = mapCoins.begin(); it != mapCoins.end(); it++) - BatchWriteCoins(batch, it->first, it->second); - BatchWriteHashBestChain(batch, pindex->GetBlockHash()); - - return db.WriteBatch(batch); -} - -CBlockTreeDB::CBlockTreeDB(bool fMemory) : CLevelDB(GetDataDir() / "blktree", fMemory) { -} - -bool CBlockTreeDB::WriteBlockIndex(const CDiskBlockIndex& blockindex) -{ - return Write(make_pair('b', blockindex.GetBlockHash()), blockindex); -} - -bool CBlockTreeDB::ReadBestInvalidWork(CBigNum& bnBestInvalidWork) -{ - return Read('I', bnBestInvalidWork); -} - -bool CBlockTreeDB::WriteBestInvalidWork(const CBigNum& bnBestInvalidWork) -{ - return Write('I', bnBestInvalidWork); -} - -bool CBlockTreeDB::WriteBlockFileInfo(int nFile, const CBlockFileInfo &info) { - return Write(make_pair('f', nFile), info); -} - -bool CBlockTreeDB::ReadBlockFileInfo(int nFile, CBlockFileInfo &info) { - return Read(make_pair('f', nFile), info); -} - -bool CBlockTreeDB::WriteLastBlockFile(int nFile) { - return Write('l', nFile); -} - -bool CBlockTreeDB::ReadLastBlockFile(int &nFile) { - return Read('l', nFile); -} - -bool CCoinsViewDB::GetStats(CCoinsStats &stats) { - leveldb::Iterator *pcursor = db.NewIterator(); - pcursor->SeekToFirst(); - - while (pcursor->Valid()) { - try { - leveldb::Slice slKey = pcursor->key(); - CDataStream ssKey(slKey.data(), slKey.data()+slKey.size(), SER_DISK, CLIENT_VERSION); - char chType; - ssKey >> chType; - if (chType == 'c' && !fRequestShutdown) { - leveldb::Slice slValue = pcursor->value(); - CDataStream ssValue(slValue.data(), slValue.data()+slValue.size(), SER_DISK, CLIENT_VERSION); - CCoins coins; - ssValue >> coins; - uint256 txhash; - ssKey >> txhash; - - stats.nTransactions++; - BOOST_FOREACH(const CTxOut &out, coins.vout) { - if (!out.IsNull()) - stats.nTransactionOutputs++; - } - stats.nSerializedSize += 32 + slValue.size(); - } - pcursor->Next(); - } catch (std::exception &e) { - return error("%s() : deserialize error", __PRETTY_FUNCTION__); - } - } - delete pcursor; - stats.nHeight = GetBestBlock()->nHeight; - return true; -} - -bool CBlockTreeDB::LoadBlockIndexGuts() -{ - leveldb::Iterator *pcursor = NewIterator(); - - CDataStream ssKeySet(SER_DISK, CLIENT_VERSION); - ssKeySet << make_pair('b', uint256(0)); - pcursor->Seek(ssKeySet.str()); - - // Load mapBlockIndex - while (pcursor->Valid()) { - try { - leveldb::Slice slKey = pcursor->key(); - CDataStream ssKey(slKey.data(), slKey.data()+slKey.size(), SER_DISK, CLIENT_VERSION); - char chType; - ssKey >> chType; - if (chType == 'b' && !fRequestShutdown) { - leveldb::Slice slValue = pcursor->value(); - CDataStream ssValue(slValue.data(), slValue.data()+slValue.size(), SER_DISK, CLIENT_VERSION); - CDiskBlockIndex diskindex; - ssValue >> diskindex; - - // Construct block index object - CBlockIndex* pindexNew = InsertBlockIndex(diskindex.GetBlockHash()); - pindexNew->pprev = InsertBlockIndex(diskindex.hashPrev); - pindexNew->nHeight = diskindex.nHeight; - pindexNew->nFile = diskindex.nFile; - pindexNew->nDataPos = diskindex.nDataPos; - pindexNew->nUndoPos = diskindex.nUndoPos; - pindexNew->nVersion = diskindex.nVersion; - pindexNew->hashMerkleRoot = diskindex.hashMerkleRoot; - pindexNew->nTime = diskindex.nTime; - pindexNew->nBits = diskindex.nBits; - pindexNew->nNonce = diskindex.nNonce; - pindexNew->nStatus = diskindex.nStatus; - pindexNew->nTx = diskindex.nTx; - - // Watch for genesis block - if (pindexGenesisBlock == NULL && diskindex.GetBlockHash() == hashGenesisBlock) - pindexGenesisBlock = pindexNew; - - if (!pindexNew->CheckIndex()) - return error("LoadBlockIndex() : CheckIndex failed: %s", pindexNew->ToString().c_str()); - - pcursor->Next(); - } else { - break; // if shutdown requested or finished loading block index - } - } catch (std::exception &e) { - return error("%s() : deserialize error", __PRETTY_FUNCTION__); - } - } - delete pcursor; - - return true; -} diff --git a/src/txdb-leveldb.h b/src/txdb-leveldb.h deleted file mode 100644 index 123ec00d23..0000000000 --- a/src/txdb-leveldb.h +++ /dev/null @@ -1,47 +0,0 @@ -// Copyright (c) 2009-2010 Satoshi Nakamoto -// Copyright (c) 2009-2012 The Bitcoin developers -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. -#ifndef BITCOIN_TXDB_LEVELDB_H -#define BITCOIN_TXDB_LEVELDB_H - -#include "main.h" -#include "leveldb.h" - -/** CCoinsView backed by the LevelDB coin database (coins/) */ -class CCoinsViewDB : public CCoinsView -{ -protected: - CLevelDB db; -public: - CCoinsViewDB(bool fMemory = false); - - 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 &mapCoins, CBlockIndex *pindex); - bool GetStats(CCoinsStats &stats); -}; - -/** Access to the block database (blktree/) */ -class CBlockTreeDB : public CLevelDB -{ -public: - CBlockTreeDB(bool fMemory = false); -private: - CBlockTreeDB(const CBlockTreeDB&); - void operator=(const CBlockTreeDB&); -public: - bool WriteBlockIndex(const CDiskBlockIndex& blockindex); - bool ReadBestInvalidWork(CBigNum& bnBestInvalidWork); - bool WriteBestInvalidWork(const CBigNum& bnBestInvalidWork); - bool ReadBlockFileInfo(int nFile, CBlockFileInfo &fileinfo); - bool WriteBlockFileInfo(int nFile, const CBlockFileInfo &fileinfo); - bool ReadLastBlockFile(int &nFile); - bool WriteLastBlockFile(int nFile); - bool LoadBlockIndexGuts(); -}; - -#endif // BITCOIN_TXDB_LEVELDB_H diff --git a/src/txdb.cpp b/src/txdb.cpp new file mode 100644 index 0000000000..67d15cb58f --- /dev/null +++ b/src/txdb.cpp @@ -0,0 +1,189 @@ +// Copyright (c) 2009-2010 Satoshi Nakamoto +// Copyright (c) 2009-2012 The Bitcoin developers +// Distributed under the MIT/X11 software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#include "txdb.h" +#include "main.h" + +using namespace std; + +void static BatchWriteCoins(CLevelDBBatch &batch, const uint256 &hash, const CCoins &coins) { + if (coins.IsPruned()) + batch.Erase(make_pair('c', hash)); + else + batch.Write(make_pair('c', hash), coins); +} + +void static BatchWriteHashBestChain(CLevelDBBatch &batch, const uint256 &hash) { + batch.Write('B', hash); +} + +CCoinsViewDB::CCoinsViewDB(bool fMemory) : db(GetDataDir() / "coins", fMemory) { +} + +bool CCoinsViewDB::GetCoins(uint256 txid, CCoins &coins) { + return db.Read(make_pair('c', txid), coins); +} + +bool CCoinsViewDB::SetCoins(uint256 txid, const CCoins &coins) { + CLevelDBBatch batch; + BatchWriteCoins(batch, txid, coins); + return db.WriteBatch(batch); +} + +bool CCoinsViewDB::HaveCoins(uint256 txid) { + return db.Exists(make_pair('c', txid)); +} + +CBlockIndex *CCoinsViewDB::GetBestBlock() { + uint256 hashBestChain; + if (!db.Read('B', hashBestChain)) + return NULL; + std::map::iterator it = mapBlockIndex.find(hashBestChain); + if (it == mapBlockIndex.end()) + return NULL; + return it->second; +} + +bool CCoinsViewDB::SetBestBlock(CBlockIndex *pindex) { + CLevelDBBatch batch; + BatchWriteHashBestChain(batch, pindex->GetBlockHash()); + return db.WriteBatch(batch); +} + +bool CCoinsViewDB::BatchWrite(const std::map &mapCoins, CBlockIndex *pindex) { + printf("Committing %u changed transactions to coin database...\n", (unsigned int)mapCoins.size()); + + CLevelDBBatch batch; + for (std::map::const_iterator it = mapCoins.begin(); it != mapCoins.end(); it++) + BatchWriteCoins(batch, it->first, it->second); + BatchWriteHashBestChain(batch, pindex->GetBlockHash()); + + return db.WriteBatch(batch); +} + +CBlockTreeDB::CBlockTreeDB(bool fMemory) : CLevelDB(GetDataDir() / "blktree", fMemory) { +} + +bool CBlockTreeDB::WriteBlockIndex(const CDiskBlockIndex& blockindex) +{ + return Write(make_pair('b', blockindex.GetBlockHash()), blockindex); +} + +bool CBlockTreeDB::ReadBestInvalidWork(CBigNum& bnBestInvalidWork) +{ + return Read('I', bnBestInvalidWork); +} + +bool CBlockTreeDB::WriteBestInvalidWork(const CBigNum& bnBestInvalidWork) +{ + return Write('I', bnBestInvalidWork); +} + +bool CBlockTreeDB::WriteBlockFileInfo(int nFile, const CBlockFileInfo &info) { + return Write(make_pair('f', nFile), info); +} + +bool CBlockTreeDB::ReadBlockFileInfo(int nFile, CBlockFileInfo &info) { + return Read(make_pair('f', nFile), info); +} + +bool CBlockTreeDB::WriteLastBlockFile(int nFile) { + return Write('l', nFile); +} + +bool CBlockTreeDB::ReadLastBlockFile(int &nFile) { + return Read('l', nFile); +} + +bool CCoinsViewDB::GetStats(CCoinsStats &stats) { + leveldb::Iterator *pcursor = db.NewIterator(); + pcursor->SeekToFirst(); + + while (pcursor->Valid()) { + try { + leveldb::Slice slKey = pcursor->key(); + CDataStream ssKey(slKey.data(), slKey.data()+slKey.size(), SER_DISK, CLIENT_VERSION); + char chType; + ssKey >> chType; + if (chType == 'c' && !fRequestShutdown) { + leveldb::Slice slValue = pcursor->value(); + CDataStream ssValue(slValue.data(), slValue.data()+slValue.size(), SER_DISK, CLIENT_VERSION); + CCoins coins; + ssValue >> coins; + uint256 txhash; + ssKey >> txhash; + + stats.nTransactions++; + BOOST_FOREACH(const CTxOut &out, coins.vout) { + if (!out.IsNull()) + stats.nTransactionOutputs++; + } + stats.nSerializedSize += 32 + slValue.size(); + } + pcursor->Next(); + } catch (std::exception &e) { + return error("%s() : deserialize error", __PRETTY_FUNCTION__); + } + } + delete pcursor; + stats.nHeight = GetBestBlock()->nHeight; + return true; +} + +bool CBlockTreeDB::LoadBlockIndexGuts() +{ + leveldb::Iterator *pcursor = NewIterator(); + + CDataStream ssKeySet(SER_DISK, CLIENT_VERSION); + ssKeySet << make_pair('b', uint256(0)); + pcursor->Seek(ssKeySet.str()); + + // Load mapBlockIndex + while (pcursor->Valid()) { + try { + leveldb::Slice slKey = pcursor->key(); + CDataStream ssKey(slKey.data(), slKey.data()+slKey.size(), SER_DISK, CLIENT_VERSION); + char chType; + ssKey >> chType; + if (chType == 'b' && !fRequestShutdown) { + leveldb::Slice slValue = pcursor->value(); + CDataStream ssValue(slValue.data(), slValue.data()+slValue.size(), SER_DISK, CLIENT_VERSION); + CDiskBlockIndex diskindex; + ssValue >> diskindex; + + // Construct block index object + CBlockIndex* pindexNew = InsertBlockIndex(diskindex.GetBlockHash()); + pindexNew->pprev = InsertBlockIndex(diskindex.hashPrev); + pindexNew->nHeight = diskindex.nHeight; + pindexNew->nFile = diskindex.nFile; + pindexNew->nDataPos = diskindex.nDataPos; + pindexNew->nUndoPos = diskindex.nUndoPos; + pindexNew->nVersion = diskindex.nVersion; + pindexNew->hashMerkleRoot = diskindex.hashMerkleRoot; + pindexNew->nTime = diskindex.nTime; + pindexNew->nBits = diskindex.nBits; + pindexNew->nNonce = diskindex.nNonce; + pindexNew->nStatus = diskindex.nStatus; + pindexNew->nTx = diskindex.nTx; + + // Watch for genesis block + if (pindexGenesisBlock == NULL && diskindex.GetBlockHash() == hashGenesisBlock) + pindexGenesisBlock = pindexNew; + + if (!pindexNew->CheckIndex()) + return error("LoadBlockIndex() : CheckIndex failed: %s", pindexNew->ToString().c_str()); + + pcursor->Next(); + } else { + break; // if shutdown requested or finished loading block index + } + } catch (std::exception &e) { + return error("%s() : deserialize error", __PRETTY_FUNCTION__); + } + } + delete pcursor; + + return true; +} diff --git a/src/txdb.h b/src/txdb.h index e21a1e6774..123ec00d23 100644 --- a/src/txdb.h +++ b/src/txdb.h @@ -2,13 +2,46 @@ // Copyright (c) 2009-2012 The Bitcoin developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#ifndef BITCOIN_TXDB_H -#define BITCOIN_TXDB_H +#ifndef BITCOIN_TXDB_LEVELDB_H +#define BITCOIN_TXDB_LEVELDB_H -#ifdef USE_LEVELDB -#include "txdb-leveldb.h" -#else -#include "txdb-bdb.h" -#endif +#include "main.h" +#include "leveldb.h" -#endif // BITCOIN_TXDB_H +/** CCoinsView backed by the LevelDB coin database (coins/) */ +class CCoinsViewDB : public CCoinsView +{ +protected: + CLevelDB db; +public: + CCoinsViewDB(bool fMemory = false); + + 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 &mapCoins, CBlockIndex *pindex); + bool GetStats(CCoinsStats &stats); +}; + +/** Access to the block database (blktree/) */ +class CBlockTreeDB : public CLevelDB +{ +public: + CBlockTreeDB(bool fMemory = false); +private: + CBlockTreeDB(const CBlockTreeDB&); + void operator=(const CBlockTreeDB&); +public: + bool WriteBlockIndex(const CDiskBlockIndex& blockindex); + bool ReadBestInvalidWork(CBigNum& bnBestInvalidWork); + bool WriteBestInvalidWork(const CBigNum& bnBestInvalidWork); + bool ReadBlockFileInfo(int nFile, CBlockFileInfo &fileinfo); + bool WriteBlockFileInfo(int nFile, const CBlockFileInfo &fileinfo); + bool ReadLastBlockFile(int &nFile); + bool WriteLastBlockFile(int nFile); + bool LoadBlockIndexGuts(); +}; + +#endif // BITCOIN_TXDB_LEVELDB_H -- cgit v1.2.3