initial libtorrent sync 1466

This commit is contained in:
Marcos Pinto 2007-08-19 07:46:55 +00:00
parent 7f2232f34f
commit 4164f15735
26 changed files with 525 additions and 1043 deletions

View File

@ -261,6 +261,17 @@ namespace libtorrent
{ return std::auto_ptr<alert>(new torrent_paused_alert(*this)); }
};
struct TORRENT_EXPORT torrent_checked_alert: torrent_alert
{
torrent_checked_alert(torrent_handle const& h, std::string const& msg)
: torrent_alert(h, alert::info, msg)
{}
virtual std::auto_ptr<alert> clone() const
{ return std::auto_ptr<alert>(new torrent_checked_alert(*this)); }
};
struct TORRENT_EXPORT url_seed_alert: torrent_alert
{
url_seed_alert(

View File

@ -1,78 +0,0 @@
/*
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_ALLOCATE_RESOURCES_HPP_INCLUDED
#define TORRENT_ALLOCATE_RESOURCES_HPP_INCLUDED
#include <map>
#include <utility>
#include <boost/shared_ptr.hpp>
#include "libtorrent/resource_request.hpp"
#include "libtorrent/peer_id.hpp"
#include "libtorrent/socket.hpp"
#include "libtorrent/session.hpp"
namespace libtorrent
{
class peer_connection;
class torrent;
int saturated_add(int a, int b);
// Function to allocate a limited resource fairly among many consumers.
// It takes into account the current use, and the consumer's desired use.
// Should be invoked periodically to allow it adjust to the situation (make
// sure "used" is updated between calls!).
// 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::map<sha1_hash, boost::shared_ptr<torrent> >& torrents
, resource_request torrent::* res);
void allocate_resources(
int resources
, std::map<tcp::endpoint, peer_connection*>& connections
, resource_request peer_connection::* res);
// Used for global limits.
void allocate_resources(
int resources
, std::vector<session*>& _sessions
, resource_request session::* res);
}
#endif

View File

@ -1,328 +0,0 @@
/*
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_ALLOCATE_RESOURCES_IMPL_HPP_INCLUDED
#define TORRENT_ALLOCATE_RESOURCES_IMPL_HPP_INCLUDED
#include <map>
#include <utility>
#include <boost/shared_ptr.hpp>
#include "libtorrent/resource_request.hpp"
#include "libtorrent/peer_id.hpp"
#include "libtorrent/socket.hpp"
#include "libtorrent/size_type.hpp"
#ifdef min
#undef min
#endif
#ifdef max
#undef max
#endif
namespace libtorrent
{
int saturated_add(int a, int b);
namespace aux
{
// give num_resources to r,
// return how how many were actually accepted.
inline int give(resource_request& r, int num_resources)
{
assert(num_resources >= 0);
assert(r.given <= r.max);
int accepted = (std::min)(num_resources, r.max - r.given);
assert(accepted >= 0);
r.given += accepted;
assert(r.given <= r.max);
return accepted;
}
inline int div_round_up(int numerator, int denominator)
{
return (numerator + denominator - 1) / denominator;
}
#ifndef NDEBUG
template<class It, class T>
class allocate_resources_contract_check
{
int m_resources;
It m_start;
It m_end;
resource_request T::* m_res;
public:
allocate_resources_contract_check(
int resources
, It start
, It end
, resource_request T::* res)
: m_resources(resources)
, m_start(start)
, m_end(end)
, m_res(res)
{
assert(m_resources >= 0);
for (It i = m_start, end(m_end); i != end; ++i)
{
assert(((*i).*m_res).max >= 0);
assert(((*i).*m_res).given >= 0);
}
}
~allocate_resources_contract_check()
{
int sum_given = 0;
int sum_max = 0;
int sum_min = 0;
for (It i = m_start, end(m_end); i != end; ++i)
{
assert(((*i).*m_res).max >= 0);
assert(((*i).*m_res).min >= 0);
assert(((*i).*m_res).max >= ((*i).*m_res).min);
assert(((*i).*m_res).given >= 0);
assert(((*i).*m_res).given <= ((*i).*m_res).max);
sum_given = saturated_add(sum_given, ((*i).*m_res).given);
sum_max = saturated_add(sum_max, ((*i).*m_res).max);
sum_min = saturated_add(sum_min, ((*i).*m_res).min);
}
if (sum_given != (std::min)(std::max(m_resources, sum_min), sum_max))
{
std::cerr << sum_given << " " << m_resources << " " << sum_min << " " << sum_max << std::endl;
assert(false);
}
}
};
#endif
template<class It, class T>
void allocate_resources_impl(
int resources
, It start
, It end
, resource_request T::* res)
{
assert(resources >= 0);
#ifndef NDEBUG
allocate_resources_contract_check<It, T> contract_check(
resources
, start
, end
, res);
#endif
for (It i = start; i != end; ++i)
{
resource_request& r = (*i).*res;
r.leftovers = (std::max)(r.used - r.given, 0);
}
if (resources == resource_request::inf)
{
// No competition for resources.
// Just give everyone what they want.
for (It i = start; i != end; ++i)
{
((*i).*res).given = ((*i).*res).max;
}
return;
}
// Resources are scarce
int sum_max = 0;
int sum_min = 0;
// the number of consumer that saturated their
// quota last time slice
int num_saturated = 0;
// the total resources that those saturated their
// quota used. This is used to calculate the mean
// of the saturating consumers, in order to
// balance their quotas for the next time slice.
size_type saturated_sum = 0;
for (It i = start; i != end; ++i)
{
resource_request& r = (*i).*res;
sum_max = saturated_add(sum_max, r.max);
assert(r.min < resource_request::inf);
assert(r.min >= 0);
assert(r.min <= r.max);
sum_min += r.min;
// a consumer that uses 95% or more of its assigned
// quota is considered saturating
size_type used = r.used;
if (r.given == 0) continue;
if (used * 20 / r.given >= 19)
{
++num_saturated;
saturated_sum += r.given;
}
}
if (sum_max <= resources)
{
// it turns out that there's no competition for resources
// after all.
for (It i = start; i != end; ++i)
{
((*i).*res).given = ((*i).*res).max;
}
return;
}
if (sum_min >= resources)
{
// the amount of resources is smaller than
// the minimum resources to distribute, so
// give everyone the minimum
for (It i = start; i != end; ++i)
{
((*i).*res).given = ((*i).*res).min;
}
return;
}
// now, the "used" field will be used as a target value.
// the algorithm following this loop will then scale the
// used values to fit the available resources and store
// the scaled values as given. So, the ratios of the
// used values will be maintained.
for (It i = start; i != end; ++i)
{
resource_request& r = (*i).*res;
int target;
size_type used = r.used;
if (r.given > 0 && used * 20 / r.given >= 19)
{
assert(num_saturated > 0);
target = div_round_up(saturated_sum, num_saturated);
target += div_round_up(target, 10);
}
else
{
target = r.used;
}
if (target > r.max) target = r.max;
else if (target < r.min) target = r.min;
// move 12.5% towards the the target value
r.used = r.given + div_round_up(target - r.given, 8);
r.given = r.min;
}
resources = (std::max)(resources, sum_min);
int resources_to_distribute = (std::min)(resources, sum_max) - sum_min;
assert(resources_to_distribute >= 0);
#ifndef NDEBUG
int prev_resources_to_distribute = resources_to_distribute;
#endif
while (resources_to_distribute > 0)
{
// in order to scale, we need to calculate the sum of
// all the used values.
size_type total_used = 0;
size_type max_used = 0;
for (It i = start; i != end; ++i)
{
resource_request& r = (*i).*res;
if (r.given == r.max) continue;
assert(r.given < r.max);
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;
assert(kNumer >= 0);
assert(kDenom >= 0);
assert(kNumer <= (std::numeric_limits<int>::max)());
if (kNumer * max_used <= kDenom)
{
kNumer = 1;
kDenom = max_used;
assert(kDenom >= 0);
}
for (It i = start; i != end && resources_to_distribute > 0; ++i)
{
resource_request& r = (*i).*res;
if (r.given == r.max) continue;
assert(r.given < r.max);
size_type used = (size_type)r.used + 1;
if (used < 1) used = 1;
size_type to_give = used * kNumer / kDenom;
if (to_give > resources_to_distribute)
to_give = resources_to_distribute;
assert(to_give >= 0);
assert(to_give <= resources_to_distribute);
#ifndef NDEBUG
int tmp = resources_to_distribute;
#endif
resources_to_distribute -= give(r, (int)to_give);
assert(resources_to_distribute <= tmp);
assert(resources_to_distribute >= 0);
}
assert(resources_to_distribute >= 0);
assert(resources_to_distribute < prev_resources_to_distribute);
#ifndef NDEBUG
prev_resources_to_distribute = resources_to_distribute;
#endif
}
assert(resources_to_distribute == 0);
}
} // namespace libtorrent::aux
}
#endif

View File

@ -273,8 +273,20 @@ namespace libtorrent
void set_max_connections(int limit);
void set_max_uploads(int limit);
int num_uploads() const;
int num_connections() const;
int max_connections() const { return m_max_connections; }
int max_uploads() const { return m_max_uploads; }
int num_uploads() const { return m_num_unchoked; }
int num_connections() const
{ return m_connections.size(); }
void unchoke_peer(peer_connection& c)
{
torrent* t = c.associated_torrent().lock().get();
assert(t);
t->unchoke_peer(c);
++m_num_unchoked;
}
session_status status() const;
void set_peer_id(peer_id const& id);
@ -417,6 +429,28 @@ namespace libtorrent
int m_max_uploads;
int m_max_connections;
// the number of unchoked peers
int m_num_unchoked;
// this is initialized to the unchoke_interval
// session_setting and decreased every second.
// when it reaches zero, it is reset to the
// unchoke_interval and the unchoke set is
// recomputed.
int m_unchoke_time_scaler;
// works like unchoke_time_scaler but it
// is only decresed when the unchoke set
// is recomputed, and when it reaches zero,
// the optimistic unchoke is moved to another peer.
int m_optimistic_unchoke_time_scaler;
// works like unchoke_time_scaler. Each time
// it reaches 0, and all the connections are
// used, the worst connection will be disconnected
// from the torrent with the most peers
int m_disconnect_time_scaler;
// statistics gathered from all torrents.
stat m_stat;

View File

@ -65,7 +65,6 @@ POSSIBILITY OF SUCH DAMAGE.
#include "libtorrent/alert.hpp"
#include "libtorrent/torrent_handle.hpp"
#include "libtorrent/torrent.hpp"
#include "libtorrent/allocate_resources.hpp"
#include "libtorrent/peer_request.hpp"
#include "libtorrent/piece_block_progress.hpp"
#include "libtorrent/config.hpp"

View File

@ -64,7 +64,6 @@ POSSIBILITY OF SUCH DAMAGE.
#include "libtorrent/alert.hpp"
#include "libtorrent/torrent_handle.hpp"
#include "libtorrent/torrent.hpp"
#include "libtorrent/allocate_resources.hpp"
#include "libtorrent/peer_request.hpp"
#include "libtorrent/piece_block_progress.hpp"
#include "libtorrent/config.hpp"
@ -213,7 +212,7 @@ namespace libtorrent
void add_stat(size_type downloaded, size_type uploaded);
// is called once every second by the main loop
void second_tick(float tick_interval);
void second_tick(float tick_interval) throw();
boost::shared_ptr<socket_type> get_socket() const { return m_socket; }
tcp::endpoint const& remote() const { return m_remote; }

View File

@ -89,7 +89,7 @@ namespace libtorrent
void new_connection(peer_connection& c);
// the given connection was just closed
void connection_closed(const peer_connection& c);
void connection_closed(const peer_connection& c) throw();
// the peer has got at least one interesting piece
void peer_is_interesting(peer_connection& c);
@ -155,6 +155,13 @@ namespace libtorrent
// this is true if the peer is a seed
bool seed;
// true if this peer currently is unchoked
// because of an optimistic unchoke.
// when the optimistic unchoke is moved to
// another peer, this peer will be choked
// if this is true
bool optimistically_unchoked;
// the time when this peer was optimistically unchoked
// the last time.
libtorrent::ptime last_optimistically_unchoked;
@ -203,15 +210,7 @@ namespace libtorrent
peer_connection* connection;
};
int num_peers() const
{
return m_peers.size();
}
int num_uploads() const
{
return m_num_unchoked;
}
int num_peers() const { return m_peers.size(); }
typedef std::list<peer>::iterator iterator;
typedef std::list<peer>::const_iterator const_iterator;
@ -219,9 +218,10 @@ namespace libtorrent
iterator end_peer() { return m_peers.end(); }
bool connect_one_peer();
bool disconnect_one_peer();
private:
/*
bool unchoke_one_peer();
void choke_one_peer();
iterator find_choke_candidate();
@ -233,8 +233,7 @@ namespace libtorrent
void seed_choke_one_peer();
iterator find_seed_choke_candidate();
iterator find_seed_unchoke_candidate();
bool disconnect_one_peer();
*/
iterator find_disconnect_candidate();
iterator find_connect_candidate();
@ -242,10 +241,6 @@ namespace libtorrent
torrent* m_torrent;
// the number of unchoked peers
// at any given time
int m_num_unchoked;
// free download we have got that hasn't
// been distributed yet.
size_type m_available_free_upload;
@ -253,7 +248,7 @@ namespace libtorrent
// if there is a connection limit,
// we disconnect one peer every minute in hope of
// establishing a connection with a better peer
ptime m_last_optimistic_disconnect;
// ptime m_last_optimistic_disconnect;
};
}

