You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@geode.apache.org by kl...@apache.org on 2016/02/08 22:58:45 UTC
[18/50] [abbrv] incubator-geode git commit: GEODE-14: Integration of
GemFire Session Replication and Hibernate modules
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/48552465/extensions/gemfire-modules/src/main/java/com/gemstone/gemfire/modules/session/catalina/callback/LocalSessionCacheWriter.java
----------------------------------------------------------------------
diff --git a/extensions/gemfire-modules/src/main/java/com/gemstone/gemfire/modules/session/catalina/callback/LocalSessionCacheWriter.java b/extensions/gemfire-modules/src/main/java/com/gemstone/gemfire/modules/session/catalina/callback/LocalSessionCacheWriter.java
new file mode 100644
index 0000000..0385ebf
--- /dev/null
+++ b/extensions/gemfire-modules/src/main/java/com/gemstone/gemfire/modules/session/catalina/callback/LocalSessionCacheWriter.java
@@ -0,0 +1,59 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one or more
+* contributor license agreements. See the NOTICE file distributed with
+* this work for additional information regarding copyright ownership.
+* The ASF licenses this file to You under the Apache License, Version 2.0
+* (the "License"); you may not use this file except in compliance with
+* the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+package com.gemstone.gemfire.modules.session.catalina.callback;
+
+import com.gemstone.gemfire.cache.CacheWriterException;
+import com.gemstone.gemfire.cache.Declarable;
+import com.gemstone.gemfire.cache.EntryEvent;
+import com.gemstone.gemfire.cache.EntryNotFoundException;
+import com.gemstone.gemfire.cache.Region;
+import com.gemstone.gemfire.cache.util.CacheWriterAdapter;
+
+import javax.servlet.http.HttpSession;
+import java.util.Properties;
+
+public class LocalSessionCacheWriter extends CacheWriterAdapter<String, HttpSession> implements Declarable {
+
+ private final Region<String, HttpSession> backingRegion;
+
+ public LocalSessionCacheWriter(Region<String, HttpSession> backingRegion) {
+ this.backingRegion = backingRegion;
+ }
+
+ public void beforeCreate(EntryEvent<String, HttpSession> event) throws CacheWriterException {
+ this.backingRegion.put(event.getKey(), event.getNewValue(), event.getCallbackArgument());
+ }
+
+ public void beforeUpdate(EntryEvent<String, HttpSession> event) throws CacheWriterException {
+ this.backingRegion.put(event.getKey(), event.getNewValue(), event.getCallbackArgument());
+ }
+
+ public void beforeDestroy(EntryEvent<String, HttpSession> event) throws CacheWriterException {
+ try {
+ this.backingRegion.destroy(event.getKey(), event.getCallbackArgument());
+ } catch (EntryNotFoundException e) {
+ // I think it is safe to ignore this exception. The entry could have
+ // expired already in the backing region.
+ }
+ }
+
+ public void close() {
+ }
+
+ public void init(Properties p) {
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/48552465/extensions/gemfire-modules/src/main/java/com/gemstone/gemfire/modules/session/catalina/callback/SessionExpirationCacheListener.java
----------------------------------------------------------------------
diff --git a/extensions/gemfire-modules/src/main/java/com/gemstone/gemfire/modules/session/catalina/callback/SessionExpirationCacheListener.java b/extensions/gemfire-modules/src/main/java/com/gemstone/gemfire/modules/session/catalina/callback/SessionExpirationCacheListener.java
new file mode 100644
index 0000000..dff6d58
--- /dev/null
+++ b/extensions/gemfire-modules/src/main/java/com/gemstone/gemfire/modules/session/catalina/callback/SessionExpirationCacheListener.java
@@ -0,0 +1,77 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one or more
+* contributor license agreements. See the NOTICE file distributed with
+* this work for additional information regarding copyright ownership.
+* The ASF licenses this file to You under the Apache License, Version 2.0
+* (the "License"); you may not use this file except in compliance with
+* the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+package com.gemstone.gemfire.modules.session.catalina.callback;
+
+import com.gemstone.gemfire.cache.Declarable;
+import com.gemstone.gemfire.cache.EntryEvent;
+import com.gemstone.gemfire.cache.Operation;
+import com.gemstone.gemfire.cache.util.CacheListenerAdapter;
+import com.gemstone.gemfire.modules.session.catalina.DeltaSession;
+import com.gemstone.gemfire.modules.session.catalina.DeltaSessionManager;
+import com.gemstone.gemfire.modules.util.ContextMapper;
+
+import javax.servlet.http.HttpSession;
+import java.util.Properties;
+
+public class SessionExpirationCacheListener extends CacheListenerAdapter<String, HttpSession> implements Declarable {
+
+ public void afterDestroy(EntryEvent<String, HttpSession> event) {
+ // A Session expired. If it was destroyed by GemFire expiration, process it.
+ // If it was destroyed via Session.invalidate, ignore it since it has
+ // already been processed.
+ DeltaSession session = null;
+ if (event.getOperation() == Operation.EXPIRE_DESTROY) {
+ session = (DeltaSession) event.getOldValue();
+ } else {
+ /*
+ * This comes into play when we're dealing with an empty client proxy. We
+ * need the actual destroyed object to come back from the server so that
+ * any associated listeners can fire correctly. Having the destroyed
+ * object come back as the callback arg depends on setting the property
+ * gemfire.EXPIRE_SENDS_ENTRY_AS_CALLBACK.
+ */
+ Object callback = event.getCallbackArgument();
+ if (callback != null && callback instanceof DeltaSession) {
+ session = (DeltaSession) callback;
+ DeltaSessionManager m = ContextMapper.getContext(session.getContextName());
+ if (m != null) {
+ session.setOwner(m);
+ }
+ }
+ }
+ if (session != null) {
+ session.processExpired();
+ }
+ }
+
+ public void init(Properties p) {
+ }
+
+ public boolean equals(Object obj) {
+ // This method is only implemented so that RegionAttributesCreation.sameAs
+ // works properly.
+ if (this == obj) {
+ return true;
+ }
+
+ if (obj == null || !(obj instanceof SessionExpirationCacheListener)) {
+ return false;
+ }
+
+ return true;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/48552465/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..90b6f28
--- /dev/null
+++ b/extensions/gemfire-modules/src/main/java/com/gemstone/gemfire/modules/session/catalina/internal/DeltaSessionAttributeEvent.java
@@ -0,0 +1,25 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one or more
+* contributor license agreements. See the NOTICE file distributed with
+* this work for additional information regarding copyright ownership.
+* The ASF licenses this file to You under the Apache License, Version 2.0
+* (the "License"); you may not use this file except in compliance with
+* the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+package 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/48552465/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..47df071
--- /dev/null
+++ b/extensions/gemfire-modules/src/main/java/com/gemstone/gemfire/modules/session/catalina/internal/DeltaSessionAttributeEventBatch.java
@@ -0,0 +1,88 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one or more
+* contributor license agreements. See the NOTICE file distributed with
+* this work for additional information regarding copyright ownership.
+* The ASF licenses this file to You under the Apache License, Version 2.0
+* (the "License"); you may not use this file except in compliance with
+* the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+package com.gemstone.gemfire.modules.session.catalina.internal;
+
+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;
+
+import java.io.DataInput;
+import java.io.DataOutput;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+@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/48552465/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..989474f
--- /dev/null
+++ b/extensions/gemfire-modules/src/main/java/com/gemstone/gemfire/modules/session/catalina/internal/DeltaSessionDestroyAttributeEvent.java
@@ -0,0 +1,73 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one or more
+* contributor license agreements. See the NOTICE file distributed with
+* this work for additional information regarding copyright ownership.
+* The ASF licenses this file to You under the Apache License, Version 2.0
+* (the "License"); you may not use this file except in compliance with
+* the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+package com.gemstone.gemfire.modules.session.catalina.internal;
+
+import com.gemstone.gemfire.DataSerializable;
+import com.gemstone.gemfire.DataSerializer;
+import com.gemstone.gemfire.Instantiator;
+import com.gemstone.gemfire.modules.session.catalina.DeltaSession;
+
+import java.io.DataInput;
+import java.io.DataOutput;
+import java.io.IOException;
+
+
+@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/48552465/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..2d59103
--- /dev/null
+++ b/extensions/gemfire-modules/src/main/java/com/gemstone/gemfire/modules/session/catalina/internal/DeltaSessionStatistics.java
@@ -0,0 +1,88 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one or more
+* contributor license agreements. See the NOTICE file distributed with
+* this work for additional information regarding copyright ownership.
+* The ASF licenses this file to You under the Apache License, Version 2.0
+* (the "License"); you may not use this file except in compliance with
+* the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+package 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/48552465/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..6678e55
--- /dev/null
+++ b/extensions/gemfire-modules/src/main/java/com/gemstone/gemfire/modules/session/catalina/internal/DeltaSessionUpdateAttributeEvent.java
@@ -0,0 +1,83 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one or more
+* contributor license agreements. See the NOTICE file distributed with
+* this work for additional information regarding copyright ownership.
+* The ASF licenses this file to You under the Apache License, Version 2.0
+* (the "License"); you may not use this file except in compliance with
+* the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+package com.gemstone.gemfire.modules.session.catalina.internal;
+
+import com.gemstone.gemfire.DataSerializable;
+import com.gemstone.gemfire.DataSerializer;
+import com.gemstone.gemfire.Instantiator;
+import com.gemstone.gemfire.modules.session.catalina.DeltaSession;
+
+import java.io.DataInput;
+import java.io.DataOutput;
+import java.io.IOException;
+
+@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/48552465/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..dbe8e05
--- /dev/null
+++ b/extensions/gemfire-modules/src/main/java/com/gemstone/gemfire/modules/util/Banner.java
@@ -0,0 +1,59 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one or more
+* contributor license agreements. See the NOTICE file distributed with
+* this work for additional information regarding copyright ownership.
+* The ASF licenses this file to You under the Apache License, Version 2.0
+* (the "License"); you may not use this file except in compliance with
+* the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+package com.gemstone.gemfire.modules.util;
+
+import com.gemstone.gemfire.internal.GemFireVersion;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.util.Properties;
+
+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/48552465/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..827c6f7
--- /dev/null
+++ b/extensions/gemfire-modules/src/main/java/com/gemstone/gemfire/modules/util/BootstrappingFunction.java
@@ -0,0 +1,188 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one or more
+* contributor license agreements. See the NOTICE file distributed with
+* this work for additional information regarding copyright ownership.
+* The ASF licenses this file to You under the Apache License, Version 2.0
+* (the "License"); you may not use this file except in compliance with
+* the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+package 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/48552465/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..8cd600e
--- /dev/null
+++ b/extensions/gemfire-modules/src/main/java/com/gemstone/gemfire/modules/util/ClassLoaderObjectInputStream.java
@@ -0,0 +1,40 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one or more
+* contributor license agreements. See the NOTICE file distributed with
+* this work for additional information regarding copyright ownership.
+* The ASF licenses this file to You under the Apache License, Version 2.0
+* (the "License"); you may not use this file except in compliance with
+* the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+package 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/48552465/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..3b7b2de
--- /dev/null
+++ b/extensions/gemfire-modules/src/main/java/com/gemstone/gemfire/modules/util/ContextMapper.java
@@ -0,0 +1,53 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one or more
+* contributor license agreements. See the NOTICE file distributed with
+* this work for additional information regarding copyright ownership.
+* The ASF licenses this file to You under the Apache License, Version 2.0
+* (the "License"); you may not use this file except in compliance with
+* the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+package 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.
+ * <p>
+ * 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/48552465/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..564ccb7
--- /dev/null
+++ b/extensions/gemfire-modules/src/main/java/com/gemstone/gemfire/modules/util/CreateRegionFunction.java
@@ -0,0 +1,245 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one or more
+* contributor license agreements. See the NOTICE file distributed with
+* this work for additional information regarding copyright ownership.
+* The ASF licenses this file to You under the Apache License, Version 2.0
+* (the "License"); you may not use this file except in compliance with
+* the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+package com.gemstone.gemfire.modules.util;
+
+import com.gemstone.gemfire.cache.Cache;
+import com.gemstone.gemfire.cache.CacheFactory;
+import com.gemstone.gemfire.cache.Declarable;
+import com.gemstone.gemfire.cache.Region;
+import com.gemstone.gemfire.cache.RegionFactory;
+import com.gemstone.gemfire.cache.RegionShortcut;
+import com.gemstone.gemfire.cache.client.ClientCache;
+import com.gemstone.gemfire.cache.execute.Function;
+import com.gemstone.gemfire.cache.execute.FunctionContext;
+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/48552465/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..baca5b8
--- /dev/null
+++ b/extensions/gemfire-modules/src/main/java/com/gemstone/gemfire/modules/util/DebugCacheListener.java
@@ -0,0 +1,72 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one or more
+* contributor license agreements. See the NOTICE file distributed with
+* this work for additional information regarding copyright ownership.
+* The ASF licenses this file to You under the Apache License, Version 2.0
+* (the "License"); you may not use this file except in compliance with
+* the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+package com.gemstone.gemfire.modules.util;
+
+import com.gemstone.gemfire.cache.Declarable;
+import com.gemstone.gemfire.cache.EntryEvent;
+import com.gemstone.gemfire.cache.util.CacheListenerAdapter;
+
+import java.util.Properties;
+
+@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/48552465/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..dff5b95
--- /dev/null
+++ b/extensions/gemfire-modules/src/main/java/com/gemstone/gemfire/modules/util/ModuleStatistics.java
@@ -0,0 +1,91 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one or more
+* contributor license agreements. See the NOTICE file distributed with
+* this work for additional information regarding copyright ownership.
+* The ASF licenses this file to You under the Apache License, Version 2.0
+* (the "License"); you may not use this file except in compliance with
+* the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+package 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/48552465/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..5b025bc
--- /dev/null
+++ b/extensions/gemfire-modules/src/main/java/com/gemstone/gemfire/modules/util/RegionConfiguration.java
@@ -0,0 +1,308 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one or more
+* contributor license agreements. See the NOTICE file distributed with
+* this work for additional information regarding copyright ownership.
+* The ASF licenses this file to You under the Apache License, Version 2.0
+* (the "License"); you may not use this file except in compliance with
+* the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+package com.gemstone.gemfire.modules.util;
+
+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;
+
+import java.io.DataInput;
+import java.io.DataOutput;
+import java.io.IOException;
+import java.io.InputStream;
+
+/**
+ * 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/48552465/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..c25082b
--- /dev/null
+++ b/extensions/gemfire-modules/src/main/java/com/gemstone/gemfire/modules/util/RegionConfigurationCacheListener.java
@@ -0,0 +1,114 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one or more
+* contributor license agreements. See the NOTICE file distributed with
+* this work for additional information regarding copyright ownership.
+* The ASF licenses this file to You under the Apache License, Version 2.0
+* (the "License"); you may not use this file except in compliance with
+* the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+package com.gemstone.gemfire.modules.util;
+
+import com.gemstone.gemfire.cache.Cache;
+import com.gemstone.gemfire.cache.CacheFactory;
+import com.gemstone.gemfire.cache.Declarable;
+import com.gemstone.gemfire.cache.EntryEvent;
+import com.gemstone.gemfire.cache.Region;
+import com.gemstone.gemfire.cache.RegionEvent;
+import com.gemstone.gemfire.cache.RegionExistsException;
+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/48552465/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..78e4423
--- /dev/null
+++ b/extensions/gemfire-modules/src/main/java/com/gemstone/gemfire/modules/util/RegionHelper.java
@@ -0,0 +1,241 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one or more
+* contributor license agreements. See the NOTICE file distributed with
+* this work for additional information regarding copyright ownership.
+* The ASF licenses this file to You under the Apache License, Version 2.0
+* (the "License"); you may not use this file except in compliance with
+* the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+package com.gemstone.gemfire.modules.util;
+
+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;
+
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.util.HashSet;
+import java.util.Set;
+import java.util.concurrent.CancellationException;
+
+@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/48552465/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..13791a3
--- /dev/null
+++ b/extensions/gemfire-modules/src/main/java/com/gemstone/gemfire/modules/util/RegionSizeFunction.java
@@ -0,0 +1,56 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one or more
+* contributor license agreements. See the NOTICE file distributed with
+* this work for additional information regarding copyright ownership.
+* The ASF licenses this file to You under the Apache License, Version 2.0
+* (the "License"); you may not use this file except in compliance with
+* the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+package com.gemstone.gemfire.modules.util;
+
+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;
+
+import java.util.Properties;
+
+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/48552465/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..fec1fc1
--- /dev/null
+++ b/extensions/gemfire-modules/src/main/java/com/gemstone/gemfire/modules/util/RegionStatus.java
@@ -0,0 +1,21 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.gemstone.gemfire.modules.util;
+
+public enum RegionStatus {
+ VALID, INVALID
+}