ISPN-7350 Read only entities can be inserted and deleted

This commit is contained in:
Galder Zamarreño 2012-05-24 21:11:11 +02:00
parent af554fe59b
commit 61a8416463
11 changed files with 138 additions and 293 deletions

View File

@ -25,11 +25,10 @@ public class CollectionRegionImpl extends BaseTransactionalDataRegion implements
}
public CollectionRegionAccessStrategy buildAccessStrategy(AccessType accessType) throws CacheException {
if (AccessType.READ_ONLY.equals(accessType)) {
return new ReadOnlyAccess(this);
} else if (AccessType.TRANSACTIONAL.equals(accessType)) {
if (AccessType.READ_ONLY.equals(accessType)
|| AccessType.TRANSACTIONAL.equals(accessType))
return new TransactionalAccess(this);
}
throw new CacheException("Unsupported access type [" + accessType.getExternalName() + "]");
}

View File

@ -1,42 +0,0 @@
package org.hibernate.cache.infinispan.collection;
import org.infinispan.util.logging.Log;
import org.infinispan.util.logging.LogFactory;
import org.hibernate.cache.CacheException;
import org.hibernate.cache.spi.access.SoftLock;
/**
* This defines the strategy for transactional access to collection data in a
* Infinispan instance.
* <p/>
* The read-only access to a Infinispan really is still transactional, just with
* the extra semantic or guarantee that we will not update data.
*
* @author Chris Bredesen
* @author Galder Zamarreño
* @since 3.5
*/
class ReadOnlyAccess extends TransactionalAccess {
private static final Log log = LogFactory.getLog(ReadOnlyAccess.class);
ReadOnlyAccess(CollectionRegionImpl region) {
super(region);
}
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");
}
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 item");
}
}

View File

@ -1,8 +1,5 @@
package org.hibernate.cache.infinispan.entity;
import org.infinispan.util.logging.Log;
import org.infinispan.util.logging.LogFactory;
import org.hibernate.cache.CacheException;
import org.hibernate.cache.spi.access.SoftLock;
@ -15,36 +12,21 @@ import org.hibernate.cache.spi.access.SoftLock;
* @since 3.5
*/
class ReadOnlyAccess extends TransactionalAccess {
private static final Log log = LogFactory.getLog(ReadOnlyAccess.class);
ReadOnlyAccess(EntityRegionImpl region) {
super(region);
}
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 item");
}
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 item");
}
@Override
public boolean update(Object key, Object value, Object currentVersion, Object previousVersion) throws CacheException {
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 {
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");
}
}

View File

@ -51,12 +51,6 @@ public class CollectionRegionImplTestCase extends AbstractEntityCollectionRegion
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");

View File

@ -1,63 +0,0 @@
/*
* JBoss, Home of Professional Open Source.
* Copyright 2009, Red Hat, Inc. and/or it's affiliates, and individual contributors
* as indicated by the @author tags. See the copyright.txt file in the
* distribution for a full listing of individual contributors.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY 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 along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
package org.hibernate.test.cache.infinispan.collection;
import org.junit.Test;
import org.hibernate.cache.spi.access.AccessType;
import static org.junit.Assert.fail;
/**
* ReadOnlyExtraAPITestCase.
*
* @author Galder Zamarreño
* @since 3.5
*/
public class ReadOnlyExtraAPITestCase extends TransactionalExtraAPITestCase {
@Override
protected AccessType getAccessType() {
return AccessType.READ_ONLY;
}
@Test
@Override
public void testLockItem() {
try {
getCollectionAccessStrategy().lockItem( KEY, new Integer( 1 ) );
fail( "Call to lockItem did not throw exception" );
}
catch (UnsupportedOperationException expected) {
}
}
@Test
@Override
public void testLockRegion() {
try {
getCollectionAccessStrategy().lockRegion();
fail( "Call to lockRegion did not throw exception" );
}
catch (UnsupportedOperationException expected) {
}
}
}

View File

