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  package net.sf.ehcache.hibernate.regions;
17  
18  import java.util.Properties;
19  
20  import net.sf.ehcache.Ehcache;
21  import net.sf.ehcache.Element;
22  import net.sf.ehcache.concurrent.CacheLockProvider;
23  import net.sf.ehcache.concurrent.LockType;
24  import net.sf.ehcache.concurrent.StripedReadWriteLockSync;
25  import net.sf.ehcache.constructs.nonstop.NonStopCacheException;
26  import net.sf.ehcache.hibernate.nonstop.HibernateNonstopCacheExceptionHandler;
27  import net.sf.ehcache.hibernate.strategy.EhcacheAccessStrategyFactory;
28  
29  import org.hibernate.cache.CacheDataDescription;
30  import org.hibernate.cache.CacheException;
31  import org.hibernate.cache.TransactionalDataRegion;
32  import org.hibernate.cache.access.SoftLock;
33  import org.hibernate.cfg.Settings;
34  
35  /***
36   * An Ehcache specific TransactionalDataRegion.
37   * <p>
38   * This is the common superclass entity and collection regions.
39   *
40   * @author Chris Dennis
41   * @author Greg Luck
42   * @author Emmanuel Bernard
43   * @author Abhishek Sanoujam
44   */
45  public class EhcacheTransactionalDataRegion extends EhcacheDataRegion implements TransactionalDataRegion {
46  
47      private static final int LOCAL_LOCK_PROVIDER_CONCURRENCY = 128;
48  
49      /***
50       * Hibernate settings associated with the persistence unit.
51       */
52      protected final Settings settings;
53  
54      /***
55       * Metadata associated with the objects stored in the region.
56       */
57      protected final CacheDataDescription metadata;
58  
59      private final CacheLockProvider lockProvider;
60  
61      /***
62       * Construct an transactional Hibernate cache region around the given Ehcache instance.
63       */
64      EhcacheTransactionalDataRegion(EhcacheAccessStrategyFactory accessStrategyFactory, Ehcache cache, Settings settings,
65              CacheDataDescription metadata, Properties properties) {
66          super(accessStrategyFactory, cache, properties);
67          this.settings = settings;
68          this.metadata = metadata;
69  
70          Object context = cache.getInternalContext();
71          if (context instanceof CacheLockProvider) {
72              this.lockProvider = (CacheLockProvider) context;
73          } else {
74              this.lockProvider = new StripedReadWriteLockSync(LOCAL_LOCK_PROVIDER_CONCURRENCY);
75          }
76      }
77  
78      /***
79       * Return the hibernate settings
80       *
81       * @return settings
82       */
83      public Settings getSettings() {
84          return settings;
85      }
86  
87      /***
88       * {@inheritDoc}
89       */
90      public boolean isTransactionAware() {
91          return false;
92      }
93  
94      /***
95       * {@inheritDoc}
96       */
97      public CacheDataDescription getCacheDataDescription() {
98          return metadata;
99      }
100 
101     /***
102      * Get the value mapped to this key, or null if no value is mapped to this key.
103      */
104     public final Object get(Object key) {
105         try {
106             Element element = cache.get(key);
107             if (element == null) {
108                 return null;
109             } else {
110                 return element.getObjectValue();
111             }
112         } catch (net.sf.ehcache.CacheException e) {
113             if (e instanceof NonStopCacheException) {
114                 HibernateNonstopCacheExceptionHandler.getInstance().handleNonstopCacheException((NonStopCacheException) e);
115                 return null;
116             } else {
117                 throw new CacheException(e);
118             }
119         }
120     }
121 
122     /***
123      * Map the given value to the given key, replacing any existing mapping for this key
124      */
125     public final void put(Object key, Object value) throws CacheException {
126         try {
127             Element element = new Element(key, value);
128             if (value instanceof SoftLock) {
129                 element.setPinned(true);
130                 element.setEternal(true);
131             }
132             cache.put(element);
133         } catch (IllegalArgumentException e) {
134             throw new CacheException(e);
135         } catch (IllegalStateException e) {
136             throw new CacheException(e);
137         } catch (net.sf.ehcache.CacheException e) {
138             if (e instanceof NonStopCacheException) {
139                 HibernateNonstopCacheExceptionHandler.getInstance().handleNonstopCacheException((NonStopCacheException) e);
140             } else {
141                 throw new CacheException(e);
142             }
143         }
144     }
145 
146     /***
147      * Remove the mapping for this key (if any exists).
148      */
149     public final void remove(Object key) throws CacheException {
150         try {
151             cache.remove(key);
152         } catch (ClassCastException e) {
153             throw new CacheException(e);
154         } catch (IllegalStateException e) {
155             throw new CacheException(e);
156         } catch (net.sf.ehcache.CacheException e) {
157             if (e instanceof NonStopCacheException) {
158                 HibernateNonstopCacheExceptionHandler.getInstance().handleNonstopCacheException((NonStopCacheException) e);
159             } else {
160                 throw new CacheException(e);
161             }
162         }
163     }
164 
165     /***
166      * Remove all mapping from this cache region.
167      */
168     public final void clear() throws CacheException {
169         try {
170             cache.removeAll();
171         } catch (IllegalStateException e) {
172             throw new CacheException(e);
173         } catch (net.sf.ehcache.CacheException e) {
174             if (e instanceof NonStopCacheException) {
175                 HibernateNonstopCacheExceptionHandler.getInstance().handleNonstopCacheException((NonStopCacheException) e);
176             } else {
177                 throw new CacheException(e);
178             }
179         }
180     }
181 
182     /***
183      * Attempts to write lock the mapping for the given key.
184      */
185     public final void writeLock(Object key) {
186         try {
187             lockProvider.getSyncForKey(key).lock(LockType.WRITE);
188         } catch (net.sf.ehcache.CacheException e) {
189             if (e instanceof NonStopCacheException) {
190                 HibernateNonstopCacheExceptionHandler.getInstance().handleNonstopCacheException((NonStopCacheException) e);
191             } else {
192                 throw new CacheException(e);
193             }
194         }
195     }
196 
197     /***
198      * Attempts to write unlock the mapping for the given key.
199      */
200     public final void writeUnlock(Object key) {
201         try {
202             lockProvider.getSyncForKey(key).unlock(LockType.WRITE);
203         } catch (net.sf.ehcache.CacheException e) {
204             if (e instanceof NonStopCacheException) {
205                 HibernateNonstopCacheExceptionHandler.getInstance().handleNonstopCacheException((NonStopCacheException) e);
206             } else {
207                 throw new CacheException(e);
208             }
209         }
210     }
211 
212     /***
213      * Attempts to read lock the mapping for the given key.
214      */
215     public final void readLock(Object key) {
216         try {
217             lockProvider.getSyncForKey(key).lock(LockType.WRITE);
218         } catch (net.sf.ehcache.CacheException e) {
219             if (e instanceof NonStopCacheException) {
220                 HibernateNonstopCacheExceptionHandler.getInstance().handleNonstopCacheException((NonStopCacheException) e);
221             } else {
222                 throw new CacheException(e);
223             }
224         }
225     }
226 
227     /***
228      * Attempts to read unlock the mapping for the given key.
229      */
230     public final void readUnlock(Object key) {
231         try {
232             lockProvider.getSyncForKey(key).unlock(LockType.WRITE);
233         } catch (net.sf.ehcache.CacheException e) {
234             if (e instanceof NonStopCacheException) {
235                 HibernateNonstopCacheExceptionHandler.getInstance().handleNonstopCacheException((NonStopCacheException) e);
236             } else {
237                 throw new CacheException(e);
238             }
239         }
240     }
241 
242     /***
243      * Returns <code>true</code> if the locks used by the locking methods of this region are the independent of the cache.
244      * <p>
245      * Independent locks are not locked by the cache when the cache is accessed directly.  This means that for an independent lock
246      * lock holds taken through a region method will not block direct access to the cache via other means.
247      */
248     public final boolean locksAreIndependentOfCache() {
249         return lockProvider instanceof StripedReadWriteLockSync;
250     }
251 }