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

nizhikov 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 cb313f7379f IGNITE-23513 Use limited representation for arrays in 
BinaryObjectExImpl::toString (#11610)
cb313f7379f is described below

commit cb313f7379f38a469fa8d3b3e245a185c9608a88
Author: Sergey Korotkov <[email protected]>
AuthorDate: Mon Oct 28 14:53:35 2024 +0700

    IGNITE-23513 Use limited representation for arrays in 
BinaryObjectExImpl::toString (#11610)
---
 .../ignite/internal/binary/BinaryObjectExImpl.java | 59 ++++++++++++---
 .../util/tostring/GridToStringBuilder.java         |  2 +-
 .../binary/BinaryObjectToStringSelfTest.java       | 86 ++++++++++++++++++++++
 3 files changed, 134 insertions(+), 13 deletions(-)

diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryObjectExImpl.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryObjectExImpl.java
index 27bbbe7c17f..453cdbf69be 100644
--- 
a/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryObjectExImpl.java
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryObjectExImpl.java
@@ -19,7 +19,6 @@ package org.apache.ignite.internal.binary;
 
 import java.math.BigDecimal;
 import java.nio.ByteBuffer;
-import java.util.Arrays;
 import java.util.IdentityHashMap;
 import java.util.Iterator;
 import java.util.Map;
@@ -37,6 +36,8 @@ import org.apache.ignite.lang.IgniteUuid;
 import org.apache.ignite.thread.IgniteThread;
 import org.jetbrains.annotations.Nullable;
 
+import static 
org.apache.ignite.internal.util.tostring.GridToStringBuilder.COLLECTION_LIMIT;
+
 /**
  * Internal binary object interface.
  */
@@ -269,23 +270,23 @@ public abstract class BinaryObjectExImpl implements 
BinaryObjectEx {
     private void appendValue(Object val, SB buf, BinaryReaderHandles ctx,
         IdentityHashMap<BinaryObject, Integer> handles) {
         if (val instanceof byte[])
-            buf.a(Arrays.toString((byte[])val));
+            buf.a(S.arrayToString(val));
         else if (val instanceof short[])
-            buf.a(Arrays.toString((short[])val));
+            buf.a(S.arrayToString(val));
         else if (val instanceof int[])
-            buf.a(Arrays.toString((int[])val));
+            buf.a(S.arrayToString(val));
         else if (val instanceof long[])
-            buf.a(Arrays.toString((long[])val));
+            buf.a(S.arrayToString(val));
         else if (val instanceof float[])
-            buf.a(Arrays.toString((float[])val));
+            buf.a(S.arrayToString(val));
         else if (val instanceof double[])
-            buf.a(Arrays.toString((double[])val));
+            buf.a(S.arrayToString(val));
         else if (val instanceof char[])
-            buf.a(Arrays.toString((char[])val));
+            buf.a(S.arrayToString(val));
         else if (val instanceof boolean[])
-            buf.a(Arrays.toString((boolean[])val));
+            buf.a(S.arrayToString(val));
         else if (val instanceof BigDecimal[])
-            buf.a(Arrays.toString((BigDecimal[])val));
+            buf.a(S.arrayToString(val));
         else if (val instanceof IgniteUuid)
             buf.a(val);
         else if (val instanceof BinaryObjectExImpl) {
@@ -308,14 +309,20 @@ public abstract class BinaryObjectExImpl implements 
BinaryObjectEx {
 
             buf.a('[');
 
-            for (int i = 0; i < arr.length; i++) {
+            int len = Math.min(arr.length, COLLECTION_LIMIT);
+
+            for (int i = 0; i < len; i++) {
                 Object o = arr[i];
 
                 appendValue(o, buf, ctx, handles);
 
-                if (i < arr.length - 1)
+                if (i < len - 1)
                     buf.a(", ");
             }
+
+            handleOverflow(buf, arr.length);
+
+            buf.a(']');
         }
         else if (val instanceof Iterable) {
             Iterable<Object> col = (Iterable<Object>)val;
@@ -324,15 +331,23 @@ public abstract class BinaryObjectExImpl implements 
BinaryObjectEx {
 
             Iterator it = col.iterator();
 
+            int cnt = 0;
+
             while (it.hasNext()) {
                 Object o = it.next();
 
                 appendValue(o, buf, ctx, handles);
 
+                if (++cnt == COLLECTION_LIMIT)
+                    break;
+
                 if (it.hasNext())
                     buf.a(", ");
             }
 
+            if (it.hasNext())
+                buf.a("... and more");
+
             buf.a('}');
         }
         else if (val instanceof Map) {
@@ -342,6 +357,8 @@ public abstract class BinaryObjectExImpl implements 
BinaryObjectEx {
 
             Iterator<Map.Entry<Object, Object>> it = map.entrySet().iterator();
 
+            int cnt = 0;
+
             while (it.hasNext()) {
                 Map.Entry<Object, Object> e = it.next();
 
@@ -351,16 +368,34 @@ public abstract class BinaryObjectExImpl implements 
BinaryObjectEx {
 
                 appendValue(e.getValue(), buf, ctx, handles);
 
+                if (++cnt == COLLECTION_LIMIT)
+                    break;
+
                 if (it.hasNext())
                     buf.a(", ");
             }
 
+            handleOverflow(buf, map.size());
+
             buf.a('}');
         }
         else
             buf.a(val);
     }
 
+    /**
+     * Writes overflow message to buffer if needed.
+     *
+     * @param buf String builder buffer.
+     * @param size Size to compare with limit.
+     */
+    private static void handleOverflow(SB buf, int size) {
+        int overflow = size - COLLECTION_LIMIT;
+
+        if (overflow > 0)
+            buf.a("... and ").a(overflow).a(" more");
+    }
+
     /**
      * Check if object graph has circular references.
      *
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/util/tostring/GridToStringBuilder.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/util/tostring/GridToStringBuilder.java
index 11eb3d9561a..d38c0f8711e 100644
--- 
a/modules/core/src/main/java/org/apache/ignite/internal/util/tostring/GridToStringBuilder.java
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/util/tostring/GridToStringBuilder.java
@@ -122,7 +122,7 @@ public class GridToStringBuilder {
     public static final int DFLT_TO_STRING_COLLECTION_LIMIT = 100;
 
     /** */
-    private static final int COLLECTION_LIMIT =
+    public static final int COLLECTION_LIMIT =
         IgniteSystemProperties.getInteger(IGNITE_TO_STRING_COLLECTION_LIMIT, 
DFLT_TO_STRING_COLLECTION_LIMIT);
 
     /** Every thread has its own string builder. */
diff --git 
a/modules/core/src/test/java/org/apache/ignite/internal/binary/BinaryObjectToStringSelfTest.java
 
b/modules/core/src/test/java/org/apache/ignite/internal/binary/BinaryObjectToStringSelfTest.java
index 02939b55263..7b11ad91007 100644
--- 
a/modules/core/src/test/java/org/apache/ignite/internal/binary/BinaryObjectToStringSelfTest.java
+++ 
b/modules/core/src/test/java/org/apache/ignite/internal/binary/BinaryObjectToStringSelfTest.java
@@ -17,15 +17,20 @@
 
 package org.apache.ignite.internal.binary;
 
+import java.math.BigDecimal;
 import java.util.Arrays;
 import java.util.Collection;
 import java.util.HashMap;
+import java.util.List;
 import java.util.Map;
+import org.apache.ignite.IgniteSystemProperties;
 import org.apache.ignite.binary.BinaryObject;
 import org.apache.ignite.configuration.IgniteConfiguration;
 import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest;
 import org.junit.Test;
 
+import static 
org.apache.ignite.internal.util.tostring.GridToStringBuilder.DFLT_TO_STRING_COLLECTION_LIMIT;
+
 /**
  * Tests for {@code BinaryObject.toString()}.
  */
@@ -72,6 +77,87 @@ public class BinaryObjectToStringSelfTest extends 
GridCommonAbstractTest {
         bo.toString();
     }
 
+    /**
+     * Check if toString produce limited representation respecting the
+     * {@link IgniteSystemProperties#IGNITE_TO_STRING_COLLECTION_LIMIT } limit.
+     *
+     * @throws Exception If failed.
+     */
+    @Test
+    public void testToStringForLargeArrays() throws Exception {
+        List<String> types = Arrays.asList(
+            "byte",
+            "short",
+            "int",
+            "long",
+            "float",
+            "double",
+            "char",
+            "boolean",
+            "BigDecimal",
+            "Object",
+            "Iterable",
+            "Map"
+        );
+
+        for (String type : types) {
+            assertFalse(String.format("type=%s, size=%d", type, 
DFLT_TO_STRING_COLLECTION_LIMIT - 1),
+                    containElipsis(type, getObject(type, 
DFLT_TO_STRING_COLLECTION_LIMIT - 1)));
+
+            assertFalse(String.format("type=%s, size=%d", type, 
DFLT_TO_STRING_COLLECTION_LIMIT),
+                    containElipsis(type, getObject(type, 
DFLT_TO_STRING_COLLECTION_LIMIT)));
+
+            assertTrue(String.format("type=%s, size=%d", type, 
DFLT_TO_STRING_COLLECTION_LIMIT + 1),
+                    containElipsis(type, getObject(type, 
DFLT_TO_STRING_COLLECTION_LIMIT + 1)));
+        }
+    }
+
+    /** */
+    private Object getObject(String type, int size) {
+        switch (type) {
+            case "byte":
+                return new byte[size];
+            case "short":
+                return new short[size];
+            case "int":
+                return new int[size];
+            case "long":
+                return new long[size];
+            case "float":
+                return new float[size];
+            case "double":
+                return new double[size];
+            case "char":
+                return new char[size];
+            case "boolean":
+                return new boolean[size];
+            case "BigDecimal":
+                return new BigDecimal[size];
+            case "Object":
+                return new MyObject[size];
+            case "Map":
+                Map<Integer, MyObject> map = new HashMap<>();
+
+                for (int i = 0; i < size; i++)
+                    map.put(i, new MyObject());
+
+                return map;
+            default:
+                // Iterable
+                return Arrays.asList(new String[size]);
+        }
+    }
+
+    /** */
+    private boolean containElipsis(String type, Object val) {
+        BinaryObject bo = grid().binary()
+                .builder(type)
+                .setField("field", val)
+                .build();
+
+        return bo.toString().contains("...");
+    }
+
     /**
      */
     private static class MyObject {

Reply via email to