122 lines
3.4 KiB
C++
122 lines
3.4 KiB
C++
/**
|
|
* =========================================================================
|
|
* File : block_cache.h
|
|
* Project : 0 A.D.
|
|
* Description : cache for aligned I/O blocks.
|
|
* =========================================================================
|
|
*/
|
|
|
|
// license: GPL; see lib/license.txt
|
|
|
|
#ifndef INCLUDED_BLOCK_CACHE
|
|
#define INCLUDED_BLOCK_CACHE
|
|
|
|
#include <boost/shared_ptr.hpp>
|
|
#include "io_buf.h"
|
|
|
|
/**
|
|
* block := power-of-two sized chunk of a file.
|
|
* all transfers are expanded to naturally aligned, whole blocks
|
|
* (this makes caching parts of files feasible; it is also much faster
|
|
* for some aio implementations, e.g. wposix).
|
|
*
|
|
* measurements show this value to yield best read throughput.
|
|
**/
|
|
static const size_t BLOCK_SIZE = 32*KiB;
|
|
|
|
|
|
/**
|
|
* ID that uniquely identifies a block within a file
|
|
**/
|
|
class BlockId
|
|
{
|
|
public:
|
|
BlockId();
|
|
BlockId(const char* atom_fn, off_t ofs);
|
|
bool operator==(const BlockId& rhs) const;
|
|
bool operator!=(const BlockId& rhs) const;
|
|
|
|
private:
|
|
const char* m_atom_fn;
|
|
u32 m_blockIndex;
|
|
};
|
|
|
|
|
|
/**
|
|
* cache of (aligned) file blocks with support for zero-copy IO.
|
|
* absorbs the overhead of rounding up archive IOs to the nearest block
|
|
* boundaries by keeping the last few blocks in memory.
|
|
*
|
|
* the interface is quite similar to FileCache; see the note there.
|
|
**/
|
|
class BlockCache
|
|
{
|
|
public:
|
|
/**
|
|
* @param cacheSize total size [bytes] that the cache is to manage.
|
|
* the default value is enough to support temp buffers and
|
|
* absorb the cost of unaligned reads from a few archives.
|
|
**/
|
|
BlockCache(size_t cacheSize = 16 * BLOCK_SIZE);
|
|
|
|
/**
|
|
* Reserve a block for use as an IO buffer.
|
|
*
|
|
* @return suitably aligned memory; never fails.
|
|
*
|
|
* no further operations with the same id are allowed to succeed
|
|
* until MarkComplete has been called.
|
|
**/
|
|
IoBuf Reserve(BlockId id);
|
|
|
|
/**
|
|
* Indicate that IO into the block has completed.
|
|
*
|
|
* this allows the cache to satisfy subsequent Retrieve() calls by
|
|
* returning this block; if CONFIG_READ_ONLY_CACHE, the block is
|
|
* made read-only. if need be and no references are currently attached
|
|
* to it, the memory can also be commandeered by Reserve().
|
|
**/
|
|
void MarkComplete(BlockId id);
|
|
|
|
/**
|
|
* Attempt to retrieve a block the file cache.
|
|
*
|
|
* @return 0 if not in cache or its IO is still pending, otherwise a
|
|
* pointer to its (read-only) contents.
|
|
*
|
|
* if successful, a reference is added to the block.
|
|
**/
|
|
IoBuf Retrieve(BlockId id);
|
|
|
|
/**
|
|
* Indicate the block contents are no longer needed.
|
|
*
|
|
* this decreases the reference count; the memory can only be reused
|
|
* if it reaches 0. the block remains in cache until evicted by a
|
|
* subsequent Reserve() call.
|
|
*
|
|
* note: fails (raises a warning) if called for a buffer that is
|
|
* currently between Reserve and MarkComplete operations.
|
|
**/
|
|
void Release(BlockId id);
|
|
|
|
/**
|
|
* Invalidate the contents of the cache.
|
|
*
|
|
* this effectively discards the contents of existing blocks
|
|
* (more specifically: prevents them from satisfying Retrieve() calls
|
|
* until a subsequent Reserve/MarkComplete of that block).
|
|
*
|
|
* useful for self-tests: multiple independent IO tests run in the same
|
|
* process and must not influence each other via the cache.
|
|
**/
|
|
void InvalidateAll();
|
|
|
|
private:
|
|
class Impl;
|
|
boost::shared_ptr<Impl> impl;
|
|
};
|
|
|
|
#endif * #ifndef INCLUDED_BLOCK_CACHE
|