@ -30,64 +30,58 @@ import org.hibernate.cache.spi.access.AccessType;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.fail;
/**
* Base class for tests of TRANSACTIONAL access.
*
*
* @author Galder Zamarreño
* @since 3.5
*/
public abstract class AbstractReadOnlyAccessTestCase extends AbstractEntityRegionAccessStrategyTestCase {
@Override
protected AccessType getAccessType() {
return AccessType.READ_ONLY;
}
@Test
@Override
public void testPutFromLoad() throws Exception {
putFromLoadTest(false);
}
@Override
protected AccessType getAccessType() {
return AccessType.READ_ONLY;
}
@Test
@Override
public void testPutFromLoadMinimal() throws Exception {
putFromLoadTest(true);
}
private void putFromLoadTest(boolean minimal) throws Exception {
final String KEY = KEY_BASE + testCount++;
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()));
}
@Test
@Override
public void testPutFromLoad() throws Exception {
putFromLoadTest(false);
}
@Test
@Override
public void testUpdate() throws Exception {
final String KEY = KEY_BASE + testCount++;
try {
localAccessStrategy.update(KEY, VALUE2, new Integer(2), new Integer(1));
fail("Call to update did not throw exception");
}
catch (UnsupportedOperationException good) {}
}
@Test
@Override
public void testPutFromLoadMinimal() throws Exception {
putFromLoadTest(true);
}
private void putFromLoadTest(boolean minimal) throws Exception {
final String KEY = KEY_BASE + testCount++;
long txTimestamp = System.currentTimeMillis();
BatchModeTransactionManager.getInstance().begin();
assertNull(localAccessStrategy.get(KEY, System.currentTimeMillis()));
if (minimal)
localAccessStrategy.putFromLoad(KEY, VALUE1, txTimestamp, 1, true);
else
localAccessStrategy.putFromLoad(KEY, VALUE1, txTimestamp, 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()));
}
@Test(expected = UnsupportedOperationException.class)
@Override
public void testUpdate() throws Exception {
localAccessStrategy.update(KEY_BASE + testCount++,
VALUE2, 2, 1);
}
}

View File

