You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@jackrabbit.apache.org by Walter Raboch <wr...@ingen.at> on 2005/08/06 18:02:03 UTC

concurrency problem

Hi all,

I wrote a simple test to simulate some concurrent sessions. But the test 
fails with exceptions. Is this a bug or do I get damaged by to much sun 
in my short vacation?

It happens with CQFileSystem and LocalFileSystem with all persistence 
managers.

cheers,
Walter

--
run 1 (empty repository):
=========================
s0: started.
s1: started.
s2: started.
s3: started.
s4: started.
.................................................s0: ended.
.s1: ended.
s2: ended.
s3: ended.
s4: ended.


run 2 (data from run 1):
========================
s0: started.
s1: started.
s2: started.
s3: started.
s4: started.
s2: Exception: removing testnode
javax.jcr.nodetype.ConstraintViolationException: 
3b2fe68b-7747-459d-92b2-216b0af472e2 needs to be saved as well.
	at org.apache.jackrabbit.core.ItemImpl.save(ItemImpl.java:1289)
	at org.apache.jackrabbit.core.SessionImpl.save(SessionImpl.java:747)
	at TestSession.run(TestSession.java:61)
	at java.lang.Thread.run(Unknown Source)
s3: Exception: removing testnode
javax.jcr.nodetype.ConstraintViolationException: 
3b2fe68b-7747-459d-92b2-216b0af472e2 needs to be saved as well.
	at org.apache.jackrabbit.core.ItemImpl.save(ItemImpl.java:1289)
	at org.apache.jackrabbit.core.SessionImpl.save(SessionImpl.java:747)
	at TestSession.run(TestSession.java:61)
	at java.lang.Thread.run(Unknown Source)
s3: ended.
s2: ended.
s4: Exception: removing testnode
javax.jcr.nodetype.ConstraintViolationException: 
1dca23f9-e6d5-47b3-830c-a272b9387925 needs to be saved as well.
	at org.apache.jackrabbit.core.ItemImpl.save(ItemImpl.java:1289)
	at org.apache.jackrabbit.core.SessionImpl.save(SessionImpl.java:747)
	at TestSession.run(TestSession.java:61)
	at java.lang.Thread.run(Unknown Source)
s4: ended.
s0: Exception: adding testnode
javax.jcr.ItemNotFoundException: 3b2fe68b-7747-459d-92b2-216b0af472e2
	at 
org.apache.jackrabbit.core.ItemManager.createItemInstance(ItemManager.java:498)
	at org.apache.jackrabbit.core.ItemManager.getItem(ItemManager.java:349)
	at 
org.apache.jackrabbit.core.NodeImpl.internalAddChildNode(NodeImpl.java:781)
	at org.apache.jackrabbit.core.NodeImpl.internalAddNode(NodeImpl.java:725)
	at org.apache.jackrabbit.core.NodeImpl.internalAddNode(NodeImpl.java:672)
	at org.apache.jackrabbit.core.NodeImpl.addNode(NodeImpl.java:1721)
	at TestSession.run(TestSession.java:69)
	at java.lang.Thread.run(Unknown Source)
s0: ended.
..........s1: ended.


Source:
=======

import javax.jcr.Node;
import javax.jcr.NodeIterator;
import javax.jcr.Property;
import javax.jcr.PropertyIterator;
import javax.jcr.Repository;
import javax.jcr.RepositoryException;
import javax.jcr.Session;
import javax.jcr.SimpleCredentials;
import javax.jcr.Value;

import org.apache.jackrabbit.core.RepositoryImpl;
import org.apache.jackrabbit.core.config.RepositoryConfig;

public class JackRabbitTest {
	
	public static void performanceTest(Repository r) {
		try {
			for( int i=0; i<5; i++ ) {
				Session session = r.login(new SimpleCredentials("admin", 
"".toCharArray()), null);
				TestSession ts = new TestSession("s" + i, session);
				Thread th = new Thread(ts);
				th.start();
				Thread.sleep(100);
			}
		} catch (Exception e){
			System.err.println(e);
		    e.printStackTrace();
		}
	}
	
	public static void main(String[] args) {
		 try {
		      String configFile = "repository.xml";
		      String repHomeDir = "repository.home";
		
		      RepositoryConfig c = RepositoryConfig.create(configFile, 
repHomeDir);
		      Repository r = RepositoryImpl.create(c);

		      performanceTest(r);
		    } catch (Exception e){
		      System.err.println(e);
		      e.printStackTrace();
		    }
	}
}
------------
import java.util.Random;

import javax.jcr.ItemNotFoundException;
import javax.jcr.Node;
import javax.jcr.Session;
import javax.jcr.lock.Lock;

import org.apache.jackrabbit.value.StringValue;

public class TestSession implements Runnable {

	Session session;
	String identity;
	Random r;
	
	TestSession( String identity, Session s ) {
		this.session = s;
		this.identity = identity;
		r = new Random();
	}
	
	private void debug(String msg) {
		System.out.println( identity + ": " + msg);
	}
	
	private void sleep() {
		long l = r.nextInt(900)+200;
		try {
			Thread.sleep( l );
		} catch(InterruptedException ie) {
		}
	}
	
	public void run() {
		
		debug("started.");
		String state = "";
		try {
			Node rn = session.getRootNode();
			
	    		state = "searching testnode";
			if (rn.hasNode("testnode-" + identity)) {
		    	try {
		    		state = "removing testnode";
		    		rn.getNode("testnode-" + identity).remove();
		    		session.save();
			    	sleep();
		    	} catch(ItemNotFoundException infe) {
		    		debug("error while removing testnode " + identity);
		    		infe.printStackTrace();
		    	}
		    }
     		state = "adding testnode";
		    Node n = rn.addNode("testnode-" + identity , "nt:unstructured");		
		
		    session.save();
		    state = "setting property";		
		    n.setProperty("testprop", new StringValue("Hello World!"));
		    session.save();
		    sleep();
		
		    for(int i=0; i<100; i++) {
		    	state = "adding subnode " + i;
		    	n.addNode("x" + i, "nt:unstructured");
		    	state = "adding property to subnode " + i;
		    	n.setProperty("testprop","xxx");
		    	if(i%10==0)	{
		    		state = "saving pending subnodes";
		    		session.save();
		    		System.out.print(".");
		    	}
		    	sleep();
		    }
		    session.save();

		} catch( Exception e) {
			debug("Exception: " + state);
			e.printStackTrace();
		} finally {
			session.logout();
		}

		debug("ended.");
	}
}



Re: concurrency problem

Posted by Stefan Guggisberg <st...@gmail.com>.
hi walter,

On 8/22/05, Walter Raboch <wr...@ingen.at> wrote:
> Hi Stefan,
> 
> >>the first InvalidItemStateException is correct.
> >>i'll investigate the ItemNotFoundException. i guess there's
> >>a 'synchronized' missing somewhere...
> >
> > this issue should be fixed now (r233511).
> 
> JackRabbit is still hanging on the Node.unlock() function.

that's a new issue. please post a jira bug with detailed instructions
how to reporduce the problem.

thanks
stefan

