/* * 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.ThreadSafe; import org.jboss.cache.config.Configuration; import org.jboss.cache.interceptors.base.CommandInterceptor; import org.jgroups.Address; import java.util.List; import java.util.Map; import java.util.Set; /** * Interface for a Cache where data mappings are grouped and stored in a tree data * structure consisting of {@link Node}s. *

* This is the central construct and basic client API of JBoss Cache and is used for * cache-wide operations. *

* The cache is constructed using a {@link CacheFactory} and is started * using {@link #start}, if not already started by the CacheFactory. *

* Once constructed, the Cache interface can be used to create or access {@link Node}s, which contain data. Once references * to {@link Node}s are obtained, data can be stored in them, *

* As a convenience (and mainly to provide a familiar API to the older JBoss Cache 1.x.x releases) methods are provided that * operate directly on nodes. *

*

* A simple example of usage: *

 *    // creates with default settings and starts the cache
 *    Cache cache = new DefaultCacheFactory().createCache();
 *    Fqn personRecords = Fqn.fromString("/org/mycompany/personRecords");
 * 

* Node rootNode = cache.getRoot(); * Node personRecordsNode = rootNode.addChild(personRecords); *

* // now add some person records. * Fqn peterGriffin = Fqn.fromString("/peterGriffin"); * Fqn stewieGriffin = Fqn.fromString("/stewieGriffin"); *

* // the addChild() API uses relative Fqns * Node peter = personRecordsNode.addChild(peterGriffin); * Node stewie = personRecordsNode.addChild(stewieGriffin); *

* peter.put("name", "Peter Griffin"); * peter.put("ageGroup", "MidLifeCrisis"); * peter.put("homicidal", Boolean.FALSE); *

* stewie.put("name", "Stewie Griffin"); * stewie.put("ageGroup", "Infant"); * stewie.put("homicidal", Boolean.TRUE); *

* peter.getFqn().toString(); // will print out /org/mycompany/personRecords/peterGriffin * stewie.getFqn().toString(); // will print out /org/mycompany/personRecords/stewieGriffin *

* peter.getFqn().getParent().equals(stewie.getFqn().getParent()); // will return true *

*

*

* For more information, please read the JBoss Cache user guide and tutorial, available on the JBoss Cache documentation site, * and look through the examples shipped with the JBoss Cache distribution. * * @author Manik Surtani (manik AT jboss DOT org) * @see Node * @see CacheFactory * @since 2.0.0 */ @ThreadSafe public interface Cache extends Lifecycle { /** * Retrieves the configuration of this cache. * * @return the configuration. */ Configuration getConfiguration(); /** * Returns the root node of this cache. * * @return the root node */ Node getRoot(); /** * Adds a {@link org.jboss.cache.notifications.annotation.CacheListener}-annotated object to the entire cache. The object passed in needs to be properly annotated with the * {@link org.jboss.cache.notifications.annotation.CacheListener} annotation otherwise an {@link org.jboss.cache.notifications.IncorrectCacheListenerException} will be thrown. * * @param listener listener to add */ void addCacheListener(Object listener); /** * Removes a {@link org.jboss.cache.notifications.annotation.CacheListener}-annotated object from the cache. The object passed in needs to be properly annotated with the * {@link org.jboss.cache.notifications.annotation.CacheListener} annotation otherwise an {@link org.jboss.cache.notifications.IncorrectCacheListenerException} will be thrown. * * @param listener listener to remove */ void removeCacheListener(Object listener); /** * Retrieves an immutable {@link List} of objects annotated as {@link org.jboss.cache.notifications.annotation.CacheListener}s attached to the cache. * * @return an immutable {@link List} of objects annotated as {@link org.jboss.cache.notifications.annotation.CacheListener}s attached to the cache. */ Set getCacheListeners(); /** * Associates the specified value with the specified key for a {@link Node} in this cache. * If the {@link Node} previously contained a mapping for this key, the old value is replaced by the specified value. * * @param fqn absolute {@link Fqn} to the {@link Node} to be accessed. * @param key key with which the specified value is to be associated. * @param value value to be associated with the specified key. * @return previous value associated with specified key, or null if there was no mapping for key. * A null return can also indicate that the Node previously associated null with the specified key, if the implementation supports null values. * @throws IllegalStateException if the cache is not in a started state. */ V put(Fqn fqn, K key, V value); /** * Convenience method that takes a string representation of an Fqn. Otherwise identical to {@link #put(Fqn, Object, Object)} * * @param fqn String representation of the Fqn * @param key key with which the specified value is to be associated. * @param value value to be associated with the specified key. * @return previous value associated with specified key, or null if there was no mapping for key. * A null return can also indicate that the Node previously associated null with the specified key, if the implementation supports null values. * @throws IllegalStateException if the cache is not in a started state */ V put(String fqn, K key, V value); /** * Under special operating behavior, associates the value with the specified key for a node identified by the Fqn passed in. *
    *
  • Only goes through if the node specified does not exist; no-op otherwise. *
  • Force asynchronous mode for replication to prevent any blocking.
  • *
  • invalidation does not take place.
  • *
  • 0ms lock timeout to prevent any blocking here either. If the lock is not acquired, this method is a no-op, and swallows the timeout exception.
  • *
  • Ongoing transactions are suspended before this call, so failures here will not affect any ongoing transactions.
  • *
  • Errors and exceptions are 'silent' - logged at a much lower level than normal, and this method does not throw exceptions
  • *
* This method is for caching data that has an external representation in storage, where, concurrent modification and * transactions are not a consideration, and failure to put the data in the cache should be treated as a 'suboptimal outcome' * rather than a 'failing outcome'. *

* An example of when this method is useful is when data is read from, for example, a legacy datastore, and is cached before * returning the data to the caller. Subsequent calls would prefer to get the data from the cache and if the data doesn't exist * in the cache, fetch again from the legacy datastore. *

* See JBCACHE-848 for details around this feature. *

* * @param fqn absolute {@link Fqn} to the {@link Node} to be accessed. * @param key key with which the specified value is to be associated. * @param value value to be associated with the specified key. * @throws IllegalStateException if {@link #getCacheStatus()} would not return {@link org.jboss.cache.CacheStatus#STARTED}. */ void putForExternalRead(Fqn fqn, K key, V value); /** * Copies all of the mappings from the specified map to a {@link Node}. * * @param fqn absolute {@link Fqn} to the {@link Node} to copy the data to * @param data mappings to copy * @throws IllegalStateException if the cache is not in a started state */ void put(Fqn fqn, Map data); /** * Convenience method that takes a string representation of an Fqn. Otherwise identical to {@link #put(Fqn, java.util.Map)} * * @param fqn String representation of the Fqn * @param data data map to insert * @throws IllegalStateException if the cache is not in a started state */ void put(String fqn, Map data); /** * Removes the mapping for this key from a Node. * Returns the value to which the Node previously associated the key, or * null if the Node contained no mapping for this key. * * @param fqn absolute {@link Fqn} to the {@link Node} to be accessed. * @param key key whose mapping is to be removed from the Node * @return previous value associated with specified Node's key * @throws IllegalStateException if the cache is not in a started state */ V remove(Fqn fqn, K key); /** * Convenience method that takes a string representation of an Fqn. Otherwise identical to {@link #remove(Fqn, Object)} * * @param fqn string representation of the Fqn to retrieve * @param key key to remove * @return old value removed, or null if the fqn does not exist * @throws IllegalStateException if the cache is not in a started state */ V remove(String fqn, K key); /** * Removes a {@link Node} indicated by absolute {@link Fqn}. * * @param fqn {@link Node} to remove * @return true if the node was removed, false if the node was not found * @throws IllegalStateException if the cache is not in a started state */ boolean removeNode(Fqn fqn); /** * Convenience method that takes a string representation of an Fqn. Otherwise identical to {@link #removeNode(Fqn)} * * @param fqn string representation of the Fqn to retrieve * @return true if the node was found and removed, false otherwise * @throws IllegalStateException if the cache is not in a started state */ boolean removeNode(String fqn); /** * A convenience method to retrieve a node directly from the cache. Equivalent to calling cache.getRoot().getChild(fqn). * * @param fqn fqn of the node to retrieve * @return a Node object, or a null if the node does not exist. * @throws IllegalStateException if the cache is not in a started state */ Node getNode(Fqn fqn); /** * Convenience method that takes a string representation of an Fqn. Otherwise identical to {@link #getNode(Fqn)} * * @param fqn string representation of the Fqn to retrieve * @return node, or null if the node does not exist * @throws IllegalStateException if the cache is not in a started state */ Node getNode(String fqn); /** * Returns all children of a given node. Returns an empty set if there are no children. * The set is unmodifiable. * * @param fqn The fully qualified name of the node * @return Set an unmodifiable set of children names, Object. */ Set getChildrenNames(Fqn fqn); /** * Convenience method that takes a String representation of an Fqn. Otherwise identical to {@link #getChildrenNames(Fqn)} * * @param fqn as a string * @return Set an unmodifiable set of children names, Object. */ Set getChildrenNames(String fqn); /** * Tests if a node is a leaf, i.e., doesn't have any children * @param fqn fqn to test * @return true if it is a leaf, false otherwise */ boolean isLeaf(Fqn fqn); /** * Tests if a node is a leaf, i.e., doesn't have any children * @param fqn fqn to test * @return true if it is a leaf, false otherwise */ boolean isLeaf(String fqn); /** * Convenience method that allows for direct access to the data in a {@link Node}. * * @param fqn absolute {@link Fqn} to the {@link Node} to be accessed. * @param key key under which value is to be retrieved. * @return returns data held under specified key in {@link Node} denoted by specified Fqn. * @throws IllegalStateException if the cache is not in a started state */ V get(Fqn fqn, K key); /** * Convenience method that takes a string representation of an Fqn. Otherwise identical to {@link #get(Fqn, Object)} * * @param fqn string representation of the Fqn to retrieve * @param key key to fetch * @return value, or null if the fqn does not exist. * @throws IllegalStateException if the cache is not in a started state */ V get(String fqn, K key); /** * Eviction call that evicts the specified {@link Node} from memory. * * @param fqn absolute {@link Fqn} to the {@link Node} to be evicted. * @param recursive evicts children as well * @throws IllegalStateException if the cache is not in a started state */ void evict(Fqn fqn, boolean recursive); /** * Eviction call that evicts the specified {@link Node} from memory. Not recursive. * * @param fqn absolute {@link Fqn} to the {@link Node} to be evicted. * @throws IllegalStateException if the cache is not in a started state */ void evict(Fqn fqn); /** * Retrieves a {@link Region} for a given {@link Fqn}. If the region does not exist, * and
  • createIfAbsent
  • is true, then one is created. *

    * If not, parent Fqns will be consulted in turn for registered regions, gradually working up to * Fqn.ROOT. If no regions are defined in any of the parents either, a null is returned. * * @param fqn Fqn that is contained in a region. * @param createIfAbsent If true, will create a new associated region if not found. * @return a MarshRegion. Null if none is found. * @see Region */ Region getRegion(Fqn fqn, boolean createIfAbsent); /** * Removes a region denoted by the Fqn passed in. * * @param fqn of the region to remove * @return true if a region did exist and was removed; false otherwise. */ boolean removeRegion(Fqn fqn); /** * Lifecycle method that initializes configuration state, the root node, etc. * * @throws CacheException if there are creation problems */ void create() throws CacheException; /** * Lifecycle method that starts the cache loader, * starts cache replication, starts the region manager, etc., and (if configured) warms the cache using a * state transfer or cache loader preload. * * @throws CacheException if there are startup problems */ void start() throws CacheException; /** * Lifecycle method that stops the cache, including replication, * clustering, cache loading, notifications, etc., and clears all cache in-memory state. *

    * State can be reconstituted by using either a cache loader or state transfer when the cache starts again. */ void stop(); /** * Lifecycle method that destroys the cache and removes any interceptors/configuration elements. * Cache can then be restarted (potentially after reconfiguring) using {@link #create()} and {@link #start()}. */ void destroy(); /** * Gets where the cache currently is its lifecycle transitions. * * @return the CacheStatus. Will not return null. */ CacheStatus getCacheStatus(); /** * @return the current invocation context for the current invocation and cache instance. * @throws IllegalStateException if the cache has been destroyed. */ InvocationContext getInvocationContext(); /** * Sets the passed in {@link org.jboss.cache.InvocationContext} as current. * * @param ctx invocation context to use * @throws IllegalStateException if the cache has been destroyed. */ void setInvocationContext(InvocationContext ctx); /** * Returns the local address of this cache in a cluster, or null * if running in local mode. * * @return the local address of this cache in a cluster, or null * if running in local mode. */ Address getLocalAddress(); /** * Returns a list of members in the cluster, or null * if running in local mode. * * @return a {@link List} of members in the cluster, or null * if running in local mode. */ List

    getMembers(); /** * Moves a part of the cache to a different subtree. *

    * E.g.: *

    * assume a cache structure such as: *

    *

        *  /a/b/c
        *  /a/b/d
        *  /a/b/e
        * 

    *

    * Fqn f1 = Fqn.fromString("/a/b/c"); * Fqn f2 = Fqn.fromString("/a/b/d"); *

    * cache.move(f1, f2); *

    *

    * Will result in: *

        * 

    * /a/b/d/c * /a/b/e *

    *

    *

    * and now *

    *

        *  Fqn f3 = Fqn.fromString("/a/b/e");
        *  Fqn f4 = Fqn.fromString("/a");
        *  cache.move(f3, f4);
        * 
    *

    * will result in: *

        * /a/b/d/c
        * /a/e
        * 
    * No-op if the node to be moved is the root node. *

    * Note: As of 3.0.0 and when using MVCC locking, more specific behaviour is defined as follows: *

      *
    • A no-op if the node is moved unto itself. E.g., move(fqn, fqn.getParent()) will not do anything.
    • *
    • If a target node does not exist it will be created silently, to be more consistent with other APIs such as put() on a nonexistent node.
    • *
    • If the source node does not exist this is a no-op, to be more consistent with other APIs such as get() on a nonexistent node.
    • *
    * * @param nodeToMove the Fqn of the node to move. * @param newParent new location under which to attach the node being moved. * @throws NodeNotExistsException may throw one of these if the target node does not exist or if a different thread has moved this node elsewhere already. * @throws IllegalStateException if {@link #getCacheStatus()} would not return {@link CacheStatus#STARTED}. */ void move(Fqn nodeToMove, Fqn newParent) throws NodeNotExistsException; /** * Convenience method that takes in string representations of Fqns. Otherwise identical to {@link #move(Fqn, Fqn)} * * @throws IllegalStateException if {@link #getCacheStatus()} would not return {@link CacheStatus#STARTED}. */ void move(String nodeToMove, String newParent) throws NodeNotExistsException; /** * Returns the version of the cache as a string. * * @return the version string of the cache. * @see Version#printVersion */ String getVersion(); /** * Retrieves a defensively copied data map of the underlying node. A convenience method to retrieving a node and * getting data from the node directly. * * @param fqn * @return map of data, or an empty map * @throws CacheException * @throws IllegalStateException if {@link #getCacheStatus()} would not return {@link CacheStatus#STARTED}. */ Map getData(Fqn fqn); /** * Convenience method that takes in a String represenation of the Fqn. Otherwise identical to {@link #getKeys(Fqn)}. */ Set getKeys(String fqn); /** * Returns a set of attribute keys for the Fqn. * Returns null if the node is not found, otherwise a Set. * The set is a copy of the actual keys for this node. *

    * A convenience method to retrieving a node and * getting keys from the node directly. * * @param fqn name of the node * @throws IllegalStateException if {@link #getCacheStatus()} would not return {@link CacheStatus#STARTED}. */ Set getKeys(Fqn fqn); /** * Convenience method that takes in a String represenation of the Fqn. Otherwise identical to {@link #clearData(Fqn)}. * * @throws IllegalStateException if {@link #getCacheStatus()} would not return {@link CacheStatus#STARTED}. */ void clearData(String fqn); /** * Removes the keys and properties from a named node. *

    * A convenience method to retrieving a node and * getting keys from the node directly. * * @param fqn name of the node * @throws IllegalStateException if {@link #getCacheStatus()} would not return {@link CacheStatus#STARTED}. */ void clearData(Fqn fqn); /** * Starts a batch. This is a lightweight batching mechanism that groups cache writes together and finally performs the * write, persistence and/or replication when {@link #endBatch(boolean)} is called rather than for each invocation on the * cache. *

    * Note that if there is an existing transaction in scope and the cache has been configured to use a JTA compliant * transaction manager, calls to {@link #startBatch()} and {@link #endBatch(boolean)} are ignored and treated as no-ops. *

    * * @see #endBatch(boolean) * @since 3.0 */ void startBatch(); /** * Ends an existing ongoing batch. A no-op if a batch has not been started yet. *

    * Note that if there is an existing transaction in scope and the cache has been configured to use a JTA compliant * transaction manager, calls to {@link #startBatch()} and {@link #endBatch(boolean)} are ignored and treated as no-ops. *

    * * @param successful if true, changes made in the batch are committed. If false, they are discarded. * @see #startBatch() * @since 3.0 */ void endBatch(boolean successful); /** * Adds a custom interceptor to the interceptor chain, at specified position, where the first interceptor in the chain * is at position 0 and the last one at getInterceptorChain().size() - 1. * * @param i the interceptor to add * @param position the position to add the interceptor * @since 3.0 */ void addInterceptor(CommandInterceptor i, int position); /** * Adds a custom interceptor to the interceptor chain, after an instance of the specified interceptor type. Throws a * cache exception if it cannot find an interceptor of the specified type. * * @param i interceptor to add * @param afterInterceptor interceptor type after which to place custom interceptor * @since 3.0 */ void addInterceptor(CommandInterceptor i, Class afterInterceptor); /** * Removes the interceptor at a specified position, where the first interceptor in the chain * is at position 0 and the last one at getInterceptorChain().size() - 1. * * @param position the position at which to remove an interceptor * @since 3.0 */ void removeInterceptor(int position); /** * Removes the interceptor of specified type. * * @param interceptorType type of interceptor to remove * @since 3.0 */ void removeInterceptor(Class interceptorType); }