1 |
| |
2 |
| |
3 |
| |
4 |
| |
5 |
| |
6 |
| |
7 |
| package org.jboss.cache.optimistic; |
8 |
| |
9 |
| import org.apache.commons.logging.Log; |
10 |
| import org.apache.commons.logging.LogFactory; |
11 |
| import org.jboss.cache.AbstractNode; |
12 |
| import org.jboss.cache.CacheSPI; |
13 |
| import org.jboss.cache.Fqn; |
14 |
| import org.jboss.cache.Node; |
15 |
| import org.jboss.cache.NodeSPI; |
16 |
| import org.jboss.cache.VersionedNode; |
17 |
| import org.jboss.cache.transaction.GlobalTransaction; |
18 |
| |
19 |
| import java.util.ArrayList; |
20 |
| import java.util.Collections; |
21 |
| import java.util.HashMap; |
22 |
| import java.util.HashSet; |
23 |
| import java.util.List; |
24 |
| import java.util.Map; |
25 |
| import java.util.Set; |
26 |
| |
27 |
| |
28 |
| |
29 |
| |
30 |
| |
31 |
| |
32 |
| |
33 |
| public class WorkspaceNodeImpl<K, V> extends AbstractNode<K, V> implements WorkspaceNode<K, V> |
34 |
| { |
35 |
| |
36 |
| private static Log log = LogFactory.getLog(WorkspaceNodeImpl.class); |
37 |
| |
38 |
| private NodeSPI<K, V> node; |
39 |
| private TransactionWorkspace workspace; |
40 |
| private DataVersion version = DefaultDataVersion.ZERO; |
41 |
| private boolean dirty; |
42 |
| private boolean created; |
43 |
| private boolean childrenModified; |
44 |
| private Map<Object, NodeSPI<K, V>> optimisticChildNodeMap; |
45 |
| private Set<Fqn> childrenAdded = new HashSet<Fqn>(); |
46 |
| private Set<Fqn> childrenRemoved = new HashSet<Fqn>(); |
47 |
| private Map<K, V> optimisticDataMap; |
48 |
| private boolean versioningImplicit = true; |
49 |
| |
50 |
| |
51 |
| |
52 |
| |
53 |
1053958
| public WorkspaceNodeImpl(NodeSPI<K, V> node, TransactionWorkspace workspace)
|
54 |
| { |
55 |
1053958
| if (!(node instanceof VersionedNode))
|
56 |
| { |
57 |
0
| throw new IllegalArgumentException("node " + node + " not VersionedNode");
|
58 |
| } |
59 |
1053958
| this.node = node;
|
60 |
1053958
| this.workspace = workspace;
|
61 |
1053958
| optimisticDataMap = new HashMap<K, V>(node.getDataDirect());
|
62 |
1053958
| Map<Object, Node<K, V>> childrenMap = node.getChildrenMapDirect();
|
63 |
| |
64 |
| |
65 |
| |
66 |
1053958
| this.optimisticChildNodeMap = childrenMap == null ? new HashMap() : new HashMap(childrenMap);
|
67 |
| |
68 |
1053958
| this.version = node.getVersion();
|
69 |
1053958
| if (version == null)
|
70 |
| { |
71 |
0
| throw new IllegalStateException("VersionedNode version null");
|
72 |
| } |
73 |
| } |
74 |
| |
75 |
1053159
| public boolean isChildrenModified()
|
76 |
| { |
77 |
1053159
| return childrenModified;
|
78 |
| } |
79 |
| |
80 |
| |
81 |
| |
82 |
| |
83 |
1054860
| public boolean isDirty()
|
84 |
| { |
85 |
1054860
| return dirty;
|
86 |
| } |
87 |
| |
88 |
2116086
| public Fqn getFqn()
|
89 |
| { |
90 |
2116086
| return node.getFqn();
|
91 |
| } |
92 |
| |
93 |
275
| public void putAll(Map<K, V> data)
|
94 |
| { |
95 |
275
| realPut(data, false);
|
96 |
275
| dirty = true;
|
97 |
| } |
98 |
| |
99 |
0
| public void replaceAll(Map<K, V> data)
|
100 |
| { |
101 |
0
| clearData();
|
102 |
0
| putAll(data);
|
103 |
| } |
104 |
| |
105 |
1431
| public V put(K key, V value)
|
106 |
| { |
107 |
1431
| dirty = true;
|
108 |
1431
| return optimisticDataMap.put(key, value);
|
109 |
| |
110 |
| } |
111 |
| |
112 |
20
| public V remove(K key)
|
113 |
| { |
114 |
20
| dirty = true;
|
115 |
20
| return optimisticDataMap.remove(key);
|
116 |
| |
117 |
| } |
118 |
| |
119 |
1049917
| public V get(K key)
|
120 |
| { |
121 |
1049917
| return optimisticDataMap.get(key);
|
122 |
| } |
123 |
| |
124 |
34
| public Set<K> getKeys()
|
125 |
| { |
126 |
34
| return optimisticDataMap.keySet();
|
127 |
| } |
128 |
| |
129 |
| |
130 |
320
| public Set<Object> getChildrenNames()
|
131 |
| { |
132 |
320
| return new HashSet<Object>(optimisticChildNodeMap.keySet());
|
133 |
| } |
134 |
| |
135 |
275
| private void realPut(Map<K, V> data, boolean eraseData)
|
136 |
| { |
137 |
275
| realPut(data, eraseData, true);
|
138 |
| } |
139 |
| |
140 |
275
| private void realPut(Map<K, V> data, boolean eraseData, boolean forceDirtyFlag)
|
141 |
| { |
142 |
275
| if (forceDirtyFlag) dirty = true;
|
143 |
275
| if (eraseData)
|
144 |
| { |
145 |
0
| optimisticDataMap.clear();
|
146 |
| } |
147 |
164
| if (data != null) optimisticDataMap.putAll(data);
|
148 |
| } |
149 |
| |
150 |
0
| public Node<K, V> getParent()
|
151 |
| { |
152 |
0
| return node.getParent();
|
153 |
| } |
154 |
| |
155 |
1403
| public NodeSPI<K, V> createChild(Object child_name, NodeSPI<K, V> parent, CacheSPI<K, V> cache, DataVersion version)
|
156 |
| { |
157 |
1403
| if (child_name == null)
|
158 |
| { |
159 |
0
| return null;
|
160 |
| } |
161 |
| |
162 |
| |
163 |
1403
| NodeSPI child = optimisticChildNodeMap.get(child_name);
|
164 |
| |
165 |
| |
166 |
1403
| if (child == null)
|
167 |
| { |
168 |
1403
| child = (NodeSPI) cache.getConfiguration().getRuntimeConfig().getNodeFactory().createNodeOfType(parent, child_name, parent, null);
|
169 |
1403
| optimisticChildNodeMap.put(child_name, child);
|
170 |
1403
| childrenAdded.add(child.getFqn());
|
171 |
1403
| childrenRemoved.remove(child.getFqn());
|
172 |
| } |
173 |
1403
| childrenModified = true;
|
174 |
1403
| return child;
|
175 |
| } |
176 |
| |
177 |
1415
| public boolean isVersioningImplicit()
|
178 |
| { |
179 |
1415
| return versioningImplicit;
|
180 |
| } |
181 |
| |
182 |
3833
| public void setVersioningImplicit(boolean b)
|
183 |
| { |
184 |
3833
| versioningImplicit = b;
|
185 |
| } |
186 |
| |
187 |
4927
| public NodeSPI<K, V> getChild(Object childName)
|
188 |
| { |
189 |
| |
190 |
4927
| return optimisticChildNodeMap.get(childName);
|
191 |
| } |
192 |
| |
193 |
1058793
| public NodeSPI<K, V> getNode()
|
194 |
| { |
195 |
1058793
| return node;
|
196 |
| } |
197 |
| |
198 |
1055499
| public DataVersion getVersion()
|
199 |
| { |
200 |
1055499
| return version;
|
201 |
| } |
202 |
| |
203 |
222
| public void setVersion(DataVersion version)
|
204 |
| { |
205 |
222
| this.version = version;
|
206 |
| } |
207 |
| |
208 |
1092
| public List<Set<Fqn>> getMergedChildren()
|
209 |
| { |
210 |
| |
211 |
1092
| List<Set<Fqn>> l = new ArrayList<Set<Fqn>>(2);
|
212 |
1092
| l.add(childrenAdded);
|
213 |
1092
| l.add(childrenRemoved);
|
214 |
1092
| return l;
|
215 |
| } |
216 |
| |
217 |
1224
| public Map<K, V> getMergedData()
|
218 |
| { |
219 |
1224
| return optimisticDataMap;
|
220 |
| } |
221 |
| |
222 |
0
| public TransactionWorkspace getTransactionWorkspace()
|
223 |
| { |
224 |
0
| return workspace;
|
225 |
| } |
226 |
| |
227 |
5698
| public boolean isCreated()
|
228 |
| { |
229 |
5698
| return created;
|
230 |
| } |
231 |
| |
232 |
1403
| public void markAsCreated()
|
233 |
| { |
234 |
1403
| created = true;
|
235 |
| |
236 |
| |
237 |
| } |
238 |
| |
239 |
2122
| public Map<K, V> getData()
|
240 |
| { |
241 |
2122
| return Collections.unmodifiableMap(optimisticDataMap);
|
242 |
| } |
243 |
| |
244 |
0
| public String toString()
|
245 |
| { |
246 |
0
| StringBuffer sb = new StringBuffer();
|
247 |
0
| if (deleted) sb.append("del ");
|
248 |
0
| if (dirty) sb.append("dirty ");
|
249 |
0
| if (created) sb.append("new ");
|
250 |
0
| return getClass().getSimpleName() + " [ fqn=" + getFqn() + " " + sb + "ver=" + version + " " + (versioningImplicit ? "implicit" : "explicit") + "]";
|
251 |
| } |
252 |
| |
253 |
0
| public Node<K, V> addChild(Fqn f)
|
254 |
| { |
255 |
0
| CacheSPI cache = getCache();
|
256 |
0
| Node newNode = this;
|
257 |
0
| GlobalTransaction gtx = cache.getInvocationContext().getGlobalTransaction();
|
258 |
| |
259 |
0
| if (f.size() == 1)
|
260 |
| { |
261 |
0
| newNode = createChild(f.get(0), node, getCache(), version);
|
262 |
| } |
263 |
| else |
264 |
| { |
265 |
| |
266 |
0
| Node currentParent = this;
|
267 |
0
| for (Object o : f.peekElements())
|
268 |
| { |
269 |
0
| if (currentParent instanceof WorkspaceNode)
|
270 |
| { |
271 |
0
| newNode = ((WorkspaceNode) currentParent).getNode().getOrCreateChild(o, gtx);
|
272 |
| } |
273 |
| else |
274 |
| { |
275 |
0
| if (currentParent instanceof WorkspaceNode)
|
276 |
| { |
277 |
0
| newNode = ((WorkspaceNode) currentParent).getNode().getOrCreateChild(o, gtx);
|
278 |
| } |
279 |
| else |
280 |
| { |
281 |
0
| newNode = ((NodeSPI) currentParent).getOrCreateChild(o, gtx);
|
282 |
| } |
283 |
| } |
284 |
0
| currentParent = newNode;
|
285 |
| } |
286 |
| } |
287 |
0
| return newNode;
|
288 |
| } |
289 |
| |
290 |
12
| public void addChild(WorkspaceNode child)
|
291 |
| { |
292 |
12
| optimisticChildNodeMap.put(child.getFqn().getLastElement(), child.getNode());
|
293 |
12
| childrenAdded.add(child.getFqn());
|
294 |
12
| childrenRemoved.remove(child.getFqn());
|
295 |
0
| if (log.isTraceEnabled()) log.trace("Adding child " + child.getFqn());
|
296 |
| } |
297 |
| |
298 |
11
| public void clearData()
|
299 |
| { |
300 |
11
| dirty = true;
|
301 |
11
| optimisticDataMap.clear();
|
302 |
| } |
303 |
| |
304 |
0
| public int dataSize()
|
305 |
| { |
306 |
0
| return optimisticDataMap.size();
|
307 |
| } |
308 |
| |
309 |
17
| public NodeSPI<K, V> getChild(Fqn f)
|
310 |
| { |
311 |
17
| if (f.size() > 1)
|
312 |
| { |
313 |
0
| throw new UnsupportedOperationException("Workspace node does not support fetching indirect children");
|
314 |
| } |
315 |
17
| return getChild(f.getLastElement());
|
316 |
| } |
317 |
| |
318 |
0
| public Set<Node<K, V>> getChildren()
|
319 |
| { |
320 |
0
| throw new UnsupportedOperationException();
|
321 |
| } |
322 |
| |
323 |
0
| public boolean hasChild(Fqn f)
|
324 |
| { |
325 |
0
| throw new UnsupportedOperationException();
|
326 |
| } |
327 |
| |
328 |
0
| public NodeSPI<K, V> getNodeSPI()
|
329 |
| { |
330 |
0
| throw new UnsupportedOperationException("WorkspaceNode has no access to a NodeSPI");
|
331 |
| } |
332 |
| |
333 |
0
| public V putIfAbsent(K k, V v)
|
334 |
| { |
335 |
0
| throw new UnsupportedOperationException();
|
336 |
| } |
337 |
| |
338 |
0
| public V replace(K key, V value)
|
339 |
| { |
340 |
0
| throw new UnsupportedOperationException();
|
341 |
| } |
342 |
| |
343 |
0
| public boolean replace(K key, V oldValue, V newValue)
|
344 |
| { |
345 |
0
| throw new UnsupportedOperationException();
|
346 |
| } |
347 |
| |
348 |
28
| public boolean removeChild(Fqn f)
|
349 |
| { |
350 |
0
| if (f.size() > 1) throw new UnsupportedOperationException("Workspace nodes can only remove direct children!");
|
351 |
28
| Object key = f.getLastElement();
|
352 |
28
| return removeChild(key);
|
353 |
| } |
354 |
| |
355 |
206
| public boolean removeChild(Object childName)
|
356 |
| { |
357 |
206
| NodeSPI n = optimisticChildNodeMap.remove(childName);
|
358 |
206
| if (n != null)
|
359 |
| { |
360 |
178
| childrenRemoved.add(n.getFqn());
|
361 |
178
| childrenAdded.remove(n.getFqn());
|
362 |
178
| childrenModified = true;
|
363 |
178
| return true;
|
364 |
| } |
365 |
| else |
366 |
| { |
367 |
28
| return false;
|
368 |
| } |
369 |
| } |
370 |
| |
371 |
0
| protected CacheSPI<K, V> getCache()
|
372 |
| { |
373 |
0
| return node.getCache();
|
374 |
| } |
375 |
| } |