Merge
authorcoleenp
Tue, 15 Mar 2016 20:37:35 +0000
changeset 37111 98572401ab0a
parent 37110 0c468eab5c66 (current diff)
parent 37109 e8530ec83532 (diff)
child 37112 fe72d1d082ff
child 37113 5a33bf5089ac
Merge
--- a/hotspot/src/share/vm/logging/log.cpp	Tue Mar 15 15:43:04 2016 -0400
+++ b/hotspot/src/share/vm/logging/log.cpp	Tue Mar 15 20:37:35 2016 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2016, 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
@@ -136,4 +136,27 @@
   LogConfiguration::parse_log_arguments("stdout", saved_config, NULL, NULL, log.error_stream());
   os::free(saved_config);
 }
+
+static int Test_logconfiguration_subscribe_triggered = 0;
+
+static void Test_logconfiguration_subscribe_helper() {
+  Test_logconfiguration_subscribe_triggered++;
+}
+
+void Test_logconfiguration_subscribe() {
+  ResourceMark rm;
+  LogHandle(logging) log;
+
+  LogConfiguration::register_update_listener(&Test_logconfiguration_subscribe_helper);
+
+  LogConfiguration::parse_log_arguments("stdout", "logging=trace", NULL, NULL, log.error_stream());
+  assert(Test_logconfiguration_subscribe_triggered == 1, "subscription not triggered (1)");
+
+  LogConfiguration::configure_stdout(LogLevel::Debug, true, LOG_TAGS(gc));
+  assert(Test_logconfiguration_subscribe_triggered == 2, "subscription not triggered (2)");
+
+  LogConfiguration::disable_logging();
+  assert(Test_logconfiguration_subscribe_triggered == 3, "subscription not triggered (3)");
+}
+
 #endif // PRODUCT
--- a/hotspot/src/share/vm/logging/logConfiguration.cpp	Tue Mar 15 15:43:04 2016 -0400
+++ b/hotspot/src/share/vm/logging/logConfiguration.cpp	Tue Mar 15 20:37:35 2016 +0000
@@ -40,6 +40,9 @@
 LogOutput** LogConfiguration::_outputs = NULL;
 size_t      LogConfiguration::_n_outputs = 0;
 
+LogConfiguration::UpdateListenerFunction* LogConfiguration::_listener_callbacks = NULL;
+size_t      LogConfiguration::_n_listener_callbacks = 0;
+
 // Stack object to take the lock for configuring the logging.
 // Should only be held during the critical parts of the configuration
 // (when calling configure_output or reading/modifying the outputs array).
@@ -254,6 +257,7 @@
   for (size_t i = 0; i < _n_outputs; i++) {
     disable_output(i);
   }
+  notify_update_listeners();
 }
 
 void LogConfiguration::configure_stdout(LogLevelType level, bool exact_match, ...) {
@@ -282,6 +286,7 @@
   // Apply configuration to stdout (output #0), with the same decorators as before.
   ConfigurationLock cl;
   configure_output(0, expr, LogOutput::Stdout->decorators());
+  notify_update_listeners();
 }
 
 bool LogConfiguration::parse_command_line_arguments(const char* opts) {
@@ -373,6 +378,7 @@
     }
   }
   configure_output(idx, expr, decorators);
+  notify_update_listeners();
   return true;
 }
 
@@ -471,3 +477,20 @@
   }
 }
 
+void LogConfiguration::register_update_listener(UpdateListenerFunction cb) {
+  assert(cb != NULL, "Should not register NULL as listener");
+  ConfigurationLock cl;
+  size_t idx = _n_listener_callbacks++;
+  _listener_callbacks = REALLOC_C_HEAP_ARRAY(UpdateListenerFunction,
+                                             _listener_callbacks,
+                                             _n_listener_callbacks,
+                                             mtLogging);
+  _listener_callbacks[idx] = cb;
+}
+
+void LogConfiguration::notify_update_listeners() {
+  assert(ConfigurationLock::current_thread_has_lock(), "notify_update_listeners must be called in ConfigurationLock scope (lock held)");
+  for (size_t i = 0; i < _n_listener_callbacks; i++) {
+    _listener_callbacks[i]();
+  }
+}
--- a/hotspot/src/share/vm/logging/logConfiguration.hpp	Tue Mar 15 15:43:04 2016 -0400
+++ b/hotspot/src/share/vm/logging/logConfiguration.hpp	Tue Mar 15 20:37:35 2016 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2016, 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
@@ -37,10 +37,26 @@
 // kept implicitly in the LogTagSets and their LogOutputLists. During configuration the tagsets
 // are iterated over and updated accordingly.
 class LogConfiguration : public AllStatic {
+ public:
+  // Function for listeners
+  typedef void (*UpdateListenerFunction)(void);
+
+  // Register callback for config change.
+  // The callback is always called with ConfigurationLock held,
+  // hence doing log reconfiguration from the callback will deadlock.
+  // The main Java thread may call this callback if there is an early registration
+  // else the attach listener JavaThread, started via diagnostic command, will be executing thread.
+  // The main purpose of this callback is to see if a loglevel have been changed.
+  // There is no way to unregister.
+  static void register_update_listener(UpdateListenerFunction cb);
+
  private:
   static LogOutput**  _outputs;
   static size_t       _n_outputs;
 
+  static UpdateListenerFunction*    _listener_callbacks;
+  static size_t                     _n_listener_callbacks;
+
   // Create a new output. Returns NULL if failed.
   static LogOutput* new_output(char* name, const char* options, outputStream* errstream);
 
@@ -60,6 +76,9 @@
   // Configure output (add or update existing configuration) to log on tag-level combination using specified decorators.
   static void configure_output(size_t idx, const LogTagLevelExpression& tag_level_expression, const LogDecorators& decorators);
 
+  // This should be called after any configuration change while still holding ConfigurationLock
+  static void notify_update_listeners();
+
  public:
   // Initialization and finalization of log configuration, to be run at vm startup and shutdown respectively.
   static void initialize(jlong vm_start_time);
--- a/hotspot/src/share/vm/utilities/internalVMTests.cpp	Tue Mar 15 15:43:04 2016 -0400
+++ b/hotspot/src/share/vm/utilities/internalVMTests.cpp	Tue Mar 15 20:37:35 2016 +0000
@@ -69,6 +69,7 @@
   run_unit_test(JSON_test);
   run_unit_test(Test_log_length);
   run_unit_test(Test_configure_stdout);
+  run_unit_test(Test_logconfiguration_subscribe);
   run_unit_test(DirectivesParser_test);
   run_unit_test(Test_TempNewSymbol);
 #if INCLUDE_VM_STRUCTS