optimized file_pool lookups and string handling

This commit is contained in:
Arvid Norberg 2010-08-23 08:48:02 +00:00
parent b747cdab8a
commit b7b542f587
8 changed files with 73 additions and 42 deletions

View File

@ -60,6 +60,7 @@ POSSIBILITY OF SUCH DAMAGE.
#include "libtorrent/file.hpp"
#include "libtorrent/peer_info.hpp"
#include "libtorrent/socket_io.hpp" // print_address
#include "libtorrent/time.hpp"
using boost::bind;
@ -130,16 +131,29 @@ bool sleep_and_input(char* c, int sleep)
// sets the terminal to single-character mode
// and resets when destructed
set_keypress s;
libtorrent::ptime start = libtorrent::time_now_hires();
int ret = 0;
retry:
fd_set set;
FD_ZERO(&set);
FD_SET(0, &set);
timeval tv = {sleep, 0};
if (select(1, &set, 0, 0, &tv) > 0)
ret = select(1, &set, 0, 0, &tv);
if (ret > 0)
{
*c = getc(stdin);
return true;
}
if (errno == EINTR)
{
if (total_milliseconds(libtorrent::time_now_hires() - start) < sleep * 1000)
goto retry;
return false;
}
if (ret < 0 && errno != 0 && errno != ETIMEDOUT)
fprintf(stderr, "select failed: %s\n", strerror(errno));
libtorrent::sleep(500);
return false;
}

View File

@ -52,7 +52,9 @@ struct peer_conn
: s(ios)
, read_pos(0)
, state(handshaking)
, pieces(num_pieces)
// don't request anything from the last piece
// to keep things simple
, pieces(num_pieces - 1)
, block(0)
, blocks_per_piece(blocks_pp)
, info_hash(ih)
@ -248,6 +250,7 @@ int main(int argc, char const* argv[])
conns.push_back(new peer_conn(ios, ti.num_pieces(), ti.piece_length() / 16 / 1024
, ep, (char const*)&ti.info_hash()[0]));
libtorrent::sleep(1);
ios.poll_one();
}
ios.run();

View File

