Browse Source

Fast databases.

cl-refactor
Gav Wood 10 years ago
parent
commit
55df43ff4b
  1. 2
      libethcore/Common.cpp
  2. 54
      libethereum/BlockChain.cpp
  3. 26
      libethereum/BlockChain.h
  4. 2
      libethereum/Client.cpp
  5. 7
      libethereum/EthereumPeer.cpp

2
libethcore/Common.cpp

@ -36,7 +36,7 @@ namespace eth
const unsigned c_ethashVersion = c_ethashRevision;
const unsigned c_protocolVersion = 60;
const unsigned c_minorProtocolVersion = 0;
const unsigned c_databaseBaseVersion = 8;
const unsigned c_databaseBaseVersion = 9;
#if ETH_FATDB
const unsigned c_databaseVersionModifier = 1;
#else

54
libethereum/BlockChain.cpp

@ -21,6 +21,9 @@
#include "BlockChain.h"
#if ETH_PROFILING_GPERF
#include <gperftools/profiler.h>
#endif
#include <leveldb/db.h>
#include <boost/timer.hpp>
#include <boost/filesystem.hpp>
@ -65,7 +68,7 @@ std::ostream& dev::eth::operator<<(std::ostream& _out, BlockChain const& _bc)
return _out;
}
ldb::Slice dev::eth::toSlice(h256 const& _h, unsigned _sub)
ldb::Slice dev::eth::oldToSlice(h256 const& _h, unsigned _sub)
{
#if ALL_COMPILERS_ARE_CPP11_COMPLIANT
static thread_local h256 h = _h ^ sha3(h256(u256(_sub)));
@ -79,6 +82,21 @@ ldb::Slice dev::eth::toSlice(h256 const& _h, unsigned _sub)
#endif
}
ldb::Slice dev::eth::toSlice(h256 const& _h, unsigned _sub)
{
#if ALL_COMPILERS_ARE_CPP11_COMPLIANT
static thread_local h256 h = _h ^ sha3(h256(u256(_sub)));
return ldb::Slice((char const*)&h, 32);
#else
static boost::thread_specific_ptr<FixedHash<33>> t_h;
if (!t_h.get())
t_h.reset(new FixedHash<33>);
*t_h = FixedHash<33>(_h);
(*t_h)[32] = (uint8_t)_sub;
return (ldb::Slice)t_h->ref();//(char const*)t_h.get(), 32);
#endif
}
#if ETH_DEBUG
static const chrono::system_clock::duration c_collectionDuration = chrono::seconds(15);
static const unsigned c_collectionQueueSize = 2;
@ -148,7 +166,7 @@ void BlockChain::open(std::string const& _path, WithExisting _we)
}
}
if (!details(m_genesisHash))
if (_we != WithExisting::Verify && !details(m_genesisHash))
{
// Insert details of genesis block.
m_details[m_genesisHash] = BlockDetails(0, c_genesisDifficulty, h256(), {});
@ -178,7 +196,6 @@ void BlockChain::close()
m_blocks.clear();
}
#include <gperftools/profiler.h>
#define IGNORE_EXCEPTIONS(X) try { X; } catch (...) {}
void BlockChain::rebuild(std::string const& _path, std::function<void(unsigned, unsigned)> const& _progress)
@ -187,6 +204,7 @@ void BlockChain::rebuild(std::string const& _path, std::function<void(unsigned,
ProfilerStart("BlockChain_rebuild.log");
#endif
// unsigned originalNumber = (unsigned)BlockInfo(oldBlock(m_lastBlockHash)).number;
unsigned originalNumber = number();
// Keep extras DB around, but under a temp name
@ -968,3 +986,33 @@ bytes BlockChain::block(h256 const& _hash) const
return m_blocks[_hash];
}
bytes BlockChain::oldBlock(h256 const& _hash) const
{
if (_hash == m_genesisHash)
return m_genesisBlock;
{
ReadGuard l(x_blocks);
auto it = m_blocks.find(_hash);
if (it != m_blocks.end())
return it->second;
}
string d;
m_blocksDB->Get(m_readOptions, oldToSlice(_hash), &d);
if (!d.size())
{
cwarn << "Couldn't find requested block:" << _hash.abridged();
return bytes();
}
WriteGuard l(x_blocks);
m_blocks[_hash].resize(d.size());
memcpy(m_blocks[_hash].data(), d.data(), d.size());
noteUsed(_hash);
return m_blocks[_hash];
}

26
libethereum/BlockChain.h

@ -64,6 +64,7 @@ struct BlockChainWarn: public LogChannel { static const char* name() { return "=
std::map<Address, Account> const& genesisState();
ldb::Slice toSlice(h256 const& _h, unsigned _sub = 0);
ldb::Slice oldToSlice(h256 const& _h, unsigned _sub = 0);
using BlocksHash = std::map<h256, bytes>;
using TransactionHashes = h256s;
@ -119,6 +120,7 @@ public:
/// Get a block (RLP format) for the given hash (or the most recent mined if none given). Thread-safe.
bytes block(h256 const& _hash) const;
bytes block() const { return block(currentHash()); }
bytes oldBlock(h256 const& _hash) const;
/// Get the familial details concerning a block (or the most recent mined if none given). Thread-safe.
BlockDetails details(h256 const& _hash) const { return queryExtras<BlockDetails, ExtraDetails>(_hash, m_details, x_details, NullBlockDetails); }
@ -268,6 +270,30 @@ private:
return ret.first->second;
}
template<class T, unsigned N> T oldQueryExtras(h256 const& _h, std::map<h256, T>& _m, boost::shared_mutex& _x, T const& _n, ldb::DB* _extrasDB = nullptr) const
{
{
ReadGuard l(_x);
auto it = _m.find(_h);
if (it != _m.end())
return it->second;
}
std::string s;
(_extrasDB ? _extrasDB : m_extrasDB)->Get(m_readOptions, oldToSlice(_h, N), &s);
if (s.empty())
{
// cout << "Not found in DB: " << _h << endl;
return _n;
}
noteUsed(_h, N);
WriteGuard l(_x);
auto ret = _m.insert(std::make_pair(_h, T(RLP(s))));
return ret.first->second;
}
void checkConsistency();
/// The caches of the disk DB and their locks.

2
libethereum/Client.cpp

@ -123,7 +123,7 @@ Client::Client(p2p::Host* _extNet, std::string const& _dbPath, WithExisting _for
m_bc(_dbPath, max(m_vc.action(), _forceAction), [](unsigned d, unsigned t){ cerr << "REVISING BLOCKCHAIN: Processed " << d << " of " << t << "...\r"; }),
m_gp(new TrivialGasPricer),
m_stateDB(State::openDB(_dbPath, max(m_vc.action(), _forceAction))),
m_preMine(m_stateDB),
m_preMine(m_stateDB, BaseState::CanonGenesis),
m_postMine(m_stateDB)
{
m_gp->update(m_bc);

7
libethereum/EthereumPeer.cpp

@ -478,7 +478,12 @@ bool EthereumPeer::interpret(unsigned _id, RLP const& _r)
clogS(NetMessageSummary) << dec << success << "imported OK," << unknown << "with unknown parents," << future << "with future timestamps," << got << " already known," << repeated << " repeats received.";
if (m_asking == Asking::Blocks)
transition(Asking::Blocks);
{
if (!got)
transition(Asking::Blocks);
else
transition(Asking::Nothing);
}
break;
}
case NewBlockPacket:

Loading…
Cancel
Save