optimized file_pool lookups and string handling
This commit is contained in:
parent
b747cdab8a
commit
b7b542f587
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
|||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue