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 {