optimized session::add_torrent() by putting more info in torrent_info, to make it possible to reproduce the exact info section from an torrent_info object. The result is that the .torrent file is only parsed once.
This commit is contained in:
parent
f770d1438d
commit
f63702c964
|
@ -1,10 +1,11 @@
|
|||
* greatly improved the command line control of the example client_test
|
||||
* fixed bug where upload rate limit was not being applied
|
||||
* changed the interface to session::add_torrent for soem speed optimizations.
|
||||
* greatly improved the command line control of the example client_test.
|
||||
* fixed bug where upload rate limit was not being applied.
|
||||
* files that are being checked will no longer stall files that don't need
|
||||
checking.
|
||||
* changed the way libtorrent identifies support for its excentions
|
||||
to look for 'ext' at the end of the peer-id.
|
||||
* improved performance by adding a circle buffer for the send buffer
|
||||
* improved performance by adding a circle buffer for the send buffer.
|
||||
* fixed bugs in the http tracker connection when using an http proxy.
|
||||
* fixed problem with storage's file pool when creating torrents and then
|
||||
starting to seed them.
|
||||
|
|
2
Jamfile
2
Jamfile
|
@ -36,7 +36,6 @@ project torrent
|
|||
<threading>multi
|
||||
<toolset>msvc:<cxxflags>/Zc:wchar_t
|
||||
<toolset>msvc:<cxxflags>/Zc:forScope
|
||||
<define>TORRENT_PROFILE
|
||||
|
||||
: usage-requirements
|
||||
|
||||
|
@ -44,7 +43,6 @@ project torrent
|
|||
<include>$(BOOST_ROOT)
|
||||
<variant>release:<define>NDEBUG
|
||||
<define>BOOST_ALL_NO_LIB
|
||||
<define>TORRENT_PROFILE
|
||||
|
||||
;
|
||||
|
||||
|
|
|
@ -555,7 +555,7 @@ class session: public boost::noncopyable
|
|||
, const char* listen_interface = 0);
|
||||
|
||||
torrent_handle add_torrent(
|
||||
entry const& e
|
||||
torrent_info const& ti
|
||||
, boost::filesystem::path const& save_path
|
||||
, entry const& resume_data = entry()
|
||||
, bool compact_mode = true
|
||||
|
@ -630,7 +630,7 @@ timeout can be set with <tt class="docutils literal"><span class="pre">set_http_
|
|||
<blockquote>
|
||||
<pre class="literal-block">
|
||||
torrent_handle add_torrent(
|
||||
entry const& e
|
||||
torrent_info const& ti
|
||||
, boost::filesystem::path const& save_path
|
||||
, entry const& resume_data = entry()
|
||||
, bool compact_mode = true
|
||||
|
@ -667,10 +667,10 @@ size is an even power of 2, so must the block size be. If the block size given h
|
|||
out to be greater than the piece size, it will simply be clamped to the piece size.</p>
|
||||
<p>The <a class="reference" href="#torrent-handle">torrent_handle</a> returned by <tt class="docutils literal"><span class="pre">add_torrent()</span></tt> can be used to retrieve information
|
||||
about the torrent's progress, its peers etc. It is also used to abort a torrent.</p>
|
||||
<p>The second overload that takes a tracker url and an info-hash instead of metadata (<tt class="docutils literal"><span class="pre">entry</span></tt>)
|
||||
can be used with torrents where (at least some) peers support the metadata extension. For
|
||||
the overload to be available, libtorrent must be built with extensions enabled
|
||||
(<tt class="docutils literal"><span class="pre">TORRENT_ENABLE_EXTENSIONS</span></tt> defined).</p>
|
||||
<p>The second overload that takes a tracker url and an info-hash instead of metadata
|
||||
(<tt class="docutils literal"><span class="pre">torrent_info</span></tt>) can be used with torrents where (at least some) peers support
|
||||
the metadata extension. For the overload to be available, libtorrent must be built
|
||||
with extensions enabled (<tt class="docutils literal"><span class="pre">TORRENT_ENABLE_EXTENSIONS</span></tt> defined).</p>
|
||||
</div>
|
||||
<div class="section" id="remove-torrent">
|
||||
<h2><a name="remove-torrent">remove_torrent()</a></h2>
|
||||
|
|
|
@ -433,7 +433,7 @@ The ``session`` class has the following synopsis::
|
|||
, const char* listen_interface = 0);
|
||||
|
||||
torrent_handle add_torrent(
|
||||
entry const& e
|
||||
torrent_info const& ti
|
||||
, boost::filesystem::path const& save_path
|
||||
, entry const& resume_data = entry()
|
||||
, bool compact_mode = true
|
||||
|
@ -512,7 +512,7 @@ add_torrent()
|
|||
::
|
||||
|
||||
torrent_handle add_torrent(
|
||||
entry const& e
|
||||
torrent_info const& ti
|
||||
, boost::filesystem::path const& save_path
|
||||
, entry const& resume_data = entry()
|
||||
, bool compact_mode = true
|
||||
|
@ -554,10 +554,10 @@ out to be greater than the piece size, it will simply be clamped to the piece si
|
|||
The torrent_handle_ returned by ``add_torrent()`` can be used to retrieve information
|
||||
about the torrent's progress, its peers etc. It is also used to abort a torrent.
|
||||
|
||||
The second overload that takes a tracker url and an info-hash instead of metadata (``entry``)
|
||||
can be used with torrents where (at least some) peers support the metadata extension. For
|
||||
the overload to be available, libtorrent must be built with extensions enabled
|
||||
(``TORRENT_ENABLE_EXTENSIONS`` defined).
|
||||
The second overload that takes a tracker url and an info-hash instead of metadata
|
||||
(``torrent_info``) can be used with torrents where (at least some) peers support
|
||||
the metadata extension. For the overload to be available, libtorrent must be built
|
||||
with extensions enabled (``TORRENT_ENABLE_EXTENSIONS`` defined).
|
||||
|
||||
remove_torrent()
|
||||
----------------
|
||||
|
|
|
@ -242,7 +242,7 @@ void print_peer_info(std::ostream& out, std::vector<libtorrent::peer_info> const
|
|||
{
|
||||
using namespace libtorrent;
|
||||
|
||||
out << " down up q r flags block progress client \n";
|
||||
out << " down (total) up (total) q r flags block progress client \n";
|
||||
|
||||
for (std::vector<peer_info>::const_iterator i = peers.begin();
|
||||
i != peers.end(); ++i)
|
||||
|
@ -289,7 +289,7 @@ void add_torrent(libtorrent::session& ses
|
|||
in.unsetf(std::ios_base::skipws);
|
||||
entry e = bdecode(std::istream_iterator<char>(in), std::istream_iterator<char>());
|
||||
torrent_info t(e);
|
||||
TORRENT_CHECKPOINT("-- load torrent");
|
||||
|
||||
std::cout << t.name() << "\n";
|
||||
|
||||
TORRENT_CHECKPOINT("++ load resumedata");
|
||||
|
@ -306,12 +306,17 @@ void add_torrent(libtorrent::session& ses
|
|||
}
|
||||
catch (invalid_encoding&) {}
|
||||
catch (boost::filesystem::filesystem_error&) {}
|
||||
TORRENT_CHECKPOINT("-- load resumedata");
|
||||
|
||||
handles.push_back(ses.add_torrent(e, save_path, resume_data, true, 16 * 1024));
|
||||
TORRENT_CHECKPOINT("++ ses::add_torrent");
|
||||
|
||||
handles.push_back(ses.add_torrent(t, save_path, resume_data, true, 16 * 1024));
|
||||
TORRENT_CHECKPOINT("-- ses::add_torrent");
|
||||
|
||||
handles.back().set_max_connections(60);
|
||||
handles.back().set_max_uploads(-1);
|
||||
handles.back().set_ratio(preferred_ratio);
|
||||
|
||||
TORRENT_CHECKPOINT("-- add_torrent");
|
||||
}
|
||||
|
||||
int main(int ac, char* av[])
|
||||
|
|
|
@ -58,20 +58,16 @@ int main(int argc, char* argv[])
|
|||
in.unsetf(std::ios_base::skipws);
|
||||
entry e = bdecode(std::istream_iterator<char>(in), std::istream_iterator<char>());
|
||||
|
||||
|
||||
|
||||
std::cout << "\n\n----- raw info -----\n\n";
|
||||
e.print(std::cout);
|
||||
|
||||
|
||||
torrent_info t(e);
|
||||
|
||||
// print info about torrent
|
||||
std::cout << "\n\n----- torrent file info -----\n\n";
|
||||
std::cout << "trackers:\n";
|
||||
for (std::vector<announce_entry>::const_iterator i = t.trackers().begin();
|
||||
i != t.trackers().end();
|
||||
++i)
|
||||
i != t.trackers().end(); ++i)
|
||||
{
|
||||
std::cout << i->tier << ": " << i->url << "\n";
|
||||
}
|
||||
|
|
|
@ -65,7 +65,7 @@ int main(int argc, char* argv[])
|
|||
std::ifstream in(argv[1], std::ios_base::binary);
|
||||
in.unsetf(std::ios_base::skipws);
|
||||
entry e = bdecode(std::istream_iterator<char>(in), std::istream_iterator<char>());
|
||||
s.add_torrent(e, "./");
|
||||
s.add_torrent(torrent_info(e), "./");
|
||||
|
||||
// wait for the user to end
|
||||
char a;
|
||||
|
|
|
@ -54,7 +54,6 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
#endif
|
||||
|
||||
#include "libtorrent/torrent_handle.hpp"
|
||||
//#include "libtorrent/torrent.hpp"
|
||||
#include "libtorrent/entry.hpp"
|
||||
#include "libtorrent/torrent_info.hpp"
|
||||
#include "libtorrent/socket.hpp"
|
||||
|
@ -317,12 +316,24 @@ namespace libtorrent
|
|||
|
||||
// all torrent_handles must be destructed before the session is destructed!
|
||||
torrent_handle add_torrent(
|
||||
entry const& metadata
|
||||
torrent_info const& ti
|
||||
, boost::filesystem::path const& save_path
|
||||
, entry const& resume_data = entry()
|
||||
, bool compact_mode = true
|
||||
, int block_size = 16 * 1024);
|
||||
|
||||
// TODO: depricated, this is for backwards compatibility only
|
||||
torrent_handle add_torrent(
|
||||
entry const& e
|
||||
, boost::filesystem::path const& save_path
|
||||
, entry const& resume_data = entry()
|
||||
, bool compact_mode = true
|
||||
, int block_size = 16 * 1024)
|
||||
{
|
||||
return add_torrent(torrent_info(e), save_path, resume_data
|
||||
, compact_mode, block_size);
|
||||
}
|
||||
|
||||
torrent_handle add_torrent(
|
||||
char const* tracker_url
|
||||
, sha1_hash const& info_hash
|
||||
|
|
|
@ -97,7 +97,6 @@ namespace libtorrent
|
|||
torrent(
|
||||
detail::session_impl& ses
|
||||
, detail::checker_impl& checker
|
||||
, entry const& metadata
|
||||
, torrent_info const& tf
|
||||
, boost::filesystem::path const& save_path
|
||||
, address const& net_interface
|
||||
|
@ -386,7 +385,7 @@ namespace libtorrent
|
|||
|
||||
bool valid_metadata() const
|
||||
{ return m_storage.get() != 0 && m_connections_initialized; }
|
||||
std::vector<char> const& metadata() const { return m_metadata; }
|
||||
std::vector<char> const& metadata() const;
|
||||
|
||||
bool received_metadata(
|
||||
char const* buf
|
||||
|
@ -524,7 +523,8 @@ namespace libtorrent
|
|||
// this buffer is filled with the info-section of
|
||||
// the metadata file while downloading it from
|
||||
// peers, and while sending it.
|
||||
std::vector<char> m_metadata;
|
||||
// it is mutable because it's generated lazily
|
||||
mutable std::vector<char> m_metadata;
|
||||
|
||||
// this is a bitfield of size 256, each bit represents
|
||||
// a piece of the metadata. It is set to one if we
|
||||
|
|
|
@ -91,7 +91,7 @@ namespace libtorrent
|
|||
torrent_info(entry const& torrent_file);
|
||||
~torrent_info();
|
||||
|
||||
entry create_torrent();
|
||||
entry create_torrent() const;
|
||||
entry create_info_metadata() const;
|
||||
void set_comment(char const* str);
|
||||
void set_creator(char const* str);
|
||||
|
@ -168,7 +168,9 @@ namespace libtorrent
|
|||
size_type m_total_size;
|
||||
|
||||
// the hash that identifies this torrent
|
||||
sha1_hash m_info_hash;
|
||||
// it is mutable because it's calculated
|
||||
// lazily
|
||||
mutable sha1_hash m_info_hash;
|
||||
|
||||
std::string m_name;
|
||||
|
||||
|
@ -191,6 +193,12 @@ namespace libtorrent
|
|||
// or not. e.g. test/test there's one file and one directory
|
||||
// and they have the same name.
|
||||
bool m_multifile;
|
||||
|
||||
// contains any non-parsed entries from the info-section
|
||||
// these are kept in order to be able to accurately
|
||||
// reproduce the info-section when sending the metadata
|
||||
// to peers.
|
||||
entry m_extra_info;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -651,9 +651,9 @@ namespace libtorrent
|
|||
assert(num_blocks > 0);
|
||||
|
||||
#ifdef TORRENT_VERBOSE_LOGGING
|
||||
std::ofstream f("piece_picker.log", std::ios_base::app);
|
||||
f << "backup_blocks: " << backup_blocks.size() << "\n"
|
||||
<< "used: " << std::min(num_blocks, (int)backup_blocks.size()) << "\n----\n";
|
||||
// std::ofstream f("piece_picker.log", std::ios_base::app);
|
||||
// f << "backup_blocks: " << backup_blocks.size() << "\n"
|
||||
// << "used: " << std::min(num_blocks, (int)backup_blocks.size()) << "\n----\n";
|
||||
#endif
|
||||
|
||||
interesting_blocks.insert(interesting_blocks.end()
|
||||
|
|
|
@ -382,6 +382,9 @@ namespace libtorrent { namespace detail
|
|||
{
|
||||
#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
|
||||
m_logger = create_log("main_session", false);
|
||||
using boost::posix_time::second_clock;
|
||||
using boost::posix_time::to_simple_string;
|
||||
(*m_logger) << to_simple_string(second_clock::universal_time()) << "\n";
|
||||
#endif
|
||||
std::fill(m_extension_enabled, m_extension_enabled
|
||||
+ peer_connection::num_supported_extensions, true);
|
||||
|
@ -1142,13 +1145,12 @@ namespace libtorrent
|
|||
// current platform.
|
||||
// if the torrent already exists, this will throw duplicate_torrent
|
||||
torrent_handle session::add_torrent(
|
||||
entry const& metadata
|
||||
torrent_info const& ti
|
||||
, boost::filesystem::path const& save_path
|
||||
, entry const& resume_data
|
||||
, bool compact_mode
|
||||
, int block_size)
|
||||
{
|
||||
TORRENT_CHECKPOINT("++ session::add_torrent()");
|
||||
// make sure the block_size is an even power of 2
|
||||
#ifndef NDEBUG
|
||||
for (int i = 0; i < 32; ++i)
|
||||
|
@ -1163,7 +1165,6 @@ namespace libtorrent
|
|||
|
||||
|
||||
assert(!save_path.empty());
|
||||
torrent_info ti(metadata);
|
||||
|
||||
if (ti.begin_files() == ti.end_files())
|
||||
throw std::runtime_error("no files in torrent");
|
||||
|
@ -1184,7 +1185,7 @@ namespace libtorrent
|
|||
// the checker thread and store it before starting
|
||||
// the thread
|
||||
boost::shared_ptr<torrent> torrent_ptr(
|
||||
new torrent(m_impl, m_checker_impl, metadata, ti, save_path
|
||||
new torrent(m_impl, m_checker_impl, ti, save_path
|
||||
, m_impl.m_listen_interface, compact_mode, block_size));
|
||||
|
||||
boost::shared_ptr<detail::piece_checker_data> d(
|
||||
|
@ -1200,7 +1201,6 @@ namespace libtorrent
|
|||
// job in its queue
|
||||
m_checker_impl.m_cond.notify_one();
|
||||
|
||||
TORRENT_CHECKPOINT("-- session::add_torrent()");
|
||||
return torrent_handle(&m_impl, &m_checker_impl, ti.info_hash());
|
||||
}
|
||||
|
||||
|
|
|
@ -182,7 +182,6 @@ namespace libtorrent
|
|||
torrent::torrent(
|
||||
detail::session_impl& ses
|
||||
, detail::checker_impl& checker
|
||||
, entry const& metadata
|
||||
, torrent_info const& tf
|
||||
, boost::filesystem::path const& save_path
|
||||
, address const& net_interface
|
||||
|
@ -246,7 +245,6 @@ namespace libtorrent
|
|||
m_ul_bandwidth_quota.min = 100;
|
||||
m_ul_bandwidth_quota.max = resource_request::inf;
|
||||
|
||||
|
||||
if (m_ses.m_upload_rate == -1)
|
||||
{
|
||||
m_ul_bandwidth_quota.given = resource_request::inf;
|
||||
|
@ -256,13 +254,7 @@ namespace libtorrent
|
|||
m_ul_bandwidth_quota.given = 400;
|
||||
}
|
||||
|
||||
|
||||
m_policy.reset(new policy(this));
|
||||
// if anything should be optimized in this constructor
|
||||
// this encoding should be made on demand. But that would
|
||||
// require the copying of the entry-tree instead, which
|
||||
// probably is more expensive
|
||||
bencode(std::back_inserter(m_metadata), metadata["info"]);
|
||||
init();
|
||||
}
|
||||
|
||||
|
@ -1340,6 +1332,14 @@ namespace libtorrent
|
|||
return m_tracker_address;
|
||||
}
|
||||
|
||||
std::vector<char> const& torrent::metadata() const
|
||||
{
|
||||
if (m_metadata.empty())
|
||||
bencode(std::back_inserter(m_metadata), m_torrent_file.create_torrent());
|
||||
assert(!m_metadata.empty());
|
||||
return m_metadata;
|
||||
}
|
||||
|
||||
torrent_status torrent::status() const
|
||||
{
|
||||
assert(std::accumulate(
|
||||
|
|
|
@ -436,8 +436,7 @@ namespace libtorrent
|
|||
entry::list_type& peer_list = ret["peers"].list();
|
||||
|
||||
for (torrent::const_peer_iterator i = t->begin();
|
||||
i != t->end();
|
||||
++i)
|
||||
i != t->end(); ++i)
|
||||
{
|
||||
// we cannot save remote connection
|
||||
// since we don't know their listen port
|
||||
|
|
|
@ -124,6 +124,7 @@ namespace libtorrent
|
|||
torrent_info::torrent_info(const entry& torrent_file)
|
||||
: m_creation_date(date(not_a_date_time))
|
||||
, m_multifile(false)
|
||||
, m_extra_info(entry::dictionary_t)
|
||||
{
|
||||
try
|
||||
{
|
||||
|
@ -146,6 +147,7 @@ namespace libtorrent
|
|||
, m_name()
|
||||
, m_creation_date(second_clock::universal_time())
|
||||
, m_multifile(false)
|
||||
, m_extra_info(entry::dictionary_t)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -156,6 +158,7 @@ namespace libtorrent
|
|||
, m_name()
|
||||
, m_creation_date(second_clock::universal_time())
|
||||
, m_multifile(false)
|
||||
, m_extra_info(entry::dictionary_t)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -251,6 +254,24 @@ namespace libtorrent
|
|||
hash_string.begin() + i*20
|
||||
, hash_string.begin() + (i+1)*20
|
||||
, m_piece_hash[i].begin());
|
||||
|
||||
for (entry::dictionary_type::const_iterator i = info.dict().begin()
|
||||
, end(info.dict().end()); i != end; ++i)
|
||||
{
|
||||
if (i->first == "pieces"
|
||||
|| i->first == "piece length"
|
||||
|| i->first == "length")
|
||||
continue;
|
||||
m_extra_info[i->first] = i->second;
|
||||
}
|
||||
|
||||
#ifndef NDEBUG
|
||||
std::vector<char> info_section_buf;
|
||||
entry gen_info_section = create_info_metadata();
|
||||
bencode(std::back_inserter(info_section_buf), gen_info_section);
|
||||
assert(hasher(&info_section_buf[0], info_section_buf.size()).final()
|
||||
== m_info_hash);
|
||||
#endif
|
||||
}
|
||||
|
||||
// extracts information from a libtorrent file and fills in the structures in
|
||||
|
@ -405,35 +426,40 @@ namespace libtorrent
|
|||
// you have to add files to the torrent first
|
||||
assert(!m_files.empty());
|
||||
|
||||
entry info(entry::dictionary_t);
|
||||
entry info(m_extra_info);
|
||||
|
||||
if (!info.find_key("name"))
|
||||
info["name"] = m_name;
|
||||
|
||||
info["name"] = m_name;
|
||||
if (!m_multifile)
|
||||
{
|
||||
info["length"] = m_files.front().size;
|
||||
}
|
||||
else
|
||||
{
|
||||
entry& files = info["files"];
|
||||
files = entry(entry::list_t);
|
||||
|
||||
for (std::vector<file_entry>::const_iterator i = m_files.begin();
|
||||
i != m_files.end(); ++i)
|
||||
if (!info.find_key("files"))
|
||||
{
|
||||
files.list().push_back(entry(entry::dictionary_t));
|
||||
entry& file_e = files.list().back();
|
||||
file_e["length"] = i->size;
|
||||
entry& path_e = file_e["path"];
|
||||
path_e = entry(entry::list_t);
|
||||
entry& files = info["files"];
|
||||
files = entry(entry::list_t);
|
||||
|
||||
fs::path const& file_path(i->path);
|
||||
assert(file_path.has_branch_path());
|
||||
assert(*file_path.begin() == m_name);
|
||||
|
||||
for (fs::path::iterator j = boost::next(file_path.begin());
|
||||
j != file_path.end(); ++j)
|
||||
for (std::vector<file_entry>::const_iterator i = m_files.begin();
|
||||
i != m_files.end(); ++i)
|
||||
{
|
||||
path_e.list().push_back(*j);
|
||||
files.list().push_back(entry(entry::dictionary_t));
|
||||
entry& file_e = files.list().back();
|
||||
file_e["length"] = i->size;
|
||||
entry& path_e = file_e["path"];
|
||||
path_e = entry(entry::list_t);
|
||||
|
||||
fs::path const& file_path(i->path);
|
||||
assert(file_path.has_branch_path());
|
||||
assert(*file_path.begin() == m_name);
|
||||
|
||||
for (fs::path::iterator j = boost::next(file_path.begin());
|
||||
j != file_path.end(); ++j)
|
||||
{
|
||||
path_e.list().push_back(*j);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -445,8 +471,7 @@ namespace libtorrent
|
|||
std::string& p = pieces.string();
|
||||
|
||||
for (std::vector<sha1_hash>::const_iterator i = m_piece_hash.begin();
|
||||
i != m_piece_hash.end();
|
||||
++i)
|
||||
i != m_piece_hash.end(); ++i)
|
||||
{
|
||||
p.append((char*)i->begin(), (char*)i->end());
|
||||
}
|
||||
|
@ -454,7 +479,7 @@ namespace libtorrent
|
|||
return info;
|
||||
}
|
||||
|
||||
entry torrent_info::create_torrent()
|
||||
entry torrent_info::create_torrent() const
|
||||
{
|
||||
assert(m_piece_length > 0);
|
||||
|
||||
|
|
Loading…
Reference in New Issue