[Lldb-commits] [lldb] r295442 - Reapply "Refactor log channel registration mechanism"

Pavel Labath via lldb-commits lldb-commits at lists.llvm.org
Fri Feb 17 05:27:43 PST 2017


Author: labath
Date: Fri Feb 17 07:27:42 2017
New Revision: 295442

URL: http://llvm.org/viewvc/llvm-project?rev=295442&view=rev
Log:
Reapply "Refactor log channel registration mechanism"

Changes wrt. previous version:
- add #include <atomic>: fix build on windows
- add extra {} around the string literals used to initialize
  llvm::StringLiteral: fix gcc build

Modified:
    lldb/trunk/include/lldb/Core/Log.h
    lldb/trunk/include/lldb/Core/PluginManager.h
    lldb/trunk/include/lldb/lldb-forward.h
    lldb/trunk/include/lldb/lldb-private-interfaces.h
    lldb/trunk/source/Commands/CommandObjectLog.cpp
    lldb/trunk/source/Core/Log.cpp
    lldb/trunk/source/Core/PluginManager.cpp
    lldb/trunk/source/Plugins/SymbolFile/DWARF/LogChannelDWARF.cpp
    lldb/trunk/source/Plugins/SymbolFile/DWARF/LogChannelDWARF.h
    lldb/trunk/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
    lldb/trunk/unittests/Core/LogTest.cpp

Modified: lldb/trunk/include/lldb/Core/Log.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Core/Log.h?rev=295442&r1=295441&r2=295442&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Core/Log.h (original)
+++ lldb/trunk/include/lldb/Core/Log.h Fri Feb 17 07:27:42 2017
@@ -12,7 +12,6 @@
 
 // Project includes
 #include "lldb/Core/Logging.h"
-#include "lldb/Core/PluginInterface.h"
 #include "lldb/Utility/ConstString.h"
 #include "lldb/Utility/Flags.h"
 #include "lldb/lldb-private.h"
@@ -20,6 +19,7 @@
 // Other libraries and framework includes
 #include "llvm/Support/FormatVariadic.h"
 // C++ Includes
+#include <atomic>
 #include <cstdarg>
 #include <cstdint>
 // C Includes
@@ -44,6 +44,53 @@ namespace lldb_private {
 
 class Log final {
 public:
+  // Description of a log channel category.
+  struct Category {
+    llvm::StringLiteral name;
+    llvm::StringLiteral description;
+    uint32_t flag;
+  };
+
+  // This class describes a log channel. It also encapsulates the behavior
+  // necessary to enable a log channel in an atomic manner.
+  class Channel {
+    std::atomic<Log *> log_ptr;
+
+  public:
+    const llvm::ArrayRef<Category> categories;
+    const uint32_t default_flags;
+
+    constexpr Channel(llvm::ArrayRef<Log::Category> categories,
+                      uint32_t default_flags)
+        : log_ptr(nullptr), categories(categories),
+          default_flags(default_flags) {}
+
+    // This function is safe to call at any time
+    // FIXME: Not true yet, mask access is not atomic
+    Log *GetLogIfAll(uint32_t mask) {
+      Log *log = log_ptr.load(std::memory_order_acquire);
+      if (log && log->GetMask().AllSet(mask))
+        return log;
+      return nullptr;
+    }
+
+    // This function is safe to call at any time
+    // FIXME: Not true yet, mask access is not atomic
+    Log *GetLogIfAny(uint32_t mask) {
+      Log *log = log_ptr.load(std::memory_order_acquire);
+      if (log && log->GetMask().AnySet(mask))
+        return log;
+      return nullptr;
+    }
+
+    // Calls to Enable and disable need to be serialized externally.
+    void Enable(Log &log, const std::shared_ptr<llvm::raw_ostream> &stream_sp,
+                uint32_t flags);
+
+    // Calls to Enable and disable need to be serialized externally.
+    void Disable(uint32_t flags);
+  };
+
   //------------------------------------------------------------------
   // Callback definitions for abstracted plug-in log access.
   //------------------------------------------------------------------
@@ -63,6 +110,9 @@ public:
   //------------------------------------------------------------------
   // Static accessors for logging channels
   //------------------------------------------------------------------
+  static void Register(llvm::StringRef name, Channel &channel);
+  static void Unregister(llvm::StringRef name);
+
   static void RegisterLogChannel(const ConstString &channel,
                                  const Log::Callbacks &log_callbacks);
 
@@ -73,13 +123,13 @@ public:
 
   static bool
   EnableLogChannel(const std::shared_ptr<llvm::raw_ostream> &log_stream_sp,
-                   uint32_t log_options, const char *channel,
+                   uint32_t log_options, llvm::StringRef channel,
                    const char **categories, Stream &error_stream);
 
-  static void
-  EnableAllLogChannels(const std::shared_ptr<llvm::raw_ostream> &log_stream_sp,
-                       uint32_t log_options, const char **categories,
-                       Stream *feedback_strm);
+  static bool DisableLogChannel(llvm::StringRef channel,
+                                const char **categories, Stream &error_stream);
+
+  static bool ListChannelCategories(llvm::StringRef channel, Stream &stream);
 
   static void DisableAllLogChannels(Stream *feedback_strm);
 
@@ -90,12 +140,6 @@ public:
   static void Terminate();
 
   //------------------------------------------------------------------
-  // Auto completion
-  //------------------------------------------------------------------
-  static void AutoCompleteChannelName(const char *channel_name,
-                                      StringList &matches);
-
-  //------------------------------------------------------------------
   // Member functions
   //------------------------------------------------------------------
   Log();
@@ -162,34 +206,6 @@ private:
               const llvm::formatv_object_base &payload);
 };
 
