You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@geode.apache.org by ab...@apache.org on 2016/02/17 19:23:42 UTC
[38/51] [partial] incubator-geode git commit: GEODE-917: rename
gemfire subprojects to geode
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/f6c4c2f9/extensions/geode-modules-hibernate/src/main/java/com/gemstone/gemfire/modules/hibernate/internal/ClientServerRegionFactoryDelegate.java
----------------------------------------------------------------------
diff --git a/extensions/geode-modules-hibernate/src/main/java/com/gemstone/gemfire/modules/hibernate/internal/ClientServerRegionFactoryDelegate.java b/extensions/geode-modules-hibernate/src/main/java/com/gemstone/gemfire/modules/hibernate/internal/ClientServerRegionFactoryDelegate.java
new file mode 100644
index 0000000..980e6ab
--- /dev/null
+++ b/extensions/geode-modules-hibernate/src/main/java/com/gemstone/gemfire/modules/hibernate/internal/ClientServerRegionFactoryDelegate.java
@@ -0,0 +1,208 @@
+/*
+* 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.hibernate.internal;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Properties;
+import java.util.StringTokenizer;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.gemstone.gemfire.cache.GemFireCache;
+import com.gemstone.gemfire.cache.Region;
+import com.gemstone.gemfire.cache.RegionShortcut;
+import com.gemstone.gemfire.cache.client.ClientCache;
+import com.gemstone.gemfire.cache.client.ClientCacheFactory;
+import com.gemstone.gemfire.cache.client.ClientRegionFactory;
+import com.gemstone.gemfire.cache.client.ClientRegionShortcut;
+import com.gemstone.gemfire.cache.execute.FunctionService;
+import com.gemstone.gemfire.modules.util.BootstrappingFunction;
+import com.gemstone.gemfire.modules.util.CreateRegionFunction;
+import com.gemstone.gemfire.modules.util.RegionConfiguration;
+
+public class ClientServerRegionFactoryDelegate extends RegionFactoryDelegate {
+
+ private static final String DEFAULT_SERVER_REGION_TYPE = RegionShortcut.PARTITION.name();
+
+ private static final String DEFAULT_CLIENT_REGION_TYPE = ClientRegionShortcut.PROXY.name();
+
+ private ClientCache clientCache;
+
+ public ClientServerRegionFactoryDelegate(Properties gemfireProperties,
+ Properties regionProperties) {
+ super(gemfireProperties, regionProperties);
+ }
+
+ @Override
+ public GemFireCache startCache() {
+ log.info("Creating a GemFire client cache");
+ String locatorsString = (String)gemfireProperties.remove("locators");
+ checkExistingCache();
+ ClientCacheFactory ccf = new ClientCacheFactory(gemfireProperties).setPoolSubscriptionEnabled(true);
+ List<LocatorHolder> locators = getLocatorsMap(locatorsString);
+ for (LocatorHolder locHolder : locators) {
+ log.debug("adding pool locator with host {} port {}", locHolder.host, locHolder.port);
+ ccf.addPoolLocator(locHolder.host, locHolder.port);
+ }
+ this.clientCache = ccf.create();
+
+ log.debug("GemFire client cache creation completed");
+ // bootstrap the servers
+ FunctionService.onServers(this.clientCache).execute(new BootstrappingFunction()).getResult();
+ FunctionService.registerFunction(new CreateRegionFunction(this.clientCache));
+ return this.clientCache;
+ }
+
+ private List<LocatorHolder> getLocatorsMap(String locatorsString) {
+ List<LocatorHolder> retval = new ArrayList<LocatorHolder>();
+ if (locatorsString == null || locatorsString.isEmpty()) {
+ return retval;
+ }
+ StringTokenizer st = new StringTokenizer(locatorsString, ",");
+ while (st.hasMoreTokens()) {
+ String locator = st.nextToken();
+ int portIndex = locator.indexOf('[');
+ if (portIndex < 1) {
+ portIndex = locator.lastIndexOf(':');
+ }
+ // starting in 5.1.0.4 we allow '@' as the bind-addr separator
+ // to let people use IPv6 numeric addresses (which contain colons)
+ int bindAddrIdx = locator.lastIndexOf('@', portIndex - 1);
+
+ if (bindAddrIdx < 0) {
+ bindAddrIdx = locator.lastIndexOf(':', portIndex - 1);
+ }
+
+ String host = locator.substring(0,
+ bindAddrIdx > -1 ? bindAddrIdx : portIndex);
+
+ if (host.indexOf(':') >= 0) {
+ bindAddrIdx = locator.lastIndexOf('@');
+ host = locator.substring(0, bindAddrIdx > -1 ? bindAddrIdx : portIndex);
+ }
+ int lastIndex = locator.lastIndexOf(']');
+ if (lastIndex == -1) {
+ if (locator.indexOf('[') >= 0) {
+ throw new IllegalArgumentException("Invalid locator");
+ } else {
+ // Using host:port syntax
+ lastIndex = locator.length();
+ }
+ }
+ String port = locator.substring(portIndex + 1, lastIndex);
+ int portVal = 0;
+ try {
+ portVal = Integer.parseInt(port);
+ if (portVal < 1 || portVal > 65535) {
+ throw new IllegalArgumentException("port should be grater than zero and less than 65536");
+ }
+ } catch (NumberFormatException ex) {
+ throw new IllegalArgumentException("Invalid Locator");
+ }
+ retval.add(new LocatorHolder(host, portVal));
+ }
+ return retval;
+ }
+
+ @Override
+ public Region<Object, EntityWrapper> createRegion(String regionName) {
+ // first create the region on the server
+ String serverRegionType = getServerRegionType(regionName);
+ RegionConfiguration regionConfig = new RegionConfiguration();
+ regionConfig.setRegionName(regionName);
+ regionConfig.setRegionAttributesId(serverRegionType);
+ regionConfig.setCacheWriterName(EntityRegionWriter.class.getCanonicalName());
+ FunctionService.onServer(this.clientCache).withArgs(regionConfig)
+ .execute(CreateRegionFunction.ID).getResult();
+ // now create region on the client
+ Region<Object, EntityWrapper> r = this.clientCache.getRegion(regionName);
+ if (r != null) {
+ return r;
+ }
+ String clientRegionType = getClientRegionType(regionName);
+ ClientRegionFactory<Object, EntityWrapper> rf = this.clientCache
+ .createClientRegionFactory(ClientRegionShortcut
+ .valueOf(clientRegionType));
+ r = rf.create(regionName);
+ return r;
+ }
+
+ private String getClientRegionType(String regionName) {
+ String rType = getOverridenClientRegionType(regionName);
+ if (rType != null) {
+ return rType.toUpperCase();
+ }
+ rType = regionProperties.getProperty("gemfire.default-client-region-attributes-id");
+ if (rType == null) {
+ rType = DEFAULT_CLIENT_REGION_TYPE;
+ }
+ return rType.toUpperCase();
+ }
+
+ private String getServerRegionType(String regionName) {
+ String rType = getOverridenServerRegionType(regionName);
+ if (rType != null) {
+ return rType.toUpperCase();
+ }
+ rType = regionProperties.getProperty("gemfire.default-region-attributes-id");
+ if (rType == null) {
+ rType = DEFAULT_SERVER_REGION_TYPE;
+ }
+ return rType.toUpperCase();
+ }
+
+ private String getOverridenServerRegionType(String regionName) {
+ String rType = null;
+ Iterator<Object> it = regionProperties.keySet().iterator();
+ while (it.hasNext()) {
+ String current = (String)it.next();
+ if (current.contains(regionName) && !current.contains("client")) {
+ rType = regionProperties.getProperty(current);
+ break;
+ }
+ }
+ return rType;
+ }
+
+ private String getOverridenClientRegionType(String regionName) {
+ String rType = null;
+ Iterator<Object> it = regionProperties.keySet().iterator();
+ while (it.hasNext()) {
+ String current = (String)it.next();
+ if (current.contains(regionName) && current.contains("client")) {
+ rType = regionProperties.getProperty(current);
+ break;
+ }
+ }
+ return rType;
+ }
+
+ private static class LocatorHolder {
+ private String host;
+ private int port;
+ private LocatorHolder(String host, int port) {
+ this.host = host;
+ this.port = port;
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/f6c4c2f9/extensions/geode-modules-hibernate/src/main/java/com/gemstone/gemfire/modules/hibernate/internal/CollectionAccess.java
----------------------------------------------------------------------
diff --git a/extensions/geode-modules-hibernate/src/main/java/com/gemstone/gemfire/modules/hibernate/internal/CollectionAccess.java b/extensions/geode-modules-hibernate/src/main/java/com/gemstone/gemfire/modules/hibernate/internal/CollectionAccess.java
new file mode 100644
index 0000000..f1898d8
--- /dev/null
+++ b/extensions/geode-modules-hibernate/src/main/java/com/gemstone/gemfire/modules/hibernate/internal/CollectionAccess.java
@@ -0,0 +1,224 @@
+/*
+* 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.hibernate.internal;
+
+import java.io.Serializable;
+import java.lang.reflect.Field;
+import java.util.HashSet;
+import java.util.Set;
+
+import org.hibernate.cache.CacheException;
+import org.hibernate.cache.CollectionRegion;
+import org.hibernate.cache.access.CollectionRegionAccessStrategy;
+import org.hibernate.cache.access.SoftLock;
+import org.hibernate.cache.entry.CollectionCacheEntry;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.gemstone.gemfire.cache.CacheWriterException;
+import com.gemstone.gemfire.cache.EntryExistsException;
+import com.gemstone.gemfire.cache.EntryNotFoundException;
+import com.gemstone.gemfire.cache.Region;
+import com.gemstone.gemfire.cache.client.ServerOperationException;
+
+public class CollectionAccess implements
+ CollectionRegionAccessStrategy {
+
+ private final GemFireCollectionRegion region;
+
+ private Logger log = LoggerFactory.getLogger(getClass());
+
+ /**
+ * if we know the entity whose ids are stored in this
+ * collection, we can prefetch those entities using
+ * getAll. This field stores that child entity name.
+ */
+ private String childEntityName;
+
+ public CollectionAccess(GemFireCollectionRegion region) {
+ this.region = region;
+ String regionName = this.region.getGemFireRegion().getName().trim();
+ regionName = regionName.replace("\\/", "");
+ int lastPeriod = regionName.lastIndexOf('.');
+ if (lastPeriod < 0) {
+ log.info("Eager prefetching disabled for region: {}", this.region.getName());
+ return;
+ }
+ String entityName = regionName.substring(0, lastPeriod);
+ String collectionFieldName = regionName.substring(lastPeriod+1);
+ log.debug("entity name: {}, collectionFieldName: {}", entityName, collectionFieldName);
+ try {
+ Class parentClass = Class.forName(entityName);
+ Field[] fields = parentClass.getDeclaredFields();
+ for (Field field : fields) {
+ log.debug("genericType: {}", field.getGenericType());
+ if (field.getName().equals(collectionFieldName)) {
+ String genericString = field.toGenericString();
+ log.debug("genericType: for required field name: {}", field.toGenericString());
+ int startDependentEntityIndex = genericString.indexOf("<");
+ if (startDependentEntityIndex != -1 &&
+ genericString.indexOf("<", startDependentEntityIndex+1) == -1) {
+ int childDependentEntityIndex = genericString.indexOf(">");
+ this.childEntityName = genericString.substring(startDependentEntityIndex+1, childDependentEntityIndex);
+ log.debug("For Collection {} using child entity: {}", this.region.getGemFireRegion().getName(), this.childEntityName);
+ }
+ }
+ }
+ }
+ catch (ClassNotFoundException e) {
+ //ok to ignore, we will not use pre-fetching
+ }
+ if (this.childEntityName == null) {
+ log.info("Eager prefetching disabled for region: {}", this.region.getName());
+ }
+ }
+
+ @Override
+ public CollectionRegion getRegion() {
+ return this.region;
+ }
+
+ @Override
+ public Object get(Object key, long txTimestamp) throws CacheException {
+ EntityWrapper wrapper = this.region.getGemFireRegion().get(key);
+ if (wrapper == null) {
+ this.region.getStats().incCacheMiss();
+ log.debug("Cache miss for {} ts: {}",key, txTimestamp);
+ return null;
+ } else {
+ this.region.getStats().incCacheHit();
+ log.debug("cache hit {} count: {} ", key, this.region.getStats().getCacheHits());
+ // do pre-fetching
+ if (isPrefetchPossible()) {
+ log.debug("for key: {} prefetching entries: {}", key, wrapper.getEntity());
+ prefetchKeys((CollectionCacheEntry)wrapper.getEntity());
+ }
+ }
+ return wrapper.getEntity();
+ }
+
+ private void prefetchKeys(CollectionCacheEntry entry) {
+ StringBuilder builder = new StringBuilder(this.childEntityName+"#");
+ Serializable[] childEntityKeys = entry.getState();
+ Set<String> getAllSet = new HashSet<String>();
+ for (Serializable id : childEntityKeys) {
+ String key = builder.append(id).toString();
+ log.debug("adding key {} to getAll set", key);
+ getAllSet.add(key);
+ }
+ GemFireEntityRegion childRegion = this.region.regionFactory.getEntityRegion(this.childEntityName);
+ log.debug("prefetching {} keys", getAllSet.size());
+ if (!getAllSet.isEmpty() && childRegion != null) {
+ childRegion.getAll(getAllSet);
+ }
+ }
+
+ private boolean isPrefetchPossible() {
+ return this.childEntityName != null;
+ }
+
+ private void printRegionContents(Region<Object, EntityWrapper> r) {
+ log.debug("printing contents of {} ",r);
+ for (Object k : r.keySet()) {
+ log.debug("key {} value {} ",k,r.get(k));
+ }
+ }
+
+ @Override
+ public boolean putFromLoad(Object key, Object value, long txTimestamp,
+ Object version) throws CacheException {
+ return putFromLoad(key, value, txTimestamp, version, true);
+ }
+
+ @Override
+ public boolean putFromLoad(Object key, Object value, long txTimestamp,
+ Object version, boolean minimalPutOverride) throws CacheException {
+ EntityWrapper wrapper = new EntityWrapper(value, 1L);
+ log.debug("putting a new collection entry from load {} value: {}",key, wrapper);
+ boolean remove = false;
+ try {
+ this.region.getGemFireRegion().create(key, wrapper);
+ } catch (EntryExistsException ee) {
+ log.debug("key {} exists in the cache already, destroying", key);
+ remove = true;
+ } catch (CacheWriterException writerEx) {
+ this.region.getStats().incHibernateDestroyJobsScheduled();
+ log.debug("caught a CacheWriterException {} ",writerEx.getMessage());
+ remove = true;
+ } catch (ServerOperationException serverEx) {
+ if (serverEx.getCause() instanceof CacheWriterException) {
+ this.region.getStats().incHibernateDestroyJobsScheduled();
+ log.debug("caught a ServerOperationException caused by CacheWriterException {} ",serverEx.getMessage());
+ } else {
+ throw serverEx;
+ }
+ remove = true;
+ }
+ if (remove) {
+ this.region.getGemFireRegion().remove(key);
+ return false;
+ }
+ return true;
+ }
+
+ @Override
+ public SoftLock lockItem(Object key, Object version) throws CacheException {
+ // there are no updates to the collectionCache,
+ // so no need to lock/version
+ return null;
+ }
+
+ @Override
+ public SoftLock lockRegion() throws CacheException {
+ return null;
+ }
+
+ @Override
+ public void unlockItem(Object key, SoftLock lock) throws CacheException {
+ }
+
+ @Override
+ public void unlockRegion(SoftLock lock) throws CacheException {
+ }
+
+ @Override
+ public void remove(Object key) throws CacheException {
+ log.debug("removing key {}",key);
+ this.region.getGemFireRegion().remove(key);
+ }
+
+ @Override
+ public void removeAll() throws CacheException {
+ log.debug("removing all keys");
+ this.region.getGemFireRegion().clear();
+ }
+
+ @Override
+ public void evict(Object key) throws CacheException {
+ // TODO we should implement a method on Region to evict
+ // a particular entry, destroying is inefficient
+ log.debug("removing key {}", key);
+ this.region.getGemFireRegion().remove(key);
+ }
+
+ @Override
+ public void evictAll() throws CacheException {
+ log.debug("removing all keys");
+ this.region.getGemFireRegion().clear();
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/f6c4c2f9/extensions/geode-modules-hibernate/src/main/java/com/gemstone/gemfire/modules/hibernate/internal/EntityRegionWriter.java
----------------------------------------------------------------------
diff --git a/extensions/geode-modules-hibernate/src/main/java/com/gemstone/gemfire/modules/hibernate/internal/EntityRegionWriter.java b/extensions/geode-modules-hibernate/src/main/java/com/gemstone/gemfire/modules/hibernate/internal/EntityRegionWriter.java
new file mode 100644
index 0000000..5a4e5e1
--- /dev/null
+++ b/extensions/geode-modules-hibernate/src/main/java/com/gemstone/gemfire/modules/hibernate/internal/EntityRegionWriter.java
@@ -0,0 +1,87 @@
+/*
+* 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.hibernate.internal;
+
+
+import java.util.Properties;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.gemstone.gemfire.cache.CacheWriterException;
+import com.gemstone.gemfire.cache.Declarable;
+import com.gemstone.gemfire.cache.EntryEvent;
+import com.gemstone.gemfire.cache.util.CacheWriterAdapter;
+
+public class EntityRegionWriter extends CacheWriterAdapter implements Declarable {
+
+ private Logger log = LoggerFactory.getLogger(getClass());
+
+// @Override
+// public void beforeCreate(EntryEvent event) {
+// event.getRegion().getCache().getLogger().info("GFE:Writer invoked for beforeCreate:"+event);
+// final Object key = event.getKey();
+// EntityWrapper val = (EntityWrapper)event.getNewValue();
+// EntityWrapper oldVal = (EntityWrapper)event.getOldValue();
+// log.debug("beforeCreate: key:"+key+" val:"+val.getEntity()+" ver:"+val.getVersion()+" region:"+event.getRegion().getName()+" oldVal:"+oldVal+" this:"+System.identityHashCode(this));
+// }
+
+ @Override
+ public void beforeUpdate(EntryEvent event) {
+ log.debug("Writer invoked for beforeUpdate:{}",event);
+ final Object key = event.getKey();
+ EntityWrapper val = (EntityWrapper)event.getNewValue();
+ if (val.getVersion() < 0) {
+ // no need for version check for NonStrictReadWrite
+ // this is needed because CacheEntry does not implement equals
+ return;
+ }
+ EntityWrapper oldVal = (EntityWrapper)event.getOldValue();
+ // if same entity was loaded from two different VMs,
+ // i.e. version same and entity equal then no need to destroy
+ //
+ if (oldVal.getVersion() == val.getVersion()) {
+ if (val.getEntity().equals(oldVal.getEntity())) {
+ // since CacheEntry does not override equals
+ // this check is probably of no use
+ return;
+ }
+ } else if (oldVal.getVersion() < val.getVersion()) {
+ return;
+ }
+ log.debug("For key {} old version was {} new version was {}", new Object[] {key, oldVal.getVersion(), val.getVersion()});
+ throw new CacheWriterException("key "+key+" had a newer version");
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ // This method is only implemented so that RegionCreator.validateRegion works properly.
+ // The CacheWriter comparison fails because two of these instances are not equal.
+ if (this == obj) {
+ return true;
+ }
+
+ if (obj == null || !(obj instanceof EntityRegionWriter)) {
+ return false;
+ }
+ return true;
+ }
+
+ @Override
+ public void init(Properties arg0) {
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/f6c4c2f9/extensions/geode-modules-hibernate/src/main/java/com/gemstone/gemfire/modules/hibernate/internal/EntityVersion.java
----------------------------------------------------------------------
diff --git a/extensions/geode-modules-hibernate/src/main/java/com/gemstone/gemfire/modules/hibernate/internal/EntityVersion.java b/extensions/geode-modules-hibernate/src/main/java/com/gemstone/gemfire/modules/hibernate/internal/EntityVersion.java
new file mode 100644
index 0000000..abfb675
--- /dev/null
+++ b/extensions/geode-modules-hibernate/src/main/java/com/gemstone/gemfire/modules/hibernate/internal/EntityVersion.java
@@ -0,0 +1,28 @@
+/*
+* 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.hibernate.internal;
+
+import org.hibernate.cache.access.SoftLock;
+
+/**
+ *
+ * @author sbawaska
+ */
+public interface EntityVersion extends SoftLock {
+
+ public Long getVersion();
+}
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/f6c4c2f9/extensions/geode-modules-hibernate/src/main/java/com/gemstone/gemfire/modules/hibernate/internal/EntityVersionImpl.java
----------------------------------------------------------------------
diff --git a/extensions/geode-modules-hibernate/src/main/java/com/gemstone/gemfire/modules/hibernate/internal/EntityVersionImpl.java b/extensions/geode-modules-hibernate/src/main/java/com/gemstone/gemfire/modules/hibernate/internal/EntityVersionImpl.java
new file mode 100644
index 0000000..ad160e4
--- /dev/null
+++ b/extensions/geode-modules-hibernate/src/main/java/com/gemstone/gemfire/modules/hibernate/internal/EntityVersionImpl.java
@@ -0,0 +1,51 @@
+/*
+* 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.hibernate.internal;
+
+/**
+ *
+ * @author sbawaska
+ */
+public class EntityVersionImpl implements EntityVersion {
+
+ private final Long version;
+
+ public EntityVersionImpl(Long version) {
+ this.version = version;
+ }
+
+ @Override
+ public Long getVersion() {
+ return this.version;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj instanceof EntityVersionImpl) {
+ EntityVersionImpl other = (EntityVersionImpl)obj;
+ if (this.version.equals(other.version)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public int hashCode() {
+ return this.version.hashCode();
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/f6c4c2f9/extensions/geode-modules-hibernate/src/main/java/com/gemstone/gemfire/modules/hibernate/internal/EntityWrapper.java
----------------------------------------------------------------------
diff --git a/extensions/geode-modules-hibernate/src/main/java/com/gemstone/gemfire/modules/hibernate/internal/EntityWrapper.java b/extensions/geode-modules-hibernate/src/main/java/com/gemstone/gemfire/modules/hibernate/internal/EntityWrapper.java
new file mode 100644
index 0000000..ab92dea
--- /dev/null
+++ b/extensions/geode-modules-hibernate/src/main/java/com/gemstone/gemfire/modules/hibernate/internal/EntityWrapper.java
@@ -0,0 +1,89 @@
+/*
+* 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.hibernate.internal;
+
+import java.io.DataInput;
+import java.io.DataOutput;
+import java.io.IOException;
+
+import com.gemstone.gemfire.DataSerializable;
+import com.gemstone.gemfire.DataSerializer;
+
+public class EntityWrapper implements DataSerializable {
+
+ private static final long serialVersionUID = 8616754027252339041L;
+
+ private Object entity;
+
+ private long version;
+
+ public EntityWrapper(Object entity, long version) {
+ this.entity = entity;
+ this.version = version;
+ }
+
+ /**
+ * for {@link DataSerializer}
+ */
+ public EntityWrapper() {
+ }
+
+ public long getVersion() {
+ return version;
+ }
+
+ public Object getEntity() {
+ return entity;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj instanceof EntityWrapper) {
+ EntityWrapper other = (EntityWrapper)obj;
+ if (this.version == other.version) {
+ //CacheEntry does not override equals, hence cannot be used in this comparison
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public int hashCode() {
+ return Long.valueOf(this.version).hashCode();
+ }
+
+ @Override
+ public String toString() {
+ return new StringBuilder()
+ .append("EntityWrapper@" + System.identityHashCode(this))
+ .append(" Entity:" + this.entity).append(" version:" + this.version)
+ .toString();
+ }
+
+ @Override
+ public void toData(DataOutput out) throws IOException {
+ out.writeLong(this.version);
+ DataSerializer.writeObject(this.entity, out);
+ }
+
+ @Override
+ public void fromData(DataInput in) throws IOException, ClassNotFoundException {
+ this.version = in.readLong();
+ this.entity = DataSerializer.readObject(in);
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/f6c4c2f9/extensions/geode-modules-hibernate/src/main/java/com/gemstone/gemfire/modules/hibernate/internal/GemFireBaseRegion.java
----------------------------------------------------------------------
diff --git a/extensions/geode-modules-hibernate/src/main/java/com/gemstone/gemfire/modules/hibernate/internal/GemFireBaseRegion.java b/extensions/geode-modules-hibernate/src/main/java/com/gemstone/gemfire/modules/hibernate/internal/GemFireBaseRegion.java
new file mode 100644
index 0000000..9e77a98
--- /dev/null
+++ b/extensions/geode-modules-hibernate/src/main/java/com/gemstone/gemfire/modules/hibernate/internal/GemFireBaseRegion.java
@@ -0,0 +1,166 @@
+/*
+* 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.hibernate.internal;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+import java.util.concurrent.ExecutorService;
+
+import org.hibernate.cache.CacheDataDescription;
+import org.hibernate.cache.CacheException;
+import org.hibernate.cache.Region;
+import org.hibernate.cache.Timestamper;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.gemstone.gemfire.distributed.DistributedSystem;
+import com.gemstone.gemfire.internal.cache.LocalRegion;
+import com.gemstone.gemfire.modules.hibernate.GemFireRegionFactory;
+import com.gemstone.gemfire.modules.util.ModuleStatistics;
+
+public class GemFireBaseRegion implements Region {
+
+ /**
+ * the backing region
+ */
+ protected final com.gemstone.gemfire.cache.Region<Object, EntityWrapper> region;
+
+ /**
+ * to determine if the operation should be forwarded to server
+ */
+ protected final boolean isClientRegion;
+
+ protected final CacheDataDescription metadata;
+
+ private final Logger log = LoggerFactory.getLogger(getClass());
+
+ protected final GemFireRegionFactory regionFactory;
+
+ protected final ModuleStatistics stats;
+
+ public GemFireBaseRegion(com.gemstone.gemfire.cache.Region<Object, EntityWrapper> region,
+ boolean isClient, CacheDataDescription metadata, GemFireRegionFactory regionFactory) {
+ this.region = region;
+ this.isClientRegion = isClient;
+ this.metadata = metadata;
+ this.regionFactory = regionFactory;
+ DistributedSystem system = ((LocalRegion)region).getSystem();
+ this.stats = ModuleStatistics.getInstance(system);
+
+ }
+
+ public com.gemstone.gemfire.cache.Region<Object, EntityWrapper> getGemFireRegion() {
+ return this.region;
+ }
+
+ public ModuleStatistics getStats() {
+ return this.stats;
+ }
+
+ public ExecutorService getExecutorService() {
+ return this.regionFactory.getExecutorService();
+ }
+
+ @Override
+ public String getName() {
+ return this.region.getName();
+ }
+
+ @Override
+ public void destroy() throws CacheException {
+ if (!this.region.isDestroyed()) {
+ this.region.localDestroyRegion();
+ }
+ }
+
+ /*
+ * I did not see any useful callers from hibernate-core
+ */
+ @Override
+ public boolean contains(Object key) {
+ log.debug("contains key called for :" + key);
+ if (isClientRegion) {
+ // TODO should this be done?
+ return this.region.containsKeyOnServer(key);
+ }
+ return this.region.containsKey(key);
+ }
+
+ @Override
+ public long getSizeInMemory() {
+ return 0;
+ }
+
+ @Override
+ public long getElementCountInMemory() {
+ return this.region.size();
+ }
+
+ @Override
+ public long getElementCountOnDisk() {
+ LocalRegion lr = (LocalRegion)this.region;
+ if (lr.getDiskRegion() != null) {
+ return lr.getDiskRegion().getNumOverflowOnDisk();
+ }
+ return 0;
+ }
+
+ @Override
+ public Map<Object, EntityWrapper> toMap() {
+ return Collections.unmodifiableMap(this.region);
+ }
+
+ /*
+ * only used by updateTimestamps cache
+ */
+ @Override
+ public long nextTimestamp() {
+ log.debug("nextTimestamp called");
+ return Timestamper.next();
+ }
+
+ /*
+ * this is used by updateTimestamps cache only
+ */
+ @Override
+ public int getTimeout() {
+ return 60*1000; // all other cache providers have same value
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj instanceof GemFireBaseRegion) {
+ GemFireBaseRegion other = (GemFireBaseRegion)obj;
+ if (this.region.getName().equals(other.region.getName())
+ && this.isClientRegion == other.isClientRegion) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public int hashCode() {
+ return this.region.hashCode() + (this.isClientRegion ? 1 : 0);
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/f6c4c2f9/extensions/geode-modules-hibernate/src/main/java/com/gemstone/gemfire/modules/hibernate/internal/GemFireCollectionRegion.java
----------------------------------------------------------------------
diff --git a/extensions/geode-modules-hibernate/src/main/java/com/gemstone/gemfire/modules/hibernate/internal/GemFireCollectionRegion.java b/extensions/geode-modules-hibernate/src/main/java/com/gemstone/gemfire/modules/hibernate/internal/GemFireCollectionRegion.java
new file mode 100644
index 0000000..620a332
--- /dev/null
+++ b/extensions/geode-modules-hibernate/src/main/java/com/gemstone/gemfire/modules/hibernate/internal/GemFireCollectionRegion.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.hibernate.internal;
+
+import org.hibernate.cache.CacheDataDescription;
+import org.hibernate.cache.CacheException;
+import org.hibernate.cache.CollectionRegion;
+import org.hibernate.cache.access.AccessType;
+import org.hibernate.cache.access.CollectionRegionAccessStrategy;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.gemstone.gemfire.cache.Region;
+import com.gemstone.gemfire.modules.hibernate.GemFireRegionFactory;
+
+public class GemFireCollectionRegion extends GemFireBaseRegion implements CollectionRegion {
+
+ private Logger log = LoggerFactory.getLogger(getClass());
+
+ public GemFireCollectionRegion(Region<Object, EntityWrapper> region,
+ boolean isClient, CacheDataDescription metadata,
+ GemFireRegionFactory regionFactory) {
+ super(region, isClient, metadata, regionFactory);
+ }
+
+ @Override
+ public boolean isTransactionAware() {
+ // TODO Auto-generated method stub
+ return false;
+ }
+
+ @Override
+ public CacheDataDescription getCacheDataDescription() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public CollectionRegionAccessStrategy buildAccessStrategy(
+ AccessType accessType) throws CacheException {
+ log.debug("creating collection access for region:"+this.region.getName());
+ return new CollectionAccess(this);
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/f6c4c2f9/extensions/geode-modules-hibernate/src/main/java/com/gemstone/gemfire/modules/hibernate/internal/GemFireEntityRegion.java
----------------------------------------------------------------------
diff --git a/extensions/geode-modules-hibernate/src/main/java/com/gemstone/gemfire/modules/hibernate/internal/GemFireEntityRegion.java b/extensions/geode-modules-hibernate/src/main/java/com/gemstone/gemfire/modules/hibernate/internal/GemFireEntityRegion.java
new file mode 100644
index 0000000..22ac466
--- /dev/null
+++ b/extensions/geode-modules-hibernate/src/main/java/com/gemstone/gemfire/modules/hibernate/internal/GemFireEntityRegion.java
@@ -0,0 +1,187 @@
+/*
+* 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.hibernate.internal;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+import java.util.concurrent.ExecutorService;
+
+import org.hibernate.cache.CacheDataDescription;
+import org.hibernate.cache.CacheException;
+import org.hibernate.cache.EntityRegion;
+import org.hibernate.cache.access.AccessType;
+import org.hibernate.cache.access.EntityRegionAccessStrategy;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.gemstone.gemfire.cache.Region;
+import com.gemstone.gemfire.distributed.DistributedSystem;
+import com.gemstone.gemfire.internal.cache.LocalRegion;
+import com.gemstone.gemfire.modules.hibernate.GemFireRegionFactory;
+import com.gemstone.gemfire.modules.util.ModuleStatistics;
+
+public class GemFireEntityRegion extends GemFireBaseRegion implements EntityRegion {
+
+ private final Logger log = LoggerFactory.getLogger(getClass());
+
+ private final boolean USE_JTA = Boolean.getBoolean("gemfiremodules.useJTA");
+
+ /**
+ * keys for which interest has been registered already
+ */
+ private ConcurrentMap<Object, Boolean> registeredKeys = new ConcurrentHashMap<Object, Boolean>();
+
+ /**
+ * map to store the entries that were pre-fetched when the underlying region has no local storage
+ */
+ protected ConcurrentMap<Object, EntityWrapper> preFetchMap = new ConcurrentHashMap<Object, EntityWrapper>();
+
+ public GemFireEntityRegion(Region<Object, EntityWrapper> region,
+ boolean isClient, CacheDataDescription metadata, GemFireRegionFactory regionFactory) {
+ super(region, isClient, metadata, regionFactory);
+ }
+
+ @Override
+ public boolean isTransactionAware() {
+ // there are no colocation guarantees while using hibernate
+ // so return false for a PartitionedRegion for now
+ if (USE_JTA) {
+ return true;
+ }
+ return false;
+ }
+
+ @Override
+ public CacheDataDescription getCacheDataDescription() {
+ return this.metadata;
+ }
+
+ @Override
+ public EntityRegionAccessStrategy buildAccessStrategy(AccessType accessType)
+ throws CacheException {
+ if (AccessType.READ_ONLY.equals(accessType)) {
+ log.info("creating read-only access for region: " + this.getName());
+ return new ReadOnlyAccess(this);
+ }
+ else if (AccessType.NONSTRICT_READ_WRITE.equals(accessType)) {
+ log.info("creating nonstrict-read-write access for region: "
+ + this.getName());
+ return new NonStrictReadWriteAccess(this);
+ }
+ else if (AccessType.READ_WRITE.equals(accessType)) {
+ log.info("creating read-write access for region: "
+ + this.getName());
+ return new ReadWriteAccess(this);
+ }
+ else if (AccessType.TRANSACTIONAL.equals(accessType)) {
+ log.info("creating transactional access for region: "
+ + this.getName());
+ return new TransactionalAccess(this);
+ }
+ throw new UnsupportedOperationException("Unknown access type: "
+ + accessType);
+ }
+
+ /**
+ * Should this region should register interest in keys.
+ * @return true for client regions with storage
+ */
+ public boolean isRegisterInterestRequired() {
+ return this.isClientRegion && this.region.getAttributes().getDataPolicy().withStorage();
+ }
+
+ /**
+ * register interest in this key, if not already registered
+ * @param key
+ */
+ public void registerInterest(Object key) {
+ if (!this.registeredKeys.containsKey(key)) {
+ this.region.registerInterest(key);
+ this.registeredKeys.put(key, Boolean.TRUE);
+ log.debug("registered interest in key{}", key);
+ }
+ }
+
+ public void registerInterest(Collection<?> list) {
+ // build a list of keys for which interest is not
+ // already registered
+ List<Object> interestList = new ArrayList<Object>();
+ for (Object o : list) {
+ if (!this.registeredKeys.containsKey(o)) {
+ interestList.add(o);
+ }
+ }
+ // register interest in this list
+ this.region.registerInterest(interestList);
+ log.debug("registered interest in {} keys", interestList.size());
+ }
+
+ /**
+ * wraps the keys in {@link KeyWrapper} and calls getAll
+ * on the underlying GemFire region. When the underlying region
+ * is a proxy region, the fetched entries are stored in a local
+ * map.
+ * @param keys
+ */
+ public void getAll(Collection<?> keys) {
+ Set<KeyWrapper> wrappedKeys = new HashSet<KeyWrapper>();
+ for (Object o : keys) {
+ wrappedKeys.add(new KeyWrapper(o));
+ }
+ if (isRegisterInterestRequired()) {
+ registerInterest(wrappedKeys);
+ } else {
+ Map<Object, EntityWrapper> retVal = this.region.getAll(wrappedKeys);
+ putInLocalMap(retVal);
+ }
+ }
+
+ /**
+ * if the underlying gemfire region does not have local storage, put
+ * the pre-fetched entries in {@link #preFetchMap}
+ * @param map map of prefetched entries
+ */
+ private void putInLocalMap(Map<Object, EntityWrapper> map) {
+ if (!this.region.getAttributes().getDataPolicy().withStorage()) {
+ // if the value is null, do not cache in preFetchMap
+ for (Entry<Object, EntityWrapper> e : map.entrySet()) {
+ if (e.getValue() != null) {
+ this.preFetchMap.put(e.getKey(), e.getValue());
+ log.debug("putting key: {} value: {} in local map", e.getKey(), e.getValue());
+ }
+ }
+ }
+ }
+
+ /**
+ * If this key was pre-fetched, get the entity.
+ * @param key
+ * @return the prefetched entity
+ */
+ public EntityWrapper get(Object key) {
+ return this.preFetchMap.remove(key);
+ }
+}
+
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/f6c4c2f9/extensions/geode-modules-hibernate/src/main/java/com/gemstone/gemfire/modules/hibernate/internal/GemFireQueryResultsRegion.java
----------------------------------------------------------------------
diff --git a/extensions/geode-modules-hibernate/src/main/java/com/gemstone/gemfire/modules/hibernate/internal/GemFireQueryResultsRegion.java b/extensions/geode-modules-hibernate/src/main/java/com/gemstone/gemfire/modules/hibernate/internal/GemFireQueryResultsRegion.java
new file mode 100644
index 0000000..ce06b85
--- /dev/null
+++ b/extensions/geode-modules-hibernate/src/main/java/com/gemstone/gemfire/modules/hibernate/internal/GemFireQueryResultsRegion.java
@@ -0,0 +1,113 @@
+/*
+* 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.hibernate.internal;
+
+import java.util.Collections;
+import java.util.Map;
+
+import org.hibernate.cache.CacheException;
+import org.hibernate.cache.QueryResultsRegion;
+import org.hibernate.cache.Timestamper;
+import org.hibernate.cache.TimestampsRegion;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.gemstone.gemfire.cache.EntryNotFoundException;
+import com.gemstone.gemfire.cache.Region;
+
+public class GemFireQueryResultsRegion implements QueryResultsRegion, TimestampsRegion {
+
+ private final Region region;
+
+ private Logger log = LoggerFactory.getLogger(getClass());
+
+ public GemFireQueryResultsRegion(Region region) {
+ this.region = region;
+ }
+
+ @Override
+ public Object get(Object key) throws CacheException {
+ log.debug("get query results for {} ", key);
+ return this.region.get(key);
+ }
+
+ @Override
+ public void put(Object key, Object value) throws CacheException {
+ log.debug("For key {} putting query results {} ", key, value);
+ this.region.put(key, value);
+ }
+
+ @Override
+ public void evict(Object key) throws CacheException {
+ log.debug("removing query results for key {}", key);
+ this.region.remove(key);
+ }
+
+ @Override
+ public void evictAll() throws CacheException {
+ log.debug("clearing the query cache");
+ this.region.clear();
+ }
+
+ @Override
+ public String getName() {
+ return this.region.getName();
+ }
+
+ @Override
+ public void destroy() throws CacheException {
+ if (!this.region.isDestroyed()) {
+ this.region.destroyRegion();
+ }
+ }
+
+ @Override
+ public boolean contains(Object key) {
+ return this.region.containsKey(key);
+ }
+
+ @Override
+ public long getSizeInMemory() {
+ return -1;
+ }
+
+ @Override
+ public long getElementCountInMemory() {
+ return this.region.size();
+ }
+
+ @Override
+ public long getElementCountOnDisk() {
+ // TODO make this an overflow region
+ return -1;
+ }
+
+ @Override
+ public Map toMap() {
+ return Collections.unmodifiableMap(this.region);
+ }
+
+ @Override
+ public long nextTimestamp() {
+ return Timestamper.next();
+ }
+
+ @Override
+ public int getTimeout() {
+ return 60*1000; // all other cache providers have same value
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/f6c4c2f9/extensions/geode-modules-hibernate/src/main/java/com/gemstone/gemfire/modules/hibernate/internal/KeyWrapper.java
----------------------------------------------------------------------
diff --git a/extensions/geode-modules-hibernate/src/main/java/com/gemstone/gemfire/modules/hibernate/internal/KeyWrapper.java b/extensions/geode-modules-hibernate/src/main/java/com/gemstone/gemfire/modules/hibernate/internal/KeyWrapper.java
new file mode 100644
index 0000000..c321076
--- /dev/null
+++ b/extensions/geode-modules-hibernate/src/main/java/com/gemstone/gemfire/modules/hibernate/internal/KeyWrapper.java
@@ -0,0 +1,93 @@
+/*
+* 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.hibernate.internal;
+
+import java.io.DataInput;
+import java.io.DataOutput;
+import java.io.IOException;
+import java.io.Serializable;
+
+import org.hibernate.cache.CacheKey;
+
+import com.gemstone.gemfire.DataSerializable;
+import com.gemstone.gemfire.DataSerializer;
+
+/**
+ * wraps {@link CacheKey}, and implements equals and
+ * hashCode. This is required for register interest
+ * operation/prefetching
+ * @author sbawaska
+ *
+ */
+public class KeyWrapper implements DataSerializable {
+
+ private Serializable key;
+ private String entityName;
+
+ private static final String separator = "#";
+
+ public KeyWrapper() {
+ }
+
+ public KeyWrapper(Object p_key) {
+ if (p_key instanceof String) {
+ String stringKey = (String)p_key;
+ this.key = stringKey.substring(stringKey.indexOf(separator)+1);
+ this.entityName = stringKey.substring(0, stringKey.indexOf(separator));
+ } else {
+ CacheKey cacheKey = (CacheKey)p_key;
+ this.key = cacheKey.getKey();
+ this.entityName = cacheKey.getEntityOrRoleName();
+ }
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj instanceof KeyWrapper) {
+ KeyWrapper other = (KeyWrapper)obj;
+ if (this.key.toString().equals(other.key.toString())
+ && this.entityName.equals(other.entityName)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public int hashCode() {
+ return this.key.toString().hashCode() + this.entityName.hashCode();
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder();
+ sb.append(this.entityName).append(separator).append(this.key);
+ return sb.toString();
+ }
+
+ @Override
+ public void toData(DataOutput out) throws IOException {
+ DataSerializer.writeObject(this.key, out);
+ out.writeUTF(this.entityName);
+ }
+
+ @Override
+ public void fromData(DataInput in) throws IOException, ClassNotFoundException {
+ this.key = DataSerializer.readObject(in);
+ this.entityName = in.readUTF();
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/f6c4c2f9/extensions/geode-modules-hibernate/src/main/java/com/gemstone/gemfire/modules/hibernate/internal/NonStrictReadWriteAccess.java
----------------------------------------------------------------------
diff --git a/extensions/geode-modules-hibernate/src/main/java/com/gemstone/gemfire/modules/hibernate/internal/NonStrictReadWriteAccess.java b/extensions/geode-modules-hibernate/src/main/java/com/gemstone/gemfire/modules/hibernate/internal/NonStrictReadWriteAccess.java
new file mode 100644
index 0000000..ad617e4
--- /dev/null
+++ b/extensions/geode-modules-hibernate/src/main/java/com/gemstone/gemfire/modules/hibernate/internal/NonStrictReadWriteAccess.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.hibernate.internal;
+
+import org.hibernate.cache.CacheException;
+import org.hibernate.cache.access.SoftLock;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class NonStrictReadWriteAccess extends Access {
+
+ private Logger log = LoggerFactory.getLogger(getClass());
+
+ public NonStrictReadWriteAccess(GemFireEntityRegion region) {
+ super(region);
+ }
+
+ @Override
+ public SoftLock lockItem(Object key, Object version) throws CacheException {
+ log.debug("lock item called for key {}", key);
+ return null;
+ }
+
+ @Override
+ public boolean afterUpdate(Object key, Object value, Object currentVersion,
+ Object previousVersion, SoftLock lock) throws CacheException {
+ log.debug("after update called for key: {} value: {}", key, value);
+ getGemFireRegion().put(getWrappedKey(key), new EntityWrapper(value, -1L));
+ return true;
+ }
+
+ @Override
+ public boolean update(Object key, Object value, Object currentVersion,
+ Object previousVersion) throws CacheException {
+ log.debug("updating key: {} value: {}", key, value);
+ getGemFireRegion().put(getWrappedKey(key), new EntityWrapper(value, -1L));
+ return true;
+ }
+//
+// @Override
+// public boolean insert(Object key, Object value, Object version)
+// throws CacheException {
+// log.debug("inserting key:{} value:{}", key, value);
+// getGemFireRegion().put(key, new EntityWrapper(value, -1L));
+// return true;
+// }
+//
+// @Override
+// public boolean afterInsert(Object key, Object value, Object version)
+// throws CacheException {
+// log.debug("after insert called for key:{} value:{}", key, value);
+// getGemFireRegion().put(key, new EntityWrapper(value, -1L));
+// return true;
+// }
+//
+ @Override
+ public boolean putFromLoad(Object key, Object value, long txTimestamp,
+ Object version) throws CacheException {
+ return putFromLoad(key, value, txTimestamp, version, true);
+ }
+
+ @Override
+ public boolean putFromLoad(Object key, Object value, long txTimestamp,
+ Object version, boolean minimalPutOverride) throws CacheException {
+ log.debug("putting a new entry from load key:{} value:{}", key, value);
+ getGemFireRegion().put(getWrappedKey(key), new EntityWrapper(value, -1L));
+ return true;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/f6c4c2f9/extensions/geode-modules-hibernate/src/main/java/com/gemstone/gemfire/modules/hibernate/internal/ReadOnlyAccess.java
----------------------------------------------------------------------
diff --git a/extensions/geode-modules-hibernate/src/main/java/com/gemstone/gemfire/modules/hibernate/internal/ReadOnlyAccess.java b/extensions/geode-modules-hibernate/src/main/java/com/gemstone/gemfire/modules/hibernate/internal/ReadOnlyAccess.java
new file mode 100644
index 0000000..6f54067
--- /dev/null
+++ b/extensions/geode-modules-hibernate/src/main/java/com/gemstone/gemfire/modules/hibernate/internal/ReadOnlyAccess.java
@@ -0,0 +1,55 @@
+/*
+* 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.hibernate.internal;
+
+import org.hibernate.cache.CacheException;
+import org.hibernate.cache.access.SoftLock;
+
+public class ReadOnlyAccess extends Access {
+
+ public ReadOnlyAccess(GemFireEntityRegion region) {
+ super(region);
+ }
+
+ @Override
+ public boolean insert(Object key, Object value, Object version)
+ throws CacheException {
+ throw new UnsupportedOperationException(
+ "insert not supported on read only access");
+ }
+
+ @Override
+ public boolean update(Object key, Object value, Object currentVersion,
+ Object previousVersion) throws CacheException {
+ throw new UnsupportedOperationException(
+ "update not supported on read only access");
+ }
+
+ @Override
+ public boolean afterInsert(Object key, Object value, Object version)
+ throws CacheException {
+ throw new UnsupportedOperationException(
+ "insert not supported on read only access");
+ }
+
+ @Override
+ public boolean afterUpdate(Object key, Object value, Object currentVersion,
+ Object previousVersion, SoftLock lock) throws CacheException {
+ throw new UnsupportedOperationException(
+ "update not supported on read only access");
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/f6c4c2f9/extensions/geode-modules-hibernate/src/main/java/com/gemstone/gemfire/modules/hibernate/internal/ReadWriteAccess.java
----------------------------------------------------------------------
diff --git a/extensions/geode-modules-hibernate/src/main/java/com/gemstone/gemfire/modules/hibernate/internal/ReadWriteAccess.java b/extensions/geode-modules-hibernate/src/main/java/com/gemstone/gemfire/modules/hibernate/internal/ReadWriteAccess.java
new file mode 100644
index 0000000..3c80174
--- /dev/null
+++ b/extensions/geode-modules-hibernate/src/main/java/com/gemstone/gemfire/modules/hibernate/internal/ReadWriteAccess.java
@@ -0,0 +1,36 @@
+/*
+* 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.hibernate.internal;
+
+import org.hibernate.cache.CacheException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class ReadWriteAccess extends Access {
+
+ private Logger log = LoggerFactory.getLogger(getClass());
+
+ public ReadWriteAccess(GemFireEntityRegion region) {
+ super(region);
+ }
+
+ @Override
+ public boolean update(Object key, Object value, Object currentVersion,
+ Object previousVersion) throws CacheException {
+ return super.update(key, value, currentVersion, previousVersion);
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/f6c4c2f9/extensions/geode-modules-hibernate/src/main/java/com/gemstone/gemfire/modules/hibernate/internal/RegionFactoryDelegate.java
----------------------------------------------------------------------
diff --git a/extensions/geode-modules-hibernate/src/main/java/com/gemstone/gemfire/modules/hibernate/internal/RegionFactoryDelegate.java b/extensions/geode-modules-hibernate/src/main/java/com/gemstone/gemfire/modules/hibernate/internal/RegionFactoryDelegate.java
new file mode 100644
index 0000000..76fdf77
--- /dev/null
+++ b/extensions/geode-modules-hibernate/src/main/java/com/gemstone/gemfire/modules/hibernate/internal/RegionFactoryDelegate.java
@@ -0,0 +1,153 @@
+/*
+* 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.hibernate.internal;
+
+import java.util.Iterator;
+import java.util.Properties;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.gemstone.gemfire.cache.Cache;
+import com.gemstone.gemfire.cache.CacheFactory;
+import com.gemstone.gemfire.cache.DataPolicy;
+import com.gemstone.gemfire.cache.GemFireCache;
+import com.gemstone.gemfire.cache.Region;
+import com.gemstone.gemfire.cache.RegionShortcut;
+import com.gemstone.gemfire.cache.client.ClientRegionShortcut;
+import com.gemstone.gemfire.cache.execute.FunctionService;
+import com.gemstone.gemfire.internal.cache.GemFireCacheImpl;
+import com.gemstone.gemfire.modules.hibernate.GemFireCacheProvider;
+import com.gemstone.gemfire.modules.util.BootstrappingFunction;
+import com.gemstone.gemfire.modules.util.CreateRegionFunction;
+import com.gemstone.gemfire.modules.util.RegionConfiguration;
+
+public class RegionFactoryDelegate {
+
+ private static final String LOG_FILE = "log-file";
+
+ private static final String CACHE_XML_FILE = "cache-xml-file";
+
+ private static final String DEFAULT_REGION_TYPE = RegionShortcut.REPLICATE_HEAP_LRU.name();
+
+ private static final String CLIENT_DEFAULT_REGION_TYPE = ClientRegionShortcut.PROXY.name();
+
+ protected final Properties gemfireProperties;
+ protected final Properties regionProperties;
+
+ protected Logger log = LoggerFactory.getLogger(getClass());
+
+ private Cache cache;
+
+ public RegionFactoryDelegate(Properties gemfireProperties, Properties regionProperties) {
+ this.gemfireProperties = gemfireProperties;
+ this.regionProperties = regionProperties;
+ }
+
+ public GemFireCache startCache() {
+ log.info("Creating a GemFire cache");
+ checkExistingCache();
+ cache = new CacheFactory(gemfireProperties).create();
+ log.debug("GemFire cache creation completed");
+ FunctionService.onMembers(this.cache.getDistributedSystem()).execute(new BootstrappingFunction()).getResult();
+ FunctionService.registerFunction(new CreateRegionFunction(cache));
+ return cache;
+ }
+
+ /**
+ * When hibernate module is running within servlet container, we should
+ * check if http module is being used and make sure that we use
+ * same cache-xml and log-file properties.
+ */
+ protected void checkExistingCache() {
+ Cache existingCache = GemFireCacheImpl.getInstance();
+ if (existingCache == null) {
+ return;
+ }
+ Properties existingProps = existingCache.getDistributedSystem().getProperties();
+ String cacheXML = existingProps.getProperty(CACHE_XML_FILE);
+ String logFile = existingProps.getProperty(LOG_FILE, "");
+ this.gemfireProperties.setProperty(CACHE_XML_FILE, cacheXML);
+ this.gemfireProperties.setProperty(LOG_FILE, logFile);
+ log.info("Existing GemFire cache detected. Using same "+CACHE_XML_FILE+":"+cacheXML+
+ " and "+LOG_FILE+":"+logFile+" as existing cache");
+ }
+
+ public Region<Object, EntityWrapper> createRegion(String regionName) {
+ Region<Object, EntityWrapper> r = cache.getRegion(regionName);
+ if (r != null) {
+ // for the peer-to-peer case, for now we assume that
+ // cache.xml will be the same for all peers
+ // TODO validate regions without this assumption
+ return r;
+ }
+ String regionType = getRegionType(regionName);
+ boolean isLocalRegion = regionType.contains("LOCAL") ? true : false;
+ RegionConfiguration regionConfig = new RegionConfiguration();
+ regionConfig.setRegionName(regionName);
+ regionConfig.setRegionAttributesId(regionType);
+ regionConfig.setCacheWriterName(EntityRegionWriter.class.getCanonicalName());
+ com.gemstone.gemfire.cache.RegionFactory<Object, EntityWrapper> rFactory = this.cache
+ .createRegionFactory(RegionShortcut.valueOf(regionType));
+ rFactory.setCacheWriter(new EntityRegionWriter());
+ if (isLocalRegion) {
+ rFactory.setDataPolicy(DataPolicy.REPLICATE);
+ }
+ r = rFactory.create(regionName);
+ // create same region on peers
+ if (!isLocalRegion) {
+ FunctionService.onMembers(this.cache.getDistributedSystem())
+ .withArgs(regionConfig).execute(CreateRegionFunction.ID).getResult();
+ }
+ return r;
+ }
+
+ /**
+ * returns the type of region to create by consulting the properties specified
+ * in hibernate.cfg.xml
+ *
+ * @see #createRegion(String)
+ * @param regionName
+ * @return string representation of {@link RegionShortcut}
+ * @see GemFireCacheProvider
+ */
+ protected String getRegionType(String regionName) {
+ String rType = getOverridenRegionType(regionName);
+ if (rType != null) {
+ return rType.toUpperCase();
+ }
+ rType = regionProperties
+ .getProperty("gemfire.default-region-attributes-id");
+ if (rType == null) {
+ rType = DEFAULT_REGION_TYPE;
+ }
+ return rType.toUpperCase();
+ }
+
+ private String getOverridenRegionType(String regionName) {
+ String rType = null;
+ Iterator<Object> it = regionProperties.keySet().iterator();
+ while (it.hasNext()) {
+ String current = (String)it.next();
+ if (current.contains(regionName)) {
+ rType = regionProperties.getProperty(current);
+ break;
+ }
+ }
+ return rType;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/f6c4c2f9/extensions/geode-modules-hibernate/src/main/java/com/gemstone/gemfire/modules/hibernate/internal/TransactionalAccess.java
----------------------------------------------------------------------
diff --git a/extensions/geode-modules-hibernate/src/main/java/com/gemstone/gemfire/modules/hibernate/internal/TransactionalAccess.java b/extensions/geode-modules-hibernate/src/main/java/com/gemstone/gemfire/modules/hibernate/internal/TransactionalAccess.java
new file mode 100644
index 0000000..f12eab9
--- /dev/null
+++ b/extensions/geode-modules-hibernate/src/main/java/com/gemstone/gemfire/modules/hibernate/internal/TransactionalAccess.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.hibernate.internal;
+
+public class TransactionalAccess extends Access {
+
+ public TransactionalAccess(GemFireEntityRegion region) {
+ super(region);
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/f6c4c2f9/extensions/geode-modules-hibernate/src/test/java/com/gemstone/gemfire/modules/Event.java
----------------------------------------------------------------------
diff --git a/extensions/geode-modules-hibernate/src/test/java/com/gemstone/gemfire/modules/Event.java b/extensions/geode-modules-hibernate/src/test/java/com/gemstone/gemfire/modules/Event.java
new file mode 100644
index 0000000..962c083
--- /dev/null
+++ b/extensions/geode-modules-hibernate/src/test/java/com/gemstone/gemfire/modules/Event.java
@@ -0,0 +1,67 @@
+/*
+* 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;
+
+import java.util.Date;
+
+public class Event {
+ private Long id;
+
+ private String title;
+ private Date date;
+ private int i;
+
+ public Event() {}
+
+ public Long getId() {
+ return id;
+ }
+
+ private void setId(Long id) {
+ this.id = id;
+ }
+
+ public Date getDate() {
+ return date;
+ }
+
+ public Integer getVersion() {
+ return i;
+ }
+
+ public void setVersion(int i) {
+ this.i = i;
+ }
+
+ public void setDate(Date date) {
+ this.date = date;
+ }
+
+ public String getTitle() {
+ return title;
+ }
+
+ public void setTitle(String title) {
+ this.title = title;
+ }
+ @Override
+ public String toString() {
+ StringBuilder b = new StringBuilder();
+ b.append("Event:id:"+id+" title:"+title+" date:"+date);
+ return b.toString();
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/f6c4c2f9/extensions/geode-modules-hibernate/src/test/java/com/gemstone/gemfire/modules/HibernateJUnitTest.java
----------------------------------------------------------------------
diff --git a/extensions/geode-modules-hibernate/src/test/java/com/gemstone/gemfire/modules/HibernateJUnitTest.java b/extensions/geode-modules-hibernate/src/test/java/com/gemstone/gemfire/modules/HibernateJUnitTest.java
new file mode 100644
index 0000000..9a86f10
--- /dev/null
+++ b/extensions/geode-modules-hibernate/src/test/java/com/gemstone/gemfire/modules/HibernateJUnitTest.java
@@ -0,0 +1,410 @@
+/*
+* 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;
+
+import com.gemstone.gemfire.cache.Region;
+import com.gemstone.gemfire.cache.Region.Entry;
+import com.gemstone.gemfire.internal.cache.GemFireCacheImpl;
+import com.gemstone.gemfire.modules.Owner.Status;
+import com.gemstone.gemfire.test.junit.categories.IntegrationTest;
+import org.hibernate.Query;
+import org.hibernate.Session;
+import org.hibernate.SessionFactory;
+import org.hibernate.cfg.AnnotationConfiguration;
+import org.hibernate.cfg.Configuration;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.File;
+import java.sql.Connection;
+import java.sql.DriverManager;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.Date;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Properties;
+import java.util.logging.Level;
+
+import static org.junit.Assert.assertEquals;
+
+@Category(IntegrationTest.class)
+public class HibernateJUnitTest {
+
+ private Logger log = LoggerFactory.getLogger(getClass());
+
+ //private static final String jdbcURL = "jdbc:hsqldb:hsql://localhost/test";
+ private static final String jdbcURL = "jdbc:hsqldb:mem:test";
+
+ static File tmpDir;
+
+ static String gemfireLog;
+
+ @Before
+ public void setUp() throws Exception {
+ // Create a per-user scratch directory
+ tmpDir = new File(System.getProperty("java.io.tmpdir"),
+ "gemfire_modules-" + System.getProperty("user.name"));
+ tmpDir.mkdirs();
+ tmpDir.deleteOnExit();
+
+ gemfireLog = tmpDir.getPath() +
+ System.getProperty("file.separator") + "gemfire_modules.log";
+ }
+
+ public static SessionFactory getSessionFactory(Properties overrideProps) {
+ System.setProperty("gemfire.home", "GEMFIREHOME");
+ Configuration cfg = new Configuration();
+ cfg.setProperty("hibernate.dialect", "org.hibernate.dialect.HSQLDialect");
+ cfg.setProperty("hibernate.connection.driver_class",
+ "org.hsqldb.jdbcDriver");
+ // cfg.setProperty("hibernate.connection.url", "jdbc:hsqldb:mem:test");
+ cfg.setProperty("hibernate.connection.url", jdbcURL);
+ cfg.setProperty("hibernate.connection.username", "sa");
+ cfg.setProperty("hibernate.connection.password", "");
+ cfg.setProperty("hibernate.connection.pool_size", "1");
+ cfg.setProperty("hibernate.connection.autocommit", "true");
+ cfg.setProperty("hibernate.hbm2ddl.auto", "update");
+
+ cfg.setProperty("hibernate.cache.region.factory_class",
+ "com.gemstone.gemfire.modules.hibernate.GemFireRegionFactory");
+ cfg.setProperty("hibernate.show_sql", "true");
+ cfg.setProperty("hibernate.cache.use_query_cache", "true");
+ //cfg.setProperty("gemfire.mcast-port", AvailablePort.getRandomAvailablePort(AvailablePort.JGROUPS)+"");
+ cfg.setProperty("gemfire.mcast-port", "0");
+ cfg.setProperty("gemfire.statistic-sampling-enabled", "true");
+ cfg.setProperty("gemfire.log-file", gemfireLog);
+ cfg.setProperty("gemfire.writable-working-dir", tmpDir.getPath());
+ //cfg.setProperty("gemfire.statistic-archive-file", "plugin-stats-file.gfs");
+ //cfg.setProperty("gemfire.default-client-region-attributes-id", "CACHING_PROXY");
+ //cfg.setProperty("gemfire.cache-topology", "client-server");
+ //cfg.setProperty("gemfire.locators", "localhost[5432]");
+ //cfg.setProperty("gemfire.log-level", "fine");
+ // cfg.setProperty("", "");
+ cfg.addClass(Person.class);
+ cfg.addClass(Event.class);
+ if (overrideProps != null) {
+ Iterator it = overrideProps.keySet().iterator();
+ while (it.hasNext()) {
+ String key = (String)it.next();
+ cfg.setProperty(key, overrideProps.getProperty(key));
+ }
+ }
+ return cfg.buildSessionFactory();
+ }
+
+ @Test
+ public void testpreload() {
+ log.info("SWAP:creating session factory In hibernateTestCase");
+
+ Session session = getSessionFactory(null).openSession();
+ log.info("SWAP:session opened");
+ session.beginTransaction();
+ Event theEvent = new Event();
+ theEvent.setTitle("title");
+ theEvent.setDate(new Date());
+ session.save(theEvent);
+ Long id = theEvent.getId();
+ session.getTransaction().commit();
+ session.beginTransaction();
+ Event ev = (Event)session.get(Event.class, id);
+ log.info("SWAP:load complete: " + ev);
+ session.getTransaction().commit();
+ }
+
+ @Test
+ public void testNothing() throws Exception {
+ java.util.logging.Logger.getLogger("org.hibernate").setLevel(Level.ALL);
+ log.info("SWAP:creating session factory In hibernateTestCase");
+
+ Session session = getSessionFactory(null).openSession();
+ log.info("SWAP:session opened");
+ // session.setFlushMode(FlushMode.COMMIT);
+ session.beginTransaction();
+ Event theEvent = new Event();
+ theEvent.setTitle("title");
+ theEvent.setDate(new Date());
+ //session.save(theEvent);
+ session.persist(theEvent);
+ Long id = theEvent.getId();
+ session.getTransaction().commit();
+ log.info("commit complete...doing load");
+ session.beginTransaction();
+ Event ev = (Event)session.load(Event.class, id);
+ log.info("load complete: " + ev);
+ log.trace("SWAP");
+ ev.setTitle("newTitle");
+ session.save(ev);
+ log.info("commit");
+ session.getTransaction().commit();
+ log.info("save complete " + ev);
+
+ session.beginTransaction();
+ ev = (Event)session.load(Event.class, id);
+ log.info("load complete: " + ev);
+ ev.setTitle("newTitle2");
+ session.save(ev);
+ log.info("commit");
+ session.getTransaction().commit();
+ log.info("save complete " + ev);
+
+ ev = (Event)session.load(Event.class, id);
+ log.info("second load " + ev);
+ session.flush();
+ session.close();
+ log.info("flush complete session:" + session);
+
+ for (int i=0; i<5; i++) {
+ session = getSessionFactory(null).openSession();
+ log.info("doing get "+id);
+ // ev = (Event) session.load(Event.class, id);
+ ev = (Event)session.get(Event.class, id);
+ log.info("third load " + ev);
+ }
+ printExistingDB();
+ Iterator it = GemFireCacheImpl.getInstance().rootRegions().iterator();
+ while (it.hasNext()) {
+ Region r = (Region)it.next();
+ System.out.println("Region:"+r);
+ Iterator enIt = r.entrySet().iterator();
+ while (enIt.hasNext()) {
+ Region.Entry re = (Entry)enIt.next();
+ System.out.println("key:"+re.getKey()+" value:"+re.getValue());
+ }
+ }
+ Thread.sleep(3000);
+ //System.in.read();
+ // try direct data
+
+ }
+
+ public void _testInvalidation() {
+ Session s = getSessionFactory(null).openSession();
+ }
+
+ static Long personId;
+
+ @Test
+ public void testRelationship() throws Exception {
+ //java.util.logging.Logger.getLogger("org.hibernate").setLevel(Level.ALL);
+ Properties props = new Properties();
+ props.put("gemfire.topology", "client-server");
+ Session session = getSessionFactory(null).openSession();
+ session.beginTransaction();
+
+ Person thePerson = new Person();
+ thePerson.setFirstname("foo");
+ thePerson.setLastname("bar");
+ thePerson.setAge(1);
+ thePerson.setId(99L);
+ session.save(thePerson);
+ personId = thePerson.getId();
+ log.info("person saved");
+
+ Event theEvent = new Event();
+ theEvent.setTitle("title");
+ theEvent.setDate(new Date());
+ session.save(theEvent);
+ Long eventId = theEvent.getId();
+ log.info("event saved");
+
+ Event theEvent2 = new Event();
+ theEvent2.setTitle("title2");
+ theEvent2.setDate(new Date());
+ session.save(theEvent2);
+ Long eventId2 = theEvent2.getId();
+ log.info("event2 saved");
+ session.getTransaction().commit();
+
+ session.beginTransaction();
+ Person aPerson = (Person) session.load(Person.class, personId);
+ Event anEvent = (Event) session.load(Event.class, eventId);
+ Event anEvent2 = (Event) session.load(Event.class, eventId2);
+ log.info("adding event to person");
+ aPerson.getE().add(anEvent);
+ aPerson.getE().add(anEvent2);
+ log.info("calling commit");
+
+ session.getTransaction().commit();
+ log.info("commit complete");
+ session.close();
+ log.info("opening new session");
+ session = getSessionFactory(null).openSession();
+ log.info("SWAP:loading person");
+ aPerson = (Person)session.load(Person.class, personId);
+ log.info("loading events");
+ Iterator<Event> e = aPerson.getE().iterator();
+ while (e.hasNext()) {
+ e.next();
+ }
+ session.close();
+ log.info("opening new session");
+ session = getSessionFactory(null).openSession();
+ log.info("SWAP:loading person");
+ aPerson = (Person)session.load(Person.class, personId);
+ log.info("loading events");
+ e = aPerson.getE().iterator();
+ while (e.hasNext()) {
+ e.next();
+ }
+
+ log.info(aPerson.getE()+"");
+ session.close();
+ //System.in.read();
+// log.info("opening third session");
+// session = getSessionFactory().openSession();
+// log.info("loading person");
+// aPerson = (Person)session.load(Person.class, personId);
+// log.info("loading events");
+// log.info(aPerson.getEvents()+"");
+ }
+
+ public void _testQueryCache() throws Exception {
+ Session session = getSessionFactory(null).openSession();
+ Query q = session.createQuery("from Event");
+ q.setCacheable(true);
+ List l = q.list();
+ log.info("list:"+l);
+// log.info("Sleeping for 10 seconds");
+// Thread.sleep(10000);
+ l = q.list();
+ log.info("list2:"+l);
+ log.info("updating an event");
+ session.beginTransaction();
+ Event e = (Event)l.get(0);
+ e.setDate(new Date());
+ session.saveOrUpdate(e);
+ session.getTransaction().commit();
+ l = q.list();
+ log.info("list3:"+l);
+ }
+
+ @Test
+ public void testInsert() {
+ Session session = getSessionFactory(null).openSession();
+ Region r = GemFireCacheImpl.getExisting().getRegion(Person.class.getCanonicalName());
+ int initSize = r.size();
+ session.beginTransaction();
+ log.info("SWAP: Saving Person");
+ Person p = new Person();
+ p.setId(10L);
+ p.setFirstname("foo");
+ p.setLastname("bar");
+ session.saveOrUpdate("Person", p);
+ session.getTransaction().commit();
+ assertEquals(1, session.getStatistics().getEntityCount());
+ assertEquals(initSize+1, r.size());
+
+ session.beginTransaction();
+ p.setAge(1);
+ session.saveOrUpdate(p);
+ session.getTransaction().commit();
+ assertEquals(1, session.getStatistics().getEntityCount());
+ }
+
+ @Test
+ public void testNormalRegion() {
+ Properties props = new Properties();
+ props.setProperty("gemfire.default-region-attributes-id", "LOCAL");
+ Session session = getSessionFactory(props).openSession();
+ session.beginTransaction();
+ Event theEvent = new Event();
+ theEvent.setTitle("title");
+ theEvent.setDate(new Date());
+ session.save(theEvent);
+ Long id = theEvent.getId();
+ session.getTransaction().commit();
+ session.beginTransaction();
+ Event ev = (Event)session.load(Event.class, id);
+ ev.setTitle("newTitle");
+ session.save(ev);
+ session.getTransaction().commit();
+ }
+
+ private void printExistingDB() throws SQLException {
+ try {
+ Class.forName("org.hsqldb.jdbc.JDBCDriver");
+ }
+ catch (Exception e) {
+ System.err.println("ERROR: failed to load HSQLDB JDBC driver.");
+ e.printStackTrace();
+ return;
+ }
+
+ Connection c = DriverManager.getConnection(jdbcURL, "SA", "");
+ log.info("issuing query...");
+ ResultSet rs = c.createStatement().executeQuery("select * from events");
+ int col = rs.getMetaData().getColumnCount();
+ while (rs.next()) {
+ StringBuilder b = new StringBuilder();
+ for (int i = 1; i <= col; i++) {
+ b.append(" col:" + i + ":" + rs.getString(i));
+ }
+ log.info("Query result:" + b.toString());
+ }
+ }
+
+ @Test
+ public void testEnum() {
+ AnnotationConfiguration cfg = new AnnotationConfiguration();
+ cfg.addAnnotatedClass(Owner.class);
+ cfg.setProperty("hibernate.dialect", "org.hibernate.dialect.HSQLDialect");
+ cfg.setProperty("hibernate.connection.driver_class",
+ "org.hsqldb.jdbcDriver");
+ cfg.setProperty("hibernate.connection.url", jdbcURL);
+ cfg.setProperty("hibernate.connection.username", "sa");
+ cfg.setProperty("hibernate.connection.password", "");
+ cfg.setProperty("hibernate.connection.pool_size", "1");
+ cfg.setProperty("hibernate.connection.autocommit", "true");
+ cfg.setProperty("hibernate.hbm2ddl.auto", "update");
+
+ cfg.setProperty("hibernate.cache.region.factory_class",
+ "com.gemstone.gemfire.modules.hibernate.GemFireRegionFactory");
+ cfg.setProperty("hibernate.show_sql", "true");
+ cfg.setProperty("hibernate.cache.use_query_cache", "true");
+ cfg.setProperty("gemfire.statistic-sampling-enabled", "true");
+ cfg.setProperty("gemfire.log-file", gemfireLog);
+ cfg.setProperty("gemfire.writable-working-dir", tmpDir.getPath());
+ cfg.setProperty("gemfire.mcast-port", "0");
+ //cfg.setProperty("gemfire.cache-topology", "client-server");
+
+ SessionFactory sf = cfg.buildSessionFactory();
+ Session session = sf.openSession();
+ session.beginTransaction();
+ Owner o = new Owner();
+ o.setAddress("addr");
+ o.setCity("pdx");
+ o.setStatus(Status.PREMIUM);
+ session.save(o);
+ long id = o.getId();
+ log.info("testEnum:commiting tx");
+ session.getTransaction().commit();
+ session.close();
+
+ session = sf.openSession();
+ Owner o1 = (Owner) session.load(Owner.class, id);
+ log.info("loaded:"+o);
+ assertEquals(o.getAddress(), o1.getAddress());
+ assertEquals(o.getCity(), o1.getCity());
+ assertEquals(o.getStatus(), o1.getStatus());
+ o1.setAddress("address2");
+ session.save(o1);
+ }
+}