forked from premiere/premiere-libtorrent
made the storage into a customization point. it is now interchangable for a custom implementation
This commit is contained in:
parent
52d6a201be
commit
029953c5ae
|
@ -98,7 +98,8 @@ int main(int argc, char* argv[])
|
|||
t.set_piece_size(piece_size);
|
||||
|
||||
file_pool fp;
|
||||
storage st(t, full_path.branch_path(), fp);
|
||||
boost::scoped_ptr<storage_interface> st(
|
||||
default_storage_constructor(t, full_path.branch_path(), fp));
|
||||
t.add_tracker(argv[2]);
|
||||
|
||||
// calculate the hash for all pieces
|
||||
|
@ -106,7 +107,7 @@ int main(int argc, char* argv[])
|
|||
std::vector<char> buf(piece_size);
|
||||
for (int i = 0; i < num; ++i)
|
||||
{
|
||||
st.read(&buf[0], i, 0, t.piece_size(i));
|
||||
st->read(&buf[0], i, 0, t.piece_size(i));
|
||||
hasher h(&buf[0], t.piece_size(i));
|
||||
t.set_hash(i, h.final());
|
||||
std::cerr << (i+1) << "/" << num << "\r";
|
||||
|
|
|
@ -238,7 +238,8 @@ namespace libtorrent
|
|||
, boost::filesystem::path const& save_path
|
||||
, entry const& resume_data
|
||||
, bool compact_mode
|
||||
, int block_size);
|
||||
, int block_size
|
||||
, storage_constructor_type sc);
|
||||
|
||||
torrent_handle add_torrent(
|
||||
char const* tracker_url
|
||||
|
@ -247,7 +248,8 @@ namespace libtorrent
|
|||
, boost::filesystem::path const& save_path
|
||||
, entry const& resume_data
|
||||
, bool compact_mode
|
||||
, int block_size);
|
||||
, int block_size
|
||||
, storage_constructor_type sc);
|
||||
|
||||
void remove_torrent(torrent_handle const& h);
|
||||
|
||||
|
|
|
@ -1,3 +1,35 @@
|
|||
/*
|
||||
|
||||
Copyright (c) 2007, Arvid Norberg
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in
|
||||
the documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the author nor the names of its
|
||||
contributors may be used to endorse or promote products derived
|
||||
from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef TORRENT_NATPMP_HPP
|
||||
#define TORRENT_NATPMP_HPP
|
||||
|
||||
|
|
|
@ -61,6 +61,7 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
#include "libtorrent/fingerprint.hpp"
|
||||
|
||||
#include "libtorrent/resource_request.hpp"
|
||||
#include "libtorrent/storage.hpp"
|
||||
|
||||
#ifdef _MSC_VER
|
||||
# include <eh.h>
|
||||
|
@ -137,7 +138,8 @@ namespace libtorrent
|
|||
, boost::filesystem::path const& save_path
|
||||
, entry const& resume_data = entry()
|
||||
, bool compact_mode = true
|
||||
, int block_size = 16 * 1024);
|
||||
, int block_size = 16 * 1024
|
||||
, storage_constructor_type sc = default_storage_constructor);
|
||||
|
||||
// TODO: deprecated, this is for backwards compatibility only
|
||||
torrent_handle add_torrent(
|
||||
|
@ -145,10 +147,11 @@ namespace libtorrent
|
|||
, boost::filesystem::path const& save_path
|
||||
, entry const& resume_data = entry()
|
||||
, bool compact_mode = true
|
||||
, int block_size = 16 * 1024)
|
||||
, int block_size = 16 * 1024
|
||||
, storage_constructor_type sc = default_storage_constructor)
|
||||
{
|
||||
return add_torrent(torrent_info(e), save_path, resume_data
|
||||
, compact_mode, block_size);
|
||||
, compact_mode, block_size, sc);
|
||||
}
|
||||
|
||||
torrent_handle add_torrent(
|
||||
|
@ -158,7 +161,8 @@ namespace libtorrent
|
|||
, boost::filesystem::path const& save_path
|
||||
, entry const& resume_data = entry()
|
||||
, bool compact_mode = true
|
||||
, int block_size = 16 * 1024);
|
||||
, int block_size = 16 * 1024
|
||||
, storage_constructor_type sc = default_storage_constructor);
|
||||
|
||||
session_proxy abort() { return session_proxy(m_impl); }
|
||||
|
||||
|
|
|
@ -87,40 +87,30 @@ namespace libtorrent
|
|||
std::string m_msg;
|
||||
};
|
||||
|
||||
class TORRENT_EXPORT storage
|
||||
struct TORRENT_EXPORT storage_interface
|
||||
{
|
||||
public:
|
||||
storage(
|
||||
const torrent_info& info
|
||||
, const boost::filesystem::path& path
|
||||
, file_pool& fp);
|
||||
|
||||
void swap(storage&);
|
||||
|
||||
// may throw file_error if storage for slot does not exist
|
||||
size_type read(char* buf, int slot, int offset, int size);
|
||||
virtual size_type read(char* buf, int slot, int offset, int size) = 0;
|
||||
|
||||
// may throw file_error if storage for slot hasn't been allocated
|
||||
void write(const char* buf, int slot, int offset, int size);
|
||||
virtual void write(const char* buf, int slot, int offset, int size) = 0;
|
||||
|
||||
bool move_storage(boost::filesystem::path save_path);
|
||||
virtual bool move_storage(boost::filesystem::path save_path) = 0;
|
||||
|
||||
// this will close all open files that are opened for
|
||||
// writing. This is called when a torrent has finished
|
||||
// downloading.
|
||||
void release_files();
|
||||
|
||||
#ifndef NDEBUG
|
||||
// overwrites some slots with the
|
||||
// contents of others
|
||||
void shuffle();
|
||||
#endif
|
||||
|
||||
private:
|
||||
class impl;
|
||||
boost::shared_ptr<impl> m_pimpl;
|
||||
virtual void release_files() = 0;
|
||||
virtual ~storage_interface() {}
|
||||
};
|
||||
|
||||
typedef storage_interface* (&storage_constructor_type)(
|
||||
torrent_info const&, boost::filesystem::path const&
|
||||
, file_pool&);
|
||||
|
||||
TORRENT_EXPORT storage_interface* default_storage_constructor(torrent_info const& ti
|
||||
, boost::filesystem::path const& path, file_pool& fp);
|
||||
|
||||
class TORRENT_EXPORT piece_manager : boost::noncopyable
|
||||
{
|
||||
public:
|
||||
|
@ -128,7 +118,8 @@ namespace libtorrent
|
|||
piece_manager(
|
||||
const torrent_info& info
|
||||
, const boost::filesystem::path& path
|
||||
, file_pool& fp);
|
||||
, file_pool& fp
|
||||
, storage_constructor_type sc);
|
||||
|
||||
~piece_manager();
|
||||
|
||||
|
|
|
@ -68,6 +68,7 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
#include "libtorrent/config.hpp"
|
||||
#include "libtorrent/escape_string.hpp"
|
||||
#include "libtorrent/bandwidth_manager.hpp"
|
||||
#include "libtorrent/storage.hpp"
|
||||
|
||||
namespace libtorrent
|
||||
{
|
||||
|
@ -100,7 +101,8 @@ namespace libtorrent
|
|||
, tcp::endpoint const& net_interface
|
||||
, bool compact_mode
|
||||
, int block_size
|
||||
, session_settings const& s);
|
||||
, session_settings const& s
|
||||
, storage_constructor_type sc);
|
||||
|
||||
// used with metadata-less torrents
|
||||
// (the metadata is downloaded from the peers)
|
||||
|
@ -114,7 +116,8 @@ namespace libtorrent
|
|||
, tcp::endpoint const& net_interface
|
||||
, bool compact_mode
|
||||
, int block_size
|
||||
, session_settings const& s);
|
||||
, session_settings const& s
|
||||
, storage_constructor_type sc);
|
||||
|
||||
~torrent();
|
||||
|
||||
|
@ -658,6 +661,8 @@ namespace libtorrent
|
|||
|
||||
session_settings const& m_settings;
|
||||
|
||||
storage_constructor_type m_storage_constructor;
|
||||
|
||||
#ifndef TORRENT_DISABLE_EXTENSIONS
|
||||
typedef std::list<boost::shared_ptr<torrent_plugin> > extension_list_t;
|
||||
extension_list_t m_extensions;
|
||||
|
|
|
@ -1,3 +1,35 @@
|
|||
/*
|
||||
|
||||
Copyright (c) 2007, Arvid Norberg
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in
|
||||
the documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the author nor the names of its
|
||||
contributors may be used to endorse or promote products derived
|
||||
from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
#include <libtorrent/natpmp.hpp>
|
||||
#include <libtorrent/io.hpp>
|
||||
#include <boost/bind.hpp>
|
||||
|
@ -31,7 +63,16 @@ natpmp::natpmp(io_service& ios, portmap_callback_t const& cb)
|
|||
if (i->endpoint().address().is_v4()) break;
|
||||
}
|
||||
|
||||
if (i == udp::resolver_iterator()) return;
|
||||
if (i == udp::resolver_iterator())
|
||||
{
|
||||
#if defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING)
|
||||
m_log << "local host name did not resolve to an IPv4 address. "
|
||||
"disabling NAT-PMP" << std::endl;
|
||||
#endif
|
||||
m_disabled = true;
|
||||
return;
|
||||
}
|
||||
|
||||
address_v4 local = i->endpoint().address().to_v4();
|
||||
#if defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING)
|
||||
m_log << to_simple_string(microsec_clock::universal_time())
|
||||
|
@ -45,7 +86,7 @@ natpmp::natpmp(io_service& ios, portmap_callback_t const& cb)
|
|||
// the local address seems to be an external
|
||||
// internet address. Assume it is not behind a NAT
|
||||
#if defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING)
|
||||
m_log << "not on a NAT. disable NAT-PMP" << std::endl;
|
||||
m_log << "not on a NAT. disabling NAT-PMP" << std::endl;
|
||||
#endif
|
||||
m_disabled = true;
|
||||
return;
|
||||
|
|
|
@ -167,10 +167,11 @@ namespace libtorrent
|
|||
, boost::filesystem::path const& save_path
|
||||
, entry const& resume_data
|
||||
, bool compact_mode
|
||||
, int block_size)
|
||||
, int block_size
|
||||
, storage_constructor_type sc)
|
||||
{
|
||||
return m_impl->add_torrent(ti, save_path, resume_data
|
||||
, compact_mode, block_size);
|
||||
, compact_mode, block_size, sc);
|
||||
}
|
||||
|
||||
torrent_handle session::add_torrent(
|
||||
|
@ -180,10 +181,11 @@ namespace libtorrent
|
|||
, boost::filesystem::path const& save_path
|
||||
, entry const& e
|
||||
, bool compact_mode
|
||||
, int block_size)
|
||||
, int block_size
|
||||
, storage_constructor_type sc)
|
||||
{
|
||||
return m_impl->add_torrent(tracker_url, info_hash, name, save_path, e
|
||||
, compact_mode, block_size);
|
||||
, compact_mode, block_size, sc);
|
||||
}
|
||||
|
||||
void session::remove_torrent(const torrent_handle& h)
|
||||
|
|
|
@ -1219,7 +1219,8 @@ namespace libtorrent { namespace detail
|
|||
, boost::filesystem::path const& save_path
|
||||
, entry const& resume_data
|
||||
, bool compact_mode
|
||||
, int block_size)
|
||||
, int block_size
|
||||
, storage_constructor_type sc)
|
||||
{
|
||||
// make sure the block_size is an even power of 2
|
||||
#ifndef NDEBUG
|
||||
|
@ -1259,7 +1260,7 @@ namespace libtorrent { namespace detail
|
|||
boost::shared_ptr<torrent> torrent_ptr(
|
||||
new torrent(*this, m_checker_impl, ti, save_path
|
||||
, m_listen_interface, compact_mode, block_size
|
||||
, settings()));
|
||||
, settings(), sc));
|
||||
|
||||
#ifndef TORRENT_DISABLE_EXTENSIONS
|
||||
for (extension_list_t::iterator i = m_extensions.begin()
|
||||
|
@ -1304,7 +1305,8 @@ namespace libtorrent { namespace detail
|
|||
, boost::filesystem::path const& save_path
|
||||
, entry const&
|
||||
, bool compact_mode
|
||||
, int block_size)
|
||||
, int block_size
|
||||
, storage_constructor_type sc)
|
||||
{
|
||||
// make sure the block_size is an even power of 2
|
||||
#ifndef NDEBUG
|
||||
|
@ -1345,7 +1347,7 @@ namespace libtorrent { namespace detail
|
|||
boost::shared_ptr<torrent> torrent_ptr(
|
||||
new torrent(*this, m_checker_impl, tracker_url, info_hash, name
|
||||
, save_path, m_listen_interface, compact_mode, block_size
|
||||
, settings()));
|
||||
, settings(), sc));
|
||||
|
||||
#ifndef TORRENT_DISABLE_EXTENSIONS
|
||||
for (extension_list_t::iterator i = m_extensions.begin()
|
||||
|
|
215
src/storage.cpp
215
src/storage.cpp
|
@ -341,53 +341,41 @@ namespace libtorrent
|
|||
int slot;
|
||||
};
|
||||
|
||||
class storage::impl : public thread_safe_storage, boost::noncopyable
|
||||
class storage : public storage_interface, thread_safe_storage, boost::noncopyable
|
||||
{
|
||||
public:
|
||||
impl(torrent_info const& info, path const& path, file_pool& fp)
|
||||
storage(torrent_info const& info, path const& path, file_pool& fp)
|
||||
: thread_safe_storage(info.num_pieces())
|
||||
, info(info)
|
||||
, files(fp)
|
||||
, m_info(info)
|
||||
, m_files(fp)
|
||||
{
|
||||
save_path = complete(path);
|
||||
assert(save_path.is_complete());
|
||||
assert(info.begin_files() != info.end_files());
|
||||
m_save_path = complete(path);
|
||||
assert(m_save_path.is_complete());
|
||||
}
|
||||
|
||||
impl(impl const& x)
|
||||
: thread_safe_storage(x.info.num_pieces())
|
||||
, info(x.info)
|
||||
, save_path(x.save_path)
|
||||
, files(x.files)
|
||||
{}
|
||||
void release_files();
|
||||
|
||||
~impl()
|
||||
bool move_storage(path save_path);
|
||||
size_type read(char* buf, int slot, int offset, int size);
|
||||
void write(const char* buf, int slot, int offset, int size);
|
||||
|
||||
~storage()
|
||||
{
|
||||
files.release(this);
|
||||
m_files.release(this);
|
||||
}
|
||||
|
||||
torrent_info const& info;
|
||||
path save_path;
|
||||
torrent_info const& m_info;
|
||||
path m_save_path;
|
||||
// the file pool is typically stored in
|
||||
// the session, to make all storage
|
||||
// instances use the same pool
|
||||
file_pool& files;
|
||||
file_pool& m_files;
|
||||
};
|
||||
|
||||
storage::storage(torrent_info const& info, path const& path
|
||||
, file_pool& fp)
|
||||
: m_pimpl(new impl(info, path, fp))
|
||||
{
|
||||
assert(info.begin_files() != info.end_files());
|
||||
}
|
||||
|
||||
void storage::release_files()
|
||||
{
|
||||
m_pimpl->files.release(m_pimpl.get());
|
||||
}
|
||||
|
||||
void storage::swap(storage& other)
|
||||
{
|
||||
m_pimpl.swap(other.m_pimpl);
|
||||
m_files.release(this);
|
||||
}
|
||||
|
||||
// returns true on success
|
||||
|
@ -396,7 +384,7 @@ namespace libtorrent
|
|||
path old_path;
|
||||
path new_path;
|
||||
|
||||
save_path = complete(save_path);
|
||||
m_save_path = complete(save_path);
|
||||
|
||||
#if defined(_WIN32) && defined(UNICODE)
|
||||
std::wstring wsave_path(safe_convert(save_path.native_file_string()));
|
||||
|
@ -415,10 +403,10 @@ namespace libtorrent
|
|||
return false;
|
||||
#endif
|
||||
|
||||
m_pimpl->files.release(m_pimpl.get());
|
||||
m_files.release(this);
|
||||
|
||||
old_path = m_pimpl->save_path / m_pimpl->info.name();
|
||||
new_path = save_path / m_pimpl->info.name();
|
||||
old_path = m_save_path / m_info.name();
|
||||
new_path = save_path / m_info.name();
|
||||
|
||||
try
|
||||
{
|
||||
|
@ -427,7 +415,7 @@ namespace libtorrent
|
|||
#else
|
||||
rename(old_path, new_path);
|
||||
#endif
|
||||
m_pimpl->save_path = save_path;
|
||||
m_save_path = save_path;
|
||||
return true;
|
||||
}
|
||||
catch (std::exception&) {}
|
||||
|
@ -435,15 +423,14 @@ namespace libtorrent
|
|||
}
|
||||
|
||||
#ifndef NDEBUG
|
||||
|
||||
/*
|
||||
void storage::shuffle()
|
||||
{
|
||||
int num_pieces = m_pimpl->info.num_pieces();
|
||||
int num_pieces = m_info.num_pieces();
|
||||
|
||||
std::vector<int> pieces(num_pieces);
|
||||
for (std::vector<int>::iterator i = pieces.begin();
|
||||
i != pieces.end();
|
||||
++i)
|
||||
i != pieces.end(); ++i)
|
||||
{
|
||||
*i = static_cast<int>(i - pieces.begin());
|
||||
}
|
||||
|
@ -456,13 +443,13 @@ namespace libtorrent
|
|||
{
|
||||
const int slot_index = targets[i];
|
||||
const int piece_index = pieces[i];
|
||||
const int slot_size =static_cast<int>(m_pimpl->info.piece_size(slot_index));
|
||||
const int slot_size =static_cast<int>(m_info.piece_size(slot_index));
|
||||
std::vector<char> buf(slot_size);
|
||||
read(&buf[0], piece_index, 0, slot_size);
|
||||
write(&buf[0], slot_index, 0, slot_size);
|
||||
}
|
||||
}
|
||||
|
||||
*/
|
||||
#endif
|
||||
|
||||
size_type storage::read(
|
||||
|
@ -472,27 +459,27 @@ namespace libtorrent
|
|||
, int size)
|
||||
{
|
||||
assert(buf != 0);
|
||||
assert(slot >= 0 && slot < m_pimpl->info.num_pieces());
|
||||
assert(slot >= 0 && slot < m_info.num_pieces());
|
||||
assert(offset >= 0);
|
||||
assert(offset < m_pimpl->info.piece_size(slot));
|
||||
assert(offset < m_info.piece_size(slot));
|
||||
assert(size > 0);
|
||||
|
||||
slot_lock lock(*m_pimpl, slot);
|
||||
slot_lock lock(*this, slot);
|
||||
|
||||
#ifndef NDEBUG
|
||||
std::vector<file_slice> slices
|
||||
= m_pimpl->info.map_block(slot, offset, size);
|
||||
= m_info.map_block(slot, offset, size);
|
||||
assert(!slices.empty());
|
||||
#endif
|
||||
|
||||
size_type start = slot * (size_type)m_pimpl->info.piece_length() + offset;
|
||||
assert(start + size <= m_pimpl->info.total_size());
|
||||
size_type start = slot * (size_type)m_info.piece_length() + offset;
|
||||
assert(start + size <= m_info.total_size());
|
||||
|
||||
// find the file iterator and file offset
|
||||
size_type file_offset = start;
|
||||
std::vector<file_entry>::const_iterator file_iter;
|
||||
|
||||
for (file_iter = m_pimpl->info.begin_files();;)
|
||||
for (file_iter = m_info.begin_files();;)
|
||||
{
|
||||
if (file_offset < file_iter->size)
|
||||
break;
|
||||
|
@ -501,10 +488,8 @@ namespace libtorrent
|
|||
++file_iter;
|
||||
}
|
||||
|
||||
boost::shared_ptr<file> in(m_pimpl->files.open_file(
|
||||
m_pimpl.get()
|
||||
, m_pimpl->save_path / file_iter->path
|
||||
, file::in));
|
||||
boost::shared_ptr<file> in(m_files.open_file(
|
||||
this, m_save_path / file_iter->path, file::in));
|
||||
|
||||
assert(file_offset < file_iter->size);
|
||||
|
||||
|
@ -523,7 +508,7 @@ namespace libtorrent
|
|||
#endif
|
||||
|
||||
int left_to_read = size;
|
||||
int slot_size = static_cast<int>(m_pimpl->info.piece_size(slot));
|
||||
int slot_size = static_cast<int>(m_info.piece_size(slot));
|
||||
|
||||
if (offset + left_to_read > slot_size)
|
||||
left_to_read = slot_size - offset;
|
||||
|
@ -549,7 +534,7 @@ namespace libtorrent
|
|||
assert(int(slices.size()) > counter);
|
||||
size_type slice_size = slices[counter].size;
|
||||
assert(slice_size == read_bytes);
|
||||
assert(m_pimpl->info.file_at(slices[counter].file_index).path
|
||||
assert(m_info.file_at(slices[counter].file_index).path
|
||||
== file_iter->path);
|
||||
#endif
|
||||
|
||||
|
@ -575,12 +560,11 @@ namespace libtorrent
|
|||
// this file was empty, don't increment the slice counter
|
||||
if (read_bytes > 0) ++counter;
|
||||
#endif
|
||||
path path = m_pimpl->save_path / file_iter->path;
|
||||
path path = m_save_path / file_iter->path;
|
||||
|
||||
file_offset = 0;
|
||||
in = m_pimpl->files.open_file(
|
||||
m_pimpl.get()
|
||||
, path, file::in);
|
||||
in = m_files.open_file(
|
||||
this, path, file::in);
|
||||
in->seek(0);
|
||||
}
|
||||
}
|
||||
|
@ -597,38 +581,37 @@ namespace libtorrent
|
|||
{
|
||||
assert(buf != 0);
|
||||
assert(slot >= 0);
|
||||
assert(slot < m_pimpl->info.num_pieces());
|
||||
assert(slot < m_info.num_pieces());
|
||||
assert(offset >= 0);
|
||||
assert(size > 0);
|
||||
|
||||
slot_lock lock(*m_pimpl, slot);
|
||||
slot_lock lock(*this, slot);
|
||||
|
||||
#ifndef NDEBUG
|
||||
std::vector<file_slice> slices
|
||||
= m_pimpl->info.map_block(slot, offset, size);
|
||||
= m_info.map_block(slot, offset, size);
|
||||
assert(!slices.empty());
|
||||
#endif
|
||||
|
||||
size_type start = slot * (size_type)m_pimpl->info.piece_length() + offset;
|
||||
size_type start = slot * (size_type)m_info.piece_length() + offset;
|
||||
|
||||
// find the file iterator and file offset
|
||||
size_type file_offset = start;
|
||||
std::vector<file_entry>::const_iterator file_iter;
|
||||
|
||||
for (file_iter = m_pimpl->info.begin_files();;)
|
||||
for (file_iter = m_info.begin_files();;)
|
||||
{
|
||||
if (file_offset < file_iter->size)
|
||||
break;
|
||||
|
||||
file_offset -= file_iter->size;
|
||||
++file_iter;
|
||||
assert(file_iter != m_pimpl->info.end_files());
|
||||
assert(file_iter != m_info.end_files());
|
||||
}
|
||||
|
||||
path p(m_pimpl->save_path / file_iter->path);
|
||||
boost::shared_ptr<file> out = m_pimpl->files.open_file(
|
||||
m_pimpl.get()
|
||||
, p, file::out | file::in);
|
||||
path p(m_save_path / file_iter->path);
|
||||
boost::shared_ptr<file> out = m_files.open_file(
|
||||
this, p, file::out | file::in);
|
||||
|
||||
assert(file_offset < file_iter->size);
|
||||
assert(slices[0].offset == file_offset);
|
||||
|
@ -643,7 +626,7 @@ namespace libtorrent
|
|||
}
|
||||
|
||||
int left_to_write = size;
|
||||
int slot_size = static_cast<int>(m_pimpl->info.piece_size(slot));
|
||||
int slot_size = static_cast<int>(m_info.piece_size(slot));
|
||||
|
||||
if (offset + left_to_write > slot_size)
|
||||
left_to_write = slot_size - offset;
|
||||
|
@ -667,7 +650,7 @@ namespace libtorrent
|
|||
{
|
||||
assert(int(slices.size()) > counter);
|
||||
assert(slices[counter].size == write_bytes);
|
||||
assert(m_pimpl->info.file_at(slices[counter].file_index).path
|
||||
assert(m_info.file_at(slices[counter].file_index).path
|
||||
== file_iter->path);
|
||||
|
||||
assert(buf_pos >= 0);
|
||||
|
@ -695,21 +678,22 @@ namespace libtorrent
|
|||
#endif
|
||||
++file_iter;
|
||||
|
||||
assert(file_iter != m_pimpl->info.end_files());
|
||||
path p = m_pimpl->save_path / file_iter->path;
|
||||
assert(file_iter != m_info.end_files());
|
||||
path p = m_save_path / file_iter->path;
|
||||
file_offset = 0;
|
||||
out = m_pimpl->files.open_file(
|
||||
m_pimpl.get()
|
||||
, p, file::out | file::in);
|
||||
out = m_files.open_file(
|
||||
this, p, file::out | file::in);
|
||||
|
||||
out->seek(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
storage_interface* default_storage_constructor(torrent_info const& ti
|
||||
, boost::filesystem::path const& path, file_pool& fp)
|
||||
{
|
||||
return new storage(ti, path, fp);
|
||||
}
|
||||
|
||||
// -- piece_manager -----------------------------------------------------
|
||||
|
||||
|
@ -721,7 +705,8 @@ namespace libtorrent
|
|||
impl(
|
||||
torrent_info const& info
|
||||
, path const& path
|
||||
, file_pool& fp);
|
||||
, file_pool& fp
|
||||
, storage_constructor_type sc);
|
||||
|
||||
bool check_fastresume(
|
||||
aux::piece_checker_data& d
|
||||
|
@ -761,7 +746,7 @@ namespace libtorrent
|
|||
|
||||
bool move_storage(path save_path)
|
||||
{
|
||||
if (m_storage.move_storage(save_path))
|
||||
if (m_storage->move_storage(save_path))
|
||||
{
|
||||
m_save_path = complete(save_path);
|
||||
return true;
|
||||
|
@ -788,7 +773,7 @@ namespace libtorrent
|
|||
void debug_log() const;
|
||||
#endif
|
||||
#endif
|
||||
storage m_storage;
|
||||
boost::scoped_ptr<storage_interface> m_storage;
|
||||
|
||||
// if this is true, pieces are always allocated at the
|
||||
// lowest possible slot index. If it is false, pieces
|
||||
|
@ -871,8 +856,9 @@ namespace libtorrent
|
|||
piece_manager::impl::impl(
|
||||
torrent_info const& info
|
||||
, path const& save_path
|
||||
, file_pool& fp)
|
||||
: m_storage(info, save_path, fp)
|
||||
, file_pool& fp
|
||||
, storage_constructor_type sc)
|
||||
: m_storage(sc(info, save_path, fp))
|
||||
, m_compact_mode(false)
|
||||
, m_fill_mode(true)
|
||||
, m_info(info)
|
||||
|
@ -885,8 +871,9 @@ namespace libtorrent
|
|||
piece_manager::piece_manager(
|
||||
torrent_info const& info
|
||||
, path const& save_path
|
||||
, file_pool& fp)
|
||||
: m_pimpl(new impl(info, save_path, fp))
|
||||
, file_pool& fp
|
||||
, storage_constructor_type sc)
|
||||
: m_pimpl(new impl(info, save_path, fp, sc))
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -901,7 +888,7 @@ namespace libtorrent
|
|||
|
||||
void piece_manager::impl::release_files()
|
||||
{
|
||||
m_storage.release_files();
|
||||
m_storage->release_files();
|
||||
}
|
||||
|
||||
void piece_manager::impl::export_piece_map(
|
||||
|
@ -1003,7 +990,7 @@ namespace libtorrent
|
|||
for (int i = 0; i < num_blocks-1; ++i)
|
||||
{
|
||||
if (!bitmask[i]) continue;
|
||||
m_storage.read(
|
||||
m_storage->read(
|
||||
&buf[0]
|
||||
, slot_index
|
||||
, i * block_size
|
||||
|
@ -1012,7 +999,7 @@ namespace libtorrent
|
|||
}
|
||||
if (bitmask[num_blocks - 1])
|
||||
{
|
||||
m_storage.read(
|
||||
m_storage->read(
|
||||
&buf[0]
|
||||
, slot_index
|
||||
, block_size * (num_blocks - 1)
|
||||
|
@ -1035,7 +1022,7 @@ namespace libtorrent
|
|||
assert(m_piece_to_slot[piece_index] >= 0 && m_piece_to_slot[piece_index] < (int)m_slot_to_piece.size());
|
||||
int slot = m_piece_to_slot[piece_index];
|
||||
assert(slot >= 0 && slot < (int)m_slot_to_piece.size());
|
||||
return m_storage.read(buf, slot, offset, size);
|
||||
return m_storage->read(buf, slot, offset, size);
|
||||
}
|
||||
|
||||
size_type piece_manager::read(
|
||||
|
@ -1059,7 +1046,7 @@ namespace libtorrent
|
|||
assert(piece_index >= 0 && piece_index < (int)m_piece_to_slot.size());
|
||||
int slot = allocate_slot_for_piece(piece_index);
|
||||
assert(slot >= 0 && slot < (int)m_slot_to_piece.size());
|
||||
m_storage.write(buf, slot, offset, size);
|
||||
m_storage->write(buf, slot, offset, size);
|
||||
}
|
||||
|
||||
void piece_manager::write(
|
||||
|
@ -1241,7 +1228,7 @@ namespace libtorrent
|
|||
// use while debugging to find
|
||||
// states that cannot be scanned
|
||||
// by check_pieces.
|
||||
// m_storage.shuffle();
|
||||
// m_storage->shuffle();
|
||||
|
||||
m_piece_to_slot.resize(m_info.num_pieces(), has_no_slot);
|
||||
m_slot_to_piece.resize(m_info.num_pieces(), unallocated);
|
||||
|
@ -1389,7 +1376,7 @@ namespace libtorrent
|
|||
try
|
||||
{
|
||||
|
||||
m_storage.read(
|
||||
m_storage->read(
|
||||
&m_piece_data[0]
|
||||
, m_current_slot
|
||||
, 0
|
||||
|
@ -1468,14 +1455,14 @@ namespace libtorrent
|
|||
const int slot1_size = static_cast<int>(m_info.piece_size(piece_index));
|
||||
const int slot2_size = other_piece >= 0 ? static_cast<int>(m_info.piece_size(other_piece)) : 0;
|
||||
std::vector<char> buf1(slot1_size);
|
||||
m_storage.read(&buf1[0], m_current_slot, 0, slot1_size);
|
||||
m_storage->read(&buf1[0], m_current_slot, 0, slot1_size);
|
||||
if (slot2_size > 0)
|
||||
{
|
||||
std::vector<char> buf2(slot2_size);
|
||||
m_storage.read(&buf2[0], piece_index, 0, slot2_size);
|
||||
m_storage.write(&buf2[0], m_current_slot, 0, slot2_size);
|
||||
m_storage->read(&buf2[0], piece_index, 0, slot2_size);
|
||||
m_storage->write(&buf2[0], m_current_slot, 0, slot2_size);
|
||||
}
|
||||
m_storage.write(&buf1[0], piece_index, 0, slot1_size);
|
||||
m_storage->write(&buf1[0], piece_index, 0, slot1_size);
|
||||
assert(m_slot_to_piece[m_current_slot] == unassigned
|
||||
|| m_piece_to_slot[m_slot_to_piece[m_current_slot]] == m_current_slot);
|
||||
}
|
||||
|
@ -1501,14 +1488,14 @@ namespace libtorrent
|
|||
const int slot1_size = static_cast<int>(m_info.piece_size(other_piece));
|
||||
const int slot2_size = piece_index >= 0 ? static_cast<int>(m_info.piece_size(piece_index)) : 0;
|
||||
std::vector<char> buf1(slot1_size);
|
||||
m_storage.read(&buf1[0], other_slot, 0, slot1_size);
|
||||
m_storage->read(&buf1[0], other_slot, 0, slot1_size);
|
||||
if (slot2_size > 0)
|
||||
{
|
||||
std::vector<char> buf2(slot2_size);
|
||||
m_storage.read(&buf2[0], m_current_slot, 0, slot2_size);
|
||||
m_storage.write(&buf2[0], other_slot, 0, slot2_size);
|
||||
m_storage->read(&buf2[0], m_current_slot, 0, slot2_size);
|
||||
m_storage->write(&buf2[0], other_slot, 0, slot2_size);
|
||||
}
|
||||
m_storage.write(&buf1[0], m_current_slot, 0, slot1_size);
|
||||
m_storage->write(&buf1[0], m_current_slot, 0, slot1_size);
|
||||
assert(m_slot_to_piece[m_current_slot] == unassigned
|
||||
|| m_piece_to_slot[m_slot_to_piece[m_current_slot]] == m_current_slot);
|
||||
}
|
||||
|
@ -1550,10 +1537,10 @@ namespace libtorrent
|
|||
std::vector<char> buf1(static_cast<int>(slot1_size));
|
||||
std::vector<char> buf2(static_cast<int>(slot3_size));
|
||||
|
||||
m_storage.read(&buf2[0], m_current_slot, 0, slot3_size);
|
||||
m_storage.read(&buf1[0], slot1, 0, slot1_size);
|
||||
m_storage.write(&buf1[0], m_current_slot, 0, slot1_size);
|
||||
m_storage.write(&buf2[0], slot1, 0, slot3_size);
|
||||
m_storage->read(&buf2[0], m_current_slot, 0, slot3_size);
|
||||
m_storage->read(&buf1[0], slot1, 0, slot1_size);
|
||||
m_storage->write(&buf1[0], m_current_slot, 0, slot1_size);
|
||||
m_storage->write(&buf2[0], slot1, 0, slot3_size);
|
||||
|
||||
assert(m_slot_to_piece[m_current_slot] == unassigned
|
||||
|| m_piece_to_slot[m_slot_to_piece[m_current_slot]] == m_current_slot);
|
||||
|
@ -1592,15 +1579,15 @@ namespace libtorrent
|
|||
std::vector<char> buf1(static_cast<int>(m_info.piece_length()));
|
||||
std::vector<char> buf2(static_cast<int>(m_info.piece_length()));
|
||||
|
||||
m_storage.read(&buf2[0], m_current_slot, 0, slot3_size);
|
||||
m_storage.read(&buf1[0], slot2, 0, slot2_size);
|
||||
m_storage.write(&buf1[0], m_current_slot, 0, slot2_size);
|
||||
m_storage->read(&buf2[0], m_current_slot, 0, slot3_size);
|
||||
m_storage->read(&buf1[0], slot2, 0, slot2_size);
|
||||
m_storage->write(&buf1[0], m_current_slot, 0, slot2_size);
|
||||
if (slot1_size > 0)
|
||||
{
|
||||
m_storage.read(&buf1[0], slot1, 0, slot1_size);
|
||||
m_storage.write(&buf1[0], slot2, 0, slot1_size);
|
||||
m_storage->read(&buf1[0], slot1, 0, slot1_size);
|
||||
m_storage->write(&buf1[0], slot2, 0, slot1_size);
|
||||
}
|
||||
m_storage.write(&buf2[0], slot1, 0, slot3_size);
|
||||
m_storage->write(&buf2[0], slot1, 0, slot3_size);
|
||||
assert(m_slot_to_piece[m_current_slot] == unassigned
|
||||
|| m_piece_to_slot[m_slot_to_piece[m_current_slot]] == m_current_slot);
|
||||
}
|
||||
|
@ -1778,8 +1765,8 @@ namespace libtorrent
|
|||
|
||||
const int slot_size = static_cast<int>(m_info.piece_size(slot_index));
|
||||
std::vector<char> buf(slot_size);
|
||||
m_storage.read(&buf[0], piece_index, 0, slot_size);
|
||||
m_storage.write(&buf[0], slot_index, 0, slot_size);
|
||||
m_storage->read(&buf[0], piece_index, 0, slot_size);
|
||||
m_storage->write(&buf[0], slot_index, 0, slot_size);
|
||||
|
||||
assert(m_slot_to_piece[piece_index] == piece_index);
|
||||
assert(m_piece_to_slot[piece_index] == piece_index);
|
||||
|
@ -1866,7 +1853,7 @@ namespace libtorrent
|
|||
if (m_piece_to_slot[pos] != has_no_slot)
|
||||
{
|
||||
assert(m_piece_to_slot[pos] >= 0);
|
||||
m_storage.read(&buffer[0], m_piece_to_slot[pos], 0, static_cast<int>(m_info.piece_size(pos)));
|
||||
m_storage->read(&buffer[0], m_piece_to_slot[pos], 0, static_cast<int>(m_info.piece_size(pos)));
|
||||
new_free_slot = m_piece_to_slot[pos];
|
||||
m_slot_to_piece[pos] = pos;
|
||||
m_piece_to_slot[pos] = pos;
|
||||
|
@ -1877,7 +1864,7 @@ namespace libtorrent
|
|||
m_free_slots.push_back(new_free_slot);
|
||||
|
||||
if (write_back || m_fill_mode)
|
||||
m_storage.write(&buffer[0], pos, 0, static_cast<int>(m_info.piece_size(pos)));
|
||||
m_storage->write(&buffer[0], pos, 0, static_cast<int>(m_info.piece_size(pos)));
|
||||
}
|
||||
|
||||
assert(m_free_slots.size() > 0);
|
||||
|
|
|
@ -226,7 +226,8 @@ namespace libtorrent
|
|||
, tcp::endpoint const& net_interface
|
||||
, bool compact_mode
|
||||
, int block_size
|
||||
, session_settings const& s)
|
||||
, session_settings const& s
|
||||
, storage_constructor_type sc)
|
||||
: m_torrent_file(tf)
|
||||
, m_abort(false)
|
||||
, m_paused(false)
|
||||
|
@ -265,6 +266,7 @@ namespace libtorrent
|
|||
, m_default_block_size(block_size)
|
||||
, m_connections_initialized(true)
|
||||
, m_settings(s)
|
||||
, m_storage_constructor(sc)
|
||||
{
|
||||
#ifndef NDEBUG
|
||||
m_initial_done = 0;
|
||||
|
@ -315,7 +317,8 @@ namespace libtorrent
|
|||
, tcp::endpoint const& net_interface
|
||||
, bool compact_mode
|
||||
, int block_size
|
||||
, session_settings const& s)
|
||||
, session_settings const& s
|
||||
, storage_constructor_type sc)
|
||||
: m_torrent_file(info_hash)
|
||||
, m_abort(false)
|
||||
, m_paused(false)
|
||||
|
@ -353,6 +356,7 @@ namespace libtorrent
|
|||
, m_default_block_size(block_size)
|
||||
, m_connections_initialized(false)
|
||||
, m_settings(s)
|
||||
, m_storage_constructor(sc)
|
||||
{
|
||||
#ifndef NDEBUG
|
||||
m_initial_done = 0;
|
||||
|
@ -452,7 +456,8 @@ namespace libtorrent
|
|||
assert(m_torrent_file.total_size() >= 0);
|
||||
|
||||
m_have_pieces.resize(m_torrent_file.num_pieces(), false);
|
||||
m_storage.reset(new piece_manager(m_torrent_file, m_save_path, m_ses.m_files));
|
||||
m_storage.reset(new piece_manager(m_torrent_file, m_save_path
|
||||
, m_ses.m_files, m_storage_constructor));
|
||||
m_block_size = calculate_block_size(m_torrent_file, m_default_block_size);
|
||||
m_picker.reset(new piece_picker(
|
||||
static_cast<int>(m_torrent_file.piece_length() / m_block_size)
|
||||
|
|
Loading…
Reference in New Issue