1 | package com.hammurapi.store; |
2 | |
3 | import java.util.Collection; |
4 | import java.util.Comparator; |
5 | import java.util.Iterator; |
6 | import java.util.Map; |
7 | import java.util.concurrent.ExecutorService; |
8 | import java.util.concurrent.locks.Lock; |
9 | import java.util.concurrent.locks.ReadWriteLock; |
10 | |
11 | import com.hammurapi.common.concurrent.NonBlockingExecutorService; |
12 | import com.hammurapi.extract.Extractor; |
13 | import com.hammurapi.extract.Predicate; |
14 | import com.hammurapi.store.Index.Type; |
15 | |
16 | /** |
17 | * This class operates on master's data. It uses master's locks and storage, and is aware if the master already holds a certain lock. |
18 | * In this case this implementation doesn't acquire its own lock but operates |
19 | * within master's lock because it acts on behalf of the master. |
20 | * Attempt to acquire write lock if the master holds read lock results in exception. |
21 | * Deputy stores are used by the AbstractStore implementations to operate in asynchronous tasks. |
22 | * @author Pavel Vlasov |
23 | * |
24 | * @param <T> |
25 | * @param <PK> |
26 | */ |
27 | public abstract class DeputyStore<T,PK,S extends Store<T,PK,S>> extends AbstractStore<T,PK,S> { |
28 | |
29 | protected AbstractStore<T,PK,S> master; |
30 | public int hashCode() { |
31 | return master.hashCode(); |
32 | } |
33 | |
34 | public Handle<T, PK, S> put(T obj) { |
35 | return master.put(obj); |
36 | } |
37 | |
38 | public boolean equals(Object obj) { |
39 | return master.equals(obj); |
40 | } |
41 | |
42 | public Iterable<T> getAll() { |
43 | return master.getAll(); |
44 | } |
45 | |
46 | public T getByPrimaryKey(PK primaryKey) { |
47 | return master.getByPrimaryKey(primaryKey); |
48 | } |
49 | |
50 | public Iterable<T> get(Predicate<T, S> selector) { |
51 | return master.get(selector); |
52 | } |
53 | |
54 | public <V> Iterable<V> get( |
55 | Predicate<T, S> selector, |
56 | Extractor<T, V, S> extractor, |
57 | boolean ordered, |
58 | Comparator<V> comparator) { |
59 | return master.get(selector, extractor, ordered, comparator); |
60 | } |
61 | |
62 | public String toString() { |
63 | return master.toString(); |
64 | } |
65 | |
66 | public void clear() { |
67 | master.clear(); |
68 | } |
69 | |
70 | public boolean remove(T obj) { |
71 | return master.remove(obj); |
72 | } |
73 | |
74 | public boolean removeByPrimaryKey(PK primaryKey) { |
75 | return master.removeByPrimaryKey(primaryKey); |
76 | } |
77 | |
78 | public int remove(Predicate<T, S> selector) { |
79 | return master.remove(selector); |
80 | } |
81 | |
82 | public int update( |
83 | Predicate<T, S> selector, |
84 | UpdateTask<T, PK, S> updater) { |
85 | |
86 | return master.update(selector, updater); |
87 | } |
88 | |
89 | @Override |
90 | public <V> Index<T, PK, V, S> addIndex( |
91 | Predicate<T, S> predicate, |
92 | Extractor<T, V, S> extractor, |
93 | Type type, |
94 | boolean ordered, |
95 | Comparator<V> comparator) { |
96 | |
97 | return master.addIndex(predicate, extractor, type, ordered, comparator); |
98 | } |
99 | |
100 | public Extractor<T, PK, S> getPrimaryKeyExtractor() { |
101 | return master.getPrimaryKeyExtractor(); |
102 | } |
103 | |
104 | public int queryAll(QueryTask<T, PK, S> query) { |
105 | return master.queryAll(query); |
106 | } |
107 | |
108 | public int query( |
109 | Predicate<T, S> selector, |
110 | QueryTask<T, PK, S> query) { |
111 | |
112 | return master.query(selector, query); |
113 | } |
114 | |
115 | public Iterator<T> iterator() { |
116 | return master.iterator(); |
117 | } |
118 | |
119 | public S createView(Predicate<T, S> selector, ViewType viewType) { |
120 | return master.createView(selector, viewType); |
121 | } |
122 | |
123 | public Lock readLock() { |
124 | return masterLock.readLock(); |
125 | } |
126 | |
127 | public Lock writeLock() { |
128 | return masterLock.writeLock(); |
129 | } |
130 | |
131 | private ReadWriteLock masterLock; |
132 | |
133 | private NonBlockingExecutorService nonBlockingExecutorService; |
134 | |
135 | /** |
136 | * Creates deputy store. |
137 | * @param master Master store. |
138 | * @param masterLock Lock which delegates to master lock and can be used |
139 | * from multiple threads/processes, i.e. the lock owner is not the current |
140 | * thread but the master store. |
141 | */ |
142 | public DeputyStore(AbstractStore<T,PK,S> master, ReadWriteLock masterLock) { |
143 | this.master = master; |
144 | this.masterLock = masterLock; |
145 | if (master.getExecutorService() instanceof NonBlockingExecutorService) { |
146 | this.nonBlockingExecutorService = (NonBlockingExecutorService) master.getExecutorService(); |
147 | } else { |
148 | this.nonBlockingExecutorService = new NonBlockingExecutorService(master.getExecutorService()); |
149 | } |
150 | } |
151 | |
152 | @Override |
153 | protected Map<PK, Handle<T, PK, S>> getPkStore() { |
154 | return master.getPkStore(); |
155 | } |
156 | |
157 | @Override |
158 | protected Collection<Handle<T, PK, S>> getNoPkStore() { |
159 | return master.getNoPkStore(); |
160 | } |
161 | |
162 | @Override |
163 | protected ExecutorService getExecutorService() { |
164 | return nonBlockingExecutorService; |
165 | } |
166 | |
167 | @Override |
168 | protected Handle<T, PK, S> createHandle( |
169 | T obj, |
170 | PK primaryKey, |
171 | Map<S, Map<Extractor<T, ? super PK, S>, ? super PK>> cache, |
172 | Predicate<T, S>[] validators) { |
173 | return master.createHandle(obj, primaryKey, cache, validators); |
174 | } |
175 | |
176 | @Override |
177 | protected Collection<Handle<T, PK, S>> createIndexCollection(boolean unique, boolean ordered, Comparator<T> comparator) { |
178 | return master.createIndexCollection(unique, ordered, comparator); |
179 | } |
180 | |
181 | @Override |
182 | protected Map<S, Map<Extractor<T, ? super PK, S>, ? super PK>> createCache() { |
183 | return master.createCache(); |
184 | } |
185 | |
186 | @Override |
187 | protected ReadWriteLock createMasterLock() { |
188 | if (masterLock instanceof DeputyReadWriteLock) { |
189 | return ((DeputyReadWriteLock) masterLock).createDeputy(); |
190 | } |
191 | |
192 | throw new UnsupportedOperationException("Creating master locks from non-deputy locks is not implemented."); |
193 | } |
194 | |
195 | @Override |
196 | protected void onRemoved(int removed) { |
197 | master.onRemoved(removed); |
198 | } |
199 | |
200 | @Override |
201 | protected Collection<AbstractIndex<T, PK, ?, S>> getIndices() { |
202 | return master.getIndices(); |
203 | } |
204 | |
205 | @Override |
206 | protected <V> AbstractIndex<T, PK, V, S> createIndex( |
207 | Predicate<T, S> predicate, |
208 | Extractor<T, V, S> extractor, Type type, |
209 | boolean ordered, Comparator<V> comparator) { |
210 | return master.createIndex(predicate, extractor, type, ordered, comparator); |
211 | } |
212 | |
213 | protected AbstractStore<T, PK, S> getMaster() { |
214 | return master; |
215 | } |
216 | } |