0
0
mirror of https://github.com/mongodb/mongo.git synced 2024-12-01 09:32:32 +01:00
mongodb/db/reccache.h
2009-02-04 11:26:51 -05:00

129 lines
3.1 KiB
C++

// reccache.h
#pragma once
#include "reci.h"
#include "recstore.h"
namespace mongo {
class RecCache {
struct Node {
Node() { dirty = false; newer = 0; }
char *data;
DiskLoc loc;
bool dirty;
Node *older, *newer;
};
unsigned recsize;
map<DiskLoc, Node*> m;
set<DiskLoc> dirtyl;
Node *newest, *oldest;
unsigned nnodes;
public:
static BasicRecStore tempStore;
void writeDirty();
void ejectOld();
private:
void writeIfDirty(Node *n);
void touch(Node* n) {
if( n == newest )
return;
if( n == oldest ) {
oldest = oldest->newer;
assert( oldest || nnodes == 1 );
}
if( n->older )
n->older->newer = n->newer;
if( n->newer )
n->newer->older = n->older;
n->newer = 0;
n->older = newest;
newest->newer = n;
newest = n;
}
Node* mkNode() {
Node *n = new Node();
n->data = (char *) calloc(recsize,1); // calloc is TEMP for testing. change to malloc
n->older = newest;
if( newest )
newest->newer = n;
else {
assert( oldest == 0 );
oldest = n;
}
newest = n;
nnodes++;
return n;
}
fileofs fileOfs(DiskLoc d) {
// temp impl
return d.getOfs();
}
void dump();
public:
RecCache(unsigned sz) : recsize(sz) {
nnodes = 0;
newest = oldest = 0;
}
void dirty(DiskLoc d) {
map<DiskLoc, Node*>::iterator i = m.find(d);
if( i != m.end() ) {
Node *n = i->second;
if( !n->dirty ) {
n->dirty = true;
dirtyl.insert(n->loc);
}
}
}
char* get(DiskLoc d, unsigned len) {
assert( d.a() == 9999 );
assert( len == recsize );
map<DiskLoc, Node*>::iterator i = m.find(d);
if( i != m.end() ) {
touch(i->second);
return i->second->data;
}
Node *n = mkNode();
n->loc = d;
tempStore.get(fileOfs(d), n->data, recsize); // could throw exception
m.insert( pair<DiskLoc, Node*>(d, n) );
return n->data;
}
DiskLoc insert(const char *ns, const void *obuf, int len, bool god) {
fileofs o = tempStore.insert((const char *) obuf, len);
assert( o <= 0x7fffffff );
Node *n = mkNode();
memcpy(n->data, obuf, len);
DiskLoc d(9999, (int) o);
n->loc = d;
m[d] = n;
return d;
}
};
class BasicCached_RecStore : public RecStoreInterface {
public:
static RecCache rc;
static char* get(DiskLoc d, unsigned len) {
return rc.get(d, len);
}
static DiskLoc insert(const char *ns, const void *obuf, int len, bool god) {
return rc.insert(ns, obuf, len, god);
}
static void modified(DiskLoc d) {
assert( d.a() == 9999 );
rc.dirty(d);
}
};
} /*namespace*/