This is an automated email from the ASF dual-hosted git repository. av pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/ignite.git
The following commit(s) were added to refs/heads/master by this push: new fe8fd20 IGNITE-11978 javadoc enhancement for the ReadRepair feature (#6689) fe8fd20 is described below commit fe8fd2041a17d4d315408ebcf90def33db17c66c Author: Slava Koptilin <slava.kopti...@gmail.com> AuthorDate: Wed Aug 28 14:35:21 2019 +0300 IGNITE-11978 javadoc enhancement for the ReadRepair feature (#6689) --- .../main/java/org/apache/ignite/IgniteCache.java | 24 ++++++-- .../events/CacheConsistencyViolationEvent.java | 69 ++++++++++++++++------ .../processors/cache/CacheOperationContext.java | 4 +- .../cache/GatewayProtectedCacheProxy.java | 24 ++++---- .../processors/cache/GridCacheAdapter.java | 14 ++++- .../GridNearReadRepairAbstractFuture.java | 14 ++++- .../GridNearReadRepairCheckOnlyFuture.java | 20 ++++++- .../near/consistency/GridNearReadRepairFuture.java | 12 +++- .../cache/consistency/AbstractReadRepairTest.java | 2 +- 9 files changed, 143 insertions(+), 40 deletions(-) diff --git a/modules/core/src/main/java/org/apache/ignite/IgniteCache.java b/modules/core/src/main/java/org/apache/ignite/IgniteCache.java index 9711a33..002f2c2 100644 --- a/modules/core/src/main/java/org/apache/ignite/IgniteCache.java +++ b/modules/core/src/main/java/org/apache/ignite/IgniteCache.java @@ -63,8 +63,10 @@ import org.apache.ignite.lang.IgniteBiPredicate; import org.apache.ignite.lang.IgniteClosure; import org.apache.ignite.lang.IgniteFuture; import org.apache.ignite.mxbean.CacheMetricsMXBean; +import org.apache.ignite.transactions.TransactionConcurrency; import org.apache.ignite.transactions.TransactionException; import org.apache.ignite.transactions.TransactionHeuristicException; +import org.apache.ignite.transactions.TransactionIsolation; import org.apache.ignite.transactions.TransactionRollbackException; import org.apache.ignite.transactions.TransactionTimeoutException; import org.jetbrains.annotations.Nullable; @@ -145,18 +147,32 @@ public interface IgniteCache<K, V> extends javax.cache.Cache<K, V>, IgniteAsyncS * <li>for transactional caches: * <p>values across the topology will be replaced by latest versioned value: * <ul> - * <li>automaticaly for OPTIMISTIC || READ_COMMITTED transactions</li> - * <li>at commit() for PESSIMISTIC && !READ_COMMITTED transactions</li> + * <li>automatically for transactions that have {@link TransactionConcurrency#OPTIMISTIC} concurrency mode + * or {@link TransactionIsolation#READ_COMMITTED} isolation level</li> + * <li>at commit() phase for transactions that have {@link TransactionConcurrency#PESSIMISTIC} concurrency mode + * and isolation level other than {@link TransactionIsolation#READ_COMMITTED}</li> * </ul> * <p>consistency violation event will be recorded in case it's configured as recordable</li> - * <li>for atomic caches: consistency violation exception will be thrown.</li> + * <li>for atomic caches: consistency violation exception will be thrown. + * Be aware that consistency violation event will not be recorded in this case.</li> * </ul> * <p> * One more important thing is that this proxy usage does not guarantee "all copies check" in case value * already cached inside the transaction. In case you use !READ_COMMITTED isolation mode and already have * cached value, for example already read the value or performed a write, you'll gain the cached value. * <p> - * Local caches and caches without backups, obviously, can not be checked using this feature. + * Due to the nature of the atomic cache, false-positive results can be observed. For example, an attempt to check + * consistency under cache loading may lead to consistency violation exception. By default, the implementation tries + * to check the given key three times. The number of attempts can be changed using + * {@link IgniteSystemProperties#IGNITE_NEAR_GET_MAX_REMAPS} property. + * <p> + * Consistency check is incompatible with the following cache configurations: + * <ul> + * <li>Caches without backups.</li> + * <li>Local caches.</li> + * <li>Near caches.</li> + * <li>Caches that use "read-through" mode.</li> + * </ul> * <p> * Full list of repairable methods: * <ul> diff --git a/modules/core/src/main/java/org/apache/ignite/events/CacheConsistencyViolationEvent.java b/modules/core/src/main/java/org/apache/ignite/events/CacheConsistencyViolationEvent.java index 9fcc889..01fee82 100644 --- a/modules/core/src/main/java/org/apache/ignite/events/CacheConsistencyViolationEvent.java +++ b/modules/core/src/main/java/org/apache/ignite/events/CacheConsistencyViolationEvent.java @@ -24,46 +24,81 @@ import org.apache.ignite.cluster.ClusterNode; import static org.apache.ignite.events.EventType.EVT_CONSISTENCY_VIOLATION; /** - * Event indicates consistency violation detection. + * Event indicates a consistency violation. + * <p> + * Grid events are used for notification about what happens within the grid. Note that by + * design Ignite keeps all events generated on the local node locally and it provides + * APIs for performing a distributed queries across multiple nodes: + * <ul> + * <li> + * {@link org.apache.ignite.IgniteEvents#remoteQuery(org.apache.ignite.lang.IgnitePredicate, long, int...)} - + * asynchronously querying events occurred on the nodes specified, including remote nodes. + * </li> + * <li> + * {@link org.apache.ignite.IgniteEvents#localQuery(org.apache.ignite.lang.IgnitePredicate, int...)} - + * querying only local events stored on this local node. + * </li> + * <li> + * {@link org.apache.ignite.IgniteEvents#localListen(org.apache.ignite.lang.IgnitePredicate, int...)} - + * listening to local grid events (events from remote nodes not included). + * </li> + * </ul> + * User can also wait for events using method {@link org.apache.ignite.IgniteEvents#waitForLocal(org.apache.ignite.lang.IgnitePredicate, int...)}. + * <h1 class="header">Events and Performance</h1> + * Note that by default all events in Ignite are enabled and therefore generated and stored + * by whatever event storage SPI is configured. Ignite can and often does generate thousands events per seconds + * under the load and therefore it creates a significant additional load on the system. If these events are + * not needed by the application this load is unnecessary and leads to significant performance degradation. + * <p> + * It is <b>highly recommended</b> to enable only those events that your application logic requires + * by using {@link org.apache.ignite.configuration.IgniteConfiguration#getIncludeEventTypes()} method in Ignite configuration. Note that certain + * events are required for Ignite's internal operations and such events will still be generated but not stored by + * event storage SPI if they are disabled in Ignite configuration. * * @see EventType#EVT_CONSISTENCY_VIOLATION */ -public class CacheConsistencyViolationEvent extends EventAdapter { +public class CacheConsistencyViolationEvent<K, V> extends EventAdapter { /** Serial version UID. */ private static final long serialVersionUID = 0L; - /** Original distribution. */ - Map<UUID /*Node*/, Map<Object /*Key*/, Object /*Value*/>> locEntries; + /** Represents original values of entries that were affected by a cache operation.*/ + final Map<UUID /*Node*/, Map<K,V>> originalEntries; - /** Fixed entries. */ - Map<Object /*Key*/, Object /*Value*/> fixedEntries; + /** Collection of repaired entries. */ + final Map<K,V> repairedEntries; /** + * Creates a new instance of CacheConsistencyViolationEvent. * + * @param node Local node. + * @param msg Event message. + * @param originalEntries Collection of original entries affected by a cache operation. + * @param repairedEntries Collection of repaired entries. */ public CacheConsistencyViolationEvent( ClusterNode node, String msg, - Map<UUID, Map<Object, Object>> locEntries, - Map<Object, Object> fixedEntries) { + Map<UUID, Map<K, V>> originalEntries, + Map<K, V> repairedEntries) { super(node, msg, EVT_CONSISTENCY_VIOLATION); - this.locEntries = locEntries; - this.fixedEntries = fixedEntries; + this.originalEntries = originalEntries; + this.repairedEntries = repairedEntries; } /** - * Original distribution. + * Returns a mapping node ids to a collection of original entries affected by a cache operation. + * @return Collection of original entries. */ - public Map<UUID, Map<Object, Object>> getEntries() { - return locEntries; + public Map<UUID, Map<K, V>> getEntries() { + return originalEntries; } /** - * Fixed entries. - * Will be fixed in case of transaction commit. + * Returns a collection of repaired entries. + * @return Collection of repaired entries. */ - public Map<Object, Object> getFixedEntries() { - return fixedEntries; + public Map<K, V> getRepairedEntries() { + return repairedEntries; } } diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/CacheOperationContext.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/CacheOperationContext.java index 47eea68..73f873c 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/CacheOperationContext.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/CacheOperationContext.java @@ -50,7 +50,7 @@ public class CacheOperationContext implements Serializable { /** */ private final boolean recovery; - /** */ + /** Read-repair flag. */ private final boolean readRepair; /** Client ID which operates over this projection. */ @@ -89,7 +89,7 @@ public class CacheOperationContext implements Serializable { * @param keepBinary Keep binary flag. * @param expiryPlc Expiry policy. * @param dataCenterId Data center id. - * @param readRepair Read Repair. + * @param readRepair Read-repair flag. */ public CacheOperationContext( boolean skipStore, diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GatewayProtectedCacheProxy.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GatewayProtectedCacheProxy.java index 8023b00..11b24aa 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GatewayProtectedCacheProxy.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GatewayProtectedCacheProxy.java @@ -236,22 +236,26 @@ public class GatewayProtectedCacheProxy<K, V> extends AsyncSupportAdapter<Ignite CacheOperationGate opGate = onEnter(); try { - if (context().mvccEnabled()) // Can (should?) be supported in future. - throw new UnsupportedOperationException("Read Repair is not supported at MVCC mode."); + if (context().mvccEnabled()) { + throw new UnsupportedOperationException( + "The TRANSACTIONAL_SNAPSHOT mode is incompatible with the read-repair feature."); + } - if (context().isNear()) // Can be supported in future. - throw new UnsupportedOperationException("Read Repair is not supported for near caches."); + if (context().isNear()) + throw new UnsupportedOperationException("Read-repair is incompatible with near caches."); - if (context().readThrough()) // Can be supported in future. + if (context().readThrough()) { // Read Repair get operation produces different versions for same entries loaded via readThrough feature. - throw new UnsupportedOperationException("Read Repair is not supported for caches with readThrough enabled."); + throw new UnsupportedOperationException("Read-repair is incompatible with caches that use readThrough."); + } - if (context().isLocal()) // Can't be supported in future. - throw new UnsupportedOperationException("Read Repair is not supported for local caches."); + if (context().isLocal()) + throw new UnsupportedOperationException("Read-repair is incompatible with local caches."); - if (context().config().getBackups() == 0) // Can't be supported in future. - throw new UnsupportedOperationException("Read Repair is suitable only in case " + + if (context().config().getBackups() == 0) { + throw new UnsupportedOperationException("Read-repair is suitable only in case " + "at least 1 backup configured for cache."); + } boolean readRepair = opCtx.readRepair(); diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheAdapter.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheAdapter.java index a6476fa..020b3a2 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheAdapter.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheAdapter.java @@ -5050,7 +5050,12 @@ public abstract class GridCacheAdapter<K, V> implements IgniteInternalCache<K, V } /** - * Checks and repairs entries across the topology. + * Checks the given {@code keys} and repairs entries across the topology if needed. + * + * @param keys Keys. + * @param opCtx Operation context. + * @param skipVals Skip values flag. + * @return Compound future that represents a result of repair action. */ protected IgniteInternalFuture<Void> repairAsync( Collection<? extends K> keys, @@ -5067,7 +5072,12 @@ public abstract class GridCacheAdapter<K, V> implements IgniteInternalCache<K, V } /** - * Checks and repairs entry across the topology. + * Checks the given {@code key} and repairs entry across the topology if needed. + * + * @param key Key. + * @param opCtx Operation context. + * @param skipVals Skip values flag. + * @return Recover future. */ protected IgniteInternalFuture<Void> repairAsync( final K key, diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/consistency/GridNearReadRepairAbstractFuture.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/consistency/GridNearReadRepairAbstractFuture.java index 551f8eb..aba5b84 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/consistency/GridNearReadRepairAbstractFuture.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/consistency/GridNearReadRepairAbstractFuture.java @@ -90,7 +90,17 @@ public abstract class GridNearReadRepairAbstractFuture extends GridFutureAdapter private AffinityTopologyVersion topVer; /** + * Creates a new instance of GridNearReadRepairAbstractFuture. * + * @param topVer Topology version. + * @param ctx Cache context. + * @param keys Keys. + * @param readThrough Read-through flag. + * @param taskName Task name. + * @param deserializeBinary Deserialize binary flag. + * @param recovery Partition recovery flag. + * @param expiryPlc Expiry policy. + * @param tx Transaction. Can be {@code null} in case of atomic cache. */ protected GridNearReadRepairAbstractFuture( AffinityTopologyVersion topVer, @@ -117,7 +127,7 @@ public abstract class GridNearReadRepairAbstractFuture extends GridFutureAdapter } /** - * + * @param topVer Affinity topology version. */ protected synchronized void map(AffinityTopologyVersion topVer) { this.topVer = topVer; @@ -175,7 +185,9 @@ public abstract class GridNearReadRepairAbstractFuture extends GridFutureAdapter } /** + * Collects results of each 'get' future and prepares an overall result of the operation. * + * @param finished Future represents a result of GET operation. */ protected synchronized void onResult(IgniteInternalFuture<Map<KeyCacheObject, EntryGetResult>> finished) { if (isDone() || /*remapping*/ topVer == null) diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/consistency/GridNearReadRepairCheckOnlyFuture.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/consistency/GridNearReadRepairCheckOnlyFuture.java index 0388e3f..e04ea27 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/consistency/GridNearReadRepairCheckOnlyFuture.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/consistency/GridNearReadRepairCheckOnlyFuture.java @@ -47,7 +47,19 @@ public class GridNearReadRepairCheckOnlyFuture extends GridNearReadRepairAbstrac private boolean keepCacheObjects; /** + * Creates a new instance of GridNearReadRepairCheckOnlyFuture. * + * @param ctx Cache context. + * @param keys Keys. + * @param readThrough Read-through flag. + * @param taskName Task name. + * @param deserializeBinary Deserialize binary flag. + * @param recovery Partition recovery flag. + * @param expiryPlc Expiry policy. + * @param skipVals Skip values flag. + * @param needVer Need version flag. + * @param keepCacheObjects Keep cache objects flag. + * @param tx Transaction. Can be {@code null} in case of atomic cache. */ public GridNearReadRepairCheckOnlyFuture( GridCacheContext ctx, @@ -103,7 +115,9 @@ public class GridNearReadRepairCheckOnlyFuture extends GridNearReadRepairAbstrac } /** - * Produces 1 entry's value. + * Returns a future represents 1 entry's value. + * + * @return Future represents 1 entry's value. */ public <K, V> IgniteInternalFuture<V> single() { return chain((fut) -> { @@ -142,7 +156,9 @@ public class GridNearReadRepairCheckOnlyFuture extends GridNearReadRepairAbstrac } /** - * Produces entry map. + * Returns a future represents entries map. + * + * @return Future represents entries map. */ public <K, V> IgniteInternalFuture<Map<K, V>> multi() { return chain((fut) -> { diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/consistency/GridNearReadRepairFuture.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/consistency/GridNearReadRepairFuture.java index 35aae3c..f546fd7 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/consistency/GridNearReadRepairFuture.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/consistency/GridNearReadRepairFuture.java @@ -41,7 +41,17 @@ import static org.apache.ignite.events.EventType.EVT_CONSISTENCY_VIOLATION; */ public class GridNearReadRepairFuture extends GridNearReadRepairAbstractFuture { /** + * Creates a new instance of GridNearReadRepairFuture. * + * @param topVer Affinity topology version. + * @param ctx Cache context. + * @param keys Keys. + * @param readThrough Read-through flag. + * @param taskName Task name. + * @param deserializeBinary Deserialize binary flag. + * @param recovery Partition recovery flag. + * @param expiryPlc Expiry policy. + * @param tx Transaction. */ public GridNearReadRepairFuture( AffinityTopologyVersion topVer, @@ -157,7 +167,7 @@ public class GridNearReadRepairFuture extends GridNearReadRepairAbstractFuture { } } - evtMgr.record(new CacheConsistencyViolationEvent( + evtMgr.record(new CacheConsistencyViolationEvent<>( ctx.discovery().localNode(), "Consistency violation fixed.", originalMap, diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/consistency/AbstractReadRepairTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/consistency/AbstractReadRepairTest.java index 30414ae..2ebcc00 100644 --- a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/consistency/AbstractReadRepairTest.java +++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/consistency/AbstractReadRepairTest.java @@ -158,7 +158,7 @@ public abstract class AbstractReadRepairTest extends GridCommonAbstractTest { while (!evtDeq.isEmpty()) { CacheConsistencyViolationEvent evt = evtDeq.remove(); - fixed.putAll(evt.getFixedEntries()); // Optimistic and read commited transactions produce per key fixes. + fixed.putAll(evt.getRepairedEntries()); // Optimistic and read committed transactions produce per key fixes. } int misses = 0;