git-svn-id: https://profuse.googlecode.com/svn/branches/v2@127 aa027e90-d47c-11dd-86d7-074df07e0730
This commit is contained in:
parent
5c48dcb813
commit
9fc279ef64
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -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
|
|
@ -16,6 +16,7 @@ using namespace LittleEndian;
|
||||||
#pragma mark VolumeDirectory
|
#pragma mark VolumeDirectory
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
VolumeDirectory *VolumeDirectory::Create(const char *name, BlockDevice *device)
|
VolumeDirectory *VolumeDirectory::Create(const char *name, BlockDevice *device)
|
||||||
{
|
{
|
||||||
return new VolumeDirectory(name, device);
|
return new VolumeDirectory(name, device);
|
||||||
|
|
Loading…
Reference in New Issue