forked from premiere/premiere-libtorrent
serve cache hits without a round-trip to the disk thread for improved seeding performance
This commit is contained in:
parent
4efabcefff
commit
85ef2528c6
|
@ -351,7 +351,11 @@ namespace libtorrent
|
||||||
int free_piece(cached_piece_entry& p, mutex::scoped_lock& l);
|
int free_piece(cached_piece_entry& p, mutex::scoped_lock& l);
|
||||||
int drain_piece_bufs(cached_piece_entry& p, std::vector<char*>& buf
|
int drain_piece_bufs(cached_piece_entry& p, std::vector<char*>& buf
|
||||||
, mutex::scoped_lock& l);
|
, mutex::scoped_lock& l);
|
||||||
int try_read_from_cache(disk_io_job const& j, bool& hit);
|
|
||||||
|
enum cache_flags_t {
|
||||||
|
cache_only = 1
|
||||||
|
};
|
||||||
|
int try_read_from_cache(disk_io_job const& j, bool& hit, int flags = 0);
|
||||||
int read_piece_from_cache_and_hash(disk_io_job const& j, sha1_hash& h);
|
int read_piece_from_cache_and_hash(disk_io_job const& j, sha1_hash& h);
|
||||||
int cache_piece(disk_io_job const& j, cache_piece_index_t::iterator& p
|
int cache_piece(disk_io_job const& j, cache_piece_index_t::iterator& p
|
||||||
, bool& hit, int options, mutex::scoped_lock& l);
|
, bool& hit, int options, mutex::scoped_lock& l);
|
||||||
|
|
|
@ -32,6 +32,7 @@ POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
#include "libtorrent/disk_buffer_pool.hpp"
|
#include "libtorrent/disk_buffer_pool.hpp"
|
||||||
#include "libtorrent/assert.hpp"
|
#include "libtorrent/assert.hpp"
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
#if TORRENT_USE_MLOCK && !defined TORRENT_WINDOWS
|
#if TORRENT_USE_MLOCK && !defined TORRENT_WINDOWS
|
||||||
#include <sys/mman.h>
|
#include <sys/mman.h>
|
||||||
|
@ -99,7 +100,7 @@ namespace libtorrent
|
||||||
#ifdef TORRENT_DISABLE_POOL_ALLOCATOR
|
#ifdef TORRENT_DISABLE_POOL_ALLOCATOR
|
||||||
char* ret = page_aligned_allocator::malloc(m_block_size);
|
char* ret = page_aligned_allocator::malloc(m_block_size);
|
||||||
#else
|
#else
|
||||||
char* ret = (char*)m_pool.ordered_malloc();
|
char* ret = (char*)m_pool.malloc();
|
||||||
m_pool.set_next_size(m_settings.cache_buffer_chunk_size);
|
m_pool.set_next_size(m_settings.cache_buffer_chunk_size);
|
||||||
#endif
|
#endif
|
||||||
++m_in_use;
|
++m_in_use;
|
||||||
|
|
|
@ -1234,7 +1234,7 @@ namespace libtorrent
|
||||||
return j.buffer_size;
|
return j.buffer_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
int disk_io_thread::try_read_from_cache(disk_io_job const& j, bool& hit)
|
int disk_io_thread::try_read_from_cache(disk_io_job const& j, bool& hit, int flags)
|
||||||
{
|
{
|
||||||
TORRENT_ASSERT(j.buffer);
|
TORRENT_ASSERT(j.buffer);
|
||||||
TORRENT_ASSERT(j.cache_min_time >= 0);
|
TORRENT_ASSERT(j.cache_min_time >= 0);
|
||||||
|
@ -1254,6 +1254,7 @@ namespace libtorrent
|
||||||
// we got a request for.
|
// we got a request for.
|
||||||
if (p == idx.end())
|
if (p == idx.end())
|
||||||
{
|
{
|
||||||
|
if (flags & cache_only) return -2;
|
||||||
// if we use an explicit read cache and we
|
// if we use an explicit read cache and we
|
||||||
// couldn't find the block in the cache,
|
// couldn't find the block in the cache,
|
||||||
// pretend that there's not enough space
|
// pretend that there's not enough space
|
||||||
|
@ -1290,13 +1291,28 @@ namespace libtorrent
|
||||||
return m_queue_buffer_size;
|
return m_queue_buffer_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
typedef std::list<std::pair<disk_io_job, int> > job_queue_t;
|
||||||
|
void completion_queue_handler(job_queue_t* completed_jobs)
|
||||||
|
{
|
||||||
|
boost::shared_ptr<job_queue_t> holder(completed_jobs);
|
||||||
|
|
||||||
|
for (job_queue_t::iterator i = completed_jobs->begin()
|
||||||
|
, end(completed_jobs->end()); i != end; ++i)
|
||||||
|
{
|
||||||
|
TORRENT_TRY
|
||||||
|
{
|
||||||
|
i->first.callback(i->second, i->first);
|
||||||
|
}
|
||||||
|
TORRENT_CATCH(std::exception& e)
|
||||||
|
{}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int disk_io_thread::add_job(disk_io_job const& j
|
int disk_io_thread::add_job(disk_io_job const& j
|
||||||
, mutex::scoped_lock& l
|
, mutex::scoped_lock& l
|
||||||
, boost::function<void(int, disk_io_job const&)> const& f)
|
, boost::function<void(int, disk_io_job const&)> const& f)
|
||||||
{
|
{
|
||||||
m_jobs.push_back(j);
|
const_cast<disk_io_job&>(j).start_time = time_now_hires();
|
||||||
m_jobs.back().callback.swap(const_cast<boost::function<void(int, disk_io_job const&)>&>(f));
|
|
||||||
m_jobs.back().start_time = time_now_hires();
|
|
||||||
|
|
||||||
if (j.action == disk_io_job::write)
|
if (j.action == disk_io_job::write)
|
||||||
{
|
{
|
||||||
|
@ -1305,6 +1321,36 @@ namespace libtorrent
|
||||||
&& m_settings.max_queued_disk_bytes > 0)
|
&& m_settings.max_queued_disk_bytes > 0)
|
||||||
m_exceeded_write_queue = true;
|
m_exceeded_write_queue = true;
|
||||||
}
|
}
|
||||||
|
else if (j.action == disk_io_job::read)
|
||||||
|
{
|
||||||
|
// if this is a cache hit, return it right away!
|
||||||
|
// this is OK because the cache is actually protected by
|
||||||
|
// the m_piece_mutex
|
||||||
|
bool hit = false;
|
||||||
|
if (j.buffer == 0)
|
||||||
|
{
|
||||||
|
// this is OK because the disk_buffer pool has its
|
||||||
|
// own mutex to protect the pool allocator
|
||||||
|
const_cast<disk_io_job&>(j).buffer = allocate_buffer("send buffer");
|
||||||
|
}
|
||||||
|
int ret = try_read_from_cache(j, hit, cache_only);
|
||||||
|
if (hit && ret >= 0)
|
||||||
|
{
|
||||||
|
TORRENT_ASSERT(f);
|
||||||
|
const_cast<disk_io_job&>(j).callback.swap(
|
||||||
|
const_cast<boost::function<void(int, disk_io_job const&)>&>(f));
|
||||||
|
job_queue_t* q = new job_queue_t;
|
||||||
|
q->push_back(std::make_pair(j, ret));
|
||||||
|
m_ios.post(boost::bind(completion_queue_handler, q));
|
||||||
|
return m_queue_buffer_size;
|
||||||
|
}
|
||||||
|
free_buffer(j.buffer);
|
||||||
|
const_cast<disk_io_job&>(j).buffer = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_jobs.push_back(j);
|
||||||
|
m_jobs.back().callback.swap(const_cast<boost::function<void(int, disk_io_job const&)>&>(f));
|
||||||
|
|
||||||
m_signal.signal(l);
|
m_signal.signal(l);
|
||||||
return m_queue_buffer_size;
|
return m_queue_buffer_size;
|
||||||
}
|
}
|
||||||
|
@ -1340,23 +1386,6 @@ namespace libtorrent
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef std::list<std::pair<disk_io_job, int> > job_queue_t;
|
|
||||||
void completion_queue_handler(job_queue_t* completed_jobs)
|
|
||||||
{
|
|
||||||
boost::shared_ptr<job_queue_t> holder(completed_jobs);
|
|
||||||
|
|
||||||
for (job_queue_t::iterator i = completed_jobs->begin()
|
|
||||||
, end(completed_jobs->end()); i != end; ++i)
|
|
||||||
{
|
|
||||||
TORRENT_TRY
|
|
||||||
{
|
|
||||||
i->first.callback(i->second, i->first);
|
|
||||||
}
|
|
||||||
TORRENT_CATCH(std::exception& e)
|
|
||||||
{}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void disk_io_thread::post_callback(disk_io_job const& j, int ret)
|
void disk_io_thread::post_callback(disk_io_job const& j, int ret)
|
||||||
{
|
{
|
||||||
if (!j.callback) return;
|
if (!j.callback) return;
|
||||||
|
@ -1937,8 +1966,7 @@ namespace libtorrent
|
||||||
m_log << log_time();
|
m_log << log_time();
|
||||||
#endif
|
#endif
|
||||||
INVARIANT_CHECK;
|
INVARIANT_CHECK;
|
||||||
TORRENT_ASSERT(j.buffer == 0);
|
if (j.buffer == 0) j.buffer = allocate_buffer("send buffer");
|
||||||
j.buffer = allocate_buffer("send buffer");
|
|
||||||
TORRENT_ASSERT(j.buffer_size <= m_block_size);
|
TORRENT_ASSERT(j.buffer_size <= m_block_size);
|
||||||
if (j.buffer == 0)
|
if (j.buffer == 0)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue