removed the session mutex for improved performance

This commit is contained in:
Arvid Norberg 2010-07-14 04:16:38 +00:00
parent 3310198dae
commit 4e576f93fd
21 changed files with 753 additions and 566 deletions

View File

@ -1,3 +1,4 @@
* removed the session mutex for improved performance
* added upload and download activity timer stats for torrents
* made the reuse-address flag configurable on the listen socket
* moved UDP trackers over to use a single socket

View File

@ -480,23 +480,26 @@ class session: public boost::noncopyable
int num_uploads() const;
int num_connections() const;
bool load_asnum_db(char const* file);
bool load_asnum_db(wchar_t const* file);
bool load_country_db(char const* file);
bool load_country_db(wchar_t const* file);
void load_asnum_db(char const* file);
void load_asnum_db(wchar_t const* file);
void load_country_db(char const* file);
void load_country_db(wchar_t const* file);
int as_for_ip(address const& adr);
void set_ip_filter(ip_filter const& f);
ip_filter const& get_ip_filter() const;
ip_filter get_ip_filter() const;
session_status status() const;
cache_status get_cache_status() const;
bool is_listening() const;
unsigned short listen_port() const;
enum { listen_reuse_address = 1 };
bool listen_on(
std::pair<int, int> const& port_range
, char const* interface = 0);
, char const* interface = 0
, int flags = 0);
std::auto_ptr<alert> pop_alert();
alert const* wait_for_alert(time_duration max_wait);
@ -706,12 +709,9 @@ There are 3 different modes:</p>
<dd>All pieces will be written to the place where they belong and sparse files
will be used. This is the recommended, and default mode.</dd>
<dt>storage_mode_allocate</dt>
<dd>Same as <tt class="docutils literal"><span class="pre">storage_mode_sparse</span></tt> except that files will be ftruncated on
startup (SetEndOfFile() on windows). For filesystem that supports sparse
files, this is in all practical aspects identical to sparse mode. For
filesystems that don't, it will allocate the data for the files. The mac
filesystem HFS+ doesn't support sparse files, it will allocate the files
with zeroes.</dd>
<dd>All pieces will be written to their final position, all files will be
allocated in full when the torrent is first started. This is done with
<tt class="docutils literal"><span class="pre">fallocate()</span></tt> and similar calls. This mode minimizes fragmentation.</dd>
<dt>storage_mode_compact</dt>
<dd>The storage will grow as more pieces are downloaded, and pieces
are rearranged to finally be in their correct places once the entire torrent has been
@ -892,10 +892,10 @@ to 8 on windows.</p>
<h2>load_asnum_db() load_country_db() int as_for_ip()</h2>
<blockquote>
<pre class="literal-block">
bool load_asnum_db(char const* file);
bool load_asnum_db(wchar_t const* file);
bool load_country_db(char const* file);
bool load_country_db(wchar_t const* file);
void load_asnum_db(char const* file);
void load_asnum_db(wchar_t const* file);
void load_country_db(char const* file);
void load_country_db(wchar_t const* file);
int as_for_ip(address const&amp; adr);
</pre>
</blockquote>
@ -925,7 +925,7 @@ generated.</p>
<blockquote>
<dl class="docutils">
<dt>::</dt>
<dd>ip_filter const&amp; get_ip_filter() const;</dd>
<dd>ip_filter get_ip_filter() const;</dd>
</dl>
</blockquote>
<p>Returns the ip_filter currently in the session. See <a class="reference internal" href="#ip-filter">ip_filter</a>.</p>
@ -1130,7 +1130,8 @@ bool is_listening() const;
unsigned short listen_port() const;
bool listen_on(
std::pair&lt;int, int&gt; const&amp; port_range
, char const* interface = 0);
, char const* interface = 0
, int flags = 0);
</pre>
</blockquote>
<p><tt class="docutils literal"><span class="pre">is_listening()</span></tt> will tell you whether or not the session has successfully
@ -1156,6 +1157,10 @@ want to listen on. If you don't specify an interface, libtorrent may attempt to
listen on multiple interfaces (typically 0.0.0.0 and ::). This means that if your
IPv6 interface doesn't work, you may still see a <a class="reference internal" href="#listen-failed-alert">listen_failed_alert</a>, even though
the IPv4 port succeeded.</p>
<p>The <tt class="docutils literal"><span class="pre">flags</span></tt> parameter can either be 0 or <tt class="docutils literal"><span class="pre">session::listen_reuse_address</span></tt>, which
will set the reuse address socket option on the listen socket(s). By default, the
listen socket does not use reuse address. If you're running a service that needs
to run on a specific port no matter if it's in use, set this flag.</p>
<p>If you're also starting the DHT, it is a good idea to do that after you've called
<tt class="docutils literal"><span class="pre">listen_on()</span></tt>, since the default listen port for the DHT is the same as the tcp
listen socket. If you start the DHT first, it will assume the tcp port is free and
@ -1298,10 +1303,10 @@ it only has any effect if the proxy supports UDP.</p>
<h2>peer_proxy() web_seed_proxy() tracker_proxy() dht_proxy()</h2>
<blockquote>
<pre class="literal-block">
proxy_settings const&amp; peer_proxy() const;
proxy_settings const&amp; web_seed_proxy() const;
proxy_settings const&amp; tracker_proxy() const;
proxy_settings const&amp; dht_proxy() const;
proxy_settings peer_proxy() const;
proxy_settings web_seed_proxy() const;
proxy_settings tracker_proxy() const;
proxy_settings dht_proxy() const;
</pre>
</blockquote>
<p>These functions returns references to their respective current settings.</p>

View File

@ -193,14 +193,14 @@ The ``session`` class has the following synopsis::
int num_uploads() const;
int num_connections() const;
bool load_asnum_db(char const* file);
bool load_asnum_db(wchar_t const* file);
bool load_country_db(char const* file);
bool load_country_db(wchar_t const* file);
void load_asnum_db(char const* file);
void load_asnum_db(wchar_t const* file);
void load_country_db(char const* file);
void load_country_db(wchar_t const* file);
int as_for_ip(address const& adr);
void set_ip_filter(ip_filter const& f);
ip_filter const& get_ip_filter() const;
ip_filter get_ip_filter() const;
session_status status() const;
cache_status get_cache_status() const;
@ -647,10 +647,10 @@ load_asnum_db() load_country_db() int as_for_ip()
::
bool load_asnum_db(char const* file);
bool load_asnum_db(wchar_t const* file);
bool load_country_db(char const* file);
bool load_country_db(wchar_t const* file);
void load_asnum_db(char const* file);
void load_asnum_db(wchar_t const* file);
void load_country_db(char const* file);
void load_country_db(wchar_t const* file);
int as_for_ip(address const& adr);
These functions are not available if ``TORRENT_DISABLE_GEO_IP`` is defined. They
@ -684,7 +684,7 @@ get_ip_filter()
---------------
::
ip_filter const& get_ip_filter() const;
ip_filter get_ip_filter() const;
Returns the ip_filter currently in the session. See ip_filter_.
@ -1114,10 +1114,10 @@ peer_proxy() web_seed_proxy() tracker_proxy() dht_proxy()
::
proxy_settings const& peer_proxy() const;
proxy_settings const& web_seed_proxy() const;
proxy_settings const& tracker_proxy() const;
proxy_settings const& dht_proxy() const;
proxy_settings peer_proxy() const;
proxy_settings web_seed_proxy() const;
proxy_settings tracker_proxy() const;
proxy_settings dht_proxy() const;
These functions returns references to their respective current settings.

View File

@ -126,6 +126,8 @@ a list of entries.</p>
<li>torrent_handle::get_download_queue</li>
<li>torrent_handle::piece_availability</li>
</ul>
<p><tt class="docutils literal"><span class="pre">create_torrent::add_node()</span></tt> takes two arguments, one string and one integer,
instead of a pair. The string is the address and the integer is the port.</p>
<p>For an example python program, see <tt class="docutils literal"><span class="pre">client.py</span></tt> in the <tt class="docutils literal"><span class="pre">bindings/python</span></tt>
directory.</p>
<p>A very simple example usage of the module would be something like this:</p>

View File

@ -34,7 +34,7 @@ POSSIBILITY OF SUCH DAMAGE.
#define TORRENT_ALERT_HPP_INCLUDED
#include <memory>
#include <queue>
#include <deque>
#include <string>
#ifdef _MSC_VER
@ -145,15 +145,15 @@ namespace libtorrent {
size_t alert_queue_size_limit() const { return m_queue_size_limit; }
size_t set_alert_queue_size_limit(size_t queue_size_limit_);
void set_dispatch_function(boost::function<void(alert const&)> const&);
void set_dispatch_function(boost::function<void(std::auto_ptr<alert>)> const&);
private:
std::queue<alert*> m_alerts;
std::deque<alert*> m_alerts;
mutable mutex m_mutex;
condition m_condition;
int m_alert_mask;
size_t m_queue_size_limit;
boost::function<void(alert const&)> m_dispatch;
boost::function<void(std::auto_ptr<alert>)> m_dispatch;
io_service& m_ios;
};

View File

@ -177,9 +177,18 @@ namespace libtorrent
void incoming_connection(boost::shared_ptr<socket_type> const& s);
// must be locked to access the data
// in this struct
mutable mutex m_mutex;
#ifdef TORRENT_DEBUG
#if defined BOOST_HAS_PTHREADS
pthread_t m_network_thread;
#endif
bool is_network_thread() const
{
#if defined BOOST_HAS_PTHREADS
return m_network_thread == pthread_self();
#endif
return true;
}
#endif
boost::weak_ptr<torrent> find_torrent(const sha1_hash& info_hash);
peer_id const& get_peer_id() const { return m_peer_id; }
@ -190,7 +199,7 @@ namespace libtorrent
session_settings const& settings() const { return m_settings; }
#ifndef TORRENT_DISABLE_DHT
void add_dht_node(std::pair<std::string, int> const& node);
void add_dht_node_name(std::pair<std::string, int> const& node);
void add_dht_node(udp::endpoint n);
void add_dht_router(std::pair<std::string, int> const& node);
void set_dht_settings(dht_settings const& s);
@ -200,7 +209,7 @@ namespace libtorrent
void start_dht(entry const& startup_state);
#ifndef TORRENT_NO_DEPRECATE
entry dht_state(mutex::scoped_lock& l) const;
entry dht_state() const;
#endif
void maybe_update_udp_mapping(int nat, int local_port, int external_port);
@ -252,7 +261,7 @@ namespace libtorrent
void set_alert_mask(int m);
size_t set_alert_queue_size_limit(size_t queue_size_limit_);
std::auto_ptr<alert> pop_alert();
void set_alert_dispatch(boost::function<void(alert const&)> const&);
void set_alert_dispatch(boost::function<void(std::auto_ptr<alert>)> const&);
alert const* wait_for_alert(time_duration max_wait);
@ -292,8 +301,8 @@ namespace libtorrent
void announce_lsd(sha1_hash const& ih);
void save_state(entry& e, boost::uint32_t flags, mutex::scoped_lock& l) const;
void load_state(lazy_entry const& e);
void save_state(entry* e, boost::uint32_t flags) const;
void load_state(lazy_entry const* e);
void set_peer_proxy(proxy_settings const& s)
{
@ -323,6 +332,7 @@ namespace libtorrent
}
proxy_settings const& dht_proxy() const
{ return m_dht_proxy; }
bool is_dht_running() const { return m_dht; }
#endif
#if TORRENT_USE_I2P
@ -343,22 +353,22 @@ namespace libtorrent
std::string as_name_for_ip(address const& a);
int as_for_ip(address const& a);
std::pair<const int, int>* lookup_as(int as);
bool load_asnum_db(char const* file);
void load_asnum_db(std::string file);
bool has_asnum_db() const { return m_asnum_db; }
bool load_country_db(char const* file);
void load_country_db(std::string file);
bool has_country_db() const { return m_country_db; }
char const* country_for_ip(address const& a);
#if TORRENT_USE_WSTRING
bool load_asnum_db(wchar_t const* file);
bool load_country_db(wchar_t const* file);
void load_asnum_db(std::wstring file);
void load_country_db(std::wstring file);
#endif // TORRENT_USE_WSTRING
#endif // TORRENT_DISABLE_GEO_IP
void start_lsd();
void start_natpmp(natpmp* n);
void start_upnp(upnp* u);
natpmp* start_natpmp();
upnp* start_upnp();
void stop_lsd();
void stop_natpmp();
@ -387,11 +397,14 @@ namespace libtorrent
void set_external_address(address const& ip);
address const& external_address() const { return m_external_address; }
// used when posting synchronous function
// calls to session_impl and torrent objects
mutable libtorrent::mutex mut;
mutable libtorrent::condition cond;
// private:
void update_disk_thread_settings();
void on_dht_state_callback(condition& c
, entry& e, bool& done) const;
void on_lsd_peer(tcp::endpoint peer, sha1_hash const& ih);
void setup_socket_buffers(socket_type& s);
@ -794,6 +807,7 @@ namespace libtorrent
std::string m_logpath;
public:
boost::shared_ptr<logger> m_logger;
private:
#endif

View File

@ -289,6 +289,7 @@ namespace libtorrent
, int block_size = 16 * 1024);
~disk_io_thread();
void abort();
void join();
// aborts read operations

View File

@ -642,8 +642,6 @@ namespace libtorrent
, std::size_t bytes_transferred);
void on_receive_data(error_code const& error
, std::size_t bytes_transferred);
void on_receive_data_nolock(error_code const& error
, std::size_t bytes_transferred);
// this is the limit on the number of outstanding requests
// we have to this peer. This is initialized to the settings

View File

@ -275,7 +275,7 @@ namespace libtorrent
#ifndef TORRENT_DISABLE_ENCRYPTION
void set_pe_settings(pe_settings const& settings);
pe_settings const& get_pe_settings() const;
pe_settings get_pe_settings() const;
#endif
#ifndef TORRENT_DISABLE_EXTENSIONS
@ -284,11 +284,11 @@ namespace libtorrent
#ifndef TORRENT_DISABLE_GEO_IP
int as_for_ip(address const& addr);
bool load_asnum_db(char const* file);
bool load_country_db(char const* file);
void load_asnum_db(char const* file);
void load_country_db(char const* file);
#if TORRENT_USE_WSTRING
bool load_country_db(wchar_t const* file);
bool load_asnum_db(wchar_t const* file);
void load_country_db(wchar_t const* file);
void load_asnum_db(wchar_t const* file);
#endif
#endif
@ -302,7 +302,7 @@ namespace libtorrent
#endif
void set_ip_filter(ip_filter const& f);
ip_filter const& get_ip_filter() const;
ip_filter get_ip_filter() const;
void set_port_filter(port_filter const& f);
void set_peer_id(peer_id const& pid);
@ -354,24 +354,24 @@ namespace libtorrent
void remove_torrent(const torrent_handle& h, int options = none);
void set_settings(session_settings const& s);
session_settings const& settings();
session_settings settings();
void set_peer_proxy(proxy_settings const& s);
void set_web_seed_proxy(proxy_settings const& s);
void set_tracker_proxy(proxy_settings const& s);
proxy_settings const& peer_proxy() const;
proxy_settings const& web_seed_proxy() const;
proxy_settings const& tracker_proxy() const;
proxy_settings peer_proxy() const;
proxy_settings web_seed_proxy() const;
proxy_settings tracker_proxy() const;
#ifndef TORRENT_DISABLE_DHT
void set_dht_proxy(proxy_settings const& s);
proxy_settings const& dht_proxy() const;
proxy_settings dht_proxy() const;
#endif
#if TORRENT_USE_I2P
void set_i2p_proxy(proxy_settings const& s);
proxy_settings const& i2p_proxy() const;
proxy_settings i2p_proxy() const;
#endif
int upload_rate_limit() const;
@ -400,7 +400,7 @@ namespace libtorrent
size_t set_alert_queue_size_limit(size_t queue_size_limit_);
alert const* wait_for_alert(time_duration max_wait);
void set_alert_dispatch(boost::function<void(alert const&)> const& fun);
void set_alert_dispatch(boost::function<void(std::auto_ptr<alert>)> const& fun);
connection_queue& get_connection_queue();

View File

@ -172,8 +172,7 @@ namespace libtorrent
void on_resume_data_checked(int ret, disk_io_job const& j);
void on_force_recheck(int ret, disk_io_job const& j);
void on_piece_checked(int ret, disk_io_job const& j);
void files_checked_lock();
void files_checked(mutex::scoped_lock const&);
void files_checked();
void start_checking();
void start_announcing();
@ -228,6 +227,8 @@ namespace libtorrent
bool is_sequential_download() const
{ return m_sequential_download; }
void queue_up();
void queue_down();
void set_queue_position(int p);
int queue_position() const { return m_sequence_number; }
@ -307,7 +308,7 @@ namespace libtorrent
void file_progress(std::vector<size_type>& fp, int flags = 0) const;
void use_interface(const char* net_interface);
void use_interface(std::string net_interface);
tcp::endpoint get_interface() const { return m_net_interface; }
void connect_to_url_seed(std::list<web_seed_entry>::iterator url);
@ -408,6 +409,7 @@ namespace libtorrent
bool want_more_peers() const;
bool try_connect_peer();
void give_connect_points(int points);
void add_peer(tcp::endpoint const& adr, int source);
// the number of peers that belong to this torrent
int num_peers() const { return (int)m_connections.size(); }

View File

@ -336,7 +336,7 @@ namespace libtorrent {
while (!m_alerts.empty())
{
delete m_alerts.front();
m_alerts.pop();
m_alerts.pop_front();
}
}
@ -367,21 +367,20 @@ namespace libtorrent {
return m_alerts.front();
}
void alert_manager::set_dispatch_function(boost::function<void(alert const&)> const& fun)
void alert_manager::set_dispatch_function(boost::function<void(std::auto_ptr<alert>)> const& fun)
{
mutex::scoped_lock lock(m_mutex);
m_dispatch = fun;
std::queue<alert*> alerts = m_alerts;
while (!m_alerts.empty()) m_alerts.pop();
std::deque<alert*> alerts;
m_alerts.swap(alerts);
lock.unlock();
while (!alerts.empty())
{
m_dispatch(*alerts.front());
delete alerts.front();
alerts.pop();
m_dispatch(std::auto_ptr<alert>(alerts.front()));
alerts.pop_front();
}
}
@ -399,12 +398,12 @@ namespace libtorrent {
if (m_dispatch)
{
TORRENT_ASSERT(m_alerts.empty());
m_ios.post(boost::bind(&dispatch_alert, m_dispatch, alert_.clone().release()));
m_dispatch(std::auto_ptr<alert>(alert_.clone()));
return;
}
if (m_alerts.size() >= m_queue_size_limit) return;
m_alerts.push(alert_.clone().release());
m_alerts.push_back(alert_.clone().release());
m_condition.signal(lock);
m_condition.clear(lock);
}
@ -413,10 +412,11 @@ namespace libtorrent {
{
mutex::scoped_lock lock(m_mutex);
TORRENT_ASSERT(!m_alerts.empty());
if (m_alerts.empty())
return std::auto_ptr<alert>(0);
alert* result = m_alerts.front();
m_alerts.pop();
m_alerts.pop_front();
return std::auto_ptr<alert>(result);
}

View File

@ -368,7 +368,7 @@ namespace libtorrent
TORRENT_ASSERT(m_abort == true);
}
void disk_io_thread::join()
void disk_io_thread::abort()
{
mutex::scoped_lock l(m_queue_mutex);
disk_io_job j;
@ -376,10 +376,12 @@ namespace libtorrent
j.action = disk_io_job::abort_thread;
m_jobs.insert(m_jobs.begin(), j);
m_signal.signal(l);
l.unlock();
}
void disk_io_thread::join()
{
m_disk_io_thread.join();
l.lock();
mutex::scoped_lock l(m_queue_mutex);
TORRENT_ASSERT(m_abort == true);
m_jobs.clear();
}

View File

