Hibernate SVN: r14106 - core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/timestamp.
by hibernate-commits@lists.jboss.org
Author: bstansberry(a)jboss.com
Date: 2007-10-18 23:13:41 -0400 (Thu, 18 Oct 2007)
New Revision: 14106
Modified:
core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/timestamp/TimestampsRegionImpl.java
Log:
Evict fixes
Modified: core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/timestamp/TimestampsRegionImpl.java
===================================================================
--- core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/timestamp/TimestampsRegionImpl.java 2007-10-19 03:13:13 UTC (rev 14105)
+++ core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/timestamp/TimestampsRegionImpl.java 2007-10-19 03:13:41 UTC (rev 14106)
@@ -32,7 +32,9 @@
import org.jboss.cache.config.Option;
import org.jboss.cache.notifications.annotation.CacheListener;
import org.jboss.cache.notifications.annotation.NodeModified;
+import org.jboss.cache.notifications.annotation.NodeRemoved;
import org.jboss.cache.notifications.event.NodeModifiedEvent;
+import org.jboss.cache.notifications.event.NodeRemovedEvent;
/**
* Defines the behavior of the timestamps cache region for JBossCache 2.x.
@@ -81,7 +83,7 @@
// TODO Is this a valid operation on a timestamps cache?
localCache.remove(key);
Option opt = getNonLockingDataVersionOption(true);
- CacheHelper.remove(getCacheInstance(), getRegionFqn(), key, opt);
+ CacheHelper.removeNode(getCacheInstance(), getRegionFqn(), key, opt);
}
public void evictAll() throws CacheException {
@@ -89,6 +91,8 @@
localCache.clear();
Option opt = getNonLockingDataVersionOption(true);
CacheHelper.removeAll(getCacheInstance(), getRegionFqn(), opt);
+ // Restore the region root node
+ CacheHelper.addNode(getCacheInstance(), getRegionFqn(), false, true, null);
}
public Object get(Object key) throws CacheException {
@@ -121,11 +125,11 @@
// prevents reads and other updates
Transaction tx = suspend();
try {
+ // TODO Why not use the timestamp in a DataVersion?
+ Option opt = getNonLockingDataVersionOption(false);
// We ensure ASYNC semantics (JBCACHE-1175)
- Option opt = getNonLockingDataVersionOption(false);
opt.setForceAsynchronous(true);
- getCacheInstance().getInvocationContext().setOptionOverrides(opt);
- getCacheInstance().put(new Fqn(regionFqn, key), ITEM, value);
+ CacheHelper.put(getCacheInstance(), getRegionFqn(), key, value, opt);
} catch (Exception e) {
throw new CacheException(e);
} finally {
@@ -160,6 +164,30 @@
}
}
+ /**
+ * Monitors cache events and updates the local cache
+ *
+ * @param event
+ */
+ @NodeRemoved
+ public void nodeRemoved(NodeRemovedEvent event) {
+ if (event.isOriginLocal() || event.isPre())
+ return;
+
+ Fqn fqn = event.getFqn();
+ Fqn regFqn = getRegionFqn();
+ if (fqn.size() == regFqn.size() + 1 && fqn.isChildOf(regFqn)) {
+ Object key = fqn.get(regFqn.size());
+ localCache.remove(key);
+ }
+ else if (fqn.equals(regFqn)) {
+ localCache.clear();
+ }
+ }
+
+ /**
+ * Brings all data from the distributed cache into our local cache.
+ */
private void populateLocalCache() {
Set children = CacheHelper.getChildrenNames(getCacheInstance(), getRegionFqn());
for (Object key : children) {
@@ -189,9 +217,10 @@
if (increase) {
oldVal = (Long) localCache.put(key, value);
// Double check that it was an increase
- if (oldVal != null && oldVal.longValue() > newVal) {
+ if (oldVal != null && oldVal.longValue() > newVal) {
// Nope; Restore the old value
- increase = updateLocalCache(key, oldVal);
+ updateLocalCache(key, oldVal);
+ increase = false;
}
}
} catch (ClassCastException cce) {
17 years, 3 months
Hibernate SVN: r14105 - core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/query.
by hibernate-commits@lists.jboss.org
Author: bstansberry(a)jboss.com
Date: 2007-10-18 23:13:13 -0400 (Thu, 18 Oct 2007)
New Revision: 14105
Modified:
core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/query/QueryResultsRegionImpl.java
Log:
Evict fixes
Modified: core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/query/QueryResultsRegionImpl.java
===================================================================
--- core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/query/QueryResultsRegionImpl.java 2007-10-19 02:14:44 UTC (rev 14104)
+++ core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/query/QueryResultsRegionImpl.java 2007-10-19 03:13:13 UTC (rev 14105)
@@ -71,7 +71,7 @@
Option opt = getNonLockingDataVersionOption(false);
if (localOnly)
opt.setCacheModeLocal(true);
- CacheHelper.remove(getCacheInstance(), getRegionFqn(), key, opt);
+ CacheHelper.removeNode(getCacheInstance(), getRegionFqn(), key, opt);
}
public void evictAll() throws CacheException {
@@ -79,6 +79,8 @@
if (localOnly)
opt.setCacheModeLocal(true);
CacheHelper.removeAll(getCacheInstance(), getRegionFqn(), opt);
+ // Restore the region root node
+ CacheHelper.addNode(getCacheInstance(), getRegionFqn(), false, true, null);
}
public Object get(Object key) throws CacheException {
17 years, 3 months
Hibernate SVN: r14104 - search/trunk/doc/reference/en/modules.
by hibernate-commits@lists.jboss.org
Author: epbernard
Date: 2007-10-18 22:14:44 -0400 (Thu, 18 Oct 2007)
New Revision: 14104
Modified:
search/trunk/doc/reference/en/modules/configuration.xml
Log:
HSEARCH-127 type and wrong property names
Modified: search/trunk/doc/reference/en/modules/configuration.xml
===================================================================
--- search/trunk/doc/reference/en/modules/configuration.xml 2007-10-18 22:31:39 UTC (rev 14103)
+++ search/trunk/doc/reference/en/modules/configuration.xml 2007-10-19 02:14:44 UTC (rev 14104)
@@ -253,7 +253,7 @@
</row>
<row>
- <entry><literal>org.hibernate.worker.backend</literal></entry>
+ <entry><literal>hibernate.worker.backend</literal></entry>
<entry>Out of the box support for the Apache Lucene back end and
the JMS back end. Default to <literal>lucene</literal>. Supports
@@ -261,7 +261,7 @@
</row>
<row>
- <entry><literal>org.hibernate.worker.execution</literal></entry>
+ <entry><literal>hibernate.worker.execution</literal></entry>
<entry>Supports synchronous and asynchrounous execution. Default
to <literal><literal>sync</literal></literal>. Supports also
@@ -269,14 +269,14 @@
</row>
<row>
- <entry><literal>org.hibernate.worker.thread_pool.size</literal></entry>
+ <entry><literal>hibernate.worker.thread_pool.size</literal></entry>
<entry>Defines the number of threads in the pool. useful only for
asynchrounous execution. Default to 1.</entry>
</row>
<row>
- <entry><literal>org.hibernate.worker.buffer_queue.max</literal></entry>
+ <entry><literal>hibernate.worker.buffer_queue.max</literal></entry>
<entry>Defines the maximal number of work queue if the thread poll
is starved. Useful only for asynchrounous execution. Default to
@@ -285,7 +285,7 @@
</row>
<row>
- <entry><literal>org.hibernate.worker.jndi.*</literal></entry>
+ <entry><literal>hibernate.worker.jndi.*</literal></entry>
<entry>Defines the JNDI properties to initiate the InitialContext
(if needed). JNDI is only used by the JMS back end.</entry>
@@ -293,7 +293,7 @@
<row>
<entry><literal>
- org.hibernate.worker.jms.connection_factory</literal></entry>
+ hibernate.worker.jms.connection_factory</literal></entry>
<entry>Mandatory for the JMS back end. Defines the JNDI name to
lookup the JMS connection factory from
@@ -302,7 +302,7 @@
</row>
<row>
- <entry><literal> org.hibernate.worker.jms.queue</literal></entry>
+ <entry><literal>hibernate.worker.jms.queue</literal></entry>
<entry>Mandatory for the JMS back end. Defines the JNDI name to
lookup the JMS queue from. The queue will be used to post work
@@ -310,7 +310,7 @@
</row>
<row>
- <entry><literal> org.hibernate.worker.batch_size</literal></entry>
+ <entry><literal>hibernate.worker.batch_size</literal></entry>
<entry>Defines the maximum number of elements indexed before
flushing the transaction-bound queue. Default to 0 (ie no limit).
@@ -476,13 +476,13 @@
<programlisting><hibernate-configuration>
<session-factory>
...
- <event type="post-update"
+ <event type="post-update"/>
<listener class="org.hibernate.search.event.FullTextIndexEventListener"/>
</event>
- <event type="post-insert"
+ <event type="post-insert"/>
<listener class="org.hibernate.search.event.FullTextIndexEventListener"/>
</event>
- <event type="post-delete"
+ <event type="post-delete"/>
<listener class="org.hibernate.search.event.FullTextIndexEventListener"/>
</event>
</session-factory>
17 years, 3 months
Hibernate SVN: r14103 - in core/trunk: testsuite/src/test/java/org/hibernate/test/generated and 4 other directories.
by hibernate-commits@lists.jboss.org
Author: gbadner
Date: 2007-10-18 18:31:39 -0400 (Thu, 18 Oct 2007)
New Revision: 14103
Added:
core/trunk/testsuite/src/test/java/org/hibernate/test/instrument/cases/TestSharedPKOneToOneExecutable.java
core/trunk/testsuite/src/test/java/org/hibernate/test/instrument/domain/EntityWithOneToOnes.java
core/trunk/testsuite/src/test/java/org/hibernate/test/instrument/domain/OneToOneNoProxy.java
core/trunk/testsuite/src/test/java/org/hibernate/test/instrument/domain/OneToOneProxy.java
core/trunk/testsuite/src/test/java/org/hibernate/test/instrument/domain/SharedPKOneToOne.hbm.xml
Modified:
core/trunk/core/src/main/java/org/hibernate/persister/entity/AbstractEntityPersister.java
core/trunk/testsuite/src/test/java/org/hibernate/test/generated/AbstractGeneratedPropertyTest.java
core/trunk/testsuite/src/test/java/org/hibernate/test/instrument/buildtime/InstrumentTest.java
core/trunk/testsuite/src/test/java/org/hibernate/test/instrument/cases/TestLazyExecutable.java
core/trunk/testsuite/src/test/java/org/hibernate/test/instrument/runtime/AbstractTransformingClassLoaderInstrumentTestCase.java
core/trunk/testsuite/src/test/java/org/hibernate/test/instrument/runtime/CGLIBInstrumentationTest.java
core/trunk/testsuite/src/test/java/org/hibernate/test/instrument/runtime/JavassistInstrumentationTest.java
Log:
HHH-2627 : Generated and lazy properties leak prepared statements
Modified: core/trunk/core/src/main/java/org/hibernate/persister/entity/AbstractEntityPersister.java
===================================================================
--- core/trunk/core/src/main/java/org/hibernate/persister/entity/AbstractEntityPersister.java 2007-10-18 22:28:23 UTC (rev 14102)
+++ core/trunk/core/src/main/java/org/hibernate/persister/entity/AbstractEntityPersister.java 2007-10-18 22:31:39 UTC (rev 14103)
@@ -776,31 +776,35 @@
Object result = null;
PreparedStatement ps = null;
- ResultSet rs = null;
try {
final String lazySelect = getSQLLazySelectString();
- if ( lazySelect != null ) {
- // null sql means that the only lazy properties
- // are shared PK one-to-one associations which are
- // handled differently in the Type#nullSafeGet code...
- ps = session.getBatcher().prepareSelectStatement(lazySelect);
- getIdentifierType().nullSafeSet( ps, id, 1, session );
- rs = session.getBatcher().getResultSet( ps );
- rs.next();
+ ResultSet rs = null;
+ try {
+ if ( lazySelect != null ) {
+ // null sql means that the only lazy properties
+ // are shared PK one-to-one associations which are
+ // handled differently in the Type#nullSafeGet code...
+ ps = session.getBatcher().prepareSelectStatement(lazySelect);
+ getIdentifierType().nullSafeSet( ps, id, 1, session );
+ rs = ps.executeQuery();
+ rs.next();
+ }
+ final Object[] snapshot = entry.getLoadedState();
+ for ( int j = 0; j < lazyPropertyNames.length; j++ ) {
+ Object propValue = lazyPropertyTypes[j].nullSafeGet( rs, lazyPropertyColumnAliases[j], session, entity );
+ if ( initializeLazyProperty( fieldName, entity, session, snapshot, j, propValue ) ) {
+ result = propValue;
+ }
+ }
}
- final Object[] snapshot = entry.getLoadedState();
- for ( int j = 0; j < lazyPropertyNames.length; j++ ) {
- Object propValue = lazyPropertyTypes[j].nullSafeGet( rs, lazyPropertyColumnAliases[j], session, entity );
- if ( initializeLazyProperty( fieldName, entity, session, snapshot, j, propValue ) ) {
- result = propValue;
+ finally {
+ if ( rs != null ) {
+ rs.close();
}
}
}
finally {
- if ( rs != null ) {
- session.getBatcher().closeQueryStatement( ps, rs );
- }
- else if ( ps != null ) {
+ if ( ps != null ) {
session.getBatcher().closeStatement( ps );
}
}
@@ -3695,26 +3699,32 @@
try {
PreparedStatement ps = session.getBatcher().prepareSelectStatement( selectionSQL );
- ResultSet rs = null;
try {
getIdentifierType().nullSafeSet( ps, id, 1, session );
- rs = session.getBatcher().getResultSet( ps );
- if ( !rs.next() ) {
- throw new HibernateException(
- "Unable to locate row for retrieval of generated properties: " +
- MessageHelper.infoString( this, id, getFactory() )
- );
+ ResultSet rs = ps.executeQuery();
+ try {
+ if ( !rs.next() ) {
+ throw new HibernateException(
+ "Unable to locate row for retrieval of generated properties: " +
+ MessageHelper.infoString( this, id, getFactory() )
+ );
+ }
+ for ( int i = 0; i < getPropertySpan(); i++ ) {
+ if ( includeds[i] != ValueInclusion.NONE ) {
+ Object hydratedState = getPropertyTypes()[i].hydrate( rs, getPropertyAliases( "", i ), session, entity );
+ state[i] = getPropertyTypes()[i].resolve( hydratedState, session, entity );
+ setPropertyValue( entity, i, state[i], session.getEntityMode() );
+ }
+ }
}
- for ( int i = 0; i < getPropertySpan(); i++ ) {
- if ( includeds[i] != ValueInclusion.NONE ) {
- Object hydratedState = getPropertyTypes()[i].hydrate( rs, getPropertyAliases( "", i ), session, entity );
- state[i] = getPropertyTypes()[i].resolve( hydratedState, session, entity );
- setPropertyValue( entity, i, state[i], session.getEntityMode() );
+ finally {
+ if ( rs != null ) {
+ rs.close();
}
}
}
finally {
- session.getBatcher().closeQueryStatement( ps, rs );
+ session.getBatcher().closeStatement( ps );
}
}
catch( SQLException sqle ) {
Modified: core/trunk/testsuite/src/test/java/org/hibernate/test/generated/AbstractGeneratedPropertyTest.java
===================================================================
--- core/trunk/testsuite/src/test/java/org/hibernate/test/generated/AbstractGeneratedPropertyTest.java 2007-10-18 22:28:23 UTC (rev 14102)
+++ core/trunk/testsuite/src/test/java/org/hibernate/test/generated/AbstractGeneratedPropertyTest.java 2007-10-18 22:31:39 UTC (rev 14103)
@@ -1,4 +1,4 @@
-// $Id: AbstractGeneratedPropertyTest.java 10977 2006-12-12 23:28:04Z steve.ebersole(a)jboss.com $
+// $Id: AbstractGeneratedPropertyTest.java 10976 2006-12-12 23:22:26Z steve.ebersole(a)jboss.com $
package org.hibernate.test.generated;
import org.hibernate.Session;
@@ -17,6 +17,13 @@
}
public final void testGeneratedProperty() {
+ // The following block is repeated 300 times to reproduce HHH-2627.
+ // Without the fix, Oracle will run out of cursors using 10g with
+ // a default installation (ORA-01000: maximum open cursors exceeded).
+ // The number of loops may need to be adjusted depending on the how
+ // Oracle is configured.
+ // Note: The block is not indented to avoid a lot of irrelevant differences.
+ for ( int i=0; i<300; i++ ) {
GeneratedPropertyEntity entity = new GeneratedPropertyEntity();
entity.setName( "entity-1" );
Session s = openSession();
@@ -43,5 +50,6 @@
s.delete( entity );
t.commit();
s.close();
+ }
}
}
Modified: core/trunk/testsuite/src/test/java/org/hibernate/test/instrument/buildtime/InstrumentTest.java
===================================================================
--- core/trunk/testsuite/src/test/java/org/hibernate/test/instrument/buildtime/InstrumentTest.java 2007-10-18 22:28:23 UTC (rev 14102)
+++ core/trunk/testsuite/src/test/java/org/hibernate/test/instrument/buildtime/InstrumentTest.java 2007-10-18 22:31:39 UTC (rev 14103)
@@ -1,4 +1,4 @@
-//$Id: InstrumentTest.java 10977 2006-12-12 23:28:04Z steve.ebersole(a)jboss.com $
+//$Id: InstrumentTest.java 10976 2006-12-12 23:22:26Z steve.ebersole(a)jboss.com $
package org.hibernate.test.instrument.buildtime;
import junit.framework.Test;
@@ -14,6 +14,7 @@
import org.hibernate.test.instrument.cases.TestIsPropertyInitializedExecutable;
import org.hibernate.test.instrument.cases.TestLazyPropertyCustomTypeExecutable;
import org.hibernate.test.instrument.cases.TestManyToOneProxyExecutable;
+import org.hibernate.test.instrument.cases.TestSharedPKOneToOneExecutable;
import org.hibernate.test.instrument.cases.Executable;
import org.hibernate.junit.UnitTestCase;
@@ -62,6 +63,10 @@
execute( new TestLazyPropertyCustomTypeExecutable() );
}
+ public void testSharedPKOneToOne() {
+ execute( new TestSharedPKOneToOneExecutable() );
+ }
+
private void execute(Executable executable) {
executable.prepare();
try {
Modified: core/trunk/testsuite/src/test/java/org/hibernate/test/instrument/cases/TestLazyExecutable.java
===================================================================
--- core/trunk/testsuite/src/test/java/org/hibernate/test/instrument/cases/TestLazyExecutable.java 2007-10-18 22:28:23 UTC (rev 14102)
+++ core/trunk/testsuite/src/test/java/org/hibernate/test/instrument/cases/TestLazyExecutable.java 2007-10-18 22:31:39 UTC (rev 14103)
@@ -17,6 +17,14 @@
*/
public class TestLazyExecutable extends AbstractExecutable {
public void execute() {
+ // The following block is repeated 100 times to reproduce HHH-2627.
+ // Without the fix, Oracle will run out of cursors using 10g with
+ // a default installation (ORA-01000: maximum open cursors exceeded).
+ // The number of loops may need to be adjusted depending on the how
+ // Oracle is configured.
+ // Note: The block is not indented to avoid a lot of irrelevant differences.
+ for ( int i=0; i<100; i++ ) {
+
SessionFactory factory = getFactory();
Session s = factory.openSession();
Transaction t = s.beginTransaction();
@@ -192,6 +200,9 @@
s.flush();
t.commit();
s.close();
+
+ }
+
}
}
Added: core/trunk/testsuite/src/test/java/org/hibernate/test/instrument/cases/TestSharedPKOneToOneExecutable.java
===================================================================
--- core/trunk/testsuite/src/test/java/org/hibernate/test/instrument/cases/TestSharedPKOneToOneExecutable.java (rev 0)
+++ core/trunk/testsuite/src/test/java/org/hibernate/test/instrument/cases/TestSharedPKOneToOneExecutable.java 2007-10-18 22:31:39 UTC (rev 14103)
@@ -0,0 +1,69 @@
+package org.hibernate.test.instrument.cases;
+
+import org.hibernate.Session;
+import org.hibernate.Transaction;
+import org.hibernate.Hibernate;
+import org.hibernate.test.instrument.domain.EntityWithOneToOnes;
+import org.hibernate.test.instrument.domain.OneToOneProxy;
+import org.hibernate.test.instrument.domain.OneToOneNoProxy;
+import junit.framework.Assert;
+
+/**
+ *
+ * @author Gail Badner
+ */
+public class TestSharedPKOneToOneExecutable extends AbstractExecutable {
+
+ protected String[] getResources() {
+ return new String[] {"org/hibernate/test/instrument/domain/SharedPKOneToOne.hbm.xml"};
+ }
+
+ public void execute() {
+ Session s = getFactory().openSession();
+ Transaction t = s.beginTransaction();
+ EntityWithOneToOnes root = new EntityWithOneToOnes( "root" );
+ OneToOneProxy oneToOneProxy = new OneToOneProxy( "oneToOneProxy" );
+ root.setOneToOneProxy( oneToOneProxy );
+ oneToOneProxy.setEntity( root );
+ OneToOneNoProxy oneToOneNoProxy = new OneToOneNoProxy( "oneToOneNoProxy" );
+ root.setOneToOneNoProxy( oneToOneNoProxy );
+ oneToOneNoProxy.setEntity( root );
+
+ s.save( root );
+ t.commit();
+ s.close();
+
+ // NOTE : oneToOneProxy is mapped with lazy="proxy"; oneToOneNoProxy with lazy="no-proxy"...
+
+ s = getFactory().openSession();
+ t = s.beginTransaction();
+ // load root
+ root = ( EntityWithOneToOnes ) s.load( EntityWithOneToOnes.class, root.getId() );
+ Assert.assertFalse( Hibernate.isInitialized( root ) );
+ Assert.assertFalse( Hibernate.isPropertyInitialized( root, "name" ) );
+ Assert.assertFalse( Hibernate.isPropertyInitialized( root, "oneToOneProxy" ) );
+ Assert.assertFalse( Hibernate.isPropertyInitialized( root, "oneToOneNoProxy" ) );
+
+ root.getName();
+ Assert.assertTrue( Hibernate.isInitialized( root ) );
+ Assert.assertTrue( Hibernate.isPropertyInitialized( root, "name" ) );
+ Assert.assertTrue( Hibernate.isPropertyInitialized( root, "oneToOneProxy" ) );
+ Assert.assertFalse( Hibernate.isPropertyInitialized( root, "oneToOneNoProxy" ) );
+
+ // get a handle to the oneToOneProxy proxy reference (and make certain that
+ // this does not force the lazy properties of the root entity
+ // to get initialized.
+ root.getOneToOneProxy();
+ Assert.assertTrue( Hibernate.isInitialized( oneToOneProxy ) );
+ Assert.assertTrue( Hibernate.isPropertyInitialized( root.getOneToOneProxy(), "name" ) );
+ Assert.assertFalse( Hibernate.isPropertyInitialized( root, "oneToOneNoProxy" ) );
+
+ root.getOneToOneNoProxy();
+ Assert.assertTrue( Hibernate.isPropertyInitialized( root, "oneToOneNoProxy" ) );
+ Assert.assertTrue( Hibernate.isPropertyInitialized( root.getOneToOneNoProxy(), "name") );
+
+ s.delete( root );
+ t.commit();
+ s.close();
+ }
+}
Added: core/trunk/testsuite/src/test/java/org/hibernate/test/instrument/domain/EntityWithOneToOnes.java
===================================================================
--- core/trunk/testsuite/src/test/java/org/hibernate/test/instrument/domain/EntityWithOneToOnes.java (rev 0)
+++ core/trunk/testsuite/src/test/java/org/hibernate/test/instrument/domain/EntityWithOneToOnes.java 2007-10-18 22:31:39 UTC (rev 14103)
@@ -0,0 +1,50 @@
+package org.hibernate.test.instrument.domain;
+
+/**
+ * @author Gail Badner
+ */
+public class EntityWithOneToOnes {
+ private Long id;
+ private String name;
+ private OneToOneNoProxy oneToOneNoProxy;
+ private OneToOneProxy oneToOneProxy;
+
+ public EntityWithOneToOnes() {
+ }
+
+ public EntityWithOneToOnes(String name) {
+ this.name = name;
+ }
+
+ public Long getId() {
+ return id;
+ }
+
+ public void setId(Long id) {
+ this.id = id;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public OneToOneNoProxy getOneToOneNoProxy() {
+ return oneToOneNoProxy;
+ }
+
+ public void setOneToOneNoProxy(OneToOneNoProxy oneToOneNoProxy) {
+ this.oneToOneNoProxy = oneToOneNoProxy;
+ }
+
+ public OneToOneProxy getOneToOneProxy() {
+ return oneToOneProxy;
+ }
+
+ public void setOneToOneProxy(OneToOneProxy oneToOneProxy) {
+ this.oneToOneProxy = oneToOneProxy;
+ }
+}
Added: core/trunk/testsuite/src/test/java/org/hibernate/test/instrument/domain/OneToOneNoProxy.java
===================================================================
--- core/trunk/testsuite/src/test/java/org/hibernate/test/instrument/domain/OneToOneNoProxy.java (rev 0)
+++ core/trunk/testsuite/src/test/java/org/hibernate/test/instrument/domain/OneToOneNoProxy.java 2007-10-18 22:31:39 UTC (rev 14103)
@@ -0,0 +1,45 @@
+package org.hibernate.test.instrument.domain;
+
+/**
+ * @author Gail Badner
+ */
+public class OneToOneNoProxy {
+ private Long entityId;
+ private String name;
+ private EntityWithOneToOnes entity;
+
+ public OneToOneNoProxy() {}
+ public OneToOneNoProxy(String name) {
+ this.name = name;
+ }
+ /**
+ * @return Returns the id.
+ */
+ public Long getEntityId() {
+ return entityId;
+ }
+ /**
+ * @param entityId The id to set.
+ */
+ public void setEntityId(Long entityId) {
+ this.entityId = entityId;
+ }
+ /**
+ * @return Returns the name.
+ */
+ public String getName() {
+ return name;
+ }
+ /**
+ * @param name The name to set.
+ */
+ public void setName(String name) {
+ this.name = name;
+ }
+ public EntityWithOneToOnes getEntity() {
+ return entity;
+ }
+ public void setEntity(EntityWithOneToOnes entity) {
+ this.entity = entity;
+ }
+}
Added: core/trunk/testsuite/src/test/java/org/hibernate/test/instrument/domain/OneToOneProxy.java
===================================================================
--- core/trunk/testsuite/src/test/java/org/hibernate/test/instrument/domain/OneToOneProxy.java (rev 0)
+++ core/trunk/testsuite/src/test/java/org/hibernate/test/instrument/domain/OneToOneProxy.java 2007-10-18 22:31:39 UTC (rev 14103)
@@ -0,0 +1,45 @@
+package org.hibernate.test.instrument.domain;
+
+/**
+ * @author Gail Badner
+ */
+public class OneToOneProxy {
+ private Long entityId;
+ private String name;
+ private EntityWithOneToOnes entity;
+
+ public OneToOneProxy() {}
+ public OneToOneProxy(String name) {
+ this.name = name;
+ }
+ /**
+ * @return Returns the id.
+ */
+ public Long getEntityId() {
+ return entityId;
+ }
+ /**
+ * @param entityId The id to set.
+ */
+ public void setEntityId(Long entityId) {
+ this.entityId = entityId;
+ }
+ /**
+ * @return Returns the name.
+ */
+ public String getName() {
+ return name;
+ }
+ /**
+ * @param name The name to set.
+ */
+ public void setName(String name) {
+ this.name = name;
+ }
+ public EntityWithOneToOnes getEntity() {
+ return entity;
+ }
+ public void setEntity(EntityWithOneToOnes entity) {
+ this.entity = entity;
+ }
+}
Added: core/trunk/testsuite/src/test/java/org/hibernate/test/instrument/domain/SharedPKOneToOne.hbm.xml
===================================================================
--- core/trunk/testsuite/src/test/java/org/hibernate/test/instrument/domain/SharedPKOneToOne.hbm.xml (rev 0)
+++ core/trunk/testsuite/src/test/java/org/hibernate/test/instrument/domain/SharedPKOneToOne.hbm.xml 2007-10-18 22:31:39 UTC (rev 14103)
@@ -0,0 +1,51 @@
+<?xml version="1.0"?>
+<!DOCTYPE hibernate-mapping PUBLIC
+ "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
+ "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
+
+<!--
+
+ This mapping demonstrates shared PK one-to-one associations using
+ lazy="proxy" and lazy="no-proxy".
+
+ Implementation note: This test does not include any other
+ lazy properties, and allows testing special case code in
+ AbstractEntityPersister.initializeLazyPropertiesFromDatastore()
+ (lazy select string will be null) and OneToOne.nullSafeGet()
+ (ResultSet arg is ignored and the owner's ID is returned).
+
+-->
+
+<hibernate-mapping package="org.hibernate.test.instrument.domain" default-access="field">
+
+ <class name="EntityWithOneToOnes">
+ <id name="id" column="ID" type="long">
+ <generator class="increment"/>
+ </id>
+ <one-to-one name="oneToOneNoProxy" class="OneToOneNoProxy" lazy="no-proxy" cascade="all" />
+ <one-to-one name="oneToOneProxy" class="OneToOneProxy" lazy="proxy" cascade="all" />
+ <property name="name"/>
+ </class>
+
+ <class name="OneToOneNoProxy">
+ <id name="entityId">
+ <generator class="foreign">
+ <param name="property">entity</param>
+ </generator>
+ </id>
+ <one-to-one name="entity" class="EntityWithOneToOnes" constrained="true"/>
+ <property name="name"/>
+ </class>
+
+ <class name="OneToOneProxy">
+ <id name="entityId">
+ <generator class="foreign">
+ <param name="property">entity</param>
+ </generator>
+ </id>
+ <one-to-one name="entity" class="EntityWithOneToOnes" constrained="true"/>
+ <property name="name"/>
+ </class>
+
+
+</hibernate-mapping>
Modified: core/trunk/testsuite/src/test/java/org/hibernate/test/instrument/runtime/AbstractTransformingClassLoaderInstrumentTestCase.java
===================================================================
--- core/trunk/testsuite/src/test/java/org/hibernate/test/instrument/runtime/AbstractTransformingClassLoaderInstrumentTestCase.java 2007-10-18 22:28:23 UTC (rev 14102)
+++ core/trunk/testsuite/src/test/java/org/hibernate/test/instrument/runtime/AbstractTransformingClassLoaderInstrumentTestCase.java 2007-10-18 22:31:39 UTC (rev 14103)
@@ -78,8 +78,10 @@
executeExecutable( "org.hibernate.test.instrument.cases.TestLazyPropertyCustomTypeExecutable" );
}
+ public void testSharedPKOneToOne() {
+ executeExecutable( "org.hibernate.test.instrument.cases.TestSharedPKOneToOneExecutable" );
+ }
-
// reflection code to ensure isolation into the created classloader ~~~~~~~
private static final Class[] SIG = new Class[] {};
Modified: core/trunk/testsuite/src/test/java/org/hibernate/test/instrument/runtime/CGLIBInstrumentationTest.java
===================================================================
--- core/trunk/testsuite/src/test/java/org/hibernate/test/instrument/runtime/CGLIBInstrumentationTest.java 2007-10-18 22:28:23 UTC (rev 14102)
+++ core/trunk/testsuite/src/test/java/org/hibernate/test/instrument/runtime/CGLIBInstrumentationTest.java 2007-10-18 22:31:39 UTC (rev 14103)
@@ -48,4 +48,8 @@
public void testManyToOneProxy() {
super.testManyToOneProxy(); //To change body of overridden methods use File | Settings | File Templates.
}
+
+ public void testSharedPKOneToOne() {
+ super.testSharedPKOneToOne();
+ }
}
Modified: core/trunk/testsuite/src/test/java/org/hibernate/test/instrument/runtime/JavassistInstrumentationTest.java
===================================================================
--- core/trunk/testsuite/src/test/java/org/hibernate/test/instrument/runtime/JavassistInstrumentationTest.java 2007-10-18 22:28:23 UTC (rev 14102)
+++ core/trunk/testsuite/src/test/java/org/hibernate/test/instrument/runtime/JavassistInstrumentationTest.java 2007-10-18 22:31:39 UTC (rev 14103)
@@ -49,4 +49,8 @@
public void testManyToOneProxy() {
super.testManyToOneProxy();
}
+
+ public void testSharedPKOneToOne() {
+ super.testSharedPKOneToOne();
+ }
}
17 years, 3 months
Hibernate SVN: r14102 - in core/branches/Branch_3_2: test/org/hibernate/test/generated and 4 other directories.
by hibernate-commits@lists.jboss.org
Author: gbadner
Date: 2007-10-18 18:28:23 -0400 (Thu, 18 Oct 2007)
New Revision: 14102
Added:
core/branches/Branch_3_2/test/org/hibernate/test/instrument/cases/TestSharedPKOneToOneExecutable.java
core/branches/Branch_3_2/test/org/hibernate/test/instrument/domain/EntityWithOneToOnes.java
core/branches/Branch_3_2/test/org/hibernate/test/instrument/domain/OneToOneNoProxy.java
core/branches/Branch_3_2/test/org/hibernate/test/instrument/domain/OneToOneProxy.java
core/branches/Branch_3_2/test/org/hibernate/test/instrument/domain/SharedPKOneToOne.hbm.xml
Modified:
core/branches/Branch_3_2/src/org/hibernate/persister/entity/AbstractEntityPersister.java
core/branches/Branch_3_2/test/org/hibernate/test/generated/AbstractGeneratedPropertyTest.java
core/branches/Branch_3_2/test/org/hibernate/test/instrument/buildtime/InstrumentTest.java
core/branches/Branch_3_2/test/org/hibernate/test/instrument/cases/TestLazyExecutable.java
core/branches/Branch_3_2/test/org/hibernate/test/instrument/runtime/AbstractTransformingClassLoaderInstrumentTestCase.java
core/branches/Branch_3_2/test/org/hibernate/test/instrument/runtime/CGLIBInstrumentationTest.java
core/branches/Branch_3_2/test/org/hibernate/test/instrument/runtime/JavassistInstrumentationTest.java
Log:
HHH-2627 : Generated and lazy properties leak prepared statements
Modified: core/branches/Branch_3_2/src/org/hibernate/persister/entity/AbstractEntityPersister.java
===================================================================
--- core/branches/Branch_3_2/src/org/hibernate/persister/entity/AbstractEntityPersister.java 2007-10-18 20:08:50 UTC (rev 14101)
+++ core/branches/Branch_3_2/src/org/hibernate/persister/entity/AbstractEntityPersister.java 2007-10-18 22:28:23 UTC (rev 14102)
@@ -776,31 +776,35 @@
Object result = null;
PreparedStatement ps = null;
- ResultSet rs = null;
try {
final String lazySelect = getSQLLazySelectString();
- if ( lazySelect != null ) {
- // null sql means that the only lazy properties
- // are shared PK one-to-one associations which are
- // handled differently in the Type#nullSafeGet code...
- ps = session.getBatcher().prepareSelectStatement(lazySelect);
- getIdentifierType().nullSafeSet( ps, id, 1, session );
- rs = session.getBatcher().getResultSet( ps );
- rs.next();
+ ResultSet rs = null;
+ try {
+ if ( lazySelect != null ) {
+ // null sql means that the only lazy properties
+ // are shared PK one-to-one associations which are
+ // handled differently in the Type#nullSafeGet code...
+ ps = session.getBatcher().prepareSelectStatement(lazySelect);
+ getIdentifierType().nullSafeSet( ps, id, 1, session );
+ rs = ps.executeQuery();
+ rs.next();
+ }
+ final Object[] snapshot = entry.getLoadedState();
+ for ( int j = 0; j < lazyPropertyNames.length; j++ ) {
+ Object propValue = lazyPropertyTypes[j].nullSafeGet( rs, lazyPropertyColumnAliases[j], session, entity );
+ if ( initializeLazyProperty( fieldName, entity, session, snapshot, j, propValue ) ) {
+ result = propValue;
+ }
+ }
}
- final Object[] snapshot = entry.getLoadedState();
- for ( int j = 0; j < lazyPropertyNames.length; j++ ) {
- Object propValue = lazyPropertyTypes[j].nullSafeGet( rs, lazyPropertyColumnAliases[j], session, entity );
- if ( initializeLazyProperty( fieldName, entity, session, snapshot, j, propValue ) ) {
- result = propValue;
+ finally {
+ if ( rs != null ) {
+ rs.close();
}
}
}
finally {
- if ( rs != null ) {
- session.getBatcher().closeQueryStatement( ps, rs );
- }
- else if ( ps != null ) {
+ if ( ps != null ) {
session.getBatcher().closeStatement( ps );
}
}
@@ -3695,26 +3699,32 @@
try {
PreparedStatement ps = session.getBatcher().prepareSelectStatement( selectionSQL );
- ResultSet rs = null;
try {
getIdentifierType().nullSafeSet( ps, id, 1, session );
- rs = session.getBatcher().getResultSet( ps );
- if ( !rs.next() ) {
- throw new HibernateException(
- "Unable to locate row for retrieval of generated properties: " +
- MessageHelper.infoString( this, id, getFactory() )
- );
+ ResultSet rs = ps.executeQuery();
+ try {
+ if ( !rs.next() ) {
+ throw new HibernateException(
+ "Unable to locate row for retrieval of generated properties: " +
+ MessageHelper.infoString( this, id, getFactory() )
+ );
+ }
+ for ( int i = 0; i < getPropertySpan(); i++ ) {
+ if ( includeds[i] != ValueInclusion.NONE ) {
+ Object hydratedState = getPropertyTypes()[i].hydrate( rs, getPropertyAliases( "", i ), session, entity );
+ state[i] = getPropertyTypes()[i].resolve( hydratedState, session, entity );
+ setPropertyValue( entity, i, state[i], session.getEntityMode() );
+ }
+ }
}
- for ( int i = 0; i < getPropertySpan(); i++ ) {
- if ( includeds[i] != ValueInclusion.NONE ) {
- Object hydratedState = getPropertyTypes()[i].hydrate( rs, getPropertyAliases( "", i ), session, entity );
- state[i] = getPropertyTypes()[i].resolve( hydratedState, session, entity );
- setPropertyValue( entity, i, state[i], session.getEntityMode() );
+ finally {
+ if ( rs != null ) {
+ rs.close();
}
}
}
finally {
- session.getBatcher().closeQueryStatement( ps, rs );
+ session.getBatcher().closeStatement( ps );
}
}
catch( SQLException sqle ) {
Modified: core/branches/Branch_3_2/test/org/hibernate/test/generated/AbstractGeneratedPropertyTest.java
===================================================================
--- core/branches/Branch_3_2/test/org/hibernate/test/generated/AbstractGeneratedPropertyTest.java 2007-10-18 20:08:50 UTC (rev 14101)
+++ core/branches/Branch_3_2/test/org/hibernate/test/generated/AbstractGeneratedPropertyTest.java 2007-10-18 22:28:23 UTC (rev 14102)
@@ -17,6 +17,13 @@
}
public final void testGeneratedProperty() {
+ // The following block is repeated 300 times to reproduce HHH-2627.
+ // Without the fix, Oracle will run out of cursors using 10g with
+ // a default installation (ORA-01000: maximum open cursors exceeded).
+ // The number of loops may need to be adjusted depending on the how
+ // Oracle is configured.
+ // Note: The block is not indented to avoid a lot of irrelevant differences.
+ for ( int i=0; i<300; i++ ) {
GeneratedPropertyEntity entity = new GeneratedPropertyEntity();
entity.setName( "entity-1" );
Session s = openSession();
@@ -43,5 +50,6 @@
s.delete( entity );
t.commit();
s.close();
+ }
}
}
Modified: core/branches/Branch_3_2/test/org/hibernate/test/instrument/buildtime/InstrumentTest.java
===================================================================
--- core/branches/Branch_3_2/test/org/hibernate/test/instrument/buildtime/InstrumentTest.java 2007-10-18 20:08:50 UTC (rev 14101)
+++ core/branches/Branch_3_2/test/org/hibernate/test/instrument/buildtime/InstrumentTest.java 2007-10-18 22:28:23 UTC (rev 14102)
@@ -14,6 +14,7 @@
import org.hibernate.test.instrument.cases.TestIsPropertyInitializedExecutable;
import org.hibernate.test.instrument.cases.TestLazyPropertyCustomTypeExecutable;
import org.hibernate.test.instrument.cases.TestManyToOneProxyExecutable;
+import org.hibernate.test.instrument.cases.TestSharedPKOneToOneExecutable;
import org.hibernate.test.instrument.cases.Executable;
import org.hibernate.junit.UnitTestCase;
@@ -62,6 +63,10 @@
execute( new TestLazyPropertyCustomTypeExecutable() );
}
+ public void testSharedPKOneToOne() {
+ execute( new TestSharedPKOneToOneExecutable() );
+ }
+
private void execute(Executable executable) {
executable.prepare();
try {
Modified: core/branches/Branch_3_2/test/org/hibernate/test/instrument/cases/TestLazyExecutable.java
===================================================================
--- core/branches/Branch_3_2/test/org/hibernate/test/instrument/cases/TestLazyExecutable.java 2007-10-18 20:08:50 UTC (rev 14101)
+++ core/branches/Branch_3_2/test/org/hibernate/test/instrument/cases/TestLazyExecutable.java 2007-10-18 22:28:23 UTC (rev 14102)
@@ -17,6 +17,14 @@
*/
public class TestLazyExecutable extends AbstractExecutable {
public void execute() {
+ // The following block is repeated 100 times to reproduce HHH-2627.
+ // Without the fix, Oracle will run out of cursors using 10g with
+ // a default installation (ORA-01000: maximum open cursors exceeded).
+ // The number of loops may need to be adjusted depending on the how
+ // Oracle is configured.
+ // Note: The block is not indented to avoid a lot of irrelevant differences.
+ for ( int i=0; i<100; i++ ) {
+
SessionFactory factory = getFactory();
Session s = factory.openSession();
Transaction t = s.beginTransaction();
@@ -192,6 +200,9 @@
s.flush();
t.commit();
s.close();
+
+ }
+
}
}
Added: core/branches/Branch_3_2/test/org/hibernate/test/instrument/cases/TestSharedPKOneToOneExecutable.java
===================================================================
--- core/branches/Branch_3_2/test/org/hibernate/test/instrument/cases/TestSharedPKOneToOneExecutable.java (rev 0)
+++ core/branches/Branch_3_2/test/org/hibernate/test/instrument/cases/TestSharedPKOneToOneExecutable.java 2007-10-18 22:28:23 UTC (rev 14102)
@@ -0,0 +1,69 @@
+package org.hibernate.test.instrument.cases;
+
+import org.hibernate.Session;
+import org.hibernate.Transaction;
+import org.hibernate.Hibernate;
+import org.hibernate.test.instrument.domain.EntityWithOneToOnes;
+import org.hibernate.test.instrument.domain.OneToOneProxy;
+import org.hibernate.test.instrument.domain.OneToOneNoProxy;
+import junit.framework.Assert;
+
+/**
+ *
+ * @author Gail Badner
+ */
+public class TestSharedPKOneToOneExecutable extends AbstractExecutable {
+
+ protected String[] getResources() {
+ return new String[] {"org/hibernate/test/instrument/domain/SharedPKOneToOne.hbm.xml"};
+ }
+
+ public void execute() {
+ Session s = getFactory().openSession();
+ Transaction t = s.beginTransaction();
+ EntityWithOneToOnes root = new EntityWithOneToOnes( "root" );
+ OneToOneProxy oneToOneProxy = new OneToOneProxy( "oneToOneProxy" );
+ root.setOneToOneProxy( oneToOneProxy );
+ oneToOneProxy.setEntity( root );
+ OneToOneNoProxy oneToOneNoProxy = new OneToOneNoProxy( "oneToOneNoProxy" );
+ root.setOneToOneNoProxy( oneToOneNoProxy );
+ oneToOneNoProxy.setEntity( root );
+
+ s.save( root );
+ t.commit();
+ s.close();
+
+ // NOTE : oneToOneProxy is mapped with lazy="proxy"; oneToOneNoProxy with lazy="no-proxy"...
+
+ s = getFactory().openSession();
+ t = s.beginTransaction();
+ // load root
+ root = ( EntityWithOneToOnes ) s.load( EntityWithOneToOnes.class, root.getId() );
+ Assert.assertFalse( Hibernate.isInitialized( root ) );
+ Assert.assertFalse( Hibernate.isPropertyInitialized( root, "name" ) );
+ Assert.assertFalse( Hibernate.isPropertyInitialized( root, "oneToOneProxy" ) );
+ Assert.assertFalse( Hibernate.isPropertyInitialized( root, "oneToOneNoProxy" ) );
+
+ root.getName();
+ Assert.assertTrue( Hibernate.isInitialized( root ) );
+ Assert.assertTrue( Hibernate.isPropertyInitialized( root, "name" ) );
+ Assert.assertTrue( Hibernate.isPropertyInitialized( root, "oneToOneProxy" ) );
+ Assert.assertFalse( Hibernate.isPropertyInitialized( root, "oneToOneNoProxy" ) );
+
+ // get a handle to the oneToOneProxy proxy reference (and make certain that
+ // this does not force the lazy properties of the root entity
+ // to get initialized.
+ root.getOneToOneProxy();
+ Assert.assertTrue( Hibernate.isInitialized( oneToOneProxy ) );
+ Assert.assertTrue( Hibernate.isPropertyInitialized( root.getOneToOneProxy(), "name" ) );
+ Assert.assertFalse( Hibernate.isPropertyInitialized( root, "oneToOneNoProxy" ) );
+
+ root.getOneToOneNoProxy();
+ Assert.assertTrue( Hibernate.isPropertyInitialized( root, "oneToOneNoProxy" ) );
+ Assert.assertTrue( Hibernate.isPropertyInitialized( root.getOneToOneNoProxy(), "name") );
+
+ s.delete( root );
+ t.commit();
+ s.close();
+ }
+}
Added: core/branches/Branch_3_2/test/org/hibernate/test/instrument/domain/EntityWithOneToOnes.java
===================================================================
--- core/branches/Branch_3_2/test/org/hibernate/test/instrument/domain/EntityWithOneToOnes.java (rev 0)
+++ core/branches/Branch_3_2/test/org/hibernate/test/instrument/domain/EntityWithOneToOnes.java 2007-10-18 22:28:23 UTC (rev 14102)
@@ -0,0 +1,50 @@
+package org.hibernate.test.instrument.domain;
+
+/**
+ * @author Gail Badner
+ */
+public class EntityWithOneToOnes {
+ private Long id;
+ private String name;
+ private OneToOneNoProxy oneToOneNoProxy;
+ private OneToOneProxy oneToOneProxy;
+
+ public EntityWithOneToOnes() {
+ }
+
+ public EntityWithOneToOnes(String name) {
+ this.name = name;
+ }
+
+ public Long getId() {
+ return id;
+ }
+
+ public void setId(Long id) {
+ this.id = id;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public OneToOneNoProxy getOneToOneNoProxy() {
+ return oneToOneNoProxy;
+ }
+
+ public void setOneToOneNoProxy(OneToOneNoProxy oneToOneNoProxy) {
+ this.oneToOneNoProxy = oneToOneNoProxy;
+ }
+
+ public OneToOneProxy getOneToOneProxy() {
+ return oneToOneProxy;
+ }
+
+ public void setOneToOneProxy(OneToOneProxy oneToOneProxy) {
+ this.oneToOneProxy = oneToOneProxy;
+ }
+}
Added: core/branches/Branch_3_2/test/org/hibernate/test/instrument/domain/OneToOneNoProxy.java
===================================================================
--- core/branches/Branch_3_2/test/org/hibernate/test/instrument/domain/OneToOneNoProxy.java (rev 0)
+++ core/branches/Branch_3_2/test/org/hibernate/test/instrument/domain/OneToOneNoProxy.java 2007-10-18 22:28:23 UTC (rev 14102)
@@ -0,0 +1,45 @@
+package org.hibernate.test.instrument.domain;
+
+/**
+ * @author Gail Badner
+ */
+public class OneToOneNoProxy {
+ private Long entityId;
+ private String name;
+ private EntityWithOneToOnes entity;
+
+ public OneToOneNoProxy() {}
+ public OneToOneNoProxy(String name) {
+ this.name = name;
+ }
+ /**
+ * @return Returns the id.
+ */
+ public Long getEntityId() {
+ return entityId;
+ }
+ /**
+ * @param entityId The id to set.
+ */
+ public void setEntityId(Long entityId) {
+ this.entityId = entityId;
+ }
+ /**
+ * @return Returns the name.
+ */
+ public String getName() {
+ return name;
+ }
+ /**
+ * @param name The name to set.
+ */
+ public void setName(String name) {
+ this.name = name;
+ }
+ public EntityWithOneToOnes getEntity() {
+ return entity;
+ }
+ public void setEntity(EntityWithOneToOnes entity) {
+ this.entity = entity;
+ }
+}
Added: core/branches/Branch_3_2/test/org/hibernate/test/instrument/domain/OneToOneProxy.java
===================================================================
--- core/branches/Branch_3_2/test/org/hibernate/test/instrument/domain/OneToOneProxy.java (rev 0)
+++ core/branches/Branch_3_2/test/org/hibernate/test/instrument/domain/OneToOneProxy.java 2007-10-18 22:28:23 UTC (rev 14102)
@@ -0,0 +1,45 @@
+package org.hibernate.test.instrument.domain;
+
+/**
+ * @author Gail Badner
+ */
+public class OneToOneProxy {
+ private Long entityId;
+ private String name;
+ private EntityWithOneToOnes entity;
+
+ public OneToOneProxy() {}
+ public OneToOneProxy(String name) {
+ this.name = name;
+ }
+ /**
+ * @return Returns the id.
+ */
+ public Long getEntityId() {
+ return entityId;
+ }
+ /**
+ * @param entityId The id to set.
+ */
+ public void setEntityId(Long entityId) {
+ this.entityId = entityId;
+ }
+ /**
+ * @return Returns the name.
+ */
+ public String getName() {
+ return name;
+ }
+ /**
+ * @param name The name to set.
+ */
+ public void setName(String name) {
+ this.name = name;
+ }
+ public EntityWithOneToOnes getEntity() {
+ return entity;
+ }
+ public void setEntity(EntityWithOneToOnes entity) {
+ this.entity = entity;
+ }
+}
Added: core/branches/Branch_3_2/test/org/hibernate/test/instrument/domain/SharedPKOneToOne.hbm.xml
===================================================================
--- core/branches/Branch_3_2/test/org/hibernate/test/instrument/domain/SharedPKOneToOne.hbm.xml (rev 0)
+++ core/branches/Branch_3_2/test/org/hibernate/test/instrument/domain/SharedPKOneToOne.hbm.xml 2007-10-18 22:28:23 UTC (rev 14102)
@@ -0,0 +1,51 @@
+<?xml version="1.0"?>
+<!DOCTYPE hibernate-mapping PUBLIC
+ "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
+ "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
+
+<!--
+
+ This mapping demonstrates shared PK one-to-one associations using
+ lazy="proxy" and lazy="no-proxy".
+
+ Implementation note: This test does not include any other
+ lazy properties, and allows testing special case code in
+ AbstractEntityPersister.initializeLazyPropertiesFromDatastore()
+ (lazy select string will be null) and OneToOne.nullSafeGet()
+ (ResultSet arg is ignored and the owner's ID is returned).
+
+-->
+
+<hibernate-mapping package="org.hibernate.test.instrument.domain" default-access="field">
+
+ <class name="EntityWithOneToOnes">
+ <id name="id" column="ID" type="long">
+ <generator class="increment"/>
+ </id>
+ <one-to-one name="oneToOneNoProxy" class="OneToOneNoProxy" lazy="no-proxy" cascade="all" />
+ <one-to-one name="oneToOneProxy" class="OneToOneProxy" lazy="proxy" cascade="all" />
+ <property name="name"/>
+ </class>
+
+ <class name="OneToOneNoProxy">
+ <id name="entityId">
+ <generator class="foreign">
+ <param name="property">entity</param>
+ </generator>
+ </id>
+ <one-to-one name="entity" class="EntityWithOneToOnes" constrained="true"/>
+ <property name="name"/>
+ </class>
+
+ <class name="OneToOneProxy">
+ <id name="entityId">
+ <generator class="foreign">
+ <param name="property">entity</param>
+ </generator>
+ </id>
+ <one-to-one name="entity" class="EntityWithOneToOnes" constrained="true"/>
+ <property name="name"/>
+ </class>
+
+
+</hibernate-mapping>
Modified: core/branches/Branch_3_2/test/org/hibernate/test/instrument/runtime/AbstractTransformingClassLoaderInstrumentTestCase.java
===================================================================
--- core/branches/Branch_3_2/test/org/hibernate/test/instrument/runtime/AbstractTransformingClassLoaderInstrumentTestCase.java 2007-10-18 20:08:50 UTC (rev 14101)
+++ core/branches/Branch_3_2/test/org/hibernate/test/instrument/runtime/AbstractTransformingClassLoaderInstrumentTestCase.java 2007-10-18 22:28:23 UTC (rev 14102)
@@ -78,8 +78,10 @@
executeExecutable( "org.hibernate.test.instrument.cases.TestLazyPropertyCustomTypeExecutable" );
}
+ public void testSharedPKOneToOne() {
+ executeExecutable( "org.hibernate.test.instrument.cases.TestSharedPKOneToOneExecutable" );
+ }
-
// reflection code to ensure isolation into the created classloader ~~~~~~~
private static final Class[] SIG = new Class[] {};
Modified: core/branches/Branch_3_2/test/org/hibernate/test/instrument/runtime/CGLIBInstrumentationTest.java
===================================================================
--- core/branches/Branch_3_2/test/org/hibernate/test/instrument/runtime/CGLIBInstrumentationTest.java 2007-10-18 20:08:50 UTC (rev 14101)
+++ core/branches/Branch_3_2/test/org/hibernate/test/instrument/runtime/CGLIBInstrumentationTest.java 2007-10-18 22:28:23 UTC (rev 14102)
@@ -48,4 +48,8 @@
public void testManyToOneProxy() {
super.testManyToOneProxy(); //To change body of overridden methods use File | Settings | File Templates.
}
+
+ public void testSharedPKOneToOne() {
+ super.testSharedPKOneToOne();
+ }
}
Modified: core/branches/Branch_3_2/test/org/hibernate/test/instrument/runtime/JavassistInstrumentationTest.java
===================================================================
--- core/branches/Branch_3_2/test/org/hibernate/test/instrument/runtime/JavassistInstrumentationTest.java 2007-10-18 20:08:50 UTC (rev 14101)
+++ core/branches/Branch_3_2/test/org/hibernate/test/instrument/runtime/JavassistInstrumentationTest.java 2007-10-18 22:28:23 UTC (rev 14102)
@@ -49,4 +49,8 @@
public void testManyToOneProxy() {
super.testManyToOneProxy();
}
+
+ public void testSharedPKOneToOne() {
+ super.testSharedPKOneToOne();
+ }
}
17 years, 3 months
Hibernate SVN: r14101 - in core/trunk/cache-jbosscache2: src/main and 29 other directories.
by hibernate-commits@lists.jboss.org
Author: bstansberry(a)jboss.com
Date: 2007-10-18 16:08:50 -0400 (Thu, 18 Oct 2007)
New Revision: 14101
Added:
core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/JBossCacheRegionFactory.java
core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/JndiMultiplexedJBossCacheRegionFactory.java
core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/JndiSharedJBossCacheRegionFactory.java
core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/MultiplexedJBossCacheRegionFactory.java
core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/SharedJBossCacheRegionFactory.java
core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/access/
core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/access/OptimisticTransactionalAccessDelegate.java
core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/access/TransactionalAccessDelegate.java
core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/builder/JBossCacheFactory.java
core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/builder/JBossCacheFactoryImpl.java
core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/builder/JndiMultiplexingCacheInstanceManager.java
core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/builder/JndiSharedCacheInstanceManager.java
core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/builder/SharedCacheInstanceManager.java
core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/collection/OptimisticReadOnlyAccess.java
core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/collection/OptimisticTransactionalAccess.java
core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/entity/OptimisticReadOnlyAccess.java
core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/entity/OptimisticTransactionalAccess.java
core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/query/
core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/query/QueryResultsRegionImpl.java
core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/timestamp/
core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/timestamp/TimestampsRegionImpl.java
core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/util/CacheHelper.java
core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/util/CircumventChecksDataVersion.java
core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/util/DataVersionAdapter.java
core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/util/NonLockingDataVersion.java
core/trunk/cache-jbosscache2/src/main/resources/
core/trunk/cache-jbosscache2/src/main/resources/org/
core/trunk/cache-jbosscache2/src/main/resources/org/hibernate/
core/trunk/cache-jbosscache2/src/main/resources/org/hibernate/cache/
core/trunk/cache-jbosscache2/src/main/resources/org/hibernate/cache/jbc2/
core/trunk/cache-jbosscache2/src/main/resources/org/hibernate/cache/jbc2/builder/
core/trunk/cache-jbosscache2/src/main/resources/org/hibernate/cache/jbc2/builder/jbc2-configs.xml
core/trunk/cache-jbosscache2/src/test/java/org/hibernate/
core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/
core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/
core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/
core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/AbstractEntityCollectionRegionTestCase.java
core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/AbstractJBossCacheTestCase.java
core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/AbstractRegionImplTestCase.java
core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/JBossCacheComplianceTest.java
core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/JBossCacheRegionFactoryTestCase.java
core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/builder/
core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/builder/CacheInstanceManagerTestBase.java
core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/builder/MultiplexedCacheInstanceManagerTestCase.java
core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/builder/SharedCacheInstanceManagerTestCase.java
core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/collection/
core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/collection/AbstractCollectionRegionAccessStrategyTestCase.java
core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/collection/AbstractReadOnlyAccessTestCase.java
core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/collection/AbstractTransactionalAccessTestCase.java
core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/collection/CollectionRegionImplTestCase.java
core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/collection/OptimisticInvalidatedTransactionalTestCase.java
core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/collection/OptimisticReadOnlyExtraAPITestCase.java
core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/collection/OptimisticReadOnlyTestCase.java
core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/collection/OptimisticReplicatedTransactionalTestCase.java
core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/collection/OptimisticTransactionalExtraAPITestCase.java
core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/collection/PessimisticInvalidatedTransactionalTestCase.java
core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/collection/PessimisticReadOnlyExtraAPITestCase.java
core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/collection/PessimisticReadOnlyTestCase.java
core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/collection/PessimisticReplicatedTransactionalTestCase.java
core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/collection/PessimisticTransactionalExtraAPITestCase.java
core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/entity/
core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/entity/AbstractEntityRegionAccessStrategyTestCase.java
core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/entity/AbstractReadOnlyAccessTestCase.java
core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/entity/AbstractTransactionalAccessTestCase.java
core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/entity/EntityRegionImplTestCase.java
core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/entity/OptimisticInvalidatedTransactionalTestCase.java
core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/entity/OptimisticReadOnlyExtraAPITestCase.java
core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/entity/OptimisticReadOnlyTestCase.java
core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/entity/OptimisticReplicatedTransactionalTestCase.java
core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/entity/OptimisticTransactionalExtraAPITestCase.java
core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/entity/PessimisticInvalidatedTransactionalTestCase.java
core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/entity/PessimisticReadOnlyExtraAPITestCase.java
core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/entity/PessimisticReadOnlyTestCase.java
core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/entity/PessimisticReplicatedTransactionalTestCase.java
core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/entity/PessimisticTransactionalExtraAPITestCase.java
core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/functional/
core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/functional/AbstractEntityCacheFunctionalTestCase.java
core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/functional/AbstractQueryCacheFunctionalTestCase.java
core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/functional/CacheTestCaseBase.java
core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/functional/Item.hbm.xml
core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/functional/Item.java
core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/functional/OptimisticJBossCacheTestDisabled.java
core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/functional/PessimisticJBossCacheTestDisabled.java
core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/functional/VersionedItem.java
core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/functional/optimistic-treecache.xml
core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/functional/pessimistic-treecache.xml
core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/query/
core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/query/QueryRegionImplTestCase.java
core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/timestamp/
core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/timestamp/TimestampsRegionImplTestCase.java
core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/tm/
core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/tm/DummyConnectionProvider.java
core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/tm/DummyTransaction.java
core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/tm/DummyTransactionManager.java
core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/tm/DummyTransactionManagerLookup.java
core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/tm/jbc2/
core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/tm/jbc2/BatchModeTransactionManagerLookup.java
core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/util/
core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/util/CacheTestSupport.java
core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/util/CacheTestUtil.java
core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/util/optimistic-local-cache.xml
core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/util/pessimistic-local-cache.xml
core/trunk/cache-jbosscache2/src/test/resources/hibernate.cfg.xml
core/trunk/cache-jbosscache2/src/test/resources/hibernate.properties
core/trunk/cache-jbosscache2/src/test/resources/log4j.properties
core/trunk/cache-jbosscache2/src/test/resources/treecache.xml
Removed:
core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/JBossCacheRegionFactory.java
core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/builder/InvalidationCacheInstanceManager.java
core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/util/CacheModeHelper.java
Modified:
core/trunk/cache-jbosscache2/
core/trunk/cache-jbosscache2/pom.xml
core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/BasicRegionAdapter.java
core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/CacheInstanceManager.java
core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/TransactionalDataRegionAdapter.java
core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/builder/MultiplexingCacheInstanceManager.java
core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/collection/CollectionRegionImpl.java
core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/collection/ReadOnlyAccess.java
core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/collection/TransactionalAccess.java
core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/entity/EntityRegionImpl.java
core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/entity/ReadOnlyAccess.java
core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/entity/TransactionalAccess.java
Log:
[HHH-2555] Reimplement Hibernate/JBC 2.0 integration
Property changes on: core/trunk/cache-jbosscache2
___________________________________________________________________
Name: svn:ignore
- target
local
*.ipr
*.iws
*.iml
.classpath
.project
.nbattrs
*.log
*.properties
.clover
+ target
local
*.ipr
*.iws
*.iml
.classpath
.project
.nbattrs
*.log
*.properties
.clover
.settings
bin
Modified: core/trunk/cache-jbosscache2/pom.xml
===================================================================
--- core/trunk/cache-jbosscache2/pom.xml 2007-10-18 19:49:17 UTC (rev 14100)
+++ core/trunk/cache-jbosscache2/pom.xml 2007-10-18 20:08:50 UTC (rev 14101)
@@ -25,16 +25,36 @@
<version>${version}</version>
</dependency>
<dependency>
- <groupId>jboss</groupId>
- <artifactId>jboss-cache</artifactId>
+ <groupId>${groupId}</groupId>
+ <artifactId>hibernate-testing</artifactId>
+ <version>${version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.jboss.cache</groupId>
+ <artifactId>jbosscache-core</artifactId>
<!-- I'd prefer this, at least until we get a GA...
<version>[2.0.0.BETA2,)</version>
-->
- <version>2.0.0.BETA2</version>
- </dependency>
+ <version>2.1.0.BETA1</version>
+ </dependency>
+ <!-- test dependencies -->
</dependencies>
- <build>
+ <build>
+ <testResources>
+ <testResource>
+ <filtering>false</filtering>
+ <directory>src/test/java</directory>
+ <includes>
+ <include>**/*.xml</include>
+ </includes>
+ </testResource>
+ <testResource>
+ <filtering>true</filtering>
+ <directory>src/test/resources</directory>
+ </testResource>
+ </testResources>
+
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
@@ -43,8 +63,72 @@
<source>1.5</source>
<target>1.5</target>
</configuration>
- </plugin>
+ </plugin>
+ <plugin>
+ <groupId>org.jboss.maven.plugins</groupId>
+ <artifactId>maven-test-ext-plugin</artifactId>
+ <version>1.1.0</version>
+ <executions>
+ <execution>
+ <goals>
+ <goal>extend</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-surefire-plugin</artifactId>
+ <configuration>
+ <systemProperties>
+ <property>
+ <name>hibernate.test.validatefailureexpected</name>
+ <value>true</value>
+ </property>
+ </systemProperties>
+ </configuration>
+ </plugin>
</plugins>
- </build>
+ </build>
+
+ <profiles>
+ <!-- HSQLDB is the default (eventually move to H2) -->
+ <profile>
+ <id>hsqldb</id>
+ <activation>
+ <activeByDefault>true</activeByDefault>
+ </activation>
+ <dependencies>
+ <dependency>
+ <groupId>hsqldb</groupId>
+ <artifactId>hsqldb</artifactId>
+ <version>1.8.0.2</version>
+ </dependency>
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-log4j12</artifactId>
+ <version>1.4.2</version>
+ </dependency>
+ <dependency>
+ <groupId>log4j</groupId>
+ <artifactId>log4j</artifactId>
+ <version>1.2.14</version>
+ </dependency>
+ <dependency>
+ <groupId>cglib</groupId>
+ <artifactId>cglib</artifactId>
+ <version>2.1_3</version>
+ </dependency>
+ </dependencies>
+ <properties>
+ <db.dialect>org.hibernate.dialect.HSQLDialect</db.dialect>
+ <jdbc.driver>org.hsqldb.jdbcDriver</jdbc.driver>
+ <jdbc.url>jdbc:hsqldb:target/test/db/hsqldb/hibernate</jdbc.url>
+ <jdbc.user>sa</jdbc.user>
+ <jdbc.pass/>
+ <jdbc.isolation/>
+ </properties>
+ </profile>
+ </profiles>
</project>
Modified: core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/BasicRegionAdapter.java
===================================================================
--- core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/BasicRegionAdapter.java 2007-10-18 19:49:17 UTC (rev 14100)
+++ core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/BasicRegionAdapter.java 2007-10-18 20:08:50 UTC (rev 14101)
@@ -19,128 +19,307 @@
import java.util.Map;
import java.util.Set;
+import javax.transaction.SystemException;
+import javax.transaction.Transaction;
+import javax.transaction.TransactionManager;
+
import org.jboss.cache.Cache;
import org.jboss.cache.Fqn;
+import org.jboss.cache.Node;
+import org.jboss.cache.NodeSPI;
+import org.jboss.cache.config.Configuration;
import org.jboss.cache.config.Option;
+import org.jboss.cache.config.Configuration.NodeLockingScheme;
+import org.jboss.cache.notifications.annotation.CacheListener;
+import org.jboss.cache.notifications.annotation.NodeCreated;
+import org.jboss.cache.notifications.event.NodeCreatedEvent;
+import org.jboss.cache.optimistic.DataVersion;
import org.hibernate.cache.CacheException;
import org.hibernate.cache.Region;
+import org.hibernate.cache.jbc2.util.CacheHelper;
+import org.hibernate.cache.jbc2.util.NonLockingDataVersion;
/**
- * General support for writing {@link Region} implementations for
- *
- *
+ * General support for writing {@link Region} implementations for JBoss Cache
+ * 2.x.
+ *
+ *
* @author Steve Ebersole
*/
+@CacheListener
public abstract class BasicRegionAdapter implements Region {
- public static final String ITEM = "item";
+ public static final String ITEM = CacheHelper.ITEM;
- protected final Cache jbcCache;
- protected final String regionName;
- protected final Fqn regionFqn;
+ protected final Cache jbcCache;
+ protected final String regionName;
+ protected final Fqn regionFqn;
+ protected final boolean optimistic;
+
+ protected final TransactionManager transactionManager;
- public BasicRegionAdapter(Cache jbcCache, String regionName) {
- this.jbcCache = jbcCache;
- this.regionName = regionName;
- this.regionFqn = Fqn.fromString( regionName.replace( '.', '/' ) );
- activateLocalClusterNode();
- }
+ protected SetResidentListener listener;
+
+ public BasicRegionAdapter(Cache jbcCache, String regionName, String regionPrefix) {
+ this.jbcCache = jbcCache;
+ this.transactionManager = jbcCache.getConfiguration().getRuntimeConfig().getTransactionManager();
+ this.regionName = regionName;
+ this.regionFqn = createRegionFqn(regionName, regionPrefix);
+ optimistic = jbcCache.getConfiguration().getNodeLockingScheme() == NodeLockingScheme.OPTIMISTIC;
+ activateLocalClusterNode();
+ }
- private void activateLocalClusterNode() {
- org.jboss.cache.Region jbcRegion = jbcCache.getRegion( regionFqn, true );
- if ( jbcRegion.isActive() ) {
- return;
- }
- ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
- if ( classLoader == null ) {
- classLoader = getClass().getClassLoader();
- }
- jbcRegion.registerContextClassLoader( classLoader );
- jbcRegion.activate();
- }
+ protected abstract Fqn<String> createRegionFqn(String regionName, String regionPrefix);
- public String getName() {
- return regionName;
- }
+ protected void activateLocalClusterNode() {
+ try {
+ Configuration cfg = jbcCache.getConfiguration();
+ if (cfg.isUseRegionBasedMarshalling()) {
+ org.jboss.cache.Region jbcRegion = jbcCache.getRegion(regionFqn, true);
+ ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
+ if (classLoader == null) {
+ classLoader = getClass().getClassLoader();
+ }
+ jbcRegion.registerContextClassLoader(classLoader);
+ if (jbcRegion.isActive() == false) {
+ jbcRegion.activate();
+ }
+ }
+
+ // If we are using replication, we may remove the root node
+ // and then need to re-add it. In that case, the fact
+ // that it is resident will not replicate, so use a listener
+ // to set it as resident
+ if (CacheHelper.isClusteredReplication(cfg.getCacheMode())) {
+ listener = new SetResidentListener();
+ jbcCache.addCacheListener(listener);
+ }
+
+ // Make sure the root node for the region exists and
+ // has a DataVersion that never complains
+ Node regionRoot = jbcCache.getRoot().getChild( regionFqn );
+ if (regionRoot == null) {
+ // Establish the region root node with a non-locking data version
+ DataVersion version = optimistic ? NonLockingDataVersion.INSTANCE : null;
+ regionRoot = CacheHelper.addNode(jbcCache, regionFqn, true, true, version);
+ }
+ else if (optimistic && regionRoot instanceof NodeSPI) {
+ // FIXME Hacky workaround to JBCACHE-1202
+ if ((((NodeSPI) regionRoot).getVersion() instanceof NonLockingDataVersion) == false) {
+ ((NodeSPI) regionRoot).setVersion(NonLockingDataVersion.INSTANCE);
+ }
+ }
+ // Never evict this node
+ regionRoot.setResident(true);
+ }
+ catch (Exception e) {
+ throw new CacheException(e.getMessage(), e);
+ }
+ }
- public Cache getCacheInstance() {
- return jbcCache;
- }
+ public String getName() {
+ return regionName;
+ }
- public Fqn getRegionFqn() {
- return regionFqn;
- }
+ public Cache getCacheInstance() {
+ return jbcCache;
+ }
- public void destroy() throws CacheException {
- try {
- // NOTE : this is being used from the process of shutting down a
- // SessionFactory. Specific things to consider:
- // (1) this clearing of the region should not propogate to
- // other nodes on the cluster (if any); this is the
- // cache-mode-local option bit...
- // (2) really just trying a best effort to cleanup after
- // ourselves; lock failures, etc are not critical here;
- // this is the fail-silently option bit...
- Option option = new Option();
- option.setCacheModeLocal( true );
- option.setFailSilently( true );
- jbcCache.getInvocationContext().setOptionOverrides( option );
- jbcCache.removeNode( regionFqn );
- deactivateLocalNode();
- }
- catch( Exception e ) {
- throw new CacheException( e );
- }
- }
+ public Fqn getRegionFqn() {
+ return regionFqn;
+ }
- private void deactivateLocalNode() {
- org.jboss.cache.Region jbcRegion = jbcCache.getRegion( regionFqn, false );
- if ( jbcRegion != null && jbcRegion.isActive() ) {
- jbcRegion.deactivate();
- jbcRegion.unregisterContextClassLoader();
- }
- }
+ public void destroy() throws CacheException {
+ try {
+ // NOTE : this is being used from the process of shutting down a
+ // SessionFactory. Specific things to consider:
+ // (1) this clearing of the region should not propogate to
+ // other nodes on the cluster (if any); this is the
+ // cache-mode-local option bit...
+ // (2) really just trying a best effort to cleanup after
+ // ourselves; lock failures, etc are not critical here;
+ // this is the fail-silently option bit...
+ Option option = new Option();
+ option.setCacheModeLocal(true);
+ option.setFailSilently(true);
+ if (optimistic) {
+ option.setDataVersion(NonLockingDataVersion.INSTANCE);
+ }
+ jbcCache.getInvocationContext().setOptionOverrides(option);
+ jbcCache.removeNode(regionFqn);
+ deactivateLocalNode();
+ } catch (Exception e) {
+ throw new CacheException(e);
+ }
+ finally {
+ if (listener != null)
+ jbcCache.removeCacheListener(listener);
+ }
+ }
- public long getSizeInMemory() {
- // not supported
- return -1;
- }
+ protected void deactivateLocalNode() {
+ org.jboss.cache.Region jbcRegion = jbcCache.getRegion(regionFqn, false);
+ if (jbcRegion != null && jbcRegion.isActive()) {
+ jbcRegion.deactivate();
+ jbcRegion.unregisterContextClassLoader();
+ }
+ }
- public long getElementCountInMemory() {
- try {
- Set children = jbcCache.getRoot().getChild( regionFqn ).getChildrenNames();
- return children == null ? 0 : children.size();
- }
- catch ( Exception e ) {
- throw new CacheException( e );
- }
- }
+ public long getSizeInMemory() {
+ // not supported
+ return -1;
+ }
- public long getElementCountOnDisk() {
- return -1;
- }
+ public long getElementCountInMemory() {
+ try {
+ Set childrenNames = CacheHelper.getChildrenNames(jbcCache, regionFqn);
+ return childrenNames.size();
+ } catch (Exception e) {
+ throw new CacheException(e);
+ }
+ }
- public Map toMap() {
- try {
- Map result = new HashMap();
- Set childrenNames = jbcCache.getRoot().getChild( regionFqn ).getChildrenNames();
- if (childrenNames != null) {
- for ( Object childName : childrenNames ) {
- result.put( childName, jbcCache.get( new Fqn( regionFqn, childName ), ITEM ) );
- }
- }
- return result;
- }
- catch (Exception e) {
- throw new CacheException(e);
- }
- }
+ public long getElementCountOnDisk() {
+ return -1;
+ }
- public long nextTimestamp() {
- return System.currentTimeMillis() / 100;
- }
+ public Map toMap() {
+ try {
+ Map result = new HashMap();
+ Set childrenNames = CacheHelper.getChildrenNames(jbcCache, regionFqn);
+ for (Object childName : childrenNames) {
+ result.put(childName, jbcCache.get(new Fqn(regionFqn, childName), ITEM));
+ }
+ return result;
+ } catch (Exception e) {
+ throw new CacheException(e);
+ }
+ }
- public int getTimeout() {
- return 600; //60 seconds
- }
+ public long nextTimestamp() {
+ return System.currentTimeMillis() / 100;
+ }
+
+ public int getTimeout() {
+ return 600; // 60 seconds
+ }
+
+ /**
+ * Performs a JBoss Cache <code>get(Fqn, Object)</code> after first
+ * {@link #suspend suspending any ongoing transaction}. Wraps any exception
+ * in a {@link CacheException}. Ensures any ongoing transaction is resumed.
+ *
+ * @param key
+ * @param opt any option to add to the get invocation. May be <code>null</code>
+ * @param suppressTimeout should any TimeoutException be suppressed?
+ * @return
+ */
+ protected Object suspendAndGet(Object key, Option opt, boolean suppressTimeout) throws CacheException {
+ Transaction tx = suspend();
+ try {
+ CacheHelper.setInvocationOption(getCacheInstance(), opt);
+ if (suppressTimeout)
+ return CacheHelper.getAllowingTimeout(getCacheInstance(), getRegionFqn(), key);
+ else
+ return CacheHelper.get(getCacheInstance(), getRegionFqn(), key);
+ } finally {
+ resume(tx);
+ }
+ }
+
+ /**
+ * Tell the TransactionManager to suspend any ongoing transaction.
+ *
+ * @return the transaction that was suspended, or <code>null</code> if
+ * there wasn't one
+ */
+ protected Transaction suspend() {
+ Transaction tx = null;
+ try {
+ if (transactionManager != null) {
+ tx = transactionManager.suspend();
+ }
+ } catch (SystemException se) {
+ throw new CacheException("Could not suspend transaction", se);
+ }
+ return tx;
+ }
+
+ /**
+ * Tell the TransactionManager to resume the given transaction
+ *
+ * @param tx
+ * the transaction to suspend. May be <code>null</code>.
+ */
+ protected void resume(Transaction tx) {
+ try {
+ if (tx != null)
+ transactionManager.resume(tx);
+ } catch (Exception e) {
+ throw new CacheException("Could not resume transaction", e);
+ }
+ }
+
+ /**
+ * Get an Option with a {@link Option#getDataVersion() data version}
+ * of {@link NonLockingDataVersion}. The data version will not be
+ * set if the cache is not configured for optimistic locking.
+ *
+ * @param allowNullReturn If <code>true</code>, return <code>null</code>
+ * if the cache is not using optimistic locking.
+ * If <code>false</code>, return a default
+ * {@link Option}.
+ *
+ * @return the Option, or <code>null</code>.
+ */
+ protected Option getNonLockingDataVersionOption(boolean allowNullReturn) {
+ return optimistic ? NonLockingDataVersion.getInvocationOption()
+ : (allowNullReturn) ? null : new Option();
+ }
+
+ public static Fqn<String> getTypeFirstRegionFqn(String regionName, String regionPrefix, String regionType) {
+ Fqn<String> base = Fqn.fromString(regionType);
+ Fqn<String> added = Fqn.fromString(escapeRegionName(regionName, regionPrefix));
+ return new Fqn<String>(base, added);
+ }
+
+ public static Fqn<String> getTypeLastRegionFqn(String regionName, String regionPrefix, String regionType) {
+ Fqn<String> base = Fqn.fromString(escapeRegionName(regionName, regionPrefix));
+ return new Fqn<String>(base, regionType);
+ }
+
+ public static String escapeRegionName(String regionName, String regionPrefix) {
+ String escaped = null;
+ int idx = -1;
+ if (regionPrefix != null) {
+ idx = regionName.indexOf(regionPrefix);
+ }
+
+ if (idx > -1) {
+ int regionEnd = idx + regionPrefix.length();
+ String prefix = regionName.substring(0, regionEnd);
+ String suffix = regionName.substring(regionEnd);
+ suffix = suffix.replace('.', '/');
+ escaped = prefix + suffix;
+ } else {
+ escaped = regionName.replace('.', '/');
+ if (regionPrefix != null && regionPrefix.length() > 0) {
+ escaped = regionPrefix + "/" + escaped;
+ }
+ }
+ return escaped;
+ }
+
+ @CacheListener
+ public class SetResidentListener {
+
+ @NodeCreated
+ public void nodeCreated(NodeCreatedEvent event) {
+ if (!event.isPre() && event.getFqn().equals(getRegionFqn())) {
+ Node regionRoot = jbcCache.getRoot().getChild(getRegionFqn());
+ regionRoot.setResident(true);
+ }
+ }
+
+ }
}
Modified: core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/CacheInstanceManager.java
===================================================================
--- core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/CacheInstanceManager.java 2007-10-18 19:49:17 UTC (rev 14100)
+++ core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/CacheInstanceManager.java 2007-10-18 20:08:50 UTC (rev 14101)
@@ -15,48 +15,69 @@
*/
package org.hibernate.cache.jbc2;
+import java.util.Properties;
+
+import org.hibernate.cache.CacheException;
+import org.hibernate.cfg.Settings;
import org.jboss.cache.Cache;
/**
* Acts as a buffer from how instances of {@link Cache} are built/obtained.
- *
+ *
* @author Steve Ebersole
*/
public interface CacheInstanceManager {
- /**
- * Retrieve a handle to the {@link Cache} instance to be used for storing
- * entity data.
- *
- * @return The entity data cache instance.
- */
- public Cache getEntityCacheInstance();
+ /**
+ * Retrieve a handle to the {@link Cache} instance to be used for storing
+ * entity data.
+ *
+ * @return The entity data cache instance.
+ */
+ public Cache getEntityCacheInstance();
- /**
- * Retrieve a handle to the {@link Cache} instance to be used for storing
- * collection data.
- *
- * @return The collection data cache instance.
- */
- public Cache getCollectionCacheInstance();
+ /**
+ * Retrieve a handle to the {@link Cache} instance to be used for storing
+ * collection data.
+ *
+ * @return The collection data cache instance.
+ */
+ public Cache getCollectionCacheInstance();
- /**
- * Retrieve a handle to the {@link Cache} instance to be used for storing
- * query results.
- *
- * @return The query result cache instance.
- */
- public Cache getQueryCacheInstance();
+ /**
+ * Retrieve a handle to the {@link Cache} instance to be used for storing
+ * query results.
+ *
+ * @return The query result cache instance.
+ */
+ public Cache getQueryCacheInstance();
- /**
- * Retrieve a handle to the {@link Cache} instance to be used for storing
- * timestamps.
- *
- * @return The timestamps cache instance.
- */
- public Cache getTimestampsCacheInstance();
+ /**
+ * Retrieve a handle to the {@link Cache} instance to be used for storing
+ * timestamps.
+ *
+ * @return The timestamps cache instance.
+ */
+ public Cache getTimestampsCacheInstance();
- /**
- * Release any held resources.
- */
- public void release();
+ /**
+ * Lifecycle callback to perform any necessary initialization of the
+ * CacheInstanceManager. Called exactly once during the construction of a
+ * {@link org.hibernate.impl.SessionFactoryImpl}.
+ *
+ * @param settings
+ * The settings in effect.
+ * @param properties
+ * The defined cfg properties
+ * @throws CacheException
+ * Indicates problems starting the L2 cache impl; considered as
+ * a sign to stop {@link org.hibernate.SessionFactory} building.
+ */
+ public void start(Settings settings, Properties properties) throws CacheException;
+
+ /**
+ * Lifecycle callback to perform any necessary cleanup of the underlying
+ * CacheInstanceManager. Called exactly once during
+ * {@link org.hibernate.SessionFactory#close}.
+ */
+ public void stop();
}
Deleted: core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/JBossCacheRegionFactory.java
===================================================================
--- core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/JBossCacheRegionFactory.java 2007-10-18 19:49:17 UTC (rev 14100)
+++ core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/JBossCacheRegionFactory.java 2007-10-18 20:08:50 UTC (rev 14101)
@@ -1,89 +0,0 @@
-/*
- * Copyright (c) 2007, Red Hat Middleware, LLC. All rights reserved.
- *
- * This copyrighted material is made available to anyone wishing to use, modify,
- * copy, or redistribute it subject to the terms and conditions of the GNU
- * Lesser General Public License, v. 2.1. This program is distributed in the
- * hope that it will be useful, but WITHOUT A WARRANTY; without even the implied
- * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details. You should have received a
- * copy of the GNU Lesser General Public License, v.2.1 along with this
- * distribution; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * Red Hat Author(s): Steve Ebersole
- */
-package org.hibernate.cache.jbc2;
-
-import java.util.Properties;
-
-import org.hibernate.cache.CacheDataDescription;
-import org.hibernate.cache.CacheException;
-import org.hibernate.cache.CollectionRegion;
-import org.hibernate.cache.EntityRegion;
-import org.hibernate.cache.QueryResultsRegion;
-import org.hibernate.cache.RegionFactory;
-import org.hibernate.cache.TimestampsRegion;
-import org.hibernate.cache.jbc2.builder.InvalidationCacheInstanceManager;
-import org.hibernate.cache.jbc2.collection.CollectionRegionImpl;
-import org.hibernate.cache.jbc2.entity.EntityRegionImpl;
-import org.hibernate.cfg.Settings;
-
-/**
- * {@inheritDoc}
- *
- * @author Steve Ebersole
- */
-public class JBossCacheRegionFactory implements RegionFactory {
- private CacheInstanceManager cacheInstanceManager;
-
- public JBossCacheRegionFactory() {
- }
-
- public JBossCacheRegionFactory(CacheInstanceManager cacheInstanceManager) {
- this.cacheInstanceManager = cacheInstanceManager;
- }
-
- public void start(Settings settings, Properties properties) throws CacheException {
- if ( cacheInstanceManager == null ) {
- cacheInstanceManager = new InvalidationCacheInstanceManager( settings, properties );
- }
- }
-
- public void stop() {
- if ( cacheInstanceManager != null ) {
- cacheInstanceManager.release();
- }
- }
-
- public boolean isMinimalPutsEnabledByDefault() {
- return true;
- }
-
- public long nextTimestamp() {
- return System.currentTimeMillis() / 100;
- }
-
- public EntityRegion buildEntityRegion(
- String regionName,
- Properties properties,
- CacheDataDescription metadata) throws CacheException {
- return new EntityRegionImpl( cacheInstanceManager.getEntityCacheInstance(), regionName, metadata );
- }
-
- public CollectionRegion buildCollectionRegion(
- String regionName,
- Properties properties,
- CacheDataDescription metadata) throws CacheException {
- return new CollectionRegionImpl( cacheInstanceManager.getCollectionCacheInstance(), regionName, metadata );
- }
-
- public QueryResultsRegion buildQueryResultsRegion(String regionName, Properties properties) throws CacheException {
- return null;
- }
-
- public TimestampsRegion buildTimestampsRegion(String regionName, Properties properties) throws CacheException {
- return null;
- }
-
-}
Added: core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/JBossCacheRegionFactory.java
===================================================================
--- core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/JBossCacheRegionFactory.java (rev 0)
+++ core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/JBossCacheRegionFactory.java 2007-10-18 20:08:50 UTC (rev 14101)
@@ -0,0 +1,145 @@
+/*
+ * Copyright (c) 2007, Red Hat Middleware, LLC. All rights reserved.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, v. 2.1. This program is distributed in the
+ * hope that it will be useful, but WITHOUT A WARRANTY; without even the implied
+ * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details. You should have received a
+ * copy of the GNU Lesser General Public License, v.2.1 along with this
+ * distribution; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Red Hat Author(s): Steve Ebersole
+ */
+package org.hibernate.cache.jbc2;
+
+import java.util.Properties;
+
+import org.hibernate.cache.CacheDataDescription;
+import org.hibernate.cache.CacheException;
+import org.hibernate.cache.CollectionRegion;
+import org.hibernate.cache.EntityRegion;
+import org.hibernate.cache.QueryResultsRegion;
+import org.hibernate.cache.RegionFactory;
+import org.hibernate.cache.TimestampsRegion;
+import org.hibernate.cache.jbc2.builder.JndiSharedCacheInstanceManager;
+import org.hibernate.cache.jbc2.builder.SharedCacheInstanceManager;
+import org.hibernate.cache.jbc2.collection.CollectionRegionImpl;
+import org.hibernate.cache.jbc2.entity.EntityRegionImpl;
+import org.hibernate.cache.jbc2.query.QueryResultsRegionImpl;
+import org.hibernate.cache.jbc2.timestamp.TimestampsRegionImpl;
+import org.hibernate.cfg.Environment;
+import org.hibernate.cfg.Settings;
+import org.hibernate.util.PropertiesHelper;
+import org.jboss.cache.DefaultCacheFactory;
+
+;
+
+/**
+ * {@link RegionFactory} that uses one or more JBoss Cache instances for
+ * caching entities, collections, queries and timestamps. How the factory
+ * obtains a reference to the needed JBoss Cache instance(s) is determined
+ * by the injected {@link CacheInstanceManager}.
+ * <p>
+ * By default uses {@link SharedCacheInstanceManager} as its
+ * {@link #getCacheInstanceManager() CacheInstanceManager}.
+ * Basically, this uses a single shared JBoss Cache for entities, collections,
+ * queries and timestamps. The JBoss Cache instance is created by the
+ * JBC {@link DefaultCacheFactory} using the resource identified by the
+ * {@link JndiSharedCacheInstanceManager#CACHE_RESOURCE_PROP}
+ * configuration property.
+ * </p>
+ * <p>
+ * Also exposes an overloaded constructor that allows injection of different
+ * <code>CacheInstanceManager</code> implementations.
+ * </p>
+ *
+ * @author Steve Ebersole
+ * @author Brian Stansberry
+ */
+public class JBossCacheRegionFactory implements RegionFactory {
+ private CacheInstanceManager cacheInstanceManager;
+
+ /**
+ * FIXME Per the RegionFactory class Javadoc, this constructor version
+ * should not be necessary.
+ *
+ * @param props
+ */
+ public JBossCacheRegionFactory(Properties props) {
+ this();
+ }
+
+ /**
+ * Create a new JBossCacheRegionFactory.
+ */
+ public JBossCacheRegionFactory() {
+ }
+
+ /**
+ * Create a new JBossCacheRegionFactory that uses the provided
+ * {@link CacheInstanceManager}.
+ *
+ * @param cacheInstanceManager
+ */
+ public JBossCacheRegionFactory(CacheInstanceManager cacheInstanceManager) {
+ this.cacheInstanceManager = cacheInstanceManager;
+ }
+
+ public CacheInstanceManager getCacheInstanceManager() {
+ return cacheInstanceManager;
+ }
+
+ public void start(Settings settings, Properties properties) throws CacheException {
+ if (cacheInstanceManager == null) {
+ cacheInstanceManager = new SharedCacheInstanceManager();
+ }
+
+ cacheInstanceManager.start(settings, properties);
+ }
+
+ public void stop() {
+ if (cacheInstanceManager != null) {
+ cacheInstanceManager.stop();
+ }
+ }
+
+ public boolean isMinimalPutsEnabledByDefault() {
+ return true;
+ }
+
+ public long nextTimestamp() {
+ return System.currentTimeMillis() / 100;
+ }
+
+ public EntityRegion buildEntityRegion(String regionName, Properties properties, CacheDataDescription metadata)
+ throws CacheException {
+ return new EntityRegionImpl(cacheInstanceManager.getEntityCacheInstance(), regionName,
+ getRegionPrefix(properties), metadata);
+ }
+
+ public CollectionRegion buildCollectionRegion(String regionName, Properties properties,
+ CacheDataDescription metadata) throws CacheException {
+ return new CollectionRegionImpl(cacheInstanceManager.getCollectionCacheInstance(), regionName,
+ getRegionPrefix(properties), metadata);
+ }
+
+ public QueryResultsRegion buildQueryResultsRegion(String regionName, Properties properties) throws CacheException {
+
+ return new QueryResultsRegionImpl(cacheInstanceManager.getQueryCacheInstance(), regionName,
+ getRegionPrefix(properties), properties);
+ }
+
+ public TimestampsRegion buildTimestampsRegion(String regionName, Properties properties) throws CacheException {
+
+ return new TimestampsRegionImpl(cacheInstanceManager.getTimestampsCacheInstance(), regionName,
+ getRegionPrefix(properties), properties);
+ }
+
+ public static String getRegionPrefix(Properties properties) {
+ return PropertiesHelper.getString(Environment.CACHE_REGION_PREFIX, properties, null);
+ }
+
+}
Property changes on: core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/JBossCacheRegionFactory.java
___________________________________________________________________
Name: svn:executable
+ *
Added: core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/JndiMultiplexedJBossCacheRegionFactory.java
===================================================================
--- core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/JndiMultiplexedJBossCacheRegionFactory.java (rev 0)
+++ core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/JndiMultiplexedJBossCacheRegionFactory.java 2007-10-18 20:08:50 UTC (rev 14101)
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2007, Red Hat Middleware, LLC. All rights reserved.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, v. 2.1. This program is distributed in the
+ * hope that it will be useful, but WITHOUT A WARRANTY; without even the implied
+ * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details. You should have received a
+ * copy of the GNU Lesser General Public License, v.2.1 along with this
+ * distribution; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Red Hat Author(s): Brian Stansberry
+ */
+
+package org.hibernate.cache.jbc2;
+
+import java.util.Properties;
+
+import org.hibernate.cache.jbc2.builder.JndiMultiplexingCacheInstanceManager;
+
+/**
+ * {@link JBossCacheRegionFactory} that uses
+ * {@link JndiMultiplexingCacheInstanceManager} as its
+ * {@link #getCacheInstanceManager() CacheInstanceManager}.
+ * <p>
+ * Supports separate JBoss Cache instances for entity, collection, query
+ * and timestamp caching, with the expectation that a single multiplexed
+ * JGroups channel will be shared between the caches. JBoss Cache instances
+ * are created from a factory.
+ * </p>
+ * <p>
+ * This version finds the factory in JNDI. See
+ * {@link JndiMultiplexingCacheInstanceManager} for configuration details.
+ * </p>
+ *
+ * @author Brian Stansberry
+ * @version $Revision$
+ */
+public class JndiMultiplexedJBossCacheRegionFactory extends JBossCacheRegionFactory {
+
+ /**
+ * FIXME Per the RegionFactory class Javadoc, this constructor version
+ * should not be necessary.
+ *
+ * @param props
+ */
+ public JndiMultiplexedJBossCacheRegionFactory(Properties props) {
+ this();
+ }
+
+ /**
+ * Create a new MultiplexedJBossCacheRegionFactory.
+ *
+ */
+ public JndiMultiplexedJBossCacheRegionFactory() {
+ super(new JndiMultiplexingCacheInstanceManager());
+ }
+
+}
Added: core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/JndiSharedJBossCacheRegionFactory.java
===================================================================
--- core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/JndiSharedJBossCacheRegionFactory.java (rev 0)
+++ core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/JndiSharedJBossCacheRegionFactory.java 2007-10-18 20:08:50 UTC (rev 14101)
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2007, Red Hat Middleware, LLC. All rights reserved.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, v. 2.1. This program is distributed in the
+ * hope that it will be useful, but WITHOUT A WARRANTY; without even the implied
+ * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details. You should have received a
+ * copy of the GNU Lesser General Public License, v.2.1 along with this
+ * distribution; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Red Hat Author(s): Brian Stansberry
+ */
+
+package org.hibernate.cache.jbc2;
+
+import java.util.Properties;
+
+import org.hibernate.cache.jbc2.builder.JndiSharedCacheInstanceManager;
+
+/**
+ * {@link JBossCacheRegionFactory} that uses
+ * {@link JndiSharedCacheInstanceManager} as its
+ * {@link #getCacheInstanceManager() CacheInstanceManager}.
+ * <p>
+ * Basically, uses a single shared JBoss Cache for entities, collections,
+ * queries and timestamps. The JBoss Cache instance is found in JNDI
+ * using the value of the {@link JndiSharedCacheInstanceManager#CACHE_RESOURCE_PROP}
+ * configuration property as the name to look up.
+ * </p>
+ *
+ * @author Brian Stansberry
+ * @version $Revision$
+ */
+public class JndiSharedJBossCacheRegionFactory extends JBossCacheRegionFactory {
+
+ /**
+ * FIXME Per the RegionFactory class Javadoc, this constructor version
+ * should not be necessary.
+ *
+ * @param props
+ */
+ public JndiSharedJBossCacheRegionFactory(Properties props) {
+ this();
+ }
+
+ /**
+ * Create a new MultiplexedJBossCacheRegionFactory.
+ *
+ */
+ public JndiSharedJBossCacheRegionFactory() {
+ super(new JndiSharedCacheInstanceManager());
+ }
+
+}
Added: core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/MultiplexedJBossCacheRegionFactory.java
===================================================================
--- core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/MultiplexedJBossCacheRegionFactory.java (rev 0)
+++ core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/MultiplexedJBossCacheRegionFactory.java 2007-10-18 20:08:50 UTC (rev 14101)
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2007, Red Hat Middleware, LLC. All rights reserved.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, v. 2.1. This program is distributed in the
+ * hope that it will be useful, but WITHOUT A WARRANTY; without even the implied
+ * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details. You should have received a
+ * copy of the GNU Lesser General Public License, v.2.1 along with this
+ * distribution; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Red Hat Author(s): Brian Stansberry
+ */
+
+package org.hibernate.cache.jbc2;
+
+import java.util.Properties;
+
+import org.hibernate.cache.jbc2.builder.MultiplexingCacheInstanceManager;
+
+/**
+ * {@link JBossCacheRegionFactory} that uses
+ * {@link MultiplexingCacheInstanceManager} as its
+ * {@link #getCacheInstanceManager() CacheInstanceManager}.
+ * <p>
+ * Supports separate JBoss Cache instances for entity, collection, query
+ * and timestamp caching, with the expectation that a single multiplexed
+ * JGroups channel will be shared between the caches. JBoss Cache instances
+ * are created from a factory.
+ * </p>
+ * <p>
+ * This version instantiates the factory itself. See
+ * {@link MultiplexingCacheInstanceManager} for configuration details.
+ * </p>
+ *
+ * @author Brian Stansberry
+ * @version $Revision$
+ */
+public class MultiplexedJBossCacheRegionFactory extends JBossCacheRegionFactory {
+
+ /**
+ * FIXME Per the RegionFactory class Javadoc, this constructor version
+ * should not be necessary.
+ *
+ * @param props
+ */
+ public MultiplexedJBossCacheRegionFactory(Properties props) {
+ this();
+ }
+
+ /**
+ * Create a new MultiplexedJBossCacheRegionFactory.
+ *
+ */
+ public MultiplexedJBossCacheRegionFactory() {
+ super(new MultiplexingCacheInstanceManager());
+ }
+
+}
Added: core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/SharedJBossCacheRegionFactory.java
===================================================================
--- core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/SharedJBossCacheRegionFactory.java (rev 0)
+++ core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/SharedJBossCacheRegionFactory.java 2007-10-18 20:08:50 UTC (rev 14101)
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2007, Red Hat Middleware, LLC. All rights reserved.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, v. 2.1. This program is distributed in the
+ * hope that it will be useful, but WITHOUT A WARRANTY; without even the implied
+ * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details. You should have received a
+ * copy of the GNU Lesser General Public License, v.2.1 along with this
+ * distribution; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Red Hat Author(s): Brian Stansberry
+ */
+
+package org.hibernate.cache.jbc2;
+
+import java.util.Properties;
+
+import org.hibernate.cache.jbc2.builder.JndiSharedCacheInstanceManager;
+import org.hibernate.cache.jbc2.builder.SharedCacheInstanceManager;
+import org.jboss.cache.DefaultCacheFactory;
+
+/**
+ * {@link JBossCacheRegionFactory} that uses
+ * {@link SharedCacheInstanceManager} as its
+ * {@link #getCacheInstanceManager() CacheInstanceManager}.
+ * <p>
+ * Basically, uses a single shared JBoss Cache for entities, collections,
+ * queries and timestamps. The JBoss Cache instance created by the
+ * JBC {@link DefaultCacheFactory} using the resource identified by the
+ * {@link JndiSharedCacheInstanceManager#CACHE_RESOURCE_PROP}
+ * configuration property.
+ * </p>
+ *
+ * @author Brian Stansberry
+ * @version $Revision$
+ */
+public class SharedJBossCacheRegionFactory extends JBossCacheRegionFactory {
+
+ /**
+ * FIXME Per the RegionFactory class Javadoc, this constructor version
+ * should not be necessary.
+ *
+ * @param props
+ */
+ public SharedJBossCacheRegionFactory(Properties props) {
+ this();
+ }
+
+ /**
+ * Create a new MultiplexedJBossCacheRegionFactory.
+ *
+ */
+ public SharedJBossCacheRegionFactory() {
+ super(new SharedCacheInstanceManager());
+ }
+
+}
Modified: core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/TransactionalDataRegionAdapter.java
===================================================================
--- core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/TransactionalDataRegionAdapter.java 2007-10-18 19:49:17 UTC (rev 14100)
+++ core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/TransactionalDataRegionAdapter.java 2007-10-18 20:08:50 UTC (rev 14101)
@@ -15,36 +15,38 @@
*/
package org.hibernate.cache.jbc2;
+import org.hibernate.cache.CacheDataDescription;
+import org.hibernate.cache.TransactionalDataRegion;
import org.jboss.cache.Cache;
-import org.hibernate.cache.TransactionalDataRegion;
-import org.hibernate.cache.CacheDataDescription;
-
/**
* {@inheritDoc}
- *
+ *
* @author Steve Ebersole
*/
-public class TransactionalDataRegionAdapter extends BasicRegionAdapter implements TransactionalDataRegion {
- protected final CacheDataDescription metadata;
+public abstract class TransactionalDataRegionAdapter extends BasicRegionAdapter implements TransactionalDataRegion {
- public TransactionalDataRegionAdapter(Cache jbcCache, String regionName, CacheDataDescription metadata) {
- super( jbcCache, regionName );
- this.metadata = metadata;
- }
+ protected final CacheDataDescription metadata;
- /**
- * Here, for JBossCache, we consider the cache to be transaction aware if the underlying
- * cache instance has a refernece to the transaction manager.
- */
- public boolean isTransactionAware() {
- return jbcCache.getConfiguration().getRuntimeConfig().getTransactionManager() != null;
- }
+ public TransactionalDataRegionAdapter(Cache jbcCache, String regionName, String regionPrefix,
+ CacheDataDescription metadata) {
+ super(jbcCache, regionName, regionPrefix);
+ this.metadata = metadata;
+ }
- /**
- * {@inheritDoc}
- */
- public CacheDataDescription getCacheDataDescription() {
- return metadata;
- }
+ /**
+ * Here, for JBossCache, we consider the cache to be transaction aware if
+ * the underlying cache instance has a reference to the transaction manager.
+ */
+ public boolean isTransactionAware() {
+ return transactionManager != null;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public CacheDataDescription getCacheDataDescription() {
+ return metadata;
+ }
+
}
Added: core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/access/OptimisticTransactionalAccessDelegate.java
===================================================================
--- core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/access/OptimisticTransactionalAccessDelegate.java (rev 0)
+++ core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/access/OptimisticTransactionalAccessDelegate.java 2007-10-18 20:08:50 UTC (rev 14101)
@@ -0,0 +1,144 @@
+/*
+ * Copyright (c) 2007, Red Hat Middleware, LLC. All rights reserved.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, v. 2.1. This program is distributed in the
+ * hope that it will be useful, but WITHOUT A WARRANTY; without even the implied
+ * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details. You should have received a
+ * copy of the GNU Lesser General Public License, v.2.1 along with this
+ * distribution; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Red Hat Author(s): Brian Stansberry
+ */
+
+package org.hibernate.cache.jbc2.access;
+
+import org.hibernate.cache.CacheDataDescription;
+import org.hibernate.cache.CacheException;
+import org.hibernate.cache.access.CollectionRegionAccessStrategy;
+import org.hibernate.cache.access.EntityRegionAccessStrategy;
+import org.hibernate.cache.jbc2.util.CacheHelper;
+import org.hibernate.cache.jbc2.util.DataVersionAdapter;
+import org.hibernate.cache.jbc2.util.NonLockingDataVersion;
+import org.jboss.cache.Cache;
+import org.jboss.cache.Fqn;
+import org.jboss.cache.config.Option;
+import org.jboss.cache.optimistic.DataVersion;
+
+/**
+ * Defines the strategy for transactional access to entity or collection data in
+ * an optimistic-locking JBoss Cache using its 2.x APIs.
+ * <p>
+ * The intent of this class is to encapsulate common code and serve as a
+ * delegate for {@link EntityRegionAccessStrategy} and
+ * {@link CollectionRegionAccessStrategy} implementations.
+ * </p>
+ *
+ * @author Brian Stansberry
+ * @version $Revision: 1 $
+ */
+public class OptimisticTransactionalAccessDelegate extends TransactionalAccessDelegate {
+
+ protected final CacheDataDescription dataDescription;
+
+ public OptimisticTransactionalAccessDelegate(Cache cache, Fqn regionFqn, CacheDataDescription dataDescription) {
+ super(cache, regionFqn);
+ this.dataDescription = dataDescription;
+ }
+
+ /**
+ * Overrides the
+ * {@link TransactionalAccessDelegate#evict(Object) superclass} by adding a
+ * {@link NonLockingDataVersion} to the invocation.
+ */
+ @Override
+ public void evict(Object key) throws CacheException {
+
+ Option opt = NonLockingDataVersion.getInvocationOption();
+ CacheHelper.remove(cache, regionFqn, key, opt);
+ }
+
+ /**
+ * Overrides the {@link TransactionalAccessDelegate#evictAll() superclass}
+ * by adding a {@link NonLockingDataVersion} to the invocation.
+ */
+ @Override
+ public void evictAll() throws CacheException {
+
+ evictOrRemoveAll();
+ }
+
+ /**
+ * Overrides the
+ * {@link TransactionalAccessDelegate#insert(Object, Object, Object) superclass}
+ * by adding a {@link DataVersion} to the invocation.
+ */
+ @Override
+ public boolean insert(Object key, Object value, Object version) throws CacheException {
+
+ Option opt = getDataVersionOption(version, null);
+ CacheHelper.put(cache, regionFqn, key, value, opt);
+ return true;
+ }
+
+ @Override
+ public boolean putFromLoad(Object key, Object value, long txTimestamp, Object version, boolean minimalPutOverride)
+ throws CacheException {
+
+ // We ignore minimalPutOverride. JBossCache putForExternalRead is
+ // already about as minimal as we can get; it will promptly return
+ // if it discovers that the node we want to write to already exists
+ Option opt = getDataVersionOption(version, version);
+ return CacheHelper.putForExternalRead(cache, regionFqn, key, value, opt);
+ }
+
+ @Override
+ public boolean putFromLoad(Object key, Object value, long txTimestamp, Object version) throws CacheException {
+
+ Option opt = getDataVersionOption(version, version);
+ return CacheHelper.putForExternalRead(cache, regionFqn, key, value, opt);
+ }
+
+ @Override
+ public void remove(Object key) throws CacheException {
+
+ Option opt = NonLockingDataVersion.getInvocationOption();
+ CacheHelper.remove(cache, regionFqn, key, opt);
+ }
+
+ @Override
+ public void removeAll() throws CacheException {
+
+ evictOrRemoveAll();
+ }
+
+ @Override
+ public boolean update(Object key, Object value, Object currentVersion, Object previousVersion)
+ throws CacheException {
+
+ Option opt = getDataVersionOption(currentVersion, previousVersion);
+ CacheHelper.put(cache, regionFqn, key, value, opt);
+ return true;
+ }
+
+ private Option getDataVersionOption(Object currentVersion, Object previousVersion) {
+ DataVersion dv = (dataDescription != null && dataDescription.isVersioned()) ? new DataVersionAdapter(
+ currentVersion, previousVersion, dataDescription.getVersionComparator(), dataDescription.toString())
+ : NonLockingDataVersion.INSTANCE;
+ Option opt = new Option();
+ opt.setDataVersion(dv);
+ return opt;
+ }
+
+ private void evictOrRemoveAll() {
+ Option opt = NonLockingDataVersion.getInvocationOption();
+ CacheHelper.removeAll(cache, regionFqn, opt);
+
+ // Restablish the region root node with a non-locking data version
+ CacheHelper.addNode(cache, regionFqn, false, true, NonLockingDataVersion.INSTANCE);
+ }
+
+}
Property changes on: core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/access/OptimisticTransactionalAccessDelegate.java
___________________________________________________________________
Name: svn:executable
+ *
Added: core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/access/TransactionalAccessDelegate.java
===================================================================
--- core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/access/TransactionalAccessDelegate.java (rev 0)
+++ core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/access/TransactionalAccessDelegate.java 2007-10-18 20:08:50 UTC (rev 14101)
@@ -0,0 +1,124 @@
+/*
+ * Copyright (c) 2007, Red Hat Middleware, LLC. All rights reserved.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, v. 2.1. This program is distributed in the
+ * hope that it will be useful, but WITHOUT A WARRANTY; without even the implied
+ * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details. You should have received a
+ * copy of the GNU Lesser General Public License, v.2.1 along with this
+ * distribution; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Red Hat Author(s): Steve Ebersole
+ */
+package org.hibernate.cache.jbc2.access;
+
+import org.hibernate.cache.CacheException;
+import org.hibernate.cache.access.CollectionRegionAccessStrategy;
+import org.hibernate.cache.access.EntityRegionAccessStrategy;
+import org.hibernate.cache.access.SoftLock;
+import org.hibernate.cache.jbc2.util.CacheHelper;
+import org.jboss.cache.Cache;
+import org.jboss.cache.Fqn;
+
+/**
+ * Defines the strategy for transactional access to entity or collection data in
+ * a pessimistic-locking JBoss Cache using its 2.x APIs.
+ * <p>
+ * The intent of this class is to encapsulate common code and serve as a
+ * delegate for {@link EntityRegionAccessStrategy} and
+ * {@link CollectionRegionAccessStrategy} implementations.
+ * </p>
+ *
+ * @author Brian Stansberry
+ */
+public class TransactionalAccessDelegate {
+
+ protected final Cache cache;
+ protected final Fqn regionFqn;
+
+ public TransactionalAccessDelegate(Cache cache, Fqn regionFqn) {
+ this.cache = cache;
+ this.regionFqn = regionFqn;
+ }
+
+ public Object get(Object key, long txTimestamp) throws CacheException {
+
+ return CacheHelper.get(cache, regionFqn, key);
+ }
+
+ public boolean putFromLoad(Object key, Object value, long txTimestamp, Object version) throws CacheException {
+
+ return CacheHelper.putForExternalRead(cache, regionFqn, key, value);
+ }
+
+ public boolean putFromLoad(Object key, Object value, long txTimestamp, Object version, boolean minimalPutOverride)
+ throws CacheException {
+
+ // We ignore minimalPutOverride. JBossCache putForExternalRead is
+ // already about as minimal as we can get; it will promptly return
+ // if it discovers that the node we want to write to already exists
+ return CacheHelper.putForExternalRead(cache, regionFqn, key, value);
+ }
+
+ public SoftLock lockItem(Object key, Object version) throws CacheException {
+ return null;
+ }
+
+ public SoftLock lockRegion() throws CacheException {
+ return null;
+ }
+
+ public void unlockItem(Object key, SoftLock lock) throws CacheException {
+ }
+
+ public void unlockRegion(SoftLock lock) throws CacheException {
+ }
+
+ public boolean insert(Object key, Object value, Object version) throws CacheException {
+
+ CacheHelper.put(cache, regionFqn, key, value);
+ return true;
+ }
+
+ public boolean afterInsert(Object key, Object value, Object version) throws CacheException {
+ return false;
+ }
+
+ public boolean update(Object key, Object value, Object currentVersion, Object previousVersion)
+ throws CacheException {
+
+ CacheHelper.put(cache, regionFqn, key, value);
+ return true;
+ }
+
+ public boolean afterUpdate(Object key, Object value, Object currentVersion, Object previousVersion, SoftLock lock)
+ throws CacheException {
+ return false;
+ }
+
+ public void remove(Object key) throws CacheException {
+
+ CacheHelper.remove(cache, regionFqn, key);
+ }
+
+ public void removeAll() throws CacheException {
+ evictOrRemoveAll();
+ }
+
+ public void evict(Object key) throws CacheException {
+ CacheHelper.remove(cache, regionFqn, key);
+ }
+
+ public void evictAll() throws CacheException {
+ evictOrRemoveAll();
+ }
+
+ private void evictOrRemoveAll() throws CacheException {
+ CacheHelper.removeAll(cache, regionFqn);
+ // Restore the region root node
+ CacheHelper.addNode(cache, regionFqn, false, true, null);
+ }
+}
Property changes on: core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/access/TransactionalAccessDelegate.java
___________________________________________________________________
Name: svn:executable
+ *
Deleted: core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/builder/InvalidationCacheInstanceManager.java
===================================================================
--- core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/builder/InvalidationCacheInstanceManager.java 2007-10-18 19:49:17 UTC (rev 14100)
+++ core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/builder/InvalidationCacheInstanceManager.java 2007-10-18 20:08:50 UTC (rev 14101)
@@ -1,112 +0,0 @@
-/*
- * Copyright (c) 2007, Red Hat Middleware, LLC. All rights reserved.
- *
- * This copyrighted material is made available to anyone wishing to use, modify,
- * copy, or redistribute it subject to the terms and conditions of the GNU
- * Lesser General Public License, v. 2.1. This program is distributed in the
- * hope that it will be useful, but WITHOUT A WARRANTY; without even the implied
- * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details. You should have received a
- * copy of the GNU Lesser General Public License, v.2.1 along with this
- * distribution; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * Red Hat Author(s): Steve Ebersole
- */
-package org.hibernate.cache.jbc2.builder;
-
-import java.util.Properties;
-import javax.transaction.TransactionManager;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.jboss.cache.Cache;
-import org.jboss.cache.DefaultCacheFactory;
-
-import org.hibernate.cache.CacheException;
-import org.hibernate.cache.jbc2.CacheInstanceManager;
-import org.hibernate.cache.jbc2.util.CacheModeHelper;
-import org.hibernate.cfg.Settings;
-import org.hibernate.util.PropertiesHelper;
-
-/**
- * A {@link CacheInstanceManager} implementation where we use a single cache instance
- * we assume to be configured for invalidation if operating on a cluster. Under that
- * assumption, we can store all data into the same {@link Cache} instance.
- * <p/>
- * todo : this is built on the assumption that JBC clustered invalidation is changed to keep the "cache node" around on the other "cluster nodes"
- *
- * @author Steve Ebersole
- */
-public class InvalidationCacheInstanceManager implements CacheInstanceManager {
- public static final String CACHE_RESOURCE_PROP = "hibernate.cache.region.jbc2.cfg.invalidation";
- public static final String DEFAULT_CACHE_RESOURCE = "treecache.xml";
-
- private static final Logger log = LoggerFactory.getLogger( InvalidationCacheInstanceManager.class );
-
- private final Cache cache;
-
- public InvalidationCacheInstanceManager(Settings settings, Properties properties) {
- String configResource = PropertiesHelper.getString( CACHE_RESOURCE_PROP, properties, DEFAULT_CACHE_RESOURCE );
- cache = DefaultCacheFactory.getInstance().createCache( configResource, false );
- if ( settings.getTransactionManagerLookup() != null ) {
- TransactionManager tm = settings.getTransactionManagerLookup().getTransactionManager( properties );
- if ( tm != null ) {
- cache.getConfiguration().getRuntimeConfig().setTransactionManager( tm );
- }
- }
- cache.start();
- }
-
- public InvalidationCacheInstanceManager(Cache cache) {
- this.cache = cache;
- }
-
- /**
- * {@inheritDoc}
- */
- public Cache getEntityCacheInstance() {
- return cache;
- }
-
- /**
- * {@inheritDoc}
- */
- public Cache getCollectionCacheInstance() {
- return cache;
- }
-
- /**
- * {@inheritDoc}
- */
- public Cache getQueryCacheInstance() {
- if ( CacheModeHelper.isClusteredInvalidation( cache ) ) {
- throw new CacheException( "Query cache not supported for clustered invalidation" );
- }
- return cache;
- }
-
- /**
- * {@inheritDoc}
- */
- public Cache getTimestampsCacheInstance() {
- if ( CacheModeHelper.isClusteredInvalidation( cache ) ) {
- throw new CacheException( "Query cache not supported for clustered invalidation" );
- }
- return cache;
- }
-
- /**
- * {@inheritDoc}
- */
- public void release() {
- if ( cache != null ) {
- try {
- cache.stop();
- }
- catch( Throwable t ) {
- log.warn( "Unable to stop cache instance", t );
- }
- }
- }
-}
Added: core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/builder/JBossCacheFactory.java
===================================================================
--- core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/builder/JBossCacheFactory.java (rev 0)
+++ core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/builder/JBossCacheFactory.java 2007-10-18 20:08:50 UTC (rev 14101)
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2007, Red Hat Middleware, LLC. All rights reserved.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, v. 2.1. This program is distributed in the
+ * hope that it will be useful, but WITHOUT A WARRANTY; without even the implied
+ * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details. You should have received a
+ * copy of the GNU Lesser General Public License, v.2.1 along with this
+ * distribution; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Red Hat Author(s): Brian Stansberry
+ */
+
+package org.hibernate.cache.jbc2.builder;
+
+import java.util.Set;
+
+import org.jboss.cache.Cache;
+
+/**
+ * Factory and registry for JBoss Cache instances configured using
+ * named configurations.
+ *
+ * @author <a href="brian.stansberry(a)jboss.com">Brian Stansberry</a>
+ * @version $Revision: 1 $
+ */
+public interface JBossCacheFactory {
+
+ /**
+ * Gets all the names of all the configurations of which this object
+ * is aware.
+ *
+ * @return
+ */
+ Set getConfigurationNames();
+
+ /**
+ * Get a cache configured according to the given configuration name.
+ * <p>
+ * The caller is free to invoke the {@link Cache#create()} and
+ * {@link Cache#start()} lifecycle methods on the returned cache, but
+ * the @link Cache#stop()} and {@link Cache#destroy()} methods should not
+ * be invoked, since it is quite possible other session factories are
+ * still using the cache. Use {@link #releaseCache(String)} to notify this
+ * factory that the caller is no longer using a cache; let the factory
+ * control stopping and destroying the underlying cache.
+ * </p>
+ *
+ * @param configName the name of the configuration
+ * @param create should the cache be instantiated if it
+ * hasn't already been?
+ * @return the cache, or <code>null</code> if
+ * <code>create</code> is false and the cache hasn't
+ * been created previously.
+ *
+ * @throws IllegalArgumentException if this object is unaware of
+ * <code>configName</code>
+ * @throws Exception if there is a problem instantiating the cache
+ */
+ Cache getCache(String configName, boolean create) throws Exception;
+
+ /**
+ * Notifies the factory that the caller is no longer using the given
+ * cache. The factory may perform cleanup operations, such as
+ * stopping and destroying the cache.
+ *
+ * @param configName
+ */
+ void releaseCache(String configName);
+
+}
\ No newline at end of file
Added: core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/builder/JBossCacheFactoryImpl.java
===================================================================
--- core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/builder/JBossCacheFactoryImpl.java (rev 0)
+++ core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/builder/JBossCacheFactoryImpl.java 2007-10-18 20:08:50 UTC (rev 14101)
@@ -0,0 +1,361 @@
+/*
+ * Copyright (c) 2007, Red Hat Middleware, LLC. All rights reserved.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, v. 2.1. This program is distributed in the
+ * hope that it will be useful, but WITHOUT A WARRANTY; without even the implied
+ * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details. You should have received a
+ * copy of the GNU Lesser General Public License, v.2.1 along with this
+ * distribution; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Red Hat Author(s): Brian Stansberry
+ */
+
+package org.hibernate.cache.jbc2.builder;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.InputStream;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
+import java.util.Map.Entry;
+
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+
+import org.hibernate.cache.CacheException;
+import org.jboss.cache.Cache;
+import org.jboss.cache.CacheStatus;
+import org.jboss.cache.DefaultCacheFactory;
+import org.jboss.cache.config.Configuration;
+import org.jboss.cache.config.ConfigurationException;
+import org.jboss.cache.xml.XmlHelper;
+import org.jgroups.ChannelFactory;
+import org.jgroups.JChannelFactory;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.w3c.dom.DOMImplementation;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+import org.w3c.dom.ls.DOMImplementationLS;
+import org.w3c.dom.ls.LSOutput;
+import org.w3c.dom.ls.LSSerializer;
+
+/**
+ * A JBossCacheConfigurationFactory. This is a basic prototype of a
+ * JBCACHE-1156 solution; only in Hibernate code base for a very short
+ * period.
+ *
+ * @author <a href="brian.stansberry(a)jboss.com">Brian Stansberry</a>
+ * @version $Revision: 1 $
+ */
+public class JBossCacheFactoryImpl implements JBossCacheFactory {
+
+ private static final Logger log = LoggerFactory.getLogger(JBossCacheFactoryImpl.class);
+
+ private static final String DOCUMENT_ROOT = "cache-configs";
+ private static final String CONFIG_ROOT = "cache-config";
+ private static final String CONFIG_NAME = "name";
+
+ private static JBossCacheFactoryImpl sharedFactory;
+ private static String sharedChannelFactoryCfg;
+
+ private XmlConfigurationParser parser;
+ private String configResource;
+ private Map configs = new HashMap();
+ private Map caches = new HashMap();
+ private Map checkouts = new HashMap();
+ private ChannelFactory channelFactory;
+ private boolean started;
+
+ public JBossCacheFactoryImpl(String configResource, ChannelFactory factory) {
+
+ parser = new XmlConfigurationParser();
+ this.configResource = configResource;
+ this.channelFactory = factory;
+ }
+
+ public static synchronized JBossCacheFactory getSharedInstance(String cacheConfigResource, String channelFactoryConfigResource) {
+
+ if (sharedFactory == null) {
+ ChannelFactory cf = new JChannelFactory();
+ try {
+ cf.setMultiplexerConfig(channelFactoryConfigResource);
+ }
+ catch (Exception e) {
+ throw new CacheException("Problem setting ChannelFactory config", e);
+ }
+ sharedFactory = new JBossCacheFactoryImpl(cacheConfigResource, cf);
+ sharedChannelFactoryCfg = channelFactoryConfigResource;
+ }
+ else {
+ // Validate that the provided resources match the existing singleton
+ if (!sharedFactory.getConfigResource().equals(cacheConfigResource)) {
+ throw new CacheException("Provided cacheConfigResource does " +
+ "not match the existing shared factory: provided = " +
+ cacheConfigResource + "; existing = " + sharedFactory.getConfigResource());
+ }
+ else if (!sharedChannelFactoryCfg.equals(channelFactoryConfigResource)) {
+ throw new IllegalStateException("Provided channelFactoryConfigResource does " +
+ "not match the existing shared factory: provided = " +
+ channelFactoryConfigResource + "; existing = " + sharedChannelFactoryCfg);
+
+ }
+ }
+
+ return sharedFactory;
+ }
+
+ public void start() {
+ if (!started) {
+ this.configs = parser.parseConfigs(configResource);
+ started = true;
+ }
+ }
+
+ public void stop() {
+ if (started) {
+ synchronized (caches) {
+ for (Iterator it = caches.entrySet().iterator(); it.hasNext(); ) {
+ Map.Entry entry = (Entry) it.next();
+ destroyCache((Cache) entry.getValue());
+ it.remove();
+ }
+ caches.clear();
+ checkouts.clear();
+ configs.clear();
+ }
+ started = false;
+ }
+ }
+
+ public String getConfigResource() {
+ return configResource;
+ }
+
+ public ChannelFactory getChannelFactory() {
+ return channelFactory;
+ }
+
+ public Set getConfigurationNames()
+ {
+ return new HashSet(configs.keySet());
+ }
+
+ public Cache getCache(String configName, boolean create) throws Exception
+ {
+ Cache cache = null;
+ synchronized (caches) {
+ cache = (Cache) caches.get(configName);
+ if (cache == null && create) {
+ Configuration config = getConfiguration(configName);
+ cache = DefaultCacheFactory.getInstance().createCache(config, false);
+ registerCache(cache, configName);
+ }
+ else if (cache != null) {
+ incrementCheckout(configName);
+ }
+ }
+
+ return cache;
+ }
+
+ private int incrementCheckout(String configName) {
+ synchronized (checkouts) {
+ Integer count = (Integer) checkouts.get(configName);
+ if (count == null)
+ count = new Integer(0);
+ Integer newVal = new Integer(count.intValue() + 1);
+ checkouts.put(configName, newVal);
+ return newVal.intValue();
+ }
+ }
+
+ private int decrementCheckout(String configName) {
+ synchronized (checkouts) {
+ Integer count = (Integer) checkouts.get(configName);
+ if (count == null || count.intValue() < 1)
+ throw new IllegalStateException("invalid count of " + count + " for " + configName);
+
+ Integer newVal = new Integer(count.intValue() - 1);
+ checkouts.put(configName, newVal);
+ return newVal.intValue();
+ }
+ }
+
+ public void registerCache(Cache cache, String configName) {
+ synchronized (caches) {
+ if (caches.containsKey(configName))
+ throw new IllegalStateException(configName + " already registered");
+ caches.put(configName, cache);
+ incrementCheckout(configName);
+ }
+ }
+
+ public void releaseCache(String configName) {
+
+ synchronized (caches) {
+ if (!caches.containsKey(configName))
+ throw new IllegalStateException(configName + " not registered");
+ if (decrementCheckout(configName) == 0) {
+ Cache cache = (Cache) caches.remove(configName);
+ destroyCache(cache);
+ }
+ }
+ }
+
+ private void destroyCache(Cache cache) {
+ if (cache.getCacheStatus() == CacheStatus.STARTED) {
+ cache.stop();
+ }
+ if (cache.getCacheStatus() != CacheStatus.DESTROYED
+ && cache.getCacheStatus() != CacheStatus.INSTANTIATED) {
+ cache.destroy();
+ }
+ }
+
+ public Configuration getConfiguration(String configName) throws Exception {
+ Element element = (Element) configs.get(configName);
+ if (element == null)
+ throw new IllegalArgumentException("unknown config " + configName);
+ Configuration config = parser.parseConfig(element);
+ if (channelFactory != null && config.getMultiplexerStack() != null) {
+ config.getRuntimeConfig().setMuxChannelFactory(channelFactory);
+ }
+ return config;
+ }
+
+ class XmlConfigurationParser extends org.jboss.cache.factories.XmlConfigurationParser {
+
+ public Map parseConfigs(String configs) {
+ InputStream is = getAsInputStreamFromClassLoader(configs);
+ if (is == null)
+ {
+ if (log.isDebugEnabled())
+ log.debug("Unable to find configuration file " + configs + " in classpath; searching for this file on the filesystem instead.");
+ try
+ {
+ is = new FileInputStream(configs);
+ }
+ catch (FileNotFoundException e)
+ {
+ throw new ConfigurationException("Unable to find config file " + configs + " either in classpath or on the filesystem!", e);
+ }
+ }
+
+ return parseConfigs(is);
+ }
+
+ public Map parseConfigs(InputStream stream) {
+
+ // loop through all elements in XML.
+ Element root = XmlHelper.getDocumentRoot(stream);
+ NodeList list = root.getElementsByTagName(CONFIG_ROOT);
+ if (list == null || list.getLength() == 0)
+ throw new ConfigurationException("Can't find " + CONFIG_ROOT + " tag");
+
+ Map result = new HashMap();
+
+ for (int i = 0; i < list.getLength(); i++)
+ {
+ org.w3c.dom.Node node = list.item(i);
+ if (node.getNodeType() != org.w3c.dom.Node.ELEMENT_NODE)
+ {
+ continue;
+ }
+
+ Element element = (Element) node;
+ String name = element.getAttribute(CONFIG_NAME);
+ if (name == null || name.trim().length() == 0)
+ throw new ConfigurationException("Element " + element + " has no name attribute");
+
+ result.put(name.trim(), element);
+ }
+
+ return result;
+ }
+
+ public Configuration parseConfig(Element config) throws Exception {
+
+ DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory.newInstance();
+ DocumentBuilder builder = docBuilderFactory.newDocumentBuilder();
+ Document doc = builder.newDocument();
+ Element root = doc.createElement(DOCUMENT_ROOT);
+ doc.appendChild(root);
+ Node imported = doc.importNode(config, true);
+ root.appendChild(imported);
+
+ DOMImplementation domImpl = doc.getImplementation();
+
+ DOMImplementationLS impl =
+ (DOMImplementationLS)domImpl.getFeature("LS", "3.0");
+
+ LSSerializer writer = impl.createLSSerializer();
+ LSOutput output = impl.createLSOutput();
+ output.setEncoding("UTF-8");
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ output.setByteStream(baos);
+ writer.write(doc, output);
+
+ ByteArrayInputStream is = new ByteArrayInputStream(baos.toByteArray());
+ return parseStream(is);
+ }
+
+
+ @Override
+ protected Element getMBeanElement(Element root)
+ {
+ // This is following JBoss convention.
+ NodeList list = root.getElementsByTagName(CONFIG_ROOT);
+ if (list == null) throw new ConfigurationException("Can't find " + CONFIG_ROOT + " tag");
+
+ if (list.getLength() > 1) throw new ConfigurationException("Has multiple " + CONFIG_ROOT + " tag");
+
+ Node node = list.item(0);
+ Element element = null;
+ if (node.getNodeType() == org.w3c.dom.Node.ELEMENT_NODE)
+ {
+ element = (Element) node;
+ }
+ else
+ {
+ throw new ConfigurationException("Can't find " + CONFIG_ROOT + " element");
+ }
+ return element;
+ }
+
+
+ }
+
+ public static void main(String[] args)
+ {
+ try
+ {
+ JChannelFactory cf = new JChannelFactory();
+ cf.setMultiplexerConfig("stacks.xml");
+ JBossCacheFactoryImpl factory = new JBossCacheFactoryImpl("jbc2-configs.xml", cf);
+ for (Iterator iter = factory.getConfigurationNames().iterator(); iter.hasNext(); )
+ {
+ String name = (String) iter.next();
+ Cache c = factory.getCache(name, true);
+ c.start();
+ System.out.println(name + " == " + c);
+ factory.releaseCache(name);
+ System.out.println(name + " == " + c.getCacheStatus());
+ }
+ } catch (Exception e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace(System.out);
+ }
+ }
+}
Added: core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/builder/JndiMultiplexingCacheInstanceManager.java
===================================================================
--- core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/builder/JndiMultiplexingCacheInstanceManager.java (rev 0)
+++ core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/builder/JndiMultiplexingCacheInstanceManager.java 2007-10-18 20:08:50 UTC (rev 14101)
@@ -0,0 +1,95 @@
+/*
+ * Copyright (c) 2007, Red Hat Middleware, LLC. All rights reserved.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, v. 2.1. This program is distributed in the
+ * hope that it will be useful, but WITHOUT A WARRANTY; without even the implied
+ * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details. You should have received a
+ * copy of the GNU Lesser General Public License, v.2.1 along with this
+ * distribution; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Red Hat Author(s): Brian Stansberry
+ */
+
+package org.hibernate.cache.jbc2.builder;
+
+import java.util.Properties;
+
+import javax.naming.Context;
+import javax.naming.InitialContext;
+import javax.naming.NamingException;
+
+import org.hibernate.cache.CacheException;
+import org.hibernate.cfg.Settings;
+import org.hibernate.util.NamingHelper;
+import org.hibernate.util.PropertiesHelper;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+
+/**
+ * A {@link MultiplexingCacheInstanceManager} that finds its cache factory
+ * in JNDI rather than creating one itself.
+ *
+ * @author <a href="brian.stansberry(a)jboss.com">Brian Stansberry</a>
+ * @version $Revision: 1 $
+ */
+public class JndiMultiplexingCacheInstanceManager extends MultiplexingCacheInstanceManager {
+
+ private static final Logger log = LoggerFactory.getLogger(JndiMultiplexingCacheInstanceManager.class);
+
+ /**
+ * Specifies the JNDI name under which the {@link JBossCacheFactory} to use is bound.
+ * There is no default value -- the user must specify the property.
+ */
+ public static final String CACHE_FACTORY_RESOURCE_PROP = "hibernate.cache.region.jbc2.cachefactory";
+
+ /**
+ * Create a new JndiMultiplexingCacheInstanceManager.
+ */
+ public JndiMultiplexingCacheInstanceManager() {
+ super();
+ }
+
+ @Override
+ public void start(Settings settings, Properties properties) throws CacheException {
+
+ String name = PropertiesHelper.getString(CACHE_FACTORY_RESOURCE_PROP, properties, null);
+ if (name == null)
+ throw new CacheException("Configuration property " + CACHE_FACTORY_RESOURCE_PROP + " not set");
+
+ JBossCacheFactory cf = locateCacheFactory( name, NamingHelper.getJndiProperties( properties ) );
+ setCacheFactory( cf );
+
+ super.start(settings, properties);
+ }
+
+ private JBossCacheFactory locateCacheFactory(String jndiNamespace, Properties jndiProperties) {
+
+ Context ctx = null;
+ try {
+ ctx = new InitialContext( jndiProperties );
+ return (JBossCacheFactory) ctx.lookup( jndiNamespace );
+ }
+ catch (NamingException ne) {
+ String msg = "Unable to retreive Cache from JNDI [" + jndiNamespace + "]";
+ log.info( msg, ne );
+ throw new CacheException( msg );
+ }
+ finally {
+ if ( ctx != null ) {
+ try {
+ ctx.close();
+ }
+ catch( NamingException ne ) {
+ log.info( "Unable to release initial context", ne );
+ }
+ }
+ }
+ }
+
+
+}
Added: core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/builder/JndiSharedCacheInstanceManager.java
===================================================================
--- core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/builder/JndiSharedCacheInstanceManager.java (rev 0)
+++ core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/builder/JndiSharedCacheInstanceManager.java 2007-10-18 20:08:50 UTC (rev 14101)
@@ -0,0 +1,105 @@
+/*
+ * Copyright (c) 2007, Red Hat Middleware, LLC. All rights reserved.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, v. 2.1. This program is distributed in the
+ * hope that it will be useful, but WITHOUT A WARRANTY; without even the implied
+ * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details. You should have received a
+ * copy of the GNU Lesser General Public License, v.2.1 along with this
+ * distribution; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Red Hat Author(s): Brian Stansberry
+ */
+
+package org.hibernate.cache.jbc2.builder;
+
+import java.util.Properties;
+
+import javax.naming.Context;
+import javax.naming.InitialContext;
+import javax.naming.NamingException;
+
+import org.hibernate.cache.CacheException;
+import org.hibernate.cfg.Settings;
+import org.hibernate.util.NamingHelper;
+import org.hibernate.util.PropertiesHelper;
+import org.jboss.cache.Cache;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * A {@link SharedCacheInstanceManager} that finds the shared cache in JNDI
+ * rather than instantiating one from an XML config file.
+ *
+ * @author <a href="brian.stansberry(a)jboss.com">Brian Stansberry</a>
+ * @version $Revision: 1 $
+ */
+public class JndiSharedCacheInstanceManager extends SharedCacheInstanceManager {
+
+ private static final Logger log = LoggerFactory.getLogger(JndiSharedCacheInstanceManager.class);
+
+ /**
+ * Specifies the JNDI name under which the {@link Cache} to use is bound.
+ * <p>
+ * Note that although this configuration property has the same name as that by
+ * in {@link SharedCacheInstanceManager#CACHE_RESOURCE_PROP the superclass},
+ * the meaning here is different. Note also that in this class' usage
+ * of the property, there is no default value -- the user must specify
+ * the property.
+ */
+ public static final String CACHE_RESOURCE_PROP = "hibernate.cache.region.jbc2.cfg.shared";
+
+ /**
+ * Create a new JndiSharedCacheInstanceManager.
+ *
+ */
+ public JndiSharedCacheInstanceManager() {
+ super();
+ }
+
+ @Override
+ protected Cache createSharedCache(Settings settings, Properties properties) {
+
+ String name = PropertiesHelper.getString(CACHE_RESOURCE_PROP, properties, null);
+ if (name == null)
+ throw new CacheException("Configuration property " + CACHE_RESOURCE_PROP + " not set");
+
+ return locateCache( name, NamingHelper.getJndiProperties( properties ) );
+ }
+
+ /**
+ * No-op; we don't own the cache so we shouldn't stop it.
+ */
+ @Override
+ protected void stopSharedCache(Cache cache) {
+ // no-op. We don't own the cache so we shouldn't stop it.
+ }
+
+ private Cache locateCache(String jndiNamespace, Properties jndiProperties) {
+
+ Context ctx = null;
+ try {
+ ctx = new InitialContext( jndiProperties );
+ return (Cache) ctx.lookup( jndiNamespace );
+ }
+ catch (NamingException ne) {
+ String msg = "Unable to retreive Cache from JNDI [" + jndiNamespace + "]";
+ log.info( msg, ne );
+ throw new CacheException( msg );
+ }
+ finally {
+ if ( ctx != null ) {
+ try {
+ ctx.close();
+ }
+ catch( NamingException ne ) {
+ log.info( "Unable to release initial context", ne );
+ }
+ }
+ }
+ }
+
+}
Modified: core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/builder/MultiplexingCacheInstanceManager.java
===================================================================
--- core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/builder/MultiplexingCacheInstanceManager.java 2007-10-18 19:49:17 UTC (rev 14100)
+++ core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/builder/MultiplexingCacheInstanceManager.java 2007-10-18 20:08:50 UTC (rev 14101)
@@ -19,188 +19,442 @@
import javax.transaction.TransactionManager;
import org.jboss.cache.Cache;
-import org.jboss.cache.DefaultCacheFactory;
+import org.jboss.cache.CacheStatus;
+import org.jboss.cache.config.Configuration;
+import org.jgroups.ChannelFactory;
+import org.jgroups.JChannelFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.hibernate.cache.CacheException;
import org.hibernate.cache.jbc2.CacheInstanceManager;
import org.hibernate.cfg.Settings;
+import org.hibernate.transaction.TransactionManagerLookup;
import org.hibernate.util.PropertiesHelper;
/**
- * Here we build separate {@link Cache} instances for each type of region, but
- * using the jgroups multiplexer under the covers to re-use the same group
- * communication stack.
- * <p/>
- * todo : this can get simplified once JBC implemants their "configuration factory" (the stuff akin to channel factory) - http://jira.jboss.com/jira/browse/JBCACHE-1156
+ * Allows building separate {@link Cache} instances for each type of region, but
+ * supports using the JGroups multiplexer under the covers to re-use the same group
+ * communication stack. <p/> todo : replace the prototype cache factory with
+ * the equivalent JBoss Cache solution from
+ * http://jira.jboss.com/jira/browse/JBCACHE-1156
*
* @author Steve Ebersole
+ * @author Brian Stansberry
*/
public class MultiplexingCacheInstanceManager implements CacheInstanceManager {
- public static final String ENTITY_CACHE_RESOURCE_PROP = "hibernate.cache.region.jbc2.cfg.entity";
- public static final String COLL_CACHE_RESOURCE_PROP = "hibernate.cache.region.jbc2.cfg.collection";
- public static final String TS_CACHE_RESOURCE_PROP = "hibernate.cache.region.jbc2.cfg.ts";
- public static final String QUERY_CACHE_RESOURCE_PROP = "hibernate.cache.region.jbc2.cfg.query";
- public static final String DEF_ENTITY_RESOURCE = "entity-cache.xml";
- public static final String DEF_COLL_RESOURCE = "collection-cache.xml";
- public static final String DEF_TS_RESOURCE = "ts-cache.xml";
- public static final String DEF_QUERY_RESOURCE = "query-cache.xml";
+ private static final Logger log = LoggerFactory.getLogger(MultiplexingCacheInstanceManager.class);
+
+ /**
+ * Classpath or filesystem resource identifying containing JBoss Cache
+ * configurations the factory should use.
+ *
+ * @see #DEF_CACHE_FACTORY_RESOURCE
+ */
+ public static final String CACHE_FACTORY_RESOURCE_PROP = "hibernate.cache.region.jbc2.configs";
+ /**
+ * Classpath or filesystem resource identifying containing JGroups protocol
+ * stack configurations the <code>org.jgroups.ChannelFactory</code>
+ * should use.
+ *
+ * @see #DEF_MULTIPLEXER_RESOURCE
+ */
+ public static final String CHANNEL_FACTORY_RESOURCE_PROP = "hibernate.cache.region.jbc2.multiplexer.stacks";
+
+ /**
+ * Name of the configuration that should be used for entity caches.
+ *
+ * @see #DEF_ENTITY_RESOURCE
+ */
+ public static final String ENTITY_CACHE_RESOURCE_PROP = "hibernate.cache.region.jbc2.cfg.entity";
+ /**
+ * Name of the configuration that should be used for collection caches.
+ * No default value, as by default we try to use the same JBoss Cache
+ * instance we use for entity caching.
+ *
+ * @see #ENTITY_CACHE_RESOURCE_PROP
+ * @see #DEF_ENTITY_RESOURCE
+ */
+ public static final String COLLECTION_CACHE_RESOURCE_PROP = "hibernate.cache.region.jbc2.cfg.collection";
+ /**
+ * Name of the configuration that should be used for timestamp caches.
+ *
+ * @see #DEF_TS_RESOURCE
+ */
+ public static final String TIMESTAMP_CACHE_RESOURCE_PROP = "hibernate.cache.region.jbc2.cfg.ts";
+ /**
+ * Name of the configuration that should be used for query caches.
+ *
+ * @see #DEF_QUERY_RESOURCE
+ */
+ public static final String QUERY_CACHE_RESOURCE_PROP = "hibernate.cache.region.jbc2.cfg.query";
- public static final String OPTIMISTIC_LOCKING_SCHEME = "OPTIMISTIC";
+ /**
+ * Default value for {@link #CACHE_FACTORY_RESOURCE_PROP}. Specifies
+ * the "jbc2-configs.xml" file in this package.
+ */
+ public static final String DEF_CACHE_FACTORY_RESOURCE = "org/hibernate/cache/jbc2/builder/jbc2-configs.xml";
+ /**
+ * Default value for {@link #CHANNEL_FACTORY_RESOURCE_PROP}. Specifies
+ * "stacks.xml", which can be found in the root of the JGroups jar file.
+ * Thus, leaving this value at default means using the default protocol
+ * stack configs provided by JGroups.
+ */
+ public static final String DEF_MULTIPLEXER_RESOURCE = "stacks.xml";
+ /**
+ * Default value for {@link #ENTITY_CACHE_RESOURCE_PROP}.
+ */
+ public static final String DEF_ENTITY_RESOURCE = "optimistic-entity";
+ /**
+ * Default value for {@link #TIMESTAMP_CACHE_RESOURCE_PROP}.
+ */
+ public static final String DEF_TS_RESOURCE = "timestamps-cache";
+ /**
+ * Default value for {@link #ENTITY_CACHE_RESOURCE_PROP}.
+ */
+ public static final String DEF_QUERY_RESOURCE = "local-query";
- private static final Logger log = LoggerFactory.getLogger( MultiplexingCacheInstanceManager.class );
+ /** Cache for entities */
+ private Cache jbcEntityCache;
+ /** Cache for collections */
+ private Cache jbcCollectionCache;
+ /** Cache for timestamps */
+ private Cache jbcTsCache;
+ /** Cache for queries */
+ private Cache jbcQueryCache;
+ /** Name of config used for entities. */
+ private String entityConfig = null;
+ /** Name of config used for collections. */
+ private String collectionConfig = null;
+ /** Name of config used for queries. */
+ private String queryConfig = null;
+ /** Name of config used for timestamps. */
+ private String tsConfig = null;
+
+ /** Our cache factory */
+ private JBossCacheFactory jbcFactory;
+ /** Our channel factory */
+ private ChannelFactory channelFactory;
+ /**
+ * Did we create the factory ourself and thus can assume we are not
+ * sharing it (and the caches) with other users?
+ */
+ private boolean selfCreatedFactory;
- private final Cache jbcEntityCache;
- private final Cache jbcCollectionCache;
- private final Cache jbcTsCache;
- private final Cache jbcQueryCache;
+ /**
+ * Create a new MultiplexingCacheInstanceManager.
+ */
+ public MultiplexingCacheInstanceManager() {
+ }
+
+ /**
+ * Create a new MultiplexingCacheInstanceManager using the provided
+ * {@link Cache}s.
+ * <p>
+ * If this constructor is used, the {@link #start(Settings, Properties)}
+ * method will make no attempt to create a cache factory or obtain caches
+ * from it. Only the <code>Cache</code>s passed as arguments to this
+ * constructor will be available.
+ * </p>
+ *
+ */
+ public MultiplexingCacheInstanceManager(Cache jbcEntityCache, Cache jbcCollectionCache,
+ Cache jbcTsCache, Cache jbcQueryCache) {
+
+ this.jbcEntityCache = jbcEntityCache;
+ this.jbcCollectionCache = jbcCollectionCache;
+ this.jbcTsCache = jbcTsCache;
+ this.jbcQueryCache = jbcQueryCache;
+ }
+
+ /**
+ * Gets the cache factory.
+ */
+ public JBossCacheFactory getCacheFactory() {
+ return jbcFactory;
+ }
- public MultiplexingCacheInstanceManager(Settings settings, Properties properties) {
- try {
- TransactionManager tm = settings.getTransactionManagerLookup() == null
- ? null
- : settings.getTransactionManagerLookup().getTransactionManager( properties );
- if ( settings.isSecondLevelCacheEnabled() ) {
- jbcEntityCache = buildEntityRegionCacheInstance( properties );
- jbcCollectionCache = buildCollectionRegionCacheInstance( properties );
- if ( tm != null ) {
- jbcEntityCache.getConfiguration().getRuntimeConfig().setTransactionManager( tm );
- jbcCollectionCache.getConfiguration().getRuntimeConfig().setTransactionManager( tm );
- }
- }
- else {
- jbcEntityCache = null;
- jbcCollectionCache = null;
- }
- if ( settings.isQueryCacheEnabled() ) {
- jbcTsCache = buildTsRegionCacheInstance( properties );
- jbcQueryCache = buildQueryRegionCacheInstance( properties );
- }
- else {
- jbcTsCache = null;
- jbcQueryCache = null;
- }
- }
- catch( CacheException ce ) {
- throw ce;
- }
- catch( Throwable t ) {
- throw new CacheException( "Unable to start region factory", t );
- }
- }
+ /**
+ * Sets the cache factory.
+ * @param cacheFactory the cache factory
+ */
+ public void setCacheFactory(JBossCacheFactory factory) {
+ this.jbcFactory = factory;
+ }
+
+ /**
+ * Gets the channel factory.
+ */
+ public ChannelFactory getChannelFactory() {
+ return channelFactory;
+ }
+
+ /**
+ * Set the channel factory.
+ *
+ * @param factory the channel factory
+ */
+ public void setChannelFactory(ChannelFactory factory) {
+ this.channelFactory = factory;
+ }
- public MultiplexingCacheInstanceManager(Cache jbcEntityCache, Cache jbcCollectionCache, Cache jbcTsCache, Cache jbcQueryCache) {
- this.jbcEntityCache = jbcEntityCache;
- this.jbcCollectionCache = jbcCollectionCache;
- this.jbcTsCache = jbcTsCache;
- this.jbcQueryCache = jbcQueryCache;
- }
+ /**
+ * {@inheritDoc}
+ */
+ public Cache getEntityCacheInstance() {
+ return jbcEntityCache;
+ }
- protected Cache buildEntityRegionCacheInstance(Properties properties) {
- try {
- String configResource = PropertiesHelper.getString( ENTITY_CACHE_RESOURCE_PROP, properties, DEF_ENTITY_RESOURCE );
- return DefaultCacheFactory.getInstance().createCache( configResource );
- }
- catch( Throwable t ) {
- throw new CacheException( "unable to build entity region cache instance", t );
- }
- }
+ /**
+ * {@inheritDoc}
+ */
+ public Cache getCollectionCacheInstance() {
+ return jbcCollectionCache;
+ }
- protected Cache buildCollectionRegionCacheInstance(Properties properties) {
- try {
- String configResource = PropertiesHelper.getString( COLL_CACHE_RESOURCE_PROP, properties, DEF_COLL_RESOURCE );
- return DefaultCacheFactory.getInstance().createCache( configResource );
- }
- catch( Throwable t ) {
- throw new CacheException( "unable to build collection region cache instance", t );
- }
- }
+ /**
+ * {@inheritDoc}
+ */
+ public Cache getQueryCacheInstance() {
+ return jbcQueryCache;
+ }
- protected Cache buildTsRegionCacheInstance(Properties properties) {
- try {
- String configResource = PropertiesHelper.getString( TS_CACHE_RESOURCE_PROP, properties, DEF_TS_RESOURCE );
- return DefaultCacheFactory.getInstance().createCache( configResource );
- }
- catch( Throwable t ) {
- throw new CacheException( "unable to build timestamps region cache instance", t );
- }
- }
+ /**
+ * {@inheritDoc}
+ */
+ public Cache getTimestampsCacheInstance() {
+ return jbcTsCache;
+ }
- protected Cache buildQueryRegionCacheInstance(Properties properties) {
- try {
- String configResource = PropertiesHelper.getString( QUERY_CACHE_RESOURCE_PROP, properties, DEF_QUERY_RESOURCE );
- return DefaultCacheFactory.getInstance().createCache( configResource );
- }
- catch( Throwable t ) {
- throw new CacheException( "unable to build query region cache instance", t );
- }
- }
+ /**
+ * {@inheritDoc}
+ */
+ public void start(Settings settings, Properties properties) throws CacheException {
+ try {
+ // We need our tm, so get it now and avoid doing other work
+ // if there is a problem
+ TransactionManagerLookup tml = settings.getTransactionManagerLookup();
+ TransactionManager tm = (tml == null ? null : tml.getTransactionManager(properties));
- /**
- * {@inheritDoc}
- */
- public Cache getEntityCacheInstance() {
- return jbcEntityCache;
- }
+ // We only build caches if *none* were passed in. Passing in
+ // caches counts as a clear statement of exactly what is wanted
+ boolean buildCaches = jbcEntityCache == null
+ && jbcCollectionCache == null
+ && jbcTsCache == null
+ && jbcQueryCache == null;
+
+ // Set up the cache factory
+ if (buildCaches && jbcFactory == null) {
+ // See if the user configured a multiplexer stack
+ if (channelFactory == null) {
+ String muxStacks = PropertiesHelper.getString(CHANNEL_FACTORY_RESOURCE_PROP, properties, DEF_MULTIPLEXER_RESOURCE);
+ if (muxStacks != null) {
+ channelFactory = new JChannelFactory();
+ channelFactory.setMultiplexerConfig(muxStacks);
+ }
+ }
+
+ String factoryRes = PropertiesHelper.getString(CACHE_FACTORY_RESOURCE_PROP, properties, DEF_CACHE_FACTORY_RESOURCE);
+ // FIXME use an impl from JBossCache
+ jbcFactory = new JBossCacheFactoryImpl(factoryRes, channelFactory);
+ ((JBossCacheFactoryImpl) jbcFactory).start();
+ selfCreatedFactory = true;
+ }
+
+ if (settings.isSecondLevelCacheEnabled()) {
- /**
- * {@inheritDoc}
- */
- public Cache getCollectionCacheInstance() {
- return jbcCollectionCache;
- }
+ if (buildCaches) {
+ entityConfig = PropertiesHelper
+ .getString(ENTITY_CACHE_RESOURCE_PROP, properties, DEF_ENTITY_RESOURCE);
+ jbcEntityCache = jbcFactory.getCache(entityConfig, true);
+
+ // Default to collections sharing entity cache if there is one
+ collectionConfig = PropertiesHelper.getString(COLLECTION_CACHE_RESOURCE_PROP, properties, entityConfig);
+ if (entityConfig.equals(collectionConfig)) {
+ jbcCollectionCache = jbcEntityCache;
+ }
+ else {
+ jbcCollectionCache = jbcFactory.getCache(collectionConfig, true);
+ }
+ }
+
+ if (jbcEntityCache != null) {
+ configureTransactionManager(jbcEntityCache, tm, false);
+ jbcEntityCache.start();
+ }
+ if (jbcCollectionCache != null) {
+ configureTransactionManager(jbcCollectionCache, tm, false);
+ jbcCollectionCache.start();
+ }
+
+ }
+ else {
+ jbcEntityCache = null;
+ jbcCollectionCache = null;
+ }
- /**
- * {@inheritDoc}
- */
- public Cache getQueryCacheInstance() {
- return jbcQueryCache;
- }
+ if (settings.isQueryCacheEnabled()) {
- /**
- * {@inheritDoc}
- */
- public Cache getTimestampsCacheInstance() {
- return jbcTsCache;
- }
+ if (buildCaches) {
+ // Default to sharing the entity cache if there is one
+ String dfltQueryResource = (entityConfig == null ? DEF_QUERY_RESOURCE : entityConfig);
+ queryConfig = PropertiesHelper.getString(QUERY_CACHE_RESOURCE_PROP, properties, dfltQueryResource);
+ if (queryConfig.equals(entityConfig)) {
+ jbcQueryCache = jbcEntityCache;
+ } else if (queryConfig.equals(collectionConfig)) {
+ jbcQueryCache = jbcCollectionCache;
+ } else {
+ jbcQueryCache = jbcFactory.getCache(queryConfig, true);
+ }
+
+ // For Timestamps, we default to a separate config
+ tsConfig = PropertiesHelper.getString(TIMESTAMP_CACHE_RESOURCE_PROP, properties, DEF_TS_RESOURCE);
+ if (tsConfig.equals(queryConfig)) {
+ jbcTsCache = jbcQueryCache;
+ }
+ else if (tsConfig.equals(entityConfig)) {
+ jbcTsCache = jbcEntityCache;
+ }
+ else if (tsConfig.equals(collectionConfig)) {
+ jbcTsCache = jbcCollectionCache;
+ }
+ else {
+ jbcTsCache = jbcFactory.getCache(tsConfig, true);
+ }
+ }
+
+ if (jbcQueryCache != null) {
+ configureTransactionManager(jbcQueryCache, tm, false);
+ jbcQueryCache.start();
+ }
+ if (jbcTsCache != null) {
+ configureTransactionManager(jbcTsCache, tm, true);
+ jbcTsCache.start();
+ }
+ }
+ else {
+ jbcTsCache = null;
+ jbcQueryCache = null;
+ }
+ }
+ catch (CacheException ce) {
+ throw ce;
+ }
+ catch (Throwable t) {
+ throw new CacheException("Unable to start region factory", t);
+ }
+ }
- /**
- * {@inheritDoc}
- */
- public void release() {
- if ( jbcEntityCache != null ) {
- try {
- jbcEntityCache.stop();
- }
- catch( Throwable t ) {
- log.info( "Unable to stop entity cache instance", t );
- }
- }
- if ( jbcCollectionCache != null ) {
- try {
- jbcCollectionCache.stop();
- }
- catch( Throwable t ) {
- log.info( "Unable to stop collection cache instance", t );
- }
- }
- if ( jbcTsCache != null ) {
- try {
- jbcTsCache.stop();
- }
- catch( Throwable t ) {
- log.info( "Unable to stop timestamp cache instance", t );
- }
- }
- if ( jbcQueryCache != null ) {
- try {
- jbcQueryCache.stop();
- }
- catch( Throwable t ) {
- log.info( "Unable to stop query cache instance", t );
- }
- }
- }
+ /**
+ * {@inheritDoc}
+ */
+ public void stop() {
+ releaseCaches();
+ if (selfCreatedFactory) {
+ ((JBossCacheFactoryImpl) jbcFactory).stop();
+ }
+ }
+
+ /**
+ * Injects the given TransactionManager into the cache.
+ *
+ * @param cache the cache. cannot be <code>null</code>
+ * @param tm the transaction manager Hibernate recognizes
+ * May be <code>null</code>
+ * @param allowNull whether we accept a null transaction manager in the cache
+ * if <code>tm</code> is not <code>null</code>
+ *
+ * @throws CacheException if <code>cache</code> is already started and is
+ * configured with a different TransactionManager
+ * than the one we would inject
+ */
+ private void configureTransactionManager(Cache cache, TransactionManager tm, boolean allowNull) {
+ Configuration cacheConfig = cache.getConfiguration();
+ TransactionManager cacheTm = cacheConfig.getRuntimeConfig().getTransactionManager();
+ if (!safeEquals(tm, cacheTm)) {
+ if (cache.getCacheStatus() != CacheStatus.INSTANTIATED) {
+ // We can't change the TM on a running cache; just check
+ // if the cache has no TM and we're OK with that
+ if (!allowNull || cacheTm != null) {
+ throw new CacheException("JBoss Cache is already started " + "with a transaction manager ("
+ + cacheTm + ") that doesn't match our own (" + tm + ")");
+ }
+ } else {
+ // Configure the cache to use our TM
+ cacheConfig.getRuntimeConfig().setTransactionManager(tm);
+ if (tm == null) {
+ // Make sure JBC doesn't look one up
+ cacheConfig.setTransactionManagerLookupClass(null);
+ }
+ }
+ }
+ }
+
+ /**
+ * Notify cache factory that we are no longer using the caches.
+ */
+ private void releaseCaches() {
+
+ // This method should be implemented assuming it's valid to
+ // do start/stop/start -- leave state appropriate for another start
+
+ if (jbcEntityCache != null && entityConfig != null) {
+ try {
+ jbcFactory.releaseCache(entityConfig);
+ jbcEntityCache = null;
+
+ // Make sure we don't re-release the same cache
+ if (entityConfig.equals(collectionConfig))
+ collectionConfig = null;
+ if (entityConfig.equals(queryConfig))
+ queryConfig = null;
+ if (entityConfig.equals(tsConfig))
+ tsConfig = null;
+ entityConfig = null;
+ } catch (Throwable t) {
+ log.info("Unable to release entity cache instance", t);
+ }
+ }
+ if (jbcCollectionCache != null && collectionConfig != null) {
+ try {
+ jbcFactory.releaseCache(collectionConfig);
+ jbcCollectionCache = null;
+
+ if (collectionConfig.equals(queryConfig))
+ queryConfig = null;
+ if (collectionConfig.equals(tsConfig))
+ tsConfig = null;
+ collectionConfig = null;
+ } catch (Throwable t) {
+ log.info("Unable to stop collection cache instance", t);
+ }
+ }
+ if (jbcQueryCache != null && queryConfig != null) {
+ try {
+ jbcFactory.releaseCache(queryConfig);
+ jbcQueryCache = null;
+
+ if (queryConfig.equals(tsConfig))
+ tsConfig = null;
+ queryConfig = null;
+ } catch (Throwable t) {
+ log.info("Unable to stop query cache instance", t);
+ }
+ }
+ if (jbcTsCache != null && tsConfig != null) {
+ try {
+ jbcFactory.releaseCache(tsConfig);
+ jbcTsCache = null;
+
+ tsConfig = null;
+ } catch (Throwable t) {
+ log.info("Unable to stop timestamp cache instance", t);
+ }
+ }
+ }
+
+ private boolean safeEquals(Object a, Object b) {
+ return (a == b || (a != null && a.equals(b)));
+ }
}
Copied: core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/builder/SharedCacheInstanceManager.java (from rev 14071, core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/builder/InvalidationCacheInstanceManager.java)
===================================================================
--- core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/builder/SharedCacheInstanceManager.java (rev 0)
+++ core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/builder/SharedCacheInstanceManager.java 2007-10-18 20:08:50 UTC (rev 14101)
@@ -0,0 +1,247 @@
+/*
+ * Copyright (c) 2007, Red Hat Middleware, LLC. All rights reserved.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, v. 2.1. This program is distributed in the
+ * hope that it will be useful, but WITHOUT A WARRANTY; without even the implied
+ * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details. You should have received a
+ * copy of the GNU Lesser General Public License, v.2.1 along with this
+ * distribution; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Red Hat Author(s): Steve Ebersole
+ */
+package org.hibernate.cache.jbc2.builder;
+
+import java.util.Properties;
+import javax.transaction.TransactionManager;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.jboss.cache.Cache;
+import org.jboss.cache.CacheStatus;
+import org.jboss.cache.DefaultCacheFactory;
+import org.jboss.cache.config.Configuration;
+import org.jgroups.ChannelFactory;
+import org.jgroups.JChannelFactory;
+
+import org.hibernate.cache.CacheException;
+import org.hibernate.cache.jbc2.CacheInstanceManager;
+import org.hibernate.cache.jbc2.util.CacheHelper;
+import org.hibernate.cfg.Settings;
+import org.hibernate.util.PropertiesHelper;
+
+/**
+ * A {@link CacheInstanceManager} implementation where we use a single cache
+ * instance we assume to be configured for invalidation if operating on a
+ * cluster. Under that assumption, we can store all data into the same
+ * {@link Cache} instance.
+ *
+ * @author Steve Ebersole
+ */
+public class SharedCacheInstanceManager implements CacheInstanceManager {
+
+ private static final Logger log = LoggerFactory.getLogger(SharedCacheInstanceManager.class);
+
+ /**
+ * Classpath or filesystem resource identifying containing JBoss Cache
+ * configuration settings the {@link Cache} should use.
+ *
+ * @see #DEFAULT_CACHE_RESOURCE
+ */
+ public static final String CACHE_RESOURCE_PROP = "hibernate.cache.region.jbc2.cfg.shared";
+
+ /**
+ * Default name for the JBoss Cache configuration file.
+ */
+ public static final String DEFAULT_CACHE_RESOURCE = "treecache.xml";
+ /**
+ * Classpath or filesystem resource identifying containing JGroups protocol
+ * stack configurations the <code>org.jgroups.ChannelFactory</code>
+ * should use.
+ *
+ * @see #DEF_MULTIPLEXER_RESOURCE
+ */
+ public static final String CHANNEL_FACTORY_RESOURCE_PROP = "hibernate.cache.region.jbc2.cfg.multiplexer.stacks";
+ /**
+ * Default value for {@link #CHANNEL_FACTORY_RESOURCE_PROP}. Specifies
+ * "stacks.xml", which can be found in the root of the JGroups jar file.
+ * Thus, leaving this value at default means using the default protocol
+ * stack configs provided by JGroups.
+ */
+ public static final String DEF_MULTIPLEXER_RESOURCE = "stacks.xml";
+
+ private Cache cache;
+ private ChannelFactory channelFactory;
+ private boolean use2ndLevel;
+ private boolean useQuery;
+
+ public SharedCacheInstanceManager() {
+ }
+
+ public SharedCacheInstanceManager(ChannelFactory channelFactory) {
+ this.channelFactory = channelFactory;
+ }
+
+ public SharedCacheInstanceManager(Cache cache) {
+ this.cache = cache;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public Cache getEntityCacheInstance() {
+ return use2ndLevel ? cache : null;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public Cache getCollectionCacheInstance() {
+ return use2ndLevel ? cache : null;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public Cache getQueryCacheInstance() {
+
+ if (!useQuery)
+ return null;
+
+ if (CacheHelper.isClusteredInvalidation(cache)) {
+ throw new CacheException("Query cache not supported for clustered invalidation");
+ }
+ return cache;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void start(Settings settings, Properties properties) throws CacheException {
+
+ use2ndLevel = settings.isSecondLevelCacheEnabled();
+ useQuery = settings.isQueryCacheEnabled();
+
+ if (cache == null) {
+
+ if (channelFactory == null) {
+ String muxStacks = PropertiesHelper.getString(CHANNEL_FACTORY_RESOURCE_PROP, properties, DEF_MULTIPLEXER_RESOURCE);
+ if (muxStacks != null) {
+ channelFactory = new JChannelFactory();
+ try {
+ channelFactory.setMultiplexerConfig(muxStacks);
+ }
+ catch (Exception e) {
+ throw new CacheException("Problem setting ChannelFactory config", e);
+ }
+ }
+ }
+ cache = createSharedCache(settings, properties);
+ configureTransactionManager(cache, settings, properties);
+ if (cache.getConfiguration().getMultiplexerStack() != null
+ && cache.getConfiguration().getRuntimeConfig().getMuxChannelFactory() == null) {
+ cache.getConfiguration().getRuntimeConfig().setMuxChannelFactory(channelFactory);
+ }
+ }
+ cache.start();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public Cache getTimestampsCacheInstance() {
+
+ if (!useQuery)
+ return null;
+
+ if (CacheHelper.isClusteredInvalidation(cache)) {
+ throw new CacheException("Query cache not supported for clustered invalidation");
+ }
+ return cache;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void stop() {
+ if (cache != null) {
+ stopSharedCache(cache);
+ }
+ }
+
+ /**
+ * Create a cache using the given settings and properties.
+ *
+ * @param settings
+ * @param properties
+ * @return
+ */
+ protected Cache createSharedCache(Settings settings, Properties properties)
+ {
+ String configResource = PropertiesHelper.getString(CACHE_RESOURCE_PROP, properties, DEFAULT_CACHE_RESOURCE);
+ return DefaultCacheFactory.getInstance().createCache(configResource, false);
+ }
+
+ /**
+ * Injects the TransactionManager found via {@link Settings#getTransactionManagerLookup()}
+ * into the cache.
+ *
+ * @param cache
+ * @param settings
+ * @param properties
+ *
+ * @throws CacheException if <code>cache</code> is already started and is
+ * configured with a different TransactionManager
+ * than the one we would inject
+ */
+ protected void configureTransactionManager(Cache cache, Settings settings, Properties properties) {
+
+ TransactionManager tm = null;
+ if (settings.getTransactionManagerLookup() != null) {
+ tm = settings.getTransactionManagerLookup().getTransactionManager(properties);
+ }
+
+ Configuration cacheConfig = cache.getConfiguration();
+ TransactionManager cacheTm = cacheConfig.getRuntimeConfig().getTransactionManager();
+
+ if (!safeEquals(tm, cacheTm)) {
+ if (cache.getCacheStatus() != CacheStatus.INSTANTIATED
+ && cache.getCacheStatus() != CacheStatus.DESTROYED) {
+ throw new CacheException("JBoss Cache is already started " + "with a transaction manager ("
+ + cacheTm + ") that doesn't match our own (" + tm + ")");
+ } else {
+ // Configure the cache to use our TM
+ cacheConfig.getRuntimeConfig().setTransactionManager(tm);
+ if (tm == null) {
+ // Make sure JBC doesn't look one up
+ cacheConfig.setTransactionManagerLookupClass(null);
+ }
+ }
+ }
+ }
+
+ private boolean safeEquals(Object a, Object b) {
+ return (a == b || (a != null && a.equals(b)));
+ }
+
+ /**
+ * Stops the shared cache.
+ * @param cache the shared cache
+ */
+ protected void stopSharedCache(Cache cache) {
+ try {
+ if (cache.getCacheStatus() == CacheStatus.STARTED) {
+ cache.stop();
+ }
+ if (cache.getCacheStatus() != CacheStatus.DESTROYED
+ && cache.getCacheStatus() != CacheStatus.INSTANTIATED) {
+ cache.destroy();
+ }
+ } catch (Throwable t) {
+ log.warn("Unable to stop cache instance", t);
+ }
+ }
+}
Modified: core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/collection/CollectionRegionImpl.java
===================================================================
--- core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/collection/CollectionRegionImpl.java 2007-10-18 19:49:17 UTC (rev 14100)
+++ core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/collection/CollectionRegionImpl.java 2007-10-18 20:08:50 UTC (rev 14101)
@@ -16,6 +16,8 @@
package org.hibernate.cache.jbc2.collection;
import org.jboss.cache.Cache;
+import org.jboss.cache.Fqn;
+import org.jboss.cache.config.Configuration.NodeLockingScheme;
import org.hibernate.cache.CacheDataDescription;
import org.hibernate.cache.CacheException;
@@ -25,25 +27,35 @@
import org.hibernate.cache.jbc2.TransactionalDataRegionAdapter;
/**
- * Defines the behavior of the collection cache regions for JBossCache.
- *
+ * Defines the behavior of the collection cache regions for JBossCache 2.x.
+ *
* @author Steve Ebersole
*/
public class CollectionRegionImpl extends TransactionalDataRegionAdapter implements CollectionRegion {
- public CollectionRegionImpl(Cache jbcCache, String regionName, CacheDataDescription metadata) {
- super( jbcCache, regionName, metadata );
- }
- public CollectionRegionAccessStrategy buildAccessStrategy(AccessType accessType) throws CacheException {
- if ( AccessType.READ_ONLY.equals( accessType ) ) {
- return new ReadOnlyAccess( this );
- }
- if ( AccessType.TRANSACTIONAL.equals( accessType ) ) {
- return new TransactionalAccess( this );
- }
+ public static final String TYPE = "COLL";
+ private boolean optimistic;
- // todo : add support for READ_WRITE ( + NONSTRICT_READ_WRITE ??? )
+ public CollectionRegionImpl(Cache jbcCache, String regionName, String regionPrefix, CacheDataDescription metadata) {
+ super(jbcCache, regionName, regionPrefix, metadata);
+ optimistic = (jbcCache.getConfiguration().getNodeLockingScheme() == NodeLockingScheme.OPTIMISTIC);
+ }
- throw new CacheException( "unsupported access type [" + accessType.getName() + "]" );
- }
+ public CollectionRegionAccessStrategy buildAccessStrategy(AccessType accessType) throws CacheException {
+ if (AccessType.READ_ONLY.equals(accessType)) {
+ return optimistic ? new OptimisticReadOnlyAccess(this) : new ReadOnlyAccess(this);
+ }
+ if (AccessType.TRANSACTIONAL.equals(accessType)) {
+ return optimistic ? new OptimisticTransactionalAccess(this) : new TransactionalAccess(this);
+ }
+
+ // todo : add support for READ_WRITE ( + NONSTRICT_READ_WRITE ??? )
+
+ throw new CacheException("unsupported access type [" + accessType.getName() + "]");
+ }
+
+ @Override
+ protected Fqn<String> createRegionFqn(String regionName, String regionPrefix) {
+ return getTypeLastRegionFqn(regionName, regionPrefix, TYPE);
+ }
}
Added: core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/collection/OptimisticReadOnlyAccess.java
===================================================================
--- core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/collection/OptimisticReadOnlyAccess.java (rev 0)
+++ core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/collection/OptimisticReadOnlyAccess.java 2007-10-18 20:08:50 UTC (rev 14101)
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2007, Red Hat Middleware, LLC. All rights reserved.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, v. 2.1. This program is distributed in the
+ * hope that it will be useful, but WITHOUT A WARRANTY; without even the implied
+ * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details. You should have received a
+ * copy of the GNU Lesser General Public License, v.2.1 along with this
+ * distribution; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Red Hat Author(s): Brian Stansberry
+ */
+
+package org.hibernate.cache.jbc2.collection;
+
+import org.hibernate.cache.CacheException;
+import org.hibernate.cache.access.SoftLock;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * This defines the strategy for transactional access to collection data in an
+ * optimistic-locking JBossCache using its 2.x APIs. <p/> The read-only access
+ * to a JBossCache really is still transactional, just with the extra semantic
+ * or guarantee that we will not update data.
+ *
+ * @author Brian Stansberry
+ */
+public class OptimisticReadOnlyAccess extends OptimisticTransactionalAccess {
+
+ private static final Logger log = LoggerFactory.getLogger(OptimisticReadOnlyAccess.class);
+
+ /**
+ * Create a new OptimisticReadOnlyAccess.
+ *
+ * @param region
+ */
+ public OptimisticReadOnlyAccess(CollectionRegionImpl region) {
+ super(region);
+ }
+
+ @Override
+ public SoftLock lockItem(Object key, Object version) throws CacheException {
+ throw new UnsupportedOperationException("Illegal attempt to edit read only item");
+ }
+
+ @Override
+ public SoftLock lockRegion() throws CacheException {
+ throw new UnsupportedOperationException("Illegal attempt to edit read only region");
+ }
+
+ @Override
+ public void unlockItem(Object key, SoftLock lock) throws CacheException {
+ log.error("Illegal attempt to edit read only item");
+ }
+
+ @Override
+ public void unlockRegion(SoftLock lock) throws CacheException {
+ log.error("Illegal attempt to edit read only region");
+ }
+}
Property changes on: core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/collection/OptimisticReadOnlyAccess.java
___________________________________________________________________
Name: svn:executable
+ *
Added: core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/collection/OptimisticTransactionalAccess.java
===================================================================
--- core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/collection/OptimisticTransactionalAccess.java (rev 0)
+++ core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/collection/OptimisticTransactionalAccess.java 2007-10-18 20:08:50 UTC (rev 14101)
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2007, Red Hat Middleware, LLC. All rights reserved.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, v. 2.1. This program is distributed in the
+ * hope that it will be useful, but WITHOUT A WARRANTY; without even the implied
+ * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details. You should have received a
+ * copy of the GNU Lesser General Public License, v.2.1 along with this
+ * distribution; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Red Hat Author(s): Brian Stansberry
+ */
+
+package org.hibernate.cache.jbc2.collection;
+
+import org.hibernate.cache.jbc2.access.OptimisticTransactionalAccessDelegate;
+
+/**
+ * Defines the strategy for transactional access to entity data in an
+ * optimistic-locking JBoss Cache using its 2.x APIs
+ *
+ * @author Brian Stansberry
+ * @version $Revision: 1 $
+ */
+public class OptimisticTransactionalAccess extends TransactionalAccess {
+
+ /**
+ * Create a new OptimisticTransactionalAccess.
+ *
+ * @param region
+ */
+ public OptimisticTransactionalAccess(CollectionRegionImpl region) {
+
+ // We use a different delegate than the non-optimistic superclass default
+ super(region, new OptimisticTransactionalAccessDelegate(region.getCacheInstance(), region.getRegionFqn(),
+ region.getCacheDataDescription()));
+ }
+
+}
Property changes on: core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/collection/OptimisticTransactionalAccess.java
___________________________________________________________________
Name: svn:executable
+ *
Modified: core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/collection/ReadOnlyAccess.java
===================================================================
--- core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/collection/ReadOnlyAccess.java 2007-10-18 19:49:17 UTC (rev 14100)
+++ core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/collection/ReadOnlyAccess.java 2007-10-18 20:08:50 UTC (rev 14101)
@@ -22,50 +22,37 @@
import org.hibernate.cache.CacheException;
/**
- * This defines the strategy for transactional access to enity data in JBossCache using its 2.x APIs
- * <p/>
- * read-only access to a JBossCache really is still transactional, just with
- * the extra semantic or guarentee that we will not update data.
- *
+ * This defines the strategy for transactional access to collection data in a
+ * pessimistic-locking JBossCache using its 2.x APIs. <p/> The read-only access
+ * to a JBossCache really is still transactional, just with the extra semantic
+ * or guarantee that we will not update data.
+ *
* @author Steve Ebersole
*/
public class ReadOnlyAccess extends TransactionalAccess {
- private static final Logger log = LoggerFactory.getLogger( ReadOnlyAccess.class );
+ private static final Logger log = LoggerFactory.getLogger(ReadOnlyAccess.class);
- public ReadOnlyAccess(CollectionRegionImpl region) {
- super( region );
- }
+ public ReadOnlyAccess(CollectionRegionImpl region) {
+ super(region);
+ }
- public SoftLock lockItem(Object key, Object version) throws CacheException {
- throw new UnsupportedOperationException( "Illegal attempt to edit read only item" );
- }
+ @Override
+ public SoftLock lockItem(Object key, Object version) throws CacheException {
+ throw new UnsupportedOperationException("Illegal attempt to edit read only item");
+ }
- public SoftLock lockRegion() throws CacheException {
- throw new UnsupportedOperationException( "Illegal attempt to edit read only region" );
- }
+ @Override
+ public SoftLock lockRegion() throws CacheException {
+ throw new UnsupportedOperationException("Illegal attempt to edit read only region");
+ }
- public void unlockItem(Object key, SoftLock lock) throws CacheException {
- log.error( "Illegal attempt to edit read only item" );
- }
+ @Override
+ public void unlockItem(Object key, SoftLock lock) throws CacheException {
+ log.error("Illegal attempt to edit read only item");
+ }
- public void unlockRegion(SoftLock lock) throws CacheException {
- log.error( "Illegal attempt to edit read only region" );
- }
-
- public boolean update(
- Object key,
- Object value,
- Object currentVersion,
- Object previousVersion) throws CacheException {
- throw new UnsupportedOperationException( "Illegal attempt to edit read only item" );
- }
-
- public boolean afterUpdate(
- Object key,
- Object value,
- Object currentVersion,
- Object previousVersion,
- SoftLock lock) throws CacheException {
- throw new UnsupportedOperationException( "Illegal attempt to edit read only item" );
- }
+ @Override
+ public void unlockRegion(SoftLock lock) throws CacheException {
+ log.error("Illegal attempt to edit read only region");
+ }
}
Modified: core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/collection/TransactionalAccess.java
===================================================================
--- core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/collection/TransactionalAccess.java 2007-10-18 19:49:17 UTC (rev 14100)
+++ core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/collection/TransactionalAccess.java 2007-10-18 20:08:50 UTC (rev 14101)
@@ -15,68 +15,100 @@
*/
package org.hibernate.cache.jbc2.collection;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
+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.CollectionRegion;
-import org.hibernate.cache.CacheException;
+import org.hibernate.cache.jbc2.access.TransactionalAccessDelegate;
/**
- * todo : implement
- *
+ * This defines the strategy for transactional access to collection data in a
+ * pessimistic-locking JBossCache using its 2.x APIs
+ *
* @author Steve Ebersole
+ * @author Brian Stansberry
*/
public class TransactionalAccess implements CollectionRegionAccessStrategy {
- private static final Logger log = LoggerFactory.getLogger( TransactionalAccess.class );
- private final CollectionRegionImpl region;
+ private final CollectionRegionImpl region;
- public TransactionalAccess(CollectionRegionImpl region) {
- this.region = region;
- }
+ /**
+ * Most of our logic is shared between this and entity regions, so we
+ * delegate to a class that encapsulates it
+ */
+ private final TransactionalAccessDelegate delegate;
- public CollectionRegion getRegion() {
- return region;
- }
+ /**
+ * Create a new TransactionalAccess.
+ *
+ * @param region
+ */
+ public TransactionalAccess(CollectionRegionImpl region) {
+ this(region, new TransactionalAccessDelegate(region.getCacheInstance(), region.getRegionFqn()));
+ }
- public Object get(Object key, long txTimestamp) throws CacheException {
- return null;
- }
+ /**
+ * Allow subclasses to define the delegate.
+ *
+ * @param region
+ * @param delegate
+ */
+ protected TransactionalAccess(CollectionRegionImpl region, TransactionalAccessDelegate delegate) {
+ this.region = region;
+ this.delegate = delegate;
+ }
- public boolean putFromLoad(Object key, Object value, long txTimestamp, Object version) throws CacheException {
- return false;
- }
+ public CollectionRegion getRegion() {
+ return region;
+ }
- public boolean putFromLoad(Object key, Object value, long txTimestamp, Object version, boolean minimalPutOverride)
- throws CacheException {
- return false;
- }
+ public Object get(Object key, long txTimestamp) throws CacheException {
- public SoftLock lockItem(Object key, Object version) throws CacheException {
- return null;
- }
+ return delegate.get(key, txTimestamp);
+ }
- public SoftLock lockRegion() throws CacheException {
- return null;
- }
+ public boolean putFromLoad(Object key, Object value, long txTimestamp, Object version) throws CacheException {
- public void unlockItem(Object key, SoftLock lock) throws CacheException {
- }
+ return delegate.putFromLoad(key, value, txTimestamp, version);
+ }
- public void unlockRegion(SoftLock lock) throws CacheException {
- }
+ public boolean putFromLoad(Object key, Object value, long txTimestamp, Object version, boolean minimalPutOverride)
+ throws CacheException {
- public void remove(Object key) throws CacheException {
- }
+ return delegate.putFromLoad(key, value, txTimestamp, version, minimalPutOverride);
+ }
- public void removeAll() throws CacheException {
- }
+ public void remove(Object key) throws CacheException {
- public void evict(Object key) throws CacheException {
- }
+ delegate.remove(key);
+ }
- public void evictAll() throws CacheException {
- }
+ public void removeAll() throws CacheException {
+ delegate.removeAll();
+ }
+
+ public void evict(Object key) throws CacheException {
+ delegate.evict(key);
+ }
+
+ public void evictAll() throws CacheException {
+ delegate.evictAll();
+ }
+
+ // Following methods we don't delegate since they have so little logic
+ // it's clearer to just implement them here
+
+ public SoftLock lockItem(Object key, Object version) throws CacheException {
+ return null;
+ }
+
+ public SoftLock lockRegion() throws CacheException {
+ return null;
+ }
+
+ public void unlockItem(Object key, SoftLock lock) throws CacheException {
+ }
+
+ public void unlockRegion(SoftLock lock) throws CacheException {
+ }
}
Modified: core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/entity/EntityRegionImpl.java
===================================================================
--- core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/entity/EntityRegionImpl.java 2007-10-18 19:49:17 UTC (rev 14100)
+++ core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/entity/EntityRegionImpl.java 2007-10-18 20:08:50 UTC (rev 14101)
@@ -16,6 +16,8 @@
package org.hibernate.cache.jbc2.entity;
import org.jboss.cache.Cache;
+import org.jboss.cache.Fqn;
+import org.jboss.cache.config.Configuration.NodeLockingScheme;
import org.hibernate.cache.CacheDataDescription;
import org.hibernate.cache.CacheException;
@@ -26,28 +28,39 @@
/**
* Defines the behavior of the entity cache regions for JBossCache.
- *
+ *
* @author Steve Ebersole
*/
public class EntityRegionImpl extends TransactionalDataRegionAdapter implements EntityRegion {
- public EntityRegionImpl(Cache jbcCache, String regionName, CacheDataDescription metadata) {
- super( jbcCache, regionName, metadata );
- }
+ public static final String TYPE = "ENTITY";
+
+ private boolean optimistic;
- /**
- * {@inheritDoc}
- */
- public EntityRegionAccessStrategy buildAccessStrategy(AccessType accessType) throws CacheException {
- if ( AccessType.READ_ONLY.equals( accessType ) ) {
- return new ReadOnlyAccess( this );
- }
- if ( AccessType.TRANSACTIONAL.equals( accessType ) ) {
- return new TransactionalAccess( this );
- }
+ public EntityRegionImpl(Cache jbcCache, String regionName, String regionPrefix, CacheDataDescription metadata) {
+ super(jbcCache, regionName, regionPrefix, metadata);
+ optimistic = (jbcCache.getConfiguration().getNodeLockingScheme() == NodeLockingScheme.OPTIMISTIC);
+ }
- // todo : add support for READ_WRITE ( + NONSTRICT_READ_WRITE ??? )
+ /**
+ * {@inheritDoc}
+ */
+ public EntityRegionAccessStrategy buildAccessStrategy(AccessType accessType) throws CacheException {
+ if (AccessType.READ_ONLY.equals(accessType)) {
+ return optimistic ? new OptimisticReadOnlyAccess(this) : new ReadOnlyAccess(this);
+ }
+ if (AccessType.TRANSACTIONAL.equals(accessType)) {
+ return optimistic ? new OptimisticTransactionalAccess(this) : new TransactionalAccess(this);
+ }
- throw new CacheException( "unsupported access type [" + accessType.getName() + "]" );
- }
+ // todo : add support for READ_WRITE ( + NONSTRICT_READ_WRITE ??? )
+
+ throw new CacheException("unsupported access type [" + accessType.getName() + "]");
+ }
+
+ @Override
+ protected Fqn<String> createRegionFqn(String regionName, String regionPrefix) {
+ return getTypeLastRegionFqn(regionName, regionPrefix, TYPE);
+ }
+
}
Added: core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/entity/OptimisticReadOnlyAccess.java
===================================================================
--- core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/entity/OptimisticReadOnlyAccess.java (rev 0)
+++ core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/entity/OptimisticReadOnlyAccess.java 2007-10-18 20:08:50 UTC (rev 14101)
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2007, Red Hat Middleware, LLC. All rights reserved.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, v. 2.1. This program is distributed in the
+ * hope that it will be useful, but WITHOUT A WARRANTY; without even the implied
+ * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details. You should have received a
+ * copy of the GNU Lesser General Public License, v.2.1 along with this
+ * distribution; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Red Hat Author(s): Steve Ebersole
+ */
+package org.hibernate.cache.jbc2.entity;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import org.hibernate.cache.access.SoftLock;
+import org.hibernate.cache.CacheException;
+
+/**
+ * This defines the strategy for read-only access to enity data in an
+ * optimistic-locking JBossCache using its 2.x APIs <p/> The read-only access to
+ * a JBossCache really is still transactional, just with the extra semantic or
+ * guarantee that we will not update data.
+ *
+ * @author Brian Stansberry
+ */
+public class OptimisticReadOnlyAccess extends OptimisticTransactionalAccess {
+ private static final Logger log = LoggerFactory.getLogger(OptimisticReadOnlyAccess.class);
+
+ public OptimisticReadOnlyAccess(EntityRegionImpl region) {
+ super(region);
+ }
+
+ @Override
+ public SoftLock lockItem(Object key, Object version) throws CacheException {
+ throw new UnsupportedOperationException("Illegal attempt to edit read only item");
+ }
+
+ @Override
+ public SoftLock lockRegion() throws CacheException {
+ throw new UnsupportedOperationException("Illegal attempt to edit read only region");
+ }
+
+ @Override
+ public void unlockItem(Object key, SoftLock lock) throws CacheException {
+ log.error("Illegal attempt to edit read only item");
+ }
+
+ @Override
+ public void unlockRegion(SoftLock lock) throws CacheException {
+ log.error("Illegal attempt to edit read only region");
+ }
+
+ @Override
+ public boolean update(Object key, Object value, Object currentVersion, Object previousVersion)
+ throws CacheException {
+ throw new UnsupportedOperationException("Illegal attempt to edit read only item");
+ }
+
+ @Override
+ public boolean afterUpdate(Object key, Object value, Object currentVersion, Object previousVersion, SoftLock lock)
+ throws CacheException {
+ throw new UnsupportedOperationException("Illegal attempt to edit read only item");
+ }
+}
Property changes on: core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/entity/OptimisticReadOnlyAccess.java
___________________________________________________________________
Name: svn:executable
+ *
Added: core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/entity/OptimisticTransactionalAccess.java
===================================================================
--- core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/entity/OptimisticTransactionalAccess.java (rev 0)
+++ core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/entity/OptimisticTransactionalAccess.java 2007-10-18 20:08:50 UTC (rev 14101)
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2007, Red Hat Middleware, LLC. All rights reserved.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, v. 2.1. This program is distributed in the
+ * hope that it will be useful, but WITHOUT A WARRANTY; without even the implied
+ * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details. You should have received a
+ * copy of the GNU Lesser General Public License, v.2.1 along with this
+ * distribution; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Red Hat Author(s): Brian Stansberry
+ */
+
+package org.hibernate.cache.jbc2.entity;
+
+import org.hibernate.cache.jbc2.access.OptimisticTransactionalAccessDelegate;
+
+/**
+ * Defines the strategy for transactional access to entity data in an
+ * optimistic-locking JBoss Cache using its 2.x APIs
+ *
+ * @author Brian Stansberry
+ * @version $Revision: 1 $
+ */
+public class OptimisticTransactionalAccess extends TransactionalAccess {
+
+ /**
+ * Create a new OptimisticTransactionalAccess.
+ *
+ * @param region
+ */
+ public OptimisticTransactionalAccess(EntityRegionImpl region) {
+ super(region, new OptimisticTransactionalAccessDelegate(region.getCacheInstance(), region.getRegionFqn(),
+ region.getCacheDataDescription()));
+ }
+}
Property changes on: core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/entity/OptimisticTransactionalAccess.java
___________________________________________________________________
Name: svn:executable
+ *
Modified: core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/entity/ReadOnlyAccess.java
===================================================================
--- core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/entity/ReadOnlyAccess.java 2007-10-18 19:49:17 UTC (rev 14100)
+++ core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/entity/ReadOnlyAccess.java 2007-10-18 20:08:50 UTC (rev 14101)
@@ -22,50 +22,49 @@
import org.hibernate.cache.CacheException;
/**
- * This defines the strategy for transactional access to enity data in JBossCache using its 2.x APIs
- * <p/>
- * read-only access to a JBossCache really is still transactional, just with
- * the extra semantic or guarentee that we will not update data.
- *
+ * This defines the strategy for transactional access to enity data in
+ * JBossCache using its 2.x APIs <p/> read-only access to a JBossCache really is
+ * still transactional, just with the extra semantic or guarentee that we will
+ * not update data.
+ *
* @author Steve Ebersole
*/
public class ReadOnlyAccess extends TransactionalAccess {
- private static final Logger log = LoggerFactory.getLogger( ReadOnlyAccess.class );
+ private static final Logger log = LoggerFactory.getLogger(ReadOnlyAccess.class);
- public ReadOnlyAccess(EntityRegionImpl region) {
- super( region );
- }
+ public ReadOnlyAccess(EntityRegionImpl region) {
+ super(region);
+ }
- public SoftLock lockItem(Object key, Object version) throws CacheException {
- throw new UnsupportedOperationException( "Illegal attempt to edit read only item" );
- }
+ @Override
+ public SoftLock lockItem(Object key, Object version) throws CacheException {
+ throw new UnsupportedOperationException("Illegal attempt to edit read only item");
+ }
- public SoftLock lockRegion() throws CacheException {
- throw new UnsupportedOperationException( "Illegal attempt to edit read only region" );
- }
+ @Override
+ public SoftLock lockRegion() throws CacheException {
+ throw new UnsupportedOperationException("Illegal attempt to edit read only region");
+ }
- public void unlockItem(Object key, SoftLock lock) throws CacheException {
- log.error( "Illegal attempt to edit read only item" );
- }
+ @Override
+ public void unlockItem(Object key, SoftLock lock) throws CacheException {
+ log.error("Illegal attempt to edit read only item");
+ }
- public void unlockRegion(SoftLock lock) throws CacheException {
- log.error( "Illegal attempt to edit read only region" );
- }
+ @Override
+ public void unlockRegion(SoftLock lock) throws CacheException {
+ log.error("Illegal attempt to edit read only region");
+ }
- public boolean update(
- Object key,
- Object value,
- Object currentVersion,
- Object previousVersion) throws CacheException {
- throw new UnsupportedOperationException( "Illegal attempt to edit read only item" );
- }
+ @Override
+ public boolean update(Object key, Object value, Object currentVersion, Object previousVersion)
+ throws CacheException {
+ throw new UnsupportedOperationException("Illegal attempt to edit read only item");
+ }
- public boolean afterUpdate(
- Object key,
- Object value,
- Object currentVersion,
- Object previousVersion,
- SoftLock lock) throws CacheException {
- throw new UnsupportedOperationException( "Illegal attempt to edit read only item" );
- }
+ @Override
+ public boolean afterUpdate(Object key, Object value, Object currentVersion, Object previousVersion, SoftLock lock)
+ throws CacheException {
+ throw new UnsupportedOperationException("Illegal attempt to edit read only item");
+ }
}
Modified: core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/entity/TransactionalAccess.java
===================================================================
--- core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/entity/TransactionalAccess.java 2007-10-18 19:49:17 UTC (rev 14100)
+++ core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/entity/TransactionalAccess.java 2007-10-18 20:08:50 UTC (rev 14101)
@@ -15,145 +15,108 @@
*/
package org.hibernate.cache.jbc2.entity;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.jboss.cache.Fqn;
-import org.jboss.cache.lock.TimeoutException;
-
import org.hibernate.cache.access.EntityRegionAccessStrategy;
import org.hibernate.cache.access.SoftLock;
+import org.hibernate.cache.jbc2.access.TransactionalAccessDelegate;
import org.hibernate.cache.EntityRegion;
import org.hibernate.cache.CacheException;
/**
- * This defines the strategy for transactional access to enity data
- * in JBossCache using its 2.x APIs
- *
+ * Defines the strategy for transactional access to entity data in a
+ * pessimistic-locking JBossCache using its 2.x APIs
+ *
* @author Steve Ebersole
*/
public class TransactionalAccess implements EntityRegionAccessStrategy {
- private static final Logger log = LoggerFactory.getLogger( TransactionalAccess.class );
- private final EntityRegionImpl region;
+ protected final EntityRegionImpl region;
- public TransactionalAccess(EntityRegionImpl region) {
- this.region = region;
- }
+ /**
+ * Most of our logic is shared between this and entity regions, so we
+ * delegate to a class that encapsulates it
+ */
+ private final TransactionalAccessDelegate delegate;
- public EntityRegion getRegion() {
- return region;
- }
+ public TransactionalAccess(EntityRegionImpl region) {
+ this(region, new TransactionalAccessDelegate(region.getCacheInstance(), region.getRegionFqn()));
+ }
- public Object get(Object key, long txTimestamp) throws CacheException {
- try {
- return region.getCacheInstance().get( region.getRegionFqn(), EntityRegionImpl.ITEM );
- }
- catch ( Exception e ) {
- throw new CacheException( e );
- }
- }
+ protected TransactionalAccess(EntityRegionImpl region, TransactionalAccessDelegate delegate) {
+ this.region = region;
+ this.delegate = delegate;
+ }
- public boolean putFromLoad(
- Object key,
- Object value,
- long txTimestamp,
- Object version) throws CacheException {
- try {
- region.getCacheInstance().putForExternalRead( new Fqn( region.getRegionFqn(), key ), EntityRegionImpl.ITEM, value );
- return true;
- }
- catch ( TimeoutException te) {
- //ignore!
- log.debug( "ignoring write lock acquisition failure" );
- return false;
- }
- catch ( Throwable t ) {
- throw new CacheException( t );
- }
- }
+ public EntityRegion getRegion() {
+ return region;
+ }
- public boolean putFromLoad(
- Object key,
- Object value,
- long txTimestamp,
- Object version,
- boolean minimalPutOverride) throws CacheException {
- if ( minimalPutOverride && get( key, txTimestamp ) != null ) {
- if ( log.isDebugEnabled() ) {
- log.debug( "item already cached: " + key );
- }
- return false;
- }
- return putFromLoad( key, value, txTimestamp, version );
- }
+ public Object get(Object key, long txTimestamp) throws CacheException {
- public SoftLock lockItem(Object key, Object version) throws CacheException {
- return null;
- }
+ return delegate.get(key, txTimestamp);
+ }
- public SoftLock lockRegion() throws CacheException {
- return null;
- }
+ public boolean putFromLoad(Object key, Object value, long txTimestamp, Object version) throws CacheException {
- public void unlockItem(Object key, SoftLock lock) throws CacheException {
- }
+ return delegate.putFromLoad(key, value, txTimestamp, version);
+ }
- public void unlockRegion(SoftLock lock) throws CacheException {
- }
+ public boolean putFromLoad(Object key, Object value, long txTimestamp, Object version, boolean minimalPutOverride)
+ throws CacheException {
- public boolean insert(Object key, Object value, Object version) throws CacheException {
- try {
- region.getCacheInstance().put( new Fqn( region.getRegionFqn(), key ), EntityRegionImpl.ITEM, value );
- }
- catch ( Throwable t ) {
- throw new CacheException( t );
- }
- return true;
- }
+ return delegate.putFromLoad(key, value, txTimestamp, version, minimalPutOverride);
+ }
- public boolean afterInsert(Object key, Object value, Object version) throws CacheException {
- return false;
- }
+ public boolean insert(Object key, Object value, Object version) throws CacheException {
- public boolean update(Object key, Object value, Object currentVersion, Object previousVersion)
- throws CacheException {
- try {
- region.getCacheInstance().put( new Fqn( region.getRegionFqn(), key ), EntityRegionImpl.ITEM, value );
- }
- catch ( Throwable t ) {
- throw new CacheException( t );
- }
- return true;
- }
+ return delegate.insert(key, value, version);
+ }
- public boolean afterUpdate(Object key, Object value, Object currentVersion, Object previousVersion, SoftLock lock)
- throws CacheException {
- return false;
- }
+ public boolean update(Object key, Object value, Object currentVersion, Object previousVersion)
+ throws CacheException {
- public void remove(Object key) throws CacheException {
- try {
- region.getCacheInstance().removeNode( new Fqn( region.getRegionFqn(), key ) );
- }
- catch ( Exception e ) {
- throw new CacheException( e );
- }
- }
+ return delegate.update(key, value, currentVersion, previousVersion);
+ }
- public void removeAll() throws CacheException {
- try {
- region.getCacheInstance().removeNode( region.getRegionFqn() );
- }
- catch ( Exception e ) {
- throw new CacheException( e );
- }
- }
+ public void remove(Object key) throws CacheException {
- public void evict(Object key) throws CacheException {
- remove( key );
- }
+ delegate.remove(key);
+ }
- public void evictAll() throws CacheException {
- removeAll();
- }
+ public void removeAll() throws CacheException {
+ delegate.removeAll();
+ }
+
+ public void evict(Object key) throws CacheException {
+ delegate.evict(key);
+ }
+
+ public void evictAll() throws CacheException {
+ delegate.evictAll();
+ }
+
+ // Following methods we don't delegate since they have so little logic
+ // it's clearer to just implement them here
+
+ public SoftLock lockItem(Object key, Object version) throws CacheException {
+ return null;
+ }
+
+ public SoftLock lockRegion() throws CacheException {
+ return null;
+ }
+
+ public void unlockItem(Object key, SoftLock lock) throws CacheException {
+ }
+
+ public void unlockRegion(SoftLock lock) throws CacheException {
+ }
+
+ public boolean afterInsert(Object key, Object value, Object version) throws CacheException {
+ return false;
+ }
+
+ public boolean afterUpdate(Object key, Object value, Object currentVersion, Object previousVersion, SoftLock lock)
+ throws CacheException {
+ return false;
+ }
}
Added: core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/query/QueryResultsRegionImpl.java
===================================================================
--- core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/query/QueryResultsRegionImpl.java (rev 0)
+++ core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/query/QueryResultsRegionImpl.java 2007-10-18 20:08:50 UTC (rev 14101)
@@ -0,0 +1,124 @@
+/*
+ * Copyright (c) 2007, Red Hat Middleware, LLC. All rights reserved.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, v. 2.1. This program is distributed in the
+ * hope that it will be useful, but WITHOUT A WARRANTY; without even the implied
+ * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details. You should have received a
+ * copy of the GNU Lesser General Public License, v.2.1 along with this
+ * distribution; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Red Hat Author(s): Brian Stansberry
+ */
+
+package org.hibernate.cache.jbc2.query;
+
+import java.util.Properties;
+
+import org.hibernate.cache.CacheException;
+import org.hibernate.cache.QueryResultsRegion;
+import org.hibernate.cache.jbc2.TransactionalDataRegionAdapter;
+import org.hibernate.cache.jbc2.util.CacheHelper;
+import org.hibernate.util.PropertiesHelper;
+import org.jboss.cache.Cache;
+import org.jboss.cache.Fqn;
+import org.jboss.cache.config.Option;
+
+/**
+ * Defines the behavior of the query cache regions for JBossCache 2.x.
+ *
+ * @author Brian Stansberry
+ * @version $Revision$
+ */
+public class QueryResultsRegionImpl extends TransactionalDataRegionAdapter implements QueryResultsRegion {
+
+ public static final String QUERY_CACHE_LOCAL_ONLY_PROP = "hibernate.cache.region.jbc2.query.localonly";
+
+
+ /**
+ * Whether we should set an option to disable propagation of changes around
+ * cluster.
+ */
+ private boolean localOnly;
+
+ /**
+ * Create a new QueryResultsRegionImpl.
+ *
+ * @param jbcCache
+ * @param regionName
+ * @param regionPrefix
+ * TODO
+ */
+ public QueryResultsRegionImpl(Cache jbcCache, String regionName, String regionPrefix, Properties properties) {
+ super(jbcCache, regionName, regionPrefix, null);
+
+ // If JBC is using INVALIDATION, we don't want to propagate changes.
+ // We use the Timestamps cache to manage invalidation
+ localOnly = CacheHelper.isClusteredInvalidation(jbcCache);
+ if (!localOnly) {
+ // We don't want to waste effort setting an option if JBC is
+ // already in LOCAL mode. If JBC is REPL_(A)SYNC then check
+ // if they passed an config option to disable query replication
+ localOnly = CacheHelper.isClusteredReplication(jbcCache)
+ && PropertiesHelper.getBoolean(QUERY_CACHE_LOCAL_ONLY_PROP, properties, false);
+ }
+ }
+
+ public void evict(Object key) throws CacheException {
+ Option opt = getNonLockingDataVersionOption(false);
+ if (localOnly)
+ opt.setCacheModeLocal(true);
+ CacheHelper.remove(getCacheInstance(), getRegionFqn(), key, opt);
+ }
+
+ public void evictAll() throws CacheException {
+ Option opt = getNonLockingDataVersionOption(false);
+ if (localOnly)
+ opt.setCacheModeLocal(true);
+ CacheHelper.removeAll(getCacheInstance(), getRegionFqn(), opt);
+ }
+
+ public Object get(Object key) throws CacheException {
+
+ // Don't hold the JBC node lock throughout the tx, as that
+ // prevents updates
+ // Add a zero (or low) timeout option so we don't block
+ // waiting for tx's that did a put to commit
+ Option opt = new Option();
+ opt.setLockAcquisitionTimeout(0);
+ return suspendAndGet(key, opt, true);
+ }
+
+ public void put(Object key, Object value) throws CacheException {
+
+ // Here we don't want to suspend the tx. If we do:
+ // 1) We might be caching query results that reflect uncommitted
+ // changes. No tx == no WL on cache node, so other threads
+ // can prematurely see those query results
+ // 2) No tx == immediate replication. More overhead, plus we
+ // spread issue #1 above around the cluster
+
+ // Add a zero (or quite low) timeout option so we don't block
+ // Ignore any TimeoutException. Basically we forego caching the
+ // query result in order to avoid blocking for concurrent reads.
+ // Reads are done with suspended tx, so they should not hold the
+ // lock for long. Not caching the query result is OK, since
+ // any subsequent read will just see the old result with its
+ // out-of-date timestamp; that result will be discarded and the
+ // db query performed again.
+ Option opt = getNonLockingDataVersionOption(false);
+ opt.setLockAcquisitionTimeout(2);
+ if (localOnly)
+ opt.setCacheModeLocal(true);
+ CacheHelper.putAllowingTimeout(getCacheInstance(), getRegionFqn(), key, value, opt);
+ }
+
+ @Override
+ protected Fqn<String> createRegionFqn(String regionName, String regionPrefix) {
+ return Fqn.fromString(escapeRegionName(regionName, regionPrefix));
+ }
+
+}
Property changes on: core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/query/QueryResultsRegionImpl.java
___________________________________________________________________
Name: svn:keywords
+ Id Revision
Name: svn:eol-style
+ native
Added: core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/timestamp/TimestampsRegionImpl.java
===================================================================
--- core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/timestamp/TimestampsRegionImpl.java (rev 0)
+++ core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/timestamp/TimestampsRegionImpl.java 2007-10-18 20:08:50 UTC (rev 14101)
@@ -0,0 +1,207 @@
+/*
+ * Copyright (c) 2007, Red Hat Middleware, LLC. All rights reserved.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, v. 2.1. This program is distributed in the
+ * hope that it will be useful, but WITHOUT A WARRANTY; without even the implied
+ * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details. You should have received a
+ * copy of the GNU Lesser General Public License, v.2.1 along with this
+ * distribution; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Red Hat Author(s): Brian Stansberry
+ */
+
+package org.hibernate.cache.jbc2.timestamp;
+
+import java.util.Map;
+import java.util.Properties;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+
+import javax.transaction.Transaction;
+
+import org.hibernate.cache.CacheException;
+import org.hibernate.cache.TimestampsRegion;
+import org.hibernate.cache.jbc2.TransactionalDataRegionAdapter;
+import org.hibernate.cache.jbc2.util.CacheHelper;
+import org.jboss.cache.Cache;
+import org.jboss.cache.Fqn;
+import org.jboss.cache.config.Option;
+import org.jboss.cache.notifications.annotation.CacheListener;
+import org.jboss.cache.notifications.annotation.NodeModified;
+import org.jboss.cache.notifications.event.NodeModifiedEvent;
+
+/**
+ * Defines the behavior of the timestamps cache region for JBossCache 2.x.
+ * <p>
+ * Maintains a local (authoritative) cache of timestamps along with the
+ * distributed cache held in JBoss Cache. Listens for changes in the distributed
+ * cache and updates the local cache accordingly. Ensures that any changes in
+ * the local cache represent an increase in the timestamp. This approach allows
+ * timestamp changes to be replicated asynchronously by JBoss Cache while still
+ * preventing backward changes in timestamps.
+ * </p>
+ *
+ * @author Brian Stansberry
+ * @version $Revision$
+ */
+@CacheListener
+public class TimestampsRegionImpl extends TransactionalDataRegionAdapter implements TimestampsRegion {
+
+ public static final String TYPE = "TS";
+
+ private final Map localCache = new ConcurrentHashMap();
+
+ /**
+ * Create a new TimestampsRegionImpl.
+ *
+ * @param jbcCache
+ * @param regionName
+ * @param regionPrefix
+ * TODO
+ * @param metadata
+ */
+ public TimestampsRegionImpl(Cache jbcCache, String regionName, String regionPrefix, Properties properties) {
+ super(jbcCache, regionName, regionPrefix, null);
+
+ jbcCache.addCacheListener(this);
+
+ populateLocalCache();
+ }
+
+ @Override
+ protected Fqn<String> createRegionFqn(String regionName, String regionPrefix) {
+ return getTypeFirstRegionFqn(regionName, regionPrefix, TYPE);
+ }
+
+ public void evict(Object key) throws CacheException {
+ // TODO Is this a valid operation on a timestamps cache?
+ localCache.remove(key);
+ Option opt = getNonLockingDataVersionOption(true);
+ CacheHelper.remove(getCacheInstance(), getRegionFqn(), key, opt);
+ }
+
+ public void evictAll() throws CacheException {
+ // TODO Is this a valid operation on a timestamps cache?
+ localCache.clear();
+ Option opt = getNonLockingDataVersionOption(true);
+ CacheHelper.removeAll(getCacheInstance(), getRegionFqn(), opt);
+ }
+
+ public Object get(Object key) throws CacheException {
+
+ Object timestamp = localCache.get(key);
+ if (timestamp == null) {
+ // Check the cluster-wide cache
+ // Don't hold the cache node lock throughout the tx, as that
+ // prevents updates
+ timestamp = suspendAndGet(key, null, false);
+ updateLocalCache(key, timestamp);
+ }
+ return timestamp;
+ }
+
+ public void put(Object key, Object value) throws CacheException {
+
+ // Immediately update the local cache
+ boolean incremented = updateLocalCache(key, value);
+
+ if (incremented) {
+ // Now the cluster-wide cache
+
+ // TODO there's a race here where 2 threads can get through
+ // updateLocalCache() in proper sequence but then the earlier
+ // one updates JBC *later*. This should only affect newly
+ // joined nodes who populate their initial localCache from JBC.
+
+ // Don't hold the JBC node lock throughout the tx, as that
+ // prevents reads and other updates
+ Transaction tx = suspend();
+ try {
+ // We ensure ASYNC semantics (JBCACHE-1175)
+ Option opt = getNonLockingDataVersionOption(false);
+ opt.setForceAsynchronous(true);
+ getCacheInstance().getInvocationContext().setOptionOverrides(opt);
+ getCacheInstance().put(new Fqn(regionFqn, key), ITEM, value);
+ } catch (Exception e) {
+ throw new CacheException(e);
+ } finally {
+ resume(tx);
+ }
+ }
+ }
+
+ @Override
+ public void destroy() throws CacheException {
+
+ localCache.clear();
+ getCacheInstance().removeCacheListener(this);
+ super.destroy();
+ }
+
+ /**
+ * Monitors cache events and updates the local cache
+ *
+ * @param event
+ */
+ @NodeModified
+ public void nodeModified(NodeModifiedEvent event) {
+ if (event.isOriginLocal() || event.isPre())
+ return;
+
+ Fqn fqn = event.getFqn();
+ Fqn regFqn = getRegionFqn();
+ if (fqn.size() == regFqn.size() + 1 && fqn.isChildOf(regFqn)) {
+ Object key = fqn.get(regFqn.size());
+ updateLocalCache(key, event.getData().get(ITEM));
+ }
+ }
+
+ private void populateLocalCache() {
+ Set children = CacheHelper.getChildrenNames(getCacheInstance(), getRegionFqn());
+ for (Object key : children) {
+ get(key);
+ }
+ }
+
+ /**
+ * Updates the local cache, ensuring that the new value represents a higher
+ * value than the old (i.e. timestamp never goes back in time).
+ *
+ * @param key
+ * @param value
+ */
+ private boolean updateLocalCache(Object key, Object value) {
+ if (value == null)
+ return false;
+
+ boolean increase = true;
+
+ long newVal = 0;
+ try {
+ newVal = ((Long) value).longValue();
+
+ Long oldVal = (Long) localCache.get(key);
+ increase = oldVal == null || newVal > oldVal.longValue();
+ if (increase) {
+ oldVal = (Long) localCache.put(key, value);
+ // Double check that it was an increase
+ if (oldVal != null && oldVal.longValue() > newVal) {
+ // Nope; Restore the old value
+ increase = updateLocalCache(key, oldVal);
+ }
+ }
+ } catch (ClassCastException cce) {
+ // TODO -- this is stupid; look into changing TimestampsRegion API
+ // not using Long; just store it
+ localCache.put(key, value);
+ }
+
+ return increase;
+
+ }
+
+}
Property changes on: core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/timestamp/TimestampsRegionImpl.java
___________________________________________________________________
Name: svn:keywords
+ Id Revision
Name: svn:eol-style
+ native
Copied: core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/util/CacheHelper.java (from rev 13968, core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/util/CacheModeHelper.java)
===================================================================
--- core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/util/CacheHelper.java (rev 0)
+++ core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/util/CacheHelper.java 2007-10-18 20:08:50 UTC (rev 14101)
@@ -0,0 +1,441 @@
+/*
+ * Copyright (c) 2007, Red Hat Middleware, LLC. All rights reserved.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, v. 2.1. This program is distributed in the
+ * hope that it will be useful, but WITHOUT A WARRANTY; without even the implied
+ * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details. You should have received a
+ * copy of the GNU Lesser General Public License, v.2.1 along with this
+ * distribution; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Red Hat Author(s): Steve Ebersole
+ */
+package org.hibernate.cache.jbc2.util;
+
+import java.util.Collections;
+import java.util.Set;
+
+import org.hibernate.cache.CacheException;
+import org.jboss.cache.Cache;
+import org.jboss.cache.Fqn;
+import org.jboss.cache.InvocationContext;
+import org.jboss.cache.Node;
+import org.jboss.cache.config.Configuration;
+import org.jboss.cache.config.Option;
+import org.jboss.cache.lock.TimeoutException;
+import org.jboss.cache.optimistic.DataVersion;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Helper for dealing with JBossCache {@link Configuration.CacheMode}.
+ *
+ * @author Steve Ebersole
+ * @author Brian Stansberry
+ */
+public class CacheHelper {
+
+ /** Key under which items are cached */
+ public static final String ITEM = "item";
+ /** Key and value used in a hack to create region root nodes */
+ public static final String DUMMY = "dummy";
+
+ private static final Logger log = LoggerFactory.getLogger(CacheHelper.class);
+
+ /**
+ * Disallow external instantiation of CacheHelper.
+ */
+ private CacheHelper() {
+ }
+
+ /**
+ * Is this cache participating in a cluster with invalidation?
+ *
+ * @param cache
+ * The cache to check.
+ * @return True if the cache is configured for synchronous/asynchronous
+ * invalidation; false otherwise.
+ */
+ public static boolean isClusteredInvalidation(Cache cache) {
+ return isClusteredInvalidation(cache.getConfiguration().getCacheMode());
+ }
+
+ /**
+ * Does this cache mode indicate clustered invalidation?
+ *
+ * @param cacheMode
+ * The cache to check
+ * @return True if the cache mode is confiogured for
+ * synchronous/asynchronous invalidation; false otherwise.
+ */
+ public static boolean isClusteredInvalidation(Configuration.CacheMode cacheMode) {
+ return cacheMode == Configuration.CacheMode.INVALIDATION_ASYNC
+ || cacheMode == Configuration.CacheMode.INVALIDATION_SYNC;
+ }
+
+ /**
+ * Is this cache participating in a cluster with replication?
+ *
+ * @param cache
+ * The cache to check.
+ * @return True if the cache is configured for synchronous/asynchronous
+ * invalidation; false otherwise.
+ */
+ public static boolean isClusteredReplication(Cache cache) {
+ return isClusteredReplication(cache.getConfiguration().getCacheMode());
+ }
+
+ /**
+ * Does this cache mode indicate clustered replication?
+ *
+ * @param cacheMode
+ * The cache to check
+ * @return True if the cache mode is confiogured for
+ * synchronous/asynchronous invalidation; false otherwise.
+ */
+ public static boolean isClusteredReplication(Configuration.CacheMode cacheMode) {
+ return cacheMode == Configuration.CacheMode.REPL_ASYNC || cacheMode == Configuration.CacheMode.REPL_SYNC;
+ }
+
+ public static boolean isSynchronous(Cache cache) {
+ return isSynchronous(cache.getConfiguration().getCacheMode());
+ }
+
+ public static boolean isSynchronous(Configuration.CacheMode cacheMode) {
+ return cacheMode == Configuration.CacheMode.REPL_SYNC || cacheMode == Configuration.CacheMode.INVALIDATION_SYNC;
+ }
+
+ public static Set getChildrenNames(Cache cache, Fqn fqn) {
+ Node node = cache.getRoot().getChild(fqn);
+ return (node != null) ? node.getChildrenNames() : Collections.emptySet();
+ }
+
+ /**
+ * Builds an {@link Fqn} from <code>region</code> and <code>key</code>
+ * and performs a JBoss Cache <code>get(Fqn, Object)</code>, wrapping any
+ * exception in a {@link CacheException}.
+ *
+ * @param cache
+ * the cache to invoke on
+ * @param region
+ * base Fqn for the cache region
+ * @param key
+ * specific key to append to the <code>region</code> to form
+ * the full Fqn
+ */
+ public static Object get(Cache cache, Fqn region, Object key) throws CacheException {
+ try {
+ return cache.get(new Fqn(region, key), ITEM);
+ } catch (Exception e) {
+ throw new CacheException(e);
+ }
+ }
+
+ /**
+ * Builds an {@link Fqn} from <code>region</code> and <code>key</code>
+ * and performs a JBoss Cache <code>get(Fqn, Object)</code>, wrapping any
+ * exception in a {@link CacheException}.
+ *
+ * @param cache
+ * the cache to invoke on
+ * @param region
+ * base Fqn for the cache region
+ * @param key
+ * specific key to append to the <code>region</code> to form
+ * the full Fqn
+ */
+ public static Object getAllowingTimeout(Cache cache, Fqn region, Object key) throws CacheException {
+ try {
+ return cache.get(new Fqn(region, key), ITEM);
+ }
+ catch (TimeoutException ignored) {
+ // ignore it
+ return null;
+ }
+ catch (Exception e) {
+ throw new CacheException(e);
+ }
+ }
+
+ /**
+ * Builds an {@link Fqn} from <code>region</code> and <code>key</code>
+ * and performs a JBoss Cache <code>put(Object, Object)</code>, wrapping
+ * any exception in a {@link CacheException}.
+ *
+ * @param cache
+ * the cache to invoke on
+ * @param region
+ * base Fqn for the cache region
+ * @param key
+ * specific key to append to the <code>region</code> to form
+ * the full Fqn
+ * @param value
+ * data to store in the cache node
+ */
+ public static void put(Cache cache, Fqn region, Object key, Object value) throws CacheException {
+
+ put(cache, region, key, value, null);
+ }
+
+ /**
+ * Builds an {@link Fqn} from <code>region</code> and <code>key</code>
+ * and performs a JBoss Cache <code>put(Object, Object)</code>, wrapping
+ * any exception in a {@link CacheException}.
+ *
+ * @param cache
+ * the cache to invoke on
+ * @param region
+ * base Fqn for the cache region
+ * @param key
+ * specific key to append to the <code>region</code> to form
+ * the full Fqn
+ * @param value
+ * data to store in the cache node
+ * @param option
+ * invocation Option to set for this invocation. May be
+ * <code>null</code>.
+ */
+ public static void put(Cache cache, Fqn region, Object key, Object value, Option option) throws CacheException {
+ try {
+ setInvocationOption(cache, option);
+ cache.put(new Fqn(region, key), ITEM, value);
+ } catch (Exception e) {
+ throw new CacheException(e);
+ }
+ }
+
+ /**
+ * Builds an {@link Fqn} from <code>region</code> and <code>key</code>
+ * and performs a JBoss Cache <code>put(Object, Object)</code>, ignoring any
+ * {@link TimeoutException} and wrapping any other exception in a {@link CacheException}.
+ *
+ * @param cache
+ * the cache to invoke on
+ * @param region
+ * base Fqn for the cache region
+ * @param key
+ * specific key to append to the <code>region</code> to form
+ * the full Fqn
+ * @param value
+ * data to store in the cache node
+ * @param option
+ * invocation Option to set for this invocation. May be
+ * <code>null</code>.
+ */
+ public static void putAllowingTimeout(Cache cache, Fqn region, Object key, Object value, Option option) throws CacheException {
+ try {
+ setInvocationOption(cache, option);
+ cache.put(new Fqn(region, key), ITEM, value);
+ }
+ catch (TimeoutException allowed) {
+ // ignore it
+ }
+ catch (Exception e) {
+ throw new CacheException(e);
+ }
+ }
+
+ /**
+ * Builds an {@link Fqn} from <code>region</code> and <code>key</code>
+ * and performs a JBoss Cache
+ * <code>putForExternalRead(Object, Object)</code>, wrapping any
+ * exception in a {@link CacheException}. Ignores any JBoss Cache
+ * {@link TimeoutException}.
+ *
+ * @param cache
+ * the cache to invoke on
+ * @param region
+ * base Fqn for the cache region
+ * @param key
+ * specific key to append to the <code>region</code> to form
+ * the full Fqn
+ * @param value
+ * data to store in the cache node
+ */
+ public static boolean putForExternalRead(Cache cache, Fqn region, Object key, Object value) throws CacheException {
+
+ return putForExternalRead(cache, region, key, value, null);
+ }
+
+ /**
+ * Builds an {@link Fqn} from <code>region</code> and <code>key</code>
+ * and performs a JBoss Cache
+ * <code>putForExternalRead(Object, Object)</code>, wrapping any
+ * exception in a {@link CacheException}. Ignores any JBoss Cache
+ * {@link TimeoutException}.
+ *
+ * @param cache
+ * the cache to invoke on
+ * @param region
+ * base Fqn for the cache region
+ * @param key
+ * specific key to append to the <code>region</code> to form
+ * the full Fqn
+ * @param value
+ * data to store in the cache node
+ * @param option
+ * invocation Option to set for this invocation. May be
+ * <code>null</code>.
+ */
+ public static boolean putForExternalRead(Cache cache, Fqn region, Object key, Object value, Option option)
+ throws CacheException {
+ try {
+ setInvocationOption(cache, option);
+ cache.putForExternalRead(new Fqn(region, key), ITEM, value);
+ return true;
+ } catch (TimeoutException te) {
+ // ignore!
+ log.debug("ignoring write lock acquisition failure");
+ return false;
+ } catch (Throwable t) {
+ throw new CacheException(t);
+ }
+ }
+
+ /**
+ * Builds an {@link Fqn} from <code>region</code> and <code>key</code>
+ * and performs a JBoss Cache <code>removeNode(Fqn)</code>, wrapping any
+ * exception in a {@link CacheException}.
+ *
+ * @param cache
+ * the cache to invoke on
+ * @param region
+ * base Fqn for the cache region
+ * @param key
+ * specific key to append to the <code>region</code> to form
+ * the full Fqn
+ */
+ public static void remove(Cache cache, Fqn region, Object key) throws CacheException {
+
+ remove(cache, region, key, null);
+ }
+
+ /**
+ * Builds an {@link Fqn} from <code>region</code> and <code>key</code>
+ * and performs a JBoss Cache <code>removeNode(Fqn)</code>, wrapping any
+ * exception in a {@link CacheException}.
+ *
+ * @param cache
+ * the cache to invoke on
+ * @param region
+ * base Fqn for the cache region
+ * @param key
+ * specific key to append to the <code>region</code> to form
+ * the full Fqn
+ * @param option
+ * invocation Option to set for this invocation. May be
+ * <code>null</code>.
+ */
+ public static void remove(Cache cache, Fqn region, Object key, Option option) throws CacheException {
+ try {
+ setInvocationOption(cache, option);
+ cache.removeNode(new Fqn(region, key));
+ } catch (Exception e) {
+ throw new CacheException(e);
+ }
+ }
+
+ /**
+ * Performs a JBoss Cache <code>removeNode(Fqn)</code>, wrapping any
+ * exception in a {@link CacheException}.
+ *
+ * @param cache
+ * the cache to invoke on
+ * @param region
+ * base Fqn for the cache region
+ */
+ public static void removeAll(Cache cache, Fqn region) throws CacheException {
+
+ removeAll(cache, region, null);
+ }
+
+ /**
+ * Performs a JBoss Cache <code>removeNode(Fqn)</code>, wrapping any
+ * exception in a {@link CacheException}.
+ *
+ * @param cache
+ * the cache to invoke on
+ * @param region
+ * base Fqn for the cache region
+ * @param option
+ * invocation Option to set for this invocation. May be
+ * <code>null</code>.
+ */
+ public static void removeAll(Cache cache, Fqn region, Option option) throws CacheException {
+ try {
+ setInvocationOption(cache, option);
+ cache.removeNode(region);
+ } catch (Exception e) {
+ throw new CacheException(e);
+ }
+ }
+
+ public static Node addNode(Cache cache, Fqn fqn, boolean localOnly, boolean resident, DataVersion version)
+ throws CacheException {
+ try {
+ Option option = null;
+ if (localOnly || version != null) {
+ option = new Option();
+ option.setCacheModeLocal(localOnly);
+ option.setDataVersion(version);
+ }
+
+ Node root = cache.getRoot();
+ setInvocationOption(cache, option);
+ // FIXME hack to work around fact that calling
+ // Node added = root.addChild( fqn ); doesn't
+ // properly set the version on the node
+ Node added = null;
+ if (version == null) {
+ added = root.addChild( fqn );
+ }
+ else {
+ cache.put(fqn, DUMMY, DUMMY);
+ added = root.getChild(fqn);
+ }
+ if (resident)
+ added.setResident(true);
+ return added;
+ }
+ catch (Exception e) {
+ throw new CacheException(e);
+ }
+ }
+
+
+ /**
+ * Assigns the given Option to the cache's {@link InvocationContext}. Does
+ * nothing if <code>option</code> is <code>null</code>.
+ *
+ * @param cache
+ * the cache. Cannot be <code>null</code>.
+ * @param option
+ * the option. May be <code>null</code>.
+ *
+ * @see {@link Cache#getInvocationContext()}
+ * @see {@link InvocationContext#setOptionOverrides(Option)}
+ */
+ public static void setInvocationOption(Cache cache, Option option) {
+ if (option != null) {
+ cache.getInvocationContext().setOptionOverrides(option);
+ }
+ }
+
+ /**
+ * Creates an {@link Option} using the given {@link DataVersion} and passes
+ * it to {@link #setInvocationOption(Cache, Option)}.
+ *
+ * @param cache
+ * the cache to set the Option on. Cannot be <code>null</code>.
+ * @param version
+ * the DataVersion to set. Cannot be <code>null</code>.
+ */
+ public static void setDataVersionOption(Cache cache, DataVersion version) {
+ Option option = new Option();
+ option.setDataVersion(version);
+ setInvocationOption(cache, option);
+ }
+}
Deleted: core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/util/CacheModeHelper.java
===================================================================
--- core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/util/CacheModeHelper.java 2007-10-18 19:49:17 UTC (rev 14100)
+++ core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/util/CacheModeHelper.java 2007-10-18 20:08:50 UTC (rev 14101)
@@ -1,54 +0,0 @@
-/*
- * Copyright (c) 2007, Red Hat Middleware, LLC. All rights reserved.
- *
- * This copyrighted material is made available to anyone wishing to use, modify,
- * copy, or redistribute it subject to the terms and conditions of the GNU
- * Lesser General Public License, v. 2.1. This program is distributed in the
- * hope that it will be useful, but WITHOUT A WARRANTY; without even the implied
- * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details. You should have received a
- * copy of the GNU Lesser General Public License, v.2.1 along with this
- * distribution; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * Red Hat Author(s): Steve Ebersole
- */
-package org.hibernate.cache.jbc2.util;
-
-import org.jboss.cache.Cache;
-import org.jboss.cache.config.Configuration;
-
-/**
- * Helper for dealing with JBossCache {@link Configuration.CacheMode}.
- *
- * @author Steve Ebersole
- */
-public class CacheModeHelper {
- /**
- * Disallow external instantiation of CacheModeHelper.
- */
- private CacheModeHelper() {
- }
-
- /**
- * Is this cache participating in a cluster with invalidation?
- *
- * @param cache The cache to check.
- * @return True if the cache is configured for synchronous/asynchronous invalidation; false
- * otherwise.
- */
- public static boolean isClusteredInvalidation(Cache cache) {
- return isClusteredInvalidation( cache.getConfiguration().getCacheMode() );
- }
-
- /**
- * Does this cache mode indicate clustered invalidation?
- *
- * @param cacheMode The cache to check
- * @return True if the cache mode is confiogured for synchronous/asynchronous invalidation; false
- * otherwise.
- */
- public static boolean isClusteredInvalidation(Configuration.CacheMode cacheMode) {
- return cacheMode == Configuration.CacheMode.REPL_ASYNC || cacheMode == Configuration.CacheMode.REPL_SYNC;
- }
-}
Added: core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/util/CircumventChecksDataVersion.java
===================================================================
--- core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/util/CircumventChecksDataVersion.java (rev 0)
+++ core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/util/CircumventChecksDataVersion.java 2007-10-18 20:08:50 UTC (rev 14101)
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2007, Red Hat Middleware, LLC. All rights reserved.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, v. 2.1. This program is distributed in the
+ * hope that it will be useful, but WITHOUT A WARRANTY; without even the implied
+ * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details. You should have received a
+ * copy of the GNU Lesser General Public License, v.2.1 along with this
+ * distribution; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Red Hat Author(s): Brian Stansberry
+ */
+
+package org.hibernate.cache.jbc2.util;
+
+import org.hibernate.cache.CacheException;
+import org.jboss.cache.config.Option;
+import org.jboss.cache.optimistic.DataVersion;
+
+/**
+ * Used to signal to a DataVersionAdapter to simply not perform any checks. This
+ * is currently needed for proper handling of remove() calls for entity cache
+ * regions (we do not know the version info...).
+ *
+ * @author <a href="brian.stansberry(a)jboss.com">Brian Stansberry</a>
+ * @version $Revision: 1 $
+ */
+public class CircumventChecksDataVersion implements DataVersion {
+
+ private static final long serialVersionUID = 7996980646166032369L;
+
+ public static final DataVersion INSTANCE = new CircumventChecksDataVersion();
+
+ public static Option getInvocationOption() {
+ Option option = new Option();
+ option.setDataVersion(INSTANCE);
+ return option;
+ }
+
+ public boolean newerThan(DataVersion dataVersion) {
+ throw new CacheException("optimistic locking checks should never happen on CircumventChecksDataVersion");
+ }
+
+}
Property changes on: core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/util/CircumventChecksDataVersion.java
___________________________________________________________________
Name: svn:executable
+ *
Added: core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/util/DataVersionAdapter.java
===================================================================
--- core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/util/DataVersionAdapter.java (rev 0)
+++ core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/util/DataVersionAdapter.java 2007-10-18 20:08:50 UTC (rev 14101)
@@ -0,0 +1,152 @@
+/*
+ * Copyright (c) 2007, Red Hat Middleware, LLC. All rights reserved.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, v. 2.1. This program is distributed in the
+ * hope that it will be useful, but WITHOUT A WARRANTY; without even the implied
+ * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details. You should have received a
+ * copy of the GNU Lesser General Public License, v.2.1 along with this
+ * distribution; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Red Hat Author(s): Brian Stansberry
+ */
+
+package org.hibernate.cache.jbc2.util;
+
+import java.io.IOException;
+import java.util.Comparator;
+
+import org.hibernate.cache.jbc2.entity.TransactionalAccess;
+import org.hibernate.util.CalendarComparator;
+import org.hibernate.util.ComparableComparator;
+import org.jboss.cache.optimistic.DataVersion;
+import org.jboss.cache.optimistic.DefaultDataVersion;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * A DataVersionAdapter.
+ *
+ * @author <a href="brian.stansberry(a)jboss.com">Brian Stansberry</a>
+ * @version $Revision: 1 $
+ */
+public class DataVersionAdapter implements DataVersion {
+
+ private static final Logger log = LoggerFactory.getLogger(TransactionalAccess.class);
+
+ private static final long serialVersionUID = 5564692336076405571L;
+
+ private final Object currentVersion;
+
+ private final Object previousVersion;
+
+ /**
+ * Comparator does not extend Serializable and the std impls don't either,
+ * so we make the field transient to allow special handling
+ */
+ private transient Comparator versionComparator;
+
+ private final String sourceIdentifer;
+
+ public DataVersionAdapter(Object currentVersion, Object previousVersion, Comparator versionComparator,
+ String sourceIdentifer) {
+ this.currentVersion = currentVersion;
+ this.previousVersion = previousVersion;
+ this.versionComparator = versionComparator;
+ this.sourceIdentifer = sourceIdentifer;
+ log.trace("created " + this);
+ }
+
+ /**
+ * newerThan() call is dispatched against the DataVersion currently
+ * associated with the node; the passed dataVersion param is the DataVersion
+ * associated with the data we are trying to put into the node. <p/> we are
+ * expected to return true in the case where we (the current node
+ * DataVersion) are newer that then incoming value. Returning true here
+ * essentially means that a optimistic lock failure has occured (because
+ * conversely, the value we are trying to put into the node is "older than"
+ * the value already there...)
+ */
+ public boolean newerThan(DataVersion dataVersion) {
+ log.trace("checking [" + this + "] against [" + dataVersion + "]");
+ if (dataVersion instanceof CircumventChecksDataVersion) {
+ log.trace("skipping lock checks...");
+ return false;
+ } else if (dataVersion instanceof NonLockingDataVersion) {
+ // can happen because of the multiple ways Cache.remove()
+ // can be invoked :(
+ log.trace("skipping lock checks...");
+ return false;
+ } else if (dataVersion instanceof DefaultDataVersion) {
+ if (((DefaultDataVersion) dataVersion).getRawVersion() == 0) {
+ // JBC put a version in the node when it created it as
+ // part of building a larger tree
+ return true;
+ } else {
+ log.error("Cannot compare to " + dataVersion);
+ return false;
+ }
+ }
+ DataVersionAdapter other = (DataVersionAdapter) dataVersion;
+ if (other.previousVersion == null) {
+ log.warn("Unexpected optimistic lock check on inserting data");
+ // work around the "feature" where tree cache is validating the
+ // inserted node during the next transaction. no idea...
+ if (this == dataVersion) {
+ log.trace("skipping lock checks due to same DV instance");
+ return false;
+ }
+ }
+
+ if (currentVersion == null) {
+ // If the workspace node has null as well, OK; if not we've
+ // been modified in a non-comparable manner, which we have to
+ // treat as us being newer
+ return (other.previousVersion != null);
+ }
+
+ return versionComparator.compare(currentVersion, other.previousVersion) >= 1;
+ }
+
+ public String toString() {
+ return super.toString() + " [current=" + currentVersion + ", previous=" + previousVersion + ", src="
+ + sourceIdentifer + "]";
+ }
+
+
+ private void writeObject(java.io.ObjectOutputStream out) throws IOException {
+ out.defaultWriteObject();
+
+ // The standard comparator types are not Serializable but are singletons
+ if (versionComparator instanceof ComparableComparator)
+ out.writeByte(0);
+ else if (versionComparator instanceof CalendarComparator)
+ out.writeByte(1);
+ else {
+ out.writeByte(999);
+ out.writeObject(versionComparator);
+ }
+ }
+
+ private void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException {
+
+ in.defaultReadObject();
+ byte comparatorType = in.readByte();
+ switch (comparatorType) {
+ case 0:
+ versionComparator = ComparableComparator.INSTANCE;
+ break;
+ case 1:
+ versionComparator = CalendarComparator.INSTANCE;
+ break;
+ default:
+ versionComparator = (Comparator) in.readObject();
+ }
+ }
+
+
+
+}
Property changes on: core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/util/DataVersionAdapter.java
___________________________________________________________________
Name: svn:executable
+ *
Added: core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/util/NonLockingDataVersion.java
===================================================================
--- core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/util/NonLockingDataVersion.java (rev 0)
+++ core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/util/NonLockingDataVersion.java 2007-10-18 20:08:50 UTC (rev 14101)
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2007, Red Hat Middleware, LLC. All rights reserved.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, v. 2.1. This program is distributed in the
+ * hope that it will be useful, but WITHOUT A WARRANTY; without even the implied
+ * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details. You should have received a
+ * copy of the GNU Lesser General Public License, v.2.1 along with this
+ * distribution; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Red Hat Author(s): Brian Stansberry
+ */
+
+package org.hibernate.cache.jbc2.util;
+
+import org.hibernate.cache.jbc2.entity.TransactionalAccess;
+import org.jboss.cache.config.Option;
+import org.jboss.cache.optimistic.DataVersion;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * {@link DataVersion} used in regions where no locking should ever occur. This
+ * includes query-caches, update-timestamps caches, collection caches, and
+ * entity caches where the entity is not versioned.
+ *
+ * @author <a href="brian.stansberry(a)jboss.com">Brian Stansberry</a>
+ * @version $Revision: 1 $
+ */
+public class NonLockingDataVersion implements DataVersion {
+
+ private static final Logger log = LoggerFactory.getLogger(TransactionalAccess.class);
+
+ private static final long serialVersionUID = 7050722490368630553L;
+
+ public static final DataVersion INSTANCE = new NonLockingDataVersion();
+
+ public static Option getInvocationOption() {
+ Option option = new Option();
+ option.setDataVersion(INSTANCE);
+ return option;
+ }
+
+ public boolean newerThan(DataVersion dataVersion) {
+
+// if (dataVersion instanceof DefaultDataVersion) {
+// log.info("unexpectedly validating against a DefaultDataVersion", new Exception("Just a stack trace"));
+// return true;
+// }
+// else {
+ log.trace("non locking lock check...");
+ return false;
+// }
+ }
+
+}
Property changes on: core/trunk/cache-jbosscache2/src/main/java/org/hibernate/cache/jbc2/util/NonLockingDataVersion.java
___________________________________________________________________
Name: svn:executable
+ *
Added: core/trunk/cache-jbosscache2/src/main/resources/org/hibernate/cache/jbc2/builder/jbc2-configs.xml
===================================================================
(Binary files differ)
Property changes on: core/trunk/cache-jbosscache2/src/main/resources/org/hibernate/cache/jbc2/builder/jbc2-configs.xml
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/AbstractEntityCollectionRegionTestCase.java
===================================================================
--- core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/AbstractEntityCollectionRegionTestCase.java (rev 0)
+++ core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/AbstractEntityCollectionRegionTestCase.java 2007-10-18 20:08:50 UTC (rev 14101)
@@ -0,0 +1,140 @@
+/*
+ * Copyright (c) 2007, Red Hat Middleware, LLC. All rights reserved.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, v. 2.1. This program is distributed in the
+ * hope that it will be useful, but WITHOUT A WARRANTY; without even the implied
+ * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details. You should have received a
+ * copy of the GNU Lesser General Public License, v.2.1 along with this
+ * distribution; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Red Hat Author(s): Brian Stansberry
+ */
+
+package org.hibernate.test.cache.jbc2;
+
+import java.util.Properties;
+
+import org.hibernate.cache.CacheDataDescription;
+import org.hibernate.cache.RegionFactory;
+import org.hibernate.cache.TransactionalDataRegion;
+import org.hibernate.cache.access.AccessType;
+import org.hibernate.cache.jbc2.JBossCacheRegionFactory;
+import org.hibernate.cache.jbc2.MultiplexedJBossCacheRegionFactory;
+import org.hibernate.cache.jbc2.SharedJBossCacheRegionFactory;
+import org.hibernate.cache.jbc2.builder.MultiplexingCacheInstanceManager;
+import org.hibernate.cache.jbc2.builder.SharedCacheInstanceManager;
+import org.hibernate.cfg.Configuration;
+import org.hibernate.cfg.Environment;
+import org.hibernate.test.util.CacheTestUtil;
+
+/**
+ * Base class for tests of EntityRegion and CollectionRegion implementations.
+ *
+ * @author <a href="brian.stansberry(a)jboss.com">Brian Stansberry</a>
+ * @version $Revision: 1 $
+ */
+public abstract class AbstractEntityCollectionRegionTestCase extends AbstractRegionImplTestCase {
+
+ /**
+ * Create a new EntityCollectionRegionTestCaseBase.
+ *
+ * @param name
+ */
+ public AbstractEntityCollectionRegionTestCase(String name) {
+ super(name);
+ }
+
+ /**
+ * Create a Region backed by an OPTIMISTIC locking JBoss Cache, and then
+ * ensure that it handles calls to buildAccessStrategy as expected when
+ * all the various {@link AccessType}s are passed as arguments.
+ */
+ public void testSupportedAccessTypesOptimistic() throws Exception {
+
+ supportedAccessTypeTest(true);
+ }
+
+ /**
+ * Creates a Region backed by an PESSIMISTIC locking JBoss Cache, and then
+ * ensures that it handles calls to buildAccessStrategy as expected when
+ * all the various {@link AccessType}s are passed as arguments.
+ */
+ public void testSupportedAccessTypesPessimistic() throws Exception {
+
+ supportedAccessTypeTest(false);
+ }
+
+ private void supportedAccessTypeTest(boolean optimistic) throws Exception {
+
+ Configuration cfg = CacheTestUtil.buildConfiguration("test", MultiplexedJBossCacheRegionFactory.class, true, false);
+ String entityCfg = optimistic ? "optimistic-entity" : "pessimistic-entity";
+ cfg.setProperty(MultiplexingCacheInstanceManager.ENTITY_CACHE_RESOURCE_PROP, entityCfg);
+
+ JBossCacheRegionFactory regionFactory = CacheTestUtil.startRegionFactory(cfg, getCacheTestSupport());
+
+ supportedAccessTypeTest(regionFactory, cfg.getProperties());
+ }
+
+ /**
+ * Creates a Region using the given factory, and then ensure that it
+ * handles calls to buildAccessStrategy as expected when all the
+ * various {@link AccessType}s are passed as arguments.
+ */
+ protected abstract void supportedAccessTypeTest(RegionFactory regionFactory, Properties properties);
+
+ /**
+ * Test that the Region properly implements
+ * {@link TransactionalDataRegion#isTransactionAware()}.
+ *
+ * @throws Exception
+ */
+ public void testIsTransactionAware() throws Exception {
+
+ Configuration cfg = CacheTestUtil.buildConfiguration("test", SharedJBossCacheRegionFactory.class, true, false);
+ cfg.setProperty(SharedCacheInstanceManager.CACHE_RESOURCE_PROP, CacheTestUtil.LOCAL_PESSIMISTIC_CACHE);
+
+ JBossCacheRegionFactory regionFactory = CacheTestUtil.startRegionFactory(cfg, getCacheTestSupport());
+
+ TransactionalDataRegion region = (TransactionalDataRegion) createRegion(regionFactory, "test/test", cfg.getProperties(), getCacheDataDescription());
+
+ assertTrue("Region is transaction-aware", region.isTransactionAware());
+
+ CacheTestUtil.stopRegionFactory(regionFactory, getCacheTestSupport());
+
+ cfg = CacheTestUtil.buildConfiguration("test", SharedJBossCacheRegionFactory.class, true, false);
+ cfg.setProperty(SharedCacheInstanceManager.CACHE_RESOURCE_PROP, CacheTestUtil.LOCAL_PESSIMISTIC_CACHE);
+ // Make it non-transactional
+ cfg.getProperties().remove(Environment.TRANSACTION_MANAGER_STRATEGY);
+
+ regionFactory = CacheTestUtil.startRegionFactory(cfg, getCacheTestSupport());
+
+ region = (TransactionalDataRegion) createRegion(regionFactory, "test/test", cfg.getProperties(), getCacheDataDescription());
+
+ assertFalse("Region is not transaction-aware", region.isTransactionAware());
+
+ CacheTestUtil.stopRegionFactory(regionFactory, getCacheTestSupport());
+ }
+
+ public void testGetCacheDataDescription() throws Exception {
+ Configuration cfg = CacheTestUtil.buildConfiguration("test", SharedJBossCacheRegionFactory.class, true, false);
+ cfg.setProperty(SharedCacheInstanceManager.CACHE_RESOURCE_PROP, CacheTestUtil.LOCAL_PESSIMISTIC_CACHE);
+
+ JBossCacheRegionFactory regionFactory = CacheTestUtil.startRegionFactory(cfg, getCacheTestSupport());
+
+ TransactionalDataRegion region = (TransactionalDataRegion) createRegion(regionFactory, "test/test", cfg.getProperties(), getCacheDataDescription());
+
+ CacheDataDescription cdd = region.getCacheDataDescription();
+
+ assertNotNull(cdd);
+
+ CacheDataDescription expected = getCacheDataDescription();
+ assertEquals(expected.isMutable(), cdd.isMutable());
+ assertEquals(expected.isVersioned(), cdd.isVersioned());
+ assertEquals(expected.getVersionComparator(), cdd.getVersionComparator());
+
+ }
+}
Added: core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/AbstractJBossCacheTestCase.java
===================================================================
--- core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/AbstractJBossCacheTestCase.java (rev 0)
+++ core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/AbstractJBossCacheTestCase.java 2007-10-18 20:08:50 UTC (rev 14101)
@@ -0,0 +1,118 @@
+package org.hibernate.test.cache.jbc2;
+
+import java.util.Enumeration;
+import java.util.HashSet;
+import java.util.Set;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+
+import org.hibernate.cache.RegionFactory;
+import org.hibernate.junit.UnitTestCase;
+import org.hibernate.test.util.CacheTestSupport;
+import org.jboss.cache.Cache;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Base class for all non-functional tests of JBoss Cache integration.
+ *
+ * @author <a href="brian.stansberry(a)jboss.com">Brian Stansberry</a>
+ * @version $Revision: 1 $
+ */
+public abstract class AbstractJBossCacheTestCase extends UnitTestCase {
+
+ public static final String REGION_PREFIX = "test";
+
+ private CacheTestSupport testSupport = new CacheTestSupport();
+ protected final Logger log = LoggerFactory.getLogger(getClass());
+
+
+ public AbstractJBossCacheTestCase(String name) {
+ super(name);
+ }
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+
+ testSupport.setUp();
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ super.tearDown();
+
+ testSupport.tearDown();
+ }
+
+ protected void registerCache(Cache cache) {
+ testSupport.registerCache(cache);
+ }
+
+ protected void unregisterCache(Cache cache) {
+ testSupport.unregisterCache(cache);
+ }
+
+ protected void registerFactory(RegionFactory factory) {
+ testSupport.registerFactory(factory);
+ }
+
+ protected void unregisterFactory(RegionFactory factory) {
+ testSupport.unregisterFactory(factory);
+ }
+
+ protected CacheTestSupport getCacheTestSupport() {
+ return testSupport;
+ }
+
+ protected void sleep(long ms) {
+ try {
+ Thread.sleep(ms);
+ }
+ catch (InterruptedException e) {
+ log.warn("Interrupted during sleep", e);
+ }
+ }
+
+
+ /**
+ * Supports easy creation of a TestSuite where a subclass' "FailureExpected"
+ * version of a base test is included in the suite, while the base test
+ * is excluded. E.g. test class FooTestCase includes method testBar(), while test
+ * class SubFooTestCase extends FooTestCase includes method testBarFailureExcluded().
+ * Passing SubFooTestCase.class to this method will return a suite that
+ * does not include testBar().
+ *
+ * FIXME Move this to UnitTestCase
+ */
+ public static TestSuite createFailureExpectedSuite(Class testClass) {
+
+ TestSuite allTests = new TestSuite(testClass);
+ Set failureExpected = new HashSet();
+ Enumeration tests = allTests.tests();
+ while (tests.hasMoreElements()) {
+ Test t = (Test) tests.nextElement();
+ if (t instanceof TestCase) {
+ String name = ((TestCase) t).getName();
+ if (name.endsWith("FailureExpected"))
+ failureExpected.add(name);
+ }
+ }
+
+ TestSuite result = new TestSuite();
+ tests = allTests.tests();
+ while (tests.hasMoreElements()) {
+ Test t = (Test) tests.nextElement();
+ if (t instanceof TestCase) {
+ String name = ((TestCase) t).getName();
+ if (!failureExpected.contains(name + "FailureExpected")) {
+ result.addTest(t);
+ }
+ }
+ }
+
+ return result;
+ }
+}
\ No newline at end of file
Added: core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/AbstractRegionImplTestCase.java
===================================================================
--- core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/AbstractRegionImplTestCase.java (rev 0)
+++ core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/AbstractRegionImplTestCase.java 2007-10-18 20:08:50 UTC (rev 14101)
@@ -0,0 +1,122 @@
+/*
+ * Copyright (c) 2007, Red Hat Middleware, LLC. All rights reserved.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, v. 2.1. This program is distributed in the
+ * hope that it will be useful, but WITHOUT A WARRANTY; without even the implied
+ * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details. You should have received a
+ * copy of the GNU Lesser General Public License, v.2.1 along with this
+ * distribution; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Red Hat Author(s): Brian Stansberry
+ */
+
+package org.hibernate.test.cache.jbc2;
+
+import java.util.Properties;
+
+import org.hibernate.cache.CacheDataDescription;
+import org.hibernate.cache.Region;
+import org.hibernate.cache.impl.CacheDataDescriptionImpl;
+import org.hibernate.cache.jbc2.JBossCacheRegionFactory;
+import org.hibernate.cache.jbc2.SharedJBossCacheRegionFactory;
+import org.hibernate.cache.jbc2.builder.SharedCacheInstanceManager;
+import org.hibernate.cfg.Configuration;
+import org.hibernate.test.util.CacheTestUtil;
+import org.hibernate.util.ComparableComparator;
+import org.jboss.cache.Cache;
+import org.jboss.cache.DefaultCacheFactory;
+import org.jboss.cache.Fqn;
+import org.jboss.cache.Node;
+import org.jboss.cache.config.Option;
+import org.jgroups.JChannelFactory;
+
+/**
+ * Base class for tests of Region implementations.
+ *
+ * @author <a href="brian.stansberry(a)jboss.com">Brian Stansberry</a>
+ * @version $Revision: 1 $
+ */
+public abstract class AbstractRegionImplTestCase extends AbstractJBossCacheTestCase {
+
+ /**
+ * Create a new RegionImplTestCaseBase.
+ *
+ * @param name
+ */
+ public AbstractRegionImplTestCase(String name) {
+ super(name);
+ }
+
+ /**
+ * Tests proper handling of region initialization and destruction.
+ *
+ * @throws Exception
+ */
+ public void testActivationDeactivation() throws Exception {
+
+ // Set up a cache to monitor affects of starting the region
+ Cache remoteCache = DefaultCacheFactory.getInstance().createCache(SharedCacheInstanceManager.DEFAULT_CACHE_RESOURCE, false);
+
+ // This test assumes replication; verify that's correct
+ assertEquals("Cache is REPL_SYNC", "REPL_SYNC", remoteCache.getConfiguration().getCacheModeString());
+
+ JChannelFactory channelFactory = new JChannelFactory();
+ channelFactory.setMultiplexerConfig(SharedCacheInstanceManager.DEF_MULTIPLEXER_RESOURCE);
+ remoteCache.getConfiguration().getRuntimeConfig().setMuxChannelFactory(channelFactory);
+ remoteCache.start();
+
+ // Make sure we stop the remoteCache
+ registerCache(remoteCache);
+
+ Fqn regionFqn = getRegionFqn("test/test", "test");
+
+ assertNull("No region node", remoteCache.getRoot().getChild( regionFqn ));
+
+ Configuration cfg = CacheTestUtil.buildConfiguration("test", SharedJBossCacheRegionFactory.class, true, true);
+ JBossCacheRegionFactory regionFactory = CacheTestUtil.startRegionFactory(cfg, getCacheTestSupport());
+
+ Region region = createRegion(regionFactory, "test/test", cfg.getProperties(), getCacheDataDescription());
+
+ Cache localCache = getJBossCache( regionFactory );
+
+ // This test assumes replication; verify that's correct
+ assertEquals("Cache is REPL_SYNC", "REPL_SYNC", localCache.getConfiguration().getCacheModeString());
+
+ // Region creation should not have affected remoteCache
+
+ assertNull("No region node", remoteCache.getRoot().getChild( regionFqn ));
+ Node regionRoot = localCache.getRoot().getChild( regionFqn );
+ assertTrue("Has a node at " + regionFqn, regionRoot != null );
+ assertTrue(regionFqn + " is resident", regionRoot.isResident() );
+
+ // Confirm region destroy does not affect remote cache
+
+ Option option = new Option();
+ option.setCacheModeLocal(true);
+ remoteCache.getInvocationContext().setOptionOverrides(option);
+ remoteCache.put(regionFqn, "test", "test");
+
+ assertEquals("Put succeeded", "test", remoteCache.get(regionFqn, "test"));
+ assertNull("Put was local", localCache.get(regionFqn, "test"));
+
+ region.destroy();
+
+ assertEquals("Remote cache unchanged", "test", remoteCache.get(regionFqn, "test"));
+ assertNull("No region node", localCache.getRoot().getChild( regionFqn ));
+ }
+
+ protected abstract Cache getJBossCache(JBossCacheRegionFactory regionFactory);
+
+ protected abstract Fqn getRegionFqn(String regionName, String regionPrefix);
+
+ protected abstract Region createRegion(JBossCacheRegionFactory regionFactory, String regionName, Properties properties, CacheDataDescription cdd);
+
+ protected CacheDataDescription getCacheDataDescription() {
+ return new CacheDataDescriptionImpl(true, true, ComparableComparator.INSTANCE);
+ }
+
+}
Added: core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/JBossCacheComplianceTest.java
===================================================================
--- core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/JBossCacheComplianceTest.java (rev 0)
+++ core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/JBossCacheComplianceTest.java 2007-10-18 20:08:50 UTC (rev 14101)
@@ -0,0 +1,150 @@
+package org.hibernate.test.cache.jbc2;
+
+import junit.framework.TestCase;
+
+import org.hibernate.cache.RegionFactory;
+import org.hibernate.cache.jbc2.JBossCacheRegionFactory;
+import org.hibernate.cache.jbc2.MultiplexedJBossCacheRegionFactory;
+import org.hibernate.cache.jbc2.builder.SharedCacheInstanceManager;
+import org.hibernate.cache.jbc2.util.CacheHelper;
+import org.hibernate.cfg.Configuration;
+import org.hibernate.cfg.Settings;
+import org.hibernate.test.util.CacheTestSupport;
+import org.hibernate.test.util.CacheTestUtil;
+import org.jboss.cache.Cache;
+import org.jboss.cache.Fqn;
+import org.jboss.cache.config.Option;
+import org.jboss.cache.optimistic.DataVersion;
+import org.jboss.cache.transaction.BatchModeTransactionManager;
+
+/**
+ * Tests that JBC itself functions as expected in certain areas where there
+ * may have been problems in the past. Basically tests JBC itself, not the
+ * Hibernate/JBC integration.
+ *
+ * TODO if the equivalent tests are not in the JBC testsuite, add them.
+ *
+ * @author Brian Stansberry
+ */
+public class JBossCacheComplianceTest extends TestCase {
+
+ private CacheTestSupport testSupport = new CacheTestSupport();
+
+
+ public JBossCacheComplianceTest(String x) {
+ super(x);
+ }
+
+ protected String getConfigResourceKey() {
+ return SharedCacheInstanceManager.CACHE_RESOURCE_PROP;
+ }
+
+ protected String getConfigResourceLocation() {
+ return "org/hibernate/test/cache/jbc2/functional/optimistic-treecache.xml";
+ }
+
+ protected Class<? extends RegionFactory> getCacheRegionFactory() {
+ return JBossCacheRegionFactory.class;
+ }
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+
+ testSupport.setUp();
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+
+ testSupport.tearDown();
+
+ super.tearDown();
+ }
+
+ @SuppressWarnings("unchecked")
+ public void testCacheLevelStaleWritesFail() throws Throwable {
+
+ Configuration cfg = CacheTestUtil.buildConfiguration("", MultiplexedJBossCacheRegionFactory.class, true, false);
+ cfg.setProperty(getConfigResourceKey(), getConfigResourceLocation());
+
+ Settings settings = cfg.buildSettings();
+
+ Fqn<String> fqn = Fqn.fromString("/whatever");
+ JBossCacheRegionFactory regionFactory = (JBossCacheRegionFactory) settings.getRegionFactory();
+ regionFactory.start(settings, cfg.getProperties());
+
+ // Make sure we clean up when done
+ testSupport.registerFactory(regionFactory);
+
+ Cache<Object, Object> treeCache = regionFactory.getCacheInstanceManager().getEntityCacheInstance();
+
+ // Make sure this is an OPTIMISTIC cache
+ assertEquals("Cache is OPTIMISTIC", "OPTIMISTIC", treeCache.getConfiguration().getNodeLockingSchemeString());
+
+ Long long1 = new Long(1);
+ Long long2 = new Long(2);
+
+ try {
+ System.out.println("****************************************************************");
+ BatchModeTransactionManager.getInstance().begin();
+ CacheHelper.setInvocationOption(treeCache, ManualDataVersion.gen(1));
+ treeCache.put(fqn, "ITEM", long1);
+ BatchModeTransactionManager.getInstance().commit();
+
+ System.out.println("****************************************************************");
+ BatchModeTransactionManager.getInstance().begin();
+ CacheHelper.setInvocationOption(treeCache, ManualDataVersion.gen(2));
+ treeCache.put(fqn, "ITEM", long2);
+ BatchModeTransactionManager.getInstance().commit();
+
+ try {
+ System.out.println("****************************************************************");
+ BatchModeTransactionManager.getInstance().begin();
+ CacheHelper.setInvocationOption(treeCache, ManualDataVersion.gen(1));
+ treeCache.put(fqn, "ITEM", long1);
+ BatchModeTransactionManager.getInstance().commit();
+ fail("stale write allowed");
+ } catch (Throwable ignore) {
+ // expected behavior
+ try {
+ BatchModeTransactionManager.getInstance().rollback();
+ }
+ catch (IllegalStateException ignored) {
+ // tx is already cleared
+ }
+ }
+
+ Long current = (Long) treeCache.get(fqn, "ITEM");
+ assertEquals("unexpected current value", 2, current.longValue());
+ } finally {
+ try {
+ treeCache.remove(fqn, "ITEM");
+ } catch (Throwable ignore) {
+ }
+ }
+ }
+
+ private static class ManualDataVersion implements DataVersion {
+
+ /** The serialVersionUID */
+ private static final long serialVersionUID = 1L;
+
+ private final int version;
+
+ public ManualDataVersion(int version) {
+ this.version = version;
+ }
+
+ public boolean newerThan(DataVersion dataVersion) {
+ return this.version > ((ManualDataVersion) dataVersion).version;
+ }
+
+ public static Option gen(int version) {
+ ManualDataVersion mdv = new ManualDataVersion(version);
+ Option option = new Option();
+ option.setDataVersion(mdv);
+ return option;
+ }
+ }
+}
Property changes on: core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/JBossCacheComplianceTest.java
___________________________________________________________________
Name: svn:executable
+ *
Added: core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/JBossCacheRegionFactoryTestCase.java
===================================================================
--- core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/JBossCacheRegionFactoryTestCase.java (rev 0)
+++ core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/JBossCacheRegionFactoryTestCase.java 2007-10-18 20:08:50 UTC (rev 14101)
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 2007, Red Hat Middleware, LLC. All rights reserved.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, v. 2.1. This program is distributed in the
+ * hope that it will be useful, but WITHOUT A WARRANTY; without even the implied
+ * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details. You should have received a
+ * copy of the GNU Lesser General Public License, v.2.1 along with this
+ * distribution; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Red Hat Author(s): Brian Stansberry
+ */
+
+package org.hibernate.test.cache.jbc2;
+
+import java.util.Properties;
+
+import org.hibernate.cache.jbc2.CacheInstanceManager;
+import org.hibernate.cache.jbc2.JBossCacheRegionFactory;
+import org.hibernate.cache.jbc2.builder.MultiplexingCacheInstanceManager;
+import org.hibernate.cache.jbc2.builder.SharedCacheInstanceManager;
+import org.hibernate.cfg.Configuration;
+import org.hibernate.cfg.Settings;
+import org.hibernate.test.util.CacheTestUtil;
+import org.jboss.cache.Cache;
+import org.jboss.cache.CacheStatus;
+
+/**
+ * A JBossCacheRegionFactoryTestCase.
+ *
+ * @author <a href="brian.stansberry(a)jboss.com">Brian Stansberry</a>
+ * @version $Revision: 1 $
+ */
+public class JBossCacheRegionFactoryTestCase extends AbstractJBossCacheTestCase {
+
+ /**
+ * Create a new JBossCacheRegionFactoryTestCase.
+ *
+ * @param name
+ */
+ public JBossCacheRegionFactoryTestCase(String name) {
+ super(name);
+ }
+
+ public void testDefaultConfig() throws Exception {
+
+ Configuration cfg = CacheTestUtil.buildConfiguration("", JBossCacheRegionFactory.class, true, true);
+
+ JBossCacheRegionFactory regionFactory = CacheTestUtil.startRegionFactory(cfg, getCacheTestSupport());
+
+ CacheInstanceManager mgr = regionFactory.getCacheInstanceManager();
+ assertTrue("Correct default CacheInstanceManager type", mgr instanceof SharedCacheInstanceManager);
+
+ Cache cache = mgr.getEntityCacheInstance();
+ assertTrue("entity cache exists", cache != null);
+ assertEquals("Used correct config", "TestSharedCache", cache.getConfiguration().getClusterName());
+ assertEquals("Cache started", CacheStatus.STARTED, cache.getCacheStatus());
+
+ CacheTestUtil.stopRegionFactory(regionFactory, getCacheTestSupport());
+
+ assertEquals("Cache destroyed", CacheStatus.DESTROYED, cache.getCacheStatus());
+ }
+
+ public void testInjectedCacheInstanceManager() {
+
+ Configuration cfg = CacheTestUtil.buildConfiguration("", JBossCacheRegionFactory.class, true, true);
+
+ CacheInstanceManager cim = new MultiplexingCacheInstanceManager();
+ JBossCacheRegionFactory regionFactory = new JBossCacheRegionFactory(cim);
+
+ Settings settings = cfg.buildSettings();
+ Properties properties = cfg.getProperties();
+
+ regionFactory.start(settings, properties);
+ // Ensure we clean up
+ registerFactory(regionFactory);
+
+ assertEquals("Used injected CacheInstanceManager", cim, regionFactory.getCacheInstanceManager());
+
+ CacheTestUtil.stopRegionFactory(regionFactory, getCacheTestSupport());
+ }
+
+}
Added: core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/builder/CacheInstanceManagerTestBase.java
===================================================================
--- core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/builder/CacheInstanceManagerTestBase.java (rev 0)
+++ core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/builder/CacheInstanceManagerTestBase.java 2007-10-18 20:08:50 UTC (rev 14101)
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2007, Red Hat Middleware, LLC. All rights reserved.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, v. 2.1. This program is distributed in the
+ * hope that it will be useful, but WITHOUT A WARRANTY; without even the implied
+ * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details. You should have received a
+ * copy of the GNU Lesser General Public License, v.2.1 along with this
+ * distribution; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Red Hat Author(s): Brian Stansberry
+ */
+
+package org.hibernate.test.cache.jbc2.builder;
+
+import org.hibernate.cache.jbc2.CacheInstanceManager;
+import org.hibernate.cache.jbc2.JBossCacheRegionFactory;
+import org.hibernate.cfg.Configuration;
+import org.hibernate.test.cache.jbc2.AbstractJBossCacheTestCase;
+import org.hibernate.test.util.CacheTestUtil;
+
+/**
+ * A CacheInstanceManagerTestBase.
+ *
+ * @author <a href="brian.stansberry(a)jboss.com">Brian Stansberry</a>
+ * @version $Revision: 1 $
+ */
+public abstract class CacheInstanceManagerTestBase extends AbstractJBossCacheTestCase {
+
+ /**
+ * Create a new CacheInstanceManagerTestBase.
+ *
+ * @param name
+ */
+ public CacheInstanceManagerTestBase(String name) {
+ super(name);
+ }
+
+ protected abstract Class getRegionFactoryClass();
+
+ public void testUse2ndLevelCache() throws Exception {
+ Configuration cfg = CacheTestUtil.buildConfiguration("", getRegionFactoryClass(), false, true);
+
+ JBossCacheRegionFactory regionFactory = CacheTestUtil.startRegionFactory(cfg, getCacheTestSupport());
+
+ CacheInstanceManager cim = regionFactory.getCacheInstanceManager();
+
+ assertNull(cim.getCollectionCacheInstance());
+ assertNull(cim.getEntityCacheInstance());
+ assertNotNull(cim.getQueryCacheInstance());
+ assertNotNull(cim.getTimestampsCacheInstance());
+ }
+
+ public void testUseQueryCache() throws Exception {
+ Configuration cfg = CacheTestUtil.buildConfiguration("", getRegionFactoryClass(), true, false);
+
+ JBossCacheRegionFactory regionFactory = CacheTestUtil.startRegionFactory(cfg, getCacheTestSupport());
+
+ CacheInstanceManager cim = regionFactory.getCacheInstanceManager();
+
+ assertNotNull(cim.getCollectionCacheInstance());
+ assertNotNull(cim.getEntityCacheInstance());
+ assertNull(cim.getQueryCacheInstance());
+ assertNull(cim.getTimestampsCacheInstance());
+ }
+}
Added: core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/builder/MultiplexedCacheInstanceManagerTestCase.java
===================================================================
--- core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/builder/MultiplexedCacheInstanceManagerTestCase.java (rev 0)
+++ core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/builder/MultiplexedCacheInstanceManagerTestCase.java 2007-10-18 20:08:50 UTC (rev 14101)
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2007, Red Hat Middleware, LLC. All rights reserved.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, v. 2.1. This program is distributed in the
+ * hope that it will be useful, but WITHOUT A WARRANTY; without even the implied
+ * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details. You should have received a
+ * copy of the GNU Lesser General Public License, v.2.1 along with this
+ * distribution; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Red Hat Author(s): Brian Stansberry
+ */
+
+package org.hibernate.test.cache.jbc2.builder;
+
+import org.hibernate.cache.jbc2.MultiplexedJBossCacheRegionFactory;
+
+
+/**
+ * A SharedCacheInstanceManagerTestCase.
+ *
+ * @author <a href="brian.stansberry(a)jboss.com">Brian Stansberry</a>
+ * @version $Revision: 1 $
+ */
+public class MultiplexedCacheInstanceManagerTestCase extends CacheInstanceManagerTestBase {
+
+ /**
+ * Create a new SharedCacheInstanceManagerTestCase.
+ *
+ * @param name
+ */
+ public MultiplexedCacheInstanceManagerTestCase(String name) {
+ super(name);
+ }
+
+ @Override
+ protected Class getRegionFactoryClass() {
+ return MultiplexedJBossCacheRegionFactory.class;
+ }
+
+}
Added: core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/builder/SharedCacheInstanceManagerTestCase.java
===================================================================
--- core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/builder/SharedCacheInstanceManagerTestCase.java (rev 0)
+++ core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/builder/SharedCacheInstanceManagerTestCase.java 2007-10-18 20:08:50 UTC (rev 14101)
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2007, Red Hat Middleware, LLC. All rights reserved.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, v. 2.1. This program is distributed in the
+ * hope that it will be useful, but WITHOUT A WARRANTY; without even the implied
+ * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details. You should have received a
+ * copy of the GNU Lesser General Public License, v.2.1 along with this
+ * distribution; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Red Hat Author(s): Brian Stansberry
+ */
+
+package org.hibernate.test.cache.jbc2.builder;
+
+import org.hibernate.cache.jbc2.SharedJBossCacheRegionFactory;
+
+/**
+ * A SharedCacheInstanceManagerTestCase.
+ *
+ * @author <a href="brian.stansberry(a)jboss.com">Brian Stansberry</a>
+ * @version $Revision: 1 $
+ */
+public class SharedCacheInstanceManagerTestCase extends CacheInstanceManagerTestBase {
+
+ /**
+ * Create a new SharedCacheInstanceManagerTestCase.
+ *
+ * @param name
+ */
+ public SharedCacheInstanceManagerTestCase(String name) {
+ super(name);
+ }
+
+ @Override
+ protected Class getRegionFactoryClass() {
+ return SharedJBossCacheRegionFactory.class;
+ }
+
+}
Added: core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/collection/AbstractCollectionRegionAccessStrategyTestCase.java
===================================================================
--- core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/collection/AbstractCollectionRegionAccessStrategyTestCase.java (rev 0)
+++ core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/collection/AbstractCollectionRegionAccessStrategyTestCase.java 2007-10-18 20:08:50 UTC (rev 14101)
@@ -0,0 +1,539 @@
+/*
+ * Copyright (c) 2007, Red Hat Middleware, LLC. All rights reserved.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, v. 2.1. This program is distributed in the
+ * hope that it will be useful, but WITHOUT A WARRANTY; without even the implied
+ * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details. You should have received a
+ * copy of the GNU Lesser General Public License, v.2.1 along with this
+ * distribution; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Red Hat Author(s): Brian Stansberry
+ */
+
+package org.hibernate.test.cache.jbc2.collection;
+
+import java.util.Iterator;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+import junit.extensions.TestSetup;
+import junit.framework.AssertionFailedError;
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+import org.hibernate.cache.CacheDataDescription;
+import org.hibernate.cache.CollectionRegion;
+import org.hibernate.cache.access.AccessType;
+import org.hibernate.cache.access.CollectionRegionAccessStrategy;
+import org.hibernate.cache.impl.CacheDataDescriptionImpl;
+import org.hibernate.cache.jbc2.BasicRegionAdapter;
+import org.hibernate.cache.jbc2.JBossCacheRegionFactory;
+import org.hibernate.cache.jbc2.MultiplexedJBossCacheRegionFactory;
+import org.hibernate.cache.jbc2.builder.MultiplexingCacheInstanceManager;
+import org.hibernate.cache.jbc2.collection.CollectionRegionImpl;
+import org.hibernate.cache.jbc2.entity.TransactionalAccess;
+import org.hibernate.cache.jbc2.util.CacheHelper;
+import org.hibernate.cache.jbc2.util.NonLockingDataVersion;
+import org.hibernate.cfg.Configuration;
+import org.hibernate.test.cache.jbc2.AbstractJBossCacheTestCase;
+import org.hibernate.test.util.CacheTestUtil;
+import org.hibernate.util.ComparableComparator;
+import org.jboss.cache.Cache;
+import org.jboss.cache.Fqn;
+import org.jboss.cache.Node;
+import org.jboss.cache.NodeSPI;
+import org.jboss.cache.transaction.BatchModeTransactionManager;
+
+/**
+ * Base class for tests of CollectionRegionAccessStrategy impls.
+ *
+ * @author <a href="brian.stansberry(a)jboss.com">Brian Stansberry</a>
+ * @version $Revision: 1 $
+ */
+public abstract class AbstractCollectionRegionAccessStrategyTestCase extends AbstractJBossCacheTestCase {
+
+ public static final String REGION_NAME = "test/com.foo.test";
+ public static final String KEY = "KEY";
+ public static final String VALUE1 = "VALUE1";
+ public static final String VALUE2 = "VALUE2";
+
+ protected static Configuration localCfg;
+ protected static JBossCacheRegionFactory localRegionFactory;
+ protected static Cache localCache;
+ protected static Configuration remoteCfg;
+ protected static JBossCacheRegionFactory remoteRegionFactory;
+ protected static Cache remoteCache;
+
+ protected CollectionRegion localCollectionRegion;
+ protected CollectionRegionAccessStrategy localAccessStrategy;
+
+ protected CollectionRegion remoteCollectionRegion;
+ protected CollectionRegionAccessStrategy remoteAccessStrategy;
+
+ protected boolean invalidation;
+ protected boolean optimistic;
+ protected boolean synchronous;
+
+ protected Exception node1Exception;
+ protected Exception node2Exception;
+
+ protected AssertionFailedError node1Failure;
+ protected AssertionFailedError node2Failure;
+
+ public static Test getTestSetup(Class testClass, String configName) {
+ TestSuite suite = new TestSuite(testClass);
+ return new AccessStrategyTestSetup(suite, configName);
+ }
+
+ public static Test getTestSetup(Test test, String configName) {
+ return new AccessStrategyTestSetup(test, configName);
+ }
+
+ /**
+ * Create a new TransactionalAccessTestCase.
+ *
+ * @param name
+ */
+ public AbstractCollectionRegionAccessStrategyTestCase(String name) {
+ super(name);
+ }
+
+ protected abstract AccessType getAccessType();
+
+ protected void setUp() throws Exception {
+ super.setUp();
+
+ invalidation = CacheHelper.isClusteredInvalidation(localCache);
+ synchronous = CacheHelper.isSynchronous(localCache);
+ optimistic = localCache.getConfiguration().getNodeLockingScheme() == org.jboss.cache.config.Configuration.NodeLockingScheme.OPTIMISTIC;
+ localCollectionRegion = localRegionFactory.buildCollectionRegion(REGION_NAME, localCfg.getProperties(), getCacheDataDescription());
+ localAccessStrategy = localCollectionRegion.buildAccessStrategy(getAccessType());
+
+ remoteCollectionRegion = remoteRegionFactory.buildCollectionRegion(REGION_NAME, remoteCfg.getProperties(), getCacheDataDescription());
+ remoteAccessStrategy = remoteCollectionRegion.buildAccessStrategy(getAccessType());
+
+ node1Exception = null;
+ node2Exception = null;
+
+ node1Failure = null;
+ node2Failure = null;
+ }
+
+ protected void tearDown() throws Exception {
+
+ super.tearDown();
+
+ if (localCollectionRegion != null)
+ localCollectionRegion.destroy();
+ if (remoteCollectionRegion != null)
+ remoteCollectionRegion.destroy();
+
+ try {
+ localCache.getInvocationContext().getOptionOverrides().setCacheModeLocal(true);
+ localCache.removeNode(Fqn.ROOT);
+ }
+ catch (Exception e) {
+ log.error("Problem purging local cache" ,e);
+ }
+
+ try {
+ remoteCache.getInvocationContext().getOptionOverrides().setCacheModeLocal(true);
+ remoteCache.removeNode(Fqn.ROOT);
+ }
+ catch (Exception e) {
+ log.error("Problem purging remote cache" ,e);
+ }
+
+ node1Exception = null;
+ node2Exception = null;
+
+ node1Failure = null;
+ node2Failure = null;
+ }
+
+ protected static Configuration createConfiguration(String configName) {
+ Configuration cfg = CacheTestUtil.buildConfiguration(REGION_PREFIX, MultiplexedJBossCacheRegionFactory.class, true, false);
+ cfg.setProperty(MultiplexingCacheInstanceManager.ENTITY_CACHE_RESOURCE_PROP, configName);
+ return cfg;
+ }
+
+ protected CacheDataDescription getCacheDataDescription() {
+ return new CacheDataDescriptionImpl(true, true, ComparableComparator.INSTANCE);
+ }
+
+ protected boolean isUsingOptimisticLocking() {
+ return optimistic;
+ }
+
+ protected boolean isUsingInvalidation() {
+ return invalidation;
+ }
+
+ protected boolean isSynchronous() {
+ return synchronous;
+ }
+
+ protected Fqn getRegionFqn(String regionName, String regionPrefix) {
+ return BasicRegionAdapter.getTypeLastRegionFqn(regionName, regionPrefix, CollectionRegionImpl.TYPE);
+ }
+
+ /**
+ * This is just a setup test where we assert that the cache config is
+ * as we expected.
+ */
+ public abstract void testCacheConfiguration();
+
+ /**
+ * Test method for {@link TransactionalAccess#getRegion()}.
+ */
+ public void testGetRegion() {
+ assertEquals("Correct region", localCollectionRegion, localAccessStrategy.getRegion());
+ }
+
+ /**
+ * Test method for {@link TransactionalAccess#putFromLoad(java.lang.Object, java.lang.Object, long, java.lang.Object)}.
+ */
+ public void testPutFromLoad() throws Exception {
+ putFromLoadTest(false);
+ }
+
+ /**
+ * Test method for {@link TransactionalAccess#putFromLoad(java.lang.Object, java.lang.Object, long, java.lang.Object, boolean)}.
+ */
+ public void testPutFromLoadMinimal() throws Exception {
+ putFromLoadTest(true);
+ }
+
+ /**
+ * Simulate 2 nodes, both start, tx do a get, experience a cache miss,
+ * then 'read from db.' First does a putFromLoad, then an evict (to represent a change).
+ * Second tries to do a putFromLoad with stale data (i.e. it took
+ * longer to read from the db). Both commit their tx. Then
+ * both start a new tx and get. First should see the updated data;
+ * second should either see the updated data (isInvalidation()( == false)
+ * or null (isInvalidation() == true).
+ *
+ * @param useMinimalAPI
+ * @throws Exception
+ */
+ private void putFromLoadTest(final boolean useMinimalAPI) throws Exception {
+
+ final CountDownLatch writeLatch1 = new CountDownLatch(1);
+ final CountDownLatch writeLatch2 = new CountDownLatch(1);
+ final CountDownLatch completionLatch = new CountDownLatch(2);
+
+ Thread node1 = new Thread() {
+
+ public void run() {
+
+ try {
+ long txTimestamp = System.currentTimeMillis();
+ BatchModeTransactionManager.getInstance().begin();
+
+ assertEquals("node1 starts clean", null, localAccessStrategy.get(KEY, txTimestamp));
+
+ writeLatch1.await();
+
+ if (useMinimalAPI) {
+ localAccessStrategy.putFromLoad(KEY, VALUE2, txTimestamp, new Integer(2), true);
+ }
+ else {
+ localAccessStrategy.putFromLoad(KEY, VALUE2, txTimestamp, new Integer(2));
+ }
+
+ BatchModeTransactionManager.getInstance().commit();
+ }
+ catch (Exception e) {
+ log.error("node1 caught exception", e);
+ node1Exception = e;
+ rollback();
+ }
+ catch (AssertionFailedError e) {
+ node1Failure = e;
+ rollback();
+ }
+ finally {
+ // Let node2 write
+ writeLatch2.countDown();
+ completionLatch.countDown();
+ }
+ }
+ };
+
+ Thread node2 = new Thread() {
+
+ public void run() {
+
+ try {
+ long txTimestamp = System.currentTimeMillis();
+ BatchModeTransactionManager.getInstance().begin();
+
+ assertNull("node1 starts clean", remoteAccessStrategy.get(KEY, txTimestamp));
+
+ // Let node1 write
+ writeLatch1.countDown();
+ // Wait for node1 to finish
+ writeLatch2.await();
+
+ // Let the first PFER propagate
+ sleep(200);
+
+ if (useMinimalAPI) {
+ remoteAccessStrategy.putFromLoad(KEY, VALUE1, txTimestamp, new Integer(1), true);
+ }
+ else {
+ remoteAccessStrategy.putFromLoad(KEY, VALUE1, txTimestamp, new Integer(1));
+ }
+
+ BatchModeTransactionManager.getInstance().commit();
+ }
+ catch (Exception e) {
+ log.error("node2 caught exception", e);
+ node2Exception = e;
+ rollback();
+ }
+ catch (AssertionFailedError e) {
+ node2Failure = e;
+ rollback();
+ }
+ finally {
+ completionLatch.countDown();
+ }
+ }
+ };
+
+ node1.setDaemon(true);
+ node2.setDaemon(true);
+
+ node1.start();
+ node2.start();
+
+ assertTrue("Threads completed", completionLatch.await(2, TimeUnit.SECONDS));
+
+ if (node1Failure != null)
+ throw node1Failure;
+ if (node2Failure != null)
+ throw node2Failure;
+
+ assertEquals("node1 saw no exceptions", null, node1Exception);
+ assertEquals("node2 saw no exceptions", null, node2Exception);
+
+ // let the final PFER propagate
+ sleep(100);
+
+ long txTimestamp = System.currentTimeMillis();
+ String msg1 = "Correct node1 value";
+ String msg2 = "Correct node2 value";
+ Object expected1 = null;
+ Object expected2 = null;
+ if (isUsingInvalidation()) {
+ if (isUsingOptimisticLocking()) {
+ expected1 = null; // the initial VALUE2 DataVersion should prevent the node2 put
+ expected2 = VALUE2;
+
+ // We know this case fails
+ msg1 = msg2 = "Known issue JBCACHE-1203";
+ }
+ else {
+ // node2 can write since there is no data version
+ // We count on db locking to prevent this case
+ expected1 = VALUE1;
+ expected2 = null; // invalidated by node2
+
+ // We know this case fails
+ msg1 = msg2 = "Known issue JBCACHE-1203";
+ }
+ }
+ else {
+ // the initial VALUE2 should prevent the node2 put
+ expected1 = VALUE2;
+ expected2 = VALUE2;
+ }
+
+ assertEquals(msg1, expected1, localAccessStrategy.get(KEY, txTimestamp));
+ assertEquals(msg2, expected2, remoteAccessStrategy.get(KEY, txTimestamp));
+ }
+
+ /**
+ * Test method for {@link TransactionalAccess#remove(java.lang.Object)}.
+ */
+ public void testRemove() {
+ evictOrRemoveTest(false);
+ }
+
+ /**
+ * Test method for {@link TransactionalAccess#removeAll()}.
+ */
+ public void testRemoveAll() {
+ evictOrRemoveAllTest(false);
+ }
+
+ /**
+ * Test method for {@link TransactionalAccess#evict(java.lang.Object)}.
+ *
+ * FIXME add testing of the "immediately without regard for transaction
+ * isolation" bit in the CollectionRegionAccessStrategy API.
+ */
+ public void testEvict() {
+ evictOrRemoveTest(true);
+ }
+
+ /**
+ * Test method for {@link TransactionalAccess#evictAll()}.
+ *
+ * FIXME add testing of the "immediately without regard for transaction
+ * isolation" bit in the CollectionRegionAccessStrategy API.
+ */
+ public void testEvictAll() {
+ evictOrRemoveAllTest(true);
+ }
+
+ private void evictOrRemoveTest(boolean evict) {
+ assertNull("local is clean", localAccessStrategy.get(KEY, System.currentTimeMillis()));
+ assertNull("remote is clean", remoteAccessStrategy.get(KEY, System.currentTimeMillis()));
+
+ localAccessStrategy.putFromLoad(KEY, VALUE1, System.currentTimeMillis(), new Integer(1));
+ assertEquals(VALUE1, localAccessStrategy.get(KEY, System.currentTimeMillis()));
+ remoteAccessStrategy.putFromLoad(KEY, VALUE1, System.currentTimeMillis(), new Integer(1));
+ assertEquals(VALUE1, remoteAccessStrategy.get(KEY, System.currentTimeMillis()));
+
+ // Wait for async propagation
+ sleep(250);
+
+ if (evict)
+ localAccessStrategy.evict(KEY);
+ else
+ localAccessStrategy.remove(KEY);
+
+ assertEquals(null, localAccessStrategy.get(KEY, System.currentTimeMillis()));
+
+ assertEquals(null, remoteAccessStrategy.get(KEY, System.currentTimeMillis()));
+ }
+
+ private void evictOrRemoveAllTest(boolean evict) {
+
+ Fqn regionFqn = getRegionFqn(REGION_NAME, REGION_PREFIX);
+
+ Node regionRoot = localCache.getRoot().getChild(regionFqn);
+ assertFalse(regionRoot == null);
+ assertEquals(0, regionRoot.getChildrenNames().size());
+ assertTrue(regionRoot.isResident());
+
+ if (isUsingOptimisticLocking()) {
+ assertEquals(NonLockingDataVersion.class, ((NodeSPI) regionRoot).getVersion().getClass());
+ }
+
+ regionRoot = remoteCache.getRoot().getChild(regionFqn);
+ assertFalse(regionRoot == null);
+ assertEquals(0, regionRoot.getChildrenNames().size());
+ assertTrue(regionRoot.isResident());
+
+ if (isUsingOptimisticLocking()) {
+ assertEquals(NonLockingDataVersion.class, ((NodeSPI) regionRoot).getVersion().getClass());
+ }
+
+ assertNull("local is clean", localAccessStrategy.get(KEY, System.currentTimeMillis()));
+ assertNull("remote is clean", remoteAccessStrategy.get(KEY, System.currentTimeMillis()));
+
+ localAccessStrategy.putFromLoad(KEY, VALUE1, System.currentTimeMillis(), new Integer(1));
+ assertEquals(VALUE1, localAccessStrategy.get(KEY, System.currentTimeMillis()));
+ remoteAccessStrategy.putFromLoad(KEY, VALUE1, System.currentTimeMillis(), new Integer(1));
+ assertEquals(VALUE1, remoteAccessStrategy.get(KEY, System.currentTimeMillis()));
+
+ // Wait for async propagation
+ sleep(250);
+
+
+
+ if (isUsingOptimisticLocking()) {
+ regionRoot = localCache.getRoot().getChild(regionFqn);
+ assertEquals(NonLockingDataVersion.class, ((NodeSPI) regionRoot).getVersion().getClass());
+ regionRoot = remoteCache.getRoot().getChild(regionFqn);
+ assertEquals(NonLockingDataVersion.class, ((NodeSPI) regionRoot).getVersion().getClass());
+ }
+
+ if (evict)
+ localAccessStrategy.evictAll();
+ else
+ localAccessStrategy.removeAll();
+
+ regionRoot = localCache.getRoot().getChild(regionFqn);
+ assertFalse(regionRoot == null);
+ assertEquals(0, regionRoot.getChildrenNames().size());
+ assertTrue(regionRoot.isResident());
+
+ regionRoot = remoteCache.getRoot().getChild(regionFqn);
+ assertFalse(regionRoot == null);
+ if (isUsingInvalidation()) {
+ // JBC seems broken: see http://www.jboss.com/index.html?module=bb&op=viewtopic&t=121408
+ // FIXME replace with the following when JBCACHE-1199 and JBCACHE-1200 are done:
+ //assertFalse(regionRoot.isValid());
+ checkNodeIsEmpty(regionRoot);
+ }
+ else {
+ // Same assertion, just different assertion msg
+ assertEquals(0, regionRoot.getChildrenNames().size());
+ }
+ assertTrue(regionRoot.isResident());
+
+ assertNull("local is clean", localAccessStrategy.get(KEY, System.currentTimeMillis()));
+ assertNull("remote is clean", remoteAccessStrategy.get(KEY, System.currentTimeMillis()));
+ }
+
+ private void checkNodeIsEmpty(Node node) {
+ assertEquals("Known issue JBCACHE-1200. node " + node.getFqn() + " should not have keys", 0, node.getKeys().size());
+ for (Iterator it = node.getChildren().iterator(); it.hasNext(); ) {
+ checkNodeIsEmpty((Node) it.next());
+ }
+ }
+
+ private void rollback() {
+ try {
+ BatchModeTransactionManager.getInstance().rollback();
+ }
+ catch (Exception e) {
+ log.error(e.getMessage(), e);
+ }
+
+ }
+
+ private static class AccessStrategyTestSetup extends TestSetup {
+
+ private String configName;
+
+ public AccessStrategyTestSetup(Test test, String configName) {
+ super(test);
+ this.configName = configName;
+ }
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ localCfg = createConfiguration(configName);
+ localRegionFactory = CacheTestUtil.startRegionFactory(localCfg);
+ localCache = localRegionFactory.getCacheInstanceManager().getCollectionCacheInstance();
+
+ remoteCfg = createConfiguration(configName);
+ remoteRegionFactory = CacheTestUtil.startRegionFactory(remoteCfg);
+ remoteCache = remoteRegionFactory.getCacheInstanceManager().getCollectionCacheInstance();
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ super.tearDown();
+
+ if (localRegionFactory != null)
+ localRegionFactory.stop();
+
+ if (remoteRegionFactory != null)
+ remoteRegionFactory.stop();
+ }
+
+
+ }
+
+}
Added: core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/collection/AbstractReadOnlyAccessTestCase.java
===================================================================
--- core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/collection/AbstractReadOnlyAccessTestCase.java (rev 0)
+++ core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/collection/AbstractReadOnlyAccessTestCase.java 2007-10-18 20:08:50 UTC (rev 14101)
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2007, Red Hat Middleware, LLC. All rights reserved.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, v. 2.1. This program is distributed in the
+ * hope that it will be useful, but WITHOUT A WARRANTY; without even the implied
+ * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details. You should have received a
+ * copy of the GNU Lesser General Public License, v.2.1 along with this
+ * distribution; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Red Hat Author(s): Brian Stansberry
+ */
+
+package org.hibernate.test.cache.jbc2.collection;
+
+import org.hibernate.cache.access.AccessType;
+
+/**
+ * Base class for tests of TRANSACTIONAL access.
+ *
+ * @author <a href="brian.stansberry(a)jboss.com">Brian Stansberry</a>
+ * @version $Revision: 1 $
+ */
+public abstract class AbstractReadOnlyAccessTestCase extends AbstractCollectionRegionAccessStrategyTestCase {
+
+ /**
+ * Create a new AbstractTransactionalAccessTestCase.
+ *
+ */
+ public AbstractReadOnlyAccessTestCase(String name) {
+ super(name);
+ }
+
+ @Override
+ protected AccessType getAccessType() {
+ return AccessType.READ_ONLY;
+ }
+
+}
Added: core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/collection/AbstractTransactionalAccessTestCase.java
===================================================================
--- core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/collection/AbstractTransactionalAccessTestCase.java (rev 0)
+++ core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/collection/AbstractTransactionalAccessTestCase.java 2007-10-18 20:08:50 UTC (rev 14101)
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2007, Red Hat Middleware, LLC. All rights reserved.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, v. 2.1. This program is distributed in the
+ * hope that it will be useful, but WITHOUT A WARRANTY; without even the implied
+ * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details. You should have received a
+ * copy of the GNU Lesser General Public License, v.2.1 along with this
+ * distribution; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Red Hat Author(s): Brian Stansberry
+ */
+
+package org.hibernate.test.cache.jbc2.collection;
+
+import org.hibernate.cache.access.AccessType;
+
+/**
+ * Base class for tests of TRANSACTIONAL access.
+ *
+ * @author <a href="brian.stansberry(a)jboss.com">Brian Stansberry</a>
+ * @version $Revision: 1 $
+ */
+public abstract class AbstractTransactionalAccessTestCase extends AbstractCollectionRegionAccessStrategyTestCase {
+
+ /**
+ * Create a new AbstractTransactionalAccessTestCase.
+ *
+ */
+ public AbstractTransactionalAccessTestCase(String name) {
+ super(name);
+ }
+
+ @Override
+ protected AccessType getAccessType() {
+ return AccessType.TRANSACTIONAL;
+ }
+
+}
Added: core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/collection/CollectionRegionImplTestCase.java
===================================================================
--- core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/collection/CollectionRegionImplTestCase.java (rev 0)
+++ core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/collection/CollectionRegionImplTestCase.java 2007-10-18 20:08:50 UTC (rev 14101)
@@ -0,0 +1,97 @@
+/*
+ * Copyright (c) 2007, Red Hat Middleware, LLC. All rights reserved.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, v. 2.1. This program is distributed in the
+ * hope that it will be useful, but WITHOUT A WARRANTY; without even the implied
+ * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details. You should have received a
+ * copy of the GNU Lesser General Public License, v.2.1 along with this
+ * distribution; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Red Hat Author(s): Brian Stansberry
+ */
+
+package org.hibernate.test.cache.jbc2.collection;
+
+import java.util.Properties;
+
+import org.hibernate.cache.CacheDataDescription;
+import org.hibernate.cache.CacheException;
+import org.hibernate.cache.CollectionRegion;
+import org.hibernate.cache.Region;
+import org.hibernate.cache.RegionFactory;
+import org.hibernate.cache.access.AccessType;
+import org.hibernate.cache.jbc2.BasicRegionAdapter;
+import org.hibernate.cache.jbc2.CacheInstanceManager;
+import org.hibernate.cache.jbc2.JBossCacheRegionFactory;
+import org.hibernate.cache.jbc2.collection.CollectionRegionImpl;
+import org.hibernate.test.cache.jbc2.AbstractEntityCollectionRegionTestCase;
+import org.jboss.cache.Cache;
+import org.jboss.cache.Fqn;
+
+/**
+ * Tests of CollectionRegionImpl.
+ *
+ * @author <a href="brian.stansberry(a)jboss.com">Brian Stansberry</a>
+ * @version $Revision: 1 $
+ */
+public class CollectionRegionImplTestCase extends AbstractEntityCollectionRegionTestCase {
+
+ /**
+ * Create a new EntityRegionImplTestCase.
+ *
+ * @param name
+ */
+ public CollectionRegionImplTestCase(String name) {
+ super(name);
+ }
+
+ protected void supportedAccessTypeTest(RegionFactory regionFactory, Properties properties) {
+
+ CollectionRegion region = regionFactory.buildCollectionRegion("test", properties, null);
+
+ assertNull("Got TRANSACTIONAL", region.buildAccessStrategy(AccessType.TRANSACTIONAL).lockRegion());
+
+ try
+ {
+ region.buildAccessStrategy(AccessType.READ_ONLY).lockRegion();
+ fail("Did not get READ_ONLY");
+ }
+ catch (UnsupportedOperationException good) {}
+
+ try
+ {
+ region.buildAccessStrategy(AccessType.NONSTRICT_READ_WRITE);
+ fail("Incorrectly got NONSTRICT_READ_WRITE");
+ }
+ catch (CacheException good) {}
+
+ try
+ {
+ region.buildAccessStrategy(AccessType.READ_WRITE);
+ fail("Incorrectly got READ_WRITE");
+ }
+ catch (CacheException good) {}
+ }
+
+ @Override
+ protected Region createRegion(JBossCacheRegionFactory regionFactory, String regionName, Properties properties, CacheDataDescription cdd) {
+ return regionFactory.buildCollectionRegion(regionName, properties, cdd);
+ }
+
+ @Override
+ protected Cache getJBossCache(JBossCacheRegionFactory regionFactory) {
+ CacheInstanceManager mgr = regionFactory.getCacheInstanceManager();
+ return mgr.getCollectionCacheInstance();
+ }
+
+ @Override
+ protected Fqn getRegionFqn(String regionName, String regionPrefix) {
+ return BasicRegionAdapter.getTypeLastRegionFqn(regionName, regionPrefix, CollectionRegionImpl.TYPE);
+ }
+
+
+}
Added: core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/collection/OptimisticInvalidatedTransactionalTestCase.java
===================================================================
--- core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/collection/OptimisticInvalidatedTransactionalTestCase.java (rev 0)
+++ core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/collection/OptimisticInvalidatedTransactionalTestCase.java 2007-10-18 20:08:50 UTC (rev 14101)
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2007, Red Hat Middleware, LLC. All rights reserved.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, v. 2.1. This program is distributed in the
+ * hope that it will be useful, but WITHOUT A WARRANTY; without even the implied
+ * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details. You should have received a
+ * copy of the GNU Lesser General Public License, v.2.1 along with this
+ * distribution; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Red Hat Author(s): Brian Stansberry
+ */
+
+package org.hibernate.test.cache.jbc2.collection;
+
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+/**
+ * Tests TRANSACTIONAL access when optimistic locking and invalidation are used.
+ *
+ * @author <a href="brian.stansberry(a)jboss.com">Brian Stansberry</a>
+ * @version $Revision: 1 $
+ */
+public class OptimisticInvalidatedTransactionalTestCase
+ extends AbstractTransactionalAccessTestCase {
+
+ /**
+ * Create a new TransactionalAccessTestCase.
+ *
+ * @param name
+ */
+ public OptimisticInvalidatedTransactionalTestCase(String name) {
+ super(name);
+ }
+
+ public static Test suite() throws Exception {
+ TestSuite suite = createFailureExpectedSuite(OptimisticInvalidatedTransactionalTestCase.class);
+ return getTestSetup(suite, "optimistic-entity");
+ }
+
+ @Override
+ public void testCacheConfiguration() {
+ assertTrue("Using Invalidation", isUsingInvalidation());
+ assertTrue("Using Optimistic locking", isUsingOptimisticLocking());
+ assertTrue("Synchronous mode", isSynchronous());
+ }
+
+ // Known failures
+
+ public void testEvictAllFailureExpected() {
+ super.testEvictAll();
+ }
+
+ public void testRemoveAllFailureExpected() {
+ super.testRemoveAll();
+ }
+
+ public void testPutFromLoadFailureExpected() throws Exception {
+ super.testPutFromLoad();
+ }
+
+ public void testPutFromLoadMinimalFailureExpected() throws Exception {
+ super.testPutFromLoadMinimal();
+ }
+}
Added: core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/collection/OptimisticReadOnlyExtraAPITestCase.java
===================================================================
--- core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/collection/OptimisticReadOnlyExtraAPITestCase.java (rev 0)
+++ core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/collection/OptimisticReadOnlyExtraAPITestCase.java 2007-10-18 20:08:50 UTC (rev 14101)
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 2007, Red Hat Middleware, LLC. All rights reserved.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, v. 2.1. This program is distributed in the
+ * hope that it will be useful, but WITHOUT A WARRANTY; without even the implied
+ * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details. You should have received a
+ * copy of the GNU Lesser General Public License, v.2.1 along with this
+ * distribution; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Red Hat Author(s): Brian Stansberry
+ */
+
+package org.hibernate.test.cache.jbc2.collection;
+
+import org.hibernate.cache.access.AccessType;
+import org.hibernate.cache.access.CollectionRegionAccessStrategy;
+import org.hibernate.cache.jbc2.entity.TransactionalAccess;
+
+/**
+ * Tests for the "extra API" in EntityRegionAccessStrategy; in this
+ * version using Optimistic locking with READ_ONLY access.
+ * <p>
+ * By "extra API" we mean those methods that are superfluous to the
+ * function of the JBC integration, where the impl is a no-op or a static
+ * false return value, UnsupportedOperationException, etc.
+ *
+ * @author <a href="brian.stansberry(a)jboss.com">Brian Stansberry</a>
+ * @version $Revision: 1 $
+ */
+public class OptimisticReadOnlyExtraAPITestCase extends OptimisticTransactionalExtraAPITestCase {
+
+ private static CollectionRegionAccessStrategy localAccessStrategy;
+
+ /**
+ * Create a new TransactionalAccessTestCase.
+ *
+ * @param name
+ */
+ public OptimisticReadOnlyExtraAPITestCase(String name) {
+ super(name);
+ }
+
+ @Override
+ protected AccessType getAccessType() {
+ return AccessType.READ_ONLY;
+ }
+
+ @Override
+ protected CollectionRegionAccessStrategy getCollectionAccessStrategy() {
+ return localAccessStrategy;
+ }
+
+ @Override
+ protected void setCollectionAccessStrategy(CollectionRegionAccessStrategy strategy) {
+ localAccessStrategy = strategy;
+ }
+
+ /**
+ * Test method for {@link TransactionalAccess#lockItem(java.lang.Object, java.lang.Object)}.
+ */
+ @Override
+ public void testLockItem() {
+ try {
+ getCollectionAccessStrategy().lockItem(KEY, new Integer(1));
+ fail("Call to lockItem did not throw exception");
+ }
+ catch (UnsupportedOperationException expected) {}
+ }
+
+ /**
+ * Test method for {@link TransactionalAccess#lockRegion()}.
+ */
+ @Override
+ public void testLockRegion() {
+ try {
+ getCollectionAccessStrategy().lockRegion();
+ fail("Call to lockRegion did not throw exception");
+ }
+ catch (UnsupportedOperationException expected) {}
+ }
+
+}
Added: core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/collection/OptimisticReadOnlyTestCase.java
===================================================================
--- core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/collection/OptimisticReadOnlyTestCase.java (rev 0)
+++ core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/collection/OptimisticReadOnlyTestCase.java 2007-10-18 20:08:50 UTC (rev 14101)
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2007, Red Hat Middleware, LLC. All rights reserved.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, v. 2.1. This program is distributed in the
+ * hope that it will be useful, but WITHOUT A WARRANTY; without even the implied
+ * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details. You should have received a
+ * copy of the GNU Lesser General Public License, v.2.1 along with this
+ * distribution; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Red Hat Author(s): Brian Stansberry
+ */
+
+package org.hibernate.test.cache.jbc2.collection;
+
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+/**
+ * Tests READ_ONLY access when optimistic locking and invalidation are used.
+ *
+ * @author <a href="brian.stansberry(a)jboss.com">Brian Stansberry</a>
+ * @version $Revision: 1 $
+ */
+public class OptimisticReadOnlyTestCase extends AbstractReadOnlyAccessTestCase {
+
+ /**
+ * Create a new PessimisticTransactionalAccessTestCase.
+ *
+ * @param name
+ */
+ public OptimisticReadOnlyTestCase(String name) {
+ super(name);
+ }
+
+ public static Test suite() throws Exception {
+ TestSuite suite = createFailureExpectedSuite(OptimisticReadOnlyTestCase.class);
+ return getTestSetup(suite, "optimistic-entity");
+ }
+
+ @Override
+ public void testCacheConfiguration() {
+ assertTrue("Using Invalidation", isUsingInvalidation());
+ assertTrue("Using Optimistic locking", isUsingOptimisticLocking());
+ assertTrue("Synchronous mode", isSynchronous());
+ }
+
+ // Known failures
+
+ public void testEvictAllFailureExpected() {
+ super.testEvictAll();
+ }
+
+ public void testRemoveAllFailureExpected() {
+ super.testRemoveAll();
+ }
+
+ public void testPutFromLoadFailureExpected() throws Exception {
+ super.testPutFromLoad();
+ }
+
+ public void testPutFromLoadMinimalFailureExpected() throws Exception {
+ super.testPutFromLoadMinimal();
+ }
+
+}
Added: core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/collection/OptimisticReplicatedTransactionalTestCase.java
===================================================================
--- core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/collection/OptimisticReplicatedTransactionalTestCase.java (rev 0)
+++ core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/collection/OptimisticReplicatedTransactionalTestCase.java 2007-10-18 20:08:50 UTC (rev 14101)
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2007, Red Hat Middleware, LLC. All rights reserved.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, v. 2.1. This program is distributed in the
+ * hope that it will be useful, but WITHOUT A WARRANTY; without even the implied
+ * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details. You should have received a
+ * copy of the GNU Lesser General Public License, v.2.1 along with this
+ * distribution; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Red Hat Author(s): Brian Stansberry
+ */
+
+package org.hibernate.test.cache.jbc2.collection;
+
+import junit.framework.Test;
+
+/**
+ * Tests TRANSACTIONAL access when optimistic locking and replication are used.
+ *
+ * @author <a href="brian.stansberry(a)jboss.com">Brian Stansberry</a>
+ * @version $Revision: 1 $
+ */
+public class OptimisticReplicatedTransactionalTestCase extends AbstractTransactionalAccessTestCase {
+
+ /**
+ * Create a new PessimisticTransactionalAccessTestCase.
+ *
+ * @param name
+ */
+ public OptimisticReplicatedTransactionalTestCase(String name) {
+ super(name);
+ }
+
+ public static Test suite() throws Exception {
+ return getTestSetup(OptimisticReplicatedTransactionalTestCase.class, "optimistic-shared");
+ }
+
+ @Override
+ public void testCacheConfiguration() {
+ assertFalse("Using Invalidation", isUsingInvalidation());
+ assertTrue("Using Optimistic locking", isUsingOptimisticLocking());
+ assertTrue("Synchronous mode", isSynchronous());
+ }
+
+
+
+}
Added: core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/collection/OptimisticTransactionalExtraAPITestCase.java
===================================================================
--- core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/collection/OptimisticTransactionalExtraAPITestCase.java (rev 0)
+++ core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/collection/OptimisticTransactionalExtraAPITestCase.java 2007-10-18 20:08:50 UTC (rev 14101)
@@ -0,0 +1,147 @@
+/*
+ * Copyright (c) 2007, Red Hat Middleware, LLC. All rights reserved.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, v. 2.1. This program is distributed in the
+ * hope that it will be useful, but WITHOUT A WARRANTY; without even the implied
+ * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details. You should have received a
+ * copy of the GNU Lesser General Public License, v.2.1 along with this
+ * distribution; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Red Hat Author(s): Brian Stansberry
+ */
+
+package org.hibernate.test.cache.jbc2.collection;
+
+import org.hibernate.cache.CollectionRegion;
+import org.hibernate.cache.access.AccessType;
+import org.hibernate.cache.access.CollectionRegionAccessStrategy;
+import org.hibernate.cache.access.SoftLock;
+import org.hibernate.cache.jbc2.JBossCacheRegionFactory;
+import org.hibernate.cache.jbc2.MultiplexedJBossCacheRegionFactory;
+import org.hibernate.cache.jbc2.builder.MultiplexingCacheInstanceManager;
+import org.hibernate.cache.jbc2.entity.TransactionalAccess;
+import org.hibernate.cfg.Configuration;
+import org.hibernate.test.cache.jbc2.AbstractJBossCacheTestCase;
+import org.hibernate.test.util.CacheTestUtil;
+import org.jboss.cache.Cache;
+
+/**
+ * Tests for the "extra API" in CollectionRegionAccessStrategy; in this base
+ * version using Optimistic locking with TRANSACTIONAL access.
+ * <p>
+ * By "extra API" we mean those methods that are superfluous to the
+ * function of the JBC integration, where the impl is a no-op or a static
+ * false return value, UnsupportedOperationException, etc.
+ *
+ * @author <a href="brian.stansberry(a)jboss.com">Brian Stansberry</a>
+ * @version $Revision: 1 $
+ */
+public class OptimisticTransactionalExtraAPITestCase extends AbstractJBossCacheTestCase {
+
+ public static final String REGION_NAME = "test/com.foo.test";
+ public static final String KEY = "KEY";
+ public static final String VALUE1 = "VALUE1";
+ public static final String VALUE2 = "VALUE2";
+
+ private static CollectionRegionAccessStrategy localAccessStrategy;
+
+ private static boolean optimistic;
+
+ /**
+ * Create a new TransactionalAccessTestCase.
+ *
+ * @param name
+ */
+ public OptimisticTransactionalExtraAPITestCase(String name) {
+ super(name);
+ }
+
+ protected void setUp() throws Exception {
+ super.setUp();
+
+ if (getCollectionAccessStrategy() == null) {
+ Configuration cfg = createConfiguration();
+ JBossCacheRegionFactory rf = CacheTestUtil.startRegionFactory(cfg, getCacheTestSupport());
+ Cache localCache = rf.getCacheInstanceManager().getEntityCacheInstance();
+ optimistic = localCache.getConfiguration().getNodeLockingScheme() == org.jboss.cache.config.Configuration.NodeLockingScheme.OPTIMISTIC;
+ CollectionRegion localCollectionRegion = rf.buildCollectionRegion(REGION_NAME, cfg.getProperties(), null);
+ setCollectionAccessStrategy(localCollectionRegion.buildAccessStrategy(getAccessType()));
+ }
+ }
+
+ protected void tearDown() throws Exception {
+
+ super.tearDown();
+ }
+
+ protected Configuration createConfiguration() {
+ Configuration cfg = CacheTestUtil.buildConfiguration(REGION_PREFIX, MultiplexedJBossCacheRegionFactory.class, true, false);
+ cfg.setProperty(MultiplexingCacheInstanceManager.ENTITY_CACHE_RESOURCE_PROP, getCacheConfigName());
+ return cfg;
+ }
+
+ protected String getCacheConfigName() {
+ return "optimistic-entity";
+ }
+
+ protected boolean isUsingOptimisticLocking() {
+ return optimistic;
+ }
+
+ protected AccessType getAccessType() {
+ return AccessType.TRANSACTIONAL;
+ }
+
+ protected CollectionRegionAccessStrategy getCollectionAccessStrategy() {
+ return localAccessStrategy;
+ }
+
+ protected void setCollectionAccessStrategy(CollectionRegionAccessStrategy strategy) {
+ localAccessStrategy = strategy;
+ }
+
+ /**
+ * This is just a setup test where we assert that the cache config is
+ * as we expected.
+ */
+ public void testCacheConfiguration() {
+ assertTrue("Using Optimistic locking", isUsingOptimisticLocking());
+ }
+
+ /**
+ * Test method for {@link TransactionalAccess#lockItem(java.lang.Object, java.lang.Object)}.
+ */
+ public void testLockItem() {
+ assertNull(getCollectionAccessStrategy().lockItem(KEY, new Integer(1)));
+ }
+
+ /**
+ * Test method for {@link TransactionalAccess#lockRegion()}.
+ */
+ public void testLockRegion() {
+ assertNull(getCollectionAccessStrategy().lockRegion());
+ }
+
+ /**
+ * Test method for {@link TransactionalAccess#unlockItem(java.lang.Object, org.hibernate.cache.access.SoftLock)}.
+ */
+ public void testUnlockItem() {
+ getCollectionAccessStrategy().unlockItem(KEY, new MockSoftLock());
+ }
+
+ /**
+ * Test method for {@link TransactionalAccess#unlockRegion(org.hibernate.cache.access.SoftLock)}.
+ */
+ public void testUnlockRegion() {
+ getCollectionAccessStrategy().unlockItem(KEY, new MockSoftLock());
+ }
+
+ public static class MockSoftLock implements SoftLock {
+
+ }
+
+}
Added: core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/collection/PessimisticInvalidatedTransactionalTestCase.java
===================================================================
--- core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/collection/PessimisticInvalidatedTransactionalTestCase.java (rev 0)
+++ core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/collection/PessimisticInvalidatedTransactionalTestCase.java 2007-10-18 20:08:50 UTC (rev 14101)
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2007, Red Hat Middleware, LLC. All rights reserved.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, v. 2.1. This program is distributed in the
+ * hope that it will be useful, but WITHOUT A WARRANTY; without even the implied
+ * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details. You should have received a
+ * copy of the GNU Lesser General Public License, v.2.1 along with this
+ * distribution; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Red Hat Author(s): Brian Stansberry
+ */
+
+package org.hibernate.test.cache.jbc2.collection;
+
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+/**
+ * Tests TRANSACTIONAL access when pessimistic locking and invalidation are used.
+ *
+ * @author <a href="brian.stansberry(a)jboss.com">Brian Stansberry</a>
+ * @version $Revision: 1 $
+ */
+public class PessimisticInvalidatedTransactionalTestCase extends AbstractTransactionalAccessTestCase {
+
+ /**
+ * Create a new PessimisticTransactionalAccessTestCase.
+ *
+ * @param name
+ */
+ public PessimisticInvalidatedTransactionalTestCase(String name) {
+ super(name);
+ }
+
+ public static Test suite() throws Exception {
+ TestSuite suite = createFailureExpectedSuite(PessimisticInvalidatedTransactionalTestCase.class);
+ return getTestSetup(suite, "pessimistic-entity");
+ }
+
+ @Override
+ public void testCacheConfiguration() {
+ assertTrue("Using Invalidation", isUsingInvalidation());
+ assertFalse("Using Optimistic locking", isUsingOptimisticLocking());
+ assertTrue("Synchronous mode", isSynchronous());
+ }
+
+ // Known failures
+
+ public void testEvictAllFailureExpected() {
+ super.testEvictAll();
+ }
+
+ public void testRemoveAllFailureExpected() {
+ super.testRemoveAll();
+ }
+
+ public void testPutFromLoadFailureExpected() throws Exception {
+ super.testPutFromLoad();
+ }
+
+ public void testPutFromLoadMinimalFailureExpected() throws Exception {
+ super.testPutFromLoadMinimal();
+ }
+
+}
Added: core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/collection/PessimisticReadOnlyExtraAPITestCase.java
===================================================================
--- core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/collection/PessimisticReadOnlyExtraAPITestCase.java (rev 0)
+++ core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/collection/PessimisticReadOnlyExtraAPITestCase.java 2007-10-18 20:08:50 UTC (rev 14101)
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2007, Red Hat Middleware, LLC. All rights reserved.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, v. 2.1. This program is distributed in the
+ * hope that it will be useful, but WITHOUT A WARRANTY; without even the implied
+ * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details. You should have received a
+ * copy of the GNU Lesser General Public License, v.2.1 along with this
+ * distribution; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Red Hat Author(s): Brian Stansberry
+ */
+
+package org.hibernate.test.cache.jbc2.collection;
+
+import org.hibernate.cache.access.CollectionRegionAccessStrategy;
+
+/**
+ * Tests for the "extra API" in EntityRegionAccessStrategy; in this
+ * version using pessimistic locking with READ_ONLY access.
+ * <p>
+ * By "extra API" we mean those methods that are superfluous to the
+ * function of the JBC integration, where the impl is a no-op or a static
+ * false return value, UnsupportedOperationException, etc.
+ *
+ * @author <a href="brian.stansberry(a)jboss.com">Brian Stansberry</a>
+ * @version $Revision: 1 $
+ */
+public class PessimisticReadOnlyExtraAPITestCase extends OptimisticReadOnlyExtraAPITestCase {
+
+ private static CollectionRegionAccessStrategy localAccessStrategy;
+
+ /**
+ * Create a new PessimisticAccessStrategyExtraAPITestCase.
+ *
+ * @param name
+ */
+ public PessimisticReadOnlyExtraAPITestCase(String name) {
+ super(name);
+ }
+
+ @Override
+ protected String getCacheConfigName() {
+ return "pessimistic-entity";
+ }
+
+ @Override
+ protected CollectionRegionAccessStrategy getCollectionAccessStrategy() {
+ return localAccessStrategy;
+ }
+
+ @Override
+ protected void setCollectionAccessStrategy(CollectionRegionAccessStrategy strategy) {
+ localAccessStrategy = strategy;
+ }
+
+ @Override
+ public void testCacheConfiguration() {
+ assertFalse("Using Optimistic locking", isUsingOptimisticLocking());
+ }
+
+}
Added: core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/collection/PessimisticReadOnlyTestCase.java
===================================================================
--- core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/collection/PessimisticReadOnlyTestCase.java (rev 0)
+++ core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/collection/PessimisticReadOnlyTestCase.java 2007-10-18 20:08:50 UTC (rev 14101)
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2007, Red Hat Middleware, LLC. All rights reserved.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, v. 2.1. This program is distributed in the
+ * hope that it will be useful, but WITHOUT A WARRANTY; without even the implied
+ * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details. You should have received a
+ * copy of the GNU Lesser General Public License, v.2.1 along with this
+ * distribution; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Red Hat Author(s): Brian Stansberry
+ */
+
+package org.hibernate.test.cache.jbc2.collection;
+
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+/**
+ * Tests READ_ONLY access when pessimistic locking and invalidation are used.
+ *
+ * @author <a href="brian.stansberry(a)jboss.com">Brian Stansberry</a>
+ * @version $Revision: 1 $
+ */
+public class PessimisticReadOnlyTestCase extends AbstractReadOnlyAccessTestCase {
+
+ /**
+ * Create a new PessimisticTransactionalAccessTestCase.
+ *
+ * @param name
+ */
+ public PessimisticReadOnlyTestCase(String name) {
+ super(name);
+ }
+
+ public static Test suite() throws Exception {
+ TestSuite suite = createFailureExpectedSuite(PessimisticReadOnlyTestCase.class);
+ return getTestSetup(suite, "pessimistic-entity");
+ }
+
+ // Known failures
+
+ public void testEvictAllFailureExpected() {
+ super.testEvictAll();
+ }
+
+ public void testRemoveAllFailureExpected() {
+ super.testRemoveAll();
+ }
+
+ public void testPutFromLoadFailureExpected() throws Exception {
+ super.testPutFromLoad();
+ }
+
+ public void testPutFromLoadMinimalFailureExpected() throws Exception {
+ super.testPutFromLoadMinimal();
+ }
+
+ // Overrides
+
+ @Override
+ public void testCacheConfiguration() {
+ assertTrue("Using Invalidation", isUsingInvalidation());
+ assertFalse("Using Optimistic locking", isUsingOptimisticLocking());
+ }
+
+}
Added: core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/collection/PessimisticReplicatedTransactionalTestCase.java
===================================================================
--- core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/collection/PessimisticReplicatedTransactionalTestCase.java (rev 0)
+++ core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/collection/PessimisticReplicatedTransactionalTestCase.java 2007-10-18 20:08:50 UTC (rev 14101)
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2007, Red Hat Middleware, LLC. All rights reserved.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, v. 2.1. This program is distributed in the
+ * hope that it will be useful, but WITHOUT A WARRANTY; without even the implied
+ * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details. You should have received a
+ * copy of the GNU Lesser General Public License, v.2.1 along with this
+ * distribution; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Red Hat Author(s): Brian Stansberry
+ */
+
+package org.hibernate.test.cache.jbc2.collection;
+
+import junit.framework.Test;
+
+/**
+ * Tests TRANSACTIONAL access when pessimistic locking and replication are used.
+ *
+ * @author <a href="brian.stansberry(a)jboss.com">Brian Stansberry</a>
+ * @version $Revision: 1 $
+ */
+public class PessimisticReplicatedTransactionalTestCase extends AbstractTransactionalAccessTestCase {
+
+ /**
+ * Create a new PessimisticTransactionalAccessTestCase.
+ *
+ * @param name
+ */
+ public PessimisticReplicatedTransactionalTestCase(String name) {
+ super(name);
+ }
+
+ public static Test suite() throws Exception {
+ return getTestSetup(PessimisticReplicatedTransactionalTestCase.class, "pessimistic-shared");
+ }
+
+ @Override
+ public void testCacheConfiguration() {
+ assertFalse("Using Invalidation", isUsingInvalidation());
+ assertFalse("Using Optimistic locking", isUsingOptimisticLocking());
+ assertTrue("Synchronous mode", isSynchronous());
+ }
+
+
+
+}
Added: core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/collection/PessimisticTransactionalExtraAPITestCase.java
===================================================================
--- core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/collection/PessimisticTransactionalExtraAPITestCase.java (rev 0)
+++ core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/collection/PessimisticTransactionalExtraAPITestCase.java 2007-10-18 20:08:50 UTC (rev 14101)
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2007, Red Hat Middleware, LLC. All rights reserved.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, v. 2.1. This program is distributed in the
+ * hope that it will be useful, but WITHOUT A WARRANTY; without even the implied
+ * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details. You should have received a
+ * copy of the GNU Lesser General Public License, v.2.1 along with this
+ * distribution; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Red Hat Author(s): Brian Stansberry
+ */
+
+package org.hibernate.test.cache.jbc2.collection;
+
+import org.hibernate.cache.access.CollectionRegionAccessStrategy;
+
+/**
+ * Tests for the "extra API" in EntityRegionAccessStrategy; in this base
+ * version using Optimistic locking with TRANSACTIONAL access.
+ * <p>
+ * By "extra API" we mean those methods that are superfluous to the
+ * function of the JBC integration, where the impl is a no-op or a static
+ * false return value, UnsupportedOperationException, etc.
+ *
+ * @author <a href="brian.stansberry(a)jboss.com">Brian Stansberry</a>
+ * @version $Revision: 1 $
+ */
+public class PessimisticTransactionalExtraAPITestCase extends OptimisticTransactionalExtraAPITestCase {
+
+ private static CollectionRegionAccessStrategy localAccessStrategy;
+
+ /**
+ * Create a new PessimisticAccessStrategyExtraAPITestCase.
+ *
+ * @param name
+ */
+ public PessimisticTransactionalExtraAPITestCase(String name) {
+ super(name);
+ }
+
+ @Override
+ protected String getCacheConfigName() {
+ return "pessimistic-entity";
+ }
+
+ @Override
+ protected CollectionRegionAccessStrategy getCollectionAccessStrategy() {
+ return localAccessStrategy;
+ }
+
+ @Override
+ protected void setCollectionAccessStrategy(CollectionRegionAccessStrategy strategy) {
+ localAccessStrategy = strategy;
+ }
+
+ @Override
+ public void testCacheConfiguration() {
+ assertFalse("Using Optimistic locking", isUsingOptimisticLocking());
+ }
+
+}
Added: core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/entity/AbstractEntityRegionAccessStrategyTestCase.java
===================================================================
--- core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/entity/AbstractEntityRegionAccessStrategyTestCase.java (rev 0)
+++ core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/entity/AbstractEntityRegionAccessStrategyTestCase.java 2007-10-18 20:08:50 UTC (rev 14101)
@@ -0,0 +1,736 @@
+/*
+ * Copyright (c) 2007, Red Hat Middleware, LLC. All rights reserved.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, v. 2.1. This program is distributed in the
+ * hope that it will be useful, but WITHOUT A WARRANTY; without even the implied
+ * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details. You should have received a
+ * copy of the GNU Lesser General Public License, v.2.1 along with this
+ * distribution; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Red Hat Author(s): Brian Stansberry
+ */
+
+package org.hibernate.test.cache.jbc2.entity;
+
+import java.util.Iterator;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+import junit.extensions.TestSetup;
+import junit.framework.AssertionFailedError;
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+import org.hibernate.cache.CacheDataDescription;
+import org.hibernate.cache.EntityRegion;
+import org.hibernate.cache.access.AccessType;
+import org.hibernate.cache.access.EntityRegionAccessStrategy;
+import org.hibernate.cache.impl.CacheDataDescriptionImpl;
+import org.hibernate.cache.jbc2.BasicRegionAdapter;
+import org.hibernate.cache.jbc2.JBossCacheRegionFactory;
+import org.hibernate.cache.jbc2.MultiplexedJBossCacheRegionFactory;
+import org.hibernate.cache.jbc2.builder.MultiplexingCacheInstanceManager;
+import org.hibernate.cache.jbc2.entity.EntityRegionImpl;
+import org.hibernate.cache.jbc2.entity.TransactionalAccess;
+import org.hibernate.cache.jbc2.util.CacheHelper;
+import org.hibernate.cache.jbc2.util.NonLockingDataVersion;
+import org.hibernate.cfg.Configuration;
+import org.hibernate.test.cache.jbc2.AbstractJBossCacheTestCase;
+import org.hibernate.test.util.CacheTestUtil;
+import org.hibernate.util.ComparableComparator;
+import org.jboss.cache.Cache;
+import org.jboss.cache.Fqn;
+import org.jboss.cache.Node;
+import org.jboss.cache.NodeSPI;
+import org.jboss.cache.transaction.BatchModeTransactionManager;
+
+/**
+ * Base class for tests of EntityRegionAccessStrategy impls.
+ *
+ * @author <a href="brian.stansberry(a)jboss.com">Brian Stansberry</a>
+ * @version $Revision: 1 $
+ */
+public abstract class AbstractEntityRegionAccessStrategyTestCase extends AbstractJBossCacheTestCase {
+
+ public static final String REGION_NAME = "test/com.foo.test";
+ public static final String KEY = "KEY";
+ public static final String VALUE1 = "VALUE1";
+ public static final String VALUE2 = "VALUE2";
+
+ protected static Configuration localCfg;
+ protected static JBossCacheRegionFactory localRegionFactory;
+ protected static Cache localCache;
+ protected static Configuration remoteCfg;
+ protected static JBossCacheRegionFactory remoteRegionFactory;
+ protected static Cache remoteCache;
+
+ protected static boolean invalidation;
+ protected static boolean optimistic;
+ protected static boolean synchronous;
+
+ protected EntityRegion localEntityRegion;
+ protected EntityRegionAccessStrategy localAccessStrategy;
+
+ protected EntityRegion remoteEntityRegion;
+ protected EntityRegionAccessStrategy remoteAccessStrategy;
+
+ protected Exception node1Exception;
+ protected Exception node2Exception;
+
+ protected AssertionFailedError node1Failure;
+ protected AssertionFailedError node2Failure;
+
+
+ public static Test getTestSetup(Class testClass, String configName) {
+ TestSuite suite = new TestSuite(testClass);
+ return new AccessStrategyTestSetup(suite, configName);
+ }
+
+ public static Test getTestSetup(Test test, String configName) {
+ return new AccessStrategyTestSetup(test, configName);
+ }
+
+
+ /**
+ * Create a new TransactionalAccessTestCase.
+ *
+ * @param name
+ */
+ public AbstractEntityRegionAccessStrategyTestCase(String name) {
+ super(name);
+ }
+
+ protected abstract AccessType getAccessType();
+
+ protected void setUp() throws Exception {
+ super.setUp();
+
+ localEntityRegion = localRegionFactory.buildEntityRegion(REGION_NAME, localCfg.getProperties(), getCacheDataDescription());
+ localAccessStrategy = localEntityRegion.buildAccessStrategy(getAccessType());
+
+ remoteEntityRegion = remoteRegionFactory.buildEntityRegion(REGION_NAME, remoteCfg.getProperties(), getCacheDataDescription());
+ remoteAccessStrategy = remoteEntityRegion.buildAccessStrategy(getAccessType());
+
+ node1Exception = null;
+ node2Exception = null;
+
+ node1Failure = null;
+ node2Failure = null;
+ }
+
+ protected void tearDown() throws Exception {
+
+ super.tearDown();
+
+ if (localEntityRegion != null)
+ localEntityRegion.destroy();
+ if (remoteEntityRegion != null)
+ remoteEntityRegion.destroy();
+
+ try {
+ localCache.getInvocationContext().getOptionOverrides().setCacheModeLocal(true);
+ localCache.removeNode(Fqn.ROOT);
+ }
+ catch (Exception e) {
+ log.error("Problem purging local cache" ,e);
+ }
+
+ try {
+ remoteCache.getInvocationContext().getOptionOverrides().setCacheModeLocal(true);
+ remoteCache.removeNode(Fqn.ROOT);
+ }
+ catch (Exception e) {
+ log.error("Problem purging remote cache" ,e);
+ }
+
+ node1Exception = null;
+ node2Exception = null;
+
+ node1Failure = null;
+ node2Failure = null;
+ }
+
+ protected static Configuration createConfiguration(String configName) {
+ Configuration cfg = CacheTestUtil.buildConfiguration(REGION_PREFIX, MultiplexedJBossCacheRegionFactory.class, true, false);
+ cfg.setProperty(MultiplexingCacheInstanceManager.ENTITY_CACHE_RESOURCE_PROP, configName);
+ return cfg;
+ }
+
+ protected CacheDataDescription getCacheDataDescription() {
+ return new CacheDataDescriptionImpl(true, true, ComparableComparator.INSTANCE);
+ }
+
+ protected boolean isUsingOptimisticLocking() {
+ return optimistic;
+ }
+
+ protected boolean isUsingInvalidation() {
+ return invalidation;
+ }
+
+ protected boolean isSynchronous() {
+ return synchronous;
+ }
+
+ protected Fqn getRegionFqn(String regionName, String regionPrefix) {
+ return BasicRegionAdapter.getTypeLastRegionFqn(regionName, regionPrefix, EntityRegionImpl.TYPE);
+ }
+
+ /**
+ * This is just a setup test where we assert that the cache config is
+ * as we expected.
+ */
+ public abstract void testCacheConfiguration();
+
+ /**
+ * Test method for {@link TransactionalAccess#getRegion()}.
+ */
+ public void testGetRegion() {
+ assertEquals("Correct region", localEntityRegion, localAccessStrategy.getRegion());
+ }
+
+ /**
+ * Test method for {@link TransactionalAccess#putFromLoad(java.lang.Object, java.lang.Object, long, java.lang.Object)}.
+ */
+ public void testPutFromLoad() throws Exception {
+ putFromLoadTest(false);
+ }
+
+ /**
+ * Test method for {@link TransactionalAccess#putFromLoad(java.lang.Object, java.lang.Object, long, java.lang.Object, boolean)}.
+ */
+ public void testPutFromLoadMinimal() throws Exception {
+ putFromLoadTest(true);
+ }
+
+ /**
+ * Simulate 2 nodes, both start, tx do a get, experience a cache miss,
+ * then 'read from db.' First does a putFromLoad, then an update.
+ * Second tries to do a putFromLoad with stale data (i.e. it took
+ * longer to read from the db). Both commit their tx. Then
+ * both start a new tx and get. First should see the updated data;
+ * second should either see the updated data (isInvalidation()( == false)
+ * or null (isInvalidation() == true).
+ *
+ * @param useMinimalAPI
+ * @throws Exception
+ */
+ private void putFromLoadTest(final boolean useMinimalAPI) throws Exception {
+
+ final CountDownLatch writeLatch1 = new CountDownLatch(1);
+ final CountDownLatch writeLatch2 = new CountDownLatch(1);
+ final CountDownLatch completionLatch = new CountDownLatch(2);
+
+ Thread node1 = new Thread() {
+
+ public void run() {
+
+ try {
+ long txTimestamp = System.currentTimeMillis();
+ BatchModeTransactionManager.getInstance().begin();
+
+ assertNull("node1 starts clean", localAccessStrategy.get(KEY, txTimestamp));
+
+ writeLatch1.await();
+
+ if (useMinimalAPI) {
+ localAccessStrategy.putFromLoad(KEY, VALUE1, txTimestamp, new Integer(1), true);
+ }
+ else {
+ localAccessStrategy.putFromLoad(KEY, VALUE1, txTimestamp, new Integer(1));
+ }
+
+ localAccessStrategy.update(KEY, VALUE2, new Integer(2), new Integer(1));
+
+ BatchModeTransactionManager.getInstance().commit();
+ }
+ catch (Exception e) {
+ log.error("node1 caught exception", e);
+ node1Exception = e;
+ rollback();
+ }
+ catch (AssertionFailedError e) {
+ node1Failure = e;
+ rollback();
+ }
+ finally {
+ // Let node2 write
+ writeLatch2.countDown();
+ completionLatch.countDown();
+ }
+ }
+ };
+
+ Thread node2 = new Thread() {
+
+ public void run() {
+
+ try {
+ long txTimestamp = System.currentTimeMillis();
+ BatchModeTransactionManager.getInstance().begin();
+
+ assertNull("node1 starts clean", remoteAccessStrategy.get(KEY, txTimestamp));
+
+ // Let node1 write
+ writeLatch1.countDown();
+ // Wait for node1 to finish
+ writeLatch2.await();
+
+ if (useMinimalAPI) {
+ remoteAccessStrategy.putFromLoad(KEY, VALUE1, txTimestamp, new Integer(1), true);
+ }
+ else {
+ remoteAccessStrategy.putFromLoad(KEY, VALUE1, txTimestamp, new Integer(1));
+ }
+
+ BatchModeTransactionManager.getInstance().commit();
+ }
+ catch (Exception e) {
+ log.error("node2 caught exception", e);
+ node2Exception = e;
+ rollback();
+ }
+ catch (AssertionFailedError e) {
+ node2Failure = e;
+ rollback();
+ }
+ finally {
+ completionLatch.countDown();
+ }
+ }
+ };
+
+ node1.setDaemon(true);
+ node2.setDaemon(true);
+
+ node1.start();
+ node2.start();
+
+ assertTrue("Threads completed", completionLatch.await(2, TimeUnit.SECONDS));
+
+ if (node1Failure != null)
+ throw node1Failure;
+ if (node2Failure != null)
+ throw node2Failure;
+
+ assertEquals("node1 saw no exceptions", null, node1Exception);
+ assertEquals("node2 saw no exceptions", null, node2Exception);
+
+ long txTimestamp = System.currentTimeMillis();
+ assertEquals("Correct node1 value", VALUE2, localAccessStrategy.get(KEY, txTimestamp));
+
+ if (isUsingInvalidation()) {
+ if (isUsingOptimisticLocking())
+ // The node is "deleted" but it's ghost data version prevents the stale node2 PFER
+ assertEquals("Correct node2 value", null, remoteAccessStrategy.get(KEY, txTimestamp));
+ else {
+ // no data version to prevent the PFER; we count on db locks preventing this
+ assertEquals("Expected node2 value", VALUE1, remoteAccessStrategy.get(KEY, txTimestamp));
+ }
+ }
+ else {
+ // The node1 update is replicated, preventing the node2 PFER
+ assertEquals("Correct node2 value", VALUE2, remoteAccessStrategy.get(KEY, txTimestamp));
+ }
+ }
+
+ /**
+ * Test method for {@link TransactionalAccess#insert(java.lang.Object, java.lang.Object, java.lang.Object)}.
+ */
+ public void testInsert() throws Exception {
+
+ final CountDownLatch readLatch = new CountDownLatch(1);
+ final CountDownLatch commitLatch = new CountDownLatch(1);
+ final CountDownLatch completionLatch = new CountDownLatch(2);
+
+ Thread inserter = new Thread() {
+
+ public void run() {
+
+ try {
+ long txTimestamp = System.currentTimeMillis();
+ BatchModeTransactionManager.getInstance().begin();
+
+ assertNull("Correct initial value", localAccessStrategy.get(KEY, txTimestamp));
+
+ localAccessStrategy.insert(KEY, VALUE1, new Integer(1));
+
+ readLatch.countDown();
+ commitLatch.await();
+
+ BatchModeTransactionManager.getInstance().commit();
+ }
+ catch (Exception e) {
+ log.error("node1 caught exception", e);
+ node1Exception = e;
+ rollback();
+ }
+ catch (AssertionFailedError e) {
+ node1Failure = e;
+ rollback();
+ }
+ finally {
+ completionLatch.countDown();
+ }
+ }
+ };
+
+ Thread reader = new Thread() {
+
+ public void run() {
+
+ try {
+ long txTimestamp = System.currentTimeMillis();
+ BatchModeTransactionManager.getInstance().begin();
+
+ readLatch.await();
+ Object expected = isUsingOptimisticLocking() ? null : VALUE1;
+
+ assertEquals("Correct initial value", expected, localAccessStrategy.get(KEY, txTimestamp));
+
+ BatchModeTransactionManager.getInstance().commit();
+ }
+ catch (Exception e) {
+ log.error("node1 caught exception", e);
+ node1Exception = e;
+ rollback();
+ }
+ catch (AssertionFailedError e) {
+ node1Failure = e;
+ rollback();
+ }
+ finally {
+ commitLatch.countDown();
+ completionLatch.countDown();
+ }
+ }
+ };
+
+ inserter.setDaemon(true);
+ reader.setDaemon(true);
+ inserter.start();
+ reader.start();
+
+ if (isUsingOptimisticLocking())
+ assertTrue("Threads completed", completionLatch.await(1, TimeUnit.SECONDS));
+ else {
+ // Reader should be blocking for lock
+ assertFalse("Threads completed", completionLatch.await(250, TimeUnit.MILLISECONDS));
+ commitLatch.countDown();
+ assertTrue("Threads completed", completionLatch.await(1, TimeUnit.SECONDS));
+ }
+
+ if (node1Failure != null)
+ throw node1Failure;
+ if (node2Failure != null)
+ throw node2Failure;
+
+ assertEquals("node1 saw no exceptions", null, node1Exception);
+ assertEquals("node2 saw no exceptions", null, node2Exception);
+
+ long txTimestamp = System.currentTimeMillis();
+ assertEquals("Correct node1 value", VALUE1, localAccessStrategy.get(KEY, txTimestamp));
+ Object expected = isUsingInvalidation() ? null : VALUE1;
+ assertEquals("Correct node2 value", expected, remoteAccessStrategy.get(KEY, txTimestamp));
+ }
+
+ /**
+ * Test method for {@link TransactionalAccess#update(java.lang.Object, java.lang.Object, java.lang.Object, java.lang.Object)}.
+ */
+ public void testUpdate() throws Exception {
+
+ // Set up initial state
+ localAccessStrategy.putFromLoad(KEY, VALUE1, System.currentTimeMillis(), new Integer(1));
+ remoteAccessStrategy.putFromLoad(KEY, VALUE1, System.currentTimeMillis(), new Integer(1));
+
+ // Let the async put propagate
+ sleep(250);
+
+ final CountDownLatch readLatch = new CountDownLatch(1);
+ final CountDownLatch commitLatch = new CountDownLatch(1);
+ final CountDownLatch completionLatch = new CountDownLatch(2);
+
+ Thread updater = new Thread() {
+
+ public void run() {
+
+ try {
+ long txTimestamp = System.currentTimeMillis();
+ BatchModeTransactionManager.getInstance().begin();
+
+ assertEquals("Correct initial value", VALUE1, localAccessStrategy.get(KEY, txTimestamp));
+
+ localAccessStrategy.update(KEY, VALUE2, new Integer(2), new Integer(1));
+
+ readLatch.countDown();
+ commitLatch.await();
+
+ BatchModeTransactionManager.getInstance().commit();
+ }
+ catch (Exception e) {
+ log.error("node1 caught exception", e);
+ node1Exception = e;
+ rollback();
+ }
+ catch (AssertionFailedError e) {
+ node1Failure = e;
+ rollback();
+ }
+ finally {
+ completionLatch.countDown();
+ }
+ }
+ };
+
+ Thread reader = new Thread() {
+
+ public void run() {
+ try {
+ long txTimestamp = System.currentTimeMillis();
+ BatchModeTransactionManager.getInstance().begin();
+
+ readLatch.await();
+
+ // This will block w/ pessimistic locking and then
+ // read the new value; w/ optimistic it shouldn't
+ // block and will read the old value
+ Object expected = isUsingOptimisticLocking() ? VALUE1 : VALUE2;
+ assertEquals("Correct value", expected, localAccessStrategy.get(KEY, txTimestamp));
+
+ BatchModeTransactionManager.getInstance().commit();
+ }
+ catch (Exception e) {
+ log.error("node1 caught exception", e);
+ node1Exception = e;
+ rollback();
+ }
+ catch (AssertionFailedError e) {
+ node1Failure = e;
+ rollback();
+ }
+ finally {
+ commitLatch.countDown();
+ completionLatch.countDown();
+ }
+ }
+ };
+
+ updater.setDaemon(true);
+ reader.setDaemon(true);
+ updater.start();
+ reader.start();
+
+ if (isUsingOptimisticLocking())
+ // Should complete promptly
+ assertTrue(completionLatch.await(1, TimeUnit.SECONDS));
+ else {
+ // Reader thread should be blocking
+ assertFalse(completionLatch.await(250, TimeUnit.MILLISECONDS));
+ // Let the writer commit down
+ commitLatch.countDown();
+ assertTrue(completionLatch.await(1, TimeUnit.SECONDS));
+ }
+
+ if (node1Failure != null)
+ throw node1Failure;
+ if (node2Failure != null)
+ throw node2Failure;
+
+ assertEquals("node1 saw no exceptions", null, node1Exception);
+ assertEquals("node2 saw no exceptions", null, node2Exception);
+
+ long txTimestamp = System.currentTimeMillis();
+ assertEquals("Correct node1 value", VALUE2, localAccessStrategy.get(KEY, txTimestamp));
+ Object expected = isUsingInvalidation() ? null : VALUE2;
+ assertEquals("Correct node2 value", expected, remoteAccessStrategy.get(KEY, txTimestamp));
+ }
+
+ /**
+ * Test method for {@link TransactionalAccess#remove(java.lang.Object)}.
+ */
+ public void testRemove() {
+ evictOrRemoveTest(false);
+ }
+
+ /**
+ * Test method for {@link TransactionalAccess#removeAll()}.
+ */
+ public void testRemoveAll() {
+ evictOrRemoveAllTest(false);
+ }
+
+ /**
+ * Test method for {@link TransactionalAccess#evict(java.lang.Object)}.
+ *
+ * FIXME add testing of the "immediately without regard for transaction
+ * isolation" bit in the EntityRegionAccessStrategy API.
+ */
+ public void testEvict() {
+ evictOrRemoveTest(true);
+ }
+
+ /**
+ * Test method for {@link TransactionalAccess#evictAll()}.
+ *
+ * FIXME add testing of the "immediately without regard for transaction
+ * isolation" bit in the EntityRegionAccessStrategy API.
+ */
+ public void testEvictAll() {
+ evictOrRemoveAllTest(true);
+ }
+
+ private void evictOrRemoveTest(boolean evict) {
+ assertNull("local is clean", localAccessStrategy.get(KEY, System.currentTimeMillis()));
+ assertNull("remote is clean", remoteAccessStrategy.get(KEY, System.currentTimeMillis()));
+
+ localAccessStrategy.putFromLoad(KEY, VALUE1, System.currentTimeMillis(), new Integer(1));
+ assertEquals(VALUE1, localAccessStrategy.get(KEY, System.currentTimeMillis()));
+ remoteAccessStrategy.putFromLoad(KEY, VALUE1, System.currentTimeMillis(), new Integer(1));
+ assertEquals(VALUE1, remoteAccessStrategy.get(KEY, System.currentTimeMillis()));
+
+ // Wait for async propagation
+ sleep(250);
+
+ if (evict)
+ localAccessStrategy.evict(KEY);
+ else
+ localAccessStrategy.remove(KEY);
+
+ assertEquals(null, localAccessStrategy.get(KEY, System.currentTimeMillis()));
+
+// sleep(1000);
+
+ assertEquals(null, remoteAccessStrategy.get(KEY, System.currentTimeMillis()));
+ }
+
+ private void evictOrRemoveAllTest(boolean evict) {
+
+ Fqn regionFqn = getRegionFqn(REGION_NAME, REGION_PREFIX);
+
+ Node regionRoot = localCache.getRoot().getChild(regionFqn);
+ assertFalse(regionRoot == null);
+ assertEquals(0, regionRoot.getChildrenNames().size());
+ assertTrue(regionRoot.isResident());
+
+ if (isUsingOptimisticLocking()) {
+ assertEquals(NonLockingDataVersion.class, ((NodeSPI) regionRoot).getVersion().getClass());
+ }
+
+ regionRoot = remoteCache.getRoot().getChild(regionFqn);
+ assertFalse(regionRoot == null);
+ assertEquals(0, regionRoot.getChildrenNames().size());
+ assertTrue(regionRoot.isResident());
+
+ if (isUsingOptimisticLocking()) {
+ assertEquals(NonLockingDataVersion.class, ((NodeSPI) regionRoot).getVersion().getClass());
+ }
+
+ assertNull("local is clean", localAccessStrategy.get(KEY, System.currentTimeMillis()));
+ assertNull("remote is clean", remoteAccessStrategy.get(KEY, System.currentTimeMillis()));
+
+ localAccessStrategy.putFromLoad(KEY, VALUE1, System.currentTimeMillis(), new Integer(1));
+ assertEquals(VALUE1, localAccessStrategy.get(KEY, System.currentTimeMillis()));
+ remoteAccessStrategy.putFromLoad(KEY, VALUE1, System.currentTimeMillis(), new Integer(1));
+ assertEquals(VALUE1, remoteAccessStrategy.get(KEY, System.currentTimeMillis()));
+
+ // Wait for async propagation
+ sleep(250);
+
+
+
+ if (isUsingOptimisticLocking()) {
+ regionRoot = localCache.getRoot().getChild(regionFqn);
+ assertEquals(NonLockingDataVersion.class, ((NodeSPI) regionRoot).getVersion().getClass());
+ regionRoot = remoteCache.getRoot().getChild(regionFqn);
+ assertEquals(NonLockingDataVersion.class, ((NodeSPI) regionRoot).getVersion().getClass());
+ }
+
+ if (evict)
+ localAccessStrategy.evictAll();
+ else
+ localAccessStrategy.removeAll();
+
+ regionRoot = localCache.getRoot().getChild(regionFqn);
+ assertFalse(regionRoot == null);
+ assertEquals(0, regionRoot.getChildrenNames().size());
+ assertTrue(regionRoot.isResident());
+
+ regionRoot = remoteCache.getRoot().getChild(regionFqn);
+ assertFalse(regionRoot == null);
+ if (isUsingInvalidation()) {
+ // JBC seems broken: see http://www.jboss.com/index.html?module=bb&op=viewtopic&t=121408
+ // FIXME replace with the following when JBCACHE-1199 and JBCACHE-1200 are done:
+ //assertFalse(regionRoot.isValid());
+ checkNodeIsEmpty(regionRoot);
+ }
+ else {
+ // Same assertion, just different assertion msg
+ assertEquals(0, regionRoot.getChildrenNames().size());
+ }
+ assertTrue(regionRoot.isResident());
+
+ assertNull("local is clean", localAccessStrategy.get(KEY, System.currentTimeMillis()));
+ assertNull("remote is clean", remoteAccessStrategy.get(KEY, System.currentTimeMillis()));
+ }
+
+ private void checkNodeIsEmpty(Node node) {
+ assertEquals("Known issue JBCACHE-1200. node " + node.getFqn() + " should not have keys", 0, node.getKeys().size());
+ for (Iterator it = node.getChildren().iterator(); it.hasNext(); ) {
+ checkNodeIsEmpty((Node) it.next());
+ }
+ }
+
+ protected void rollback() {
+ try {
+ BatchModeTransactionManager.getInstance().rollback();
+ }
+ catch (Exception e) {
+ log.error(e.getMessage(), e);
+ }
+
+ }
+
+ private static class AccessStrategyTestSetup extends TestSetup {
+
+ private String configName;
+
+ public AccessStrategyTestSetup(Test test, String configName) {
+ super(test);
+ this.configName = configName;
+ }
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ localCfg = createConfiguration(configName);
+ localRegionFactory = CacheTestUtil.startRegionFactory(localCfg);
+ localCache = localRegionFactory.getCacheInstanceManager().getEntityCacheInstance();
+
+ remoteCfg = createConfiguration(configName);
+ remoteRegionFactory = CacheTestUtil.startRegionFactory(remoteCfg);
+ remoteCache = remoteRegionFactory.getCacheInstanceManager().getEntityCacheInstance();
+
+ invalidation = CacheHelper.isClusteredInvalidation(localCache);
+ synchronous = CacheHelper.isSynchronous(localCache);
+ optimistic = localCache.getConfiguration().getNodeLockingScheme() == org.jboss.cache.config.Configuration.NodeLockingScheme.OPTIMISTIC;
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ super.tearDown();
+
+ if (localRegionFactory != null)
+ localRegionFactory.stop();
+
+ if (remoteRegionFactory != null)
+ remoteRegionFactory.stop();
+ }
+
+
+ }
+
+}
Added: core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/entity/AbstractReadOnlyAccessTestCase.java
===================================================================
--- core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/entity/AbstractReadOnlyAccessTestCase.java (rev 0)
+++ core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/entity/AbstractReadOnlyAccessTestCase.java 2007-10-18 20:08:50 UTC (rev 14101)
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2007, Red Hat Middleware, LLC. All rights reserved.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, v. 2.1. This program is distributed in the
+ * hope that it will be useful, but WITHOUT A WARRANTY; without even the implied
+ * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details. You should have received a
+ * copy of the GNU Lesser General Public License, v.2.1 along with this
+ * distribution; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Red Hat Author(s): Brian Stansberry
+ */
+
+package org.hibernate.test.cache.jbc2.entity;
+
+import org.hibernate.cache.access.AccessType;
+import org.jboss.cache.transaction.BatchModeTransactionManager;
+
+/**
+ * Base class for tests of TRANSACTIONAL access.
+ *
+ * @author <a href="brian.stansberry(a)jboss.com">Brian Stansberry</a>
+ * @version $Revision: 1 $
+ */
+public abstract class AbstractReadOnlyAccessTestCase extends AbstractEntityRegionAccessStrategyTestCase {
+
+ /**
+ * Create a new AbstractTransactionalAccessTestCase.
+ *
+ */
+ public AbstractReadOnlyAccessTestCase(String name) {
+ super(name);
+ }
+
+ @Override
+ protected AccessType getAccessType() {
+ return AccessType.READ_ONLY;
+ }
+
+ @Override
+ public void testPutFromLoad() throws Exception {
+ putFromLoadTest(false);
+ }
+
+ @Override
+ public void testPutFromLoadMinimal() throws Exception {
+ putFromLoadTest(true);
+ }
+
+ private void putFromLoadTest(boolean minimal) throws Exception {
+ long txTimestamp = System.currentTimeMillis();
+ BatchModeTransactionManager.getInstance().begin();
+ assertNull(localAccessStrategy.get(KEY, System.currentTimeMillis()));
+ if (minimal)
+ localAccessStrategy.putFromLoad(KEY, VALUE1, txTimestamp, new Integer(1), true);
+ else
+ localAccessStrategy.putFromLoad(KEY, VALUE1, txTimestamp, new Integer(1));
+
+ sleep(250);
+ Object expected = isUsingInvalidation() ? null : VALUE1;
+ assertEquals(expected, remoteAccessStrategy.get(KEY, System.currentTimeMillis()));
+
+ BatchModeTransactionManager.getInstance().commit();
+ assertEquals(VALUE1, localAccessStrategy.get(KEY, System.currentTimeMillis()));
+ assertEquals(expected, remoteAccessStrategy.get(KEY, System.currentTimeMillis()));
+ }
+
+ @Override
+ public void testUpdate() throws Exception {
+ try {
+ localAccessStrategy.update(KEY, VALUE2, new Integer(2), new Integer(1));
+ fail("Call to update did not throw exception");
+ }
+ catch (UnsupportedOperationException good) {}
+ }
+
+}
Added: core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/entity/AbstractTransactionalAccessTestCase.java
===================================================================
--- core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/entity/AbstractTransactionalAccessTestCase.java (rev 0)
+++ core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/entity/AbstractTransactionalAccessTestCase.java 2007-10-18 20:08:50 UTC (rev 14101)
@@ -0,0 +1,137 @@
+/*
+ * Copyright (c) 2007, Red Hat Middleware, LLC. All rights reserved.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, v. 2.1. This program is distributed in the
+ * hope that it will be useful, but WITHOUT A WARRANTY; without even the implied
+ * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details. You should have received a
+ * copy of the GNU Lesser General Public License, v.2.1 along with this
+ * distribution; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Red Hat Author(s): Brian Stansberry
+ */
+
+package org.hibernate.test.cache.jbc2.entity;
+
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+import junit.framework.AssertionFailedError;
+
+import org.hibernate.cache.access.AccessType;
+import org.jboss.cache.transaction.BatchModeTransactionManager;
+
+/**
+ * Base class for tests of TRANSACTIONAL access.
+ *
+ * @author <a href="brian.stansberry(a)jboss.com">Brian Stansberry</a>
+ * @version $Revision: 1 $
+ */
+public abstract class AbstractTransactionalAccessTestCase extends AbstractEntityRegionAccessStrategyTestCase {
+
+ /**
+ * Create a new AbstractTransactionalAccessTestCase.
+ *
+ */
+ public AbstractTransactionalAccessTestCase(String name) {
+ super(name);
+ }
+
+ @Override
+ protected AccessType getAccessType() {
+ return AccessType.TRANSACTIONAL;
+ }
+
+ public void testContestedPutFromLoad() throws Exception {
+
+ localAccessStrategy.putFromLoad(KEY, VALUE1, System.currentTimeMillis(), new Integer(1));
+
+ final CountDownLatch pferLatch = new CountDownLatch(1);
+ final CountDownLatch pferCompletionLatch = new CountDownLatch(1);
+ final CountDownLatch commitLatch = new CountDownLatch(1);
+ final CountDownLatch completionLatch = new CountDownLatch(1);
+
+ Thread blocker = new Thread() {
+
+ public void run() {
+
+ try {
+ long txTimestamp = System.currentTimeMillis();
+ BatchModeTransactionManager.getInstance().begin();
+
+ assertEquals("Correct initial value", VALUE1, localAccessStrategy.get(KEY, txTimestamp));
+
+ localAccessStrategy.update(KEY, VALUE2, new Integer(2), new Integer(1));
+
+ pferLatch.countDown();
+ commitLatch.await();
+
+ BatchModeTransactionManager.getInstance().commit();
+ }
+ catch (Exception e) {
+ log.error("node1 caught exception", e);
+ node1Exception = e;
+ rollback();
+ }
+ catch (AssertionFailedError e) {
+ node1Failure = e;
+ rollback();
+ }
+ finally {
+ completionLatch.countDown();
+ }
+ }
+ };
+
+ Thread putter = new Thread() {
+
+ public void run() {
+
+ try {
+ long txTimestamp = System.currentTimeMillis();
+ BatchModeTransactionManager.getInstance().begin();
+
+ localAccessStrategy.putFromLoad(KEY, VALUE1, txTimestamp, new Integer(1));
+
+ BatchModeTransactionManager.getInstance().commit();
+ }
+ catch (Exception e) {
+ log.error("node1 caught exception", e);
+ node1Exception = e;
+ rollback();
+ }
+ catch (AssertionFailedError e) {
+ node1Failure = e;
+ rollback();
+ }
+ finally {
+ pferCompletionLatch.countDown();
+ }
+ }
+ };
+
+ blocker.start();
+ assertTrue("Active tx has done an update", pferLatch.await(1, TimeUnit.SECONDS));
+ putter.start();
+ assertTrue("putFromLoadreturns promtly", pferCompletionLatch.await(10, TimeUnit.MILLISECONDS));
+
+ commitLatch.countDown();
+
+ assertTrue("Threads completed", completionLatch.await(1, TimeUnit.SECONDS));
+
+ if (node1Failure != null)
+ throw node1Failure;
+ if (node2Failure != null)
+ throw node2Failure;
+
+ assertEquals("node1 saw no exceptions", null, node1Exception);
+ assertEquals("node2 saw no exceptions", null, node2Exception);
+
+ long txTimestamp = System.currentTimeMillis();
+ assertEquals("Correct node1 value", VALUE2, localAccessStrategy.get(KEY, txTimestamp));
+ }
+
+}
Added: core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/entity/EntityRegionImplTestCase.java
===================================================================
--- core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/entity/EntityRegionImplTestCase.java (rev 0)
+++ core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/entity/EntityRegionImplTestCase.java 2007-10-18 20:08:50 UTC (rev 14101)
@@ -0,0 +1,98 @@
+/*
+ * Copyright (c) 2007, Red Hat Middleware, LLC. All rights reserved.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, v. 2.1. This program is distributed in the
+ * hope that it will be useful, but WITHOUT A WARRANTY; without even the implied
+ * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details. You should have received a
+ * copy of the GNU Lesser General Public License, v.2.1 along with this
+ * distribution; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Red Hat Author(s): Brian Stansberry
+ */
+
+package org.hibernate.test.cache.jbc2.entity;
+
+import java.util.Properties;
+
+import org.hibernate.cache.CacheDataDescription;
+import org.hibernate.cache.CacheException;
+import org.hibernate.cache.EntityRegion;
+import org.hibernate.cache.Region;
+import org.hibernate.cache.RegionFactory;
+import org.hibernate.cache.access.AccessType;
+import org.hibernate.cache.jbc2.BasicRegionAdapter;
+import org.hibernate.cache.jbc2.CacheInstanceManager;
+import org.hibernate.cache.jbc2.JBossCacheRegionFactory;
+import org.hibernate.cache.jbc2.entity.EntityRegionImpl;
+import org.hibernate.test.cache.jbc2.AbstractEntityCollectionRegionTestCase;
+import org.jboss.cache.Cache;
+import org.jboss.cache.Fqn;
+
+/**
+ * Tests of EntityRegionImpl.
+ *
+ * @author <a href="brian.stansberry(a)jboss.com">Brian Stansberry</a>
+ * @version $Revision: 1 $
+ */
+public class EntityRegionImplTestCase extends AbstractEntityCollectionRegionTestCase {
+
+ /**
+ * Create a new EntityRegionImplTestCase.
+ *
+ * @param name
+ */
+ public EntityRegionImplTestCase(String name) {
+ super(name);
+ }
+
+ protected void supportedAccessTypeTest(RegionFactory regionFactory, Properties properties) {
+
+ EntityRegion region = regionFactory.buildEntityRegion("test", properties, null);
+
+ assertNull("Got TRANSACTIONAL", region.buildAccessStrategy(AccessType.TRANSACTIONAL).lockRegion());
+
+ try
+ {
+ region.buildAccessStrategy(AccessType.READ_ONLY).lockRegion();
+ fail("Did not get READ_ONLY");
+ }
+ catch (UnsupportedOperationException good) {}
+
+ try
+ {
+ region.buildAccessStrategy(AccessType.NONSTRICT_READ_WRITE);
+ fail("Incorrectly got NONSTRICT_READ_WRITE");
+ }
+ catch (CacheException good) {}
+
+ try
+ {
+ region.buildAccessStrategy(AccessType.READ_WRITE);
+ fail("Incorrectly got READ_WRITE");
+ }
+ catch (CacheException good) {}
+
+ }
+
+ @Override
+ protected Region createRegion(JBossCacheRegionFactory regionFactory, String regionName, Properties properties, CacheDataDescription cdd) {
+ return regionFactory.buildEntityRegion(regionName, properties, cdd);
+ }
+
+ @Override
+ protected Cache getJBossCache(JBossCacheRegionFactory regionFactory) {
+ CacheInstanceManager mgr = regionFactory.getCacheInstanceManager();
+ return mgr.getEntityCacheInstance();
+ }
+
+ @Override
+ protected Fqn getRegionFqn(String regionName, String regionPrefix) {
+ return BasicRegionAdapter.getTypeLastRegionFqn(regionName, regionPrefix, EntityRegionImpl.TYPE);
+ }
+
+
+}
Added: core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/entity/OptimisticInvalidatedTransactionalTestCase.java
===================================================================
--- core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/entity/OptimisticInvalidatedTransactionalTestCase.java (rev 0)
+++ core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/entity/OptimisticInvalidatedTransactionalTestCase.java 2007-10-18 20:08:50 UTC (rev 14101)
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2007, Red Hat Middleware, LLC. All rights reserved.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, v. 2.1. This program is distributed in the
+ * hope that it will be useful, but WITHOUT A WARRANTY; without even the implied
+ * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details. You should have received a
+ * copy of the GNU Lesser General Public License, v.2.1 along with this
+ * distribution; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Red Hat Author(s): Brian Stansberry
+ */
+
+package org.hibernate.test.cache.jbc2.entity;
+
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+/**
+ * Tests TRANSACTIONAL access when optimistic locking and invalidation are used.
+ *
+ * @author <a href="brian.stansberry(a)jboss.com">Brian Stansberry</a>
+ * @version $Revision: 1 $
+ */
+public class OptimisticInvalidatedTransactionalTestCase extends AbstractTransactionalAccessTestCase {
+
+ /**
+ * Create a new OptimisticInvalidatedTransactionalTestCase.
+ *
+ * @param name
+ */
+ public OptimisticInvalidatedTransactionalTestCase(String name) {
+ super(name);
+ }
+
+ public static Test suite() throws Exception {
+ TestSuite suite = createFailureExpectedSuite(OptimisticInvalidatedTransactionalTestCase.class);
+ return getTestSetup(suite, "optimistic-entity");
+ }
+
+ @Override
+ public void testCacheConfiguration() {
+ assertTrue("Using Invalidation", isUsingInvalidation());
+ assertTrue("Using Optimistic locking", isUsingOptimisticLocking());
+ assertTrue("Synchronous mode", isSynchronous());
+ }
+
+ // Known failures
+
+ public void testEvictAllFailureExpected() {
+ super.testEvictAll();
+ }
+
+ public void testRemoveAllFailureExpected() {
+ super.testRemoveAll();
+ }
+}
Added: core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/entity/OptimisticReadOnlyExtraAPITestCase.java
===================================================================
--- core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/entity/OptimisticReadOnlyExtraAPITestCase.java (rev 0)
+++ core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/entity/OptimisticReadOnlyExtraAPITestCase.java 2007-10-18 20:08:50 UTC (rev 14101)
@@ -0,0 +1,98 @@
+/*
+ * Copyright (c) 2007, Red Hat Middleware, LLC. All rights reserved.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, v. 2.1. This program is distributed in the
+ * hope that it will be useful, but WITHOUT A WARRANTY; without even the implied
+ * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details. You should have received a
+ * copy of the GNU Lesser General Public License, v.2.1 along with this
+ * distribution; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Red Hat Author(s): Brian Stansberry
+ */
+
+package org.hibernate.test.cache.jbc2.entity;
+
+import org.hibernate.cache.access.AccessType;
+import org.hibernate.cache.access.EntityRegionAccessStrategy;
+import org.hibernate.cache.jbc2.entity.TransactionalAccess;
+
+/**
+ * Tests for the "extra API" in EntityRegionAccessStrategy; in this
+ * version using Optimistic locking with READ_ONLY access.
+ * <p>
+ * By "extra API" we mean those methods that are superfluous to the
+ * function of the JBC integration, where the impl is a no-op or a static
+ * false return value, UnsupportedOperationException, etc.
+ *
+ * @author <a href="brian.stansberry(a)jboss.com">Brian Stansberry</a>
+ * @version $Revision: 1 $
+ */
+public class OptimisticReadOnlyExtraAPITestCase extends OptimisticTransactionalExtraAPITestCase {
+
+ private static EntityRegionAccessStrategy localAccessStrategy;
+
+ /**
+ * Create a new TransactionalAccessTestCase.
+ *
+ * @param name
+ */
+ public OptimisticReadOnlyExtraAPITestCase(String name) {
+ super(name);
+ }
+
+ @Override
+ protected AccessType getAccessType() {
+ return AccessType.READ_ONLY;
+ }
+
+ @Override
+ protected EntityRegionAccessStrategy getEntityAccessStrategy() {
+ return localAccessStrategy;
+ }
+
+ @Override
+ protected void setEntityRegionAccessStrategy(EntityRegionAccessStrategy strategy) {
+ localAccessStrategy = strategy;
+ }
+
+ /**
+ * Test method for {@link TransactionalAccess#lockItem(java.lang.Object, java.lang.Object)}.
+ */
+ @Override
+ public void testLockItem() {
+ try {
+ getEntityAccessStrategy().lockItem(KEY, new Integer(1));
+ fail("Call to lockItem did not throw exception");
+ }
+ catch (UnsupportedOperationException expected) {}
+ }
+
+ /**
+ * Test method for {@link TransactionalAccess#lockRegion()}.
+ */
+ @Override
+ public void testLockRegion() {
+ try {
+ getEntityAccessStrategy().lockRegion();
+ fail("Call to lockRegion did not throw exception");
+ }
+ catch (UnsupportedOperationException expected) {}
+ }
+
+ /**
+ * Test method for {@link TransactionalAccess#afterUpdate(java.lang.Object, java.lang.Object, java.lang.Object, java.lang.Object, org.hibernate.cache.access.SoftLock)}.
+ */
+ @Override
+ public void testAfterUpdate() {
+ try {
+ getEntityAccessStrategy().afterUpdate(KEY, VALUE2, new Integer(1), new Integer(2), new MockSoftLock());
+ fail("Call to afterUpdate did not throw exception");
+ }
+ catch (UnsupportedOperationException expected) {}
+ }
+
+}
Added: core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/entity/OptimisticReadOnlyTestCase.java
===================================================================
--- core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/entity/OptimisticReadOnlyTestCase.java (rev 0)
+++ core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/entity/OptimisticReadOnlyTestCase.java 2007-10-18 20:08:50 UTC (rev 14101)
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2007, Red Hat Middleware, LLC. All rights reserved.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, v. 2.1. This program is distributed in the
+ * hope that it will be useful, but WITHOUT A WARRANTY; without even the implied
+ * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details. You should have received a
+ * copy of the GNU Lesser General Public License, v.2.1 along with this
+ * distribution; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Red Hat Author(s): Brian Stansberry
+ */
+
+package org.hibernate.test.cache.jbc2.entity;
+
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+/**
+ * Tests READ_ONLY access when optimistic locking and invalidation are used.
+ *
+ * @author <a href="brian.stansberry(a)jboss.com">Brian Stansberry</a>
+ * @version $Revision: 1 $
+ */
+public class OptimisticReadOnlyTestCase extends AbstractReadOnlyAccessTestCase {
+
+ /**
+ * Create a new PessimisticTransactionalAccessTestCase.
+ *
+ * @param name
+ */
+ public OptimisticReadOnlyTestCase(String name) {
+ super(name);
+ }
+
+ public static Test suite() throws Exception {
+ TestSuite suite = createFailureExpectedSuite(OptimisticReadOnlyTestCase.class);
+ return getTestSetup(suite, "optimistic-entity");
+ }
+
+ @Override
+ public void testCacheConfiguration() {
+ assertTrue("Using Invalidation", isUsingInvalidation());
+ assertTrue("Using Optimistic locking", isUsingOptimisticLocking());
+ assertTrue("Synchronous mode", isSynchronous());
+ }
+
+ // Known failures
+
+ public void testEvictAllFailureExpected() {
+ super.testEvictAll();
+ }
+
+ public void testRemoveAllFailureExpected() {
+ super.testRemoveAll();
+ }
+
+}
Added: core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/entity/OptimisticReplicatedTransactionalTestCase.java
===================================================================
--- core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/entity/OptimisticReplicatedTransactionalTestCase.java (rev 0)
+++ core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/entity/OptimisticReplicatedTransactionalTestCase.java 2007-10-18 20:08:50 UTC (rev 14101)
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2007, Red Hat Middleware, LLC. All rights reserved.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, v. 2.1. This program is distributed in the
+ * hope that it will be useful, but WITHOUT A WARRANTY; without even the implied
+ * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details. You should have received a
+ * copy of the GNU Lesser General Public License, v.2.1 along with this
+ * distribution; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Red Hat Author(s): Brian Stansberry
+ */
+
+package org.hibernate.test.cache.jbc2.entity;
+
+import junit.framework.Test;
+
+/**
+ * Tests TRANSACTIONAL access when optimistic locking and replication are used.
+ *
+ * @author <a href="brian.stansberry(a)jboss.com">Brian Stansberry</a>
+ * @version $Revision: 1 $
+ */
+public class OptimisticReplicatedTransactionalTestCase extends AbstractTransactionalAccessTestCase {
+
+ /**
+ * Create a new PessimisticTransactionalAccessTestCase.
+ *
+ * @param name
+ */
+ public OptimisticReplicatedTransactionalTestCase(String name) {
+ super(name);
+ }
+
+ public static Test suite() throws Exception {
+ return getTestSetup(OptimisticReplicatedTransactionalTestCase.class, "optimistic-shared");
+ }
+
+ @Override
+ public void testCacheConfiguration() {
+ assertFalse("Using Invalidation", isUsingInvalidation());
+ assertTrue("Using Optimistic locking", isUsingOptimisticLocking());
+ assertTrue("Synchronous mode", isSynchronous());
+ }
+
+
+
+}
Added: core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/entity/OptimisticTransactionalExtraAPITestCase.java
===================================================================
--- core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/entity/OptimisticTransactionalExtraAPITestCase.java (rev 0)
+++ core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/entity/OptimisticTransactionalExtraAPITestCase.java 2007-10-18 20:08:50 UTC (rev 14101)
@@ -0,0 +1,161 @@
+/*
+ * Copyright (c) 2007, Red Hat Middleware, LLC. All rights reserved.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, v. 2.1. This program is distributed in the
+ * hope that it will be useful, but WITHOUT A WARRANTY; without even the implied
+ * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details. You should have received a
+ * copy of the GNU Lesser General Public License, v.2.1 along with this
+ * distribution; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Red Hat Author(s): Brian Stansberry
+ */
+
+package org.hibernate.test.cache.jbc2.entity;
+
+import org.hibernate.cache.EntityRegion;
+import org.hibernate.cache.access.AccessType;
+import org.hibernate.cache.access.EntityRegionAccessStrategy;
+import org.hibernate.cache.access.SoftLock;
+import org.hibernate.cache.jbc2.JBossCacheRegionFactory;
+import org.hibernate.cache.jbc2.MultiplexedJBossCacheRegionFactory;
+import org.hibernate.cache.jbc2.builder.MultiplexingCacheInstanceManager;
+import org.hibernate.cache.jbc2.entity.TransactionalAccess;
+import org.hibernate.cfg.Configuration;
+import org.hibernate.test.cache.jbc2.AbstractJBossCacheTestCase;
+import org.hibernate.test.util.CacheTestUtil;
+import org.jboss.cache.Cache;
+
+/**
+ * Tests for the "extra API" in EntityRegionAccessStrategy; in this base
+ * version using Optimistic locking with TRANSACTIONAL access.
+ * <p>
+ * By "extra API" we mean those methods that are superfluous to the
+ * function of the JBC integration, where the impl is a no-op or a static
+ * false return value, UnsupportedOperationException, etc.
+ *
+ * @author <a href="brian.stansberry(a)jboss.com">Brian Stansberry</a>
+ * @version $Revision: 1 $
+ */
+public class OptimisticTransactionalExtraAPITestCase extends AbstractJBossCacheTestCase {
+
+ public static final String REGION_NAME = "test/com.foo.test";
+ public static final String KEY = "KEY";
+ public static final String VALUE1 = "VALUE1";
+ public static final String VALUE2 = "VALUE2";
+
+ private static EntityRegionAccessStrategy localAccessStrategy;
+
+ private static boolean optimistic;
+
+ /**
+ * Create a new TransactionalAccessTestCase.
+ *
+ * @param name
+ */
+ public OptimisticTransactionalExtraAPITestCase(String name) {
+ super(name);
+ }
+
+ protected void setUp() throws Exception {
+ super.setUp();
+
+ if (getEntityAccessStrategy() == null) {
+ Configuration cfg = createConfiguration();
+ JBossCacheRegionFactory rf = CacheTestUtil.startRegionFactory(cfg, getCacheTestSupport());
+ Cache localCache = rf.getCacheInstanceManager().getEntityCacheInstance();
+ optimistic = localCache.getConfiguration().getNodeLockingScheme() == org.jboss.cache.config.Configuration.NodeLockingScheme.OPTIMISTIC;
+ EntityRegion localEntityRegion = rf.buildEntityRegion(REGION_NAME, cfg.getProperties(), null);
+ setEntityRegionAccessStrategy(localEntityRegion.buildAccessStrategy(getAccessType()));
+ }
+ }
+
+ protected void tearDown() throws Exception {
+
+ super.tearDown();
+ }
+
+ protected Configuration createConfiguration() {
+ Configuration cfg = CacheTestUtil.buildConfiguration(REGION_PREFIX, MultiplexedJBossCacheRegionFactory.class, true, false);
+ cfg.setProperty(MultiplexingCacheInstanceManager.ENTITY_CACHE_RESOURCE_PROP, getCacheConfigName());
+ return cfg;
+ }
+
+ protected String getCacheConfigName() {
+ return "optimistic-entity";
+ }
+
+ protected boolean isUsingOptimisticLocking() {
+ return optimistic;
+ }
+
+ protected AccessType getAccessType() {
+ return AccessType.TRANSACTIONAL;
+ }
+
+ protected EntityRegionAccessStrategy getEntityAccessStrategy() {
+ return localAccessStrategy;
+ }
+
+ protected void setEntityRegionAccessStrategy(EntityRegionAccessStrategy strategy) {
+ localAccessStrategy = strategy;
+ }
+
+ /**
+ * This is just a setup test where we assert that the cache config is
+ * as we expected.
+ */
+ public void testCacheConfiguration() {
+ assertTrue("Using Optimistic locking", isUsingOptimisticLocking());
+ }
+
+ /**
+ * Test method for {@link TransactionalAccess#lockItem(java.lang.Object, java.lang.Object)}.
+ */
+ public void testLockItem() {
+ assertNull(getEntityAccessStrategy().lockItem(KEY, new Integer(1)));
+ }
+
+ /**
+ * Test method for {@link TransactionalAccess#lockRegion()}.
+ */
+ public void testLockRegion() {
+ assertNull(getEntityAccessStrategy().lockRegion());
+ }
+
+ /**
+ * Test method for {@link TransactionalAccess#unlockItem(java.lang.Object, org.hibernate.cache.access.SoftLock)}.
+ */
+ public void testUnlockItem() {
+ getEntityAccessStrategy().unlockItem(KEY, new MockSoftLock());
+ }
+
+ /**
+ * Test method for {@link TransactionalAccess#unlockRegion(org.hibernate.cache.access.SoftLock)}.
+ */
+ public void testUnlockRegion() {
+ getEntityAccessStrategy().unlockItem(KEY, new MockSoftLock());
+ }
+
+ /**
+ * Test method for {@link TransactionalAccess#afterInsert(java.lang.Object, java.lang.Object, java.lang.Object)}.
+ */
+ public void testAfterInsert() {
+ assertFalse("afterInsert always returns false", getEntityAccessStrategy().afterInsert(KEY, VALUE1, new Integer(1)));
+ }
+
+ /**
+ * Test method for {@link TransactionalAccess#afterUpdate(java.lang.Object, java.lang.Object, java.lang.Object, java.lang.Object, org.hibernate.cache.access.SoftLock)}.
+ */
+ public void testAfterUpdate() {
+ assertFalse("afterInsert always returns false", getEntityAccessStrategy().afterUpdate(KEY, VALUE2, new Integer(1), new Integer(2), new MockSoftLock()));
+ }
+
+ public static class MockSoftLock implements SoftLock {
+
+ }
+
+}
Added: core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/entity/PessimisticInvalidatedTransactionalTestCase.java
===================================================================
--- core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/entity/PessimisticInvalidatedTransactionalTestCase.java (rev 0)
+++ core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/entity/PessimisticInvalidatedTransactionalTestCase.java 2007-10-18 20:08:50 UTC (rev 14101)
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2007, Red Hat Middleware, LLC. All rights reserved.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, v. 2.1. This program is distributed in the
+ * hope that it will be useful, but WITHOUT A WARRANTY; without even the implied
+ * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details. You should have received a
+ * copy of the GNU Lesser General Public License, v.2.1 along with this
+ * distribution; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Red Hat Author(s): Brian Stansberry
+ */
+
+package org.hibernate.test.cache.jbc2.entity;
+
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+/**
+ * Tests TRANSACTIONAL access when pessimistic locking and invalidation are used.
+ *
+ * @author <a href="brian.stansberry(a)jboss.com">Brian Stansberry</a>
+ * @version $Revision: 1 $
+ */
+public class PessimisticInvalidatedTransactionalTestCase extends AbstractTransactionalAccessTestCase {
+
+ /**
+ * Create a new PessimisticTransactionalAccessTestCase.
+ *
+ * @param name
+ */
+ public PessimisticInvalidatedTransactionalTestCase(String name) {
+ super(name);
+ }
+
+ public static Test suite() throws Exception {
+ TestSuite suite = createFailureExpectedSuite(PessimisticInvalidatedTransactionalTestCase.class);
+ return getTestSetup(suite, "pessimistic-entity");
+ }
+
+ // Known failures
+
+ public void testEvictAllFailureExpected() {
+ super.testEvictAll();
+ }
+
+ public void testRemoveAllFailureExpected() {
+ super.testRemoveAll();
+ }
+
+ // Overrides
+
+ @Override
+ public void testCacheConfiguration() {
+ assertTrue("Using Invalidation", isUsingInvalidation());
+ assertFalse("Using Optimistic locking", isUsingOptimisticLocking());
+ assertTrue("Synchronous mode", isSynchronous());
+ }
+
+}
Added: core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/entity/PessimisticReadOnlyExtraAPITestCase.java
===================================================================
--- core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/entity/PessimisticReadOnlyExtraAPITestCase.java (rev 0)
+++ core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/entity/PessimisticReadOnlyExtraAPITestCase.java 2007-10-18 20:08:50 UTC (rev 14101)
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2007, Red Hat Middleware, LLC. All rights reserved.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, v. 2.1. This program is distributed in the
+ * hope that it will be useful, but WITHOUT A WARRANTY; without even the implied
+ * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details. You should have received a
+ * copy of the GNU Lesser General Public License, v.2.1 along with this
+ * distribution; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Red Hat Author(s): Brian Stansberry
+ */
+
+package org.hibernate.test.cache.jbc2.entity;
+
+import org.hibernate.cache.access.EntityRegionAccessStrategy;
+
+/**
+ * Tests for the "extra API" in EntityRegionAccessStrategy; in this
+ * version using pessimistic locking with READ_ONLY access.
+ * <p>
+ * By "extra API" we mean those methods that are superfluous to the
+ * function of the JBC integration, where the impl is a no-op or a static
+ * false return value, UnsupportedOperationException, etc.
+ *
+ * @author <a href="brian.stansberry(a)jboss.com">Brian Stansberry</a>
+ * @version $Revision: 1 $
+ */
+public class PessimisticReadOnlyExtraAPITestCase extends OptimisticReadOnlyExtraAPITestCase {
+
+ private static EntityRegionAccessStrategy localAccessStrategy;
+
+ /**
+ * Create a new PessimisticAccessStrategyExtraAPITestCase.
+ *
+ * @param name
+ */
+ public PessimisticReadOnlyExtraAPITestCase(String name) {
+ super(name);
+ }
+
+ @Override
+ protected String getCacheConfigName() {
+ return "pessimistic-entity";
+ }
+
+ @Override
+ protected EntityRegionAccessStrategy getEntityAccessStrategy() {
+ return localAccessStrategy;
+ }
+
+ @Override
+ protected void setEntityRegionAccessStrategy(EntityRegionAccessStrategy strategy) {
+ localAccessStrategy = strategy;
+ }
+
+ @Override
+ public void testCacheConfiguration() {
+ assertFalse("Using Optimistic locking", isUsingOptimisticLocking());
+ }
+
+}
Added: core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/entity/PessimisticReadOnlyTestCase.java
===================================================================
--- core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/entity/PessimisticReadOnlyTestCase.java (rev 0)
+++ core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/entity/PessimisticReadOnlyTestCase.java 2007-10-18 20:08:50 UTC (rev 14101)
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2007, Red Hat Middleware, LLC. All rights reserved.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, v. 2.1. This program is distributed in the
+ * hope that it will be useful, but WITHOUT A WARRANTY; without even the implied
+ * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details. You should have received a
+ * copy of the GNU Lesser General Public License, v.2.1 along with this
+ * distribution; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Red Hat Author(s): Brian Stansberry
+ */
+
+package org.hibernate.test.cache.jbc2.entity;
+
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+import org.hibernate.cache.access.AccessType;
+
+/**
+ * Tests READ_ONLY access when pessimistic locking and invalidation are used.
+ *
+ * @author <a href="brian.stansberry(a)jboss.com">Brian Stansberry</a>
+ * @version $Revision: 1 $
+ */
+public class PessimisticReadOnlyTestCase extends AbstractReadOnlyAccessTestCase {
+
+ /**
+ * Create a new PessimisticTransactionalAccessTestCase.
+ *
+ * @param name
+ */
+ public PessimisticReadOnlyTestCase(String name) {
+ super(name);
+ }
+
+ public static Test suite() throws Exception {
+ TestSuite suite = createFailureExpectedSuite(PessimisticReadOnlyTestCase.class);
+ return getTestSetup(suite, "pessimistic-entity");
+ }
+
+ // Known failures
+
+ public void testEvictAllFailureExpected() {
+ super.testEvictAll();
+ }
+
+ public void testRemoveAllFailureExpected() {
+ super.testRemoveAll();
+ }
+
+ // Overrides
+
+
+ @Override
+ public void testCacheConfiguration() {
+ assertTrue("Using Invalidation", isUsingInvalidation());
+ assertFalse("Using Optimistic locking", isUsingOptimisticLocking());
+ }
+
+
+}
Added: core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/entity/PessimisticReplicatedTransactionalTestCase.java
===================================================================
--- core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/entity/PessimisticReplicatedTransactionalTestCase.java (rev 0)
+++ core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/entity/PessimisticReplicatedTransactionalTestCase.java 2007-10-18 20:08:50 UTC (rev 14101)
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2007, Red Hat Middleware, LLC. All rights reserved.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, v. 2.1. This program is distributed in the
+ * hope that it will be useful, but WITHOUT A WARRANTY; without even the implied
+ * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details. You should have received a
+ * copy of the GNU Lesser General Public License, v.2.1 along with this
+ * distribution; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Red Hat Author(s): Brian Stansberry
+ */
+
+package org.hibernate.test.cache.jbc2.entity;
+
+import junit.framework.Test;
+
+/**
+ * Tests TRANSACTIONAL access when pessimistic locking and replication are used.
+ *
+ * @author <a href="brian.stansberry(a)jboss.com">Brian Stansberry</a>
+ * @version $Revision: 1 $
+ */
+public class PessimisticReplicatedTransactionalTestCase extends AbstractTransactionalAccessTestCase {
+
+ /**
+ * Create a new PessimisticTransactionalAccessTestCase.
+ *
+ * @param name
+ */
+ public PessimisticReplicatedTransactionalTestCase(String name) {
+ super(name);
+ }
+
+ public static Test suite() throws Exception {
+ return getTestSetup(PessimisticReplicatedTransactionalTestCase.class, "pessimistic-shared");
+ }
+
+ @Override
+ public void testCacheConfiguration() {
+ assertFalse("Using Invalidation", isUsingInvalidation());
+ assertFalse("Using Optimistic locking", isUsingOptimisticLocking());
+ assertTrue("Synchronous mode", isSynchronous());
+ }
+
+
+
+}
Added: core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/entity/PessimisticTransactionalExtraAPITestCase.java
===================================================================
--- core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/entity/PessimisticTransactionalExtraAPITestCase.java (rev 0)
+++ core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/entity/PessimisticTransactionalExtraAPITestCase.java 2007-10-18 20:08:50 UTC (rev 14101)
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2007, Red Hat Middleware, LLC. All rights reserved.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, v. 2.1. This program is distributed in the
+ * hope that it will be useful, but WITHOUT A WARRANTY; without even the implied
+ * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details. You should have received a
+ * copy of the GNU Lesser General Public License, v.2.1 along with this
+ * distribution; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Red Hat Author(s): Brian Stansberry
+ */
+
+package org.hibernate.test.cache.jbc2.entity;
+
+import org.hibernate.cache.access.EntityRegionAccessStrategy;
+
+/**
+ * Tests for the "extra API" in EntityRegionAccessStrategy; in this base
+ * version using Optimistic locking with TRANSACTIONAL access.
+ * <p>
+ * By "extra API" we mean those methods that are superfluous to the
+ * function of the JBC integration, where the impl is a no-op or a static
+ * false return value, UnsupportedOperationException, etc.
+ *
+ * @author <a href="brian.stansberry(a)jboss.com">Brian Stansberry</a>
+ * @version $Revision: 1 $
+ */
+public class PessimisticTransactionalExtraAPITestCase extends OptimisticTransactionalExtraAPITestCase {
+
+ private static EntityRegionAccessStrategy localAccessStrategy;
+
+ /**
+ * Create a new PessimisticAccessStrategyExtraAPITestCase.
+ *
+ * @param name
+ */
+ public PessimisticTransactionalExtraAPITestCase(String name) {
+ super(name);
+ }
+
+ @Override
+ protected String getCacheConfigName() {
+ return "pessimistic-entity";
+ }
+
+ @Override
+ protected EntityRegionAccessStrategy getEntityAccessStrategy() {
+ return localAccessStrategy;
+ }
+
+ @Override
+ protected void setEntityRegionAccessStrategy(EntityRegionAccessStrategy strategy) {
+ localAccessStrategy = strategy;
+ }
+
+ @Override
+ public void testCacheConfiguration() {
+ assertFalse("Using Optimistic locking", isUsingOptimisticLocking());
+ }
+
+}
Added: core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/functional/AbstractEntityCacheFunctionalTestCase.java
===================================================================
--- core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/functional/AbstractEntityCacheFunctionalTestCase.java (rev 0)
+++ core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/functional/AbstractEntityCacheFunctionalTestCase.java 2007-10-18 20:08:50 UTC (rev 14101)
@@ -0,0 +1,103 @@
+package org.hibernate.test.cache.jbc2.functional;
+
+import java.util.Map;
+
+import org.hibernate.Session;
+import org.hibernate.Transaction;
+import org.hibernate.cache.ReadWriteCache;
+import org.hibernate.stat.SecondLevelCacheStatistics;
+import org.hibernate.stat.Statistics;
+
+/**
+ * Common requirement entity caching testing for each
+ * {@link org.hibernate.cache.RegionFactory} impl.
+ *
+ * @author Steve Ebersole
+ */
+public abstract class AbstractEntityCacheFunctionalTestCase extends CacheTestCaseBase {
+
+ // note that a lot of the functionality here is intended to be used
+ // in creating specific tests for each CacheProvider that would extend
+ // from a base test case (this) for common requirement testing...
+
+ public AbstractEntityCacheFunctionalTestCase(String x) {
+ super(x);
+ }
+
+ @Override
+ protected boolean getUseQueryCache() {
+ return false;
+ }
+
+ public void testEmptySecondLevelCacheEntry() throws Exception {
+ getSessions().evictEntity(Item.class.getName());
+ Statistics stats = getSessions().getStatistics();
+ stats.clear();
+ SecondLevelCacheStatistics statistics = stats.getSecondLevelCacheStatistics(Item.class.getName());
+ Map cacheEntries = statistics.getEntries();
+ assertEquals(0, cacheEntries.size());
+ }
+
+ public void testStaleWritesLeaveCacheConsistent() {
+ Session s = openSession();
+ Transaction txn = s.beginTransaction();
+ VersionedItem item = new VersionedItem();
+ item.setName("steve");
+ item.setDescription("steve's item");
+ s.save(item);
+ txn.commit();
+ s.close();
+
+ Long initialVersion = item.getVersion();
+
+ // manually revert the version property
+ item.setVersion(new Long(item.getVersion().longValue() - 1));
+
+ try {
+ s = openSession();
+ txn = s.beginTransaction();
+ s.update(item);
+ txn.commit();
+ s.close();
+ fail("expected stale write to fail");
+ } catch (Throwable expected) {
+ // expected behavior here
+ if (txn != null) {
+ try {
+ txn.rollback();
+ } catch (Throwable ignore) {
+ }
+ }
+ } finally {
+ if (s != null && s.isOpen()) {
+ try {
+ s.close();
+ } catch (Throwable ignore) {
+ }
+ }
+ }
+
+ // check the version value in the cache...
+ SecondLevelCacheStatistics slcs = sfi().getStatistics().getSecondLevelCacheStatistics(
+ VersionedItem.class.getName());
+
+ Object entry = slcs.getEntries().get(item.getId());
+ Long cachedVersionValue;
+ if (entry instanceof ReadWriteCache.Lock) {
+ // FIXME don't know what to test here
+ cachedVersionValue = new Long(((ReadWriteCache.Lock) entry).getUnlockTimestamp());
+ } else {
+ cachedVersionValue = (Long) ((Map) entry).get("_version");
+ assertEquals(initialVersion.longValue(), cachedVersionValue.longValue());
+ }
+
+ // cleanup
+ s = openSession();
+ txn = s.beginTransaction();
+ item = (VersionedItem) s.load(VersionedItem.class, item.getId());
+ s.delete(item);
+ txn.commit();
+ s.close();
+
+ }
+}
Added: core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/functional/AbstractQueryCacheFunctionalTestCase.java
===================================================================
--- core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/functional/AbstractQueryCacheFunctionalTestCase.java (rev 0)
+++ core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/functional/AbstractQueryCacheFunctionalTestCase.java 2007-10-18 20:08:50 UTC (rev 14101)
@@ -0,0 +1,97 @@
+/*
+ * Copyright (c) 2007, Red Hat Middleware, LLC. All rights reserved.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, v. 2.1. This program is distributed in the
+ * hope that it will be useful, but WITHOUT A WARRANTY; without even the implied
+ * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details. You should have received a
+ * copy of the GNU Lesser General Public License, v.2.1 along with this
+ * distribution; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Red Hat Author(s): Brian Stansberry
+ */
+
+package org.hibernate.test.cache.jbc2.functional;
+
+import java.util.Map;
+
+import org.hibernate.Session;
+import org.hibernate.Transaction;
+import org.hibernate.cache.ReadWriteCache;
+import org.hibernate.stat.SecondLevelCacheStatistics;
+
+/**
+ * A QueryCacheEnabledCacheProviderTestCase.
+ *
+ * @author <a href="brian.stansberry(a)jboss.com">Brian Stansberry</a>
+ * @version $Revision: 1 $
+ */
+public abstract class AbstractQueryCacheFunctionalTestCase extends AbstractEntityCacheFunctionalTestCase {
+
+ /**
+ * Create a new QueryCacheEnabledCacheProviderTestCase.
+ *
+ * @param x
+ */
+ public AbstractQueryCacheFunctionalTestCase(String x) {
+ super(x);
+ }
+
+ @Override
+ protected boolean getUseQueryCache() {
+ return true;
+ }
+
+ public void testQueryCacheInvalidation() {
+ Session s = openSession();
+ Transaction t = s.beginTransaction();
+ Item i = new Item();
+ i.setName("widget");
+ i.setDescription("A really top-quality, full-featured widget.");
+ s.persist(i);
+ t.commit();
+ s.close();
+
+ SecondLevelCacheStatistics slcs = s.getSessionFactory().getStatistics().getSecondLevelCacheStatistics(
+ Item.class.getName());
+
+ assertEquals(slcs.getPutCount(), 1);
+ assertEquals(slcs.getElementCountInMemory(), 1);
+ assertEquals(slcs.getEntries().size(), 1);
+
+ s = openSession();
+ t = s.beginTransaction();
+ i = (Item) s.get(Item.class, i.getId());
+
+ assertEquals(slcs.getHitCount(), 1);
+ assertEquals(slcs.getMissCount(), 0);
+
+ i.setDescription("A bog standard item");
+
+ t.commit();
+ s.close();
+
+ assertEquals(slcs.getPutCount(), 2);
+
+ Object entry = slcs.getEntries().get(i.getId());
+ Map map;
+ if (entry instanceof ReadWriteCache.Item) {
+ map = (Map) ((ReadWriteCache.Item) entry).getValue();
+ } else {
+ map = (Map) entry;
+ }
+ assertTrue(map.get("description").equals("A bog standard item"));
+ assertTrue(map.get("name").equals("widget"));
+
+ // cleanup
+ s = openSession();
+ t = s.beginTransaction();
+ s.delete(i);
+ t.commit();
+ s.close();
+ }
+
+}
Property changes on: core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/functional/AbstractQueryCacheFunctionalTestCase.java
___________________________________________________________________
Name: svn:executable
+ *
Added: core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/functional/CacheTestCaseBase.java
===================================================================
--- core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/functional/CacheTestCaseBase.java (rev 0)
+++ core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/functional/CacheTestCaseBase.java 2007-10-18 20:08:50 UTC (rev 14101)
@@ -0,0 +1,81 @@
+package org.hibernate.test.cache.jbc2.functional;
+
+import org.hibernate.cache.RegionFactory;
+import org.hibernate.cfg.Configuration;
+import org.hibernate.cfg.Environment;
+import org.hibernate.junit.functional.FunctionalTestCase;
+import org.hibernate.test.tm.DummyConnectionProvider;
+import org.hibernate.test.tm.DummyTransactionManagerLookup;
+
+/**
+ * Provides common configuration setups for cache testing.
+ *
+ * @author Brian Stansberry
+ */
+public abstract class CacheTestCaseBase extends FunctionalTestCase {
+
+ // note that a lot of the functionality here is intended to be used
+ // in creating specific tests for each CacheProvider that would extend
+ // from a base test case (this) for common requirement testing...
+
+ public CacheTestCaseBase(String x) {
+ super(x);
+ }
+
+ public String[] getMappings() {
+ return new String[] { "cache/jbc2/functional/Item.hbm.xml" };
+ }
+
+ public void configure(Configuration cfg) {
+ super.configure(cfg);
+
+ cfg.setProperty(Environment.CACHE_REGION_PREFIX, "test");
+ cfg.setProperty(Environment.USE_SECOND_LEVEL_CACHE, "true");
+ cfg.setProperty(Environment.GENERATE_STATISTICS, "true");
+ cfg.setProperty(Environment.USE_STRUCTURED_CACHE, "true");
+ cfg.setProperty(Environment.CACHE_REGION_FACTORY, getCacheRegionFactory().getName());
+
+ cfg.setProperty(Environment.USE_QUERY_CACHE, String.valueOf(getUseQueryCache()));
+ cfg.setProperty(Environment.CONNECTION_PROVIDER, DummyConnectionProvider.class.getName());
+ cfg.setProperty(Environment.TRANSACTION_MANAGER_STRATEGY, DummyTransactionManagerLookup.class.getName());
+
+ configureCacheFactory(cfg);
+ }
+
+ public String getCacheConcurrencyStrategy() {
+ return "transactional";
+ }
+
+ /**
+ * The cache provider to be tested.
+ *
+ * @return The cache provider.
+ */
+ protected void configureCacheFactory(Configuration cfg) {
+ if (getConfigResourceKey() != null) {
+ cfg.setProperty(getConfigResourceKey(), getConfigResourceLocation());
+ }
+ }
+
+ protected abstract Class<? extends RegionFactory> getCacheRegionFactory();
+
+ protected abstract boolean getUseQueryCache();
+
+ /**
+ * For provider-specific configuration, the name of the property key the
+ * provider expects.
+ *
+ * @return The provider-specific config key.
+ */
+ protected String getConfigResourceKey() {
+ return Environment.CACHE_REGION_FACTORY;
+ }
+
+ /**
+ * For provider-specific configuration, the resource location of that config
+ * resource.
+ *
+ * @return The config resource location.
+ */
+ protected abstract String getConfigResourceLocation();
+}
Property changes on: core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/functional/CacheTestCaseBase.java
___________________________________________________________________
Name: svn:executable
+ *
Added: core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/functional/Item.hbm.xml
===================================================================
--- core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/functional/Item.hbm.xml (rev 0)
+++ core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/functional/Item.hbm.xml 2007-10-18 20:08:50 UTC (rev 14101)
@@ -0,0 +1,26 @@
+<?xml version="1.0"?>
+<!DOCTYPE hibernate-mapping PUBLIC
+ "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
+ "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
+
+<hibernate-mapping
+ package="org.hibernate.test.cache.jbc2.functional">
+
+ <class name="Item" table="Items">
+ <id name="id">
+ <generator class="increment"/>
+ </id>
+ <property name="name" not-null="true"/>
+ <property name="description" not-null="true"/>
+ </class>
+
+ <class name="VersionedItem" table="VersionedItems">
+ <id name="id">
+ <generator class="increment"/>
+ </id>
+ <version name="version" type="long"/>
+ <property name="name" not-null="true"/>
+ <property name="description" not-null="true"/>
+ </class>
+
+</hibernate-mapping>
Property changes on: core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/functional/Item.hbm.xml
___________________________________________________________________
Name: svn:executable
+ *
Added: core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/functional/Item.java
===================================================================
--- core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/functional/Item.java (rev 0)
+++ core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/functional/Item.java 2007-10-18 20:08:50 UTC (rev 14101)
@@ -0,0 +1,35 @@
+//$Id: Item.java 5686 2005-02-12 07:27:32Z steveebersole $
+package org.hibernate.test.cache.jbc2.functional;
+
+/**
+ * @author Gavin King
+ */
+public class Item {
+ private Long id;
+ private String name;
+ private String description;
+
+ public String getDescription() {
+ return description;
+ }
+
+ public void setDescription(String description) {
+ this.description = description;
+ }
+
+ public Long getId() {
+ return id;
+ }
+
+ public void setId(Long id) {
+ this.id = id;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+}
Property changes on: core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/functional/Item.java
___________________________________________________________________
Name: svn:executable
+ *
Added: core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/functional/OptimisticJBossCacheTestDisabled.java
===================================================================
--- core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/functional/OptimisticJBossCacheTestDisabled.java (rev 0)
+++ core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/functional/OptimisticJBossCacheTestDisabled.java 2007-10-18 20:08:50 UTC (rev 14101)
@@ -0,0 +1,41 @@
+package org.hibernate.test.cache.jbc2.functional;
+
+import junit.framework.Test;
+
+import org.hibernate.cache.RegionFactory;
+import org.hibernate.cache.jbc2.JBossCacheRegionFactory;
+import org.hibernate.cache.jbc2.builder.SharedCacheInstanceManager;
+import org.hibernate.junit.functional.FunctionalTestClassTestSuite;
+
+/**
+ * FIXME Move to hibernate-testsuite project and rename class x- "Disabled"
+ *
+ * @author Brian Stansberry
+ */
+public class OptimisticJBossCacheTestDisabled extends AbstractQueryCacheFunctionalTestCase {
+
+ // note that a lot of the fucntionality here is intended to be used
+ // in creating specific tests for each CacheProvider that would extend
+ // from a base test case (this) for common requirement testing...
+
+ public OptimisticJBossCacheTestDisabled(String x) {
+ super(x);
+ }
+
+ public static Test suite() {
+ return new FunctionalTestClassTestSuite(OptimisticJBossCacheTestDisabled.class);
+ }
+
+ protected Class<? extends RegionFactory> getCacheRegionFactory() {
+ return JBossCacheRegionFactory.class;
+ }
+
+ protected String getConfigResourceKey() {
+ return SharedCacheInstanceManager.CACHE_RESOURCE_PROP;
+ }
+
+ protected String getConfigResourceLocation() {
+ return "org/hibernate/test/cache/jbc2/functional/optimistic-treecache.xml";
+ }
+
+}
Property changes on: core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/functional/OptimisticJBossCacheTestDisabled.java
___________________________________________________________________
Name: svn:executable
+ *
Added: core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/functional/PessimisticJBossCacheTestDisabled.java
===================================================================
--- core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/functional/PessimisticJBossCacheTestDisabled.java (rev 0)
+++ core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/functional/PessimisticJBossCacheTestDisabled.java 2007-10-18 20:08:50 UTC (rev 14101)
@@ -0,0 +1,41 @@
+package org.hibernate.test.cache.jbc2.functional;
+
+import junit.framework.Test;
+
+import org.hibernate.cache.RegionFactory;
+import org.hibernate.cache.jbc2.JBossCacheRegionFactory;
+import org.hibernate.cache.jbc2.builder.SharedCacheInstanceManager;
+import org.hibernate.junit.functional.FunctionalTestClassTestSuite;
+
+/**
+ * FIXME Move to hibernate-testsuite project and rename class x- "Disabled"
+ *
+ * @author Brian Stansberry
+ */
+public class PessimisticJBossCacheTestDisabled extends AbstractQueryCacheFunctionalTestCase {
+
+ // note that a lot of the fucntionality here is intended to be used
+ // in creating specific tests for each CacheProvider that would extend
+ // from a base test case (this) for common requirement testing...
+
+ public PessimisticJBossCacheTestDisabled(String x) {
+ super(x);
+ }
+
+ public static Test suite() {
+ return new FunctionalTestClassTestSuite(PessimisticJBossCacheTestDisabled.class);
+ }
+
+ protected Class<? extends RegionFactory> getCacheRegionFactory() {
+ return JBossCacheRegionFactory.class;
+ }
+
+ protected String getConfigResourceKey() {
+ return SharedCacheInstanceManager.CACHE_RESOURCE_PROP;
+ }
+
+ protected String getConfigResourceLocation() {
+ return "org/hibernate/test/cache/jbc2/functional/pessimistic-treecache.xml";
+ }
+
+}
Property changes on: core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/functional/PessimisticJBossCacheTestDisabled.java
___________________________________________________________________
Name: svn:executable
+ *
Added: core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/functional/VersionedItem.java
===================================================================
--- core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/functional/VersionedItem.java (rev 0)
+++ core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/functional/VersionedItem.java 2007-10-18 20:08:50 UTC (rev 14101)
@@ -0,0 +1,16 @@
+package org.hibernate.test.cache.jbc2.functional;
+
+/**
+ * @author Steve Ebersole
+ */
+public class VersionedItem extends Item {
+ private Long version;
+
+ public Long getVersion() {
+ return version;
+ }
+
+ public void setVersion(Long version) {
+ this.version = version;
+ }
+}
Property changes on: core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/functional/VersionedItem.java
___________________________________________________________________
Name: svn:executable
+ *
Added: core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/functional/optimistic-treecache.xml
===================================================================
--- core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/functional/optimistic-treecache.xml (rev 0)
+++ core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/functional/optimistic-treecache.xml 2007-10-18 20:08:50 UTC (rev 14101)
@@ -0,0 +1,138 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!-- ===================================================================== -->
+<!-- -->
+<!-- Sample JBoss Cache Service Configuration -->
+<!-- Recommended for use as Hibernate's 2nd Level Cache -->
+<!-- For use with JBossCache >= 2.0.0 ONLY!!! -->
+<!-- -->
+<!-- ===================================================================== -->
+
+<server>
+
+ <classpath codebase="./lib" archives="jboss-cache.jar, jgroups.jar"/>
+
+
+ <!-- ==================================================================== -->
+ <!-- Defines TreeCache configuration -->
+ <!-- ==================================================================== -->
+
+ <mbean code="org.jboss.cache.jmx.CacheJmxWrapper"
+ name="jboss.cache:service=TreeCache">
+
+ <depends>jboss:service=Naming</depends>
+ <depends>jboss:service=TransactionManager</depends>
+
+ <!--
+ TransactionManager configuration not required for Hibernate!
+ Hibernate will plug in its own transaction manager integration.
+ -->
+
+
+ <!--
+ Node locking scheme:
+ OPTIMISTIC
+ PESSIMISTIC (default)
+ -->
+ <attribute name="NodeLockingScheme">OPTIMISTIC</attribute>
+
+ <!--
+ Note that this attribute is IGNORED if your NodeLockingScheme above is OPTIMISTIC.
+
+ Isolation level : SERIALIZABLE
+ REPEATABLE_READ (default)
+ READ_COMMITTED
+ READ_UNCOMMITTED
+ NONE
+ -->
+ <attribute name="IsolationLevel">REPEATABLE_READ</attribute>
+
+ <!--
+ Valid modes are LOCAL
+ REPL_ASYNC
+ REPL_SYNC
+ INVALIDATION_ASYNC
+ INVALIDATION_SYNC
+
+ INVALIDATION_ASYNC is highly recommended as the mode for use
+ with clustered second-level caches.
+ -->
+ <attribute name="CacheMode">REPL_SYNC</attribute>
+
+ <!-- Name of cluster. Needs to be the same for all clusters, in order
+ to find each other
+ -->
+ <attribute name="ClusterName">TreeCache-Cluster</attribute>
+
+ <attribute name="ClusterConfig">
+ <config>
+ <!-- UDP: if you have a multihomed machine,
+ set the bind_addr attribute to the appropriate NIC IP address -->
+ <!-- UDP: On Windows machines, because of the media sense feature
+ being broken with multicast (even after disabling media sense)
+ set the loopback attribute to true -->
+ <UDP mcast_addr="228.1.2.3" mcast_port="48866"
+ ip_ttl="64" ip_mcast="true"
+ mcast_send_buf_size="150000" mcast_recv_buf_size="80000"
+ ucast_send_buf_size="150000" ucast_recv_buf_size="80000"
+ loopback="false"/>
+ <PING timeout="2000" num_initial_members="3"/>
+ <MERGE2 min_interval="10000" max_interval="20000"/>
+ <FD shun="true"/>
+ <FD_SOCK/>
+ <VERIFY_SUSPECT timeout="1500"/>
+ <pbcast.NAKACK gc_lag="50" retransmit_timeout="600,1200,2400,4800"
+ max_xmit_size="8192"/>
+ <UNICAST timeout="600,1200,2400" window_size="100" min_threshold="10"/>
+ <pbcast.STABLE desired_avg_gossip="20000"/>
+ <FRAG frag_size="8192"/>
+ <pbcast.GMS join_timeout="5000" join_retry_timeout="2000"
+ shun="true" print_local_addr="true"/>
+ <pbcast.STATE_TRANSFER/>
+ </config>
+ </attribute>
+
+ <!--
+ Whether or not to fetch state on joining a cluster
+ NOTE this used to be called FetchStateOnStartup and has been renamed to be more descriptive.
+ -->
+ <attribute name="FetchInMemoryState">false</attribute>
+
+ <!--
+ Number of milliseconds to wait until all responses for a
+ synchronous call have been received.
+ -->
+ <attribute name="SyncReplTimeout">20000</attribute>
+
+ <!-- Max number of milliseconds to wait for a lock acquisition -->
+ <attribute name="LockAcquisitionTimeout">15000</attribute>
+
+ <!--
+ Indicate whether to use marshalling or not. Set this to true if you are running under a scoped
+ class loader, e.g., inside an application server. Default is "false".
+ -->
+ <attribute name="UseRegionBasedMarshalling">true</attribute>
+ <!-- Must match the value of "useRegionBasedMarshalling" -->
+ <attribute name="InactiveOnStartup">true</attribute>
+
+ <!-- Specific eviction policy configurations. This is LRU -->
+ <attribute name="EvictionPolicyConfig">
+ <config>
+ <attribute name="wakeUpIntervalSeconds">5</attribute>
+ <!-- Name of the DEFAULT eviction policy class. -->
+ <attribute name="policyClass">org.jboss.cache.eviction.LRUPolicy</attribute>
+ <!-- Cache wide default -->
+ <region name="/_default_">
+ <attribute name="maxNodes">5000</attribute>
+ <attribute name="timeToLiveSeconds">1000</attribute>
+ </region>
+ <!-- Don't ever evict modification timestamps -->
+ <region name="/TS">
+ <attribute name="maxNodes">0</attribute>
+ <attribute name="timeToLiveSeconds">0</attribute>
+ </region>
+ </config>
+ </attribute>
+
+ </mbean>
+</server>
Property changes on: core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/functional/optimistic-treecache.xml
___________________________________________________________________
Name: svn:executable
+ *
Added: core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/functional/pessimistic-treecache.xml
===================================================================
--- core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/functional/pessimistic-treecache.xml (rev 0)
+++ core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/functional/pessimistic-treecache.xml 2007-10-18 20:08:50 UTC (rev 14101)
@@ -0,0 +1,118 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!-- ===================================================================== -->
+<!-- -->
+<!-- Sample TreeCache Service Configuration -->
+<!-- -->
+<!-- ===================================================================== -->
+
+<server>
+
+ <classpath codebase="./lib" archives="jboss-cache.jar, jgroups.jar"/>
+
+
+ <!-- ==================================================================== -->
+ <!-- Defines TreeCache configuration -->
+ <!-- ==================================================================== -->
+
+ <mbean code="org.jboss.cache.jmx.CacheJmxWrapper"
+ name="jboss.cache:service=TreeCache">
+
+ <depends>jboss:service=Naming</depends>
+ <depends>jboss:service=TransactionManager</depends>
+
+ <!--
+ TransactionManager configuration not required for Hibernate!
+ Hibernate will plug in its own transaction manager integration.
+ -->
+
+ <!--
+ Node isolation level : SERIALIZABLE
+ REPEATABLE_READ (default)
+ READ_COMMITTED
+ READ_UNCOMMITTED
+ NONE
+ -->
+ <attribute name="IsolationLevel">REPEATABLE_READ</attribute>
+
+ <!--
+ Valid modes are LOCAL
+ REPL_ASYNC
+ REPL_SYNC
+ -->
+ <attribute name="CacheMode">LOCAL</attribute>
+
+ <!-- Name of cluster. Needs to be the same for all clusters, in order
+ to find each other
+ -->
+ <attribute name="ClusterName">TreeCache-Cluster</attribute>
+
+ <attribute name="ClusterConfig">
+ <config>
+ <!-- UDP: if you have a multihomed machine,
+ set the bind_addr attribute to the appropriate NIC IP address -->
+ <!-- UDP: On Windows machines, because of the media sense feature
+ being broken with multicast (even after disabling media sense)
+ set the loopback attribute to true -->
+ <UDP mcast_addr="228.1.2.3" mcast_port="45566"
+ ip_ttl="64" ip_mcast="true"
+ mcast_send_buf_size="150000" mcast_recv_buf_size="80000"
+ ucast_send_buf_size="150000" ucast_recv_buf_size="80000"
+ loopback="false"/>
+ <PING timeout="2000" num_initial_members="3"/>
+ <MERGE2 min_interval="10000" max_interval="20000"/>
+ <FD shun="true"/>
+ <VERIFY_SUSPECT timeout="1500"/>
+ <pbcast.NAKACK gc_lag="50" retransmit_timeout="600,1200,2400,4800"/>
+ <pbcast.STABLE desired_avg_gossip="20000"/>
+ <UNICAST timeout="600,1200,2400" window_size="100" min_threshold="10"/>
+ <FRAG frag_size="8192"/>
+ <pbcast.GMS join_timeout="5000" join_retry_timeout="2000"
+ shun="true" print_local_addr="true"/>
+ <pbcast.STATE_TRANSFER/>
+ </config>
+ </attribute>
+
+ <!-- Must be true if any entity deployment uses a scoped classloader -->
+ <attribute name="UseRegionBasedMarshalling">true</attribute>
+ <!-- Must match the value of "useRegionBasedMarshalling" -->
+ <attribute name="InactiveOnStartup">true</attribute>
+
+ <!--
+ The max amount of time (in milliseconds) we wait until the
+ initial state (ie. the contents of the cache) are retrieved from
+ existing members in a clustered environment
+ -->
+ <attribute name="StateRetrievalTimeout">20000</attribute>
+
+ <!--
+ Number of milliseconds to wait until all responses for a
+ synchronous call have been received.
+ -->
+ <attribute name="SyncReplTimeout">20000</attribute>
+
+ <!-- Max number of milliseconds to wait for a lock acquisition -->
+ <attribute name="LockAcquisitionTimeout">15000</attribute>
+
+ <!-- Specific eviction policy configurations. This is LRU -->
+ <attribute name="EvictionPolicyConfig">
+ <config>
+ <attribute name="wakeUpIntervalSeconds">5</attribute>
+ <!-- Name of the DEFAULT eviction policy class. -->
+ <attribute name="policyClass">org.jboss.cache.eviction.LRUPolicy</attribute>
+ <!-- Cache wide default -->
+ <region name="/_default_">
+ <attribute name="maxNodes">5000</attribute>
+ <attribute name="timeToLiveSeconds">1000</attribute>
+ </region>
+ <!-- Don't ever evict modification timestamps -->
+ <region name="/TS">
+ <attribute name="maxNodes">0</attribute>
+ <attribute name="timeToLiveSeconds">0</attribute>
+ </region>
+ </config>
+ </attribute>
+ </mbean>
+
+
+</server>
Property changes on: core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/functional/pessimistic-treecache.xml
___________________________________________________________________
Name: svn:executable
+ *
Added: core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/query/QueryRegionImplTestCase.java
===================================================================
--- core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/query/QueryRegionImplTestCase.java (rev 0)
+++ core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/query/QueryRegionImplTestCase.java 2007-10-18 20:08:50 UTC (rev 14101)
@@ -0,0 +1,320 @@
+/*
+ * Copyright (c) 2007, Red Hat Middleware, LLC. All rights reserved.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, v. 2.1. This program is distributed in the
+ * hope that it will be useful, but WITHOUT A WARRANTY; without even the implied
+ * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details. You should have received a
+ * copy of the GNU Lesser General Public License, v.2.1 along with this
+ * distribution; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Red Hat Author(s): Brian Stansberry
+ */
+
+package org.hibernate.test.cache.jbc2.query;
+
+import java.util.Properties;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+import junit.framework.AssertionFailedError;
+
+import org.hibernate.cache.CacheDataDescription;
+import org.hibernate.cache.QueryResultsRegion;
+import org.hibernate.cache.Region;
+import org.hibernate.cache.jbc2.BasicRegionAdapter;
+import org.hibernate.cache.jbc2.CacheInstanceManager;
+import org.hibernate.cache.jbc2.JBossCacheRegionFactory;
+import org.hibernate.cache.jbc2.MultiplexedJBossCacheRegionFactory;
+import org.hibernate.cache.jbc2.builder.MultiplexingCacheInstanceManager;
+import org.hibernate.cfg.Configuration;
+import org.hibernate.test.cache.jbc2.AbstractRegionImplTestCase;
+import org.hibernate.test.util.CacheTestUtil;
+import org.jboss.cache.Cache;
+import org.jboss.cache.Fqn;
+import org.jboss.cache.notifications.annotation.CacheListener;
+import org.jboss.cache.notifications.annotation.NodeVisited;
+import org.jboss.cache.notifications.event.NodeVisitedEvent;
+import org.jboss.cache.transaction.BatchModeTransactionManager;
+
+/**
+ * Tests of QueryResultRegionImpl.
+ *
+ * @author <a href="brian.stansberry(a)jboss.com">Brian Stansberry</a>
+ * @version $Revision: 1 $
+ */
+public class QueryRegionImplTestCase extends AbstractRegionImplTestCase {
+
+ private static final String KEY = "Key";
+ private static final String VALUE1 = "value1";
+ private static final String VALUE2 = "value2";
+
+ /**
+ * Create a new EntityRegionImplTestCase.
+ *
+ * @param name
+ */
+ public QueryRegionImplTestCase(String name) {
+ super(name);
+ }
+
+ @Override
+ protected Region createRegion(JBossCacheRegionFactory regionFactory, String regionName, Properties properties, CacheDataDescription cdd) {
+ return regionFactory.buildQueryResultsRegion(regionName, properties);
+ }
+
+ @Override
+ protected Cache getJBossCache(JBossCacheRegionFactory regionFactory) {
+ CacheInstanceManager mgr = regionFactory.getCacheInstanceManager();
+ return mgr.getQueryCacheInstance();
+ }
+
+ @Override
+ protected Fqn getRegionFqn(String regionName, String regionPrefix) {
+ return Fqn.fromString(BasicRegionAdapter.escapeRegionName(regionName, regionPrefix));
+ }
+
+ public void testPutDoesNotBlockGetOptimistic() throws Exception {
+ putDoesNotBlockGetTest("optimistic-shared");
+ }
+
+ public void testPutDoesNotBlockGetPessimistic() throws Exception {
+ putDoesNotBlockGetTest("pessimistic-shared");
+ }
+
+ private void putDoesNotBlockGetTest(String configName) throws Exception {
+
+ Configuration cfg = CacheTestUtil.buildConfiguration("test", MultiplexedJBossCacheRegionFactory.class, false, true);
+ cfg.setProperty(MultiplexingCacheInstanceManager.QUERY_CACHE_RESOURCE_PROP, configName);
+ // Use the local-query config for timestamps as well to save time
+ cfg.setProperty(MultiplexingCacheInstanceManager.TIMESTAMP_CACHE_RESOURCE_PROP, configName);
+ JBossCacheRegionFactory regionFactory = CacheTestUtil.startRegionFactory(cfg, getCacheTestSupport());
+
+ final QueryResultsRegion region = regionFactory.buildQueryResultsRegion("test/com.foo.test", cfg.getProperties());
+
+ region.put(KEY, VALUE1);
+ assertEquals(VALUE1, region.get(KEY));
+
+ final CountDownLatch readerLatch = new CountDownLatch(1);
+ final CountDownLatch writerLatch = new CountDownLatch(1);
+ final CountDownLatch completionLatch = new CountDownLatch(1);
+ final ExceptionHolder holder = new ExceptionHolder();
+
+ Thread reader = new Thread() {
+
+ public void run() {
+ try {
+ BatchModeTransactionManager.getInstance().begin();
+ assertTrue(VALUE2.equals(region.get(KEY)) == false);
+ BatchModeTransactionManager.getInstance().commit();
+ }
+ catch (AssertionFailedError e) {
+ holder.a1 = e;
+ rollback();
+ }
+ catch (Exception e) {
+ holder.e1 = e;
+ rollback();
+ }
+ finally {
+ readerLatch.countDown();
+ }
+ }
+ };
+
+ Thread writer = new Thread() {
+
+ public void run() {
+ try {
+ BatchModeTransactionManager.getInstance().begin();
+ region.put(KEY, VALUE2);
+ writerLatch.await();
+ BatchModeTransactionManager.getInstance().commit();
+ }
+ catch (Exception e) {
+ holder.e2 = e;
+ rollback();
+ }
+ finally {
+ completionLatch.countDown();
+ }
+ }
+ };
+
+ reader.setDaemon(true);
+ writer.setDaemon(true);
+
+ writer.start();
+ assertFalse("Writer is blocking", completionLatch.await(100, TimeUnit.MILLISECONDS));
+
+ // Start the reader
+ reader.start();
+ assertTrue("Reader finished promptly", readerLatch.await(100, TimeUnit.MILLISECONDS));
+
+ writerLatch.countDown();
+ assertTrue("Reader finished promptly", completionLatch.await(100, TimeUnit.MILLISECONDS));
+
+ assertEquals(VALUE2, region.get(KEY));
+
+ if (holder.a1 != null)
+ throw holder.a1;
+ else if (holder.a2 != null)
+ throw holder.a2;
+
+ assertEquals("writer saw no exceptions", null, holder.e1);
+ assertEquals("reader saw no exceptions", null, holder.e2);
+ }
+
+ public void testGetDoesNotBlockPutOptimistic() throws Exception {
+ getDoesNotBlockPutTest("optimistic-shared");
+ }
+
+ public void testGetDoesNotBlockPutPessimistic() throws Exception {
+ getDoesNotBlockPutTest("pessimistic-shared");
+ }
+
+ private void getDoesNotBlockPutTest(String configName) throws Exception {
+
+ Configuration cfg = CacheTestUtil.buildConfiguration("test", MultiplexedJBossCacheRegionFactory.class, false, true);
+ cfg.setProperty(MultiplexingCacheInstanceManager.QUERY_CACHE_RESOURCE_PROP, configName);
+ // Use the local-query config for timestamps as well to save time
+ cfg.setProperty(MultiplexingCacheInstanceManager.TIMESTAMP_CACHE_RESOURCE_PROP, configName);
+ JBossCacheRegionFactory regionFactory = CacheTestUtil.startRegionFactory(cfg, getCacheTestSupport());
+
+ final QueryResultsRegion region = regionFactory.buildQueryResultsRegion("test/com.foo.test", cfg.getProperties());
+
+ region.put(KEY, VALUE1);
+ assertEquals(VALUE1, region.get(KEY));
+
+ final Fqn rootFqn = getRegionFqn("test/com.foo.test", "test");
+ final Cache jbc = getJBossCache(regionFactory);
+
+ final CountDownLatch blockerLatch = new CountDownLatch(1);
+ final CountDownLatch writerLatch = new CountDownLatch(1);
+ final CountDownLatch completionLatch = new CountDownLatch(1);
+ final ExceptionHolder holder = new ExceptionHolder();
+
+ Thread blocker = new Thread() {
+
+ public void run() {
+ Fqn toBlock = new Fqn(rootFqn, KEY);
+ GetBlocker blocker = new GetBlocker(blockerLatch,toBlock);
+ try {
+ jbc.addCacheListener(blocker);
+
+ BatchModeTransactionManager.getInstance().begin();
+ region.get(KEY);
+ BatchModeTransactionManager.getInstance().commit();
+ }
+ catch (Exception e) {
+ holder.e1 = e;
+ rollback();
+ }
+ finally {
+ jbc.removeCacheListener(blocker);
+ }
+ }
+ };
+
+ Thread writer = new Thread() {
+
+ public void run() {
+ try {
+ writerLatch.await();
+
+ BatchModeTransactionManager.getInstance().begin();
+ region.put(KEY, VALUE2);
+ BatchModeTransactionManager.getInstance().commit();
+ }
+ catch (Exception e) {
+ holder.e2 = e;
+ rollback();
+ }
+ finally {
+ completionLatch.countDown();
+ }
+ }
+ };
+
+ blocker.setDaemon(true);
+ writer.setDaemon(true);
+
+ boolean unblocked = false;
+ try {
+ blocker.start();
+ writer.start();
+
+ assertFalse("Blocker is blocking", completionLatch.await(100, TimeUnit.MILLISECONDS));
+ // Start the writer
+ writerLatch.countDown();
+ assertTrue("Writer finished promptly", completionLatch.await(100, TimeUnit.MILLISECONDS));
+
+ blockerLatch.countDown();
+ unblocked = true;
+
+ if ("PESSIMISTIC".equals(jbc.getConfiguration().getNodeLockingSchemeString())) {
+ assertEquals(VALUE1, region.get(KEY));
+ }
+ else {
+ assertEquals(VALUE2, region.get(KEY));
+ }
+
+ if (holder.a1 != null)
+ throw holder.a1;
+ else if (holder.a2 != null)
+ throw holder.a2;
+
+ assertEquals("blocker saw no exceptions", null, holder.e1);
+ assertEquals("writer saw no exceptions", null, holder.e2);
+ }
+ finally {
+ if (!unblocked)
+ blockerLatch.countDown();
+ }
+ }
+
+ private void rollback() {
+ try {
+ BatchModeTransactionManager.getInstance().rollback();
+ }
+ catch (Exception e) {
+ log.error(e.getMessage(), e);
+ }
+
+ }
+
+ @CacheListener
+ public class GetBlocker {
+
+ private CountDownLatch latch;
+ private Fqn fqn;
+
+ GetBlocker(CountDownLatch latch, Fqn fqn) {
+ this.latch = latch;
+ this.fqn = fqn;
+ }
+
+ @NodeVisited
+ public void nodeVisisted(NodeVisitedEvent event) {
+
+ if (event.isPre() && event.getFqn().equals(fqn)) {
+ try {
+ latch.await();
+ }
+ catch (InterruptedException e) {
+ log.error("Interrupted waiting for latch", e);
+ }
+ }
+ }
+ }
+
+ private class ExceptionHolder {
+ Exception e1;
+ Exception e2;
+ AssertionFailedError a1;
+ AssertionFailedError a2;
+ }
+}
Added: core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/timestamp/TimestampsRegionImplTestCase.java
===================================================================
--- core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/timestamp/TimestampsRegionImplTestCase.java (rev 0)
+++ core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/cache/jbc2/timestamp/TimestampsRegionImplTestCase.java 2007-10-18 20:08:50 UTC (rev 14101)
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2007, Red Hat Middleware, LLC. All rights reserved.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, v. 2.1. This program is distributed in the
+ * hope that it will be useful, but WITHOUT A WARRANTY; without even the implied
+ * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details. You should have received a
+ * copy of the GNU Lesser General Public License, v.2.1 along with this
+ * distribution; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Red Hat Author(s): Brian Stansberry
+ */
+
+package org.hibernate.test.cache.jbc2.timestamp;
+
+import java.util.Properties;
+
+import org.hibernate.cache.CacheDataDescription;
+import org.hibernate.cache.Region;
+import org.hibernate.cache.jbc2.BasicRegionAdapter;
+import org.hibernate.cache.jbc2.CacheInstanceManager;
+import org.hibernate.cache.jbc2.JBossCacheRegionFactory;
+import org.hibernate.cache.jbc2.timestamp.TimestampsRegionImpl;
+import org.hibernate.test.cache.jbc2.AbstractRegionImplTestCase;
+import org.jboss.cache.Cache;
+import org.jboss.cache.Fqn;
+
+/**
+ * Tests of TimestampsRegionImpl.
+ *
+ * @author <a href="brian.stansberry(a)jboss.com">Brian Stansberry</a>
+ * @version $Revision: 1 $
+ */
+public class TimestampsRegionImplTestCase extends AbstractRegionImplTestCase {
+
+ /**
+ * Create a new EntityRegionImplTestCase.
+ *
+ * @param name
+ */
+ public TimestampsRegionImplTestCase(String name) {
+ super(name);
+ }
+
+ @Override
+ protected Region createRegion(JBossCacheRegionFactory regionFactory, String regionName, Properties properties, CacheDataDescription cdd) {
+ return regionFactory.buildTimestampsRegion(regionName, properties);
+ }
+
+ @Override
+ protected Cache getJBossCache(JBossCacheRegionFactory regionFactory) {
+ CacheInstanceManager mgr = regionFactory.getCacheInstanceManager();
+ return mgr.getTimestampsCacheInstance();
+ }
+
+ @Override
+ protected Fqn getRegionFqn(String regionName, String regionPrefix) {
+ return BasicRegionAdapter.getTypeFirstRegionFqn(regionName, regionPrefix, TimestampsRegionImpl.TYPE);
+ }
+
+
+}
Added: core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/tm/DummyConnectionProvider.java
===================================================================
--- core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/tm/DummyConnectionProvider.java (rev 0)
+++ core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/tm/DummyConnectionProvider.java 2007-10-18 20:08:50 UTC (rev 14101)
@@ -0,0 +1,52 @@
+//$Id: DummyConnectionProvider.java 6501 2005-04-24 00:18:28Z oneovthafew $
+package org.hibernate.test.tm;
+
+import java.sql.Connection;
+import java.sql.SQLException;
+import java.util.Properties;
+
+import org.hibernate.HibernateException;
+import org.hibernate.connection.ConnectionProvider;
+import org.hibernate.connection.ConnectionProviderFactory;
+
+/**
+ * FIXME Get this class into hibernate-testing so we don't have to maintain
+ * a copy here. Can't use the hibernate-testsuite version as that would
+ * lead to circular project dependencies.
+ *
+ * @author Gavin King
+ */
+public class DummyConnectionProvider implements ConnectionProvider {
+
+ ConnectionProvider cp;
+ boolean isTransaction;
+
+ public void configure(Properties props) throws HibernateException {
+ cp = ConnectionProviderFactory.newConnectionProvider();
+ }
+
+ public Connection getConnection() throws SQLException {
+ DummyTransactionManager dtm = DummyTransactionManager.INSTANCE;
+ if (dtm != null && dtm.getCurrent() != null && dtm.getCurrent().getConnection() != null) {
+ isTransaction = true;
+ return dtm.getCurrent().getConnection();
+ } else {
+ isTransaction = false;
+ return cp.getConnection();
+ }
+ }
+
+ public void closeConnection(Connection conn) throws SQLException {
+ if (!isTransaction)
+ conn.close();
+ }
+
+ public void close() throws HibernateException {
+
+ }
+
+ public boolean supportsAggressiveRelease() {
+ return true;
+ }
+
+}
Property changes on: core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/tm/DummyConnectionProvider.java
___________________________________________________________________
Name: svn:executable
+ *
Added: core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/tm/DummyTransaction.java
===================================================================
--- core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/tm/DummyTransaction.java (rev 0)
+++ core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/tm/DummyTransaction.java 2007-10-18 20:08:50 UTC (rev 14101)
@@ -0,0 +1,143 @@
+//$Id: DummyTransaction.java 8411 2005-10-14 23:29:04Z maxcsaucdk $
+package org.hibernate.test.tm;
+
+import java.sql.Connection;
+import java.sql.SQLException;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.transaction.HeuristicMixedException;
+import javax.transaction.HeuristicRollbackException;
+import javax.transaction.RollbackException;
+import javax.transaction.Status;
+import javax.transaction.Synchronization;
+import javax.transaction.SystemException;
+import javax.transaction.Transaction;
+import javax.transaction.xa.XAResource;
+
+/**
+ * FIXME Get this class into hibernate-testing so we don't have to maintain
+ * a copy here. Can't use the hibernate-testsuite version as that would
+ * lead to circular project dependencies.
+ *
+ * @author Gavin King
+ */
+public class DummyTransaction implements Transaction {
+
+ int status;
+ private Connection connection;
+ List synchronizations = new ArrayList();
+ private DummyTransactionManager transactionManager;
+
+ DummyTransaction(DummyTransactionManager transactionManager) {
+ status = Status.STATUS_NO_TRANSACTION;
+ this.transactionManager = transactionManager;
+ }
+
+ public void begin() throws SystemException {
+ try {
+ connection = transactionManager.connections.getConnection();
+ } catch (SQLException sqle) {
+
+ sqle.printStackTrace();
+ throw new SystemException(sqle.toString());
+ }
+ status = Status.STATUS_ACTIVE;
+ }
+
+ public void commit() throws RollbackException, HeuristicMixedException, HeuristicRollbackException,
+ SecurityException, IllegalStateException, SystemException {
+
+ if (status == Status.STATUS_MARKED_ROLLBACK) {
+ rollback();
+ } else {
+ status = Status.STATUS_PREPARING;
+
+ for (int i = 0; i < synchronizations.size(); i++) {
+ Synchronization s = (Synchronization) synchronizations.get(i);
+ s.beforeCompletion();
+ }
+
+ status = Status.STATUS_COMMITTING;
+
+ try {
+ connection.commit();
+ connection.close();
+ } catch (SQLException sqle) {
+ status = Status.STATUS_UNKNOWN;
+ throw new SystemException();
+ }
+
+ status = Status.STATUS_COMMITTED;
+
+ for (int i = 0; i < synchronizations.size(); i++) {
+ Synchronization s = (Synchronization) synchronizations.get(i);
+ s.afterCompletion(status);
+ }
+
+ // status = Status.STATUS_NO_TRANSACTION;
+ transactionManager.endCurrent(this);
+ }
+
+ }
+
+ public boolean delistResource(XAResource arg0, int arg1) throws IllegalStateException, SystemException {
+ // TODO Auto-generated method stub
+ return false;
+ }
+
+ public boolean enlistResource(XAResource arg0) throws RollbackException, IllegalStateException, SystemException {
+ // TODO Auto-generated method stub
+ return false;
+ }
+
+ public int getStatus() throws SystemException {
+ return status;
+ }
+
+ public void registerSynchronization(Synchronization sync) throws RollbackException, IllegalStateException,
+ SystemException {
+ synchronizations.add(sync);
+ }
+
+ public void rollback() throws IllegalStateException, SystemException {
+
+ status = Status.STATUS_ROLLING_BACK;
+
+ // Synch.beforeCompletion() should *not* be called for rollbacks
+ // for ( int i=0; i<synchronizations.size(); i++ ) {
+ // Synchronization s = (Synchronization) synchronizations.get(i);
+ // s.beforeCompletion();
+ // }
+
+ status = Status.STATUS_ROLLEDBACK;
+
+ try {
+ connection.rollback();
+ connection.close();
+ } catch (SQLException sqle) {
+ status = Status.STATUS_UNKNOWN;
+ throw new SystemException();
+ }
+
+ for (int i = 0; i < synchronizations.size(); i++) {
+ Synchronization s = (Synchronization) synchronizations.get(i);
+ s.afterCompletion(status);
+ }
+
+ // status = Status.STATUS_NO_TRANSACTION;
+ transactionManager.endCurrent(this);
+ }
+
+ public void setRollbackOnly() throws IllegalStateException, SystemException {
+ status = Status.STATUS_MARKED_ROLLBACK;
+ }
+
+ void setConnection(Connection connection) {
+ this.connection = connection;
+ }
+
+ public Connection getConnection() {
+ return connection;
+ }
+}
Property changes on: core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/tm/DummyTransaction.java
___________________________________________________________________
Name: svn:executable
+ *
Added: core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/tm/DummyTransactionManager.java
===================================================================
--- core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/tm/DummyTransactionManager.java (rev 0)
+++ core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/tm/DummyTransactionManager.java 2007-10-18 20:08:50 UTC (rev 14101)
@@ -0,0 +1,85 @@
+//$Id: DummyTransactionManager.java 7003 2005-06-03 16:09:59Z steveebersole $
+package org.hibernate.test.tm;
+
+import java.util.Properties;
+
+import javax.transaction.HeuristicMixedException;
+import javax.transaction.HeuristicRollbackException;
+import javax.transaction.InvalidTransactionException;
+import javax.transaction.NotSupportedException;
+import javax.transaction.RollbackException;
+import javax.transaction.SystemException;
+import javax.transaction.Transaction;
+import javax.transaction.TransactionManager;
+
+import org.hibernate.connection.ConnectionProvider;
+import org.hibernate.connection.ConnectionProviderFactory;
+
+/**
+ * FIXME Get this class into hibernate-testing so we don't have to maintain
+ * a copy here. Can't use the hibernate-testsuite version as that would
+ * lead to circular project dependencies.
+ *
+ * @author Gavin King
+ */
+public class DummyTransactionManager implements TransactionManager {
+
+ public static DummyTransactionManager INSTANCE;
+
+ private DummyTransaction current;
+ ConnectionProvider connections;
+
+ public DummyTransactionManager(Properties props) {
+ connections = ConnectionProviderFactory.newConnectionProvider();
+ }
+
+ public void begin() throws NotSupportedException, SystemException {
+ current = new DummyTransaction(this);
+ current.begin();
+ }
+
+ public void commit() throws RollbackException, HeuristicMixedException, HeuristicRollbackException,
+ SecurityException, IllegalStateException, SystemException {
+ current.commit();
+ }
+
+ public int getStatus() throws SystemException {
+ return current.getStatus();
+ }
+
+ public Transaction getTransaction() throws SystemException {
+ return current;
+ }
+
+ public void resume(Transaction tx) throws InvalidTransactionException, IllegalStateException, SystemException {
+ current = (DummyTransaction) tx;
+ }
+
+ public void rollback() throws IllegalStateException, SecurityException, SystemException {
+ current.rollback();
+
+ }
+
+ public void setRollbackOnly() throws IllegalStateException, SystemException {
+ current.setRollbackOnly();
+ }
+
+ public void setTransactionTimeout(int t) throws SystemException {
+ }
+
+ public Transaction suspend() throws SystemException {
+ Transaction result = current;
+ current = null;
+ return result;
+ }
+
+ public DummyTransaction getCurrent() {
+ return current;
+ }
+
+ void endCurrent(DummyTransaction tx) {
+ if (current == tx)
+ current = null;
+ }
+
+}
Property changes on: core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/tm/DummyTransactionManager.java
___________________________________________________________________
Name: svn:executable
+ *
Added: core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/tm/DummyTransactionManagerLookup.java
===================================================================
--- core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/tm/DummyTransactionManagerLookup.java (rev 0)
+++ core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/tm/DummyTransactionManagerLookup.java 2007-10-18 20:08:50 UTC (rev 14101)
@@ -0,0 +1,31 @@
+//$Id: DummyTransactionManagerLookup.java 5693 2005-02-13 01:59:07Z oneovthafew $
+package org.hibernate.test.tm;
+
+import java.util.Properties;
+
+import javax.transaction.TransactionManager;
+
+import org.hibernate.HibernateException;
+import org.hibernate.transaction.TransactionManagerLookup;
+
+/**
+ * FIXME Get this class into hibernate-testing so we don't have to maintain
+ * a copy here. Can't use the hibernate-testsuite version as that would
+ * lead to circular project dependencies.
+ *
+ * @author Gavin King
+ */
+public class DummyTransactionManagerLookup implements TransactionManagerLookup {
+
+ public TransactionManager getTransactionManager(Properties props) throws HibernateException {
+ if (DummyTransactionManager.INSTANCE == null) {
+ DummyTransactionManager.INSTANCE = new DummyTransactionManager(props);
+ }
+ return DummyTransactionManager.INSTANCE;
+ }
+
+ public String getUserTransactionName() {
+ throw new UnsupportedOperationException();
+ }
+
+}
Property changes on: core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/tm/DummyTransactionManagerLookup.java
___________________________________________________________________
Name: svn:executable
+ *
Added: core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/tm/jbc2/BatchModeTransactionManagerLookup.java
===================================================================
--- core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/tm/jbc2/BatchModeTransactionManagerLookup.java (rev 0)
+++ core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/tm/jbc2/BatchModeTransactionManagerLookup.java 2007-10-18 20:08:50 UTC (rev 14101)
@@ -0,0 +1,34 @@
+//$Id: DummyTransactionManagerLookup.java 5693 2005-02-13 01:59:07Z oneovthafew $
+package org.hibernate.test.tm.jbc2;
+
+import java.util.Properties;
+
+import javax.transaction.TransactionManager;
+
+import org.hibernate.HibernateException;
+import org.hibernate.transaction.TransactionManagerLookup;
+import org.jboss.cache.transaction.BatchModeTransactionManager;
+
+/**
+ * Uses the JBoss Cache BatchModeTransactionManager. Should not be used in
+ * any tests that simulate usage of database connections.
+ *
+ * @author Brian Stansberry
+ */
+public class BatchModeTransactionManagerLookup
+ implements TransactionManagerLookup {
+
+ public TransactionManager getTransactionManager(Properties props) throws HibernateException {
+ try {
+ return BatchModeTransactionManager.getInstance();
+ }
+ catch (Exception e) {
+ throw new HibernateException("Failed getting BatchModeTransactionManager", e);
+ }
+ }
+
+ public String getUserTransactionName() {
+ throw new UnsupportedOperationException();
+ }
+
+}
Property changes on: core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/tm/jbc2/BatchModeTransactionManagerLookup.java
___________________________________________________________________
Name: svn:executable
+ *
Added: core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/util/CacheTestSupport.java
===================================================================
--- core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/util/CacheTestSupport.java (rev 0)
+++ core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/util/CacheTestSupport.java 2007-10-18 20:08:50 UTC (rev 14101)
@@ -0,0 +1,108 @@
+/*
+ * Copyright (c) 2007, Red Hat Middleware, LLC. All rights reserved.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, v. 2.1. This program is distributed in the
+ * hope that it will be useful, but WITHOUT A WARRANTY; without even the implied
+ * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details. You should have received a
+ * copy of the GNU Lesser General Public License, v.2.1 along with this
+ * distribution; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Red Hat Author(s): Brian Stansberry
+ */
+
+package org.hibernate.test.util;
+
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Set;
+
+import org.hibernate.cache.RegionFactory;
+import org.jboss.cache.Cache;
+
+/**
+ * Support class for tracking and cleaning up objects used in tests.
+ *
+ * @author <a href="brian.stansberry(a)jboss.com">Brian Stansberry</a>
+ * @version $Revision: 1 $
+ */
+public class CacheTestSupport {
+
+ private Set<Cache> caches = new HashSet();
+ private Set<RegionFactory> factories = new HashSet();
+ private Exception exception;
+
+ public void registerCache(Cache cache) {
+ caches.add(cache);
+ }
+
+ public void registerFactory(RegionFactory factory) {
+ factories.add(factory);
+ }
+
+ public void unregisterCache(Cache cache) {
+ caches.remove(cache);
+ }
+
+ public void unregisterFactory(RegionFactory factory) {
+ factories.remove(factory);
+ }
+
+ public void setUp() throws Exception {
+ cleanUp();
+ throwStoredException();
+ }
+
+ public void tearDown() throws Exception {
+ cleanUp();
+ throwStoredException();
+ }
+
+ private void cleanUp() {
+ for (Iterator it = factories.iterator(); it.hasNext(); ) {
+ try {
+ ((RegionFactory) it.next()).stop();
+ }
+ catch (Exception e) {
+ storeException(e);
+ }
+ finally {
+ it.remove();
+ }
+ }
+ factories.clear();
+
+ for (Iterator it = caches.iterator(); it.hasNext(); ) {
+ try {
+ Cache cache = (Cache) it.next();
+ cache.stop();
+ cache.destroy();
+ }
+ catch (Exception e) {
+ storeException(e);
+ }
+ finally {
+ it.remove();
+ }
+ }
+ caches.clear();
+ }
+
+ private void storeException(Exception e) {
+ if (this.exception == null) {
+ this.exception = e;
+ }
+ }
+
+ private void throwStoredException() throws Exception {
+ if (exception != null) {
+ Exception toThrow = exception;
+ exception = null;
+ throw toThrow;
+ }
+ }
+
+}
Added: core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/util/CacheTestUtil.java
===================================================================
--- core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/util/CacheTestUtil.java (rev 0)
+++ core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/util/CacheTestUtil.java 2007-10-18 20:08:50 UTC (rev 14101)
@@ -0,0 +1,109 @@
+/*
+ * Copyright (c) 2007, Red Hat Middleware, LLC. All rights reserved.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, v. 2.1. This program is distributed in the
+ * hope that it will be useful, but WITHOUT A WARRANTY; without even the implied
+ * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details. You should have received a
+ * copy of the GNU Lesser General Public License, v.2.1 along with this
+ * distribution; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Red Hat Author(s): Brian Stansberry
+ */
+
+package org.hibernate.test.util;
+
+import java.util.Properties;
+
+import org.hibernate.cache.jbc2.JBossCacheRegionFactory;
+import org.hibernate.cache.jbc2.SharedJBossCacheRegionFactory;
+import org.hibernate.cache.jbc2.builder.SharedCacheInstanceManager;
+import org.hibernate.cfg.Configuration;
+import org.hibernate.cfg.Environment;
+import org.hibernate.cfg.Settings;
+import org.hibernate.test.tm.jbc2.BatchModeTransactionManagerLookup;
+
+/**
+ * Utilities for cache testing.
+ *
+ * @author <a href="brian.stansberry(a)jboss.com">Brian Stansberry</a>
+ * @version $Revision: 1 $
+ */
+public class CacheTestUtil {
+
+ public static String LOCAL_OPTIMISIC_CACHE;
+ public static String LOCAL_PESSIMISTIC_CACHE;
+
+ static {
+ String pkg = CacheTestUtil.class.getPackage().getName().replace('.', '/');
+ LOCAL_OPTIMISIC_CACHE = pkg + "/optimistic-local-cache.xml";
+ LOCAL_PESSIMISTIC_CACHE = pkg + "/pessimistic-local-cache.xml";
+ }
+
+ public static Configuration buildConfiguration(String regionPrefix, Class regionFactory, boolean use2ndLevel, boolean useQueries) {
+
+ Configuration cfg = new Configuration();
+ cfg.setProperty(Environment.GENERATE_STATISTICS, "true");
+ cfg.setProperty(Environment.USE_STRUCTURED_CACHE, "true");
+// cfg.setProperty(Environment.CONNECTION_PROVIDER, DummyConnectionProvider.class.getName());
+ cfg.setProperty(Environment.TRANSACTION_MANAGER_STRATEGY, BatchModeTransactionManagerLookup.class.getName());
+
+ cfg.setProperty(Environment.CACHE_REGION_FACTORY, regionFactory.getName());
+ cfg.setProperty(Environment.CACHE_REGION_PREFIX, regionPrefix);
+ cfg.setProperty(Environment.USE_SECOND_LEVEL_CACHE, String.valueOf(use2ndLevel));
+ cfg.setProperty(Environment.USE_QUERY_CACHE, String.valueOf(useQueries));
+
+ return cfg;
+ }
+
+ public static Configuration buildLocalOnlyConfiguration(String regionPrefix, boolean optimistic, boolean use2ndLevel, boolean useQueries) {
+ Configuration cfg = buildConfiguration(regionPrefix, SharedJBossCacheRegionFactory.class, use2ndLevel, useQueries);
+
+ String resource = CacheTestUtil.class.getPackage().getName().replace('.', '/') + "/";
+ resource += optimistic ? "optimistic" : "pessimistic";
+ resource += "-local-cache.xml";
+
+ cfg.setProperty(SharedCacheInstanceManager.CACHE_RESOURCE_PROP, resource);
+
+ return cfg;
+ }
+
+ public static JBossCacheRegionFactory startRegionFactory(Configuration cfg)
+ throws ClassNotFoundException, InstantiationException, IllegalAccessException {
+
+ Settings settings = cfg.buildSettings();
+ Properties properties = cfg.getProperties();
+
+ String factoryType = cfg.getProperty(Environment.CACHE_REGION_FACTORY);
+ Class factoryClass = Thread.currentThread().getContextClassLoader().loadClass(factoryType);
+ JBossCacheRegionFactory regionFactory = (JBossCacheRegionFactory) factoryClass.newInstance();
+
+ regionFactory.start(settings, properties);
+
+ return regionFactory;
+ }
+
+ public static JBossCacheRegionFactory startRegionFactory(Configuration cfg, CacheTestSupport testSupport)
+ throws ClassNotFoundException, InstantiationException, IllegalAccessException {
+
+ JBossCacheRegionFactory factory = startRegionFactory(cfg);
+ testSupport.registerFactory(factory);
+ return factory;
+ }
+
+ public static void stopRegionFactory(JBossCacheRegionFactory factory, CacheTestSupport testSupport) {
+
+ factory.stop();
+ testSupport.unregisterFactory(factory);
+ }
+
+ /**
+ * Prevent instantiation.
+ */
+ private CacheTestUtil() {
+ }
+
+}
Added: core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/util/optimistic-local-cache.xml
===================================================================
--- core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/util/optimistic-local-cache.xml (rev 0)
+++ core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/util/optimistic-local-cache.xml 2007-10-18 20:08:50 UTC (rev 14101)
@@ -0,0 +1,138 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!-- ===================================================================== -->
+<!-- -->
+<!-- Sample JBoss Cache Service Configuration -->
+<!-- Recommended for use as Hibernate's 2nd Level Cache -->
+<!-- For use with JBossCache >= 2.0.0 ONLY!!! -->
+<!-- -->
+<!-- ===================================================================== -->
+
+<server>
+
+ <classpath codebase="./lib" archives="jboss-cache.jar, jgroups.jar"/>
+
+
+ <!-- ==================================================================== -->
+ <!-- Defines TreeCache configuration -->
+ <!-- ==================================================================== -->
+
+ <mbean code="org.jboss.cache.jmx.CacheJmxWrapper"
+ name="jboss.cache:service=TreeCache">
+
+ <depends>jboss:service=Naming</depends>
+ <depends>jboss:service=TransactionManager</depends>
+
+ <!--
+ TransactionManager configuration not required for Hibernate!
+ Hibernate will plug in its own transaction manager integration.
+ -->
+
+
+ <!--
+ Node locking scheme:
+ OPTIMISTIC
+ PESSIMISTIC (default)
+ -->
+ <attribute name="NodeLockingScheme">OPTIMISTIC</attribute>
+
+ <!--
+ Note that this attribute is IGNORED if your NodeLockingScheme above is OPTIMISTIC.
+
+ Isolation level : SERIALIZABLE
+ REPEATABLE_READ (default)
+ READ_COMMITTED
+ READ_UNCOMMITTED
+ NONE
+ -->
+ <attribute name="IsolationLevel">REPEATABLE_READ</attribute>
+
+ <!--
+ Valid modes are LOCAL
+ REPL_ASYNC
+ REPL_SYNC
+ INVALIDATION_ASYNC
+ INVALIDATION_SYNC
+
+ INVALIDATION_ASYNC is highly recommended as the mode for use
+ with clustered second-level caches.
+ -->
+ <attribute name="CacheMode">REPL_SYNC</attribute>
+
+ <!-- Name of cluster. Needs to be the same for all clusters, in order
+ to find each other
+ -->
+ <attribute name="ClusterName">TreeCache-Cluster</attribute>
+
+ <attribute name="ClusterConfig">
+ <config>
+ <!-- UDP: if you have a multihomed machine,
+ set the bind_addr attribute to the appropriate NIC IP address -->
+ <!-- UDP: On Windows machines, because of the media sense feature
+ being broken with multicast (even after disabling media sense)
+ set the loopback attribute to true -->
+ <UDP mcast_addr="228.1.2.3" mcast_port="48866"
+ ip_ttl="64" ip_mcast="true"
+ mcast_send_buf_size="150000" mcast_recv_buf_size="80000"
+ ucast_send_buf_size="150000" ucast_recv_buf_size="80000"
+ loopback="false"/>
+ <PING timeout="2000" num_initial_members="3"/>
+ <MERGE2 min_interval="10000" max_interval="20000"/>
+ <FD shun="true"/>
+ <FD_SOCK/>
+ <VERIFY_SUSPECT timeout="1500"/>
+ <pbcast.NAKACK gc_lag="50" retransmit_timeout="600,1200,2400,4800"
+ max_xmit_size="8192"/>
+ <UNICAST timeout="600,1200,2400" window_size="100" min_threshold="10"/>
+ <pbcast.STABLE desired_avg_gossip="20000"/>
+ <FRAG frag_size="8192"/>
+ <pbcast.GMS join_timeout="5000" join_retry_timeout="2000"
+ shun="true" print_local_addr="true"/>
+ <pbcast.STATE_TRANSFER/>
+ </config>
+ </attribute>
+
+ <!--
+ Whether or not to fetch state on joining a cluster
+ NOTE this used to be called FetchStateOnStartup and has been renamed to be more descriptive.
+ -->
+ <attribute name="FetchInMemoryState">false</attribute>
+
+ <!--
+ Number of milliseconds to wait until all responses for a
+ synchronous call have been received.
+ -->
+ <attribute name="SyncReplTimeout">20000</attribute>
+
+ <!-- Max number of milliseconds to wait for a lock acquisition -->
+ <attribute name="LockAcquisitionTimeout">15000</attribute>
+
+ <!--
+ Indicate whether to use marshalling or not. Set this to true if you are running under a scoped
+ class loader, e.g., inside an application server. Default is "false".
+ -->
+ <attribute name="UseRegionBasedMarshalling">true</attribute>
+ <!-- Must match the value of "useRegionBasedMarshalling" -->
+ <attribute name="InactiveOnStartup">true</attribute>
+
+ <!-- Specific eviction policy configurations. This is LRU -->
+ <attribute name="EvictionPolicyConfig">
+ <config>
+ <attribute name="wakeUpIntervalSeconds">5</attribute>
+ <!-- Name of the DEFAULT eviction policy class. -->
+ <attribute name="policyClass">org.jboss.cache.eviction.LRUPolicy</attribute>
+ <!-- Cache wide default -->
+ <region name="/_default_">
+ <attribute name="maxNodes">5000</attribute>
+ <attribute name="timeToLiveSeconds">1000</attribute>
+ </region>
+ <!-- Don't ever evict modification timestamps -->
+ <region name="/TS">
+ <attribute name="maxNodes">0</attribute>
+ <attribute name="timeToLiveSeconds">0</attribute>
+ </region>
+ </config>
+ </attribute>
+
+ </mbean>
+</server>
Property changes on: core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/util/optimistic-local-cache.xml
___________________________________________________________________
Name: svn:executable
+ *
Added: core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/util/pessimistic-local-cache.xml
===================================================================
--- core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/util/pessimistic-local-cache.xml (rev 0)
+++ core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/util/pessimistic-local-cache.xml 2007-10-18 20:08:50 UTC (rev 14101)
@@ -0,0 +1,118 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!-- ===================================================================== -->
+<!-- -->
+<!-- Sample TreeCache Service Configuration -->
+<!-- -->
+<!-- ===================================================================== -->
+
+<server>
+
+ <classpath codebase="./lib" archives="jboss-cache.jar, jgroups.jar"/>
+
+
+ <!-- ==================================================================== -->
+ <!-- Defines TreeCache configuration -->
+ <!-- ==================================================================== -->
+
+ <mbean code="org.jboss.cache.jmx.CacheJmxWrapper"
+ name="jboss.cache:service=TreeCache">
+
+ <depends>jboss:service=Naming</depends>
+ <depends>jboss:service=TransactionManager</depends>
+
+ <!--
+ TransactionManager configuration not required for Hibernate!
+ Hibernate will plug in its own transaction manager integration.
+ -->
+
+ <!--
+ Node isolation level : SERIALIZABLE
+ REPEATABLE_READ (default)
+ READ_COMMITTED
+ READ_UNCOMMITTED
+ NONE
+ -->
+ <attribute name="IsolationLevel">REPEATABLE_READ</attribute>
+
+ <!--
+ Valid modes are LOCAL
+ REPL_ASYNC
+ REPL_SYNC
+ -->
+ <attribute name="CacheMode">LOCAL</attribute>
+
+ <!-- Name of cluster. Needs to be the same for all clusters, in order
+ to find each other
+ -->
+ <attribute name="ClusterName">TreeCache-Cluster</attribute>
+
+ <attribute name="ClusterConfig">
+ <config>
+ <!-- UDP: if you have a multihomed machine,
+ set the bind_addr attribute to the appropriate NIC IP address -->
+ <!-- UDP: On Windows machines, because of the media sense feature
+ being broken with multicast (even after disabling media sense)
+ set the loopback attribute to true -->
+ <UDP mcast_addr="228.1.2.3" mcast_port="45566"
+ ip_ttl="64" ip_mcast="true"
+ mcast_send_buf_size="150000" mcast_recv_buf_size="80000"
+ ucast_send_buf_size="150000" ucast_recv_buf_size="80000"
+ loopback="false"/>
+ <PING timeout="2000" num_initial_members="3"/>
+ <MERGE2 min_interval="10000" max_interval="20000"/>
+ <FD shun="true"/>
+ <VERIFY_SUSPECT timeout="1500"/>
+ <pbcast.NAKACK gc_lag="50" retransmit_timeout="600,1200,2400,4800"/>
+ <pbcast.STABLE desired_avg_gossip="20000"/>
+ <UNICAST timeout="600,1200,2400" window_size="100" min_threshold="10"/>
+ <FRAG frag_size="8192"/>
+ <pbcast.GMS join_timeout="5000" join_retry_timeout="2000"
+ shun="true" print_local_addr="true"/>
+ <pbcast.STATE_TRANSFER/>
+ </config>
+ </attribute>
+
+ <!-- Must be true if any entity deployment uses a scoped classloader -->
+ <attribute name="UseRegionBasedMarshalling">true</attribute>
+ <!-- Must match the value of "useRegionBasedMarshalling" -->
+ <attribute name="InactiveOnStartup">true</attribute>
+
+ <!--
+ The max amount of time (in milliseconds) we wait until the
+ initial state (ie. the contents of the cache) are retrieved from
+ existing members in a clustered environment
+ -->
+ <attribute name="StateRetrievalTimeout">20000</attribute>
+
+ <!--
+ Number of milliseconds to wait until all responses for a
+ synchronous call have been received.
+ -->
+ <attribute name="SyncReplTimeout">20000</attribute>
+
+ <!-- Max number of milliseconds to wait for a lock acquisition -->
+ <attribute name="LockAcquisitionTimeout">15000</attribute>
+
+ <!-- Specific eviction policy configurations. This is LRU -->
+ <attribute name="EvictionPolicyConfig">
+ <config>
+ <attribute name="wakeUpIntervalSeconds">5</attribute>
+ <!-- Name of the DEFAULT eviction policy class. -->
+ <attribute name="policyClass">org.jboss.cache.eviction.LRUPolicy</attribute>
+ <!-- Cache wide default -->
+ <region name="/_default_">
+ <attribute name="maxNodes">5000</attribute>
+ <attribute name="timeToLiveSeconds">1000</attribute>
+ </region>
+ <!-- Don't ever evict modification timestamps -->
+ <region name="/TS">
+ <attribute name="maxNodes">0</attribute>
+ <attribute name="timeToLiveSeconds">0</attribute>
+ </region>
+ </config>
+ </attribute>
+ </mbean>
+
+
+</server>
Property changes on: core/trunk/cache-jbosscache2/src/test/java/org/hibernate/test/util/pessimistic-local-cache.xml
___________________________________________________________________
Name: svn:executable
+ *
Added: core/trunk/cache-jbosscache2/src/test/resources/hibernate.cfg.xml
===================================================================
--- core/trunk/cache-jbosscache2/src/test/resources/hibernate.cfg.xml (rev 0)
+++ core/trunk/cache-jbosscache2/src/test/resources/hibernate.cfg.xml 2007-10-18 20:08:50 UTC (rev 14101)
@@ -0,0 +1,8 @@
+<!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
+<hibernate-configuration>
+ <session-factory name="foo">
+ <property name="show_sql">true</property>
+ <mapping resource="org/hibernate/test/legacy/Simple.hbm.xml"/>
+ <class-cache class="org.hibernate.test.legacy.Simple" region="Simple" usage="read-write"/>
+ </session-factory>
+</hibernate-configuration>
\ No newline at end of file
Property changes on: core/trunk/cache-jbosscache2/src/test/resources/hibernate.cfg.xml
___________________________________________________________________
Name: svn:executable
+ *
Added: core/trunk/cache-jbosscache2/src/test/resources/hibernate.properties
===================================================================
--- core/trunk/cache-jbosscache2/src/test/resources/hibernate.properties (rev 0)
+++ core/trunk/cache-jbosscache2/src/test/resources/hibernate.properties 2007-10-18 20:08:50 UTC (rev 14101)
@@ -0,0 +1,30 @@
+################################################################################
+# Copyright (c) 2007, Red Hat Middleware, LLC. All rights reserved. #
+# #
+# This copyrighted material is made available to anyone wishing to use, modify,#
+# copy, or redistribute it subject to the terms and conditions of the GNU #
+# Lesser General Public License, v. 2.1. This program is distributed in the #
+# hope that it will be useful, but WITHOUT A WARRANTY; without even the implied#
+# warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU #
+# Lesser General Public License for more details. You should have received a #
+# copy of the GNU Lesser General Public License, v.2.1 along with this #
+# distribution; if not, write to the Free Software Foundation, Inc., #
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #
+# #
+# Red Hat Author(s): Steve Ebersole #
+################################################################################
+hibernate.dialect org.hibernate.dialect.HSQLDialect
+hibernate.connection.driver_class org.hsqldb.jdbcDriver
+hibernate.connection.url jdbc:hsqldb:target/test/db/hsqldb/hibernate
+hibernate.connection.username sa
+hibernate.connection.password
+hibernate.connection.isolation
+
+hibernate.connection.pool_size 5
+
+hibernate.format_sql true
+
+hibernate.max_fetch_depth 5
+
+hibernate.cache.region_prefix hibernate.test
+hibernate.cache.provider_class org.hibernate.cache.HashtableCacheProvider
Property changes on: core/trunk/cache-jbosscache2/src/test/resources/hibernate.properties
___________________________________________________________________
Name: svn:executable
+ *
Added: core/trunk/cache-jbosscache2/src/test/resources/log4j.properties
===================================================================
--- core/trunk/cache-jbosscache2/src/test/resources/log4j.properties (rev 0)
+++ core/trunk/cache-jbosscache2/src/test/resources/log4j.properties 2007-10-18 20:08:50 UTC (rev 14101)
@@ -0,0 +1,9 @@
+log4j.appender.stdout=org.apache.log4j.ConsoleAppender
+log4j.appender.stdout.Target=System.out
+log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
+log4j.appender.stdout.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n
+
+
+log4j.rootLogger=info, stdout
+
+log4j.logger.org.hibernate.test=info
\ No newline at end of file
Property changes on: core/trunk/cache-jbosscache2/src/test/resources/log4j.properties
___________________________________________________________________
Name: svn:executable
+ *
Added: core/trunk/cache-jbosscache2/src/test/resources/treecache.xml
===================================================================
--- core/trunk/cache-jbosscache2/src/test/resources/treecache.xml (rev 0)
+++ core/trunk/cache-jbosscache2/src/test/resources/treecache.xml 2007-10-18 20:08:50 UTC (rev 14101)
@@ -0,0 +1,113 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!-- ===================================================================== -->
+<!-- -->
+<!-- Sample TreeCache Service Configuration -->
+<!-- -->
+<!-- ===================================================================== -->
+
+<server>
+
+ <classpath codebase="./lib" archives="jboss-cache.jar, jgroups.jar"/>
+
+
+ <!-- ==================================================================== -->
+ <!-- Defines TreeCache configuration -->
+ <!-- ==================================================================== -->
+
+ <mbean code="org.jboss.cache.jmx.CacheJmxWrapper"
+ name="jboss.cache:service=TreeCache">
+
+ <depends>jboss:service=Naming</depends>
+ <depends>jboss:service=TransactionManager</depends>
+
+ <!-- TransactionManager configuration not required for Hibernate!
+ Hibernate will plug in its own transaction manager integration.
+ -->
+
+ <!-- Node locking scheme:
+ OPTIMISTIC
+ PESSIMISTIC (default)
+ -->
+ <attribute name="NodeLockingScheme">PESSIMISTIC</attribute>
+
+ <!--
+ Isolation level : SERIALIZABLE
+ REPEATABLE_READ (default)
+ READ_COMMITTED
+ READ_UNCOMMITTED
+ NONE
+ -->
+ <attribute name="IsolationLevel">REPEATABLE_READ</attribute>
+
+ <!-- Valid modes are LOCAL
+ REPL_ASYNC
+ REPL_SYNC
+ INVALIDATION_ASYNC
+ INVALIDATION_SYNC
+
+ INVALIDATION_SYNC is highly recommended as the mode for use
+ with entity and collection caches.
+ -->
+ <attribute name="CacheMode">REPL_SYNC</attribute>
+
+ <!-- Name of cluster. Needs to be the same for all members, in order
+ to find each other -->
+ <attribute name="ClusterName">TestSharedCache</attribute>
+
+ <!-- Use a UDP (multicast) based stack. Need JGroups flow control (FC)
+ because timestamp communication will not require a synchronous response.
+ -->
+ <attribute name="MultiplexerStack">udp</attribute>
+
+ <!-- Used for timestamps, so must fetch state. -->
+ <attribute name="FetchInMemoryState">true</attribute>
+
+ <!--
+ The max amount of time (in milliseconds) we wait until the
+ state (ie. the contents of the cache) are retrieved from
+ existing members at startup.
+ -->
+ <attribute name="StateRetrievalTimeout">20000</attribute>
+
+ <!--
+ Number of milliseconds to wait until all responses for a
+ synchronous call have been received.
+ -->
+ <attribute name="SyncReplTimeout">20000</attribute>
+
+ <!-- Max number of milliseconds to wait for a lock acquisition -->
+ <attribute name="LockAcquisitionTimeout">15000</attribute>
+
+ <!--
+ Indicate whether to use marshalling or not. Set this to true if you
+ are running under a scoped class loader, e.g., inside an application
+ server. Default is "false".
+ -->
+ <attribute name="UseRegionBasedMarshalling">true</attribute>
+ <!-- Must match the value of "useRegionBasedMarshalling" -->
+ <attribute name="InactiveOnStartup">true</attribute>
+
+ <!-- Specific eviction policy configurations. This is LRU -->
+ <attribute name="EvictionPolicyConfig">
+ <config>
+ <attribute name="wakeUpIntervalSeconds">5</attribute>
+ <!-- Name of the DEFAULT eviction policy class. -->
+ <attribute name="policyClass">org.jboss.cache.eviction.LRUPolicy</attribute>
+ <!-- Cache wide default -->
+ <region name="/_default_">
+ <attribute name="maxNodes">5000</attribute>
+ <attribute name="timeToLiveSeconds">1000</attribute>
+ </region>
+ <!-- Don't ever evict modification timestamps -->
+ <region name="/TS">
+ <attribute name="maxNodes">0</attribute>
+ <attribute name="timeToLiveSeconds">0</attribute>
+ </region>
+ </config>
+ </attribute>
+
+ </mbean>
+
+
+</server>
Property changes on: core/trunk/cache-jbosscache2/src/test/resources/treecache.xml
___________________________________________________________________
Name: svn:executable
+ *
17 years, 3 months
Hibernate SVN: r14100 - in commons-annotations/trunk: src/test/org/hibernate/annotations/common/test/reflection/java and 2 other directories.
by hibernate-commits@lists.jboss.org
Author: nusco
Date: 2007-10-18 15:49:17 -0400 (Thu, 18 Oct 2007)
New Revision: 14100
Modified:
commons-annotations/trunk/
commons-annotations/trunk/src/test/org/hibernate/annotations/common/test/reflection/java/XAnnotatedElementTestCase.java
commons-annotations/trunk/src/test/org/hibernate/annotations/common/test/reflection/java/generics/Dad.java
commons-annotations/trunk/src/test/org/hibernate/annotations/common/test/reflection/java/generics/deep/Dummy.java
commons-annotations/trunk/src/test/org/hibernate/annotations/common/test/reflection/java/generics/deep/DummySubclass.java
commons-annotations/trunk/src/test/org/hibernate/annotations/common/test/reflection/java/generics/deep/GenericSuperclass1.java
commons-annotations/trunk/src/test/org/hibernate/annotations/common/test/reflection/java/generics/deep/GenericSuperclass2.java
commons-annotations/trunk/src/test/org/hibernate/annotations/common/test/reflection/java/generics/deep/Subclass1.java
commons-annotations/trunk/src/test/org/hibernate/annotations/common/test/reflection/java/generics/deep/Subclass2.java
Log:
Removed unused code
Property changes on: commons-annotations/trunk
___________________________________________________________________
Name: svn:ignore
+ .classpath
.project
Modified: commons-annotations/trunk/src/test/org/hibernate/annotations/common/test/reflection/java/XAnnotatedElementTestCase.java
===================================================================
--- commons-annotations/trunk/src/test/org/hibernate/annotations/common/test/reflection/java/XAnnotatedElementTestCase.java 2007-10-18 06:20:04 UTC (rev 14099)
+++ commons-annotations/trunk/src/test/org/hibernate/annotations/common/test/reflection/java/XAnnotatedElementTestCase.java 2007-10-18 19:49:17 UTC (rev 14100)
@@ -1,7 +1,5 @@
package org.hibernate.annotations.common.test.reflection.java;
-import javax.persistence.Transient;
-
import junit.framework.TestCase;
import org.hibernate.annotations.common.reflection.XAnnotatedElement;
import org.hibernate.annotations.common.test.reflection.java.generics.TestAnnotation;
@@ -13,7 +11,7 @@
public void testKnowsWhetherAnAnnotationIsPresent() {
assertTrue( getConcreteInstance().isAnnotationPresent( TestAnnotation.class ) );
- assertFalse( getConcreteInstance().isAnnotationPresent( Transient.class ) );
+ assertFalse( getConcreteInstance().isAnnotationPresent( Override.class ) );
}
public void testReturnsSpecificAnnotations() {
Modified: commons-annotations/trunk/src/test/org/hibernate/annotations/common/test/reflection/java/generics/Dad.java
===================================================================
--- commons-annotations/trunk/src/test/org/hibernate/annotations/common/test/reflection/java/generics/Dad.java 2007-10-18 06:20:04 UTC (rev 14099)
+++ commons-annotations/trunk/src/test/org/hibernate/annotations/common/test/reflection/java/generics/Dad.java 2007-10-18 19:49:17 UTC (rev 14100)
@@ -3,14 +3,11 @@
import java.util.List;
import java.util.Map;
-import javax.persistence.Entity;
-
/**
* @author Davide Marchignoli
* @author Paolo Perrotta
*/
@TestAnnotation(name = "xyz")
-@Entity
public class Dad<T> extends Grandpa<List<T>, Integer> {
static Integer staticField;
Modified: commons-annotations/trunk/src/test/org/hibernate/annotations/common/test/reflection/java/generics/deep/Dummy.java
===================================================================
--- commons-annotations/trunk/src/test/org/hibernate/annotations/common/test/reflection/java/generics/deep/Dummy.java 2007-10-18 06:20:04 UTC (rev 14099)
+++ commons-annotations/trunk/src/test/org/hibernate/annotations/common/test/reflection/java/generics/deep/Dummy.java 2007-10-18 19:49:17 UTC (rev 14100)
@@ -1,14 +1,6 @@
package org.hibernate.annotations.common.test.reflection.java.generics.deep;
-import javax.persistence.MappedSuperclass;
-import javax.persistence.Id;
-
-/**
- *
- */
-@MappedSuperclass
public class Dummy {
- @Id
protected Long id;
private String name;
Modified: commons-annotations/trunk/src/test/org/hibernate/annotations/common/test/reflection/java/generics/deep/DummySubclass.java
===================================================================
--- commons-annotations/trunk/src/test/org/hibernate/annotations/common/test/reflection/java/generics/deep/DummySubclass.java 2007-10-18 06:20:04 UTC (rev 14099)
+++ commons-annotations/trunk/src/test/org/hibernate/annotations/common/test/reflection/java/generics/deep/DummySubclass.java 2007-10-18 19:49:17 UTC (rev 14100)
@@ -1,12 +1,6 @@
package org.hibernate.annotations.common.test.reflection.java.generics.deep;
-import javax.persistence.Entity;
-
import org.hibernate.annotations.common.test.reflection.java.generics.deep.Dummy;
-/**
- *
- */
-@Entity
public class DummySubclass extends Dummy {
}
Modified: commons-annotations/trunk/src/test/org/hibernate/annotations/common/test/reflection/java/generics/deep/GenericSuperclass1.java
===================================================================
--- commons-annotations/trunk/src/test/org/hibernate/annotations/common/test/reflection/java/generics/deep/GenericSuperclass1.java 2007-10-18 06:20:04 UTC (rev 14099)
+++ commons-annotations/trunk/src/test/org/hibernate/annotations/common/test/reflection/java/generics/deep/GenericSuperclass1.java 2007-10-18 19:49:17 UTC (rev 14100)
@@ -1,20 +1,10 @@
package org.hibernate.annotations.common.test.reflection.java.generics.deep;
-import javax.persistence.MappedSuperclass;
-import javax.persistence.OneToOne;
-import javax.persistence.Id;
-
import org.hibernate.annotations.common.test.reflection.java.generics.deep.Dummy;
-/**
- *
- */
-@MappedSuperclass
public class GenericSuperclass1<T extends Dummy> {
- @Id
protected Long id;
- @OneToOne
protected T dummy;
Modified: commons-annotations/trunk/src/test/org/hibernate/annotations/common/test/reflection/java/generics/deep/GenericSuperclass2.java
===================================================================
--- commons-annotations/trunk/src/test/org/hibernate/annotations/common/test/reflection/java/generics/deep/GenericSuperclass2.java 2007-10-18 06:20:04 UTC (rev 14099)
+++ commons-annotations/trunk/src/test/org/hibernate/annotations/common/test/reflection/java/generics/deep/GenericSuperclass2.java 2007-10-18 19:49:17 UTC (rev 14100)
@@ -1,13 +1,7 @@
package org.hibernate.annotations.common.test.reflection.java.generics.deep;
-import javax.persistence.MappedSuperclass;
-
import org.hibernate.annotations.common.test.reflection.java.generics.deep.Dummy;
import org.hibernate.annotations.common.test.reflection.java.generics.deep.GenericSuperclass1;
-/**
- *
- */
-@MappedSuperclass
public class GenericSuperclass2<T extends Dummy> extends GenericSuperclass1<T> {
}
Modified: commons-annotations/trunk/src/test/org/hibernate/annotations/common/test/reflection/java/generics/deep/Subclass1.java
===================================================================
--- commons-annotations/trunk/src/test/org/hibernate/annotations/common/test/reflection/java/generics/deep/Subclass1.java 2007-10-18 06:20:04 UTC (rev 14099)
+++ commons-annotations/trunk/src/test/org/hibernate/annotations/common/test/reflection/java/generics/deep/Subclass1.java 2007-10-18 19:49:17 UTC (rev 14100)
@@ -1,13 +1,7 @@
package org.hibernate.annotations.common.test.reflection.java.generics.deep;
-import javax.persistence.Entity;
-
import org.hibernate.annotations.common.test.reflection.java.generics.deep.DummySubclass;
import org.hibernate.annotations.common.test.reflection.java.generics.deep.GenericSuperclass1;
-/**
- *
- */
-@Entity
public class Subclass1 extends GenericSuperclass1<DummySubclass> {
}
Modified: commons-annotations/trunk/src/test/org/hibernate/annotations/common/test/reflection/java/generics/deep/Subclass2.java
===================================================================
--- commons-annotations/trunk/src/test/org/hibernate/annotations/common/test/reflection/java/generics/deep/Subclass2.java 2007-10-18 06:20:04 UTC (rev 14099)
+++ commons-annotations/trunk/src/test/org/hibernate/annotations/common/test/reflection/java/generics/deep/Subclass2.java 2007-10-18 19:49:17 UTC (rev 14100)
@@ -1,13 +1,7 @@
package org.hibernate.annotations.common.test.reflection.java.generics.deep;
-import javax.persistence.Entity;
-
import org.hibernate.annotations.common.test.reflection.java.generics.deep.DummySubclass;
import org.hibernate.annotations.common.test.reflection.java.generics.deep.GenericSuperclass2;
-/**
- *
- */
-@Entity
public class Subclass2 extends GenericSuperclass2<DummySubclass> {
}
17 years, 3 months
Hibernate SVN: r14099 - core/trunk/core/src/main/java/org/hibernate/id.
by hibernate-commits@lists.jboss.org
Author: gbadner
Date: 2007-10-18 02:20:04 -0400 (Thu, 18 Oct 2007)
New Revision: 14099
Modified:
core/trunk/core/src/main/java/org/hibernate/id/IdentityGenerator.java
Log:
HHH-1312 : Unclosed ResultSet when using Identity
Modified: core/trunk/core/src/main/java/org/hibernate/id/IdentityGenerator.java
===================================================================
--- core/trunk/core/src/main/java/org/hibernate/id/IdentityGenerator.java 2007-10-18 06:17:56 UTC (rev 14098)
+++ core/trunk/core/src/main/java/org/hibernate/id/IdentityGenerator.java 2007-10-18 06:20:04 UTC (rev 14099)
@@ -70,10 +70,19 @@
public Serializable executeAndExtract(PreparedStatement insert) throws SQLException {
insert.executeUpdate();
- return IdentifierGeneratorFactory.getGeneratedIdentity(
- insert.getGeneratedKeys(),
- persister.getIdentifierType()
- );
+ ResultSet rs = null;
+ try {
+ rs = insert.getGeneratedKeys();
+ return IdentifierGeneratorFactory.getGeneratedIdentity(
+ rs,
+ persister.getIdentifierType()
+ );
+ }
+ finally {
+ if ( rs != null ) {
+ rs.close();
+ }
+ }
}
}
17 years, 3 months
Hibernate SVN: r14098 - core/branches/Branch_3_2/src/org/hibernate/id.
by hibernate-commits@lists.jboss.org
Author: gbadner
Date: 2007-10-18 02:17:56 -0400 (Thu, 18 Oct 2007)
New Revision: 14098
Modified:
core/branches/Branch_3_2/src/org/hibernate/id/IdentityGenerator.java
Log:
HHH-1312 : Unclosed ResultSet when using Identity
Modified: core/branches/Branch_3_2/src/org/hibernate/id/IdentityGenerator.java
===================================================================
--- core/branches/Branch_3_2/src/org/hibernate/id/IdentityGenerator.java 2007-10-17 20:59:49 UTC (rev 14097)
+++ core/branches/Branch_3_2/src/org/hibernate/id/IdentityGenerator.java 2007-10-18 06:17:56 UTC (rev 14098)
@@ -71,10 +71,19 @@
public Serializable executeAndExtract(PreparedStatement insert) throws SQLException {
insert.executeUpdate();
- return IdentifierGeneratorFactory.getGeneratedIdentity(
- GetGeneratedKeysHelper.getGeneratedKey( insert ),
- persister.getIdentifierType()
- );
+ ResultSet rs = null;
+ try {
+ rs = GetGeneratedKeysHelper.getGeneratedKey( insert );
+ return IdentifierGeneratorFactory.getGeneratedIdentity(
+ rs,
+ persister.getIdentifierType()
+ );
+ }
+ finally {
+ if ( rs != null ) {
+ rs.close();
+ }
+ }
}
}
17 years, 3 months
Hibernate SVN: r14097 - in core/branches/Branch_3_2: src/org/hibernate/hql/ast/tree and 1 other directories.
by hibernate-commits@lists.jboss.org
Author: steve.ebersole(a)jboss.com
Date: 2007-10-17 16:59:49 -0400 (Wed, 17 Oct 2007)
New Revision: 14097
Added:
core/branches/Branch_3_2/src/org/hibernate/hql/ast/tree/AbstractNullnessCheckNode.java
core/branches/Branch_3_2/src/org/hibernate/hql/ast/tree/IsNotNullLogicOperatorNode.java
core/branches/Branch_3_2/src/org/hibernate/hql/ast/tree/IsNullLogicOperatorNode.java
Modified:
core/branches/Branch_3_2/src/org/hibernate/hql/ast/SqlASTFactory.java
core/branches/Branch_3_2/src/org/hibernate/hql/ast/tree/UnaryLogicOperatorNode.java
core/branches/Branch_3_2/test/org/hibernate/test/hql/ASTParserLoadingTest.java
Log:
HHH-2826 : (HQL) <component> is [not] null
Modified: core/branches/Branch_3_2/src/org/hibernate/hql/ast/SqlASTFactory.java
===================================================================
--- core/branches/Branch_3_2/src/org/hibernate/hql/ast/SqlASTFactory.java 2007-10-17 20:59:18 UTC (rev 14096)
+++ core/branches/Branch_3_2/src/org/hibernate/hql/ast/SqlASTFactory.java 2007-10-17 20:59:49 UTC (rev 14097)
@@ -1,13 +1,18 @@
// $Id$
package org.hibernate.hql.ast;
+import java.lang.reflect.Constructor;
+
import antlr.ASTFactory;
import antlr.Token;
import antlr.collections.AST;
+
import org.hibernate.hql.antlr.HqlSqlTokenTypes;
import org.hibernate.hql.ast.tree.AggregateNode;
+import org.hibernate.hql.ast.tree.BetweenOperatorNode;
import org.hibernate.hql.ast.tree.BinaryArithmeticOperatorNode;
import org.hibernate.hql.ast.tree.BinaryLogicOperatorNode;
+import org.hibernate.hql.ast.tree.BooleanLiteralNode;
import org.hibernate.hql.ast.tree.Case2Node;
import org.hibernate.hql.ast.tree.CaseNode;
import org.hibernate.hql.ast.tree.CollectionFunction;
@@ -19,10 +24,14 @@
import org.hibernate.hql.ast.tree.FromElement;
import org.hibernate.hql.ast.tree.IdentNode;
import org.hibernate.hql.ast.tree.ImpliedFromElement;
+import org.hibernate.hql.ast.tree.InLogicOperatorNode;
import org.hibernate.hql.ast.tree.IndexNode;
import org.hibernate.hql.ast.tree.InitializeableNode;
import org.hibernate.hql.ast.tree.InsertStatement;
import org.hibernate.hql.ast.tree.IntoClause;
+import org.hibernate.hql.ast.tree.IsNotNullLogicOperatorNode;
+import org.hibernate.hql.ast.tree.IsNullLogicOperatorNode;
+import org.hibernate.hql.ast.tree.JavaConstantNode;
import org.hibernate.hql.ast.tree.LiteralNode;
import org.hibernate.hql.ast.tree.MethodNode;
import org.hibernate.hql.ast.tree.OrderByClause;
@@ -30,19 +39,13 @@
import org.hibernate.hql.ast.tree.QueryNode;
import org.hibernate.hql.ast.tree.SelectClause;
import org.hibernate.hql.ast.tree.SelectExpressionImpl;
+import org.hibernate.hql.ast.tree.SessionFactoryAwareNode;
import org.hibernate.hql.ast.tree.SqlFragment;
import org.hibernate.hql.ast.tree.SqlNode;
import org.hibernate.hql.ast.tree.UnaryArithmeticNode;
+import org.hibernate.hql.ast.tree.UnaryLogicOperatorNode;
import org.hibernate.hql.ast.tree.UpdateStatement;
-import org.hibernate.hql.ast.tree.BetweenOperatorNode;
-import org.hibernate.hql.ast.tree.UnaryLogicOperatorNode;
-import org.hibernate.hql.ast.tree.InLogicOperatorNode;
-import org.hibernate.hql.ast.tree.JavaConstantNode;
-import org.hibernate.hql.ast.tree.SessionFactoryAwareNode;
-import org.hibernate.hql.ast.tree.BooleanLiteralNode;
-import java.lang.reflect.Constructor;
-
/**
* Custom AST factory the intermediate tree that causes ANTLR to create specialized
* AST nodes, given the AST node type (from HqlSqlTokenTypes). HqlSqlWalker registers
@@ -157,7 +160,9 @@
case NOT_BETWEEN:
return BetweenOperatorNode.class;
case IS_NULL:
+ return IsNullLogicOperatorNode.class;
case IS_NOT_NULL:
+ return IsNotNullLogicOperatorNode.class;
case EXISTS:
return UnaryLogicOperatorNode.class;
default:
Added: core/branches/Branch_3_2/src/org/hibernate/hql/ast/tree/AbstractNullnessCheckNode.java
===================================================================
--- core/branches/Branch_3_2/src/org/hibernate/hql/ast/tree/AbstractNullnessCheckNode.java (rev 0)
+++ core/branches/Branch_3_2/src/org/hibernate/hql/ast/tree/AbstractNullnessCheckNode.java 2007-10-17 20:59:49 UTC (rev 14097)
@@ -0,0 +1,133 @@
+/*
+ * Copyright (c) 2007, Red Hat Middleware, LLC. All rights reserved.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, v. 2.1. This program is distributed in the
+ * hope that it will be useful, but WITHOUT A WARRANTY; without even the implied
+ * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details. You should have received a
+ * copy of the GNU Lesser General Public License, v.2.1 along with this
+ * distribution; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Red Hat Author(s): Steve Ebersole
+ */
+package org.hibernate.hql.ast.tree;
+
+import antlr.collections.AST;
+
+import org.hibernate.type.Type;
+import org.hibernate.engine.SessionFactoryImplementor;
+import org.hibernate.hql.antlr.HqlSqlTokenTypes;
+import org.hibernate.util.StringHelper;
+import org.hibernate.HibernateException;
+
+/**
+ * AbstractNullnessCheckNode implementation
+ *
+ * @author Steve Ebersole
+ */
+public abstract class AbstractNullnessCheckNode extends UnaryLogicOperatorNode {
+ public void initialize() {
+ // TODO : this really needs to be delayed unitl after we definitively know the operand node type;
+ // where this is currently a problem is parameters for which where we cannot unequivocally
+ // resolve an expected type
+ Type operandType = extractDataType( getOperand() );
+ if ( operandType == null ) {
+ return;
+ }
+ SessionFactoryImplementor sessionFactory = getSessionFactoryHelper().getFactory();
+ int operandColumnSpan = operandType.getColumnSpan( sessionFactory );
+ if ( operandColumnSpan > 1 ) {
+ mutateRowValueConstructorSyntax( operandColumnSpan );
+ }
+ }
+
+ protected abstract int getExpansionConnectorType();
+ protected abstract String getExpansionConnectorText();
+
+ private void mutateRowValueConstructorSyntax(int operandColumnSpan) {
+ final int comparisonType = getType();
+ final String comparisonText = getText();
+
+ final int expansionConnectorType = getExpansionConnectorType();
+ final String expansionConnectorText = getExpansionConnectorText();
+
+ setType( expansionConnectorType );
+ setText( expansionConnectorText );
+
+ String[] mutationTexts = extractMutationTexts( getOperand(), operandColumnSpan );
+
+ AST container = this;
+ for ( int i = operandColumnSpan - 1; i > 0; i-- ) {
+ if ( i == 1 ) {
+ AST op1 = getASTFactory().create( comparisonType, comparisonText );
+ AST operand1 = getASTFactory().create( HqlSqlTokenTypes.SQL_TOKEN, mutationTexts[0] );
+ op1.setFirstChild( operand1 );
+ container.setFirstChild( op1 );
+ AST op2 = getASTFactory().create( comparisonType, comparisonText );
+ AST operand2 = getASTFactory().create( HqlSqlTokenTypes.SQL_TOKEN, mutationTexts[1] );
+ op2.setFirstChild( operand2 );
+ op1.setNextSibling( op2 );
+ }
+ else {
+ AST op = getASTFactory().create( comparisonType, comparisonText );
+ AST operand = getASTFactory().create( HqlSqlTokenTypes.SQL_TOKEN, mutationTexts[i] );
+ op.setFirstChild( operand );
+ AST newContainer = getASTFactory().create( expansionConnectorType, expansionConnectorText );
+ container.setFirstChild( newContainer );
+ newContainer.setNextSibling( op );
+ container = newContainer;
+ }
+ }
+ }
+
+ protected Type extractDataType(Node operand) {
+ Type type = null;
+ if ( operand instanceof SqlNode ) {
+ type = ( ( SqlNode ) operand ).getDataType();
+ }
+ if ( type == null && operand instanceof ExpectedTypeAwareNode ) {
+ type = ( ( ExpectedTypeAwareNode ) operand ).getExpectedType();
+ }
+ return type;
+ }
+
+ private static String[] extractMutationTexts(Node operand, int count) {
+ if ( operand instanceof ParameterNode ) {
+ String[] rtn = new String[count];
+ for ( int i = 0; i < count; i++ ) {
+ rtn[i] = "?";
+ }
+ return rtn;
+ }
+ else if ( operand.getType() == HqlSqlTokenTypes.VECTOR_EXPR ) {
+ String[] rtn = new String[ operand.getNumberOfChildren() ];
+ int x = 0;
+ AST node = operand.getFirstChild();
+ while ( node != null ) {
+ rtn[ x++ ] = node.getText();
+ node = node.getNextSibling();
+ }
+ return rtn;
+ }
+ else if ( operand instanceof SqlNode ) {
+ String nodeText = operand.getText();
+ if ( nodeText.startsWith( "(" ) ) {
+ nodeText = nodeText.substring( 1 );
+ }
+ if ( nodeText.endsWith( ")" ) ) {
+ nodeText = nodeText.substring( 0, nodeText.length() - 1 );
+ }
+ String[] splits = StringHelper.split( ", ", nodeText );
+ if ( count != splits.length ) {
+ throw new HibernateException( "SqlNode's text did not reference expected number of columns" );
+ }
+ return splits;
+ }
+ else {
+ throw new HibernateException( "dont know how to extract row value elements from node : " + operand );
+ }
+ }
+}
Added: core/branches/Branch_3_2/src/org/hibernate/hql/ast/tree/IsNotNullLogicOperatorNode.java
===================================================================
--- core/branches/Branch_3_2/src/org/hibernate/hql/ast/tree/IsNotNullLogicOperatorNode.java (rev 0)
+++ core/branches/Branch_3_2/src/org/hibernate/hql/ast/tree/IsNotNullLogicOperatorNode.java 2007-10-17 20:59:49 UTC (rev 14097)
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2007, Red Hat Middleware, LLC. All rights reserved.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, v. 2.1. This program is distributed in the
+ * hope that it will be useful, but WITHOUT A WARRANTY; without even the implied
+ * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details. You should have received a
+ * copy of the GNU Lesser General Public License, v.2.1 along with this
+ * distribution; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Red Hat Author(s): Steve Ebersole
+ */
+package org.hibernate.hql.ast.tree;
+
+import org.hibernate.hql.antlr.HqlSqlTokenTypes;
+
+/**
+ * IsNotNullLogicOperatorNode implementation
+ *
+ * @author Steve Ebersole
+ */
+public class IsNotNullLogicOperatorNode extends AbstractNullnessCheckNode {
+ protected int getExpansionConnectorType() {
+ return HqlSqlTokenTypes.OR;
+ }
+
+ protected String getExpansionConnectorText() {
+ return "OR";
+ }
+}
Added: core/branches/Branch_3_2/src/org/hibernate/hql/ast/tree/IsNullLogicOperatorNode.java
===================================================================
--- core/branches/Branch_3_2/src/org/hibernate/hql/ast/tree/IsNullLogicOperatorNode.java (rev 0)
+++ core/branches/Branch_3_2/src/org/hibernate/hql/ast/tree/IsNullLogicOperatorNode.java 2007-10-17 20:59:49 UTC (rev 14097)
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2007, Red Hat Middleware, LLC. All rights reserved.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, v. 2.1. This program is distributed in the
+ * hope that it will be useful, but WITHOUT A WARRANTY; without even the implied
+ * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details. You should have received a
+ * copy of the GNU Lesser General Public License, v.2.1 along with this
+ * distribution; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Red Hat Author(s): Steve Ebersole
+ */
+package org.hibernate.hql.ast.tree;
+
+import org.hibernate.hql.antlr.HqlSqlTokenTypes;
+
+/**
+ * Represents a 'is null' check.
+ *
+ * @author Steve Ebersole
+ */
+public class IsNullLogicOperatorNode extends AbstractNullnessCheckNode {
+ protected int getExpansionConnectorType() {
+ return HqlSqlTokenTypes.AND;
+ }
+
+ protected String getExpansionConnectorText() {
+ return "AND";
+ }
+}
Modified: core/branches/Branch_3_2/src/org/hibernate/hql/ast/tree/UnaryLogicOperatorNode.java
===================================================================
--- core/branches/Branch_3_2/src/org/hibernate/hql/ast/tree/UnaryLogicOperatorNode.java 2007-10-17 20:59:18 UTC (rev 14096)
+++ core/branches/Branch_3_2/src/org/hibernate/hql/ast/tree/UnaryLogicOperatorNode.java 2007-10-17 20:59:49 UTC (rev 14097)
@@ -4,9 +4,11 @@
import org.hibernate.Hibernate;
/**
- * @author <a href="mailto:steve@hibernate.org">Steve Ebersole </a>
+ * Represents a unary operator node.
+ *
+ * @author Steve Ebersole
*/
-public class UnaryLogicOperatorNode extends SqlNode implements UnaryOperatorNode {
+public class UnaryLogicOperatorNode extends HqlSqlWalkerNode implements UnaryOperatorNode {
public Node getOperand() {
return ( Node ) getFirstChild();
}
Modified: core/branches/Branch_3_2/test/org/hibernate/test/hql/ASTParserLoadingTest.java
===================================================================
--- core/branches/Branch_3_2/test/org/hibernate/test/hql/ASTParserLoadingTest.java 2007-10-17 20:59:18 UTC (rev 14096)
+++ core/branches/Branch_3_2/test/org/hibernate/test/hql/ASTParserLoadingTest.java 2007-10-17 20:59:49 UTC (rev 14097)
@@ -101,6 +101,41 @@
return new FunctionalTestClassTestSuite( ASTParserLoadingTest.class );
}
+ public void testComponentNullnessChecks() {
+ Session s = openSession();
+ s.beginTransaction();
+ Human h = new Human();
+ h.setName( new Name( "Johnny", 'B', "Goode" ) );
+ s.save( h );
+ h = new Human();
+ h.setName( new Name( "Steve", null, "Ebersole" ) );
+ s.save( h );
+ h = new Human();
+ h.setName( new Name( "Bono", null, null ) );
+ s.save( h );
+ h = new Human();
+ h.setName( new Name( null, null, null ) );
+ s.save( h );
+ s.getTransaction().commit();
+ s.close();
+
+ s = openSession();
+ s.beginTransaction();
+ List results = s.createQuery( "from Human where name is null" ).list();
+ assertEquals( 1, results.size() );
+ results = s.createQuery( "from Human where name is not null" ).list();
+ assertEquals( 3, results.size() );
+ s.createQuery( "from Human where ? is null" ).setParameter( 0, null ).list();
+ s.getTransaction().commit();
+ s.close();
+
+ s = openSession();
+ s.beginTransaction();
+ s.createQuery( "delete Human" ).executeUpdate();
+ s.getTransaction().commit();
+ s.close();
+ }
+
public void testInvalidCollectionDereferencesFail() {
Session s = openSession();
s.beginTransaction();
17 years, 3 months