You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ignite.apache.org by tl...@apache.org on 2021/04/29 11:51:41 UTC

[ignite] branch master updated: IGNITE-14610 fix BinaryBuilderReader doesn't supports reference (HANDLE) to collection (#9057)

This is an automated email from the ASF dual-hosted git repository.

tledkov 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 dc168e9  IGNITE-14610 fix BinaryBuilderReader doesn't supports reference (HANDLE) to collection (#9057)
dc168e9 is described below

commit dc168e914362d448e02c3f7d2083d2dbcc20ba65
Author: tledkov <tl...@gridgain.com>
AuthorDate: Thu Apr 29 14:51:21 2021 +0300

    IGNITE-14610 fix BinaryBuilderReader doesn't supports reference (HANDLE) to collection (#9057)
---
 .../binary/builder/BinaryBuilderReader.java        | 89 +++++++++++++++-----
 .../internal/binary/BinaryMarshallerSelfTest.java  | 97 ++++++++++++++++++++++
 2 files changed, 165 insertions(+), 21 deletions(-)

diff --git a/modules/core/src/main/java/org/apache/ignite/internal/binary/builder/BinaryBuilderReader.java b/modules/core/src/main/java/org/apache/ignite/internal/binary/builder/BinaryBuilderReader.java
index c46be5d..dc12b09 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/binary/builder/BinaryBuilderReader.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/binary/builder/BinaryBuilderReader.java
@@ -51,7 +51,7 @@ public class BinaryBuilderReader implements BinaryPositionReadable {
     private final BinaryReaderExImpl reader;
 
     /** */
-    private final Map<Integer, BinaryObjectBuilderImpl> objMap;
+    private final Map<Integer, Object> objMap;
 
     /** */
     private int pos;
@@ -382,19 +382,21 @@ public class BinaryBuilderReader implements BinaryPositionReadable {
             case GridBinaryMarshaller.HANDLE: {
                 int objStart = pos - readIntPositioned(pos + 1);
 
-                BinaryObjectBuilderImpl res = objMap.get(objStart);
+                Object res = objMap.get(objStart);
 
-                if (res == null) {
-                    res = new BinaryObjectBuilderImpl(new BinaryBuilderReader(this, objStart), objStart);
+                if (res != null)
+                    return res;
 
-                    objMap.put(objStart, res);
-                }
+                // Read handle by position
+                res = getValueQuickly(objStart, len - (objStart - pos));
+
+                objMap.put(objStart, res);
 
                 return res;
             }
 
             case GridBinaryMarshaller.OBJ: {
-                BinaryObjectBuilderImpl res = objMap.get(pos);
+                Object res = objMap.get(pos);
 
                 if (res == null) {
                     res = new BinaryObjectBuilderImpl(new BinaryBuilderReader(this, pos), pos);
@@ -454,8 +456,18 @@ public class BinaryBuilderReader implements BinaryPositionReadable {
             case GridBinaryMarshaller.ENUM_ARR:
             case GridBinaryMarshaller.OBJ_ARR:
             case GridBinaryMarshaller.COL:
-            case GridBinaryMarshaller.MAP:
-                return new LazyCollection(pos);
+            case GridBinaryMarshaller.MAP: {
+                Object res = objMap.get(pos);
+
+                if (res != null)
+                    return res;
+
+                res = new LazyCollection(pos);
+
+                objMap.put(pos, res);
+
+                return res;
+            }
 
             case GridBinaryMarshaller.ENUM: {
                 if (len == 1) {
@@ -516,13 +528,20 @@ public class BinaryBuilderReader implements BinaryPositionReadable {
             case GridBinaryMarshaller.HANDLE: {
                 int objStart = pos - 1 - readInt();
 
-                BinaryObjectBuilderImpl res = objMap.get(objStart);
+                Object res = objMap.get(objStart);
 
-                if (res == null) {
-                    res = new BinaryObjectBuilderImpl(new BinaryBuilderReader(this, objStart), objStart);
+                if (res != null)
+                    return res;
 
-                    objMap.put(objStart, res);
-                }
+                // Read handle by position
+                int savedPos = pos;
+                pos = objStart;
+
+                res = parseValue();
+
+                pos = savedPos;
+
+                objMap.put(objStart, res);
 
                 return res;
             }
@@ -530,7 +549,7 @@ public class BinaryBuilderReader implements BinaryPositionReadable {
             case GridBinaryMarshaller.OBJ: {
                 pos--;
 
-                BinaryObjectBuilderImpl res = objMap.get(pos);
+                Object res = objMap.get(pos);
 
                 if (res == null) {
                     res = new BinaryObjectBuilderImpl(new BinaryBuilderReader(this, pos), pos);
@@ -764,24 +783,52 @@ public class BinaryBuilderReader implements BinaryPositionReadable {
                 int size = readInt();
                 byte colType = arr[pos++];
 
+                Object res = objMap.get(pos);
+                Object parseRes;
+
                 switch (colType) {
                     case GridBinaryMarshaller.USER_COL:
                     case GridBinaryMarshaller.ARR_LIST:
-                        return new BinaryLazyArrayList(this, size);
+                        parseRes = new BinaryLazyArrayList(this, size);
+
+                        break;
 
                     case GridBinaryMarshaller.LINKED_LIST:
-                        return new BinaryLazyLinkedList(this, size);
+                        parseRes = new BinaryLazyLinkedList(this, size);
+
+                        break;
 
                     case GridBinaryMarshaller.HASH_SET:
                     case GridBinaryMarshaller.LINKED_HASH_SET:
-                        return new BinaryLazySet(this, size);
+                        parseRes = new BinaryLazySet(this, size);
+
+                        break;
+
+                    default:
+                        throw new BinaryObjectException("Unknown collection type: " + colType);
+                }
+
+                if (res == null) {
+                    objMap.put(pos, parseRes);
+
+                    res = parseRes;
                 }
 
-                throw new BinaryObjectException("Unknown collection type: " + colType);
+                return res;
             }
 
-            case GridBinaryMarshaller.MAP:
-                return BinaryLazyMap.parseMap(this);
+            case GridBinaryMarshaller.MAP: {
+                Object res = objMap.get(pos);
+                Object parseRes = BinaryLazyMap.parseMap(this);
+
+                if (res == null) {
+                    objMap.put(pos, parseRes);
+
+                    res = parseRes;
+                }
+
+                return res;
+            }
 
             case GridBinaryMarshaller.ENUM:
                 return new BinaryBuilderEnum(this);
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/binary/BinaryMarshallerSelfTest.java b/modules/core/src/test/java/org/apache/ignite/internal/binary/BinaryMarshallerSelfTest.java
index f48bf9a..60f287a 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/binary/BinaryMarshallerSelfTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/binary/BinaryMarshallerSelfTest.java
@@ -43,6 +43,7 @@ import java.util.HashSet;
 import java.util.Iterator;
 import java.util.LinkedHashMap;
 import java.util.LinkedHashSet;
+import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
 import java.util.Objects;
@@ -52,6 +53,7 @@ import java.util.TreeSet;
 import java.util.UUID;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.ConcurrentSkipListSet;
+import java.util.function.Function;
 import java.util.stream.Collectors;
 import java.util.stream.IntStream;
 import com.google.common.collect.ImmutableList;
@@ -89,6 +91,7 @@ import org.apache.ignite.internal.processors.platform.utils.PlatformUtils;
 import org.apache.ignite.internal.util.GridUnsafe;
 import org.apache.ignite.internal.util.IgniteUtils;
 import org.apache.ignite.internal.util.lang.GridMapEntry;
+import org.apache.ignite.internal.util.lang.IgnitePair;
 import org.apache.ignite.internal.util.lang.IgniteThrowableConsumer;
 import org.apache.ignite.internal.util.typedef.F;
 import org.apache.ignite.internal.util.typedef.T2;
@@ -1032,6 +1035,56 @@ public class BinaryMarshallerSelfTest extends GridCommonAbstractTest {
     }
 
     /**
+     * Checks {@link BinaryBuilderReader#parseValue()} for object that contains handles to collection.
+     *
+     * @throws Exception If failed.
+     */
+    @Test
+    public void handleToCollection() throws Exception {
+        final IgnitePair<String>[] fieldsColAndHandle = new IgnitePair[] {
+            new IgnitePair<>("lst", "hndLst"),
+            new IgnitePair<>("linkedLst", "hndLinkedLst"),
+            new IgnitePair<>("map", "hndMap"),
+            new IgnitePair<>("linkedMap", "hndLinkedMap")
+        };
+        BinaryMarshaller m = binaryMarshaller();
+
+        HandleToCollections obj = new HandleToCollections();
+
+        BinaryObject bo = marshal(obj, m);
+
+        for (int i = 0; i < 10; ++i) {
+            BinaryObjectBuilder bob = bo.toBuilder();
+
+            if (i > 0)
+                assertEquals(i - 1, (int)bo.field("a"));
+
+            bob.setField("a", i);
+
+            for (IgnitePair<String> flds : fieldsColAndHandle) {
+                // Different orders to read collection and handle to collection.
+                Object col;
+                Object colHnd;
+
+                if (i % 2 == 0) {
+                    col = bob.getField(flds.get1());
+                    colHnd = bob.getField(flds.get2());
+                }
+                else {
+                    colHnd = bob.getField(flds.get2());
+                    col = bob.getField(flds.get1());
+                }
+
+                // Must be assertSame but now BinaryObjectBuilder doesn't support handle to collection.
+                // Now we check only that BinaryObjectBuilder#getField doesn't crash and returns valid collection.
+                assertEquals("Check: " + flds, col, colHnd);
+            }
+
+            bo = bob.build();
+        }
+    }
+
+    /**
      *
      */
     private static class EnclosingObj implements Serializable {
@@ -5826,4 +5879,48 @@ public class BinaryMarshallerSelfTest extends GridCommonAbstractTest {
             }
         }
     }
+
+    /** */
+    public static class HandleToCollections {
+        /** */
+        List<Value> lst;
+
+        /** */
+        List<Value> hndLst;
+
+        /** */
+        List<Value> linkedLst;
+
+        /** */
+        List<Value> hndLinkedLst;
+
+        /** */
+        Map<Integer, Value> map;
+
+        /** */
+        Map<Integer, Value> hndMap;
+
+        /** */
+        Map<Integer, Value> linkedMap;
+
+        /** */
+        Map<Integer, Value> hndLinkedMap;
+
+        /** */
+        public HandleToCollections() {
+            lst = new ArrayList<>(Arrays.asList(new Value(0), new Value(1)));
+            hndLst = lst;
+
+            linkedLst = new LinkedList<>(Arrays.asList(new Value(0), new Value(1)));
+            hndLinkedLst = linkedLst;
+
+            map = IntStream.range(0, 1).boxed()
+                .collect(Collectors.toMap(Function.identity(), Value::new));
+            hndMap = map;
+
+            linkedMap = IntStream.range(0, 1).boxed()
+                .collect(Collectors.toMap(Function.identity(), Value::new, (a, b) -> a, LinkedHashMap::new));
+            hndLinkedMap = linkedMap;
+        }
+    }
 }