aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPieter Wuille <pieter.wuille@gmail.com>2017-05-12 15:19:19 -0700
committerPieter Wuille <pieter.wuille@gmail.com>2017-05-26 13:33:39 -0700
commitc3aa0c11947dfd82702df276d39bb7f748dd83a1 (patch)
tree56b0c561bee4a5fcf9f6c54b85c9d1200569d718
parentd342424301013ec47dc146a4beb49d5c9319d80a (diff)
Report on-disk size in gettxoutsetinfo
-rw-r--r--src/coins.cpp1
-rw-r--r--src/coins.h4
-rw-r--r--src/dbwrapper.h17
-rw-r--r--src/rpc/blockchain.cpp4
-rw-r--r--src/txdb.cpp5
-rw-r--r--src/txdb.h2
-rwxr-xr-xtest/functional/blockchain.py3
7 files changed, 35 insertions, 1 deletions
diff --git a/src/coins.cpp b/src/coins.cpp
index b2e33abf33..02f424fad6 100644
--- a/src/coins.cpp
+++ b/src/coins.cpp
@@ -55,6 +55,7 @@ uint256 CCoinsViewBacked::GetBestBlock() const { return base->GetBestBlock(); }
void CCoinsViewBacked::SetBackend(CCoinsView &viewIn) { base = &viewIn; }
bool CCoinsViewBacked::BatchWrite(CCoinsMap &mapCoins, const uint256 &hashBlock) { return base->BatchWrite(mapCoins, hashBlock); }
CCoinsViewCursor *CCoinsViewBacked::Cursor() const { return base->Cursor(); }
+size_t CCoinsViewBacked::EstimateSize() const { return base->EstimateSize(); }
SaltedTxidHasher::SaltedTxidHasher() : k0(GetRand(std::numeric_limits<uint64_t>::max())), k1(GetRand(std::numeric_limits<uint64_t>::max())) {}
diff --git a/src/coins.h b/src/coins.h
index 12cfd6bf6b..47ef90114b 100644
--- a/src/coins.h
+++ b/src/coins.h
@@ -319,6 +319,9 @@ public:
//! As we use CCoinsViews polymorphically, have a virtual destructor
virtual ~CCoinsView() {}
+
+ //! Estimate database size (0 if not implemented)
+ virtual size_t EstimateSize() const { return 0; }
};
@@ -336,6 +339,7 @@ public:
void SetBackend(CCoinsView &viewIn);
bool BatchWrite(CCoinsMap &mapCoins, const uint256 &hashBlock);
CCoinsViewCursor *Cursor() const;
+ size_t EstimateSize() const override;
};
diff --git a/src/dbwrapper.h b/src/dbwrapper.h
index 442f37b420..24ef71bfbf 100644
--- a/src/dbwrapper.h
+++ b/src/dbwrapper.h
@@ -305,7 +305,22 @@ public:
* Return true if the database managed by this class contains no entries.
*/
bool IsEmpty();
+
+ template<typename K>
+ size_t EstimateSize(const K& key_begin, const K& key_end) const
+ {
+ CDataStream ssKey1(SER_DISK, CLIENT_VERSION), ssKey2(SER_DISK, CLIENT_VERSION);
+ ssKey1.reserve(DBWRAPPER_PREALLOC_KEY_SIZE);
+ ssKey2.reserve(DBWRAPPER_PREALLOC_KEY_SIZE);
+ ssKey1 << key_begin;
+ ssKey2 << key_end;
+ leveldb::Slice slKey1(ssKey1.data(), ssKey1.size());
+ leveldb::Slice slKey2(ssKey2.data(), ssKey2.size());
+ uint64_t size = 0;
+ leveldb::Range range(slKey1, slKey2);
+ pdb->GetApproximateSizes(&range, 1, &size);
+ return size;
+ }
};
#endif // BITCOIN_DBWRAPPER_H
-
diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp
index d2f955fb32..e59b9b86bb 100644
--- a/src/rpc/blockchain.cpp
+++ b/src/rpc/blockchain.cpp
@@ -782,6 +782,7 @@ struct CCoinsStats
uint64_t nTransactions;
uint64_t nTransactionOutputs;
uint256 hashSerialized;
+ uint64_t nDiskSize;
CAmount nTotalAmount;
CCoinsStats() : nHeight(0), nTransactions(0), nTransactionOutputs(0), nTotalAmount(0) {}
@@ -826,6 +827,7 @@ static bool GetUTXOStats(CCoinsView *view, CCoinsStats &stats)
}
stats.hashSerialized = ss.GetHash();
stats.nTotalAmount = nTotalAmount;
+ stats.nDiskSize = view->EstimateSize();
return true;
}
@@ -892,6 +894,7 @@ UniValue gettxoutsetinfo(const JSONRPCRequest& request)
" \"transactions\": n, (numeric) The number of transactions\n"
" \"txouts\": n, (numeric) The number of output transactions\n"
" \"hash_serialized\": \"hash\", (string) The serialized hash\n"
+ " \"disk_size\": n, (numeric) The estimated size of the chainstate on disk\n"
" \"total_amount\": x.xxx (numeric) The total amount\n"
"}\n"
"\nExamples:\n"
@@ -909,6 +912,7 @@ UniValue gettxoutsetinfo(const JSONRPCRequest& request)
ret.push_back(Pair("transactions", (int64_t)stats.nTransactions));
ret.push_back(Pair("txouts", (int64_t)stats.nTransactionOutputs));
ret.push_back(Pair("hash_serialized_2", stats.hashSerialized.GetHex()));
+ ret.push_back(Pair("disk_size", stats.nDiskSize));
ret.push_back(Pair("total_amount", ValueFromAmount(stats.nTotalAmount)));
} else {
throw JSONRPCError(RPC_INTERNAL_ERROR, "Unable to read UTXO set");
diff --git a/src/txdb.cpp b/src/txdb.cpp
index 76aab23983..f139384a22 100644
--- a/src/txdb.cpp
+++ b/src/txdb.cpp
@@ -67,6 +67,11 @@ bool CCoinsViewDB::BatchWrite(CCoinsMap &mapCoins, const uint256 &hashBlock) {
return db.WriteBatch(batch);
}
+size_t CCoinsViewDB::EstimateSize() const
+{
+ return db.EstimateSize(DB_COINS, (char)(DB_COINS+1));
+}
+
CBlockTreeDB::CBlockTreeDB(size_t nCacheSize, bool fMemory, bool fWipe) : CDBWrapper(GetDataDir() / "blocks" / "index", nCacheSize, fMemory, fWipe) {
}
diff --git a/src/txdb.h b/src/txdb.h
index 117e7201fb..df164cb820 100644
--- a/src/txdb.h
+++ b/src/txdb.h
@@ -78,6 +78,8 @@ public:
uint256 GetBestBlock() const;
bool BatchWrite(CCoinsMap &mapCoins, const uint256 &hashBlock);
CCoinsViewCursor *Cursor() const;
+
+ size_t EstimateSize() const override;
};
/** Specialization of CCoinsViewCursor to iterate over a CCoinsViewDB */
diff --git a/test/functional/blockchain.py b/test/functional/blockchain.py
index b0faea9b38..4bfd3ee677 100755
--- a/test/functional/blockchain.py
+++ b/test/functional/blockchain.py
@@ -50,6 +50,9 @@ class BlockchainTest(BitcoinTestFramework):
assert_equal(res['height'], 200)
assert_equal(res['txouts'], 200)
assert_equal(res['bestblock'], node.getblockhash(200))
+ size = res['disk_size']
+ assert size > 6400
+ assert size < 64000
assert_equal(len(res['bestblock']), 64)
assert_equal(len(res['hash_serialized_2']), 64)