1 7 package org.jboss.cache.interceptors; 8 9 import org.jboss.cache.CacheException; 10 import org.jboss.cache.Fqn; 11 import org.jboss.cache.GlobalTransaction; 12 import org.jboss.cache.InvocationContext; 13 import org.jboss.cache.NodeSPI; 14 import org.jboss.cache.marshall.MethodCall; 15 import org.jboss.cache.marshall.MethodDeclarations; 16 import org.jboss.cache.optimistic.DataVersioningException; 17 import org.jboss.cache.optimistic.DefaultDataVersion; 18 import org.jboss.cache.optimistic.TransactionWorkspace; 19 import org.jboss.cache.optimistic.WorkspaceNode; 20 21 import javax.transaction.Transaction ; 22 import java.util.Collection ; 23 import java.util.Map ; 24 25 42 public class OptimisticValidatorInterceptor extends OptimisticInterceptor 43 { 44 public Object invoke(MethodCall m) throws Throwable 45 { 46 if (MethodDeclarations.isBuddyGroupOrganisationMethod(m.getMethodId())) return super.invoke(m); 48 49 InvocationContext ctx = cache.getInvocationContext(); 50 Transaction tx = ctx.getTransaction(); 51 GlobalTransaction gtx = ctx.getGlobalTransaction(); 52 Object retval = null; 53 54 if (tx == null) 55 { 56 throw new CacheException("Not in a transaction"); 57 } 58 59 switch (m.getMethodId()) 62 { 63 case MethodDeclarations.optimisticPrepareMethod_id: 64 validateNodes(gtx); 66 break; 67 case MethodDeclarations.commitMethod_id: 68 commit(gtx); 69 break; 70 case MethodDeclarations.rollbackMethod_id: 71 rollBack(gtx); 72 break; 73 default: 74 retval = super.invoke(m); 75 break; 76 } 77 return retval; 78 } 79 80 81 private void validateNodes(GlobalTransaction gtx) throws CacheException 82 { 83 TransactionWorkspace workspace; 84 85 try 86 { 87 workspace = getTransactionWorkspace(gtx); 88 } 89 catch (CacheException e) 90 { 91 throw new CacheException("unable to retrieve workspace", e); 92 } 93 94 Collection <WorkspaceNode> nodes = workspace.getNodes().values(); 96 97 if (log.isDebugEnabled()) log.debug("validating nodes. Num nodes: " + nodes.size()); 99 simpleValidate(nodes); 100 log.debug("validated nodes"); 101 } 102 103 private void simpleValidate(Collection <WorkspaceNode> nodes) throws DataVersioningException 104 { 105 boolean trace = log.isTraceEnabled(); 106 for (WorkspaceNode workspaceNode : nodes) 107 { 108 Fqn fqn = workspaceNode.getFqn(); 109 if (trace) log.trace("Validating version for node " + fqn); 110 111 NodeSPI realNode; 112 realNode = cache.peek(fqn); 113 114 if (realNode == null && !workspaceNode.isCreated()) 117 { 118 throw new DataVersioningException("Real node for " + fqn + " is null, and this wasn't newly created in this tx!"); 119 } 120 121 if (realNode != null && workspaceNode.isCreated()) 122 { 123 throw new DataVersioningException("Tx attempted to create " + fqn + " anew. It has already been created since this tx started by another (possibly remote) tx."); 124 } 125 126 if (!workspaceNode.isCreated() && (workspaceNode.isDeleted() || workspaceNode.isDirty())) 127 { 128 if (!realNode.getVersion().getClass().equals(workspaceNode.getVersion().getClass()) && checkNotInitialRootVersion(realNode)) 130 { 131 throw new DataVersioningException("Attempting to apply data version of type " + workspaceNode.getVersion().getClass() + " to a node [fqn = " + realNode.getFqn() + "] that already contains version of type " + realNode.getVersion().getClass()); 132 } 133 if (realNode.getVersion().newerThan(workspaceNode.getVersion())) 134 { 135 throw new DataVersioningException("DataNode [" + fqn + "] version " + workspaceNode.getNode().getVersion() + " is newer than workspace node " + workspaceNode.getVersion()); 137 } 138 } 139 } 140 } 141 142 private boolean checkNotInitialRootVersion(NodeSPI n) 143 { 144 return !n.getFqn().isRoot() || !(n.getVersion() instanceof DefaultDataVersion) || n.getVersion() != DefaultDataVersion.ZERO; 145 } 146 147 private void commit(GlobalTransaction gtx) 148 { 149 TransactionWorkspace workspace; 150 151 try 152 { 153 workspace = getTransactionWorkspace(gtx); 154 } 155 catch (CacheException e) 156 { 157 log.trace("we can't rollback", e); 158 return; 159 } 160 161 log.debug("commiting validated changes "); 162 Collection <WorkspaceNode> nodes = workspace.getNodes().values(); 164 165 boolean trace = log.isTraceEnabled(); 166 for (WorkspaceNode wrappedNode : nodes) 167 { 168 if (wrappedNode.isDeleted()) 170 { 171 if (trace) log.trace("Workspace node " + wrappedNode.getFqn() + " deleted; removing"); 172 NodeSPI dNode = wrappedNode.getNode(); 173 174 175 if (dNode.getFqn().isRoot()) 176 { 177 log.warn("Attempted to delete the root node"); 178 } 179 else 180 { 181 NodeSPI parent = dNode.getParent(); 182 if (parent == null) 183 { 184 throw new IllegalStateException ("dNode " + dNode + " has no parent"); 185 } 186 187 parent.removeChildDirect(dNode.getFqn().getLastElement()); 188 } 189 } 190 else 191 { 192 if (wrappedNode.isDirty()) 195 { 196 NodeSPI current = wrappedNode.getNode(); 197 Map mergedChildren = wrappedNode.getMergedChildren(); 198 199 current.setChildrenMapDirect(mergedChildren); 201 202 Map mergedData = wrappedNode.getMergedData(); 205 206 current.clearDataDirect(); 207 current.putDirect(mergedData); 208 209 if (wrappedNode.isVersioningImplicit()) 210 { 211 if (trace) log.trace("Versioning is implicit; incrementing."); 212 current.setVersion(((DefaultDataVersion) wrappedNode.getVersion()).increment()); 213 } 214 else 215 { 216 if (trace) log.trace("Versioning is explicit; not attempting an increment."); 217 current.setVersion(wrappedNode.getVersion()); 218 } 219 if (trace) 220 { 221 log.trace("Setting version of node " + current.getFqn() + " from " + wrappedNode.getVersion() + " to " + current.getVersion()); 222 } 223 } 224 else 225 { 226 if (trace) 227 { 228 log.trace("Merging node " + wrappedNode.getFqn() + " not necessary since the node is not dirty"); 229 } 230 } 231 } 232 } 233 234 } 235 236 private void rollBack(GlobalTransaction gtx) 237 { 238 TransactionWorkspace workspace; 239 try 240 { 241 workspace = getTransactionWorkspace(gtx); 242 Map nodes = workspace.getNodes(); 243 nodes.clear(); 244 } 245 catch (CacheException e) 246 { 247 log.info("Unable to roll back", e); 248 } 249 } 250 } 251 | Popular Tags |