From 6a01b035be314674071ef8b24eccbb5d197e32ec Mon Sep 17 00:00:00 2001 From: Arvid Norberg Date: Mon, 1 Aug 2011 08:03:26 +0000 Subject: [PATCH] add missing files --- include/libtorrent/disk_buffer_pool.hpp | 126 ++++++++++++++ src/disk_buffer_pool.cpp | 212 ++++++++++++++++++++++++ 2 files changed, 338 insertions(+) create mode 100644 include/libtorrent/disk_buffer_pool.hpp create mode 100644 src/disk_buffer_pool.cpp diff --git a/include/libtorrent/disk_buffer_pool.hpp b/include/libtorrent/disk_buffer_pool.hpp new file mode 100644 index 000000000..c9d1cbbb2 --- /dev/null +++ b/include/libtorrent/disk_buffer_pool.hpp @@ -0,0 +1,126 @@ +/* + +Copyright (c) 2007-2011, 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_DISK_BUFFER_POOL +#define TORRENT_DISK_BUFFER_POOL + +#include "libtorrent/config.hpp" +#include "libtorrent/thread.hpp" +#include "libtorrent/session_settings.hpp" +#include "libtorrent/allocator.hpp" + +#ifndef TORRENT_DISABLE_POOL_ALLOCATOR +#include +#endif + +#if defined TORRENT_DEBUG || TORRENT_RELEASE_ASSERTS +#include +#endif + +namespace libtorrent +{ + struct TORRENT_EXPORT disk_buffer_pool : boost::noncopyable + { + disk_buffer_pool(int block_size); +#if defined TORRENT_DEBUG || TORRENT_RELEASE_ASSERTS + ~disk_buffer_pool(); +#endif + +#if defined TORRENT_DEBUG || TORRENT_RELEASE_ASSERTS + bool is_disk_buffer(char* buffer + , mutex::scoped_lock& l) const; + bool is_disk_buffer(char* buffer) const; +#endif + + char* allocate_buffer(char const* category); + void free_buffer(char* buf); + void free_multiple_buffers(char** bufvec, int numbufs); + + int block_size() const { return m_block_size; } + +#ifdef TORRENT_STATS + int disk_allocations() const + { return m_allocations; } +#endif + +#ifdef TORRENT_DISK_STATS + std::ofstream m_disk_access_log; +#endif + + void release_memory(); + + int in_use() const { return m_in_use; } + + protected: + + void free_buffer_impl(char* buf, mutex::scoped_lock& l); + + // number of bytes per block. The BitTorrent + // protocol defines the block size to 16 KiB. + const int m_block_size; + + // number of disk buffers currently allocated + int m_in_use; + + session_settings m_settings; + + private: + + mutable mutex m_pool_mutex; + +#ifndef TORRENT_DISABLE_POOL_ALLOCATOR + // memory pool for read and write operations + // and disk cache + boost::pool m_pool; +#endif + +#if defined TORRENT_DISK_STATS || defined TORRENT_STATS + int m_allocations; +#endif +#ifdef TORRENT_DISK_STATS + public: + void rename_buffer(char* buf, char const* category); + protected: + std::map m_categories; + std::map m_buf_to_category; + std::ofstream m_log; + private: +#endif +#if defined TORRENT_DEBUG || TORRENT_RELEASE_ASSERTS + int m_magic; +#endif + }; + +} + +#endif // TORRENT_DISK_BUFFER_POOL + diff --git a/src/disk_buffer_pool.cpp b/src/disk_buffer_pool.cpp new file mode 100644 index 000000000..9d9d8dfc7 --- /dev/null +++ b/src/disk_buffer_pool.cpp @@ -0,0 +1,212 @@ +/* + +Copyright (c) 2007-2011, 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/disk_buffer_pool.hpp" +#include "libtorrent/assert.hpp" + +#if TORRENT_USE_MLOCK && !defined TORRENT_WINDOWS +#include +#endif + +namespace libtorrent +{ + disk_buffer_pool::disk_buffer_pool(int block_size) + : m_block_size(block_size) + , m_in_use(0) +#ifndef TORRENT_DISABLE_POOL_ALLOCATOR + , m_pool(block_size, m_settings.cache_buffer_chunk_size) +#endif + { +#if defined TORRENT_DISK_STATS || defined TORRENT_STATS + m_allocations = 0; +#endif +#ifdef TORRENT_DISK_STATS + m_log.open("disk_buffers.log", std::ios::trunc); + m_categories["read cache"] = 0; + m_categories["write cache"] = 0; + + m_disk_access_log.open("disk_access.log", std::ios::trunc); +#endif +#if defined TORRENT_DEBUG || TORRENT_RELEASE_ASSERTS + m_magic = 0x1337; +#endif + } + +#if defined TORRENT_DEBUG || TORRENT_RELEASE_ASSERTS + disk_buffer_pool::~disk_buffer_pool() + { + TORRENT_ASSERT(m_magic == 0x1337); + m_magic = 0; + } +#endif + +#if defined TORRENT_DEBUG || TORRENT_RELEASE_ASSERTS || defined TORRENT_DISK_STATS + bool disk_buffer_pool::is_disk_buffer(char* buffer + , mutex::scoped_lock& l) const + { + TORRENT_ASSERT(m_magic == 0x1337); +#ifdef TORRENT_DISK_STATS + if (m_buf_to_category.find(buffer) + == m_buf_to_category.end()) return false; +#endif +#ifdef TORRENT_DISABLE_POOL_ALLOCATOR + return true; +#else + return m_pool.is_from(buffer); +#endif + } + + bool disk_buffer_pool::is_disk_buffer(char* buffer) const + { + mutex::scoped_lock l(m_pool_mutex); + return is_disk_buffer(buffer, l); + } +#endif + + char* disk_buffer_pool::allocate_buffer(char const* category) + { + mutex::scoped_lock l(m_pool_mutex); + TORRENT_ASSERT(m_magic == 0x1337); +#ifdef TORRENT_DISABLE_POOL_ALLOCATOR + char* ret = page_aligned_allocator::malloc(m_block_size); +#else + char* ret = (char*)m_pool.ordered_malloc(); + m_pool.set_next_size(m_settings.cache_buffer_chunk_size); +#endif + ++m_in_use; +#if TORRENT_USE_MLOCK + if (m_settings.lock_disk_cache) + { +#ifdef TORRENT_WINDOWS + VirtualLock(ret, m_block_size); +#else + mlock(ret, m_block_size); +#endif + } +#endif + +#if defined TORRENT_DISK_STATS || defined TORRENT_STATS + ++m_allocations; +#endif +#ifdef TORRENT_DISK_STATS + ++m_categories[category]; + m_buf_to_category[ret] = category; + m_log << log_time() << " " << category << ": " << m_categories[category] << "\n"; +#endif + TORRENT_ASSERT(ret == 0 || is_disk_buffer(ret, l)); + return ret; + } + +#ifdef TORRENT_DISK_STATS + void disk_buffer_pool::rename_buffer(char* buf, char const* category) + { + mutex::scoped_lock l(m_pool_mutex); + TORRENT_ASSERT(is_disk_buffer(buf, l)); + TORRENT_ASSERT(m_categories.find(m_buf_to_category[buf]) + != m_categories.end()); + std::string const& prev_category = m_buf_to_category[buf]; + --m_categories[prev_category]; + m_log << log_time() << " " << prev_category << ": " << m_categories[prev_category] << "\n"; + + ++m_categories[category]; + m_buf_to_category[buf] = category; + m_log << log_time() << " " << category << ": " << m_categories[category] << "\n"; + TORRENT_ASSERT(m_categories.find(m_buf_to_category[buf]) + != m_categories.end()); + } +#endif + + void disk_buffer_pool::free_multiple_buffers(char** bufvec, int numbufs) + { + char** end = bufvec + numbufs; + // sort the pointers in order to maximize cache hits + std::sort(bufvec, end); + + mutex::scoped_lock l(m_pool_mutex); + for (; bufvec != end; ++bufvec) + { + char* buf = *bufvec; + TORRENT_ASSERT(buf); + free_buffer_impl(buf, l);; + } + } + + void disk_buffer_pool::free_buffer(char* buf) + { + mutex::scoped_lock l(m_pool_mutex); + free_buffer_impl(buf, l); + } + + void disk_buffer_pool::free_buffer_impl(char* buf, mutex::scoped_lock& l) + { + TORRENT_ASSERT(buf); + TORRENT_ASSERT(m_magic == 0x1337); + TORRENT_ASSERT(is_disk_buffer(buf, l)); +#if defined TORRENT_DISK_STATS || defined TORRENT_STATS + --m_allocations; +#endif +#ifdef TORRENT_DISK_STATS + TORRENT_ASSERT(m_categories.find(m_buf_to_category[buf]) + != m_categories.end()); + std::string const& category = m_buf_to_category[buf]; + --m_categories[category]; + m_log << log_time() << " " << category << ": " << m_categories[category] << "\n"; + m_buf_to_category.erase(buf); +#endif +#if TORRENT_USE_MLOCK + if (m_settings.lock_disk_cache) + { +#ifdef TORRENT_WINDOWS + VirtualUnlock(buf, m_block_size); +#else + munlock(buf, m_block_size); +#endif + } +#endif +#ifdef TORRENT_DISABLE_POOL_ALLOCATOR + page_aligned_allocator::free(buf); +#else + m_pool.free(buf); +#endif + --m_in_use; + } + + void disk_buffer_pool::release_memory() + { + TORRENT_ASSERT(m_magic == 0x1337); +#ifndef TORRENT_DISABLE_POOL_ALLOCATOR + mutex::scoped_lock l(m_pool_mutex); + m_pool.release_memory(); +#endif + } +} +