> 
> ... everything fine until here...
> s13: 4
> s13: 5
> s13: 6
> s13: 7   -> unlock()
> s14: started.
> s14: 1   -> session.getRootNode()
> s15: started.
> s15: 1
> s16: started.
> 
> I just find this failure during the first run (emtpy repository home
> directory). 2nd and 3th run are fine after killing the vm from first
> run, but with already initialized repository directory these time.
> 
> 1. rm -rf repository.home
> 2. run -> hang
> 3. kill
> 4. run -> ok
> 5. run -> ok
> 
> cheers,
> Walter
> 
>

Re: concurrency problem

Posted by Walter Raboch <wr...@ingen.at>.
Hi Stefan,

>>the first InvalidItemStateException is correct.
>>i'll investigate the ItemNotFoundException. i guess there's
>>a 'synchronized' missing somewhere...
> 
> this issue should be fixed now (r233511).

JackRabbit is still hanging on the Node.unlock() function.

... everything fine until here...
s13: 4
s13: 5
s13: 6
s13: 7   -> unlock()
s14: started.
s14: 1   -> session.getRootNode()
s15: started.
s15: 1
s16: started.

I just find this failure during the first run (emtpy repository home 
directory). 2nd and 3th run are fine after killing the vm from first 
run, but with already initialized repository directory these time.

1. rm -rf repository.home
2. run -> hang
3. kill
4. run -> ok
5. run -> ok

cheers,
Walter

Re: concurrency problem

Posted by Stefan Guggisberg <st...@gmail.com>.
On 8/11/05, Stefan Guggisberg <st...@gmail.com> wrote:
> On 8/11/05, Walter Raboch <wr...@ingen.at> wrote:
> > Hi Stefan,
> >
> > >>Thanks for the discussion. Now I unterstand jackrabbits way of doing.
> > >>But in my opinion adding child nodes should not alter the parent node
> > >>itself. Just changing some properties is a state change.
> > >
> > > i don't agree. see 7.1.4 Adding Nodes in the jsr 170 spec:
> > > <quote>
> > > In order to save a newly added node, save must be called either on the
> > > Session, or on the new node's parent or higher-order ancestor
> > > (grandparent, etc.).
> > > </quote>
> > >>Furthermore there should be an error just in the case, that both updates
> > >>overwrite the changes of the other -> to prevent lost update problems.
> > >>In my example code it´s not the case, so I would prefer no error at all.
> > >>What do you think?
> > >
> > > AFAIK lost updates did never happen. your testcase failed in the right
> > > situations
> > > but threw the wrong exceptions. i committed a fix for that problem yesterday.
> > > IMO it now works as it should according to the jsr 170 spec.
> >
> > You are right according to the spec. Let me try to explain my thoughts:
> >
> > s0: read root node
> > s1: read root node
> > s0: add or remove child "c1"
> > s1: add or remove child "c2"
> > s0: rn.save()
> > s1: rn.save()
> >
> > All this without error. Because the changes of both sessions dont
> > interfere.
> 
> i can see what you mean. unfortunately there's no trivial solution.
> child node additions & removals per se are not guaranteed to
> be non-interfering. there's even a great chance that they actually
> *are* interfering. just think of same-name siblings. the same applies
> for child re-ordering.
> 
> an application should lock the parent node to stay clear of such
> concurrency issues (pessimistic locking approach).
> 
> > If both sessions change the same child or attribute, there should be
> > thrown an InvalidItemStateException.
> >
> > s0: read root node
> > s1: read root node
> > s0: set property p="hello"
> > s1: set property p="world"
> > s0: save
> > s1: save -> InvalidItemStateException
> >
> > What do you think?
> >
> > To our first problem with my testcase. I rerun the code but it still
> > fails with ItemNotFoundExceptions. But I dont know why.
> 
> the first InvalidItemStateException is correct.
> i'll investigate the ItemNotFoundException. i guess there's
> a 'synchronized' missing somewhere...

this issue should be fixed now (r233511).

cheers
stefan

> 
> cheers
> stefan
> 
> >
> > cheers, Walter
> > --
> > Output of rerun (revision 231423):
> > ==================================
> > s0: started.
> > s1: started.
> > s2: started.
> > s3: started.
> > s4: started.
> > s3: Exception: removing testnode
> > javax.jcr.InvalidItemStateException: /: the item cannot be saved because
> > it has been modified externally.
> >         at
> > org.apache.jackrabbit.core.ItemImpl.getTransientStates(ItemImpl.java:347)
> >         at org.apache.jackrabbit.core.ItemImpl.save(ItemImpl.java:1205)
> >         at org.apache.jackrabbit.core.SessionImpl.save(SessionImpl.java:747)
> >         at TestSession.run(TestSession.java:62)
> >         at java.lang.Thread.run(Unknown Source)
> > s3: ended.
> > javax.jcr.ItemNotFoundException: 545ab69b-0297-427c-a05a-217e3c8f7d88
> >         at
> > org.apache.jackrabbit.core.ItemManager.createItemInstance(ItemManager.java:498)
> >         at org.apache.jackrabbit.core.ItemManager.getItem(ItemManager.java:349)
> >         at
> > org.apache.jackrabbit.core.NodeImpl.internalAddChildNode(NodeImpl.java:781)
> >         at org.apache.jackrabbit.core.NodeImpl.internalAddNode(NodeImpl.java:725)
> >         at org.apache.jackrabbit.core.NodeImpl.internalAddNode(NodeImpl.java:672)
> >         at org.apache.jackrabbit.core.NodeImpl.addNode(NodeImpl.java:1721)
> >         at TestSession.run(TestSession.java:70)
> >         at java.lang.Thread.run(Unknown Source)
> > s0: Exception: adding testnode
> > s0: ended.
> > s4: Exception: removing testnode
> > javax.jcr.InvalidItemStateException: /: the item cannot be saved because
> > it has been modified externally.
> >         at
> > org.apache.jackrabbit.core.ItemImpl.getTransientStates(ItemImpl.java:347)
> >         at org.apache.jackrabbit.core.ItemImpl.save(ItemImpl.java:1205)
> >         at org.apache.jackrabbit.core.SessionImpl.save(SessionImpl.java:747)
> >         at TestSession.run(TestSession.java:62)
> >         at java.lang.Thread.run(Unknown Source)
> > s4: ended.
> > s1: Exception: adding testnode
> > javax.jcr.ItemNotFoundException: e170d490-b7c1-4dfa-be14-f8932162b9f7
> >         at
> > org.apache.jackrabbit.core.ItemManager.createItemInstance(ItemManager.java:498)
> >         at org.apache.jackrabbit.core.ItemManager.getItem(ItemManager.java:349)
> >         at
> > org.apache.jackrabbit.core.NodeImpl.internalAddChildNode(NodeImpl.java:781)
> >         at org.apache.jackrabbit.core.NodeImpl.internalAddNode(NodeImpl.java:725)
> >         at org.apache.jackrabbit.core.NodeImpl.internalAddNode(NodeImpl.java:672)
> >         at org.apache.jackrabbit.core.NodeImpl.addNode(NodeImpl.java:1721)
> >         at TestSession.run(TestSession.java:70)
> >         at java.lang.Thread.run(Unknown Source)
> > s1: ended.
> > ..........s2: ended.
> >
> >
> >
>

Re: concurrency problem

Posted by Nicolas Belisle <Ni...@bibl.ulaval.ca>.
Hi Waler,

