ignite-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From sboi...@apache.org
Subject [02/17] ignite git commit: ignite-7195: Length limit for GridToStringBuilder
Date Thu, 11 Jan 2018 12:10:52 GMT
ignite-7195: Length limit for GridToStringBuilder


Project: http://git-wip-us.apache.org/repos/asf/ignite/repo
Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/5d66516d
Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/5d66516d
Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/5d66516d

Branch: refs/heads/ignite-zk
Commit: 5d66516d18b84878331918b79afe452d70bd7a42
Parents: f2edb7e
Author: Alexander Belyak <alexandr.belyak@xored.com>
Authored: Wed Jan 10 12:03:20 2018 +0300
Committer: sboikov <sboikov@gridgain.com>
Committed: Wed Jan 10 12:03:20 2018 +0300

----------------------------------------------------------------------
 .../apache/ignite/IgniteSystemProperties.java   |   8 +
 .../util/tostring/CircularStringBuilder.java    | 179 +++++++++
 .../util/tostring/GridToStringBuilder.java      | 359 ++++++++++++++-----
 .../util/tostring/GridToStringThreadLocal.java  |   9 +-
 .../internal/util/tostring/SBLengthLimit.java   |  74 ++++
 .../internal/util/tostring/SBLimitedLength.java | 285 +++++++++++++++
 .../tostring/CircularStringBuilderSelfTest.java |  69 ++++
 .../tostring/GridToStringBuilderSelfTest.java   | 116 +++++-
 .../testsuites/IgniteUtilSelfTestSuite.java     |   2 +
 9 files changed, 1014 insertions(+), 87 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/5d66516d/modules/core/src/main/java/org/apache/ignite/IgniteSystemProperties.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/IgniteSystemProperties.java b/modules/core/src/main/java/org/apache/ignite/IgniteSystemProperties.java