-class LogChannel : public PluginInterface {
-public:
-  LogChannel();
-
-  ~LogChannel() override;
-
-  static lldb::LogChannelSP FindPlugin(const char *plugin_name);
-
-  // categories is an array of chars that ends with a NULL element.
-  virtual void Disable(const char **categories, Stream *feedback_strm) = 0;
-
-  virtual bool
-  Enable(const std::shared_ptr<llvm::raw_ostream> &log_stream_sp,
-         uint32_t log_options,
-         Stream *feedback_strm, // Feedback stream for argument errors etc
-         const char **categories) = 0; // The categories to enable within this
-                                       // logging stream, if empty, enable
-                                       // default set
-
-  virtual void ListCategories(Stream *strm) = 0;
-
-protected:
-  std::unique_ptr<Log> m_log_ap;
-
-private:
-  DISALLOW_COPY_AND_ASSIGN(LogChannel);
-};
-
 } // namespace lldb_private
 
 #define LLDB_LOG(log, ...)                                                     \

Modified: lldb/trunk/include/lldb/Core/PluginManager.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Core/PluginManager.h?rev=295442&r1=295441&r2=295442&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Core/PluginManager.h (original)
+++ lldb/trunk/include/lldb/Core/PluginManager.h Fri Feb 17 07:27:42 2017
@@ -210,22 +210,6 @@ public:
   GetObjectContainerGetModuleSpecificationsCallbackAtIndex(uint32_t idx);
 
   //------------------------------------------------------------------
-  // LogChannel
-  //------------------------------------------------------------------
-  static bool RegisterPlugin(const ConstString &name, const char *description,
-                             LogChannelCreateInstance create_callback);
-
-  static bool UnregisterPlugin(LogChannelCreateInstance create_callback);
-
-  static LogChannelCreateInstance
-  GetLogChannelCreateCallbackAtIndex(uint32_t idx);
-
-  static LogChannelCreateInstance
-  GetLogChannelCreateCallbackForPluginName(const ConstString &name);
-
-  static const char *GetLogChannelCreateNameAtIndex(uint32_t idx);
-
-  //------------------------------------------------------------------
   // Platform
   //------------------------------------------------------------------
   static bool

Modified: lldb/trunk/include/lldb/lldb-forward.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/lldb-forward.h?rev=295442&r1=295441&r2=295442&view=diff
==============================================================================
--- lldb/trunk/include/lldb/lldb-forward.h (original)
+++ lldb/trunk/include/lldb/lldb-forward.h Fri Feb 17 07:27:42 2017
@@ -127,7 +127,6 @@ class MemoryRegionInfo;
 class LineTable;
 class Listener;
 class Log;
-class LogChannel;
 class Mangled;
 class Materializer;
 class MemoryHistory;
@@ -362,7 +361,6 @@ typedef std::unique_ptr<lldb_private::Sy
 typedef std::shared_ptr<lldb_private::LineTable> LineTableSP;
 typedef std::shared_ptr<lldb_private::Listener> ListenerSP;
 typedef std::weak_ptr<lldb_private::Listener> ListenerWP;
-typedef std::shared_ptr<lldb_private::LogChannel> LogChannelSP;
 typedef std::shared_ptr<lldb_private::MemoryHistory> MemoryHistorySP;
 typedef std::shared_ptr<lldb_private::MemoryRegionInfo> MemoryRegionInfoSP;
 typedef std::unique_ptr<lldb_private::MemoryRegionInfo> MemoryRegionInfoUP;

Modified: lldb/trunk/include/lldb/lldb-private-interfaces.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/lldb-private-interfaces.h?rev=295442&r1=295441&r2=295442&view=diff
==============================================================================
--- lldb/trunk/include/lldb/lldb-private-interfaces.h (original)
+++ lldb/trunk/include/lldb/lldb-private-interfaces.h Fri Feb 17 07:27:42 2017
@@ -45,7 +45,6 @@ typedef ObjectFile *(*ObjectFileCreateMe
     const lldb::ProcessSP &process_sp, lldb::addr_t offset);
 typedef bool (*ObjectFileSaveCore)(const lldb::ProcessSP &process_sp,
                                    const FileSpec &outfile, Error &error);
-typedef LogChannel *(*LogChannelCreateInstance)();
 typedef EmulateInstruction *(*EmulateInstructionCreateInstance)(
     const ArchSpec &arch, InstructionType inst_type);
 typedef OperatingSystem *(*OperatingSystemCreateInstance)(Process *process,

Modified: lldb/trunk/source/Commands/CommandObjectLog.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Commands/CommandObjectLog.cpp?rev=295442&r1=295441&r2=295442&view=diff
==============================================================================
--- lldb/trunk/source/Commands/CommandObjectLog.cpp (original)
+++ lldb/trunk/source/Commands/CommandObjectLog.cpp Fri Feb 17 07:27:42 2017
@@ -227,25 +227,15 @@ protected:
       return false;
     }
 
-    Log::Callbacks log_callbacks;
-
     const std::string channel = args[0].ref;
     args.Shift(); // Shift off the channel
-    if (Log::GetLogChannelCallbacks(ConstString(channel), log_callbacks)) {
-      log_callbacks.disable(args.GetConstArgumentVector(),
-                            &result.GetErrorStream());
-      result.SetStatus(eReturnStatusSuccessFinishNoResult);
-    } else if (channel == "all") {
+    if (channel == "all") {
       Log::DisableAllLogChannels(&result.GetErrorStream());
+      result.SetStatus(eReturnStatusSuccessFinishNoResult);
     } else {
-      LogChannelSP log_channel_sp(LogChannel::FindPlugin(channel.data()));
-      if (log_channel_sp) {
-        log_channel_sp->Disable(args.GetConstArgumentVector(),
-                                &result.GetErrorStream());
+      if (Log::DisableLogChannel(channel, args.GetConstArgumentVector(),
+                                 result.GetErrorStream()))
         result.SetStatus(eReturnStatusSuccessFinishNoResult);
-      } else
-        result.AppendErrorWithFormat("Invalid log channel '%s'.\n",
-                                     channel.data());
     }
     return result.Succeeded();
   }
