You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@jackrabbit.apache.org by Robert Shiner <ra...@googlemail.com> on 2006/04/20 12:53:45 UTC

Concurrent modifications ...

Hi,

I wonder if you can help me.

I would like to write some code that adds a folder to a parent, but I want
to do this in such a way that it will work during concurrent modifications.

The code I currently have is as follows ...

  // Start the session
  Session session = repository.login(new SimpleCredentials("admin",
"admin".toCharArray()));
  try
  {
      // Get the root node for now
      Node rootNode = session.getRootNode();

     // Wait untill a lock is available on the parent folder
     boolean hasLock = false;
     while (hasLock == false)
     {
        if (folder.isLocked() == false)
        {
           try
           {
              // Take the lock out on the parent
              folder.lock(false, true);
              hasLock = true;
           }
           catch (Exception exception)
           {
              // Ignore and retry
           }
        }

         Thread.yield();
      }

      // Add the new folder
      rootNode.addNode ("testFolder_" + System.currentTimeMillis(),
"nt:folder");

      // Save the session
      session.save();
  }
  finally
  {
      // Log out, lock is revoked
      session.logout();
  }

I have a couple of questions:

1)  Is this pattern ok or is there a better way to do things?
2)  I have assumed that the parent node (the root node in this example) is
lockable.  If it isn't what is the best way to apply the lockable aspect in
a concurrent safe way?

I'm new to JackRabbit and trying to evaluate its capabilities.  Any help or
feedback will be gratefully received.

Thanks in advance,
Bob

Re: Concurrent modifications ...

Posted by Robert Shiner <ra...@googlemail.com>.
Marcel,

Thanks for your quick response,

Bob

On 4/21/06, Marcel Reutegger <ma...@gmx.net> wrote:
>
> Robert Shiner wrote:
> > Yup, that seems to work, thanks.  Although not against 1.0, I needed to
> > checkout and build the latest snapshot.
>
> oh, you are right. thanks for pointing that out. the related issue is:
> JCR-336.
>
> > Does anyone know when the next release with the lock fixes in is due?
> >
> > Also I have a question around applying the lockable mixin.
> >
> > I understand that a node can not be locked unless it has the lockable
> mixin
> > applied.
>
> IMO a good node type design already has the mix:lockable mixin in its
> definition for nodes that should be lockable. with such a design it is
> then not necessary for an application to add mixins on node instances.
>
> > If I want to lock a node, but I'm not sure whether it already has
> > the lockable mixin, how can I check and then add the mixin in such a way
> > that is safe in a concurrent environment?
>
> node.isNodeType("mix:lockable") will return true if it is lockable.
>
> you need to aquire a deep lock on a lockable ancestor of that node then
> you can add a mixin to the desired node. but as I pointed out before I
> suggest you do not add mixins to individual node instances but define
> lockable mixins in your type hierarchy.
>
> regards
>   marcel
>

Re: Concurrent modifications ...

Posted by Marcel Reutegger <ma...@gmx.net>.
Robert Shiner wrote:
> Yup, that seems to work, thanks.  Although not against 1.0, I needed to
> checkout and build the latest snapshot.

oh, you are right. thanks for pointing that out. the related issue is: 
JCR-336.

> Does anyone know when the next release with the lock fixes in is due?
> 
> Also I have a question around applying the lockable mixin.
> 
> I understand that a node can not be locked unless it has the lockable mixin
> applied.

IMO a good node type design already has the mix:lockable mixin in its 
definition for nodes that should be lockable. with such a design it is 
then not necessary for an application to add mixins on node instances.

> If I want to lock a node, but I'm not sure whether it already has
> the lockable mixin, how can I check and then add the mixin in such a way
> that is safe in a concurrent environment?

node.isNodeType("mix:lockable") will return true if it is lockable.

you need to aquire a deep lock on a lockable ancestor of that node then 
you can add a mixin to the desired node. but as I pointed out before I 
suggest you do not add mixins to individual node instances but define 
lockable mixins in your type hierarchy.

regards
  marcel

Re: Concurrent modifications ...

Posted by Robert Shiner <ra...@googlemail.com>.
Hi,

Yup, that seems to work, thanks.  Although not against 1.0, I needed to
checkout and build the latest snapshot.

Does anyone know when the next release with the lock fixes in is due?

Also I have a question around applying the lockable mixin.

