/*
 * Licensed to the Apache Software Foundation (ASF) under one or more contributor license
 * agreements. See the NOTICE file distributed with this work for additional information regarding
 * copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance with the License. You may obtain a
 * copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software distributed under the License
 * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
 * or implied. See the License for the specific language governing permissions and limitations under
 * the License.
 */

package org.apache.geode.cache;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.locks.Lock;

import org.apache.geode.cache.client.ClientRegionFactory;
import org.apache.geode.cache.client.Pool;
import org.apache.geode.cache.client.ServerConnectivityException;
import org.apache.geode.cache.client.ServerOperationException;
import org.apache.geode.cache.client.SubscriptionNotEnabledException;
import org.apache.geode.cache.query.FunctionDomainException;
import org.apache.geode.cache.query.NameResolutionException;
import org.apache.geode.cache.query.QueryInvalidException;
import org.apache.geode.cache.query.QueryInvocationTargetException;
import org.apache.geode.cache.query.QueryService;
import org.apache.geode.cache.query.SelectResults;
import org.apache.geode.cache.query.TypeMismatchException;
import org.apache.geode.cache.snapshot.RegionSnapshotService;

/**
 * Manages subregions and cached data. Each region can contain multiple subregions and entries for
 * data. Regions provide a hierarchical name space within the cache. Also, a region can be used to
 * group cached objects for management purposes.
 * <p>
 *
 * The Region interface basically contains two set of APIs: Region management APIs; and
 * (potentially) distributed operations on entries. Non-distributed operations on entries are
 * provided by the inner interface, {@link org.apache.geode.cache.Region.Entry}.
 * <p>
 *
 * Each {@link org.apache.geode.cache.Cache} defines a single top region called the root region.
 * User applications can use the root region to create subregions for isolated name space and object
 * grouping.
 * <p>
 *
 * A region's name can be any String except that it should not contain the region name separator, a
 * forward slash (/).
 *
 * <code>Region</code>s can be referenced by a relative path name from any region higher in the
 * hierarchy in {@link #getSubregion}. You can get the relative path from the root region with
 * {@link #getFullPath}. The name separator is used to concatenate all the region names together
 * from the root, starting with the root's subregions.
 * <p>
 * Relative region names can provide a convenient method to locate a subregion directly from some
 * higher region. For example, a region structure is as follows: a region named
 * <i>3rd_level_region</i> has parent region <i>2nd_level_region</i>; region <i>2nd_level_region</i>
 * in turn has parent region <i>1st_level_region</i>; and region <i>1st_level_region</i> is a child
 * of the root region. Then,the user can get the region <i>3rd_level_region</i> from the root region
 * by issuing:
 *
 * <pre>
 *  <code>
 *  region3 = root.getSubregion("1st_level_region/2nd_level_region/3rd_level_region");
 *  </code>
 * </pre>
 *
 * or the user can get the region <i>3rd_level_region</i> from region <i>1st_level_region</i> by
 * issuing
 *
 * <pre>
 *  <code>
 *  region3 = region1.getSubregion("2nd_level_region/3rd_level_region");
 *  </code>
 * </pre>
 * <p>
 * Region entries are identified by their key. Any Object can be used as a key as long as the key
 * Object is region-wide unique and implements both the equals and hashCode methods. For regions
 * with distributed scope, the key must also be Serializable.
 * <p>
 * Regions and their entries can be locked. The <code>Lock</code> obtained from
 * {@link #getRegionDistributedLock} is a distributed lock on the entire Region, and the
 * <code>Lock</code> obtained from {@link Region#getDistributedLock} is a distributed lock on the
 * individual entry.
 *
 * <p>
 * If the scope is <code>Scope.GLOBAL</code>, the methods that modify, destroy, or invalidate the
 * entries in this region will also get a distributed lock. See the documentations for
 * {@link #getDistributedLock} and {@link #getRegionDistributedLock} for details on the implicit
 * locking that occurs for regions with <code>Scope.GLOBAL</code>.
 * <p>
 * Unless otherwise specified, all of these methods throw a <code>CacheClosedException</code> if the
 * Cache is closed at the time of invocation, or a <code>RegionDestroyedException</code> if this
 * region has been destroyed. Serializability Requirements for arguments: Several methods in the
 * region API take parameters such as key, value and callback parameters.All of these parameters are
 * typed as objects. For distributed regions, keys, values and callback parameters have to be
 * serializable Failure to meet these serialization requirements causes API methods to throw
 * IllegalArgumentException.
 * <p>
 * Implementation of the java.util.concurrent.ConcurrentMap interface was added in version 6.5.
 * These methods give various levels of concurrency guarantees based on the scope and data policy of
 * the region. They are implemented in the peer cache and client/server cache but are disallowed in
 * peer Regions having NORMAL or EMPTY data policies.
 * <p>
 * The semantics of the ConcurrentMap methods on a Partitioned Region are consistent with those
 * expected on a ConcurrentMap. In particular multiple writers in different JVMs of the same key in
 * the same Partitioned Region will be done atomically.
 * <p>
 * The same is true for a region with GLOBAL scope. All operations will be done atomically since a
 * distributed lock will be held while the operation is done.
 * <p>
 * The same is true for a region with LOCAL scope. All ops will be done atomically since the
 * underlying map is a concurrent hash map and no distribution is involved.
 * <p>
 * For peer REPLICATE and PRELOADED regions atomicity is limited to threads in the JVM the operation
 * starts in. There is no coordination with other members of the system unless the operation is
 * performed in a transaction.
 * <p>
 * For client server regions the atomicity is determined by the scope and data policy of the server
 * region as described above. The operation is actually performed on the server as described above.
 * Clients will always send the ConcurrentMap operation to the server and the result returned by the
 * ConcurrentMap method in client will reflect what was done on the server. Same goes for any
 * CacheListener called on the client. Any local state on the client will be updated to be
 * consistent with the state change made on the server.
 * <p>
 *
 * @see RegionAttributes
 * @see AttributesFactory
 * @see AttributesMutator
 * @see Region.Entry
 * @since GemFire 2.0
 */

