1 |
| |
2 |
| |
3 |
| |
4 |
| |
5 |
| |
6 |
| |
7 |
| package org.jboss.cache.interceptors; |
8 |
| |
9 |
| import org.jboss.cache.CacheException; |
10 |
| import org.jboss.cache.CacheSPI; |
11 |
| import org.jboss.cache.Fqn; |
12 |
| import org.jboss.cache.InvocationContext; |
13 |
| import org.jboss.cache.NodeFactory; |
14 |
| import org.jboss.cache.NodeSPI; |
15 |
| import org.jboss.cache.marshall.MethodCall; |
16 |
| import org.jboss.cache.marshall.MethodDeclarations; |
17 |
| import org.jboss.cache.notifications.Notifier; |
18 |
| import org.jboss.cache.optimistic.DataVersion; |
19 |
| import org.jboss.cache.optimistic.DefaultDataVersion; |
20 |
| import org.jboss.cache.optimistic.TransactionWorkspace; |
21 |
| import org.jboss.cache.optimistic.WorkspaceNode; |
22 |
| import org.jboss.cache.transaction.GlobalTransaction; |
23 |
| |
24 |
| import java.util.ArrayList; |
25 |
| import java.util.List; |
26 |
| |
27 |
| |
28 |
| |
29 |
| |
30 |
| |
31 |
| |
32 |
| |
33 |
| |
34 |
| |
35 |
| |
36 |
| public class OptimisticCreateIfNotExistsInterceptor extends OptimisticInterceptor |
37 |
| { |
38 |
| |
39 |
| |
40 |
| |
41 |
| |
42 |
| private NodeFactory nodeFactory; |
43 |
| |
44 |
912
| public void setCache(CacheSPI cache)
|
45 |
| { |
46 |
912
| super.setCache(cache);
|
47 |
| |
48 |
912
| nodeFactory = cache.getConfiguration().getRuntimeConfig().getNodeFactory();
|
49 |
| } |
50 |
| |
51 |
1055021
| public Object invoke(InvocationContext ctx) throws Throwable
|
52 |
| { |
53 |
1055021
| MethodCall m = ctx.getMethodCall();
|
54 |
1055021
| if (MethodDeclarations.isPutMethod(m.getMethodId()))
|
55 |
| { |
56 |
2074
| Object[] args = m.getArgs();
|
57 |
2074
| Fqn fqn = (Fqn) (args != null ? args[1] : null);
|
58 |
| |
59 |
2074
| if (cache.peek(fqn, false) == null)
|
60 |
| { |
61 |
1601
| createNode(ctx, fqn, false);
|
62 |
| } |
63 |
| } |
64 |
1052947
| else if (m.getMethodId() == MethodDeclarations.moveMethodLocal_id)
|
65 |
| { |
66 |
28
| Object[] args = m.getArgs();
|
67 |
28
| move(ctx, (Fqn) args[0], (Fqn) args[1]);
|
68 |
| } |
69 |
| |
70 |
1055019
| return super.invoke(ctx);
|
71 |
| } |
72 |
| |
73 |
28
| private void move(InvocationContext ctx, Fqn nodeFqn, Fqn newParent)
|
74 |
| { |
75 |
28
| List<Fqn> fqns = new ArrayList<Fqn>();
|
76 |
28
| fqns.add(newParent);
|
77 |
| |
78 |
| |
79 |
28
| NodeSPI node = cache.peek(nodeFqn, true);
|
80 |
28
| greedyGetFqns(fqns, node, newParent);
|
81 |
| |
82 |
| |
83 |
0
| if (trace) log.trace("Adding Fqns " + fqns + " for a move() operation.");
|
84 |
| |
85 |
| |
86 |
28
| for (Fqn f : fqns)
|
87 |
| { |
88 |
38
| if (cache.peek(f, false) == null) createNode(ctx, f, true);
|
89 |
| } |
90 |
| } |
91 |
| |
92 |
| |
93 |
| |
94 |
| |
95 |
| |
96 |
| |
97 |
| |
98 |
1639
| private void createNode(InvocationContext ctx, Fqn targetFqn, boolean suppressNotification) throws CacheException
|
99 |
| { |
100 |
| |
101 |
0
| if (targetFqn == null) return;
|
102 |
| |
103 |
1639
| boolean debug = log.isDebugEnabled();
|
104 |
| |
105 |
1639
| GlobalTransaction gtx = getGlobalTransaction(ctx);
|
106 |
1637
| TransactionWorkspace workspace = getTransactionWorkspace(gtx);
|
107 |
| |
108 |
1637
| WorkspaceNode workspaceNode;
|
109 |
| |
110 |
1637
| List<Fqn> nodesCreated = new ArrayList<Fqn>();
|
111 |
| |
112 |
| |
113 |
| |
114 |
1637
| synchronized (workspace)
|
115 |
| { |
116 |
1637
| DataVersion version = null;
|
117 |
1637
| if (ctx.getOptionOverrides() != null && ctx.getOptionOverrides().getDataVersion() != null)
|
118 |
| { |
119 |
149
| version = ctx.getOptionOverrides().getDataVersion();
|
120 |
149
| workspace.setVersioningImplicit(false);
|
121 |
| } |
122 |
| |
123 |
| |
124 |
1637
| workspaceNode = workspace.getNode(Fqn.ROOT);
|
125 |
0
| if (debug) log.debug("GlobalTransaction: " + gtx + "; Root: " + workspaceNode);
|
126 |
| |
127 |
| |
128 |
1637
| if (workspaceNode == null)
|
129 |
| { |
130 |
896
| NodeSPI node = cache.getRoot();
|
131 |
896
| workspaceNode = nodeFactory.createWorkspaceNode(node, workspace);
|
132 |
896
| workspace.addNode(workspaceNode);
|
133 |
896
| log.debug("Created root node in workspace.");
|
134 |
| } |
135 |
| else |
136 |
| { |
137 |
741
| log.debug("Found root node in workspace.");
|
138 |
| } |
139 |
| |
140 |
| |
141 |
1637
| Fqn currentFqn = Fqn.ROOT;
|
142 |
| |
143 |
| |
144 |
1637
| int targetFqnSize = targetFqn.size(), currentDepth = 1;
|
145 |
1637
| for (Object childName : targetFqn.peekElements())
|
146 |
| { |
147 |
3892
| boolean isTargetFqn = (currentDepth == targetFqnSize);
|
148 |
3892
| currentDepth++;
|
149 |
| |
150 |
| |
151 |
| |
152 |
| |
153 |
0
| if (debug) log.debug("Attempting to get child " + childName);
|
154 |
3892
| NodeSPI currentNode = workspaceNode.getChild(childName);
|
155 |
| |
156 |
| |
157 |
3892
| if (currentNode == null)
|
158 |
| { |
159 |
| |
160 |
0
| if (trace) log.trace("Creating new child, since it doesn't exist in the cache.");
|
161 |
| |
162 |
| |
163 |
| |
164 |
1403
| if (workspaceNode.isDeleted())
|
165 |
| { |
166 |
| |
167 |
0
| if (trace)
|
168 |
0
| log.trace("Parent node doesn't exist in workspace or has been deleted. Adding to workspace.");
|
169 |
0
| workspace.addNode(workspaceNode);
|
170 |
0
| if (!(workspaceNode.getVersion() instanceof DefaultDataVersion))
|
171 |
0
| workspaceNode.setVersioningImplicit(false);
|
172 |
| } |
173 |
| else |
174 |
| { |
175 |
0
| if (trace) log.trace("Parent node exists: " + workspaceNode);
|
176 |
| } |
177 |
| |
178 |
| |
179 |
1403
| DataVersion versionToPassIn = null;
|
180 |
129
| if (isTargetFqn && !workspace.isVersioningImplicit()) versionToPassIn = version;
|
181 |
| |
182 |
1403
| NodeSPI newUnderlyingChildNode = workspaceNode.createChild(childName, workspaceNode.getNode(), cache, versionToPassIn);
|
183 |
| |
184 |
| |
185 |
1403
| workspaceNode = nodeFactory.createWorkspaceNode(newUnderlyingChildNode, workspace);
|
186 |
1403
| workspaceNode.setVersioningImplicit(versionToPassIn == null || !isTargetFqn);
|
187 |
1403
| if (trace)
|
188 |
0
| log.trace("setting versioning of " + workspaceNode.getFqn() + " to be " + (workspaceNode.isVersioningImplicit() ? "implicit" : "explicit"));
|
189 |
| |
190 |
| |
191 |
1403
| workspace.addNode(workspaceNode);
|
192 |
1403
| workspaceNode.markAsCreated();
|
193 |
| |
194 |
| |
195 |
1403
| nodesCreated.add(workspaceNode.getFqn());
|
196 |
| } |
197 |
| else |
198 |
| { |
199 |
| |
200 |
2489
| workspaceNode = workspace.getNode(currentNode.getFqn());
|
201 |
| |
202 |
2489
| if (workspaceNode == null || workspaceNode.isDeleted())
|
203 |
| { |
204 |
510
| if (trace)
|
205 |
0
| log.trace("Child node " + currentNode.getFqn() + " doesn't exist in workspace or has been deleted. Adding to workspace in gtx " + gtx);
|
206 |
| |
207 |
510
| workspaceNode = nodeFactory.createWorkspaceNode(currentNode, workspace);
|
208 |
510
| if (isTargetFqn && !workspace.isVersioningImplicit())
|
209 |
| { |
210 |
0
| workspaceNode.setVersion(version);
|
211 |
0
| workspaceNode.setVersioningImplicit(false);
|
212 |
| } |
213 |
| else |
214 |
| { |
215 |
510
| workspaceNode.setVersioningImplicit(true);
|
216 |
| } |
217 |
510
| if (trace)
|
218 |
0
| log.trace("setting versioning of " + workspaceNode.getFqn() + " to be " + (workspaceNode.isVersioningImplicit() ? "implicit" : "explicit"));
|
219 |
510
| workspace.addNode(workspaceNode);
|
220 |
| } |
221 |
| else |
222 |
| { |
223 |
0
| if (trace) log.trace("Found child node in the workspace: " + currentNode);
|
224 |
| |
225 |
| } |
226 |
| } |
227 |
| } |
228 |
| |
229 |
| } |
230 |
| |
231 |
1637
| if (!suppressNotification)
|
232 |
| { |
233 |
1599
| if (nodesCreated.size() > 0)
|
234 |
| { |
235 |
1088
| Notifier n = cache.getNotifier();
|
236 |
1088
| for (Fqn temp : nodesCreated)
|
237 |
| { |
238 |
1365
| n.notifyNodeCreated(temp, true, ctx);
|
239 |
1365
| n.notifyNodeCreated(temp, false, ctx);
|
240 |
0
| if (trace) log.trace("Notifying cache of node created in workspace " + temp);
|
241 |
| } |
242 |
| } |
243 |
| } |
244 |
| } |
245 |
| |
246 |
| } |