View Javadoc

1   /***
2    *  Copyright 2003-2010 Terracotta, Inc.
3    *
4    *  Licensed under the Apache License, Version 2.0 (the "License");
5    *  you may not use this file except in compliance with the License.
6    *  You may obtain a copy of the License at
7    *
8    *      http://www.apache.org/licenses/LICENSE-2.0
9    *
10   *  Unless required by applicable law or agreed to in writing, software
11   *  distributed under the License is distributed on an "AS IS" BASIS,
12   *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   *  See the License for the specific language governing permissions and
14   *  limitations under the License.
15   */
16  
17  package net.sf.ehcache.constructs.nonstop.concurrency;
18  
19  import java.util.concurrent.Callable;
20  
21  import net.sf.ehcache.config.NonstopConfiguration;
22  import net.sf.ehcache.constructs.nonstop.ClusterOperationCallable;
23  import net.sf.ehcache.constructs.nonstop.ThrowTimeoutException;
24  
25  /***
26   *
27   * Callable used with nonstop when explicit lock has been acquired
28   *
29   * @author Abhishek Sanoujam
30   *
31   * @param <V>
32   */
33  public class CacheOperationUnderExplicitLockCallable<V> implements Callable<V> {
34  
35      private final Callable<V> cacheOperationCallable;
36      private final ExplicitLockingContext appThreadLockContext;
37      private final NonstopConfiguration nonstopConfiguration;
38  
39      /***
40       * public constructor
41       *
42       * @param currentThreadLockContext
43       * @param nonstopConfiguration
44       * @param callable
45       */
46      public CacheOperationUnderExplicitLockCallable(ExplicitLockingContext currentThreadLockContext,
47              NonstopConfiguration nonstopConfiguration, Callable<V> callable) {
48          appThreadLockContext = currentThreadLockContext;
49          this.nonstopConfiguration = nonstopConfiguration;
50          cacheOperationCallable = callable;
51      }
52  
53      /***
54       * {@inheritDoc}
55       */
56      public V call() throws Exception {
57          if (isExplicitLockApi()) {
58              // always invoke directly the explicit locking apis
59              return cacheOperationCallable.call();
60          }
61          if (appThreadLockContext.areLocksAcquiredByOtherThreads(NonstopThreadUniqueIdProvider.getCurrentNonstopThreadUniqueId())) {
62              // invalid lock state, some other thread has acquired explicit locks for the app thread corresponding
63              // to this nonstop thread, which can only be another nonstop thread before rejoin.
64              // Meaning rejoin happened and as locks are invalid after rejoin, throw exception if configured
65              switch (nonstopConfiguration.getTimeoutBehavior().getTimeoutBehaviorType()) {
66                  case NOOP:
67                  case LOCAL_READS:
68                      // for noop and localReads, make the executor service rethrow as TimeoutException,
69                      // so that appropriate action according to behavior can be done
70                      throw new ThrowTimeoutException();
71                  default:
72                      // always throw InvalidLockStateAfterRejoinException for exception-on-timeout behavior
73                      throw new InvalidLockStateAfterRejoinException();
74              }
75          } else {
76              return cacheOperationCallable.call();
77          }
78      }
79  
80      private boolean isExplicitLockApi() {
81          return cacheOperationCallable instanceof ClusterOperationCallable
82                  && ((ClusterOperationCallable) cacheOperationCallable).getClusterOperation() instanceof ExplicitLockingClusterOperation;
83      }
84  
85  }