1 /***
2 *
3 * Copyright 2004 Protique Ltd
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 *
17 **/
18 package org.codehaus.activespace.cache.impl;
19
20 import javax.cache.Cache;
21 import java.util.HashMap;
22 import java.util.Iterator;
23 import java.util.Map;
24
25 /***
26 * Implements a thread local view of a cache which implements am
27 * optimistic transaction policy using the
28 * <i>REPEATABLE_READ</i> transaction isolation level, such that
29 * values looked up in the cache will remain the same during the transaction
30 * which is unlike the <i>READ_COMMITTED</i> isolation level where only committed
31 * data is read but the data can change during the transaction.
32 *
33 * @version $Revision: 1.1 $
34 */
35 public class RepeatableReadThreadCache extends ThreadCache {
36 private Map localReads;
37
38 public RepeatableReadThreadCache(Cache behindCache) {
39 super(behindCache);
40 this.localReads = createMap();
41 }
42
43 public RepeatableReadThreadCache(Cache behindCache, Map localChanges, Map localRemoves, Map localReads) {
44 super(behindCache, localChanges, localRemoves);
45 this.localReads = localReads;
46 }
47
48 public Object remove(Object key) {
49 VersionedValue entry = (VersionedValue) localReads.remove(key);
50 if (entry != null) {
51 localRemove(key, entry.getVersion());
52 return entry.getValue();
53 }
54 else {
55 return super.remove(key);
56 }
57 }
58
59 public TransactionalCacheCommand createTransactionCommand() {
60 TransactionalCacheCommand answer = super.createTransactionCommand();
61 Map readVersions = new HashMap(localReads.size());
62 for (Iterator iter = localReads.entrySet().iterator(); iter.hasNext();) {
63 Entry entry = (Entry) iter.next();
64 Object key = entry.getKey();
65 VersionedValue versionValue = (VersionedValue) entry.getValue();
66 readVersions.put(key, versionValue.getVersion());
67 }
68 answer.setReadVersions(readVersions);
69 return answer;
70 }
71
72 protected Object getLocalChangeValue(Object key) {
73 VersionedValue entry = (VersionedValue) localReads.get(key);
74 if (entry != null) {
75 return entry.getValue();
76 }
77 else {
78 Object value = super.getLocalChangeValue(key);
79 localReads.put(key, createVersionedValue(key, value));
80 return value;
81 }
82 }
83 }