You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@jackrabbit.apache.org by Przemyslaw Pakulski <pr...@cognifide.com> on 2006/03/07 16:12:42 UTC

Concurrent locking operations fail

Hi,

I prepared simple test which tries to lock/unlock single node from many 
threads. I expected only LockExceptions thrown by some threads which can 
occur if node is already locked by other thread.

But I get incorrect effect sporadically. It looks like some thread 
managed to acquire lock, but then can't release it.

Following exception is thrown then :

javax.jcr.InvalidItemStateException: 
7c198c7b-76c8-47c8-96a8-d9dfefd4b387 has been modified externally
     at org.apache.jackrabbit.core.ItemImpl.save(ItemImpl.java:1193)
     at org.apache.jackrabbit.core.NodeImpl.unlock(NodeImpl.java:3790)
     at JrTestConcurrentLocks.run(JrTestConcurrentLocks.java:95)

additionally warning appears in log

org.apache.jackrabbit.core.lock.LockManagerImpl$LockInfo.loggingOut(LockManagerImpl.java:892) 
- Unable to unlock session-scoped lock on node 
'7c198c7b-76c8-47c8-96a8-d9dfefd4b387-W': Unable to unlock node. Node 
has pending changes: /folder

In consequence node is left in locked state. It looks like a bug.
If one thread locked node successfully, then none other can modify it, 
and the same thread should release lock without any problems.

Shouldn't be lock operation atomic itself ?

Przemo

Re: Concurrent locking operations fail

Posted by Tobias Bocanegra <to...@day.com>.
hi przemo.
thanx for reporting this. i created a jira issue for this:
http://issues.apache.org/jira/browse/JCR-336

regards, toby

