0
0
mirror of https://github.com/mongodb/mongo.git synced 2024-12-01 09:32:32 +01:00
mongodb/db/namespace.h
2008-02-11 11:37:11 -05:00

216 lines
4.6 KiB
C++

// namespace.h
#pragma once
#include "../util/hashtab.h"
#include "../util/mmap.h"
class Cursor;
#pragma pack(push)
#pragma pack(1)
class Namespace {
public:
Namespace(const char *ns) {
*this = ns;
}
Namespace& operator=(const char *ns) {
memset(buf, 0, 128); /* this is just to keep stuff clean in the files for easy dumping and reading */
strcpy_s(buf, 128, ns); return *this;
}
void kill() {
buf[0] = 0x7f;
}
bool operator==(const Namespace& r) { return strcmp(buf, r.buf) == 0; }
int hash() const {
unsigned x = 0;
const char *p = buf;
while( *p ) {
x = x * 131 + *p;
p++;
}
return (x & 0x7fffffff) | 0x8000000; // must be > 0
}
char buf[128];
};
const int Buckets = 19;
const int MaxBucket = 18;
const int MaxIndexes = 10;
class IndexDetails {
public:
DiskLoc head; /* btree head */
DiskLoc info; /* index info object. { name:, ns:, key: } */
/* pull out the relevant key objects from obj, so we
can index them. Note that the set is multiple elements
only when it's a "multikey" array.
keys will be left empty if key not found in the object.
*/
void getKeysFromObject(JSObj& obj, set<JSObj>& keys);
// returns name of this index's storage area
// client.table.$index
string indexNamespace() {
JSObj io = info.obj();
string s;
s.reserve(128);
s = io.getStringField("ns");
assert( !s.empty() );
s += ".$";
s += io.getStringField("name");
return s;
}
};
extern int bucketSizes[];
class NamespaceDetails {
public:
NamespaceDetails() {
datasize = nrecords = 0;
lastExtentSize = 0;
nIndexes = 0;
memset(reserved, 0, sizeof(reserved));
}
DiskLoc firstExtent;
DiskLoc lastExtent;
DiskLoc deletedList[Buckets];
long long datasize;
long long nrecords;
int lastExtentSize;
int nIndexes;
IndexDetails indexes[MaxIndexes];
char reserved[256-16-4-4-8*MaxIndexes-8];
//returns offset in indexes[]
int findIndexByName(const char *name) {
for( int i = 0; i < nIndexes; i++ ) {
if( strcmp(indexes[i].info.obj().getStringField("name"),name) == 0 )
return i;
}
return -1;
}
/* return which "deleted bucket" for this size object */
static int bucket(int n) {
for( int i = 0; i < Buckets; i++ )
if( bucketSizes[i] > n )
return i;
return Buckets-1;
}
DiskLoc alloc(int lenToAlloc, DiskLoc& extentLoc);
void addDeletedRec(DeletedRecord *d, DiskLoc dloc);
private:
DiskLoc _alloc(int len);
};
#pragma pack(pop)
class NamespaceIndex {
friend class NamespaceCursor;
public:
NamespaceIndex() { }
void init(const char *dir, const char *client) {
string path = dir;
path += client;
path += ".ns";
const int LEN = 16 * 1024 * 1024;
void *p = f.map(path.c_str(), LEN);
if( p == 0 ) {
cout << "couldn't open namespace.idx " << path.c_str() << endl;
exit(-3);
}
ht = new HashTable<Namespace,NamespaceDetails>(p, LEN, "namespace index");
}
void add(const char *ns, DiskLoc& loc) {
Namespace n(ns);
NamespaceDetails details;
details.lastExtent = details.firstExtent = loc;
ht->put(n, details);
}
NamespaceDetails* details(const char *ns) {
Namespace n(ns);
return ht->get(n);
}
void kill(const char *ns) {
Namespace n(ns);
ht->kill(n);
}
bool find(const char *ns, DiskLoc& loc) {
NamespaceDetails *l = details(ns);
if( l ) {
loc = l->firstExtent;
return true;
}
return false;
}
private:
MemoryMappedFile f;
HashTable<Namespace,NamespaceDetails> *ht;
};
extern const char *dbpath;
/*
class NamespaceIndexMgr {
public:
NamespaceIndexMgr() { }
NamespaceIndex* get(const char *client) {
map<string,NamespaceIndex*>::iterator it = m.find(client);
if( it != m.end() )
return it->second;
NamespaceIndex *ni = new NamespaceIndex();
ni->init(dbpath, client);
m[client] = ni;
return ni;
}
private:
map<string,NamespaceIndex*> m;
};
extern NamespaceIndexMgr namespaceIndexMgr;
*/
// "client.a.b.c" -> "client"
inline void nsToClient(const char *ns, char *client) {
const char *p = ns;
char *q = client;
while( *p != '.' ) {
if( *p == 0 ) {
assert(false);
*client = 0;
return;
}
*q++ = *p++;
}
*q = 0;
assert(q-client<256);
}
/*
inline NamespaceIndex* nsindex(const char *ns) {
char client[256];
nsToClient(ns, client);
return namespaceIndexMgr.get(client);
}
inline NamespaceDetails* nsdetails(const char *ns) {
return nsindex(ns)->details(ns);
}
*/
//auto_ptr<Cursor> makeNamespaceCursor();