diff --git a/include/Makefile.am b/include/Makefile.am index 38ef16cdc..30ddc56c9 100644 --- a/include/Makefile.am +++ b/include/Makefile.am @@ -3,6 +3,7 @@ libtorrent/alert_types.hpp \ libtorrent/allocate_resources.hpp \ libtorrent/async_gethostbyname.hpp \ libtorrent/bencode.hpp \ +libtorrent/buffer.hpp \ libtorrent/debug.hpp \ libtorrent/entry.hpp \ libtorrent/escape_string.hpp \ diff --git a/src/Makefile.am b/src/Makefile.am index 75f22b60b..bf4cfcecc 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1,7 +1,7 @@ lib_LTLIBRARIES = libtorrent.la libtorrent_la_SOURCES = allocate_resources.cpp async_gethostbyname.cpp \ -entry.cpp escape_string.cpp \ +buffer.cpp entry.cpp escape_string.cpp \ peer_connection.cpp piece_picker.cpp policy.cpp \ session.cpp sha1.cpp socket.cpp stat.cpp \ storage.cpp torrent.cpp torrent_handle.cpp \ @@ -15,6 +15,7 @@ $(top_srcdir)/include/libtorrent/alert_types.hpp \ $(top_srcdir)/include/libtorrent/allocate_resources.hpp \ $(top_srcdir)/include/libtorrent/async_gethostbyname.hpp \ $(top_srcdir)/include/libtorrent/bencode.hpp \ +$(top_srcdir)/include/libtorrent/buffer.hpp \ $(top_srcdir)/include/libtorrent/debug.hpp \ $(top_srcdir)/include/libtorrent/entry.hpp \ $(top_srcdir)/include/libtorrent/escape_string.hpp \ diff --git a/src/storage.cpp b/src/storage.cpp index 995a5b742..f1284a259 100755 --- a/src/storage.cpp +++ b/src/storage.cpp @@ -194,7 +194,7 @@ namespace log << s; log.flush(); } - +/* struct file_key { file_key(sha1_hash ih, path f): info_hash(ih), file_path(f) {} @@ -208,14 +208,15 @@ namespace return file_path < fk.file_path; } }; - +*/ struct file_entry { file_entry(boost::shared_ptr const& f) : file_ptr(f) , last_use(pt::second_clock::universal_time()) {} mutable boost::shared_ptr file_ptr; - file_key key; + path file_path; + void* key; pt::ptime last_use; file::open_mode mode; }; @@ -224,16 +225,23 @@ namespace { file_pool(int size): m_size(size) {} - boost::shared_ptr open_file(sha1_hash const& info_hash, path const& p, file::open_mode m) + boost::shared_ptr open_file(void* st, path const& p, file::open_mode m) { + assert(st != 0); assert(p.is_complete()); typedef file_set::nth_index<0>::type path_view; path_view& pt = m_files.get<0>(); - path_view::iterator i = pt.find(file_key(info_hash, p)); + path_view::iterator i = pt.find(p); if (i != pt.end()) { file_entry e = *i; e.last_use = pt::second_clock::universal_time(); + + // if you hit this assert, you probably have more than one + // storage/torrent using the same file at the same time! + assert(e.key == st); + + e.key = st; if ((e.mode & m) != m) { // close the file before we open it with @@ -265,24 +273,23 @@ namespace } file_entry e(boost::shared_ptr(new file(p, m))); e.mode = m; - e.key.info_hash = info_hash; - e.key.file_path = p; + e.key = st; + e.file_path = p; pt.insert(e); return e.file_ptr; } - void release(sha1_hash const& info_hash) + void release(void* st) { - using namespace boost::lambda; - using boost::lambda::_1; + assert(st != 0); + using boost::tie; + + typedef file_set::nth_index<2>::type key_view; + key_view& kt = m_files.get<2>(); + + key_view::iterator start, end; + tie(start, end) = kt.equal_range(st); - typedef file_set::nth_index<0>::type path_view; - path_view& pt = m_files.get<0>(); - file_key lower_key(info_hash, path()); - file_key upper_key(info_hash, path()); - upper_key.info_hash[19] += 1; - std::pair r - = pt.range(!(_1 < lower_key), _1 < upper_key); /* std::cerr << "releasing files!\n"; for (path_view::iterator i = r.first; i != r.second; ++i) @@ -290,7 +297,7 @@ namespace std::cerr << i->key.file_path.native_file_string() << "\n"; } */ - pt.erase(r.first, r.second); + kt.erase(start, end); /* std::cerr << "files left: " << pt.size() << "\n"; for (path_view::iterator i = pt.begin(); i != pt.end(); ++i) @@ -305,9 +312,12 @@ namespace typedef boost::multi_index_container< file_entry, indexed_by< - ordered_unique > + ordered_unique > , ordered_non_unique > + , ordered_non_unique > > > file_set; @@ -430,7 +440,7 @@ namespace libtorrent int slot; }; - class storage::impl : public thread_safe_storage + class storage::impl : public thread_safe_storage, boost::noncopyable { public: impl(torrent_info const& info, path const& path) @@ -449,7 +459,7 @@ namespace libtorrent ~impl() { - files.release(info.info_hash()); + files.release(this); } torrent_info const& info; @@ -467,7 +477,7 @@ namespace libtorrent void storage::release_files() { - m_pimpl->files.release(m_pimpl->info.info_hash()); + m_pimpl->files.release(m_pimpl.get()); } void storage::swap(storage& other) @@ -500,7 +510,7 @@ namespace libtorrent return false; #endif - m_pimpl->files.release(m_pimpl->info.info_hash()); + m_pimpl->files.release(m_pimpl.get()); if (m_pimpl->info.num_files() == 1) { @@ -601,7 +611,7 @@ namespace libtorrent } boost::shared_ptr in(m_pimpl->files.open_file( - m_pimpl->info.info_hash() + m_pimpl.get() , m_pimpl->save_path / file_iter->path , file::in)); @@ -656,7 +666,7 @@ namespace libtorrent file_offset = 0; in = m_pimpl->files.open_file( - m_pimpl->info.info_hash() + m_pimpl.get() , path, file::in); in->seek(0); } @@ -698,7 +708,7 @@ namespace libtorrent path p(m_pimpl->save_path / file_iter->path); boost::shared_ptr out = m_pimpl->files.open_file( - m_pimpl->info.info_hash() + m_pimpl.get() , p, file::out | file::in); assert(file_offset < file_iter->size); @@ -757,7 +767,7 @@ namespace libtorrent path p = m_pimpl->save_path / file_iter->path; file_offset = 0; out = m_pimpl->files.open_file( - m_pimpl->info.info_hash() + m_pimpl.get() , p, file::out | file::in); out->seek(0); diff --git a/test/Makefile.am b/test/Makefile.am index 857e6655b..3045e1e50 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -13,6 +13,9 @@ test_ip_filter_LDADD = $(top_builddir)/src/libtorrent.la test_piece_picker_SOURCES = main.cpp test_piece_picker.cpp test_piece_picker_LDADD = $(top_builddir)/src/libtorrent.la +test_storage_SOURCES = main.cpp test_storage.cpp +test_storage_LDADD = $(top_builddir)/src/libtorrent.la + noinst_HEADERS = test.hpp AM_CXXFLAGS=-ftemplate-depth-50 -I$(top_srcdir)/include @DEBUGFLAGS@ @PTHREAD_CFLAGS@ diff --git a/test/test_storage.cpp b/test/test_storage.cpp index e52eea5b6..858dde3f9 100644 --- a/test/test_storage.cpp +++ b/test/test_storage.cpp @@ -43,7 +43,10 @@ int test_main() int num_pieces = (613 + 17 + piece_size - 1) / piece_size; TEST_CHECK(info.num_pieces() == num_pieces); - + + char piece[piece_size]; + + { // avoid having two storages use the same files storage s(info, initial_path()); // write piece 1 (in slot 0) @@ -51,7 +54,6 @@ int test_main() s.write(piece1 + half, 0, half, half); // verify piece 1 - char piece[piece_size]; s.read(piece, 0, 0, piece_size); TEST_CHECK(std::equal(piece, piece + piece_size, piece1)); @@ -69,6 +71,7 @@ int test_main() // make sure the files have the correct size TEST_CHECK(file_size(initial_path() / "temp_storage" / "test1.tmp") == 17); TEST_CHECK(file_size(initial_path() / "temp_storage" / "test2.tmp") == 31); + } // make sure the piece_manager can identify the pieces piece_manager pm(info, initial_path());