public interface Region<K, V> extends ConcurrentMap<K, V> {
  /** The region name separator character. */
  char SEPARATOR_CHAR = '/';

  /** The region name separator character, represented as a string for convenience. */
  String SEPARATOR = "/";

  /**
   * Returns the name of this region. A region's name can be any non-empty String providing it does
   * not contain the name separator, a forward slash (/). If this is the root region, returns
   * "root".
   * <p>
   * Does not throw a <code>CacheClosedException</code> or a <code>RegionDestroyedException</code>.
   *
   * @return the name of this region
   */
  String getName();

  /**
   * Returns the full path of this region starting with a forward slash, followed by the root,
   * including every subregion in the path to this region. The path separator is a forward slash.
   * <p>
   * Does not throw a <code>CacheClosedException</code> or a <code>RegionDestroyedException</code>.
   *
   * @return the full path of this region
   */
  String getFullPath();

  /**
   * Gets the parent region of this region. If this region is a root region (i.e. has no parents),
   * returns null.
   * <p>
   * Does not throw a <code>CacheClosedException</code> or a <code>RegionDestroyedException</code>.
   *
   * @param <PK> the type of keys in the parent region
   * @param <PV> the type of values in the parent region
   * @return the parent region which contains this region; null, if this region is the root region
   * @see Region#createSubregion(String, RegionAttributes) createSubregion
   */
  <PK, PV> Region<PK, PV> getParentRegion();

  /**
   * Returns the <code>RegionAttributes</code> for this region. This object is backed by this
   * region, so if attributes are modified using this region's <code>AttributesMutator</code>, this
   * <code>RegionAttributes</code> object will immediately reflect the change.
   * <p>
   * Does not throw a <code>CacheClosedException</code> or a <code>RegionDestroyedException</code>.
   *
   * @return the <code>RegionAttributes</code> of this region
   * @see Region#createSubregion(String, RegionAttributes)
   * @see AttributesMutator
   * @see AttributesFactory
   * @see #getAttributesMutator
   */
  RegionAttributes<K, V> getAttributes();