View File

@ -1,99 +0,0 @@
/*
Copyright (c) 2003, Magnus Jonsson, Arvid Norberg
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
#include <boost/integer_traits.hpp>
#ifdef min
#undef min
#endif
#ifdef max
#undef max
#endif
#include "libtorrent/config.hpp"
namespace libtorrent
{
struct TORRENT_EXPORT resource_request
{
resource_request()
: used(0)
, min(0)
, max(0)
, given(0)
, leftovers(0)
{}
resource_request(int used_, int min_, int max_, int given_)
: used(used_)
, min(min_)
, max(max_)
, given(given_)
, leftovers(0)
{}
int left() const
{
assert(given <= max);
assert(given >= min);
assert(used >= 0);
return (std::max)(given - used, 0);
}
void reset() { used = leftovers; leftovers = 0; }
static const int inf = boost::integer_traits<int>::const_max;
// right now I'm actively using this amount
int used;
// given cannot be smaller than min
// and not greater than max.
int min;
int max;
// Reply: Okay, you're allowed to use this amount (a compromise):
int given;
// this is the amount of resources that exceeded the
// given limit. When the used field is reset (after resources
// have been distributed), it is reset to this number.
int leftovers;
};
}
#endif

View File

@ -61,7 +61,6 @@ POSSIBILITY OF SUCH DAMAGE.
#include "libtorrent/version.hpp"
#include "libtorrent/fingerprint.hpp"
#include "libtorrent/resource_request.hpp"
#include "libtorrent/storage.hpp"
#ifdef _MSC_VER
@ -266,12 +265,6 @@ namespace libtorrent
void stop_natpmp();
void stop_upnp();
// Resource management used for global limits.
resource_request m_ul_bandwidth_quota;
resource_request m_dl_bandwidth_quota;
resource_request m_uploads_quota;
resource_request m_connections_quota;
private:
// just a way to initialize boost.filesystem

View File

@ -105,7 +105,8 @@ namespace libtorrent
, send_redundant_have(false)
, lazy_bitfields(true)
, inactivity_timeout(600)
, unchoke_interval(20)
, unchoke_interval(15)
, optimistic_unchoke_multiplier(4)
, num_want(200)
, initial_picker_threshold(4)
, allowed_fast_set_size(10)
@ -242,6 +243,10 @@ namespace libtorrent
// the number of seconds between chokes/unchokes
int unchoke_interval;
// the number of unchoke intervals between
// optimistic unchokes
int optimistic_unchoke_multiplier;
// if this is set, this IP will be reported do the
// tracker in the ip= parameter.
address announce_ip;

View File

@ -62,7 +62,6 @@ POSSIBILITY OF SUCH DAMAGE.
#include "libtorrent/tracker_manager.hpp"
#include "libtorrent/stat.hpp"
#include "libtorrent/alert.hpp"
#include "libtorrent/resource_request.hpp"
#include "libtorrent/piece_picker.hpp"
#include "libtorrent/config.hpp"
#include "libtorrent/escape_string.hpp"
@ -154,10 +153,6 @@ namespace libtorrent
bool verify_resume_data(entry& rd, std::string& error)
{ assert(m_storage); return m_storage->verify_resume_data(rd, error); }
// is called every second by session. This will
// caclulate the upload/download and number
// of connections this torrent needs. And prepare
// it for being used by allocate_resources.
void second_tick(stat& accumulator, float tick_interval);
// debug purpose only
@ -254,6 +249,15 @@ namespace libtorrent
void remove_url_seed(std::string const& url)
{ m_web_seeds.erase(url); }
std::set<std::string> url_seeds() const
{ return m_web_seeds; }
bool free_upload_slots() const
{ return m_num_uploads < m_max_uploads; }
void choke_peer(peer_connection& c);
bool unchoke_peer(peer_connection& c);
// used by peer_connection to attach itself to a torrent
// since incoming connections don't know what torrent
// they're a part of until they have received an info_hash.
@ -516,11 +520,6 @@ namespace libtorrent
// --------------------------------------------
// RESOURCE MANAGEMENT
void distribute_resources(float tick_interval);
resource_request m_uploads_quota;
resource_request m_connections_quota;
void set_peer_upload_limit(tcp::endpoint ip, int limit);
void set_peer_download_limit(tcp::endpoint ip, int limit);
@ -530,7 +529,9 @@ namespace libtorrent
int download_limit() const;
void set_max_uploads(int limit);
int max_uploads() const { return m_max_uploads; }
void set_max_connections(int limit);
int max_connections() const { return m_max_connections; }
void move_storage(fs::path const& save_path);
// unless this returns true, new connections must wait
@ -705,9 +706,9 @@ namespace libtorrent
// determine the timeout until next try.
int m_failed_trackers;
// this is a counter that is increased every
// second, and when it reaches 10, the policy::pulse()
// is called and the time scaler is reset to 0.
// this is a counter that is decreased every
// second, and when it reaches 0, the policy::pulse()
// is called and the time scaler is reset to 10.
int m_time_scaler;
// the bitmask that says which pieces we have
@ -775,6 +776,15 @@ namespace libtorrent
storage_constructor_type m_storage_constructor;
// the maximum number of uploads for this torrent
int m_max_uploads;
// the number of unchoked peers in this torrent
int m_num_uploads;
// the maximum number of connections for this torrent
int m_max_connections;
#ifndef TORRENT_DISABLE_EXTENSIONS
typedef std::list<boost::shared_ptr<torrent_plugin> > extension_list_t;
extension_list_t m_extensions;

View File

@ -34,6 +34,7 @@ POSSIBILITY OF SUCH DAMAGE.
#define TORRENT_TORRENT_HANDLE_HPP_INCLUDED
#include <vector>
#include <set>
#ifdef _MSC_VER
#pragma warning(push, 1)
@ -273,7 +274,9 @@ namespace libtorrent
std::vector<announce_entry> const& trackers() const;
void replace_trackers(std::vector<announce_entry> const&) const;
void add_url_seed(std::string const& url);
void add_url_seed(std::string const& url) const;
void remove_url_seed(std::string const& url) const;
std::set<std::string> url_seeds() const;
bool has_metadata() const;
const torrent_info& get_torrent_info() const;

View File

@ -65,7 +65,6 @@ POSSIBILITY OF SUCH DAMAGE.
#include "libtorrent/alert.hpp"
#include "libtorrent/torrent_handle.hpp"
#include "libtorrent/torrent.hpp"
#include "libtorrent/allocate_resources.hpp"
#include "libtorrent/peer_request.hpp"
#include "libtorrent/piece_block_progress.hpp"
#include "libtorrent/config.hpp"

View File

@ -12,8 +12,7 @@ kademlia/rpc_manager.cpp \
kademlia/traversal_algorithm.cpp
endif
libtorrent_la_SOURCES = allocate_resources.cpp \
entry.cpp escape_string.cpp \
libtorrent_la_SOURCES = entry.cpp escape_string.cpp \
peer_connection.cpp bt_peer_connection.cpp web_peer_connection.cpp \
natpmp.cpp piece_picker.cpp policy.cpp session.cpp session_impl.cpp sha1.cpp \
stat.cpp storage.cpp torrent.cpp torrent_handle.cpp pe_crypto.cpp \
@ -28,8 +27,6 @@ $(kademlia_sources)
noinst_HEADERS = \
$(top_srcdir)/include/libtorrent/alert.hpp \
$(top_srcdir)/include/libtorrent/alert_types.hpp \
$(top_srcdir)/include/libtorrent/allocate_resources.hpp \
$(top_srcdir)/include/libtorrent/aux_/allocate_resources_impl.hpp \
$(top_srcdir)/include/libtorrent/aux_/session_impl.hpp \
$(top_srcdir)/include/libtorrent/bandwidth_manager.hpp \
$(top_srcdir)/include/libtorrent/bencode.hpp \
@ -71,7 +68,6 @@ $(top_srcdir)/include/libtorrent/peer_request.hpp \
$(top_srcdir)/include/libtorrent/piece_block_progress.hpp \
$(top_srcdir)/include/libtorrent/piece_picker.hpp \
$(top_srcdir)/include/libtorrent/policy.hpp \
$(top_srcdir)/include/libtorrent/resource_request.hpp \
$(top_srcdir)/include/libtorrent/session.hpp \
$(top_srcdir)/include/libtorrent/size_type.hpp \
$(top_srcdir)/include/libtorrent/socket.hpp \

View File

@ -1,225 +0,0 @@
/*
Copyright (c) 2006, Magnus Jonsson, Arvid Norberg
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.
*/
//The Standard Library defines the two template functions std::min()
//and std::max() in the <algorithm> header. In general, you should
//use these template functions for calculating the min and max values
//of a pair. Unfortunately, Visual C++ does not define these function
// templates. This is because the names min and max clash with
//the traditional min and max macros defined in <windows.h>.
//As a workaround, Visual C++ defines two alternative templates with
//identical functionality called _cpp_min() and _cpp_max(). You can
//use them instead of std::min() and std::max().To disable the
//generation of the min and max macros in Visual C++, #define
//NOMINMAX before #including <windows.h>.
#include "libtorrent/pch.hpp"
#ifdef _WIN32
//support boost1.32.0(2004-11-19 18:47)
//now all libs can be compiled and linked with static module
#define NOMINMAX
#endif
#include "libtorrent/allocate_resources.hpp"
#include "libtorrent/size_type.hpp"
#include "libtorrent/peer_connection.hpp"
#include "libtorrent/torrent.hpp"
#include "libtorrent/aux_/allocate_resources_impl.hpp"
#include <cassert>
#include <algorithm>
#include <boost/limits.hpp>
#if defined(_MSC_VER) && _MSC_VER < 1310
#define for if (false) {} else for
#else
#include <boost/iterator/transform_iterator.hpp>
#endif
namespace libtorrent
{
int saturated_add(int a, int b)
{
assert(a >= 0);
assert(b >= 0);
assert(a <= resource_request::inf);
assert(b <= resource_request::inf);
assert(resource_request::inf + resource_request::inf < 0);
unsigned int sum = unsigned(a) + unsigned(b);
if (sum > unsigned(resource_request::inf))
sum = resource_request::inf;
assert(sum >= unsigned(a) && sum >= unsigned(b));
return int(sum);
}
#if defined(_MSC_VER) && _MSC_VER < 1310
namespace detail
{
struct iterator_wrapper
{
typedef std::map<sha1_hash, boost::shared_ptr<torrent> >::iterator orig_iter;
orig_iter iter;
iterator_wrapper(orig_iter i): iter(i) {}
void operator++() { ++iter; }
torrent& operator*() { return *(iter->second); }
bool operator==(const iterator_wrapper& i) const
{ return iter == i.iter; }
bool operator!=(const iterator_wrapper& i) const
{ return iter != i.iter; }
};
struct iterator_wrapper2
{
typedef std::map<tcp::endpoint, peer_connection*>::iterator orig_iter;
orig_iter iter;
iterator_wrapper2(orig_iter i): iter(i) {}
void operator++() { ++iter; }
peer_connection& operator*() { return *(iter->second); }
bool operator==(const iterator_wrapper2& i) const
{ return iter == i.iter; }
bool operator!=(const iterator_wrapper2& i) const
{ return iter != i.iter; }
};
}
void allocate_resources(
int resources
, std::map<sha1_hash, boost::shared_ptr<torrent> >& c
, resource_request torrent::* res)
{
aux::allocate_resources_impl(
resources
, detail::iterator_wrapper(c.begin())
, detail::iterator_wrapper(c.end())
, res);
}
void allocate_resources(
int resources
, std::map<tcp::endpoint, peer_connection*>& c
, resource_request peer_connection::* res)
{
aux::allocate_resources_impl(
resources
, detail::iterator_wrapper2(c.begin())
, detail::iterator_wrapper2(c.end())
, res);
}
#else
namespace aux
{
peer_connection& pick_peer(
std::pair<boost::shared_ptr<stream_socket>
, boost::intrusive_ptr<peer_connection> > const& p)
{
return *p.second;
}
peer_connection& pick_peer2(
std::pair<tcp::endpoint, peer_connection*> const& p)
{
return *p.second;
}
torrent& deref(std::pair<sha1_hash, boost::shared_ptr<torrent> > const& p)
{
return *p.second;
}
session& deref(session* p)
{
return *p;
}
}
void allocate_resources(
int resources
, std::map<sha1_hash, boost::shared_ptr<torrent> >& c
, resource_request torrent::* res)
{
typedef std::map<sha1_hash, boost::shared_ptr<torrent> >::iterator orig_iter;
typedef std::pair<sha1_hash, boost::shared_ptr<torrent> > in_param;
typedef boost::transform_iterator<torrent& (*)(in_param const&), orig_iter> new_iter;
aux::allocate_resources_impl(
resources
, new_iter(c.begin(), &aux::deref)
, new_iter(c.end(), &aux::deref)
, res);
}
void allocate_resources(
int resources
, std::map<tcp::endpoint, peer_connection*>& c
, resource_request peer_connection::* res)
{
typedef std::map<tcp::endpoint, peer_connection*>::iterator orig_iter;
typedef std::pair<tcp::endpoint, peer_connection*> in_param;
typedef boost::transform_iterator<peer_connection& (*)(in_param const&), orig_iter> new_iter;
aux::allocate_resources_impl(
resources
, new_iter(c.begin(), &aux::pick_peer2)
, new_iter(c.end(), &aux::pick_peer2)
, res);
}
void allocate_resources(
int resources
, std::vector<session*>& _sessions
, resource_request session::* res)
{
typedef std::vector<session*>::iterator orig_iter;
typedef session* in_param;
typedef boost::transform_iterator<session& (*)(in_param), orig_iter> new_iter;
aux::allocate_resources_impl(
resources
, new_iter(_sessions.begin(), &aux::deref)
, new_iter(_sessions.end(), &aux::deref)
, res);
}
#endif
} // namespace libtorrent

