Please check out Mordor !

Member Discussions

terms



[Previous] [Next] [Post] [Reply] [Topics] [Summary] [Search]


1. New MUD storage option (see MySQL vs. Flatfiles) Mon Sep 27, 2004 [5:06 PM]
lindahlb
Email not supplied
member since: Mar 2, 2001
Reply
I've been working on a project for a while now that I call MudDB. The project isn't quite finished - its going through the debugging stages right now and I plan on releasing it as open source. It's an object-oriented database written for C++ that has the following features:

1) full data reliability (ACID) via a global transaction
2) fine-grained locking (object level)
3) locking policies of none, exclusive, and reader/writer
4) multithread safe
5) embedded in code
6) syntax similiar to regular pointer interface
7) user-specified clustering optimization
8) supports class changes (auto-versioning!)
9) minimal 4 byte overhead per object (less than some memory allocators!)
10) minimal .8% cache waste (bookkeeping)
11) supports C++ virtual functions
12) one variable length array (at end of object)

The following limitations are needed to provide incredibly optimized access - something that the more flexible commercial solutions aren't able to offer. Now these limitations aren't necessarily required - but I felt that these limitations were loose enough to fit any MUD - even a large one:
1) 1020 classes
2) 255 loads before garbage collection is required
3) 4KB maximum size per object

At this point I'm just looking for suggestions or comments on my implementation and what else I should add support for. See below for more details, as well as an example of how one would use the sytnax of the database system.

Note that the 4KB max object size wouldn't be too difficult to expand to larger sizes (256KB) with too big of a hit to performance. Smaller object access wouldn't be minimally comprimised, but I felt that there isn't much of a need for objects larger than 4096 bytes - at least not enough to sacrifice some of the optimization. The problem with allowing for large objects is that they would thrash the cache and would be better off implemented seperately (since they would typically be documentation text files).

A few tools that it comes with is the garbage collector (required to be run at least every 255 times the database is opened). Clustering tool (a tool that will optimize the clustering of objects as specified by the user-programmer). A dumping tool (dumps the database into a full text format - XML support a future possibility). A reporting tool (object lookup and tracing).

I built it because there doesn't seem to be a good product out there that can give us MUD programmers what we want - an effecient reliable object-oriented database that is optimized for a multitude of small classes where inheritance is common. Something that gives us similiar attirbutes to virtual memory, but is persistant as well. One that also supports dynamic dispatch (virtual function tables), changes to class structure (automatic versioning), and clustering. Where clustering is allowing the programmer to specify what objects are accessed around the same point in time - providing a significant optimization (the clustering tool is also run while the database is closed).

The syntax is very simple and intuitive, with everything being accessible from a root object.

The source code is quite small, and minimalistic headers are used (to cut down on compilation time - a problem with gcc). Consider each unit between headers as a seperate file.

A simple session:

#include <mdb/object.h>

class Game : public Object {
MDB_DECLARE(Game, Object);
public:
int version;
int array[5];
mdb::ptr<Game> recurse;
mdb::ptr<Game> other[5];
char variablename[1];
void update();
};

#include <mdb/class.h>

MDB_REGISTER(Game, Object)
MDB_VAR(version)
MDB_ARY(array)
MDB_VAR(recurse)
MDB_ARY(other)
MDB_VARY(variablename)
MBD_END

#include <mdb/database.h>

mdb::Database db(name, cacheSize);
db.open();
mdb::ptr<GameData> p = db.getRoot<GameData>();
if (p->version < THIS_VERSION) {
modify(p)->update();
modify(p)->version = THIS_VERSION;
}
db.commit(); // or rollback to cancel changes
db.close();

#include <mdb/accessors.h>
{// a writer object submits an object for multiple writes - optimization
Writer<Game> w;
w->recurse = p;
w->variablename[0] = '\0';
}

int result = 0;
{// a reader object submits an object for multiple reads - optimization
Reader<Game> r;
result = r->array[0] + r->array[1] + r->array[2];
}


(Comment added by lindahlb on Mon Sep 27 18:15:05 2004)

Oh, another possible extension I would be adding would be dynamic dispatch member access:


// this pointer can point to any database object
mdb::ptr<mdb::Object> p = db.getRoot();

mdb::Class cls = p->myClass();
mdb::Member mbr = cls["membername"];

// the below would throw an exception if the
// member didn't exist or the type was wrong
p["membername"] = newarray;

// this would be equivalent to the above
// except much faster access
p[mbr] = newarray;
p[mbr][0] = newvalue;

mbr->name // the string name of the member
mbr->type // an enum describing the type of the member
mbr->size // an value describing the size of the member
mbr->offset // a value describing the offset in raw bytes
mbr->elements // the number of elements in the member, 0 if
// variable, 1 if a non-array, else, the
// number of array elements


(Comment added by lindahlb on Mon Sep 27 18:19:57 2004)

Oh, sorry about the code portions. The forums ate the extra lines.




[Previous] [Next] [Post] [Reply] [Topics] [Summary] [Search]