[ 
https://issues.apache.org/jira/browse/IGNITE-16057?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
 ]

Vladimir Ermakov updated IGNITE-16057:
--------------------------------------
    Description: 
Second read of array field fail and read some garbage.
This happen because when object read with handle stream position don't move to 
the end of already deserialized object.
So second array element is just random bytes from the middle of the stream.

Root cause:

In the previous patch, handlers were added to allow to cache values that have 
already been read. Handles were added for objects, but not for arrays. When 
reading an array, it first creates a new array instance and then reads the 
objects in that array in the order in which they appear in the array.

The problem is that when an object is read, the position of the next object in 
the binary array is set. This way we can always continue reading objects in 
order. But now we just return a cached object, and don't calculate next 
position. So we read garbage, or we get an error when we try to read the next 
item because we don't know its real position.

Siggestion fix:

We need to add handle logic when reading arrays. Then when you try to read the 
array again, a cached copy will be returned.

It is also necessary to consider the deserialization flag. If it is set, it is 
necessary to re-read the array and fill it with deserialized copies of objects.

 

BinaryObjectBuilderAdditionalSelfTest
{code:java}
    /** */
    @Test
    public void testArrayFieldSeveralRead() throws Exception {
        try (Ignite ignite = startGrid(1)) {
            TestClass1[] expArr = new TestClass1[] {new TestClass1(), new 
TestClass1()};

            BinaryObject arrObj = ignite.binary().toBinary(new 
TestClsWithArray(expArr));

            for (int i = 0; i < 10; i++)
                Assert.assertArrayEquals(i + " iteration", expArr, 
PlatformUtils.unwrapBinariesInArray(arrObj.field("arr")));

            arrObj = 
ignite.binary().builder(TestClsWithArray.class.getName()).setField("arr", 
expArr).build();

            for (int i = 0; i < 10; i++)
                Assert.assertArrayEquals(i + " iteration", expArr, 
PlatformUtils.unwrapBinariesInArray(arrObj.field("arr")));
        }
        finally {
            clearBinaryMeta();
        }
    }

    /** Test class with array. */
    public static class TestClsWithArray {
        /** */
        private final Object[] arr;

        /** */
        public TestClsWithArray(TestClass1[] arr) {
            this.arr = arr;
        }
    }
{code}

  was:
Second read of array field fail and read some garbage.
This happen because when object read with handle stream position don't move to 
the end of already deserialized object.
So second array element is just random bytes from the middle of the stream.

BinaryObjectBuilderAdditionalSelfTest
{code:java}
    /** */
    @Test
    public void testArrayFieldSeveralRead() throws Exception {
        try (Ignite ignite = startGrid(1)) {
            TestClass1[] expArr = new TestClass1[] {new TestClass1(), new 
TestClass1()};

            BinaryObject arrObj = ignite.binary().toBinary(new 
TestClsWithArray(expArr));

            for (int i = 0; i < 10; i++)
                Assert.assertArrayEquals(i + " iteration", expArr, 
PlatformUtils.unwrapBinariesInArray(arrObj.field("arr")));

            arrObj = 
ignite.binary().builder(TestClsWithArray.class.getName()).setField("arr", 
expArr).build();

            for (int i = 0; i < 10; i++)
                Assert.assertArrayEquals(i + " iteration", expArr, 
PlatformUtils.unwrapBinariesInArray(arrObj.field("arr")));
        }
        finally {
            clearBinaryMeta();
        }
    }

    /** Test class with array. */
    public static class TestClsWithArray {
        /** */
        private final Object[] arr;

        /** */
        public TestClsWithArray(TestClass1[] arr) {
            this.arr = arr;
        }
    }
{code}


> Second read of array field from BinaryObject fail
> -------------------------------------------------
>
>                 Key: IGNITE-16057
>                 URL: https://issues.apache.org/jira/browse/IGNITE-16057
>             Project: Ignite
>          Issue Type: Bug
>            Reporter: Nikolay Izhikov
>            Assignee: Vladimir Ermakov
>            Priority: Blocker
>              Labels: ise
>
> Second read of array field fail and read some garbage.
> This happen because when object read with handle stream position don't move 
> to the end of already deserialized object.
> So second array element is just random bytes from the middle of the stream.
> Root cause:
> In the previous patch, handlers were added to allow to cache values that have 
> already been read. Handles were added for objects, but not for arrays. When 
> reading an array, it first creates a new array instance and then reads the 
> objects in that array in the order in which they appear in the array.
> The problem is that when an object is read, the position of the next object 
> in the binary array is set. This way we can always continue reading objects 
> in order. But now we just return a cached object, and don't calculate next 
> position. So we read garbage, or we get an error when we try to read the next 
> item because we don't know its real position.
> Siggestion fix:
> We need to add handle logic when reading arrays. Then when you try to read 
> the array again, a cached copy will be returned.
> It is also necessary to consider the deserialization flag. If it is set, it 
> is necessary to re-read the array and fill it with deserialized copies of 
> objects.
>  
> BinaryObjectBuilderAdditionalSelfTest
> {code:java}
>     /** */
>     @Test
>     public void testArrayFieldSeveralRead() throws Exception {
>         try (Ignite ignite = startGrid(1)) {
>             TestClass1[] expArr = new TestClass1[] {new TestClass1(), new 
> TestClass1()};
>             BinaryObject arrObj = ignite.binary().toBinary(new 
> TestClsWithArray(expArr));
>             for (int i = 0; i < 10; i++)
>                 Assert.assertArrayEquals(i + " iteration", expArr, 
> PlatformUtils.unwrapBinariesInArray(arrObj.field("arr")));
>             arrObj = 
> ignite.binary().builder(TestClsWithArray.class.getName()).setField("arr", 
> expArr).build();
>             for (int i = 0; i < 10; i++)
>                 Assert.assertArrayEquals(i + " iteration", expArr, 
> PlatformUtils.unwrapBinariesInArray(arrObj.field("arr")));
>         }
>         finally {
>             clearBinaryMeta();
>         }
>     }
>     /** Test class with array. */
>     public static class TestClsWithArray {
>         /** */
>         private final Object[] arr;
>         /** */
>         public TestClsWithArray(TestClass1[] arr) {
>             this.arr = arr;
>         }
>     }
> {code}



--
This message was sent by Atlassian Jira
(v8.20.1#820001)

Reply via email to