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
llvm-svn: 295442
diff --git a/lldb/source/Core/Log.cpp b/lldb/source/Core/Log.cpp
index 0a98379..181dcc2 100644
--- a/lldb/source/Core/Log.cpp
+++ b/lldb/source/Core/Log.cpp
@@ -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 @@
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 @@
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::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 @@
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);
-
- 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);
+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;
}
+
+ 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 @@
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::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 @@
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 @@
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;