  /**
   * Returns a mutator object used for modifying this region's attributes after region creation.
   * Note that some attributes are immutable after region creation.
   *
   * @return the <code>AttributesMutator</code> object
   * @see #getAttributes
   */
  AttributesMutator<K, V> getAttributesMutator();

  /**
   * Returns the <code>CacheStatistics</code> for this region. If the region is a partitioned proxy
   * region then the values for all the statistics will be 0.
   *
   * @return the <code>CacheStatistics</code> of this region
   * @throws StatisticsDisabledException if statistics have been disabled for this region
   */
  CacheStatistics getStatistics() throws StatisticsDisabledException;

  /**
   * Invalidates this region. Invalidation cascades to all entries and subregions. After the
   * <code>invalidateRegion</code>, this region and the entries in it still exist. To remove all the
   * entries and this region, <code>destroyRegion</code> should be used. The region invalidate will
   * be distributed to other caches if the scope is not <code>Scope.LOCAL</code>.
   * <p>
   * Does not update any <code>CacheStatistics</code>.
   *
   * @throws org.apache.geode.distributed.LeaseExpiredException if lease expired on distributed lock
   *         for Scope.GLOBAL
   * @throws TimeoutException if timed out getting distributed lock for <code>Scope.GLOBAL</code>
   * @see CacheListener#afterRegionInvalidate
   */
  void invalidateRegion() throws TimeoutException;

  /**
   * Invalidates this region. The invalidation will cascade to all the subregions and cached
   * entries. After the <code>invalidateRegion</code>, the region and the entries in it still exist.
   * In order to remove all the entries and the region, <code>destroyRegion</code> should be used.
   * The region invalidate will be distributed to other caches if the scope is not
   * <code>Scope.LOCAL</code>.
   * <p>
   * Does not update any <code>CacheStatistics</code>.
   *
   * @param aCallbackArgument a user-defined parameter to pass to callback events triggered by this
   *        method. Can be null. Should be serializable.
   * @throws org.apache.geode.distributed.LeaseExpiredException if lease expired on distributed lock
   *         for <code>Scope.GLOBAL</code>
   * @throws TimeoutException if timed out getting distributed lock for <code>Scope.GLOBAL</code>
   * @throws IllegalArgumentException if aCallbackArgument is not serializable
   * @see CacheListener#afterRegionInvalidate
   */
  void invalidateRegion(Object aCallbackArgument) throws TimeoutException;



  /**
   * Invalidates this region in the local cache only. Invalidation cascades to all entries and
   * subregions. After the <code>invalidateRegion</code>, this region and the entries in it still
   * exist. To remove all the entries and this region, destroyRegion should be used.
   *
   * Does not update any <code>CacheStatistics</code>.
   *
   * @throws IllegalStateException if this region is distributed and
   *         {@link DataPolicy#withReplication replicated}
   * @throws UnsupportedOperationException If the region is a partitioned region
   * @see CacheListener#afterRegionInvalidate
   */
  void localInvalidateRegion();

  /**
   * Invalidates this region in the local cache only, and provides a user-defined argument to the
   * <code>CacheListener</code>. The invalidation will cascade to all the subregions and cached
   * entries. After the <code>invalidateRegion</code>, the region and the entries in it still exist.
   * In order to remove all the entries and the region, destroyRegion should be used.
   *
   * Does not update any <code>CacheStatistics</code>.
   *
   * @param aCallbackArgument a user-defined parameter to pass to callback events triggered by this
   *        method. Can be null.
   * @throws IllegalStateException if the region is distributed and
   *         {@link DataPolicy#withReplication replicated}
   * @throws UnsupportedOperationException If the region is a partitioned region
   * @see CacheListener#afterRegionInvalidate
   */

  void localInvalidateRegion(Object aCallbackArgument);


