From 2d37f0151d0837655f7a668fced7e059c8d4ab36 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Tue, 29 Jul 2014 01:25:55 +0200 Subject: [PATCH] Fixed block buffer issue. --- libethcore/CommonEth.cpp | 2 +- libethential/Common.cpp | 2 +- libethereum/BlockChain.cpp | 1 + libethereum/BlockQueue.cpp | 45 +++++++++++++++++++++----------------- libethereum/BlockQueue.h | 7 +++++- 5 files changed, 34 insertions(+), 23 deletions(-) diff --git a/libethcore/CommonEth.cpp b/libethcore/CommonEth.cpp index 3c1a336eb..e88de28e1 100644 --- a/libethcore/CommonEth.cpp +++ b/libethcore/CommonEth.cpp @@ -29,7 +29,7 @@ using namespace eth; //#define ETH_ADDRESS_DEBUG 1 -const unsigned eth::c_protocolVersion = 24; +const unsigned eth::c_protocolVersion = 23; const unsigned eth::c_databaseVersion = 1; static const vector> g_units = diff --git a/libethential/Common.cpp b/libethential/Common.cpp index 070210abd..7c3d39f93 100644 --- a/libethential/Common.cpp +++ b/libethential/Common.cpp @@ -27,6 +27,6 @@ using namespace eth; namespace eth { -char const* EthVersion = "0.6.1"; +char const* EthVersion = "0.5.18"; } diff --git a/libethereum/BlockChain.cpp b/libethereum/BlockChain.cpp index 290afc589..43ce6f150 100644 --- a/libethereum/BlockChain.cpp +++ b/libethereum/BlockChain.cpp @@ -186,6 +186,7 @@ h256s BlockChain::sync(BlockQueue& _bq, OverlayDB const& _stateDB, unsigned _max } catch (...){} } + _bq.doneDrain(); return ret; } diff --git a/libethereum/BlockQueue.cpp b/libethereum/BlockQueue.cpp index da21e6929..3f636b102 100644 --- a/libethereum/BlockQueue.cpp +++ b/libethereum/BlockQueue.cpp @@ -34,7 +34,8 @@ bool BlockQueue::import(bytesConstRef _block, BlockChain const& _bc) h256 h = sha3(_block); UpgradableGuard l(m_lock); - if (m_readySet.count(h) || m_futureSet.count(h)) + + if (m_readySet.count(h) || m_drainingSet.count(h) || m_futureSet.count(h)) // Already know about this one. return false; @@ -65,39 +66,43 @@ bool BlockQueue::import(bytesConstRef _block, BlockChain const& _bc) if (bi.timestamp > (u256)time(0)) return false; - UpgradeGuard ul(l); - - // We now know it. - if (!m_readySet.count(bi.parentHash) && !_bc.details(bi.parentHash)) { - // We don't know the parent (yet) - queue it up for later. It'll get resent to us if we find out about its ancestry later on. - m_future.insert(make_pair(bi.parentHash, make_pair(h, _block.toBytes()))); - m_futureSet.insert(h); - return true; - } + UpgradeGuard ul(l); - // If valid, append to blocks. - m_ready.push_back(_block.toBytes()); - m_readySet.insert(h); + // We now know it. + if (!m_readySet.count(bi.parentHash) && !m_drainingSet.count(bi.parentHash) && !_bc.details(bi.parentHash)) + { + // We don't know the parent (yet) - queue it up for later. It'll get resent to us if we find out about its ancestry later on. + m_future.insert(make_pair(bi.parentHash, make_pair(h, _block.toBytes()))); + m_futureSet.insert(h); + } + else + { + // If valid, append to blocks. + m_ready.push_back(_block.toBytes()); + m_readySet.insert(h); - noteReadyWithoutWriteGuard(h); + noteReadyWithoutWriteGuard(h); + } + } return true; } void BlockQueue::noteReadyWithoutWriteGuard(h256 _good) { - h256s goodQueue(1, _good); + list goodQueue(1, _good); while (goodQueue.size()) { - auto r = m_future.equal_range(goodQueue.back()); - goodQueue.pop_back(); + auto r = m_future.equal_range(goodQueue.front()); + goodQueue.pop_front(); for (auto it = r.first; it != r.second; ++it) { - m_futureSet.erase(it->second.first); m_ready.push_back(it->second.second); - m_readySet.erase(it->second.first); - goodQueue.push_back(it->second.first); + auto newReady = it->second.first; + m_futureSet.erase(newReady); + m_readySet.insert(newReady); + goodQueue.push_back(newReady); } m_future.erase(r.first, r.second); } diff --git a/libethereum/BlockQueue.h b/libethereum/BlockQueue.h index 7ec68215a..d66bfabd9 100644 --- a/libethereum/BlockQueue.h +++ b/libethereum/BlockQueue.h @@ -43,7 +43,11 @@ public: bool import(bytesConstRef _tx, BlockChain const& _bc); /// Grabs the blocks that are ready, giving them in the correct order for insertion into the chain. - void drain(std::vector& o_out) { WriteGuard l(m_lock); swap(o_out, m_ready); m_readySet.clear(); } + /// Don't forget to call doneDrain() once you're done importing. + void drain(std::vector& o_out) { WriteGuard l(m_lock); if (m_drainingSet.empty()) { swap(o_out, m_ready); swap(m_drainingSet, m_readySet); } } + + /// Must be called after a drain() call. Notes that the drained blocks have been imported into the blockchain, so we can forget about them. + void doneDrain() { WriteGuard l(m_lock); m_drainingSet.clear(); } /// Notify the queue that the chain has changed and a new block has attained 'ready' status (i.e. is in the chain). void noteReady(h256 _b) { WriteGuard l(m_lock); noteReadyWithoutWriteGuard(_b); } @@ -56,6 +60,7 @@ private: mutable boost::shared_mutex m_lock; ///< General lock. std::set m_readySet; ///< All blocks ready for chain-import. + std::set m_drainingSet; ///< All blocks being imported. std::vector m_ready; ///< List of blocks, in correct order, ready for chain-import. std::set m_futureSet; ///< Set of all blocks whose parents are not ready/in-chain. std::multimap> m_future; ///< For transactions that have an unknown parent; we map their parent hash to the block stuff, and insert once the block appears.