@ -2392,7 +2392,7 @@ namespace libtorrent
void peer_connection::on_disk_write_complete(int ret, disk_io_job const& j
, peer_request p, boost::shared_ptr<torrent> t)
{
mutex::scoped_lock l(m_ses.m_mutex);
TORRENT_ASSERT(m_ses.is_network_thread());
INVARIANT_CHECK;
@ -3168,7 +3168,7 @@ namespace libtorrent
void peer_connection::on_timeout()
{
mutex::scoped_lock l(m_ses.m_mutex);
TORRENT_ASSERT(m_ses.is_network_thread());
TORRENT_ASSERT(m_connecting);
#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING || defined TORRENT_ERROR_LOGGING
@ -4061,7 +4061,7 @@ namespace libtorrent
void peer_connection::on_disk_read_complete(int ret, disk_io_job const& j, peer_request r)
{
mutex::scoped_lock l(m_ses.m_mutex);
TORRENT_ASSERT(m_ses.is_network_thread());
m_reading_bytes -= r.length;
@ -4379,7 +4379,7 @@ namespace libtorrent
else
{
m_channel_state[download_channel] = peer_info::bw_network;
on_receive_data_nolock(ec, bytes_transferred);
on_receive_data(ec, bytes_transferred);
}
}
@ -4636,14 +4636,7 @@ namespace libtorrent
void peer_connection::on_receive_data(const error_code& error
, std::size_t bytes_transferred)
{
mutex::scoped_lock l(m_ses.m_mutex);
on_receive_data_nolock(error, bytes_transferred);
}
void peer_connection::on_receive_data_nolock(const error_code& error
, std::size_t bytes_transferred)
{
TORRENT_ASSERT(m_ses.is_network_thread());
INVARIANT_CHECK;
// keep ourselves alive in until this function exits in
@ -4777,7 +4770,7 @@ namespace libtorrent
void peer_connection::on_connect(int ticket)
{
mutex::scoped_lock l(m_ses.m_mutex);
TORRENT_ASSERT(m_ses.is_network_thread());
#ifdef TORRENT_DEBUG
// in case we disconnect here, we need to
// keep the connection alive until the
@ -4869,7 +4862,7 @@ namespace libtorrent
{
ptime completed = time_now();
mutex::scoped_lock l(m_ses.m_mutex);
TORRENT_ASSERT(m_ses.is_network_thread());
INVARIANT_CHECK;
@ -4932,7 +4925,7 @@ namespace libtorrent
void peer_connection::on_send_data(error_code const& error
, std::size_t bytes_transferred)
{
mutex::scoped_lock l(m_ses.m_mutex);
TORRENT_ASSERT(m_ses.is_network_thread());
INVARIANT_CHECK;

View File

@ -229,6 +229,87 @@ namespace libtorrent
return set;
}
// wrapper around a function that's executed in the network thread
// ans synchronized in the client thread
template <class R>
void fun_ret(R* ret, bool* done, condition* e, mutex* m, boost::function<R(void)> f)
{
*ret = f();
mutex::scoped_lock l(*m);
*done = true;
e->signal(l);
}
void fun_wrap(bool* done, condition* e, mutex* m, boost::function<void(void)> f)
{
f();
mutex::scoped_lock l(*m);
*done = true;
e->signal(l);
}
#define TORRENT_ASYNC_CALL(x) \
m_impl->m_io_service.post(boost::bind(&session_impl:: x, m_impl.get()))
#define TORRENT_ASYNC_CALL1(x, a1) \
m_impl->m_io_service.post(boost::bind(&session_impl:: x, m_impl.get(), a1))
#define TORRENT_ASYNC_CALL2(x, a1, a2) \
m_impl->m_io_service.post(boost::bind(&session_impl:: x, m_impl.get(), a1, a2))
#define TORRENT_SYNC_CALL(x) \
bool done = false; \
mutex::scoped_lock l(m_impl->mut); \
m_impl->cond.clear(l); \
m_impl->m_io_service.post(boost::bind(&fun_wrap, &done, &m_impl->cond, &m_impl->mut, boost::function<void(void)>(boost::bind(&session_impl:: x, m_impl.get())))); \
do { m_impl->cond.wait(l); } while(!done)
#define TORRENT_SYNC_CALL1(x, a1) \
bool done = false; \
mutex::scoped_lock l(m_impl->mut); \
m_impl->cond.clear(l); \
m_impl->m_io_service.post(boost::bind(&fun_wrap, &done, &m_impl->cond, &m_impl->mut, boost::function<void(void)>(boost::bind(&session_impl:: x, m_impl.get(), a1)))); \
do { m_impl->cond.wait(l); } while(!done)
#define TORRENT_SYNC_CALL2(x, a1, a2) \
bool done = false; \
mutex::scoped_lock l(m_impl->mut); \
m_impl->cond.clear(l); \
m_impl->m_io_service.post(boost::bind(&fun_wrap, &done, &m_impl->cond, &m_impl->mut, boost::function<void(void)>(boost::bind(&session_impl:: x, m_impl.get(), a1, a2)))); \
do { m_impl->cond.wait(l); } while(!done)
#define TORRENT_SYNC_CALL_RET(type, x) \
bool done = false; \
type r; \
mutex::scoped_lock l(m_impl->mut); \
m_impl->cond.clear(l); \
m_impl->m_io_service.post(boost::bind(&fun_ret<type>, &r, &done, &m_impl->cond, &m_impl->mut, boost::function<type(void)>(boost::bind(&session_impl:: x, m_impl.get())))); \
do { m_impl->cond.wait(l); } while(!done)
#define TORRENT_SYNC_CALL_RET1(type, x, a1) \
bool done = false; \
type r; \
mutex::scoped_lock l(m_impl->mut); \
m_impl->cond.clear(l); \
m_impl->m_io_service.post(boost::bind(&fun_ret<type>, &r, &done, &m_impl->cond, &m_impl->mut, boost::function<type(void)>(boost::bind(&session_impl:: x, m_impl.get(), a1)))); \
do { m_impl->cond.wait(l); } while(!done)
#define TORRENT_SYNC_CALL_RET2(type, x, a1, a2) \
bool done = false; \
type r; \
mutex::scoped_lock l(m_impl->mut); \
m_impl->cond.clear(l); \
m_impl->m_io_service.post(boost::bind(&fun_ret<type>, &r, &done, &m_impl->cond, &m_impl->mut, boost::function<type(void)>(boost::bind(&session_impl:: x, m_impl.get(), a1, a2)))); \
do { m_impl->cond.wait(l); } while(!done)
#define TORRENT_SYNC_CALL_RET3(type, x, a1, a2, a3) \
bool done = false; \
type r; \
mutex::scoped_lock l(m_impl->mut); \
m_impl->cond.clear(l); \
m_impl->m_io_service.post(boost::bind(&fun_ret<type>, &r, &done, &m_impl->cond, &m_impl->mut, boost::function<type(void)>(boost::bind(&session_impl:: x, m_impl.get(), a1, a2, a3)))); \
do { m_impl->cond.wait(l); } while(!done)
session::session(
fingerprint const& id
, std::pair<int, int> listen_port_range
@ -310,7 +391,6 @@ namespace libtorrent
session::~session()
{
mutex::scoped_lock l(m_impl->m_mutex);
#ifdef TORRENT_MEMDEBUG
stop_malloc_debug();
#endif
@ -319,59 +399,55 @@ namespace libtorrent
// abort the session and let the destructor
// of the proxy to syncronize
if (!m_impl.unique())
m_impl->abort();
{
TORRENT_ASYNC_CALL(abort);
}
}
void session::save_state(entry& e, boost::uint32_t flags) const
{
mutex::scoped_lock l(m_impl->m_mutex);
m_impl->save_state(e, flags, l);
TORRENT_SYNC_CALL2(save_state, &e, flags);
}
void session::load_state(lazy_entry const& e)
{
mutex::scoped_lock l(m_impl->m_mutex);
m_impl->load_state(e);
// this needs to be synchronized since the lifespan
// of e is tied to the caller
TORRENT_SYNC_CALL1(load_state, &e);
}
#ifndef TORRENT_DISABLE_EXTENSIONS
void session::add_extension(boost::function<boost::shared_ptr<torrent_plugin>(torrent*, void*)> ext)
{
mutex::scoped_lock l(m_impl->m_mutex);
m_impl->add_extension(ext);
TORRENT_ASYNC_CALL1(add_extension, ext);
}
#endif
#ifndef TORRENT_DISABLE_GEO_IP
bool session::load_asnum_db(char const* file)
void session::load_asnum_db(char const* file)
{
mutex::scoped_lock l(m_impl->m_mutex);
return m_impl->load_asnum_db(file);
TORRENT_ASYNC_CALL1(load_asnum_db, std::string(file));
}
bool session::load_country_db(char const* file)
void session::load_country_db(char const* file)
{
mutex::scoped_lock l(m_impl->m_mutex);
return m_impl->load_country_db(file);
TORRENT_ASYNC_CALL1(load_country_db, std::string(file));
}
int session::as_for_ip(address const& addr)
{
mutex::scoped_lock l(m_impl->m_mutex);
return m_impl->as_for_ip(addr);
}
#if TORRENT_USE_WSTRING
bool session::load_asnum_db(wchar_t const* file)
void session::load_asnum_db(wchar_t const* file)
{
mutex::scoped_lock l(m_impl->m_mutex);
return m_impl->load_asnum_db(file);
TORRENT_ASYNC_CALL1(load_asnum_db, std::wstring(file));
}
bool session::load_country_db(wchar_t const* file)
void session::load_country_db(wchar_t const* file)
{
mutex::scoped_lock l(m_impl->m_mutex);
return m_impl->load_country_db(file);
TORRENT_ASYNC_CALL1(load_country_db, std::wstring(file));
}
#endif // TORRENT_USE_WSTRING
#endif // TORRENT_DISABLE_GEO_IP
@ -383,89 +459,80 @@ namespace libtorrent
bencode(std::back_inserter(buf), ses_state);
lazy_entry e;
lazy_bdecode(&buf[0], &buf[0] + buf.size(), e);
mutex::scoped_lock l(m_impl->m_mutex);
m_impl->load_state(e);
TORRENT_SYNC_CALL1(load_state, &e);
}
entry session::state() const
{
entry ret;
mutex::scoped_lock l(m_impl->m_mutex);
m_impl->save_state(ret, 0xffffffff, l);
TORRENT_SYNC_CALL2(save_state, &ret, 0xffffffff);
return ret;
}
#endif
void session::set_ip_filter(ip_filter const& f)
{
mutex::scoped_lock l(m_impl->m_mutex);
m_impl->set_ip_filter(f);
TORRENT_ASYNC_CALL1(set_ip_filter, f);
}
ip_filter const& session::get_ip_filter() const
ip_filter session::get_ip_filter() const
{
mutex::scoped_lock l(m_impl->m_mutex);
return m_impl->get_ip_filter();
TORRENT_SYNC_CALL_RET(ip_filter, get_ip_filter);
return r;
}
void session::set_port_filter(port_filter const& f)
{
mutex::scoped_lock l(m_impl->m_mutex);
m_impl->set_port_filter(f);
TORRENT_ASYNC_CALL1(set_port_filter, f);
}
void session::set_peer_id(peer_id const& id)
{
mutex::scoped_lock l(m_impl->m_mutex);
m_impl->set_peer_id(id);
TORRENT_ASYNC_CALL1(set_peer_id, id);
}
peer_id session::id() const
{
mutex::scoped_lock l(m_impl->m_mutex);
return m_impl->get_peer_id();
TORRENT_SYNC_CALL_RET(peer_id, get_peer_id);
return r;
}
io_service& session::get_io_service()
{
mutex::scoped_lock l(m_impl->m_mutex);
return m_impl->m_io_service;
}
void session::set_key(int key)
{
mutex::scoped_lock l(m_impl->m_mutex);
m_impl->set_key(key);
TORRENT_ASYNC_CALL1(set_key, key);
}
std::vector<torrent_handle> session::get_torrents() const
{
mutex::scoped_lock l(m_impl->m_mutex);
return m_impl->get_torrents();
TORRENT_SYNC_CALL_RET(std::vector<torrent_handle>, get_torrents);
return r;
}
torrent_handle session::find_torrent(sha1_hash const& info_hash) const
{
mutex::scoped_lock l(m_impl->m_mutex);
return m_impl->find_torrent_handle(info_hash);
TORRENT_SYNC_CALL_RET1(torrent_handle, find_torrent_handle, info_hash);
return r;
}
#ifndef BOOST_NO_EXCEPTIONS
torrent_handle session::add_torrent(add_torrent_params const& params)
{
mutex::scoped_lock l(m_impl->m_mutex);
error_code ec;
torrent_handle ret = m_impl->add_torrent(params, ec);
TORRENT_SYNC_CALL_RET2(torrent_handle, add_torrent, params, ec);
if (ec) throw libtorrent_exception(ec);
return ret;
return r;
}
#endif
torrent_handle session::add_torrent(add_torrent_params const& params, error_code& ec)
{
mutex::scoped_lock l(m_impl->m_mutex);
return m_impl->add_torrent(params, ec);
TORRENT_SYNC_CALL_RET2(torrent_handle, add_torrent, params, ec);
return r;
}
#ifndef BOOST_NO_EXCEPTIONS
@ -542,58 +609,53 @@ namespace libtorrent
void session::remove_torrent(const torrent_handle& h, int options)
{
mutex::scoped_lock l(m_impl->m_mutex);
m_impl->remove_torrent(h, options);
TORRENT_ASYNC_CALL2(remove_torrent, h, options);
}
bool session::listen_on(
std::pair<int, int> const& port_range
, const char* net_interface, int flags)
{
mutex::scoped_lock l(m_impl->m_mutex);
return m_impl->listen_on(port_range, net_interface, flags);
TORRENT_SYNC_CALL_RET3(bool, listen_on, port_range, net_interface, flags);
return r;
}
unsigned short session::listen_port() const
{
mutex::scoped_lock l(m_impl->m_mutex);
return m_impl->listen_port();
TORRENT_SYNC_CALL_RET(unsigned short, listen_port);
return r;
}
session_status session::status() const
{
mutex::scoped_lock l(m_impl->m_mutex);
return m_impl->status();
TORRENT_SYNC_CALL_RET(session_status, status);
return r;
}
void session::pause()
{
mutex::scoped_lock l(m_impl->m_mutex);
m_impl->pause();
TORRENT_ASYNC_CALL(pause);
}
void session::resume()
{
mutex::scoped_lock l(m_impl->m_mutex);
m_impl->resume();
TORRENT_ASYNC_CALL(resume);
}
bool session::is_paused() const
{
mutex::scoped_lock l(m_impl->m_mutex);
return m_impl->is_paused();
TORRENT_SYNC_CALL_RET(bool, is_paused);
return r;
}
void session::get_cache_info(sha1_hash const& ih
, std::vector<cached_piece_info>& ret) const
{
mutex::scoped_lock l(m_impl->m_mutex);
m_impl->m_disk_thread.get_cache_info(ih, ret);
}
cache_status session::get_cache_status() const
{
mutex::scoped_lock l(m_impl->m_mutex);
return m_impl->m_disk_thread.status();
}
@ -601,53 +663,47 @@ namespace libtorrent
void session::start_dht()
{
mutex::scoped_lock l(m_impl->m_mutex);
// the state is loaded in load_state()
m_impl->start_dht();
TORRENT_ASYNC_CALL(start_dht);
}
void session::stop_dht()
{
mutex::scoped_lock l(m_impl->m_mutex);
m_impl->stop_dht();
TORRENT_ASYNC_CALL(stop_dht);
}
void session::set_dht_settings(dht_settings const& settings)
{
mutex::scoped_lock l(m_impl->m_mutex);
m_impl->set_dht_settings(settings);
TORRENT_ASYNC_CALL1(set_dht_settings, settings);
}
#ifndef TORRENT_NO_DEPRECATE
void session::start_dht(entry const& startup_state)
{
mutex::scoped_lock l(m_impl->m_mutex);
m_impl->start_dht(startup_state);
TORRENT_ASYNC_CALL1(start_dht, startup_state);
}
entry session::dht_state() const
{
mutex::scoped_lock l(m_impl->m_mutex);
return m_impl->dht_state(l);
TORRENT_SYNC_CALL_RET(entry, dht_state);
return r;
}
#endif
void session::add_dht_node(std::pair<std::string, int> const& node)
{
mutex::scoped_lock l(m_impl->m_mutex);
m_impl->add_dht_node(node);
TORRENT_ASYNC_CALL1(add_dht_node_name, node);
}
void session::add_dht_router(std::pair<std::string, int> const& node)
{
mutex::scoped_lock l(m_impl->m_mutex);
m_impl->add_dht_router(node);
TORRENT_ASYNC_CALL1(add_dht_router, node);
}
bool session::is_dht_running() const
{
mutex::scoped_lock l(m_impl->m_mutex);
return m_impl->m_dht;
TORRENT_SYNC_CALL_RET(bool, is_dht_running);
return r;
}
#endif
@ -655,230 +711,211 @@ namespace libtorrent
#ifndef TORRENT_DISABLE_ENCRYPTION
void session::set_pe_settings(pe_settings const& settings)
{
mutex::scoped_lock l(m_impl->m_mutex);
m_impl->set_pe_settings(settings);
TORRENT_ASYNC_CALL1(set_pe_settings, settings);
}
pe_settings const& session::get_pe_settings() const
pe_settings session::get_pe_settings() const
{
mutex::scoped_lock l(m_impl->m_mutex);
return m_impl->get_pe_settings();
TORRENT_SYNC_CALL_RET(pe_settings, get_pe_settings);
return r;
}
#endif
bool session::is_listening() const
{
mutex::scoped_lock l(m_impl->m_mutex);
return m_impl->is_listening();
TORRENT_SYNC_CALL_RET(bool, is_listening);
return r;
}
void session::set_settings(session_settings const& s)
{
mutex::scoped_lock l(m_impl->m_mutex);
m_impl->set_settings(s);
TORRENT_ASYNC_CALL1(set_settings, s);
}
session_settings const& session::settings()
session_settings session::settings()
{
mutex::scoped_lock l(m_impl->m_mutex);
return m_impl->settings();
TORRENT_SYNC_CALL_RET(session_settings, settings);
return r;
}
void session::set_peer_proxy(proxy_settings const& s)
{
mutex::scoped_lock l(m_impl->m_mutex);
m_impl->set_peer_proxy(s);
TORRENT_ASYNC_CALL1(set_peer_proxy, s);
}
void session::set_web_seed_proxy(proxy_settings const& s)
{
mutex::scoped_lock l(m_impl->m_mutex);
m_impl->set_web_seed_proxy(s);
TORRENT_ASYNC_CALL1(set_web_seed_proxy, s);
}
void session::set_tracker_proxy(proxy_settings const& s)
{
mutex::scoped_lock l(m_impl->m_mutex);
m_impl->set_tracker_proxy(s);
TORRENT_ASYNC_CALL1(set_tracker_proxy, s);
}
proxy_settings const& session::peer_proxy() const
proxy_settings session::peer_proxy() const
{
mutex::scoped_lock l(m_impl->m_mutex);
return m_impl->peer_proxy();
TORRENT_SYNC_CALL_RET(proxy_settings, peer_proxy);
return r;
}
proxy_settings const& session::web_seed_proxy() const
proxy_settings session::web_seed_proxy() const
{
mutex::scoped_lock l(m_impl->m_mutex);
return m_impl->web_seed_proxy();
TORRENT_SYNC_CALL_RET(proxy_settings, web_seed_proxy);
return r;
}
proxy_settings const& session::tracker_proxy() const
proxy_settings session::tracker_proxy() const
{
mutex::scoped_lock l(m_impl->m_mutex);
return m_impl->tracker_proxy();
TORRENT_SYNC_CALL_RET(proxy_settings, tracker_proxy);
return r;
}
#ifndef TORRENT_DISABLE_DHT
void session::set_dht_proxy(proxy_settings const& s)
{
mutex::scoped_lock l(m_impl->m_mutex);
m_impl->set_dht_proxy(s);
TORRENT_ASYNC_CALL1(set_dht_proxy, s);
}
proxy_settings const& session::dht_proxy() const
proxy_settings session::dht_proxy() const
{
mutex::scoped_lock l(m_impl->m_mutex);
return m_impl->dht_proxy();
TORRENT_SYNC_CALL_RET(proxy_settings, dht_proxy);
return r;
}
#endif
#if TORRENT_USE_I2P
void session::set_i2p_proxy(proxy_settings const& s)
{
mutex::scoped_lock l(m_impl->m_mutex);
m_impl->set_i2p_proxy(s);
TORRENT_ASYNC_CALL1(set_i2p_proxy, s);
}
proxy_settings const& session::i2p_proxy() const
proxy_settings session::i2p_proxy() const
{
mutex::scoped_lock l(m_impl->m_mutex);
return m_impl->i2p_proxy();
TORRENT_SYNC_CALL_RET(proxy_settings, i2p_proxy);
return r;
}
#endif
int session::max_uploads() const
{
mutex::scoped_lock l(m_impl->m_mutex);
return m_impl->max_uploads();
TORRENT_SYNC_CALL_RET(int, max_uploads);
return r;
}
void session::set_max_uploads(int limit)
{
mutex::scoped_lock l(m_impl->m_mutex);
m_impl->set_max_uploads(limit);
TORRENT_ASYNC_CALL1(set_max_uploads, limit);
}
int session::max_connections() const
{
mutex::scoped_lock l(m_impl->m_mutex);
return m_impl->max_connections();
TORRENT_SYNC_CALL_RET(int, max_connections);
return r;
}
void session::set_max_connections(int limit)
{
mutex::scoped_lock l(m_impl->m_mutex);
m_impl->set_max_connections(limit);
TORRENT_ASYNC_CALL1(set_max_connections, limit);
}
int session::max_half_open_connections() const
{
mutex::scoped_lock l(m_impl->m_mutex);
return m_impl->max_half_open_connections();
TORRENT_SYNC_CALL_RET(int, max_half_open_connections);
return r;
}
void session::set_max_half_open_connections(int limit)
{
mutex::scoped_lock l(m_impl->m_mutex);
m_impl->set_max_half_open_connections(limit);
TORRENT_ASYNC_CALL1(set_max_half_open_connections, limit);
}
int session::local_upload_rate_limit() const
{
mutex::scoped_lock l(m_impl->m_mutex);
return m_impl->local_upload_rate_limit();
TORRENT_SYNC_CALL_RET(int, local_upload_rate_limit);
return r;
}
int session::local_download_rate_limit() const
{
mutex::scoped_lock l(m_impl->m_mutex);
return m_impl->local_download_rate_limit();
TORRENT_SYNC_CALL_RET(int, local_download_rate_limit);
return r;
}
int session::upload_rate_limit() const
{
mutex::scoped_lock l(m_impl->m_mutex);
return m_impl->upload_rate_limit();
TORRENT_SYNC_CALL_RET(int, upload_rate_limit);
return r;
}
int session::download_rate_limit() const
{
mutex::scoped_lock l(m_impl->m_mutex);
return m_impl->download_rate_limit();
TORRENT_SYNC_CALL_RET(int, download_rate_limit);
return r;
}
void session::set_local_upload_rate_limit(int bytes_per_second)
{
mutex::scoped_lock l(m_impl->m_mutex);
m_impl->set_local_upload_rate_limit(bytes_per_second);
TORRENT_ASYNC_CALL1(set_local_upload_rate_limit, bytes_per_second);
}
void session::set_local_download_rate_limit(int bytes_per_second)
{
mutex::scoped_lock l(m_impl->m_mutex);
m_impl->set_local_download_rate_limit(bytes_per_second);
TORRENT_ASYNC_CALL1(set_local_download_rate_limit, bytes_per_second);
}
void session::set_upload_rate_limit(int bytes_per_second)
{
mutex::scoped_lock l(m_impl->m_mutex);
m_impl->set_upload_rate_limit(bytes_per_second);
TORRENT_ASYNC_CALL1(set_upload_rate_limit, bytes_per_second);
}
void session::set_download_rate_limit(int bytes_per_second)
{
mutex::scoped_lock l(m_impl->m_mutex);
m_impl->set_download_rate_limit(bytes_per_second);
TORRENT_ASYNC_CALL1(set_download_rate_limit, bytes_per_second);
}
int session::num_uploads() const
{
mutex::scoped_lock l(m_impl->m_mutex);
return m_impl->num_uploads();
TORRENT_SYNC_CALL_RET(int, num_uploads);
return r;
}
int session::num_connections() const
{
mutex::scoped_lock l(m_impl->m_mutex);
return m_impl->num_connections();
TORRENT_SYNC_CALL_RET(int, num_connections);
return r;
}
std::auto_ptr<alert> session::pop_alert()
{
mutex::scoped_lock l(m_impl->m_mutex);
return m_impl->pop_alert();
}
void session::set_alert_dispatch(boost::function<void(alert const&)> const& fun)
void session::set_alert_dispatch(boost::function<void(std::auto_ptr<alert>)> const& fun)
{
// this function deliberately doesn't acquire the mutex
return m_impl->set_alert_dispatch(fun);
TORRENT_ASYNC_CALL1(set_alert_dispatch, fun);
}
alert const* session::wait_for_alert(time_duration max_wait)
{
// this function deliberately doesn't acquire the mutex
return m_impl->wait_for_alert(max_wait);
}
void session::set_alert_mask(int m)
{
mutex::scoped_lock l(m_impl->m_mutex);
m_impl->set_alert_mask(m);
TORRENT_ASYNC_CALL1(set_alert_mask, m);
}
size_t session::set_alert_queue_size_limit(size_t queue_size_limit_)
{
mutex::scoped_lock l(m_impl->m_mutex);
return m_impl->set_alert_queue_size_limit(queue_size_limit_);
TORRENT_SYNC_CALL_RET1(size_t, set_alert_queue_size_limit, queue_size_limit_);
return r;
}
#ifndef TORRENT_NO_DEPRECATE
void session::set_severity_level(alert::severity_t s)
{
mutex::scoped_lock l(m_impl->m_mutex);
int m = 0;
switch (s)
{
@ -893,85 +930,44 @@ namespace libtorrent
default: break;
}
m_impl->set_alert_mask(m);
TORRENT_ASYNC_CALL1(set_alert_mask, m);
}
#endif
void session::start_lsd()
{
mutex::scoped_lock l(m_impl->m_mutex);
m_impl->start_lsd();
TORRENT_ASYNC_CALL(start_lsd);
}
natpmp* session::start_natpmp()
{
mutex::scoped_lock l(m_impl->m_mutex);
if (m_impl->m_natpmp) return m_impl->m_natpmp.get();
// the natpmp constructor may fail and call the callbacks
// into the session_impl. We cannot hold the mutex then
l.unlock();
natpmp* n = new (std::nothrow) natpmp(m_impl->m_io_service
, m_impl->m_listen_interface.address()
, boost::bind(&session_impl::on_port_mapping
, m_impl.get(), _1, _2, _3, 0)
, boost::bind(&session_impl::on_port_map_log
, m_impl.get(), _1, 0));
l.lock();
if (n == 0) return 0;
m_impl->start_natpmp(n);
return n;
TORRENT_SYNC_CALL_RET(natpmp*, start_natpmp);
return r;
}
upnp* session::start_upnp()
{
mutex::scoped_lock l(m_impl->m_mutex);
if (m_impl->m_upnp) return m_impl->m_upnp.get();
// the upnp constructor may fail and call the callbacks
// into the session_impl. We cannot hold the mutex then
l.unlock();
upnp* u = new (std::nothrow) upnp(m_impl->m_io_service
, m_impl->m_half_open
, m_impl->m_listen_interface.address()
, m_impl->m_settings.user_agent
, boost::bind(&session_impl::on_port_mapping
, m_impl.get(), _1, _2, _3, 1)
, boost::bind(&session_impl::on_port_map_log
, m_impl.get(), _1, 1)
, m_impl->m_settings.upnp_ignore_nonrouters);
l.lock();
if (u == 0) return 0;
m_impl->start_upnp(u);
return u;
TORRENT_SYNC_CALL_RET(upnp*, start_upnp);
return r;
}
void session::stop_lsd()
{
mutex::scoped_lock l(m_impl->m_mutex);
m_impl->stop_lsd();
TORRENT_ASYNC_CALL(stop_lsd);
}
void session::stop_natpmp()
{
mutex::scoped_lock l(m_impl->m_mutex);
m_impl->stop_natpmp();
TORRENT_ASYNC_CALL(stop_natpmp);
}
void session::stop_upnp()
{
mutex::scoped_lock l(m_impl->m_mutex);
m_impl->stop_upnp();
TORRENT_ASYNC_CALL(stop_upnp);
}
connection_queue& session::get_connection_queue()
{
mutex::scoped_lock l(m_impl->m_mutex);
return m_impl->m_half_open;
}
}

View File

@ -750,8 +750,10 @@ namespace aux {
m_thread.reset(new thread(boost::bind(&session_impl::main_thread, this)));
}
void session_impl::save_state(entry& e, boost::uint32_t flags, mutex::scoped_lock& l) const
void session_impl::save_state(entry* eptr, boost::uint32_t flags) const
{
entry& e = *eptr;
if (flags & session::save_settings)
{
// TODO: move these to session_settings
@ -780,12 +782,7 @@ namespace aux {
#ifndef TORRENT_DISABLE_DHT
if (m_dht && (flags & session::save_dht_state))
{
condition cond;
entry& state = e["dht state"];
bool done = false;
m_io_service.post(boost::bind(&session_impl::on_dht_state_callback
, this, boost::ref(cond), boost::ref(state), boost::ref(done)));
while (!done) cond.wait(l);
e["dht state"] = m_dht->state();
}
#endif
@ -814,29 +811,29 @@ namespace aux {
}
void session_impl::load_state(lazy_entry const& e)
void session_impl::load_state(lazy_entry const* e)
{
lazy_entry const* settings;
if (e.type() != lazy_entry::dict_t) return;
if (e->type() != lazy_entry::dict_t) return;
set_upload_rate_limit(e.dict_find_int_value("upload_rate_limit", 0));
set_download_rate_limit(e.dict_find_int_value("download_rate_limit", 0));
set_local_upload_rate_limit(e.dict_find_int_value("local_upload_rate_limit", 0));
set_local_download_rate_limit(e.dict_find_int_value("local_download_rate_limit", 0));
set_max_uploads(e.dict_find_int_value("max_uploads", 0));
set_max_half_open_connections(e.dict_find_int_value("max_half_open_connections", 0));
set_max_connections(e.dict_find_int_value("max_connections", 0));
set_upload_rate_limit(e->dict_find_int_value("upload_rate_limit", 0));
set_download_rate_limit(e->dict_find_int_value("download_rate_limit", 0));
set_local_upload_rate_limit(e->dict_find_int_value("local_upload_rate_limit", 0));
set_local_download_rate_limit(e->dict_find_int_value("local_download_rate_limit", 0));
set_max_uploads(e->dict_find_int_value("max_uploads", 0));
set_max_half_open_connections(e->dict_find_int_value("max_half_open_connections", 0));
set_max_connections(e->dict_find_int_value("max_connections", 0));
for (int i = 0; i < sizeof(all_settings)/sizeof(all_settings[0]); ++i)
{
session_category const& c = all_settings[i];
settings = e.dict_find_dict(c.name);
settings = e->dict_find_dict(c.name);
if (!settings) continue;
load_struct(*settings, reinterpret_cast<char*>(this) + c.offset, c.map, c.num_entries);
}
#ifndef TORRENT_DISABLE_DHT
settings = e.dict_find_dict("dht");
settings = e->dict_find_dict("dht");
if (settings)
{
dht_settings s;
@ -844,7 +841,7 @@ namespace aux {
, sizeof(dht_settings_map)/sizeof(dht_settings_map[0]));
set_dht_settings(s);
}
settings = e.dict_find_dict("dht state");
settings = e->dict_find_dict("dht state");
if (settings)
{
m_dht_state = *settings;
@ -853,7 +850,7 @@ namespace aux {
#endif
#if TORRENT_USE_I2P
settings = e.dict_find_dict("i2p");
settings = e->dict_find_dict("i2p");
if (settings)
{
proxy_settings s;
@ -863,7 +860,7 @@ namespace aux {
}
#endif
#ifndef TORRENT_DISABLE_GEO_IP
settings = e.dict_find_dict("AS map");
settings = e->dict_find_dict("AS map");
if (settings)
{
for (int i = 0; i < settings->dict_size(); ++i)
@ -1115,6 +1112,15 @@ namespace aux {
// the uTP connections cannot be closed gracefully
m_udp_socket.close();
m_external_udp_port = 0;
#ifndef TORRENT_DISABLE_GEO_IP
if (m_asnum_db) GeoIP_delete(m_asnum_db);
if (m_country_db) GeoIP_delete(m_country_db);
m_asnum_db = 0;
m_country_db = 0;
#endif
m_disk_thread.abort();
}
void session_impl::set_port_filter(port_filter const& f)
@ -1635,13 +1641,12 @@ namespace aux {
void session_impl::on_accept_connection(shared_ptr<socket_type> const& s
, weak_ptr<socket_acceptor> listen_socket, error_code const& e)
{
TORRENT_ASSERT(is_network_thread());
boost::shared_ptr<socket_acceptor> listener = listen_socket.lock();
if (!listener) return;
if (e == asio::error::operation_aborted) return;
mutex::scoped_lock l(m_mutex);
if (m_abort) return;
error_code ec;
@ -1918,8 +1923,8 @@ namespace aux {
// wake them up
void session_impl::on_disk_queue()
{
mutex::scoped_lock l(m_mutex);
TORRENT_ASSERT(is_network_thread());
for (connection_map::iterator i = m_connections.begin();
i != m_connections.end();)
{
@ -1948,7 +1953,7 @@ namespace aux {
void session_impl::on_tick(error_code const& e)
{
mutex::scoped_lock l(m_mutex);
TORRENT_ASSERT(is_network_thread());
ptime now = time_now_hires();
aux::g_current_time = now;
@ -2438,9 +2443,9 @@ namespace aux {
void session_impl::on_dht_announce(error_code const& e)
{
TORRENT_ASSERT(is_network_thread());
if (e) return;
mutex::scoped_lock l(m_mutex);
if (m_abort) return;
// announce to DHT every 15 minutes
@ -2464,9 +2469,9 @@ namespace aux {
void session_impl::on_lsd_announce(error_code const& e)
{
TORRENT_ASSERT(is_network_thread());
if (e) return;
mutex::scoped_lock l(m_mutex);
if (m_abort) return;
// announce on local network every 5 minutes
@ -2944,6 +2949,12 @@ namespace aux {
void session_impl::main_thread()
{
#ifdef TORRENT_DEBUG
#if defined BOOST_HAS_PTHREADS
m_network_thread = pthread_self();
#endif
#endif
TORRENT_ASSERT(is_network_thread());
eh_initializer();
bool stop_loop = false;
@ -2961,7 +2972,6 @@ namespace aux {
}
m_io_service.reset();
mutex::scoped_lock l(m_mutex);
stop_loop = m_abort;
}
@ -2969,7 +2979,6 @@ namespace aux {
(*m_logger) << time_now_string() << " locking mutex\n";
#endif
mutex::scoped_lock l(m_mutex);
/*
#ifdef TORRENT_DEBUG
for (torrent_map::iterator i = m_torrents.begin();
@ -2993,6 +3002,8 @@ namespace aux {
// session is locked!
boost::weak_ptr<torrent> session_impl::find_torrent(sha1_hash const& info_hash)
{
TORRENT_ASSERT(is_network_thread());
std::map<sha1_hash, boost::shared_ptr<torrent> >::iterator i
= m_torrents.find(info_hash);
#ifdef TORRENT_DEBUG
@ -3274,7 +3285,7 @@ namespace aux {
void session_impl::on_lsd_peer(tcp::endpoint peer, sha1_hash const& ih)
{
mutex::scoped_lock l(m_mutex);
TORRENT_ASSERT(is_network_thread());
INVARIANT_CHECK;
@ -3308,7 +3319,8 @@ namespace aux {
void session_impl::on_port_mapping(int mapping, int port
, error_code const& ec, int map_transport)
{
mutex::scoped_lock l(m_mutex);
TORRENT_ASSERT(is_network_thread());
TORRENT_ASSERT(map_transport >= 0 && map_transport <= 1);
if (mapping == m_udp_mapping[map_transport] && port != 0)
@ -3521,30 +3533,15 @@ namespace aux {
m_dht_settings = settings;
}
void session_impl::on_dht_state_callback(condition& c
, entry& e, bool& done) const
{
mutex::scoped_lock l(m_mutex);
if (m_dht) e = m_dht->state();
done = true;
c.signal(l);
}
#ifndef TORRENT_NO_DEPRECATE
entry session_impl::dht_state(mutex::scoped_lock& l) const
entry session_impl::dht_state() const
{
condition cond;
if (!m_dht) return entry();
entry e;
bool done = false;
m_io_service.post(boost::bind(&session_impl::on_dht_state_callback
, this, boost::ref(cond), boost::ref(e), boost::ref(done)));
while (!done) cond.wait(l);
return e;
return m_dht->state();
}
#endif
void session_impl::add_dht_node(std::pair<std::string, int> const& node)
void session_impl::add_dht_node_name(std::pair<std::string, int> const& node)
{
TORRENT_ASSERT(m_dht);
m_dht->add_node(node);
@ -3584,22 +3581,15 @@ namespace aux {
session_impl::~session_impl()
{
mutex::scoped_lock l(m_mutex);
#if defined BOOST_HAS_PTHREADS
TORRENT_ASSERT(!is_network_thread());
#endif
#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
(*m_logger) << time_now_string() << "\n\n *** shutting down session *** \n\n";
#endif
abort();
TORRENT_ASSERT(m_connections.empty());
m_io_service.post(boost::bind(&session_impl::abort, this));
#ifndef TORRENT_DISABLE_GEO_IP
if (m_asnum_db) GeoIP_delete(m_asnum_db);
if (m_country_db) GeoIP_delete(m_country_db);
m_asnum_db = 0;
m_country_db = 0;
#endif
l.unlock();
// we need to wait for the disk-io thread to
// die first, to make sure it won't post any
// more messages to the io_service containing references
@ -3702,7 +3692,7 @@ namespace aux {
m_upload_channel.throttle(bytes_per_second);
}
void session_impl::set_alert_dispatch(boost::function<void(alert const&)> const& fun)
void session_impl::set_alert_dispatch(boost::function<void(std::auto_ptr<alert>)> const& fun)
{
m_alerts.set_dispatch_function(fun);
}
@ -3712,9 +3702,7 @@ namespace aux {
// too expensive
// INVARIANT_CHECK;
if (m_alerts.pending())
return m_alerts.get();
return std::auto_ptr<alert>(0);
return m_alerts.get();
}
alert const* session_impl::wait_for_alert(time_duration max_wait)
@ -3765,10 +3753,22 @@ namespace aux {
m_lsd->use_broadcast(true);
}
void session_impl::start_natpmp(natpmp* n)
natpmp* session_impl::start_natpmp()
{
INVARIANT_CHECK;
if (m_natpmp) return m_natpmp.get();
// the natpmp constructor may fail and call the callbacks
// into the session_impl.
natpmp* n = new (std::nothrow) natpmp(m_io_service
, m_listen_interface.address()
, boost::bind(&session_impl::on_port_mapping
, this, _1, _2, _3, 0)
, boost::bind(&session_impl::on_port_map_log
, this, _1, 0));
if (n == 0) return 0;
m_natpmp = n;
if (m_listen_interface.port() > 0)
@ -3783,10 +3783,25 @@ namespace aux {
}
}
void session_impl::start_upnp(upnp* u)
upnp* session_impl::start_upnp()
{
INVARIANT_CHECK;
if (m_upnp) return m_upnp.get();
// the upnp constructor may fail and call the callbacks
upnp* u = new (std::nothrow) upnp(m_io_service
, m_half_open
, m_listen_interface.address()
, m_settings.user_agent
, boost::bind(&session_impl::on_port_mapping
, this, _1, _2, _3, 1)
, boost::bind(&session_impl::on_port_map_log
, this, _1, 1)
, m_settings.upnp_ignore_nonrouters);
if (u == 0) return 0;
m_upnp = u;
m_upnp->discover_device();

View File

@ -167,7 +167,7 @@ namespace
void on_read_failed_block(piece_block b, address a, int ret, disk_io_job const& j)
{
mutex::scoped_lock l(m_torrent.session().m_mutex);
TORRENT_ASSERT(m_torrent.session().is_network_thread());
disk_buffer_holder buffer(m_torrent.session(), j.buffer);
@ -248,7 +248,7 @@ namespace
void on_read_ok_block(std::pair<piece_block, block_entry> b, int ret, disk_io_job const& j)
{
mutex::scoped_lock l(m_torrent.session().m_mutex);
TORRENT_ASSERT(m_torrent.session().is_network_thread());
disk_buffer_holder buffer(m_torrent.session(), j.buffer);

View File

@ -636,7 +636,7 @@ namespace libtorrent
void torrent::on_disk_read_complete(int ret, disk_io_job const& j, peer_request r, read_piece_struct* rp)
{
mutex::scoped_lock l(m_ses.m_mutex);
TORRENT_ASSERT(m_ses.is_network_thread());
disk_buffer_holder buffer(m_ses, j.buffer);
@ -716,7 +716,7 @@ namespace libtorrent
void torrent::on_disk_write_complete(int ret, disk_io_job const& j
, peer_request p)
{
mutex::scoped_lock l(m_ses.m_mutex);
TORRENT_ASSERT(m_ses.is_network_thread());
INVARIANT_CHECK;
@ -864,7 +864,7 @@ namespace libtorrent
if (m_seed_mode)
{
m_ses.m_io_service.post(boost::bind(&torrent::files_checked_lock, shared_from_this()));
m_ses.m_io_service.post(boost::bind(&torrent::files_checked, shared_from_this()));
std::vector<char>().swap(m_resume_data);
lazy_entry().swap(m_resume_entry);
return;
@ -937,7 +937,7 @@ namespace libtorrent
void torrent::on_resume_data_checked(int ret, disk_io_job const& j)
{
mutex::scoped_lock l(m_ses.m_mutex);
TORRENT_ASSERT(m_ses.is_network_thread());
if (ret == piece_manager::fatal_disk_error)
{
@ -1120,7 +1120,7 @@ namespace libtorrent
}
}
files_checked(l);
files_checked();
}
else
{
@ -1191,7 +1191,7 @@ namespace libtorrent
void torrent::on_force_recheck(int ret, disk_io_job const& j)
{
mutex::scoped_lock l(m_ses.m_mutex);
TORRENT_ASSERT(m_ses.is_network_thread());
if (ret == piece_manager::fatal_disk_error)
{
@ -1201,7 +1201,7 @@ namespace libtorrent
if (ret == 0)
{
// if there are no files, just start
files_checked(l);
files_checked();
}
else
{
@ -1223,7 +1223,7 @@ namespace libtorrent
void torrent::on_piece_checked(int ret, disk_io_job const& j)
{
mutex::scoped_lock l(m_ses.m_mutex);
TORRENT_ASSERT(m_ses.is_network_thread());
INVARIANT_CHECK;
if (ret == piece_manager::disk_check_aborted)
@ -1263,15 +1263,15 @@ namespace libtorrent
if (ret == piece_manager::need_full_check) return;
dequeue_torrent_check();
files_checked(l);
files_checked();
}
void torrent::use_interface(const char* net_interface)
void torrent::use_interface(std::string net_interface)
{
INVARIANT_CHECK;
error_code ec;
address a(address::from_string(net_interface, ec));
address a(address::from_string(net_interface.c_str(), ec));
if (ec) return;
m_net_interface = tcp::endpoint(a, 0);
}
@ -1287,7 +1287,7 @@ namespace libtorrent
void torrent::on_tracker_announce()
{
mutex::scoped_lock l(m_ses.m_mutex);
TORRENT_ASSERT(m_ses.is_network_thread());
m_waiting_tracker = false;
if (m_abort) return;
announce_with_tracker();
@ -1537,7 +1537,7 @@ namespace libtorrent
void torrent::tracker_warning(tracker_request const& req, std::string const& msg)
{
mutex::scoped_lock l(m_ses.m_mutex);
TORRENT_ASSERT(m_ses.is_network_thread());
INVARIANT_CHECK;
@ -1548,7 +1548,7 @@ namespace libtorrent
void torrent::tracker_scrape_response(tracker_request const& req
, int complete, int incomplete, int downloaded)
{
mutex::scoped_lock l(m_ses.m_mutex);
TORRENT_ASSERT(m_ses.is_network_thread());
INVARIANT_CHECK;
TORRENT_ASSERT(req.kind == tracker_request::scrape_request);
@ -1574,7 +1574,7 @@ namespace libtorrent
, int incomplete
, address const& external_ip)
{
mutex::scoped_lock l(m_ses.m_mutex);
TORRENT_ASSERT(m_ses.is_network_thread());
INVARIANT_CHECK;
TORRENT_ASSERT(r.kind == tracker_request::announce_request);
@ -1756,7 +1756,7 @@ namespace libtorrent
#if TORRENT_USE_I2P
void torrent::on_i2p_resolve(error_code const& ec, char const* dest)
{
mutex::scoped_lock l(m_ses.m_mutex);
TORRENT_ASSERT(m_ses.is_network_thread());
INVARIANT_CHECK;
@ -1773,7 +1773,7 @@ namespace libtorrent
void torrent::on_peer_name_lookup(error_code const& e, tcp::resolver::iterator host
, peer_id pid)
{
mutex::scoped_lock l(m_ses.m_mutex);
TORRENT_ASSERT(m_ses.is_network_thread());
INVARIANT_CHECK;
@ -2572,7 +2572,7 @@ namespace libtorrent
void torrent::on_files_deleted(int ret, disk_io_job const& j)
{
mutex::scoped_lock l(m_ses.m_mutex);
TORRENT_ASSERT(m_ses.is_network_thread());
if (ret != 0)
{
@ -2589,7 +2589,7 @@ namespace libtorrent
void torrent::on_files_released(int ret, disk_io_job const& j)
{
/*
mutex::scoped_lock l(m_ses.m_mutex);
TORRENT_ASSERT(m_ses.is_network_thread());
if (alerts().should_post<torrent_paused_alert>())
{
@ -2606,7 +2606,7 @@ namespace libtorrent
void torrent::on_save_resume_data(int ret, disk_io_job const& j)
{
mutex::scoped_lock l(m_ses.m_mutex);
TORRENT_ASSERT(m_ses.is_network_thread());
if (!j.resume_data)
{
@ -2623,7 +2623,7 @@ namespace libtorrent
void torrent::on_file_renamed(int ret, disk_io_job const& j)
{
mutex::scoped_lock l(m_ses.m_mutex);
TORRENT_ASSERT(m_ses.is_network_thread());
if (ret == 0)
{
@ -2641,7 +2641,7 @@ namespace libtorrent
void torrent::on_torrent_paused(int ret, disk_io_job const& j)
{
mutex::scoped_lock l(m_ses.m_mutex);
TORRENT_ASSERT(m_ses.is_network_thread());
if (alerts().should_post<torrent_paused_alert>())
alerts().post_alert(torrent_paused_alert(get_handle()));
@ -3348,7 +3348,7 @@ namespace libtorrent
void torrent::on_proxy_name_lookup(error_code const& e, tcp::resolver::iterator host
, std::list<web_seed_entry>::iterator web)
{
mutex::scoped_lock l(m_ses.m_mutex);
TORRENT_ASSERT(m_ses.is_network_thread());
INVARIANT_CHECK;
@ -3411,7 +3411,7 @@ namespace libtorrent
void torrent::on_name_lookup(error_code const& e, tcp::resolver::iterator host
, std::list<web_seed_entry>::iterator web, tcp::endpoint proxy)
{
mutex::scoped_lock l(m_ses.m_mutex);
TORRENT_ASSERT(m_ses.is_network_thread());
INVARIANT_CHECK;
@ -3564,7 +3564,7 @@ namespace libtorrent
void torrent::on_country_lookup(error_code const& error, tcp::resolver::iterator i
, intrusive_ptr<peer_connection> p) const
{
mutex::scoped_lock l(m_ses.m_mutex);
TORRENT_ASSERT(m_ses.is_network_thread());
INVARIANT_CHECK;
@ -4688,14 +4688,9 @@ namespace libtorrent
return index;
}
void torrent::files_checked_lock()
{
mutex::scoped_lock l(m_ses.m_mutex);
files_checked(l);
}
void torrent::files_checked(mutex::scoped_lock const& l)
void torrent::files_checked()
{
TORRENT_ASSERT(m_ses.is_network_thread());
TORRENT_ASSERT(m_torrent_file->is_valid());
if (m_abort) return;
@ -4799,6 +4794,7 @@ namespace libtorrent
void torrent::move_storage(std::string const& save_path)
{
TORRENT_ASSERT(m_ses.is_network_thread());
INVARIANT_CHECK;
if (m_owning_storage.get())
@ -4818,7 +4814,7 @@ namespace libtorrent
void torrent::on_storage_moved(int ret, disk_io_job const& j)
{
mutex::scoped_lock l(m_ses.m_mutex);
TORRENT_ASSERT(m_ses.is_network_thread());
if (ret == 0)
{
@ -4847,17 +4843,20 @@ namespace libtorrent
torrent_handle torrent::get_handle()
{
TORRENT_ASSERT(m_ses.is_network_thread());
return torrent_handle(shared_from_this());
}
session_settings const& torrent::settings() const
{
TORRENT_ASSERT(m_ses.is_network_thread());
return m_ses.settings();
}
#ifdef TORRENT_DEBUG
void torrent::check_invariant() const
{
TORRENT_ASSERT(m_ses.is_network_thread());
if (is_paused()) TORRENT_ASSERT(num_peers() == 0);
if (!should_check_files())
@ -5005,10 +5004,25 @@ namespace libtorrent
#endif
void torrent::set_sequential_download(bool sd)
{ m_sequential_download = sd; }
{
TORRENT_ASSERT(m_ses.is_network_thread());
m_sequential_download = sd;
}
void torrent::queue_up()
{
set_queue_position(queue_position() == 0
? queue_position() : queue_position() - 1);
}
void torrent::queue_down()
{
set_queue_position(queue_position() + 1);
}
void torrent::set_queue_position(int p)
{
TORRENT_ASSERT(m_ses.is_network_thread());
TORRENT_ASSERT((p == -1) == is_finished()
|| (!m_auto_managed && p == -1)
|| (m_abort && p == -1));
@ -5080,6 +5094,7 @@ namespace libtorrent
void torrent::set_max_uploads(int limit)
{
TORRENT_ASSERT(m_ses.is_network_thread());
TORRENT_ASSERT(limit >= -1);
if (limit <= 0) limit = (std::numeric_limits<int>::max)();
m_max_uploads = limit;
@ -5087,6 +5102,7 @@ namespace libtorrent
void torrent::set_max_connections(int limit)
{
TORRENT_ASSERT(m_ses.is_network_thread());
TORRENT_ASSERT(limit >= -1);
if (limit <= 0) limit = (std::numeric_limits<int>::max)();
m_max_connections = limit;
@ -5094,6 +5110,7 @@ namespace libtorrent
void torrent::set_peer_upload_limit(tcp::endpoint ip, int limit)
{
TORRENT_ASSERT(m_ses.is_network_thread());
TORRENT_ASSERT(limit >= -1);
peer_iterator i = std::find_if(m_connections.begin(), m_connections.end()
, boost::bind(&peer_connection::remote, _1) == ip);
@ -5103,6 +5120,7 @@ namespace libtorrent
void torrent::set_peer_download_limit(tcp::endpoint ip, int limit)
{
TORRENT_ASSERT(m_ses.is_network_thread());
TORRENT_ASSERT(limit >= -1);
peer_iterator i = std::find_if(m_connections.begin(), m_connections.end()
, boost::bind(&peer_connection::remote, _1) == ip);
@ -5112,6 +5130,7 @@ namespace libtorrent
void torrent::set_upload_limit(int limit)
{
TORRENT_ASSERT(m_ses.is_network_thread());
TORRENT_ASSERT(limit >= -1);
if (limit <= 0) limit = 0;
m_bandwidth_channel[peer_connection::upload_channel].throttle(limit);
@ -5119,6 +5138,7 @@ namespace libtorrent
int torrent::upload_limit() const
{
TORRENT_ASSERT(m_ses.is_network_thread());
int limit = m_bandwidth_channel[peer_connection::upload_channel].throttle();
if (limit == (std::numeric_limits<int>::max)()) limit = -1;
return limit;
@ -5126,6 +5146,7 @@ namespace libtorrent
void torrent::set_download_limit(int limit)
{
TORRENT_ASSERT(m_ses.is_network_thread());
TORRENT_ASSERT(limit >= -1);
if (limit <= 0) limit = 0;
m_bandwidth_channel[peer_connection::download_channel].throttle(limit);
@ -5133,6 +5154,7 @@ namespace libtorrent
int torrent::download_limit() const
{
TORRENT_ASSERT(m_ses.is_network_thread());
int limit = m_bandwidth_channel[peer_connection::download_channel].throttle();
if (limit == (std::numeric_limits<int>::max)()) limit = -1;
return limit;
@ -5140,6 +5162,7 @@ namespace libtorrent
void torrent::delete_files()
{
TORRENT_ASSERT(m_ses.is_network_thread());
#if defined TORRENT_VERBOSE_LOGGING
for (peer_iterator i = m_connections.begin();
i != m_connections.end(); ++i)
@ -5161,6 +5184,7 @@ namespace libtorrent
void torrent::clear_error()
{
TORRENT_ASSERT(m_ses.is_network_thread());
if (!m_error) return;
bool checking_files = should_check_files();
if (m_ses.m_auto_manage_time_scaler > 2)
@ -5175,6 +5199,7 @@ namespace libtorrent
void torrent::set_error(error_code const& ec, std::string const& error_file)
{
TORRENT_ASSERT(m_ses.is_network_thread());
bool checking_files = should_check_files();
m_error = ec;
m_error_file = error_file;
@ -5189,6 +5214,7 @@ namespace libtorrent
void torrent::auto_managed(bool a)
{
TORRENT_ASSERT(m_ses.is_network_thread());
INVARIANT_CHECK;
if (m_auto_managed == a) return;
@ -5214,6 +5240,7 @@ namespace libtorrent
// the higher seed rank, the more important to seed
int torrent::seed_rank(session_settings const& s) const
{
TORRENT_ASSERT(m_ses.is_network_thread());
enum flags
{
seed_ratio_not_met = 0x400000,
@ -5276,6 +5303,7 @@ namespace libtorrent
// this is an async operation triggered by the client
void torrent::save_resume_data()
{
TORRENT_ASSERT(m_ses.is_network_thread());
INVARIANT_CHECK;
if (!m_owning_storage.get())
@ -5304,6 +5332,7 @@ namespace libtorrent
bool torrent::should_check_files() const
{
TORRENT_ASSERT(m_ses.is_network_thread());
// #error should m_allow_peers really affect checking?
return (m_state == torrent_status::checking_files
|| m_state == torrent_status::queued_for_checking)
@ -5314,23 +5343,27 @@ namespace libtorrent
void torrent::flush_cache()
{
TORRENT_ASSERT(m_ses.is_network_thread());
m_storage->async_release_files(
boost::bind(&torrent::on_cache_flushed, shared_from_this(), _1, _2));
}
void torrent::on_cache_flushed(int ret, disk_io_job const& j)
{
TORRENT_ASSERT(m_ses.is_network_thread());
if (alerts().should_post<cache_flushed_alert>())
alerts().post_alert(cache_flushed_alert(get_handle()));
}
bool torrent::is_paused() const
{
TORRENT_ASSERT(m_ses.is_network_thread());
return !m_allow_peers || m_ses.is_paused();
}
void torrent::pause()
{
TORRENT_ASSERT(m_ses.is_network_thread());
INVARIANT_CHECK;
if (!m_allow_peers) return;
@ -5352,6 +5385,7 @@ namespace libtorrent
void torrent::do_pause()
{
TORRENT_ASSERT(m_ses.is_network_thread());
if (!is_paused()) return;
#ifndef TORRENT_DISABLE_EXTENSIONS
@ -5397,6 +5431,7 @@ namespace libtorrent
void torrent::set_allow_peers(bool b)
{
TORRENT_ASSERT(m_ses.is_network_thread());
if (m_allow_peers == b) return;
bool checking_files = should_check_files();
@ -5421,6 +5456,7 @@ namespace libtorrent
void torrent::resume()
{
TORRENT_ASSERT(m_ses.is_network_thread());
INVARIANT_CHECK;
if (m_allow_peers
@ -5439,6 +5475,7 @@ namespace libtorrent
void torrent::do_resume()
{
TORRENT_ASSERT(m_ses.is_network_thread());
if (is_paused()) return;
#ifndef TORRENT_DISABLE_EXTENSIONS
@ -5465,6 +5502,7 @@ namespace libtorrent
void torrent::update_tracker_timer(ptime now)
{
TORRENT_ASSERT(m_ses.is_network_thread());
if (!m_announcing) return;
ptime next_announce = max_time();
@ -5511,6 +5549,7 @@ namespace libtorrent
void torrent::start_announcing()
{
TORRENT_ASSERT(m_ses.is_network_thread());
if (is_paused()) return;
// if we don't have metadata, we need to announce
// before checking files, to get peers to
@ -5552,6 +5591,7 @@ namespace libtorrent
void torrent::stop_announcing()
{
TORRENT_ASSERT(m_ses.is_network_thread());
if (!m_announcing) return;
error_code ec;
@ -5571,6 +5611,7 @@ namespace libtorrent
void torrent::second_tick(stat& accumulator, int tick_interval_ms)
{
TORRENT_ASSERT(m_ses.is_network_thread());
INVARIANT_CHECK;
ptime now = time_now();
@ -5749,6 +5790,7 @@ namespace libtorrent
void torrent::refresh_explicit_cache(int cache_size)
{
TORRENT_ASSERT(m_ses.is_network_thread());
if (!ready_for_connections()) return;
// rotate the cached pieces
@ -5835,6 +5877,7 @@ namespace libtorrent
void torrent::get_suggested_pieces(std::vector<int>& s) const
{
TORRENT_ASSERT(m_ses.is_network_thread());
if (settings().suggest_mode == session_settings::no_piece_suggestions)
{
s.clear();
@ -5869,6 +5912,7 @@ namespace libtorrent
void torrent::add_stats(stat const& s)
{
TORRENT_ASSERT(m_ses.is_network_thread());
// these stats are propagated to the session
// stats the next time second_tick is called
m_stat += s;
@ -5876,6 +5920,7 @@ namespace libtorrent
void torrent::request_time_critical_pieces()
{
TORRENT_ASSERT(m_ses.is_network_thread());
// build a list of peers and sort it by download_queue_time
std::vector<peer_connection*> peers;
peers.reserve(m_connections.size());
@ -5975,6 +6020,7 @@ namespace libtorrent
std::set<std::string> torrent::web_seeds(web_seed_entry::type_t type) const
{
TORRENT_ASSERT(m_ses.is_network_thread());
std::set<std::string> ret;
for (std::list<web_seed_entry>::const_iterator i = m_web_seeds.begin()
, end(m_web_seeds.end()); i != end; ++i)
@ -5987,6 +6033,7 @@ namespace libtorrent
void torrent::retry_web_seed(peer_connection* p, int retry)
{
TORRENT_ASSERT(m_ses.is_network_thread());
std::list<web_seed_entry>::iterator i = std::find_if(m_web_seeds.begin(), m_web_seeds.end()
, (boost::bind(&web_seed_entry::connection, _1) == p));
@ -5998,6 +6045,7 @@ namespace libtorrent
bool torrent::try_connect_peer()
{
TORRENT_ASSERT(m_ses.is_network_thread());
TORRENT_ASSERT(want_more_peers());
if (m_deficit_counter < 100) return false;
m_deficit_counter -= 100;
@ -6007,14 +6055,23 @@ namespace libtorrent
void torrent::give_connect_points(int points)
{
TORRENT_ASSERT(m_ses.is_network_thread());
TORRENT_ASSERT(points <= 100);
TORRENT_ASSERT(points > 0);
TORRENT_ASSERT(want_more_peers());
m_deficit_counter += points;
}
void torrent::add_peer(tcp::endpoint const& adr, int source)
{
TORRENT_ASSERT(m_ses.is_network_thread());
peer_id id(0);
m_policy.add_peer(adr, id, source, 0);
}
void torrent::async_verify_piece(int piece_index, boost::function<void(int)> const& f)
{
TORRENT_ASSERT(m_ses.is_network_thread());
// INVARIANT_CHECK;
TORRENT_ASSERT(m_storage);
@ -6044,7 +6101,7 @@ namespace libtorrent
void torrent::on_piece_verified(int ret, disk_io_job const& j
, boost::function<void(int)> f)
{
mutex::scoped_lock l(m_ses.m_mutex);
TORRENT_ASSERT(m_ses.is_network_thread());
// return value:
// 0: success, piece passed hash check
@ -6472,7 +6529,7 @@ namespace libtorrent
, int response_code, error_code const& ec, const std::string& msg
, int retry_interval)
{
mutex::scoped_lock l(m_ses.m_mutex);
TORRENT_ASSERT(m_ses.is_network_thread());
INVARIANT_CHECK;

View File

@ -61,6 +61,7 @@ POSSIBILITY OF SUCH DAMAGE.
#include "libtorrent/aux_/session_impl.hpp"
#include "libtorrent/invariant_check.hpp"
#include "libtorrent/utf8.hpp"
#include "libtorrent/thread.hpp"
#if defined(_MSC_VER) && _MSC_VER < 1300
namespace std
@ -72,50 +73,124 @@ namespace std
using libtorrent::aux::session_impl;
#ifdef BOOST_NO_EXCEPTIONS
#define TORRENT_FORWARD(call) \
boost::shared_ptr<torrent> t = m_torrent.lock(); \
if (!t) return; \
mutex::scoped_lock l(t->session().m_mutex); \
t->call
#define TORRENT_FORWARD_RETURN(call, def) \
boost::shared_ptr<torrent> t = m_torrent.lock(); \
if (!t) return def; \
mutex::scoped_lock l(t->session().m_mutex); \
return t->call
#define TORRENT_FORWARD_RETURN2(call, def) \
boost::shared_ptr<torrent> t = m_torrent.lock(); \
if (!t) return def; \
mutex::scoped_lock l(t->session().m_mutex); \
t->call
#else
#define TORRENT_FORWARD(call) \
boost::shared_ptr<torrent> t = m_torrent.lock(); \
if (!t) throw_invalid_handle(); \
mutex::scoped_lock l(t->session().m_mutex); \
t->call
#define TORRENT_FORWARD_RETURN(call, def) \
boost::shared_ptr<torrent> t = m_torrent.lock(); \
if (!t) throw_invalid_handle(); \
mutex::scoped_lock l(t->session().m_mutex); \
return t->call
#define TORRENT_FORWARD_RETURN2(call, def) \
boost::shared_ptr<torrent> t = m_torrent.lock(); \
if (!t) throw_invalid_handle(); \
mutex::scoped_lock l(t->session().m_mutex); \
t->call
#endif
namespace libtorrent
{
template <class R>
void fun_ret(R* ret, bool* done, condition* e, mutex* m, boost::function<R(void)> f)
{
*ret = f();
mutex::scoped_lock l(*m);
*done = true;
e->signal(l);
}
// defined in session.cpp
void fun_wrap(bool* done, condition* e, mutex* m, boost::function<void(void)> f);
#define TORRENT_ASYNC_CALL(x) \
boost::shared_ptr<torrent> t = m_torrent.lock(); \
if (!t) return; \
session_impl& ses = t->session(); \
ses.m_io_service.post(boost::bind(&torrent:: x, t))
#define TORRENT_ASYNC_CALL1(x, a1) \
boost::shared_ptr<torrent> t = m_torrent.lock(); \
if (!t) return; \
session_impl& ses = t->session(); \
ses.m_io_service.post(boost::bind(&torrent:: x, t, a1))
#define TORRENT_ASYNC_CALL2(x, a1, a2) \
boost::shared_ptr<torrent> t = m_torrent.lock(); \
if (!t) return; \
session_impl& ses = t->session(); \
ses.m_io_service.post(boost::bind(&torrent:: x, t, a1, a2))
#define TORRENT_ASYNC_CALL3(x, a1, a2, a3) \
boost::shared_ptr<torrent> t = m_torrent.lock(); \
if (!t) return; \
session_impl& ses = t->session(); \
ses.m_io_service.post(boost::bind(&torrent:: x, t, a1, a2, a3))
#define TORRENT_SYNC_CALL(x) \
boost::shared_ptr<torrent> t = m_torrent.lock(); \
if (!t) return; \
bool done = false; \
session_impl& ses = t->session(); \
mutex::scoped_lock l(ses.mut); \
ses.cond.clear(l); \
ses.m_io_service.post(boost::bind(&fun_wrap, &done, &ses.cond, &ses.mut, boost::function<void(void)>(boost::bind(&torrent:: x, t)))); \
do { ses.cond.wait(l); } while(!done)
#define TORRENT_SYNC_CALL1(x, a1) \
boost::shared_ptr<torrent> t = m_torrent.lock(); \
if (t) { \
bool done = false; \
session_impl& ses = t->session(); \
mutex::scoped_lock l(ses.mut); \
ses.cond.clear(l); \
ses.m_io_service.post(boost::bind(&fun_wrap, &done, &ses.cond, &ses.mut, boost::function<void(void)>(boost::bind(&torrent:: x, t, a1)))); \
t.reset(); \
do { ses.cond.wait(l); } while(!done); }
#define TORRENT_SYNC_CALL2(x, a1, a2) \
boost::shared_ptr<torrent> t = m_torrent.lock(); \
if (t) { \
bool done = false; \
session_impl& ses = t->session(); \
mutex::scoped_lock l(ses.mut); \
ses.cond.clear(l); \
ses.m_io_service.post(boost::bind(&fun_wrap, &done, &ses.cond, &ses.mut, boost::function<void(void)>(boost::bind(&torrent:: x, t, a1, a2)))); \
t.reset(); \
do { ses.cond.wait(l); } while(!done); }
#define TORRENT_SYNC_CALL3(x, a1, a2, a3) \
boost::shared_ptr<torrent> t = m_torrent.lock(); \
if (t) { \
bool done = false; \
session_impl& ses = t->session(); \
mutex::scoped_lock l(ses.mut); \
ses.cond.clear(l); \
ses.m_io_service.post(boost::bind(&fun_wrap, &done, &ses.cond, &ses.mut, boost::function<void(void)>(boost::bind(&torrent:: x, t, a1, a2, a3)))); \
t.reset(); \
do { ses.cond.wait(l); } while(!done); }
#define TORRENT_SYNC_CALL_RET(type, def, x) \
boost::shared_ptr<torrent> t = m_torrent.lock(); \
if (!t) return def; \
bool done = false; \
session_impl& ses = t->session(); \
type r; \
mutex::scoped_lock l(ses.mut); \
ses.cond.clear(l); \
ses.m_io_service.post(boost::bind(&fun_ret<type>, &r, &done, &ses.cond, &ses.mut, boost::function<type(void)>(boost::bind(&torrent:: x, t)))); \
t.reset(); \
do { ses.cond.wait(l); } while(!done)
#define TORRENT_SYNC_CALL_RET1(type, def, x, a1) \
boost::shared_ptr<torrent> t = m_torrent.lock(); \
if (!t) return def; \
bool done = false; \
session_impl& ses = t->session(); \
type r; \
mutex::scoped_lock l(ses.mut); \
ses.cond.clear(l); \
ses.m_io_service.post(boost::bind(&fun_ret<type>, &r, &done, &ses.cond, &ses.mut, boost::function<type(void)>(boost::bind(&torrent:: x, t, a1)))); \
t.reset(); \
do { ses.cond.wait(l); } while(!done)
#define TORRENT_SYNC_CALL_RET2(type, def, x, a1, a2) \
boost::shared_ptr<torrent> t = m_torrent.lock(); \
if (!t) return def; \
bool done = false; \
session_impl& ses = t->session(); \
type r; \
mutex::scoped_lock l(ses.mut); \
ses.cond.clear(l); \
ses.m_io_service.post(boost::bind(&fun_ret<type>, &r, &done, &ses.cond, &ses.mut, boost::function<type(void)>(boost::bind(&torrent:: x, t, a1, a2)))); \
t.reset(); \
do { ses.cond.wait(l); } while(!done)
#ifndef BOOST_NO_EXCEPTIONS
void throw_invalid_handle()
{
@ -134,86 +209,91 @@ namespace libtorrent
{
INVARIANT_CHECK;
const static sha1_hash empty;
TORRENT_FORWARD_RETURN(torrent_file().info_hash(), empty);
TORRENT_SYNC_CALL_RET(sha1_hash, empty, info_hash);
return r;
}
int torrent_handle::max_uploads() const
{
INVARIANT_CHECK;
TORRENT_FORWARD_RETURN(max_uploads(), 0);
TORRENT_SYNC_CALL_RET(int, 0, max_uploads);
return r;
}
void torrent_handle::set_max_uploads(int max_uploads) const
{
INVARIANT_CHECK;
TORRENT_ASSERT(max_uploads >= 2 || max_uploads == -1);
TORRENT_FORWARD(set_max_uploads(max_uploads));
TORRENT_ASYNC_CALL1(set_max_uploads, max_uploads);
}
void torrent_handle::use_interface(const char* net_interface) const
{
INVARIANT_CHECK;
TORRENT_FORWARD(use_interface(net_interface));
TORRENT_ASYNC_CALL1(use_interface, std::string(net_interface));
}
int torrent_handle::max_connections() const
{
INVARIANT_CHECK;
TORRENT_FORWARD_RETURN(max_connections(), 0);
TORRENT_SYNC_CALL_RET(int, 0, max_connections);
return r;
}
void torrent_handle::set_max_connections(int max_connections) const
{
INVARIANT_CHECK;
TORRENT_ASSERT(max_connections >= 2 || max_connections == -1);
TORRENT_FORWARD(set_max_connections(max_connections));
TORRENT_ASYNC_CALL1(set_max_connections, max_connections);
}
void torrent_handle::set_peer_upload_limit(tcp::endpoint ip, int limit) const
{
INVARIANT_CHECK;
TORRENT_ASSERT(limit >= -1);
TORRENT_FORWARD(set_peer_upload_limit(ip, limit));
TORRENT_ASYNC_CALL2(set_peer_upload_limit, ip, limit);
}
void torrent_handle::set_peer_download_limit(tcp::endpoint ip, int limit) const
{
INVARIANT_CHECK;
TORRENT_ASSERT(limit >= -1);
TORRENT_FORWARD(set_peer_download_limit(ip, limit));
TORRENT_ASYNC_CALL2(set_peer_download_limit, ip, limit);
}
void torrent_handle::set_upload_limit(int limit) const
{
INVARIANT_CHECK;
TORRENT_ASSERT(limit >= -1);
TORRENT_FORWARD(set_upload_limit(limit));
TORRENT_ASYNC_CALL1(set_upload_limit, limit);
}
int torrent_handle::upload_limit() const
{
INVARIANT_CHECK;
TORRENT_FORWARD_RETURN(upload_limit(), 0);
TORRENT_SYNC_CALL_RET(int, 0, upload_limit);
return r;
}
void torrent_handle::set_download_limit(int limit) const
{
INVARIANT_CHECK;
TORRENT_ASSERT(limit >= -1);
TORRENT_FORWARD(set_download_limit(limit));
TORRENT_ASYNC_CALL1(set_download_limit, limit);
}
int torrent_handle::download_limit() const
{
INVARIANT_CHECK;
TORRENT_FORWARD_RETURN(download_limit(), 0);
TORRENT_SYNC_CALL_RET(int, 0, download_limit);
return r;
}
void torrent_handle::move_storage(
std::string const& save_path) const
{
INVARIANT_CHECK;
TORRENT_FORWARD(move_storage(save_path));
TORRENT_ASYNC_CALL1(move_storage, save_path);
}
#if TORRENT_USE_WSTRING
@ -223,7 +303,7 @@ namespace libtorrent
INVARIANT_CHECK;
std::string utf8;
wchar_utf8(save_path, utf8);
TORRENT_FORWARD(move_storage(utf8));
TORRENT_ASYNC_CALL1(move_storage, utf8);
}
void torrent_handle::rename_file(int index, std::wstring const& new_name) const
@ -231,14 +311,14 @@ namespace libtorrent
INVARIANT_CHECK;
std::string utf8;
wchar_utf8(new_name, utf8);
TORRENT_FORWARD(rename_file(index, utf8));
TORRENT_ASYNC_CALL2(rename_file, index, utf8);
}
#endif // TORRENT_USE_WSTRING
void torrent_handle::rename_file(int index, std::string const& new_name) const
{
INVARIANT_CHECK;
TORRENT_FORWARD(rename_file(index, new_name));
TORRENT_ASYNC_CALL2(rename_file, index, new_name);
}
void torrent_handle::add_extension(
@ -246,141 +326,148 @@ namespace libtorrent
, void* userdata)
{
INVARIANT_CHECK;
TORRENT_FORWARD(add_extension(ext, userdata));
TORRENT_ASYNC_CALL2(add_extension, ext, userdata);
}
bool torrent_handle::has_metadata() const
{
INVARIANT_CHECK;
TORRENT_FORWARD_RETURN(valid_metadata(), false);
TORRENT_SYNC_CALL_RET(bool, false, valid_metadata);
return r;
}
bool torrent_handle::set_metadata(char const* metadata, int size) const
{
INVARIANT_CHECK;
TORRENT_FORWARD_RETURN(set_metadata(metadata, size), false);
TORRENT_SYNC_CALL_RET2(bool, false, set_metadata, metadata, size);
return r;
}
bool torrent_handle::is_seed() const
{
INVARIANT_CHECK;
TORRENT_FORWARD_RETURN(is_seed(), false);
TORRENT_SYNC_CALL_RET(bool, false, is_seed);
return r;
}
bool torrent_handle::is_finished() const
{
INVARIANT_CHECK;
TORRENT_FORWARD_RETURN(is_finished(), false);
TORRENT_SYNC_CALL_RET(bool, false, is_finished);
return r;
}
bool torrent_handle::is_paused() const
{
INVARIANT_CHECK;
TORRENT_FORWARD_RETURN(is_torrent_paused(), false);
TORRENT_SYNC_CALL_RET(bool, false, is_torrent_paused);
return r;
}
void torrent_handle::pause() const
{
INVARIANT_CHECK;
TORRENT_FORWARD(pause());
TORRENT_ASYNC_CALL(pause);
}
void torrent_handle::set_upload_mode(bool b) const
{
INVARIANT_CHECK;
TORRENT_FORWARD(set_upload_mode(b));
TORRENT_ASYNC_CALL1(set_upload_mode, b);
}
void torrent_handle::flush_cache() const
{
INVARIANT_CHECK;
TORRENT_FORWARD(flush_cache());
TORRENT_ASYNC_CALL(flush_cache);
}
void torrent_handle::save_resume_data() const
{
INVARIANT_CHECK;
TORRENT_FORWARD(save_resume_data());
TORRENT_ASYNC_CALL(save_resume_data);
}
bool torrent_handle::need_save_resume_data() const
{
INVARIANT_CHECK;
TORRENT_FORWARD_RETURN(need_save_resume_data(), false);
TORRENT_SYNC_CALL_RET(bool, false, need_save_resume_data);
return r;
}
void torrent_handle::force_recheck() const
{
INVARIANT_CHECK;
TORRENT_FORWARD(force_recheck());
TORRENT_ASYNC_CALL(force_recheck);
}
void torrent_handle::resume() const
{
INVARIANT_CHECK;
TORRENT_FORWARD(resume());
TORRENT_ASYNC_CALL(resume);
}
bool torrent_handle::is_auto_managed() const
{
INVARIANT_CHECK;
TORRENT_FORWARD_RETURN(is_auto_managed(), true);
TORRENT_SYNC_CALL_RET(bool, false, is_auto_managed);
return r;
}
void torrent_handle::auto_managed(bool m) const
{
INVARIANT_CHECK;
TORRENT_FORWARD(auto_managed(m));
TORRENT_ASYNC_CALL1(auto_managed, m);
}
void torrent_handle::set_priority(int p) const
{
INVARIANT_CHECK;
TORRENT_FORWARD(set_priority(p));
TORRENT_ASYNC_CALL1(set_priority, p);
}
int torrent_handle::queue_position() const
{
INVARIANT_CHECK;
TORRENT_FORWARD_RETURN(queue_position(), -1);
TORRENT_SYNC_CALL_RET(int, -1, queue_position);
return r;
}
void torrent_handle::queue_position_up() const
{
INVARIANT_CHECK;
TORRENT_FORWARD(set_queue_position(t->queue_position() == 0
? t->queue_position() : t->queue_position() - 1));
TORRENT_ASYNC_CALL(queue_down);
}
void torrent_handle::queue_position_down() const
{
INVARIANT_CHECK;
TORRENT_FORWARD(set_queue_position(t->queue_position() + 1));
TORRENT_ASYNC_CALL(queue_up);
}
void torrent_handle::queue_position_top() const
{
INVARIANT_CHECK;
TORRENT_FORWARD(set_queue_position(0));
TORRENT_ASYNC_CALL1(set_queue_position, 0);
}
void torrent_handle::queue_position_bottom() const
{
INVARIANT_CHECK;
TORRENT_FORWARD(set_queue_position((std::numeric_limits<int>::max)()));
TORRENT_ASYNC_CALL1(set_queue_position, INT_MAX);
}
void torrent_handle::clear_error() const
{
INVARIANT_CHECK;
TORRENT_FORWARD(clear_error());
TORRENT_ASYNC_CALL(clear_error);
}
void torrent_handle::set_tracker_login(std::string const& name
, std::string const& password) const
{
INVARIANT_CHECK;
TORRENT_FORWARD(set_tracker_login(name, password));
TORRENT_ASYNC_CALL2(set_tracker_login, name, password);
}
#ifndef TORRENT_NO_DEPRECATE
@ -388,7 +475,7 @@ namespace libtorrent
void torrent_handle::file_progress(std::vector<float>& progress) const
{
INVARIANT_CHECK;
TORRENT_FORWARD(file_progress(progress));
TORRENT_SYNC_CALL1(file_progress, boost::ref(progress));
}
#endif
#endif
@ -396,88 +483,93 @@ namespace libtorrent
void torrent_handle::file_progress(std::vector<size_type>& progress, int flags) const
{
INVARIANT_CHECK;
TORRENT_FORWARD(file_progress(progress, flags));
TORRENT_SYNC_CALL2(file_progress, boost::ref(progress), flags);
}
torrent_status torrent_handle::status(boost::uint32_t flags) const
{
INVARIANT_CHECK;
TORRENT_FORWARD_RETURN(status(flags), torrent_status());
TORRENT_SYNC_CALL_RET1(torrent_status, torrent_status(), status, flags);
return r;
}
void torrent_handle::set_sequential_download(bool sd) const
{
INVARIANT_CHECK;
TORRENT_FORWARD(set_sequential_download(sd));
TORRENT_ASYNC_CALL1(set_sequential_download, sd);
}
bool torrent_handle::is_sequential_download() const
{
INVARIANT_CHECK;
TORRENT_FORWARD_RETURN(is_sequential_download(), false);
TORRENT_SYNC_CALL_RET(bool, false, is_sequential_download);
return r;
}
std::string torrent_handle::name() const
{
INVARIANT_CHECK;
TORRENT_FORWARD_RETURN(name(), "");
TORRENT_SYNC_CALL_RET(std::string, "", name);
return r;
}
void torrent_handle::piece_availability(std::vector<int>& avail) const
{
INVARIANT_CHECK;
TORRENT_FORWARD(piece_availability(avail));
TORRENT_SYNC_CALL1(piece_availability, boost::ref(avail));
}
void torrent_handle::piece_priority(int index, int priority) const
{
INVARIANT_CHECK;
TORRENT_FORWARD(set_piece_priority(index, priority));
TORRENT_ASYNC_CALL2(set_piece_priority, index, priority);
}
int torrent_handle::piece_priority(int index) const
{
INVARIANT_CHECK;
TORRENT_FORWARD_RETURN(piece_priority(index), 0);
TORRENT_SYNC_CALL_RET1(int, 0, piece_priority, index);
return r;
}
void torrent_handle::prioritize_pieces(std::vector<int> const& pieces) const
{
INVARIANT_CHECK;
TORRENT_FORWARD(prioritize_pieces(pieces));
TORRENT_ASYNC_CALL1(prioritize_pieces, pieces);
}
std::vector<int> torrent_handle::piece_priorities() const
{
INVARIANT_CHECK;
std::vector<int> ret;
TORRENT_FORWARD_RETURN2(piece_priorities(ret), ret);
TORRENT_SYNC_CALL1(piece_priorities, boost::ref(ret));
return ret;
}
void torrent_handle::file_priority(int index, int priority) const
{
INVARIANT_CHECK;
TORRENT_FORWARD(set_file_priority(index, priority));
TORRENT_ASYNC_CALL2(set_file_priority, index, priority);
}
int torrent_handle::file_priority(int index) const
{
INVARIANT_CHECK;
TORRENT_FORWARD_RETURN(file_priority(index), 0);
TORRENT_SYNC_CALL_RET1(int, 0, file_priority, index);
return r;
}
void torrent_handle::prioritize_files(std::vector<int> const& files) const
{
INVARIANT_CHECK;
TORRENT_FORWARD(prioritize_files(files));
TORRENT_ASYNC_CALL1(prioritize_files, files);
}
std::vector<int> torrent_handle::file_priorities() const
{
INVARIANT_CHECK;
std::vector<int> ret;
TORRENT_FORWARD_RETURN2(file_priorities(ret), ret);
TORRENT_SYNC_CALL1(file_priorities, ret);
return ret;
}
@ -487,33 +579,34 @@ namespace libtorrent
void torrent_handle::filter_piece(int index, bool filter) const
{
INVARIANT_CHECK;
TORRENT_FORWARD(filter_piece(index, filter));
TORRENT_ASYNC_CALL2(filter_piece, index, filter);
}
void torrent_handle::filter_pieces(std::vector<bool> const& pieces) const
{
INVARIANT_CHECK;
TORRENT_FORWARD(filter_pieces(pieces));
TORRENT_ASYNC_CALL1(filter_pieces, pieces);
}
bool torrent_handle::is_piece_filtered(int index) const
{
INVARIANT_CHECK;
TORRENT_FORWARD_RETURN(is_piece_filtered(index), false);
TORRENT_SYNC_CALL_RET1(bool, false, is_piece_filtered, index);
return r;
}
std::vector<bool> torrent_handle::filtered_pieces() const
{
INVARIANT_CHECK;
std::vector<bool> ret;
TORRENT_FORWARD_RETURN2(filtered_pieces(ret), ret);
TORRENT_SYNC_CALL1(filtered_pieces, ret);
return ret;
}
void torrent_handle::filter_files(std::vector<bool> const& files) const
{
INVARIANT_CHECK;
TORRENT_FORWARD(filter_files(files));
TORRENT_ASYNC_CALL1(filter_files, files);
}
// ============ end deprecation ===============
@ -523,76 +616,80 @@ namespace libtorrent
{
INVARIANT_CHECK;
const static std::vector<announce_entry> empty;
TORRENT_FORWARD_RETURN(trackers(), empty);
TORRENT_SYNC_CALL_RET(std::vector<announce_entry>, empty, trackers);
return r;
}
void torrent_handle::add_url_seed(std::string const& url) const
{
INVARIANT_CHECK;
TORRENT_FORWARD(add_web_seed(url, web_seed_entry::url_seed));
TORRENT_ASYNC_CALL2(add_web_seed, url, web_seed_entry::url_seed);
}
void torrent_handle::remove_url_seed(std::string const& url) const
{
INVARIANT_CHECK;
TORRENT_FORWARD(remove_web_seed(url, web_seed_entry::url_seed));
TORRENT_ASYNC_CALL2(remove_web_seed, url, web_seed_entry::url_seed);
}
std::set<std::string> torrent_handle::url_seeds() const
{
INVARIANT_CHECK;
const static std::set<std::string> empty;
TORRENT_FORWARD_RETURN(web_seeds(web_seed_entry::url_seed), empty);
TORRENT_SYNC_CALL_RET1(std::set<std::string>, empty, web_seeds, web_seed_entry::url_seed);
return r;
}
void torrent_handle::add_http_seed(std::string const& url) const
{
INVARIANT_CHECK;
TORRENT_FORWARD(add_web_seed(url, web_seed_entry::http_seed));
TORRENT_ASYNC_CALL2(add_web_seed, url, web_seed_entry::http_seed);
}
void torrent_handle::remove_http_seed(std::string const& url) const
{
INVARIANT_CHECK;
TORRENT_FORWARD(remove_web_seed(url, web_seed_entry::http_seed));
TORRENT_ASYNC_CALL2(remove_web_seed, url, web_seed_entry::http_seed);
}
std::set<std::string> torrent_handle::http_seeds() const
{
INVARIANT_CHECK;
const static std::set<std::string> empty;
TORRENT_FORWARD_RETURN(web_seeds(web_seed_entry::http_seed), empty);
TORRENT_SYNC_CALL_RET1(std::set<std::string>, empty, web_seeds, web_seed_entry::http_seed);
return r;
}
void torrent_handle::replace_trackers(
std::vector<announce_entry> const& urls) const
{
INVARIANT_CHECK;
TORRENT_FORWARD(replace_trackers(urls));
TORRENT_ASYNC_CALL1(replace_trackers, urls);
}
void torrent_handle::add_tracker(announce_entry const& url) const
{
INVARIANT_CHECK;
TORRENT_FORWARD(add_tracker(url));
TORRENT_ASYNC_CALL1(add_tracker, url);
}
void torrent_handle::add_piece(int piece, char const* data, int flags) const
{
INVARIANT_CHECK;
TORRENT_FORWARD(add_piece(piece, data, flags));
TORRENT_SYNC_CALL3(add_piece, piece, data, flags);
}
void torrent_handle::read_piece(int piece) const
{
INVARIANT_CHECK;
TORRENT_FORWARD(read_piece(piece));
TORRENT_ASYNC_CALL1(read_piece, piece);
}
storage_interface* torrent_handle::get_storage_impl() const
{
INVARIANT_CHECK;
TORRENT_FORWARD_RETURN(get_storage(), 0);
TORRENT_SYNC_CALL_RET(storage_interface*, 0, get_storage);
return r;
}
torrent_info const& torrent_handle::get_torrent_info() const
@ -608,7 +705,7 @@ namespace libtorrent
#else
throw_invalid_handle();
#endif
mutex::scoped_lock l(t->session().m_mutex);
// mutex::scoped_lock l(t->session().m_mutex);
if (!t->valid_metadata())
#ifdef BOOST_NO_EXCEPTIONS
return empty;
@ -630,8 +727,18 @@ namespace libtorrent
INVARIANT_CHECK;
entry ret(entry::dictionary_t);
TORRENT_FORWARD_RETURN2(write_resume_data(ret), ret);
t->filesystem().write_resume_data(ret);
TORRENT_SYNC_CALL1(write_resume_data, boost::ref(ret));
if (t)
{
bool done = false;
session_impl& ses = t->session();
mutex::scoped_lock l(ses.mut);
ses.cond.clear(l);
ses.m_io_service.post(boost::bind(&fun_wrap, &done, &ses.cond
, &ses.mut, boost::function<void(void)>(boost::bind(
&piece_manager::write_resume_data, &t->filesystem(), boost::ref(ret)))));
do { ses.cond.wait(l); } while(!done);
}
return ret;
}
@ -640,64 +747,54 @@ namespace libtorrent
std::string torrent_handle::save_path() const
{
INVARIANT_CHECK;
TORRENT_FORWARD_RETURN(save_path(), std::string());
TORRENT_SYNC_CALL_RET(std::string, "", save_path);
return r;
}
void torrent_handle::connect_peer(tcp::endpoint const& adr, int source) const
{
INVARIANT_CHECK;
boost::shared_ptr<torrent> t = m_torrent.lock();
if (!t)
#ifdef BOOST_NO_EXCEPTIONS
return;
#else
throw_invalid_handle();
#endif
mutex::scoped_lock l(t->session().m_mutex);
peer_id id;
std::fill(id.begin(), id.end(), 0);
t->get_policy().add_peer(adr, id, source, 0);
TORRENT_ASYNC_CALL2(add_peer, adr, source);
}
void torrent_handle::force_reannounce(
boost::posix_time::time_duration duration) const
{
INVARIANT_CHECK;
TORRENT_FORWARD(force_tracker_request(time_now() + seconds(duration.total_seconds())));
TORRENT_ASYNC_CALL1(force_tracker_request, time_now() + seconds(duration.total_seconds()));
}
#ifndef TORRENT_DISABLE_DHT
void torrent_handle::force_dht_announce() const
{
INVARIANT_CHECK;
TORRENT_FORWARD(dht_announce());
TORRENT_ASYNC_CALL(dht_announce);
}
#endif
void torrent_handle::force_reannounce() const
{
INVARIANT_CHECK;
TORRENT_FORWARD(force_tracker_request());
TORRENT_ASYNC_CALL1(force_tracker_request, time_now());
}
void torrent_handle::scrape_tracker() const
{
INVARIANT_CHECK;
TORRENT_FORWARD(scrape_tracker());
TORRENT_ASYNC_CALL(scrape_tracker);
}
bool torrent_handle::super_seeding() const
{
INVARIANT_CHECK;
TORRENT_FORWARD_RETURN(super_seeding(), false);
TORRENT_SYNC_CALL_RET(bool, false, super_seeding);
return r;
}
void torrent_handle::super_seeding(bool on) const
{
INVARIANT_CHECK;
TORRENT_FORWARD(super_seeding(on));
TORRENT_ASYNC_CALL1(super_seeding, on);
}
void torrent_handle::set_ratio(float ratio) const
@ -707,45 +804,46 @@ namespace libtorrent
TORRENT_ASSERT(ratio >= 0.f);
if (ratio < 1.f && ratio > 0.f)
ratio = 1.f;
TORRENT_FORWARD(set_ratio(ratio));
TORRENT_ASYNC_CALL1(set_ratio, ratio);
}
#ifndef TORRENT_DISABLE_RESOLVE_COUNTRIES
void torrent_handle::resolve_countries(bool r)
{
INVARIANT_CHECK;
TORRENT_FORWARD(resolve_countries(r));
TORRENT_ASYNC_CALL1(resolve_countries, r);
}
bool torrent_handle::resolve_countries() const
{
INVARIANT_CHECK;
TORRENT_FORWARD_RETURN(resolving_countries(), false);
TORRENT_SYNC_CALL_RET(bool, false, resolving_countries);
return r;
}
#endif
void torrent_handle::get_full_peer_list(std::vector<peer_list_entry>& v) const
{
INVARIANT_CHECK;
TORRENT_FORWARD(get_full_peer_list(v));
TORRENT_SYNC_CALL1(get_full_peer_list, boost::ref(v));
}
void torrent_handle::get_peer_info(std::vector<peer_info>& v) const
{
INVARIANT_CHECK;
TORRENT_FORWARD(get_peer_info(v));
TORRENT_SYNC_CALL1(get_peer_info, boost::ref(v));
}
void torrent_handle::get_download_queue(std::vector<partial_piece_info>& queue) const
{
INVARIANT_CHECK;
TORRENT_FORWARD(get_download_queue(queue));
TORRENT_SYNC_CALL1(get_download_queue, boost::ref(queue));
}
void torrent_handle::set_piece_deadline(int index, int deadline, int flags) const
{
INVARIANT_CHECK;
TORRENT_FORWARD(set_piece_deadline(index, deadline, flags));
TORRENT_ASYNC_CALL3(set_piece_deadline, index, deadline, flags);
}
}

View File

@ -172,13 +172,13 @@ namespace libtorrent
void tracker_manager::sent_bytes(int bytes)
{
// mutex::scoped_lock l(m_ses.m_mutex);
TORRENT_ASSERT(m_ses.is_network_thread());
m_ses.m_stat.sent_tracker_bytes(bytes);
}
void tracker_manager::received_bytes(int bytes)
{
mutex::scoped_lock l(m_ses.m_mutex);
TORRENT_ASSERT(m_ses.is_network_thread());
m_ses.m_stat.received_tracker_bytes(bytes);
}

View File

@ -384,6 +384,7 @@ void run_elevator_test()
// this is not guaranteed, but very very likely
TEST_CHECK(turns > 20);
dio.abort();
dio.join();
}
}
@ -574,6 +575,7 @@ void run_storage_tests(boost::intrusive_ptr<torrent_info> info
ios.poll(ec);
if (ec) std::cerr << "poll: " << ec.message() << std::endl;
io.abort();
io.join();
remove_all(combine_path(test_path, "temp_storage2"), ec);
if (ec) std::cerr << "remove_all: " << ec.message() << std::endl;
@ -723,6 +725,7 @@ void test_check_files(std::string const& test_path
TEST_EQUAL(pieces[1], false);
TEST_EQUAL(pieces[2], false);
TEST_EQUAL(pieces[3], true);
io.abort();
io.join();
}

View File

@ -112,9 +112,9 @@ void test_rate()
}
void print_alert(alert const& a)
void print_alert(std::auto_ptr<alert>)
{
std::cout << "ses1 (alert dispatch function): " << a.message() << std::endl;
std::cout << "ses1 (alert dispatch function): "/* << a.message() */ << std::endl;
}
// simulate a full disk