I invested some efforts to create a template class implementing 
waitForLock() functionality. It respects the JSR, so it can be used with 
any implementation that supports locking.

You can read about it here :
http://www.mail-archive.com/jackrabbit-dev%40incubator.apache.org/msg01870.html

Note: I haven't used it in production. I also welcome any comments...

Regards,

Nicolas


Le 10:29 2005-08-11, vous avez écrit:
>Hi Stefan,
>
>>the first InvalidItemStateException is correct. i'll investigate the 
>>ItemNotFoundException. i guess there's a 'synchronized' missing somewhere...
>
>I extended my testcase a little bit. Now I lock the rootnode for 
>adding/deleting subnodes. But the program hangs sometimes while
>locking or releasing the lock again.
>
>Some waitForLock() method would be cool too ;) Perhaps with
>some sort of waitQueue. But I know - its not in the spec.
>
>cheers,
>Walter
>--
>
>public void run() {
>                 // simulate a user...
>                 debug("started.");
>                 String state = "";
>                 Lock l = null;
>                 Node rn = null;
>                 try {
>                         debug("1");
>                         rn = session.getRootNode();
>                         debug("2");
>                         int count = 0;
>                         while(rn.isLocked() && count < 30) {
>                                 sleep();
>                                 count++;
>                         }
>                         debug("3");
>                         l = rn.lock(false, true);
>                         debug("4");
>                 state = "searching testnode";
>                         if (rn.hasNode("testnode-" + identity)) {
>                                 debug("4.1");
>                         try {
>                                 state = "removing testnode";
>                                 rn.getNode("testnode-" + identity).remove();
>                                 debug("4.2");
>                                 session.save();
>                                 sleep();
>                         } catch(ItemNotFoundException infe) {
>                                 debug("error while removing testnode " + 
> identity);
>                                 infe.printStackTrace();
>                         }
>                     }
>                         debug("5");
>                 state = "adding testnode";
>                     Node n = rn.addNode("testnode-" + identity , 
> "nt:unstructured");
>                     debug("6");
>                     session.save();
>                     debug("7");
>                     rn.unlock();
>                     debug("8");
>                     state = "setting property";
>                     n.setProperty("testprop", new StringValue("Hello 
> World!"));
>                     session.save();
>                     sleep();
>
>                     for(int i=0; i<100; i++) {
>                         state = "adding subnode " + i;
>                         n.addNode("x" + i, "nt:unstructured");
>                         state = "adding property to subnode " + i;
>                         n.setProperty("testprop","xxx");
>                         if(i%10==0)     {
>                                 state = "saving pending subnodes";
>                                 session.save();
>                                 System.out.print(".");
>                         }
>                         sleep();
>                     }
>                     session.save();
>
>                 } catch( Exception e) {
>                         debug("Exception: " + state);
>                         e.printStackTrace();
>                 } finally {
>                         if(l != null && rn != null) {
>                                 try {
>                                         rn.unlock();
>                                 } catch( RepositoryException e ) 
> {
>                                 }
>                         }
>                         session.logout();
>                 }
>
>                 debug("ended.");
>         }


Re: concurrency problem

Posted by Walter Raboch <wr...@ingen.at>.
Hi Stefan,

> the first InvalidItemStateException is correct. 
> i'll investigate the ItemNotFoundException. i guess there's 
> a 'synchronized' missing somewhere...

I extended my testcase a little bit. Now I lock the rootnode for 
adding/deleting subnodes. But the program hangs sometimes while
locking or releasing the lock again.

Some waitForLock() method would be cool too ;) Perhaps with
some sort of waitQueue. But I know - its not in the spec.

cheers,
Walter
--

public void run() {
		// simulate a user...
		debug("started.");
		String state = "";
		Lock l = null;
		Node rn = null;
		try {
			debug("1");
			rn = session.getRootNode();
			debug("2");
			int count = 0;
			while(rn.isLocked() && count < 30) {
				sleep();
				count++;
			}
			debug("3");
			l = rn.lock(false, true);
			debug("4");
	    	state = "searching testnode";
			if (rn.hasNode("testnode-" + identity)) {
				debug("4.1");
		    	try {
		    		state = "removing testnode";
		    		rn.getNode("testnode-" + identity).remove();
		    		debug("4.2");
		    		session.save();
			    	sleep();
		    	} catch(ItemNotFoundException infe) {
		    		debug("error while removing testnode " + identity);
		    		infe.printStackTrace();
		    	}
		    }
			debug("5");
     		state = "adding testnode";
		    Node n = rn.addNode("testnode-" + identity , "nt:unstructured");		
		    debug("6");
		    session.save();
		    debug("7");
		    rn.unlock();
		    debug("8");
		    state = "setting property";		
		    n.setProperty("testprop", new StringValue("Hello World!"));
		    session.save();
		    sleep();
		
		    for(int i=0; i<100; i++) {
		    	state = "adding subnode " + i;
		    	n.addNode("x" + i, "nt:unstructured");
		    	state = "adding property to subnode " + i;
		    	n.setProperty("testprop","xxx");
		    	if(i%10==0)	{
		    		state = "saving pending subnodes";
		    		session.save();
		    		System.out.print(".");
		    	}
		    	sleep();
		    }
		    session.save();

		} catch( Exception e) {
			debug("Exception: " + state);
			e.printStackTrace();
		} finally {
			if(l != null && rn != null) {
				try {
					rn.unlock();
				} catch( RepositoryException e ) {				
				}
			}
			session.logout();
		}

		debug("ended.");
	}

Re: concurrency problem

Posted by Stefan Guggisberg <st...@gmail.com>.
On 8/11/05, Walter Raboch <wr...@ingen.at> wrote:
> Hi Stefan,
> 
> >>Thanks for the discussion. Now I unterstand jackrabbits way of doing.
> >>But in my opinion adding child nodes should not alter the parent node
> >>itself. Just changing some properties is a state change.
> >
> > i don't agree. see 7.1.4 Adding Nodes in the jsr 170 spec:
> > <quote>
> > In order to save a newly added node, save must be called either on the
> > Session, or on the new node's parent or higher-order ancestor
> > (grandparent, etc.).
> > </quote>
> >>Furthermore there should be an error just in the case, that both updates
> >>overwrite the changes of the other -> to prevent lost update problems.
> >>In my example code it´s not the case, so I would prefer no error at all.
> >>What do you think?
> >
> > AFAIK lost updates did never happen. your testcase failed in the right
> > situations
> > but threw the wrong exceptions. i committed a fix for that problem yesterday.
> > IMO it now works as it should according to the jsr 170 spec.
> 
> You are right according to the spec. Let me try to explain my thoughts:
> 
> s0: read root node
> s1: read root node
> s0: add or remove child "c1"
> s1: add or remove child "c2"
> s0: rn.save()
> s1: rn.save()
> 
> All this without error. Because the changes of both sessions dont
> interfere.

i can see what you mean. unfortunately there's no trivial solution.
child node additions & removals per se are not guaranteed to 
be non-interfering. there's even a great chance that they actually
*are* interfering. just think of same-name siblings. the same applies 
for child re-ordering.

an application should lock the parent node to stay clear of such
concurrency issues (pessimistic locking approach).

> If both sessions change the same child or attribute, there should be
> thrown an InvalidItemStateException.
> 
> s0: read root node
> s1: read root node
> s0: set property p="hello"
> s1: set property p="world"
> s0: save
> s1: save -> InvalidItemStateException
> 
> What do you think?
> 
> To our first problem with my testcase. I rerun the code but it still
> fails with ItemNotFoundExceptions. But I dont know why.

the first InvalidItemStateException is correct. 
i'll investigate the ItemNotFoundException. i guess there's 
a 'synchronized' missing somewhere...

cheers
stefan

> 
> cheers, Walter
> --
> Output of rerun (revision 231423):
> ==================================
> s0: started.
> s1: started.
> s2: started.
> s3: started.
> s4: started.
> s3: Exception: removing testnode
> javax.jcr.InvalidItemStateException: /: the item cannot be saved because
> it has been modified externally.
>         at
> org.apache.jackrabbit.core.ItemImpl.getTransientStates(ItemImpl.java:347)
>         at org.apache.jackrabbit.core.ItemImpl.save(ItemImpl.java:1205)
>         at org.apache.jackrabbit.core.SessionImpl.save(SessionImpl.java:747)
>         at TestSession.run(TestSession.java:62)
>         at java.lang.Thread.run(Unknown Source)
> s3: ended.
> javax.jcr.ItemNotFoundException: 545ab69b-0297-427c-a05a-217e3c8f7d88
>         at
> org.apache.jackrabbit.core.ItemManager.createItemInstance(ItemManager.java:498)
>         at org.apache.jackrabbit.core.ItemManager.getItem(ItemManager.java:349)
>         at
> org.apache.jackrabbit.core.NodeImpl.internalAddChildNode(NodeImpl.java:781)
>         at org.apache.jackrabbit.core.NodeImpl.internalAddNode(NodeImpl.java:725)
>         at org.apache.jackrabbit.core.NodeImpl.internalAddNode(NodeImpl.java:672)
>         at org.apache.jackrabbit.core.NodeImpl.addNode(NodeImpl.java:1721)
>         at TestSession.run(TestSession.java:70)
>         at java.lang.Thread.run(Unknown Source)
> s0: Exception: adding testnode
> s0: ended.
> s4: Exception: removing testnode
> javax.jcr.InvalidItemStateException: /: the item cannot be saved because
> it has been modified externally.
>         at
> org.apache.jackrabbit.core.ItemImpl.getTransientStates(ItemImpl.java:347)
>         at org.apache.jackrabbit.core.ItemImpl.save(ItemImpl.java:1205)
>         at org.apache.jackrabbit.core.SessionImpl.save(SessionImpl.java:747)
>         at TestSession.run(TestSession.java:62)
>         at java.lang.Thread.run(Unknown Source)
> s4: ended.
> s1: Exception: adding testnode
> javax.jcr.ItemNotFoundException: e170d490-b7c1-4dfa-be14-f8932162b9f7
>         at
> org.apache.jackrabbit.core.ItemManager.createItemInstance(ItemManager.java:498)
>         at org.apache.jackrabbit.core.ItemManager.getItem(ItemManager.java:349)
>         at
> org.apache.jackrabbit.core.NodeImpl.internalAddChildNode(NodeImpl.java:781)
>         at org.apache.jackrabbit.core.NodeImpl.internalAddNode(NodeImpl.java:725)
>         at org.apache.jackrabbit.core.NodeImpl.internalAddNode(NodeImpl.java:672)
>         at org.apache.jackrabbit.core.NodeImpl.addNode(NodeImpl.java:1721)
>         at TestSession.run(TestSession.java:70)
>         at java.lang.Thread.run(Unknown Source)
> s1: ended.
> ..........s2: ended.
> 
> 
>

Re: concurrency problem

Posted by Walter Raboch <wr...@ingen.at>.
Hi Stefan,

>>Thanks for the discussion. Now I unterstand jackrabbits way of doing.
>>But in my opinion adding child nodes should not alter the parent node
>>itself. Just changing some properties is a state change.
> 
> i don't agree. see 7.1.4 Adding Nodes in the jsr 170 spec:
> <quote>
> In order to save a newly added node, save must be called either on the
> Session, or on the new node's parent or higher-order ancestor
> (grandparent, etc.).
> </quote>
>>Furthermore there should be an error just in the case, that both updates
>>overwrite the changes of the other -> to prevent lost update problems.
>>In my example code it´s not the case, so I would prefer no error at all.
>>What do you think?
> 
> AFAIK lost updates did never happen. your testcase failed in the right
> situations
> but threw the wrong exceptions. i committed a fix for that problem yesterday.
> IMO it now works as it should according to the jsr 170 spec.

You are right according to the spec. Let me try to explain my thoughts:

s0: read root node
s1: read root node
s0: add or remove child "c1"
s1: add or remove child "c2"
s0: rn.save()
s1: rn.save()

All this without error. Because the changes of both sessions dont 
interfere.
If both sessions change the same child or attribute, there should be 
thrown an InvalidItemStateException.

s0: read root node
s1: read root node
s0: set property p="hello"
s1: set property p="world"
s0: save
s1: save -> InvalidItemStateException

What do you think?

To our first problem with my testcase. I rerun the code but it still 
fails with ItemNotFoundExceptions. But I dont know why.

cheers, Walter
--
Output of rerun (revision 231423):
==================================
s0: started.
s1: started.
s2: started.
s3: started.
s4: started.
s3: Exception: removing testnode
javax.jcr.InvalidItemStateException: /: the item cannot be saved because 
it has been modified externally.
	at 
org.apache.jackrabbit.core.ItemImpl.getTransientStates(ItemImpl.java:347)
	at org.apache.jackrabbit.core.ItemImpl.save(ItemImpl.java:1205)
	at org.apache.jackrabbit.core.SessionImpl.save(SessionImpl.java:747)
	at TestSession.run(TestSession.java:62)
	at java.lang.Thread.run(Unknown Source)
s3: ended.
javax.jcr.ItemNotFoundException: 545ab69b-0297-427c-a05a-217e3c8f7d88
	at 
org.apache.jackrabbit.core.ItemManager.createItemInstance(ItemManager.java:498)
	at org.apache.jackrabbit.core.ItemManager.getItem(ItemManager.java:349)
	at 
org.apache.jackrabbit.core.NodeImpl.internalAddChildNode(NodeImpl.java:781)
	at org.apache.jackrabbit.core.NodeImpl.internalAddNode(NodeImpl.java:725)
	at org.apache.jackrabbit.core.NodeImpl.internalAddNode(NodeImpl.java:672)
	at org.apache.jackrabbit.core.NodeImpl.addNode(NodeImpl.java:1721)
	at TestSession.run(TestSession.java:70)
	at java.lang.Thread.run(Unknown Source)
s0: Exception: adding testnode
s0: ended.
s4: Exception: removing testnode
javax.jcr.InvalidItemStateException: /: the item cannot be saved because 
it has been modified externally.
	at 
org.apache.jackrabbit.core.ItemImpl.getTransientStates(ItemImpl.java:347)
	at org.apache.jackrabbit.core.ItemImpl.save(ItemImpl.java:1205)
	at org.apache.jackrabbit.core.SessionImpl.save(SessionImpl.java:747)
	at TestSession.run(TestSession.java:62)
	at java.lang.Thread.run(Unknown Source)
s4: ended.
s1: Exception: adding testnode
javax.jcr.ItemNotFoundException: e170d490-b7c1-4dfa-be14-f8932162b9f7
	at 
org.apache.jackrabbit.core.ItemManager.createItemInstance(ItemManager.java:498)
	at org.apache.jackrabbit.core.ItemManager.getItem(ItemManager.java:349)
	at 
org.apache.jackrabbit.core.NodeImpl.internalAddChildNode(NodeImpl.java:781)
	at org.apache.jackrabbit.core.NodeImpl.internalAddNode(NodeImpl.java:725)
	at org.apache.jackrabbit.core.NodeImpl.internalAddNode(NodeImpl.java:672)
	at org.apache.jackrabbit.core.NodeImpl.addNode(NodeImpl.java:1721)
	at TestSession.run(TestSession.java:70)
	at java.lang.Thread.run(Unknown Source)
s1: ended.
..........s2: ended.


Re: concurrency problem

Posted by Stefan Guggisberg <st...@gmail.com>.
hi walter,

On 8/10/05, Walter Raboch <wr...@ingen.at> wrote:
> Hi Stefan,
> 
> > the correct beahviour should be:
> >
> > s0 : Read the rootNode
> > s1 : Read the rootNode
> > s0 : Modify rootNode : remove testnode-s0
> > s1 : Modify rootNode : remove testnode-s1 & save() -->ERROR the rootNode
> 
>   there should be no error at this point, s0 has not been saved yet.

absolutely correct, i haven't been careful enough when i copy/pasted it,
sorry for that. let me try again;)

