5 Replies Latest reply on Sep 4, 2012 1:27 PM by Erik Salter

    Lock that doesn't lock?!

    Amit Lieberman Newbie

      Hi,

      i'm using infinispan to lock a stateless session bean. I expect that only one thread will be able to got insinde the lock code in the cluster.

      Surprisingly enough, even with one jboss running standalone configuration I get two threads inside the lock for the same key

       

      code:

       

      {code}

          @AroundInvoke
          public Object lock(final InvocationContext context) throws Exception {
              try{
                  // Getting the lock
                  boolean lock = cache.lock(SERIAL_ACTION_PIPE_LOCK_STRING);
                  if (!lock){
                      throw new L4MException("Failed to obtain lock for SerialActionPipe");
                  }else {
                      return context.proceed();
                  }
              }finally {

       

                  // Unlocking
                  LockManager lockManager = cache.getLockManager();
                  Object owner = lockManager.getOwner(SERIAL_ACTION_PIPE_LOCK_STRING);
                  if (owner != null){
                      lockManager.unlock(Arrays.<Object>asList(SERIAL_ACTION_PIPE_LOCK_STRING), owner);
                  }
              }
          }

       

       

      {code}

       

       

       

       

      cache definition

       

       

      {code}      

      <local-cache name="ra-serial-action-pipe" start="EAGER">

                          <transaction mode="NON_XA" locking="PESSIMISTIC"/>

                          <eviction strategy="NONE" max-entries="1"/>

                      </local-cache>

      {code}

       

       

      Please advise

          Amit

        • 1. Re: Lock that doesn't lock?!
          Erik Salter Newbie

          Hi Amit,

           

          The lock implementation supports re-entrancy based on owner, and not necessarily on thread boundaries.  The "owner" is normally a GlobalTransaction instance.  So, presuming your JBoss instance corresponds to a single node in your cluster, I would expect this behavior.

           

          However, the LockManager wasn't really designed to be called this way.  Cluster locks were designed to be released on transaction commit or rollback.  So why not try this?

           

           

                  try {

           

                      tm.begin();

                     // Getting the lock

                      boolean lock = cache.lock(SERIAL_ACTION_PIPE_LOCK_STRING);

                      if (!lock){

                          throw new L4MException("Failed to obtain lock for SerialActionPipe");

                      }else {

                          return context.proceed();

                  } catch (Exception e) {

           

                      tm.setRollbackOnly();

                      throw e;

                  }

           

                  finally {

           

                      int status = -1;

                      try {

                          status = tm.getStatus();

                      } catch (Exception e) {

                      }

           

                      if (status == Status.STATUS_ACTIVE) {

                          tm.commit();

                      } else {

                          tm.rollback();

                      }

                  }

              }

          • 2. Re: Lock that doesn't lock?!
            Radai Rosenblatt Newbie

            HI Erik.

             

            so, injesting a UserTransaction into an @EJB that deals with an infinispan cache would allow finer-grained locking ?

            • 3. Re: Lock that doesn't lock?!
              Amit Lieberman Newbie

              Hi Erik,

              When trying to use a user transaction to work with the lock I'm getting:

              : java.lang.IllegalStateException: BaseTransaction.checkTransactionState - ARJUNA016051: thread is already associated with a transaction!

              This code is part of a wider transaction. I only want to acheive a cluster wide lock - not play with the transactions - is there a way to do that with infinispan?

              • 4. Re: Lock that doesn't lock?!
                Mircea Markus Master

                In order to be able to use the AdvancedCache.lock() method the cache needs to be transactional and pessimistic(your cache is like that) and the invocation of the .lock() is required to be peformed in the scope of a transaction. I would expect an exception to be thrown because your code doesn't invoke lock in a tx's context, do you get sucha thing?

                Also don't use the lock methods from cache.getLockManager() as thse are intended for internal reasons.

                • 5. Re: Lock that doesn't lock?!
                  Erik Salter Newbie

                  If it's part of a transaction already, you can call lock() safely.  The lock will then be released on transaction commit or rollback.  The code I posted is a design pattern for illustrating how user code needs to work to use explicit/pessimistic locking.