[e-lang] Alternative persistence system

Thomas Leonard tal at it-innovation.soton.ac.uk
Mon Oct 12 11:04:53 EDT 2009


On Mon, 2009-10-12 at 09:25 -0400, Kevin Reid wrote:
> On Oct 12, 2009, at 5:58, Thomas Leonard wrote:
[...]
> > 1. Scalability: The system does not scale well. When an object's state
> > changes, the entire object graph has to be written out, which takes  
> > time
> > proportional to the number of objects in the system (roughly 10 ms per
> > object on my machine), not to the number of changes. Fixing this  
> > would,
> > presumably, require making each persistent object's representation be
> > independent of that of all other persistent objects. Ideally, I'd like
> > to save after creating every persistent object, before giving the  
> > sturdy
> > ref to the user. I expect to be creating many such objects per  
> > second in
> > some cases.
> 
> This is an efficiency problem; E-on-Java is just not very fast at  
> executing E code, which includes the implementation of the persistence  
> subsystem.

It's not so much the speed (although that's not great), it's that it
doesn't scale up if I have e.g. thousands of objects or more (which
doesn't seem unreasonable). I'll probably want to save each object as a
row in a database at some point.

> Due to E's requirements for consistency on revival, an entire vat  
> *must* be persisted as a unit. (Of course, if an application such as  
> yours has weaker requirements you can use an alternate system.)

I had to violate this anyway, because my application allows users to
upload large files, which get stored in the file-system, not in memory.
In this case, snapshots make things worse, because an infrequent
snapshot is less likely to match the rest of the saved state.

e.g. if I revoke someone's access to a storage area and then upload
confidential data and then the server crashes, it will revive with them
still having access to the file. If saving was fast, the storage area
object could ensure that the revocation was saved before returning.

I'll probably need to put logs and usage data in the file-system too.

For some applications you may need to snapshot the whole state, but the
scheme below doesn't prevent that (and in fact the current version does
snapshot everything at once). But I think there must be a large set of
applications where this is not useful.

> > 2. Redundant information:
[...]
> The repeated references are necessary to preserve capability security.  
> However, if an object needs multiple authorities, say 'timer' and  
> 'stdout', then one thing you can do is have it persist as a reference  
> to a bundle of them:
> 
> def jobAuthority { # which is an exit or gotten from some loader
>    to timer() { return timer }
>    to stdout() { return stdout }
> }

Using a loader would conflict with (1), and allowing modules to call
surgeon.addExit didn't look safe (what if one module replaces another
module's exit?).

> > 6. Too many code paths:
[...]
> The "revive" operation *should*, when possible, be the same as the  
> "create" operation. Exceptions should be reviewed with suspicion.

Anything with a default state seems to be an exception. Either you get
the user to provide your default state (as a mutable object), or you
need separate methods. Admittedly, the create operation should normally
call the revive one internally.

> Makers-for-revival *are* part of the public API because as soon as  
> your app is deployed, people have saved data which uses those  
> interfaces.

True, but if I know that the only callers are previous versions of my
own code then providing an upgrade path is easier.

> > A possible solution
> ...

Thanks for looking at this. I want to make sure I've got a reasonable
system.

> I suspect that your solution is, in general, able to work more  
> straightforwardly *for your application* because you have additional  
> constraints:
> 
>    1. Your objects are arranged in a hierarchy.

Yes. Although you could regard E's current system as a special case of
this: a simple two-level hierarchy with all objects being children of
the SturdyRefMaker (in myOptSwissRetainers), and with a load function
that adds no authority.

>    2. You have no objects with which your application is mutually  
> suspicious.

I don't think that's the case, except that an object always trusts its
creator (there's not much you can do about that, after all). But objects
don't trust their children, in general, or other objects.

> To expand on the second point, your scheme of reviving objects with  
> authority based on their parents would fail dangerously if the child  
> object was not actually one of yours, but something which did not have  
> that authority in the previous incarnation and now gets it.

How can the child not be one of mine? The parent tells the persistence
system how to revive the child, e.g.

def makeChatServer(timer) {
        return def chatServer {
                to makePublic(persistNode) {
                        return def chatServerPub {
                                to createChatRoom(name) {
                                        require(validRoomName(name))
                                        return persistNode.makeSturdyChild("loadChatRoom", [name])
                                }
                        }
                }

                to loadChatRoom(name) {
                        return makeChatRoom(name, timer, <file:rooms>[name])
                }
        }
}

The only children of persistNode are those added by createChatRoom
(since that's the only thing with access to
persistNode.makeSturdyChild), and they're created by loadChatRoom.

Each chatRoom will get its own persistNode; it can't add more children
to the chatServer and it can't change the name of the load function (if
the persisted argument "name" was a mutable object then it could change
that, because we pass it to makeChatRoom).

> I don't know your real persistence infrastructure, so I can't say  
> whether this actually makes sense, but that is the general form of my  
> suspicion: that you have something which is easier to use, but either  
> less powerful or unsafe-given-untrusted-code (depending on the details).

I'd certainly like to make sure that it isn't less safe.


-- 
Dr Thomas Leonard
IT Innovation Centre
2 Venture Road
Southampton
Hampshire SO16 7NP

Tel: +44 0 23 8076 0834
Fax: +44 0 23 8076 0833
mailto:tal at it-innovation.soton.ac.uk
http://www.it-innovation.soton.ac.uk 



More information about the e-lang mailing list