View File

@ -1369,7 +1369,7 @@ namespace libtorrent
assert(t->is_seed() == (std::count(bitfield.begin(), bitfield.end(), true) == num_pieces));
if (t->is_seed() && m_ses.settings().lazy_bitfields)
{
num_lazy_pieces = std::min(50, num_pieces / 10);
num_lazy_pieces = (std::min)(50, num_pieces / 10);
if (num_lazy_pieces < 1) num_lazy_pieces = 1;
for (int i = 0; i < num_pieces; ++i)
{
@ -1735,7 +1735,7 @@ namespace libtorrent
if (m_sync_bytes_read >= 512)
throw protocol_error("sync hash not found within 532 bytes");
cut_receive_buffer(bytes_processed, std::min(packet_size(), (512+20) - m_sync_bytes_read));
cut_receive_buffer(bytes_processed, (std::min)(packet_size(), (512+20) - m_sync_bytes_read));
assert(!packet_finished());
return;
@ -1873,7 +1873,7 @@ namespace libtorrent
if (m_sync_bytes_read >= 512)
throw protocol_error("sync verification constant not found within 520 bytes");
cut_receive_buffer(bytes_processed, std::min(packet_size(), (512+8) - m_sync_bytes_read));
cut_receive_buffer(bytes_processed, (std::min)(packet_size(), (512+8) - m_sync_bytes_read));
assert(!packet_finished());
return;

View File

@ -250,7 +250,7 @@ namespace libtorrent
assert(m_state == read_body);
if (m_content_length >= 0)
return buffer::const_interval(m_recv_buffer.begin + m_body_start_pos
, m_recv_buffer.begin + std::min(m_recv_pos
, m_recv_buffer.begin + (std::min)(m_recv_pos
, m_body_start_pos + m_content_length));
else
return buffer::const_interval(m_recv_buffer.begin + m_body_start_pos
@ -408,7 +408,7 @@ namespace libtorrent
{
m_send_buffer += "numwant=";
m_send_buffer += boost::lexical_cast<std::string>(
std::min(req.num_want, 999));
(std::min)(req.num_want, 999));
m_send_buffer += '&';
}
if (m_settings.announce_ip != address() && !url_has_argument(request, "ip"))

View File

@ -109,8 +109,8 @@ namespace libtorrent
, m_prefer_whole_pieces(false)
, m_request_large_blocks(false)
, m_non_prioritized(false)
, m_upload_limit(resource_request::inf)
, m_download_limit(resource_request::inf)
, m_upload_limit(bandwidth_limit::inf)
, m_download_limit(bandwidth_limit::inf)
, m_peer_info(peerinfo)
, m_speed(slow)
, m_connection_ticket(-1)
@ -185,8 +185,8 @@ namespace libtorrent
, m_prefer_whole_pieces(false)
, m_request_large_blocks(false)
, m_non_prioritized(false)
, m_upload_limit(resource_request::inf)
, m_download_limit(resource_request::inf)
, m_upload_limit(bandwidth_limit::inf)
, m_download_limit(bandwidth_limit::inf)
, m_peer_info(peerinfo)
, m_speed(slow)
, m_remote_bytes_dled(0)
@ -441,8 +441,6 @@ namespace libtorrent
void peer_connection::add_stat(size_type downloaded, size_type uploaded)
{
INVARIANT_CHECK;
m_statistics.add_stat(downloaded, uploaded);
}
@ -527,27 +525,20 @@ namespace libtorrent
&& (p.start % t->block_size() == 0);
}
struct disconnect_torrent
{
disconnect_torrent(boost::weak_ptr<torrent>& t): m_t(&t) {}
~disconnect_torrent() { if (m_t) m_t->reset(); }
void cancel() { m_t = 0; }
private:
boost::weak_ptr<torrent>* m_t;
};
void peer_connection::attach_to_torrent(sha1_hash const& ih)
{
INVARIANT_CHECK;
assert(!m_disconnecting);
m_torrent = m_ses.find_torrent(ih);
boost::shared_ptr<torrent> t = m_torrent.lock();
assert(m_torrent.expired());
boost::weak_ptr<torrent> wpt = m_ses.find_torrent(ih);
boost::shared_ptr<torrent> t = wpt.lock();
if (t && t->is_aborted())
{
m_torrent.reset();
#ifdef TORRENT_VERBOSE_LOGGING
(*m_logger) << " *** the torrent has been aborted\n";
#endif
t.reset();
}
@ -555,12 +546,18 @@ namespace libtorrent
{
// we couldn't find the torrent!
#ifdef TORRENT_VERBOSE_LOGGING
(*m_logger) << " couldn't find a torrent with the given info_hash: " << ih << "\n";
(*m_logger) << " *** couldn't find a torrent with the given info_hash: " << ih << "\n";
(*m_logger) << " torrents:\n";
session_impl::torrent_map const& torrents = m_ses.m_torrents;
for (session_impl::torrent_map::const_iterator i = torrents.begin()
, end(torrents.end()); i != end; ++i)
{
(*m_logger) << " " << i->second->torrent_file().info_hash() << "\n";
}
#endif
throw std::runtime_error("got info-hash that is not in our session");
}
disconnect_torrent disconnect(m_torrent);
if (t->is_paused())
{
// paused torrents will not accept
@ -571,21 +568,27 @@ namespace libtorrent
throw std::runtime_error("connection rejected by paused torrent");
}
assert(m_torrent.expired());
// check to make sure we don't have another connection with the same
// info_hash and peer_id. If we do. close this connection.
t->attach_peer(this);
m_torrent = wpt;
assert(!m_torrent.expired());
// if the torrent isn't ready to accept
// connections yet, we'll have to wait with
// our initialization
if (t->ready_for_connections()) init();
assert(!m_torrent.expired());
// assume the other end has no pieces
// if we don't have valid metadata yet,
// leave the vector unallocated
assert(m_num_pieces == 0);
std::fill(m_have_piece.begin(), m_have_piece.end(), false);
disconnect.cancel();
assert(!m_torrent.expired());
}
// message handlers
@ -1543,7 +1546,7 @@ namespace libtorrent
// if the peer has the piece and we want
// to download it, request it
if (m_have_piece.size() > index
if (int(m_have_piece.size()) > index
&& m_have_piece[index]
&& t->has_picker()
&& t->picker().piece_priority(index) > 0)
@ -1656,7 +1659,7 @@ namespace libtorrent
int block_offset = block.block_index * t->block_size();
int block_size
= std::min((int)t->torrent_file().piece_size(block.piece_index)-block_offset,
= (std::min)((int)t->torrent_file().piece_size(block.piece_index)-block_offset,
t->block_size());
assert(block_size > 0);
assert(block_size <= t->block_size());
@ -1757,7 +1760,7 @@ namespace libtorrent
piece_block block = m_request_queue.front();
int block_offset = block.block_index * t->block_size();
int block_size = std::min((int)t->torrent_file().piece_size(
int block_size = (std::min)((int)t->torrent_file().piece_size(
block.piece_index) - block_offset, t->block_size());
assert(block_size > 0);
assert(block_size <= t->block_size());
@ -1797,7 +1800,7 @@ namespace libtorrent
#endif
*/
block_offset = block.block_index * t->block_size();
block_size = std::min((int)t->torrent_file().piece_size(
block_size = (std::min)((int)t->torrent_file().piece_size(
block.piece_index) - block_offset, t->block_size());
assert(block_size > 0);
assert(block_size <= t->block_size());
@ -1900,7 +1903,7 @@ namespace libtorrent
void peer_connection::set_upload_limit(int limit)
{
assert(limit >= -1);
if (limit == -1) limit = resource_request::inf;
if (limit == -1) limit = std::numeric_limits<int>::max();
if (limit < 10) limit = 10;
m_upload_limit = limit;
m_bandwidth_limit[upload_channel].throttle(m_upload_limit);
@ -1909,7 +1912,7 @@ namespace libtorrent
void peer_connection::set_download_limit(int limit)
{
assert(limit >= -1);
if (limit == -1) limit = resource_request::inf;
if (limit == -1) limit = std::numeric_limits<int>::max();
if (limit < 10) limit = 10;
m_download_limit = limit;
m_bandwidth_limit[download_channel].throttle(m_download_limit);
@ -1996,7 +1999,7 @@ namespace libtorrent
p.pieces = get_bitfield();
ptime now = time_now();
p.last_request = now - m_last_request;
p.last_active = now - std::max(m_last_sent, m_last_receive);
p.last_active = now - (std::max)(m_last_sent, m_last_receive);
// this will set the flags so that we can update them later
p.flags = 0;
@ -2044,10 +2047,13 @@ namespace libtorrent
if (m_packet_size >= m_recv_pos) m_recv_buffer.resize(m_packet_size);
}
void peer_connection::second_tick(float tick_interval)
void peer_connection::second_tick(float tick_interval) throw()
{
INVARIANT_CHECK;
try
{
ptime now(time_now());
boost::shared_ptr<torrent> t = m_torrent.lock();
@ -2160,14 +2166,14 @@ namespace libtorrent
if (t->ratio() != 1.f)
soon_downloaded = (size_type)(soon_downloaded*(double)t->ratio());
double upload_speed_limit = std::min((soon_downloaded - have_uploaded
double upload_speed_limit = (std::min)((soon_downloaded - have_uploaded
+ bias) / break_even_time, double(m_upload_limit));
upload_speed_limit = std::min(upload_speed_limit,
upload_speed_limit = (std::min)(upload_speed_limit,
(double)std::numeric_limits<int>::max());
m_bandwidth_limit[upload_channel].throttle(
std::min(std::max((int)upload_speed_limit, 20)
(std::min)((std::max)((int)upload_speed_limit, 20)
, m_upload_limit));
}
@ -2186,43 +2192,14 @@ namespace libtorrent
}
fill_send_buffer();
/*
size_type diff = share_diff();
enum { block_limit = 2 }; // how many blocks difference is considered unfair
// if the peer has been choked, send the current piece
// as fast as possible
if (diff > block_limit*m_torrent->block_size() || m_torrent->is_seed() || is_choked())
{
// if we have downloaded more than one piece more
// than we have uploaded OR if we are a seed
// have an unlimited upload rate
m_ul_bandwidth_quota.wanted = std::numeric_limits<int>::max();
}
else
catch (std::exception& e)
{
float ratio = m_torrent->ratio();
// if we have downloaded too much, response with an
// upload rate of 10 kB/s more than we dowlload
// if we have uploaded too much, send with a rate of
// 10 kB/s less than we receive
int bias = 0;
if (diff > -block_limit*m_torrent->block_size())
{
bias = static_cast<int>(m_statistics.download_rate() * ratio) / 2;
if (bias < 10*1024) bias = 10*1024;
}
else
{
bias = -static_cast<int>(m_statistics.download_rate() * ratio) / 2;
}
m_ul_bandwidth_quota.wanted = static_cast<int>(m_statistics.download_rate()) + bias;
// the maximum send_quota given our download rate from this peer
if (m_ul_bandwidth_quota.wanted < 256) m_ul_bandwidth_quota.wanted = 256;
#ifdef TORRENT_VERBOSE_LOGGING
(*m_logger) << "**ERROR**: " << e.what() << "\n";
#endif
m_ses.connection_failed(m_socket, remote(), e.what());
}
*/
}
void peer_connection::fill_send_buffer()

View File

@ -189,7 +189,8 @@ namespace libtorrent
// infinite loop, fighting to request the same blocks.
void request_a_block(torrent& t, peer_connection& c)
{
assert(!t.is_seed());
if (t.is_seed()) return;
assert(t.valid_metadata());
assert(c.peer_info_struct() != 0 || !dynamic_cast<bt_peer_connection*>(&c));
int num_requests = c.desired_queue_size()
@ -298,6 +299,7 @@ namespace libtorrent
assert(p.num_peers(*i) == 1);
assert(p.is_requested(*i));
num_requests--;
if (num_requests == 0) break;
}
if (busy_pieces.empty() || num_requests == 0)
@ -331,9 +333,8 @@ namespace libtorrent
policy::policy(torrent* t)
: m_torrent(t)
, m_num_unchoked(0)
, m_available_free_upload(0)
, m_last_optimistic_disconnect(min_time())
// , m_last_optimistic_disconnect(min_time())
{ assert(t); }
// disconnects and removes all peers that are now filtered
@ -375,7 +376,7 @@ namespace libtorrent
m_peers.erase(i++);
}
}
/*
// finds the peer that has the worst download rate
// and returns it. May return 0 if all peers are
// choked.
@ -457,7 +458,7 @@ namespace libtorrent
}
return unchoke_peer;
}
*/
policy::iterator policy::find_disconnect_candidate()
{
INVARIANT_CHECK;
@ -542,7 +543,7 @@ namespace libtorrent
return candidate;
}
/*
policy::iterator policy::find_seed_choke_candidate()
{
INVARIANT_CHECK;
@ -648,7 +649,7 @@ namespace libtorrent
--m_num_unchoked;
}
}
*/
void policy::pulse()
{
INVARIANT_CHECK;
@ -680,7 +681,7 @@ namespace libtorrent
// -------------------------------------
// maintain the number of connections
// -------------------------------------
/*
// count the number of connected peers except for peers
// that are currently in the process of disconnecting
int num_connected_peers = 0;
@ -692,10 +693,9 @@ namespace libtorrent
++num_connected_peers;
}
if (m_torrent->m_connections_quota.given != std::numeric_limits<int>::max())
if (m_torrent->max_connections() != std::numeric_limits<int>::max())
{
int max_connections = m_torrent->m_connections_quota.given;
int max_connections = m_torrent->max_connections();
if (num_connected_peers >= max_connections)
{
@ -723,7 +723,7 @@ namespace libtorrent
--num_connected_peers;
}
}
*/
// ------------------------
// upload shift
// ------------------------
@ -754,7 +754,7 @@ namespace libtorrent
, m_torrent->end()
, m_available_free_upload);
}
/*
// ------------------------
// seed choking policy
// ------------------------
@ -870,6 +870,7 @@ namespace libtorrent
while (m_num_unchoked < m_torrent->m_uploads_quota.given
&& unchoke_one_peer());
}
*/
}
int policy::count_choked() const
@ -902,7 +903,8 @@ namespace libtorrent
// override at a time
assert(c.remote() == c.get_socket()->remote_endpoint());
if (m_torrent->num_peers() >= m_torrent->m_connections_quota.given
if (m_torrent->num_peers() >= m_torrent->max_connections()
&& m_torrent->session().num_connections() >= m_torrent->session().max_connections()
&& c.remote().address() != m_torrent->current_tracker().address())
{
throw protocol_error("too many connections, refusing incoming connection"); // cause a disconnect
@ -984,7 +986,7 @@ namespace libtorrent
i->connection = &c;
assert(i->connection);
i->connected = time_now();
m_last_optimistic_disconnect = time_now();
// m_last_optimistic_disconnect = time_now();
}
void policy::peer_from_tracker(const tcp::endpoint& remote, const peer_id& pid
@ -1172,14 +1174,38 @@ namespace libtorrent
// In that case we don't care if people are leeching, they
// can't pay for their downloads anyway.
if (c.is_choked()
&& m_num_unchoked < m_torrent->m_uploads_quota.given
&& m_torrent->session().num_uploads() < m_torrent->session().max_uploads()
&& (m_torrent->ratio() == 0
|| c.share_diff() >= -free_upload_amount
|| m_torrent->is_seed()))
{
c.send_unchoke();
++m_num_unchoked;
m_torrent->session().unchoke_peer(c);
}
#if defined(TORRENT_VERBOSE_LOGGING)
else if (c.is_choked())
{
std::string reason;
if (m_torrent->session().num_uploads() >= m_torrent->session().max_uploads())
{
reason = "the number of uploads ("
+ boost::lexical_cast<std::string>(m_torrent->session().num_uploads())
+ ") is more than or equal to the limit ("
+ boost::lexical_cast<std::string>(m_torrent->session().max_uploads())
+ ")";
}
else
{
reason = "the share ratio ("
+ boost::lexical_cast<std::string>(c.share_diff())
+ ") is <= free_upload_amount ("
+ boost::lexical_cast<std::string>(int(free_upload_amount))
+ ") and we are not seeding and the ratio ("
+ boost::lexical_cast<std::string>(m_torrent->ratio())
+ ")is non-zero";
}
(*c.m_logger) << time_now_string() << " DID NOT UNCHOKE [ " << reason << " ]\n";
}
#endif
}
// called when a peer is no longer interested in us
@ -1211,7 +1237,7 @@ namespace libtorrent
}
*/
}
/*
bool policy::unchoke_one_peer()
{
INVARIANT_CHECK;
@ -1240,7 +1266,7 @@ namespace libtorrent
p->connection->send_choke();
--m_num_unchoked;
}
*/
bool policy::connect_one_peer()
{
INVARIANT_CHECK;
@ -1256,7 +1282,7 @@ namespace libtorrent
try
{
p->connected = m_last_optimistic_disconnect = time_now();
p->connected = time_now();
p->connection = m_torrent->connect_to_peer(&*p);
if (p->connection == 0) return false;
p->connection->add_stat(p->prev_amount_download, p->prev_amount_upload);
@ -1289,33 +1315,30 @@ namespace libtorrent
}
// this is called whenever a peer connection is closed
void policy::connection_closed(const peer_connection& c) try
void policy::connection_closed(const peer_connection& c) throw()
{
INVARIANT_CHECK;
// assert(c.is_disconnecting());
bool unchoked = false;
peer* p = c.peer_info_struct();
// if we couldn't find the connection in our list, just ignore it.
if (p == 0) return;
iterator i = std::find_if(
assert(std::find_if(
m_peers.begin()
, m_peers.end()
, match_peer_connection(c));
, match_peer_connection(c))
!= m_peers.end());
assert(p->connection == &c);
// if we couldn't find the connection in our list, just ignore it.
if (i == m_peers.end()) return;
assert(i->connection == &c);
i->connection = 0;
p->connection = 0;
p->optimistically_unchoked = false;
i->connected = time_now();
if (!c.is_choked() && !m_torrent->is_aborted())
{
unchoked = true;
}
p->connected = time_now();
if (c.failed())
{
++i->failcount;
// i->connected = time_now();
++p->failcount;
// p->connected = time_now();
}
// if the share ratio is 0 (infinite), the
@ -1327,25 +1350,8 @@ namespace libtorrent
assert(c.share_diff() < std::numeric_limits<size_type>::max());
m_available_free_upload += c.share_diff();
}
i->prev_amount_download += c.statistics().total_payload_download();
i->prev_amount_upload += c.statistics().total_payload_upload();
if (unchoked)
{
// if the peer that is diconnecting is unchoked
// then unchoke another peer in order to maintain
// the total number of unchoked peers
--m_num_unchoked;
if (m_torrent->is_seed()) seed_unchoke_one_peer();
else unchoke_one_peer();
}
}
catch (std::exception& e)
{
#ifndef NDEBUG
std::string err = e.what();
#endif
assert(false);
p->prev_amount_download += c.statistics().total_payload_download();
p->prev_amount_upload += c.statistics().total_payload_upload();
}
void policy::peer_is_interesting(peer_connection& c)
@ -1376,7 +1382,6 @@ namespace libtorrent
void policy::check_invariant() const
{
if (m_torrent->is_aborted()) return;
int actual_unchoked = 0;
int connected_peers = 0;
int total_connections = 0;
@ -1405,10 +1410,7 @@ namespace libtorrent
++nonempty_connections;
if (!p.connection->is_disconnecting())
++connected_peers;
if (!p.connection->is_choked()) ++actual_unchoked;
}
// assert(actual_unchoked <= m_torrent->m_uploads_quota.given);
assert(actual_unchoked == m_num_unchoked);
int num_torrent_peers = 0;
for (torrent::const_peer_iterator i = m_torrent->begin();
@ -1475,6 +1477,7 @@ namespace libtorrent
, failcount(0)
, hashfails(0)
, seed(false)
, optimistically_unchoked(false)
, last_optimistically_unchoked(min_time())
, connected(min_time())
, trust_points(0)

View File

@ -68,7 +68,6 @@ POSSIBILITY OF SUCH DAMAGE.
#include "libtorrent/alert_types.hpp"
#include "libtorrent/invariant_check.hpp"
#include "libtorrent/file.hpp"
#include "libtorrent/allocate_resources.hpp"
#include "libtorrent/bt_peer_connection.hpp"
#include "libtorrent/ip_filter.hpp"
#include "libtorrent/socket.hpp"

View File

@ -68,7 +68,6 @@ POSSIBILITY OF SUCH DAMAGE.
#include "libtorrent/alert_types.hpp"
#include "libtorrent/invariant_check.hpp"
#include "libtorrent/file.hpp"
#include "libtorrent/allocate_resources.hpp"
#include "libtorrent/bt_peer_connection.hpp"
#include "libtorrent/ip_filter.hpp"
#include "libtorrent/socket.hpp"
@ -223,6 +222,12 @@ namespace detail
if (!m_ses.is_aborted())
{
m_ses.m_torrents.insert(std::make_pair(t->info_hash, t->torrent_ptr));
if (m_ses.m_alerts.should_post(alert::info))
{
m_ses.m_alerts.post_alert(torrent_checked_alert(
processing->torrent_ptr->get_handle()
, "torrent finished checking"));
}
if (t->torrent_ptr->is_seed() && m_ses.m_alerts.should_post(alert::info))
{
m_ses.m_alerts.post_alert(torrent_finished_alert(
@ -345,6 +350,12 @@ namespace detail
processing->torrent_ptr->files_checked(processing->unfinished_pieces);
m_ses.m_torrents.insert(std::make_pair(
processing->info_hash, processing->torrent_ptr));
if (m_ses.m_alerts.should_post(alert::info))
{
m_ses.m_alerts.post_alert(torrent_checked_alert(
processing->torrent_ptr->get_handle()
, "torrent finished checking"));
}
if (processing->torrent_ptr->is_seed()
&& m_ses.m_alerts.should_post(alert::info))
{
@ -505,8 +516,12 @@ namespace detail
, m_listen_interface(address::from_string(listen_interface), listen_port_range.first)
, m_external_listen_port(0)
, m_abort(false)
, m_max_uploads(-1)
, m_max_connections(-1)
, m_max_uploads(8)
, m_max_connections(200)
, m_num_unchoked(0)
, m_unchoke_time_scaler(0)
, m_optimistic_unchoke_time_scaler(0)
, m_disconnect_time_scaler(0)
, m_incoming_connection(false)
, m_last_tick(time_now())
#ifndef TORRENT_DISABLE_DHT
@ -821,7 +836,10 @@ namespace detail
assert(p->is_disconnecting());
connection_map::iterator i = m_connections.find(p->get_socket());
if (i != m_connections.end())
{
if (!i->second->is_choked()) --m_num_unchoked;
m_connections.erase(i);
}
}
void session_impl::set_peer_id(peer_id const& id)
@ -901,7 +919,9 @@ namespace detail
// round robin fashion, so that every torrent is
// equallt likely to connect to a peer
if (!m_torrents.empty() && m_half_open.free_slots())
if (!m_torrents.empty()
&& m_half_open.free_slots()
&& num_connections() < m_max_connections)
{
// this is the maximum number of connections we will
// attempt this tick
@ -918,11 +938,13 @@ namespace detail
{
torrent& t = *i->second;
if (t.want_more_peers())
{
if (t.try_connect_peer())
{
--max_connections;
steps_since_last_connect = 0;
}
}
++m_next_connect_torrent;
++steps_since_last_connect;
++i;
@ -976,18 +998,7 @@ namespace detail
continue;
}
try
{
c.keep_alive();
}
catch (std::exception& exc)
{
#ifdef TORRENT_VERBOSE_LOGGING
(*c.m_logger) << "**ERROR**: " << exc.what() << "\n";
#endif
c.set_failed();
c.disconnect();
}
c.keep_alive();
}
// check each torrent for tracker updates
@ -1019,30 +1030,173 @@ namespace detail
}
m_stat.second_tick(tick_interval);
// distribute the maximum upload rate among the torrents
assert(m_max_uploads >= -1);
assert(m_max_connections >= -1);
allocate_resources(m_max_uploads == -1
? std::numeric_limits<int>::max()
: m_max_uploads
, m_torrents
, &torrent::m_uploads_quota);
allocate_resources(m_max_connections == -1
? std::numeric_limits<int>::max()
: m_max_connections
, m_torrents
, &torrent::m_connections_quota);
for (std::map<sha1_hash, boost::shared_ptr<torrent> >::iterator i
= m_torrents.begin(); i != m_torrents.end(); ++i)
// --------------------------------------------------------------
// unchoke set and optimistic unchoke calculations
// --------------------------------------------------------------
m_unchoke_time_scaler--;
if (m_unchoke_time_scaler <= 0 && !m_connections.empty())
{
#ifndef NDEBUG
i->second->check_invariant();
#endif
i->second->distribute_resources(tick_interval);
m_unchoke_time_scaler = settings().unchoke_interval;
std::vector<peer_connection*> peers;
for (connection_map::iterator i = m_connections.begin()
, end(m_connections.end()); i != end; ++i)
{
peer_connection* p = i->second.get();
torrent* t = p->associated_torrent().lock().get();
if (!p->peer_info_struct()
|| t == 0
|| !p->is_peer_interested()
|| p->is_disconnecting()
|| p->is_connecting()
|| (p->share_diff() < -free_upload_amount
&& !t->is_seed()))
{
if (!i->second->is_choked() && t)
t->choke_peer(*i->second);
continue;
}
peers.push_back(i->second.get());
}
// sort the peers that are eligible for unchoke by download rate and secondary
// by total upload. The reason for this is, if all torrents are being seeded,
// the download rate will be 0, and the peers we have sent the least to should
// be unchoked
std::sort(peers.begin(), peers.end()
, bind(&stat::total_payload_upload, bind(&peer_connection::statistics, _1))
< bind(&stat::total_payload_upload, bind(&peer_connection::statistics, _2)));
std::stable_sort(peers.begin(), peers.end()
, bind(&stat::download_payload_rate, bind(&peer_connection::statistics, _1))
> bind(&stat::download_payload_rate, bind(&peer_connection::statistics, _2)));
// reserve one upload slot for optimistic unchokes
int unchoke_set_size = m_max_uploads - 1;
m_num_unchoked = 0;
// go through all the peers and unchoke the first ones and choke
// all the other ones.
for (std::vector<peer_connection*>::iterator i = peers.begin()
, end(peers.end()); i != end; ++i)
{
peer_connection* p = *i;
assert(p);
torrent* t = p->associated_torrent().lock().get();
assert(t);
if (unchoke_set_size > 0)
{
if (p->is_choked())
{
if (t->unchoke_peer(*p))
{
--unchoke_set_size;
++m_num_unchoked;
}
}
else
{
--unchoke_set_size;
++m_num_unchoked;
}
assert(p->peer_info_struct());
if (p->peer_info_struct()->optimistically_unchoked)
{
// force a new optimistic unchoke
m_optimistic_unchoke_time_scaler = 0;
p->peer_info_struct()->optimistically_unchoked = false;
}
}
else
{
if (!p->is_choked() && !p->peer_info_struct()->optimistically_unchoked)
t->choke_peer(*p);
}
}
m_optimistic_unchoke_time_scaler--;
if (m_optimistic_unchoke_time_scaler <= 0)
{
m_optimistic_unchoke_time_scaler
= settings().optimistic_unchoke_multiplier;
// find the peer that has been waiting the longest to be optimistically
// unchoked
connection_map::iterator current_optimistic_unchoke = m_connections.end();
connection_map::iterator optimistic_unchoke_candidate = m_connections.end();
ptime last_unchoke = max_time();
for (connection_map::iterator i = m_connections.begin()
, end(m_connections.end()); i != end; ++i)
{
peer_connection* p = i->second.get();
assert(p);
policy::peer* pi = p->peer_info_struct();
if (!pi) continue;
torrent* t = p->associated_torrent().lock().get();
if (!t) continue;
if (pi->optimistically_unchoked)
{
assert(current_optimistic_unchoke == m_connections.end());
current_optimistic_unchoke = i;
}
if (pi->last_optimistically_unchoked < last_unchoke
&& !p->is_connecting()
&& !p->is_disconnecting()
&& p->is_peer_interested()
&& t->free_upload_slots()
&& p->is_choked())
{
last_unchoke = pi->last_optimistically_unchoked;
optimistic_unchoke_candidate = i;
}
}
if (optimistic_unchoke_candidate != m_connections.end()
&& optimistic_unchoke_candidate != current_optimistic_unchoke)
{
if (current_optimistic_unchoke != m_connections.end())
{
torrent* t = current_optimistic_unchoke->second->associated_torrent().lock().get();
assert(t);
t->choke_peer(*current_optimistic_unchoke->second);
current_optimistic_unchoke->second->peer_info_struct()->optimistically_unchoked = false;
}
torrent* t = optimistic_unchoke_candidate->second->associated_torrent().lock().get();
assert(t);
bool ret = t->unchoke_peer(*optimistic_unchoke_candidate->second);
assert(ret);
optimistic_unchoke_candidate->second->peer_info_struct()->optimistically_unchoked = true;
}
if (optimistic_unchoke_candidate != m_connections.end())
++m_num_unchoked;
}
}
// --------------------------------------------------------------
// disconnect peers when we have too many
// --------------------------------------------------------------
--m_disconnect_time_scaler;
if (m_disconnect_time_scaler <= 0)
{
m_disconnect_time_scaler = 60;
// every 60 seconds, disconnect the worst peer
// if we have reached the connection limit
if (num_connections() >= max_connections() && !m_torrents.empty())
{
torrent_map::iterator i = std::max_element(m_torrents.begin(), m_torrents.end()
, bind(&torrent::num_peers, bind(&torrent_map::value_type::second, _1)));
assert(i != m_torrents.end());
i->second->get_policy().disconnect_one_peer();
}
}
}
catch (std::exception& exc)
@ -1832,6 +1986,7 @@ namespace detail
{
assert(limit > 0 || limit == -1);
mutex_t::scoped_lock l(m_mutex);
if (limit <= 0) limit = std::numeric_limits<int>::max();
m_max_uploads = limit;
}
@ -1839,6 +1994,7 @@ namespace detail
{
assert(limit > 0 || limit == -1);
mutex_t::scoped_lock l(m_mutex);
if (limit <= 0) limit = std::numeric_limits<int>::max();
m_max_connections = limit;
}
@ -1846,7 +2002,7 @@ namespace detail
{
assert(limit > 0 || limit == -1);
mutex_t::scoped_lock l(m_mutex);
if (limit <= 0) limit = std::numeric_limits<int>::max();
m_half_open.limit(limit);
}
@ -1854,7 +2010,7 @@ namespace detail
{
assert(bytes_per_second > 0 || bytes_per_second == -1);
mutex_t::scoped_lock l(m_mutex);
if (bytes_per_second == -1) bytes_per_second = bandwidth_limit::inf;
if (bytes_per_second <= 0) bytes_per_second = bandwidth_limit::inf;
m_bandwidth_manager[peer_connection::download_channel]->throttle(bytes_per_second);
}
@ -1862,28 +2018,10 @@ namespace detail
{
assert(bytes_per_second > 0 || bytes_per_second == -1);
mutex_t::scoped_lock l(m_mutex);
if (bytes_per_second == -1) bytes_per_second = bandwidth_limit::inf;
if (bytes_per_second <= 0) bytes_per_second = bandwidth_limit::inf;
m_bandwidth_manager[peer_connection::upload_channel]->throttle(bytes_per_second);
}
int session_impl::num_uploads() const
{
int uploads = 0;
mutex_t::scoped_lock l(m_mutex);
for (torrent_map::const_iterator i = m_torrents.begin()
, end(m_torrents.end()); i != end; i++)
{
uploads += i->second->get_policy().num_uploads();
}
return uploads;
}
int session_impl::num_connections() const
{
mutex_t::scoped_lock l(m_mutex);
return m_connections.size();
}
std::auto_ptr<alert> session_impl::pop_alert()
{
mutex_t::scoped_lock l(m_mutex);
@ -1977,18 +2115,28 @@ namespace detail
#ifndef NDEBUG
void session_impl::check_invariant(const char *place)
{
assert(m_max_connections > 0);
assert(m_max_uploads > 0);
assert(place);
int unchokes = 0;
int num_optimistic = 0;
for (connection_map::iterator i = m_connections.begin();
i != m_connections.end(); ++i)
{
assert(i->second);
boost::shared_ptr<torrent> t = i->second->associated_torrent().lock();
if (!i->second->is_choked()) ++unchokes;
if (i->second->peer_info_struct()
&& i->second->peer_info_struct()->optimistically_unchoked)
++num_optimistic;
if (t)
{
assert(t->get_policy().has_connection(boost::get_pointer(i->second)));
}
}
assert(num_optimistic == 0 || num_optimistic == 1);
assert(m_num_unchoked == unchokes);
}
#endif
@ -2101,7 +2249,7 @@ namespace detail
const std::string& bitmask = (*i)["bitmask"].string();
const int num_bitmask_bytes = std::max(num_blocks_per_piece / 8, 1);
const int num_bitmask_bytes = (std::max)(num_blocks_per_piece / 8, 1);
if ((int)bitmask.size() != num_bitmask_bytes)
{
error = "invalid size of bitmask (" + boost::lexical_cast<std::string>(bitmask.size()) + ")";
@ -2110,7 +2258,7 @@ namespace detail
for (int j = 0; j < num_bitmask_bytes; ++j)
{
unsigned char bits = bitmask[j];
int num_bits = std::min(num_blocks_per_piece - j*8, 8);
int num_bits = (std::min)(num_blocks_per_piece - j*8, 8);
for (int k = 0; k < num_bits; ++k)
{
const int bit = j * 8 + k;

View File

@ -2096,7 +2096,7 @@ namespace libtorrent
, offset += stack_buffer_size)
{
m_storage->write(zeroes, pos, offset
, std::min(piece_size, stack_buffer_size));
, (std::min)(piece_size, stack_buffer_size));
}
written = true;
}

View File

@ -199,22 +199,16 @@ namespace libtorrent
, m_connections_initialized(true)
, m_settings(s)
, m_storage_constructor(sc)
, m_max_uploads(std::numeric_limits<int>::max())
, m_num_uploads(0)
, m_max_connections(std::numeric_limits<int>::max())
{
#ifndef NDEBUG
m_initial_done = 0;
#endif
m_uploads_quota.min = 0;
m_connections_quota.min = 2;
// this will be corrected the next time the main session
// distributes resources, i.e. on average in 0.5 seconds
m_connections_quota.given = 100;
m_uploads_quota.max = std::numeric_limits<int>::max();
m_connections_quota.max = std::numeric_limits<int>::max();
m_policy.reset(new policy(this));
}
torrent::torrent(
session_impl& ses
, aux::checker_impl& checker
@ -268,6 +262,9 @@ namespace libtorrent
, m_connections_initialized(false)
, m_settings(s)
, m_storage_constructor(sc)
, m_max_uploads(std::numeric_limits<int>::max())
, m_num_uploads(0)
, m_max_connections(std::numeric_limits<int>::max())
{
#ifndef NDEBUG
m_initial_done = 0;
@ -277,13 +274,6 @@ namespace libtorrent
if (name) m_name.reset(new std::string(name));
m_uploads_quota.min = 0;
m_connections_quota.min = 2;
// this will be corrected the next time the main session
// distributes resources, i.e. on average in 0.5 seconds
m_connections_quota.given = 100;
m_uploads_quota.max = std::numeric_limits<int>::max();
m_connections_quota.max = std::numeric_limits<int>::max();
if (tracker_url)
{
m_trackers.push_back(announce_entry(tracker_url));
@ -329,6 +319,14 @@ namespace libtorrent
INVARIANT_CHECK;
#if defined(TORRENT_VERBOSE_LOGGING)
for (peer_iterator i = m_connections.begin();
i != m_connections.end(); ++i)
{
(*i->second->m_logger) << "*** DESTRUCTING TORRENT\n";
}
#endif
assert(m_abort);
if (!m_connections.empty())
disconnect_all();
@ -1020,6 +1018,15 @@ namespace libtorrent
m_event = tracker_request::stopped;
// disconnect all peers and close all
// files belonging to the torrents
#if defined(TORRENT_VERBOSE_LOGGING)
for (peer_iterator i = m_connections.begin();
i != m_connections.end(); ++i)
{
(*i->second->m_logger) << "*** ABORTING TORRENT\n";
}
#endif
disconnect_all();
if (m_owning_storage.get()) m_storage->async_release_files();
m_owning_storage = 0;
@ -1383,6 +1390,27 @@ namespace libtorrent
return req;
}
void torrent::choke_peer(peer_connection& c)
{
INVARIANT_CHECK;
assert(!c.is_choked());
assert(m_num_uploads > 0);
c.send_choke();
--m_num_uploads;
}
bool torrent::unchoke_peer(peer_connection& c)
{
INVARIANT_CHECK;
assert(c.is_choked());
if (m_num_uploads >= m_max_uploads) return false;
c.send_unchoke();
++m_num_uploads;
return true;
}
void torrent::cancel_block(piece_block block)
{
for (peer_iterator i = m_connections.begin()
@ -1394,7 +1422,7 @@ namespace libtorrent
void torrent::remove_peer(peer_connection* p) try
{
INVARIANT_CHECK;
// INVARIANT_CHECK;
assert(p != 0);
@ -1433,6 +1461,9 @@ namespace libtorrent
}
}
if (!p->is_choked())
--m_num_uploads;
m_policy->connection_closed(*p);
p->set_peer_info(0);
m_connections.erase(i);
@ -1890,7 +1921,7 @@ namespace libtorrent
void torrent::attach_peer(peer_connection* p)
{
INVARIANT_CHECK;
// INVARIANT_CHECK;
assert(p != 0);
assert(!p->is_local());
@ -1955,7 +1986,7 @@ namespace libtorrent
bool torrent::want_more_peers() const
{
return int(m_connections.size()) < m_connections_quota.given
return int(m_connections.size()) < m_max_connections
&& m_ses.m_half_open.free_slots()
&& !m_paused;
}
@ -2122,7 +2153,7 @@ namespace libtorrent
if ((unsigned)m_currently_trying_tracker >= m_trackers.size())
{
int delay = tracker_retry_delay_min
+ std::min(m_failed_trackers, (int)tracker_failed_max)
+ (std::min)(m_failed_trackers, (int)tracker_failed_max)
* (tracker_retry_delay_max - tracker_retry_delay_min)
/ tracker_failed_max;
@ -2354,6 +2385,7 @@ namespace libtorrent
// size_type download = m_stat.total_payload_download();
// size_type done = boost::get<0>(bytes_done());
// assert(download >= done - m_initial_done);
int num_uploads = 0;
std::map<piece_block, int> num_requests;
for (const_peer_iterator i = begin(); i != end(); ++i)
{
@ -2364,10 +2396,12 @@ namespace libtorrent
for (std::deque<piece_block>::const_iterator i = p.download_queue().begin()
, end(p.download_queue().end()); i != end; ++i)
++num_requests[*i];
if (!p.is_choked()) ++num_uploads;
torrent* associated_torrent = p.associated_torrent().lock().get();
if (associated_torrent != this)
assert(false);
}
assert(num_uploads == m_num_uploads);
if (has_picker())
{
@ -2425,15 +2459,15 @@ namespace libtorrent
void torrent::set_max_uploads(int limit)
{
assert(limit >= -1);
if (limit == -1) limit = std::numeric_limits<int>::max();
m_uploads_quota.max = std::max(m_uploads_quota.min, limit);
if (limit <= 0) limit = std::numeric_limits<int>::max();
m_max_uploads = limit;
}
void torrent::set_max_connections(int limit)
{
assert(limit >= -1);
if (limit == -1) limit = std::numeric_limits<int>::max();
m_connections_quota.max = std::max(m_connections_quota.min, limit);
if (limit <= 0) limit = std::numeric_limits<int>::max();
m_max_connections = limit;
}
void torrent::set_peer_upload_limit(tcp::endpoint ip, int limit)
@ -2455,7 +2489,7 @@ namespace libtorrent
void torrent::set_upload_limit(int limit)
{
assert(limit >= -1);
if (limit == -1) limit = std::numeric_limits<int>::max();
if (limit <= 0) limit = std::numeric_limits<int>::max();
if (limit < num_peers() * 10) limit = num_peers() * 10;
m_bandwidth_limit[peer_connection::upload_channel].throttle(limit);
}
@ -2470,7 +2504,7 @@ namespace libtorrent
void torrent::set_download_limit(int limit)
{
assert(limit >= -1);
if (limit == -1) limit = std::numeric_limits<int>::max();
if (limit <= 0) limit = std::numeric_limits<int>::max();
if (limit < num_peers() * 10) limit = num_peers() * 10;
m_bandwidth_limit[peer_connection::download_channel].throttle(limit);
}
@ -2496,6 +2530,14 @@ namespace libtorrent
}
#endif
#if defined(TORRENT_VERBOSE_LOGGING)
for (peer_iterator i = m_connections.begin();
i != m_connections.end(); ++i)
{
(*i->second->m_logger) << "*** PAUSING TORRENT\n";
}
#endif
disconnect_all();
m_paused = true;
// tell the tracker that we stopped
@ -2528,10 +2570,6 @@ namespace libtorrent
#endif
m_paused = false;
m_uploads_quota.min = 0;
m_connections_quota.min = 2;
m_uploads_quota.max = std::numeric_limits<int>::max();
m_connections_quota.max = std::numeric_limits<int>::max();
// tell the tracker that we're back
m_event = tracker_request::started;
@ -2545,10 +2583,6 @@ namespace libtorrent
{
INVARIANT_CHECK;
m_connections_quota.used = (int)m_connections.size();
m_uploads_quota.used = m_policy->num_uploads();
m_uploads_quota.max = (int)m_connections.size();
#ifndef TORRENT_DISABLE_EXTENSIONS
for (extension_list_t::iterator i = m_extensions.begin()
, end(m_extensions.end()); i != end; ++i)
@ -2561,10 +2595,6 @@ namespace libtorrent
{
// let the stats fade out to 0
m_stat.second_tick(tick_interval);
m_connections_quota.min = 0;
m_connections_quota.max = 0;
m_uploads_quota.min = 0;
m_uploads_quota.max = 0;
return;
}
@ -2623,6 +2653,13 @@ namespace libtorrent
}
accumulator += m_stat;
m_stat.second_tick(tick_interval);
m_time_scaler--;
if (m_time_scaler <= 0)
{
m_time_scaler = 10;
m_policy->pulse();
}
}
bool torrent::try_connect_peer()
@ -2631,18 +2668,6 @@ namespace libtorrent
return m_policy->connect_one_peer();
}
void torrent::distribute_resources(float tick_interval)
{
INVARIANT_CHECK;
m_time_scaler--;
if (m_time_scaler <= 0)
{
m_time_scaler = settings().unchoke_interval;
m_policy->pulse();
}
}
void torrent::async_verify_piece(int piece_index, boost::function<void(bool)> const& f)
{
INVARIANT_CHECK;
@ -2696,7 +2721,7 @@ namespace libtorrent
size_type done = 0;
while (size > 0)
{
size_type bytes_step = std::min(m_torrent_file.piece_size(ret.piece)
size_type bytes_step = (std::min)(m_torrent_file.piece_size(ret.piece)
- ret.start, size);
if (m_have_pieces[ret.piece]) done += bytes_step;
++ret.piece;
@ -2764,10 +2789,10 @@ namespace libtorrent
= m_trackers[m_last_working_tracker].url;
}
st.num_uploads = m_uploads_quota.used;
st.uploads_limit = m_uploads_quota.given;
st.num_connections = m_connections_quota.used;
st.connections_limit = m_connections_quota.given;
st.num_uploads = m_num_uploads;
st.uploads_limit = m_max_uploads;
st.num_connections = int(m_connections.size());
st.connections_limit = m_max_connections;
// if we don't have any metadata, stop here
if (!valid_metadata())
@ -2780,7 +2805,7 @@ namespace libtorrent
// TODO: add a progress member to the torrent that will be used in this case
// and that may be set by a plugin
// if (m_metadata_size == 0) st.progress = 0.f;
// else st.progress = std::min(1.f, m_metadata_progress / (float)m_metadata_size);
// else st.progress = (std::min)(1.f, m_metadata_progress / (float)m_metadata_size);
st.progress = 0.f;
st.block_size = 0;

View File

@ -453,14 +453,30 @@ namespace libtorrent
, m_chk, m_info_hash, bind(&torrent::trackers, _1));
}
void torrent_handle::add_url_seed(std::string const& url)
void torrent_handle::add_url_seed(std::string const& url) const
{
INVARIANT_CHECK;
return call_member<void>(m_ses, m_chk, m_info_hash
call_member<void>(m_ses, m_chk, m_info_hash
, bind(&torrent::add_url_seed, _1, url));
}
void torrent_handle::remove_url_seed(std::string const& url) const
{
INVARIANT_CHECK;
call_member<void>(m_ses, m_chk, m_info_hash
, bind(&torrent::remove_url_seed, _1, url));
}
std::set<std::string> torrent_handle::url_seeds() const
{
INVARIANT_CHECK;
return call_member<std::set<std::string> >(m_ses, m_chk, m_info_hash
, bind(&torrent::url_seeds, _1));
}
void torrent_handle::replace_trackers(
std::vector<announce_entry> const& urls) const
{
@ -561,12 +577,12 @@ namespace libtorrent
std::string bitmask;
const int num_bitmask_bytes
= std::max(num_blocks_per_piece / 8, 1);
= (std::max)(num_blocks_per_piece / 8, 1);
for (int j = 0; j < num_bitmask_bytes; ++j)
{
unsigned char v = 0;
int bits = std::min(num_blocks_per_piece - j*8, 8);
int bits = (std::min)(num_blocks_per_piece - j*8, 8);
for (int k = 0; k < bits; ++k)
v |= (i->info[j*8+k].state == piece_picker::block_info::state_finished)
? (1 << k) : 0;

View File

@ -256,7 +256,7 @@ namespace libtorrent
{
// available input is 1,2 or 3 bytes
// since we read 3 bytes at a time at most
int available_input = std::min(3, (int)std::distance(i, s.end()));
int available_input = (std::min)(3, (int)std::distance(i, s.end()));
// clear input buffer
std::fill(inbuf, inbuf+3, 0);
@ -305,7 +305,7 @@ namespace libtorrent
m_start_time = time_now();
m_read_time = time_now();
m_timeout.expires_at(std::min(
m_timeout.expires_at((std::min)(
m_read_time + seconds(m_read_timeout)
, m_start_time + seconds(m_completion_timeout)));
m_timeout.async_wait(m_strand.wrap(bind(
@ -341,7 +341,7 @@ namespace libtorrent
return;
}
m_timeout.expires_at(std::min(
m_timeout.expires_at((std::min)(
m_read_time + seconds(m_read_timeout)
, m_start_time + seconds(m_completion_timeout)));
m_timeout.async_wait(m_strand.wrap(

View File

@ -180,7 +180,7 @@ namespace libtorrent
const int block_size = t->block_size();
while (size > 0)
{
int request_size = std::min(block_size, size);
int request_size = (std::min)(block_size, size);
peer_request pr = {r.piece, r.start + r.length - size
, request_size};
m_requests.push_back(pr);
@ -510,7 +510,7 @@ namespace libtorrent
// m_piece as buffer.
int piece_size = int(m_piece.size());
int copy_size = std::min(std::min(front_request.length - piece_size
int copy_size = (std::min)(std::min(front_request.length - piece_size
, recv_buffer.left()), int(range_end - range_start - m_received_body));
m_piece.resize(piece_size + copy_size);
assert(copy_size > 0);
@ -568,7 +568,7 @@ namespace libtorrent
&& (m_received_body + recv_buffer.left() >= range_end - range_start))
{
int piece_size = int(m_piece.size());
int copy_size = std::min(std::min(m_requests.front().length - piece_size
int copy_size = (std::min)(std::min(m_requests.front().length - piece_size
, recv_buffer.left()), int(range_end - range_start - m_received_body));
assert(copy_size >= 0);
if (copy_size > 0)