2 Replies Latest reply on Nov 9, 2009 10:30 PM by Francisco Jose Peredo Noguez

    ReentrantLock: How to know which code succesfully locked something?

    Francisco Jose Peredo Noguez Master

      Hi!


      The @Synchronized annotation makes really easy to serialize access to a particular component, and if the timeout configured for @Synchronized component ends, then it throws an exception like this one:


      
      could not acquire lock on @Synchronized component SomeComponent
      
      



      The stacktrace that comes with that exception makes it easy to know which code was trying to get a lock on the component SomeComponent and failed, but what I would like to know is the the caller (and all the stacktrace) that was the last one to succesfully lock the component SomeComponent.


      Any one knows how to do that?

        • 1. Re: ReentrantLock: How to know which code succesfully locked something?
          Francisco Jose Peredo Noguez Master

          Solved it like this:


          @Interceptor(type=InterceptorType.CLIENT)
          public class ConfigurableSynchronizationInterceptor extends AbstractInterceptor
          {   
                  
               org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(ConfigurableSynchronizationInterceptor.class);
               
               public ConfigurableSynchronizationInterceptor() {
                    log.debug("Constructor");
                    
               }
               
               
               private String getStackTrace(Throwable t)
              {
                  StringWriter sw = new StringWriter();
                  PrintWriter pw = new PrintWriter(sw, true);
                  t.printStackTrace(pw);
                  pw.flush();
                  sw.flush();
                  return sw.toString();
              }
          
               
             /**
                * 
                */
               private static final long serialVersionUID = 6644552930765616337L;
               private ReentrantLock lock = new ReentrantLock(true);
               private String lockedStacktrace;
             
             @AroundInvoke
             public Object aroundInvoke(InvocationContext invocation) throws Exception
             {      
                  log.debug("Will try to get lock for: "+getComponent().getName());
                  SynchronizationConfiguration cfg=(SynchronizationConfiguration) Component.getInstance("synchronizationConfiguration");
                  if ( lock.tryLock( cfg.getSynchronizationTimeOut()/*getComponent().getTimeout()*/, TimeUnit.MILLISECONDS ) )
                {
                   try
                   {
                        lockedStacktrace = this.getStackTrace(new RuntimeException("Succesfully locked stacktrace"));
                        return invocation.proceed();
                   }
                   finally
                   {
                        lockedStacktrace = null;
                        lock.unlock();
                   }
                }
                else
                {           
                     throw new LockTimeoutException("could not acquire lock on @Synchronized component: " + 
                         getComponent().getName()+" because someone else got it at: "+lockedStacktrace);
                }
             }
             
             public boolean isInterceptorEnabled()
             {
                return getComponent().isSynchronize();
             }
          
          }
          



          Basically when I succesfully get the lock I store a string representation of the stacktrace, and, if a component fails to get the lock, I take that stored stacktrace representation and append it to the message of the LockTimeoutException.


          IMO (unless it is wrong), this should be part for Seam core behavior...