*** empty log message ***

This commit is contained in:
Arvid Norberg 2004-03-22 14:56:32 +00:00
parent bb52b74a9e
commit 27c8533716
9 changed files with 232 additions and 277 deletions

View File

@ -662,6 +662,7 @@ struct torrent_status
};
state_t state;
bool paused;
float progress;
boost::posix_time::time_duration next_announce;
boost::posix_time::time_duration announce_interval;
@ -717,6 +718,7 @@ is a pure seeder.</td>
</tr>
</tbody>
</table>
<p><tt class="literal"><span class="pre">paused</span></tt> is set to true if the torrent is paused and false otherwise.</p>
<p><tt class="literal"><span class="pre">next_announce</span></tt> is the time until the torrent will announce itself to the tracker. And
<tt class="literal"><span class="pre">announce_interval</span></tt> is the time the tracker want us to wait until we announce ourself
again the next time.</p>

View File

@ -675,6 +675,7 @@ It contains the following fields::
};
state_t state;
bool paused;
float progress;
boost::posix_time::time_duration next_announce;
boost::posix_time::time_duration announce_interval;
@ -725,6 +726,8 @@ current task is in the ``state`` member, it will be one of the following:
| | |
+--------------------------+----------------------------------------------------------+
``paused`` is set to true if the torrent is paused and false otherwise.
``next_announce`` is the time until the torrent will announce itself to the tracker. And
``announce_interval`` is the time the tracker want us to wait until we announce ourself
again the next time.

View File

@ -33,24 +33,17 @@ POSSIBILITY OF SUCH DAMAGE.
#ifndef TORRENT_ALLOCATE_RESOURCES_HPP_INCLUDED
#define TORRENT_ALLOCATE_RESOURCES_HPP_INCLUDED
#include <vector>
#include <boost/any.hpp>
#include <map>
#include <utility>
#include <boost/shared_ptr.hpp>
#include "libtorrent/resource_request.hpp"
namespace libtorrent
{
struct resource_request {
resource_request() : used(0), wanted(0), given(0) { }
// I'm right now actively using:
int used;
// I would like to use this much:
int wanted;
// Reply: Okay, you're allowed to use this much (a compromise):
int given;
};
class socket;
class peer_connection;
// Function to allocate a limited resource fairly among many consumers.
// It takes into account the current use, and the consumer's desired use.
@ -59,9 +52,11 @@ namespace libtorrent
// If resources = std::numeric_limits<int>::max() it means there is an infinite
// supply of resources (so everyone can get what they want).
void allocate_resources(int resources,
std::vector<resource_request *> & requests);
void allocate_resources(
int resources
, std::map<boost::shared_ptr<socket>, boost::shared_ptr<peer_connection> >& connections
, resource_request peer_connection::* res);
}

View File

@ -178,8 +178,12 @@ namespace libtorrent
int send_quota_left() const;
resource_request* upload_bandwidth_quota();
// ?? TODO: document
void update_send_quota_left();
// This is called for every peer right after the upload
// bandwidth has been distributed among them
// It will reset the used bandwidth to 0 and
// possibly add or remove the peer's socket
// from the socket monitor
void reset_upload_quota();
// free upload.
size_type total_free_upload() const;
@ -242,6 +246,9 @@ namespace libtorrent
void send_extensions();
void send_chat_message(const std::string& msg);
// how much bandwidth we're using, how much we want,
// and how much we are allowed to use.
resource_request m_upload_bandwidth_quota;
private:
@ -331,14 +338,10 @@ namespace libtorrent
// peer's socket from the writability monitor list.
selector& m_selector;
boost::shared_ptr<libtorrent::socket> m_socket;
// how much bandwidth we're using, how much we want,
// and how much we are allowed to use.
resource_request m_upload_bandwidth_quota;
// upload bandwidth used this second.
// Must not exceed m_upload_bandwidth_quota.given.
int m_upload_bandwidth_quota_used;
// int m_upload_bandwidth_quota_used;
// this is the torrent this connection is
// associated with. If the connection is an

View File

