From b55a1a67660265ca3d60249cb509fa22a1113ea8 Mon Sep 17 00:00:00 2001 From: Arvid Norberg Date: Tue, 21 Dec 2004 12:30:09 +0000 Subject: [PATCH] *** empty log message *** --- include/libtorrent/debug.hpp | 8 ++- include/libtorrent/file.hpp | 6 ++ include/libtorrent/peer_id.hpp | 6 +- include/libtorrent/session.hpp | 4 +- include/libtorrent/stat.hpp | 2 +- include/libtorrent/storage.hpp | 7 +++ src/file.cpp | 6 +- src/identify_client.cpp | 1 + src/peer_connection.cpp | 4 +- src/piece_picker.cpp | 4 ++ src/policy.cpp | 2 +- src/session.cpp | 54 +++++++++-------- src/storage.cpp | 106 +++++++++++++++++++++++++++++---- src/torrent.cpp | 10 ++-- 14 files changed, 166 insertions(+), 54 deletions(-) diff --git a/include/libtorrent/debug.hpp b/include/libtorrent/debug.hpp index 0f4d04d16..ad44601a7 100755 --- a/include/libtorrent/debug.hpp +++ b/include/libtorrent/debug.hpp @@ -104,8 +104,12 @@ namespace libtorrent { public: file_logger(boost::filesystem::path const& filename) - : m_file(boost::filesystem::complete("libtorrent_logs" / filename)) - {} + { + using namespace boost::filesystem; + path dir(complete("libtorrent_logs")); + if (!exists(dir)) create_directories(dir); + m_file.open(dir / filename); + } virtual void log(const char* text) { assert(text); m_file << text; } boost::filesystem::ofstream m_file; diff --git a/include/libtorrent/file.hpp b/include/libtorrent/file.hpp index 1953c97e9..ecedff2f3 100755 --- a/include/libtorrent/file.hpp +++ b/include/libtorrent/file.hpp @@ -82,12 +82,18 @@ namespace libtorrent open_mode operator|(open_mode m) const { return open_mode(m.m_mask | m_mask); } + open_mode operator&(open_mode m) const + { return open_mode(m.m_mask & m_mask); } + open_mode operator|=(open_mode m) { m_mask |= m.m_mask; return *this; } + bool operator==(open_mode m) const { return m_mask == m.m_mask; } + bool operator!=(open_mode m) const { return m_mask != m.m_mask; } + private: open_mode(int val): m_mask(val) {} diff --git a/include/libtorrent/peer_id.hpp b/include/libtorrent/peer_id.hpp index 163e56b70..0f23aaa5b 100755 --- a/include/libtorrent/peer_id.hpp +++ b/include/libtorrent/peer_id.hpp @@ -65,17 +65,17 @@ namespace libtorrent return std::count(m_number,m_number+number_size,0) == number_size; } - bool operator==(const big_number& n) const + bool operator==(big_number const& n) const { return std::equal(n.m_number, n.m_number+number_size, m_number); } - bool operator!=(const big_number& n) const + bool operator!=(big_number const& n) const { return !std::equal(n.m_number, n.m_number+number_size, m_number); } - bool operator<(const big_number& n) const + bool operator<(big_number const& n) const { for(int i = 0; i < number_size; ++i) { diff --git a/include/libtorrent/session.hpp b/include/libtorrent/session.hpp index b0b2e0e33..e3e01a403 100755 --- a/include/libtorrent/session.hpp +++ b/include/libtorrent/session.hpp @@ -175,7 +175,7 @@ namespace libtorrent // in this struct mutable boost::mutex m_mutex; torrent* find_torrent(const sha1_hash& info_hash); - const peer_id& get_peer_id() const { return m_peer_id; } + peer_id const& get_peer_id() const { return m_peer_id; } tracker_manager m_tracker_manager; torrent_map m_torrents; @@ -314,6 +314,8 @@ namespace libtorrent void enable_extension(peer_connection::extension_index i); void disable_extensions(); + void set_peer_id(peer_id const& id); + bool is_listening() const; // if the listen port failed in some way diff --git a/include/libtorrent/stat.hpp b/include/libtorrent/stat.hpp index d874d3192..ec82f983a 100755 --- a/include/libtorrent/stat.hpp +++ b/include/libtorrent/stat.hpp @@ -46,7 +46,7 @@ namespace libtorrent class stat { friend class invariant_access; - enum { history = 5 }; + enum { history = 10 }; public: stat() diff --git a/include/libtorrent/storage.hpp b/include/libtorrent/storage.hpp index 1dc355341..50d859c24 100755 --- a/include/libtorrent/storage.hpp +++ b/include/libtorrent/storage.hpp @@ -95,6 +95,11 @@ namespace libtorrent bool move_storage(boost::filesystem::path save_path); + // this will close all open files that are opened for + // writing. This is called when a torrent has finished + // downloading. + void release(); + #ifndef NDEBUG // overwrites some slots with the // contents of others @@ -121,6 +126,8 @@ namespace libtorrent , detail::piece_checker_data& data , std::vector& pieces); + void release(); + void allocate_slots(int num_slots); void mark_failed(int index); diff --git a/src/file.cpp b/src/file.cpp index f0c3baa19..3aaa2ee36 100755 --- a/src/file.cpp +++ b/src/file.cpp @@ -73,7 +73,7 @@ namespace mode_t map_open_mode(int m) { -// if (m == (mode_in | mode_out)) return O_RDWR | O_BINARY; + if (m == (mode_in | mode_out)) return O_RDWR | O_CREAT | O_BINARY | O_RANDOM; if (m == mode_out) return O_WRONLY | O_CREAT | O_BINARY | O_RANDOM; if (m == mode_in) return O_RDONLY | O_BINARY | O_RANDOM; assert(false); @@ -138,7 +138,7 @@ namespace libtorrent size_type read(char* buf, size_type num_bytes) { - assert(m_open_mode == mode_in); + assert(m_open_mode & mode_in); assert(m_fd != -1); size_type ret = ::read(m_fd, buf, num_bytes); @@ -153,7 +153,7 @@ namespace libtorrent size_type write(const char* buf, size_type num_bytes) { - assert(m_open_mode == mode_out); + assert(m_open_mode & mode_out); assert(m_fd != -1); size_type ret = ::write(m_fd, buf, num_bytes); diff --git a/src/identify_client.cpp b/src/identify_client.cpp index e828c95dd..7108ab46a 100755 --- a/src/identify_client.cpp +++ b/src/identify_client.cpp @@ -170,6 +170,7 @@ namespace , map_entry("TS", "TorrentStorm") , map_entry("U", "UPnP") , map_entry("XT", "XanTorrent") + , map_entry("eX", "eXeem") }; bool compare_first_string(map_entry const& e, char const* str) diff --git a/src/peer_connection.cpp b/src/peer_connection.cpp index fd5589b66..216097555 100755 --- a/src/peer_connection.cpp +++ b/src/peer_connection.cpp @@ -1476,8 +1476,8 @@ namespace libtorrent detail::write_uint32((int)m_torrent->metadata().size(), ptr); detail::write_uint32(offset.first, ptr); std::vector const& metadata = m_torrent->metadata(); - std::copy(&metadata[offset.first], &metadata[offset.first - + offset.second], ptr); + std::copy(metadata.begin() + offset.first + , metadata.begin() + offset.first + offset.second, ptr); } else { diff --git a/src/piece_picker.cpp b/src/piece_picker.cpp index 5bed89819..20195b13b 100755 --- a/src/piece_picker.cpp +++ b/src/piece_picker.cpp @@ -396,6 +396,10 @@ namespace libtorrent void piece_picker::dec_refcount(int i) { +#ifndef NDEBUG +// integrity_check(); +#endif + assert(i >= 0); assert(i < (int)m_piece_map.size()); diff --git a/src/policy.cpp b/src/policy.cpp index b62c5b8f4..a6dfa5b92 100755 --- a/src/policy.cpp +++ b/src/policy.cpp @@ -91,7 +91,7 @@ namespace // so, the queue size is 5 * down_rate / 16 kiB (16 kB is the size of each request) // the minimum request size is 2 and the maximum is 100 - int desired_queue_size = static_cast(5.f * c.statistics().download_rate() / (16 * 1024)); + int desired_queue_size = static_cast(queue_time * c.statistics().download_rate() / (16 * 1024)); if (desired_queue_size > max_request_queue) desired_queue_size = max_request_queue; if (desired_queue_size < min_request_queue) desired_queue_size = min_request_queue; diff --git a/src/session.cpp b/src/session.cpp index c0060648b..a7107662b 100755 --- a/src/session.cpp +++ b/src/session.cpp @@ -120,7 +120,10 @@ namespace libtorrent { namespace detail { assert(t != 0); t->parse_resume_data(t->resume_data, t->torrent_ptr->torrent_file()); - t->resume_data = entry(); // clear the resume data now that it has been used + + // clear the resume data now that it has been used + // (the fast resume data is now parsed and stored in t) + t->resume_data = entry(); t->torrent_ptr->check_files(*t, m_mutex); // lock the session to add the new torrent @@ -128,9 +131,9 @@ namespace libtorrent { namespace detail if (!t->abort) { boost::mutex::scoped_lock l(m_ses.m_mutex); - m_ses.m_torrents.insert( std::make_pair(t->info_hash, t->torrent_ptr)).first; + m_torrents.pop_front(); if (t->torrent_ptr->is_seed() && m_ses.m_alerts.should_post(alert::info)) { m_ses.m_alerts.post_alert(torrent_finished_alert( @@ -150,7 +153,8 @@ namespace libtorrent { namespace detail catch(const std::exception& e) { // This will happen if the storage fails to initialize - boost::mutex::scoped_lock l(m_ses.m_mutex); + boost::mutex::scoped_lock l(m_mutex); + boost::mutex::scoped_lock l2(m_ses.m_mutex); if (m_ses.m_alerts.should_post(alert::fatal)) { m_ses.m_alerts.post_alert( @@ -158,6 +162,7 @@ namespace libtorrent { namespace detail t->torrent_ptr->get_handle() , e.what())); } + m_torrents.pop_front(); } catch(...) { @@ -165,12 +170,9 @@ namespace libtorrent { namespace detail std::cerr << "error while checking files\n"; #endif assert(false); + boost::mutex::scoped_lock l(m_mutex); + m_torrents.pop_front(); } - - // remove ourself from the 'checking'-list - // (we're no longer in the checking state) - boost::mutex::scoped_lock l(m_mutex); - m_torrents.pop_front(); } } @@ -868,6 +870,12 @@ namespace libtorrent + peer_connection::num_supported_extensions, false); } + void session::set_peer_id(peer_id const& id) + { + boost::mutex::scoped_lock l(m_impl.m_mutex); + m_impl.m_peer_id = id; + } + void session::enable_extension(peer_connection::extension_index i) { assert(i >= 0); @@ -878,28 +886,24 @@ namespace libtorrent std::vector session::get_torrents() { + boost::mutex::scoped_lock l(m_checker_impl.m_mutex); + boost::mutex::scoped_lock l2(m_impl.m_mutex); std::vector ret; + for (std::deque::iterator i + = m_checker_impl.m_torrents.begin() + , end(m_checker_impl.m_torrents.end()); i != end; ++i) { - boost::mutex::scoped_lock l(m_checker_impl.m_mutex); - for (std::deque::iterator i - = m_checker_impl.m_torrents.begin() - , end(m_checker_impl.m_torrents.end()); i != end; ++i) - { - ret.push_back(torrent_handle(&m_impl, &m_checker_impl - , i->info_hash)); - } + ret.push_back(torrent_handle(&m_impl, &m_checker_impl + , i->info_hash)); } + for (detail::session_impl::torrent_map::iterator i + = m_impl.m_torrents.begin(), end(m_impl.m_torrents.end()); + i != end; ++i) { - boost::mutex::scoped_lock l(m_impl.m_mutex); - for (detail::session_impl::torrent_map::iterator i - = m_impl.m_torrents.begin(), end(m_impl.m_torrents.end()); - i != end; ++i) - { - if (i->second->is_aborted()) continue; - ret.push_back(torrent_handle(&m_impl, &m_checker_impl - , i->first)); - } + if (i->second->is_aborted()) continue; + ret.push_back(torrent_handle(&m_impl, &m_checker_impl + , i->first)); } return ret; } diff --git a/src/storage.cpp b/src/storage.cpp index cd0631d3d..fee718732 100755 --- a/src/storage.cpp +++ b/src/storage.cpp @@ -38,6 +38,7 @@ POSSIBILITY OF SUCH DAMAGE. #include #include #include +#include #ifdef _MSC_VER #pragma warning(push, 1) @@ -49,6 +50,8 @@ POSSIBILITY OF SUCH DAMAGE. #include #include #include +#include +#include #ifdef _MSC_VER #pragma warning(pop) @@ -72,9 +75,12 @@ namespace std #endif using namespace boost::filesystem; +namespace pt = boost::posix_time; +using boost::bind; namespace { + using namespace libtorrent; void print_to_log(const std::string& s) { @@ -93,6 +99,58 @@ namespace else return t.name() / p; } + + struct file_entry + { + file_entry(boost::shared_ptr const& f_) + : f(f_) + , last_use(pt::second_clock::universal_time()) {} + boost::shared_ptr f; + pt::ptime last_use; + file::open_mode mode; + }; + + struct file_pool + { + file_pool(int size): m_size(size) {} + + boost::shared_ptr open_file(path const& p, file::open_mode m) + { + typedef std::map::iterator iterator; + iterator i = m_files.find(p); + if (i != m_files.end()) + { + i->second.last_use = pt::second_clock::universal_time(); + if ((i->second.mode & m) != m) + { + i->second.f.reset(new file(p, m)); + i->second.mode = m; + } + return i->second.f; + } + // the file is not in our cache + if ((int)m_files.size() >= m_size) + { + i = m_files.begin(); + for (iterator j = boost::next(m_files.begin()); j != m_files.end(); ++j) + if (j->second.last_use < i->second.last_use) i = j; + m_files.erase(i); + } + file_entry e(boost::shared_ptr(new file(p, m))); + e.mode = m; + m_files.insert(std::make_pair(p, e)); + return e.f; + } + + void release() + { + m_files.clear(); + } + + private: + int m_size; + std::map m_files; + }; } namespace libtorrent @@ -194,6 +252,7 @@ namespace libtorrent impl(torrent_info const& info, path const& path) : thread_safe_storage(info.num_pieces()) , info(info) + , files(10) { save_path = complete(path); assert(save_path.is_complete()); @@ -203,10 +262,12 @@ namespace libtorrent : thread_safe_storage(x.info.num_pieces()) , info(x.info) , save_path(x.save_path) + , files(x.files) {} torrent_info const& info; path save_path; + file_pool files; }; storage::storage(const torrent_info& info, const path& path) @@ -215,6 +276,11 @@ namespace libtorrent assert(info.begin_files() != info.end_files()); } + void storage::release() + { + m_pimpl->files.release(); + } + void storage::swap(storage& other) { m_pimpl.swap(other.m_pimpl); @@ -233,6 +299,8 @@ namespace libtorrent else if(!is_directory(save_path)) return false; + m_pimpl->files.release(); + if (m_pimpl->info.num_files() == 1) { path single_file = m_pimpl->info.begin_files()->path; @@ -323,21 +391,21 @@ namespace libtorrent ++file_iter; } - file in( + boost::shared_ptr in(m_pimpl->files.open_file( m_pimpl->save_path / get_filename(m_pimpl->info, file_iter->path) - , file::in); + , file::in)); assert(file_offset < file_iter->size); - in.seek(file_offset); - if (in.tell() != file_offset) + in->seek(file_offset); + if (in->tell() != file_offset) { // the file was not big enough throw file_error("slot has no storage"); } #ifndef NDEBUG - size_type in_tell = in.tell(); + size_type in_tell = in->tell(); assert(in_tell == file_offset); #endif @@ -358,7 +426,7 @@ namespace libtorrent if (file_offset + read_bytes > file_iter->size) read_bytes = static_cast(file_iter->size - file_offset); - size_type actual_read = in.read(buf + buf_pos, read_bytes); + size_type actual_read = in->read(buf + buf_pos, read_bytes); if (read_bytes != actual_read) { @@ -377,7 +445,8 @@ namespace libtorrent path path = m_pimpl->save_path / get_filename(m_pimpl->info, file_iter->path); file_offset = 0; - in.open(path, file::in); + in = m_pimpl->files.open_file(path, file::in); + in->seek(0); } } @@ -415,12 +484,12 @@ namespace libtorrent } path p(m_pimpl->save_path / get_filename(m_pimpl->info, file_iter->path)); - file out(p, file::out); + boost::shared_ptr out = m_pimpl->files.open_file(p, file::out | file::in); assert(file_offset < file_iter->size); - out.seek(file_offset); - size_type pos = out.tell(); + out->seek(file_offset); + size_type pos = out->tell(); if (pos != file_offset) { @@ -450,7 +519,7 @@ namespace libtorrent assert(buf_pos >= 0); assert(write_bytes > 0); - size_type written = out.write(buf + buf_pos, write_bytes); + size_type written = out->write(buf + buf_pos, write_bytes); if (written != write_bytes) { @@ -472,7 +541,8 @@ namespace libtorrent assert(file_iter != m_pimpl->info.end_files()); path p = m_pimpl->save_path / get_filename(m_pimpl->info, file_iter->path); file_offset = 0; - out.open(p, file::out); + out = m_pimpl->files.open_file(p, file::out | file::in); + out->seek(0); } } } @@ -497,6 +567,8 @@ namespace libtorrent , detail::piece_checker_data& data , std::vector& pieces); + void release(); + void allocate_slots(int num_slots); void mark_failed(int index); unsigned long piece_crc( @@ -612,6 +684,16 @@ namespace libtorrent { } + void piece_manager::release() + { + m_pimpl->release(); + } + + void piece_manager::impl::release() + { + m_storage.release(); + } + void piece_manager::impl::export_piece_map( std::vector& p) const { diff --git a/src/torrent.cpp b/src/torrent.cpp index 20bd2cf4b..497c7a4de 100755 --- a/src/torrent.cpp +++ b/src/torrent.cpp @@ -280,8 +280,6 @@ namespace libtorrent m_last_working_tracker = prioritize_tracker(m_currently_trying_tracker); - m_next_request = second_clock::universal_time() - + boost::posix_time::seconds(m_duration); m_currently_trying_tracker = 0; m_duration = interval; @@ -289,7 +287,7 @@ namespace libtorrent { // if the peer list is empty, we should contact the // tracker soon again to see if there are any peers - m_next_request = second_clock::universal_time() + boost::posix_time::seconds(60); + m_next_request = second_clock::universal_time() + boost::posix_time::minutes(2); } else { @@ -531,7 +529,6 @@ namespace libtorrent tracker_request torrent::generate_tracker_request() { - m_duration = 1800; m_next_request = second_clock::universal_time() + boost::posix_time::seconds(tracker_retry_delay_max); @@ -673,6 +670,8 @@ namespace libtorrent i->second->disconnect(); } + m_storage->release(); + // make the next tracker request // be a completed-event m_event = tracker_request::completed; @@ -807,6 +806,7 @@ namespace libtorrent void torrent::pause() { + if (m_paused) return; disconnect_all(); m_paused = true; // tell the tracker that we stopped @@ -816,6 +816,7 @@ namespace libtorrent void torrent::resume() { + if (!m_paused) return; m_paused = false; // tell the tracker that we're back @@ -921,6 +922,7 @@ namespace libtorrent assert(m_storage.get()); assert(piece_index >= 0); assert(piece_index < m_torrent_file.num_pieces()); + assert(piece_index < m_have_pieces.size()); int size = static_cast(m_torrent_file.piece_size(piece_index)); std::vector buffer(size);