@@ -284,26 +274,12 @@ protected:
       Log::ListAllLogChannels(&result.GetOutputStream());
       result.SetStatus(eReturnStatusSuccessFinishResult);
     } else {
-      for (auto &entry : args.entries()) {
-        Log::Callbacks log_callbacks;
-
-        if (Log::GetLogChannelCallbacks(ConstString(entry.ref),
-                                        log_callbacks)) {
-          log_callbacks.list_categories(&result.GetOutputStream());
-          result.SetStatus(eReturnStatusSuccessFinishResult);
-        } else if (entry.ref == "all") {
-          Log::ListAllLogChannels(&result.GetOutputStream());
-          result.SetStatus(eReturnStatusSuccessFinishResult);
-        } else {
-          LogChannelSP log_channel_sp(LogChannel::FindPlugin(entry.c_str()));
-          if (log_channel_sp) {
-            log_channel_sp->ListCategories(&result.GetOutputStream());
-            result.SetStatus(eReturnStatusSuccessFinishNoResult);
-          } else
-            result.AppendErrorWithFormat("Invalid log channel '%s'.\n",
-                                         entry.c_str());
-        }
-      }
+      bool success = true;
+      for (const auto &entry : args.entries())
+        success = success && Log::ListChannelCategories(
+                                 entry.ref, result.GetOutputStream());
+      if (success)
+        result.SetStatus(eReturnStatusSuccessFinishResult);
     }
     return result.Succeeded();
   }

Modified: lldb/trunk/source/Core/Log.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Core/Log.cpp?rev=295442&r1=295441&r2=295442&view=diff
==============================================================================
--- lldb/trunk/source/Core/Log.cpp (original)
+++ lldb/trunk/source/Core/Log.cpp Fri Feb 17 07:27:42 2017
@@ -18,8 +18,10 @@
 #include "lldb/Utility/StreamString.h"
 
 // Other libraries and framework includes
+#include "llvm/ADT/STLExtras.h"
 #include "llvm/ADT/SmallString.h"
 #include "llvm/Support/Chrono.h"
+#include "llvm/Support/ManagedStatic.h"
 #include "llvm/Support/Path.h"
 #include "llvm/Support/Signals.h"
 #include "llvm/Support/raw_ostream.h"
@@ -36,6 +38,76 @@
 using namespace lldb;
 using namespace lldb_private;
 
+namespace {
+  struct ChannelAndLog {
+    Log log;
+    Log::Channel &channel;
+
+    ChannelAndLog(Log::Channel &channel) : channel(channel) {}
+  };
+  typedef llvm::StringMap<ChannelAndLog> ChannelMap;
+}
+
+static llvm::ManagedStatic<ChannelMap> g_channel_map;
+
+static void ListCategories(Stream &stream, const ChannelMap::value_type &entry) {
+  stream.Format("Logging categories for '{0}':\n", entry.first());
+  stream.Format("  all - all available logging categories\n");
+  stream.Format("  default - default set of logging categories\n");
+  for (const auto &category : entry.second.channel.categories)
+    stream.Format("  {0} - {1}\n", category.name, category.description);
+}
+
+static uint32_t GetFlags(Stream &stream, const ChannelMap::value_type &entry,
+                  const char **categories) {
+  bool list_categories = false;
+  uint32_t flags = 0;
+  for (size_t i = 0; categories[i]; ++i) {
+    if (llvm::StringRef("all").equals_lower(categories[i])) {
+      flags |= UINT32_MAX;
+      continue;
+    }
+    if (llvm::StringRef("default").equals_lower(categories[i])) {
+      flags |= entry.second.channel.default_flags;
+      continue;
+    }
+    auto cat = llvm::find_if(entry.second.channel.categories,
+                             [&](const Log::Category &c) {
+                               return c.name.equals_lower(categories[i]);
+                             });
+    if (cat != entry.second.channel.categories.end()) {
+      flags |= cat->flag;
+      continue;
+    }
+    stream.Format("error: unrecognized log category '{0}'\n", categories[i]);
+    list_categories = true;
+  }
+  if (list_categories)
+    ListCategories(stream, entry);
+  return flags;
+}
+
+void Log::Channel::Enable(Log &log,
+                          const std::shared_ptr<llvm::raw_ostream> &stream_sp,
+                          uint32_t flags) {
+  log.GetMask().Set(flags);
+  if (log.GetMask().Get()) {
+    log.SetStream(stream_sp);
+    log_ptr.store(&log, std::memory_order_release);
+  }
+}
+
+void Log::Channel::Disable(uint32_t flags) {
+  Log *log = log_ptr.load(std::memory_order_acquire);
+  if (!log)
+    return;
+  log->GetMask().Clear(flags);
+  if (!log->GetMask().Get()) {
+    log->SetStream(nullptr);
+    log_ptr.store(nullptr, std::memory_order_release);
+  }
+}
+
 Log::Log() : m_stream_sp(), m_options(0), m_mask_bits(0) {}
 
 Log::Log(const std::shared_ptr<llvm::raw_ostream> &stream_sp)
