You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@jackrabbit.apache.org by Eugeny N Dzhurinsky <eu...@jdevelop.com> on 2005/10/20 13:40:11 UTC

Multithreading/Mutliuser(?) access

Hello, I tried to make some tests when operating with same repository from the
same session with several threads (modifying the same attribute of the same
node), and I seem to fall in problems. First of all, I'm generating test
repository, and then I start 10 threads to modify property "test" of the node
/random/node1_3/node2_3. It seem to modify this path propertly,but after
session is saved and invalidated, when i'm trying to get the node, it produces

[java] DEBUG 20/23/05 02:23:38 [main] (JCRTest:279) - Exitting with thread 34
     [java] ERROR 20/23/05 02:23:38 [main] (JCRTest:307) - javax.jcr.PathNotFoundException: random/node1_3/node2_3
     [java] javax.jcr.PathNotFoundException: random/node1_3/node2_3
     [java]     at org.apache.jackrabbit.core.NodeImpl.getNode(NodeImpl.java:2240)
     [java]     at JCRTest.dumpResults(JCRTest.java:300)
     [java]     at JCRTest.main(JCRTest.java:280)

for some reason. After that it sometimes finds the node, and sometimes it does 
not find the node.

And finally set of exceptions: 
[java] ERROR 20/30/05 02:30:57 [Thread-119] (RepositoryImpl:283) - Unable to release repository lock

is thrown. Any ideas, why is that?
I attached code example (see main method), test.runTest() just creates
repository and makes some performance tests, then threads are created etc etc
etc. I would like to think I missed something in my code, but I really have no
idea what could cause node is not found sometimes and is found some another
times....

-- 
Eugene N Dzhurinsky

Re: Multithreading/Mutliuser(?) access

Posted by Marcel Reutegger <ma...@gmx.net>.
Eugeny N Dzhurinsky wrote:
> okay... but right now when trying to access node from several concurrent
> threads within the same session, these methods throws exception 
> Node already locked: /random/node1_3/node2_3

please note that you should not use multiple write threads on a single 
session because that's something that is not supported (or even 
prohibited?) by JTA, and as a consequence jackrabbit does not take 
precausions for such a case!
what jackrabbit supports are multiple threads just reading from a single 
session.

> current.lock(true, true);
> current.setProperty("test", propertyValue);
> current.save();
> current.unlock();
> 
> So I assume I should synchronize access to node in my code, right? JackRabbit
> won't just wait when node is released?

this is not a question whether jackrabbit does it some way. the jcr spec 
says that an an exception is thrown when a lock cannot be aquired!

in the end that means you have to synchronize access in you own code or 
write / use  a little utility that implements a blocking Node.lock()

we had a thread about this topic some time ago, see: 
http://thread.gmane.org/gmane.comp.apache.jackrabbit.devel/2661

regards
  marcel

Re: Multithreading/Mutliuser(?) access

Posted by Eugeny N Dzhurinsky <eu...@jdevelop.com>.
On Fri, Oct 21, 2005 at 11:41:22AM +0200, Marcel Reutegger wrote:
> mix:lockable is a mixin node type, that means you cannot create a node
> with this node type directly. you can think of it as an abstract class, 
> that you cannot instanciate.
> however you can add a mixin to an existing node using Node.addMixin()

okay... but right now when trying to access node from several concurrent
threads within the same session, these methods throws exception 
Node already locked: /random/node1_3/node2_3

current.lock(true, true);
current.setProperty("test", propertyValue);
current.save();
current.unlock();

So I assume I should synchronize access to node in my code, right? JackRabbit
won't just wait when node is released?

-- 
Eugene N Dzhurinsky

Re: Multithreading/Mutliuser(?) access

Posted by Marcel Reutegger <ma...@gmx.net>.
Eugeny N Dzhurinsky wrote:
> Actually my question is : how can I access the same node from several sessions
> and threads w/o breaking things?

simply use a separate session for each thread that writes to the 
workspace. and you will be fine. keep in mind that jcr operations on a 
read-committed basis talking in database terms. if you required a higher 
isolation level you need to use locks.

> I just need to know caveats before we will
> start implementing our CMS with JackRabbit. I wrote test application which
> emulates concurrent access to the same node, and all what I'm getting now -
> just set of exceptions, which identifies I should take care of synchronising
> between sessions by myself, but I don't see any way to do that w/o
> hacking/modifying JackRabbit code, am I correct?

that's definitively something you shouldn't do, though we are always 
happy to accept patches that improve jackrabbit. but in this case the 
exceptions you see are because the jcr specification says so.

again, use locks if you want to be sure that no other session modifies 
nodes that you are trying to commit. otherwise be prepared that a save() 
might fail.

regards
  marcel

Re: Multithreading/Mutliuser(?) access

Posted by Eugeny N Dzhurinsky <eu...@jdevelop.com>.
On Fri, Oct 21, 2005 at 11:41:22AM +0200, Marcel Reutegger wrote:
> mix:lockable is a mixin node type, that means you cannot create a node
> with this node type directly. you can think of it as an abstract class, 
> that you cannot instanciate.
> however you can add a mixin to an existing node using Node.addMixin()

Actually my question is : how can I access the same node from several sessions
and threads w/o breaking things? I just need to know caveats before we will
start implementing our CMS with JackRabbit. I wrote test application which
emulates concurrent access to the same node, and all what I'm getting now -
just set of exceptions, which identifies I should take care of synchronising
between sessions by myself, but I don't see any way to do that w/o
hacking/modifying JackRabbit code, am I correct?

-- 
Eugene N Dzhurinsky

Re: Multithreading/Mutliuser(?) access

Posted by Marcel Reutegger <ma...@gmx.net>.
mix:lockable is a mixin node type, that means you cannot create a node
with this node type directly. you can think of it as an abstract class, 
that you cannot instanciate.

however you can add a mixin to an existing node using Node.addMixin()

please have a look at secion 4.8 of the jcr spec.

regards
  marcel

Eugeny N Dzhurinsky wrote:
> On Thu, Oct 20, 2005 at 05:27:51PM +0200, Marcel Reutegger wrote:
> 
>>Because of JCRs data model this can potentially happen to any save() 
>>call, unless the modification is protected with a lock.
>>when one session modifies a node and tries to save it, another session 
>>might have been faster and the changes of the latter session win. the 
>>first session then gets an InvalidItemStateException because it tried to 
>>save inconsistent data.
> 
> 
> Okay, I understood this point. However, I found node should be set with
> nodetype mix:lockable (?) to allow locks fo changes. But if I change node type
> from nt:unstructured to mix:lockable, I'm getting exceptions:
> javax.jcr.nodetype.ConstraintViolati
> onException: no definition found in parent node's node type for new node: no
> matching child node definition found for {}node1_1: no matching child node 
> definition found for{}node1_1
>      [java] javax.jcr.nodetype.ConstraintViolationException: no definition
>      found in parent node's node type for new node: no matching child node 
>      definition found for{}node1_1: no matching child node definition found 
>      for {}node1_1
> 

Re: Multithreading/Mutliuser(?) access

Posted by Eugeny N Dzhurinsky <eu...@jdevelop.com>.
On Thu, Oct 20, 2005 at 05:27:51PM +0200, Marcel Reutegger wrote:
> Because of JCRs data model this can potentially happen to any save() 
> call, unless the modification is protected with a lock.
> when one session modifies a node and tries to save it, another session 
> might have been faster and the changes of the latter session win. the 
> first session then gets an InvalidItemStateException because it tried to 
> save inconsistent data.

