extensions
@@ -1658,11 +1659,13 @@ struct torrent_handle
void piece_priority(int index, int priority) const;
int piece_priority(int index) const;
-
void prioritize_pieces(std::vector<int> const& pieces) const;
std::vector<int> piece_priorities() const;
+ void file_priority(int index, int priority) const;
+ int file_priority(int index) const;
void prioritize_files(std::vector<int> const& files) const;
+ std::vector<int> file_priorities() const;
bool is_auto_managed() const;
void auto_managed(bool m) const;
@@ -1692,14 +1695,13 @@ Since the torrents are processed by a background thread, there is no
guarantee that a handle will remain valid between two calls.
-
+
void piece_priority(int index, int priority) const;
int piece_priority(int index) const;
void prioritize_pieces(std::vector<int> const& pieces) const;
std::vector<int> piece_priorities() const;
-void prioritize_files(std::vector<int> const& files) const;
These functions are used to set and get the prioritiy of individual pieces.
@@ -1732,9 +1734,27 @@ the torrent. All the piece priorities will be updated with the priorities
in the vector.
piece_priorities returns a vector with one element for each piece in the
torrent. Each element is the current priority of that piece.
+
+
+
+
+
+void file_priority(int index, int priority) const;
+int file_priority(int index) const;
+void prioritize_files(std::vector<int> const& files) const;
+std::vector<int> file_priorities() const;
+
+
+
index must be in the range [0, number_of_files).
+
file_priority queries or sets the priority of file index.
prioritize_files takes a vector that has at as many elements as there are
files in the torrent. Each entry is the priority of that file. The function
sets the priorities of all the pieces in the torrent based on the vector.
+
file_priorities returns a vector with the priorities of all files.
+
The priority values are the same as for piece_priority.
+
Whenever a file priority is changed, all other piece priorities are reset
+to match the file priorities. In order to maintain sepcial priorities for
+particular pieces, piece_priority has to be called again for those pieces.
diff --git a/docs/manual.rst b/docs/manual.rst
index d5ae6fe86..9cf20a2aa 100644
--- a/docs/manual.rst
+++ b/docs/manual.rst
@@ -1574,11 +1574,13 @@ Its declaration looks like this::
void piece_priority(int index, int priority) const;
int piece_priority(int index) const;
-
void prioritize_pieces(std::vector
const& pieces) const;
std::vector piece_priorities() const;
+ void file_priority(int index, int priority) const;
+ int file_priority(int index) const;
void prioritize_files(std::vector const& files) const;
+ std::vector file_priorities() const;
bool is_auto_managed() const;
void auto_managed(bool m) const;
@@ -1607,8 +1609,8 @@ it will throw ``invalid_handle``.
guarantee that a handle will remain valid between two calls.
-piece_priority() prioritize_pieces() piece_priorities() prioritize_files()
---------------------------------------------------------------------------
+piece_priority() prioritize_pieces() piece_priorities()
+-------------------------------------------------------
::
@@ -1616,7 +1618,6 @@ piece_priority() prioritize_pieces() piece_priorities() prioritize_files()
int piece_priority(int index) const;
void prioritize_pieces(std::vector const& pieces) const;
std::vector piece_priorities() const;
- void prioritize_files(std::vector const& files) const;
These functions are used to set and get the prioritiy of individual pieces.
By default all pieces have priority 1. That means that the random rarest
@@ -1650,10 +1651,32 @@ in the vector.
``piece_priorities`` returns a vector with one element for each piece in the
torrent. Each element is the current priority of that piece.
+
+file_priority() prioritize_files() file_priorities()
+----------------------------------------------------
+
+ ::
+
+ void file_priority(int index, int priority) const;
+ int file_priority(int index) const;
+ void prioritize_files(std::vector const& files) const;
+ std::vector file_priorities() const;
+
+``index`` must be in the range [0, number_of_files).
+
+``file_priority`` queries or sets the priority of file ``index``.
+
``prioritize_files`` takes a vector that has at as many elements as there are
files in the torrent. Each entry is the priority of that file. The function
sets the priorities of all the pieces in the torrent based on the vector.
+``file_priorities`` returns a vector with the priorities of all files.
+
+The priority values are the same as for ``piece_priority``.
+
+Whenever a file priority is changed, all other piece priorities are reset
+to match the file priorities. In order to maintain sepcial priorities for
+particular pieces, ``piece_priority`` has to be called again for those pieces.
file_progress()
---------------
diff --git a/include/libtorrent/torrent.hpp b/include/libtorrent/torrent.hpp
index b99e2d775..d6a0f9dd3 100644
--- a/include/libtorrent/torrent.hpp
+++ b/include/libtorrent/torrent.hpp
@@ -235,7 +235,13 @@ namespace libtorrent
void prioritize_pieces(std::vector const& pieces);
void piece_priorities(std::vector&) const;
+ void set_file_priority(int index, int priority);
+ int file_priority(int index) const;
+
void prioritize_files(std::vector const& files);
+ void file_priorities(std::vector&) const;
+
+ void update_piece_priorities();
torrent_status status() const;
@@ -770,6 +776,8 @@ namespace libtorrent
// this torrent belongs to.
aux::session_impl& m_ses;
+ std::vector m_file_priority;
+
boost::scoped_ptr m_picker;
// the queue of peer_connections that want more bandwidth
diff --git a/include/libtorrent/torrent_handle.hpp b/include/libtorrent/torrent_handle.hpp
index a062580c2..b19b2a2a9 100644
--- a/include/libtorrent/torrent_handle.hpp
+++ b/include/libtorrent/torrent_handle.hpp
@@ -392,8 +392,12 @@ namespace libtorrent
void prioritize_pieces(std::vector const& pieces) const;
std::vector piece_priorities() const;
- void prioritize_files(std::vector const& files) const;
+ // priority must be within the range [0, 7]
+ void file_priority(int index, int priority) const;
+ int file_priority(int index) const;
+ void prioritize_files(std::vector const& files) const;
+ std::vector file_priorities() const;
// set the interface to bind outgoing connections
// to.
diff --git a/src/storage.cpp b/src/storage.cpp
index 96798db9c..ee29a958b 100644
--- a/src/storage.cpp
+++ b/src/storage.cpp
@@ -436,6 +436,7 @@ namespace libtorrent
boost::scoped_ptr m_mapped_files;
file_storage const& m_files;
+ std::vector m_file_priority;
fs::path m_save_path;
// the file pool is typically stored in
// the session, to make all storage
@@ -521,7 +522,10 @@ namespace libtorrent
#ifndef BOOST_NO_EXCEPTIONS
try {
#endif
- if (allocate_files)
+ // don't allocate files with priority 0
+ int file_index = file_iter - files().begin();
+ if (allocate_files && (m_file_priority.size() <= file_index
+ || m_file_priority[file_index] > 0))
{
error_code ec;
boost::shared_ptr f = m_pool.open_file(this
@@ -543,6 +547,7 @@ namespace libtorrent
}
#endif
}
+ std::vector().swap(m_file_priority);
// close files that were opened in write mode
m_pool.release(this);
return false;
@@ -702,6 +707,15 @@ namespace libtorrent
bool storage::verify_resume_data(lazy_entry const& rd, std::string& error)
{
+ lazy_entry const* file_priority = rd.dict_find_list("file_priority");
+ if (file_priority && file_priority->list_size()
+ == files().num_files())
+ {
+ m_file_priority.resize(file_priority->list_size());
+ for (int i = 0; i < file_priority->list_size(); ++i)
+ m_file_priority[i] = file_priority->list_int_value_at(i, 1);
+ }
+
lazy_entry const* mapped_files = rd.dict_find_list("mapped_files");
if (mapped_files && mapped_files->list_size() == m_files.num_files())
{
diff --git a/src/torrent.cpp b/src/torrent.cpp
index 3b82994de..d2e1b8064 100644
--- a/src/torrent.cpp
+++ b/src/torrent.cpp
@@ -424,6 +424,9 @@ namespace libtorrent
TORRENT_ASSERT(m_torrent_file->num_files() > 0);
TORRENT_ASSERT(m_torrent_file->total_size() >= 0);
+ m_file_priority.clear();
+ m_file_priority.resize(m_torrent_file->num_files(), 1);
+
m_block_size = (std::min)(m_block_size, m_torrent_file->piece_length());
if (m_torrent_file->num_pieces()
@@ -1771,17 +1774,49 @@ namespace libtorrent
// in the torrent
TORRENT_ASSERT(int(files.size()) == m_torrent_file->num_files());
- size_type position = 0;
-
if (m_torrent_file->num_pieces() == 0) return;
+ std::copy(files.begin(), files.end(), m_file_priority.begin());
+ update_piece_priorities();
+ }
+
+ void torrent::set_file_priority(int index, int prio)
+ {
+ INVARIANT_CHECK;
+ TORRENT_ASSERT(index < m_torrent_file->num_files());
+ TORRENT_ASSERT(index >= 0);
+ if (m_file_priority[index] == prio) return;
+ m_file_priority[index] = prio;
+ update_piece_priorities();
+ }
+
+ int torrent::file_priority(int index) const
+ {
+ TORRENT_ASSERT(index < m_torrent_file->num_files());
+ TORRENT_ASSERT(index >= 0);
+ return m_file_priority[index];
+ }
+
+ void torrent::file_priorities(std::vector& files) const
+ {
+ INVARIANT_CHECK;
+ files.resize(m_file_priority.size());
+ std::copy(m_file_priority.begin(), m_file_priority.end(), files.begin());
+ }
+
+ void torrent::update_piece_priorities()
+ {
+ INVARIANT_CHECK;
+
+ if (m_torrent_file->num_pieces() == 0) return;
bool was_finished = is_finished();
+ size_type position = 0;
int piece_length = m_torrent_file->piece_length();
// initialize the piece priorities to 0, then only allow
// setting higher priorities
std::vector pieces(m_torrent_file->num_pieces(), 0);
- for (int i = 0; i < int(files.size()); ++i)
+ for (int i = 0; i < int(m_file_priority.size()); ++i)
{
size_type start = position;
size_type size = m_torrent_file->files().at(i).size;
@@ -1792,12 +1827,12 @@ namespace libtorrent
// already set (to avoid problems with overlapping pieces)
int start_piece = int(start / piece_length);
int last_piece = int((position - 1) / piece_length);
- TORRENT_ASSERT(last_piece <= int(pieces.size()));
+ TORRENT_ASSERT(last_piece < int(pieces.size()));
// if one piece spans several files, we might
// come here several times with the same start_piece, end_piece
std::for_each(pieces.begin() + start_piece
, pieces.begin() + last_piece + 1
- , bind(&set_if_greater, _1, files[i]));
+ , bind(&set_if_greater, _1, m_file_priority[i]));
}
prioritize_pieces(pieces);
update_peer_interest(was_finished);
@@ -2442,6 +2477,14 @@ namespace libtorrent
set_max_connections(rd.dict_find_int_value("max_connections", -1));
set_max_uploads(rd.dict_find_int_value("max_uploads", -1));
+ lazy_entry const* file_priority = rd.dict_find_list("file_priority");
+ if (file_priority && file_priority->list_size()
+ == m_torrent_file->num_files())
+ {
+ for (int i = 0; i < file_priority->list_size(); ++i)
+ m_file_priority[i] = file_priority->list_int_value_at(i, 1);
+ update_piece_priorities();
+ }
lazy_entry const* piece_priority = rd.dict_find_string("piece_priority");
if (piece_priority && piece_priority->string_length()
== m_torrent_file->num_pieces())
@@ -2597,6 +2640,13 @@ namespace libtorrent
for (int i = 0, end(piece_priority.size()); i < end; ++i)
piece_priority[i] = m_picker->piece_priority(i);
}
+
+ // write file priorities
+ entry::list_type& file_priority = ret["file_priority"].list();
+ file_priority.clear();
+ for (int i = 0, end(m_file_priority.size()); i < end; ++i)
+ file_priority.push_back(m_file_priority[i]);
+
}
void torrent::get_full_peer_list(std::vector& v) const
diff --git a/src/torrent_handle.cpp b/src/torrent_handle.cpp
index 4b8d8a452..e9f179e32 100644
--- a/src/torrent_handle.cpp
+++ b/src/torrent_handle.cpp
@@ -400,12 +400,32 @@ namespace libtorrent
return ret;
}
+ void torrent_handle::file_priority(int index, int priority) const
+ {
+ INVARIANT_CHECK;
+ TORRENT_FORWARD(set_file_priority(index, priority));
+ }
+
+ int torrent_handle::file_priority(int index) const
+ {
+ INVARIANT_CHECK;
+ TORRENT_FORWARD_RETURN(file_priority(index), 0);
+ }
+
void torrent_handle::prioritize_files(std::vector const& files) const
{
INVARIANT_CHECK;
TORRENT_FORWARD(prioritize_files(files));
}
+ std::vector torrent_handle::file_priorities() const
+ {
+ INVARIANT_CHECK;
+ std::vector ret;
+ TORRENT_FORWARD_RETURN2(file_priorities(ret), ret);
+ return ret;
+ }
+
// ============ start deprecation ===============
void torrent_handle::filter_piece(int index, bool filter) const