IGNITE-6553 Standalone WAL iterator fails to handle WAL delete data records - Fixes #2797.
Project: http://git-wip-us.apache.org/repos/asf/ignite/repo Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/49b83581 Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/49b83581 Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/49b83581 Branch: refs/heads/ignite-5937 Commit: 49b835812a607a116c4dbc99ce60ed1684229b34 Parents: 474479c Author: dpavlov <[email protected]> Authored: Thu Oct 5 18:10:25 2017 +0300 Committer: Alexey Goncharuk <[email protected]> Committed: Thu Oct 5 18:11:58 2017 +0300 ---------------------------------------------------------------------- .../internal/pagemem/wal/record/DataEntry.java | 13 ++++++------ .../pagemem/wal/record/UnwrapDataEntry.java | 22 +++++++++++++------- .../reader/StandaloneWalRecordsIterator.java | 11 +++++++--- .../db/wal/reader/IgniteWalReaderTest.java | 14 ++++++++++--- 4 files changed, 41 insertions(+), 19 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/ignite/blob/49b83581/modules/core/src/main/java/org/apache/ignite/internal/pagemem/wal/record/DataEntry.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/internal/pagemem/wal/record/DataEntry.java b/modules/core/src/main/java/org/apache/ignite/internal/pagemem/wal/record/DataEntry.java index d4e0b9f..cb6b482 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/pagemem/wal/record/DataEntry.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/pagemem/wal/record/DataEntry.java @@ -23,6 +23,7 @@ import org.apache.ignite.internal.processors.cache.KeyCacheObject; import org.apache.ignite.internal.processors.cache.version.GridCacheVersion; import org.apache.ignite.internal.util.tostring.GridToStringInclude; import org.apache.ignite.internal.util.typedef.internal.S; +import org.jetbrains.annotations.Nullable; /** * Represents Data Entry ({@link #key}, {@link #val value}) pair update {@link #op operation} in WAL log. @@ -32,13 +33,13 @@ public class DataEntry { @GridToStringInclude protected int cacheId; - /** Cache object key */ + /** Cache object key. */ protected KeyCacheObject key; - /** Cache object value */ - protected CacheObject val; + /** Cache object value. May be {@code} null for {@link GridCacheOperation#DELETE} */ + @Nullable protected CacheObject val; - /** Entry operation performed */ + /** Entry operation performed. */ @GridToStringInclude protected GridCacheOperation op; @@ -67,7 +68,7 @@ public class DataEntry { /** * @param cacheId Cache ID. * @param key Key. - * @param val Value. + * @param val Value or null for delete operation. * @param op Operation. * @param nearXidVer Near transaction version. * @param writeVer Write version. @@ -78,7 +79,7 @@ public class DataEntry { public DataEntry( int cacheId, KeyCacheObject key, - CacheObject val, + @Nullable CacheObject val, GridCacheOperation op, GridCacheVersion nearXidVer, GridCacheVersion writeVer, http://git-wip-us.apache.org/repos/asf/ignite/blob/49b83581/modules/core/src/main/java/org/apache/ignite/internal/pagemem/wal/record/UnwrapDataEntry.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/internal/pagemem/wal/record/UnwrapDataEntry.java b/modules/core/src/main/java/org/apache/ignite/internal/pagemem/wal/record/UnwrapDataEntry.java index 678539d..dbcc651 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/pagemem/wal/record/UnwrapDataEntry.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/pagemem/wal/record/UnwrapDataEntry.java @@ -31,13 +31,13 @@ public class UnwrapDataEntry extends DataEntry { /** Cache object value context. Context is used for unwrapping objects. */ private final CacheObjectValueContext cacheObjValCtx; - /** Keep binary. This flag disables converting of non primitive types (BinaryObjects) */ + /** Keep binary. This flag disables converting of non primitive types (BinaryObjects). */ private boolean keepBinary; /** * @param cacheId Cache ID. * @param key Key. - * @param val Value. + * @param val Value or null for delete operation. * @param op Operation. * @param nearXidVer Near transaction version. * @param writeVer Write version. @@ -45,7 +45,7 @@ public class UnwrapDataEntry extends DataEntry { * @param partId Partition ID. * @param partCnt Partition counter. * @param cacheObjValCtx cache object value context for unwrapping objects. - * @param keepBinary disable unwrapping for non primitive objects, Binary Objects would be returned instead + * @param keepBinary disable unwrapping for non primitive objects, Binary Objects would be returned instead. */ public UnwrapDataEntry( final int cacheId, @@ -66,39 +66,47 @@ public class UnwrapDataEntry extends DataEntry { /** * Unwraps key value from cache key object into primitive boxed type or source class. If client classes were used - * in key, call of this method requires classes to be available in classpath + * in key, call of this method requires classes to be available in classpath. * - * @return Key which was placed into cache. Or null if failed + * @return Key which was placed into cache. Or null if failed to convert. */ public Object unwrappedKey() { try { if (keepBinary && key instanceof BinaryObject) return key; + Object unwrapped = key.value(cacheObjValCtx, false); + if (unwrapped instanceof BinaryObject) { if (keepBinary) return unwrapped; unwrapped = ((BinaryObject)unwrapped).deserialize(); } + return unwrapped; } catch (Exception e) { cacheObjValCtx.kernalContext().log(UnwrapDataEntry.class) .error("Unable to convert key [" + key + "]", e); + return null; } } /** * Unwraps value value from cache value object into primitive boxed type or source class. If client classes were - * used in key, call of this method requires classes to be available in classpath + * used in key, call of this method requires classes to be available in classpath. * - * @return Value which was placed into cache. Or null if failed + * @return Value which was placed into cache. Or null for delete operation or for failure. */ public Object unwrappedValue() { try { + if (val == null) + return null; + if (keepBinary && val instanceof BinaryObject) return val; + return val.value(cacheObjValCtx, false); } catch (Exception e) { http://git-wip-us.apache.org/repos/asf/ignite/blob/49b83581/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/wal/reader/StandaloneWalRecordsIterator.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/wal/reader/StandaloneWalRecordsIterator.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/wal/reader/StandaloneWalRecordsIterator.java index 42bb410..a4d9e95 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/wal/reader/StandaloneWalRecordsIterator.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/wal/reader/StandaloneWalRecordsIterator.java @@ -335,12 +335,17 @@ class StandaloneWalRecordsIterator extends AbstractWalRecordsIterator { if (dataEntry instanceof LazyDataEntry) { final LazyDataEntry lazyDataEntry = (LazyDataEntry)dataEntry; + key = processor.toKeyCacheObject(fakeCacheObjCtx, lazyDataEntry.getKeyType(), lazyDataEntry.getKeyBytes()); - val = processor.toCacheObject(fakeCacheObjCtx, - lazyDataEntry.getValType(), - lazyDataEntry.getValBytes()); + + final byte type = lazyDataEntry.getValType(); + + val = type == 0 ? null : + processor.toCacheObject(fakeCacheObjCtx, + type, + lazyDataEntry.getValBytes()); } else { key = dataEntry.key(); http://git-wip-us.apache.org/repos/asf/ignite/blob/49b83581/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/db/wal/reader/IgniteWalReaderTest.java ---------------------------------------------------------------------- diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/db/wal/reader/IgniteWalReaderTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/db/wal/reader/IgniteWalReaderTest.java index 93df8b2..79387e3 100644 --- a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/db/wal/reader/IgniteWalReaderTest.java +++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/db/wal/reader/IgniteWalReaderTest.java @@ -356,6 +356,7 @@ public class IgniteWalReaderTest extends GridCommonAbstractTest { cache0.putAll(values); } + /** * Puts provided number of records to fill WAL under transactions * @@ -912,8 +913,16 @@ public class IgniteWalReaderTest extends GridCommonAbstractTest { deletesFound != null && deletesFound > 0); } - @NotNull private IgniteWalIteratorFactory createWalIteratorFactory(String subfolderName, - String workDir) throws IgniteCheckedException { + /** + * @param subfolderName Subfolder name. + * @param workDir Work directory. + * @return WAL iterator factory. + * @throws IgniteCheckedException If failed. + */ + @NotNull private IgniteWalIteratorFactory createWalIteratorFactory( + String subfolderName, + String workDir + ) throws IgniteCheckedException { final File binaryMeta = U.resolveWorkDirectory(workDir, "binary_meta", false); final File binaryMetaWithConsId = new File(binaryMeta, subfolderName); final File marshallerMapping = U.resolveWorkDirectory(workDir, "marshaller", false); @@ -924,7 +933,6 @@ public class IgniteWalReaderTest extends GridCommonAbstractTest { marshallerMapping); } - /** * @param values collection with numbers * @return sum of numbers
