IGNITE-12911 CacheObjectAdapter#put incorrect offset handling fixed - Fixes #7742.
Signed-off-by: Ilya Kasnacheev <ilya.kasnacheev@gmail.com>
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryEnumObjectImpl.java b/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryEnumObjectImpl.java
index c09cda1..d4e3d07 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryEnumObjectImpl.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryEnumObjectImpl.java
@@ -349,7 +349,7 @@
@Override public int putValue(long addr) throws IgniteCheckedException {
assert valBytes != null : "Value bytes must be initialized before object is stored";
- return CacheObjectAdapter.putValue(addr, cacheObjectType(), valBytes, 0);
+ return CacheObjectAdapter.putValue(addr, cacheObjectType(), valBytes);
}
/** {@inheritDoc} */
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryObjectImpl.java b/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryObjectImpl.java
index ef654cc..e3873ee 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryObjectImpl.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryObjectImpl.java
@@ -174,7 +174,7 @@
/** {@inheritDoc} */
@Override public int putValue(long addr) throws IgniteCheckedException {
- return CacheObjectAdapter.putValue(addr, cacheObjectType(), arr, start);
+ return CacheObjectAdapter.putValue(addr, cacheObjectType(), arr, start, length());
}
/** {@inheritDoc} */
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/CacheObjectAdapter.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/CacheObjectAdapter.java
index fa51ce5..eb1f3b3 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/CacheObjectAdapter.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/CacheObjectAdapter.java
@@ -82,27 +82,38 @@
@Override public int putValue(long addr) throws IgniteCheckedException {
assert valBytes != null : "Value bytes must be initialized before object is stored";
- return putValue(addr, cacheObjectType(), valBytes, 0);
+ return putValue(addr, cacheObjectType(), valBytes);
}
/**
* @param addr Write address.
* @param type Object type.
* @param valBytes Value bytes array.
- * @param valOff Value bytes array offset.
* @return Offset shift compared to initial address.
*/
- public static int putValue(long addr, byte type, byte[] valBytes, int valOff) {
+ public static int putValue(long addr, byte type, byte[] valBytes) {
+ return putValue(addr, type, valBytes, 0, valBytes.length);
+ }
+
+ /**
+ * @param addr Write address.
+ * @param type Object type.
+ * @param srcBytes Source value bytes array.
+ * @param srcOff Start position in sourceBytes.
+ * @param len Number of bytes for write.
+ * @return Offset shift compared to initial address.
+ */
+ public static int putValue(long addr, byte type, byte[] srcBytes, int srcOff, int len) {
int off = 0;
- PageUtils.putInt(addr, off, valBytes.length);
+ PageUtils.putInt(addr, off, len);
off += 4;
PageUtils.putByte(addr, off, type);
off++;
- PageUtils.putBytes(addr, off, valBytes, valOff);
- off += valBytes.length - valOff;
+ PageUtils.putBytes(addr, off, srcBytes, srcOff, len);
+ off += len;
return off;
}
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/CacheObjectByteArrayImpl.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/CacheObjectByteArrayImpl.java
index 5c033b6..6eac6a5 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/CacheObjectByteArrayImpl.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/CacheObjectByteArrayImpl.java
@@ -88,7 +88,7 @@
/** {@inheritDoc} */
@Override public int putValue(long addr) throws IgniteCheckedException {
- return CacheObjectAdapter.putValue(addr, cacheObjectType(), val, 0);
+ return CacheObjectAdapter.putValue(addr, cacheObjectType(), val);
}
/** {@inheritDoc} */
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/IgniteCachePutKeyAttachedBinaryObjectTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/IgniteCachePutKeyAttachedBinaryObjectTest.java
new file mode 100644
index 0000000..91277f8
--- /dev/null
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/IgniteCachePutKeyAttachedBinaryObjectTest.java
@@ -0,0 +1,177 @@
+/*
+ * 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.IgniteCache;
+import org.apache.ignite.binary.BinaryBasicNameMapper;
+import org.apache.ignite.binary.BinaryObject;
+import org.apache.ignite.binary.BinaryObjectBuilder;
+import org.apache.ignite.configuration.BinaryConfiguration;
+import org.apache.ignite.configuration.CacheConfiguration;
+import org.apache.ignite.configuration.IgniteConfiguration;
+import org.apache.ignite.failure.StopNodeFailureHandler;
+import org.apache.ignite.internal.binary.BinaryObjectImpl;
+import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest;
+import org.junit.Ignore;
+import org.junit.Test;
+
+/**
+ *
+ */
+public class IgniteCachePutKeyAttachedBinaryObjectTest extends GridCommonAbstractTest {
+ /** */
+ public static final String CACHE_NAME = "test";
+
+ /** {@inheritDoc} */
+ @Override protected IgniteConfiguration getConfiguration(String gridName) throws Exception {
+ return super.getConfiguration(gridName)
+ .setFailureHandler(new StopNodeFailureHandler())
+ .setCacheConfiguration(new CacheConfiguration<>(CACHE_NAME))
+ // For brevity, not needed to reproduce the issue.
+ .setBinaryConfiguration(new BinaryConfiguration().setNameMapper(new BinaryBasicNameMapper(true)));
+ }
+
+ /** {@inheritDoc} */
+ @Override protected void afterTest() throws Exception {
+ super.afterTest();
+
+ stopAllGrids();
+ }
+
+ /**
+ * @throws Exception If failed.
+ */
+ @Test
+ public void testAttachedBinaryKeyStoredSuccessfullyToNotEmptyCache() throws Exception {
+ startGrid(0);
+
+ IgniteCache<Object, Object> binCache = grid(0).cache(CACHE_NAME);
+
+ //Ensure that cache not empty.
+ AttachedKey ordinaryKey = new AttachedKey(0);
+
+ binCache.put(ordinaryKey, 1);
+
+ BinaryObjectBuilder holdBuilder = grid(0).binary().builder(HolderKey.class.getName());
+
+ //Creating attached key which stores as byte array.
+ BinaryObjectImpl attachedKey = holdBuilder.setField("id", new AttachedKey(1))
+ .build()
+ .field("id");
+
+ //Put data with attached key.
+ binCache.put(attachedKey, 2);
+
+ assertEquals(1, binCache.get(ordinaryKey));
+ assertEquals(2, binCache.get(attachedKey));
+ }
+
+ /**
+ * @throws Exception If failed.
+ */
+ @Test
+ @Ignore("https://issues.apache.org/jira/browse/IGNITE-13080")
+ public void testKeyRefersToSubkeyInValue() throws Exception {
+ startGrid(0);
+
+ IgniteCache<CompositeKey, CompositeValue> cache = grid(0).cache(CACHE_NAME);
+
+ SubKey subKey = new SubKey(10);
+ CompositeKey compositeKey = new CompositeKey(20, subKey);
+ CompositeValue compositeVal = new CompositeValue("foo", subKey, compositeKey);
+
+ cache.put(compositeKey, compositeVal);
+
+ IgniteCache<Object, Object> binCache = cache.withKeepBinary();
+
+ BinaryObject binObj = (BinaryObject)binCache.get(compositeKey);
+
+ binCache.put(binObj.field("key"), binObj.toBuilder().setField("val", "bar").build());
+
+ assertEquals("bar", cache.get(compositeKey).val());
+
+ assertEquals(1, cache.size());
+ }
+
+ /** */
+ public static class AttachedKey {
+ /** */
+ public int id;
+
+ /** */
+ public AttachedKey(int id) {
+ this.id = id;
+ }
+ }
+
+ /** */
+ public static class HolderKey {
+ /** */
+ public AttachedKey key;
+ }
+
+ /** */
+ public static class SubKey {
+ /** */
+ private int subId;
+
+ /** */
+ public SubKey(int subId) {
+ this.subId = subId;
+ }
+ }
+
+ /** */
+ public static class CompositeKey {
+ /** */
+ private int id;
+
+ /** */
+ private SubKey subKey;
+
+ /** */
+ public CompositeKey(int id, SubKey subKey) {
+ this.id = id;
+ this.subKey = subKey;
+ }
+ }
+
+ /** */
+ public static class CompositeValue {
+ /** */
+ private String val;
+
+ /** */
+ private SubKey subKey;
+
+ /** */
+ private CompositeKey key;
+
+ /** */
+ public CompositeValue(String val, SubKey subKey, CompositeKey key) {
+ this.val = val;
+ this.subKey = subKey;
+ this.key = key;
+ }
+
+ /** */
+ public String val() {
+ return val;
+ }
+ }
+}
diff --git a/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteCacheTestSuite8.java b/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteCacheTestSuite8.java
index 43784b3..065fff5 100644
--- a/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteCacheTestSuite8.java
+++ b/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteCacheTestSuite8.java
@@ -23,6 +23,7 @@
import org.apache.ignite.cache.ClientCreateCacheGroupOnJoinNodeMapsTest;
import org.apache.ignite.internal.processors.cache.CacheStoreTxPutAllMultiNodeTest;
import org.apache.ignite.internal.processors.cache.GridCacheOrderedPreloadingSelfTest;
+import org.apache.ignite.internal.processors.cache.IgniteCachePutKeyAttachedBinaryObjectTest;
import org.apache.ignite.internal.processors.cache.distributed.rebalancing.GridCacheRabalancingDelayedPartitionMapExchangeSelfTest;
import org.apache.ignite.internal.processors.cache.distributed.rebalancing.GridCacheRebalanceOrderTest;
import org.apache.ignite.internal.processors.cache.distributed.rebalancing.GridCacheRebalancingAsyncSelfTest;
@@ -80,6 +81,8 @@
GridTestUtils.addTestIfNeeded(suite, CleanupRestoredCachesSlowTest.class, ignoredTests);
GridTestUtils.addTestIfNeeded(suite, ClientCreateCacheGroupOnJoinNodeMapsTest.class, ignoredTests);
+ GridTestUtils.addTestIfNeeded(suite, IgniteCachePutKeyAttachedBinaryObjectTest.class, ignoredTests);
+
return suite;
}
}