I understand that a node can not be locked unless it has the lockable mixin
applied.  If I want to lock a node, but I'm not sure whether it already has
the lockable mixin, how can I check and then add the mixin in such a way
that is safe in a concurrent environment?

Thanks for you help with this, I appreciate you are all busy guys!

Thanks,
Bob

On 4/20/06, Robert Shiner <ra...@googlemail.com> wrote:
>
> Thanks Marcel,
>
> I'll give that a try.
>
> Bob
>
>
> On 4/20/06, Marcel Reutegger <ma...@gmx.net> wrote:
> >
> > Hi Bob,
> >
> > in general your code should work, but the while loop is more or less a
> > busy wait. that is your cpu will go to 100% while waiting for the lock.
> >
> > There is a utility in jackrabbit that you can use to achieve exactly
> > what you are trying to do:
> > org.apache.jackrabbit.util.Locked
> >
> > here's an example how to use it:
> >
> > final Node n = .... // the node where you want to add a folder
> > Node folder = (Node) new Locked() {
> >      protected Object run() throws RepositoryException {
> >          Node f = n.addNode("testFolder_" + System.currentTimeMillis(),
> > "nt:folder");
> >          n.save();
> >          return f;
> >      }
> > }.with(n, false);
> > // do something with the newly created folder
> > folder.getPath();
> >
> > The utility however is not included in the jackrabbit 1.0 release. You
> > have to look it up in the jackrabbit svn trunk or build jackrabbit from
> > trunk.
> >
> > regards
> >   marcel
> >
> > Robert Shiner wrote:
> > > Hi,
> > >
> > > I wonder if you can help me.
> > >
> > > I would like to write some code that adds a folder to a parent, but I
> > want
> > > to do this in such a way that it will work during concurrent
> > modifications.
> > >
> > > The code I currently have is as follows ...
> > >
> > >   // Start the session
> > >   Session session = repository.login(new SimpleCredentials("admin",
> > > "admin".toCharArray()));
> > >   try
> > >   {
> > >       // Get the root node for now
> > >       Node rootNode = session.getRootNode();
> > >
> > >      // Wait untill a lock is available on the parent folder
> > >      boolean hasLock = false;
> > >      while (hasLock == false)
> > >      {
> > >         if (folder.isLocked() == false)
> > >         {
> > >            try
> > >            {
> > >               // Take the lock out on the parent
> > >               folder.lock(false, true);
> > >               hasLock = true;
> > >            }
> > >            catch (Exception exception)
> > >            {
> > >               // Ignore and retry
> > >            }
> > >         }
> > >
> > >          Thread.yield();
> > >       }
> > >
> > >       // Add the new folder
> > >       rootNode.addNode ("testFolder_" + System.currentTimeMillis(),
> > > "nt:folder");
> > >
> > >       // Save the session
> > >       session.save();
> > >   }
> > >   finally
> > >   {
> > >       // Log out, lock is revoked
> > >       session.logout();
> > >   }
> > >
> > > I have a couple of questions:
> > >
> > > 1)  Is this pattern ok or is there a better way to do things?
> > > 2)  I have assumed that the parent node (the root node in this
> > example) is
> > > lockable.  If it isn't what is the best way to apply the lockable
> > aspect in
> > > a concurrent safe way?
> > >
> > > I'm new to JackRabbit and trying to evaluate its capabilities.  Any
> > help or
> > > feedback will be gratefully received.
> > >
> > > Thanks in advance,
> > > Bob
> > >
> >
> >
>

Re: Concurrent modifications ...

Posted by Robert Shiner <ra...@googlemail.com>.
Thanks Marcel,

I'll give that a try.

Bob