@ -50,13 +50,8 @@ public class EntityRegionImplTestCase extends AbstractEntityCollectionRegionTest
@Override
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) {
}
assertNull("Got TRANSACTIONAL",
region.buildAccessStrategy(AccessType.TRANSACTIONAL).lockRegion());
try {
region.buildAccessStrategy(AccessType.NONSTRICT_READ_WRITE);
@ -73,7 +68,7 @@ public class EntityRegionImplTestCase extends AbstractEntityCollectionRegionTest
@Override
protected void putInRegion(Region region, Object key, Object value) {
((EntityRegion) region).buildAccessStrategy(AccessType.TRANSACTIONAL).insert(key, value, new Integer(1));
((EntityRegion) region).buildAccessStrategy(AccessType.TRANSACTIONAL).insert(key, value, 1);
}
@Override

View File

@ -40,36 +40,11 @@ public class ReadOnlyExtraAPITestCase extends TransactionalExtraAPITestCase {
return AccessType.READ_ONLY;
}
@Override
public void testLockItem() {
try {
getEntityAccessStrategy().lockItem( KEY, Integer.valueOf( 1 ) );
fail( "Call to lockItem did not throw exception" );
}
catch (UnsupportedOperationException expected) {
}
}
@Override
public void testLockRegion() {
try {
getEntityAccessStrategy().lockRegion();
fail( "Call to lockRegion did not throw exception" );
}
catch (UnsupportedOperationException expected) {
}
}
@Override
public void testAfterUpdate() {
try {
getEntityAccessStrategy().afterUpdate(
KEY,
VALUE2,
Integer.valueOf( 1 ),
Integer.valueOf( 2 ),
new MockSoftLock()
);
KEY, VALUE2, 1, 2, new MockSoftLock());
fail( "Call to afterUpdate did not throw exception" );
}
catch (UnsupportedOperationException expected) {

View File

@ -0,0 +1,75 @@
package org.hibernate.test.cache.infinispan.functional;
import org.hibernate.Session;
import org.hibernate.stat.SecondLevelCacheStatistics;
import org.hibernate.stat.Statistics;
import org.infinispan.util.logging.Log;
import org.infinispan.util.logging.LogFactory;
import org.junit.Test;
import java.util.Map;
import java.util.concurrent.Callable;
import static org.infinispan.test.TestingUtil.withTx;
import static org.junit.Assert.assertEquals;
/**
* Parent tests for both transactional and
* read-only tests are defined in this class.
*
* @author Galder Zamarreño
* @since 4.1
*/
public abstract class AbstractFunctionalTestCase extends SingleNodeTestCase {
static final Log log = LogFactory.getLog(AbstractFunctionalTestCase.class);
@Test
public void testEmptySecondLevelCacheEntry() throws Exception {
sessionFactory().getCache().evictCollectionRegion( Item.class.getName() + ".items" );
Statistics stats = sessionFactory().getStatistics();
stats.clear();
SecondLevelCacheStatistics statistics = stats.getSecondLevelCacheStatistics( Item.class.getName() + ".items" );
Map cacheEntries = statistics.getEntries();
assertEquals( 0, cacheEntries.size() );
}
@Test
public void testInsertDeleteEntity() throws Exception {
final Statistics stats = sessionFactory().getStatistics();
stats.clear();
final Item item = new Item( "chris", "Chris's Item" );
withTx(tm, new Callable<Void>() {
@Override
public Void call() throws Exception {
Session s = openSession();
s.getTransaction().begin();
s.persist(item);
s.getTransaction().commit();
s.close();
return null;
}
});
log.info("Entry persisted, let's load and delete it.");
withTx(tm, new Callable<Void>() {
@Override
public Void call() throws Exception {
Session s = openSession();
s.getTransaction().begin();
Item found = (Item) s.load(Item.class, item.getId());
log.info(stats.toString());
assertEquals(item.getDescription(), found.getDescription());
assertEquals(0, stats.getSecondLevelCacheMissCount());
assertEquals(1, stats.getSecondLevelCacheHitCount());
s.delete(found);
s.getTransaction().commit();
s.close();
return null;
}
});
}
}

View File

@ -23,33 +23,17 @@
*/
package org.hibernate.test.cache.infinispan.functional;
import java.util.Map;
import org.junit.Test;
import org.hibernate.stat.SecondLevelCacheStatistics;
import org.hibernate.stat.Statistics;
import static org.junit.Assert.assertEquals;
/**
* Functional entity read-only tests.
*
* @author Galder Zamarreño
* @since 3.5
*/
public class BasicReadOnlyTestCase extends SingleNodeTestCase {
@Override
public class BasicReadOnlyTestCase extends AbstractFunctionalTestCase {
@Override
public String getCacheConcurrencyStrategy() {
return "read-only";
}
@Test
public void testEmptySecondLevelCacheEntry() throws Exception {
sessionFactory().getCache().evictEntityRegion( Item.class.getName() );
Statistics stats = sessionFactory().getStatistics();
stats.clear();
SecondLevelCacheStatistics statistics = stats.getSecondLevelCacheStatistics( Item.class.getName() + ".items" );
Map cacheEntries = statistics.getEntries();
assertEquals( 0, cacheEntries.size() );
}
}

View File

@ -33,8 +33,6 @@ import org.hibernate.Criteria;
import org.hibernate.NaturalIdLoadAccess;
import org.hibernate.cache.infinispan.access.PutFromLoadValidator;
import org.hibernate.criterion.Restrictions;
import org.infinispan.util.logging.Log;
import org.infinispan.util.logging.LogFactory;
import org.junit.After;
import org.junit.Test;
@ -51,13 +49,13 @@ import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
/**
* Functional entity transactional tests.
*
* @author Galder Zamarreño
* @since 3.5
*/
public class BasicTransactionalTestCase extends SingleNodeTestCase {
private static final Log log = LogFactory.getLog( BasicTransactionalTestCase.class );
public class BasicTransactionalTestCase extends AbstractFunctionalTestCase {
@Override
public void configure(Configuration cfg) {
@ -90,42 +88,6 @@ public class BasicTransactionalTestCase extends SingleNodeTestCase {
});
}
@Test
public void testEntityCache() throws Exception {
final Statistics stats = sessionFactory().getStatistics();
stats.clear();
final Item item = new Item( "chris", "Chris's Item" );
withTx(tm, new Callable<Void>() {
@Override
public Void call() throws Exception {
Session s = openSession();
s.getTransaction().begin();
s.persist( item );
s.getTransaction().commit();
s.close();
return null;
}
});
log.info("Entry persisted, let's load and delete it.");
withTx(tm, new Callable<Void>() {
@Override
public Void call() throws Exception {
Session s = openSession();
Item found = (Item) s.load(Item.class, item.getId());
log.info(stats.toString());
assertEquals(item.getDescription(), found.getDescription());
assertEquals(0, stats.getSecondLevelCacheMissCount());
assertEquals(1, stats.getSecondLevelCacheHitCount());
s.delete(found);
s.close();
return null;
}
});
}
@Test
public void testCollectionCache() throws Exception {
final Statistics stats = sessionFactory().getStatistics();
@ -452,16 +414,6 @@ public class BasicTransactionalTestCase extends SingleNodeTestCase {
}
}
@Test
public void testEmptySecondLevelCacheEntry() throws Exception {
sessionFactory().getCache().evictCollectionRegion( Item.class.getName() + ".items" );
Statistics stats = sessionFactory().getStatistics();
stats.clear();
SecondLevelCacheStatistics statistics = stats.getSecondLevelCacheStatistics( Item.class.getName() + ".items" );
Map cacheEntries = statistics.getEntries();
assertEquals( 0, cacheEntries.size() );
}
@Test
public void testNaturalIdCached() throws Exception {
saveSomeCitizens();