@ -49,6 +49,7 @@ POSSIBILITY OF SUCH DAMAGE.
#include "libtorrent/error_code.hpp"
#include "libtorrent/size_type.hpp"
#include "libtorrent/config.hpp"
#include "libtorrent/intrusive_ptr_base.hpp"
#ifdef TORRENT_WINDOWS
// windows part
@ -164,10 +165,8 @@ namespace libtorrent
bool m_done;
};
class TORRENT_EXPORT file: public boost::noncopyable
struct TORRENT_EXPORT file: boost::noncopyable, intrusive_ptr_base<file>
{
public:
enum
{
// when a file is opened with no_buffer

View File

@ -37,7 +37,7 @@ POSSIBILITY OF SUCH DAMAGE.
#pragma warning(push, 1)
#endif
#include <boost/shared_ptr.hpp>
#include <boost/intrusive_ptr.hpp>
#ifdef _MSC_VER
#pragma warning(pop)
@ -50,14 +50,16 @@ POSSIBILITY OF SUCH DAMAGE.
namespace libtorrent
{
struct file_entry;
struct TORRENT_EXPORT file_pool : boost::noncopyable
{
file_pool(int size = 40): m_size(size), m_low_prio_io(true) {}
boost::shared_ptr<file> open_file(void* st, std::string const& p
, int m, error_code& ec);
boost::intrusive_ptr<file> open_file(void* st, std::string const& p
, file_entry const& fe, int m, error_code& ec);
void release(void* st);
void release(std::string const& p);
void release(void* st, file_entry const& fe);
void resize(int size);
int size_limit() const { return m_size; }
void set_low_prio_io(bool b) { m_low_prio_io = b; }
@ -73,13 +75,15 @@ namespace libtorrent
struct lru_file_entry
{
lru_file_entry(): last_use(time_now()) {}
mutable boost::shared_ptr<file> file_ptr;
mutable boost::intrusive_ptr<file> file_ptr;
void* key;
ptime last_use;
int mode;
};
typedef std::map<std::string, lru_file_entry> file_set;
// maps storage pointer, file index pairs to the
// lru entry for the file
typedef std::map<std::pair<void*, int>, lru_file_entry> file_set;
file_set m_files;
mutex m_mutex;

View File

@ -45,9 +45,11 @@ POSSIBILITY OF SUCH DAMAGE.
namespace libtorrent
{
struct file;
struct TORRENT_EXPORT file_entry
{
file_entry(): offset(0), size(0), file_base(0)
file_entry(): offset(0), size(0), file_base(0), file_index(0)
, mtime(0), pad_file(false), hidden_attribute(false)
, executable_attribute(false)
, symlink_attribute(false)
@ -56,12 +58,16 @@ namespace libtorrent
std::string path;
std::string symlink_path;
copy_ptr<sha1_hash> filehash;
size_type offset; // the offset of this file inside the torrent
size_type size; // the size of this file
// the offset of this file inside the torrent
size_type offset;
// the size of this file
size_type size;
// the offset in the file where the storage starts.
// This is always 0 unless parts of the torrent is
// compressed into a single file, such as a so-called part file.
size_type file_base;
// the index of this file, as ordered in the torrent
int file_index;
time_t mtime;
bool pad_file:1;
bool hidden_attribute:1;

View File

@ -36,18 +36,19 @@ POSSIBILITY OF SUCH DAMAGE.
#include "libtorrent/assert.hpp"
#include "libtorrent/file_pool.hpp"
#include "libtorrent/error_code.hpp"
#include "libtorrent/file_storage.hpp" // for file_entry
namespace libtorrent
{
boost::shared_ptr<file> file_pool::open_file(void* st, std::string const& p
, int m, error_code& ec)
boost::intrusive_ptr<file> file_pool::open_file(void* st, std::string const& p
, file_entry const& fe, int m, error_code& ec)
{
TORRENT_ASSERT(st != 0);
TORRENT_ASSERT(is_complete(p));
TORRENT_ASSERT((m & file::rw_mask) == file::read_only
|| (m & file::rw_mask) == file::read_write);
mutex::scoped_lock l(m_mutex);
file_set::iterator i = m_files.find(p);
file_set::iterator i = m_files.find(std::make_pair(st, fe.file_index));
if (i != m_files.end())
{
lru_file_entry& e = i->second;
@ -61,7 +62,7 @@ namespace libtorrent
#if BOOST_VERSION >= 103500
ec = errors::file_collision;
#endif
return boost::shared_ptr<file>();
return boost::intrusive_ptr<file>();
}
e.key = st;
@ -74,12 +75,13 @@ namespace libtorrent
{
// close the file before we open it with
// the new read/write privilages
TORRENT_ASSERT(e.file_ptr.unique());
TORRENT_ASSERT(e.file_ptr->refcount() == 1);
e.file_ptr->close();
if (!e.file_ptr->open(p, m, ec))
std::string full_path = combine_path(p, fe.path);
if (!e.file_ptr->open(full_path, m, ec))
{
m_files.erase(i);
return boost::shared_ptr<file>();
return boost::intrusive_ptr<file>();
}
#ifdef TORRENT_WINDOWS
// file prio is supported on vista and up
@ -113,11 +115,12 @@ namespace libtorrent
ec = error_code(ENOMEM, get_posix_category());
return e.file_ptr;
}
if (!e.file_ptr->open(p, m, ec))
return boost::shared_ptr<file>();
std::string full_path = combine_path(p, fe.path);
if (!e.file_ptr->open(full_path, m, ec))
return boost::intrusive_ptr<file>();
e.mode = m;
e.key = st;
m_files.insert(std::make_pair(p, e));
m_files.insert(std::make_pair(std::make_pair(st, fe.file_index), e));
TORRENT_ASSERT(e.file_ptr->is_open());
return e.file_ptr;
}
@ -131,11 +134,10 @@ namespace libtorrent
m_files.erase(i);
}
void file_pool::release(std::string const& p)
void file_pool::release(void* st, file_entry const& fe)
{
mutex::scoped_lock l(m_mutex);
file_set::iterator i = m_files.find(p);
file_set::iterator i = m_files.find(std::make_pair(st, fe.file_index));
if (i != m_files.end()) m_files.erase(i);
}
@ -174,3 +176,4 @@ namespace libtorrent
}
}

View File

@ -196,6 +196,7 @@ namespace libtorrent
TORRENT_ASSERT(m_name == split_path(file).c_str());
m_files.push_back(file_entry());
file_entry& e = m_files.back();
e.file_index = m_files.size() - 1;
e.size = size;
e.path = file;
e.offset = m_total_size;
@ -227,6 +228,7 @@ namespace libtorrent
m_files.push_back(ent);
file_entry& e = m_files.back();
e.offset = m_total_size;
e.file_index = m_files.size() - 1;
m_total_size += ent.size;
}

View File

@ -384,7 +384,7 @@ namespace libtorrent
{
size_type (file::*regular_op)(size_type file_offset
, file::iovec_t const* bufs, int num_bufs, error_code& ec);
size_type (storage::*unaligned_op)(boost::shared_ptr<file> const& f
size_type (storage::*unaligned_op)(boost::intrusive_ptr<file> const& f
, size_type file_offset, file::iovec_t const* bufs, int num_bufs
, error_code& ec);
int cache_setting;
@ -398,9 +398,9 @@ namespace libtorrent
~storage()
{ m_pool.release(this); }
size_type read_unaligned(boost::shared_ptr<file> const& file_handle
size_type read_unaligned(boost::intrusive_ptr<file> const& file_handle
, size_type file_offset, file::iovec_t const* bufs, int num_bufs, error_code& ec);
size_type write_unaligned(boost::shared_ptr<file> const& file_handle
size_type write_unaligned(boost::intrusive_ptr<file> const& file_handle
, size_type file_offset, file::iovec_t const* bufs, int num_bufs, error_code& ec);
file_storage const& files() const { return m_mapped_files?*m_mapped_files:m_files; }
@ -409,7 +409,7 @@ namespace libtorrent
file_storage const& m_files;
// helper function to open a file in the file pool with the right mode
boost::shared_ptr<file> open_file(file_entry const& fe, int mode, error_code& ec) const;
boost::intrusive_ptr<file> open_file(file_entry const& fe, int mode, error_code& ec) const;
std::vector<boost::uint8_t> m_file_priority;
std::string m_save_path;
@ -553,7 +553,7 @@ namespace libtorrent
if (ec || s.file_size > file_iter->size || file_iter->size == 0)
{
ec.clear();
boost::shared_ptr<file> f = open_file(*file_iter, file::read_write, ec);
boost::intrusive_ptr<file> f = open_file(*file_iter, file::read_write, ec);
if (ec) set_error(file_path, ec);
else if (f)
{
@ -577,7 +577,7 @@ namespace libtorrent
if (index < 0 || index >= m_files.num_files()) return;
error_code ec;
boost::shared_ptr<file> f = open_file(files().at(index), file::read_write, ec);
boost::intrusive_ptr<file> f = open_file(files().at(index), file::read_write, ec);
if (ec || !f) return;
f->finalize();
@ -604,7 +604,7 @@ namespace libtorrent
{
if (index < 0 || index >= m_files.num_files()) return true;
std::string old_name = combine_path(m_save_path, files().at(index).path);
m_pool.release(old_name);
m_pool.release(this, files().at(index));
error_code ec;
rename(old_name, combine_path(m_save_path, new_filename), ec);
@ -714,7 +714,7 @@ namespace libtorrent
}
error_code ec;
boost::shared_ptr<file> file_handle = open_file(*file_iter, file::read_only, ec);
boost::intrusive_ptr<file> file_handle = open_file(*file_iter, file::read_only, ec);
if (!file_handle || ec) return slot;
size_type data_start = file_handle->sparse_end(file_offset);
@ -1055,7 +1055,7 @@ ret:
// open the file read only to avoid re-opening
// it in case it's already opened in read-only mode
error_code ec;
boost::shared_ptr<file> f = open_file(*file_iter, file::read_only, ec);
boost::intrusive_ptr<file> f = open_file(*file_iter, file::read_only, ec);
size_type ret = 0;
if (f && !ec) ret = f->phys_offset(file_offset);
@ -1143,7 +1143,7 @@ ret:
int buf_pos = 0;
error_code ec;
boost::shared_ptr<file> file_handle;
boost::intrusive_ptr<file> file_handle;
int bytes_left = size;
int slot_size = static_cast<int>(m_files.piece_size(slot));
@ -1250,7 +1250,7 @@ ret:
// they read an unaligned buffer from a file that requires aligned access
size_type storage::read_unaligned(boost::shared_ptr<file> const& file_handle
size_type storage::read_unaligned(boost::intrusive_ptr<file> const& file_handle
, size_type file_offset, file::iovec_t const* bufs, int num_bufs, error_code& ec)
{
const int pos_align = file_handle->pos_alignment()-1;
@ -1279,7 +1279,7 @@ ret:
return size;
}
size_type storage::write_unaligned(boost::shared_ptr<file> const& file_handle
size_type storage::write_unaligned(boost::intrusive_ptr<file> const& file_handle
, size_type file_offset, file::iovec_t const* bufs, int num_bufs, error_code& ec)
{
TORRENT_ASSERT(false); // not implemented
@ -1306,7 +1306,7 @@ ret:
return readv(&b, slot, offset, 1);
}
boost::shared_ptr<file> storage::open_file(file_entry const& fe, int mode, error_code& ec) const
boost::intrusive_ptr<file> storage::open_file(file_entry const& fe, int mode, error_code& ec) const
{
int cache_setting = m_settings ? settings().disk_io_write_mode : 0;
if (cache_setting == session_settings::disable_os_cache
@ -1316,7 +1316,7 @@ ret:
if (!m_allocate_files) mode |= file::sparse;
if (m_settings && settings().no_atime_storage) mode |= file::no_atime;
return m_pool.open_file(const_cast<storage*>(this), combine_path(m_save_path, fe.path), mode, ec);
return m_pool.open_file(const_cast<storage*>(this), m_save_path, fe, mode, ec);
}
storage_interface* default_storage_constructor(file_storage const& fs