From 258d691dae7e4fab3241b49211a4ea9657125b9b Mon Sep 17 00:00:00 2001 From: Arvid Norberg Date: Wed, 3 Mar 2004 13:47:12 +0000 Subject: [PATCH] *** empty log message *** --- docs/manual.html | 6 +- docs/manual.rst | 6 +- examples/client_test.cpp | 8 +- include/libtorrent/torrent_info.hpp | 19 +- src/session.cpp | 22 +- src/storage.cpp | 311 ---------------------------- src/torrent_info.cpp | 38 ++++ 7 files changed, 78 insertions(+), 332 deletions(-) diff --git a/docs/manual.html b/docs/manual.html index 2feec6f04..8bdf133c5 100755 --- a/docs/manual.html +++ b/docs/manual.html @@ -868,7 +868,11 @@ This reference is valid as long as the

is_valid()

Returns true if this handle refers to a valid torrent and false if it hasn't been initialized -or if the torrent it refers to has been aborted.

+or if the torrent it refers to has been aborted. Note that a handle may become invalid after +it has been added to the session. Usually this is because the storage for the torrent is +somehow invalid or if the filenames are not allowed (and hence cannot be opened/created) on +your filesystem. If such an error occurs, a file_error_alert is generated and all handles +that refers to that torrent will become invalid.

