private void prepareForRollback(NodeSPI parentNode) { parentFqn = parentNode.getFqn(); Map targetData = targetNode.getDataDirect(); if (!targetData.isEmpty()) { originalData = new HashMap(targetNode.getDataDirect()); } }
private void notifyBeforeRemove(NodeSPI n, InvocationContext ctx) { if (!skipSendingNodeEvents) { notifier.notifyNodeRemoved(fqn, true, n.getDataDirect(), ctx); } }
@Override public Object perform(InvocationContext ctx) { // first get a hold of existing data. NodeSPI node = ctx.lookUpNode(fqn); Map existingData = node == null ? null : node.getDataDirect(); if (existingData != null && !existingData.isEmpty()) { oldData = new HashMap(existingData); // defensive copy } return super.perform(ctx); }
private int numAttributes(NodeSPI n) { int count = 0; for (Object child : n.getChildrenDirect()) { count += numAttributes((NodeSPI) child); } count += n.getDataDirect().size(); return count; }
@Override public Object perform(InvocationContext ctx) { if (globalTransaction != null) { NodeSPI n = ctx.lookUpNode(fqn); originalData = n == null ? null : new HashMap(n.getDataDirect()); } return super.perform(ctx); }
@Override protected void storeStateForPutDataMap(Fqn f, InvocationContext ctx) throws Exception { loader.put(f, ctx.lookUpNode(f).getDataDirect()); }
/** * 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()); }
/** * Constructs with a node and workspace. */ public WorkspaceNodeImpl(NodeSPI<K, V> node, TransactionWorkspace workspace, NodeFactory<K, V> nodeFactory) { NodeInvocationDelegate delegate = (NodeInvocationDelegate) node; if (!(delegate.getDelegationTarget() instanceof VersionedNode)) { throw new IllegalArgumentException("node " + delegate.getDelegationTarget() + " not VersionedNode"); } this.node = node; this.workspace = workspace; Map<K, V> nodeData = node.getDataDirect(); if (!nodeData.isEmpty()) optimisticDataMap = new HashMap<K, V>(nodeData); this.version = node.getVersion(); if (version == null) { throw new IllegalStateException("VersionedNode version null"); } initFlags(); this.nodeFactory = nodeFactory; }
@Deprecated private List<NodeData> buildNodeDataLegacy(List<NodeData> list, NodeSPI node, boolean mapSafe) { NodeData data = new NodeData(buddyFqnTransformer.getActualFqn(node.getFqn()), node.getDataDirect(), mapSafe); list.add(data); for (Object childNode : node.getChildrenDirect()) { buildNodeData(list, (NodeSPI) childNode, true); } return list; }
/** * Clears the data map in the node referenced by the specified Fqn. * * @param ctx invocation context * @return null */ public Object perform(InvocationContext ctx) { if (trace) log.trace("perform(" + globalTransaction + ", \"" + fqn + "\")"); NodeSPI targetNode = peekVersioned(ctx); if (targetNode == null) { if (log.isDebugEnabled()) log.debug("node " + fqn + " not found"); return null; } Map data = targetNode.getDataDirect(); notifier.notifyNodeModified(fqn, true, NodeModifiedEvent.ModificationType.REMOVE_DATA, data, ctx); targetNode.clearDataDirect(); notifier.notifyNodeModified(fqn, false, NodeModifiedEvent.ModificationType.REMOVE_DATA, data, ctx); return null; }
@Override public Object perform(InvocationContext ctx) { NodeSPI targetNode = peekVersioned(ctx); if (targetNode != null) { Map data = targetNode.getDataDirect(); if (data != null && !data.isEmpty()) originalData = new HashMap(data); } boolean found = (Boolean) super.perform(ctx); // now record rollback info. if (globalTransaction != null && found) { NodeSPI parentNode = targetNode.getParentDirect(); prepareForRollback(parentNode); } return found; }
/** * Returns attributes for a node. */ private Map getNodeAttributes(InvocationContext ctx, Fqn fqn) throws NodeNotLoadedException { if (fqn == null) { throw new NodeNotLoadedException(); } NodeSPI n = ctx.lookUpNode(fqn); if (n != null) { return n.getDataDirect(); } else { throw new NodeNotLoadedException(); } }
Map existingData = nodeSPI.getDataDirect(); if (notifier.shouldNotifyOnNodeModified()) notifier.notifyNodeModified(fqn, false, NodeModifiedEvent.ModificationType.PUT_MAP, nodeSPI.getDataDirect(), ctx);
/** * Removes the specified key from the data map in the node referenced by the specified Fqn. * * @param ctx invocation context * @return the value being removed, if any, otherwise a null. */ public Object perform(InvocationContext ctx) { if (trace) log.trace("perform(" + globalTransaction + ", \"" + fqn + "\", key=" + key + ")"); NodeSPI n = ctx.lookUpNode(fqn); if (n == null) { if (log.isDebugEnabled()) log.debug("node " + fqn + " not found"); return null; } if (notifier.shouldNotifyOnNodeModified()) { notifier.notifyNodeModified(fqn, true, NodeModifiedEvent.ModificationType.REMOVE_DATA, n.getDataDirect(), ctx); } Object oldValue = n.removeDirect(key); if (notifier.shouldNotifyOnNodeModified()) { Map removedData = Collections.singletonMap(key, oldValue); notifier.notifyNodeModified(fqn, false, NodeModifiedEvent.ModificationType.REMOVE_DATA, removedData, ctx); } return oldValue; }
/** * Puts the specified key and value into the data map in the node referenced by the specified Fqn. * * @param ctx invocation context * @return the value being overwritten, if any, otherwise a null. */ public Object perform(InvocationContext ctx) { if (trace) log.trace("Perform('" + globalTransaction + "', '" + fqn + "', k='" + key + "', v='" + value + "')"); NodeSPI n = ctx.lookUpNode(fqn); if (n == null) throw new NodeNotExistsException("Node " + fqn + " does not exist!"); if (notifier.shouldNotifyOnNodeModified()) { notifier.notifyNodeModified(fqn, true, NodeModifiedEvent.ModificationType.PUT_DATA, n.getDataDirect(), ctx); } Object oldValue = n.putDirect(key, value); if (trace) log.trace("Old value is " + oldValue + ", dataLoaded=" + n.isDataLoaded()); if (notifier.shouldNotifyOnNodeModified()) { Map newData = Collections.singletonMap(key, value); notifier.notifyNodeModified(fqn, false, NodeModifiedEvent.ModificationType.PUT_DATA, newData, ctx); } return oldValue; }
/** * 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); } } } }
/** * Generates NodeAdded notifications for all nodes of the tree. This is * called whenever the tree is initially retrieved (state transfer) */ private void notifyAllNodesCreated(InvocationContext ctx, NodeSPI curr) { if (curr == null) return; ctx.setOriginLocal(false); cache.getNotifier().notifyNodeCreated(curr.getFqn(), true, ctx); cache.getNotifier().notifyNodeCreated(curr.getFqn(), false, ctx); // AND notify that they have been modified!! if (!curr.getKeysDirect().isEmpty()) { cache.getNotifier().notifyNodeModified(curr.getFqn(), true, NodeModifiedEvent.ModificationType.PUT_MAP, Collections.emptyMap(), ctx); cache.getNotifier().notifyNodeModified(curr.getFqn(), false, NodeModifiedEvent.ModificationType.PUT_MAP, curr.getDataDirect(), ctx); } ctx.setOriginLocal(true); Set<NodeSPI> children = curr.getChildrenDirect(); for (NodeSPI n : children) { notifyAllNodesCreated(ctx, n); } }