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 net.sf.ehcache.concurrent.LockType;
20 import net.sf.ehcache.concurrent.Sync;
21 import net.sf.ehcache.config.TimeoutBehaviorConfiguration.TimeoutBehaviorType;
22 import net.sf.ehcache.constructs.nonstop.NonStopCacheException;
23 import net.sf.ehcache.constructs.nonstop.NonstopActiveDelegateHolder;
24 import net.sf.ehcache.constructs.nonstop.store.NonstopStore;
25
26 /***
27 * Class implementing {@link Sync} and that can be executed without getting stuck.
28 *
29 * @author Abhishek Sanoujam
30 *
31 */
32 class NonstopSync implements Sync {
33
34 private final NonstopStore nonstopStore;
35
36 private final ExplicitLockingContextThreadLocal explicitLockingContextThreadLocal;
37 private final Object key;
38 private final NonstopActiveDelegateHolder nonstopActiveDelegateHolder;
39
40 /***
41 * Constructor accepting the {@link NonstopStore} and the actual {@link Sync}
42 *
43 * @param nonstopStore
44 * @param nonstopActiveDelegateHolder
45 * @param key
46 * @param key2
47 */
48 public NonstopSync(NonstopStore nonstopStore, NonstopActiveDelegateHolder nonstopActiveDelegateHolder,
49 ExplicitLockingContextThreadLocal explicitLockingContextThreadLocal, Object key) {
50 this.nonstopStore = nonstopStore;
51 this.nonstopActiveDelegateHolder = nonstopActiveDelegateHolder;
52 this.explicitLockingContextThreadLocal = explicitLockingContextThreadLocal;
53 this.key = key;
54 }
55
56 /***
57 * Return the key associated with this {@link Sync}
58 *
59 * @return the key associated with this {@link Sync}
60 */
61 public Object getKey() {
62 return key;
63 }
64
65 /***
66 * {@inheritDoc}
67 */
68 public boolean isHeldByCurrentThread(final LockType type) {
69 return nonstopStore.executeClusterOperation(new ExplicitLockingClusterOperation<Boolean>() {
70
71 public Boolean performClusterOperation() {
72 return nonstopActiveDelegateHolder.getUnderlyingCacheLockProvider().getSyncForKey(key).isHeldByCurrentThread(type);
73 }
74
75 public Boolean performClusterOperationTimedOut(final TimeoutBehaviorType configuredTimeoutBehavior) {
76 throw new NonStopCacheException("isHeldByCurrentThread() timed out");
77 }
78 });
79 }
80
81 /***
82 * {@inheritDoc}
83 */
84 public void lock(final LockType type) {
85 final ExplicitLockingContext appThreadLockContext = explicitLockingContextThreadLocal.getCurrentThreadLockContext();
86 nonstopStore.executeClusterOperation(new ExplicitLockingClusterOperation<Void>() {
87
88 public Void performClusterOperation() {
89 nonstopActiveDelegateHolder.getUnderlyingCacheLockProvider().getSyncForKey(key).lock(type);
90 appThreadLockContext.lockAcquired(NonstopThreadUniqueIdProvider.getCurrentNonstopThreadUniqueId());
91 return null;
92 }
93
94 public Void performClusterOperationTimedOut(final TimeoutBehaviorType configuredTimeoutBehavior) {
95
96 throw new NonStopCacheException("lock() timed out");
97 }
98 });
99 }
100
101 /***
102 * {@inheritDoc}
103 */
104 public boolean tryLock(final LockType type, final long msec) throws InterruptedException {
105 final ExplicitLockingContext appThreadLockContext = explicitLockingContextThreadLocal.getCurrentThreadLockContext();
106 return nonstopStore.executeClusterOperation(new ExplicitLockingClusterOperation<Boolean>() {
107
108 public Boolean performClusterOperation() throws Exception {
109 final boolean lockAcquired = nonstopActiveDelegateHolder.getUnderlyingCacheLockProvider().getSyncForKey(key)
110 .tryLock(type, msec);
111 if (lockAcquired) {
112 appThreadLockContext.lockAcquired(NonstopThreadUniqueIdProvider.getCurrentNonstopThreadUniqueId());
113 }
114 return lockAcquired;
115 }
116
117 public Boolean performClusterOperationTimedOut(final TimeoutBehaviorType configuredTimeoutBehavior) {
118
119 throw new NonStopCacheException("tryLock() timed out");
120 }
121 });
122 }
123
124 /***
125 * {@inheritDoc}
126 */
127 public void unlock(final LockType type) {
128 final ExplicitLockingContext appThreadLockContext = explicitLockingContextThreadLocal.getCurrentThreadLockContext();
129 nonstopStore.executeClusterOperation(new ExplicitLockingClusterOperation<Void>() {
130
131 public Void performClusterOperation() {
132 try {
133 if (appThreadLockContext.areLocksAcquiredByOtherThreads(NonstopThreadUniqueIdProvider.getCurrentNonstopThreadUniqueId())) {
134
135
136 throw new InvalidLockStateAfterRejoinException();
137 } else {
138 nonstopActiveDelegateHolder.getUnderlyingCacheLockProvider().getSyncForKey(key).unlock(type);
139 }
140 } finally {
141
142 appThreadLockContext.lockReleased();
143 }
144 return null;
145 }
146
147 public Void performClusterOperationTimedOut(final TimeoutBehaviorType configuredTimeoutBehavior) {
148
149 appThreadLockContext.lockReleased();
150
151 throw new NonStopCacheException("unlock() timed out");
152 }
153 });
154 }
155
156 }