diff --git a/docs/manual.rst b/docs/manual.rst index 445c7995c..0e96eec24 100755 --- a/docs/manual.rst +++ b/docs/manual.rst @@ -891,7 +891,11 @@ is_valid() ---------- Returns true if this handle refers to a valid torrent and false if it hasn't been initialized -or if the torrent it refers to has been aborted. +or if the torrent it refers to has been aborted. Note that a handle may become invalid after +it has been added to the session. Usually this is because the storage for the torrent is +somehow invalid or if the filenames are not allowed (and hence cannot be opened/created) on +your filesystem. If such an error occurs, a file_error_alert_ is generated and all handles +that refers to that torrent will become invalid. diff --git a/examples/client_test.cpp b/examples/client_test.cpp index 898560c8c..b7b4b20c1 100755 --- a/examples/client_test.cpp +++ b/examples/client_test.cpp @@ -226,7 +226,7 @@ int main(int argc, char* argv[]) return 1; } -// boost::filesystem::path::default_name_check(boost::filesystem::native); + boost::filesystem::path::default_name_check(boost::filesystem::native); http_settings settings; // settings.proxy_ip = "192.168.0.1"; @@ -340,6 +340,12 @@ int main(int argc, char* argv[]) i != handles.end(); ++i) { + if (!i->is_valid()) + { + handles.erase(i); + --i; + continue; + } torrent_status s = i->status(); switch(s.state) diff --git a/include/libtorrent/torrent_info.hpp b/include/libtorrent/torrent_info.hpp index c638ad315..ff418db5c 100755 --- a/include/libtorrent/torrent_info.hpp +++ b/include/libtorrent/torrent_info.hpp @@ -91,20 +91,11 @@ namespace libtorrent { public: - torrent_info(const entry& torrent_file) - : m_creation_date(boost::gregorian::date(1970 - , boost::gregorian::Jan - , 1)) - { - try - { - read_torrent_info(torrent_file); - } - catch(type_error&) - { - throw invalid_torrent_file(); - } - } + torrent_info(const entry& torrent_file); + + torrent_info( + const std::vector& files + , int piece_size); typedef std::vector::const_iterator file_iterator; typedef std::vector::const_reverse_iterator reverse_file_iterator; diff --git a/src/session.cpp b/src/session.cpp index d4f153805..3f12578c7 100755 --- a/src/session.cpp +++ b/src/session.cpp @@ -215,17 +215,22 @@ namespace libtorrent { namespace detail } catch(const std::exception& e) { - // TODO: generate an alert here! // This will happen if the storage fails to initialize -#ifndef NDEBUG - std::cerr << "error while checking files: " << e.what() << "\n"; -#endif + boost::mutex::scoped_lock l(m_ses.m_mutex); + if (m_ses.m_alerts.should_post(alert::fatal)) + { + m_ses.m_alerts.post_alert( + file_error_alert( + t->torrent_ptr->get_handle() + , e.what())); + } } catch(...) { #ifndef NDEBUG std::cerr << "error while checking files\n"; #endif + assert(false); } // remove ourself from the 'checking'-list @@ -730,6 +735,15 @@ namespace libtorrent { namespace detail { std::map >::iterator i = m_torrents.find(info_hash); +#ifndef NDEBUG + for (std::map >::iterator j + = m_torrents.begin(); + j != m_torrents.end(); + ++j) + { + torrent* p = boost::get_pointer(j->second); + } +#endif if (i != m_torrents.end()) return boost::get_pointer(i->second); return 0; } diff --git a/src/storage.cpp b/src/storage.cpp index 077308701..1c8082f85 100755 --- a/src/storage.cpp +++ b/src/storage.cpp @@ -750,318 +750,7 @@ namespace libtorrent { m_pimpl->write(buf, piece_index, offset, size); } -/* - void piece_manager::impl::check_pieces( - boost::mutex& mutex - , detail::piece_checker_data& data - , std::vector& pieces) - { - // synchronization ------------------------------------------------------ - boost::recursive_mutex::scoped_lock lock(m_mutex); - // ---------------------------------------------------------------------- -#ifndef NDEBUG - check_invariant(); -#endif - - m_allocating = false; - m_piece_to_slot.resize(m_info.num_pieces(), has_no_slot); - m_slot_to_piece.resize(m_info.num_pieces(), unallocated); - m_free_slots.clear(); - m_unallocated_slots.clear(); - - const std::size_t piece_size = m_info.piece_length(); - const std::size_t last_piece_size = m_info.piece_size( - m_info.num_pieces() - 1); - - - - // if we have fast-resume info - // use it instead of doing the actual checking - if (!data.piece_map.empty() - && data.piece_map.size() <= m_slot_to_piece.size()) - { - for (int i = 0; i < (int)data.piece_map.size(); ++i) - { - m_slot_to_piece[i] = data.piece_map[i]; - if (data.piece_map[i] >= 0) - { - m_piece_to_slot[data.piece_map[i]] = i; - int found_piece = data.piece_map[i]; - - // if the piece is not in the unfinished list - // we have all of it - if (std::find_if( - data.unfinished_pieces.begin() - , data.unfinished_pieces.end() - , piece_picker::has_index(found_piece)) - == data.unfinished_pieces.end()) - { - pieces[found_piece] = true; - } - } - else if (data.piece_map[i] == unassigned) - { - m_free_slots.push_back(i); - } - else - { - assert(data.piece_map[i] == unallocated); - m_unallocated_slots.push_back(i); - } - } - - for (int i = data.piece_map.size(); i < (int)pieces.size(); ++i) - { - m_unallocated_slots.push_back(i); - } -#ifndef NDEBUG - check_invariant(); -#endif - - return; - } - - - // do the real check (we didn't have valid resume data) - - bool changed_file = true; - file in; - - std::vector piece_data(m_info.piece_length()); - std::size_t piece_offset = 0; - - int current_slot = 0; - std::size_t bytes_to_read = m_info.piece_size(0); - size_type bytes_current_read = 0; - size_type seek_into_next = 0; - size_type filesize = 0; - size_type start_of_read = 0; - size_type start_of_file = 0; - - { - boost::mutex::scoped_lock lock(mutex); - data.progress = 0.f; - } - - for (torrent_info::file_iterator file_iter = m_info.begin_files(), - end_iter = m_info.end_files(); - file_iter != end_iter;) - { - assert(current_slot >= 0 && current_slot < m_info.num_pieces()); - - // Update progress meter and check if we've been requested to abort - { - boost::mutex::scoped_lock lock(mutex); - - data.progress = (float)current_slot / m_info.num_pieces(); - if (data.abort) - return; - } - - fs::path path(m_save_path / file_iter->path); - - // if the path doesn't exist, create the - // entire directory tree - if (!fs::exists(path)) - fs::create_directories(path); - - path /= file_iter->filename; - - if (changed_file) - { - try - { - changed_file = false; - bytes_current_read = seek_into_next; - in.open(path, file::in); - - in.seek(0, file::end); - filesize = in.tell(); - in.seek(seek_into_next); - } - catch (file_error&) - { - filesize = 0; - } - } - - // we are at the start of a new piece - // so we store the start of the piece - if (bytes_to_read == m_info.piece_size(current_slot)) - start_of_read = current_slot * (size_type)piece_size; - - std::size_t bytes_read = 0; - - if (filesize > 0) - { - bytes_read = in.read(&piece_data[piece_offset], bytes_to_read); - assert(bytes_read>0); - } - - bytes_current_read += bytes_read; - bytes_to_read -= bytes_read; - - assert(bytes_to_read >= 0); - - // bytes left to read, go on with next file - if (bytes_to_read > 0) - { - if (bytes_current_read != file_iter->size) - { - size_type pos; - size_type file_end = start_of_file + file_iter->size; - - for (pos = start_of_read; pos < file_end; - pos += piece_size) - { - m_unallocated_slots.push_back(current_slot); - ++current_slot; - } - - seek_into_next = pos - file_end; - if (current_slot >= m_info.num_pieces()) - { - break; - } - bytes_to_read = m_info.piece_size(current_slot); - piece_offset = 0; - } - else - { - seek_into_next = 0; - piece_offset += bytes_read; - } - - changed_file = true; - start_of_file += file_iter->size; - ++file_iter; - continue; - } - - assert(current_slot < m_info.num_pieces()); - assert(m_slot_to_piece[current_slot] == unallocated); - assert(m_piece_to_slot[current_slot] == has_no_slot || - (m_piece_to_slot[current_slot] >= 0 && - m_piece_to_slot[current_slot] < current_slot && - m_slot_to_piece[m_piece_to_slot[current_slot]] == current_slot)); - - // we need to take special actions if this is - // the last piece, since that piece might actually - // be smaller than piece_size. - - lazy_hash large_digest(&piece_data[0], piece_size); - lazy_hash small_digest(&piece_data[0], last_piece_size); - - const lazy_hash* digest[2] = { - &large_digest, &small_digest - }; - - int found_piece = -1; - - for (int i = current_slot; i < m_info.num_pieces(); ++i) - { - if (pieces[i] && i != current_slot) continue; - - const sha1_hash& hash = digest[ - (i == m_info.num_pieces() - 1) ? 1 : 0]->get(); - - if (hash == m_info.hash_for_piece(i)) - { - found_piece = i; - if (i == current_slot) break; - } - } - - if (found_piece != -1) - { - // if we have found this piece hash once already - // move it to the free pieces and don't decrease - // bytes_left - if (pieces[found_piece]) - { - assert(m_piece_to_slot[found_piece] == current_slot); - m_slot_to_piece[m_piece_to_slot[found_piece]] = unassigned; - m_free_slots.push_back(m_piece_to_slot[found_piece]); - m_piece_to_slot[found_piece] = has_no_slot; - } - - assert(m_piece_to_slot[found_piece] == has_no_slot); - m_piece_to_slot[found_piece] = current_slot; - m_slot_to_piece[current_slot] = found_piece; - pieces[found_piece] = true; - } - else - { - assert(found_piece == -1); - m_slot_to_piece[current_slot] = unassigned; - - m_free_slots.push_back(current_slot); - } - - assert(m_slot_to_piece[current_slot] != unallocated); - - // done with piece, move on to next - piece_offset = 0; - ++current_slot; - if (current_slot == m_info.num_pieces()) - { - assert(file_iter == end_iter-1); - break; - } - bytes_to_read = m_info.piece_size(current_slot); - } - - // dirty "fix" for a bug when file is corrupt - for (int i = 0; i < (int)m_info.num_pieces(); ++i) - { - if(m_piece_to_slot[i] != has_no_slot - && m_piece_to_slot[i] != i - && m_slot_to_piece[i] != unallocated) - { - assert(m_piece_to_slot[i] >= 0); - assert(m_piece_to_slot[i] < (int)m_slot_to_piece.size()); - assert(m_slot_to_piece[m_piece_to_slot[i]] == i); - if(m_slot_to_piece[i]!=unassigned) - { - assert(m_slot_to_piece[i] >= 0); - assert(m_slot_to_piece[i] < (int)m_piece_to_slot.size()); - assert(m_piece_to_slot[m_slot_to_piece[i]] == i); - - m_piece_to_slot[m_slot_to_piece[i]] = has_no_slot; - m_slot_to_piece[i] = unassigned; - m_free_slots.push_back(i); - } - m_slot_to_piece[m_piece_to_slot[i]] = unassigned; - m_free_slots.push_back(m_piece_to_slot[i]); - m_piece_to_slot[i] = has_no_slot; - } - } - -#ifndef NDEBUG - std::stringstream s; - - s << " m_free_slots: " << m_free_slots.size() << "\n" - " m_unallocated_slots: " << m_unallocated_slots.size() << "\n" - " num pieces: " << m_info.num_pieces() << "\n" - " have_pieces:\n"; - for (std::vector::iterator i = pieces.begin(); - i != pieces.end(); - ++i) - { - if (((i - pieces.begin()) % 60) == 0) s << "\n"; - if (*i) s << "1"; else s << "0"; - } - s << "\n"; - s << std::count(pieces.begin(), pieces.end(), true) << "\n"; - data.torrent_ptr->debug_log(s.str()); -#endif - -#ifndef NDEBUG - check_invariant(); -#endif - } -*/ int piece_manager::impl::identify_data( const std::vector& piece_data , int current_slot diff --git a/src/torrent_info.cpp b/src/torrent_info.cpp index fce98d44c..ac8feebdb 100755 --- a/src/torrent_info.cpp +++ b/src/torrent_info.cpp @@ -91,6 +91,44 @@ namespace namespace libtorrent { + // standard constructor that parses a torrent file + torrent_info::torrent_info(const entry& torrent_file) + : m_creation_date(boost::gregorian::date(1970 + , boost::gregorian::Jan + , 1)) + { + try + { + read_torrent_info(torrent_file); + } + catch(type_error&) + { + throw invalid_torrent_file(); + } + } + + // constructor used for creating new torrents + // will not contain any hashes, comments, creation date + // just the necessary to use it with piece manager + torrent_info::torrent_info( + const std::vector& files + , int piece_size) + : m_piece_length(piece_size) + , m_files(files) + , m_creation_date(boost::gregorian::date(1970 + , boost::gregorian::Jan + , 1)) + { + // calculate total size of all pieces + m_total_size = 0; + for (std::vector::iterator i = m_files.begin(); i != m_files.end(); ++i) + m_total_size += i->size; + + int num_pieces = static_cast((m_total_size + m_piece_length - 1) / m_piece_length); + + } + + // extracts information from a libtorrent file and fills in the structures in // the torrent object void torrent_info::read_torrent_info(const entry& torrent_file)