IGNITE-5136 GridLogThrottle memory leak Signed-off-by: Anton Vinogradov <a...@apache.org>
Project: http://git-wip-us.apache.org/repos/asf/ignite/repo Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/a3a619b6 Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/a3a619b6 Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/a3a619b6 Branch: refs/heads/ignite-5789-1 Commit: a3a619b6af66e21234e52a84ef0efecc4718cbe7 Parents: 21678bc Author: Dmitrii Ryabov <somefire...@gmail.com> Authored: Wed May 23 12:34:33 2018 +0300 Committer: Anton Vinogradov <a...@apache.org> Committed: Wed May 23 12:34:33 2018 +0300 ---------------------------------------------------------------------- .../apache/ignite/IgniteSystemProperties.java | 4 + .../ignite/internal/util/GridLogThrottle.java | 28 +++- .../apache/ignite/util/GridLogThrottleTest.java | 128 ++++++++++++------- 3 files changed, 108 insertions(+), 52 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/ignite/blob/a3a619b6/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 727e809..b6f0286 100644 --- a/modules/core/src/main/java/org/apache/ignite/IgniteSystemProperties.java +++ b/modules/core/src/main/java/org/apache/ignite/IgniteSystemProperties.java @@ -29,6 +29,7 @@ import org.apache.ignite.configuration.CacheConfiguration; import org.apache.ignite.configuration.DataStorageConfiguration; import org.apache.ignite.internal.client.GridClient; import org.apache.ignite.internal.marshaller.optimized.OptimizedMarshaller; +import org.apache.ignite.internal.util.GridLogThrottle; import org.apache.ignite.stream.StreamTransformer; import org.jetbrains.annotations.Nullable; @@ -756,6 +757,9 @@ public final class IgniteSystemProperties { */ public static final String IGNITE_WAL_LOG_TX_RECORDS = "IGNITE_WAL_LOG_TX_RECORDS"; + /** Max amount of remembered errors for {@link GridLogThrottle}. */ + public static final String IGNITE_LOG_THROTTLE_CAPACITY = "IGNITE_LOG_THROTTLE_CAPACITY"; + /** If this property is set, {@link DataStorageConfiguration#writeThrottlingEnabled} will be overridden to true * independent of initial value in configuration. */ public static final String IGNITE_OVERRIDE_WRITE_THROTTLING_ENABLED = "IGNITE_OVERRIDE_WRITE_THROTTLING_ENABLED"; http://git-wip-us.apache.org/repos/asf/ignite/blob/a3a619b6/modules/core/src/main/java/org/apache/ignite/internal/util/GridLogThrottle.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/internal/util/GridLogThrottle.java b/modules/core/src/main/java/org/apache/ignite/internal/util/GridLogThrottle.java index 59ddd1c..396cf37 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/util/GridLogThrottle.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/util/GridLogThrottle.java @@ -17,19 +17,23 @@ package org.apache.ignite.internal.util; -import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; import org.apache.ignite.IgniteLogger; +import org.apache.ignite.IgniteSystemProperties; import org.apache.ignite.internal.util.typedef.F; import org.apache.ignite.internal.util.typedef.internal.U; import org.apache.ignite.lang.IgniteBiTuple; import org.jetbrains.annotations.Nullable; +import org.jsr166.ConcurrentLinkedHashMap; + +import static org.apache.ignite.IgniteSystemProperties.IGNITE_LOG_THROTTLE_CAPACITY; +import static org.jsr166.ConcurrentLinkedHashMap.DFLT_CONCUR_LVL; /** * Grid log throttle. * <p> * Errors are logged only if they were not logged for the last - * {@link #throttleTimeout} number of minutes. + * {@link #throttleTimeout} milliseconds. * Note that not only error messages are checked for duplicates, but also exception * classes. */ @@ -37,12 +41,15 @@ public class GridLogThrottle { /** Default throttle timeout in milliseconds (value is <tt>5 * 60 * 1000</tt>). */ public static final int DFLT_THROTTLE_TIMEOUT = 5 * 60 * 1000; - /** Throttle timeout. */ - private static int throttleTimeout = DFLT_THROTTLE_TIMEOUT; + /** Throttle timeout in milliseconds. */ + private static volatile int throttleTimeout = DFLT_THROTTLE_TIMEOUT; + + /** Throttle capacity. */ + private static final int throttleCap = IgniteSystemProperties.getInteger(IGNITE_LOG_THROTTLE_CAPACITY, 128); /** Errors. */ private static final ConcurrentMap<IgniteBiTuple<Class<? extends Throwable>, String>, Long> errors = - new ConcurrentHashMap<>(); + new ConcurrentLinkedHashMap<>(throttleCap, 1f, DFLT_CONCUR_LVL, throttleCap); /** * Sets system-wide log throttle timeout. @@ -58,11 +65,20 @@ public class GridLogThrottle { * * @return System-side log throttle timeout. */ - public static long throttleTimeout() { + public static int throttleTimeout() { return throttleTimeout; } /** + * Gets system-wide log throttle capacity. + * + * @return System-side log throttle capacity. + */ + public static int throttleCapacity() { + return throttleCap; + } + + /** * Logs error if needed. * * @param log Logger. http://git-wip-us.apache.org/repos/asf/ignite/blob/a3a619b6/modules/core/src/test/java/org/apache/ignite/util/GridLogThrottleTest.java ---------------------------------------------------------------------- diff --git a/modules/core/src/test/java/org/apache/ignite/util/GridLogThrottleTest.java b/modules/core/src/test/java/org/apache/ignite/util/GridLogThrottleTest.java index 9eac0cc..37fa558 100644 --- a/modules/core/src/test/java/org/apache/ignite/util/GridLogThrottleTest.java +++ b/modules/core/src/test/java/org/apache/ignite/util/GridLogThrottleTest.java @@ -18,6 +18,7 @@ package org.apache.ignite.util; import org.apache.ignite.internal.util.typedef.internal.LT; +import org.apache.ignite.testframework.GridStringLogger; import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest; import org.apache.ignite.testframework.junits.common.GridCommonTest; @@ -28,6 +29,9 @@ import org.apache.ignite.testframework.junits.common.GridCommonTest; */ @GridCommonTest(group = "Utils") public class GridLogThrottleTest extends GridCommonAbstractTest { + /** */ + private final GridStringLogger log0 = new GridStringLogger(false, this.log); + /** Constructor. */ public GridLogThrottleTest() { super(false); @@ -41,75 +45,107 @@ public class GridLogThrottleTest extends GridCommonAbstractTest { public void testThrottle() throws Exception { LT.throttleTimeout(1000); - // LOGGED. - LT.error(log, new RuntimeException("Test exception 1."), "Test"); + String sep = System.getProperty("line.separator"); - // OMITTED. - LT.error(log, new RuntimeException("Test exception 1."), "Test"); + checkError("Test exception 1.", "Test msg", true); + checkError("Test exception 1.", "Test msg", false); - // OMITTED. - LT.error(log, new RuntimeException("Test exception 1."), "Test1"); + checkError("Test exception 2.", "Test msg", true); - // LOGGED. - LT.error(log, new RuntimeException("Test exception 2."), "Test"); + checkErrorNoThrowable("Test - without throwable.", true); + checkErrorNoThrowable("Test - without throwable.", false); + checkWarn("Test - without throwable.", false); - // LOGGED. - LT.error(log, null, "Test - without throwable."); + checkWarn("Test - without throwable 1.", true); + checkWarn("Test - without throwable 1.", false); - // OMITTED. - LT.error(log, null, "Test - without throwable."); + Thread.sleep(LT.throttleTimeout() * 2); + info("Slept for throttle timeout: " + LT.throttleTimeout() * 2); - // OMITTED. - LT.warn(log, "Test - without throwable."); + checkError("Test exception 1.", "Test msg", true); + checkError("Test exception 1.", "Test msg", false); + checkError("Test exception 1.", "Test msg1", false); - // LOGGED. - LT.warn(log, "Test - without throwable1."); + checkError("Test exception 2.", "Test msg", true); - // OMITTED. - LT.warn(log, "Test - without throwable1."); + checkWarn("Test - without throwable.", true); + checkWarn("Test - without throwable.", false); - Thread.sleep(LT.throttleTimeout()); + LT.throttleTimeout(200); - info("Slept for throttle timeout: " + LT.throttleTimeout()); + Thread.sleep(LT.throttleTimeout() * 2); + info("Slept for throttle timeout: " + LT.throttleTimeout() * 2); - // LOGGED. - LT.error(log, new RuntimeException("Test exception 1."), "Test"); + checkInfo("Test info message.", true); + checkInfo("Test info message.", false); - // OMITTED. - LT.error(log, new RuntimeException("Test exception 1."), "Test"); + for (int i = 1; i <= LT.throttleCapacity(); i++) + checkInfo("Test info message " + i, true); - // OMITTED. - LT.error(log, new RuntimeException("Test exception 1."), "Test1"); + checkInfo("Test info message.", true); + } - // LOGGED. - LT.error(log, new RuntimeException("Test exception 2."), "Test"); + /** + * @param eMsg Exception message. + * @param msg Log message. + * @param isLogExpected Is log expected or not. + */ + private void checkError(String eMsg, String msg, boolean isLogExpected) { + Exception e = eMsg != null ? new RuntimeException(eMsg) : null; - // LOGGED. - LT.warn(log, "Test - without throwable."); + LT.error(log0, e, msg); - // OMITTED. - LT.warn(log, "Test - without throwable."); + check(e, msg, isLogExpected); + } - Thread.sleep(LT.throttleTimeout()); + /** + * @param msg Log message. + * @param isLogExpected Is log expected or not. + */ + private void checkErrorNoThrowable(String msg, boolean isLogExpected) { + LT.error(log0, null, msg); - info("Slept for throttle timeout: " + LT.throttleTimeout()); + check(null, msg, isLogExpected); + } - //LOGGED. - LT.info(log(), "Test info message."); + /** + * @param msg Log message. + * @param isLogExpected Is log expected or not. + */ + private void checkWarn(String msg, boolean isLogExpected) { + LT.warn(log0, msg); - //OMMITED. - LT.info(log(), "Test info message."); + check(null, msg, isLogExpected); + } + + /** + * @param msg Log message. + * @param isLogExpected Is log expected or not. + */ + private void checkInfo(String msg, boolean isLogExpected) { + LT.info(log0, msg); + + check(null, msg, isLogExpected); + } + + /** + * @param e Exception. + * @param msg Log message. + * @param isLogExpected Is log expected or not. + */ + private void check(Exception e, String msg, boolean isLogExpected) { + String sep = System.getProperty("line.separator"); - //OMMITED. - LT.info(log(), "Test info message."); + if (isLogExpected) { + String s = msg; - //OMMITED. - LT.info(log(), "Test info message."); + if (e != null) + s += sep + "java.lang.RuntimeException: " + e.getMessage(); - //OMMITED. - LT.info(log(), "Test info message."); + assertTrue(log0.toString().contains(s)); + } else + assertEquals(log0.toString(), ""); - //OMMITED. - LT.info(log(), "Test info message."); + log0.reset(); } }