aboutsummaryrefslogtreecommitdiff
path: root/src/txdb-bdb.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/txdb-bdb.cpp')
-rw-r--r--src/txdb-bdb.cpp171
1 files changed, 171 insertions, 0 deletions
diff --git a/src/txdb-bdb.cpp b/src/txdb-bdb.cpp
new file mode 100644
index 0000000000..5e46096646
--- /dev/null
+++ b/src/txdb-bdb.cpp
@@ -0,0 +1,171 @@
+// 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("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;
+}
+
+
+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;
+}