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.strategy;
17
18 import net.sf.ehcache.hibernate.regions.EhcacheEntityRegion;
19
20 import org.hibernate.cache.CacheException;
21 import org.hibernate.cache.EntityRegion;
22 import org.hibernate.cache.access.EntityRegionAccessStrategy;
23 import org.hibernate.cache.access.SoftLock;
24 import org.hibernate.cfg.Settings;
25
26 /***
27 * Ehcache specific read/write entity region access strategy
28 *
29 * @author Chris Dennis
30 */
31 public class ReadWriteEhcacheEntityRegionAccessStrategy extends AbstractReadWriteEhcacheAccessStrategy<EhcacheEntityRegion>
32 implements EntityRegionAccessStrategy {
33
34 /***
35 * Create a read/write access strategy accessing the given entity region.
36 */
37 public ReadWriteEhcacheEntityRegionAccessStrategy(EhcacheEntityRegion region, Settings settings) {
38 super(region, settings);
39 }
40
41 /***
42 * {@inheritDoc}
43 */
44 public EntityRegion getRegion() {
45 return region;
46 }
47
48 /***
49 * A no-op since this is an asynchronous cache access strategy.
50 */
51 public boolean insert(Object key, Object value, Object version) throws CacheException {
52 return false;
53 }
54
55 /***
56 * {@inheritDoc}
57 * <p>
58 * Inserts will only succeed if there is no existing value mapped to this key.
59 */
60 public boolean afterInsert(Object key, Object value, Object version) throws CacheException {
61 region.writeLock(key);
62 try {
63 Lockable item = (Lockable) region.get(key);
64 if (item == null) {
65 region.put(key, new Item(value, version, region.nextTimestamp()));
66 return true;
67 } else {
68 return false;
69 }
70 } finally {
71 region.writeUnlock(key);
72 }
73 }
74
75 /***
76 * A no-op since this is an asynchronous cache access strategy.
77 */
78 public boolean update(Object key, Object value, Object currentVersion, Object previousVersion) throws CacheException {
79 return false;
80 }
81
82 /***
83 * {@inheritDoc}
84 * <p>
85 * Updates will only succeed if this entry was locked by this transaction and exclusively this transaction for the
86 * duration of this transaction. It is important to also note that updates will fail if the soft-lock expired during
87 * the course of this transaction.
88 */
89 public boolean afterUpdate(Object key, Object value, Object currentVersion, Object previousVersion, SoftLock lock)
90 throws CacheException {
91
92 region.writeLock(key);
93 try {
94 Lockable item = (Lockable) region.get(key);
95
96 if (item != null && item.isUnlockable(lock)) {
97 Lock lockItem = (Lock) item;
98 if (lockItem.wasLockedConcurrently()) {
99 decrementLock(key, lockItem);
100 return false;
101 } else {
102 region.put(key, new Item(value, currentVersion, region.nextTimestamp()));
103 return true;
104 }
105 } else {
106 handleLockExpiry(key, item);
107 return false;
108 }
109 } finally {
110 region.writeUnlock(key);
111 }
112 }
113 }