mirror of
https://github.com/ksherlock/profuse.git
synced 2024-06-10 17:29:32 +00:00
git-svn-id: https://profuse.googlecode.com/svn/branches/v2@234 aa027e90-d47c-11dd-86d7-074df07e0730
This commit is contained in:
parent
fc7c205fe0
commit
bc5ffeab05
177
BlockCache.cpp
177
BlockCache.cpp
|
@ -1,177 +0,0 @@
|
||||||
#include "BlockCache.h"
|
|
||||||
|
|
||||||
struct FileBlockCache::Entry {
|
|
||||||
FileBlockCache::Entry *next;
|
|
||||||
unsigned block;
|
|
||||||
unsigned count;
|
|
||||||
bool dirty;
|
|
||||||
uint8_t buffer[512];
|
|
||||||
};
|
|
||||||
|
|
||||||
FileBlockCache::FileBlockCache(Device *device)
|
|
||||||
{
|
|
||||||
_device = device;
|
|
||||||
|
|
||||||
// allocate initial buffer.
|
|
||||||
for (unsigned i = 0; i < 10; ++i)
|
|
||||||
{
|
|
||||||
Entry *e = new Entry;
|
|
||||||
std::memset(e, 0, sizeof(Entry));
|
|
||||||
|
|
||||||
_pages.push_back(e);
|
|
||||||
_unused.push_back(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
FileBlockCache::~FileBlockCache()
|
|
||||||
{
|
|
||||||
std::vector<Entry *>::iterator iter;
|
|
||||||
|
|
||||||
// todo -- check if dirty.
|
|
||||||
|
|
||||||
// deallocate everything that was allocated.
|
|
||||||
for (iter = _pages.begin(); iter != _pages.end(); ++iter)
|
|
||||||
{
|
|
||||||
Entrty *e = *iter;
|
|
||||||
if (e->dirty) sync(e);
|
|
||||||
delete e;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
uint8_t *FileBlockCache::acquire(unsigned block)
|
|
||||||
{
|
|
||||||
Entry *e = findEntry(block);
|
|
||||||
|
|
||||||
if (e)
|
|
||||||
{
|
|
||||||
if (++e->count == 1)
|
|
||||||
_unused.remove(e);
|
|
||||||
return e->buffer;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_unused.empty())
|
|
||||||
{
|
|
||||||
e = new Entry;
|
|
||||||
_pages.push_back(e);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
e = _unused.pop_front();
|
|
||||||
|
|
||||||
removeEntry(e);
|
|
||||||
}
|
|
||||||
std::memset(e, 0, sizeof(Entry));
|
|
||||||
unsigned hash = hashFunction(block);
|
|
||||||
|
|
||||||
e->block = block;
|
|
||||||
e->count = 1;
|
|
||||||
e->dirty = 0;
|
|
||||||
|
|
||||||
_device->read(block, e->buffer);
|
|
||||||
|
|
||||||
_e->next = _hashMap[hash];
|
|
||||||
_hashMap[hash] = e;
|
|
||||||
|
|
||||||
return e->buffer;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void FileBlockCache::release(unsigned block, bool dirty)
|
|
||||||
{
|
|
||||||
Entry *e = findEntry(block);
|
|
||||||
|
|
||||||
// throw error?
|
|
||||||
if (!e) return;
|
|
||||||
|
|
||||||
if (dirty) e->dirty = true;
|
|
||||||
|
|
||||||
if (e->count == 0) return;
|
|
||||||
if (--e->count == 0)
|
|
||||||
{
|
|
||||||
_unused.push_back(e);
|
|
||||||
}
|
|
||||||
// sync if dirty??
|
|
||||||
}
|
|
||||||
|
|
||||||
void FileBlockCache::markDirty(unsigned block)
|
|
||||||
{
|
|
||||||
Entry *e = findEntry(e);
|
|
||||||
|
|
||||||
if (e && e->count) e->dirty = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
Entry *FileBlockCache::findEntry(unsigned block)
|
|
||||||
{
|
|
||||||
unsigned hash = hashFunction(block);
|
|
||||||
Entry *e;
|
|
||||||
|
|
||||||
e = _hashMap[hash];
|
|
||||||
|
|
||||||
while (e && e->block != block)
|
|
||||||
{
|
|
||||||
e = e->next;
|
|
||||||
}
|
|
||||||
|
|
||||||
return e;
|
|
||||||
}
|
|
||||||
|
|
||||||
void FileBlockCache::removeEntry(Entry *e)
|
|
||||||
{
|
|
||||||
unsigned hash;
|
|
||||||
Entry *curr;
|
|
||||||
Entry *prev;
|
|
||||||
|
|
||||||
if (!e) return;
|
|
||||||
|
|
||||||
hash = hashFunction(e->block);
|
|
||||||
|
|
||||||
curr = _hashMap[hash];
|
|
||||||
|
|
||||||
if (curr == e)
|
|
||||||
{
|
|
||||||
_hashMap[hash] = e->next;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (;;)
|
|
||||||
{
|
|
||||||
prev = curr;
|
|
||||||
curr = curr->next;
|
|
||||||
|
|
||||||
if (!curr) break;
|
|
||||||
|
|
||||||
if (e == curr)
|
|
||||||
{
|
|
||||||
prev->next = e->next;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned FileBlockCache::hashFunction(unsigned block)
|
|
||||||
{
|
|
||||||
return block % HashEntries;
|
|
||||||
}
|
|
||||||
|
|
||||||
void FileBlockCache::sync(Entry *e)
|
|
||||||
{
|
|
||||||
if (!e) return;
|
|
||||||
if (!e->dirty) return;
|
|
||||||
|
|
||||||
_device->write(e->block, e->buffer);
|
|
||||||
e->dirty = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void FileBlockCache::sync()
|
|
||||||
{
|
|
||||||
std::vector<Entry *>::iterator iter;
|
|
||||||
|
|
||||||
for (iter = _pages.begin(); iter != _pages.end(); ++iter)
|
|
||||||
{
|
|
||||||
Entry *e = *iter;
|
|
||||||
|
|
||||||
if (e && e->dirty) sync(e);
|
|
||||||
}
|
|
||||||
}
|
|
81
BlockCache.h
81
BlockCache.h
|
@ -1,81 +0,0 @@
|
||||||
#ifndef __BLOCK_CACHE_H__
|
|
||||||
#define __BLOCK_CACHE__
|
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
#include <vector>
|
|
||||||
#include <list>
|
|
||||||
|
|
||||||
//#include <ext/hash_map>
|
|
||||||
//typedef std::__gnu_cxx::hash_map hash_map;
|
|
||||||
|
|
||||||
namespace ProFUSE {
|
|
||||||
|
|
||||||
class BlockCache {
|
|
||||||
public:
|
|
||||||
|
|
||||||
virtual ~BlockCache();
|
|
||||||
|
|
||||||
virtual uint8_t *acquire(unsigned block) = 0;
|
|
||||||
virtual void release(unsigned block, bool dirty = false) = 0;
|
|
||||||
virtual void markDirty(unsigned block) = 0;
|
|
||||||
|
|
||||||
virtual void sync() = 0;
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
class FileBlockCache : public BlockCache {
|
|
||||||
|
|
||||||
|
|
||||||
FileBlockCache(Device *);
|
|
||||||
virtual ~FileBlockCache();
|
|
||||||
|
|
||||||
virtual uint8_t *acquire(unsigned block);
|
|
||||||
virtual void release(unsigned block, bool dirty = false);
|
|
||||||
virtual void markDirty(unsigned block);
|
|
||||||
|
|
||||||
virtual void sync();
|
|
||||||
|
|
||||||
private:
|
|
||||||
struct Entry;
|
|
||||||
|
|
||||||
enum { HashEntries = 23 };
|
|
||||||
|
|
||||||
|
|
||||||
unsigned hashFunction(unsigned);
|
|
||||||
|
|
||||||
void removeEntry(Entry *);
|
|
||||||
Entry *findEntry(unsigned block);
|
|
||||||
void sync(Entry *);
|
|
||||||
|
|
||||||
std::vector<Entry *> _pages;
|
|
||||||
std::list<Entry *> _unused;
|
|
||||||
|
|
||||||
Entry *_hashMap[HashEntries];
|
|
||||||
|
|
||||||
Device *_device;
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
class MappedBlockCache : public BlockCache
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
|
|
||||||
MappedBlockCache(Device *);
|
|
||||||
virtual ~MappedBlockCache();
|
|
||||||
|
|
||||||
virtual uint8_t *acquire(unsigned block);
|
|
||||||
virtual void release(unsigned block, bool dirty = false);
|
|
||||||
virtual void markDirty(unsigned block);
|
|
||||||
|
|
||||||
virtual void sync();
|
|
||||||
|
|
||||||
|
|
||||||
private:
|
|
||||||
Device *_device;
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
Loading…
Reference in New Issue
Block a user