s0 : Read the rootNode
s1 : Read the rootNode
s0 : Modify rootNode : remove testnode-s0
s1 : Modify rootNode : remove testnode-s1
s0 : save()
s1 : save() -->InvalidItemStateException since the root node has been externally
     modifiied (by s0); s1's 'copy' has become stale as a result

> 
> > s0 : save()
> 
>   now there should be an error since s1 saved its state before
> 
> > s1 : save() -->InvalidItemStateException since the root node has been externally
> >       modifiied (by s0) is has s1's 'copy' has become stale as a result
> 
>   I dont think that here should be an error, since the last saved
> (commited) version  of the rootNode is from s1 and the changes from s0
> has not been valid and not commited. so the nodes state has not changed.
> 
> > we'll fix that asap.
> 
> Thanks for the discussion. Now I unterstand jackrabbits way of doing.
> But in my opinion adding child nodes should not alter the parent node
> itself. Just changing some properties is a state change.

i don't agree. see 7.1.4 Adding Nodes in the jsr 170 spec:
<quote>
In order to save a newly added node, save must be called either on the
Session, or on the new node's parent or higher-order ancestor
(grandparent, etc.).
</quote>

> 
> Furthermore there should be an error just in the case, that both updates
> overwrite the changes of the other -> to prevent lost update problems.
> In my example code it´s not the case, so I would prefer no error at all.
> What do you think?

