jackrabbit-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Nicolas Belisle <Nicolas.Beli...@bibl.ulaval.ca>
Subject Re: Problems with concurrent sessions
Date Thu, 14 Jul 2005 19:34:11 GMT
Hi again,

 > You probably want a lock call that is blocking and returns when the lock 
could be retrieved.
 > Locks in jsr-170 were primarily designed to lock nodes for a longer time 
and not just while
 > in a transaction. Maybe a blocking variant of the getLock() method is 
something we should
 > consider for the next jcr version.

I just thought about something like this (Note that I've only done a few 
tests on that class.)  :

import javax.jcr.Credentials;
import javax.jcr.LoginException;
import javax.jcr.Node;
import javax.jcr.Repository;
import javax.jcr.RepositoryException;
import javax.jcr.Session;
import javax.jcr.observation.Event;
import javax.jcr.observation.EventIterator;
import javax.jcr.observation.EventListener;

public abstract class SerializableTemplate {

     private Session session;
     private Node scope;

     public SerializableTemplate(Repository repository, Credentials cr, 
String scopePath) throws LoginException, RepositoryException {
         session = repository.login(cr);
         scope = session.getRootNode().getNode(scopePath);
     }

     public abstract void doInTransaction(Session session);

     public void execute() {
         try {
             if (!scope.isLocked()) {
                 scope.lock(true, true);
                 doInTransaction(session);
                 if (session.isLive()) {
                     session.logout();
                 }
             } else {
                 EventListener el = new EventListener() {
                     public void onEvent(EventIterator events) {
                         try {
                             if (!scope.isLocked()) {
                                 scope.lock(true, true);
                                 doInTransaction(session);
                                 if (session.isLive()) {
                                     session.logout();
                                 }
                             }
                         } catch (Exception e) {
                             throw new RuntimeException(e);
                         }
                     }
                 };
                 session.getWorkspace().getObservationManager().addEventListener(el, 
Event.PROPERTY_REMOVED, scope.getPath(), true, null, null, false);
             }
         } catch (Exception e) {
             throw new RuntimeException(e);
         }
     }
}

I don't like a few things about that class, especially the constructor...

What do you think overall ?

 > Again I think this always depends on the application on top of the 
repository.
 > Setting an isolation level as a global property does not seems to be a 
good idea to me.

Well, if many applications need control of their isolation level, maybe 
that feature should be implemented in one place or documented in a worked 
example...

Regards,

Nicolas



Le 12:34 2005-07-08, vous avez écrit:
>Hi Nicolas,
>
>Nicolas Belisle wrote:
>>  > no, but you may use locks to further control isolation level.
>>There seems to be at least two problems with that approach :
>>- You will get a (unpleasant) javax.jcr.lock.LockException if another 
>>transaction tries to lock the node (or a child).
>
>You probably want a lock call that is blocking and returns when the lock 
>could be retrieved. Locks in jsr-170 were primarily designed to lock nodes 
>for a longer time and not just while in a transaction. Maybe a blocking 
>variant of the getLock() method is something we should consider for the 
>next jcr version.
>
>>- It is not enforced even though it should be used everywhere, even for 
>>only a read.
>
>This depends on the application. I don't think you have to lock the 
>workspace when your applicaton is fine with an read-committed isolation level.
>
>>Sorry there was an error in my example. I should make more sense this way :
>>Example v.2 :
>>A : open session
>>A : read nodes "test" & "test2"
>>B : open session
>>B : delete nodes "test" & "test2"
>>B : save session //WHAT SHOULD HAPPEN ??
>>B : logout
>>A : read nodes "test" & "test2" //WHAT SHOULD HAPPEN ??
>>A : logout
>
>yeah, that definitively makes more sense ;)
>
>deleting the two nodes with Session B will be successful, unless session A 
>has locked the two nodes.
>regarding the second attempt to read the two nodes with session A, this 
>depends whether A already obtained references to the nodes or not.
>
>If A already has reference to those two nodes, calles that read the state 
>of those nodes will throw an InvalidItemStateException. Indicating that 
>the nodes do not exist anymore.
>
>If A tries to retrieve the nodes again. E.g. by calling getNodes() on the 
>parent of the just deleted nodes. The returned NodeIterator will simply 
>not contain the nodes anymore.
>
>>It would be useful if the isolation level could configured at the 
>>repository level. So if your application needs better isolation or 
>>performance you would only need to change the configuration and not your code.
>
>Again I think this always depends on the application on top of the 
>repository. Setting an isolation level as a global property does not seems 
>to be a good idea to me.
>
>>An implementation could (hypothetically) use locks in SessionImpl and use 
>>events (when a session saves/logout) to prevent throwing exceptions. A 
>>queue would hold pending operations. However, we would have to be careful 
>>about long lived sessions...
>
>I'm sorry, I cannot follow you here...
>
>regards
>  marcel


Mime
View raw message