@@ -152,9 +224,6 @@ void Log::Warning(const char *format, ..
 typedef std::map<ConstString, Log::Callbacks> CallbackMap;
 typedef CallbackMap::iterator CallbackMapIter;
 
-typedef std::map<ConstString, LogChannelSP> LogChannelMap;
-typedef LogChannelMap::iterator LogChannelMapIter;
-
 // Surround our callback map with a singleton function so we don't have any
 // global initializers.
 static CallbackMap &GetCallbackMap() {
@@ -162,9 +231,17 @@ static CallbackMap &GetCallbackMap() {
   return g_callback_map;
 }
 
-static LogChannelMap &GetChannelMap() {
-  static LogChannelMap g_channel_map;
-  return g_channel_map;
+void Log::Register(llvm::StringRef name, Channel &channel) {
+  auto iter = g_channel_map->try_emplace(name, channel);
+  assert(iter.second == true);
+  (void)iter;
+}
+
+void Log::Unregister(llvm::StringRef name) {
+  auto iter = g_channel_map->find(name);
+  assert(iter != g_channel_map->end());
+  iter->second.channel.Disable(UINT32_MAX);
+  g_channel_map->erase(iter);
 }
 
 void Log::RegisterLogChannel(const ConstString &channel,
@@ -190,7 +267,7 @@ bool Log::GetLogChannelCallbacks(const C
 
 bool Log::EnableLogChannel(
     const std::shared_ptr<llvm::raw_ostream> &log_stream_sp,
-    uint32_t log_options, const char *channel, const char **categories,
+    uint32_t log_options, llvm::StringRef channel, const char **categories,
     Stream &error_stream) {
   Log::Callbacks log_callbacks;
   if (Log::GetLogChannelCallbacks(ConstString(channel), log_callbacks)) {
@@ -198,52 +275,52 @@ bool Log::EnableLogChannel(
     return true;
   }
 
-  LogChannelSP log_channel_sp(LogChannel::FindPlugin(channel));
-  if (log_channel_sp) {
-    if (log_channel_sp->Enable(log_stream_sp, log_options, &error_stream,
-                               categories)) {
-      return true;
-    } else {
-      error_stream.Printf("Invalid log channel '%s'.\n", channel);
-      return false;
-    }
-  } else {
-    error_stream.Printf("Invalid log channel '%s'.\n", channel);
+  auto iter = g_channel_map->find(channel);
+  if (iter == g_channel_map->end()) {
+    error_stream.Format("Invalid log channel '{0}'.\n", channel);
     return false;
   }
+  uint32_t flags = categories && categories[0]
+                       ? GetFlags(error_stream, *iter, categories)
+                       : iter->second.channel.default_flags;
+  iter->second.channel.Enable(iter->second.log, log_stream_sp, flags);
+  return true;
 }
 
-void Log::EnableAllLogChannels(
-    const std::shared_ptr<llvm::raw_ostream> &log_stream_sp,
-    uint32_t log_options, const char **categories, Stream *feedback_strm) {
-  CallbackMap &callback_map = GetCallbackMap();
-  CallbackMapIter pos, end = callback_map.end();
-
-  for (pos = callback_map.begin(); pos != end; ++pos)
-    pos->second.enable(log_stream_sp, log_options, categories, feedback_strm);
+bool Log::DisableLogChannel(llvm::StringRef channel, const char **categories,
+                            Stream &error_stream) {
+  Log::Callbacks log_callbacks;
+  if (Log::GetLogChannelCallbacks(ConstString(channel), log_callbacks)) {
+    log_callbacks.disable(categories, &error_stream);
+    return true;
+  }
 
-  LogChannelMap &channel_map = GetChannelMap();
-  LogChannelMapIter channel_pos, channel_end = channel_map.end();
-  for (channel_pos = channel_map.begin(); channel_pos != channel_end;
-       ++channel_pos) {
-    channel_pos->second->Enable(log_stream_sp, log_options, feedback_strm,
-                                categories);
+  auto iter = g_channel_map->find(channel);
+  if (iter == g_channel_map->end()) {
+    error_stream.Format("Invalid log channel '{0}'.\n", channel);
+    return false;
   }
+  uint32_t flags = categories && categories[0]
+                       ? GetFlags(error_stream, *iter, categories)
+                       : UINT32_MAX;
+  iter->second.channel.Disable(flags);
+  return true;
 }
 
-void Log::AutoCompleteChannelName(const char *channel_name,
-                                  StringList &matches) {
-  LogChannelMap &map = GetChannelMap();
-  LogChannelMapIter pos, end = map.end();
-  for (pos = map.begin(); pos != end; ++pos) {
-    const char *pos_channel_name = pos->first.GetCString();
-    if (channel_name && channel_name[0]) {
-      if (NameMatches(channel_name, eNameMatchStartsWith, pos_channel_name)) {
-        matches.AppendString(pos_channel_name);
-      }
-    } else
-      matches.AppendString(pos_channel_name);
+bool Log::ListChannelCategories(llvm::StringRef channel, Stream &stream) {
+  Log::Callbacks log_callbacks;
+  if (Log::GetLogChannelCallbacks(ConstString(channel), log_callbacks)) {
+    log_callbacks.list_categories(&stream);
+    return true;
   }
+
+  auto ch = g_channel_map->find(channel);
+  if (ch == g_channel_map->end()) {
+    stream.Format("Invalid log channel '{0}'.\n", channel);
+    return false;
+  }
+  ListCategories(stream, *ch);
+  return true;
 }
 
 void Log::DisableAllLogChannels(Stream *feedback_strm) {
@@ -254,11 +331,8 @@ void Log::DisableAllLogChannels(Stream *
   for (pos = callback_map.begin(); pos != end; ++pos)
     pos->second.disable(categories, feedback_strm);
 
-  LogChannelMap &channel_map = GetChannelMap();
-  LogChannelMapIter channel_pos, channel_end = channel_map.end();
-  for (channel_pos = channel_map.begin(); channel_pos != channel_end;
-       ++channel_pos)
-    channel_pos->second->Disable(categories, feedback_strm);
+  for (auto &entry : *g_channel_map)
+    entry.second.channel.Disable(UINT32_MAX);
 }
 
 void Log::Initialize() {
@@ -270,9 +344,8 @@ void Log::Terminate() { DisableAllLogCha
 
 void Log::ListAllLogChannels(Stream *strm) {
   CallbackMap &callback_map = GetCallbackMap();
-  LogChannelMap &channel_map = GetChannelMap();
 
-  if (callback_map.empty() && channel_map.empty()) {
+  if (callback_map.empty() && g_channel_map->empty()) {
     strm->PutCString("No logging channels are currently registered.\n");
     return;
   }
@@ -281,17 +354,9 @@ void Log::ListAllLogChannels(Stream *str
   for (pos = callback_map.begin(); pos != end; ++pos)
     pos->second.list_categories(strm);
 
-  uint32_t idx = 0;
-  const char *name;
-  for (idx = 0;
-       (name = PluginManager::GetLogChannelCreateNameAtIndex(idx)) != nullptr;
-       ++idx) {
-    LogChannelSP log_channel_sp(LogChannel::FindPlugin(name));
-    if (log_channel_sp)
-      log_channel_sp->ListCategories(strm);
-  }
+  for (const auto &channel : *g_channel_map)
+    ListCategories(*strm, channel);
 }
-
 bool Log::GetVerbose() const { return m_options.Test(LLDB_LOG_OPTION_VERBOSE); }
 
 void Log::WriteHeader(llvm::raw_ostream &OS, llvm::StringRef file,
@@ -358,33 +423,3 @@ void Log::Format(llvm::StringRef file, l
   message << payload << "\n";
   WriteMessage(message.str());
 }
-
-LogChannelSP LogChannel::FindPlugin(const char *plugin_name) {
-  LogChannelSP log_channel_sp;
-  LogChannelMap &channel_map = GetChannelMap();
-  ConstString log_channel_name(plugin_name);
-  LogChannelMapIter pos = channel_map.find(log_channel_name);
-  if (pos == channel_map.end()) {
-    ConstString const_plugin_name(plugin_name);
-    LogChannelCreateInstance create_callback =
-        PluginManager::GetLogChannelCreateCallbackForPluginName(
-            const_plugin_name);
-    if (create_callback) {
-      log_channel_sp.reset(create_callback());
-      if (log_channel_sp) {
-        // Cache the one and only loaded instance of each log channel
-        // plug-in after it has been loaded once.
-        channel_map[log_channel_name] = log_channel_sp;
-      }
-    }
-  } else {
-    // We have already loaded an instance of this log channel class,
-    // so just return the cached instance.
-    log_channel_sp = pos->second;
-  }
-  return log_channel_sp;
-}
-
-LogChannel::LogChannel() : m_log_ap() {}
-
-LogChannel::~LogChannel() = default;

Modified: lldb/trunk/source/Core/PluginManager.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Core/PluginManager.cpp?rev=295442&r1=295441&r2=295442&view=diff
==============================================================================
--- lldb/trunk/source/Core/PluginManager.cpp (original)
+++ lldb/trunk/source/Core/PluginManager.cpp Fri Feb 17 07:27:42 2017
@@ -1167,93 +1167,6 @@ PluginManager::GetObjectContainerGetModu
   return nullptr;
 }
 
-#pragma mark LogChannel
-
-struct LogInstance {
-  LogInstance() : name(), description(), create_callback(nullptr) {}
-
-  ConstString name;
-  std::string description;
-  LogChannelCreateInstance create_callback;
-};
-
-typedef std::vector<LogInstance> LogInstances;
-
-static std::recursive_mutex &GetLogMutex() {
-  static std::recursive_mutex g_instances_mutex;
-  return g_instances_mutex;
-}
-
-static LogInstances &GetLogInstances() {
-  static LogInstances g_instances;
-  return g_instances;
-}
-
-bool PluginManager::RegisterPlugin(const ConstString &name,
-                                   const char *description,
-                                   LogChannelCreateInstance create_callback) {
-  if (create_callback) {
-    LogInstance instance;
-    assert((bool)name);
-    instance.name = name;
-    if (description && description[0])
-      instance.description = description;
-    instance.create_callback = create_callback;
-    std::lock_guard<std::recursive_mutex> gard(GetLogMutex());
-    GetLogInstances().push_back(instance);
-  }
-  return false;
-}
-
-bool PluginManager::UnregisterPlugin(LogChannelCreateInstance create_callback) {
-  if (create_callback) {
-    std::lock_guard<std::recursive_mutex> gard(GetLogMutex());
-    LogInstances &instances = GetLogInstances();
-
-    LogInstances::iterator pos, end = instances.end();
-    for (pos = instances.begin(); pos != end; ++pos) {
-      if (pos->create_callback == create_callback) {
-        instances.erase(pos);
-        return true;
-      }
-    }
-  }
-  return false;
-}
-
-const char *PluginManager::GetLogChannelCreateNameAtIndex(uint32_t idx) {
-  std::lock_guard<std::recursive_mutex> gard(GetLogMutex());
-  LogInstances &instances = GetLogInstances();
-  if (idx < instances.size())
-    return instances[idx].name.GetCString();
-  return nullptr;
-}
-
-LogChannelCreateInstance
-PluginManager::GetLogChannelCreateCallbackAtIndex(uint32_t idx) {
-  std::lock_guard<std::recursive_mutex> gard(GetLogMutex());
-  LogInstances &instances = GetLogInstances();
-  if (idx < instances.size())
-    return instances[idx].create_callback;
-  return nullptr;
-}
-
-LogChannelCreateInstance
-PluginManager::GetLogChannelCreateCallbackForPluginName(
-    const ConstString &name) {
-  if (name) {
-    std::lock_guard<std::recursive_mutex> gard(GetLogMutex());
-    LogInstances &instances = GetLogInstances();
-
-    LogInstances::iterator pos, end = instances.end();
-    for (pos = instances.begin(); pos != end; ++pos) {
-      if (name == pos->name)
-        return pos->create_callback;
-    }
-  }
-  return nullptr;
-}
-
 #pragma mark Platform
 
 struct PlatformInstance {

Modified: lldb/trunk/source/Plugins/SymbolFile/DWARF/LogChannelDWARF.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/SymbolFile/DWARF/LogChannelDWARF.cpp?rev=295442&r1=295441&r2=295442&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/SymbolFile/DWARF/LogChannelDWARF.cpp (original)
+++ lldb/trunk/source/Plugins/SymbolFile/DWARF/LogChannelDWARF.cpp Fri Feb 17 07:27:42 2017
@@ -9,192 +9,36 @@
 
 #include "LogChannelDWARF.h"
 
-#include "SymbolFileDWARF.h"
-#include "lldb/Core/PluginManager.h"
-#include "lldb/Core/StreamFile.h"
-#include "lldb/Interpreter/Args.h"
-
 using namespace lldb;
 using namespace lldb_private;
 
-// when the one and only logging channel is enabled, then this will be non NULL.
-static LogChannelDWARF *g_log_channel = NULL;
-
-LogChannelDWARF::LogChannelDWARF() : LogChannel() {}
+static constexpr Log::Category g_categories[] = {
+    {{"aranges"},
+     {"log the parsing of .debug_aranges"},
+     DWARF_LOG_DEBUG_ARANGES},
+    {{"comp"},
+     {"log insertions of object files into DWARF debug maps"},
+     DWARF_LOG_TYPE_COMPLETION},
+    {{"info"}, {"log the parsing of .debug_info"}, DWARF_LOG_DEBUG_INFO},
+    {{"line"}, {"log the parsing of .debug_line"}, DWARF_LOG_DEBUG_LINE},
+    {{"lookups"},
+     {"log any lookups that happen by name, regex, or address"},
+     DWARF_LOG_LOOKUPS},
+    {{"map"},
+     {"log struct/unions/class type completions"},
+     DWARF_LOG_DEBUG_MAP},
+    {{"pubnames"},
+     {"log the parsing of .debug_pubnames"},
+     DWARF_LOG_DEBUG_PUBNAMES},
+    {{"pubtypes"},
+     {"log the parsing of .debug_pubtypes"},
+     DWARF_LOG_DEBUG_PUBTYPES},
+};
 
-LogChannelDWARF::~LogChannelDWARF() {}
+Log::Channel LogChannelDWARF::g_channel(g_categories, DWARF_LOG_DEFAULT);
 
 void LogChannelDWARF::Initialize() {
-  PluginManager::RegisterPlugin(GetPluginNameStatic(),
-                                GetPluginDescriptionStatic(),
-                                LogChannelDWARF::CreateInstance);
-}
-
-void LogChannelDWARF::Terminate() {
-  PluginManager::UnregisterPlugin(LogChannelDWARF::CreateInstance);
-}
-
-LogChannel *LogChannelDWARF::CreateInstance() { return new LogChannelDWARF(); }
-
-lldb_private::ConstString LogChannelDWARF::GetPluginNameStatic() {
-  return SymbolFileDWARF::GetPluginNameStatic();
-}
-
-const char *LogChannelDWARF::GetPluginDescriptionStatic() {
-  return "DWARF log channel for debugging plug-in issues.";
-}
-
-lldb_private::ConstString LogChannelDWARF::GetPluginName() {
-  return GetPluginNameStatic();
-}
-
-uint32_t LogChannelDWARF::GetPluginVersion() { return 1; }
-
-void LogChannelDWARF::Delete() { g_log_channel = NULL; }
-
-void LogChannelDWARF::Disable(const char **categories, Stream *feedback_strm) {
-  if (m_log_ap.get() == NULL)
-    return;
-
-  uint32_t flag_bits = m_log_ap->GetMask().Get();
-  for (size_t i = 0; categories[i] != NULL; ++i) {
-    const char *arg = categories[i];
-
-    if (::strcasecmp(arg, "all") == 0)
-      flag_bits &= ~DWARF_LOG_ALL;
-    else if (::strcasecmp(arg, "info") == 0)
-      flag_bits &= ~DWARF_LOG_DEBUG_INFO;
-    else if (::strcasecmp(arg, "line") == 0)
-      flag_bits &= ~DWARF_LOG_DEBUG_LINE;
-    else if (::strcasecmp(arg, "pubnames") == 0)
-      flag_bits &= ~DWARF_LOG_DEBUG_PUBNAMES;
-    else if (::strcasecmp(arg, "pubtypes") == 0)
-      flag_bits &= ~DWARF_LOG_DEBUG_PUBTYPES;
-    else if (::strcasecmp(arg, "aranges") == 0)
-      flag_bits &= ~DWARF_LOG_DEBUG_ARANGES;
-    else if (::strcasecmp(arg, "lookups") == 0)
-      flag_bits &= ~DWARF_LOG_LOOKUPS;
-    else if (::strcasecmp(arg, "map") == 0)
-      flag_bits &= ~DWARF_LOG_DEBUG_MAP;
-    else if (::strcasecmp(arg, "default") == 0)
-      flag_bits &= ~DWARF_LOG_DEFAULT;
-    else if (::strncasecmp(arg, "comp", 4) == 0)
-      flag_bits &= ~DWARF_LOG_TYPE_COMPLETION;
-    else {
-      feedback_strm->Printf("error: unrecognized log category '%s'\n", arg);
-      ListCategories(feedback_strm);
-    }
-  }
-
-  if (flag_bits == 0)
-    Delete();
-  else
-    m_log_ap->GetMask().Reset(flag_bits);
-
-  return;
-}
-
-bool LogChannelDWARF::Enable(
-    const std::shared_ptr<llvm::raw_ostream> &log_stream_sp,
-    uint32_t log_options,
-    Stream *feedback_strm,  // Feedback stream for argument errors etc
-    const char **categories // The categories to enable within this logging
-                            // stream, if empty, enable default set
-    ) {
-  Delete();
-
-  if (m_log_ap)
-    m_log_ap->SetStream(log_stream_sp);
-  else
-    m_log_ap.reset(new Log(log_stream_sp));
-
-  g_log_channel = this;
-  uint32_t flag_bits = 0;
-  bool got_unknown_category = false;
-  for (size_t i = 0; categories[i] != NULL; ++i) {
-    const char *arg = categories[i];
-
-    if (::strcasecmp(arg, "all") == 0)
-      flag_bits |= DWARF_LOG_ALL;
-    else if (::strcasecmp(arg, "info") == 0)
-      flag_bits |= DWARF_LOG_DEBUG_INFO;
-    else if (::strcasecmp(arg, "line") == 0)
-      flag_bits |= DWARF_LOG_DEBUG_LINE;
-    else if (::strcasecmp(arg, "pubnames") == 0)
-      flag_bits |= DWARF_LOG_DEBUG_PUBNAMES;
-    else if (::strcasecmp(arg, "pubtypes") == 0)
-      flag_bits |= DWARF_LOG_DEBUG_PUBTYPES;
-    else if (::strcasecmp(arg, "aranges") == 0)
-      flag_bits |= DWARF_LOG_DEBUG_ARANGES;
-    else if (::strcasecmp(arg, "lookups") == 0)
-      flag_bits |= DWARF_LOG_LOOKUPS;
-    else if (::strcasecmp(arg, "map") == 0)
-      flag_bits |= DWARF_LOG_DEBUG_MAP;
-    else if (::strcasecmp(arg, "default") == 0)
-      flag_bits |= DWARF_LOG_DEFAULT;
-    else if (::strncasecmp(arg, "comp", 4) == 0)
-      flag_bits |= DWARF_LOG_TYPE_COMPLETION;
-    else {
-      feedback_strm->Printf("error: unrecognized log category '%s'\n", arg);
-      if (got_unknown_category == false) {
-        got_unknown_category = true;
-        ListCategories(feedback_strm);
-      }
-    }
-  }
-  if (flag_bits == 0)
-    flag_bits = DWARF_LOG_DEFAULT;
-  m_log_ap->GetMask().Reset(flag_bits);
-  m_log_ap->GetOptions().Reset(log_options);
-  return m_log_ap.get() != NULL;
-}
-
-void LogChannelDWARF::ListCategories(Stream *strm) {
-  strm->Printf(
-      "Logging categories for '%s':\n"
-      "  all - turn on all available logging categories\n"
-      "  info - log the parsing of .debug_info\n"
-      "  line - log the parsing of .debug_line\n"
-      "  pubnames - log the parsing of .debug_pubnames\n"
-      "  pubtypes - log the parsing of .debug_pubtypes\n"
-      "  aranges - log the parsing of .debug_aranges\n"
-      "  lookups - log any lookups that happen by name, regex, or address\n"
-      "  completion - log struct/unions/class type completions\n"
-      "  map - log insertions of object files into DWARF debug maps\n",
-      SymbolFileDWARF::GetPluginNameStatic().GetCString());
-}
-
-Log *LogChannelDWARF::GetLog() {
-  if (g_log_channel)
-    return g_log_channel->m_log_ap.get();
-
-  return NULL;
-}
-
-Log *LogChannelDWARF::GetLogIfAll(uint32_t mask) {
-  if (g_log_channel && g_log_channel->m_log_ap.get()) {
-    if (g_log_channel->m_log_ap->GetMask().AllSet(mask))
-      return g_log_channel->m_log_ap.get();
-  }
-  return NULL;
+  Log::Register("dwarf", g_channel);
 }
 
-Log *LogChannelDWARF::GetLogIfAny(uint32_t mask) {
-  if (g_log_channel && g_log_channel->m_log_ap.get()) {
-    if (g_log_channel->m_log_ap->GetMask().AnySet(mask))
-      return g_log_channel->m_log_ap.get();
-  }
-  return NULL;
-}
-
-void LogChannelDWARF::LogIf(uint32_t mask, const char *format, ...) {
-  if (g_log_channel) {
-    Log *log = g_log_channel->m_log_ap.get();
-    if (log && log->GetMask().AnySet(mask)) {
-      va_list args;
-      va_start(args, format);
-      log->VAPrintf(format, args);
-      va_end(args);
-    }
-  }
-}
+void LogChannelDWARF::Terminate() { Log::Unregister("dwarf"); }

Modified: lldb/trunk/source/Plugins/SymbolFile/DWARF/LogChannelDWARF.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/SymbolFile/DWARF/LogChannelDWARF.h?rev=295442&r1=295441&r2=295442&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/SymbolFile/DWARF/LogChannelDWARF.h (original)
+++ lldb/trunk/source/Plugins/SymbolFile/DWARF/LogChannelDWARF.h Fri Feb 17 07:27:42 2017
@@ -27,48 +27,17 @@
 #define DWARF_LOG_ALL (UINT32_MAX)
 #define DWARF_LOG_DEFAULT (DWARF_LOG_DEBUG_INFO)
 
-class LogChannelDWARF : public lldb_private::LogChannel {
-public:
-  LogChannelDWARF();
-
-  ~LogChannelDWARF() override;
+namespace lldb_private {
+class LogChannelDWARF {
+  static Log::Channel g_channel;
 
+public:
   static void Initialize();
-
   static void Terminate();
 
-  static lldb_private::ConstString GetPluginNameStatic();
-
-  static const char *GetPluginDescriptionStatic();
-
-  static lldb_private::LogChannel *CreateInstance();
-
-  lldb_private::ConstString GetPluginName() override;
-
-  uint32_t GetPluginVersion() override;
-
-  void Disable(const char **categories,
-               lldb_private::Stream *feedback_strm) override;
-
-  void Delete();
-
-  bool Enable(const std::shared_ptr<llvm::raw_ostream> &log_stream_sp,
-              uint32_t log_options,
-              lldb_private::Stream
-                  *feedback_strm, // Feedback stream for argument errors etc
-              const char **categories) override; // The categories to enable
-                                                 // within this logging stream,
-                                                 // if empty, enable default set
-
-  void ListCategories(lldb_private::Stream *strm) override;
-
-  static lldb_private::Log *GetLog();
-
-  static lldb_private::Log *GetLogIfAll(uint32_t mask);
-
-  static lldb_private::Log *GetLogIfAny(uint32_t mask);
-
-  static void LogIf(uint32_t mask, const char *format, ...);
+  static Log *GetLogIfAll(uint32_t mask) { return g_channel.GetLogIfAll(mask); }
+  static Log *GetLogIfAny(uint32_t mask) { return g_channel.GetLogIfAny(mask); }
 };
+}
 
 #endif // SymbolFileDWARF_LogChannelDWARF_h_

Modified: lldb/trunk/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp?rev=295442&r1=295441&r2=295442&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp (original)
+++ lldb/trunk/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp Fri Feb 17 07:27:42 2017
@@ -223,7 +223,7 @@ void SymbolFileDWARF::DebuggerInitialize
 
 void SymbolFileDWARF::Terminate() {
   PluginManager::UnregisterPlugin(CreateInstance);
-  LogChannelDWARF::Initialize();
+  LogChannelDWARF::Terminate();
 }
 
 lldb_private::ConstString SymbolFileDWARF::GetPluginNameStatic() {

Modified: lldb/trunk/unittests/Core/LogTest.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/unittests/Core/LogTest.cpp?rev=295442&r1=295441&r2=295442&view=diff
==============================================================================
--- lldb/trunk/unittests/Core/LogTest.cpp (original)
+++ lldb/trunk/unittests/Core/LogTest.cpp Fri Feb 17 07:27:42 2017
@@ -12,10 +12,30 @@
 #include "lldb/Core/Log.h"
 #include "lldb/Host/Host.h"
 #include "lldb/Utility/StreamString.h"
+#include "llvm/Support/ManagedStatic.h"
 
 using namespace lldb;
 using namespace lldb_private;
 
+enum { FOO = 1, BAR = 2 };
+static constexpr Log::Category test_categories[] = {
+    {"foo", "log foo", FOO}, {"bar", "log bar", BAR},
+};
+static constexpr uint32_t default_flags = FOO;
+
+static Log::Channel test_channel(test_categories, default_flags);
+
+struct LogChannelTest : public ::testing::Test {
+  static void SetUpTestCase() {
+    Log::Register("chan", test_channel);
+  }
+
+  static void TearDownTestCase() {
+    Log::Unregister("chan");
+    llvm::llvm_shutdown();
+  }
+};
+
 static std::string GetLogString(uint32_t log_options, const char *format,
                                 int arg) {
   std::string stream_string;
@@ -57,3 +77,96 @@ TEST(LogTest, log_options) {
             GetLogString(LLDB_LOG_OPTION_PREPEND_PROC_AND_THREAD,
                          "Hello World {0}", 47));
 }
+
+TEST(LogTest, Register) {
+  llvm::llvm_shutdown_obj obj;
+  Log::Register("chan", test_channel);
+  Log::Unregister("chan");
+  Log::Register("chan", test_channel);
+  Log::Unregister("chan");
+}
+
+TEST(LogTest, Unregister) {
+  llvm::llvm_shutdown_obj obj;
+  Log::Register("chan", test_channel);
+  EXPECT_EQ(nullptr, test_channel.GetLogIfAny(FOO));
+  const char *cat1[] = {"foo", nullptr};
+  std::string message;
+  std::shared_ptr<llvm::raw_string_ostream> stream_sp(
+      new llvm::raw_string_ostream(message));
+  StreamString err;
+  EXPECT_TRUE(Log::EnableLogChannel(stream_sp, 0, "chan", cat1, err));
+  EXPECT_NE(nullptr, test_channel.GetLogIfAny(FOO));
+  Log::Unregister("chan");
+  EXPECT_EQ(nullptr, test_channel.GetLogIfAny(FOO));
+}
+
+TEST_F(LogChannelTest, Enable) {
+  EXPECT_EQ(nullptr, test_channel.GetLogIfAll(FOO));
+  std::string message;
+  std::shared_ptr<llvm::raw_string_ostream> stream_sp(
+      new llvm::raw_string_ostream(message));
+  StreamString err;
+  EXPECT_FALSE(Log::EnableLogChannel(stream_sp, 0, "chanchan", nullptr, err));
+  EXPECT_EQ("Invalid log channel 'chanchan'.\n", err.GetString());
+  err.Clear();
+
+  EXPECT_TRUE(Log::EnableLogChannel(stream_sp, 0, "chan", nullptr, err));
+  EXPECT_EQ("", err.GetString());
+  EXPECT_NE(nullptr, test_channel.GetLogIfAll(FOO));
+  EXPECT_EQ(nullptr, test_channel.GetLogIfAll(BAR));
+
+  const char *cat2[] = {"bar", nullptr};
+  EXPECT_TRUE(Log::EnableLogChannel(stream_sp, 0, "chan", cat2, err));
+  EXPECT_NE(nullptr, test_channel.GetLogIfAll(FOO | BAR));
+
+  const char *cat3[] = {"baz", nullptr};
+  EXPECT_TRUE(Log::EnableLogChannel(stream_sp, 0, "chan", cat3, err));
+  EXPECT_TRUE(err.GetString().contains("unrecognized log category 'baz'"))
+      << "err: " << err.GetString().str();
+  EXPECT_NE(nullptr, test_channel.GetLogIfAll(FOO | BAR));
+}
+
+TEST_F(LogChannelTest, Disable) {
+  EXPECT_EQ(nullptr, test_channel.GetLogIfAll(FOO));
+  const char *cat12[] = {"foo", "bar", nullptr};
+  std::string message;
+  std::shared_ptr<llvm::raw_string_ostream> stream_sp(
+      new llvm::raw_string_ostream(message));
+  StreamString err;
+  EXPECT_TRUE(Log::EnableLogChannel(stream_sp, 0, "chan", cat12, err));
+  EXPECT_NE(nullptr, test_channel.GetLogIfAll(FOO | BAR));
+
+  const char *cat2[] = {"bar", nullptr};
+  EXPECT_TRUE(Log::DisableLogChannel("chan", cat2, err));
+  EXPECT_NE(nullptr, test_channel.GetLogIfAll(FOO));
+  EXPECT_EQ(nullptr, test_channel.GetLogIfAll(BAR));
+
+  const char *cat3[] = {"baz", nullptr};
+  EXPECT_TRUE(Log::DisableLogChannel("chan", cat3, err));
+  EXPECT_TRUE(err.GetString().contains("unrecognized log category 'baz'"))
+      << "err: " << err.GetString().str();
+  EXPECT_NE(nullptr, test_channel.GetLogIfAll(FOO));
+  EXPECT_EQ(nullptr, test_channel.GetLogIfAll(BAR));
+  err.Clear();
+
+  EXPECT_TRUE(Log::DisableLogChannel("chan", nullptr, err));
+  EXPECT_EQ(nullptr, test_channel.GetLogIfAny(FOO | BAR));
+}
+
+TEST_F(LogChannelTest, List) {
+  StreamString str;
+  EXPECT_TRUE(Log::ListChannelCategories("chan", str));
+  std::string expected =
+      R"(Logging categories for 'chan':
+  all - all available logging categories
+  default - default set of logging categories
+  foo - log foo
+  bar - log bar
+)";
+  EXPECT_EQ(expected, str.GetString().str());
+  str.Clear();
+
+  EXPECT_FALSE(Log::ListChannelCategories("chanchan", str));
+  EXPECT_EQ("Invalid log channel 'chanchan'.\n", str.GetString().str());
+}




More information about the lldb-commits mailing list