On 3/7/06, Przemyslaw Pakulski <pr...@cognifide.com> wrote:
> Hi,
>
> I prepared simple test which tries to lock/unlock single node from many
> threads. I expected only LockExceptions thrown by some threads which can
> occur if node is already locked by other thread.
>
> But I get incorrect effect sporadically. It looks like some thread
> managed to acquire lock, but then can't release it.
>
> Following exception is thrown then :
>
> javax.jcr.InvalidItemStateException:
> 7c198c7b-76c8-47c8-96a8-d9dfefd4b387 has been modified externally
>      at org.apache.jackrabbit.core.ItemImpl.save(ItemImpl.java:1193)
>      at org.apache.jackrabbit.core.NodeImpl.unlock(NodeImpl.java:3790)
>      at JrTestConcurrentLocks.run(JrTestConcurrentLocks.java:95)
>
> additionally warning appears in log
>
> org.apache.jackrabbit.core.lock.LockManagerImpl$LockInfo.loggingOut(LockManagerImpl.java:892)
> - Unable to unlock session-scoped lock on node
> '7c198c7b-76c8-47c8-96a8-d9dfefd4b387-W': Unable to unlock node. Node
> has pending changes: /folder
>
> In consequence node is left in locked state. It looks like a bug.
> If one thread locked node successfully, then none other can modify it,
> and the same thread should release lock without any problems.
>
> Shouldn't be lock operation atomic itself ?
>
> Przemo
>
>
> package com.oyster.mom.contentserver.jcr.transaction;
>
> import javax.jcr.Node;
> import javax.jcr.RepositoryException;
> import javax.jcr.Session;
> import javax.jcr.SimpleCredentials;
> import javax.jcr.lock.LockException;
>
> import org.apache.jackrabbit.core.RepositoryImpl;
> import org.apache.jackrabbit.core.config.RepositoryConfig;
>
> public class JrTestConcurrentLocks extends Thread {
>
>     private static final org.apache.commons.logging.Log log = org.apache.commons.logging.LogFactory.getLog(JrTestConcurrentLocks.class);
>
>     public static String REPOSITORY_HOME = "d:/repo/jackrabbit/";
>
>     public static String REPOSITORY_CONFIG = REPOSITORY_HOME + "repository.xml";
>
>     public static void main(String[] args) throws Exception {
>
>         JrTestConcurrentLocks test = new JrTestConcurrentLocks(-1);
>         test.startup();
>
>         JrTestConcurrentLocks tests[] = new JrTestConcurrentLocks[3];
>
>         for (int i = 0; i < tests.length; i++) {
>             JrTestConcurrentLocks x = new JrTestConcurrentLocks(i);
>             x.setSession(repository.login(new SimpleCredentials("admin", "admin".toCharArray())));
>             x.start();
>             tests[i] = x;
>         }
>
>         for (int i = 0; i < tests.length; i++) {
>             tests[i].join();
>             tests[i].getSession().logout();
>         }
>
>         test.shutdown();
>     }
>
>     private static RepositoryImpl repository;
>
>     private int id;
>
>     private Session session;
>
>     public void setSession(Session session) {
>         this.session = session;
>     }
>
>     public Session getSession() {
>         return this.session;
>     }
>
>     public JrTestConcurrentLocks(int i) {
>         this.id = i;
>     }
>
>     public void startup() throws Exception {
>         System.setProperty("java.security.auth.login.config", "c:/jaas.config");
>
>         RepositoryConfig config = RepositoryConfig.create(REPOSITORY_CONFIG, REPOSITORY_HOME);
>         repository = RepositoryImpl.create(config);
>
>         Session session = repository.login(new SimpleCredentials("admin", "admin".toCharArray()));
>         Node rootNode = session.getRootNode();
>         if (!rootNode.hasNode("folder")) {
>             Node folder = rootNode.addNode("folder");
>             folder.addMixin("mix:versionable");
>             folder.addMixin("mix:lockable");
>             rootNode.save();
>         }
>         session.logout();
>     }
>
>     public void shutdown() throws RepositoryException {
>         repository.shutdown();
>     }
>
>     public Node getFolder(Session session) throws RepositoryException {
>         return session.getRootNode().getNode("folder");
>     }
>
>     public void run() {
>
>         for (int i = 0; i < 10; i++) {
>             log.info("START id:" + id + ", i=" + i);
>
>             try {
>                 session.refresh(false);
>
>                 Node folder = getFolder(session);
>                 folder.lock(false, true);
>                 folder.unlock();
>
>                 log.info("SUCCESS id:" + id + ", i=" + i);
>             }
>             catch (LockException e) {
>                 log.info("FAIL:" + id + ", i=" + i);
>             }
>             catch (Exception e) {
>                 log.warn("ERROR:" + id + ", i=" + i, e);
>             }
>
>
>         }
>
>     }
> }
>
>
> 15:46:17 INFO  JrTestConcurrentLocks.run(JrTestConcurrentLocks.java:88) - START id:0, i=0
> 15:46:17 INFO  JrTestConcurrentLocks.run(JrTestConcurrentLocks.java:88) - START id:1, i=0
> 15:46:17 INFO  JrTestConcurrentLocks.run(JrTestConcurrentLocks.java:88) - START id:2, i=0
> 15:46:17 INFO  JrTestConcurrentLocks.run(JrTestConcurrentLocks.java:100) - FAIL:0, i=0
> 15:46:17 INFO  JrTestConcurrentLocks.run(JrTestConcurrentLocks.java:88) - START id:0, i=1
> 15:46:17 INFO  JrTestConcurrentLocks.run(JrTestConcurrentLocks.java:100) - FAIL:0, i=1
> 15:46:17 INFO  JrTestConcurrentLocks.run(JrTestConcurrentLocks.java:100) - FAIL:1, i=0
> 15:46:17 INFO  JrTestConcurrentLocks.run(JrTestConcurrentLocks.java:88) - START id:1, i=1
> 15:46:17 INFO  JrTestConcurrentLocks.run(JrTestConcurrentLocks.java:100) - FAIL:1, i=1
> 15:46:17 INFO  JrTestConcurrentLocks.run(JrTestConcurrentLocks.java:88) - START id:1, i=2
> 15:46:17 INFO  JrTestConcurrentLocks.run(JrTestConcurrentLocks.java:100) - FAIL:1, i=2
> 15:46:17 INFO  JrTestConcurrentLocks.run(JrTestConcurrentLocks.java:88) - START id:1, i=3
> 15:46:17 INFO  JrTestConcurrentLocks.run(JrTestConcurrentLocks.java:100) - FAIL:1, i=3
> 15:46:17 INFO  JrTestConcurrentLocks.run(JrTestConcurrentLocks.java:88) - START id:1, i=4
> 15:46:17 INFO  JrTestConcurrentLocks.run(JrTestConcurrentLocks.java:88) - START id:0, i=2
> 15:46:17 INFO  JrTestConcurrentLocks.run(JrTestConcurrentLocks.java:100) - FAIL:0, i=2
> 15:46:17 INFO  JrTestConcurrentLocks.run(JrTestConcurrentLocks.java:88) - START id:0, i=3
> 15:46:17 INFO  JrTestConcurrentLocks.run(JrTestConcurrentLocks.java:100) - FAIL:0, i=3
> 15:46:17 INFO  JrTestConcurrentLocks.run(JrTestConcurrentLocks.java:88) - START id:0, i=4
> 15:46:17 INFO  JrTestConcurrentLocks.run(JrTestConcurrentLocks.java:100) - FAIL:0, i=4
> 15:46:17 INFO  JrTestConcurrentLocks.run(JrTestConcurrentLocks.java:88) - START id:0, i=5
> 15:46:17 INFO  JrTestConcurrentLocks.run(JrTestConcurrentLocks.java:97) - SUCCESS id:1, i=4
> 15:46:17 WARN  JrTestConcurrentLocks.run(JrTestConcurrentLocks.java:103) - ERROR:0, i=5
> javax.jcr.ItemNotFoundException: 7c198c7b-76c8-47c8-96a8-d9dfefd4b387/{http://www.jcp.org/jcr/1.0}lockOwner
>         at org.apache.jackrabbit.core.ItemManager.createItemInstance(ItemManager.java:463)
>         at org.apache.jackrabbit.core.ItemManager.getItem(ItemManager.java:319)
>         at org.apache.jackrabbit.core.NodeImpl.getProperty(NodeImpl.java:1436)
>         at org.apache.jackrabbit.core.NodeImpl.getOrCreateProperty(NodeImpl.java:428)
>         at org.apache.jackrabbit.core.NodeImpl.internalSetProperty(NodeImpl.java:1267)
>         at org.apache.jackrabbit.core.NodeImpl.lock(NodeImpl.java:3740)
>         at JrTestConcurrentLocks.run(JrTestConcurrentLocks.java:94)
> 15:46:17 WARN  JrTestConcurrentLocks.run(JrTestConcurrentLocks.java:103) - ERROR:2, i=0
> javax.jcr.InvalidItemStateException: 7c198c7b-76c8-47c8-96a8-d9dfefd4b387 has been modified externally
>         at org.apache.jackrabbit.core.ItemImpl.save(ItemImpl.java:1193)
>         at org.apache.jackrabbit.core.NodeImpl.unlock(NodeImpl.java:3790)
>         at JrTestConcurrentLocks.run(JrTestConcurrentLocks.java:95)
> 15:46:17 INFO  JrTestConcurrentLocks.run(JrTestConcurrentLocks.java:88) - START id:1, i=5
> 15:46:18 INFO  JrTestConcurrentLocks.run(JrTestConcurrentLocks.java:88) - START id:0, i=6
> 15:46:18 INFO  JrTestConcurrentLocks.run(JrTestConcurrentLocks.java:88) - START id:2, i=1
> 15:46:18 INFO  JrTestConcurrentLocks.run(JrTestConcurrentLocks.java:100) - FAIL:1, i=5
> 15:46:18 INFO  JrTestConcurrentLocks.run(JrTestConcurrentLocks.java:100) - FAIL:0, i=6
> 15:46:18 INFO  JrTestConcurrentLocks.run(JrTestConcurrentLocks.java:100) - FAIL:2, i=1
> 15:46:18 INFO  JrTestConcurrentLocks.run(JrTestConcurrentLocks.java:88) - START id:1, i=6
> 15:46:18 INFO  JrTestConcurrentLocks.run(JrTestConcurrentLocks.java:88) - START id:0, i=7
> 15:46:18 INFO  JrTestConcurrentLocks.run(JrTestConcurrentLocks.java:88) - START id:2, i=2
> 15:46:18 INFO  JrTestConcurrentLocks.run(JrTestConcurrentLocks.java:100) - FAIL:1, i=6
> 15:46:18 INFO  JrTestConcurrentLocks.run(JrTestConcurrentLocks.java:100) - FAIL:0, i=7
> 15:46:18 INFO  JrTestConcurrentLocks.run(JrTestConcurrentLocks.java:100) - FAIL:2, i=2
> 15:46:18 INFO  JrTestConcurrentLocks.run(JrTestConcurrentLocks.java:88) - START id:1, i=7
> 15:46:18 INFO  JrTestConcurrentLocks.run(JrTestConcurrentLocks.java:88) - START id:0, i=8
> 15:46:18 INFO  JrTestConcurrentLocks.run(JrTestConcurrentLocks.java:88) - START id:2, i=3
> 15:46:18 INFO  JrTestConcurrentLocks.run(JrTestConcurrentLocks.java:100) - FAIL:1, i=7
> 15:46:18 INFO  JrTestConcurrentLocks.run(JrTestConcurrentLocks.java:100) - FAIL:0, i=8
> 15:46:18 INFO  JrTestConcurrentLocks.run(JrTestConcurrentLocks.java:100) - FAIL:2, i=3
> 15:46:18 INFO  JrTestConcurrentLocks.run(JrTestConcurrentLocks.java:88) - START id:1, i=8
> 15:46:18 INFO  JrTestConcurrentLocks.run(JrTestConcurrentLocks.java:88) - START id:0, i=9
> 15:46:18 INFO  JrTestConcurrentLocks.run(JrTestConcurrentLocks.java:88) - START id:2, i=4
> 15:46:18 INFO  JrTestConcurrentLocks.run(JrTestConcurrentLocks.java:100) - FAIL:1, i=8
> 15:46:18 INFO  JrTestConcurrentLocks.run(JrTestConcurrentLocks.java:100) - FAIL:0, i=9
> 15:46:18 INFO  JrTestConcurrentLocks.run(JrTestConcurrentLocks.java:100) - FAIL:2, i=4
> 15:46:18 INFO  JrTestConcurrentLocks.run(JrTestConcurrentLocks.java:88) - START id:1, i=9
> 15:46:18 INFO  JrTestConcurrentLocks.run(JrTestConcurrentLocks.java:88) - START id:2, i=5
> 15:46:18 INFO  JrTestConcurrentLocks.run(JrTestConcurrentLocks.java:100) - FAIL:2, i=5
> 15:46:18 INFO  JrTestConcurrentLocks.run(JrTestConcurrentLocks.java:88) - START id:2, i=6
> 15:46:18 WARN  JrTestConcurrentLocks.run(JrTestConcurrentLocks.java:103) - ERROR:1, i=9
> javax.jcr.InvalidItemStateException: /folder: the node cannot be saved because it has been modified externally.
>         at org.apache.jackrabbit.core.NodeImpl.makePersistent(NodeImpl.java:908)
>         at org.apache.jackrabbit.core.ItemImpl.persistTransientItems(ItemImpl.java:682)
>         at org.apache.jackrabbit.core.ItemImpl.save(ItemImpl.java:1173)
>         at org.apache.jackrabbit.core.NodeImpl.lock(NodeImpl.java:3744)
>         at JrTestConcurrentLocks.run(JrTestConcurrentLocks.java:94)
> 15:46:18 INFO  JrTestConcurrentLocks.run(JrTestConcurrentLocks.java:100) - FAIL:2, i=6
> 15:46:18 WARN  org.apache.jackrabbit.core.lock.LockManagerImpl$LockInfo.loggingOut(LockManagerImpl.java:892) - Unable to unlock session-scoped lock on node '7c198c7b-76c8-47c8-96a8-d9dfefd4b387-W': Unable to unlock node. Node has pending changes: /folder
> 15:46:18 INFO  JrTestConcurrentLocks.run(JrTestConcurrentLocks.java:88) - START id:2, i=7
> 15:46:18 INFO  JrTestConcurrentLocks.run(JrTestConcurrentLocks.java:100) - FAIL:2, i=7
> 15:46:18 INFO  JrTestConcurrentLocks.run(JrTestConcurrentLocks.java:88) - START id:2, i=8
> 15:46:18 INFO  JrTestConcurrentLocks.run(JrTestConcurrentLocks.java:100) - FAIL:2, i=8
> 15:46:18 INFO  JrTestConcurrentLocks.run(JrTestConcurrentLocks.java:88) - START id:2, i=9
> 15:46:18 INFO  JrTestConcurrentLocks.run(JrTestConcurrentLocks.java:100) - FAIL:2, i=9
>
>
>


--
-----------------------------------------< tobias.bocanegra@day.com >---
Tobias Bocanegra, Day Management AG, Barfuesserplatz 6, CH - 4001 Basel
T +41 61 226 98 98, F +41 61 226 98 97
-----------------------------------------------< http://www.day.com >---