jackrabbit-users mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Stefan Guggisberg <stefan.guggisb...@gmail.com>
Subject Re: Concurrent modifications to a single node
Date Fri, 23 Dec 2011 20:49:07 GMT
hi mat,


On Fri, Dec 23, 2011 at 7:37 PM, Mat Lowery <mlowery@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<mlowery@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);
>>>    }
>>>
>>>  }
>>>
>>> }
>>>
>

Mime
View raw message