From e9bd8f6e1f4c09d17fcf394cbe58c5c5fb7b5768 Mon Sep 17 00:00:00 2001 From: Arvid Norberg Date: Sun, 28 Jun 2009 00:36:41 +0000 Subject: [PATCH] turned fast-resume errors into error_codes. fixed typo in documentation --- docs/manual.rst | 53 +++++++++++++++-- include/libtorrent/error_code.hpp | 24 ++++++++ include/libtorrent/storage.hpp | 12 ++-- src/disk_io_thread.cpp | 4 +- src/error_code.cpp | 24 +++++++- src/storage.cpp | 94 +++++++++++++------------------ src/torrent.cpp | 6 +- test/test_transfer.cpp | 2 +- 8 files changed, 145 insertions(+), 74 deletions(-) diff --git a/docs/manual.rst b/docs/manual.rst index 6b49f7f9d..d148162ae 100644 --- a/docs/manual.rst +++ b/docs/manual.rst @@ -5730,7 +5730,13 @@ code symbol description 106 invalid_pex_message The peer sent an invalid peer exchange message ------ ----------------------------------------- ----------------------------------------------------------------- 107 invalid_lt_tracker_message The peer sent an invalid tracker exchange message ------- ----------------------------------------- ----------------------------------------------------------------- +====== ========================================= ================================================================= + +NAT-PMP errors: + +====== ========================================= ================================================================= +code symbol description +====== ========================================= ================================================================= 108 unsupported_protocol_version The NAT-PMP router responded with an unsupported protocol version ------ ----------------------------------------- ----------------------------------------------------------------- 109 natpmp_not_authorized You are not authorized to map ports on this NAT-PMP router @@ -5742,6 +5748,45 @@ code symbol description 112 unsupported_opcode The NAT-PMP router failed because an unsupported opcode was sent ====== ========================================= ================================================================= +fastresume data errors: + +====== ========================================= ================================================================= +code symbol description +====== ========================================= ================================================================= +113 missing_file_sizes The resume data file is missing the 'file sizes' entry +------ ----------------------------------------- ----------------------------------------------------------------- +114 no_files_in_resume_data The resume data file 'file sizes' entry is empty +------ ----------------------------------------- ----------------------------------------------------------------- +115 missing_pieces The resume data file is missing the 'pieces' and 'slots' entry +------ ----------------------------------------- ----------------------------------------------------------------- +116 mismatching_number_of_files The number of files in the resume data does not match the number + of files in the torrent +------ ----------------------------------------- ----------------------------------------------------------------- +117 mismatching_files_size One of the files on disk has a different size than in the fast + resume file +------ ----------------------------------------- ----------------------------------------------------------------- +118 mismatching_file_timestamp One of the files on disk has a different timestamp than in the + fast resume file +------ ----------------------------------------- ----------------------------------------------------------------- +119 not_a_dictionary The resume data file is not a dictionary +------ ----------------------------------------- ----------------------------------------------------------------- +120 invalid_blocks_per_piece The 'blocks per piece' entry is invalid in the resume data file +------ ----------------------------------------- ----------------------------------------------------------------- +121 missing_slots The resume file is missing the 'slots' entry, which is required + for torrents with compact allocation +------ ----------------------------------------- ----------------------------------------------------------------- +122 too_many_slots The resume file contains more slots than the torrent +------ ----------------------------------------- ----------------------------------------------------------------- +123 invalid_slot_list The 'slot' entry is invalid in the resume data +------ ----------------------------------------- ----------------------------------------------------------------- +124 invalid_piece_index One index in the 'slot' list is invalid +------ ----------------------------------------- ----------------------------------------------------------------- +125 pieces_need_reorder The pieces on disk needs to be re-ordered for the specified + allocation mode. This happens if you specify sparse allocation + and the files on disk are using compact storage. The pieces needs + to be moved to their right position +====== ========================================= ================================================================= + The names of these error codes are declared in then ``libtorrent::errors`` namespace. There is also another error category, ``libtorrent::upnp_category``, defining errors @@ -5862,7 +5907,7 @@ The interface looks like this:: virtual int writev(file::iovec_t const* bufs, int slot, int offset, int num_bufs) = 0; virtual int sparse_end(int start) const; virtual bool move_storage(fs::path save_path) = 0; - virtual bool verify_resume_data(lazy_entry const& rd, std::string& error) = 0; + virtual bool verify_resume_data(lazy_entry const& rd, error_code& error) = 0; virtual bool write_resume_data(entry& rd) const = 0; virtual bool move_slot(int src_slot, int dst_slot) = 0; virtual bool swap_slots(int slot1, int slot2) = 0; @@ -5970,7 +6015,7 @@ verify_resume_data() :: - bool verify_resume_data(lazy_entry const& rd, std::string& error) = 0; + bool verify_resume_data(lazy_entry const& rd, error_code& error) = 0; This function should verify the resume data ``rd`` with the files on disk. If the resume data seems to be up-to-date, return true. If @@ -5978,7 +6023,7 @@ not, set ``error`` to a description of what mismatched and return false. The default storage may compare file sizes and time stamps of the files. -Returning ``true`` indicates an error occurred. +Returning ``false`` indicates an error occurred. write_resume_data() diff --git a/include/libtorrent/error_code.hpp b/include/libtorrent/error_code.hpp index c52abe5ee..145478b22 100644 --- a/include/libtorrent/error_code.hpp +++ b/include/libtorrent/error_code.hpp @@ -160,11 +160,35 @@ namespace libtorrent invalid_pex_message, invalid_lt_tracker_message, +// natpmp errors unsupported_protocol_version, natpmp_not_authorized, network_failure, no_resources, unsupported_opcode, + +// fastresume errors + missing_file_sizes, + no_files_in_resume_data, + missing_pieces, + mismatching_number_of_files, + mismatching_file_size, + mismatching_file_timestamp, + not_a_dictionary, + invalid_blocks_per_piece, + missing_slots, + too_many_slots, + invalid_slot_list, + invalid_piece_index, + pieces_need_reorder, + reserved1, + reserved2, + reserved3, + reserved4, + reserved5, + reserved6, + reserved7, + reserved8, }; } diff --git a/include/libtorrent/storage.hpp b/include/libtorrent/storage.hpp index e65602a64..586072c04 100644 --- a/include/libtorrent/storage.hpp +++ b/include/libtorrent/storage.hpp @@ -139,7 +139,7 @@ namespace libtorrent virtual bool move_storage(fs::path save_path) = 0; // verify storage dependent fast resume entries - virtual bool verify_resume_data(lazy_entry const& rd, std::string& error) = 0; + virtual bool verify_resume_data(lazy_entry const& rd, error_code& error) = 0; // write storage dependent fast resume entries virtual bool write_resume_data(entry& rd) const = 0; @@ -281,7 +281,7 @@ namespace libtorrent fs::path save_path() const; - bool verify_resume_data(lazy_entry const& rd, std::string& error) + bool verify_resume_data(lazy_entry const& rd, error_code& error) { return m_storage->verify_resume_data(rd, error); } bool is_allocating() const @@ -299,17 +299,17 @@ namespace libtorrent int piece_for(int slot) const; // helper functions for check_dastresume - int check_no_fastresume(std::string& error); - int check_init_storage(std::string& error); + int check_no_fastresume(error_code& error); + int check_init_storage(error_code& error); // if error is set and return value is 'no_error' or 'need_full_check' // the error message indicates that the fast resume data was rejected // if 'fatal_disk_error' is returned, the error message indicates what // when wrong in the disk access - int check_fastresume(lazy_entry const& rd, std::string& error); + int check_fastresume(lazy_entry const& rd, error_code& error); // this function returns true if the checking is complete - int check_files(int& current_slot, int& have_piece, std::string& error); + int check_files(int& current_slot, int& have_piece, error_code& error); bool compact_allocation() const { return m_storage_mode == storage_mode_compact; } diff --git a/src/disk_io_thread.cpp b/src/disk_io_thread.cpp index 873add80a..808c7cdd9 100644 --- a/src/disk_io_thread.cpp +++ b/src/disk_io_thread.cpp @@ -1771,7 +1771,7 @@ namespace libtorrent #endif lazy_entry const* rd = (lazy_entry const*)j.buffer; TORRENT_ASSERT(rd != 0); - ret = j.storage->check_fastresume(*rd, j.str); + ret = j.storage->check_fastresume(*rd, j.error); break; } case disk_io_job::check_files: @@ -1801,7 +1801,7 @@ namespace libtorrent if (m_waiting_to_shutdown) break; - ret = j.storage->check_files(j.piece, j.offset, j.str); + ret = j.storage->check_files(j.piece, j.offset, j.error); #ifndef BOOST_NO_EXCEPTIONS try { diff --git a/src/error_code.cpp b/src/error_code.cpp index f9d20bdff..73e054e46 100644 --- a/src/error_code.cpp +++ b/src/error_code.cpp @@ -155,12 +155,34 @@ namespace libtorrent "pex message too large", "invalid pex message", "invalid lt_tracker message", - +// natpmp errors "unsupported protocol version", "not authorized to create port map (enable NAT-PMP on your router)", "network failure", "out of resources", "unsupported opcode", +// fastresume errors + "missing or invalid 'file sizes' entry", + "no files in resume data", + "missing 'slots' and 'pieces' entry", + "mismatching number of files", + "mismatching file size", + "mismatching file timestamp", + "not a dictionary", + "invalid 'blocks per piece' entry", + "missing slots list", + "file has more slots than torrent", + "invalid entry type in slot list", + "invalid piece index in slot list", + "pieces needs to be reordered", + "", + "", + "", + "", + "", + "", + "", + "", }; if (ev < 0 || ev >= sizeof(msgs)/sizeof(msgs[0])) return "Unknown error"; diff --git a/src/storage.cpp b/src/storage.cpp index 08775b7c6..4d8673617 100644 --- a/src/storage.cpp +++ b/src/storage.cpp @@ -111,7 +111,7 @@ namespace { using namespace libtorrent; - void print_to_log(const std::string& s) + void print_to_log(std::string const& s) { static std::ofstream log("log.txt"); log << s; @@ -232,11 +232,11 @@ namespace libtorrent , fs::path p , std::vector > const& sizes , bool compact_mode - , std::string* error) + , error_code& error) { if ((int)sizes.size() != fs.num_files()) { - if (error) *error = "mismatching number of files"; + error = error_code(errors::mismatching_number_of_files, libtorrent_category); return false; } p = complete(p); @@ -270,11 +270,7 @@ namespace libtorrent if ((compact_mode && size != s->first) || (!compact_mode && size < s->first)) { - if (error) *error = "filesize mismatch for file '" - + i->path.external_file_string() - + "', size: " + boost::lexical_cast(size) - + ", expected to be " + boost::lexical_cast(s->first) - + " bytes"; + error = error_code(errors::mismatching_file_size, libtorrent_category); return false; } // allow one second 'slack', because of FAT volumes @@ -283,11 +279,7 @@ namespace libtorrent if ((compact_mode && (time > s->second + 1 || time < s->second - 1)) || (!compact_mode && (time > s->second + 5 * 60 || time < s->second - 1))) { - if (error) *error = "timestamp mismatch for file '" - + i->path.external_file_string() - + "', modification date: " + boost::lexical_cast(time) - + ", expected to have modification date " - + boost::lexical_cast(s->second); + error = error_code(errors::mismatching_file_timestamp, libtorrent_category); return false; } } @@ -426,7 +418,7 @@ namespace libtorrent bool move_slot(int src_slot, int dst_slot); bool swap_slots(int slot1, int slot2); bool swap_slots3(int slot1, int slot2, int slot3); - bool verify_resume_data(lazy_entry const& rd, std::string& error); + bool verify_resume_data(lazy_entry const& rd, error_code& error); bool write_resume_data(entry& rd) const; // this identifies a read or write operation @@ -868,7 +860,7 @@ namespace libtorrent return (data_start + m_files.piece_length() - 1) / m_files.piece_length(); } - bool storage::verify_resume_data(lazy_entry const& rd, std::string& error) + bool storage::verify_resume_data(lazy_entry const& rd, error_code& error) { lazy_entry const* mapped_files = rd.dict_find_list("mapped_files"); if (mapped_files && mapped_files->list_size() == m_files.num_files()) @@ -895,7 +887,7 @@ namespace libtorrent lazy_entry const* file_sizes_ent = rd.dict_find_list("file sizes"); if (file_sizes_ent == 0) { - error = "missing or invalid 'file sizes' entry in resume data"; + error = error_code(errors::missing_file_sizes, libtorrent_category); return false; } @@ -913,7 +905,7 @@ namespace libtorrent if (file_sizes.empty()) { - error = "the number of files in resume data is 0"; + error = error_code(errors::no_files_in_resume_data, libtorrent_category); return false; } @@ -949,7 +941,7 @@ namespace libtorrent } else { - error = "missing 'slots' and 'pieces' entry in resume data"; + error = error_code(errors::missing_pieces, libtorrent_category); return false; } @@ -961,9 +953,7 @@ namespace libtorrent { if (files().num_files() != (int)file_sizes.size()) { - error = "the number of files does not match the torrent (num: " - + boost::lexical_cast(file_sizes.size()) + " actual: " - + boost::lexical_cast(files().num_files()) + ")"; + error = error_code(errors::mismatching_number_of_files, libtorrent_category); return false; } @@ -976,15 +966,13 @@ namespace libtorrent { if (!i->pad_file && i->size != fs->first) { - error = "file size for '" + i->path.external_file_string() - + "' was expected to be " - + boost::lexical_cast(i->size) + " bytes"; + error = error_code(errors::mismatching_file_size, libtorrent_category); return false; } } } return match_filesizes(files(), m_save_path, file_sizes - , !full_allocation_mode, &error); + , !full_allocation_mode, error); } @@ -1961,7 +1949,7 @@ ret: } } - int piece_manager::check_no_fastresume(std::string& error) + int piece_manager::check_no_fastresume(error_code& error) { bool has_files = m_storage->has_any_file(); @@ -2000,12 +1988,12 @@ ret: return check_init_storage(error); } - int piece_manager::check_init_storage(std::string& error) + int piece_manager::check_init_storage(error_code& error) { if (m_storage->initialize(m_storage_mode == storage_mode_allocate)) { - error = m_storage->error().message(); - TORRENT_ASSERT(!error.empty()); + error = m_storage->error(); + TORRENT_ASSERT(error); return fatal_disk_error; } m_state = state_finished; @@ -2029,7 +2017,7 @@ ret: // isn't return false and the full check // will be run int piece_manager::check_fastresume( - lazy_entry const& rd, std::string& error) + lazy_entry const& rd, error_code& error) { boost::recursive_mutex::scoped_lock lock(m_mutex); @@ -2044,7 +2032,7 @@ ret: if (rd.type() != lazy_entry::dict_t) { - error = "invalid fastresume data (not a dictionary)"; + error = error_code(errors::not_a_dictionary, libtorrent_category); return check_no_fastresume(error); } @@ -2053,7 +2041,7 @@ ret: if (blocks_per_piece != -1 && blocks_per_piece != m_files.piece_length() / block_size) { - error = "invalid 'blocks per piece' entry"; + error = error_code(errors::invalid_blocks_per_piece, libtorrent_category); return check_no_fastresume(error); } @@ -2076,15 +2064,13 @@ ret: lazy_entry const* slots = rd.dict_find_list("slots"); if (slots == 0) { - error = "missing slot list"; + error = error_code(errors::missing_slots, libtorrent_category); return check_no_fastresume(error); } if ((int)slots->list_size() > m_files.num_pieces()) { - error = "file has more slots than torrent (slots: " - + boost::lexical_cast(slots->list_size()) + " size: " - + boost::lexical_cast(m_files.num_pieces()) + " )"; + error = error_code(errors::too_many_slots, libtorrent_category); return check_no_fastresume(error); } @@ -2098,16 +2084,14 @@ ret: lazy_entry const* e = slots->list_at(i); if (e->type() != lazy_entry::int_t) { - error = "invalid entry type in slot list"; + error = error_code(errors::invalid_slot_list, libtorrent_category); return check_no_fastresume(error); } int index = int(e->int_value()); if (index >= num_pieces || index < -2) { - error = "too high index number in slot map (index: " - + boost::lexical_cast(index) + " size: " - + boost::lexical_cast(num_pieces) + ")"; + error = error_code(errors::invalid_piece_index, libtorrent_category); return check_no_fastresume(error); } if (index >= 0) @@ -2136,14 +2120,14 @@ ret: lazy_entry const* e = slots->list_at(i); if (e->type() != lazy_entry::int_t) { - error = "invalid entry type in slot list"; + error = error_code(errors::invalid_slot_list, libtorrent_category); return check_no_fastresume(error); } int index = int(e->int_value()); if (index != i && index >= 0) { - error = "invalid slot index"; + error = error_code(errors::invalid_piece_index, libtorrent_category); return check_no_fastresume(error); } } @@ -2170,7 +2154,7 @@ ret: // we're resuming a compact allocated storage m_state = state_expand_pieces; m_current_slot = 0; - error = "pieces needs to be reordered"; + error = error_code(errors::pieces_need_reorder, libtorrent_category); TORRENT_ASSERT(int(m_piece_to_slot.size()) == m_files.num_pieces()); return need_full_check; } @@ -2183,15 +2167,13 @@ ret: lazy_entry const* pieces = rd.dict_find("pieces"); if (pieces == 0 || pieces->type() != lazy_entry::string_t) { - error = "missing pieces entry"; + error = error_code(errors::missing_pieces, libtorrent_category); return check_no_fastresume(error); } if ((int)pieces->string_length() != m_files.num_pieces()) { - error = "file has more slots than torrent (slots: " - + boost::lexical_cast(pieces->string_length()) + " size: " - + boost::lexical_cast(m_files.num_pieces()) + " )"; + error = error_code(errors::too_many_slots, libtorrent_category); return check_no_fastresume(error); } @@ -2241,7 +2223,7 @@ ret: // the second return value is the progress the // file check is at. 0 is nothing done, and 1 // is finished - int piece_manager::check_files(int& current_slot, int& have_piece, std::string& error) + int piece_manager::check_files(int& current_slot, int& have_piece, error_code& error) { if (m_state == state_none) return check_no_fastresume(error); @@ -2273,8 +2255,8 @@ ret: if (m_storage->read(m_scratch_buffer2.get(), piece, 0, piece_size) != piece_size) { - error = m_storage->error().message(); - TORRENT_ASSERT(!error.empty()); + error = m_storage->error(); + TORRENT_ASSERT(error); return fatal_disk_error; } m_scratch_piece = other_piece; @@ -2286,8 +2268,8 @@ ret: int piece_size = m_files.piece_size(piece); if (m_storage->write(m_scratch_buffer.get(), piece, 0, piece_size) != piece_size) { - error = m_storage->error().message(); - TORRENT_ASSERT(!error.empty()); + error = m_storage->error(); + TORRENT_ASSERT(error); return fatal_disk_error; } m_piece_to_slot[piece] = piece; @@ -2332,8 +2314,8 @@ ret: int piece_size = m_files.piece_size(other_piece); if (m_storage->read(m_scratch_buffer.get(), piece, 0, piece_size) != piece_size) { - error = m_storage->error().message(); - TORRENT_ASSERT(!error.empty()); + error = m_storage->error(); + TORRENT_ASSERT(error); return fatal_disk_error; } m_scratch_piece = other_piece; @@ -2361,8 +2343,8 @@ ret: if (skip == -1) { - error = m_storage->error().message(); - TORRENT_ASSERT(!error.empty()); + error = m_storage->error(); + TORRENT_ASSERT(error); return fatal_disk_error; } diff --git a/src/torrent.cpp b/src/torrent.cpp index 8437095b5..97a20b56d 100644 --- a/src/torrent.cpp +++ b/src/torrent.cpp @@ -805,9 +805,7 @@ namespace libtorrent } } - bool fastresume_rejected = !j.str.empty(); - - if (fastresume_rejected && m_ses.m_alerts.should_post()) + if (j.error && m_ses.m_alerts.should_post()) { m_ses.m_alerts.post_alert(fastresume_rejected_alert(get_handle(), j.error)); } @@ -822,7 +820,7 @@ namespace libtorrent // there are either no files for this torrent // or the resume_data was accepted - if (!fastresume_rejected && m_resume_entry.type() == lazy_entry::dict_t) + if (!j.error && m_resume_entry.type() == lazy_entry::dict_t) { // parse have bitmask lazy_entry const* pieces = m_resume_entry.dict_find("pieces"); diff --git a/test/test_transfer.cpp b/test/test_transfer.cpp index d48539d11..3a9ea9a20 100644 --- a/test/test_transfer.cpp +++ b/test/test_transfer.cpp @@ -174,7 +174,7 @@ struct test_storage : storage_interface virtual bool move_storage(fs::path save_path) { return m_lower_layer->move_storage(save_path); } - virtual bool verify_resume_data(lazy_entry const& rd, std::string& error) + virtual bool verify_resume_data(lazy_entry const& rd, error_code& error) { return m_lower_layer->verify_resume_data(rd, error); } virtual bool write_resume_data(entry& rd) const