< prev index next >

src/share/vm/logging/logConfiguration.cpp

Print this page
rev 11858 : [mq]: 8157948.01


  27 #include "logging/logDecorations.hpp"
  28 #include "logging/logDecorators.hpp"
  29 #include "logging/logDiagnosticCommand.hpp"
  30 #include "logging/logFileOutput.hpp"
  31 #include "logging/logOutput.hpp"
  32 #include "logging/logStream.hpp"
  33 #include "logging/logTagLevelExpression.hpp"
  34 #include "logging/logTagSet.hpp"
  35 #include "memory/allocation.inline.hpp"
  36 #include "memory/resourceArea.hpp"
  37 #include "runtime/os.inline.hpp"
  38 #include "runtime/semaphore.hpp"
  39 #include "utilities/globalDefinitions.hpp"
  40 
  41 LogOutput** LogConfiguration::_outputs = NULL;
  42 size_t      LogConfiguration::_n_outputs = 0;
  43 
  44 LogConfiguration::UpdateListenerFunction* LogConfiguration::_listener_callbacks = NULL;
  45 size_t      LogConfiguration::_n_listener_callbacks = 0;
  46 



  47 // Stack object to take the lock for configuring the logging.
  48 // Should only be held during the critical parts of the configuration
  49 // (when calling configure_output or reading/modifying the outputs array).
  50 // Thread must never block when holding this lock.
  51 class ConfigurationLock : public StackObj {
  52  private:
  53   // Semaphore used as lock
  54   static Semaphore _semaphore;
  55   debug_only(static intx _locking_thread_id;)
  56  public:
  57   ConfigurationLock() {
  58     _semaphore.wait();
  59     debug_only(_locking_thread_id = os::current_thread_id());
  60   }
  61   ~ConfigurationLock() {
  62     debug_only(_locking_thread_id = -1);
  63     _semaphore.signal();
  64   }
  65   debug_only(static bool current_thread_has_lock();)
  66 };


  91 }
  92 
  93 void LogConfiguration::initialize(jlong vm_start_time) {
  94   LogFileOutput::set_file_name_parameters(vm_start_time);
  95   LogDecorations::initialize(vm_start_time);
  96   assert(_outputs == NULL, "Should not initialize _outputs before this function, initialize called twice?");
  97   _outputs = NEW_C_HEAP_ARRAY(LogOutput*, 2, mtLogging);
  98   _outputs[0] = LogOutput::Stdout;
  99   _outputs[1] = LogOutput::Stderr;
 100   _n_outputs = 2;
 101 }
 102 
 103 void LogConfiguration::finalize() {
 104   for (size_t i = 2; i < _n_outputs; i++) {
 105     delete _outputs[i];
 106   }
 107   FREE_C_HEAP_ARRAY(LogOutput*, _outputs);
 108 }
 109 
 110 // Normalizes the given LogOutput name to type=name form.

 111 static bool normalize_output_name(const char* full_name, char* buffer, size_t len, outputStream* errstream) {
 112   const char* start_quote = strchr(full_name, '"');
 113   const char* equals = strchr(full_name, '=');
 114   const bool quoted = start_quote != NULL;
 115   const bool is_stdout_or_stderr = (strcmp(full_name, "stdout") == 0 || strcmp(full_name, "stderr") == 0);
 116 
 117   // ignore equals sign within quotes
 118   if (quoted && equals > start_quote) {
 119     equals = NULL;
 120   }
 121 
 122   const char* prefix = "";
 123   size_t prefix_len = 0;
 124   const char* name = full_name;
 125   if (equals != NULL) {
 126     // split on equals sign
 127     name = equals + 1;
 128     prefix = full_name;
 129     prefix_len = equals - full_name + 1;
 130   } else if (!is_stdout_or_stderr) {
 131     prefix = "file=";
 132     prefix_len = strlen(prefix);
 133   }
 134   size_t name_len = strlen(name);
 135 
 136   if (quoted) {
 137     const char* end_quote = strchr(start_quote + 1, '"');
 138     if (end_quote == NULL) {
 139       errstream->print_cr("Output name has opening quote but is missing a terminating quote.");
 140       return false;
 141     }
 142     if (start_quote != name || end_quote[1] != '\0') {
 143       errstream->print_cr("Output name can not be partially quoted."
 144                           " Either surround the whole name with quotation marks,"
 145                           " or do not use quotation marks at all.");
 146       return false;
 147     }
 148     // strip start and end quote
 149     name++;
 150     name_len -= 2;
 151   }
 152 
 153   int ret = jio_snprintf(buffer, len, "%.*s%.*s", prefix_len, prefix, name_len, name);
 154   assert(ret > 0, "buffer issue");
 155   return true;
 156 }
 157 
 158 size_t LogConfiguration::find_output(const char* name) {
 159   for (size_t i = 0; i < _n_outputs; i++) {
 160     if (strcmp(_outputs[i]->name(), name) == 0) {
 161       return i;
 162     }
 163   }
 164   return SIZE_MAX;
 165 }
 166 
 167 LogOutput* LogConfiguration::new_output(const char* name,
 168                                         const char* options,
 169                                         outputStream* errstream) {
 170   LogOutput* output;
 171   if (strncmp(name, "file=", strlen("file=")) == 0) {
 172     output = new LogFileOutput(name);
 173   } else {
 174     errstream->print_cr("Unsupported log output type: %s", name);
 175     return NULL;
 176   }
 177 
 178   bool success = output->initialize(options, errstream);
 179   if (!success) {
 180     errstream->print_cr("Initialization of output '%s' using options '%s' failed.", name, options);
 181     delete output;
 182     return NULL;
 183   }
 184   return output;
 185 }
 186 
 187 size_t LogConfiguration::add_output(LogOutput* output) {
 188   size_t idx = _n_outputs++;
 189   _outputs = REALLOC_C_HEAP_ARRAY(LogOutput*, _outputs, _n_outputs, mtLogging);
 190   _outputs[idx] = output;
 191   return idx;


 378   LogTagLevelExpression expr;
 379   if (!expr.parse(what, errstream)) {
 380     return false;
 381   }
 382 
 383   LogDecorators decorators;
 384   if (!decorators.parse(decoratorstr, errstream)) {
 385     return false;
 386   }
 387 
 388   ConfigurationLock cl;
 389   size_t idx;
 390   if (outputstr[0] == '#') { // Output specified using index
 391     int ret = sscanf(outputstr + 1, SIZE_FORMAT, &idx);
 392     if (ret != 1 || idx >= _n_outputs) {
 393       errstream->print_cr("Invalid output index '%s'", outputstr);
 394       return false;
 395     }
 396   } else { // Output specified using name
 397     // Normalize the name, stripping quotes and ensures it includes type prefix
 398     size_t len = strlen(outputstr) + strlen("file=") + 1;
 399     char* normalized = NEW_C_HEAP_ARRAY(char, len, mtLogging);
 400     if (!normalize_output_name(outputstr, normalized, len, errstream)) {
 401       return false;
 402     }
 403 
 404     idx = find_output(normalized);
 405     if (idx == SIZE_MAX) {
 406       // Attempt to create and add the output
 407       LogOutput* output = new_output(normalized, output_options, errstream);
 408       if (output != NULL) {
 409         idx = add_output(output);
 410       }
 411     } else if (output_options != NULL && strlen(output_options) > 0) {
 412       errstream->print_cr("Output options for existing outputs are ignored.");
 413     }
 414 
 415     FREE_C_HEAP_ARRAY(char, normalized);
 416     if (idx == SIZE_MAX) {
 417       return false;
 418     }




  27 #include "logging/logDecorations.hpp"
  28 #include "logging/logDecorators.hpp"
  29 #include "logging/logDiagnosticCommand.hpp"
  30 #include "logging/logFileOutput.hpp"
  31 #include "logging/logOutput.hpp"
  32 #include "logging/logStream.hpp"
  33 #include "logging/logTagLevelExpression.hpp"
  34 #include "logging/logTagSet.hpp"
  35 #include "memory/allocation.inline.hpp"
  36 #include "memory/resourceArea.hpp"
  37 #include "runtime/os.inline.hpp"
  38 #include "runtime/semaphore.hpp"
  39 #include "utilities/globalDefinitions.hpp"
  40 
  41 LogOutput** LogConfiguration::_outputs = NULL;
  42 size_t      LogConfiguration::_n_outputs = 0;
  43 
  44 LogConfiguration::UpdateListenerFunction* LogConfiguration::_listener_callbacks = NULL;
  45 size_t      LogConfiguration::_n_listener_callbacks = 0;
  46 
  47 // LogFileOutput is the default type of output, its type prefix should be used if no type was specified
  48 static const char* implicit_output_prefix = LogFileOutput::Prefix;
  49 
  50 // Stack object to take the lock for configuring the logging.
  51 // Should only be held during the critical parts of the configuration
  52 // (when calling configure_output or reading/modifying the outputs array).
  53 // Thread must never block when holding this lock.
  54 class ConfigurationLock : public StackObj {
  55  private:
  56   // Semaphore used as lock
  57   static Semaphore _semaphore;
  58   debug_only(static intx _locking_thread_id;)
  59  public:
  60   ConfigurationLock() {
  61     _semaphore.wait();
  62     debug_only(_locking_thread_id = os::current_thread_id());
  63   }
  64   ~ConfigurationLock() {
  65     debug_only(_locking_thread_id = -1);
  66     _semaphore.signal();
  67   }
  68   debug_only(static bool current_thread_has_lock();)
  69 };


  94 }
  95 
  96 void LogConfiguration::initialize(jlong vm_start_time) {
  97   LogFileOutput::set_file_name_parameters(vm_start_time);
  98   LogDecorations::initialize(vm_start_time);
  99   assert(_outputs == NULL, "Should not initialize _outputs before this function, initialize called twice?");
 100   _outputs = NEW_C_HEAP_ARRAY(LogOutput*, 2, mtLogging);
 101   _outputs[0] = LogOutput::Stdout;
 102   _outputs[1] = LogOutput::Stderr;
 103   _n_outputs = 2;
 104 }
 105 
 106 void LogConfiguration::finalize() {
 107   for (size_t i = 2; i < _n_outputs; i++) {
 108     delete _outputs[i];
 109   }
 110   FREE_C_HEAP_ARRAY(LogOutput*, _outputs);
 111 }
 112 
 113 // Normalizes the given LogOutput name to type=name form.
 114 // For example, foo, "foo", file="foo", will all be normalized to file=foo (no quotes, prefixed).
 115 static bool normalize_output_name(const char* full_name, char* buffer, size_t len, outputStream* errstream) {
 116   const char* start_quote = strchr(full_name, '"');
 117   const char* equals = strchr(full_name, '=');
 118   const bool quoted = start_quote != NULL;
 119   const bool is_stdout_or_stderr = (strcmp(full_name, "stdout") == 0 || strcmp(full_name, "stderr") == 0);
 120 
 121   // ignore equals sign within quotes
 122   if (quoted && equals > start_quote) {
 123     equals = NULL;
 124   }
 125 
 126   const char* prefix = "";
 127   size_t prefix_len = 0;
 128   const char* name = full_name;
 129   if (equals != NULL) {
 130     // split on equals sign
 131     name = equals + 1;
 132     prefix = full_name;
 133     prefix_len = equals - full_name + 1;
 134   } else if (!is_stdout_or_stderr) {
 135     prefix = implicit_output_prefix;
 136     prefix_len = strlen(prefix);
 137   }
 138   size_t name_len = strlen(name);
 139 
 140   if (quoted) {
 141     const char* end_quote = strchr(start_quote + 1, '"');
 142     if (end_quote == NULL) {
 143       errstream->print_cr("Output name has opening quote but is missing a terminating quote.");
 144       return false;
 145     }
 146     if (start_quote != name || end_quote[1] != '\0') {
 147       errstream->print_cr("Output name can not be partially quoted."
 148                           " Either surround the whole name with quotation marks,"
 149                           " or do not use quotation marks at all.");
 150       return false;
 151     }
 152     // strip start and end quote
 153     name++;
 154     name_len -= 2;
 155   }
 156 
 157   int ret = jio_snprintf(buffer, len, "%.*s%.*s", prefix_len, prefix, name_len, name);
 158   assert(ret > 0, "buffer issue");
 159   return true;
 160 }
 161 
 162 size_t LogConfiguration::find_output(const char* name) {
 163   for (size_t i = 0; i < _n_outputs; i++) {
 164     if (strcmp(_outputs[i]->name(), name) == 0) {
 165       return i;
 166     }
 167   }
 168   return SIZE_MAX;
 169 }
 170 
 171 LogOutput* LogConfiguration::new_output(const char* name,
 172                                         const char* options,
 173                                         outputStream* errstream) {
 174   LogOutput* output;
 175   if (strncmp(name, LogFileOutput::Prefix, strlen(LogFileOutput::Prefix)) == 0) {
 176     output = new LogFileOutput(name);
 177   } else {
 178     errstream->print_cr("Unsupported log output type: %s", name);
 179     return NULL;
 180   }
 181 
 182   bool success = output->initialize(options, errstream);
 183   if (!success) {
 184     errstream->print_cr("Initialization of output '%s' using options '%s' failed.", name, options);
 185     delete output;
 186     return NULL;
 187   }
 188   return output;
 189 }
 190 
 191 size_t LogConfiguration::add_output(LogOutput* output) {
 192   size_t idx = _n_outputs++;
 193   _outputs = REALLOC_C_HEAP_ARRAY(LogOutput*, _outputs, _n_outputs, mtLogging);
 194   _outputs[idx] = output;
 195   return idx;


 382   LogTagLevelExpression expr;
 383   if (!expr.parse(what, errstream)) {
 384     return false;
 385   }
 386 
 387   LogDecorators decorators;
 388   if (!decorators.parse(decoratorstr, errstream)) {
 389     return false;
 390   }
 391 
 392   ConfigurationLock cl;
 393   size_t idx;
 394   if (outputstr[0] == '#') { // Output specified using index
 395     int ret = sscanf(outputstr + 1, SIZE_FORMAT, &idx);
 396     if (ret != 1 || idx >= _n_outputs) {
 397       errstream->print_cr("Invalid output index '%s'", outputstr);
 398       return false;
 399     }
 400   } else { // Output specified using name
 401     // Normalize the name, stripping quotes and ensures it includes type prefix
 402     size_t len = strlen(outputstr) + strlen(implicit_output_prefix) + 1;
 403     char* normalized = NEW_C_HEAP_ARRAY(char, len, mtLogging);
 404     if (!normalize_output_name(outputstr, normalized, len, errstream)) {
 405       return false;
 406     }
 407 
 408     idx = find_output(normalized);
 409     if (idx == SIZE_MAX) {
 410       // Attempt to create and add the output
 411       LogOutput* output = new_output(normalized, output_options, errstream);
 412       if (output != NULL) {
 413         idx = add_output(output);
 414       }
 415     } else if (output_options != NULL && strlen(output_options) > 0) {
 416       errstream->print_cr("Output options for existing outputs are ignored.");
 417     }
 418 
 419     FREE_C_HEAP_ARRAY(char, normalized);
 420     if (idx == SIZE_MAX) {
 421       return false;
 422     }


< prev index next >