/** * Checks whether a node represented by a given Fqn exists. * Deleted and invalid nodes are not considered. * * @return true if the node exists, false otherwise. */ public Object perform(InvocationContext ctx) { NodeSPI node = ctx.lookUpNode(fqn); return node != null && !node.isDeleted(); }
@Override public Set<NodeSPI<K, V>> getChildrenDirect() { // strip out deleted child nodes... if (children == null || children.size() == 0) return Collections.emptySet(); Set<NodeSPI<K, V>> exclDeleted = new HashSet<NodeSPI<K, V>>(); for (Node<K, V> n : children().values()) { NodeSPI<K, V> spi = (NodeSPI<K, V>) n; if (!spi.isDeleted()) exclDeleted.add(spi); } exclDeleted = Collections.unmodifiableSet(exclDeleted); return exclDeleted; }
/** * Retrieves a {@link org.jboss.cache.Node} referenced by the specified Fqn. * * @param ctx invocation context * @return a Node, or null if the Fqn refers to a node that does not exist. */ public Object perform(InvocationContext ctx) { NodeSPI node = ctx.lookUpNode(fqn); if (node != null && node.isDeleted()) { if (trace) log.trace("Node of type [" + node.getClass().getSimpleName() + "] found but marked as deleted in current scope. Returning null."); return null; } if (trace) log.trace("Found node, returning " + node); return node; }
private Set<Object> getCorrectedChildNames(Collection<NodeSPI<?, ?>> children) { // prune deleted children - JBCACHE-1136 Set<Object> childNames = new HashSet<Object>(); for (NodeSPI child : children) { if (!child.isDeleted()) { Object e = child.getFqn().getLastElement(); childNames.add(e); } } return childNames; } }
/** * Retrieves Set of keys for all the data stored in a node referenced by the specified Fqn. * * @param ctx invocation context * @return a Set<K> of data keys contained in a node for a given Fqn, or null if the Fqn refers to a node that does not exist. */ public Object perform(InvocationContext ctx) { NodeSPI n = ctx.lookUpNode(fqn); if (n == null || n.isDeleted()) return null; return n.getKeysDirect(); }
/** * Retrieves the names of children for a specific Fqn. * * @param ctx invocation context * @return a Set<Object> of child names, for a given Fqn, or null if the Fqn refers to a node that does not exist. */ @SuppressWarnings("unchecked") @Override public Object perform(InvocationContext ctx) { NodeSPI<?, ?> n = fqn == null ? null : ctx.lookUpNode(fqn); if (n == null || n.isDeleted()) return null; Map<Object, ? extends Node<?, ?>> childrenMap = n.getChildrenMapDirect(); Collection<NodeSPI<?, ?>> children = (Collection<NodeSPI<?, ?>>) (childrenMap.isEmpty() ? Collections.emptySet() : childrenMap.values()); return getCorrectedChildNames(children); }
/** * Retrieves the value stored under a specified key in a node referenced by the specified Fqn. * * @return an Object of type V, stored under a specific key in a node for a given Fqn, or null if the Fqn refers to a node that does not exist. */ public Object perform(InvocationContext ctx) { NodeSPI n = ctx.lookUpNode(fqn); if (n == null) { if (trace) log.trace("Node not found"); return null; } if (n.isDeleted()) { if (trace) log.trace("Node has been deleted and is of type " + n.getClass().getSimpleName()); return null; } if (sendNodeEvent) notifier.notifyNodeVisited(fqn, true, ctx); Object result = n.getDirect(key); if (trace) log.trace("Found value " + result); if (sendNodeEvent) notifier.notifyNodeVisited(fqn, false, ctx); return result; }
/** * Retrieves an unmodifiable map of data contained in a node referenced by the specified Fqn. * * @return an unmodifiable Map<K, V> of data contained in a node for a given Fqn, or null if the Fqn refers to a node that does not exist. */ public Object perform(InvocationContext ctx) { NodeSPI<?, ?> n = ctx.lookUpNode(fqn); if (n == null || n.isDeleted()) return null; return Immutables.immutableMapCopy(n.getDataDirect()); }
/** * Removes the node referenced by the specified Fqn. */ public Object perform(InvocationContext ctx) { if (trace) log.trace("perform(" + globalTransaction + ", " + fqn + ")"); // Find the node targetNode = peekVersioned(ctx); if (targetNode == null || targetNode.isDeleted()) { if (trace) log.trace("node " + fqn + " not found"); return false; } notifyBeforeRemove(targetNode, ctx); boolean found = targetNode.isValid() && !targetNode.isDeleted(); recursivelyMarkAsRemoved(targetNode, ctx); // make sure we clear all data on this node! targetNode.clearDataDirect(); notifyAfterRemove(ctx); return found; }
if (childNode == null || !childNode.isDeleted()) childNames.add(childFqn.getLastElement());
/** * Moves a node, from <tt>fqn</tt> to <tt>to</tt>, and returns null. * * @param ctx invocation context * @return null */ public Object perform(InvocationContext ctx) { if (fqn.isDirectChildOf(to)) { if (log.isDebugEnabled()) log.debug("Attempting to move " + fqn + " onto itself. Nothing to do."); return null; } NodeSPI node = ctx.lookUpNode(fqn); if (node == null || node.isDeleted()) { if (trace) log.trace("Node " + fqn + " does not exist when attempting to move node! Not doing anything."); return null; } if (trace) log.trace("Moving " + fqn + " to sit under " + to); // the actual move algorithm. NodeSPI newNode = ctx.lookUpNode(Fqn.fromRelativeElements(to, fqn.getLastElement())); Fqn newNodeFqn = newNode.getFqn(); // at this stage all child node objects we need have been created and are available in the ctx. // we just need to mark old ones as deleted, new ones as created, and move data across. notifier.notifyNodeMoved(fqn, newNodeFqn, true, ctx); moveRecursively(node, newNode, ctx); notifier.notifyNodeMoved(fqn, newNodeFqn, false, ctx); return null; }
/** * Test if this node needs to be 'undeleted' * reverse the "remove" if the node has been previously removed in the same tx, if this operation is a put() */ public static void manageReverseRemove(InvocationContext ctx, NodeSPI childNode, boolean reverseRemoveCheck, List createdNodes, CommandsFactory commandsFactory) { if (ctx.getGlobalTransaction() != null) //if no tx then reverse remove does not make sense { Fqn fqn = childNode.getFqn(); TransactionContext transactionContext = ctx.getTransactionContext(); boolean needToReverseRemove = reverseRemoveCheck && childNode.isDeleted() && transactionContext != null && transactionContext.getRemovedNodes().contains(fqn); if (!needToReverseRemove) return; childNode.markAsDeleted(false); //if we'll rollback the tx data should be added to the node again Map oldData = new HashMap(childNode.getDataDirect()); PutDataMapCommand command = commandsFactory.buildPutDataMapCommand(ctx.getGlobalTransaction(), fqn, oldData); // txTable.get(gtx).addUndoOperation(command); --- now need to make sure this is added to the normal mods list instead transactionContext.addModification(command); //we're prepared for rollback, now reset the node childNode.clearDataDirect(); if (createdNodes != null) { createdNodes.add(childNode); } } } }
public NodeSPI peek(Fqn fqn, boolean includeDeletedNodes, boolean includeInvalidNodes) { if (trace) { log.trace("peek " + fqn + ", includeDeletedNodes:" + includeDeletedNodes + ", includeInvalidNodes:" + includeInvalidNodes); } if (fqn == null || fqn.size() == 0) return getRoot(); NodeSPI n = getRoot(); int fqnSize = fqn.size(); for (int i = 0; i < fqnSize; i++) { Object obj = fqn.get(i); n = n.getChildDirect(obj); if (n == null) { return null; } else if (!includeDeletedNodes && n.isDeleted()) { return null; } else if (!includeInvalidNodes && !n.isValid()) { return null; } } return n; }
@SuppressWarnings("unchecked") private void storeInternalState(Set<Fqn> affectedFqns, InvocationContext ctx) throws Exception { // we need to suspend any txs here since they would be in the tx-committed state and if the loader attempts to // use JTA (E.g., a JDBC CL using connections from a tx aware datasource) it will fail since the tx is in an // illegal state to perform writes. See JBCACHE-1408. Transaction tx = txMgr.suspend(); try { for (Fqn f : affectedFqns) { // NOT going to store tombstones!! NodeSPI n = ctx.lookUpNode(f); if (n != null && !n.isDeleted()) { Map<Object, Object> internalState = n.getInternalState(false); loader.put(f, internalState); } } } finally { txMgr.resume(tx); } } }
/** * Evicts a node. * <p/> * See {@link org.jboss.cache.interceptors.EvictionInterceptor#visitEvictFqnCommand(org.jboss.cache.InvocationContext , EvictCommand)} * which is where the return value is used * * @return true if the node is now absent from the cache. Returns false if the node still exists; i.e. was only data removed because it still has children. */ public Object perform(InvocationContext ctx) { NodeSPI node = lookupForEviction(ctx, fqn); if ((node == null || node.isDeleted() || node.isResident()) && !recursiveEvictOnRoot(node)) { return true; } else if (recursive) { Collection<Fqn> nodesToEvict = getRecursiveEvictionNodes(); for (Fqn aFqn : nodesToEvict) { evictNode(aFqn, ctx, lookupForEviction(ctx, aFqn)); } return !nodesToEvict.isEmpty(); } else { return evictNode(fqn, ctx, node); } }
if (skipMarkerCheck || n.isDeleted())
if (n == null || !n.isDeleted())