  /**
   * Destroys the whole region. Destroy cascades to all entries and subregions. After the destroy,
   * this region object can not be used any more and any attempt to use this region object will get
   * <code>RegionDestroyedException</code>. The region destroy will be distributed to other caches
   * if the scope is not <code>Scope.LOCAL</code>.
   * <p>
   * Does not update any <code>CacheStatistics</code>.
   *
   * @throws CacheWriterException if a CacheWriter aborts the operation; if this occurs some
   *         subregions may have already been successfully destroyed.
   * @throws org.apache.geode.distributed.LeaseExpiredException if lease expired on distributed lock
   *         for Scope.GLOBAL
   * @throws TimeoutException if timed out getting distributed lock for Scope.GLOBAL
   * @see CacheListener#afterRegionDestroy
   * @see CacheWriter#beforeRegionDestroy
   */
  void destroyRegion() throws CacheWriterException, TimeoutException;

  /**
   * Destroys the whole region and provides a user-defined parameter object to any
   * <code>CacheWriter</code> invoked in the process. Destroy cascades to all entries and
   * subregions. After the destroy, this region object can not be used any more. Any attempt to use
   * this region object will get a <code>RegionDestroyedException</code> exception. The region
   * destroy is distributed to other caches if the scope is not <code>Scope.LOCAL</code>.
   * <p>
   * Does not update any <code>CacheStatistics</code>.
   *
   * @param aCallbackArgument a user-defined parameter to pass to callback events triggered by this
   *        method. Can be null. Should be serializable.
   * @throws CacheWriterException if a CacheWriter aborts the operation; if this occurs some
   *         subregions may have already been successfully destroyed.
   * @throws org.apache.geode.distributed.LeaseExpiredException if lease expired on distributed lock
   *         for Scope.GLOBAL
   * @throws TimeoutException if timed out getting distributed lock for Scope.GLOBAL
   * @throws IllegalArgumentException if aCallbackArgument is not serializable
   * @see CacheListener#afterRegionDestroy
   * @see CacheWriter#beforeRegionDestroy
   */
  void destroyRegion(Object aCallbackArgument) throws CacheWriterException, TimeoutException;

  /**
   * Destroys the whole region in the local cache only. No <code>CacheWriter</code> is invoked.
   * Destroy cascades to all entries and subregions. After the destroy, this region object can not
   * be used any more and any attempt to use this region object will get
   * {@link RegionDestroyedException} exception. This operation is not distributed to any other
   * cache.
   * <p>
   * Does not update any <code>CacheStatistics</code>.
   *
   * @see CacheListener#afterRegionDestroy
   */
  void localDestroyRegion();

  /**
   * Destroys the whole region in the local cache only, and provides a user-defined argument to a
   * <code>CacheListener</code> if any.
   *
   * No <code>CacheWriter</code> is invoked. Destroy will cascade to all the entries and subregions.
   * After the destroy, this region object can not be used any more. Any attempt to use this region
   * object will get {@link RegionDestroyedException} exception.
   * <p>
   * Does not update any <code>CacheStatistics</code>.
   *
   * @param aCallbackArgument a user-defined parameter to pass to callback events triggered by this
   *        call. Can be null.
   * @see CacheListener#afterRegionDestroy
   */
  void localDestroyRegion(Object aCallbackArgument);

  /**
   * Does a localDestroyRegion, but leaves behind the disk files if this is a region with
   * persistBackup set to true. Calls {@link CacheListener#afterRegionDestroy} on each cache
   * listener on the closed region(s). Also calls {@link CacheCallback#close} on each callback on
   * the closed region(s).
   * <p>
   * Does not update any <code>CacheStatistics</code>.
   *
   * @see Region#localDestroyRegion()
   * @see CacheListener#afterRegionDestroy
   */
  void close();

  /**
   * Obtains the snapshot service to allow the cache data to be imported or exported.
   *
   * @return the snapshot service for the region
   */
  RegionSnapshotService<K, V> getSnapshotService();

  /**
   * Saves the data in this region in a snapshot file. The data is a "concurrent" snapshot in that
   * modifications to the region while the snapshot is being written are not guaranteed to be
   * included or excluded from the snapshot. In other words, if there are concurrent modifications
   * to the region while the snapshot is being written, the snapshot may not reflect a consistent
   * state of the entire region at any moment in time.
   *
   * @param outputStream the output stream to write to
   * @throws IOException if encountered while writing the file
   * @throws UnsupportedOperationException If the region is a partitioned region
   * @see #loadSnapshot
   *
   * @deprecated as of 7.0 use {@link #getSnapshotService()}
   */
  @Deprecated
  void saveSnapshot(OutputStream outputStream) throws IOException;

