Browse Source

Add DownloadMan for download management.

cl-refactor
Gav Wood 10 years ago
parent
commit
8ec86bb362
  1. 24
      exp/main.cpp
  2. 25
      libdevcore/RangeMask.cpp
  3. 13
      libdevcore/RangeMask.h
  4. 70
      libethereum/DownloadMan.cpp
  5. 118
      libethereum/DownloadMan.h
  6. 5
      libethereum/EthereumHost.cpp
  7. 40
      libethereum/EthereumHost.h
  8. 3
      libethereum/EthereumPeer.h

24
exp/main.cpp

@ -19,12 +19,14 @@
* @date 2014
* Ethereum client.
*/
#include <functional>
#include <libdevcore/Log.h>
#include <libdevcore/Common.h>
#include <libdevcore/CommonData.h>
#include <libdevcore/RLP.h>
#include <libp2p/All.h>
#include <libdevcore/RangeMask.h>
#include <libethereum/DownloadMan.h>
#include <libwhisper/WhisperPeer.h>
using namespace std;
using namespace dev;
@ -34,7 +36,25 @@ using namespace dev::shh;
int main()
{
RangeMask<unsigned> 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<unsigned> 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;
}

25
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 <http://www.gnu.org/licenses/>.
*/
/** @file RangeMask.cpp
* @author Gav Wood <i@gavwood.com>
* @date 2014
*/
#include "RangeMask.h"

13
libdevcore/RangeMask.h

@ -24,6 +24,7 @@
#include <map>
#include <utility>
#include <vector>
#include <iostream>
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;

70
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 <http://www.gnu.org/licenses/>.
*/
/** @file DownloadMan.cpp
* @author Gav Wood <i@gavwood.com>
* @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];
}

118
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 <http://www.gnu.org/licenses/>.
*/
/** @file DownloadMan.h
* @author Gav Wood <i@gavwood.com>
* @date 2014
*/
#pragma once
#include <map>
#include <vector>
#include <set>
#include <libdevcore/Guards.h>
#include <libdevcore/Worker.h>
#include <libdevcore/RangeMask.h>
#include <libdevcore/FixedHash.h>
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<h256, unsigned> m_indices;
RangeMask<unsigned> m_asked;
RangeMask<unsigned> 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<unsigned>(0, m_chain.size());
}
RangeMask<unsigned> 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<unsigned> m_blocksGot;
mutable SharedMutex x_subs;
std::set<DownloadSub*> m_subs;
};
}
}

5
libethereum/EthereumHost.cpp

@ -15,9 +15,7 @@
along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
*/
/** @file EthereumHost.cpp
* @authors:
* Gav Wood <i@gavwood.com>
* Eric Lombrozo <elombrozo@gmail.com>
* @author Gav Wood <i@gavwood.com>
* @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;

40
libethereum/EthereumHost.h

@ -30,6 +30,7 @@
#include <thread>
#include <libdevcore/Guards.h>
#include <libdevcore/Worker.h>
#include <libdevcore/RangeMask.h>
#include <libethcore/CommonEth.h>
#include <libp2p/Common.h>
#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<DownloadSub*, UnsignedRange> 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;

3
libethereum/EthereumPeer.h

@ -28,6 +28,7 @@
#include <utility>
#include <libdevcore/RLP.h>
#include <libdevcore/Guards.h>
#include <libdevcore/RangeMask.h>
#include <libethcore/CommonEth.h>
#include <libp2p/Capability.h>
#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<unsigned> m_blocksAsked;
bool m_requireTransactions;
Mutex x_knownBlocks;

Loading…
Cancel
Save