diff --git a/exp/main.cpp b/exp/main.cpp index a88023fae..40804958e 100644 --- a/exp/main.cpp +++ b/exp/main.cpp @@ -19,12 +19,14 @@ * @date 2014 * Ethereum client. */ +#include #include #include #include #include #include #include +#include #include using namespace std; using namespace dev; @@ -34,7 +36,25 @@ using namespace dev::shh; int main() { - RangeMask m(0, 100); + DownloadMan man; + DownloadSub s0(&man); + DownloadSub s1(&man); + DownloadSub s2(&man); + man.resetToChain(h256s({u256(0), u256(1), u256(2), u256(3), u256(4), u256(5), u256(6), u256(7), u256(8)})); + cnote << s0.nextFetch(2); + cnote << s1.nextFetch(2); + cnote << s2.nextFetch(2); + s0.noteBlock(u256(0)); + s0.doneFetch(); + cnote << s0.nextFetch(2); + s1.noteBlock(u256(2)); + s1.noteBlock(u256(3)); + s1.doneFetch(); + cnote << s1.nextFetch(2); + s0.doneFetch(); + cnote << s0.nextFetch(2); + +/* RangeMask m(0, 100); cnote << m; m += UnsignedRange(3, 10); cnote << m; @@ -45,7 +65,7 @@ int main() cnote << ~m; cnote << (~m).lowest(10); for (auto i: (~m).lowest(10)) - cnote << i; + cnote << i;*/ return 0; } diff --git a/libdevcore/RangeMask.cpp b/libdevcore/RangeMask.cpp index 5ba4a1f73..5317e00e8 100644 --- a/libdevcore/RangeMask.cpp +++ b/libdevcore/RangeMask.cpp @@ -1,5 +1,22 @@ -#include "RangeMask.h" +/* + This file is part of cpp-ethereum. + + cpp-ethereum is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + cpp-ethereum is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. -RangeMask::RangeMask() -{ -} + You should have received a copy of the GNU General Public License + along with cpp-ethereum. If not, see . +*/ +/** @file RangeMask.cpp + * @author Gav Wood + * @date 2014 + */ + +#include "RangeMask.h" diff --git a/libdevcore/RangeMask.h b/libdevcore/RangeMask.h index ba8594779..d26e034f4 100644 --- a/libdevcore/RangeMask.h +++ b/libdevcore/RangeMask.h @@ -24,6 +24,7 @@ #include #include #include +#include namespace dev { @@ -52,7 +53,7 @@ public: { RangeMask ret(m_all); for (auto i = m_ranges.begin(); i != m_ranges.end() && _items; ++i) - _items -= (ret.m_ranges[i->first] = std::min(i->first + _items, i->second)); + _items -= (ret.m_ranges[i->first] = std::min(i->first + _items, i->second)) - i->first; return ret; } @@ -140,6 +141,16 @@ public: return it != m_ranges.end() && it->first <= _i && it->second > _i; } + bool empty() const + { + return m_ranges.empty(); + } + + void clear() + { + m_ranges.clear(); + } + class const_iterator { friend class RangeMask; diff --git a/libethereum/DownloadMan.cpp b/libethereum/DownloadMan.cpp new file mode 100644 index 000000000..65ad6adc4 --- /dev/null +++ b/libethereum/DownloadMan.cpp @@ -0,0 +1,70 @@ +/* + This file is part of cpp-ethereum. + + cpp-ethereum is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + cpp-ethereum is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with cpp-ethereum. If not, see . +*/ +/** @file DownloadMan.cpp + * @author Gav Wood + * @date 2014 + */ + +#include "DownloadMan.h" +using namespace std; +using namespace dev; +using namespace dev::eth; + +DownloadSub::DownloadSub(DownloadMan* _man): m_man(_man) +{ + WriteGuard l(m_man->x_subs); + m_man->m_subs.insert(this); +} + +DownloadSub::~DownloadSub() +{ + if (m_man) + { + WriteGuard l(m_man->x_subs); + m_man->m_subs.erase(this); + } +} + +h256s DownloadSub::nextFetch(unsigned _n) +{ + Guard l(m_fetch); + + m_asked.clear(); + if (!m_man) + return h256s(); + + m_asked = (~(m_man->taken() + m_attempted)).lowest(_n); + if (m_asked.empty()) + m_asked = (~(m_man->taken(true) + m_attempted)).lowest(_n); + m_attempted += m_asked; + m_indices.clear(); + h256s ret; + for (auto i: m_asked) + { + ret.push_back(m_man->m_chain[i]); + m_indices[ret.back()] = i; + } + return ret; +} + +void DownloadSub::noteBlock(h256 _hash) +{ + Guard l(m_fetch); + if (m_man && m_indices.count(_hash)) + m_man->m_blocksGot += m_indices[_hash]; +} + diff --git a/libethereum/DownloadMan.h b/libethereum/DownloadMan.h new file mode 100644 index 000000000..056f089b6 --- /dev/null +++ b/libethereum/DownloadMan.h @@ -0,0 +1,118 @@ +/* + This file is part of cpp-ethereum. + + cpp-ethereum is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + cpp-ethereum is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with cpp-ethereum. If not, see . +*/ +/** @file DownloadMan.h + * @author Gav Wood + * @date 2014 + */ + +#pragma once + +#include +#include +#include +#include +#include +#include +#include + +namespace dev +{ + +namespace eth +{ + +class DownloadMan; + +class DownloadSub +{ + friend class DownloadMan; + +public: + DownloadSub(DownloadMan* _man); + ~DownloadSub(); + + /// Finished last fetch - grab the next bunch of block hashes to download. + h256s nextFetch(unsigned _n); + + /// Note that we've received a particular block. + void noteBlock(h256 _hash); + + void doneFetch() { nextFetch(0); } + +private: + void resetFetch() // Called by DownloadMan when we need to reset the download. + { + Guard l(m_fetch); + m_indices.clear(); + m_asked.clear(); + m_attempted.clear(); + } + + DownloadMan* m_man = nullptr; + + Mutex m_fetch; + std::map m_indices; + RangeMask m_asked; + RangeMask m_attempted; +}; + +class DownloadMan +{ + friend class DownloadSub; + +public: + ~DownloadMan() + { + for (auto i: m_subs) + i->m_man = nullptr; + } + + void resetToChain(h256s const& _chain) + { + { + ReadGuard l(x_subs); + for (auto i: m_subs) + i->resetFetch(); + } + + m_chain = _chain; + m_blocksGot = RangeMask(0, m_chain.size()); + } + + RangeMask taken(bool _desperate = false) const + { + auto ret = m_blocksGot; + if (!_desperate) + { + ReadGuard l(x_subs); + for (auto i: m_subs) + ret += i->m_asked; + } + return ret; + } + +private: + h256s m_chain; + RangeMask m_blocksGot; + + mutable SharedMutex x_subs; + std::set m_subs; +}; + +} + +} diff --git a/libethereum/EthereumHost.cpp b/libethereum/EthereumHost.cpp index 2add39482..bbf673419 100644 --- a/libethereum/EthereumHost.cpp +++ b/libethereum/EthereumHost.cpp @@ -15,9 +15,7 @@ along with cpp-ethereum. If not, see . */ /** @file EthereumHost.cpp - * @authors: - * Gav Wood - * Eric Lombrozo + * @author Gav Wood * @date 2014 */ @@ -34,6 +32,7 @@ #include "TransactionQueue.h" #include "BlockQueue.h" #include "EthereumPeer.h" +#include "DownloadMan.h" using namespace std; using namespace dev; using namespace dev::eth; diff --git a/libethereum/EthereumHost.h b/libethereum/EthereumHost.h index b038e0785..3021f26ee 100644 --- a/libethereum/EthereumHost.h +++ b/libethereum/EthereumHost.h @@ -30,6 +30,7 @@ #include #include #include +#include #include #include #include "CommonNet.h" @@ -46,44 +47,6 @@ namespace eth class TransactionQueue; class BlockQueue; -#if 0 -class DownloadSub -{ - friend class DownloadMan; - -public: - h256s nextFetch(); - void noteBlock(h256 _hash, bytesConstRef _data); - -private: - void resetFetch(); // Called by DownloadMan when we need to reset the download. - - DownloadMan* m_man; - - Mutex m_fetch; - h256s m_fetching; - h256s m_activeGet; - bool m_killFetch; - RangeMask m_attempted; -}; - -class DownloadMan -{ - friend class DownloadSub; - -public: - void resetToChain(h256s const& _chain); - -private: - void cancelFetch(DownloadSub* ); - void noteBlock(h256 _hash, bytesConstRef _data); - - h256s m_chain; - RangeMask m_complete; - std::map m_fetching; -}; -#endif - /** * @brief The EthereumHost class * @warning None of this is thread-safe. You have been warned. @@ -156,6 +119,7 @@ private: mutable std::mutex x_blocksNeeded; u256 m_totalDifficultyOfNeeded; h256s m_blocksNeeded; + h256Set m_blocksOnWay; h256 m_latestBlockSent; diff --git a/libethereum/EthereumPeer.h b/libethereum/EthereumPeer.h index 7248fabd0..adf82c215 100644 --- a/libethereum/EthereumPeer.h +++ b/libethereum/EthereumPeer.h @@ -28,6 +28,7 @@ #include #include #include +#include #include #include #include "CommonNet.h" @@ -85,6 +86,8 @@ private: h256Set m_askedBlocks; ///< The blocks for which we sent the last GetBlocks for but haven't received a corresponding Blocks. bool m_askedBlocksChanged = true; + RangeMask m_blocksAsked; + bool m_requireTransactions; Mutex x_knownBlocks;