Okay, I understood this point. However, I found node should be set with
nodetype mix:lockable (?) to allow locks fo changes. But if I change node type
from nt:unstructured to mix:lockable, I'm getting exceptions:
javax.jcr.nodetype.ConstraintViolati
onException: no definition found in parent node's node type for new node: no
matching child node definition found for {}node1_1: no matching child node 
definition found for{}node1_1
     [java] javax.jcr.nodetype.ConstraintViolationException: no definition
     found in parent node's node type for new node: no matching child node 
     definition found for{}node1_1: no matching child node definition found 
     for {}node1_1

Source code attached.

-- 
Eugene N Dzhurinsky

Re: Multithreading/Mutliuser(?) access

Posted by Marcel Reutegger <ma...@gmx.net>.
Hi Eugeny,

Eugeny N Dzhurinsky wrote:
> Right now there is some other errors. I modified
> createSession to operate only on single repository (private static Repository
> repo). When several threads are working within single session, everything
> seems to be ok, but with several sessions there are a lot of exceptions about 
> 
>  [java] ERROR 20/03/05 05:03:04 [30] (JCRTest$SingleSessionAccessThread:370) - javax.jcr.In
> validItemStateException: db5e6d2d-6a07-49ac-a2b0-9cfe40d1e9a9/{}test: the item cannot be saved 
> because it has been modified externally.

Because of JCRs data model this can potentially happen to any save() 
call, unless the modification is protected with a lock.

when one session modifies a node and tries to save it, another session 
might have been faster and the changes of the latter session win. the 
first session then gets an InvalidItemStateException because it tried to 
save inconsistent data.

regards
  marcel

Re: Multithreading/Mutliuser(?) access

Posted by Eugeny N Dzhurinsky <eu...@jdevelop.com>.
On Thu, Oct 20, 2005 at 03:54:31PM +0200, Marcel Reutegger wrote:
> If I'm not totally mistaken your test creates multiple repository 
> instances with the same configuration thus running on the same location. 
> this is not allowed and should actually result in an error when 
> initializing a repository that works on data that is already access by 
> another instance.
> please make sure there is only one repository instance running.

okay, I got you. Right now there is some other errors. I modified
createSession to operate only on single repository (private static Repository
repo). When several threads are working within single session, everything
seems to be ok, but with several sessions there are a lot of exceptions about 

 [java] ERROR 20/03/05 05:03:04 [30] (JCRTest$SingleSessionAccessThread:370) - javax.jcr.In
validItemStateException: db5e6d2d-6a07-49ac-a2b0-9cfe40d1e9a9/{}test: the item cannot be saved 
because it has been modified externally.
     [java] javax.jcr.InvalidItemStateException: db5e6d2d-6a07-49ac-a2b0-9cfe40d1e9a9/{}test: t
he item cannot be saved because it has been modified externally.
     [java]     at org.apache.jackrabbit.core.ItemImpl.getTransientStates(ItemImpl.java:391)
     [java]     at org.apache.jackrabbit.core.ItemImpl.save(ItemImpl.java:1215)
     [java]     at org.apache.jackrabbit.core.SessionImpl.save(SessionImpl.java:765)
     [java]     at JCRTest.releaseSession(JCRTest.java:226)
     [java]     at JCRTest$SingleSessionAccessThread.run(JCRTest.java:368)

the same exception is thrown with LocalFS when session.save() method in releaseSession() is called.

-- 
Eugene N Dzhurinsky

Re: Multithreading/Mutliuser(?) access

Posted by Marcel Reutegger <ma...@gmx.net>.
If I'm not totally mistaken your test creates multiple repository 
instances with the same configuration thus running on the same location. 
this is not allowed and should actually result in an error when 
initializing a repository that works on data that is already access by 
another instance.

please make sure there is only one repository instance running.

regards
  marcel

Eugeny N Dzhurinsky wrote:
> I attached some error logs i've got, it seems on LocalFS everything works fine
> except Lucene's indexing errors.

Re: Multithreading/Mutliuser(?) access

Posted by Eugeny N Dzhurinsky <eu...@jdevelop.com>.
I attached some error logs i've got, it seems on LocalFS everything works fine
except Lucene's indexing errors.

-- 
Eugene N Dzhurinsky