AFAIK lost updates did never happen. your testcase failed in the right
situations
but threw the wrong exceptions. i committed a fix for that problem yesterday.
IMO it now works as it should according to the jsr 170 spec.

cheers
stefan

> 
> cheers,
> Walter
> 
>

Re: concurrency problem

Posted by Walter Raboch <wr...@ingen.at>.
Hi Stefan,

> the correct beahviour should be:
> 
> s0 : Read the rootNode
> s1 : Read the rootNode
> s0 : Modify rootNode : remove testnode-s0
> s1 : Modify rootNode : remove testnode-s1 & save() -->ERROR the rootNode

  there should be no error at this point, s0 has not been saved yet.

> s0 : save()

  now there should be an error since s1 saved its state before

> s1 : save() -->InvalidItemStateException since the root node has been externally
>       modifiied (by s0) is has s1's 'copy' has become stale as a result

  I dont think that here should be an error, since the last saved 
(commited) version  of the rootNode is from s1 and the changes from s0 
has not been valid and not commited. so the nodes state has not changed.

> we'll fix that asap.

Thanks for the discussion. Now I unterstand jackrabbits way of doing. 
But in my opinion adding child nodes should not alter the parent node 
itself. Just changing some properties is a state change.

Furthermore there should be an error just in the case, that both updates 
overwrite the changes of the other -> to prevent lost update problems.
In my example code it´s not the case, so I would prefer no error at all.
What do you think?

cheers,
Walter

Re: concurrency problem

Posted by Stefan Guggisberg <st...@gmail.com>.
On 8/8/05, Nicolas Belisle <Ni...@bibl.ulaval.ca> wrote:
> Hi Walter,
> 
> The problem is that the root Node is concurrently read & modified.
> 
> Case :
> s0 : Read the rootNode
> s1 : Read the rootNode
> s0 : Modify rootNode : remove testnode-s0 & save()
> s1 : Modify rootNode : remove testnode-s1 & save() -->ERROR the rootNode
> contains a reference to an removed node : "testnode-s0"
> 
> Note: session.save() justs saves the root Node under the covers. If you put
> your nodes in a structure like /s0/testnode-s0 your test will succeed.
> 
> Am I making sense ? or I also get damaged by to much sun in my vacation :-) ?

hehe;)

you're absolutely making sense.  the reason why the test fails is concurrent 
modifications. currently the wrong exceptions are thrown. 

the correct beahviour should be:

s0 : Read the rootNode
s1 : Read the rootNode
s0 : Modify rootNode : remove testnode-s0
s1 : Modify rootNode : remove testnode-s1 & save() -->ERROR the rootNode
s0 : save()
s1 : save() -->InvalidItemStateException since the root node has been externally
      modifiied (by s0) is has s1's 'copy' has become stale as a result

we'll fix that asap.

btw: you can avoid this situation if you lock the node beforehand.

cheers
stefan

> contains a reference to an removed node : "testnode-s0"
> 
> I also detailed some problems I had with concurrent sessions in the
> following thread :
> http://www.mail-archive.com/jackrabbit-dev@incubator.apache.org/msg01677.html
> 
> I do agree that this behavior is a bit strange (why addNode() does not
> produce the same exceptions?)...

Node.addNode() is a transient modification without affecting shared state.

cheers
stefan