  /**
   * Loads data from a file that was previously created with the saveSnapshot method. This method
   * essentially destroys the region and automatically recreates it with the data in the snapshot.
   * Any current data in the region is lost, replaced with the data in the snapshot file. Causes
   * this region and all other regions with the same name in remote caches in this distributed
   * system to be reinitialized: remote regions are cleared of all data and distributed
   * {@link DataPolicy#withReplication replicated} remote regions will do a new getInitialImage
   * operation to get the data from this snapshot. Any existing references to this region or any
   * region that is reinitialized in this manner become unusable in that any subsequent methods
   * invoked on those references will throw a RegionReinitializedException (which is a subclass of
   * RegionDestroyedException).
   * <p>
   *
   * In order to continue working with this region, a new reference needs to be acquired using
   * Cache#getRegion or Region#getSubregion (which will block until reinitialization is complete).
   * <p>
   *
   * NOTE: SUBREGIONS ARE DESTROYED. Since loading a snapshot effectively destroys the region and
   * recreates it, all subregions of this region in this cache as well as other remote caches in the
   * same distributed system are destroyed.
   * <p>
   *
   * If any error occurs while loading the snapshot, this region is destroyed and threads in remote
   * caches that are attempting to get a reference to this region will get null instead of a region
   * reference.
   *
   * The only callbacks that are invoked are called for the destroyRegion operation, i.e. the
   * CacheWriter and the close methods on callbacks. CacheListeners and other callback objects have
   * their close() methods called when the region is destroyed, and then those same callback objects
   * will be reinstalled on the new region. Therefore, the callback objects should be able to handle
   * a close() followed by events associated with the newly created region.
   *
   * @param inputStream the inputStream to load the snapshot from
   * @throws ClassNotFoundException if a class cannot be found while loading data
   * @throws IOException if error encountered while reading file.
   * @throws CacheWriterException if a CacheWriter aborts the destroyRegion operation; if this
   *         occurs some subregions may have already been successfully destroyed.
   * @throws org.apache.geode.distributed.LeaseExpiredException if lease expired on distributed lock
   *         for Scope.GLOBAL
   * @throws TimeoutException if timed out getting distributed lock for Scope.GLOBAL
   * @throws UnsupportedOperationException If the region is a partitioned region
   *
   * @see RegionReinitializedException
   *
   * @deprecated as of 7.0 use {@link #getSnapshotService()}
   */
  @Deprecated
  void loadSnapshot(InputStream inputStream)
      throws IOException, ClassNotFoundException, CacheWriterException, TimeoutException;

  /**
   * Returns a subregion with the specified name or null if doesn't exist. The name is relative from
   * this region, so it can be either a simple region name or a relative region path. If
   * <code>regionName</code> is the empty string, then this region itself is returned.
   *
   * @param <SK> the type of keys in the subregion
   * @param <SV> the type of values in the subregion
   * @param path the path to the subregion
   * @return a subregion with the specified relative path from this region, or null if it doesn't
   *         exist
   * @throws IllegalArgumentException if path starts with a forward slash or
   * @see Region Region
   * @see Region#getFullPath
   */
  <SK, SV> Region<SK, SV> getSubregion(String path);