@ -0,0 +1,52 @@
/*
Copyright (c) 2003, Magnus Jonsson
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in
the documentation and/or other materials provided with the distribution.
* Neither the name of the author nor the names of its
contributors may be used to endorse or promote products derived
from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef TORRENT_RESOURCE_REQUEST_HPP_INCLUDED
#define TORRENT_RESOURCE_REQUEST_HPP_INCLUDED
namespace libtorrent
{
struct resource_request
{
resource_request() : used(0), wanted(0), given(0) {}
// I'm right now actively using:
int used;
// I would like to use this much:
int wanted;
// Reply: Okay, you're allowed to use this much (a compromise):
int given;
};
}
#endif

View File

@ -74,6 +74,7 @@ namespace libtorrent
{
torrent_status()
: state(queued_for_checking)
, paused(false)
, progress(0.f)
, total_download(0)
, total_upload(0)

View File

@ -1,6 +1,6 @@
/*
Copyright (c) 2003, Magnus Jonsson
Copyright (c) 2003, Magnus Jonsson, Arvid Norberg
All rights reserved.
Redistribution and use in source and binary forms, with or without
@ -32,9 +32,12 @@ POSSIBILITY OF SUCH DAMAGE.
#include "libtorrent/allocate_resources.hpp"
#include "libtorrent/size_type.hpp"
#include "libtorrent/peer_connection.hpp"
#include <cassert>
#include <algorithm>
#include <boost/limits.hpp>
#include <boost/iterator/transform_iterator.hpp>
#if defined(_MSC_VER) && _MSC_VER < 1300
#define for if (false) {} else for
@ -46,89 +49,61 @@ namespace libtorrent
{
int saturated_add(int a, int b)
{
assert(a>=0);
assert(b>=0);
assert(a >= 0);
assert(b >= 0);
assert(std::numeric_limits<int>::max() + std::numeric_limits<int>::max() < 0);
int sum=a+b;
if(sum<0)
sum=std::numeric_limits<int>::max();
int sum = a + b;
if(sum < 0)
sum = std::numeric_limits<int>::max();
assert(sum>=a && sum>=b);
assert(sum >= a && sum >= b);
return sum;
}
/*
int round_up_division(int numer, int denom)
{
assert(numer>0);
assert(denom>0);
int result=(numer+denom-1)/denom;
assert(result>0);
assert(result<=numer);
return result;
}
// for use with std::sort
bool by_used(const resource_request *a, const resource_request *b)
{ return a->used < b->used; }
*/
// give num_resources to r,
// return how how many were actually accepted.
int give(resource_request *r, int num_resources)
int give(resource_request& r, int num_resources)
{
assert(r);
assert(num_resources >= 0);
assert(r->given <= r->wanted);
assert(r.given <= r.wanted);
int accepted = std::min(num_resources, r->wanted - r->given);
int accepted = std::min(num_resources, r.wanted - r.given);
assert(accepted >= 0);
r->given += accepted;
assert(r->given <= r->wanted);
r.given += accepted;
assert(r.given <= r.wanted);
return accepted;
}
// sum of requests' "wanted" field.
int total_wanted(std::vector<resource_request *> & requests)
{
int total_wanted=0;
for(int i=0;i<(int)requests.size();i++)
{
total_wanted=
saturated_add(total_wanted,requests[i]->wanted);
if(total_wanted == std::numeric_limits<int>::max())
break;
}
assert(total_wanted>=0);
return total_wanted;
}
#ifndef NDEBUG
template<class It, class T>
class allocate_resources_contract_check
{
int resources;
std::vector<resource_request *> & requests;
int m_resources;
It m_start;
It m_end;
resource_request T::* m_res;
public:
allocate_resources_contract_check(
int resources_
, std::vector<resource_request *>& requests_)
: resources(resources_)
, requests(requests_)
int resources
, It start
, It end
, resource_request T::* res)
: m_resources(resources)
, m_start(start)
, m_end(end)
, m_res(res)
{
assert(resources >= 0);
for (int i = 0; i < (int)requests.size(); ++i)
assert(m_resources >= 0);
for (It i = m_start, end(m_end); i != end; ++i)
{
assert(requests[i]->used >= 0);
assert(requests[i]->wanted >= 0);
assert(requests[i]->given >= 0);
assert(((*i).*m_res).used >= 0);
assert(((*i).*m_res).wanted >= 0);
assert(((*i).*m_res).given >= 0);
}
}
@ -136,212 +111,127 @@ namespace libtorrent
{
int sum_given = 0;
int sum_wanted = 0;
for (int i = 0; i < (int)requests.size(); ++i)
for (It i = m_start, end(m_end); i != end; ++i)
{
assert(requests[i]->used >= 0);
assert(requests[i]->wanted >= 0);
assert(requests[i]->given >= 0);
assert(requests[i]->given <= requests[i]->wanted);
assert(((*i).*m_res).wanted >= 0);
assert(((*i).*m_res).given >= 0);
assert(((*i).*m_res).given <= ((*i).*m_res).wanted);
sum_given = saturated_add(sum_given, requests[i]->given);
sum_wanted = saturated_add(sum_wanted, requests[i]->wanted);
sum_given = saturated_add(sum_given, ((*i).*m_res).given);
sum_wanted = saturated_add(sum_wanted, ((*i).*m_res).wanted);
}
assert(sum_given == std::min(resources,sum_wanted));
assert(sum_given == std::min(m_resources, sum_wanted));
}
};
#endif
} // namespace unnamed
void allocate_resources(int resources,
std::vector<resource_request *>& requests)
{
#ifndef NDEBUG
allocate_resources_contract_check contract_check(resources,requests);
#endif
template<class It, class T>
void allocate_resources_impl(
int resources
, It start
, It end
, resource_request T::* res)
{
#ifndef NDEBUG
allocate_resources_contract_check<It, T> contract_check(
resources
, start
, end
, res);
#endif
if(resources == std::numeric_limits<int>::max())
{
// No competition for resources.
// Just give everyone what they want.
for (It i = start; i != end; ++i)
{
((*i).*res).given = ((*i).*res).wanted;
}
return;
}
if(resources == std::numeric_limits<int>::max())
{
// No competition for resources.
// Just give everyone what they want.
for(int i=0;i<(int)requests.size();i++)
requests[i]->given = requests[i]->wanted;
}
else
{
// Resources are scarce
for (int i = 0; i < (int)requests.size(); ++i)
requests[i]->given = 0;
int total_wanted = 0;
for (It i = start; i != end; ++i)
{
((*i).*res).given = 0;
total_wanted = saturated_add(total_wanted, ((*i).*res).wanted);
}
if (resources == 0)
return;
int resources_to_distribute =
std::min(
resources,
total_wanted(requests));
if (resources_to_distribute == 0)
if (resources == 0 || total_wanted == 0)
return;
int resources_to_distribute = std::min(resources, total_wanted);
assert(resources_to_distribute > 0);
while(resources_to_distribute > 0)
while (resources_to_distribute > 0)
{
#if 0
int num_active=0;
for(int i = 0;i < (int)requests.size();++i)
size_type total_used = 0;
size_type max_used = 0;
for (It i = start; i != end; ++i)
{
resource_request *r=requests[i];
if(r->given == r->wanted)
continue;
num_active++;
resource_request& r = (*i).*res;
if(r.given == r.wanted) continue;
assert(r.given < r.wanted);
max_used = std::max(max_used, (size_type)r.used + 1);
total_used += (size_type)r.used + 1;
}
int max_give=resources_to_distribute/num_active;
max_give=std::max(max_give,1);
for(int i = 0;i < (int)requests.size() && resources_to_distribute;++i)
{
resource_request *r=requests[i];
if(r->given == r->wanted)
continue;
size_type kNumer = resources_to_distribute;
size_type kDenom = total_used;
int toGive = 1+std::min(max_give-1,r->used);
resources_to_distribute-=give(r,toGive);
}
#elif 0
size_type total_used=0;
size_type max_used=0;
for(int i = 0;i < (int)requests.size();++i)
if (kNumer * max_used <= kDenom)
{
resource_request *r=requests[i];
if(r->given == r->wanted)
continue;
assert(r->given < r->wanted);
max_used = std::max(max_used, (size_type)r->used + 1);
total_used += (size_type)r->used + 1;
kNumer = 1;
kDenom = max_used;
}
size_type kNumer=resources_to_distribute;
size_type kDenom=total_used;
for (It i = start; i != end && resources_to_distribute > 0; ++i)
{
size_type numer=1;
size_type denom=max_used;
resource_request& r = (*i).*res;
if(r.given == r.wanted) continue;
if(numer*kDenom >= kNumer*denom)
{
kNumer=numer;
kDenom=denom;
}
}
assert(r.given < r.wanted);
for(int i = 0;i < (int)requests.size();++i)
{
resource_request *r=requests[i];
if(r->given == r->wanted)
continue;
assert(r->given < r->wanted);
size_type numer = r->wanted - r->given;
size_type denom = (size_type)r->used + 1;
if(numer*kDenom <= kNumer*denom)
{
kNumer=numer;
kDenom=denom;
}
}
for(int i = 0;i < (int)requests.size() && resources_to_distribute;++i)
{
resource_request *r=requests[i];
if(r->given == r->wanted)
continue;
assert(r->given < r->wanted);
size_type used = (size_type)r->used + 1;
size_type toGive = (used * kNumer) / kDenom;
if(toGive>std::numeric_limits<int>::max())
toGive=std::numeric_limits<int>::max();
resources_to_distribute-=give(r,(int)toGive);
}
#else
size_type total_used=0;
size_type max_used=0;
for(int i = 0;i < (int)requests.size();++i)
{
resource_request *r=requests[i];
if(r->given == r->wanted)
continue;
assert(r->given < r->wanted);
max_used = std::max(max_used, (size_type)r->used + 1);
total_used += (size_type)r->used + 1;
}
size_type kNumer=resources_to_distribute;
size_type kDenom=total_used;
if(kNumer*max_used <= kDenom)
{
kNumer=1;
kDenom=max_used;
}
/*
if(kNumer > kDenom)
{
kNumer=1;
kDenom=1;
}
*/
for(int i = 0;i < (int)requests.size() && resources_to_distribute;++i)
{
resource_request *r=requests[i];
if(r->given == r->wanted)
continue;
assert(r->given < r->wanted);
size_type used = (size_type)r->used + 1;
size_type used = (size_type)r.used + 1;
size_type toGive = used * kNumer / kDenom;
if(toGive>std::numeric_limits<int>::max())
toGive=std::numeric_limits<int>::max();
resources_to_distribute-=give(r,(int)toGive);
if(toGive > std::numeric_limits<int>::max())
toGive = std::numeric_limits<int>::max();
resources_to_distribute -= give(r, (int)toGive);
}
/*
while(resources_to_distribute != 0)
{
int num_active=0;
for(int i = 0;i < (int)requests.size();++i)
{
resource_request *r=requests[i];
if(r->given == r->wanted)
continue;
num_active++;
}
int max_give=resources_to_distribute/num_active;
max_give=std::max(max_give,1);
for(int i = 0;i < (int)requests.size() && resources_to_distribute;++i)
{
resource_request *r=requests[i];
if(r->given == r->wanted)
continue;
int toGive = 1+std::min(max_give-1,r->used);
resources_to_distribute-=give(r,toGive);
}
}
*/
#endif
assert(resources_to_distribute >= 0);
}
assert(resources_to_distribute == 0);
}
peer_connection& pick_peer(
std::pair<boost::shared_ptr<socket>, boost::shared_ptr<peer_connection> > const& p)
{
return *p.second;
}
} // namespace anonymous
void allocate_resources(
int resources
, std::map<boost::shared_ptr<socket>, boost::shared_ptr<peer_connection> >& c
, resource_request peer_connection::* res)
{
typedef std::map<boost::shared_ptr<socket>, boost::shared_ptr<peer_connection> >::iterator orig_iter;
typedef std::pair<boost::shared_ptr<socket>, boost::shared_ptr<peer_connection> > in_param;
typedef boost::transform_iterator<peer_connection& (*)(in_param const&), orig_iter> new_iter;
allocate_resources_impl(
resources
, new_iter(c.begin(), &pick_peer)
, new_iter(c.end(), &pick_peer)
, res);
}
}
} // namespace libtorrent

