git-svn-id: https://profuse.googlecode.com/svn/branches/v2@127 aa027e90-d47c-11dd-86d7-074df07e0730

This commit is contained in:
ksherlock 2009-12-08 00:01:24 +00:00
parent 5c48dcb813
commit 9fc279ef64
3 changed files with 158 additions and 0 deletions

120
BlockCache.cpp Normal file
View File

@ -0,0 +1,120 @@
#include "BlockCache.h"
#include "BlockDevice.h"
#include "auto.h"
#include <algorithm>
/*
* Note -- everything is assumed to be single-threaded.
*
*/
using namespace ProFUSE;
typedef std::vector<BlockDescriptor>::iterator BDIter;
const unsigned CacheSize = 16;
BlockCache::BlockCache(BlockDevice *device)
{
_device = device;
_ts = 0;
_blocks.reserve(CacheSize);
}
BlockCache::~BlockCache()
{
for (BDIter iter = _blocks.begin(); iter != _blocks.end(); ++iter)
{
if (iter->data) delete[] iter->data;
}
}
void *BlockCache::acquire(unsigned block)
{
unsigned mints = -1;
unsigned freeCount = 0;
BDIter oldest;
++_ts;
/*
* keep a pointer to the oldest free entry (according to ts).
* and re-use if >= 16 entries.
*/
for (BDIter iter = _blocks.begin(); iter != _blocks.end(); ++iter)
{
if (iter->block == block)
{
++iter->count;
iter->ts = _ts;
return iter->data;
}
if (iter->count == 0)
{
++freeCount;
if (iter->ts < mints)
{
mints = iter->ts;
oldest = iter;
}
}
}
if (freeCount && (_blocks.size() >= CacheSize))
{
oldest->block = block;
oldest->count = 1;
oldest->ts = _ts;
_device->read(block, oldest->data);
return oldest->data;
}
auto_array<uint8_t> buffer(new uint8_t[512]);
BlockDescriptor bd = { block, 1, _ts, buffer.get() };
_device->read(block, buffer.get());
_blocks.push_back(bd);
return buffer.release();
}
void BlockCache::release(unsigned block)
{
for (BDIter iter = _blocks.begin(); iter != _blocks.end(); ++iter)
{
if (iter->block == block)
{
if (!--iter->count)
{
_device->write(block, iter->data);
// trim back if too many entries.
if (_blocks.size() > CacheSize)
{
delete[] iter->data;
_blocks.erase(iter);
}
}
return;
}
}
}

37
BlockCache.h Normal file
View File

@ -0,0 +1,37 @@
#ifndef __BLOCKCACHE_H__
#define __BLOCKCACHE_H__
#include <stdint.h>
#include <vector>
namespace ProFUSE {
class BlockDevice;
struct BlockDescriptor {
unsigned block;
unsigned count;
unsigned ts;
uint8_t *data;
};
class BlockCache {
BlockCache(BlockDevice *device);
~BlockCache();
void write();
void *acquire(unsigned block);
void release(unsigned block);
private:
std::vector<BlockDescriptor> _blocks;
BlockDevice *_device;
unsigned _ts;
};
}
#endif

View File

@ -16,6 +16,7 @@ using namespace LittleEndian;
#pragma mark VolumeDirectory
VolumeDirectory *VolumeDirectory::Create(const char *name, BlockDevice *device)
{
return new VolumeDirectory(name, device);