Andy,
I have not read trough the links in your last post yet but thought I might
answer the questions you posed as per my thoughts prior to reading those
posts. (concepts subject to change)
> As I understand it, the application is now involved to describe the part
> of the graph to lock. Is that right?
>
That was my thought yes. I was only looking at how to lock for write. I
had not considered read locking, though I expected it would work like the
current lock does in the sense that read locks block write locks. Though I
suppose it might be possible in some situations to specify what the thread
was going to read.
>
> To check here - locks are held for a critical section (as current design)?
> Not a single API call? Something else?
>
> The permissions system is per API call but then permissions are not
> changing like data is on a live system.
>
>
I was thinking that they would be held for a critical section only as
currently done.
I agree there are significant distinctions between the permissions and
locking as the permissions data does not change within a single call.
>
> Does failure mean an exception or waiting?
>
>
My thought was failure/exception. As you point out waiting leads to
deadlock issues. However, the decision to wait or fail could be
implemented outside of the engine that determines if the lock can be
granted. So it could be a plugable decision. For the first cut I would
simply implement failure.
But looking at the enterCriticalSection() code I see that it does not allow
failure, but that there is a mention of an error if a read lock is promoted
to a write lock. I am unsure how to handle this case. I think that a lock
failure exception may be needed.
A possible solution is to delay and retry with a retry time out/limit
before throwing a timeout type exception. This area needs work.
>
> These tests themselves have to be done by some synchronized code becaue
> there are multiple tests while other threads may be changing things at the
> same time.
>
>
agreed. The internals of the locking code need synchronization.
> How far back are you going to wind back to? In a transaction system either
> the transaction is aborted (so all the way back); some system retry (i.e.
> rerun application code).
>
I had assumed that the application would lock all the triples it needed at
the start of the lock. this is supposed to be a small critical section.
However, I can see how nested class method calls might cause multiple locks.
So lets assume code execution like:
{noformat}
{
try {
Lock( <foo ANY ANY> )
// some processing here
try {
Lock( <bar ANY ANY >)
// some processing here
} catch (LockFailedException e) {
// handle "bar" lock failure
} finally {
Unlock( <bar ANY ANY > )
}
} catch (LockFailedException e ) {
// handle "foo" lock failure
} finally {
Unlock( <foo, ANY ANY > )
}
// for grins ;)
Unlock(); // release all held locks.
}
{noformat}
The partial solution is to require lock ordering - locks must be acquired
> in the same order and same class - and for a sequence of operations, not
> just a single access.
>
> The application is now involved - this is a specialized programming model
> for the ability to have multiple writers.
>
If we consider the lock request to be a set of patterns then then the lock
itself holds a set of patterns. For example Lock( <foo ANY ANY> <bar ANY
ANY ) would create a lock holding the fooAny and barAny triples.
Subsequently calling Lock( <baz, ANY ANY> ) would result in the set: <foo
ANY ANY> <bar ANY ANY> <baz ANY ANY>. calling Unlock( <bar ANY ANY> )
would result in the set: <foo ANY ANY> <bar ANY ANY>.
So locks for a single thread do not need to be released in the order they
were acquired. But all the locks must be released when the critical
section exits.
> It would be a good thing to have as an additional choice of graph (ideally
> dataset) implementation. A multi-writer dataset, then just make graph
> views of the dataset, would great to have.
>
> Is it easy to build an experimental version using the permissions code?
>
> Andy
>
>
I'm not sure how much of the permissions code would be applicable. It uses
dynamic proxies to intercept graph and model (and assorted helper classes)
method calls.
I think the locking engine is more likely like a query engine
implementation having to do pattern matching on sets of triples.
I think that the starting place may be to extend the Lock interface to
include:
enterCriticalSection( triple .... ); // establish a lock for the triples
Graph getLockPattern(); // get the lock pattern
void lock( triple ... ); // add to lock pattern
void unlock( triple ...); // remove from lock pattern
void unlock(); // remove all locks
It might make more sense to put the last 4 into a separate interface and
have a method to return an instance of that interface. Something like:
LockHoldings getLocks();
It seems to me the complex part is going to be determining if any thread
already has the a lock on the object from the patterns. I can dig into
that to see if I can get an early prototype of lock tracking.
Claude
--
I like: Like Like - The likeliest place on the web
<http://like-like.xenei.com>
LinkedIn: http://www.linkedin.com/in/claudewarren