Default database / namespace Robert Wittams (robert.wittams@ic.ac.uk)
Mon, 03 Jul 2000 21:20:26 +0100

Hi,

Warning: I may be clueless! Don't flame too hard ;-)

I've been reading about eros and KeyKOS for a few days and I am really excited by the possibilities that eros offers.

I understand that persistence means that a lot of current uses of the filesystem in acl based systems are no longer required. But there are still a lot of situations in which it will be necessary to organise keys & data, and having a unified namespace is a goal towards which most OSs seem to be moving.

Of course as this is not mandated by the eros kernel, any implementation provided is merely a default and can be removed or ignored (by not passing the key to access it to any objects that do not need it).

If an object posseses a write key to the namespace (ie it can bind things in to the namespace), it has a channel to communicate to any other object which can read the namespace. This must be prevented, so, for example, a sandboxed domain which wanted access to *a* namespace can be passed a key to a recently constructed one, or a filtered view of the "old" namespace. The key would obviously need to be explicitly passed in all situations. And most native eros programs would never need a namespace key.

Having been impressed by the ideas presented by Hans Reiser in this paper:
http://devlinux.com/projects/reiserfs/whitepaper.html and also the Microsoft COM/OLE idea of a moniker, I propose that the default namespace of eros be flexible enough to subsume heirarchical, keyword, and relational systems.

Also, it should be possible to stack namespaces, and mount them at any point within each other.

So, the way I think this could be done:

An interface "namespace" with these operations:

	get(query)         - return an object matching a query. May be a set.
	link(query, key)   - add an association into the database for the key. 
	unlink(query, key) - remove an association for the key. 
			     Need both as multiple objects may be linked 
			     to the same criteria. 
	bind(query, key)   - maybe should be called mount? 
			     Key must be to another namespace. any querys which match go into
this namespace for further searching. Any "link" operation will try to link from the top down, on any namespaces which have a write key.

unbind(query, key)

( maybe there needs to be a way to ask which namespaces are bound in currently,

or maybe this comes in the answer to get() ? )

And a set:

length() - returns length of set, or -1 for unknown length (eg from a search that hasn't yet finished)

get(index) - returns a key to an object.

( I don't know whether the set should be able to tell you a name for the object in the database or not...)

Then multiple implementations of this interface can be defined.

So, for example - user logs in. Standard log in stuff brings up their user interface, with their namespace. This is persistent like the rest of eros, so any namespaces previously bound in are still there. So, the user has these things bound:

/desktop/ - from the users desktop manager. also represented by icons
on the screen.
/work/ - a capabilty from her employer, bound in - holds things
worked on by her and colleagues
/encyclopedia - an encyclopedia, bound into the system
/linux - her "legacy" linux filesystem
/accounts - her accounts, held in an RDBMS
/mail - her mail box
/websites/
/websites/imdb - a frontend to the internet movie database
/websites/google - """ to google
/ - a "record" oriented namespace.
/ - a "file" oriented namespace.
/ - a generic namespace. ( for any keys)

and she does these queries:

/linux/usr/local/bin - returns a set which has the contents of that
directory under
linux

/mail/["harry"] - a set of all the mail associated with the word
"harry". Her mail system associates based on mail contents.

["harry"] - a union of all the things in all the namespaces that are associated with harry. Eg her mail, a google search, encyclopedia entries etc.

Anyway, once you have a key out of the namespace, you check the alleged key type, and do what you like with it. I think something like QueryInterface could be very useful here.

So, then she sticks some stuff in the namespace.

She has a key, k1 to a file (it is a stream of bytes) about a recipe. She goes link("/recipes/yumyum", k1)
Then she goes link("[milk cheese flour]", k1) Then link("[ cooking-time/45mins ]", k1)

What happens is that the namespace asks each namespace on / to link it to recipes/yumyum . First it asks the record namespace. The key is not a record, so it
doesn't add it. Next it asks the file namespace. It is a file, so it is
added.

The rest of the links are the same, as the file oriented namespace takes things based on thier alleged type, not on the query.

In this way, efficient storage of things as either records or byte streams can be achieved. And legacy systems can be bolted in too.

The things I am wondering about:

What is the best format for queries? It might not be a character string.

It might be something like a tuple that could be passed in the data section of an eros message. Then a library routine could create this from a string. The advantage of this is that different systems could be supported - eg a windows name parser, a unix name parser, even an SQL parser. eek. Also, elements of the tuples could be other keys. Meaning that parts of names could be arbitrary objects, not just strings. Eg in a record, another record type.

Is there enough difference between a set and a namespace to warrant a seperate interface? It might be best to just return another namespace, then more querying could be done on that.

	How do you optimise for disk and memory usage bearing checkpointing in
mind?	Is this (eg the indexes) something for which explicit
journaling/IO may make sense?

Does some kind of transaction model need to be supported? If so, in what form? It might be best to have another interface for this on record oriented systems. So you do all your heavy database work with transactions via that interface, but it is still possible to add in / view stuff via the namespace interface, which internally would use a transaction for each change.

Hope some of this made sense,
Rob