  /**
   * Creates a subregion with the specified name and <code>RegionAttributes</code>. The name must
   * not contain a region name separator. If the subregion is a distributed
   * {@link DataPolicy#withReplication replicated} region, it will be initialized with data from all
   * other caches in this distributed system that have the same region.
   *
   * <p>
   * Updates the {@link CacheStatistics#getLastAccessedTime} and
   * {@link CacheStatistics#getLastModifiedTime} for this region.
   *
   * @param <SK> the type of keys in the subregion
   * @param <SV> the type of values in the subregion
   * @param subregionName the subregion name
   * @param aRegionAttributes the RegionAttributes to be used for the subregion
   * @return a subregion with the specified name
   * @throws IllegalArgumentException if aRegionAttributes is null or if regionName is null, the
   *         empty string, or contains a '/'
   * @throws IllegalStateException If the supplied RegionAttributes violate the
   *         <a href="AttributesFactory.html#creationConstraints">region creation constraints</a>
   *         with a region of the same name in another cache in the distributed system or with this
   *         (parent) region.
   * @throws org.apache.geode.distributed.LeaseExpiredException if lease expired on distributed lock
   *         for Scope.GLOBAL
   * @throws TimeoutException if timed out getting distributed lock for Scope.GLOBAL
   * @throws RegionExistsException if a subregion by the specified name already exists
   * @throws UnsupportedOperationException If the region is a partitioned region
   * @see AttributesFactory
   * @see Region#getFullPath
   * @deprecated as of 7.0 use {@link RegionFactory#createSubregion(Region, String)} or
   *             {@link ClientRegionFactory#createSubregion(Region, String)}.
   */
  @Deprecated
  <SK, SV> Region<SK, SV> createSubregion(String subregionName,
      RegionAttributes<SK, SV> aRegionAttributes) throws RegionExistsException, TimeoutException;

  /**
   * Returns a Set of all subregions. If the recursive parameter is set to true, this call will
   * recursively collect all subregions contained in this region. Otherwise, this call will only
   * return the Set of direct subregions.
   *
   * <p>
   * This <code>Set</code> is unmodifiable. It is backed by this region. Synchronization is not
   * necessary to access or iterate over this set. No <code>ConcurrentModificationException</code>s
   * will be thrown, but subregions may be added or removed while a thread is iterating. Iterators
   * are intended to be used by one thread at a time. If a stable "snapshot" view of the set is
   * required, then call one of the toArray methods on the set and iterate over the array.
   *
   * @param recursive if false, collects direct subregions only; if true, collects all subregions
   *        recursively
   * @return a Set of subregions
   */
  Set<Region<?, ?>> subregions(boolean recursive);


  /**
   * Returns the <code>Region.Entry</code> for the specified key, or null if it doesn't exist.
   *
   * @param key the key corresponding to the Entry to return
   * @return the Region.Entry for the specified key or null if not found in this region
   * @throws NullPointerException if key is null
   */
  Entry<K, V> getEntry(Object key);

  /**
   * Returns the value associated with the specified key. If the value is not present locally for
   * this entry, a netSearch and/or a CacheLoader may be invoked to get the value, depending on the
   * scope of this region. A netSearch looks for a value in every node of the system that defines
   * this region. A netLoad invokes remote loaders one at a time until one returns a value or throws
   * an exception. If any of these methods successfully retrieves a value than the value is
   * immediately returned.
   * <p>
   * For local scope, a local CacheLoader will be invoked if there is one. For global scope, the
   * order is netSearch, localLoad, netLoad. For any other distributed scope, the order is
   * localLoad, netSearch, netLoad.
   * <p>
   * netSearch and netLoad are never performed more than once, so if a loader attempts to do a
   * netSearch and one was already done, then another one will not be done.
   * <p>
   * The value returned by get is not copied, so multi-threaded applications should not modify the
   * value directly, but should use the update methods.
   * <p>
   * Updates the {@link CacheStatistics#getLastAccessedTime}, {@link CacheStatistics#getHitCount},
   * {@link CacheStatistics#getMissCount}, and {@link CacheStatistics#getLastModifiedTime} (if a new
   * value is loaded) for this region and the entry.
   * <p>
   *
   * If the <code>CacheWriter</code> throws a <code>CacheWriterException</code> when a new value is
   * retrieved from a loader, the value will not be put into the cache (a new entry will not be
   * created) but the get will return the value and not propagate the exception.
   *
   * @param key whose associated value is to be returned. The key Object must implement the equals
   *        and hashCode methods. Note that even though key is typed as "Object" if a CacheLoader is
   *        used then make sure you only pass instances of "K" in this parameter.
   * @return the value with specified key, or null if the value is not found and can't be loaded
   * @throws NullPointerException if the key is null
   * @throws IllegalArgumentException if the key does not meet the serializability requirements
   * @throws org.apache.geode.distributed.LeaseExpiredException if lease expired on distributed lock
   *         for Scope.GLOBAL
   * @throws TimeoutException if timed out doing a {@link Cache#getSearchTimeout search} for
   *         distributed or getting a distributed lock for Scope.GLOBAL
   * @throws CacheLoaderException if a cache loader throws an exception, or if the cache loader
   *         returns an object that is not serializable and this is a distributed region
   * @throws PartitionedRegionStorageException for a partitioned region fails to invoke a
   *         {@link CacheLoader}
   * @see CacheLoader#load
   * @see CacheListener#afterCreate
   * @see CacheListener#afterUpdate
   * @see CacheWriter#beforeCreate
   * @see CacheWriter#beforeUpdate
   */
  @Override
  V get(Object key) throws CacheLoaderException, TimeoutException;

