/* * JBoss, Home of Professional Open Source. * Copyright 2000 - 2008, Red Hat Middleware LLC, and individual contributors * as indicated by the @author tags. See the copyright.txt file in the * distribution for a full listing of individual contributors. * * This is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this software; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA, or see the FSF site: http://www.fsf.org. */ package org.jboss.cache; import net.jcip.annotations.NotThreadSafe; import org.jboss.cache.lock.NodeLock; import org.jboss.cache.optimistic.DataVersion; import org.jboss.cache.transaction.GlobalTransaction; import java.util.Map; import java.util.Set; /** * A more detailed interface to {@link Node}, which is used when writing plugins for or extending JBoss Cache. References are usually * obtained by calling methods on {@link org.jboss.cache.CacheSPI}. *

* You should NEVER attempt to directly cast a {@link Node} instance to this interface. In future, the implementation may not allow it. *

* This interface contains overridden method signatures of some methods from {@link Node}, overridden to ensure return * types of {@link Node} are replaced with {@link NodeSPI}. *

* An important note on the xxxDirect() methods below. These methods are counterparts to similarly named * methods in {@link Node} - e.g., {@link NodeSPI#getDirect(Object)} is a direct access counterpart to {@link Node#get(Object)}, * the difference being that: *

*

*

* The big difference with the direct access methods are that it is the onus of the caller to ensure proper locks are obtained * prior to the call. A proper call should have gone through a locking-capable interceptor first and based on the cache * configuration's locking policy, an appropriate lock should be obtained prior to the call. These direct access methods will * throw {@link org.jboss.cache.lock.LockingException}s if appropriate locks haven't been obtained by the caller. *

* It is important to node that the direct read methods, such as getDataDirect(), return unmodifiable collections. * In addition to being unmodifiable, they are also defensively copied from the underlying data map to ensure view consistency. *

* * @author Manik Surtani (manik AT jboss DOT org) * @see Node * @see org.jboss.cache.CacheSPI * @since 2.0.0 */ @NotThreadSafe public interface NodeSPI extends Node { /** * Returns true if the children of this node were loaded from a cache loader. * * @return true if the children of this node were loaded from a cache loader. */ boolean isChildrenLoaded(); /** * Sets if the children of this node were loaded from a cache loader. * * @param loaded true if loaded, false otherwise */ void setChildrenLoaded(boolean loaded); /** * Returns true if the data was loaded from the cache loader. * * @return true if the data was loaded from the cache loader. */ boolean isDataLoaded(); /** * Sets if the data was loaded from the cache loader. * * @param dataLoaded true if loaded, false otherwise */ void setDataLoaded(boolean dataLoaded); /** * Returns a map to access the raw children. * This method may return a null if the node does not have any children. It is important to note that this method * returns a direct reference to the underlying child map and is intended for internal use only. Incorrect use * may result in very inconsistent state of the cache. * * @return Map, keyed by child name, values Nodes. */ Map> getChildrenMapDirect(); /** * Sets the node's children explictly. * This method will remove all children currently associated with this node and add all the children passed in. * * @param children cannot be null */ void setChildrenMapDirect(Map> children); /** * Returns an existing child or creates a new one using a global transaction. * * @param name name of child to create * @param tx transaction under which to create child * @return newly created node * @deprecated should use the {@link org.jboss.cache.NodeFactory} instead. */ @Deprecated NodeSPI getOrCreateChild(Object name, GlobalTransaction tx); /** * Returns a lock for this node. * * @return node lock * @deprecated this will be removed in 3.0.0. Please use methods on the {@link org.jboss.cache.lock.LockManager} to lock and unlock nodes. */ @Deprecated NodeLock getLock(); /** * Sets the FQN of this node and resets the names of all children as well. * * @param f fqn to set */ void setFqn(Fqn f); /** * Returns true if the instance has been deleted in the current transaction. * * @return true if the instance has been deleted in the current transaction. */ boolean isDeleted(); /** * Marks the node as being deleted (or not) in the current transaction. This is not recursive, child nodes are not affected. * * @param marker true if the node has been deleted, false if not. */ void markAsDeleted(boolean marker); /** * Same as {@link #markAsDeleted(boolean)} except that the option to recurse into children is provided. * * @param marker true if the node has been deleted, false if not. * @param recursive if true, child nodes (and their children) are marked as well. */ void markAsDeleted(boolean marker, boolean recursive); /** * Adds or replaces a child by name. * * @param nodeName child node name (not an FQN) * @param nodeToAdd child node */ void addChild(Object nodeName, Node nodeToAdd); /** * Prints details of this node to the StringBuilder passed in. * * @param sb StringBuilder to print to * @param indent depth of this node in the tree. Used to indent details by prepending spaces. */ void printDetails(StringBuilder sb, int indent); /** * Prints basic information of this node to the StringBuilder passed in. * * @param sb StringBuilder to print to * @param indent depth of this node in the tree. Used to indent details by prepending spaces. */ @Deprecated void print(StringBuilder sb, int indent); // versioning /** * Sets the data version of this node if versioning is supported. * * @param version data version to apply * @throws UnsupportedOperationException if versioning is not supported */ void setVersion(DataVersion version); /** * Returns the data version of this node if versioning is supported. * * @return data version * @throws UnsupportedOperationException if versioning is not supported */ DataVersion getVersion(); // ------- these XXXDirect() methods work directly on the node and bypass the interceptor chain. /** * Functionally the same as {@link #getChildren()} except that it operates directly on the node and bypasses the * interceptor chain. *

* The caller needs to ensure a proper lock has been obtained prior to calling this method, otherwise a * {@link org.jboss.cache.lock.LockingException} will be thrown. *

* * @return set of child nodes. * @see #getChildren() */ Set> getChildrenDirect(); /** * Directly removes all children for this node. * The only direct method that does not have a non-direct counterpart. */ void removeChildrenDirect(); /** * Retrieves children (directly), optionally including any marked as deleted nodes. *

* The caller needs to ensure a proper lock has been obtained prior to calling this method. * * @param includeMarkedAsDeleted if true, the returned set will include nodes marked as deleted * @return a set of nodes * @throws org.jboss.cache.lock.LockingException * if locking was not obtained */ Set> getChildrenDirect(boolean includeMarkedAsDeleted); /** * Retrives a child directly by name. * Functionally the same as {@link #getChild(Object)} except that it bypasses the * interceptor chain. *

* The caller needs to ensure a proper lock has been obtained prior to calling this method. * * @param childName name of child * @return child node * @throws org.jboss.cache.lock.LockingException * if locking was not obtained * @see #getChild(Object) */ NodeSPI getChildDirect(Object childName); /** * Adds a child directly to a Node. * Functionally the same as {@link #addChild(Fqn)} except that it bypasses the * interceptor chain. *

* The caller needs to ensure a proper lock has been obtained prior to calling this method. * * @param childName name of child * @return child node * @throws org.jboss.cache.lock.LockingException * if locking was not obtained * @see #addChild(Fqn) */ NodeSPI addChildDirect(Fqn childName); /** * Same as {@link #addChildDirect(Fqn)} except that it optionally allows you to suppress notification events for * the creation of this node. * * @param f name of child * @param notify if true, notification events are sent; if false, they are not * @return child node * @throws org.jboss.cache.lock.LockingException * if locking was not obtained * @see #addChild(Fqn) */ NodeSPI addChildDirect(Fqn f, boolean notify); /** * Same as {@link #addChildDirect(Fqn, boolean)} except that it just takes a child name * * @param childName name of child * @param notify if true, notification events are sent; if false, they are not * @return child node * @throws org.jboss.cache.lock.LockingException * if locking was not obtained * @see #addChild(Fqn) */ NodeSPI addChildDirect(Object childName, boolean notify); /** * Directly adds the node passed in to the children map of the current node. Will throw a CacheException if * child.getFqn().getParent().equals(getFqn()) returns false. * * @param child child to add */ void addChildDirect(NodeSPI child); /** * Retrives a child directly by fully qualified name. * Functionally the same as {@link #getChild(Fqn)} except that it bypasses the * interceptor chain. *

* The caller needs to ensure a proper lock has been obtained prior to calling this method. * * @param childName name of child * @return child node * @throws org.jboss.cache.lock.LockingException * if locking was not obtained * @see #getChild(Fqn) */ NodeSPI getChildDirect(Fqn childName); /** * Removes a child directly from a node. * Functionally the same as {@link #removeChild(Fqn)} except that it bypasses the * interceptor chain. *

* The caller needs to ensure a proper lock has been obtained prior to calling this method, otherwise a * * @param fqn of child. * @return true if the node was found, false otherwise * @throws org.jboss.cache.lock.LockingException * if locking was not obtained * @see #removeChild(Fqn) */ boolean removeChildDirect(Fqn fqn); /** * Removes a child directly from a node. * Functionally the same as {@link #removeChild(Object)} except that bypasses the * interceptor chain. *

* The caller needs to ensure a proper lock has been obtained prior to calling this method. * * @param childName of child. * @return true if the node was found, false otherwise * @throws org.jboss.cache.lock.LockingException * if locking was not obtained * @see #removeChild(Object) */ boolean removeChildDirect(Object childName); /** * Removes a data key directly from a node. * Functionally the same as {@link #remove(Object)} except that it bypasses the * interceptor chain. *

* The caller needs to ensure a proper lock has been obtained prior to calling this method. * * @param key to remove * @return the old data contained under the key * @throws org.jboss.cache.lock.LockingException * if locking was not obtained * @see #remove(Object) */ V removeDirect(K key); /** * Functionally the same as {@link #put(Object,Object)} except that it operates directly on the node and bypasses the * interceptor chain. *

* The caller needs to ensure a proper lock has been obtained prior to calling this method, otherwise a * {@link org.jboss.cache.lock.LockingException} will be thrown. *

* * @param key of data * @param value of data * @return the previous value under the key passed in, or null * @see #put(Object,Object) */ V putDirect(K key, V value); /** * Functionally the same as {@link #putAll(Map)} except that it operates directly on the node and bypasses the * interceptor chain. *

* The caller needs to ensure a proper lock has been obtained prior to calling this method, otherwise a * {@link org.jboss.cache.lock.LockingException} will be thrown. *

* * @param data to put * @see #putAll(Map) */ void putAllDirect(Map data); /** * Functionally the same as {@link #getData()} except that it operates directly on the node and bypasses the * interceptor chain. *

* Note that this returns a reference to access the node's data. * This data should only be modified by the cache itself. * This method should never return null. *

* The caller needs to ensure a proper lock has been obtained prior to calling this method, otherwise a * {@link org.jboss.cache.lock.LockingException} will be thrown. *

* * @return map containing data * @see #getData() */ Map getDataDirect(); /** * Functionally the same as {@link #get(Object)} except that it operates directly on the node and bypasses the * interceptor chain. *

* The caller needs to ensure a proper lock has been obtained prior to calling this method, otherwise a * {@link org.jboss.cache.lock.LockingException} will be thrown. *

* * @param key data to get * @return value under key * @see #get(Object) */ V getDirect(K key); /** * Returns true if a mapping exists for this key. Returns false if no * mapping exists. * * @param key The key checked for inclusion in the node data. * @return true if a mapping exists for the key, false if not. */ boolean containsKeyDirect(K key); /** * Functionally the same as {@link #clearData()} except that it operates directly on the node and bypasses the * interceptor chain. *

* The caller needs to ensure a proper lock has been obtained prior to calling this method, otherwise a * {@link org.jboss.cache.lock.LockingException} will be thrown. *

* * @see #clearData() */ void clearDataDirect(); /** * Functionally the same as {@link #getKeys()} except that it operates directly on the node and bypasses the * interceptor chain. *

* The caller needs to ensure a proper lock has been obtained prior to calling this method, otherwise a * {@link org.jboss.cache.lock.LockingException} will be thrown. *

* * @return set of keys * @see #getKeys() */ Set getKeysDirect(); /** * Functionally the same as {@link #getChildrenNames()} except that it operates directly on the node and bypasses the * interceptor chain. *

* The caller needs to ensure a proper lock has been obtained prior to calling this method, otherwise a * {@link org.jboss.cache.lock.LockingException} will be thrown. *

* * @return set of children names * @see #getChildrenNames() */ Set getChildrenNamesDirect(); /** * Retrieves a reference to the cache in which this Node resides. * * @return a cache */ CacheSPI getCache(); // ----------- these methods override their corresponding methods in Node, so that the return types are NodeSPI rather than Node. /** * Returns the parent node as a {@link NodeSPI}, instead * of {@link Node} from {@link Node#getParent()}, and is otherwise identical. * * @return parent node * @see Node#getParent() */ NodeSPI getParentDirect(); /** * @return true if the node has one or more child nodes; false otherwise. */ boolean hasChildrenDirect(); /** * Very similar to {@link #getDataDirect()}, except that this method may also encode some internal data as attributes in the map, * using special _JBOSS_INTERNAL_XXX Strings as keys. Designed to be used by {@link org.jboss.cache.statetransfer.StateTransferGenerator} * and {@link org.jboss.cache.interceptors.CacheStoreInterceptor} which attempt to serialize nodes into a stream for storage or transfer. * * @param onlyInternalState if true, the map will only contain internal state and no other data. * @return a map containing data as well as additional information about this node. * @since 2.1.0 */ Map getInternalState(boolean onlyInternalState); /** * Very similar to {@link #putAllDirect(java.util.Map)} except that this method first scans the map for any internal attributes * using special _JBOSS_INTERNAL_XXX Strings as keys, and uses these to set internal attributes before passing * the remaining attributes to {@link #putAllDirect(java.util.Map)}. Designed to be used by {@link org.jboss.cache.statetransfer.StateTransferIntegrator} * and {@link org.jboss.cache.interceptors.CacheLoaderInterceptor} classes which attempt to create nodes based on a data stream. * * @param state state to be applied * @since 2.1.0 */ void setInternalState(Map state); /** * Sets the validity of a node. By default, all nodes are valid unless they are deleted, invalidated or moved, either * locally or remotely. To be used in conjunction with {@link #isValid()}. * * @param valid if true, the node is marked as valid; if false, the node is invalid. * @param recursive if true, the validity flag passed in is applied to all children as well. * @since 2.1.0 */ void setValid(boolean valid, boolean recursive); /** * @return true if the node is a null marker node. Only used with MVCC. */ boolean isNullNode(); /** * Marks a node for updating. Internally, this creates a copy of the delegate and performs any checks necessary to * maintain isolation level. *

* Only used with MVCC. * * @param container data container * @param writeSkewCheck if true, and the node supports write skew checking, nodes are tested for write skews. */ void markForUpdate(DataContainer container, boolean writeSkewCheck); /** * Commits any updates made on this node to the underlying data structure, making it visible to all other transactions. *

* Only used with MVCC. * * @param ctx invocation context * @param container data container */ void commitUpdate(InvocationContext ctx, DataContainer container); /** * Only used with MVCC. *

* * @return true if this node has been marked for update, false otherwise. */ boolean isChanged(); /** * Only used with MVCC. *

* * @return true if this node has been newly created in the current scope. */ boolean isCreated(); InternalNode getDelegationTarget(); /** * Sets the created flag on a node. *

* Only used with MVCC. * * @param created flag */ void setCreated(boolean created); /** * Rolls back any changes made to a node. *

* Only used with MVCC. */ void rollbackUpdate(); }