diff --git a/ChangeLog b/ChangeLog index 51c060a35..47e8ab601 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,4 @@ + * deprecated compact storage allocation * close files in separate thread on systems where close() may block (Mac OS X for instance) * don't create all directories up front when adding torrents * support DHT scrape diff --git a/bindings/python/src/session.cpp b/bindings/python/src/session.cpp index 03e865e1e..9c6fb8fcb 100644 --- a/bindings/python/src/session.cpp +++ b/bindings/python/src/session.cpp @@ -431,7 +431,9 @@ void bind_session() enum_("storage_mode_t") .value("storage_mode_allocate", storage_mode_allocate) .value("storage_mode_sparse", storage_mode_sparse) +#ifndef TORRENT_NO_DEPRECATE .value("storage_mode_compact", storage_mode_compact) +#endif ; enum_("options_t") diff --git a/docs/features.rst b/docs/features.rst index be9e806a1..9fd9bf250 100644 --- a/docs/features.rst +++ b/docs/features.rst @@ -69,8 +69,6 @@ disk management * queues torrents for file check, instead of checking all of them in parallel. * does not have any requirements on the piece order in a torrent that it resumes. This means it can resume a torrent downloaded by any client. -* supports both sparse files and compact file allocation (where pieces - are kept consolidated on disk) * seed mode, where the files on disk are assumed to be complete, and each piece's hash is verified the first time it is requested. diff --git a/docs/manual.rst b/docs/manual.rst index 1a94814f7..182a3c1f7 100644 --- a/docs/manual.rst +++ b/docs/manual.rst @@ -462,6 +462,7 @@ storage_mode_allocate ``fallocate()`` and similar calls. This mode minimizes fragmentation. storage_mode_compact + **this mode is deprecated and will be removed in future versions of libtorrent** 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 downloaded. @@ -8470,7 +8471,7 @@ libtorrent starts 2 or 3 threads. storage allocation ================== -There are three modes in which storage (files on disk) are allocated in libtorrent. +There are two modes in which storage (files on disk) are allocated in libtorrent. 1. The traditional *full allocation* mode, where the entire files are filled up with zeros before anything is downloaded. libtorrent will look for sparse files support @@ -8478,12 +8479,13 @@ There are three modes in which storage (files on disk) are allocated in libtorre zero fill support if present. This means that on NTFS, full allocation mode will only allocate storage for the downloaded pieces. -2. The *compact allocation* mode, where only files are allocated for actual - pieces that have been downloaded. - -3. The *sparse allocation*, sparse files are used, and pieces are downloaded directly +2. The *sparse allocation*, sparse files are used, and pieces are downloaded directly to where they belong. This is the recommended (and default) mode. +In previous versions of libtorrent, a 3rd mode was supported, *compact allocation*. +Support for this is deprecated and will be removed in future versions of libtorrent. +It's still described in here for completeness. + The allocation mode is selected when a torrent is started. It is passed as an argument to ``session::add_torrent()`` (see `add_torrent()`_). @@ -8539,6 +8541,9 @@ The benefits of this mode are: compact allocation ------------------ +Note that support for compact allocation is deprecated in libttorrent, and will +be removed in future versions. + The compact allocation will only allocate as much storage as it needs to keep the pieces downloaded so far. This means that pieces will be moved around to be placed at their final position in the files while downloading (to make sure the completed diff --git a/examples/client_test.cpp b/examples/client_test.cpp index c4bed03c6..79fea34f8 100644 --- a/examples/client_test.cpp +++ b/examples/client_test.cpp @@ -1036,7 +1036,7 @@ int main(int argc, char* argv[]) #endif " -l sets the listen socket queue size\n" "\n DISK OPTIONS\n" - " -a sets the allocation mode. [compact|full]\n" + " -a sets the allocation mode. [sparse|full]\n" " -R number of blocks per read cache line\n" " -C sets the max cache size. Specified in 16kB blocks\n" " -O Disallow disk job reordering\n" @@ -1161,7 +1161,7 @@ int main(int argc, char* argv[]) case 'S': settings.unchoke_slots_limit = atoi(arg); break; case 'a': if (strcmp(arg, "allocate") == 0) allocation_mode = storage_mode_allocate; - if (strcmp(arg, "compact") == 0) allocation_mode = storage_mode_compact; + if (strcmp(arg, "sparse") == 0) allocation_mode = storage_mode_sparse; break; case 's': save_path = arg; break; case 'U': torrent_upload_limit = atoi(arg) * 1000; break; diff --git a/include/libtorrent/storage.hpp b/include/libtorrent/storage.hpp index de2c8598d..08aad67e5 100644 --- a/include/libtorrent/storage.hpp +++ b/include/libtorrent/storage.hpp @@ -409,8 +409,10 @@ namespace libtorrent // this function returns true if the checking is complete int check_files(int& current_slot, int& have_piece, error_code& error); +#ifndef TORRENT_NO_DEPRECATE bool compact_allocation() const { return m_storage_mode == storage_mode_compact; } +#endif #ifdef TORRENT_DEBUG std::string name() const { return m_info->name(); } diff --git a/include/libtorrent/storage_defs.hpp b/include/libtorrent/storage_defs.hpp index e6d3098f4..365024260 100644 --- a/include/libtorrent/storage_defs.hpp +++ b/include/libtorrent/storage_defs.hpp @@ -47,7 +47,11 @@ namespace libtorrent { storage_mode_allocate = 0, storage_mode_sparse, - storage_mode_compact + // this is here for internal use + internal_storage_mode_compact_deprecated, +#ifndef TORRENT_NO_DEPRECATE + storage_mode_compact = internal_storage_mode_compact_deprecated +#endif }; typedef boost::functionwrite_resume_data(rd); - if (m_storage_mode == storage_mode_compact) + if (m_storage_mode == internal_storage_mode_compact_deprecated) { entry::list_type& slots = rd["slots"].list(); slots.clear(); @@ -1764,7 +1764,7 @@ ret: INVARIANT_CHECK; - if (m_storage_mode != storage_mode_compact) return; + if (m_storage_mode != internal_storage_mode_compact_deprecated) return; TORRENT_ASSERT(piece_index >= 0 && piece_index < (int)m_piece_to_slot.size()); int slot_index = m_piece_to_slot[piece_index]; @@ -1984,7 +1984,7 @@ ret: // that piece as unassigned, since this slot // is the correct place for the piece. m_slot_to_piece[other_slot] = unassigned; - if (m_storage_mode == storage_mode_compact) + if (m_storage_mode == internal_storage_mode_compact_deprecated) m_free_slots.push_back(other_slot); } TORRENT_ASSERT(m_piece_to_slot[piece_index] != current_slot); @@ -2036,7 +2036,7 @@ ret: m_piece_to_slot.resize(m_files.num_pieces(), has_no_slot); m_slot_to_piece.clear(); m_slot_to_piece.resize(m_files.num_pieces(), unallocated); - if (m_storage_mode == storage_mode_compact) + if (m_storage_mode == internal_storage_mode_compact_deprecated) { m_unallocated_slots.clear(); m_free_slots.clear(); @@ -2046,7 +2046,7 @@ ret: } } - if (m_storage_mode == storage_mode_compact) + if (m_storage_mode == internal_storage_mode_compact_deprecated) { // in compact mode without checking, we need to // populate the unallocated list @@ -2073,7 +2073,7 @@ ret: m_state = state_finished; m_scratch_buffer.reset(); m_scratch_buffer2.reset(); - if (m_storage_mode != storage_mode_compact) + if (m_storage_mode != internal_storage_mode_compact_deprecated) { // if no piece is out of place // since we're in full allocation mode, we can @@ -2119,7 +2119,7 @@ ret: return check_no_fastresume(error); } - storage_mode_t storage_mode = storage_mode_compact; + storage_mode_t storage_mode = internal_storage_mode_compact_deprecated; if (rd.dict_find_string_value("allocation") != "compact") storage_mode = storage_mode_sparse; @@ -2132,7 +2132,7 @@ ret: // if we don't have a piece map, we need the slots // if we're in compact mode, we also need the slots map - if (storage_mode == storage_mode_compact || rd.dict_find("pieces") == 0) + if (storage_mode == internal_storage_mode_compact_deprecated || rd.dict_find("pieces") == 0) { // read slots map lazy_entry const* slots = rd.dict_find_list("slots"); @@ -2148,7 +2148,7 @@ ret: return check_no_fastresume(error); } - if (m_storage_mode == storage_mode_compact) + if (m_storage_mode == internal_storage_mode_compact_deprecated) { int num_pieces = int(m_files.num_pieces()); m_slot_to_piece.resize(num_pieces, unallocated); @@ -2176,13 +2176,13 @@ ret: } else if (index == unassigned) { - if (m_storage_mode == storage_mode_compact) + if (m_storage_mode == internal_storage_mode_compact_deprecated) m_free_slots.push_back(i); } else { TORRENT_ASSERT(index == unallocated); - if (m_storage_mode == storage_mode_compact) + if (m_storage_mode == internal_storage_mode_compact_deprecated) m_unallocated_slots.push_back(i); } } @@ -2213,7 +2213,7 @@ ret: // by check_pieces. // m_storage->shuffle(); - if (m_storage_mode == storage_mode_compact) + if (m_storage_mode == internal_storage_mode_compact_deprecated) { if (m_unallocated_slots.empty()) switch_to_full_mode(); } @@ -2235,7 +2235,7 @@ ret: } } - else if (m_storage_mode == storage_mode_compact) + else if (m_storage_mode == internal_storage_mode_compact_deprecated) { // read piece map lazy_entry const* pieces = rd.dict_find("pieces"); @@ -2423,7 +2423,7 @@ ret: // piece overlapping with a sparse region. We should skip 'skip' number // of pieces - if (m_storage_mode == storage_mode_compact) + if (m_storage_mode == internal_storage_mode_compact_deprecated) { for (int i = m_current_slot; i < m_current_slot + skip - 1; ++i) { @@ -2447,7 +2447,7 @@ ret: // clear the memory we've been using std::multimap().swap(m_hash_to_piece); - if (m_storage_mode != storage_mode_compact) + if (m_storage_mode != internal_storage_mode_compact_deprecated) { if (!m_out_of_place) { @@ -2612,7 +2612,7 @@ ret: std::vector::iterator i = std::find(m_free_slots.begin(), m_free_slots.end(), other_slot); TORRENT_ASSERT(i != m_free_slots.end()); - if (m_storage_mode == storage_mode_compact) + if (m_storage_mode == internal_storage_mode_compact_deprecated) { m_free_slots.erase(i); m_free_slots.push_back(m_current_slot); @@ -2645,7 +2645,7 @@ ret: m_piece_to_slot[other_piece] = m_current_slot; if (piece_index == unassigned - && m_storage_mode == storage_mode_compact) + && m_storage_mode == internal_storage_mode_compact_deprecated) m_free_slots.push_back(other_slot); bool ret = false; @@ -2726,7 +2726,7 @@ ret: std::vector::iterator i = std::find(m_free_slots.begin(), m_free_slots.end(), slot1); TORRENT_ASSERT(i != m_free_slots.end()); - if (m_storage_mode == storage_mode_compact) + if (m_storage_mode == internal_storage_mode_compact_deprecated) { m_free_slots.erase(i); m_free_slots.push_back(slot2); @@ -2761,7 +2761,7 @@ ret: // the slot was identified as piece 'piece_index' if (piece_index != unassigned) m_piece_to_slot[piece_index] = m_current_slot; - else if (m_storage_mode == storage_mode_compact) + else if (m_storage_mode == internal_storage_mode_compact_deprecated) m_free_slots.push_back(m_current_slot); m_slot_to_piece[m_current_slot] = piece_index; @@ -2785,7 +2785,7 @@ ret: void piece_manager::switch_to_full_mode() { - TORRENT_ASSERT(m_storage_mode == storage_mode_compact); + TORRENT_ASSERT(m_storage_mode == internal_storage_mode_compact_deprecated); TORRENT_ASSERT(m_unallocated_slots.empty()); // we have allocated all slots, switch to // full allocation mode in order to free @@ -2801,7 +2801,7 @@ ret: { mutex::scoped_lock lock(m_mutex); - if (m_storage_mode != storage_mode_compact) return piece_index; + if (m_storage_mode != internal_storage_mode_compact_deprecated) return piece_index; INVARIANT_CHECK; @@ -2922,7 +2922,7 @@ ret: #endif TORRENT_ASSERT(!m_unallocated_slots.empty()); - TORRENT_ASSERT(m_storage_mode == storage_mode_compact); + TORRENT_ASSERT(m_storage_mode == internal_storage_mode_compact_deprecated); bool written = false; @@ -2954,7 +2954,7 @@ ret: int piece_manager::slot_for(int piece) const { - if (m_storage_mode != storage_mode_compact) return piece; + if (m_storage_mode != internal_storage_mode_compact_deprecated) return piece; TORRENT_ASSERT(piece < int(m_piece_to_slot.size())); TORRENT_ASSERT(piece >= 0); return m_piece_to_slot[piece]; @@ -2962,7 +2962,7 @@ ret: int piece_manager::piece_for(int slot) const { - if (m_storage_mode != storage_mode_compact) return slot; + if (m_storage_mode != internal_storage_mode_compact_deprecated) return slot; TORRENT_ASSERT(slot < int(m_slot_to_piece.size())); TORRENT_ASSERT(slot >= 0); return m_slot_to_piece[slot]; @@ -2977,17 +2977,17 @@ ret: && m_free_slots.empty() && m_state == state_finished) { - TORRENT_ASSERT(m_storage_mode != storage_mode_compact + TORRENT_ASSERT(m_storage_mode != internal_storage_mode_compact_deprecated || m_files.num_pieces() == 0); } - if (m_storage_mode != storage_mode_compact) + if (m_storage_mode != internal_storage_mode_compact_deprecated) { TORRENT_ASSERT(m_unallocated_slots.empty()); TORRENT_ASSERT(m_free_slots.empty()); } - if (m_storage_mode != storage_mode_compact + if (m_storage_mode != internal_storage_mode_compact_deprecated && m_state != state_expand_pieces && m_state != state_full_check) {