#ignite-1008: Add check for transactions in cache start/stop.
Project: http://git-wip-us.apache.org/repos/asf/incubator-ignite/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-ignite/commit/0be4becc Tree: http://git-wip-us.apache.org/repos/asf/incubator-ignite/tree/0be4becc Diff: http://git-wip-us.apache.org/repos/asf/incubator-ignite/diff/0be4becc Branch: refs/heads/ignite-484-1 Commit: 0be4becc99be9db8de840f0502703e278eb9f5b1 Parents: 2b63ff8 Author: ivasilinets <ivasilin...@gridgain.com> Authored: Thu Jun 11 22:33:25 2015 +0300 Committer: ivasilinets <ivasilin...@gridgain.com> Committed: Thu Jun 11 22:34:37 2015 +0300 ---------------------------------------------------------------------- .../processors/cache/GridCacheProcessor.java | 18 ++ ...teStartCacheInTransactionAtomicSelfTest.java | 32 +++ .../IgniteStartCacheInTransactionSelfTest.java | 254 +++++++++++++++++++ .../testsuites/IgniteCacheTestSuite4.java | 3 + 4 files changed, 307 insertions(+) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/0be4becc/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheProcessor.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheProcessor.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheProcessor.java index 9b16388..28341ad 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheProcessor.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheProcessor.java @@ -1874,6 +1874,8 @@ public class GridCacheProcessor extends GridProcessorAdapter { CacheType cacheType, boolean failIfExists ) { + checkEmptyTransactions(); + assert ccfg != null || nearCfg != null; DynamicCacheDescriptor desc = registeredCaches.get(maskNull(cacheName)); @@ -1964,6 +1966,8 @@ public class GridCacheProcessor extends GridProcessorAdapter { * @return Future that will be completed when cache is stopped. */ public IgniteInternalFuture<?> dynamicStopCache(String cacheName) { + checkEmptyTransactions(); + DynamicCacheChangeRequest t = new DynamicCacheChangeRequest(cacheName, ctx.localNodeId(), true); return F.first(initiateCacheChanges(F.asList(t), false)); @@ -2647,6 +2651,8 @@ public class GridCacheProcessor extends GridProcessorAdapter { * @throws IgniteCheckedException If failed. */ private IgniteCacheProxy startJCache(String cacheName, boolean failIfNotStarted) throws IgniteCheckedException { + checkEmptyTransactions(); + String masked = maskNull(cacheName); DynamicCacheDescriptor desc = registeredCaches.get(masked); @@ -2944,6 +2950,18 @@ public class GridCacheProcessor extends GridProcessorAdapter { } /** + * @throws IgniteException If transaction exist. + */ + private void checkEmptyTransactions() throws IgniteException { + if (transactions().tx() != null) + throw new IgniteException("Cannot start/stop cache within transaction."); + + if (ctx.cache().context().mvcc(). + lastExplicitLockTopologyVersion(Thread.currentThread().getId()) != null) + throw new IgniteException("Cannot start/stop cache within lock."); + } + + /** * @param val Object to check. * @throws IgniteCheckedException If validation failed. */ http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/0be4becc/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/IgniteStartCacheInTransactionAtomicSelfTest.java ---------------------------------------------------------------------- diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/IgniteStartCacheInTransactionAtomicSelfTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/IgniteStartCacheInTransactionAtomicSelfTest.java new file mode 100644 index 0000000..17320eb --- /dev/null +++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/IgniteStartCacheInTransactionAtomicSelfTest.java @@ -0,0 +1,32 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.ignite.internal.processors.cache; + +import org.apache.ignite.cache.*; + +import static org.apache.ignite.cache.CacheAtomicityMode.*; + +/** + * Check starting cache in transaction. + */ +public class IgniteStartCacheInTransactionAtomicSelfTest extends IgniteStartCacheInTransactionSelfTest { + /** {@inheritDoc} */ + @Override public CacheAtomicityMode atomicityMode() { + return ATOMIC; + } +} http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/0be4becc/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/IgniteStartCacheInTransactionSelfTest.java ---------------------------------------------------------------------- diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/IgniteStartCacheInTransactionSelfTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/IgniteStartCacheInTransactionSelfTest.java new file mode 100644 index 0000000..fb0bee2 --- /dev/null +++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/IgniteStartCacheInTransactionSelfTest.java @@ -0,0 +1,254 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.ignite.internal.processors.cache; + +import org.apache.ignite.*; +import org.apache.ignite.cache.*; +import org.apache.ignite.configuration.*; +import org.apache.ignite.testframework.*; +import org.apache.ignite.testframework.junits.common.*; +import org.apache.ignite.transactions.*; + +import java.util.concurrent.*; +import java.util.concurrent.locks.*; + +import static org.apache.ignite.cache.CacheAtomicityMode.*; + +/** + * Check starting cache in transaction. + */ +public class IgniteStartCacheInTransactionSelfTest extends GridCommonAbstractTest { + /** {@inheritDoc} */ + @Override protected IgniteConfiguration getConfiguration(String gridName) throws Exception { + IgniteConfiguration cfg = super.getConfiguration(gridName); + + CacheConfiguration ccfg = new CacheConfiguration(); + + ccfg.setAtomicityMode(atomicityMode()); + ccfg.setBackups(1); + + cfg.setCacheConfiguration(ccfg); + + return cfg; + } + + /** + * @return Cache atomicity mode. + */ + public CacheAtomicityMode atomicityMode() { + return TRANSACTIONAL; + } + + /** + * @param cacheName Cache name. + * @return Cache configuration. + */ + public CacheConfiguration cacheConfiguration(String cacheName) { + CacheConfiguration cfg = new CacheConfiguration(); + + cfg.setName(cacheName); + + return cfg; + } + + /** {@inheritDoc} */ + @Override protected void beforeTestsStarted() throws Exception { + startGrids(2); + } + + /** {@inheritDoc} */ + @Override protected void afterTestsStopped() throws Exception { + stopAllGrids(); + } + + /** + * @throws Exception If failed. + */ + public void testStartCache() throws Exception { + final Ignite ignite = grid(0); + + final String key = "key"; + final String val = "val"; + + try (Transaction tx = ignite.transactions().txStart( + TransactionConcurrency.PESSIMISTIC, TransactionIsolation.REPEATABLE_READ)){ + ignite.cache(null).put(key, val); + + GridTestUtils.assertThrows(log, new Callable<Object>() { + @Override public Object call() throws Exception { + ignite.createCache("NEW_CACHE"); + + return null; + } + }, IgniteException.class, "Cannot start/stop cache within transaction."); + + tx.commit(); + } + } + + /** + * @throws Exception If failed. + */ + public void testStartConfigurationCache() throws Exception { + final Ignite ignite = grid(0); + + final String key = "key"; + final String val = "val"; + + try (Transaction tx = ignite.transactions().txStart( + TransactionConcurrency.PESSIMISTIC, TransactionIsolation.REPEATABLE_READ)){ + ignite.cache(null).put(key, val); + + GridTestUtils.assertThrows(log, new Callable<Object>() { + @Override public Object call() throws Exception { + ignite.createCache(cacheConfiguration("NEW_CACHE")); + + return null; + } + }, IgniteException.class, "Cannot start/stop cache within transaction."); + + tx.commit(); + } + } + + /** + * @throws Exception If failed. + */ + public void testStartConfigurationCacheWithNear() throws Exception { + final Ignite ignite = grid(0); + + final String key = "key"; + final String val = "val"; + + try (Transaction tx = ignite.transactions().txStart( + TransactionConcurrency.PESSIMISTIC, TransactionIsolation.REPEATABLE_READ)){ + ignite.cache(null).put(key, val); + + GridTestUtils.assertThrows(log, new Callable<Object>() { + @Override public Object call() throws Exception { + ignite.createCache(cacheConfiguration("NEW_CACHE"), new NearCacheConfiguration()); + + return null; + } + }, IgniteException.class, "Cannot start/stop cache within transaction."); + + tx.commit(); + } + } + + /** + * @throws Exception If failed. + */ + public void testGetOrCreateCache() throws Exception { + final Ignite ignite = grid(0); + + final String key = "key"; + final String val = "val"; + + try (Transaction tx = ignite.transactions().txStart( + TransactionConcurrency.PESSIMISTIC, TransactionIsolation.REPEATABLE_READ)){ + ignite.cache(null).put(key, val); + + GridTestUtils.assertThrows(log, new Callable<Object>() { + @Override public Object call() throws Exception { + ignite.getOrCreateCache("NEW_CACHE"); + + return null; + } + }, IgniteException.class, "Cannot start/stop cache within transaction."); + + tx.commit(); + } + } + + /** + * @throws Exception If failed. + */ + public void testGetOrCreateCacheConfiguration() throws Exception { + final Ignite ignite = grid(0); + + final String key = "key"; + final String val = "val"; + + try (Transaction tx = ignite.transactions().txStart( + TransactionConcurrency.PESSIMISTIC, TransactionIsolation.REPEATABLE_READ)){ + ignite.cache(null).put(key, val); + + GridTestUtils.assertThrows(log, new Callable<Object>() { + @Override public Object call() throws Exception { + ignite.getOrCreateCache(cacheConfiguration("NEW_CACHE")); + + return null; + } + }, IgniteException.class, "Cannot start/stop cache within transaction."); + + tx.commit(); + } + } + + /** + * @throws Exception If failed. + */ + public void testStopCache() throws Exception { + final Ignite ignite = grid(0); + + final String key = "key"; + final String val = "val"; + + try (Transaction tx = ignite.transactions().txStart( + TransactionConcurrency.PESSIMISTIC, TransactionIsolation.REPEATABLE_READ)){ + ignite.cache(null).put(key, val); + + GridTestUtils.assertThrows(log, new Callable<Object>() { + @Override public Object call() throws Exception { + ignite.destroyCache(null); + + return null; + } + }, IgniteException.class, "Cannot start/stop cache within transaction."); + + tx.commit(); + } + } + + /** + * @throws Exception If failed. + */ + public void testLockCache() throws Exception { + if (atomicityMode() != TRANSACTIONAL) + return; + + final Ignite ignite = grid(0); + + final String key = "key"; + + Lock lock = ignite.cache(null).lock(key); + + lock.lock(); + + GridTestUtils.assertThrows(log, new Callable<Object>() { + @Override public Object call() throws Exception { + ignite.createCache("NEW_CACHE"); + + return null; + } + }, IgniteException.class, "Cannot start/stop cache within lock."); + + lock.unlock(); + } +} http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/0be4becc/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteCacheTestSuite4.java ---------------------------------------------------------------------- diff --git a/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteCacheTestSuite4.java b/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteCacheTestSuite4.java index a503e1e..c598e38 100644 --- a/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteCacheTestSuite4.java +++ b/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteCacheTestSuite4.java @@ -138,6 +138,9 @@ public class IgniteCacheTestSuite4 extends TestSuite { suite.addTestSuite(IgniteCacheManyClientsTest.class); + suite.addTestSuite(IgniteStartCacheInTransactionSelfTest.class); + suite.addTestSuite(IgniteStartCacheInTransactionAtomicSelfTest.class); + return suite; } }