You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@geode.apache.org by rv...@apache.org on 2015/04/28 23:40:29 UTC
[24/51] [partial] incubator-geode git commit: Init
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/19459053/gemfire-core/src/main/java/com/gemstone/gemfire/cache/DiskWriteAttributesFactory.java
----------------------------------------------------------------------
diff --git a/gemfire-core/src/main/java/com/gemstone/gemfire/cache/DiskWriteAttributesFactory.java b/gemfire-core/src/main/java/com/gemstone/gemfire/cache/DiskWriteAttributesFactory.java
new file mode 100755
index 0000000..a27ef9b
--- /dev/null
+++ b/gemfire-core/src/main/java/com/gemstone/gemfire/cache/DiskWriteAttributesFactory.java
@@ -0,0 +1,254 @@
+/*=========================================================================
+ * Copyright (c) 2010-2014 Pivotal Software, Inc. All Rights Reserved.
+ * This product is protected by U.S. and international copyright
+ * and intellectual property laws. Pivotal products are covered by
+ * one or more patents listed at http://www.pivotal.io/patents.
+ *=========================================================================
+ */
+package com.gemstone.gemfire.cache;
+
+import com.gemstone.gemfire.internal.i18n.LocalizedStrings;
+import java.util.Properties;
+
+import com.gemstone.gemfire.internal.cache.DiskWriteAttributesImpl;
+import com.gemstone.gemfire.internal.cache.xmlcache.CacheXml;
+
+/**
+ * Factory for getting DiskWriteAttribute objects
+ *
+ * @author Mitul Bid
+ * @author Asif
+ * @since 5.1
+ * @deprecated as of 6.5 use {@link DiskStoreFactory} instead
+ */
+@Deprecated
+public final class DiskWriteAttributesFactory implements java.io.Serializable
+{
+ private static final long serialVersionUID = -4077746249663727235L;
+
+ private final Properties props = new Properties();
+
+ //////////// *** Methods to get instances of DWA *** //////////////
+
+ /**
+ *
+ * Creates a new instance of DiskWriteAttributesFactory ready to create a
+ * <code>DiskWriteAttributes</code> with default settings. The default
+ * <code>DiskWriteAttributes</code> thus created will have following
+ * behaviour.
+ * <ul>
+ * <li>synchronous = false
+ * <li>auto-compact = true
+ * <li>allow-force-compaction = false
+ * <li>max-oplog-size = 1024 MB
+ * <li>time-interval = 1 sec
+ * <li>byte-threshold = 0 bytes
+ *
+ * </ul>
+ */
+ public DiskWriteAttributesFactory() {
+
+ }
+
+ /**
+ * Creates a new instance of DiskWriteAttributesFactory Factory ready to
+ * create a <code>DiskWriteAttributes</code> with the same settings as those
+ * in the specified <code>DiskWriteAttributes</code>.
+ *
+ * @param dwa
+ * the <code>DiskWriteAttributes</code> used to initialize this
+ * DiskWriteAttributesFactory
+ */
+ public DiskWriteAttributesFactory(DiskWriteAttributes dwa) {
+
+ this.props.setProperty(CacheXml.BYTES_THRESHOLD,
+ String.valueOf(dwa.getBytesThreshold()));
+ long maxOplogSizeInBytes = convertToBytes(dwa.getMaxOplogSize());
+ this.props.setProperty(CacheXml.MAX_OPLOG_SIZE,
+ String.valueOf(maxOplogSizeInBytes));
+ this.props.setProperty(CacheXml.ROLL_OPLOG,
+ String.valueOf(dwa.isRollOplogs()));
+ this.props.setProperty(DiskWriteAttributesImpl.SYNCHRONOUS_PROPERTY, String
+ .valueOf(dwa.isSynchronous()));
+ if (dwa.getTimeInterval() > -1) {
+ this.props.setProperty(CacheXml.TIME_INTERVAL,
+ String.valueOf(dwa.getTimeInterval()));
+ }
+
+ }
+
+ /**
+ * Sets whether or not the writing to the disk is synchronous.
+ *
+ * @param isSynchronous
+ * boolean if true indicates synchronous writes
+ * @deprecated as of 6.5 use {@link AttributesFactory#setDiskSynchronous} instead
+ */
+ @Deprecated
+ public void setSynchronous(boolean isSynchronous)
+ {
+ this.props.setProperty(DiskWriteAttributesImpl.SYNCHRONOUS_PROPERTY, String
+ .valueOf(isSynchronous));
+ }
+
+ /**
+ * Sets whether or not the rolling of Oplog is enabled .
+ *
+ * @param rollingEnabled true if oplogs are to be compacted automatically;
+ * false if no compaction.
+ * @deprecated as of 6.5 use {@link DiskStoreFactory#setAutoCompact} instead
+ */
+ @Deprecated
+ public void setRollOplogs(boolean rollingEnabled)
+ {
+ this.props.setProperty(CacheXml.ROLL_OPLOG, String.valueOf(rollingEnabled));
+ }
+
+ /**
+ * Sets the threshold at which an oplog will become compactable. While
+ * the percentage of live records in the oplog exceeds
+ * this threshold the oplog will not be compacted.
+ * Once the percentage of live is less than or equal to the threshold
+ * the oplog can be compacted.
+ * The lower the threshold the longer the compactor will wait before compacting an oplog.
+ * The threshold is a percentage in the range 0..100.
+ * The default is 50%.
+ * <P>Examples:
+ * A threshold of 100 causes any oplog that is no longer being written to
+ * to be compactable.
+ * A threshold of 0 causes only oplogs that have no live records to be compactable
+ * in which case the compact can simply remove the oplog file.
+ * A threshold of 50 causes an oplog to become compactable when half of its
+ * live records become dead.
+ * @deprecated as of 6.5 use {@link DiskStoreFactory#setCompactionThreshold} instead
+ */
+ @Deprecated
+ public void setCompactionThreshold(int compactionThreshold) {
+ if (compactionThreshold < 0) {
+ throw new IllegalArgumentException(LocalizedStrings.DiskWriteAttributesImpl_0_HAS_TO_BE_POSITIVE_NUMBER_AND_THE_VALUE_GIVEN_1_IS_NOT_ACCEPTABLE.toLocalizedString(new Object[] {CacheXml.COMPACTION_THRESHOLD, Integer.valueOf(compactionThreshold)}));
+ } else if (compactionThreshold > 100) {
+ throw new IllegalArgumentException(LocalizedStrings.DiskWriteAttributesImpl_0_HAS_TO_BE_LESS_THAN_2_BUT_WAS_1.toLocalizedString(new Object[] {CacheXml.COMPACTION_THRESHOLD, Integer.valueOf(compactionThreshold), Integer.valueOf(100)}));
+ }
+ this.props.setProperty(CacheXml.COMPACTION_THRESHOLD,
+ String.valueOf(compactionThreshold));
+ }
+
+ /**
+ * Sets the maximum oplog size in bytes. When the active oplog size hits
+ * the maximum a new oplog will be created.
+ * <P>Note that this method sets the same attribute as {@link #setMaxOplogSize}.
+ * The last set of the attribute determines its value.
+ * @param maxOplogSize the maximum size of the oplog in bytes.
+ * @throws IllegalArgumentException
+ * if the value specified is a negative number
+ * @deprecated as of 6.5 use {@link DiskStoreFactory#setMaxOplogSize} instead
+ */
+ @Deprecated
+ public void setMaxOplogSizeInBytes(long maxOplogSize)
+ {
+
+ if (maxOplogSize < 0) {
+ throw new IllegalArgumentException(LocalizedStrings.DiskWriteAttributesFactory_MAXIMUM_OPLOG_SIZE_SPECIFIED_HAS_TO_BE_A_NONNEGATIVE_NUMBER_AND_THE_VALUE_GIVEN_0_IS_NOT_ACCEPTABLE.toLocalizedString(Long.valueOf(maxOplogSize)));
+ }
+ this.props.setProperty(CacheXml.MAX_OPLOG_SIZE,
+ String.valueOf(maxOplogSize));
+ }
+
+ /**
+ * Sets the maximum oplog size in megabytes. When the active oplog size hits
+ * the maximum a new oplog will be created.
+ * <P>Note that this method sets the same attribute as {@link #setMaxOplogSizeInBytes}.
+ * The last set of the attribute determines its value.
+ * @param maxOplogSize the maximum size of the oplog in megabytes.
+ * @throws IllegalArgumentException
+ * if the value specified is a negative number
+ * @deprecated as of 6.5 use {@link DiskStoreFactory#setMaxOplogSize} instead
+ */
+ @Deprecated
+ public void setMaxOplogSize(int maxOplogSize)
+ {
+
+ if (maxOplogSize < 0) {
+ throw new IllegalArgumentException(LocalizedStrings.DiskWriteAttributesFactory_MAXIMUM_OPLOG_SIZE_SPECIFIED_HAS_TO_BE_A_NONNEGATIVE_NUMBER_AND_THE_VALUE_GIVEN_0_IS_NOT_ACCEPTABLE.toLocalizedString(Integer.valueOf(maxOplogSize)));
+ }
+ long maxOplogSizeInBytes = convertToBytes(maxOplogSize);
+ this.props.setProperty(CacheXml.MAX_OPLOG_SIZE, String
+ .valueOf(maxOplogSizeInBytes));
+ }
+
+ /**
+ * Takes an int which is supposed to be in megabytes
+ * and converts it to a long. This conversion takes into
+ * account that multiplication can lead to Integer.MAX_VALUE being
+ * exceeded
+ * @param megaBytes
+ * @return the converted value
+ */
+ private long convertToBytes(int megaBytes)
+ {
+ long bytes = megaBytes;
+ bytes = bytes * 1024 * 1024;
+ return bytes;
+ }
+
+ /**
+ * Sets the number of milliseconds that can elapse before unwritten data is
+ * written to disk. It has significance only in case of asynchronous mode of
+ * writing.
+ *
+ * @param timeInterval
+ * Time interval in milliseconds
+ * @throws IllegalArgumentException
+ * if the value specified is a negative number
+ * @deprecated as of 6.5 use {@link DiskStoreFactory#setTimeInterval} instead
+ */
+ @Deprecated
+ public void setTimeInterval(long timeInterval)
+ {
+ if (timeInterval < 0) {
+ throw new IllegalArgumentException(LocalizedStrings.DiskWriteAttributesFactory_TIME_INTERVAL_SPECIFIED_HAS_TO_BE_A_NONNEGATIVE_NUMBER_AND_THE_VALUE_GIVEN_0_IS_NOT_ACCEPTABLE.toLocalizedString(Long.valueOf(timeInterval)));
+ }
+
+ this.props.setProperty(CacheXml.TIME_INTERVAL,
+ String.valueOf(timeInterval));
+ }
+
+ /**
+ * Sets the number of unwritten bytes of data that can be enqueued before
+ * being written to disk. It has significance only in case of asynchronous mode
+ * of writing.
+ *
+ * @param bytesThreshold the maximum number of bytes to enqueue before async data
+ * is flushed.
+ * @throws IllegalArgumentException
+ * if the value specified is a negative number
+ * @deprecated as of 6.5 use {@link DiskStoreFactory#setQueueSize} instead
+ */
+ @Deprecated
+ public void setBytesThreshold(long bytesThreshold)
+ {
+ if (bytesThreshold < 0) {
+ throw new IllegalArgumentException(LocalizedStrings.DiskWriteAttributesFactory_QUEUE_SIZE_SPECIFIED_HAS_TO_BE_A_NONNEGATIVE_NUMBER_AND_THE_VALUE_GIVEN_0_IS_NOT_ACCEPTABLE.toLocalizedString(Long.valueOf(bytesThreshold)));
+ }
+
+ this.props.setProperty(CacheXml.BYTES_THRESHOLD,
+ String.valueOf(bytesThreshold));
+ }
+
+ /**
+ * Creates a <code>DiskWriteAttributes</code> with the current settings.
+ *
+ * @return the newly created <code>DiskWriteAttributes</code>
+ * @throws IllegalStateException
+ * if the current settings has compaction enabled with maximum Oplog
+ * Size specified as infinite ( represented by 0 ) *
+ * @since 5.1
+ * @deprecated as of 6.5 use {@link DiskStoreFactory#create} instead
+ */
+ @Deprecated
+ public DiskWriteAttributes create()
+ {
+ return new DiskWriteAttributesImpl(this.props);
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/19459053/gemfire-core/src/main/java/com/gemstone/gemfire/cache/DuplicatePrimaryPartitionException.java
----------------------------------------------------------------------
diff --git a/gemfire-core/src/main/java/com/gemstone/gemfire/cache/DuplicatePrimaryPartitionException.java b/gemfire-core/src/main/java/com/gemstone/gemfire/cache/DuplicatePrimaryPartitionException.java
new file mode 100644
index 0000000..27d71b3
--- /dev/null
+++ b/gemfire-core/src/main/java/com/gemstone/gemfire/cache/DuplicatePrimaryPartitionException.java
@@ -0,0 +1,56 @@
+/*=========================================================================
+ * Copyright (c) 2010-2014 Pivotal Software, Inc. All Rights Reserved.
+ * This product is protected by U.S. and international copyright
+ * and intellectual property laws. Pivotal products are covered by
+ * one or more patents listed at http://www.pivotal.io/patents.
+ *=========================================================================
+ */
+package com.gemstone.gemfire.cache;
+
+import com.gemstone.gemfire.GemFireException;
+
+/**
+ * This exception is thrown when two nodes are defined with same primary
+ * partitions
+ *
+ * @since 6.6
+ * @author kbachhhav
+ */
+public class DuplicatePrimaryPartitionException extends GemFireException {
+
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * Creates a new <code>DuplicatePrimaryPartitionException</code> with no
+ * detailed message.
+ */
+
+ public DuplicatePrimaryPartitionException() {
+ super();
+ }
+
+ /**
+ * Creates a new <code>DuplicatePrimaryPartitionException</code> with the
+ * given detail message.
+ */
+ public DuplicatePrimaryPartitionException(String message) {
+ super(message);
+ }
+
+ /**
+ * Creates a new <code>DuplicatePrimaryPartitionException</code> with the
+ * given cause and no detail message
+ */
+ public DuplicatePrimaryPartitionException(Throwable cause) {
+ super(cause);
+ }
+
+ /**
+ * Creates a new <code>DuplicatePrimaryPartitionException</code> with the
+ * given detail message and cause.
+ */
+ public DuplicatePrimaryPartitionException(String message, Throwable cause) {
+ super(message, cause);
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/19459053/gemfire-core/src/main/java/com/gemstone/gemfire/cache/DynamicRegionFactory.java
----------------------------------------------------------------------
diff --git a/gemfire-core/src/main/java/com/gemstone/gemfire/cache/DynamicRegionFactory.java b/gemfire-core/src/main/java/com/gemstone/gemfire/cache/DynamicRegionFactory.java
new file mode 100644
index 0000000..4922df9
--- /dev/null
+++ b/gemfire-core/src/main/java/com/gemstone/gemfire/cache/DynamicRegionFactory.java
@@ -0,0 +1,1118 @@
+/*=========================================================================
+ * Copyright (c) 2002-2014 Pivotal Software, Inc. All Rights Reserved.
+ * This product is protected by U.S. and international copyright
+ * and intellectual property laws. Pivotal products are covered by
+ * more patents listed at http://www.pivotal.io/patents.
+ *=========================================================================
+ */
+
+package com.gemstone.gemfire.cache;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
+import java.util.TreeMap;
+
+import com.gemstone.gemfire.InternalGemFireError;
+import com.gemstone.gemfire.SystemFailure;
+import com.gemstone.gemfire.cache.client.Pool;
+import com.gemstone.gemfire.cache.client.PoolManager;
+import com.gemstone.gemfire.cache.client.internal.ServerRegionProxy;
+import com.gemstone.gemfire.cache.util.BridgeWriter;
+import com.gemstone.gemfire.cache.wan.GatewaySender;
+import com.gemstone.gemfire.distributed.DistributedMember;
+import com.gemstone.gemfire.distributed.internal.InternalDistributedSystem;
+import com.gemstone.gemfire.internal.Assert;
+import com.gemstone.gemfire.internal.cache.DistributedRegion;
+import com.gemstone.gemfire.internal.cache.DynamicRegionAttributes;
+import com.gemstone.gemfire.internal.cache.DynamicRegionFactoryImpl;
+import com.gemstone.gemfire.internal.cache.EntryEventImpl;
+import com.gemstone.gemfire.internal.cache.EnumListenerEvent;
+import com.gemstone.gemfire.internal.cache.EvictionAttributesImpl;
+import com.gemstone.gemfire.internal.cache.GemFireCacheImpl;
+import com.gemstone.gemfire.internal.cache.InitialImageOperation;
+import com.gemstone.gemfire.internal.cache.InternalRegionArguments;
+import com.gemstone.gemfire.internal.cache.LocalRegion;
+import com.gemstone.gemfire.internal.cache.RegionEntry;
+import com.gemstone.gemfire.internal.cache.RegionEventImpl;
+import com.gemstone.gemfire.internal.i18n.LocalizedStrings;
+import com.gemstone.gemfire.security.GemFireSecurityException;
+
+
+/**
+ * DynamicRegionFactory provides a distributed region creation service.
+ * Any other member of the GemFire DistributedSystem that has created
+ * an instance of this class will automatically instantiate regions created
+ * through the factory from anywhere else in the DistributedSystem.
+ * <p><p>
+ * Instructions for Use:<br>
+ * <ul>
+ * <li> If your application is a client in a client/server installation,
+ * either specify the pool name in the
+ * {@link DynamicRegionFactory.Config} you'll use to create a
+ * DynamicRegionFactory <i>or</i> specify it
+ * in a dynamic-region-factory element in your cache.xml.
+ *
+ * <li> Before you've created a GemFire Cache in your application, add a
+ * line of code as follows:<br>
+ * <pre><code> DynamicRegionFactory factory = DynamicRegionFactory.get();
+ * factory.open(config);</code></pre>
+ * <pre><code> DynamicRegionFactory myFactoryHandle = DynamicRegionFactory.get().open(config);</code></pre>
+ * or just use a dynamic-region-factory element in the cache.xml.
+ *
+ * <li> Create the GemFire Cache. During cache creation, the list of dynamic Regions will either be discovered
+ * by recovering
+ * their names from disk (see {@link DynamicRegionFactory.Config#persistBackup}) or from other members of the
+ * distributed system.
+ * These dynamic Regions will be created before Cache creation completes.
+ *
+ * <li> Thereafter, when you want to create dynamic distributed Regions,
+ * create them using the {@link #createDynamicRegion}. Regions created with the factory will
+ * inherit their RegionAttributes from their parent Region, though you can override
+ * callbacks when you configure the factory.
+ *
+ * <p>All other instances of GemFire across the distributed system that
+ * instantiate and open a DynamicRegionFactory will also get the dynamic distributed Regions.
+ *
+ * <li>Non-dynamic parent Regions should be declared in cache.xml so that they can be created before
+ * the dynamic Region factory goes active and starts creating Regions. You will have cache creation
+ * problems if this isn't done.
+ *
+ * <li>A DynamicRegionListener can be registered before open is called and before cache creation
+ * so that the listener will be called if dynamic Regions are created during cache creation.
+ *
+ * </ul>
+ * <p>Saving the factory on disk:
+ * If {@link DynamicRegionFactory.Config#persistBackup} is configured for the factory, dynamic Region information
+ * is written to disk for recovery.
+ * By default the current directory is used for this information. The {@link DynamicRegionFactory.Config#diskDir}
+ * can be used to change this default.
+ * <p>
+ * Registering interest in cache server information: The {@link DynamicRegionFactory.Config#registerInterest}
+ * setting determines whether clients will register interest in server keys or not. You will generally want
+ * this to be turned on so that clients will see updates made to servers. In server processes, DynamicRegionFactory
+ * forces use of NotifyBySubscription.
+ * </ul>
+ * <p>
+ * Notes:
+ * <ul>
+ * <li>DynamicRegionFactories in non-client VMs must not be configured with a BridgeWriter.
+ * <li>If {@link #open()} is called before cache creation and the cache.xml has a dynamic-region-factory
+ * element then the cache.xml will override the open call's configuration.
+ *
+ * <li>Since the RegionAttributes of a dynamically created Region are copied
+ * from the parent Region, any callbacks, ({@link CacheListener},
+ * {@link CacheWriter}, and {@link CacheLoader}
+ * are shared by the parent and all its dynamic children
+ * so make sure the callback is thread-safe and that its
+ * {@link CacheCallback#close} implementation does not stop it from functioning.
+ * However the products BridgeLoader, BridgeWriter, and all LRUAlgorithm instances will
+ * be cloned so that each dynamic Region has its own callback.
+ *
+ * <li>The root Region name "DynamicRegions" is reserved. The factory creates a root Region of
+ * that name and uses it to keep track of what dynamic Regions exist. Applications should
+ * not directly access this Region; instead use the methods on this factory.
+ * </ul>
+ * @since 4.3
+ * @author Gideon Low
+ * @author Darrel Schneider
+ * @author Bruce Schuchardt
+ *
+ */
+@SuppressWarnings("deprecation")
+public abstract class DynamicRegionFactory {
+
+ public static final String dynamicRegionListName = "__DynamicRegions";
+ private Region dynamicRegionList = null;
+ /**
+ * This controls the delay introduced to try and avoid any race conditions
+ * between propagation of newly created Dynamic Regions
+ * and the Entries put into them.
+ */
+ private static final long regionCreateSleepMillis = Long.getLong("DynamicRegionFactory.msDelay", 250).longValue();
+ private static DynamicRegionFactory singleInstance = new DynamicRegionFactoryImpl ( );
+ GemFireCacheImpl c = null;
+ Config config = null;
+
+ /** The region listeners registered on this DynamicRegionFactory */
+ private static volatile List regionListeners = Collections.EMPTY_LIST;
+ private static final Object regionListenerLock = new Object();
+
+ /**
+ * Opens the DynamicRegionFactory with default settings.
+ */
+ public void open() {
+ open(new Config());
+ }
+
+ /**
+ * Opens the factory with the given settings.
+ * This should be sent to the factory before creating a cache. The cache
+ * will otherwise open a factory with default settings.
+ * This does not need to be sent if the cache.xml declares the use of dynamic regions.
+ * @param conf the configuration for this factory.
+ */
+ public void open(Config conf) {
+ this.config = new Config(conf);
+ }
+ /**
+ * Closes the dynamic region factory, disabling any further creation or
+ * destruction of dynamic regions in this cache.
+ */
+ protected void _close() {
+ this.config = null;
+ this.c = null;
+ }
+ /**
+ * Returns true if dynamic region factory is open; false if closed.
+ */
+ public boolean isOpen() {
+ return getConfig() != null;
+ }
+ /**
+ * Returns true if this factory is open and can produce dynamic regions.
+ * Factories are only active after their cache has been created.
+ */
+ public boolean isActive() {
+ return isOpen() && this.c != null;
+ }
+ /**
+ * Returns true if dynamic region factory is closed.
+ */
+ public boolean isClosed() {
+ return !isOpen();
+ }
+
+ /**
+ * Returns the configuration for this factory.
+ * Returns null if the factory is closed;
+ */
+ public Config getConfig() {
+ if (this.config == null)
+ return null;
+ else
+ return new Config(this.config);
+ }
+
+ public static boolean regionIsDynamicRegionList(String regionPath) {
+ return regionPath != null && regionPath.equals('/' + dynamicRegionListName);
+ }
+
+ /**
+ * The method is for internal use only. It is called implicitly during cache creation.
+ * @param theCache The GemFire <code>Cache</code>
+ * @throws CacheException
+ */
+
+ protected void _internalInit ( GemFireCacheImpl theCache ) throws CacheException
+ {
+
+ if (isClosed()) {
+ // DynamicRegions are not enabled in this vm. Just return.
+ return;
+ }
+ /**
+ * This method is called internally during cache initialization at the correct time.
+ * Initialize the factory with a GemFire Cache. We create the metadata Region which holds all our
+ * dynamically created regions.
+ */
+ try {
+ this.c = theCache;
+ this.dynamicRegionList = theCache.getRegion(dynamicRegionListName);
+ final boolean isClient = this.config.getBridgeWriter() != null || this.config.getPoolName()!=null;
+ if (this.dynamicRegionList == null) {
+ InternalRegionArguments ira = new InternalRegionArguments()
+ .setDestroyLockFlag(true)
+ .setSnapshotInputStream(null)
+ .setImageTarget(null);
+ AttributesFactory af = new AttributesFactory ();
+ if (this.config.getPersistBackup()) {
+ af.setDataPolicy(DataPolicy.PERSISTENT_REPLICATE);
+ af.setDiskWriteAttributes(new DiskWriteAttributesFactory().create());
+ if (this.config.getDiskDir() != null) {
+ af.setDiskDirs(new File[]{this.config.getDiskDir()});
+ }
+ }
+
+ if (isClient) {
+ // BRIDGE CLIENT
+ af.setScope(Scope.LOCAL);
+ af.setDataPolicy(DataPolicy.NORMAL); //MirrorType(MirrorType.NONE);
+ af.setStatisticsEnabled(true);
+ String cpName = this.config.getPoolName();
+ if (cpName != null) {
+ Pool cp = PoolManager.find(cpName);
+ if(cp==null) {
+ throw new IllegalStateException("Invalid pool name specified. This pool is not registered with the cache: " + cpName);
+ } else {
+ if (!cp.getSubscriptionEnabled()) {
+ throw new IllegalStateException("The client pool of a DynamicRegionFactory must be configured with queue-enabled set to true.");
+ }
+ af.setPoolName(cpName);
+ }
+ } else {
+ BridgeWriter bw = this.config.getBridgeWriter();
+ if (!bw.hasEstablishCallbackConnection()) {
+ throw new IllegalStateException(LocalizedStrings.DynamicRegionFactory_THE_CLIENT_POOL_OF_A_DYNAMICREGIONFACTORY_MUST_BE_CONFIGURED_WITH_ESTABLISHCALLBACKCONNECTION_SET_TO_TRUE.toLocalizedString());
+ }
+ af.setCacheWriter(bw);
+ }
+ ira.setInternalMetaRegion(new LocalMetaRegion(af.create(), ira));
+ } else {
+ af.setScope(Scope.DISTRIBUTED_ACK);
+ if (!this.config.getPersistBackup()) { // if persistBackup, the data policy has already been set
+ af.setDataPolicy(DataPolicy.REPLICATE); //setMirrorType(MirrorType.KEYS_VALUES);
+ }
+
+ for (GatewaySender gs : c.getGatewaySenders()) {
+ if (!gs.isParallel())
+ af.addGatewaySenderId(gs.getId());
+ }
+ ira.setInternalMetaRegion(new DistributedMetaRegion(af.create())); // bug fix 35432
+ }
+
+ try {
+ dynamicRegionList = theCache.createVMRegion(dynamicRegionListName, af.create(), ira);
+ }
+ catch (IOException e) {
+ // only if loading snapshot, not here
+ InternalGemFireError assErr = new InternalGemFireError(LocalizedStrings.DynamicRegionFactory_UNEXPECTED_EXCEPTION.toLocalizedString());
+ assErr.initCause(e);
+ throw assErr;
+ }
+ catch (ClassNotFoundException e) {
+ // only if loading snapshot, not here
+ InternalGemFireError assErr = new InternalGemFireError(LocalizedStrings.DynamicRegionFactory_UNEXPECTED_EXCEPTION.toLocalizedString());
+ assErr.initCause(e);
+ throw assErr;
+ }
+ if (isClient) {
+ dynamicRegionList.registerInterest("ALL_KEYS");
+ }
+ if (theCache.getLoggerI18n().fineEnabled()) {
+ theCache.getLoggerI18n().fine("Created dynamic region: " + dynamicRegionList);
+ }
+ } else {
+ if (theCache.getLoggerI18n().fineEnabled()) {
+ theCache.getLoggerI18n().fine("Retrieved dynamic region: " + dynamicRegionList);
+ }
+ }
+
+ createDefinedDynamicRegions ( );
+
+ } catch ( CacheException e ) {
+ //
+ theCache.getLoggerI18n().warning(LocalizedStrings.DynamicRegionFactory_ERROR_INITIALIZING_DYNAMICREGIONFACTORY, e);
+ throw e;
+ }
+ }
+
+ /**
+ * This creates Dynamic Regions that already exist in other publishing processes
+ *
+ */
+ private void createDefinedDynamicRegions ( ) throws CacheException {
+ // TODO: perhaps add some logic here to avoid the possiblity of synchronization issues . . . .
+ Set s = dynamicRegionList.entrySet( false );
+
+ Iterator i = s.iterator();
+ TreeMap sorted = new TreeMap();
+
+ // sort by region name before creating (bug 35528)
+ while ( i.hasNext() ) {
+ Region.Entry e = (Region.Entry)i.next();
+ DynamicRegionAttributes dda = (DynamicRegionAttributes)e.getValue();
+ sorted.put(dda.rootRegionName + "/" + dda.name, dda);
+ }
+ i = sorted.values().iterator();
+
+ while ( i.hasNext() ) {
+ DynamicRegionAttributes dda = (DynamicRegionAttributes)i.next();
+
+ doBeforeRegionCreated ( dda.rootRegionName, dda.name, null );
+ Region region = createDynamicRegionImpl ( dda.rootRegionName, dda.name, false );
+ doAfterRegionCreated ( region, false, false, null );
+
+ }
+
+ }
+
+ /**
+ * Returns the <code>DynamicRegionFactory</code> singleton instance.
+ * @return the <code>DynamicRegionFactory</code> singleton instance
+ */
+ public static DynamicRegionFactory get() {
+ return singleInstance;
+ }
+
+ /**
+ * Registers a <code>DynamicRegionListener</code> for callbacks.
+ * @param listener The <code>DynamicRegionListener</code> to be registered
+ */
+ public void registerDynamicRegionListener(DynamicRegionListener listener) {
+ synchronized (regionListenerLock) {
+ List oldListeners = regionListeners;
+ if (!oldListeners.contains(listener)) {
+ List newListeners = new ArrayList(oldListeners);
+ newListeners.add(listener);
+ regionListeners = newListeners;
+ }
+ }
+ }
+
+ /**
+ * Unregisters a <code>DynamicRegionListener</code> for callbacks.
+ * @param listener The <code>DynamicRegionListener</code> to be unregistered
+ */
+ public void unregisterDynamicRegionListener(DynamicRegionListener listener) {
+ synchronized (regionListenerLock) {
+ List oldListeners = regionListeners;
+ if (oldListeners.contains(listener)) {
+ List newListeners = new ArrayList(oldListeners);
+ if (newListeners.remove(listener)) {
+ regionListeners = newListeners;
+ }
+ }
+ }
+ }
+
+ private void doBeforeRegionCreated( String parentRegion, String regionName, DistributedMember mbr ) {
+ for ( Iterator i = regionListeners.iterator(); i.hasNext(); ) {
+ DynamicRegionListener listener = ( DynamicRegionListener ) i.next();
+ try {
+ listener.beforeRegionCreate( parentRegion, regionName );
+ }
+ catch (VirtualMachineError err) {
+ SystemFailure.initiateFailure(err);
+ // If this ever returns, rethrow the error. We're poisoned
+ // now, so don't let this thread continue.
+ throw err;
+ }
+ catch (Throwable t) {
+ // Whenever you catch Error or Throwable, you must also
+ // catch VirtualMachineError (see above). However, there is
+ // _still_ a possibility that you are dealing with a cascading
+ // error condition, so you also need to check to see if the JVM
+ // is still usable:
+ SystemFailure.checkFailure();
+ this.c.getLoggerI18n().warning(LocalizedStrings.DynamicRegionFactory_DYNAMICREGIONLISTENER__0__THREW_EXCEPTION_ON_BEFOREREGIONCREATED, listener, t);
+ }
+ }
+ }
+
+ private void doAfterRegionCreated( Region region, boolean distributed, boolean isOriginRemote, DistributedMember mbr ) {
+ RegionEvent event = new RegionEventImpl(region, Operation.REGION_CREATE, null, isOriginRemote, getMember(mbr));
+ for ( Iterator i = regionListeners.iterator(); i.hasNext(); ) {
+ DynamicRegionListener listener = ( DynamicRegionListener ) i.next();
+ try {
+ listener.afterRegionCreate( event /*region*/ );
+ }
+ catch (VirtualMachineError err) {
+ SystemFailure.initiateFailure(err);
+ // If this ever returns, rethrow the error. We're poisoned
+ // now, so don't let this thread continue.
+ throw err;
+ }
+ catch (Throwable t) {
+ // Whenever you catch Error or Throwable, you must also
+ // catch VirtualMachineError (see above). However, there is
+ // _still_ a possibility that you are dealing with a cascading
+ // error condition, so you also need to check to see if the JVM
+ // is still usable:
+ SystemFailure.checkFailure();
+ this.c.getLoggerI18n().warning(LocalizedStrings.DynamicRegionFactory_DYNAMICREGIONLISTENER__0__THREW_EXCEPTION_ON_AFTERREGIONCREATED, listener, t);
+ }
+ }
+ }
+
+ private void doBeforeRegionDestroyed( Region region, boolean distributed, boolean isOriginRemote, boolean expiration, DistributedMember mbr ) {
+ final Operation op;
+ if (!distributed && !isOriginRemote) {
+ op = expiration? Operation.REGION_EXPIRE_LOCAL_DESTROY : Operation.REGION_LOCAL_DESTROY;
+ }
+ else {
+ op = expiration? Operation.REGION_EXPIRE_DESTROY : Operation.REGION_DESTROY;
+ }
+ RegionEvent event = new RegionEventImpl(region, op, null, isOriginRemote, getMember(mbr));
+ for ( Iterator i = regionListeners.iterator(); i.hasNext(); ) {
+ DynamicRegionListener listener = ( DynamicRegionListener ) i.next();
+ try {
+ listener.beforeRegionDestroy( event /*fullRegionName*/ );
+ }
+ catch (VirtualMachineError err) {
+ SystemFailure.initiateFailure(err);
+ // If this ever returns, rethrow the error. We're poisoned
+ // now, so don't let this thread continue.
+ throw err;
+ }
+ catch (Throwable t) {
+ // Whenever you catch Error or Throwable, you must also
+ // catch VirtualMachineError (see above). However, there is
+ // _still_ a possibility that you are dealing with a cascading
+ // error condition, so you also need to check to see if the JVM
+ // is still usable:
+ SystemFailure.checkFailure();
+ this.c.getLoggerI18n().warning(LocalizedStrings.DynamicRegionFactory_DYNAMICREGIONLISTENER__0__THREW_EXCEPTION_ON_BEFOREREGIONDESTROYED, listener, t);
+ }
+ }
+ }
+
+ private void doAfterRegionDestroyed( Region region, boolean distributed, boolean isOriginRemote, boolean expiration, DistributedMember mbr ) {
+ final Operation op;
+ if (!distributed && !isOriginRemote) {
+ op = expiration? Operation.REGION_EXPIRE_LOCAL_DESTROY : Operation.REGION_LOCAL_DESTROY;
+ }
+ else {
+ op = expiration? Operation.REGION_EXPIRE_DESTROY : Operation.REGION_DESTROY;
+ }
+ RegionEvent event = new RegionEventImpl(region, op, null, isOriginRemote, getMember(mbr));
+ for ( Iterator i = regionListeners.iterator(); i.hasNext(); ) {
+ DynamicRegionListener listener = ( DynamicRegionListener ) i.next();
+ try {
+ listener.afterRegionDestroy( event /*fullRegionName*/ );
+ }
+ catch (VirtualMachineError err) {
+ SystemFailure.initiateFailure(err);
+ // If this ever returns, rethrow the error. We're poisoned
+ // now, so don't let this thread continue.
+ throw err;
+ }
+ catch (Throwable t) {
+ // Whenever you catch Error or Throwable, you must also
+ // catch VirtualMachineError (see above). However, there is
+ // _still_ a possibility that you are dealing with a cascading
+ // error condition, so you also need to check to see if the JVM
+ // is still usable:
+ SystemFailure.checkFailure();
+ this.c.getLoggerI18n().warning(LocalizedStrings.DynamicRegionFactory_DYNAMICREGIONLISTENER__0__THREW_EXCEPTION_ON_AFTERREGIONDESTROYED, listener, t);
+ }
+ }
+ }
+
+ /** return the argument, or if null the DistributedMember id of this vm */
+ private DistributedMember getMember(DistributedMember mbr) {
+ if (mbr == null) {
+ return InternalDistributedSystem.getAnyInstance().getDistributedMember();
+ }
+ else {
+ return null;
+ }
+ }
+
+
+ /**
+ * Creates the dynamic Region in the local cache and distributes the
+ * creation to other caches.
+ *
+ * @param parentRegionName the new region is created as a subregion of the region having this path
+ * @param regionName the name of the new subregion
+ * @return the <code>Region</code> created
+ * @throws CacheException
+ */
+ public Region createDynamicRegion ( String parentRegionName, String regionName ) throws CacheException {
+ if (isClosed()) {
+ throw new IllegalStateException("Dynamic region factory is closed");
+ }
+ doBeforeRegionCreated ( parentRegionName, regionName, null );
+ Region region = createDynamicRegionImpl ( parentRegionName, regionName, true );
+ doAfterRegionCreated ( region, false, false, null );
+ return region;
+ }
+
+ /**
+ * Destroys the dynamic Region in the local cache and distributes the
+ * destruction to other caches.
+ * @param fullRegionName The full path of the <code>Region</code> to be
+ * dynamically destroyed
+ * @throws CacheException
+ * @throws RegionDestroyedException if the dynamic region was never created
+ * or has already been destroyed
+ */
+ public void destroyDynamicRegion ( String fullRegionName ) throws CacheException {
+ if (!dynamicRegionList.containsKey(fullRegionName)) {
+ throw new RegionDestroyedException(LocalizedStrings.DynamicRegionFactory_DYNAMIC_REGION_0_HAS_NOT_BEEN_CREATED.toLocalizedString(fullRegionName), fullRegionName);
+ }
+ if (isClosed()) {
+ throw new IllegalStateException("Dynamic region factory is closed");
+ }
+
+ // Retrieve the region to destroy
+ Region region = c.getRegion( fullRegionName );
+ if (region != null) {
+ DistributedMember mbr = getMember(null);
+ doBeforeRegionDestroyed ( region, false, false, false, mbr );
+ // Locally destroy the region. Let the dynamicRegionList handle distributing
+ // the destroy.
+ region.localDestroyRegion();
+ destroyDynamicRegionImpl(fullRegionName);
+ doAfterRegionDestroyed ( region, false, false, false, mbr );
+ } else {
+ // make sure meta region is cleaned up locally and remotely
+ destroyDynamicRegionImpl(fullRegionName);
+ }
+ }
+
+ private Region createDynamicRegionImpl ( String parentRegionName, String newRegionName, boolean addEntry )
+ throws CacheException {
+
+ Region parentRegion = c.getRegion ( parentRegionName );
+ Region newRegion = null;
+
+ if ( parentRegion == null ) {
+ String errMsg = LocalizedStrings.DynamicRegionFactory_ERROR__COULD_NOT_FIND_A_REGION_NAMED___0_.toLocalizedString(parentRegionName);
+ RegionDestroyedException e = new RegionDestroyedException(errMsg, parentRegionName);
+ c.getLoggerI18n().warning(LocalizedStrings.DynamicRegionFactory_ERROR__COULD_NOT_FIND_A_REGION_NAMED___0_, parentRegionName, e);
+ throw e;
+ }
+
+ // Create RegionAttributes by inheriting from the parent
+ RegionAttributes rra = parentRegion.getAttributes();
+ RegionAttributes newRegionAttributes = null;
+
+ AttributesFactory af = new AttributesFactory( rra );
+ {
+ EvictionAttributes ev = rra.getEvictionAttributes();
+ if (ev != null && ev.getAlgorithm().isLRU()) {
+ EvictionAttributes rev = new EvictionAttributesImpl( (EvictionAttributesImpl)ev );
+ af.setEvictionAttributes( rev );
+ }
+ }
+
+ // for internal testing, until partitioned regions support subclasses or
+ // DynamicRegion implementation is redone to not inherit attrs from parent
+ // regions [bruce]
+ if (newRegionName.endsWith("_PRTEST_")) {
+ af.setPartitionAttributes((new PartitionAttributesFactory()).create());
+ }
+
+ newRegionAttributes = af.create();
+
+ try {
+ newRegion = parentRegion.createSubregion( newRegionName, newRegionAttributes );
+ c.getLoggerI18n().fine("Created dynamic region " + newRegion);
+ } catch (RegionExistsException ex) {
+ // a race condition exists that can cause this so just fine log it
+ c.getLoggerI18n().fine("DynamicRegion " + newRegionName + " in parent " + parentRegionName + " already existed");
+ newRegion = ex.getRegion();
+// } catch ( CacheException e ) {
+// c.getLoggerI18n().warning ( "Error creating new Dynamic Region '" + newRegionName, e );
+// throw e;
+ }
+
+ if (addEntry) {
+ DynamicRegionAttributes dra = new DynamicRegionAttributes ( );
+ dra.name = newRegionName;
+ dra.rootRegionName = parentRegion.getFullPath();
+ if (c.getLoggerI18n().fineEnabled()) {
+ c.getLoggerI18n().fine ("Putting entry into dynamic region list at key: " + newRegion.getFullPath());
+ }
+ dynamicRegionList.put ( newRegion.getFullPath(), dra );
+ }
+
+ if (config.getRegisterInterest()) {
+ ServerRegionProxy proxy = ((LocalRegion)newRegion).getServerProxy();
+ if (proxy != null) {
+ if (((Pool)proxy.getPool()).getSubscriptionEnabled()) {
+ try {
+ newRegion.registerInterest("ALL_KEYS");
+ }
+ catch (GemFireSecurityException ex) {
+ // Ignore security exceptions here
+ c.getSecurityLoggerI18n().warning(
+ LocalizedStrings.DynamicRegionFactory_EXCEPTION_WHEN_REGISTERING_INTEREST_FOR_ALL_KEYS_IN_DYNAMIC_REGION_0_1,
+ new Object[] {newRegion.getFullPath(), ex});
+ }
+ }
+ }
+ }
+
+ if (regionCreateSleepMillis > 0) {
+ try {
+ Thread.sleep( regionCreateSleepMillis );
+ } catch ( InterruptedException e ) {
+ Thread.currentThread().interrupt();
+ }
+ }
+
+ if (c.getLoggerI18n().fineEnabled()) {
+ c.getLoggerI18n().fine ( "Created Dynamic Region " + newRegion.getFullPath() );
+ }
+ return newRegion;
+ }
+
+ private void destroyDynamicRegionImpl(String fullRegionName)
+ throws CacheException {
+ // Destroy the entry in the dynamicRegionList
+ try {
+ if (c.getLoggerI18n().fineEnabled()) {
+ c.getLoggerI18n().fine ("Destroying entry from dynamic region list at key: " + fullRegionName);
+ }
+ dynamicRegionList.destroy ( fullRegionName );
+ } catch (CacheException e) {
+ c.getLoggerI18n().warning(LocalizedStrings.DynamicRegionFactory_ERROR_DESTROYING_DYNAMIC_REGION__0, fullRegionName, e);
+ throw e;
+ }
+
+ if (c.getLoggerI18n().fineEnabled()) {
+ c.getLoggerI18n().fine ( "Destroyed Dynamic Region " + fullRegionName );
+ }
+ }
+
+ /**
+ * Configuration for dynamic region factory.
+ * The default attributes are:
+ * <ul>
+ * <li>diskDir: <code>null</code>
+ * <li>bridgeWriter: <code>null</code>
+ * <li>persistBackup: <code>true</code>
+ * <li>registerInterest: <code>true</code>
+ * </ul>
+ * @since 4.3
+ */
+ public static class Config {
+ private static final boolean DISABLE_REGISTER_INTEREST = Boolean.getBoolean("DynamicRegionFactory.disableRegisterInterest");
+ private static final boolean DISABLE_PERSIST_BACKUP = Boolean.getBoolean("DynamicRegionFactory.disablePersistence");
+
+ /** Causes the factory to be persisted on disk. See {@link #diskDir} */
+ public final boolean persistBackup;
+ /** The directory where the factory's {@link #persistBackup} files are placed */
+ public final File diskDir;
+ /** Causes regions created by the factory to register interest in all keys in a corresponding server cache region */
+ public final boolean registerInterest;
+ /** The {@link BridgeWriter} to be used by the factory to communicate with
+ * the factory in its server.
+ * Client factories must configure a BridgeWriter for their factory
+ * and it must be configured to establish a callback connection.
+ */
+ public final BridgeWriter bridgeWriter;
+
+ /**
+ * The ${link Pool} to be used by the factory to communicate with
+ * the server-side factory. Client factories may use this instead of a BridgeWriter
+ */
+ public final String poolName;
+
+ /**
+ * Creates a configuration with the default attributes.
+ */
+ public Config() {
+ this(null, null, !DISABLE_PERSIST_BACKUP);
+ }
+ /**
+ * Creates a configuration with the given attributes and defaults for other attributes.
+ * @deprecated use a pool name instead of a bridge writer
+ */
+ @Deprecated
+ public Config(File diskDir, BridgeWriter bridgeWriter) {
+ this(diskDir, bridgeWriter, !DISABLE_PERSIST_BACKUP);
+ }
+
+ /**
+ * Creates a configuration with the given attributes and defaults for other attributes.
+ * @deprecated use a pool name instead of a bridge writer
+ */
+ @Deprecated
+ public Config(File diskDir, BridgeWriter bridgeWriter, boolean persistBackup) {
+ this(diskDir, bridgeWriter, persistBackup, !DISABLE_REGISTER_INTEREST);
+ }
+
+
+
+ /**
+ * Creates a configuration with the given attributes
+ * @deprecated use a pool name instead of a bridge writer
+ */
+ @Deprecated
+ public Config(
+ File diskDir,
+ BridgeWriter bridgeWriter,
+ boolean persistBackup,
+ boolean registerInterest)
+ {
+ this.registerInterest = registerInterest;
+ this.persistBackup = persistBackup;
+ this.diskDir = diskDir;
+ this.bridgeWriter = bridgeWriter;
+ this.poolName = null;
+ }
+
+
+ /**
+ * Creates a configuration with the given attributes
+ */
+ public Config(
+ File diskDir,
+ String poolName,
+ boolean persistBackup,
+ boolean registerInterest)
+ {
+ this.registerInterest = registerInterest;
+ this.persistBackup = persistBackup;
+ this.diskDir = diskDir;
+ this.poolName = poolName;
+ this.bridgeWriter = null;
+ }
+
+ /**
+ * Returns true if the factory is persisted to disk; false if not.
+ */
+ public boolean getPersistBackup() {
+ return this.persistBackup;
+ }
+
+ /**
+ * Returns true if the region will register interest in all keys of a corresponding
+ * server cache region
+ */
+ public boolean getRegisterInterest() {
+ return this.registerInterest;
+ }
+
+ /**
+ * Returns the disk directory that the dynamic region factory data
+ * will be written to.
+ * Returns null if no directory has been specified.
+ * The diskDir is only used if <code>persistBackup</code> is true.
+ */
+ public File getDiskDir() {
+ return this.diskDir;
+ }
+
+ /**
+ * Returns the {@link BridgeWriter} associated with the dynamic region factory.
+ * Returns null if there is no cache writer for dynamic regions.
+ * A cache writer will only exist if this is a client and the cache writer connects to a server.
+ */
+ public BridgeWriter getBridgeWriter() {
+ return this.bridgeWriter;
+ }
+
+ /**
+ * Returns the name of the {@link Pool} associated with the dynamic region factory.
+ * Returns null if there is no connection pool for dynamic regions.
+ */
+ public String getPoolName() {
+ return this.poolName;
+ }
+
+ /** create a new Config with settings from another one */
+ Config(Config conf) {
+ this.diskDir = conf.diskDir;
+ this.persistBackup = conf.persistBackup;
+ this.bridgeWriter = conf.bridgeWriter;
+ this.registerInterest = conf.registerInterest;
+ this.poolName = conf.poolName;
+ }
+ }
+
+ protected void buildDynamicRegion(EntryEvent event) {
+ if (!DynamicRegionFactory.this.isOpen())
+ return;
+
+ // Ignore the callback if it originated in this process (because the region
+ // will already have been created) and the event is not a bridge event
+ if ( !event.isOriginRemote() && !event.isBridgeEvent() ) return;
+ //
+ DynamicRegionAttributes dra = (DynamicRegionAttributes)event.getNewValue();
+ String parentRegionName = dra.rootRegionName;
+ String newRegionName = dra.name;
+
+ try {
+ doBeforeRegionCreated ( parentRegionName, newRegionName, event.getDistributedMember() );
+ Region region = createDynamicRegionImpl ( parentRegionName, newRegionName, false);
+ doAfterRegionCreated ( region, true, true, event.getDistributedMember() );
+ } catch ( Exception e ) {
+ c.getLoggerI18n().warning(LocalizedStrings.DynamicRegionFactory_ERROR_ATTEMPTING_TO_LOCALLY_CREATE_DYNAMIC_REGION__0, newRegionName, e);
+ }
+ }
+
+ protected void razeDynamicRegion(EntryEvent event) {
+ if (!DynamicRegionFactory.this.isOpen())
+ return;
+
+ // Because CacheClientUpdater calls localDestroy we need to allow
+ // "local" events. If this is a true local then c.getRegion will return
+ // null and this code will do nothing.
+ // When bug 35644 fixed the following "if" can be uncommented.
+// // Ignore the callback if it originated in this process (because the region
+// // will already have been destroyed)
+// if ( !event.isOriginRemote() && !(event instanceof BridgeEntryEventImpl)) return;
+
+ String fullRegionName = ( String ) event.getKey();
+ Region drRegion = c.getRegion( fullRegionName );
+ if (drRegion != null) {
+ try {
+ doBeforeRegionDestroyed ( drRegion, true, event.getOperation().isDistributed(), event.getOperation().isExpiration(), event.getDistributedMember() );
+ drRegion.localDestroyRegion();
+ doAfterRegionDestroyed ( drRegion, true, event.getOperation().isDistributed(), event.getOperation().isExpiration(), event.getDistributedMember() );
+ } catch ( Exception e ) {
+ c.getLoggerI18n().warning(LocalizedStrings.DynamicRegionFactory_ERROR_ATTEMPTING_TO_LOCALLY_DESTROY_DYNAMIC_REGION__0, fullRegionName, e);
+ }
+ }
+ }
+
+// private class DRListener implements CacheListener {
+// public void afterCreate(EntryEvent arg0) {
+// buildDynamicRegion(arg0);
+// }
+//
+// public void afterDestroy(EntryEvent arg0) {
+// razeDynamicRegion(arg0);
+// }
+//
+// public void afterInvalidate(EntryEvent arg0) {
+// // Stub, nothing to do.
+// }
+//
+// public void afterRegionDestroy(RegionEvent arg0) {
+// // Stub, nothing to do.
+// }
+//
+// public void afterRegionInvalidate(RegionEvent arg0) {
+// // Stub, nothing to do.
+// }
+//
+// public void afterUpdate(EntryEvent arg0) {
+// // Stub, nothing to do.
+// }
+//
+// public void close() {
+// // Stub, nothing to do.
+// }
+// }
+
+ // Introduced to keep symmetry with DistributedMetaRegion and potentially provide improved control of
+ // the meta data
+ private class LocalMetaRegion extends LocalRegion {
+ protected LocalMetaRegion(RegionAttributes attrs, InternalRegionArguments ira) {
+ super(dynamicRegionListName, attrs, null, DynamicRegionFactory.this.c, ira);
+ Assert.assertTrue(attrs.getScope().isLocal());
+ }
+
+ // This is an internal uses only region
+ @Override
+ protected boolean isSecret()
+ {
+ return true;
+ }
+
+ @Override
+ protected boolean isCopyOnRead() {
+ return false;
+ }
+
+// //@override event tracker not needed for this type of region
+// void initEventTracker() {
+// }
+
+ // while internal, its contents should be communicated with bridge clients
+ @Override
+ protected boolean shouldNotifyBridgeClients()
+ {
+ return getCache().getBridgeServers().size() > 0;
+ }
+
+ // Over-ride the super behavior to perform the destruction of the dynamic region
+ @Override
+ public void invokeDestroyCallbacks(EnumListenerEvent eventType, EntryEventImpl event, boolean callDispatchEventsCallback, boolean notifyGateways )
+ {
+ Assert.assertTrue(eventType.equals(EnumListenerEvent.AFTER_DESTROY));
+ // Notify bridge clients (if this is a BridgeServer)
+ event.setEventType(eventType);
+ notifyBridgeClients(event);
+ // Notify GatewayHub (if this region participates in a Gateway)
+ if (notifyGateways) {
+ notifyGatewaySender(eventType, event);
+ }
+ // Destroy the dynamic region after the clients and gateways have been notified
+ razeDynamicRegion(event);
+ }
+
+ // Over-ride the super behavior to perform the creation of the dynamic region
+ @Override
+ protected long basicPutPart2(EntryEventImpl event, RegionEntry entry,
+ boolean isInitialized, long lastModified,
+ boolean clearConflict) {
+
+ boolean isCreate = event.getOperation().isCreate();
+ boolean set = false;
+
+ if (isCreate && !event.callbacksInvoked()) {
+ // don't notify clients until all peers have created the region so that
+ // their register-interest operations will be sure to find data
+ event.callbacksInvoked(true);
+ set = true;
+ }
+
+ long result = super.basicPutPart2(event, entry, isInitialized, lastModified, clearConflict);
+
+ if (set) {
+ event.callbacksInvoked(false);
+ }
+
+ if (isCreate) {
+ buildDynamicRegion(event);
+ }
+ return result;
+ }
+
+ // The dynamic-region meta-region needs to tell clients about the event
+ // after all servers have created the region so that register-interest
+ // will work correctly
+ @Override
+ public void basicPutPart3(EntryEventImpl event, RegionEntry entry,
+ boolean isInitialized, long lastModified, boolean invokeCallbacks,
+ boolean ifNew, boolean ifOld, Object expectedOldValue,
+ boolean requireOldValue) {
+
+ super.basicPutPart3(event, entry, isInitialized, lastModified, invokeCallbacks, ifNew, ifOld, expectedOldValue, requireOldValue);
+
+ // this code is copied from LocalRegion.basicPutPart2
+ invokeCallbacks &= !entry.isTombstone(); // put() is creating a tombstone
+ if (invokeCallbacks) {
+ boolean doCallback = false;
+ if (isInitialized) {
+ if (event.isGenerateCallbacks()) {
+ doCallback = true;
+ }
+ }
+ if (doCallback) {
+ notifyGatewaySender(event.getOperation().isUpdate()? EnumListenerEvent.AFTER_UPDATE
+ : EnumListenerEvent.AFTER_CREATE, event);
+ // Notify listeners
+ if (!event.isBulkOpInProgress()) {
+ try {
+ entry.dispatchListenerEvents(event);
+ }
+ catch (InterruptedException ie) {
+ Thread.currentThread().interrupt();
+ stopper.checkCancelInProgress(null);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ // Part of the fix for bug 35432, which required a change to the
+ // distribution and notification order on the BridgeServer
+ private class DistributedMetaRegion extends DistributedRegion {
+ protected DistributedMetaRegion(RegionAttributes attrs) {
+ super(dynamicRegionListName, attrs, null, DynamicRegionFactory.this.c, new InternalRegionArguments());
+ }
+ // This is an internal uses only region
+ @Override
+ protected boolean isSecret()
+ {
+ return true;
+ }
+
+// //@override event tracker not needed for this type of region
+// void initEventTracker() {
+// }
+
+ @Override
+ protected boolean isCopyOnRead() {
+ return false;
+ }
+
+ // while internal, its contents should be communicated with bridge clients
+ @Override
+ final public boolean shouldNotifyBridgeClients()
+ {
+ return getCache().getBridgeServers().size() > 0;
+ }
+
+ // Over-ride the super behavior to perform the destruction of the dynamic region
+ //
+ @Override
+ public void invokeDestroyCallbacks(EnumListenerEvent eventType, EntryEventImpl event, boolean callDispatchEventsCallback, boolean notifyGateways)
+ {
+ Assert.assertTrue(eventType.equals(EnumListenerEvent.AFTER_DESTROY));
+ // Notify bridge clients (if this is a BridgeServer)
+ event.setEventType(eventType);
+ notifyBridgeClients(event);
+ // Notify GatewayHub (if this region participates in a Gateway)
+ if (notifyGateways) {
+ notifyGatewaySender(eventType, event);
+ }
+ // Destroy the dynamic region after the clients and gateways have been notified
+ razeDynamicRegion(event);
+ }
+
+ @Override
+ protected long basicPutPart2(EntryEventImpl event, RegionEntry entry,
+ boolean isInitialized, long lastModified,
+ boolean clearConflict)
+ {
+ boolean isCreate = event.getOperation().isCreate();
+ boolean set = false;
+ if (isCreate && !event.callbacksInvoked()) {
+ // don't notify clients until all peers have created the region so that
+ // their register-interest operations will be sure to find data
+ event.callbacksInvoked(true);
+ set = true;
+ }
+
+ long result = super.basicPutPart2(event, entry, isInitialized, lastModified, clearConflict);
+
+ if (set) {
+ event.callbacksInvoked(false);
+ }
+
+ if (isCreate) {
+ try {
+ InitialImageOperation.setInhibitStateFlush(true); // fix for bug 36175
+ buildDynamicRegion(event);
+ }
+ finally {
+ InitialImageOperation.setInhibitStateFlush(false);
+ }
+ }
+ return result;
+ }
+
+ // The dynamic-region meta-region needs to tell clients about the event
+ // after all servers have created the region so that register-interest
+ // will work correctly
+ @Override
+ public void basicPutPart3(EntryEventImpl event, RegionEntry entry,
+ boolean isInitialized, long lastModified, boolean invokeCallbacks,
+ boolean ifNew, boolean ifOld, Object expectedOldValue,
+ boolean requireOldValue) {
+
+ super.basicPutPart3(event, entry, isInitialized, lastModified, invokeCallbacks, ifNew, ifOld, expectedOldValue, requireOldValue);
+
+ // this code is copied from LocalRegion.basicPutPart2
+ invokeCallbacks &= !entry.isTombstone(); // put() is creating a tombstone
+ if (invokeCallbacks) {
+ boolean doCallback = false;
+ if (isInitialized) {
+ if (event.isGenerateCallbacks()) {
+ doCallback = true;
+ }
+ }
+ if (doCallback) {
+ notifyGatewaySender(event.getOperation().isUpdate()? EnumListenerEvent.AFTER_UPDATE
+ : EnumListenerEvent.AFTER_CREATE, event);
+ // Notify listeners
+ if (!event.isBulkOpInProgress()) {
+ try {
+ entry.dispatchListenerEvents(event);
+ }
+ catch (InterruptedException ie) {
+ Thread.currentThread().interrupt();
+ stopper.checkCancelInProgress(null);
+ }
+ }
+ }
+ }
+ }
+
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/19459053/gemfire-core/src/main/java/com/gemstone/gemfire/cache/DynamicRegionListener.java
----------------------------------------------------------------------
diff --git a/gemfire-core/src/main/java/com/gemstone/gemfire/cache/DynamicRegionListener.java b/gemfire-core/src/main/java/com/gemstone/gemfire/cache/DynamicRegionListener.java
new file mode 100644
index 0000000..968b3d0
--- /dev/null
+++ b/gemfire-core/src/main/java/com/gemstone/gemfire/cache/DynamicRegionListener.java
@@ -0,0 +1,61 @@
+/*=========================================================================
+ * Copyright (c) 2002-2014 Pivotal Software, Inc. All Rights Reserved.
+ * This product is protected by U.S. and international copyright
+ * and intellectual property laws. Pivotal products are covered by
+ * more patents listed at http://www.pivotal.io/patents.
+ *=========================================================================
+ */
+
+package com.gemstone.gemfire.cache;
+
+/**
+ * <code>DynamicRegionListener</code> is an interface that can be
+ * implemented to handle dynamic region-related events.
+
+ * The methods on a <code>DynamicRegionListener</code> are invoked synchronously.
+ * If the listener method takes a long time to execute then it will cause the
+ * operation that caused it to be invoked to take a long time.
+ * <p>
+ * Note: It is possible to receive duplicate create events when the DynamicRegionFactory
+ * goes active due to Cache creation.
+ * <p>
+ * See {@link DynamicRegionFactory}
+ *
+ * @author Gideon Low
+ * @since 4.3
+ */
+public interface DynamicRegionListener {
+
+ /**
+ * Handles the 'before region creation' event of a dynamic region. This method
+ * is invoked before the dynamic region is created in the local VM.
+ *
+ * @param parentRegionName The name of the parent region
+ * @param regionName The name of the region being created
+ */
+ public void beforeRegionCreate(String parentRegionName, String regionName);
+
+ /**
+ * Handles the 'after region creation' event of a dynamic region. This method
+ * is invoked after the dynamic region is created in the local VM.
+ *
+ * @param event A <code>RegionEvent</code> describing the event
+ */
+ public void afterRegionCreate(RegionEvent<?,?> event);
+
+ /**
+ * Handles the 'before region destroyed' event of a dynamic region. This method
+ * is invoked before the dynamic region is destroyed in the local VM.
+ *
+ * @param event A <code>RegionEvent</code> describing the event
+ */
+ public void beforeRegionDestroy(RegionEvent<?,?> event);
+
+ /**
+ * Handles the 'after region destroyed' event of a dynamic region. This method
+ * is invoked after the dynamic region is destroyed in the local VM.
+ *
+ * @param event A <code>RegionEvent</code> describing the event
+ */
+ public void afterRegionDestroy(RegionEvent<?,?> event);
+}
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/19459053/gemfire-core/src/main/java/com/gemstone/gemfire/cache/EntryDestroyedException.java
----------------------------------------------------------------------
diff --git a/gemfire-core/src/main/java/com/gemstone/gemfire/cache/EntryDestroyedException.java b/gemfire-core/src/main/java/com/gemstone/gemfire/cache/EntryDestroyedException.java
new file mode 100644
index 0000000..c656947
--- /dev/null
+++ b/gemfire-core/src/main/java/com/gemstone/gemfire/cache/EntryDestroyedException.java
@@ -0,0 +1,52 @@
+/*=========================================================================
+ * Copyright (c) 2002-2014 Pivotal Software, Inc. All Rights Reserved.
+ * This product is protected by U.S. and international copyright
+ * and intellectual property laws. Pivotal products are covered by
+ * more patents listed at http://www.pivotal.io/patents.
+ *========================================================================
+ */
+package com.gemstone.gemfire.cache;
+/**
+ * Indicates that a method was invoked on an entry that has been destroyed.
+ *
+ * @author Eric Zoerner
+ *
+ *
+ * @see Region.Entry
+ * @since 3.0
+ */
+public class EntryDestroyedException extends CacheRuntimeException
+{
+ private static final long serialVersionUID = 831865939772672542L;
+ /** Constructs a new <code>EntryDestroyedException</code>. */
+ public EntryDestroyedException()
+ {
+ super();
+ }
+
+ /**
+ * Constructs a new <code>EntryDestroyedException</code> with the message.
+ * @param s the detailed message for this exception
+ */
+ public EntryDestroyedException(String s)
+ {
+ super(s);
+ }
+
+ /** Constructs a new <code>EntryDestroyedException</code> with a detailed message
+ * and a causal exception.
+ * @param s the message
+ * @param ex a causal Throwable
+ */
+ public EntryDestroyedException(String s, Throwable ex)
+ {
+ super(s, ex);
+ }
+
+ /** Construct a <code>EntryDestroyedException</code> with a cause.
+ * @param ex the causal Throwable
+ */
+ public EntryDestroyedException(Throwable ex) {
+ super(ex);
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/19459053/gemfire-core/src/main/java/com/gemstone/gemfire/cache/EntryEvent.java
----------------------------------------------------------------------
diff --git a/gemfire-core/src/main/java/com/gemstone/gemfire/cache/EntryEvent.java b/gemfire-core/src/main/java/com/gemstone/gemfire/cache/EntryEvent.java
new file mode 100644
index 0000000..2b69ac7
--- /dev/null
+++ b/gemfire-core/src/main/java/com/gemstone/gemfire/cache/EntryEvent.java
@@ -0,0 +1,146 @@
+/*=========================================================================
+ * Copyright (c) 2002-2014 Pivotal Software, Inc. All Rights Reserved.
+ * This product is protected by U.S. and international copyright
+ * and intellectual property laws. Pivotal products are covered by
+ * more patents listed at http://www.pivotal.io/patents.
+ *========================================================================
+ */
+package com.gemstone.gemfire.cache;
+
+//import java.io.*;
+
+/** Contains information about an event affecting an entry, including
+ * its identity and the the circumstances of the event.
+ * It is passed in to <code>CacheListener</code>, <code>CapacityController</code>, and <code>CacheWriter</code>.
+ *
+ * @author Eric Zoerner
+ *
+ *
+ * @see CacheListener
+ * @see CacheWriter
+ * @see RegionEvent
+ * @since 3.0
+ */
+public interface EntryEvent<K,V> extends CacheEvent<K,V> {
+
+ /** Returns the key.
+ * @return the key
+ */
+ public K getKey();
+
+
+ /**
+ * Returns the value in the cache prior to this event.
+ * When passed to an event handler after an event occurs, this value
+ * reflects the value that was in the cache in this VM, not necessarily
+ * the value that was in the cache VM that initiated the operation.
+ * In certain scenarios the old value may no longer be available in which
+ * case <code>null</code> is returned.
+ * This can happen for disk regions when the old value is on disk only.
+ *
+ * @return the old value in the cache prior to this event.
+ * If the entry did not exist, was invalid, or was not available,
+ * then null is returned.
+ */
+ public V getOldValue();
+
+ /**
+ * Returns the serialized form of the value in the cache before this event.
+ *
+ * @return the serialized form of the value in the cache before this event
+ *
+ * @since 5.5
+ */
+ public SerializedCacheValue<V> getSerializedOldValue();
+
+ /**
+ * Returns the value in the cache after this event.
+ *
+ * @return the value in the cache after this event
+ */
+ public V getNewValue();
+
+ /**
+ * Returns the serialized form of the value in the cache after this event.
+ *
+ * @return the serialized form of the value in the cache after this event
+ *
+ * @since 5.5
+ */
+ public SerializedCacheValue<V> getSerializedNewValue();
+
+ // Flag query methods
+
+ /** Returns true if this event resulted from a loader running in this cache.
+ * Note that this will be true even if the local loader called <code>netSearch</code>.
+ *
+ * If this event is for a Partitioned Region, then true will be returned if the
+ * loader ran in the same VM as where the data is hosted. If true is returned, and {@link CacheEvent#isOriginRemote}
+ * is true, it means the data is not hosted locally, but the loader was run local to the data.
+ *
+ * @return true if this event resulted from local loader execution
+ * @deprecated as of GemFire 5.0, use {@link Operation#isLocalLoad} instead.
+ */
+ @Deprecated
+ public boolean isLocalLoad();
+
+ /** Returns true if this event resulted from a loader running that was remote
+ * from the cache that requested it, i.e., a netLoad. Note that the cache
+ * that requested the netLoad may not be this cache in which case
+ * <code>isOriginRemote</code> will also return true.
+ * @return true if this event resulted from a netLoad
+ * @deprecated as of GemFire 5.0, use {@link Operation#isNetLoad} instead.
+ */
+ @Deprecated
+ public boolean isNetLoad();
+
+ /** Returns true if this event resulted from a loader.
+ * @return true if isLocalLoad or isNetLoad
+ * @deprecated as of GemFire 5.0, use {@link Operation#isLoad} instead.
+ */
+ @Deprecated
+ public boolean isLoad();
+
+ /** Returns true if this event resulted from a <code>netSearch</code>. If the <code>netSearch</code>
+ * was invoked by a loader however, this will return false and <code>isLocalLoad()</code>
+ * or <code>isNetLoad()</code> will return true instead.
+ *
+ * @return true if this event resulted from a netSearch
+ * @deprecated as of GemFire 5.0, use {@link Operation#isNetSearch} instead.
+ */
+ @Deprecated
+ public boolean isNetSearch();
+ /**
+ * Gets the TransactionId for this EntryEvent.
+ * @return the ID of the transaction that performed the operation that
+ * generated this event; null if no transaction involved.
+ * @since 4.0
+ */
+ public TransactionId getTransactionId();
+
+ /**
+ * Returns true if this event originated on a client.
+ *
+ * @since 5.1
+ * @return true if this event originated on a client.
+ * @deprecated as of 5.7 use {@link #hasClientOrigin} instead.
+ */
+ @Deprecated
+ public boolean isBridgeEvent();
+ /**
+ * Returns true if this event originated on a client.
+ *
+ * @since 5.7
+ * @return true if this event originated on a client.
+ */
+ public boolean hasClientOrigin();
+ /**
+ * Returns <code>true</code> if the old value is "available".
+ * Not available means that an old value existed but it could not be obtained
+ * or it was deemed too expensive to obtain.
+ * Note that {@link #getOldValue} will return <code>null</code> when this
+ * method returns <code>false</code>.
+ * @since 6.0
+ */
+ public boolean isOldValueAvailable();
+}
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/19459053/gemfire-core/src/main/java/com/gemstone/gemfire/cache/EntryExistsException.java
----------------------------------------------------------------------
diff --git a/gemfire-core/src/main/java/com/gemstone/gemfire/cache/EntryExistsException.java b/gemfire-core/src/main/java/com/gemstone/gemfire/cache/EntryExistsException.java
new file mode 100644
index 0000000..6978b22
--- /dev/null
+++ b/gemfire-core/src/main/java/com/gemstone/gemfire/cache/EntryExistsException.java
@@ -0,0 +1,53 @@
+/*=========================================================================
+ * Copyright (c) 2002-2014 Pivotal Software, Inc. All Rights Reserved.
+ * This product is protected by U.S. and international copyright
+ * and intellectual property laws. Pivotal products are covered by
+ * more patents listed at http://www.pivotal.io/patents.
+ *========================================================================
+ */
+
+package com.gemstone.gemfire.cache;
+
+/** Thrown when attempting to create a <code>Region.Entry</code> that already
+ * exists in the <code>Region</code>.
+ * @author Eric Zoerner
+ *
+ * @see com.gemstone.gemfire.cache.Region#create(Object, Object)
+ * @see Region.Entry
+ * @since 3.0
+ */
+public class EntryExistsException extends CacheException {
+
+ private static final long serialVersionUID = 2925082493103537925L;
+
+ private Object oldValue;
+
+ /**
+ * Constructs an instance of <code>EntryExistsException</code> with the specified detail message.
+ * @param msg the detail message
+ * @since 6.5
+ */
+ public EntryExistsException(String msg, Object oldValue) {
+ super(msg);
+ this.oldValue = oldValue;
+ }
+
+ /**
+ * Returns the old existing value that caused this exception.
+ */
+ public Object getOldValue() {
+ return this.oldValue;
+ }
+
+ /**
+ * Sets the old existing value that caused this exception.
+ */
+ public void setOldValue(Object oldValue) {
+ this.oldValue = oldValue;
+ }
+
+ @Override
+ public String toString() {
+ return super.toString() + ", with oldValue: " + oldValue;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/19459053/gemfire-core/src/main/java/com/gemstone/gemfire/cache/EntryNotFoundException.java
----------------------------------------------------------------------
diff --git a/gemfire-core/src/main/java/com/gemstone/gemfire/cache/EntryNotFoundException.java b/gemfire-core/src/main/java/com/gemstone/gemfire/cache/EntryNotFoundException.java
new file mode 100644
index 0000000..e1265c0
--- /dev/null
+++ b/gemfire-core/src/main/java/com/gemstone/gemfire/cache/EntryNotFoundException.java
@@ -0,0 +1,42 @@
+/*=========================================================================
+ * Copyright (c) 2002-2014 Pivotal Software, Inc. All Rights Reserved.
+ * This product is protected by U.S. and international copyright
+ * and intellectual property laws. Pivotal products are covered by
+ * more patents listed at http://www.pivotal.io/patents.
+ *========================================================================
+ */
+
+package com.gemstone.gemfire.cache;
+
+/** Thrown when an operation is invoked on <code>Region</code> for an entry that
+ * doesn't exist in the <code>Region</code>. This exception is <i>not</i>
+ * thrown by {@link com.gemstone.gemfire.cache.Region#get(Object)} or {@link Region#getEntry}.
+ *
+ * @author Eric Zoerner
+ *
+ *
+ * @see com.gemstone.gemfire.cache.Region#invalidate(Object)
+ * @see com.gemstone.gemfire.cache.Region#destroy(Object)
+ * @see Region.Entry
+ * @since 3.0
+ */
+public class EntryNotFoundException extends CacheException {
+private static final long serialVersionUID = -2404101631744605659L;
+ /**
+ * Constructs an instance of <code>EntryNotFoundException</code> with the specified detail message.
+ * @param msg the detail message
+ */
+ public EntryNotFoundException(String msg) {
+ super(msg);
+ }
+
+ /**
+ * Constructs an instance of <code>EntryNotFoundException</code> with the specified detail message
+ * and cause.
+ * @param msg the detail message
+ * @param cause the causal Throwable
+ */
+ public EntryNotFoundException(String msg, Throwable cause) {
+ super(msg, cause);
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/19459053/gemfire-core/src/main/java/com/gemstone/gemfire/cache/EntryNotFoundInRegion.java
----------------------------------------------------------------------
diff --git a/gemfire-core/src/main/java/com/gemstone/gemfire/cache/EntryNotFoundInRegion.java b/gemfire-core/src/main/java/com/gemstone/gemfire/cache/EntryNotFoundInRegion.java
new file mode 100644
index 0000000..74b74c6
--- /dev/null
+++ b/gemfire-core/src/main/java/com/gemstone/gemfire/cache/EntryNotFoundInRegion.java
@@ -0,0 +1,41 @@
+/*=========================================================================
+ * Copyright (c) 2010-2014 Pivotal Software, Inc. All Rights Reserved.
+ * This product is protected by U.S. and international copyright
+ * and intellectual property laws. Pivotal products are covered by
+ * one or more patents listed at http://www.pivotal.io/patents.
+ *=========================================================================
+ */
+package com.gemstone.gemfire.cache;
+
+import com.gemstone.gemfire.GemFireException;
+import com.gemstone.gemfire.internal.i18n.LocalizedStrings;
+import com.gemstone.gemfire.InternalGemFireError;
+
+/**
+ * @deprecated this class is no longer in use
+ */
+@Deprecated
+public class EntryNotFoundInRegion extends GemFireException {
+ private static final long serialVersionUID = 5572550909947420405L;
+
+ /**
+ * Generates an {@link InternalGemFireError}
+ * @param msg the detail message
+ * @deprecated Do not create instances of this class.
+ */
+ @Deprecated
+ public EntryNotFoundInRegion(String msg) {
+ throw new InternalGemFireError(LocalizedStrings.EntryNotFoundInRegion_THIS_CLASS_IS_DEPRECATED.toLocalizedString());
+ }
+
+ /**
+ * Generates an {@link InternalGemFireError}
+ * @param msg the detail message
+ * @param cause the causal Throwable
+ * @deprecated do not create instances of this class.
+ */
+ @Deprecated
+ public EntryNotFoundInRegion(String msg, Throwable cause) {
+ throw new InternalGemFireError(LocalizedStrings.EntryNotFoundInRegion_THIS_CLASS_IS_DEPRECATED.toLocalizedString());
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/19459053/gemfire-core/src/main/java/com/gemstone/gemfire/cache/EntryOperation.java
----------------------------------------------------------------------
diff --git a/gemfire-core/src/main/java/com/gemstone/gemfire/cache/EntryOperation.java b/gemfire-core/src/main/java/com/gemstone/gemfire/cache/EntryOperation.java
new file mode 100755
index 0000000..5e75504
--- /dev/null
+++ b/gemfire-core/src/main/java/com/gemstone/gemfire/cache/EntryOperation.java
@@ -0,0 +1,77 @@
+/*=========================================================================
+ * Copyright (c) 2002-2014 Pivotal Software, Inc. All Rights Reserved.
+ * This product is protected by U.S. and international copyright
+ * and intellectual property laws. Pivotal products are covered by
+ * more patents listed at http://www.pivotal.io/patents.
+ *=========================================================================
+ */
+
+package com.gemstone.gemfire.cache;
+
+/**
+ * Gemfire Context passed to <code>PartitionedResolver</code> to compute the
+ * data location
+ *
+ * @author Yogesh Mahajan
+ * @author Mitch Thomas
+ *
+ * @see PartitionResolver
+ * @since 6.0
+ */
+public interface EntryOperation<K,V> {
+
+ /**
+ * Returns the region to which this cached object belongs or
+ * the region that raised this event for <code>RegionEvent</code>s.
+ * @return the region associated with this object or the region that raised
+ * this event.
+ */
+ public Region<K,V> getRegion();
+
+ /**
+ * Return a description of the operation that triggered this event.
+ * It may return null and should not be used to generate routing object
+ * in {@link PartitionResolver#getRoutingObject(EntryOperation)}
+ * @return the operation that triggered this event.
+ * @since 6.0
+ * @deprecated
+ */
+ public Operation getOperation();
+
+ /**
+ * Returns the key.
+ * @return the key
+ */
+ public K getKey();
+
+ /** Returns the callbackArgument passed to the method that generated this event.
+ * Provided primarily in case this object or region has already been
+ * destroyed. See the {@link Region} interface methods that take a
+ * callbackArgument parameter.
+ * Only fields on the key should be used when creating the routing object.
+ * @return the callbackArgument associated with this event. <code>null</code>
+ * is returned if the callback argument is not propagated to the event.
+ * This happens for events given to {@link TransactionListener}
+ * and to {@link CacheListener} on the remote side of a transaction commit.
+ */
+ public Object getCallbackArgument();
+
+ /**
+ * Returns <code>true</code> if the callback argument is "available".
+ * Not available means that the callback argument may have existed but it could
+ * not be obtained.
+ * Note that {@link #getCallbackArgument} will return <code>null</code>
+ * when this method returns <code>false</code>.
+ * @since 6.0
+ */
+ public boolean isCallbackArgumentAvailable();
+
+ /**
+ * Returns the value but may return null and should not be used to generate
+ * routing object in {@link PartitionResolver#getRoutingObject(EntryOperation)}.
+ * Only fields on the key should be used when creating the routing object.
+ * @return the value.
+ * @deprecated
+ */
+ public V getNewValue();
+}
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/19459053/gemfire-core/src/main/java/com/gemstone/gemfire/cache/EvictionAction.java
----------------------------------------------------------------------
diff --git a/gemfire-core/src/main/java/com/gemstone/gemfire/cache/EvictionAction.java b/gemfire-core/src/main/java/com/gemstone/gemfire/cache/EvictionAction.java
new file mode 100644
index 0000000..c4bb350
--- /dev/null
+++ b/gemfire-core/src/main/java/com/gemstone/gemfire/cache/EvictionAction.java
@@ -0,0 +1,105 @@
+package com.gemstone.gemfire.cache;
+/*=========================================================================
+ * Copyright (c) 2002-2014 Pivotal Software, Inc. All Rights Reserved.
+ * This product is protected by U.S. and international copyright
+ * and intellectual property laws. Pivotal products are covered by
+ * more patents listed at http://www.pivotal.io/patents.
+ *========================================================================
+ */
+
+import javax.print.attribute.EnumSyntax;
+/**
+ * The action that an {@link com.gemstone.gemfire.cache.EvictionAlgorithm} takes.
+ * @author Mitch Thomas
+ * @since 5.0
+ * @see com.gemstone.gemfire.cache.EvictionAlgorithm
+ * @see com.gemstone.gemfire.internal.cache.EvictionAttributesImpl
+ */
+public final class EvictionAction extends EnumSyntax
+{
+ private static final long serialVersionUID = -98840597493242980L;
+ /** Canonical EvictionAction that represents no eviction
+ */
+ public static final EvictionAction NONE = new EvictionAction(0);
+
+ /** Perform a {@link com.gemstone.gemfire.cache.Region#localDestroy(Object)
+ * localDestory} on the least recently used region entry. */
+ public static final EvictionAction LOCAL_DESTROY = new EvictionAction(1);
+
+ /** Write the value of the least recently used region entry to disk
+ * and <code>null</code>-out its value in the VM to free up heap
+ * space. Note that this action is only available when the region
+ * has been configured to access data on disk. */
+ public static final EvictionAction OVERFLOW_TO_DISK = new EvictionAction(2);
+
+ /** The default eviction action is to {@linkplain #LOCAL_DESTROY
+ * locally destroy} an Entry. */
+ public static final EvictionAction DEFAULT_EVICTION_ACTION = LOCAL_DESTROY;
+
+ private EvictionAction(int val) { super(val); }
+
+ private static final String[] stringTable = {
+ "none",
+ "local-destroy",
+ "overflow-to-disk",
+ };
+
+ @Override
+ final protected String[] getStringTable() {
+ return stringTable;
+ }
+
+ private static final EvictionAction[] enumValueTable = {
+ NONE,
+ LOCAL_DESTROY,
+ OVERFLOW_TO_DISK
+ };
+
+ @Override
+ final protected EnumSyntax[] getEnumValueTable() {
+ return enumValueTable;
+ }
+
+ public final boolean isLocalDestroy() {
+ return this == LOCAL_DESTROY;
+ }
+
+ public final boolean isOverflowToDisk() {
+ return this == OVERFLOW_TO_DISK;
+ }
+
+ public final boolean isNone() {
+ return this == NONE;
+ }
+
+ /**
+ * Returns the eviction action the corresponds to the given parameter.
+ * Returns <code>null</code> if no action corresponds.
+ * @since 6.5
+ */
+ public static EvictionAction parseValue(int v) {
+ if (v < 0 || v >= enumValueTable.length) {
+ return null;
+ } else {
+ return enumValueTable[v];
+ }
+ }
+ /**
+ *
+ * @param s
+ * @return the action parsed from the provided string. If there are problems with parsing
+ * NONE is returned.
+ */
+ public static EvictionAction parseAction(String s) {
+ if (s == null)
+ return NONE;
+ if (s.length() < 1)
+ return NONE;
+ for (int i = 0; i < stringTable.length; ++i) {
+ if (s.equals(stringTable[i])) {
+ return enumValueTable[i];
+ }
+ }
+ return NONE;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/19459053/gemfire-core/src/main/java/com/gemstone/gemfire/cache/EvictionAlgorithm.java
----------------------------------------------------------------------
diff --git a/gemfire-core/src/main/java/com/gemstone/gemfire/cache/EvictionAlgorithm.java b/gemfire-core/src/main/java/com/gemstone/gemfire/cache/EvictionAlgorithm.java
new file mode 100644
index 0000000..33cca0e
--- /dev/null
+++ b/gemfire-core/src/main/java/com/gemstone/gemfire/cache/EvictionAlgorithm.java
@@ -0,0 +1,141 @@
+package com.gemstone.gemfire.cache;
+/*=========================================================================
+ * Copyright (c) 2002-2014 Pivotal Software, Inc. All Rights Reserved.
+ * This product is protected by U.S. and international copyright
+ * and intellectual property laws. Pivotal products are covered by
+ * more patents listed at http://www.pivotal.io/patents.
+ *========================================================================
+ */
+
+import javax.print.attribute.EnumSyntax;
+
+/** The algorithm used to determine when to perform an {@link com.gemstone.gemfire.cache.EvictionAction}
+ *
+ * @author Mitch Thomas
+ * @since 5.0
+ * @see com.gemstone.gemfire.cache.EvictionAction
+ * @see com.gemstone.gemfire.internal.cache.EvictionAttributesImpl
+ */
+public final class EvictionAlgorithm extends EnumSyntax
+{
+ private static final long serialVersionUID = 5778669432033106789L;
+ /**
+ * The canonical EvictionAction that represents no eviction action
+ */
+ public static final EvictionAlgorithm NONE = new EvictionAlgorithm(0);
+
+ /**
+ * An algorithm that considers the number of Entries in the Region before
+ * invoking its {@link EvictionAction}
+ */
+ public static final EvictionAlgorithm LRU_ENTRY = new EvictionAlgorithm(1);
+
+ /**
+ * An algorithm that considers the JVM heap size before invoking its {@link EvictionAction}
+ */
+ public static final EvictionAlgorithm LRU_HEAP = new EvictionAlgorithm(2);
+
+ /**
+ * An algorithm that considers the amount of bytes consumed by the Region before invoking its {@link EvictionAction}
+ */
+ public static final EvictionAlgorithm LRU_MEMORY = new EvictionAlgorithm(3);
+
+ /**
+ * An algorithm that considers the number of Entries in the Region before
+ * invoking its {@link EvictionAction}
+ *
+ * @deprecated
+ */
+ public static final EvictionAlgorithm LIFO_ENTRY = new EvictionAlgorithm(4);
+
+ /**
+ * An algorithm that considers the amount of bytes consumed by the Region
+ * before invoking its {@link EvictionAction}
+ *
+ * @deprecated
+ */
+ public static final EvictionAlgorithm LIFO_MEMORY = new EvictionAlgorithm(5);
+
+ private EvictionAlgorithm(int val) { super(val); }
+
+ private static final String[] stringTable = {
+ "none",
+ "lru-entry-count",
+ "lru-heap-percentage",
+ "lru-memory-size",
+ "lifo-entry-count",
+ "lifo-memory-size"
+ };
+
+ @Override
+ final protected String[] getStringTable() {
+ return stringTable;
+ }
+
+ private static final EvictionAlgorithm[] enumValueTable = {
+ NONE,
+ LRU_ENTRY,
+ LRU_HEAP,
+ LRU_MEMORY,
+ LIFO_ENTRY,
+ LIFO_MEMORY,
+ };
+
+ @Override
+ final protected EnumSyntax[] getEnumValueTable() {
+ return enumValueTable;
+ }
+
+ /**
+ * Returns the eviction action the corresponds to the given parameter.
+ * Returns <code>null</code> if no action corresponds.
+ * @since 6.5
+ */
+ public static EvictionAlgorithm parseValue(int v) {
+ if (v < 0 || v >= enumValueTable.length) {
+ return null;
+ } else {
+ return enumValueTable[v];
+ }
+ }
+ public static EvictionAlgorithm parseAction(String s) {
+ if (s == null)
+ return null;
+ if (s.length() < 1)
+ return null;
+ for (int i = 0; i < stringTable.length; ++i) {
+ if (s.equals(stringTable[i])) {
+ return enumValueTable[i];
+ }
+ }
+ return null;
+ }
+
+ public final boolean isLRUEntry() {
+ return this == LRU_ENTRY;
+ }
+
+ public final boolean isLRUMemory() {
+ return this == LRU_MEMORY;
+ }
+
+ public final boolean isLRUHeap() {
+ return this == LRU_HEAP;
+ }
+
+ /** returns true if this object uses a least-recently-used algorithm */
+ public boolean isLRU() {
+ return this.isLRUEntry() || this.isLRUMemory() || this.isLRUHeap();
+ }
+
+ public final boolean isNone() {
+ return this == NONE;
+ }
+
+ /**
+ * @deprecated
+ */
+ public boolean isLIFO() {
+ return this == LIFO_ENTRY || this == LIFO_MEMORY;
+ }
+}