removed temporary assert and factored file_pool out of storage to prepare for a per session file pool
This commit is contained in:
parent
e35fc5c4be
commit
247b8ae443
1
Jamfile
1
Jamfile
|
@ -55,6 +55,7 @@ SOURCES =
|
|||
sha1.cpp
|
||||
metadata_transfer.cpp
|
||||
logger.cpp
|
||||
file_pool.cpp
|
||||
;
|
||||
|
||||
KADEMLIA_SOURCES =
|
||||
|
|
|
@ -9,6 +9,7 @@ libtorrent/entry.hpp \
|
|||
libtorrent/escape_string.hpp \
|
||||
libtorrent/extensions.hpp \
|
||||
libtorrent/file.hpp \
|
||||
libtorrent/file_pool.hpp \
|
||||
libtorrent/fingerprint.hpp \
|
||||
libtorrent/hasher.hpp \
|
||||
libtorrent/http_tracker_connection.hpp \
|
||||
|
|
|
@ -0,0 +1,101 @@
|
|||
/*
|
||||
|
||||
Copyright (c) 2006, 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_FILE_POOL_HPP
|
||||
#define TORRENT_FILE_POOL_HPP
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(push, 1)
|
||||
#endif
|
||||
|
||||
#include <boost/filesystem/path.hpp>
|
||||
#include <boost/date_time/posix_time/posix_time_types.hpp>
|
||||
#include <boost/multi_index_container.hpp>
|
||||
#include <boost/multi_index/member.hpp>
|
||||
#include <boost/multi_index/ordered_index.hpp>
|
||||
#include <boost/shared_ptr.hpp>
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
#include "libtorrent/file.hpp"
|
||||
|
||||
namespace libtorrent
|
||||
{
|
||||
|
||||
using boost::multi_index::multi_index_container;
|
||||
using boost::multi_index::ordered_non_unique;
|
||||
using boost::multi_index::ordered_unique;
|
||||
using boost::multi_index::indexed_by;
|
||||
using boost::multi_index::member;
|
||||
namespace pt = boost::posix_time;
|
||||
namespace fs = boost::filesystem;
|
||||
|
||||
struct file_pool
|
||||
{
|
||||
file_pool(int size): m_size(size) {}
|
||||
|
||||
boost::shared_ptr<file> open_file(void* st, fs::path const& p, file::open_mode m);
|
||||
void release(void* st);
|
||||
|
||||
private:
|
||||
int m_size;
|
||||
|
||||
struct lru_file_entry
|
||||
{
|
||||
lru_file_entry(boost::shared_ptr<file> const& f)
|
||||
: file_ptr(f)
|
||||
, last_use(pt::second_clock::universal_time()) {}
|
||||
mutable boost::shared_ptr<file> file_ptr;
|
||||
fs::path file_path;
|
||||
void* key;
|
||||
pt::ptime last_use;
|
||||
file::open_mode mode;
|
||||
};
|
||||
|
||||
typedef multi_index_container<
|
||||
lru_file_entry, indexed_by<
|
||||
ordered_unique<member<lru_file_entry, fs::path
|
||||
, &lru_file_entry::file_path> >
|
||||
, ordered_non_unique<member<lru_file_entry, pt::ptime
|
||||
, &lru_file_entry::last_use> >
|
||||
, ordered_non_unique<member<lru_file_entry, void*
|
||||
, &lru_file_entry::key> >
|
||||
>
|
||||
> file_set;
|
||||
|
||||
file_set m_files;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
|
@ -91,7 +91,7 @@ namespace libtorrent
|
|||
public:
|
||||
storage(
|
||||
const torrent_info& info
|
||||
, const boost::filesystem::path& path);
|
||||
, const boost::filesystem::path& path);
|
||||
|
||||
void swap(storage&);
|
||||
|
||||
|
|
|
@ -9,6 +9,7 @@ torrent_info.cpp tracker_manager.cpp \
|
|||
http_tracker_connection.cpp udp_tracker_connection.cpp \
|
||||
alert.cpp identify_client.cpp ip_filter.cpp file.cpp metadata_transfer.cpp \
|
||||
logger.cpp \
|
||||
file_pool.cpp \
|
||||
\
|
||||
kademlia/closest_nodes.cpp \
|
||||
kademlia/dht_tracker.cpp \
|
||||
|
@ -25,12 +26,17 @@ $(top_srcdir)/include/libtorrent/alert.hpp \
|
|||
$(top_srcdir)/include/libtorrent/alert_types.hpp \
|
||||
$(top_srcdir)/include/libtorrent/allocate_resources.hpp \
|
||||
$(top_srcdir)/include/libtorrent/aux_/allocate_resources_impl.hpp \
|
||||
$(top_srcdir)/include/libtorrent/aux_/session_impl.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 \
|
||||
$(top_srcdir)/include/libtorrent/extensions.hpp \
|
||||
$(top_srcdir)/include/libtorrent/extensions/metadata_transfer.hpp \
|
||||
$(top_srcdir)/include/libtorrent/extensions/logger.hpp \
|
||||
$(top_srcdir)/include/libtorrent/file.hpp \
|
||||
$(top_srcdir)/include/libtorrent/file_pool.hpp \
|
||||
$(top_srcdir)/include/libtorrent/fingerprint.hpp \
|
||||
$(top_srcdir)/include/libtorrent/hasher.hpp \
|
||||
$(top_srcdir)/include/libtorrent/session_settings.hpp \
|
||||
|
@ -51,7 +57,6 @@ $(top_srcdir)/include/libtorrent/piece_picker.hpp \
|
|||
$(top_srcdir)/include/libtorrent/policy.hpp \
|
||||
$(top_srcdir)/include/libtorrent/resource_request.hpp \
|
||||
$(top_srcdir)/include/libtorrent/session.hpp \
|
||||
$(top_srcdir)/include/libtorrent/aux_/session_impl.hpp \
|
||||
$(top_srcdir)/include/libtorrent/size_type.hpp \
|
||||
$(top_srcdir)/include/libtorrent/socket.hpp \
|
||||
$(top_srcdir)/include/libtorrent/stat.hpp \
|
||||
|
|
|
@ -0,0 +1,104 @@
|
|||
/*
|
||||
|
||||
Copyright (c) 2006, 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/file_pool.hpp"
|
||||
|
||||
namespace libtorrent
|
||||
{
|
||||
using boost::multi_index::nth_index;
|
||||
using boost::multi_index::get;
|
||||
|
||||
boost::shared_ptr<file> file_pool::open_file(void* st, fs::path const& p, file::open_mode m)
|
||||
{
|
||||
|
||||
assert(st != 0);
|
||||
assert(p.is_complete());
|
||||
typedef nth_index<file_set, 0>::type path_view;
|
||||
path_view& pt = get<0>(m_files);
|
||||
path_view::iterator i = pt.find(p);
|
||||
if (i != pt.end())
|
||||
{
|
||||
lru_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
|
||||
// the new read/write privilages
|
||||
i->file_ptr.reset();
|
||||
assert(e.file_ptr.unique());
|
||||
e.file_ptr.reset();
|
||||
e.file_ptr.reset(new file(p, m));
|
||||
e.mode = m;
|
||||
}
|
||||
pt.replace(i, e);
|
||||
return e.file_ptr;
|
||||
}
|
||||
// the file is not in our cache
|
||||
if ((int)m_files.size() >= m_size)
|
||||
{
|
||||
// the file cache is at its maximum size, close
|
||||
// the least recently used (lru) file from it
|
||||
typedef nth_index<file_set, 1>::type lru_view;
|
||||
lru_view& lt = get<1>(m_files);
|
||||
lru_view::iterator i = lt.begin();
|
||||
// the first entry in this view is the least recently used
|
||||
assert(lt.size() == 1 || (i->last_use <= boost::next(i)->last_use));
|
||||
lt.erase(i);
|
||||
}
|
||||
lru_file_entry e(boost::shared_ptr<file>(new file(p, m)));
|
||||
e.mode = m;
|
||||
e.key = st;
|
||||
e.file_path = p;
|
||||
pt.insert(e);
|
||||
return e.file_ptr;
|
||||
}
|
||||
|
||||
void file_pool::release(void* st)
|
||||
{
|
||||
assert(st != 0);
|
||||
using boost::tie;
|
||||
|
||||
typedef nth_index<file_set, 2>::type key_view;
|
||||
key_view& kt = get<2>(m_files);
|
||||
|
||||
key_view::iterator start, end;
|
||||
tie(start, end) = kt.equal_range(st);
|
||||
kt.erase(start, end);
|
||||
}
|
||||
|
||||
}
|
129
src/storage.cpp
129
src/storage.cpp
|
@ -64,6 +64,7 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
#include "libtorrent/peer_id.hpp"
|
||||
#include "libtorrent/file.hpp"
|
||||
#include "libtorrent/invariant_check.hpp"
|
||||
#include "libtorrent/file_pool.hpp"
|
||||
#include "libtorrent/aux_/session_impl.hpp"
|
||||
|
||||
#ifndef NDEBUG
|
||||
|
@ -218,135 +219,7 @@ namespace
|
|||
log << s;
|
||||
log.flush();
|
||||
}
|
||||
/*
|
||||
struct file_key
|
||||
{
|
||||
file_key(sha1_hash ih, path f): info_hash(ih), file_path(f) {}
|
||||
file_key() {}
|
||||
sha1_hash info_hash;
|
||||
path file_path;
|
||||
bool operator<(file_key const& fk) const
|
||||
{
|
||||
if (info_hash < fk.info_hash) return true;
|
||||
if (fk.info_hash < info_hash) return false;
|
||||
return file_path < fk.file_path;
|
||||
}
|
||||
};
|
||||
*/
|
||||
struct lru_file_entry
|
||||
{
|
||||
lru_file_entry(boost::shared_ptr<file> const& f)
|
||||
: file_ptr(f)
|
||||
, last_use(pt::second_clock::universal_time()) {}
|
||||
mutable boost::shared_ptr<file> file_ptr;
|
||||
path file_path;
|
||||
void* key;
|
||||
pt::ptime last_use;
|
||||
file::open_mode mode;
|
||||
};
|
||||
|
||||
struct file_pool
|
||||
{
|
||||
file_pool(int size): m_size(size) {}
|
||||
|
||||
boost::shared_ptr<file> open_file(void* st, path const& p, file::open_mode m)
|
||||
{
|
||||
assert(st != 0);
|
||||
assert(p.is_complete());
|
||||
typedef nth_index<file_set, 0>::type path_view;
|
||||
path_view& pt = get<0>(m_files);
|
||||
path_view::iterator i = pt.find(p);
|
||||
if (i != pt.end())
|
||||
{
|
||||
lru_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
|
||||
// the new read/write privilages
|
||||
i->file_ptr.reset();
|
||||
assert(e.file_ptr.unique());
|
||||
e.file_ptr.reset();
|
||||
e.file_ptr.reset(new file(p, m));
|
||||
e.mode = m;
|
||||
}
|
||||
pt.replace(i, e);
|
||||
return e.file_ptr;
|
||||
}
|
||||
// the file is not in our cache
|
||||
if ((int)m_files.size() >= m_size)
|
||||
{
|
||||
// the file cache is at its maximum size, close
|
||||
// the least recently used (lru) file from it
|
||||
typedef nth_index<file_set, 1>::type lru_view;
|
||||
lru_view& lt = get<1>(m_files);
|
||||
lru_view::iterator i = lt.begin();
|
||||
// the first entry in this view is the least recently used
|
||||
/* for (lru_view::iterator i = lt.begin(); i != lt.end(); ++i)
|
||||
{
|
||||
std::cerr << i->last_use << "\n";
|
||||
}
|
||||
*/ assert(lt.size() == 1 || (i->last_use <= boost::next(i)->last_use));
|
||||
lt.erase(i);
|
||||
}
|
||||
lru_file_entry e(boost::shared_ptr<file>(new file(p, m)));
|
||||
e.mode = m;
|
||||
e.key = st;
|
||||
e.file_path = p;
|
||||
pt.insert(e);
|
||||
return e.file_ptr;
|
||||
}
|
||||
|
||||
void release(void* st)
|
||||
{
|
||||
assert(st != 0);
|
||||
using boost::tie;
|
||||
|
||||
typedef nth_index<file_set, 2>::type key_view;
|
||||
key_view& kt = get<2>(m_files);
|
||||
|
||||
key_view::iterator start, end;
|
||||
tie(start, end) = kt.equal_range(st);
|
||||
|
||||
/*
|
||||
std::cerr << "releasing files!\n";
|
||||
for (path_view::iterator i = r.first; i != r.second; ++i)
|
||||
{
|
||||
std::cerr << i->key.file_path.native_file_string() << "\n";
|
||||
}
|
||||
*/
|
||||
kt.erase(start, end);
|
||||
/*
|
||||
std::cerr << "files left: " << pt.size() << "\n";
|
||||
for (path_view::iterator i = pt.begin(); i != pt.end(); ++i)
|
||||
{
|
||||
std::cerr << i->key.file_path.native_file_string() << "\n";
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
private:
|
||||
int m_size;
|
||||
|
||||
typedef multi_index_container<
|
||||
lru_file_entry, indexed_by<
|
||||
ordered_unique<member<lru_file_entry, path
|
||||
, &lru_file_entry::file_path> >
|
||||
, ordered_non_unique<member<lru_file_entry, pt::ptime
|
||||
, &lru_file_entry::last_use> >
|
||||
, ordered_non_unique<member<lru_file_entry, void*
|
||||
, &lru_file_entry::key> >
|
||||
>
|
||||
> file_set;
|
||||
|
||||
file_set m_files;
|
||||
};
|
||||
}
|
||||
|
||||
namespace libtorrent
|
||||
|
|
|
@ -82,8 +82,6 @@ namespace libtorrent
|
|||
{
|
||||
void throw_invalid_handle()
|
||||
{
|
||||
// TODO: TEMP!
|
||||
assert(false);
|
||||
throw invalid_handle();
|
||||
}
|
||||
|
||||
|
@ -109,7 +107,6 @@ namespace libtorrent
|
|||
if (t) return f(*t);
|
||||
}
|
||||
|
||||
assert(false);
|
||||
// throwing directly instead of calling
|
||||
// the throw_invalid_handle() function
|
||||
// avoids a warning in gcc
|
||||
|
|
Loading…
Reference in New Issue