You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@geode.apache.org by je...@apache.org on 2015/12/22 22:08:17 UTC
[05/17] incubator-geode git commit: GEODE-14: Initial integration of
gemfire-modules subproject
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/63bc5f03/extensions/gemfire-modules/src/main/java/com/gemstone/gemfire/modules/session/catalina/internal/DeltaSessionAttributeEvent.java
----------------------------------------------------------------------
diff --git a/extensions/gemfire-modules/src/main/java/com/gemstone/gemfire/modules/session/catalina/internal/DeltaSessionAttributeEvent.java b/extensions/gemfire-modules/src/main/java/com/gemstone/gemfire/modules/session/catalina/internal/DeltaSessionAttributeEvent.java
new file mode 100644
index 0000000..70f5376
--- /dev/null
+++ b/extensions/gemfire-modules/src/main/java/com/gemstone/gemfire/modules/session/catalina/internal/DeltaSessionAttributeEvent.java
@@ -0,0 +1,9 @@
+package com.gemstone.gemfire.modules.session.catalina.internal;
+
+import com.gemstone.gemfire.DataSerializable;
+import com.gemstone.gemfire.modules.session.catalina.DeltaSession;
+
+public interface DeltaSessionAttributeEvent extends DataSerializable {
+
+ public void apply(DeltaSession session);
+}
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/63bc5f03/extensions/gemfire-modules/src/main/java/com/gemstone/gemfire/modules/session/catalina/internal/DeltaSessionAttributeEventBatch.java
----------------------------------------------------------------------
diff --git a/extensions/gemfire-modules/src/main/java/com/gemstone/gemfire/modules/session/catalina/internal/DeltaSessionAttributeEventBatch.java b/extensions/gemfire-modules/src/main/java/com/gemstone/gemfire/modules/session/catalina/internal/DeltaSessionAttributeEventBatch.java
new file mode 100644
index 0000000..b0d8681
--- /dev/null
+++ b/extensions/gemfire-modules/src/main/java/com/gemstone/gemfire/modules/session/catalina/internal/DeltaSessionAttributeEventBatch.java
@@ -0,0 +1,85 @@
+/*=========================================================================
+ * 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.modules.session.catalina.internal;
+
+import java.io.DataInput;
+import java.io.DataOutput;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+import com.gemstone.gemfire.DataSerializer;
+import com.gemstone.gemfire.cache.Cache;
+import com.gemstone.gemfire.cache.Region;
+import com.gemstone.gemfire.modules.gatewaydelta.AbstractGatewayDeltaEvent;
+import com.gemstone.gemfire.modules.session.catalina.DeltaSession;
+
+@SuppressWarnings("serial")
+public class DeltaSessionAttributeEventBatch extends AbstractGatewayDeltaEvent {
+
+ private List<DeltaSessionAttributeEvent> eventQueue;
+
+ public DeltaSessionAttributeEventBatch() {
+ }
+
+ public DeltaSessionAttributeEventBatch(String regionName, String sessionId, List<DeltaSessionAttributeEvent> eventQueue) {
+ super(regionName, sessionId);
+ this.eventQueue = eventQueue;
+ }
+
+ public List<DeltaSessionAttributeEvent> getEventQueue() {
+ return this.eventQueue;
+ }
+
+ public void apply(Cache cache) {
+ Region<String,DeltaSession> region = getRegion(cache);
+ DeltaSession session = region.get(this.key);
+ if (session == null) {
+ StringBuilder builder = new StringBuilder();
+ builder
+ .append("Session ")
+ .append(this.key)
+ .append(" was not found while attempting to apply ")
+ .append(this);
+ cache.getLogger().warning(builder.toString());
+ } else {
+ session.applyAttributeEvents(region, this.eventQueue);
+ if (cache.getLogger().fineEnabled()) {
+ StringBuilder builder = new StringBuilder();
+ builder
+ .append("Applied ")
+ .append(this);
+ cache.getLogger().fine(builder.toString());
+ }
+ }
+ }
+
+ public void fromData(DataInput in) throws IOException, ClassNotFoundException {
+ super.fromData(in);
+ this.eventQueue = DataSerializer.readArrayList(in);
+ }
+
+ public void toData(DataOutput out) throws IOException {
+ super.toData(out);
+ DataSerializer.writeArrayList((ArrayList) this.eventQueue, out);
+ }
+
+ public String toString() {
+ return new StringBuilder()
+ .append("DeltaSessionAttributeEventBatch[")
+ .append("regionName=")
+ .append(this.regionName)
+ .append("; sessionId=")
+ .append(this.key)
+ .append("; numberOfEvents=")
+ .append(this.eventQueue.size())
+ .append("]")
+ .toString();
+ }
+}
+
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/63bc5f03/extensions/gemfire-modules/src/main/java/com/gemstone/gemfire/modules/session/catalina/internal/DeltaSessionDestroyAttributeEvent.java
----------------------------------------------------------------------
diff --git a/extensions/gemfire-modules/src/main/java/com/gemstone/gemfire/modules/session/catalina/internal/DeltaSessionDestroyAttributeEvent.java b/extensions/gemfire-modules/src/main/java/com/gemstone/gemfire/modules/session/catalina/internal/DeltaSessionDestroyAttributeEvent.java
new file mode 100644
index 0000000..a8ee4fa
--- /dev/null
+++ b/extensions/gemfire-modules/src/main/java/com/gemstone/gemfire/modules/session/catalina/internal/DeltaSessionDestroyAttributeEvent.java
@@ -0,0 +1,65 @@
+/*=========================================================================
+ * 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.modules.session.catalina.internal;
+
+import java.io.DataInput;
+import java.io.DataOutput;
+import java.io.IOException;
+
+import com.gemstone.gemfire.DataSerializable;
+import com.gemstone.gemfire.DataSerializer;
+import com.gemstone.gemfire.Instantiator;
+import com.gemstone.gemfire.modules.session.catalina.DeltaSession;
+
+
+@SuppressWarnings("serial")
+public class DeltaSessionDestroyAttributeEvent implements DeltaSessionAttributeEvent {
+
+ private String attributeName;
+
+ public DeltaSessionDestroyAttributeEvent() {
+ }
+
+ public DeltaSessionDestroyAttributeEvent(String attributeName) {
+ this.attributeName = attributeName;
+ }
+
+ public String getAttributeName() {
+ return this.attributeName;
+ }
+
+ public void apply(DeltaSession session) {
+ session.localDestroyAttribute(this.attributeName);
+ }
+
+ public void fromData(DataInput in) throws IOException, ClassNotFoundException {
+ this.attributeName = DataSerializer.readString(in);
+ }
+
+ public void toData(DataOutput out) throws IOException {
+ DataSerializer.writeString(this.attributeName, out);
+ }
+
+ public static void registerInstantiator(int id) {
+ Instantiator.register(new Instantiator(DeltaSessionDestroyAttributeEvent.class, id) {
+ public DataSerializable newInstance() {
+ return new DeltaSessionDestroyAttributeEvent();
+ }
+ });
+ }
+
+ public String toString() {
+ return new StringBuilder()
+ .append("DeltaSessionDestroyAttributeEvent[")
+ .append("attributeName=")
+ .append(this.attributeName)
+ .append("]")
+ .toString();
+ }
+}
+
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/63bc5f03/extensions/gemfire-modules/src/main/java/com/gemstone/gemfire/modules/session/catalina/internal/DeltaSessionStatistics.java
----------------------------------------------------------------------
diff --git a/extensions/gemfire-modules/src/main/java/com/gemstone/gemfire/modules/session/catalina/internal/DeltaSessionStatistics.java b/extensions/gemfire-modules/src/main/java/com/gemstone/gemfire/modules/session/catalina/internal/DeltaSessionStatistics.java
new file mode 100644
index 0000000..43c8df5
--- /dev/null
+++ b/extensions/gemfire-modules/src/main/java/com/gemstone/gemfire/modules/session/catalina/internal/DeltaSessionStatistics.java
@@ -0,0 +1,81 @@
+/*=========================================================================
+ * 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.modules.session.catalina.internal;
+
+import com.gemstone.gemfire.StatisticDescriptor;
+import com.gemstone.gemfire.Statistics;
+import com.gemstone.gemfire.StatisticsFactory;
+import com.gemstone.gemfire.StatisticsType;
+import com.gemstone.gemfire.StatisticsTypeFactory;
+import com.gemstone.gemfire.internal.StatisticsTypeFactoryImpl;
+
+public class DeltaSessionStatistics {
+
+ public static final String typeName = "SessionStatistics";
+
+ private static final StatisticsType type;
+
+ private static final String SESSIONS_CREATED = "sessionsCreated";
+ private static final String SESSIONS_INVALIDATED= "sessionsInvalidated";
+ private static final String SESSIONS_EXPIRED= "sessionsExpired";
+
+ private static final int sessionsCreatedId;
+ private static final int sessionsInvalidatedId;
+ private static final int sessionsExpiredId;
+
+ static {
+ // Initialize type
+ StatisticsTypeFactory f = StatisticsTypeFactoryImpl.singleton();
+ type = f.createType(typeName, typeName,
+ new StatisticDescriptor[] {
+ f.createIntCounter(SESSIONS_CREATED, "The number of sessions created", "operations"),
+ f.createIntCounter(SESSIONS_INVALIDATED, "The number of sessions invalidated by invoking invalidate", "operations"),
+ f.createIntCounter(SESSIONS_EXPIRED, "The number of sessions invalidated by timeout", "operations"),
+ }
+ );
+
+ // Initialize id fields
+ sessionsCreatedId = type.nameToId(SESSIONS_CREATED);
+ sessionsInvalidatedId = type.nameToId(SESSIONS_INVALIDATED);
+ sessionsExpiredId = type.nameToId(SESSIONS_EXPIRED);
+ }
+
+ private final Statistics stats;
+
+ public DeltaSessionStatistics(StatisticsFactory factory, String applicationName) {
+ this.stats = factory.createAtomicStatistics(type, typeName + "_" + applicationName);
+ }
+
+ public void close() {
+ this.stats.close();
+ }
+
+ public int getSessionsCreated() {
+ return this.stats.getInt(sessionsCreatedId);
+ }
+
+ public void incSessionsCreated() {
+ this.stats.incInt(sessionsCreatedId, 1);
+ }
+
+ public int getSessionsInvalidated() {
+ return this.stats.getInt(sessionsInvalidatedId);
+ }
+
+ public void incSessionsInvalidated() {
+ this.stats.incInt(sessionsInvalidatedId, 1);
+ }
+
+ public int getSessionsExpired() {
+ return this.stats.getInt(sessionsExpiredId);
+ }
+
+ public void incSessionsExpired() {
+ this.stats.incInt(sessionsExpiredId, 1);
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/63bc5f03/extensions/gemfire-modules/src/main/java/com/gemstone/gemfire/modules/session/catalina/internal/DeltaSessionUpdateAttributeEvent.java
----------------------------------------------------------------------
diff --git a/extensions/gemfire-modules/src/main/java/com/gemstone/gemfire/modules/session/catalina/internal/DeltaSessionUpdateAttributeEvent.java b/extensions/gemfire-modules/src/main/java/com/gemstone/gemfire/modules/session/catalina/internal/DeltaSessionUpdateAttributeEvent.java
new file mode 100644
index 0000000..93fdac4
--- /dev/null
+++ b/extensions/gemfire-modules/src/main/java/com/gemstone/gemfire/modules/session/catalina/internal/DeltaSessionUpdateAttributeEvent.java
@@ -0,0 +1,75 @@
+/*=========================================================================
+ * 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.modules.session.catalina.internal;
+
+import java.io.DataInput;
+import java.io.DataOutput;
+import java.io.IOException;
+
+import com.gemstone.gemfire.DataSerializable;
+import com.gemstone.gemfire.DataSerializer;
+import com.gemstone.gemfire.Instantiator;
+import com.gemstone.gemfire.modules.session.catalina.DeltaSession;
+
+@SuppressWarnings("serial")
+public class DeltaSessionUpdateAttributeEvent implements DeltaSessionAttributeEvent {
+
+ private String attributeName;
+
+ private Object attributeValue;
+
+ public DeltaSessionUpdateAttributeEvent() {
+ }
+
+ public DeltaSessionUpdateAttributeEvent(String attributeName, Object attributeValue) {
+ this.attributeName = attributeName;
+ this.attributeValue = attributeValue;
+ }
+
+ public String getAttributeName() {
+ return this.attributeName;
+ }
+
+ public Object getAttributeValue() {
+ return this.attributeValue;
+ }
+
+ public void apply(DeltaSession session) {
+ session.localUpdateAttribute(this.attributeName, this.attributeValue);
+ }
+
+ public void fromData(DataInput in) throws IOException, ClassNotFoundException {
+ this.attributeName = DataSerializer.readString(in);
+ this.attributeValue = DataSerializer.readObject(in);
+ }
+
+ public void toData(DataOutput out) throws IOException {
+ DataSerializer.writeString(this.attributeName, out);
+ DataSerializer.writeObject(this.attributeValue, out);
+ }
+
+ public static void registerInstantiator(int id) {
+ Instantiator.register(new Instantiator(DeltaSessionUpdateAttributeEvent.class, id) {
+ public DataSerializable newInstance() {
+ return new DeltaSessionUpdateAttributeEvent();
+ }
+ });
+ }
+
+ public String toString() {
+ return new StringBuilder()
+ .append("DeltaSessionUpdateAttributeEvent[")
+ .append("attributeName=")
+ .append(this.attributeName)
+ .append("; attributeValue=")
+ .append(this.attributeValue)
+ .append("]")
+ .toString();
+ }
+}
+
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/63bc5f03/extensions/gemfire-modules/src/main/java/com/gemstone/gemfire/modules/util/Banner.java
----------------------------------------------------------------------
diff --git a/extensions/gemfire-modules/src/main/java/com/gemstone/gemfire/modules/util/Banner.java b/extensions/gemfire-modules/src/main/java/com/gemstone/gemfire/modules/util/Banner.java
new file mode 100644
index 0000000..9e3332d
--- /dev/null
+++ b/extensions/gemfire-modules/src/main/java/com/gemstone/gemfire/modules/util/Banner.java
@@ -0,0 +1,49 @@
+/*=========================================================================
+ * 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.modules.util;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.util.Properties;
+
+import com.gemstone.gemfire.internal.GemFireVersion;
+
+public class Banner {
+
+ private static String VERSION = "unknown";
+
+ private static Properties props = new Properties();
+
+ static {
+ InputStream is = Banner.class.getResourceAsStream("/modules-version.properties");
+ try {
+ props.load(is);
+ VERSION = props.getProperty("version");
+ } catch (IOException e) {
+ }
+ }
+
+ public static String getString() {
+ StringWriter sw = new StringWriter();
+ PrintWriter pw = new PrintWriter(sw);
+ print(pw);
+ pw.close();
+ return sw.toString();
+ }
+
+ private static void print(PrintWriter pw) {
+ pw.println("GemFire Modules");
+ pw.print("Modules version: ");
+ pw.println(VERSION);
+ GemFireVersion.print(pw);
+ }
+
+ private Banner() {}
+}
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/63bc5f03/extensions/gemfire-modules/src/main/java/com/gemstone/gemfire/modules/util/BootstrappingFunction.java
----------------------------------------------------------------------
diff --git a/extensions/gemfire-modules/src/main/java/com/gemstone/gemfire/modules/util/BootstrappingFunction.java b/extensions/gemfire-modules/src/main/java/com/gemstone/gemfire/modules/util/BootstrappingFunction.java
new file mode 100644
index 0000000..0a68ae6
--- /dev/null
+++ b/extensions/gemfire-modules/src/main/java/com/gemstone/gemfire/modules/util/BootstrappingFunction.java
@@ -0,0 +1,180 @@
+/*=========================================================================
+ * 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.modules.util;
+
+import com.gemstone.gemfire.cache.Cache;
+import com.gemstone.gemfire.cache.CacheFactory;
+import com.gemstone.gemfire.cache.execute.Execution;
+import com.gemstone.gemfire.cache.execute.Function;
+import com.gemstone.gemfire.cache.execute.FunctionContext;
+import com.gemstone.gemfire.cache.execute.FunctionService;
+import com.gemstone.gemfire.cache.execute.ResultCollector;
+import com.gemstone.gemfire.distributed.internal.DM;
+import com.gemstone.gemfire.distributed.internal.InternalDistributedSystem;
+import com.gemstone.gemfire.distributed.internal.MembershipListener;
+import com.gemstone.gemfire.distributed.internal.membership.InternalDistributedMember;
+
+import java.util.List;
+import java.util.Set;
+
+public class BootstrappingFunction implements Function, MembershipListener {
+
+ private static final long serialVersionUID = 1856043174458190605L;
+
+ public static final String ID = "bootstrapping-function";
+
+ private static final int TIME_TO_WAIT_FOR_CACHE = Integer.getInteger("gemfiremodules.timeToWaitForCache", 30000);
+
+ @Override
+ public void execute(FunctionContext context) {
+ // Verify that the cache exists before continuing.
+ // When this function is executed by a remote membership listener, it is
+ // being invoked before the cache is started.
+ Cache cache = verifyCacheExists();
+
+ // Register as membership listener
+ registerAsMembershipListener(cache);
+
+ // Register functions
+ registerFunctions();
+
+ // Return status
+ context.getResultSender().lastResult(Boolean.TRUE);
+ }
+
+ private Cache verifyCacheExists() {
+ int timeToWait = 0;
+ Cache cache = null;
+ while (timeToWait < TIME_TO_WAIT_FOR_CACHE) {
+ try {
+ cache = CacheFactory.getAnyInstance();
+ break;
+ } catch (Exception ignore) {
+ //keep trying and hope for the best
+ }
+ try {
+ Thread.sleep(250);
+ } catch (InterruptedException ie) {
+ Thread.currentThread().interrupt();
+ break;
+ }
+ timeToWait += 250;
+ }
+
+ if (cache == null) {
+ cache = new CacheFactory().create();
+ }
+
+ return cache;
+ }
+
+ private void registerAsMembershipListener(Cache cache) {
+ DM dm = ((InternalDistributedSystem) cache.getDistributedSystem()).getDistributionManager();
+ dm.addMembershipListener(this);
+ }
+
+ private void registerFunctions() {
+ // Synchronize so that these functions aren't registered twice. The
+ // constructor for the CreateRegionFunction creates a meta region.
+ synchronized (ID) {
+ // Register the create region function if it is not already registered
+ if (!FunctionService.isRegistered(CreateRegionFunction.ID)) {
+ FunctionService.registerFunction(new CreateRegionFunction());
+ }
+
+ // Register the touch partitioned region entries function if it is not already registered
+ if (!FunctionService.isRegistered(TouchPartitionedRegionEntriesFunction.ID)) {
+ FunctionService.registerFunction(new TouchPartitionedRegionEntriesFunction());
+ }
+
+ // Register the touch replicated region entries function if it is not already registered
+ if (!FunctionService.isRegistered(TouchReplicatedRegionEntriesFunction.ID)) {
+ FunctionService.registerFunction(new TouchReplicatedRegionEntriesFunction());
+ }
+
+ // Register the region size function if it is not already registered
+ if (!FunctionService.isRegistered(RegionSizeFunction.ID)) {
+ FunctionService.registerFunction(new RegionSizeFunction());
+ }
+ }
+ }
+
+ private void bootstrapMember(InternalDistributedMember member) {
+ // Create and execute the function
+ Cache cache = CacheFactory.getAnyInstance();
+ Execution execution = FunctionService.onMember(cache.getDistributedSystem(), member);
+ ResultCollector collector = execution.execute(this);
+
+ // Get the result. Nothing is being done with it.
+ try {
+ collector.getResult();
+ } catch (Exception e) {
+ // If an exception occurs in the function, log it.
+ cache.getLogger().warning("Caught unexpected exception:", e);
+ }
+ }
+
+ @Override
+ public String getId() {
+ return ID;
+ }
+
+ @Override
+ public boolean hasResult() {
+ return true;
+ }
+
+ @Override
+ public boolean isHA() {
+ return false;
+ }
+
+ @Override
+ public boolean optimizeForWrite() {
+ return false;
+ }
+
+ public int hashCode() {
+ // This method is only implemented so that multiple instances of this class
+ // don't get added as membership listeners.
+ return ID.hashCode();
+ }
+
+ public boolean equals(Object obj) {
+ // This method is only implemented so that multiple instances of this class
+ // don't get added as membership listeners.
+ if (this == obj) {
+ return true;
+ }
+
+ if (obj == null || !(obj instanceof BootstrappingFunction)) {
+ return false;
+ }
+
+ return true;
+ }
+
+ @Override
+ public void memberDeparted(InternalDistributedMember id, boolean crashed) {
+ }
+
+ @Override
+ public void memberJoined(InternalDistributedMember id) {
+ bootstrapMember(id);
+ }
+
+ @Override
+ public void memberSuspect(InternalDistributedMember id,
+ InternalDistributedMember whoSuspected, String reason) {
+ }
+
+ @Override
+ public void quorumLost(Set<InternalDistributedMember> internalDistributedMembers,
+ List<InternalDistributedMember> internalDistributedMembers2) {
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/63bc5f03/extensions/gemfire-modules/src/main/java/com/gemstone/gemfire/modules/util/ClassLoaderObjectInputStream.java
----------------------------------------------------------------------
diff --git a/extensions/gemfire-modules/src/main/java/com/gemstone/gemfire/modules/util/ClassLoaderObjectInputStream.java b/extensions/gemfire-modules/src/main/java/com/gemstone/gemfire/modules/util/ClassLoaderObjectInputStream.java
new file mode 100644
index 0000000..6dc991a
--- /dev/null
+++ b/extensions/gemfire-modules/src/main/java/com/gemstone/gemfire/modules/util/ClassLoaderObjectInputStream.java
@@ -0,0 +1,34 @@
+/*=========================================================================
+ * 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.modules.util;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.ObjectInputStream;
+import java.io.ObjectStreamClass;
+
+/**
+ * This class is used when session attributes need to be reconstructed with a
+ * new classloader.
+ */
+public class ClassLoaderObjectInputStream extends ObjectInputStream {
+
+ private final ClassLoader loader;
+
+ public ClassLoaderObjectInputStream(InputStream in,
+ ClassLoader loader) throws IOException {
+ super(in);
+ this.loader = loader;
+ }
+
+ @Override
+ public Class<?> resolveClass(
+ ObjectStreamClass desc) throws ClassNotFoundException {
+ return Class.forName(desc.getName(), false, loader);
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/63bc5f03/extensions/gemfire-modules/src/main/java/com/gemstone/gemfire/modules/util/ContextMapper.java
----------------------------------------------------------------------
diff --git a/extensions/gemfire-modules/src/main/java/com/gemstone/gemfire/modules/util/ContextMapper.java b/extensions/gemfire-modules/src/main/java/com/gemstone/gemfire/modules/util/ContextMapper.java
new file mode 100644
index 0000000..d1a5404
--- /dev/null
+++ b/extensions/gemfire-modules/src/main/java/com/gemstone/gemfire/modules/util/ContextMapper.java
@@ -0,0 +1,41 @@
+package com.gemstone.gemfire.modules.util;
+
+import com.gemstone.gemfire.modules.session.catalina.DeltaSessionManager;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * This basic singleton class maps context paths to manager instances.
+ *
+ * This class exists for a particular corner case described here. Consider a
+ * client-server environment with empty client regions *and* the need to fire
+ * HttpSessionListener destroy events. When a session expires, in this scenario,
+ * the Gemfire destroy events originate on the server and, with some Gemfire
+ * hackery, the destroyed object ends up as the event's callback argument. At
+ * the point that the CacheListener then gets the event, the re-constituted
+ * session object has no manager associated and so we need to re-attach a
+ * manager to it so that events can be fired correctly.
+ */
+
+public class ContextMapper {
+
+ private static Map<String, DeltaSessionManager> managers =
+ new HashMap<String, DeltaSessionManager>();
+
+ private ContextMapper() {
+ // This is a singleton
+ }
+
+ public static void addContext(String path, DeltaSessionManager manager) {
+ managers.put(path, manager);
+ }
+
+ public static DeltaSessionManager getContext(String path) {
+ return managers.get(path);
+ }
+
+ public static DeltaSessionManager removeContext(String path) {
+ return managers.remove(path);
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/63bc5f03/extensions/gemfire-modules/src/main/java/com/gemstone/gemfire/modules/util/CreateRegionFunction.java
----------------------------------------------------------------------
diff --git a/extensions/gemfire-modules/src/main/java/com/gemstone/gemfire/modules/util/CreateRegionFunction.java b/extensions/gemfire-modules/src/main/java/com/gemstone/gemfire/modules/util/CreateRegionFunction.java
new file mode 100644
index 0000000..65c2c51
--- /dev/null
+++ b/extensions/gemfire-modules/src/main/java/com/gemstone/gemfire/modules/util/CreateRegionFunction.java
@@ -0,0 +1,248 @@
+/*=========================================================================
+ * 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.modules.util;
+
+import com.gemstone.gemfire.cache.*;
+
+import com.gemstone.gemfire.cache.client.ClientCache;
+import com.gemstone.gemfire.cache.execute.*;
+import com.gemstone.gemfire.cache.partition.PartitionRegionHelper;
+
+import com.gemstone.gemfire.distributed.DistributedLockService;
+
+import com.gemstone.gemfire.distributed.internal.locks.DistributedMemberLock;
+
+import com.gemstone.gemfire.internal.cache.PartitionedRegion;
+
+import com.gemstone.gemfire.internal.cache.xmlcache.CacheXmlGenerator;
+import com.gemstone.gemfire.internal.i18n.LocalizedStrings;
+
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.PrintWriter;
+
+import java.util.Properties;
+
+public class CreateRegionFunction implements Function, Declarable {
+
+ private static final long serialVersionUID = -9210226844302128969L;
+
+ private final Cache cache;
+
+ private final Region<String,RegionConfiguration> regionConfigurationsRegion;
+
+ public static final String ID = "create-region-function";
+
+ private static final boolean DUMP_SESSION_CACHE_XML =
+ Boolean.getBoolean("gemfiremodules.dumpSessionCacheXml");
+
+ private static final String REGION_CONFIGURATION_METADATA_REGION = "__regionConfigurationMetadata";
+
+ public CreateRegionFunction() {
+ this(CacheFactory.getAnyInstance());
+ }
+
+ public CreateRegionFunction(Cache cache) {
+ this.cache = cache;
+ this.regionConfigurationsRegion = createRegionConfigurationMetadataRegion();
+ }
+
+ public CreateRegionFunction(ClientCache cache) {
+ this.cache = null;
+ this.regionConfigurationsRegion = null;
+ }
+
+ public void execute(FunctionContext context) {
+ RegionConfiguration configuration = (RegionConfiguration) context.getArguments();
+ if (this.cache.getLogger().fineEnabled()) {
+ StringBuilder builder = new StringBuilder();
+ builder
+ .append("Function ")
+ .append(ID)
+ .append(" received request: ")
+ .append(configuration);
+ this.cache.getLogger().fine(builder.toString());
+ }
+
+ // Create or retrieve region
+ RegionStatus status = createOrRetrieveRegion(configuration);
+
+ // Dump XML
+ if (DUMP_SESSION_CACHE_XML) {
+ writeCacheXml();
+ }
+ // Return status
+ context.getResultSender().lastResult(status);
+ }
+
+ private RegionStatus createOrRetrieveRegion(RegionConfiguration configuration) {
+ RegionStatus status = null;
+ String regionName = configuration.getRegionName();
+ if (this.cache.getLogger().fineEnabled()) {
+ this.cache.getLogger().fine("Function " + ID + " retrieving region named: " + regionName);
+ }
+ Region region = this.cache.getRegion(regionName);
+ if (region == null) {
+ status = createRegion(configuration);
+ } else {
+ status = RegionStatus.VALID;
+ try {
+ RegionHelper.validateRegion(this.cache, configuration, region);
+ } catch (Exception e) {
+ if (!e.getMessage()
+ .equals(
+ LocalizedStrings.RegionAttributesCreation_CACHELISTENERS_ARE_NOT_THE_SAME
+ .toLocalizedString())) {
+ this.cache.getLogger().warning(e);
+ }
+ status = RegionStatus.INVALID;
+ }
+ }
+ return status;
+ }
+
+ public String getId() {
+ return ID;
+ }
+
+ public boolean optimizeForWrite() {
+ return false;
+ }
+
+ public boolean isHA() {
+ return true;
+ }
+
+ public boolean hasResult() {
+ return true;
+ }
+
+ public void init(Properties properties) {
+ }
+
+ private RegionStatus createRegion(RegionConfiguration configuration) {
+ // Get a distributed lock
+ DistributedMemberLock dml = getDistributedLock();
+ if (this.cache.getLogger().fineEnabled()) {
+ this.cache.getLogger().fine(this + ": Attempting to lock " + dml);
+ }
+ long start=0, end=0;
+ RegionStatus status = null;
+ try {
+ if (this.cache.getLogger().fineEnabled()) {
+ start = System.currentTimeMillis();
+ }
+ // Obtain a lock on the distributed lock
+ dml.lockInterruptibly();
+ if (this.cache.getLogger().fineEnabled()) {
+ end = System.currentTimeMillis();
+ this.cache.getLogger().fine(this + ": Obtained lock on " + dml + " in " + (end-start) + " ms");
+ }
+
+ // Attempt to get the region again after the lock has been obtained
+ String regionName = configuration.getRegionName();
+ Region region = this.cache.getRegion(regionName);
+
+ // If it exists now, validate it.
+ // Else put an entry into the sessionRegionConfigurationsRegion
+ // while holding the lock. This will create the region in all VMs.
+ if (region == null) {
+ this.regionConfigurationsRegion.put(regionName, configuration);
+
+ // Retrieve the region after creating it
+ region = this.cache.getRegion(regionName);
+ // If the region is null now, it wasn't created for some reason
+ // (e.g. the region attributes id were invalid)
+ if (region == null) {
+ status = RegionStatus.INVALID;
+ } else {
+ // Create the PR buckets if necessary)
+ if (region instanceof PartitionedRegion) {
+ PartitionedRegion pr = (PartitionedRegion) region;
+ createBuckets(pr);
+ }
+ status = RegionStatus.VALID;
+ }
+ } else {
+ status = RegionStatus.VALID;
+ try {
+ RegionHelper.validateRegion(this.cache, configuration, region);
+ } catch (Exception e) {
+ if (!e.getMessage()
+ .equals(
+ LocalizedStrings.RegionAttributesCreation_CACHELISTENERS_ARE_NOT_THE_SAME
+ .toLocalizedString())) {
+ this.cache.getLogger().warning(e);
+ }
+ status = RegionStatus.INVALID;
+ }
+ }
+ } catch(Exception e) {
+ StringBuilder builder = new StringBuilder();
+ builder
+ .append(this)
+ .append(": Caught Exception attempting to create region named ")
+ .append(configuration.getRegionName())
+ .append(":");
+ this.cache.getLogger().warning(builder.toString(), e);
+ status = RegionStatus.INVALID;
+ }
+ finally {
+ // Unlock the distributed lock
+ try {
+ dml.unlock();
+ }
+ catch (Exception e) {}
+ }
+ return status;
+ }
+
+ private void createBuckets(PartitionedRegion region) {
+ PartitionRegionHelper.assignBucketsToPartitions(region);
+ }
+
+ private Region<String,RegionConfiguration> createRegionConfigurationMetadataRegion() {
+ // a sessionFactory in hibernate could have been re-started
+ // so, it is possible that this region exists already
+ Region<String, RegionConfiguration> r = this.cache
+ .getRegion(REGION_CONFIGURATION_METADATA_REGION);
+ if (r != null) {
+ return r;
+ }
+ RegionFactory<String, RegionConfiguration> factory = this.cache
+ .createRegionFactory(RegionShortcut.REPLICATE);
+ factory.addCacheListener(new RegionConfigurationCacheListener());
+ return factory.create(REGION_CONFIGURATION_METADATA_REGION);
+ }
+
+ private void writeCacheXml() {
+ File file = new File("cache-" + System.currentTimeMillis() + ".xml");
+ try {
+ PrintWriter pw = new PrintWriter(new FileWriter(file), true);
+ CacheXmlGenerator.generate(this.cache, pw);
+ pw.close();
+ } catch (IOException e) {}
+ }
+
+ private DistributedMemberLock getDistributedLock() {
+ String dlsName = this.regionConfigurationsRegion.getName();
+ DistributedLockService lockService = initializeDistributedLockService(dlsName);
+ String lockToken = dlsName + "_token";
+ return new DistributedMemberLock(lockService, lockToken);
+ }
+
+ private DistributedLockService initializeDistributedLockService(String dlsName) {
+ DistributedLockService lockService = DistributedLockService.getServiceNamed(dlsName);
+ if (lockService == null) {
+ lockService = DistributedLockService.create(dlsName, this.cache.getDistributedSystem());
+ }
+ return lockService;
+ }
+}
+
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/63bc5f03/extensions/gemfire-modules/src/main/java/com/gemstone/gemfire/modules/util/DebugCacheListener.java
----------------------------------------------------------------------
diff --git a/extensions/gemfire-modules/src/main/java/com/gemstone/gemfire/modules/util/DebugCacheListener.java b/extensions/gemfire-modules/src/main/java/com/gemstone/gemfire/modules/util/DebugCacheListener.java
new file mode 100644
index 0000000..8f1d4d3
--- /dev/null
+++ b/extensions/gemfire-modules/src/main/java/com/gemstone/gemfire/modules/util/DebugCacheListener.java
@@ -0,0 +1,65 @@
+/*=========================================================================
+ * 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.modules.util;
+
+import java.util.Properties;
+
+import com.gemstone.gemfire.cache.Declarable;
+import com.gemstone.gemfire.cache.EntryEvent;
+import com.gemstone.gemfire.cache.util.CacheListenerAdapter;
+
+@SuppressWarnings("unchecked")
+public class DebugCacheListener extends CacheListenerAdapter implements Declarable {
+
+ public void afterCreate(EntryEvent event) {
+ log(event);
+ }
+
+ public void afterUpdate(EntryEvent event) {
+ log(event);
+ }
+
+ public void afterInvalidate(EntryEvent event) {
+ log(event);
+ }
+
+ public void afterDestroy(EntryEvent event) {
+ log(event);
+ }
+
+ private void log(EntryEvent event) {
+ StringBuilder builder = new StringBuilder();
+ builder
+ .append("DebugCacheListener: Received ")
+ .append(event.getOperation())
+ .append(" for key=")
+ .append(event.getKey());
+ if (event.getNewValue() != null) {
+ builder
+ .append("; value=")
+ .append(event.getNewValue());
+ }
+ event.getRegion().getCache().getLogger().info(builder.toString());
+ }
+
+ public void init(Properties p) {}
+
+ public boolean equals(Object obj) {
+ // This method is only implemented so that RegionCreator.validateRegion works properly.
+ // The CacheListener comparison fails because two of these instances are not equal.
+ if (this == obj) {
+ return true;
+ }
+
+ if (obj == null || !(obj instanceof DebugCacheListener)) {
+ return false;
+ }
+
+ return true;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/63bc5f03/extensions/gemfire-modules/src/main/java/com/gemstone/gemfire/modules/util/ModuleStatistics.java
----------------------------------------------------------------------
diff --git a/extensions/gemfire-modules/src/main/java/com/gemstone/gemfire/modules/util/ModuleStatistics.java b/extensions/gemfire-modules/src/main/java/com/gemstone/gemfire/modules/util/ModuleStatistics.java
new file mode 100644
index 0000000..5b3a9fe
--- /dev/null
+++ b/extensions/gemfire-modules/src/main/java/com/gemstone/gemfire/modules/util/ModuleStatistics.java
@@ -0,0 +1,92 @@
+/*=========================================================================
+ * 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.modules.util;
+
+import com.gemstone.gemfire.StatisticDescriptor;
+import com.gemstone.gemfire.Statistics;
+import com.gemstone.gemfire.StatisticsFactory;
+import com.gemstone.gemfire.StatisticsType;
+import com.gemstone.gemfire.StatisticsTypeFactory;
+import com.gemstone.gemfire.distributed.DistributedSystem;
+import com.gemstone.gemfire.internal.StatisticsTypeFactoryImpl;
+
+/**
+ * Statistics for modules.
+ *
+ * @author sbawaska
+ */
+public class ModuleStatistics {
+
+ private static final StatisticsType type;
+
+ private static final int cacheHitsId;
+
+ private static final int cacheMissesId;
+
+ private static final int hibernateEntityDestroyJobsScheduledId;
+
+ static {
+ StatisticsTypeFactory f = StatisticsTypeFactoryImpl.singleton();
+ type = f
+ .createType(
+ "pluginStats",
+ "statistics for hibernate plugin and hibernate L2 cache",
+ new StatisticDescriptor[]{
+ f.createLongCounter("cacheHits",
+ "number of times an entity was found in L2 cache", "count"),
+ f.createLongCounter("cacheMisses",
+ "number of times an entity was NOT found in l2 cache",
+ "count"),
+ f.createLongCounter(
+ "hibernateEntityDestroyJobsScheduled",
+ "number of entities scheduled for destroy because of version conflict with a remote member",
+ "jobs")});
+
+ cacheHitsId = type.nameToId("cacheHits");
+ cacheMissesId = type.nameToId("cacheMisses");
+ hibernateEntityDestroyJobsScheduledId = type
+ .nameToId("hibernateEntityDestroyJobsScheduled");
+ }
+
+ private final Statistics stats;
+
+ private static ModuleStatistics instance;
+
+ private ModuleStatistics(StatisticsFactory factory) {
+ this.stats = factory.createAtomicStatistics(type, "PluginStatistics");
+ }
+
+ public static ModuleStatistics getInstance(DistributedSystem system) {
+ synchronized (ModuleStatistics.class) {
+ if (instance == null) {
+ instance = new ModuleStatistics(system);
+ }
+ }
+ return instance;
+ }
+
+ public void incCacheHit() {
+ stats.incLong(cacheHitsId, 1);
+ }
+
+ public long getCacheHits() {
+ return stats.getLong(cacheHitsId);
+ }
+
+ public void incCacheMiss() {
+ stats.incLong(cacheMissesId, 1);
+ }
+
+ public long getCacheMiss() {
+ return stats.getLong(cacheMissesId);
+ }
+
+ public void incHibernateDestroyJobsScheduled() {
+ stats.incLong(hibernateEntityDestroyJobsScheduledId, 1);
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/63bc5f03/extensions/gemfire-modules/src/main/java/com/gemstone/gemfire/modules/util/RegionConfiguration.java
----------------------------------------------------------------------
diff --git a/extensions/gemfire-modules/src/main/java/com/gemstone/gemfire/modules/util/RegionConfiguration.java b/extensions/gemfire-modules/src/main/java/com/gemstone/gemfire/modules/util/RegionConfiguration.java
new file mode 100644
index 0000000..6a82cbb
--- /dev/null
+++ b/extensions/gemfire-modules/src/main/java/com/gemstone/gemfire/modules/util/RegionConfiguration.java
@@ -0,0 +1,308 @@
+/*=========================================================================
+ * 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.modules.util;
+
+import java.io.DataInput;
+import java.io.DataOutput;
+import java.io.IOException;
+import java.io.InputStream;
+
+import com.gemstone.gemfire.DataSerializable;
+import com.gemstone.gemfire.DataSerializer;
+import com.gemstone.gemfire.Instantiator;
+import com.gemstone.gemfire.cache.CacheWriter;
+import com.gemstone.gemfire.cache.CustomExpiry;
+
+/**
+ * Class <code>RegionConfiguration</code> encapsulates the configuration
+ * attributes for a <code>Region</code> to be created on the server.
+ *
+ * @author Barry Oglesby
+ *
+ * @since 6.5
+ */
+@SuppressWarnings({"serial","unchecked"})
+public class RegionConfiguration implements DataSerializable {
+
+ /**
+ * The name of the <code>Region</code> to be created
+ */
+ private String regionName;
+
+ /**
+ * The id of the <code>RegionAttributes</code> to be used
+ */
+ private String regionAttributesId;
+
+ /**
+ * The default max inactive interval. The default value is -1.
+ */
+ public static final int DEFAULT_MAX_INACTIVE_INTERVAL = -1;
+
+ /**
+ * The maximum time interval in seconds before entries are expired
+ */
+ private int maxInactiveInterval = DEFAULT_MAX_INACTIVE_INTERVAL;
+
+ /**
+ * The <code>CustomExpiry</code> to be used
+ */
+ private CustomExpiry customExpiry;
+
+ /**
+ * Whether delta replication across a <code>Gateway</code> is enabled.
+ */
+ private boolean enableGatewayDeltaReplication = false;
+
+ /**
+ * Whether replication across a <code>Gateway</code> is enabled.
+ */
+ private boolean enableGatewayReplication = false;
+
+ /**
+ * Whether to add a <code>DebugCacheListener</code> to the <code>Region</code>.
+ */
+ private boolean enableDebugListener = false;
+
+ /**
+ * Whether to add a cache listener for session expiration events
+ */
+ private boolean enableSessionExpirationCacheListener = false;
+
+ /**
+ * name for the CacheWriter to be associated with this region. This cache writer must have a
+ * zero arg constructor and must be present on the classpath on the server.
+ */
+ private String cacheWriterName;
+
+ /**
+ * Default constructor used by the <code>DataSerialiable</code> interface
+ */
+ public RegionConfiguration() {}
+
+ /**
+ * Sets the name of the <code>Region</code> to be created
+ *
+ * @param regionName
+ * The name of the <code>Region</code> to be created
+ */
+ public void setRegionName(String regionName) {
+ this.regionName = regionName;
+ }
+
+ /**
+ * Returns the name of the <code>Region</code> to be created
+ *
+ * @return the name of the <code>Region</code> to be created
+ */
+ public String getRegionName() {
+ return this.regionName;
+ }
+
+ /**
+ * Sets the id of the <code>RegionAttributes</code> to be used
+ *
+ * @param regionAttributesId
+ * The id of the <code>RegionAttributes</code> to be used
+ */
+ public void setRegionAttributesId(String regionAttributesId) {
+ this.regionAttributesId = regionAttributesId;
+ }
+
+ /**
+ * Returns the id of the <code>RegionAttributes</code> to be used
+ *
+ * @return the id of the <code>RegionAttributes</code> to be used
+ */
+ public String getRegionAttributesId() {
+ return this.regionAttributesId;
+ }
+
+ /**
+ * Sets the maximum time interval in seconds before entries are expired
+ *
+ * @param maxInactiveInterval
+ * The maximum time interval in seconds before entries are expired
+ */
+ public void setMaxInactiveInterval(int maxInactiveInterval) {
+ this.maxInactiveInterval = maxInactiveInterval;
+ }
+
+ /**
+ * Returns the maximum time interval in seconds entries are expired
+ *
+ * @return the maximum time interval in seconds before entries are expired
+ */
+ public int getMaxInactiveInterval() {
+ return this.maxInactiveInterval;
+ }
+
+ /**
+ * Sets the <code>CustomExpiry</code> to be used
+ *
+ * @param customExpiry
+ * The <code>CustomExpiry</code> to be used
+ */
+ public void setCustomExpiry(CustomExpiry customExpiry) {
+ this.customExpiry = customExpiry;
+ }
+
+ /**
+ * Returns the <code>CustomExpiry</code> to be used
+ *
+ * @return the <code>CustomExpiry</code> to be used
+ */
+ public CustomExpiry getCustomExpiry() {
+ return this.customExpiry;
+ }
+
+ /**
+ * Enables/disables delta replication across a <code>Gateway</code>.
+ *
+ * @param enableGatewayDeltaReplication
+ * true to enable, false to disable gateway delta replication.
+ */
+ public void setEnableGatewayDeltaReplication(boolean enableGatewayDeltaReplication) {
+ this.enableGatewayDeltaReplication = enableGatewayDeltaReplication;
+ }
+
+ /**
+ * Returns whether delta replication across a <code>Gateway</code> is enabled.
+ *
+ * @return whether delta replication across a <code>Gateway</code> is enabled
+ */
+ public boolean getEnableGatewayDeltaReplication() {
+ return this.enableGatewayDeltaReplication;
+ }
+
+ /**
+ * Enables/disables replication across a <code>Gateway</code>.
+ *
+ * @param enableGatewayReplication
+ * true to enable, false to disable gateway replication.
+ */
+ public void setEnableGatewayReplication(boolean enableGatewayReplication) {
+ this.enableGatewayReplication = enableGatewayReplication;
+ }
+
+ /**
+ * Returns whether replication across a <code>Gateway</code> is enabled.
+ *
+ * @return whether replication across a <code>Gateway</code> is enabled
+ */
+ public boolean getEnableGatewayReplication() {
+ return this.enableGatewayReplication;
+ }
+
+ /**
+ * Enables/disables a debug <code>CacheListener</code>.
+ *
+ * @param enableDebugListener
+ * true to enable, false to disable debug <code>CacheListener</code>.
+ */
+ public void setEnableDebugListener(boolean enableDebugListener) {
+ this.enableDebugListener = enableDebugListener;
+ }
+
+ /**
+ * Returns whether a debug <code>CacheListener</code> is enabled.
+ *
+ * @return whether a debug <code>CacheListener</code> is enabled
+ */
+ public boolean getEnableDebugListener() {
+ return this.enableDebugListener;
+ }
+
+ public void setSessionExpirationCacheListener(boolean enableSessionExpirationCacheListener) {
+ this.enableSessionExpirationCacheListener = enableSessionExpirationCacheListener;
+ }
+
+ public boolean getSessionExpirationCacheListener() {
+ return this.enableSessionExpirationCacheListener;
+ }
+
+ public void toData(DataOutput out) throws IOException {
+ DataSerializer.writeString(this.regionName, out);
+ DataSerializer.writeString(this.regionAttributesId, out);
+ DataSerializer.writePrimitiveInt(this.maxInactiveInterval, out);
+ DataSerializer.writeObject(this.customExpiry, out);
+ DataSerializer.writeBoolean(this.enableGatewayDeltaReplication, out);
+ DataSerializer.writeBoolean(this.enableGatewayReplication, out);
+ DataSerializer.writeBoolean(this.enableDebugListener, out);
+ DataSerializer.writeString(this.cacheWriterName, out);
+ DataSerializer.writeBoolean(this.enableSessionExpirationCacheListener, out);
+ }
+
+ public void fromData(DataInput in) throws IOException, ClassNotFoundException {
+ this.regionName = DataSerializer.readString(in);
+ this.regionAttributesId = DataSerializer.readString(in);
+ this.maxInactiveInterval = DataSerializer.readPrimitiveInt(in);
+ this.customExpiry = DataSerializer.readObject(in);
+ this.enableGatewayDeltaReplication = DataSerializer.readBoolean(in);
+ this.enableGatewayReplication = DataSerializer.readBoolean(in);
+ this.enableDebugListener = DataSerializer.readBoolean(in);
+ this.cacheWriterName = DataSerializer.readString(in);
+
+ // This allows for backwards compatibility with 2.1 clients
+ if (((InputStream)in).available() > 0) {
+ this.enableSessionExpirationCacheListener = DataSerializer.readBoolean(in);
+ } else {
+ this.enableSessionExpirationCacheListener = false;
+ }
+ }
+
+ /**
+ * Registers an <code>Instantiator</code> for the
+ * <code>SessionConfiguration</code> class
+ */
+ public static void registerInstantiator(int id) {
+ Instantiator.register(new Instantiator(RegionConfiguration.class, id) {
+ public DataSerializable newInstance() {
+ return new RegionConfiguration();
+ }
+ });
+ }
+
+ public String toString() {
+ return new StringBuilder()
+ .append("RegionConfiguration[")
+ .append("regionName=")
+ .append(this.regionName)
+ .append("; regionAttributesId=")
+ .append(this.regionAttributesId)
+ .append("; maxInactiveInterval=")
+ .append(this.maxInactiveInterval)
+ .append("; enableGatewayDeltaReplication=")
+ .append(this.enableGatewayDeltaReplication)
+ .append("; enableGatewayReplication=")
+ .append(this.enableGatewayReplication)
+ .append("; enableDebugListener=")
+ .append(this.enableDebugListener)
+ .append("; enableSessionExpirationCacheListener=")
+ .append(this.enableSessionExpirationCacheListener)
+ .append("; cacheWriter=")
+ .append(this.cacheWriterName)
+ .append("]")
+ .toString();
+ }
+
+ /**
+ * set the fully qualified name of the {@link CacheWriter} to be created on
+ * the server. The cacheWriter must have a zero arg constructor, and must be
+ * present on the classpath on the server.
+ * @param cacheWriterName fully qualified class name of the cacheWriter
+ */
+ public void setCacheWriterName(String cacheWriterName) {
+ this.cacheWriterName = cacheWriterName;
+ }
+
+ public String getCacheWriterName() {
+ return cacheWriterName;
+ }
+}
+
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/63bc5f03/extensions/gemfire-modules/src/main/java/com/gemstone/gemfire/modules/util/RegionConfigurationCacheListener.java
----------------------------------------------------------------------
diff --git a/extensions/gemfire-modules/src/main/java/com/gemstone/gemfire/modules/util/RegionConfigurationCacheListener.java b/extensions/gemfire-modules/src/main/java/com/gemstone/gemfire/modules/util/RegionConfigurationCacheListener.java
new file mode 100644
index 0000000..2883b0a
--- /dev/null
+++ b/extensions/gemfire-modules/src/main/java/com/gemstone/gemfire/modules/util/RegionConfigurationCacheListener.java
@@ -0,0 +1,106 @@
+/*=========================================================================
+ * 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.modules.util;
+
+import com.gemstone.gemfire.cache.*;
+
+import com.gemstone.gemfire.cache.util.CacheListenerAdapter;
+import java.util.Properties;
+
+public class RegionConfigurationCacheListener extends CacheListenerAdapter<String,RegionConfiguration> implements Declarable {
+
+ private Cache cache;
+
+ public RegionConfigurationCacheListener() {
+ this.cache = CacheFactory.getAnyInstance();
+ }
+
+ public void afterCreate(EntryEvent<String,RegionConfiguration> event) {
+ RegionConfiguration configuration = event.getNewValue();
+ if (this.cache.getLogger().fineEnabled()) {
+ this.cache.getLogger().fine("RegionConfigurationCacheListener received afterCreate for region " + event.getKey());
+ }
+ // Create region
+ // this is a replicate region, and many VMs can be doing create region
+ // simultaneously, so ignore the RegionExistsException
+ try {
+ Region region = RegionHelper.createRegion(this.cache, configuration);
+ if (this.cache.getLogger().fineEnabled()) {
+ this.cache.getLogger().fine("RegionConfigurationCacheListener created region: " + region);
+ }
+ } catch (RegionExistsException exists) {
+ // ignore
+ this.cache.getLogger().fine("Region with configuration "+configuration+" existed");
+ }
+ }
+
+ @Override
+ public void afterUpdate(EntryEvent<String, RegionConfiguration> event) {
+ // a region could have been destroyed and then
+ // re-created, we want to create region again
+ // on remote nodes
+ afterCreate(event);
+ }
+
+ public void afterRegionCreate(RegionEvent<String,RegionConfiguration> event) {
+ StringBuilder builder1=null, builder2=null;
+ Region<String,RegionConfiguration> region = event.getRegion();
+ if (this.cache.getLogger().fineEnabled()) {
+ builder1 = new StringBuilder();
+ int regionSize = region.size();
+ if (regionSize > 0) {
+ builder1
+ .append("RegionConfigurationCacheListener region ")
+ .append(region.getName())
+ .append(" has been initialized with the following ")
+ .append(regionSize)
+ .append(" region configurations:\n");
+ builder2 = new StringBuilder();
+ builder2
+ .append("RegionConfigurationCacheListener created the following ")
+ .append(regionSize)
+ .append(" regions:\n");
+ } else {
+ builder1
+ .append("RegionConfigurationCacheListener region ")
+ .append(region.getName())
+ .append(" has been initialized with no region configurations");
+ }
+ }
+ for (RegionConfiguration configuration : region.values()) {
+ if (this.cache.getLogger().fineEnabled()) {
+ builder1
+ .append("\t")
+ .append(configuration);
+ }
+ try {
+ Region createRegion = RegionHelper.createRegion(this.cache, configuration);
+ if (this.cache.getLogger().fineEnabled()) {
+ builder2
+ .append("\t")
+ .append(createRegion);
+ }
+ } catch (RegionExistsException exists) {
+ // could have been concurrently created by another function
+ if (this.cache.getLogger().fineEnabled()) {
+ builder2.append("\t").append(" region existed");
+ }
+ }
+
+ }
+ if (this.cache.getLogger().fineEnabled()) {
+ this.cache.getLogger().fine(builder1.toString());
+ if (builder2 != null) {
+ this.cache.getLogger().fine(builder2.toString());
+ }
+ }
+ }
+
+ public void init(Properties p) {
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/63bc5f03/extensions/gemfire-modules/src/main/java/com/gemstone/gemfire/modules/util/RegionHelper.java
----------------------------------------------------------------------
diff --git a/extensions/gemfire-modules/src/main/java/com/gemstone/gemfire/modules/util/RegionHelper.java b/extensions/gemfire-modules/src/main/java/com/gemstone/gemfire/modules/util/RegionHelper.java
new file mode 100644
index 0000000..91d1222
--- /dev/null
+++ b/extensions/gemfire-modules/src/main/java/com/gemstone/gemfire/modules/util/RegionHelper.java
@@ -0,0 +1,238 @@
+/*=========================================================================
+ * 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.modules.util;
+
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.util.HashSet;
+import java.util.Set;
+import java.util.concurrent.CancellationException;
+
+import com.gemstone.gemfire.cache.AttributesFactory;
+import com.gemstone.gemfire.cache.Cache;
+import com.gemstone.gemfire.cache.CacheWriter;
+import com.gemstone.gemfire.cache.ExpirationAction;
+import com.gemstone.gemfire.cache.ExpirationAttributes;
+import com.gemstone.gemfire.cache.GemFireCache;
+import com.gemstone.gemfire.cache.Region;
+import com.gemstone.gemfire.cache.RegionAttributes;
+import com.gemstone.gemfire.cache.control.RebalanceFactory;
+import com.gemstone.gemfire.cache.control.RebalanceOperation;
+import com.gemstone.gemfire.cache.control.RebalanceResults;
+import com.gemstone.gemfire.cache.control.ResourceManager;
+import com.gemstone.gemfire.cache.partition.PartitionMemberInfo;
+import com.gemstone.gemfire.cache.partition.PartitionRebalanceInfo;
+import com.gemstone.gemfire.cache.partition.PartitionRegionHelper;
+import com.gemstone.gemfire.internal.cache.xmlcache.CacheXmlGenerator;
+import com.gemstone.gemfire.internal.cache.xmlcache.RegionAttributesCreation;
+import com.gemstone.gemfire.modules.gatewaydelta.GatewayDeltaForwarderCacheListener;
+import com.gemstone.gemfire.modules.session.catalina.callback.SessionExpirationCacheListener;
+
+@SuppressWarnings({"deprecation","unchecked"})
+public class RegionHelper {
+
+ public static final String NAME = "gemfire_modules";
+
+ public static Region createRegion(Cache cache, RegionConfiguration configuration) {
+ // Use the createRegion method so that the RegionAttributes creation can be reused by validate.
+ RegionAttributes requestedRegionAttributes = getRegionAttributes(cache, configuration);
+ Region region = cache.createRegion(configuration.getRegionName(), requestedRegionAttributes);
+
+ // Log the cache xml if debugging is enabled. I'd like to be able to just
+ // log the region, but that API is not available.
+ if (configuration.getEnableDebugListener()) {
+ cache.getLogger().info("Created new session region: " + region);
+ cache.getLogger().info(generateCacheXml(cache));
+ }
+ return region;
+ }
+
+ public static void validateRegion(Cache cache, RegionConfiguration configuration, Region region) {
+ // Get the attributes of the existing region
+ RegionAttributes existingAttributes = region.getAttributes();
+
+ // Create region attributes creation on existing region attributes.
+ // The RAC is created to execute the sameAs method.
+ RegionAttributesCreation existingRACreation = new RegionAttributesCreation(existingAttributes, false);
+
+ // Create requested region attributes
+ RegionAttributes requestedRegionAttributes = getRegionAttributes(cache, configuration);
+
+ // Compare the two region attributes. This method either returns true or throws a RuntimeException.
+ existingRACreation.sameAs(requestedRegionAttributes);
+ }
+
+ public static RebalanceResults rebalanceRegion(Region region)
+ throws CancellationException, InterruptedException {
+ String regionName = region.getName(); // FilterByName only looks at name and not full path
+ if (!PartitionRegionHelper.isPartitionedRegion(region)) {
+ StringBuilder builder = new StringBuilder();
+ builder
+ .append("Region ")
+ .append(regionName)
+ .append(" is not partitioned. Instead, it is ")
+ .append(region.getAttributes().getDataPolicy())
+ .append(". It can't be rebalanced.");
+ throw new IllegalArgumentException(builder.toString());
+ }
+
+ // Rebalance the region
+ ResourceManager resourceManager = region.getCache().getResourceManager();
+ RebalanceFactory rebalanceFactory = resourceManager.createRebalanceFactory();
+ Set<String> regionsToRebalance = new HashSet<String>();
+ regionsToRebalance.add(regionName);
+ rebalanceFactory.includeRegions(regionsToRebalance);
+ RebalanceOperation rebalanceOperation = rebalanceFactory.start();
+
+ // Return the results
+ return rebalanceOperation.getResults();
+ }
+
+ public static RebalanceResults rebalanceCache(GemFireCache cache)
+ throws CancellationException, InterruptedException {
+ ResourceManager resourceManager = cache.getResourceManager();
+ RebalanceFactory rebalanceFactory = resourceManager.createRebalanceFactory();
+ RebalanceOperation rebalanceOperation = rebalanceFactory.start();
+ return rebalanceOperation.getResults();
+ }
+
+ public static String generateCacheXml(Cache cache) {
+ try {
+ StringWriter sw = new StringWriter();
+ PrintWriter pw = new PrintWriter(sw, true);
+ CacheXmlGenerator.generate(cache, pw);
+ pw.close();
+ return sw.toString();
+ } catch (Exception ex) {
+ return "";
+ }
+ }
+
+ private static RegionAttributes getRegionAttributes(Cache cache, RegionConfiguration configuration) {
+ // Create the requested attributes
+ RegionAttributes baseRequestedAttributes = cache.getRegionAttributes(configuration.getRegionAttributesId());
+ if (baseRequestedAttributes == null) {
+ throw new IllegalArgumentException("No region attributes named " + configuration.getRegionAttributesId() + " are defined.");
+ }
+ AttributesFactory requestedFactory = new AttributesFactory(baseRequestedAttributes);
+
+ // Set the expiration time and action if necessary
+ int maxInactiveInterval = configuration.getMaxInactiveInterval();
+ if (maxInactiveInterval != RegionConfiguration.DEFAULT_MAX_INACTIVE_INTERVAL) {
+ requestedFactory.setStatisticsEnabled(true);
+ if (configuration.getCustomExpiry() == null) {
+ requestedFactory.setEntryIdleTimeout(new ExpirationAttributes(maxInactiveInterval, ExpirationAction.DESTROY));
+ } else {
+ requestedFactory.setCustomEntryIdleTimeout(configuration.getCustomExpiry());
+ }
+ }
+
+ // Add the gateway delta region cache listener if necessary
+ if (configuration.getEnableGatewayDeltaReplication()) {
+ // Add the listener that forwards created/destroyed deltas to the gateway
+ requestedFactory.addCacheListener(new GatewayDeltaForwarderCacheListener(cache));
+ }
+
+ // Enable gateway replication if necessary
+ // TODO: Disabled for WAN
+// requestedFactory.setEnableGateway(configuration.getEnableGatewayReplication());
+
+ // Add the debug cache listener if necessary
+ if (configuration.getEnableDebugListener()) {
+ requestedFactory.addCacheListener(new DebugCacheListener());
+ }
+
+ if (configuration.getSessionExpirationCacheListener()) {
+ requestedFactory.addCacheListener(new SessionExpirationCacheListener());
+ }
+
+ // Add the cacheWriter if necessary
+ if (configuration.getCacheWriterName() != null) {
+ try {
+ CacheWriter writer = (CacheWriter)Class.forName(
+ configuration.getCacheWriterName()).newInstance();
+ requestedFactory.setCacheWriter(writer);
+ } catch (InstantiationException e) {
+ throw new RuntimeException("Could not set a cacheWriter for the region", e);
+ } catch (IllegalAccessException e) {
+ throw new RuntimeException("Could not set a cacheWriter for the region", e);
+ } catch (ClassNotFoundException e) {
+ throw new RuntimeException("Could not set a cacheWriter for the region", e);
+ }
+ }
+ return requestedFactory.create();
+ }
+
+ private RegionHelper() {}
+
+ public static String getRebalanceResultsMessage(RebalanceResults results) {
+ StringBuilder builder = new StringBuilder();
+ for (PartitionRebalanceInfo rebalanceInfo : results.getPartitionRebalanceDetails()) {
+ // Log the overall results
+ fillInRebalanceResultsSummary(builder, rebalanceInfo);
+
+ // Log the 'Before' results
+ fillInRebalanceResultsMemberDetails(builder, rebalanceInfo.getPartitionMemberDetailsBefore(), "Before");
+
+ // Log the 'After' results
+ fillInRebalanceResultsMemberDetails(builder, rebalanceInfo.getPartitionMemberDetailsAfter(), "After");
+ }
+ return builder.toString();
+ }
+
+ private static void fillInRebalanceResultsSummary(StringBuilder builder, PartitionRebalanceInfo rebalanceInfo) {
+ builder
+ .append("\nRebalanced region ")
+ .append(rebalanceInfo.getRegionPath())
+ .append(" in ")
+ .append(rebalanceInfo.getTime())
+ .append(" ms")
+
+ .append("\nCreated ")
+ .append(rebalanceInfo.getBucketCreatesCompleted())
+ .append(" buckets containing ")
+ .append(rebalanceInfo.getBucketCreateBytes())
+ .append(" bytes in ")
+ .append(rebalanceInfo.getBucketCreateTime())
+ .append(" ms")
+
+ .append("\nTransferred ")
+ .append(rebalanceInfo.getBucketTransfersCompleted())
+ .append(" buckets containing ")
+ .append(rebalanceInfo.getBucketTransferBytes())
+ .append(" bytes in ")
+ .append(rebalanceInfo.getBucketTransferTime())
+ .append(" ms")
+
+ .append("\nTransferred ")
+ .append(rebalanceInfo.getPrimaryTransfersCompleted())
+ .append(" primary buckets in ")
+ .append(rebalanceInfo.getPrimaryTransferTime())
+ .append(" ms");
+ }
+
+ private static void fillInRebalanceResultsMemberDetails(StringBuilder builder, Set<PartitionMemberInfo> memberInfoSet, String when) {
+ builder
+ .append("\nMember Info ")
+ .append(when)
+ .append(" Rebalance:\n");
+ for (PartitionMemberInfo info : memberInfoSet) {
+ builder
+ .append("\tdistributedMember=")
+ .append(info.getDistributedMember())
+ .append(", configuredMaxMemory=")
+ .append(info.getConfiguredMaxMemory())
+ .append(", size=")
+ .append(info.getSize())
+ .append(", bucketCount=")
+ .append(info.getBucketCount())
+ .append(", primaryCount=")
+ .append(info.getPrimaryCount());
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/63bc5f03/extensions/gemfire-modules/src/main/java/com/gemstone/gemfire/modules/util/RegionSizeFunction.java
----------------------------------------------------------------------
diff --git a/extensions/gemfire-modules/src/main/java/com/gemstone/gemfire/modules/util/RegionSizeFunction.java b/extensions/gemfire-modules/src/main/java/com/gemstone/gemfire/modules/util/RegionSizeFunction.java
new file mode 100644
index 0000000..7207ce4
--- /dev/null
+++ b/extensions/gemfire-modules/src/main/java/com/gemstone/gemfire/modules/util/RegionSizeFunction.java
@@ -0,0 +1,47 @@
+/*=========================================================================
+ * 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.modules.util;
+
+import java.util.Properties;
+
+import com.gemstone.gemfire.cache.Declarable;
+import com.gemstone.gemfire.cache.execute.Function;
+import com.gemstone.gemfire.cache.execute.FunctionContext;
+import com.gemstone.gemfire.cache.execute.RegionFunctionContext;
+
+public class RegionSizeFunction implements Function, Declarable {
+
+ private static final long serialVersionUID = -2791590491585777990L;
+
+ public static final String ID = "region-size-function";
+
+ public void execute(FunctionContext context) {
+ RegionFunctionContext rfc = (RegionFunctionContext) context;
+ context.getResultSender().lastResult(rfc.getDataSet().size());
+ }
+
+ public String getId() {
+ return ID;
+ }
+
+ public boolean hasResult() {
+ return true;
+ }
+
+ public boolean optimizeForWrite() {
+ return true;
+ }
+
+ public boolean isHA() {
+ return true;
+ }
+
+ @Override
+ public void init(Properties arg0) {
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/63bc5f03/extensions/gemfire-modules/src/main/java/com/gemstone/gemfire/modules/util/RegionStatus.java
----------------------------------------------------------------------
diff --git a/extensions/gemfire-modules/src/main/java/com/gemstone/gemfire/modules/util/RegionStatus.java b/extensions/gemfire-modules/src/main/java/com/gemstone/gemfire/modules/util/RegionStatus.java
new file mode 100644
index 0000000..076456b
--- /dev/null
+++ b/extensions/gemfire-modules/src/main/java/com/gemstone/gemfire/modules/util/RegionStatus.java
@@ -0,0 +1,5 @@
+package com.gemstone.gemfire.modules.util;
+
+public enum RegionStatus {
+ VALID, INVALID
+}
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/63bc5f03/extensions/gemfire-modules/src/main/java/com/gemstone/gemfire/modules/util/ResourceManagerValidator.java
----------------------------------------------------------------------
diff --git a/extensions/gemfire-modules/src/main/java/com/gemstone/gemfire/modules/util/ResourceManagerValidator.java b/extensions/gemfire-modules/src/main/java/com/gemstone/gemfire/modules/util/ResourceManagerValidator.java
new file mode 100644
index 0000000..0090c4e
--- /dev/null
+++ b/extensions/gemfire-modules/src/main/java/com/gemstone/gemfire/modules/util/ResourceManagerValidator.java
@@ -0,0 +1,146 @@
+/*=========================================================================
+ * 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.modules.util;
+
+import java.lang.management.ManagementFactory;
+import java.lang.management.RuntimeMXBean;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import com.gemstone.gemfire.cache.GemFireCache;
+import com.gemstone.gemfire.cache.control.ResourceManager;
+
+public class ResourceManagerValidator {
+
+ private static final Pattern DIGIT_PATTERN = Pattern.compile("(\\d+|[^\\d]+)");
+
+ public static void validateJavaStartupParameters(GemFireCache cache) {
+ // Get the input arguments
+ ResourceManager rm = cache.getResourceManager();
+ RuntimeMXBean runtimeBean = ManagementFactory.getRuntimeMXBean();
+ List<String> inputArguments = runtimeBean.getInputArguments();
+ if (cache.getLogger().fineEnabled()) {
+ cache.getLogger().fine("Full input java arguments: " + inputArguments);
+ }
+
+ // Validate the arguments based on VM vendor
+ String vmVendor = runtimeBean.getVmVendor();
+ if (vmVendor.startsWith("Sun") || vmVendor.startsWith("Apple")) {
+ // java.vm.vendor = Sun Microsystems Inc. || java.vm.vendor = Apple Inc.
+ validateSunArguments(cache, rm, inputArguments);
+ } else if (vmVendor.startsWith("IBM")) {
+ // java.vm.vendor = IBM Corporation
+ // TODO validate IBM input arguments
+ } else if (vmVendor.startsWith("BEA")) {
+ // java.vm.vendor = BEA Systems, Inc.
+ // TODO validate JRockit input arguments
+ }
+ }
+
+ private static void validateSunArguments(GemFireCache cache, ResourceManager rm, List<String> inputArguments) {
+ // Retrieve the -Xms, -Xmx, UseConcMarkSweepGC and CMSInitiatingOccupancyFraction arguments
+ String dashXms=null, dashXmx=null, useCMS=null, cmsIOF=null;
+ for (String argument : inputArguments) {
+ if (argument.startsWith("-Xms")) {
+ dashXms = argument;
+ } else if (argument.startsWith("-Xmx")) {
+ dashXmx = argument;
+ } else if (argument.equals("-XX:+UseConcMarkSweepGC")) {
+ useCMS = argument;
+ } else if (argument.startsWith("-XX:CMSInitiatingOccupancyFraction")) {
+ cmsIOF = argument;
+ }
+ }
+ if (cache.getLogger().fineEnabled()) {
+ StringBuilder builder = new StringBuilder();
+ builder
+ .append("Relevant input java arguments: ")
+ .append("dashXms=")
+ .append(dashXms)
+ .append("; dashXmx=")
+ .append(dashXmx)
+ .append("; useCMS=")
+ .append(useCMS)
+ .append("; cmsIOF=")
+ .append(cmsIOF);
+ cache.getLogger().fine(builder.toString());
+ }
+
+ // Validate the heap parameters
+ validateJavaHeapParameters(cache, dashXms, dashXmx);
+
+ // Verify CMS is specified
+ verifyCMSGC(cache, useCMS);
+
+ // Verify CMSInitiatingOccupancyFraction is specified
+ verifyCMSInitiatingOccupancyFraction(cache, rm, cmsIOF);
+ }
+
+ private static void validateJavaHeapParameters(GemFireCache cache, String dashXms, String dashXmx) {
+ if (dashXms == null) {
+ cache.getLogger().warning("Setting the initial size of the heap (configured using -Xms) is recommended so that GemFire cache eviction is optimal");
+ } else if (dashXmx == null) {
+ cache.getLogger().warning("Setting the maximum size of the heap (configured using -Xmx) is recommended so that GemFire cache eviction is optimal");
+ } else {
+ // Neither heap parameter is null. Parse them and verify they are the same.
+ List<String> dashXmsList = splitAtDigits(dashXms);
+ String dashXmsStr = dashXmsList.get(1);
+ List<String> dashXmxList = splitAtDigits(dashXmx);
+ String dashXmxStr = dashXmxList.get(1);
+ if (!dashXmsStr.equals(dashXmxStr)) {
+ StringBuilder builder = new StringBuilder();
+ builder
+ .append("Setting the initial (")
+ .append(dashXmsStr)
+ .append(dashXmsList.get(2))
+ .append(") and maximum (")
+ .append(dashXmxStr)
+ .append(dashXmxList.get(2))
+ .append(") sizes of the heap the same is recommended so that GemFire cache eviction is optimal");
+ cache.getLogger().warning(builder.toString());
+ }
+ }
+ }
+
+ private static void verifyCMSGC(GemFireCache cache, String useCMS) {
+ if (useCMS == null) {
+ cache.getLogger().warning("Using the concurrent garbage collector (configured using -XX:+UseConcMarkSweepGC) is recommended so that GemFire cache eviction is optimal");
+ }
+ }
+
+ private static void verifyCMSInitiatingOccupancyFraction(GemFireCache cache, ResourceManager rm, String cmsIOF) {
+ if (cmsIOF == null) {
+ cache.getLogger().warning("Setting the CMS initiating occupancy fraction (configured using -XX:CMSInitiatingOccupancyFraction=N) is recommended so that GemFire cache eviction is optimal");
+ } else {
+ // Parse the CMSInitiatingOccupancyFraction. Verify it is less than both eviction and critical thresholds.
+ int cmsIOFVal = Integer.parseInt(cmsIOF.split("=")[1]);
+ float currentEvictionHeapPercentage = rm.getEvictionHeapPercentage();
+ if (currentEvictionHeapPercentage !=0 && currentEvictionHeapPercentage < cmsIOFVal) {
+ cache.getLogger().warning("Setting the CMS initiating occupancy fraction (" + cmsIOFVal + ") less than the eviction heap percentage (" + currentEvictionHeapPercentage + ") is recommended so that GemFire cache eviction is optimal");
+ }
+ float currentCriticalHeapPercentage = rm.getCriticalHeapPercentage();
+ if (currentCriticalHeapPercentage !=0 && currentCriticalHeapPercentage < cmsIOFVal) {
+ cache.getLogger().warning("Setting the CMS initiating occupancy fraction (" + cmsIOFVal + ") less than the critical heap percentage (" + currentCriticalHeapPercentage + ") is recommended so that GemFire cache eviction is optimal");
+ }
+ }
+ }
+
+ private static List<String> splitAtDigits(String input) {
+ Matcher matcher = DIGIT_PATTERN.matcher(input);
+ List<String> result = new ArrayList<String>();
+ while (matcher.find()) {
+ result.add(matcher.group());
+ }
+ return result;
+ }
+
+ private ResourceManagerValidator() {}
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/63bc5f03/extensions/gemfire-modules/src/main/java/com/gemstone/gemfire/modules/util/SessionCustomExpiry.java
----------------------------------------------------------------------
diff --git a/extensions/gemfire-modules/src/main/java/com/gemstone/gemfire/modules/util/SessionCustomExpiry.java b/extensions/gemfire-modules/src/main/java/com/gemstone/gemfire/modules/util/SessionCustomExpiry.java
new file mode 100644
index 0000000..f6ddece
--- /dev/null
+++ b/extensions/gemfire-modules/src/main/java/com/gemstone/gemfire/modules/util/SessionCustomExpiry.java
@@ -0,0 +1,53 @@
+/*=========================================================================
+ * 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.modules.util;
+
+import java.io.Serializable;
+import java.util.Properties;
+
+import com.gemstone.gemfire.cache.CustomExpiry;
+import com.gemstone.gemfire.cache.Declarable;
+import com.gemstone.gemfire.cache.ExpirationAction;
+import com.gemstone.gemfire.cache.ExpirationAttributes;
+import com.gemstone.gemfire.cache.Region;
+import javax.servlet.http.HttpSession;
+
+@SuppressWarnings("serial")
+public class SessionCustomExpiry implements CustomExpiry<String, HttpSession>, Serializable, Declarable {
+
+ private static final long serialVersionUID = 182735509690640051L;
+
+ private static final ExpirationAttributes EXPIRE_NOW = new ExpirationAttributes(1, ExpirationAction.DESTROY);
+
+ public ExpirationAttributes getExpiry(Region.Entry<String, HttpSession> entry) {
+ HttpSession session = entry.getValue();
+ if (session != null) {
+ return new ExpirationAttributes(entry.getValue().getMaxInactiveInterval(), ExpirationAction.DESTROY);
+ } else {
+ return EXPIRE_NOW;
+ }
+ }
+
+ public void close() {}
+
+ public void init(Properties props) {}
+
+ public boolean equals(Object obj) {
+ // This method is only implemented so that RegionCreator.validateRegion works properly.
+ // The EntryIdleTimeout comparison fails because two of these instances are not equal.
+ if (this == obj) {
+ return true;
+ }
+
+ if (obj == null || !(obj instanceof SessionCustomExpiry)) {
+ return false;
+ }
+
+ return true;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/63bc5f03/extensions/gemfire-modules/src/main/java/com/gemstone/gemfire/modules/util/TouchPartitionedRegionEntriesFunction.java
----------------------------------------------------------------------
diff --git a/extensions/gemfire-modules/src/main/java/com/gemstone/gemfire/modules/util/TouchPartitionedRegionEntriesFunction.java b/extensions/gemfire-modules/src/main/java/com/gemstone/gemfire/modules/util/TouchPartitionedRegionEntriesFunction.java
new file mode 100644
index 0000000..d3df675
--- /dev/null
+++ b/extensions/gemfire-modules/src/main/java/com/gemstone/gemfire/modules/util/TouchPartitionedRegionEntriesFunction.java
@@ -0,0 +1,89 @@
+/*=========================================================================
+ * 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.modules.util;
+
+import com.gemstone.gemfire.cache.*;
+
+import com.gemstone.gemfire.cache.execute.*;
+import com.gemstone.gemfire.cache.partition.PartitionRegionHelper;
+
+import java.util.Properties;
+import java.util.Set;
+
+/**
+ * Touches the keys contained in the set of keys by performing a get on the
+ * partitioned region.
+ *
+ * @author Barry Oglesby
+ */
+public class TouchPartitionedRegionEntriesFunction implements Function, Declarable {
+
+ private static final long serialVersionUID = -3700389655056961153L;
+
+ private final Cache cache;
+
+ public static final String ID = "touch-partitioned-region-entries";
+
+ public TouchPartitionedRegionEntriesFunction() {
+ this(CacheFactory.getAnyInstance());
+ }
+
+ public TouchPartitionedRegionEntriesFunction(Cache cache) {
+ this.cache = cache;
+ }
+
+ @SuppressWarnings("unchecked")
+ public void execute(FunctionContext context) {
+ RegionFunctionContext rfc = (RegionFunctionContext) context;
+ Set<String> keys = (Set<String>) rfc.getFilter();
+
+ // Get local (primary) data for the context
+ Region primaryDataSet = PartitionRegionHelper.getLocalDataForContext(rfc);
+
+ if (this.cache.getLogger().fineEnabled()) {
+ StringBuilder builder = new StringBuilder();
+ builder
+ .append("Function ")
+ .append(ID)
+ .append(" received request to touch ")
+ .append(primaryDataSet.getFullPath())
+ .append("->")
+ .append(keys);
+ this.cache.getLogger().fine(builder.toString());
+ }
+
+ // Retrieve each value to update the lastAccessedTime.
+ // Note: getAll is not supported on LocalDataSet.
+ for (String key : keys) {
+ primaryDataSet.get(key);
+ }
+
+ // Return result to get around NPE in LocalResultCollectorImpl
+ context.getResultSender().lastResult(true);
+ }
+
+ public String getId() {
+ return ID;
+ }
+
+ public boolean optimizeForWrite() {
+ return true;
+ }
+
+ public boolean isHA() {
+ return false;
+ }
+
+ public boolean hasResult() {
+ return true;
+ }
+
+ public void init(Properties properties) {
+ }
+}
+
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/63bc5f03/extensions/gemfire-modules/src/main/java/com/gemstone/gemfire/modules/util/TouchReplicatedRegionEntriesFunction.java
----------------------------------------------------------------------
diff --git a/extensions/gemfire-modules/src/main/java/com/gemstone/gemfire/modules/util/TouchReplicatedRegionEntriesFunction.java b/extensions/gemfire-modules/src/main/java/com/gemstone/gemfire/modules/util/TouchReplicatedRegionEntriesFunction.java
new file mode 100644
index 0000000..a73c531
--- /dev/null
+++ b/extensions/gemfire-modules/src/main/java/com/gemstone/gemfire/modules/util/TouchReplicatedRegionEntriesFunction.java
@@ -0,0 +1,88 @@
+/*=========================================================================
+ * 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.modules.util;
+
+import com.gemstone.gemfire.cache.*;
+
+import com.gemstone.gemfire.cache.execute.*;
+import com.gemstone.gemfire.cache.partition.PartitionRegionHelper;
+
+import java.util.Properties;
+import java.util.Set;
+
+/**
+ * Touches the keys contained in the set of keys by performing a get on the
+ * replicated region. This is a non-data-aware function invoked using onMembers
+ * or onServers.
+ *
+ * @author Barry Oglesby
+ */
+public class TouchReplicatedRegionEntriesFunction implements Function, Declarable {
+
+ private static final long serialVersionUID = -7424895036162243564L;
+
+ private final Cache cache;
+
+ public static final String ID = "touch-replicated-region-entries";
+
+ public TouchReplicatedRegionEntriesFunction() {
+ this(CacheFactory.getAnyInstance());
+ }
+
+ public TouchReplicatedRegionEntriesFunction(Cache cache) {
+ this.cache = cache;
+ }
+
+ public void execute(FunctionContext context) {
+ Object[] arguments = (Object[]) context.getArguments();
+ String regionName = (String) arguments[0];
+ Set<String> keys = (Set<String>) arguments[1];
+ if (this.cache.getLogger().fineEnabled()) {
+ StringBuilder builder = new StringBuilder();
+ builder
+ .append("Function ")
+ .append(ID)
+ .append(" received request to touch ")
+ .append(regionName)
+ .append("->")
+ .append(keys);
+ this.cache.getLogger().fine(builder.toString());
+ }
+
+ // Retrieve the appropriate Region and value to update the lastAccessedTime
+ Region region = this.cache.getRegion(regionName);
+ if (region != null) {
+ region.getAll(keys);
+ }
+
+ // Return result to get around NPE in LocalResultCollectorImpl
+ context.getResultSender().lastResult(true);
+ }
+
+ public String getId() {
+ return ID;
+ }
+
+ public boolean optimizeForWrite() {
+ return false;
+ }
+
+ public boolean isHA() {
+ return false;
+ }
+
+ public boolean hasResult() {
+ // Setting this to false caused the onServers method to only execute the
+ // function on one server.
+ return true;
+ }
+
+ public void init(Properties properties) {
+ }
+}
+
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/63bc5f03/extensions/gemfire-modules/src/main/resources/modules-version.properties
----------------------------------------------------------------------
diff --git a/extensions/gemfire-modules/src/main/resources/modules-version.properties b/extensions/gemfire-modules/src/main/resources/modules-version.properties
new file mode 100644
index 0000000..7a73b41
--- /dev/null
+++ b/extensions/gemfire-modules/src/main/resources/modules-version.properties
@@ -0,0 +1 @@
+version = @VERSION@
\ No newline at end of file