[ http://issues.apache.org/jira/browse/JCR-336?page=all ]
Jukka Zitting updated JCR-336: ------------------------------ Version: 1.0 > Concurrent locking operations fail > ---------------------------------- > > Key: JCR-336 > URL: http://issues.apache.org/jira/browse/JCR-336 > Project: Jackrabbit > Type: Bug > Components: locks > Versions: 0.9, 1.0 > Environment: r383887 > Reporter: Tobias Bocanegra > Fix For: 1.1 > > 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 -- This message is automatically generated by JIRA. - If you think it was sent incorrectly contact one of the administrators: http://issues.apache.org/jira/secure/Administrators.jspa - For more information on JIRA, see: http://www.atlassian.com/software/jira