diff --git a/include/libtorrent/alert_types.hpp b/include/libtorrent/alert_types.hpp index 60dba8d15..0394b54ea 100755 --- a/include/libtorrent/alert_types.hpp +++ b/include/libtorrent/alert_types.hpp @@ -140,6 +140,21 @@ namespace libtorrent torrent_handle handle; }; + // TODO: document and test + struct file_error_alert: alert + { + file_error_alert( + const torrent_handle& h + , const std::string& msg) + : alert(alert::fatal, msg) + , handle(h) + {} + + virtual std::auto_ptr clone() const + { return std::auto_ptr(new file_error_alert(*this)); } + + torrent_handle handle; + }; } diff --git a/src/session.cpp b/src/session.cpp index 8ee64cace..f32675dc3 100755 --- a/src/session.cpp +++ b/src/session.cpp @@ -65,6 +65,7 @@ POSSIBILITY OF SUCH DAMAGE. #include "libtorrent/entry.hpp" #include "libtorrent/alert_types.hpp" #include "libtorrent/invariant_check.hpp" +#include "libtorrent/file.hpp" #if defined(_MSC_VER) && _MSC_VER < 1300 namespace std @@ -419,7 +420,7 @@ namespace libtorrent { listener->listen(m_listen_port, 5); } - catch(std::exception&) + catch (std::exception&) { if (m_listen_port > max_port) throw; @@ -517,7 +518,21 @@ namespace libtorrent assert(p->second->get_socket()->is_writable()); p->second->send_data(); } - catch(std::exception& e) + catch (file_error& e) + { + if (m_alerts.should_post(alert::fatal)) + { + m_alerts.post_alert( + file_error_alert( + p->second->associated_torrent()->get_handle() + , e.what())); + } + + m_selector.remove(*i); + m_connections.erase(p); + assert(m_selector.count_read_monitors() == m_connections.size() + 1); + } + catch (std::exception& e) { // the connection wants to disconnect for some reason, // remove it from the connection-list @@ -583,7 +598,21 @@ namespace libtorrent // (*m_logger) << "readable: " << p->first->sender().as_string() << "\n"; p->second->receive_data(); } - catch(std::exception& e) + catch (file_error& e) + { + if (m_alerts.should_post(alert::fatal)) + { + m_alerts.post_alert( + file_error_alert( + p->second->associated_torrent()->get_handle() + , e.what())); + } + + m_selector.remove(*i); + m_connections.erase(p); + assert(m_selector.count_read_monitors() == m_connections.size() + 1); + } + catch (std::exception& e) { if (m_alerts.should_post(alert::debug)) { @@ -720,15 +749,15 @@ namespace libtorrent #ifndef NDEBUG } - catch(std::bad_cast& e) + catch (std::bad_cast& e) { std::cerr << e.what() << "\n"; } - catch(std::exception& e) + catch (std::exception& e) { std::cerr << e.what() << "\n"; } - catch(...) + catch (...) { std::cerr << "error!\n"; } diff --git a/src/storage.cpp b/src/storage.cpp index e96af0518..bcb830869 100755 --- a/src/storage.cpp +++ b/src/storage.cpp @@ -1100,7 +1100,6 @@ namespace libtorrent // take one of the other matching pieces // that hasn't already been assigned - std::sort(matching_pieces.begin(), matching_pieces.end()); int other_piece = -1; for (std::vector::iterator i = matching_pieces.begin(); i != matching_pieces.end(); @@ -1122,16 +1121,29 @@ namespace libtorrent m_slot_to_piece[other_slot] = unassigned; m_free_slots.push_back(other_slot); } + assert(m_piece_to_slot[piece_index] != current_slot); + assert(m_piece_to_slot[piece_index] >= 0); + m_piece_to_slot[piece_index] = has_no_slot; } have_pieces[piece_index] = true; return piece_index; } - std::sort(matching_pieces.begin(), matching_pieces.end()); - const int piece_index = matching_pieces.back(); - have_pieces[piece_index] = true; - return piece_index; + // find a matching piece that hasn't + // already been assigned + int free_piece = -1; + for (std::vector::iterator i = matching_pieces.begin(); + i != matching_pieces.end(); + ++i) + { + if (have_pieces[*i]) continue; + free_piece = *i; + break; + } + + if (free_piece >= 0) have_pieces[free_piece] = true; + return free_piece; } void piece_manager::impl::check_pieces( @@ -1239,6 +1251,9 @@ namespace libtorrent if (piece_index >= 0) { + assert(m_slot_to_piece[current_slot] == unallocated); + assert(m_piece_to_slot[piece_index] == has_no_slot); + // the slot was identified as piece 'piece_index' m_piece_to_slot[piece_index] = current_slot; m_slot_to_piece[current_slot] = piece_index;