# HG changeset patch # User mlarsson # Date 1519810622 -3600 # Node ID fde9b3c56de496d5304bb1e69f208d8b7061351d # Parent 9637557def32e64e40a36dca02ca4cdf9aafc998 8153945: Track if log configuration has changed during runtime Reviewed-by: lfoltan, hseigel diff -r 9637557def32 -r fde9b3c56de4 src/hotspot/share/logging/logConfiguration.cpp --- a/src/hotspot/share/logging/logConfiguration.cpp Wed Feb 28 09:30:06 2018 +0100 +++ b/src/hotspot/share/logging/logConfiguration.cpp Wed Feb 28 10:37:02 2018 +0100 @@ -78,6 +78,11 @@ #endif void LogConfiguration::post_initialize() { + // Reset the reconfigured status of all outputs + for (size_t i = 0; i < _n_outputs; i++) { + _outputs[i]->_reconfigured = false; + } + LogDiagnosticCommand::registerCommand(); Log(logging) log; if (log.is_info()) { @@ -213,6 +218,8 @@ assert(idx < _n_outputs, "Invalid index, idx = " SIZE_FORMAT " and _n_outputs = " SIZE_FORMAT, idx, _n_outputs); LogOutput* output = _outputs[idx]; + output->_reconfigured = true; + // Clear the previous config description output->clear_config_string(); @@ -447,7 +454,7 @@ return true; } -void LogConfiguration::describe_available(outputStream* out){ +void LogConfiguration::describe_available(outputStream* out) { out->print("Available log levels:"); for (size_t i = 0; i < LogLevel::Count; i++) { out->print("%s %s", (i == 0 ? "" : ","), LogLevel::name(static_cast(i))); @@ -467,11 +474,14 @@ LogTagSet::describe_tagsets(out); } -void LogConfiguration::describe_current_configuration(outputStream* out){ +void LogConfiguration::describe_current_configuration(outputStream* out) { out->print_cr("Log output configuration:"); for (size_t i = 0; i < _n_outputs; i++) { out->print(" #" SIZE_FORMAT ": ", i); _outputs[i]->describe(out); + if (_outputs[i]->is_reconfigured()) { + out->print(" (reconfigured)"); + } out->cr(); } } diff -r 9637557def32 -r fde9b3c56de4 src/hotspot/share/logging/logOutput.hpp --- a/src/hotspot/share/logging/logOutput.hpp Wed Feb 28 09:30:06 2018 +0100 +++ b/src/hotspot/share/logging/logOutput.hpp Wed Feb 28 10:37:02 2018 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -43,6 +43,12 @@ private: static const size_t InitialConfigBufferSize = 256; + + // Track if the output has been reconfigured dynamically during runtime. + // The status is set each time the configuration of the output is modified, + // and is reset once after logging initialization is complete. + bool _reconfigured; + char* _config_string; size_t _config_string_buffer_size; @@ -65,11 +71,15 @@ return _decorators; } + bool is_reconfigured() const { + return _reconfigured; + } + const char* config_string() const { return _config_string; } - LogOutput() : _config_string(NULL), _config_string_buffer_size(0) { + LogOutput() : _reconfigured(false), _config_string(NULL), _config_string_buffer_size(0) { } virtual ~LogOutput(); diff -r 9637557def32 -r fde9b3c56de4 test/hotspot/gtest/logging/test_logConfiguration.cpp --- a/test/hotspot/gtest/logging/test_logConfiguration.cpp Wed Feb 28 09:30:06 2018 +0100 +++ b/test/hotspot/gtest/logging/test_logConfiguration.cpp Wed Feb 28 10:37:02 2018 +0100 @@ -225,7 +225,7 @@ // Now reconfigure logging on stderr with no decorators set_log_config("stderr", "all=off", "none"); - EXPECT_TRUE(is_described("#1: stderr all=off none\n")) << "Expecting no decorators"; + EXPECT_TRUE(is_described("#1: stderr all=off none (reconfigured)\n")) << "Expecting no decorators"; } // Test that invalid options cause configuration errors @@ -414,6 +414,33 @@ delete_file(buf); } +static size_t count_occurrences(const char* haystack, const char* needle) { + size_t count = 0; + for (const char* p = strstr(haystack, needle); p != NULL; p = strstr(p + 1, needle)) { + count++; + } + return count; +} + +TEST_OTHER_VM(LogConfiguration, output_reconfigured) { + ResourceMark rm; + stringStream ss; + + EXPECT_FALSE(is_described("(reconfigured)")); + + bool success = LogConfiguration::parse_log_arguments("#1", "all=warning", NULL, NULL, &ss); + ASSERT_TRUE(success); + EXPECT_EQ(0u, ss.size()); + + LogConfiguration::describe(&ss); + EXPECT_EQ(1u, count_occurrences(ss.as_string(), "(reconfigured)")); + + ss.reset(); + LogConfiguration::configure_stdout(LogLevel::Info, false, LOG_TAGS(logging)); + LogConfiguration::describe(&ss); + EXPECT_EQ(2u, count_occurrences(ss.as_string(), "(reconfigured)")); +} + TEST_VM_F(LogConfigurationTest, suggest_similar_selection) { static const char* nonexisting_tagset = "logging+start+exit+safepoint+gc";