On 12/25/11 8:27 PM, Selcuk AYA wrote:
On Sun, Dec 25, 2011 at 8:08 PM, Emmanuel Lécharny<[email protected]>  wrote:
On 12/25/11 5:58 PM, Selcuk AYA wrote:
On Sun, Dec 25, 2011 at 5:37 PM, Emmanuel Lecharny<[email protected]>
  wrote:
Hi,

I started to play with this concept. The idea is to able to have
encapsulated operations using their own transactions, following these
rules
:

1) if there is another pending Read transaction, and if the new operation
is
read only, then reuse the pending transaction
2) if there is another pending Read transaction, and if the new operation
is
ReadWrite, then create a new transaction
3) if there is another ReadWrite transaction, then generate an error (we
can't have such a case)

That means we can have a non limited number of encapsulated RO txns, but
we
can't have more than one RW txn running.

RO(RO(RO...(RO)...))) is possible
RO(RO(RW))) is possible
RO(RO(RW(RO is not possible
RW(RO is not possible
RW(RW is not possible

In order to implement that, we need to add one thing :
- a nbRef in readOnly transactions, which will be incremented and
decremented as soon as we add new RO txns or abort/commit txns

Is that enough ?
this is also a reply to you previous email.

I suggest we use a txn per operation but we do not have to store the
txn context pointer in operation context. We can still have the thread
context stored in thread local variable but we also store a TxnHandle
ref in EntryFilteringCursor. And we do something like this:

next()
{
   get txn handle stored in the cursor and set it as the thread local
variable.
do the next
unset the thread local variable.
}

In fact, as each operation except Search are atomic, I don't know if it's
useful to store the txn in the thread local variable. Regarding the search,
we just have to store the txn in the cursor, so we don't have to store it
into the thread local variable either.

Another reason we might not want to use thread local variable is that an
abandon operation will have to close a txn, and that means grab the txn from
another thread.It's easier to get the existing cursor, and close the cursor.
(FYI, we may have more than one thread per session, just in order to be able
to handle an AbandonRequest)

Unless I'm missing something, of course !
There are different layers and different classes that call into txn
layer and txn layer conveniently gets the current txn from the thread
local variable. If you change this you will have to pass around txn
context. Not impossible but quite a number of changes.
The pb is that if you don't pass teh txn, then you have the reverse issue : switching the threadLocal content each time you call the txn layer. IMO (and after having played around with the code), it's probably better to pass the txn we have stored. I'm still evaluating this option.

But AbondonRequest is really a problem. I see that the abandon request
listener for search just closes the cursor but at that time the txn
might be executing and we cannot just abort an executing txn.

If we consider that abandon requests are just good for Search operations, then what it does is simply to switch a flag in the OperationContext, flag which is tested when the next() method is called :

    public boolean next() throws Exception
    {
        if ( getOperationContext().isAbandoned() )
        {
            LOG.info( "Cursor has been abandoned." );
            close();
            throw new OperationAbandonedException();
        }

As the close() is called, we should be safe here.

More to come later (after the dinner)


--
Regards,
Cordialement,
Emmanuel Lécharny
www.iktek.com

Reply via email to