Adds writer test case for RCU
[folly.git] / folly / experimental / logging / LogCategory.cpp
index 6f02c9dca6a090f6d474907747fcab70920ca4d6..4cc76670d10b1a804a4480899bdb1c8bd61a850d 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 2004-present Facebook, Inc.
+ * Copyright 2017-present Facebook, Inc.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
 #include <folly/experimental/logging/LogCategory.h>
 
 #include <cstdio>
+#include <cstdlib>
 
+#include <folly/ConstexprMath.h>
 #include <folly/ExceptionString.h>
+#include <folly/FileUtil.h>
+#include <folly/MapUtil.h>
 #include <folly/experimental/logging/LogHandler.h>
 #include <folly/experimental/logging/LogMessage.h>
 #include <folly/experimental/logging/LogName.h>
@@ -26,8 +30,8 @@
 namespace folly {
 
 LogCategory::LogCategory(LoggerDB* db)
-    : effectiveLevel_{LogLevel::ERROR},
-      level_{static_cast<uint32_t>(LogLevel::ERROR)},
+    : effectiveLevel_{LogLevel::ERR},
+      level_{static_cast<uint32_t>(LogLevel::ERR)},
       parent_{nullptr},
       name_{},
       db_{db} {}
@@ -42,6 +46,31 @@ LogCategory::LogCategory(StringPiece name, LogCategory* parent)
   parent_->firstChild_ = this;
 }
 
+void LogCategory::admitMessage(const LogMessage& message) const {
+  processMessage(message);
+
+  // If this is a fatal message, flush the handlers to make sure the log
+  // message was written out, then crash.
+  if (isLogLevelFatal(message.getLevel())) {
+    auto numHandlers = db_->flushAllHandlers();
+    if (numHandlers == 0) {
+      // No log handlers were configured.
+      // Print the message to stderr, to make sure we always print the reason
+      // we are crashing somewhere.
+      auto msg = folly::to<std::string>(
+          "FATAL:",
+          message.getFileName(),
+          ":",
+          message.getLineNumber(),
+          ": ",
+          message.getMessage(),
+          "\n");
+      folly::writeFull(STDERR_FILENO, msg.data(), msg.size());
+    }
+    std::abort();
+  }
+}
+
 void LogCategory::processMessage(const LogMessage& message) const {
   // Make a copy of any attached LogHandlers, so we can release the handlers_
   // lock before holding them.
@@ -112,6 +141,27 @@ void LogCategory::clearHandlers() {
   // LogHandler destructors.
 }
 
+std::vector<std::shared_ptr<LogHandler>> LogCategory::getHandlers() const {
+  return *(handlers_.rlock());
+}
+
+void LogCategory::replaceHandlers(
+    std::vector<std::shared_ptr<LogHandler>> handlers) {
+  return handlers_.wlock()->swap(handlers);
+}
+
+void LogCategory::updateHandlers(const std::unordered_map<
+                                 std::shared_ptr<LogHandler>,
+                                 std::shared_ptr<LogHandler>>& handlerMap) {
+  auto handlers = handlers_.wlock();
+  for (auto& entry : *handlers) {
+    auto* ptr = get_ptr(handlerMap, entry);
+    if (ptr) {
+      entry = *ptr;
+    }
+  }
+}
+
 void LogCategory::setLevel(LogLevel level, bool inherit) {
   // We have to set the level through LoggerDB, since we require holding
   // the LoggerDB lock to iterate through our children in case our effective
@@ -124,11 +174,7 @@ void LogCategory::setLevelLocked(LogLevel level, bool inherit) {
   //
   // This makes sure that UNINITIALIZED is always less than any valid level
   // value, and that level values cannot conflict with our flag bits.
-  if (level > LogLevel::MAX_LEVEL) {
-    level = LogLevel::MAX_LEVEL;
-  } else if (level < LogLevel::MIN_LEVEL) {
-    level = LogLevel::MIN_LEVEL;
-  }
+  level = constexpr_clamp(level, LogLevel::MIN_LEVEL, LogLevel::MAX_LEVEL);
 
   // Make sure the inherit flag is always off for the root logger.
   if (!parent_) {
@@ -193,4 +239,4 @@ void LogCategory::parentLevelUpdated(LogLevel parentEffectiveLevel) {
 void LogCategory::registerXlogLevel(std::atomic<LogLevel>* levelPtr) {
   xlogLevels_.push_back(levelPtr);
 }
-}
+} // namespace folly