]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
DoutStreambuf: de-globalize emergency logging
authorColin Patrick McCabe <cmccabe@alumni.cmu.edu>
Wed, 1 Jun 2011 17:08:19 +0000 (10:08 -0700)
committerColin Patrick McCabe <cmccabe@alumni.cmu.edu>
Fri, 3 Jun 2011 21:47:00 +0000 (14:47 -0700)
Signed-off-by: Colin McCabe <colin.mccabe@dreamhost.com>
src/common/DoutStreambuf.cc
src/common/DoutStreambuf.h

index 8ac56acc665c9a7bec1ae1f0dc9b4a38e91a7eb6..341d4a5b59b370aba31c392bab2faf831e3a23d4 100644 (file)
  *
  */
 
+#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 <values.h>
 #include <assert.h>
@@ -42,6 +43,20 @@ extern DoutStreambuf <char> *_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<charT, traits>::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 <typename charT, typename traits>
@@ -153,6 +177,14 @@ DoutStreambuf<charT, traits>::~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<charT, traits>::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 <typename charT, typename traits>
 void DoutStreambuf<charT, traits>::
-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)
index b2bcfb299da61d25d83eaa3aef6e41e6545285a6..b21d1e020deae386339705176a836a17b5172d7f 100644 (file)
 
 class md_config_t;
 
+class EmergencyLogger {
+public:
+  virtual ~EmergencyLogger();
+  virtual void emergency_log_to_file_and_syslog(const char *const str) const = 0;
+};
+
 template <typename charT, typename traits = std::char_traits<charT> >
 class DoutStreambuf : public std::basic_streambuf<charT, traits>,
-                     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);