View File

@ -107,7 +107,7 @@ namespace libtorrent
, m_disconnecting(false)
, m_became_uninterested(boost::posix_time::second_clock::local_time())
, m_became_uninteresting(boost::posix_time::second_clock::local_time())
, m_upload_bandwidth_quota_used(0)
// , m_upload_bandwidth_quota_used(0)
{
INVARIANT_CHECK;
@ -170,7 +170,7 @@ namespace libtorrent
, m_disconnecting(false)
, m_became_uninterested(boost::posix_time::second_clock::local_time())
, m_became_uninteresting(boost::posix_time::second_clock::local_time())
, m_upload_bandwidth_quota_used(0)
// , m_upload_bandwidth_quota_used(0)
{
INVARIANT_CHECK;
@ -272,12 +272,12 @@ namespace libtorrent
int peer_connection::send_quota_left() const
{
return m_upload_bandwidth_quota.given - m_upload_bandwidth_quota_used;
return m_upload_bandwidth_quota.given - m_upload_bandwidth_quota.used;
}
void peer_connection::update_send_quota_left()
void peer_connection::reset_upload_quota()
{
m_upload_bandwidth_quota_used=0;
m_upload_bandwidth_quota.used = 0;
send_buffer_updated();
}
@ -286,7 +286,6 @@ namespace libtorrent
return &m_upload_bandwidth_quota;
}
void peer_connection::send_handshake()
{
INVARIANT_CHECK;
@ -1303,9 +1302,9 @@ namespace libtorrent
INVARIANT_CHECK;
m_statistics.second_tick();
m_upload_bandwidth_quota.used=(int)ceil(statistics().upload_rate());
m_upload_bandwidth_quota.used = (int)ceil(statistics().upload_rate());
// update_send_quota_left();
send_buffer_updated();
// If the client sends more data
// we send it data faster, otherwise, slower.
@ -1678,7 +1677,7 @@ namespace libtorrent
// we want to send data
return ((!m_requests.empty() && !m_choked)
|| !m_send_buffer.empty())
&& send_quota_left()>0;
&& send_quota_left() > 0;
}
// --------------------------
@ -1757,7 +1756,7 @@ namespace libtorrent
m_announce_queue.clear();
}
assert(m_upload_bandwidth_quota_used < m_upload_bandwidth_quota.given);
assert(m_upload_bandwidth_quota.used <= m_upload_bandwidth_quota.given);
// send the actual buffer
if (!m_send_buffer.empty())
@ -1774,7 +1773,7 @@ namespace libtorrent
if (sent > 0)
{
m_upload_bandwidth_quota_used += sent;
m_upload_bandwidth_quota.used += sent;
// manage the payload markers
int amount_payload = 0;

View File

@ -67,6 +67,7 @@ POSSIBILITY OF SUCH DAMAGE.
#include "libtorrent/invariant_check.hpp"
#include "libtorrent/file.hpp"
#include "libtorrent/allocate_resources.hpp"
#include "libtorrent/peer_connection.hpp"
#if defined(_MSC_VER) && _MSC_VER < 1300
namespace std
@ -78,6 +79,7 @@ namespace std
namespace
{
/*
int saturated_add(int a, int b)
{
assert(a>=0);
@ -90,13 +92,14 @@ namespace
assert(sum>=a && sum>=b);
return sum;
}
*/
// adjusts the upload rates of every peer connection
// to make sure the sum of all send quotas equals
// the given upload_limit. An upload limit of
// std::numeric_limits<int>::max() means unlimited upload
// rate, but the rates of each peer has to be set anyway,
// since it depends on the download rate from the peer.
/*
void control_upload_rates(
int upload_limit,
libtorrent::detail::session_impl::connection_map connections)
@ -122,6 +125,7 @@ namespace
p->update_send_quota_left();
}
}
*/
/*
void control_number_of_connections(
int connections_limit,
@ -530,12 +534,12 @@ namespace libtorrent { namespace detail
boost::shared_ptr<peer_connection> c(
new peer_connection(*this, m_selector, s));
if (m_upload_rate != -1)
/* if (m_upload_rate != -1)
{
c->upload_bandwidth_quota()->given = 0;
c->update_send_quota_left();
}
*/
m_connections.insert(std::make_pair(s, c));
m_selector.monitor_readability(s);
m_selector.monitor_errors(s);
@ -704,12 +708,17 @@ namespace libtorrent { namespace detail
// distribute the maximum upload rate among the peers
control_upload_rates(
m_upload_rate == -1
allocate_resources(m_upload_rate == -1
? std::numeric_limits<int>::max()
: m_upload_rate
, m_connections);
, m_connections
, &peer_connection::m_upload_bandwidth_quota);
for (detail::session_impl::connection_map::iterator c = m_connections.begin();
c != m_connections.end(); ++c)
{
c->second->reset_upload_quota();
}
m_tracker_manager.tick();
}
@ -1000,8 +1009,9 @@ namespace libtorrent
i != m_impl.m_connections.end();)
{
i->second->upload_bandwidth_quota()->given = std::numeric_limits<int>::max();
i->second->update_send_quota_left();
// i->second->update_send_quota_left();
}
}
std::auto_ptr<alert> session::pop_alert()