Repository: ignite Updated Branches: refs/heads/ignite-8446 48949b8f2 -> 452e078c5
IGNITE-8446 Ability to check and completely fill transactions on creation Signed-off-by: Anton Vinogradov <a...@apache.org> Project: http://git-wip-us.apache.org/repos/asf/ignite/repo Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/452e078c Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/452e078c Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/452e078c Branch: refs/heads/ignite-8446 Commit: 452e078c545ab230f26274c9fc108d95b9137fb9 Parents: 48949b8 Author: Anton Vinogradov <a...@apache.org> Authored: Tue May 29 14:54:30 2018 +0300 Committer: Anton Vinogradov <a...@apache.org> Committed: Tue May 29 14:54:30 2018 +0300 ---------------------------------------------------------------------- .../org/apache/ignite/IgniteTransactions.java | 5 + .../org/apache/ignite/events/EventType.java | 2 +- .../apache/ignite/events/TransactionEvent.java | 55 ------- .../ignite/events/TransactionStartedEvent.java | 55 +++++++ .../transactions/IgniteTransactionsImpl.java | 9 +- .../cache/transactions/TxLabelTest.java | 118 ++++++++------ .../cache/transactions/TxTimeoutTest.java | 159 +++++++++++++++++++ 7 files changed, 296 insertions(+), 107 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/ignite/blob/452e078c/modules/core/src/main/java/org/apache/ignite/IgniteTransactions.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/IgniteTransactions.java b/modules/core/src/main/java/org/apache/ignite/IgniteTransactions.java index 2bb7101..626d381 100644 --- a/modules/core/src/main/java/org/apache/ignite/IgniteTransactions.java +++ b/modules/core/src/main/java/org/apache/ignite/IgniteTransactions.java @@ -124,4 +124,9 @@ public interface IgniteTransactions { * @throws NullPointerException if label is null. */ public IgniteTransactions withLabel(String lb); + + /** + * @return Transaction label. + */ + public String label(); } http://git-wip-us.apache.org/repos/asf/ignite/blob/452e078c/modules/core/src/main/java/org/apache/ignite/events/EventType.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/events/EventType.java b/modules/core/src/main/java/org/apache/ignite/events/EventType.java index 113c53d..e814d1a 100644 --- a/modules/core/src/main/java/org/apache/ignite/events/EventType.java +++ b/modules/core/src/main/java/org/apache/ignite/events/EventType.java @@ -995,7 +995,7 @@ public interface EventType { * {@link IgniteEvents#localListen(IgnitePredicate, int...)} method to * subscribe to all transaction events. * - * @see TransactionEvent + * @see TransactionStartedEvent */ public static final int[] EVTS_TX = { EVT_TX_STARTED http://git-wip-us.apache.org/repos/asf/ignite/blob/452e078c/modules/core/src/main/java/org/apache/ignite/events/TransactionEvent.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/events/TransactionEvent.java b/modules/core/src/main/java/org/apache/ignite/events/TransactionEvent.java deleted file mode 100644 index deb9019..0000000 --- a/modules/core/src/main/java/org/apache/ignite/events/TransactionEvent.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * 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.events; - -import org.apache.ignite.cluster.ClusterNode; -import org.apache.ignite.internal.processors.cache.transactions.IgniteInternalTx; - -/** - * Event indicates there was some action with transaction, eg. creation, rollback, commit and etc. - * - * @see EventType#EVTS_TX - */ -public class TransactionEvent extends EventAdapter { - /** */ - private static final long serialVersionUID = 0L; - - /** Tx. */ - private IgniteInternalTx tx; - - /** - * @param node Node. - * @param msg Message. - * @param type Type. - * @param tx Tx. - */ - public TransactionEvent(ClusterNode node, String msg, int type, IgniteInternalTx tx) { - super(node, msg, type); - - assert tx != null; - - this.tx = tx; - } - - /** - * - */ - public IgniteInternalTx tx() { - return tx; - } -} http://git-wip-us.apache.org/repos/asf/ignite/blob/452e078c/modules/core/src/main/java/org/apache/ignite/events/TransactionStartedEvent.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/events/TransactionStartedEvent.java b/modules/core/src/main/java/org/apache/ignite/events/TransactionStartedEvent.java new file mode 100644 index 0000000..dbe7d32 --- /dev/null +++ b/modules/core/src/main/java/org/apache/ignite/events/TransactionStartedEvent.java @@ -0,0 +1,55 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.ignite.events; + +import org.apache.ignite.IgniteTransactions; +import org.apache.ignite.cluster.ClusterNode; + +/** + * Event indicates transaction creation. + * + * @see EventType#EVTS_TX + */ +public class TransactionStartedEvent extends EventAdapter { + /** */ + private static final long serialVersionUID = 0L; + + /** Tx. */ + private IgniteTransactions tx; + + /** + * @param node Node. + * @param msg Message. + * @param type Type. + * @param tx Tx. + */ + public TransactionStartedEvent(ClusterNode node, String msg, int type, IgniteTransactions tx) { + super(node, msg, type); + + assert tx != null; + + this.tx = tx; + } + + /** + * + */ + public IgniteTransactions tx() { + return tx; + } +} http://git-wip-us.apache.org/repos/asf/ignite/blob/452e078c/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteTransactionsImpl.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteTransactionsImpl.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteTransactionsImpl.java index 985dd25..b5e3a45 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteTransactionsImpl.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteTransactionsImpl.java @@ -20,7 +20,7 @@ package org.apache.ignite.internal.processors.cache.transactions; import java.util.Collection; import org.apache.ignite.IgniteTransactions; import org.apache.ignite.configuration.TransactionConfiguration; -import org.apache.ignite.events.TransactionEvent; +import org.apache.ignite.events.TransactionStartedEvent; import org.apache.ignite.internal.IgniteTransactionsEx; import org.apache.ignite.internal.managers.eventstorage.GridEventStorageManager; import org.apache.ignite.internal.processors.cache.GridCacheContext; @@ -188,7 +188,7 @@ public class IgniteTransactionsImpl<K, V> implements IgniteTransactionsEx { GridEventStorageManager evt = cctx.gridEvents(); if (sysCacheCtx == null /* ignoring system tx */ && evt.isRecordable(EVT_TX_STARTED)) - evt.record(new TransactionEvent(cctx.discovery().localNode(), null, EVT_TX_STARTED, tx)); + evt.record(new TransactionStartedEvent(cctx.discovery().localNode(), null, EVT_TX_STARTED, this)); return tx; } @@ -234,6 +234,11 @@ public class IgniteTransactionsImpl<K, V> implements IgniteTransactionsEx { return new IgniteTransactionsImpl<>(cctx, lb); } + /** {@inheritDoc} */ + @Override public String label() { + return lb; + } + /** * @param ctx Cache context. */ http://git-wip-us.apache.org/repos/asf/ignite/blob/452e078c/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/transactions/TxLabelTest.java ---------------------------------------------------------------------- diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/transactions/TxLabelTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/transactions/TxLabelTest.java index c442357..062a4e0 100644 --- a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/transactions/TxLabelTest.java +++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/transactions/TxLabelTest.java @@ -17,15 +17,16 @@ package org.apache.ignite.internal.processors.cache.transactions; -import java.util.concurrent.atomic.AtomicReference; import org.apache.ignite.Ignite; +import org.apache.ignite.IgniteCache; import org.apache.ignite.IgniteEvents; +import org.apache.ignite.IgniteTransactions; import org.apache.ignite.events.Event; -import org.apache.ignite.events.TransactionEvent; -import org.apache.ignite.internal.processors.cache.GridCacheAbstractSelfTest; -import org.apache.ignite.internal.processors.cache.distributed.near.GridNearTxLocal; +import org.apache.ignite.events.TransactionStartedEvent; import org.apache.ignite.lang.IgnitePredicate; +import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest; import org.apache.ignite.transactions.Transaction; +import org.apache.ignite.transactions.TransactionRollbackException; import static org.apache.ignite.events.EventType.EVTS_TX; import static org.apache.ignite.events.EventType.EVT_TX_STARTED; @@ -33,26 +34,25 @@ import static org.apache.ignite.events.EventType.EVT_TX_STARTED; /** * Tests transaction labels. */ -public class TxLabelTest extends GridCacheAbstractSelfTest { - /** {@inheritDoc} */ - @Override protected int gridCount() { - return 1; - } - +public class TxLabelTest extends GridCommonAbstractTest { /** * Tests transaction labels. */ - public void testLabel() { - testLabel0(grid(0), "lbl0"); - testLabel0(grid(0), "lbl1"); + public void testLabel() throws Exception { + Ignite ignite = startGrid(0); + + IgniteCache cache = ignite.getOrCreateCache(DEFAULT_CACHE_NAME); + + testLabel0(grid(0), "lbl0", cache); + testLabel0(grid(0), "lbl1", cache); try { - testLabel0(grid(0), null); + testLabel0(grid(0), null, cache); fail(); } - catch (Exception e) { - // Expected. + catch (NullPointerException e) { + assertTrue(e.getMessage().contains("label should not be empty.")); } } @@ -60,11 +60,11 @@ public class TxLabelTest extends GridCacheAbstractSelfTest { * @param ignite Ignite. * @param lbl Label. */ - private void testLabel0(Ignite ignite, String lbl) { + private void testLabel0(Ignite ignite, String lbl, IgniteCache cache) { try (Transaction tx = ignite.transactions().withLabel(lbl).txStart()) { assertEquals(lbl, tx.label()); - ignite.cache(DEFAULT_CACHE_NAME).put(0, 0); + cache.put(0, 0); tx.commit(); } @@ -73,77 +73,97 @@ public class TxLabelTest extends GridCacheAbstractSelfTest { /** * */ - public void testLabelFilledCheck() { - Ignite ignite = grid(0); + public void testLabelFilledLocalGuarantee() throws Exception { + Ignite ignite = startGrid(0); final IgniteEvents evts = ignite.events(); evts.enableLocal(EVTS_TX); - AtomicReference<Throwable> ref = new AtomicReference<>(); - evts.localListen((IgnitePredicate<Event>)e -> { - assert e instanceof TransactionEvent; + assert e instanceof TransactionStartedEvent; + + TransactionStartedEvent evt = (TransactionStartedEvent)e; - TransactionEvent evt = (TransactionEvent)e; + IgniteTransactions tx = evt.tx(); - if (((GridNearTxLocal)(evt.tx())).label() == null) - ref.set(new IllegalStateException("Label should be filled!")); + if (tx.label() == null) + tx.tx().rollback(); return true; }, EVT_TX_STARTED); - assertNull(ref.get()); - try (Transaction tx = ignite.transactions().withLabel("test").txStart()) { - // No-op. + tx.commit(); } - assertNull(ref.get()); - try (Transaction tx = ignite.transactions().txStart()) { + tx.commit(); + + fail("Should fail prior this line."); + } + catch (TransactionRollbackException ignored) { // No-op. } - - assertNotNull(ref.get()); } /** * */ - public void testLabelFilledGuarantee() { - Ignite ignite = grid(0); + public void testLabelFilledRemoteGuarantee() throws Exception { + Ignite ignite = startGrid(0); + Ignite remote = startGrid(1); final IgniteEvents evts = ignite.events(); evts.enableLocal(EVTS_TX); - class LabelNotFilledError extends Error { - private LabelNotFilledError(String msg) { - super(msg); - } - } + evts.remoteListen(null, + (IgnitePredicate<Event>)e -> { + assert e instanceof TransactionStartedEvent; - evts.localListen((IgnitePredicate<Event>)e -> { - assert e instanceof TransactionEvent; + TransactionStartedEvent evt = (TransactionStartedEvent)e; - TransactionEvent evt = (TransactionEvent)e; + IgniteTransactions tx = evt.tx(); - if (((GridNearTxLocal)(evt.tx())).label() == null) - throw new LabelNotFilledError("Label should be filled!"); + if (tx.label() == null) + tx.tx().rollback(); - return true; - }, EVT_TX_STARTED); + return true; + }, + EVT_TX_STARTED); try (Transaction tx = ignite.transactions().withLabel("test").txStart()) { - // No-op. + tx.commit(); + } + + try (Transaction tx = remote.transactions().withLabel("test").txStart()) { + tx.commit(); } try (Transaction tx = ignite.transactions().txStart()) { + tx.commit(); + fail("Should fail prior this line."); } - catch (LabelNotFilledError e) { + catch (TransactionRollbackException ignored) { // No-op. } + + try (Transaction tx = remote.transactions().txStart()) { + tx.commit(); + + fail("Should fail prior this line."); + } + catch (TransactionRollbackException ignored) { + // No-op. + } + } + + /** {@inheritDoc} */ + @Override protected void afterTest() throws Exception { + super.afterTest(); + + stopAllGrids(); } } http://git-wip-us.apache.org/repos/asf/ignite/blob/452e078c/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/transactions/TxTimeoutTest.java ---------------------------------------------------------------------- diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/transactions/TxTimeoutTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/transactions/TxTimeoutTest.java new file mode 100644 index 0000000..4d8a49a --- /dev/null +++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/transactions/TxTimeoutTest.java @@ -0,0 +1,159 @@ +/* + * 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.transactions; + +import org.apache.ignite.Ignite; +import org.apache.ignite.IgniteEvents; +import org.apache.ignite.events.Event; +import org.apache.ignite.events.TransactionStartedEvent; +import org.apache.ignite.lang.IgnitePredicate; +import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest; +import org.apache.ignite.transactions.Transaction; +import org.apache.ignite.transactions.TransactionConcurrency; +import org.apache.ignite.transactions.TransactionIsolation; +import org.apache.ignite.transactions.TransactionRollbackException; + +import static org.apache.ignite.events.EventType.EVTS_TX; +import static org.apache.ignite.events.EventType.EVT_TX_STARTED; + +/** + * Tests transaction timeout. + */ +public class TxTimeoutTest extends GridCommonAbstractTest { + /** + * + */ + public void testTimeoutSetLocalGuarantee() throws Exception { + Ignite ignite = startGrid(0); + + final IgniteEvents evts = ignite.events(); + + evts.enableLocal(EVTS_TX); + + evts.localListen((IgnitePredicate<Event>)e -> { + assert e instanceof TransactionStartedEvent; + + TransactionStartedEvent evt = (TransactionStartedEvent)e; + + Transaction tx = evt.tx().tx(); + + if (tx.timeout() < 200) + tx.rollback(); + + return true; + }, EVT_TX_STARTED); + + try (Transaction tx = ignite.transactions().txStart( + TransactionConcurrency.OPTIMISTIC, + TransactionIsolation.REPEATABLE_READ, + 200, + 2)) { + tx.commit(); + } + + try (Transaction tx = ignite.transactions().txStart( + TransactionConcurrency.OPTIMISTIC, + TransactionIsolation.REPEATABLE_READ, + 100, + 2)) { + tx.commit(); + + fail("Should fail prior this line."); + } + catch (TransactionRollbackException ignored) { + // No-op. + } + + try (Transaction tx = ignite.transactions().txStart()) { + tx.commit(); + + fail("Should fail prior this line."); + } + catch (TransactionRollbackException ignored) { + // No-op. + } + } + + /** + * + */ + public void testTimeoutSetRemoteGuarantee() throws Exception { + Ignite ignite = startGrid(0); + Ignite remote = startGrid(1); + + final IgniteEvents evts = ignite.events(); + + evts.enableLocal(EVTS_TX); + + evts.remoteListen(null, + (IgnitePredicate<Event>)e -> { + assert e instanceof TransactionStartedEvent; + + TransactionStartedEvent evt = (TransactionStartedEvent)e; + + Transaction tx = evt.tx().tx(); + + if (tx.timeout() == 0) + tx.rollback(); + + return true; + }, + EVT_TX_STARTED); + + try (Transaction tx = ignite.transactions().txStart( + TransactionConcurrency.OPTIMISTIC, + TransactionIsolation.REPEATABLE_READ, + 100, + 2)) { + tx.commit(); + } + + try (Transaction tx = remote.transactions().txStart( + TransactionConcurrency.OPTIMISTIC, + TransactionIsolation.REPEATABLE_READ, + 100, + 2)) { + tx.commit(); + } + + try (Transaction tx = ignite.transactions().txStart()) { + tx.commit(); + + fail("Should fail prior this line."); + } + catch (TransactionRollbackException ignored) { + // No-op. + } + + try (Transaction tx = remote.transactions().txStart()) { + tx.commit(); + + fail("Should fail prior this line."); + } + catch (TransactionRollbackException ignored) { + // No-op. + } + } + + /** {@inheritDoc} */ + @Override protected void afterTest() throws Exception { + super.afterTest(); + + stopAllGrids(); + } +}