From: Colin Patrick McCabe Date: Wed, 1 Jun 2011 17:08:19 +0000 (-0700) Subject: DoutStreambuf: de-globalize emergency logging X-Git-Tag: v0.30~130 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=5b7049c8a4ed88358509c10f6d89a471ed065ba7;p=ceph.git DoutStreambuf: de-globalize emergency logging Signed-off-by: Colin McCabe --- diff --git a/src/common/DoutStreambuf.cc b/src/common/DoutStreambuf.cc index 8ac56acc665c..341d4a5b59b3 100644 --- a/src/common/DoutStreambuf.cc +++ b/src/common/DoutStreambuf.cc @@ -12,13 +12,14 @@ * */ +#include "common/DoutStreambuf.h" +#include "common/Mutex.h" #include "common/code_environment.h" #include "common/config.h" -#include "common/DoutStreambuf.h" #include "common/entity_name.h" #include "common/errno.h" -#include "common/Mutex.h" #include "common/safe_io.h" +#include "common/simple_spin.h" #include #include @@ -42,6 +43,20 @@ extern DoutStreambuf *_doss; // TODO: get rid of this lock using thread-local storage extern pthread_mutex_t _dout_lock; +static simple_spinlock_t dout_emergency_lock = SIMPLE_SPINLOCK_INITIALIZER; + +/* Streams that we will write to in dout_emergency. + * Protected by dout_emergency_lock. */ +EmergencyLogger *dout_emerg_streams[] = + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; + +#define NUM_DOUT_EMERG_STREAMS \ + (sizeof(dout_emerg_streams)/sizeof(dout_emerg_streams[0])) + +EmergencyLogger::~EmergencyLogger() +{ +} + //////////////////////// Helper functions ////////////////////////// // Try a 0-byte write to a file descriptor to see if it open. static bool fd_is_open(int fd) @@ -144,6 +159,15 @@ DoutStreambuf::DoutStreambuf() // Initialize output_buffer _clear_output_buffer(); + + simple_spin_lock(&dout_emergency_lock); + for (size_t i = 0; i < NUM_DOUT_EMERG_STREAMS; ++i) { + if (dout_emerg_streams[i] == 0) { + dout_emerg_streams[i] = this; + break; + } + } + simple_spin_unlock(&dout_emergency_lock); } template @@ -153,6 +177,14 @@ DoutStreambuf::~DoutStreambuf() TEMP_FAILURE_RETRY(::close(ofd)); ofd = -1; } + simple_spin_lock(&dout_emergency_lock); + for (size_t i = 0; i < NUM_DOUT_EMERG_STREAMS; ++i) { + if (dout_emerg_streams[i] == this) { + dout_emerg_streams[i] = 0; + break; + } + } + simple_spin_unlock(&dout_emergency_lock); } // This function is called when the output buffer is filled. @@ -345,9 +377,13 @@ std::string DoutStreambuf::config_to_str() const return oss.str(); } +/* This function doesn't take the dout lock, so some interleaving or weirdness + * may happen if concurrent writes are going on. But this is for emergencies, + * so we don't care. + */ template void DoutStreambuf:: -dout_emergency_to_file_and_syslog(const char * const str) const +emergency_log_to_file_and_syslog(const char * const str) const { int len = strlen(str); if (ofd >= 0) { @@ -598,16 +634,23 @@ _rotate_files(const md_config_t *conf, const std::string &base) */ void dout_emergency(const char * const str) { + // Write to stderr. It may or may not be open, but if it is, there's a good + // chance the user will see this. int len = strlen(str); if (safe_write(STDERR_FILENO, str, len)) { // ignore errors ; } - /* Normally we would take the lock before even checking _doss, but since - * this is an emergency, we can't do that. */ - if (_doss) { - _doss->dout_emergency_to_file_and_syslog(str); + + // Write to all the file descriptors we know about. + // If we are logging to syslog, send logs to that too. + simple_spin_lock(&dout_emergency_lock); + for (size_t i = 0; i < NUM_DOUT_EMERG_STREAMS; ++i) { + if (dout_emerg_streams[i]) { + dout_emerg_streams[i]->emergency_log_to_file_and_syslog(str); + } } + simple_spin_unlock(&dout_emergency_lock); } void dout_emergency(const std::string &str) diff --git a/src/common/DoutStreambuf.h b/src/common/DoutStreambuf.h index b2bcfb299da6..b21d1e020dea 100644 --- a/src/common/DoutStreambuf.h +++ b/src/common/DoutStreambuf.h @@ -27,9 +27,16 @@ class md_config_t; +class EmergencyLogger { +public: + virtual ~EmergencyLogger(); + virtual void emergency_log_to_file_and_syslog(const char *const str) const = 0; +}; + template > class DoutStreambuf : public std::basic_streambuf, - public md_config_obs_t + public md_config_obs_t, + public EmergencyLogger { public: enum dout_streambuf_flags_t { @@ -73,7 +80,7 @@ public: // Output a string directly to the file and to syslog // (if those sinks are active) - void dout_emergency_to_file_and_syslog(const char * const str) const; + void emergency_log_to_file_and_syslog(const char * const str) const; // Reopen the logs void reopen_logs(const md_config_t *conf);