hi mat,
On Fri, Dec 23, 2011 at 7:37 PM, Mat Lowery <mlow...@pentaho.com> wrote: > I had to run the test code on 2.3.4 many times before I got the > ConcurrentModificationException. I was not able to get a > org.apache.jackrabbit.core.state.ItemStateException or > javax.jcr.InvalidItemStateException on that version. a ConcurrentModificationException would obviously be a bug. it seems to be difficult to reproduce however, i didn't see it in 20 runs. please post a jira issue and include the full stack trace and the test case. > > While I understand that the 1.6 branch is no longer maintained, I would like > to be sure that I understand correct JCR behavior. Is it a bug in 1.6.x > that the org.apache.jackrabbit.core.state.ItemStateExceptions are occurring > or that they are being wrapped with a javax.jcr.RepositoryException rather > than a javax.jcr.InvalidItemStateException? the test should succeed without throwing any exceptions. the concurrent changes are non-conflicting and should be merged silently. the ItemStateException "... has been removed, but is not present in the changelog" seems to indicate corrupted session-local state caused by concurrent node modifications. that would be a bug. cheers stefan > A sample 1.6.5 full stack is: > > javax.jcr.RepositoryException: Unable to update item: node /: Child node > entry with id 04afd8db-6515-4997-ac4e-83f066e39f53 has been removed, but is > not present in the changelog: Child node entry with id > 04afd8db-6515-4997-ac4e-83f066e39f53 has been removed, but is not present in > the changelog > at org.apache.jackrabbit.core.ItemImpl.save(ItemImpl.java:1134) > at org.apache.jackrabbit.core.SessionImpl.save(SessionImpl.java:915) > at test.JackrabbitTest$1.run(JackrabbitTest.java:38) > at > java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886) > at > java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908) > at java.lang.Thread.run(Thread.java:662) > Caused by: org.apache.jackrabbit.core.state.ItemStateException: Child node > entry with id 04afd8db-6515-4997-ac4e-83f066e39f53 has been removed, but is > not present in the changelog > at > org.apache.jackrabbit.core.state.SharedItemStateManager.validateModified(SharedItemStateManager.java:1383) > at > org.apache.jackrabbit.core.state.SharedItemStateManager.validateHierarchy(SharedItemStateManager.java:1150) > at > org.apache.jackrabbit.core.state.SharedItemStateManager.access$1100(SharedItemStateManager.java:116) > at > org.apache.jackrabbit.core.state.SharedItemStateManager$Update.begin(SharedItemStateManager.java:717) > at > org.apache.jackrabbit.core.state.SharedItemStateManager.beginUpdate(SharedItemStateManager.java:1473) > at > org.apache.jackrabbit.core.state.SharedItemStateManager.update(SharedItemStateManager.java:1503) > at > org.apache.jackrabbit.core.state.LocalItemStateManager.update(LocalItemStateManager.java:351) > at > org.apache.jackrabbit.core.state.XAItemStateManager.update(XAItemStateManager.java:354) > at > org.apache.jackrabbit.core.state.LocalItemStateManager.update(LocalItemStateManager.java:326) > at > org.apache.jackrabbit.core.state.SessionItemStateManager.update(SessionItemStateManager.java:326) > at org.apache.jackrabbit.core.ItemImpl.save(ItemImpl.java:1128) > ... 5 more > > org.apache.jackrabbit.core.state.ItemStateException: Child node entry with > id 04afd8db-6515-4997-ac4e-83f066e39f53 has been removed, but is not present > in the changelog > at > org.apache.jackrabbit.core.state.SharedItemStateManager.validateModified(SharedItemStateManager.java:1383) > at > org.apache.jackrabbit.core.state.SharedItemStateManager.validateHierarchy(SharedItemStateManager.java:1150) > at > org.apache.jackrabbit.core.state.SharedItemStateManager.access$1100(SharedItemStateManager.java:116) > at > org.apache.jackrabbit.core.state.SharedItemStateManager$Update.begin(SharedItemStateManager.java:717) > at > org.apache.jackrabbit.core.state.SharedItemStateManager.beginUpdate(SharedItemStateManager.java:1473) > at > org.apache.jackrabbit.core.state.SharedItemStateManager.update(SharedItemStateManager.java:1503) > at > org.apache.jackrabbit.core.state.LocalItemStateManager.update(LocalItemStateManager.java:351) > at > org.apache.jackrabbit.core.state.XAItemStateManager.update(XAItemStateManager.java:354) > at > org.apache.jackrabbit.core.state.LocalItemStateManager.update(LocalItemStateManager.java:326) > at > org.apache.jackrabbit.core.state.SessionItemStateManager.update(SessionItemStateManager.java:326) > at org.apache.jackrabbit.core.ItemImpl.save(ItemImpl.java:1128) > at org.apache.jackrabbit.core.SessionImpl.save(SessionImpl.java:915) > at test.JackrabbitTest$1.run(JackrabbitTest.java:38) > at > java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886) > at > java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908) > at java.lang.Thread.run(Thread.java:662) > > Thanks! > > > On 12/22/2011 03:46 PM, Stefan Guggisberg wrote: >> >> On Thu, Dec 22, 2011 at 8:39 PM, Mat Lowery<mlow...@pentaho.com> wrote: >>> >>> My understanding of concurrent modifications is that I can receive an >>> InvalidItemStateException if I have a stale view of the repository when >>> my >>> session is saved or my transaction is committed. However, I can get >>> other >>> exceptions using the code below. Furthermore, I thought Jackrabbit would >>> allow concurrent child node additions to a single node given the child >>> node >>> names were unique. >> >> correct >> >>> So I wasn't even expecting an InvalidItemStateException >>> for the code below. >>> >>> I understand that locking can prevent the InvalidItemStateException but >>> I'm >>> using transactions and committing the transaction for the sole purpose of >>> exposing a lock is something I'd like to avoid at this time. I'd like to >>> just catch the InvalidItemStateException and alert the user with a >>> friendly >>> message. >>> >>> Why do I get the given exceptions for the given code? I can supply full >>> stacks if necessary; for now, just the class and error message are shown. >> >> strange. i ran your test 20 times in a row on my macbook pro (os-x >> 10.7, java 6) >> against the current head (svn r1222443). none of the runs failed. >> >> cheers >> stefan >> >>> Jackrabbit 1.6.0: >>> * org.apache.jackrabbit.core.state.ItemStateException: there's already a >>> property state instance with id >>> >>> 243f6e39-7a3e-4d48-b051-9b4198a6a16b/{http://www.jcp.org/jcr/1.0}primaryType >>> * javax.jcr.InvalidItemStateException: Item cannot be saved because it >>> has >>> been modified externally: node / >>> * javax.jcr.InvalidItemStateException: node /: the node cannot be saved >>> because it has been modified externally. >>> >>> Jackrabbit 1.6.5: >>> * javax.jcr.InvalidItemStateException: node /: the node cannot be saved >>> because it has been modified externally. >>> * javax.jcr.InvalidItemStateException: Item cannot be saved because it >>> has >>> been modified externally: node / >>> * org.apache.jackrabbit.core.state.ItemStateException: Child node entry >>> with >>> id 04afd8db-6515-4997-ac4e-83f066e39f53 has been removed, but is not >>> present >>> in the changelog >>> >>> Jackrabbit 2.3.4: >>> * java.util.ConcurrentModificationException >>> at java.util.WeakHashMap$HashIterator.nextEntry(WeakHashMap.java:762) >>> at java.util.WeakHashMap$KeyIterator.next(WeakHashMap.java:795) >>> at >>> >>> org.apache.jackrabbit.core.cache.CacheManager.logCacheStats(CacheManager.java:164) >>> >>> package test; >>> >>> import java.io.File; >>> import java.util.concurrent.ExecutorService; >>> import java.util.concurrent.Executors; >>> import java.util.concurrent.TimeUnit; >>> import java.util.concurrent.atomic.AtomicBoolean; >>> import java.util.concurrent.atomic.AtomicInteger; >>> >>> import javax.jcr.Repository; >>> import javax.jcr.RepositoryException; >>> import javax.jcr.Session; >>> import javax.jcr.SimpleCredentials; >>> >>> import org.apache.jackrabbit.core.TransientRepository; >>> >>> public class JackrabbitTest { >>> >>> public static void main(final String[] args) throws Exception { >>> File dir = File.createTempFile("jackrabbit-test", ""); >>> dir.delete(); >>> dir.mkdir(); >>> System.out.println("created temporary directory: " + >>> dir.getAbsolutePath()); >>> dir.deleteOnExit(); >>> >>> final Repository jcrRepo = new TransientRepository(dir); >>> final AtomicBoolean passed = new AtomicBoolean(true); >>> final AtomicInteger counter = new AtomicInteger(0); >>> ExecutorService executor = Executors.newFixedThreadPool(50); >>> Runnable runnable = new Runnable() { >>> >>> @Override >>> public void run() { >>> try { >>> Session session = jcrRepo.login( >>> new SimpleCredentials("admin", >>> "admin".toCharArray())); >>> session.getRootNode().addNode("n" + >>> counter.getAndIncrement()); //unique name >>> session.save(); >>> session.logout(); >>> } catch (RepositoryException e) { >>> e.printStackTrace(); >>> passed.set(false); >>> } >>> } >>> >>> }; >>> System.out.println("Running threads"); >>> for (int i = 0; i< 500; i++) { >>> executor.execute(runnable); >>> } >>> executor.shutdown(); //Disable new tasks from being submitted >>> if (!executor.awaitTermination(120, TimeUnit.SECONDS)) { >>> System.err.println("timeout"); >>> System.exit(1); >>> } >>> if (!passed.get()) { >>> System.err.println("one or more threads got an exception"); >>> System.exit(1); >>> } else { >>> System.out.println("all threads ran with no exceptions"); >>> System.exit(0); >>> } >>> >>> } >>> >>> } >>> >