> 
> 
> Regards,
> 
> Nicolas
> 
> 
> Le 12:02 2005-08-06, vous avez écrit:
> >Hi all,
> >
> >I wrote a simple test to simulate some concurrent sessions. But the test
> >fails with exceptions. Is this a bug or do I get damaged by to much sun in
> >my short vacation?
> >
> >It happens with CQFileSystem and LocalFileSystem with all persistence
> >managers.
> >
> >cheers,
> >Walter
> >
> >--
> >run 1 (empty repository):
> >=========================
> >s0: started.
> >s1: started.
> >s2: started.
> >s3: started.
> >s4: started.
> >.................................................s0: ended.
> >.s1: ended.
> >s2: ended.
> >s3: ended.
> >s4: ended.
> >
> >
> >run 2 (data from run 1):
> >========================
> >s0: started.
> >s1: started.
> >s2: started.
> >s3: started.
> >s4: started.
> >s2: Exception: removing testnode
> >javax.jcr.nodetype.ConstraintViolationException:
> >3b2fe68b-7747-459d-92b2-216b0af472e2 needs to be saved as well.
> >         at org.apache.jackrabbit.core.ItemImpl.save(ItemImpl.java:1289)
> >         at org.apache.jackrabbit.core.SessionImpl.save(SessionImpl.java:747)
> >         at TestSession.run(TestSession.java:61)
> >         at java.lang.Thread.run(Unknown Source)
> >s3: Exception: removing testnode
> >javax.jcr.nodetype.ConstraintViolationException:
> >3b2fe68b-7747-459d-92b2-216b0af472e2 needs to be saved as well.
> >         at org.apache.jackrabbit.core.ItemImpl.save(ItemImpl.java:1289)
> >         at org.apache.jackrabbit.core.SessionImpl.save(SessionImpl.java:747)
> >         at TestSession.run(TestSession.java:61)
> >         at java.lang.Thread.run(Unknown Source)
> >s3: ended.
> >s2: ended.
> >s4: Exception: removing testnode
> >javax.jcr.nodetype.ConstraintViolationException:
> >1dca23f9-e6d5-47b3-830c-a272b9387925 needs to be saved as well.
> >         at org.apache.jackrabbit.core.ItemImpl.save(ItemImpl.java:1289)
> >         at org.apache.jackrabbit.core.SessionImpl.save(SessionImpl.java:747)
> >         at TestSession.run(TestSession.java:61)
> >         at java.lang.Thread.run(Unknown Source)
> >s4: ended.
> >s0: Exception: adding testnode
> >javax.jcr.ItemNotFoundException: 3b2fe68b-7747-459d-92b2-216b0af472e2
> >         at
> > org.apache.jackrabbit.core.ItemManager.createItemInstance(ItemManager.java:498)
> >         at
> > org.apache.jackrabbit.core.ItemManager.getItem(ItemManager.java:349)
> >         at
> > org.apache.jackrabbit.core.NodeImpl.internalAddChildNode(NodeImpl.java:781)
> >         at
> > org.apache.jackrabbit.core.NodeImpl.internalAddNode(NodeImpl.java:725)
> >         at
> > org.apache.jackrabbit.core.NodeImpl.internalAddNode(NodeImpl.java:672)
> >         at org.apache.jackrabbit.core.NodeImpl.addNode(NodeImpl.java:1721)
> >         at TestSession.run(TestSession.java:69)
> >         at java.lang.Thread.run(Unknown Source)
> >s0: ended.
> >..........s1: ended.
> >
> >
> >Source:
> >=======
> >
> >import javax.jcr.Node;
> >import javax.jcr.NodeIterator;
> >import javax.jcr.Property;
> >import javax.jcr.PropertyIterator;
> >import javax.jcr.Repository;
> >import javax.jcr.RepositoryException;
> >import javax.jcr.Session;
> >import javax.jcr.SimpleCredentials;
> >import javax.jcr.Value;
> >
> >import org.apache.jackrabbit.core.RepositoryImpl;
> >import org.apache.jackrabbit.core.config.RepositoryConfig;
> >
> >public class JackRabbitTest {
> >
> >         public static void performanceTest(Repository r) {
> >                 try {
> >                         for( int i=0; i<5; i++ ) {
> >                                 Session session = r.login(new
> > SimpleCredentials("admin", "".toCharArray()), null);
> >                                 TestSession ts = new TestSession("s" + i,
> > session);
> >                                 Thread th = new Thread(ts);
> >                                 th.start();
> >                                 Thread.sleep(100);
> >                         }
> >                 } catch (Exception e){
> >                         System.err.println(e);
> >                     e.printStackTrace();
> >                 }
> >         }
> >
> >         public static void main(String[] args) {
> >                 try {
> >                       String configFile = "repository.xml";
> >                       String repHomeDir = "repository.home";
> >
> >                       RepositoryConfig c =
> > RepositoryConfig.create(configFile, repHomeDir);
> >                       Repository r = RepositoryImpl.create(c);
> >
> >                       performanceTest(r);
> >                     } catch (Exception e){
> >                       System.err.println(e);
> >                       e.printStackTrace();
> >                     }
> >         }
> >}
> >------------
> >import java.util.Random;
> >
> >import javax.jcr.ItemNotFoundException;
> >import javax.jcr.Node;
> >import javax.jcr.Session;
> >import javax.jcr.lock.Lock;
> >
> >import org.apache.jackrabbit.value.StringValue;
> >
> >public class TestSession implements Runnable {
> >
> >         Session session;
> >         String identity;
> >         Random r;
> >
> >         TestSession( String identity, Session s ) {
> >                 this.session = s;
> >                 this.identity = identity;
> >                 r = new Random();
> >         }
> >
> >         private void debug(String msg) {
> >                 System.out.println( identity + ": " + msg);
> >         }
> >
> >         private void sleep() {
> >                 long l = r.nextInt(900)+200;
> >                 try {
> >                         Thread.sleep( l );
> >                 } catch(InterruptedException ie) {
> >                 }
> >         }
> >
> >         public void run() {
> >
> >                 debug("started.");
> >                 String state = "";
> >                 try {
> >                         Node rn = session.getRootNode();
> >
> >                         state = "searching testnode";
> >                         if (rn.hasNode("testnode-" + identity)) {
> >                         try {
> >                                 state = "removing testnode";
> >                                 rn.getNode("testnode-" + identity).remove();
> >                                 session.save();
> >                                 sleep();
> >                         } catch(ItemNotFoundException infe) {
> >                                 debug("error while removing testnode " +
> > identity);
> >                                 infe.printStackTrace();
> >                         }
> >                     }
> >                 state = "adding testnode";
> >                     Node n = rn.addNode("testnode-" + identity ,
> > "nt:unstructured");
> >
> >                     session.save();
> >                     state = "setting property";
> >                     n.setProperty("testprop", new StringValue("Hello
> > World!"));
> >                     session.save();
> >                     sleep();
> >
> >                     for(int i=0; i<100; i++) {
> >                         state = "adding subnode " + i;
> >                         n.addNode("x" + i, "nt:unstructured");
> >                         state = "adding property to subnode " + i;
> >                         n.setProperty("testprop","xxx");
> >                         if(i%10==0)     {
> >                                 state = "saving pending subnodes";
> >                                 session.save();
> >                                 System.out.print(".");
> >                         }
> >                         sleep();
> >                     }
> >                     session.save();
> >
> >                 } catch( Exception e) {
> >                         debug("Exception: " + state);
> >                         e.printStackTrace();
> >                 } finally {
> >                         session.logout();
> >                 }
> >
> >                 debug("ended.");
> >         }
> >}
> >
> >
> 
>

Re: concurrency problem

Posted by Nicolas Belisle <Ni...@bibl.ulaval.ca>.
Hi Walter,

The problem is that the root Node is concurrently read & modified.

Case :
s0 : Read the rootNode
s1 : Read the rootNode
s0 : Modify rootNode : remove testnode-s0 & save()
s1 : Modify rootNode : remove testnode-s1 & save() -->ERROR the rootNode 
contains a reference to an removed node : "testnode-s0"

Note: session.save() justs saves the root Node under the covers. If you put 
your nodes in a structure like /s0/testnode-s0 your test will succeed.

Am I making sense ? or I also get damaged by to much sun in my vacation :-) ?

I also detailed some problems I had with concurrent sessions in the 
following thread : 
http://www.mail-archive.com/jackrabbit-dev@incubator.apache.org/msg01677.html

I do agree that this behavior is a bit strange (why addNode() does not 
produce the same exceptions?)...


Regards,

Nicolas


Le 12:02 2005-08-06, vous avez écrit:
>Hi all,
>
>I wrote a simple test to simulate some concurrent sessions. But the test 
>fails with exceptions. Is this a bug or do I get damaged by to much sun in 
>my short vacation?
>
>It happens with CQFileSystem and LocalFileSystem with all persistence 
>managers.
>
>cheers,
>Walter
>
>--
>run 1 (empty repository):
>=========================
>s0: started.
>s1: started.
>s2: started.
>s3: started.
>s4: started.
>.................................................s0: ended.
>.s1: ended.
>s2: ended.
>s3: ended.
>s4: ended.
>
>
>run 2 (data from run 1):
>========================
>s0: started.
>s1: started.
>s2: started.
>s3: started.
>s4: started.
>s2: Exception: removing testnode
>javax.jcr.nodetype.ConstraintViolationException: 
>3b2fe68b-7747-459d-92b2-216b0af472e2 needs to be saved as well.
>         at org.apache.jackrabbit.core.ItemImpl.save(ItemImpl.java:1289)
>         at org.apache.jackrabbit.core.SessionImpl.save(SessionImpl.java:747)
>         at TestSession.run(TestSession.java:61)
>         at java.lang.Thread.run(Unknown Source)
>s3: Exception: removing testnode
>javax.jcr.nodetype.ConstraintViolationException: 
>3b2fe68b-7747-459d-92b2-216b0af472e2 needs to be saved as well.
>         at org.apache.jackrabbit.core.ItemImpl.save(ItemImpl.java:1289)
>         at org.apache.jackrabbit.core.SessionImpl.save(SessionImpl.java:747)
>         at TestSession.run(TestSession.java:61)
>         at java.lang.Thread.run(Unknown Source)
>s3: ended.
>s2: ended.
>s4: Exception: removing testnode
>javax.jcr.nodetype.ConstraintViolationException: 
>1dca23f9-e6d5-47b3-830c-a272b9387925 needs to be saved as well.
>         at org.apache.jackrabbit.core.ItemImpl.save(ItemImpl.java:1289)
>         at org.apache.jackrabbit.core.SessionImpl.save(SessionImpl.java:747)
>         at TestSession.run(TestSession.java:61)
>         at java.lang.Thread.run(Unknown Source)
>s4: ended.
>s0: Exception: adding testnode
>javax.jcr.ItemNotFoundException: 3b2fe68b-7747-459d-92b2-216b0af472e2
>         at 
> org.apache.jackrabbit.core.ItemManager.createItemInstance(ItemManager.java:498)
>         at 
> org.apache.jackrabbit.core.ItemManager.getItem(ItemManager.java:349)
>         at 
> org.apache.jackrabbit.core.NodeImpl.internalAddChildNode(NodeImpl.java:781)
>         at 
> org.apache.jackrabbit.core.NodeImpl.internalAddNode(NodeImpl.java:725)
>         at 
> org.apache.jackrabbit.core.NodeImpl.internalAddNode(NodeImpl.java:672)
>         at org.apache.jackrabbit.core.NodeImpl.addNode(NodeImpl.java:1721)
>         at TestSession.run(TestSession.java:69)
>         at java.lang.Thread.run(Unknown Source)
>s0: ended.
>..........s1: ended.
>
>
>Source:
>=======
>
>import javax.jcr.Node;
>import javax.jcr.NodeIterator;
>import javax.jcr.Property;
>import javax.jcr.PropertyIterator;
>import javax.jcr.Repository;
>import javax.jcr.RepositoryException;
>import javax.jcr.Session;
>import javax.jcr.SimpleCredentials;
>import javax.jcr.Value;
>
>import org.apache.jackrabbit.core.RepositoryImpl;
>import org.apache.jackrabbit.core.config.RepositoryConfig;
>
>public class JackRabbitTest {
>
>         public static void performanceTest(Repository r) {
>                 try {
>                         for( int i=0; i<5; i++ ) {
>                                 Session session = r.login(new 
> SimpleCredentials("admin", "".toCharArray()), null);
>                                 TestSession ts = new TestSession("s" + i, 
> session);
>                                 Thread th = new Thread(ts);
>                                 th.start();
>                                 Thread.sleep(100);
>                         }
>                 } catch (Exception e){
>                         System.err.println(e);
>                     e.printStackTrace();
>                 }
>         }
>
>         public static void main(String[] args) {
>                 try {
>                       String configFile = "repository.xml";
>                       String repHomeDir = "repository.home";
>
>                       RepositoryConfig c = 
> RepositoryConfig.create(configFile, repHomeDir);
>                       Repository r = RepositoryImpl.create(c);
>
>                       performanceTest(r);
>                     } catch (Exception e){
>                       System.err.println(e);
>                       e.printStackTrace();
>                     }
>         }
>}
>------------
>import java.util.Random;
>
>import javax.jcr.ItemNotFoundException;
>import javax.jcr.Node;
>import javax.jcr.Session;
>import javax.jcr.lock.Lock;
>
>import org.apache.jackrabbit.value.StringValue;
>
>public class TestSession implements Runnable {
>
>         Session session;
>         String identity;
>         Random r;
>
>         TestSession( String identity, Session s ) {
>                 this.session = s;
>                 this.identity = identity;
>                 r = new Random();
>         }
>
>         private void debug(String msg) {
>                 System.out.println( identity + ": " + msg);
>         }
>
>         private void sleep() {
>                 long l = r.nextInt(900)+200;
>                 try {
>                         Thread.sleep( l );
>                 } catch(InterruptedException ie) {
>                 }
>         }
>
>         public void run() {
>
>                 debug("started.");
>                 String state = "";
>                 try {
>                         Node rn = session.getRootNode();
>
>                         state = "searching testnode";
>                         if (rn.hasNode("testnode-" + identity)) {
>                         try {
>                                 state = "removing testnode";
>                                 rn.getNode("testnode-" + identity).remove();
>                                 session.save();
>                                 sleep();
>                         } catch(ItemNotFoundException infe) {
>                                 debug("error while removing testnode " + 
> identity);
>                                 infe.printStackTrace();
>                         }
>                     }
>                 state = "adding testnode";
>                     Node n = rn.addNode("testnode-" + identity , 
> "nt:unstructured");
>
>                     session.save();
>                     state = "setting property";
>                     n.setProperty("testprop", new StringValue("Hello 
> World!"));
>                     session.save();
>                     sleep();
>
>                     for(int i=0; i<100; i++) {
>                         state = "adding subnode " + i;
>                         n.addNode("x" + i, "nt:unstructured");
>                         state = "adding property to subnode " + i;
>                         n.setProperty("testprop","xxx");
>                         if(i%10==0)     {
>                                 state = "saving pending subnodes";
>                                 session.save();
>                                 System.out.print(".");
>                         }
>                         sleep();
>                     }
>                     session.save();
>
>                 } catch( Exception e) {
>                         debug("Exception: " + state);
>                         e.printStackTrace();
>                 } finally {
>                         session.logout();
>                 }
>
>                 debug("ended.");
>         }
>}
>
>


Re: concurrency problem

Posted by Stefan Guggisberg <st...@gmail.com>.
hi walter,
thanks, i'll have a look at it asap.

cheers
stefan

On 8/6/05, Walter Raboch <wr...@ingen.at> wrote:
> Hi all,
> 
> I wrote a simple test to simulate some concurrent sessions. But the test
> fails with exceptions. Is this a bug or do I get damaged by to much sun
> in my short vacation?
> 
> It happens with CQFileSystem and LocalFileSystem with all persistence
> managers.
> 
> cheers,
> Walter
> 
> --
> run 1 (empty repository):
> =========================
> s0: started.
> s1: started.
> s2: started.
> s3: started.
> s4: started.
> .................................................s0: ended.
> .s1: ended.
> s2: ended.
> s3: ended.
> s4: ended.
> 
> 
> run 2 (data from run 1):
> ========================
> s0: started.
> s1: started.
> s2: started.
> s3: started.
> s4: started.
> s2: Exception: removing testnode
> javax.jcr.nodetype.ConstraintViolationException:
> 3b2fe68b-7747-459d-92b2-216b0af472e2 needs to be saved as well.
>         at org.apache.jackrabbit.core.ItemImpl.save(ItemImpl.java:1289)
>         at org.apache.jackrabbit.core.SessionImpl.save(SessionImpl.java:747)
>         at TestSession.run(TestSession.java:61)
>         at java.lang.Thread.run(Unknown Source)
> s3: Exception: removing testnode
> javax.jcr.nodetype.ConstraintViolationException:
> 3b2fe68b-7747-459d-92b2-216b0af472e2 needs to be saved as well.
>         at org.apache.jackrabbit.core.ItemImpl.save(ItemImpl.java:1289)
>         at org.apache.jackrabbit.core.SessionImpl.save(SessionImpl.java:747)
>         at TestSession.run(TestSession.java:61)
>         at java.lang.Thread.run(Unknown Source)
> s3: ended.
> s2: ended.
> s4: Exception: removing testnode
> javax.jcr.nodetype.ConstraintViolationException:
> 1dca23f9-e6d5-47b3-830c-a272b9387925 needs to be saved as well.
>         at org.apache.jackrabbit.core.ItemImpl.save(ItemImpl.java:1289)
>         at org.apache.jackrabbit.core.SessionImpl.save(SessionImpl.java:747)
>         at TestSession.run(TestSession.java:61)
>         at java.lang.Thread.run(Unknown Source)
> s4: ended.
> s0: Exception: adding testnode
> javax.jcr.ItemNotFoundException: 3b2fe68b-7747-459d-92b2-216b0af472e2
>         at
> org.apache.jackrabbit.core.ItemManager.createItemInstance(ItemManager.java:498)
>         at org.apache.jackrabbit.core.ItemManager.getItem(ItemManager.java:349)
>         at
> org.apache.jackrabbit.core.NodeImpl.internalAddChildNode(NodeImpl.java:781)
>         at org.apache.jackrabbit.core.NodeImpl.internalAddNode(NodeImpl.java:725)
>         at org.apache.jackrabbit.core.NodeImpl.internalAddNode(NodeImpl.java:672)
>         at org.apache.jackrabbit.core.NodeImpl.addNode(NodeImpl.java:1721)
>         at TestSession.run(TestSession.java:69)
>         at java.lang.Thread.run(Unknown Source)
> s0: ended.
> ..........s1: ended.
> 
> 
> Source:
> =======
> 
> import javax.jcr.Node;
> import javax.jcr.NodeIterator;
> import javax.jcr.Property;
> import javax.jcr.PropertyIterator;
> import javax.jcr.Repository;
> import javax.jcr.RepositoryException;
> import javax.jcr.Session;
> import javax.jcr.SimpleCredentials;
> import javax.jcr.Value;
> 
> import org.apache.jackrabbit.core.RepositoryImpl;
> import org.apache.jackrabbit.core.config.RepositoryConfig;
> 
> public class JackRabbitTest {
> 
>         public static void performanceTest(Repository r) {
>                 try {
>                         for( int i=0; i<5; i++ ) {
>                                 Session session = r.login(new SimpleCredentials("admin",
> "".toCharArray()), null);
>                                 TestSession ts = new TestSession("s" + i, session);
>                                 Thread th = new Thread(ts);
>                                 th.start();
>                                 Thread.sleep(100);
>                         }
>                 } catch (Exception e){
>                         System.err.println(e);
>                     e.printStackTrace();
>                 }
>         }
> 
>         public static void main(String[] args) {
>                  try {
>                       String configFile = "repository.xml";
>                       String repHomeDir = "repository.home";
> 
>                       RepositoryConfig c = RepositoryConfig.create(configFile,
> repHomeDir);
>                       Repository r = RepositoryImpl.create(c);
> 
>                       performanceTest(r);
>                     } catch (Exception e){
>                       System.err.println(e);
>                       e.printStackTrace();
>                     }
>         }
> }
> ------------
> import java.util.Random;
> 
> import javax.jcr.ItemNotFoundException;
> import javax.jcr.Node;
> import javax.jcr.Session;
> import javax.jcr.lock.Lock;
> 
> import org.apache.jackrabbit.value.StringValue;
> 
> public class TestSession implements Runnable {
> 
>         Session session;
>         String identity;
>         Random r;
> 
>         TestSession( String identity, Session s ) {
>                 this.session = s;
>                 this.identity = identity;
>                 r = new Random();
>         }
> 
>         private void debug(String msg) {
>                 System.out.println( identity + ": " + msg);
>         }
> 
>         private void sleep() {
>                 long l = r.nextInt(900)+200;
>                 try {
>                         Thread.sleep( l );
>                 } catch(InterruptedException ie) {
>                 }
>         }
> 
>         public void run() {
> 
>                 debug("started.");
>                 String state = "";
>                 try {
>                         Node rn = session.getRootNode();
> 
>                         state = "searching testnode";
>                         if (rn.hasNode("testnode-" + identity)) {
>                         try {
>                                 state = "removing testnode";
>                                 rn.getNode("testnode-" + identity).remove();
>                                 session.save();
>                                 sleep();
>                         } catch(ItemNotFoundException infe) {
>                                 debug("error while removing testnode " + identity);
>                                 infe.printStackTrace();
>                         }
>                     }
>                 state = "adding testnode";
>                     Node n = rn.addNode("testnode-" + identity , "nt:unstructured");
> 
>                     session.save();
>                     state = "setting property";
>                     n.setProperty("testprop", new StringValue("Hello World!"));
>                     session.save();
>                     sleep();
> 
>                     for(int i=0; i<100; i++) {
>                         state = "adding subnode " + i;
>                         n.addNode("x" + i, "nt:unstructured");
>                         state = "adding property to subnode " + i;
>                         n.setProperty("testprop","xxx");
>                         if(i%10==0)     {
>                                 state = "saving pending subnodes";
>                                 session.save();
>                                 System.out.print(".");
>                         }
>                         sleep();
>                     }
>                     session.save();
> 
>                 } catch( Exception e) {
>                         debug("Exception: " + state);
>                         e.printStackTrace();
>                 } finally {
>                         session.logout();
>                 }
> 
>                 debug("ended.");
>         }
> }
> 
> 
> 
>