  /**
   * Returns the value associated with the specified key, passing the callback argument to any cache
   * loaders or cache writers that are invoked in the operation. If the value is not present locally
   * for this entry, a netSearch and/or a CacheLoader may be invoked to get the value, depending on
   * the scope of this region. A netSearch looks for a value in every node of the system that
   * defines this region. A netLoad invokes remote loaders one at a time until one returns a value
   * or throws an exception. If any of these methods successfully retrieves a value than the value
   * is immediately returned.
   * <p>
   * For local scope, a local CacheLoader will be invoked if there is one. For global scope, the
   * order is netSearch, localLoad, netLoad. For any other distributed scope, the order is
   * localLoad, netSearch, netLoad.
   * <p>
   * netSearch and netLoad are never performed more than once, so if a loader attempts to do a
   * netSearch and one was already done, then another one will not be done.
   * <p>
   * The value returned by get is not copied, so multi-threaded applications should not modify the
   * value directly, but should use the update methods.
   * <p>
   * Updates the {@link CacheStatistics#getLastAccessedTime}, {@link CacheStatistics#getHitCount},
   * {@link CacheStatistics#getMissCount}, and {@link CacheStatistics#getLastModifiedTime} (if a new
   * value is loaded) for this region and the entry.
   *
   * If the <code>CacheWriter</code> throws a <code>CacheWriterException</code> when a new value is
   * retrieved from a loader, then the value will not be put into the cache (a new entry will not be
   * created) but the get will return the value and not propagate the exception.
   *
   * @param key whose associated value is to be returned. The key Object must implement the equals
   *        and hashCode methods. Note that even though key is typed as "Object" if a CacheLoader is
   *        used then make sure you only pass instances of "K" in this parameter.
   * @param aCallbackArgument an argument passed into the CacheLoader if loader is used. This same
   *        argument will also be subsequently passed to a CacheWriter if the loader returns a
   *        non-null value to be placed in the cache. Modifications to this argument made in the
   *        CacheLoader will be visible to the CacheWriter even if the loader and the writer are
   *        installed in different cache VMs. It will also be passed to any other callback events
   *        triggered by this method. May be null. Should be serializable.
   * @return the value with specified key, or null if the value is not found and can't be loaded
   * @throws NullPointerException if key is null
   * @throws IllegalArgumentException if aCallbackArgument is not serializable
   * @throws org.apache.geode.distributed.LeaseExpiredException if lease expired on distributed lock
   *         for Scope.GLOBAL
   * @throws TimeoutException if timed out doing a {@link Cache#getSearchTimeout search} for
   *         distributed or getting a distributed lock for Scope.GLOBAL
   * @throws CacheLoaderException if a cache loader throws an exception, or if the cache loader
   *         returns an object that is not serializable and this is a distributed region
   * @throws PartitionedRegionStorageException for a partitioned region fails to invoke a
   *         {@link CacheLoader}
   * @see RegionAttributes
   * @see CacheLoader#load
   * @see CacheListener#afterCreate
   * @see CacheListener#afterUpdate
   * @see CacheWriter#beforeCreate
   * @see CacheWriter#beforeUpdate
   */
  V get(Object key, Object aCallbackArgument) throws TimeoutException, CacheLoaderException;

  /**