On 4/20/06, Marcel Reutegger <ma...@gmx.net> wrote:
>
> Hi Bob,
>
> in general your code should work, but the while loop is more or less a
> busy wait. that is your cpu will go to 100% while waiting for the lock.
>
> There is a utility in jackrabbit that you can use to achieve exactly
> what you are trying to do:
> org.apache.jackrabbit.util.Locked
>
> here's an example how to use it:
>
> final Node n = .... // the node where you want to add a folder
> Node folder = (Node) new Locked() {
>      protected Object run() throws RepositoryException {
>          Node f = n.addNode("testFolder_" + System.currentTimeMillis(),
> "nt:folder");
>          n.save();
>          return f;
>      }
> }.with(n, false);
> // do something with the newly created folder
> folder.getPath();
>
> The utility however is not included in the jackrabbit 1.0 release. You
> have to look it up in the jackrabbit svn trunk or build jackrabbit from
> trunk.
>
> regards
>   marcel
>
> Robert Shiner wrote:
> > Hi,
> >
> > I wonder if you can help me.
> >
> > I would like to write some code that adds a folder to a parent, but I
> want
> > to do this in such a way that it will work during concurrent
> modifications.
> >
> > The code I currently have is as follows ...
> >
> >   // Start the session
> >   Session session = repository.login(new SimpleCredentials("admin",
> > "admin".toCharArray()));
> >   try
> >   {
> >       // Get the root node for now
> >       Node rootNode = session.getRootNode();
> >
> >      // Wait untill a lock is available on the parent folder
> >      boolean hasLock = false;
> >      while (hasLock == false)
> >      {
> >         if (folder.isLocked() == false)
> >         {
> >            try
> >            {
> >               // Take the lock out on the parent
> >               folder.lock(false, true);
> >               hasLock = true;
> >            }
> >            catch (Exception exception)
> >            {
> >               // Ignore and retry
> >            }
> >         }
> >
> >          Thread.yield();
> >       }
> >
> >       // Add the new folder
> >       rootNode.addNode ("testFolder_" + System.currentTimeMillis(),
> > "nt:folder");
> >
> >       // Save the session
> >       session.save();
> >   }
> >   finally
> >   {
> >       // Log out, lock is revoked
> >       session.logout();
> >   }
> >
> > I have a couple of questions:
> >
> > 1)  Is this pattern ok or is there a better way to do things?
> > 2)  I have assumed that the parent node (the root node in this example)
> is
> > lockable.  If it isn't what is the best way to apply the lockable aspect
> in
> > a concurrent safe way?
> >
> > I'm new to JackRabbit and trying to evaluate its capabilities.  Any help
> or
> > feedback will be gratefully received.
> >
> > Thanks in advance,
> > Bob
> >
>
>

Re: Concurrent modifications ...

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

in general your code should work, but the while loop is more or less a 
busy wait. that is your cpu will go to 100% while waiting for the lock.

There is a utility in jackrabbit that you can use to achieve exactly 
what you are trying to do:
org.apache.jackrabbit.util.Locked

here's an example how to use it:

final Node n = .... // the node where you want to add a folder
Node folder = (Node) new Locked() {
     protected Object run() throws RepositoryException {
         Node f = n.addNode("testFolder_" + System.currentTimeMillis(), 
"nt:folder");
         n.save();
         return f;
     }
}.with(n, false);
// do something with the newly created folder
folder.getPath();

The utility however is not included in the jackrabbit 1.0 release. You 
have to look it up in the jackrabbit svn trunk or build jackrabbit from 
trunk.

regards
  marcel

Robert Shiner wrote:
> Hi,
> 
> I wonder if you can help me.
> 
> I would like to write some code that adds a folder to a parent, but I want
> to do this in such a way that it will work during concurrent modifications.
> 
> The code I currently have is as follows ...
> 
>   // Start the session
>   Session session = repository.login(new SimpleCredentials("admin",
> "admin".toCharArray()));
>   try
>   {
>       // Get the root node for now
>       Node rootNode = session.getRootNode();
> 
>      // Wait untill a lock is available on the parent folder
>      boolean hasLock = false;
>      while (hasLock == false)
>      {
>         if (folder.isLocked() == false)
>         {
>            try
>            {
>               // Take the lock out on the parent
>               folder.lock(false, true);
>               hasLock = true;
>            }
>            catch (Exception exception)
>            {
>               // Ignore and retry
>            }
>         }
> 
>          Thread.yield();
>       }
> 
>       // Add the new folder
>       rootNode.addNode ("testFolder_" + System.currentTimeMillis(),
> "nt:folder");
> 
>       // Save the session
>       session.save();
>   }
>   finally
>   {
>       // Log out, lock is revoked
>       session.logout();
>   }
> 
> I have a couple of questions:
> 
> 1)  Is this pattern ok or is there a better way to do things?
> 2)  I have assumed that the parent node (the root node in this example) is
> lockable.  If it isn't what is the best way to apply the lockable aspect in
> a concurrent safe way?
> 
> I'm new to JackRabbit and trying to evaluate its capabilities.  Any help or
> feedback will be gratefully received.
> 
> Thanks in advance,
> Bob
>