index 9732905..ad4835a 100644
--- a/modules/core/src/main/java/org/apache/ignite/IgniteSystemProperties.java
+++ b/modules/core/src/main/java/org/apache/ignite/IgniteSystemProperties.java
@@ -158,6 +158,14 @@ public final class IgniteSystemProperties {
      */
     public static final String IGNITE_TO_STRING_INCLUDE_SENSITIVE = "IGNITE_TO_STRING_INCLUDE_SENSITIVE";
 
+    /** Maximum length for {@code toString()} result. */
+    public static final String IGNITE_TO_STRING_MAX_LENGTH = "IGNITE_TO_STRING_MAX_LENGTH";
+
+    /**
+     * Limit collection (map, array) elements number to output.
+     */
+    public static final String IGNITE_TO_STRING_COLLECTION_LIMIT = "IGNITE_TO_STRING_COLLECTION_LIMIT";
+
     /**
      * If this property is set to {@code true} (default) and Ignite is launched
      * in verbose mode (see {@link #IGNITE_QUIET}) and no console appenders can be found

http://git-wip-us.apache.org/repos/asf/ignite/blob/5d66516d/modules/core/src/main/java/org/apache/ignite/internal/util/tostring/CircularStringBuilder.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/util/tostring/CircularStringBuilder.java b/modules/core/src/main/java/org/apache/ignite/internal/util/tostring/CircularStringBuilder.java
new file mode 100644
index 0000000..4f33724
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/util/tostring/CircularStringBuilder.java
@@ -0,0 +1,179 @@
+/*
+ * 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.util.tostring;
+
+/**
+ * Basic string builder over circular buffer.
+ */
+public class CircularStringBuilder {
+
+    /** Value */
+    private final char value[];
+
+    /** Last written character idx (-1 if empty). */
+    private int finishAt = -1;
+
+    /** Value is full flag. */
+    private boolean full;
+
+    /** Number of skipped characters */
+    private int skipped = 0;
+
+    /**
+     * Creates an CircularStringBuilder of the specified capacity.
+     *
+     * @param capacity Capacity.
+     */
+    CircularStringBuilder (int capacity) {
+        assert capacity > 0 : "Can't allocate CircularStringBuilder with capacity: " + capacity;
+
+        value = new char[capacity];
+    }
+
+    /**
+     * Returns the length (character count).
+     *
+     * @return  the length of the sequence of characters currently
+     *          represented by this object
+     */
+    public int length() { return full ? value.length : finishAt + 1; }
+
+    /**
+     * Returns the current capacity.
+     *
+     * @return  the current capacity
+     */
+    public int capacity() {
+        return value.length;
+    }
+
+    /**
+     * Appends the string representation of the {@code Object} argument.
+     *
+     * @param   obj   an {@code Object}.
+     * @return  a reference to this object.
+     */
+    public CircularStringBuilder append(Object obj) {
+        return append(String.valueOf(obj));
+    }
+
+    /**
+     * Appends the specified string to this character sequence.
+     *
+     * @param   str   a string.
+     * @return  a reference to this object.
+     */
+    public CircularStringBuilder append(String str) {
+        if (str == null)
+            return appendNull();
+
+        int objStrLen = str.length();
+
+        if (objStrLen >= value.length) {
+            // String bigger or equal to value length
+            str.getChars(objStrLen - value.length, objStrLen, value, 0);
+
+            skipped += objStrLen - value.length + finishAt + 1;
+
+            finishAt = value.length - 1;
+
+            full = true;
+        }
+        else {
+            // String smaller then value length
+            if (value.length - finishAt - 1 < objStrLen) {
+                // String doesn't fit into remaining part of value array
+                int firstPart = value.length - finishAt - 1;
+
+                if (firstPart > 0)
+                    str.getChars(0, firstPart, value, finishAt + 1);
+
+                str.getChars(firstPart, objStrLen, value, 0);
+
+                skipped += full ? objStrLen : objStrLen - firstPart;
+
+                finishAt = finishAt + objStrLen - value.length;
+            }
+            else {
+                // Whole string fin into remaining part of value array
+                str.getChars(0, objStrLen, value, finishAt + 1);
+
+                skipped += full ? objStrLen : 0;
+
+                finishAt += objStrLen;
+            }
+
+            full = full || finishAt + objStrLen >= value.length - 1;
+        }
+
+        return this;
+    }
+
+    /**
+     * Append StringBuffer
+     *
+     * @param sb StringBuffer to append.
+     * @return Reference to this object.
+     */
+    public CircularStringBuilder append(StringBuffer sb) {
+        if (sb == null)
+            return appendNull();
+
+        int len = sb.length();
+
+        if (len < value.length)
+            append(sb.toString());
+        else {
+            skipped += len - value.length;
+
+            append(sb.substring(len - value.length));
+        }
+
+        return this;
+    }
+
+    /**
+     * @return This builder.
+     */
+    private CircularStringBuilder appendNull() {
+        append("null");
+
+        return this;
+    }
+
+    /**
+     * @return Count of skipped elements.
+     */
+    public int getSkipped() { return skipped; }
+
+    /** {@inheritDoc} */
+    @Override public String toString() {
+        // Create a copy, don't share the array
+        if (full) {
+            char strValue[] = new char[value.length];
+            int firstPart = value.length - finishAt - 1;
+
+            System.arraycopy(value, finishAt + 1, strValue, 0, firstPart);
+            System.arraycopy(value, 0, strValue, firstPart, value.length - firstPart);
+
+            return new String(strValue, 0, strValue.length);
+        }
+        else
+            return new String(value, 0, finishAt + 1);
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/5d66516d/modules/core/src/main/java/org/apache/ignite/internal/util/tostring/GridToStringBuilder.java
----------------------------------------------------------------------
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 8d578ac..ab3bb75 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
@@ -20,7 +20,6 @@ package org.apache.ignite.internal.util.tostring;
 import org.apache.ignite.IgniteException;
 import org.apache.ignite.IgniteSystemProperties;
 import org.apache.ignite.internal.util.typedef.F;
-import org.apache.ignite.internal.util.typedef.internal.SB;
 import org.apache.ignite.internal.util.typedef.internal.U;
 import org.jetbrains.annotations.Nullable;
 
@@ -43,6 +42,7 @@ import java.util.concurrent.locks.ReadWriteLock;
 import java.util.concurrent.locks.ReentrantReadWriteLock;
 
 import static org.apache.ignite.IgniteSystemProperties.IGNITE_TO_STRING_INCLUDE_SENSITIVE;
+import static org.apache.ignite.IgniteSystemProperties.IGNITE_TO_STRING_COLLECTION_LIMIT;
 
 /**
  * Provides auto-generation framework for {@code toString()} output.
@@ -86,14 +86,15 @@ public class GridToStringBuilder {
     /** */
     private static final ReadWriteLock rwLock = new ReentrantReadWriteLock();
 
-    /** Maximum number of collection (map) entries to print. */
-    public static final int MAX_COL_SIZE = 200;
-
     /** {@link IgniteSystemProperties#IGNITE_TO_STRING_INCLUDE_SENSITIVE} */
     public static final boolean INCLUDE_SENSITIVE =
         IgniteSystemProperties.getBoolean(IGNITE_TO_STRING_INCLUDE_SENSITIVE, true);
 
     /** */
+    private static final int COLLECTION_LIMIT =
+        IgniteSystemProperties.getInteger(IGNITE_TO_STRING_COLLECTION_LIMIT, 100);
+
+    /** */
     private static ThreadLocal<Queue<GridToStringThreadLocal>> threadCache = new ThreadLocal<Queue<GridToStringThreadLocal>>() {
         @Override protected Queue<GridToStringThreadLocal> initialValue() {
             Queue<GridToStringThreadLocal> queue = new LinkedList<>();
@@ -104,6 +105,14 @@ public class GridToStringBuilder {
         }
     };
 
+    /** */
+    private static ThreadLocal<SBLengthLimit> threadCurLen = new ThreadLocal<SBLengthLimit>() {
+        @Override protected SBLengthLimit initialValue() {
+            return new SBLengthLimit();
+        }
+    };
+
+
     /**
      * Produces auto-generated output of string presentation for given object and its declaration class.
      *
@@ -281,11 +290,20 @@ public class GridToStringBuilder {
         addVals[4] = val4;
         addSens[4] = sens4;
 
+        SBLengthLimit lenLim = threadCurLen.get();
+
+        boolean newStr = false;
+
         try {
-            return toStringImpl(cls, tmp.getStringBuilder(), obj, addNames, addVals, addSens, 5);
+            newStr = lenLim.length() == 0;
+
+            return toStringImpl(cls, tmp.getStringBuilder(lenLim), obj, addNames, addVals, addSens, 5);
         }
         finally {
             queue.offer(tmp);
+
+            if (newStr)
+                lenLim.reset();
         }
     }
 
@@ -363,11 +381,20 @@ public class GridToStringBuilder {
         addVals[5] = val5;
         addSens[5] = sens5;
 
+        SBLengthLimit lenLim = threadCurLen.get();
+
+        boolean newStr = false;
+
         try {
-            return toStringImpl(cls, tmp.getStringBuilder(), obj, addNames, addVals, addSens, 6);
+            newStr = lenLim.length() == 0;
+
+            return toStringImpl(cls, tmp.getStringBuilder(lenLim), obj, addNames, addVals, addSens, 6);
         }
         finally {
             queue.offer(tmp);
+
+            if (newStr)
+                lenLim.reset();
         }
     }
 
@@ -453,11 +480,20 @@ public class GridToStringBuilder {
         addVals[6] = val6;
         addSens[6] = sens6;
 
+        SBLengthLimit lenLim = threadCurLen.get();
+
+        boolean newStr = false;
+
         try {
-            return toStringImpl(cls, tmp.getStringBuilder(), obj, addNames, addVals, addSens, 7);
+            newStr = lenLim.length() == 0;
+
+            return toStringImpl(cls, tmp.getStringBuilder(lenLim), obj, addNames, addVals, addSens, 7);
         }
         finally {
             queue.offer(tmp);
+
+            if (newStr)
+                lenLim.reset();
         }
     }
 
@@ -547,11 +583,20 @@ public class GridToStringBuilder {
         addVals[3] = val3;
         addSens[3] = sens3;
 
+        SBLengthLimit lenLim = threadCurLen.get();
+
+        boolean newStr = false;
+
         try {
-            return toStringImpl(cls, tmp.getStringBuilder(), obj, addNames, addVals, addSens, 4);
+            newStr = lenLim.length() == 0;
+
+            return toStringImpl(cls, tmp.getStringBuilder(lenLim), obj, addNames, addVals, addSens, 4);
         }
         finally {
             queue.offer(tmp);
+
+            if (newStr)
+                lenLim.reset();
         }
     }
 
@@ -630,11 +675,20 @@ public class GridToStringBuilder {
         addVals[2] = val2;
         addSens[2] = sens2;
 
+        SBLengthLimit lenLim = threadCurLen.get();
+
+        boolean newStr = false;
+
         try {
-            return toStringImpl(cls, tmp.getStringBuilder(), obj, addNames, addVals, addSens, 3);
+            newStr = lenLim.length() == 0;
+
+            return toStringImpl(cls, tmp.getStringBuilder(lenLim), obj, addNames, addVals, addSens, 3);
         }
         finally {
             queue.offer(tmp);
+
+            if (newStr)
+                lenLim.reset();
         }
     }
 
@@ -698,11 +752,20 @@ public class GridToStringBuilder {
         addVals[1] = val1;
         addSens[1] = sens1;
 
+        SBLengthLimit lenLim = threadCurLen.get();
+
+        boolean newStr = false;
+
         try {
-            return toStringImpl(cls, tmp.getStringBuilder(), obj, addNames, addVals, addSens, 2);
+            newStr = lenLim.length() == 0;
+
+            return toStringImpl(cls, tmp.getStringBuilder(lenLim), obj, addNames, addVals, addSens, 2);
         }
         finally {
             queue.offer(tmp);
+
+            if (newStr)
+                lenLim.reset();
         }
     }
 
@@ -753,11 +816,20 @@ public class GridToStringBuilder {
         addVals[0] = val;
         addSens[0] = sens;
 
+        SBLengthLimit lenLim = threadCurLen.get();
+
+        boolean newStr = false;
+
         try {
-            return toStringImpl(cls, tmp.getStringBuilder(), obj, addNames, addVals, addSens, 1);
+            newStr = lenLim.length() == 0;
+
+            return toStringImpl(cls, tmp.getStringBuilder(lenLim), obj, addNames, addVals, addSens, 1);
         }
         finally {
             queue.offer(tmp);
+
+            if (newStr)
+                lenLim.reset();
         }
     }
 
@@ -782,12 +854,21 @@ public class GridToStringBuilder {
         // in each string() apply.
         GridToStringThreadLocal tmp = queue.isEmpty() ? new GridToStringThreadLocal() : queue.remove();
 
+        SBLengthLimit lenLim = threadCurLen.get();
+
+        boolean newStr = false;
+
         try {
-            return toStringImpl(cls, tmp.getStringBuilder(), obj, tmp.getAdditionalNames(),
+            newStr = lenLim.length() == 0;
+
+            return toStringImpl(cls, tmp.getStringBuilder(lenLim), obj, tmp.getAdditionalNames(),
                 tmp.getAdditionalValues(), null, 0);
         }
         finally {
             queue.offer(tmp);
+
+            if (newStr)
+                lenLim.reset();
         }
     }
 
@@ -805,6 +886,66 @@ public class GridToStringBuilder {
     }
 
     /**
+     * Print value with length limitation
+     * @param buf buffer to print to.
+     * @param val value to print, can be {@code null}.
+     */
+    private static void toString(SBLimitedLength buf, Object val) {
+        if (val == null)
+            buf.a("null");
+        else
+            toString(buf, val.getClass(), val);
+    }
+
+    /**
+     * Print value with length limitation
+     * @param buf buffer to print to.
+     * @param valClass value class.
+     * @param val value to print
+     */
+    private static void toString(SBLimitedLength buf, Class<?> valClass, Object val) {
+        if (valClass.isArray())
+            buf.a(arrayToString(valClass, val));
+        else {
+            int overflow = 0;
+            char bracket = ' ';
+
+            if (val instanceof Collection && ((Collection)val).size() > COLLECTION_LIMIT) {
+                overflow = ((Collection)val).size() - COLLECTION_LIMIT;
+                bracket = ']';
+                val = F.retain((Collection) val, true, COLLECTION_LIMIT);
+            }
+            else if (val instanceof Map && ((Map)val).size() > COLLECTION_LIMIT) {
+                Map<Object, Object> tmp = U.newHashMap(COLLECTION_LIMIT);
+
+                overflow = ((Map)val).size() - COLLECTION_LIMIT;
+
+                bracket= '}';
+
+                int cntr = 0;
+
+                for (Object o : ((Map)val).entrySet()) {
+                    Map.Entry e = (Map.Entry)o;
+
+                    tmp.put(e.getKey(), e.getValue());
+
+                    if (++cntr >= COLLECTION_LIMIT)
+                        break;
+                }
+
+                val = tmp;
+            }
+
+            buf.a(val);
+
+            if (overflow > 0) {
+                buf.d(buf.length() - 1);
+                buf.a("... and ").a(overflow).a(" more").a(bracket);
+            }
+        }
+    }
+
+    /**
      * Creates an uniformed string presentation for the given object.
      *
      * @param cls Class of the object.
@@ -818,7 +959,10 @@ public class GridToStringBuilder {
      * @param <T> Type of object.
      */
     @SuppressWarnings({"unchecked"})
-    private static <T> String toStringImpl(Class<T> cls, SB buf, T obj,
+    private static <T> String toStringImpl(
+        Class<T> cls,
+        SBLimitedLength buf,
+        T obj,
         Object[] addNames,
         Object[] addVals,
         @Nullable boolean[] addSens,
@@ -844,7 +988,7 @@ public class GridToStringBuilder {
 
             for (GridToStringFieldDescriptor fd : cd.getFields()) {
                 if (!first)
-                   buf.a(", ");
+                    buf.a(", ");
                 else
                     first = false;
 
@@ -858,31 +1002,7 @@ public class GridToStringBuilder {
 
                 Class<?> fieldType = field.getType();
 
-                if (fieldType.isArray())
-                    buf.a(arrayToString(fieldType, field.get(obj)));
-                else {
-                    Object val = field.get(obj);
-
-                    if (val instanceof Collection && ((Collection)val).size() > MAX_COL_SIZE)
-                        val = F.retain((Collection)val, true, MAX_COL_SIZE);
-                    else if (val instanceof Map && ((Map)val).size() > MAX_COL_SIZE) {
-                        Map tmp = U.newHashMap(MAX_COL_SIZE);
-                        int cntr = 0;
-
-                        for (Object o : ((Map)val).entrySet()) {
-                            Map.Entry e = (Map.Entry)o;
-
-                            tmp.put(e.getKey(), e.getValue());
-
-                            if (++cntr >= MAX_COL_SIZE)
-                                break;
-                        }
-
-                        val = tmp;
-                    }
-
-                    buf.a(val);
-                }
+                toString(buf, fieldType, field.get(obj));
             }
 
             appendVals(buf, first, addNames, addVals, addSens, addLen);
@@ -910,32 +1030,6 @@ public class GridToStringBuilder {
     }
 
     /**
-     * @param arrType Type of the array.
-     * @param arr Array object.
-     * @return String representation of an array.
-     */
-    public static String arrayToString(Class arrType, Object arr) {
-        if (arrType.equals(byte[].class))
-            return Arrays.toString((byte[])arr);
-        if (arrType.equals(boolean[].class))
-            return Arrays.toString((boolean[])arr);
-        if (arrType.equals(short[].class))
-            return Arrays.toString((short[])arr);
-        if (arrType.equals(int[].class))
-            return Arrays.toString((int[])arr);
-        if (arrType.equals(long[].class))
-            return Arrays.toString((long[])arr);
-        if (arrType.equals(float[].class))
-            return Arrays.toString((float[])arr);
-        if (arrType.equals(double[].class))
-            return Arrays.toString((double[])arr);
-        if (arrType.equals(char[].class))
-            return Arrays.toString((char[])arr);
-
-        return Arrays.toString((Object[])arr);
-    }
-
-    /**
      * Produces uniformed output of string with context properties
      *
      * @param str Output prefix or {@code null} if empty.
@@ -948,6 +1042,51 @@ public class GridToStringBuilder {
     }
 
     /**
+     * @param arrType Type of the array.
+     * @param arr Array object.
+     * @return String representation of an array.
+     */
+    @SuppressWarnings({"ConstantConditions", "unchecked"})
+    public static <T> String arrayToString(Class arrType, Object arr) {
+        T[] array = (T[])arr;
+
+        if (array.length > COLLECTION_LIMIT)
+            arr = Arrays.copyOf(array, COLLECTION_LIMIT);
+
+        String res;
+
+        if (arrType.equals(byte[].class))
+            res = Arrays.toString((byte[])arr);
+        else if (arrType.equals(boolean[].class))
+            res = Arrays.toString((boolean[])arr);
+        else if (arrType.equals(short[].class))
+            res = Arrays.toString((short[])arr);
+        else if (arrType.equals(int[].class))
+            res = Arrays.toString((int[])arr);
+        else if (arrType.equals(long[].class))
+            res = Arrays.toString((long[])arr);
+        else if (arrType.equals(float[].class))
+            res = Arrays.toString((float[])arr);
+        else if (arrType.equals(double[].class))
+            res = Arrays.toString((double[])arr);
+        else if (arrType.equals(char[].class))
+            res = Arrays.toString((char[])arr);
+        else
+            res = Arrays.toString((Object[])arr);
+
+        if (array.length > COLLECTION_LIMIT) {
+            StringBuilder resSB = new StringBuilder(res);
+
+            resSB.deleteCharAt(resSB.length() - 1);
+            resSB.append("... and ").append(array.length - COLLECTION_LIMIT).append(" more]");
+
+            res = resSB.toString();
+        }
+
+        return res;
+    }
+
+    /**
      * Produces uniformed output of string with context properties
      *
      * @param str Output prefix or {@code null} if empty.
@@ -976,11 +1115,20 @@ public class GridToStringBuilder {
         propVals[0] = val;
         propSens[0] = sens;
 
+        SBLengthLimit lenLim = threadCurLen.get();
+
+        boolean newStr = false;
+
         try {
-            return toStringImpl(str, tmp.getStringBuilder(), propNames, propVals, propSens, 1);
+            newStr = lenLim.length() == 0;
+
+            return toStringImpl(str, tmp.getStringBuilder(lenLim), propNames, propVals, propSens, 1);
         }
         finally {
             queue.offer(tmp);
+
+            if (newStr)
+                lenLim.reset();
         }
     }
 
@@ -1037,11 +1185,20 @@ public class GridToStringBuilder {
         propVals[1] = val1;
         propSens[1] = sens1;
 
+        SBLengthLimit lenLim = threadCurLen.get();
+
+        boolean newStr = false;
+
         try {
-            return toStringImpl(str, tmp.getStringBuilder(), propNames, propVals, propSens, 2);
+            newStr = lenLim.length() == 0;
+
+            return toStringImpl(str, tmp.getStringBuilder(lenLim), propNames, propVals, propSens, 2);
         }
         finally {
             queue.offer(tmp);
+
+            if (newStr)
+                lenLim.reset();
         }
     }
 
@@ -1091,11 +1248,20 @@ public class GridToStringBuilder {
         propVals[2] = val2;
         propSens[2] = sens2;
 
+        SBLengthLimit lenLim = threadCurLen.get();
+
+        boolean newStr = false;
+
         try {
-            return toStringImpl(str, tmp.getStringBuilder(), propNames, propVals, propSens, 3);
+            newStr = lenLim.length() == 0;
+
+            return toStringImpl(str, tmp.getStringBuilder(lenLim), propNames, propVals, propSens, 3);
         }
         finally {
             queue.offer(tmp);
+
+            if (newStr)
+                lenLim.reset();
         }
     }
 
@@ -1153,11 +1319,20 @@ public class GridToStringBuilder {
         propVals[3] = val3;
         propSens[3] = sens3;
 
+        SBLengthLimit lenLim = threadCurLen.get();
+
+        boolean newStr = false;
+
         try {
-            return toStringImpl(str, tmp.getStringBuilder(), propNames, propVals, propSens, 4);
+            newStr = lenLim.length() == 0;
+
+            return toStringImpl(str, tmp.getStringBuilder(lenLim), propNames, propVals, propSens, 4);
         }
         finally {
             queue.offer(tmp);
+
+            if (newStr)
+                lenLim.reset();
         }
     }
 
@@ -1223,11 +1398,20 @@ public class GridToStringBuilder {
         propVals[4] = val4;
         propSens[4] = sens4;
 
+        SBLengthLimit lenLim = threadCurLen.get();
+
+        boolean newStr = false;
+
         try {
-            return toStringImpl(str, tmp.getStringBuilder(), propNames, propVals, propSens, 5);
+            newStr = lenLim.length() == 0;
+
+            return toStringImpl(str, tmp.getStringBuilder(lenLim), propNames, propVals, propSens, 5);
         }
         finally {
             queue.offer(tmp);
+
+            if (newStr)
+                lenLim.reset();
         }
     }
 
@@ -1301,11 +1485,20 @@ public class GridToStringBuilder {
         propVals[5] = val5;
         propSens[5] = sens5;
 
+        SBLengthLimit lenLim = threadCurLen.get();
+
+        boolean newStr = false;
+
         try {
-            return toStringImpl(str, tmp.getStringBuilder(), propNames, propVals, propSens, 6);
+            newStr = lenLim.length() == 0;
+
+            return toStringImpl(str, tmp.getStringBuilder(lenLim), propNames, propVals, propSens, 6);
         }
         finally {
             queue.offer(tmp);
+
+            if (newStr)
+                lenLim.reset();
         }
     }
 
@@ -1387,11 +1580,20 @@ public class GridToStringBuilder {
         propVals[6] = val6;
         propSens[6] = sens6;
 
+        SBLengthLimit lenLim = threadCurLen.get();
+
+        boolean newStr = false;
+
         try {
-            return toStringImpl(str, tmp.getStringBuilder(), propNames, propVals, propSens, 7);
+            newStr = lenLim.length() == 0;
+
+            return toStringImpl(str, tmp.getStringBuilder(lenLim), propNames, propVals, propSens, 7);
         }
         finally {
             queue.offer(tmp);
+
+            if (newStr)
+                lenLim.reset();
         }
     }
 
@@ -1406,7 +1608,7 @@ public class GridToStringBuilder {
      * @param propCnt Properties count.
      * @return String presentation of the object.
      */
-    private static String toStringImpl(String str, SB buf, Object[] propNames, Object[] propVals,
+    private static String toStringImpl(String str, SBLimitedLength buf, Object[] propNames, Object[] propVals,
         boolean[] propSens, int propCnt) {
 
         buf.setLength(0);
@@ -1433,7 +1635,7 @@ public class GridToStringBuilder {
      * @param addSens Sensitive flag of values or {@code null} if all values are not sensitive.
      * @param addLen How many additional values will be included.
      */
-    private static void appendVals(SB buf,
+    private static void appendVals(SBLimitedLength buf,
         boolean first,
         Object[] addNames,
         Object[] addVals,
@@ -1452,11 +1654,6 @@ public class GridToStringBuilder {
 
                     if (incAnn != null && incAnn.sensitive() && !INCLUDE_SENSITIVE)
                         continue;
-
-                    Class<?> cls = addVal.getClass();
-
-                    if (cls.isArray())
-                        addVal = arrayToString(cls, addVal);
                 }
 
                 if (!first)
@@ -1464,7 +1661,9 @@ public class GridToStringBuilder {
                 else
                     first = false;
 
-                buf.a(addNames[i]).a('=').a(addVal);
+                buf.a(addNames[i]).a('=');
+
+                toString(buf, addVal);
             }
         }
     }

http://git-wip-us.apache.org/repos/asf/ignite/blob/5d66516d/modules/core/src/main/java/org/apache/ignite/internal/util/tostring/GridToStringThreadLocal.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/util/tostring/GridToStringThreadLocal.java b/modules/core/src/main/java/org/apache/ignite/internal/util/tostring/GridToStringThreadLocal.java
index 8ffacb3..2f62727 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/util/tostring/GridToStringThreadLocal.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/util/tostring/GridToStringThreadLocal.java
@@ -17,14 +17,12 @@
 
 package org.apache.ignite.internal.util.tostring;
 
-import org.apache.ignite.internal.util.typedef.internal.SB;
-
 /**
  * Helper wrapper containing StringBuilder and additional values. Stored as a thread-local variable.
  */
 class GridToStringThreadLocal {
     /** */
-    private SB sb = new SB(256);
+    private SBLimitedLength sb = new SBLimitedLength(256);
 
     /** */
     private Object[] addNames = new Object[7];
@@ -36,9 +34,12 @@ class GridToStringThreadLocal {
     private boolean[] addSens = new boolean[7];
 
     /**
+     * @param len Length limit.
      * @return String builder.
      */
-    SB getStringBuilder() {
+    SBLimitedLength getStringBuilder(SBLengthLimit len) {
+        sb.initLimit(len);
+
         return sb;
     }
 

http://git-wip-us.apache.org/repos/asf/ignite/blob/5d66516d/modules/core/src/main/java/org/apache/ignite/internal/util/tostring/SBLengthLimit.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/util/tostring/SBLengthLimit.java b/modules/core/src/main/java/org/apache/ignite/internal/util/tostring/SBLengthLimit.java
new file mode 100644
index 0000000..2710a85
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/util/tostring/SBLengthLimit.java
@@ -0,0 +1,74 @@
+/*
+ * 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.util.tostring;
+
+import org.apache.ignite.IgniteSystemProperties;
+
+import static org.apache.ignite.IgniteSystemProperties.IGNITE_TO_STRING_MAX_LENGTH;
+
+/**
+ *
+ */
+class SBLengthLimit {
+    /** */
+    private static final int MAX_TO_STR_LEN = IgniteSystemProperties.getInteger(IGNITE_TO_STRING_MAX_LENGTH, 10_000);
+
+    /** Length of tail part of message */
+    private static final int TAIL_LEN = MAX_TO_STR_LEN / 10 * 2;
+
+    /** */
+    private int len;
+
+    /**
+     * @return Current length.
+     */
+    int length() {
+        return len;
+    }
+
+    /**
+     *
+     */
+    void reset() {
+        len = 0;
+    }
+
+    /**
+     * @param sb String builder.
+     * @param writtenLen Written length.
+     */
+    void onWrite(SBLimitedLength sb, int writtenLen) {
+        len += writtenLen;
+
+        if (len > MAX_TO_STR_LEN && sb.getTail() == null) {
+            CircularStringBuilder tail = new CircularStringBuilder(TAIL_LEN);
+
+            tail.append(sb.impl().substring(MAX_TO_STR_LEN - TAIL_LEN));
+
+            sb.setTail(tail);
+            sb.setLength(MAX_TO_STR_LEN - TAIL_LEN);
+        }
+    }
+
+    /**
+     * @return {@code True} if reached limit.
+     */
+    boolean overflowed() {
+        return len > MAX_TO_STR_LEN;
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/5d66516d/modules/core/src/main/java/org/apache/ignite/internal/util/tostring/SBLimitedLength.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/util/tostring/SBLimitedLength.java b/modules/core/src/main/java/org/apache/ignite/internal/util/tostring/SBLimitedLength.java
new file mode 100644
index 0000000..da6828e
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/util/tostring/SBLimitedLength.java
@@ -0,0 +1,285 @@
+/*
+ * 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.util.tostring;
+
+import org.apache.ignite.internal.util.GridStringBuilder;
+import java.util.Arrays;
+
+/**
+ *
+ */
+public class SBLimitedLength extends GridStringBuilder {
+    /** */
+    private SBLengthLimit lenLimit;
+
+    /** Additional string builder to get tail of message. */
+    private CircularStringBuilder tail;
+
+    /**
+     * @param cap Capacity.
+     */
+    SBLimitedLength(int cap) {
+        super(cap);
+    }
+
+    /**
+     * @param lenLimit Length limit.
+     */
+    void initLimit(SBLengthLimit lenLimit) {
+        this.lenLimit = lenLimit;
+        tail = null;
+    }
+
+    /**
+     * @return tail string builder.
+     */
+    public CircularStringBuilder getTail() {
+        return tail;
+    }
+
+    /**
+     * @param tail tail CircularStringBuilder to set.
+     */
+    public void setTail(CircularStringBuilder tail) {
+        this.tail = tail;
+    }
+
+    /**
+     * @param lenBeforeWrite Length before write.
+     * @return This builder.
+     */
+    private GridStringBuilder onWrite(int lenBeforeWrite) {
+        assert lenLimit != null;
+
+        lenLimit.onWrite(this, length() - lenBeforeWrite);
+
+        return this;
+    }
+
+    /** {@inheritDoc} */
+    @Override public GridStringBuilder a(Object obj) {
+        if (lenLimit.overflowed()) {
+            tail.append(obj);
+            return this;
+        }
+
+        int curLen = length();
+
+        super.a(obj);
+
+        return onWrite(curLen);
+    }
+
+    /** {@inheritDoc} */
+    @Override public GridStringBuilder a(String str) {
+        if (lenLimit.overflowed()) {
+            tail.append(str);
+            return this;
+        }
+
+        int curLen = length();
+
+        super.a(str);
+
+        return onWrite(curLen);
+    }
+
+    /** {@inheritDoc} */
+    @Override public GridStringBuilder a(StringBuffer sb) {
+        if (lenLimit.overflowed()) {
+            tail.append(sb);
+            return this;
+        }
+
+        int curLen = length();
+
+        super.a(sb);
+
+        return onWrite(curLen);
+    }
+
+    /** {@inheritDoc} */
+    @Override public GridStringBuilder a(CharSequence s) {
+        if (lenLimit.overflowed()) {
+            tail.append(s);
+            return this;
+        }
+
+        int curLen = length();
+
+        super.a(s);
+
+        return onWrite(curLen);
+    }
+
+    /** {@inheritDoc} */
+    @Override public GridStringBuilder a(CharSequence s, int start, int end) {
+        if (lenLimit.overflowed()) {
+            tail.append(s.subSequence(start, end));
+            return this;
+        }
+
+        int curLen = length();
+
+        super.a(s, start, end);
+
+        return onWrite(curLen);
+    }
+
+    /** {@inheritDoc} */
+    @Override public GridStringBuilder a(char[] str) {
+        if (lenLimit.overflowed()) {
+            tail.append(str);
+            return this;
+        }
+
+        int curLen = length();
+
+        super.a(str);
+
+        return onWrite(curLen);
+    }
+
+    /** {@inheritDoc} */
+    @Override public GridStringBuilder a(char[] str, int offset, int len) {
+        if (lenLimit.overflowed()) {
+            tail.append(Arrays.copyOfRange(str, offset, len));
+            return this;
+        }
+
+        int curLen = length();
+
+        super.a(str, offset, len);
+
+        return onWrite(curLen);
+    }
+
+    /** {@inheritDoc} */
+    @Override public GridStringBuilder a(boolean b) {
+        if (lenLimit.overflowed()) {
+            tail.append(b);
+            return this;
+        }
+
+        int curLen = length();
+
+        super.a(b);
+
+        return onWrite(curLen);
+    }
+
+    /** {@inheritDoc} */
+    @Override public GridStringBuilder a(char c) {
+        if (lenLimit.overflowed()) {
+            tail.append(c);
+            return this;
+        }
+
+        int curLen = length();
+
+        super.a(c);
+
+        return onWrite(curLen);
+    }
+
+    /** {@inheritDoc} */
+    @Override public GridStringBuilder a(int i) {
+        if (lenLimit.overflowed()) {
+            tail.append(i);
+            return this;
+        }
+
+        int curLen = length();
+
+        super.a(i);
+
+        return onWrite(curLen);
+    }
+
+    /** {@inheritDoc} */
+    @Override public GridStringBuilder a(long lng) {
+        if (lenLimit.overflowed()) {
+            tail.append(lng);
+            return this;
+        }
+
+        int curLen = length();
+
+        super.a(lng);
+
+        return onWrite(curLen);
+    }
+
+    /** {@inheritDoc} */
+    @Override public GridStringBuilder a(float f) {
+        if (lenLimit.overflowed()) {
+            tail.append(f);
+            return this;
+        }
+
+        int curLen = length();
+
+        super.a(f);
+
+        return onWrite(curLen);
+    }
+
+    /** {@inheritDoc} */
+    @Override public GridStringBuilder a(double d) {
+        if (lenLimit.overflowed()) {
+            tail.append(d);
+            return this;
+        }
+
+        int curLen = length();
+
+        super.a(d);
+
+        return onWrite(curLen);
+    }
+
+    /** {@inheritDoc} */
+    @Override public GridStringBuilder appendCodePoint(int codePoint) {
+        if (lenLimit.overflowed()) {
+            tail.append(codePoint);
+            return this;
+        }
+
+        int curLen = length();
+
+        super.appendCodePoint(codePoint);
+
+        return onWrite(curLen);
+    }
+
+    /** {@inheritDoc} */
+    @Override public String toString() {
+        if (tail == null)
+            return super.toString();
+        else {
+            int tailLen = tail.length();
+            StringBuilder res = new StringBuilder(impl().capacity() + 100);
+
+            res.append(impl());
+            res.append("... and ").append(String.valueOf(tail.getSkipped() + tailLen))
+                .append(" skipped ...").append(tail.toString());
+
+            return res.toString();
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/5d66516d/modules/core/src/test/java/org/apache/ignite/internal/util/tostring/CircularStringBuilderSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/util/tostring/CircularStringBuilderSelfTest.java b/modules/core/src/test/java/org/apache/ignite/internal/util/tostring/CircularStringBuilderSelfTest.java
new file mode 100644
index 0000000..b927863
--- /dev/null
+++ b/modules/core/src/test/java/org/apache/ignite/internal/util/tostring/CircularStringBuilderSelfTest.java
@@ -0,0 +1,69 @@
+/*
+ * 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.util.tostring;
+
+import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest;
+import org.apache.ignite.testframework.junits.common.GridCommonTest;
+
+/**
+ *
+ */
+@GridCommonTest(group = "Utils")
+public class CircularStringBuilderSelfTest extends GridCommonAbstractTest {
+    /**
+     * @throws Exception If failed.
+     */
+    public void testCSBPrimitive() throws Exception {
+        CircularStringBuilder csb = new CircularStringBuilder(1);
+        csb.append((String)null);
+        assertEquals("l", csb.toString());
+        csb.append('1');
+        assertEquals("1", csb.toString());
+
+        CircularStringBuilder csb2 = new CircularStringBuilder(1);
+        csb2.append(1);
+        assertEquals("1", csb2.toString());
+    }
+
+    /**
+    * @throws Exception If failed.
+    */
+    public void testCSBOverflow() throws Exception {
+        testSB(3, "1234", 2, "234");
+        testSB(4, "1234", 2, "1234");
+        testSB(5, "1234", 2, "41234");
+        testSB(6, "1234", 2, "341234");
+        testSB(7, "1234", 2, "2341234");
+        testSB(8, "1234", 2, "12341234");
+    }
+
+    /**
+     * @param capacity Capacity.
+     * @param pattern Pattern to add.
+     * @param num How many times pattern should be added.
+     * @param expected Expected string.
+     */
+    private void testSB(int capacity, String pattern, int num, String expected){
+        CircularStringBuilder csb = new CircularStringBuilder(capacity);
+
+        for (int i = 0; i < num; i++)
+            csb.append(pattern);
+
+        assertEquals(expected, csb.toString());
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/5d66516d/modules/core/src/test/java/org/apache/ignite/internal/util/tostring/GridToStringBuilderSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/util/tostring/GridToStringBuilderSelfTest.java b/modules/core/src/test/java/org/apache/ignite/internal/util/tostring/GridToStringBuilderSelfTest.java
index 6a0eae2..9a6b9ef 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/util/tostring/GridToStringBuilderSelfTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/util/tostring/GridToStringBuilderSelfTest.java
@@ -17,12 +17,18 @@
 
 package org.apache.ignite.internal.util.tostring;
 
+import java.lang.reflect.Array;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.List;
 import java.util.Map;
+import java.util.TreeMap;
 import java.util.UUID;
 import java.util.concurrent.locks.ReadWriteLock;
 import org.apache.ignite.IgniteLogger;
+import org.apache.ignite.IgniteSystemProperties;
+import static org.apache.ignite.IgniteSystemProperties.IGNITE_TO_STRING_COLLECTION_LIMIT;
+import static org.apache.ignite.IgniteSystemProperties.IGNITE_TO_STRING_MAX_LENGTH;
 import org.apache.ignite.internal.util.typedef.internal.S;
 import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest;
 import org.apache.ignite.testframework.junits.common.GridCommonTest;
@@ -43,7 +49,7 @@ public class GridToStringBuilderSelfTest extends GridCommonAbstractTest {
         log.info(obj.toStringManual());
         log.info(obj.toStringAutomatic());
 
-        assert obj.toStringManual().equals(obj.toStringAutomatic());
+        assertEquals (obj.toStringManual(), obj.toStringAutomatic());
     }
 
     /**
@@ -60,7 +66,7 @@ public class GridToStringBuilderSelfTest extends GridCommonAbstractTest {
         String automatic = obj.toStringWithAdditionalAutomatic();
         log.info(automatic);
 
-        assert manual.equals(automatic);
+        assertEquals(manual, automatic);
     }
 
     /**
@@ -121,6 +127,92 @@ public class GridToStringBuilderSelfTest extends GridCommonAbstractTest {
     }
 
     /**
+     * Test array print.
+     * @param v value to get array class and fill array.
+     * @param limit value of IGNITE_TO_STRING_COLLECTION_LIMIT.
+     * @throws Exception if failed.
+     */
+    private <T, V> void testArr(V v, int limit) throws Exception {
+        T[] arrOf = (T[]) Array.newInstance(v.getClass(), limit + 1);
+        Arrays.fill(arrOf, v);
+        T[] arr = Arrays.copyOf(arrOf, limit);
+
+        String arrStr = GridToStringBuilder.arrayToString(arr.getClass(), arr);
+        String arrOfStr = GridToStringBuilder.arrayToString(arrOf.getClass(), arrOf);
+
+        // Simulate overflow
+        StringBuilder resultSB = new StringBuilder(arrStr);
+            resultSB.deleteCharAt(resultSB.length()-1);
+            resultSB.append("... and ").append(arrOf.length - limit).append(" more]");
+            arrStr = resultSB.toString();
+
+        assertTrue("Collection limit error in array of type " + arrOf.getClass().getName()
+            + " error, normal arr: <" + arrStr + ">, overflowed arr: <" + arrOfStr + ">", arrStr.equals(arrOfStr));
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testToStringCollectionLimits() throws Exception {
+        int limit = IgniteSystemProperties.getInteger(IGNITE_TO_STRING_COLLECTION_LIMIT, 100);
+
+        Object vals[] = new Object[] {Byte.MIN_VALUE, Boolean.TRUE, Short.MIN_VALUE, Integer.MIN_VALUE, Long.MIN_VALUE,
+            Float.MIN_VALUE, Double.MIN_VALUE, Character.MIN_VALUE, new TestClass1()};
+        for (Object val : vals)
+            testArr(val, limit);
+
+        Map<String, String> strMap = new TreeMap<>();
+        List<String> strList = new ArrayList<>(limit+1);
+
+        TestClass1 testClass = new TestClass1();
+        testClass.strMap = strMap;
+        testClass.strListIncl = strList;
+
+        for (int i = 0; i < limit; i++) {
+            strMap.put("k" + i, "v");
+            strList.add("e");
+        }
+        String testClassStr = GridToStringBuilder.toString(TestClass1.class, testClass);
+
+        strMap.put("kz", "v"); // important to add last element in TreeMap here
+        strList.add("e");
+
+        String testClassStrOf = GridToStringBuilder.toString(TestClass1.class, testClass);
+
+        String testClassStrOfR = testClassStrOf.replaceAll("... and 1 more","");
+
+        assertTrue("Collection limit error in Map or List, normal: <" + testClassStr + ">, overflowed: <"
+            +"testClassStrOf", testClassStr.length() == testClassStrOfR.length());
+
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testToStringSizeLimits() throws Exception {
+
+        int limit = IgniteSystemProperties.getInteger(IGNITE_TO_STRING_MAX_LENGTH, 10_000);
+        int tailLen = limit / 10 * 2;
+        StringBuilder sb = new StringBuilder(limit + 10);
+        for (int i = 0; i < limit - 100; i++) {
+            sb.append('a');
+        }
+        String actual = GridToStringBuilder.toString(TestClass2.class, new TestClass2(sb.toString()));
+        String expected = "TestClass2 [str=" + sb.toString() + "]";
+        assertEquals(expected, actual);
+
+        for (int i = 0; i < 100; i++) {
+            sb.append('b');
+        }
+        actual = GridToStringBuilder.toString(TestClass2.class, new TestClass2(sb.toString()));
+        expected = "TestClass2 [str=" + sb.toString() + "]";
+        assertEquals(expected.substring(0, limit - tailLen), actual.substring(0, limit - tailLen));
+        assertEquals(expected.substring(expected.length() - tailLen), actual.substring(actual.length() - tailLen));
+        assertTrue(actual.contains("... and"));
+        assertTrue(actual.contains("skipped ..."));
+    }
+
+    /**
      * Test class.
      */
     private static class TestClass1 {
@@ -170,6 +262,12 @@ public class GridToStringBuilderSelfTest extends GridCommonAbstractTest {
 
         /** */
         @SuppressWarnings("unused")
+        @GridToStringInclude
+        private List<String> strListIncl;
+
+
+        /** */
+        @SuppressWarnings("unused")
         private final Object obj = new Object();
 
         /** */
@@ -193,7 +291,8 @@ public class GridToStringBuilderSelfTest extends GridCommonAbstractTest {
             buf.append("byteVar=").append(byteVar).append(", ");
             buf.append("name=").append(name).append(", ");
             buf.append("finalInt=").append(finalInt).append(", ");
-            buf.append("strMap=").append(strMap);
+            buf.append("strMap=").append(strMap).append(", ");
+            buf.append("strListIncl=").append(strListIncl);
 
             buf.append("]");
 
@@ -227,4 +326,15 @@ public class GridToStringBuilderSelfTest extends GridCommonAbstractTest {
             return s.toString();
         }
     }
+
+    private static class TestClass2{
+        /** */
+        @SuppressWarnings("unused")
+        @GridToStringInclude
+        private String str;
+
+        public TestClass2(String str) {
+            this.str = str;
+        }
+    }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ignite/blob/5d66516d/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteUtilSelfTestSuite.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteUtilSelfTestSuite.java b/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteUtilSelfTestSuite.java
index 20f37f7..7c99817 100644
--- a/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteUtilSelfTestSuite.java
+++ b/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteUtilSelfTestSuite.java
@@ -33,6 +33,7 @@ import org.apache.ignite.internal.util.offheap.unsafe.GridUnsafeMapSelfTest;
 import org.apache.ignite.internal.util.offheap.unsafe.GridUnsafeMemorySelfTest;
 import org.apache.ignite.internal.util.offheap.unsafe.GridUnsafePartitionedMapSelfTest;
 import org.apache.ignite.internal.util.offheap.unsafe.GridUnsafeStripedLruSefTest;
+import org.apache.ignite.internal.util.tostring.CircularStringBuilderSelfTest;
 import org.apache.ignite.internal.util.tostring.GridToStringBuilderSelfTest;
 import org.apache.ignite.lang.GridByteArrayListSelfTest;
 import org.apache.ignite.spi.discovery.ClusterMetricsSnapshotSerializeSelfTest;
@@ -76,6 +77,7 @@ public class IgniteUtilSelfTestSuite extends TestSuite {
         suite.addTestSuite(GridQueueSelfTest.class);
         suite.addTestSuite(GridStringBuilderFactorySelfTest.class);
         suite.addTestSuite(GridToStringBuilderSelfTest.class);
+        suite.addTestSuite(CircularStringBuilderSelfTest.class);
         suite.addTestSuite(GridByteArrayListSelfTest.class);
         suite.addTestSuite(GridMBeanSelfTest.class);
         suite.addTestSuite(GridMBeanDisableSelfTest.class);


Mime
View raw message