JDevlieghere created this revision.
JDevlieghere added reviewers: labath, clayborg, mib, kastiglione.
Herald added a subscriber: mgorny.
Herald added a project: All.
JDevlieghere requested review of this revision.

This patch introduces the concept of a log handlers. Log handlers allow 
customizing the way log output is emitted. The `StreamCallback` class tried to 
do something conceptually similar. The benefit of the log handler interface is 
that you don't need to conform to llvm's raw_ostream interface.

This patch is in preparation for a new kind of a new type of log handler.


https://reviews.llvm.org/D127922

Files:
  lldb/include/lldb/Core/Debugger.h
  lldb/include/lldb/Utility/Log.h
  lldb/include/lldb/Utility/StreamCallback.h
  lldb/source/Core/Debugger.cpp
  lldb/source/Utility/CMakeLists.txt
  lldb/source/Utility/Log.cpp
  lldb/source/Utility/StreamCallback.cpp
  lldb/unittests/Core/CMakeLists.txt
  lldb/unittests/Core/StreamCallbackTest.cpp

Index: lldb/unittests/Core/StreamCallbackTest.cpp
===================================================================
--- lldb/unittests/Core/StreamCallbackTest.cpp
+++ /dev/null
@@ -1,27 +0,0 @@
-//===-- StreamCallbackTest.cpp --------------------------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "lldb/Utility/StreamCallback.h"
-#include "gtest/gtest.h"
-
-using namespace lldb;
-using namespace lldb_private;
-
-static char test_baton;
-static size_t callback_count = 0;
-static void TestCallback(const char *data, void *baton) {
-  EXPECT_STREQ("Foobar", data);
-  EXPECT_EQ(&test_baton, baton);
-  ++callback_count;
-}
-
-TEST(StreamCallbackTest, Callback) {
-  StreamCallback stream(TestCallback, &test_baton);
-  stream << "Foobar";
-  EXPECT_EQ(1u, callback_count);
-}
Index: lldb/unittests/Core/CMakeLists.txt
===================================================================
--- lldb/unittests/Core/CMakeLists.txt
+++ lldb/unittests/Core/CMakeLists.txt
@@ -8,7 +8,6 @@
   RichManglingContextTest.cpp
   SourceLocationSpecTest.cpp
   SourceManagerTest.cpp
-  StreamCallbackTest.cpp
   UniqueCStringMapTest.cpp
 
   LINK_LIBS
Index: lldb/source/Utility/StreamCallback.cpp
===================================================================
--- lldb/source/Utility/StreamCallback.cpp
+++ /dev/null
@@ -1,22 +0,0 @@
-//===-- StreamCallback.cpp ------------------------------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "lldb/Utility/StreamCallback.h"
-
-#include <string>
-
-using namespace lldb_private;
-
-StreamCallback::StreamCallback(lldb::LogOutputCallback callback, void *baton)
-    : llvm::raw_ostream(true), m_callback(callback), m_baton(baton) {}
-
-void StreamCallback::write_impl(const char *Ptr, size_t Size) {
-  m_callback(std::string(Ptr, Size).c_str(), m_baton);
-}
-
-uint64_t StreamCallback::current_pos() const { return 0; }
Index: lldb/source/Utility/Log.cpp
===================================================================
--- lldb/source/Utility/Log.cpp
+++ lldb/source/Utility/Log.cpp
@@ -84,14 +84,14 @@
   return flags;
 }
 
-void Log::Enable(const std::shared_ptr<llvm::raw_ostream> &stream_sp,
+void Log::Enable(const std::shared_ptr<LogHandler> &handler_sp,
                  uint32_t options, uint32_t flags) {
   llvm::sys::ScopedWriter lock(m_mutex);
 
   MaskType mask = m_mask.fetch_or(flags, std::memory_order_relaxed);
   if (mask | flags) {
     m_options.store(options, std::memory_order_relaxed);
-    m_stream_sp = stream_sp;
+    m_handler = handler_sp;
     m_channel.log_ptr.store(this, std::memory_order_relaxed);
   }
 }
@@ -101,7 +101,7 @@
 
   MaskType mask = m_mask.fetch_and(~flags, std::memory_order_relaxed);
   if (!(mask & ~flags)) {
-    m_stream_sp.reset();
+    m_handler.reset();
     m_channel.log_ptr.store(nullptr, std::memory_order_relaxed);
   }
 }
@@ -191,10 +191,10 @@
   g_channel_map->erase(iter);
 }
 
-bool Log::EnableLogChannel(
-    const std::shared_ptr<llvm::raw_ostream> &log_stream_sp,
-    uint32_t log_options, llvm::StringRef channel,
-    llvm::ArrayRef<const char *> categories, llvm::raw_ostream &error_stream) {
+bool Log::EnableLogChannel(const std::shared_ptr<LogHandler> &log_handler_sp,
+                           uint32_t log_options, llvm::StringRef channel,
+                           llvm::ArrayRef<const char *> categories,
+                           llvm::raw_ostream &error_stream) {
   auto iter = g_channel_map->find(channel);
   if (iter == g_channel_map->end()) {
     error_stream << llvm::formatv("Invalid log channel '{0}'.\n", channel);
@@ -203,7 +203,7 @@
   uint32_t flags = categories.empty()
                        ? iter->second.m_channel.default_flags
                        : GetFlags(error_stream, *iter, categories);
-  iter->second.Enable(log_stream_sp, log_options, flags);
+  iter->second.Enable(log_handler_sp, log_options, flags);
   return true;
 }
 
@@ -314,19 +314,19 @@
 void Log::WriteMessage(const std::string &message) {
   // Make a copy of our stream shared pointer in case someone disables our log
   // while we are logging and releases the stream
-  auto stream_sp = GetStream();
-  if (!stream_sp)
+  auto handler_sp = GetHandler();
+  if (!handler_sp)
     return;
 
   Flags options = GetOptions();
   if (options.Test(LLDB_LOG_OPTION_THREADSAFE)) {
     static std::recursive_mutex g_LogThreadedMutex;
     std::lock_guard<std::recursive_mutex> guard(g_LogThreadedMutex);
-    *stream_sp << message;
-    stream_sp->flush();
+    handler_sp->Emit(message);
+    handler_sp->Flush();
   } else {
-    *stream_sp << message;
-    stream_sp->flush();
+    handler_sp->Emit(message);
+    handler_sp->Flush();
   }
 }
 
@@ -338,3 +338,31 @@
   message << payload << "\n";
   WriteMessage(message.str());
 }
+
+StreamLogHandler::StreamLogHandler(int fd, bool should_close, bool unbuffered)
+    : m_stream(fd, should_close, unbuffered) {}
+
+void StreamLogHandler::Emit(std::string message) { m_stream << message; }
+
+void StreamLogHandler::Flush() { m_stream.flush(); }
+
+std::shared_ptr<StreamLogHandler> StreamLogHandler::Create(int fd,
+                                                           bool should_close) {
+  constexpr const bool unbuffered = true;
+  return std::make_shared<StreamLogHandler>(fd, should_close, unbuffered);
+}
+
+CallbackLogHandler::CallbackLogHandler(lldb::LogOutputCallback callback,
+                                       void *baton)
+    : m_callback(callback), m_baton(baton) {}
+
+void CallbackLogHandler::Emit(std::string message) {
+  m_callback(message.c_str(), m_baton);
+}
+
+void CallbackLogHandler::Flush() {}
+
+std::shared_ptr<CallbackLogHandler>
+CallbackLogHandler::Create(lldb::LogOutputCallback callback, void *baton) {
+  return std::make_shared<CallbackLogHandler>(callback, baton);
+}
Index: lldb/source/Utility/CMakeLists.txt
===================================================================
--- lldb/source/Utility/CMakeLists.txt
+++ lldb/source/Utility/CMakeLists.txt
@@ -56,7 +56,6 @@
   State.cpp
   Status.cpp
   Stream.cpp
-  StreamCallback.cpp
   StreamString.cpp
   StringExtractor.cpp
   StringExtractorGDBRemote.cpp
Index: lldb/source/Core/Debugger.cpp
===================================================================
--- lldb/source/Core/Debugger.cpp
+++ lldb/source/Core/Debugger.cpp
@@ -51,7 +51,6 @@
 #include "lldb/Utility/ReproducerProvider.h"
 #include "lldb/Utility/State.h"
 #include "lldb/Utility/Stream.h"
-#include "lldb/Utility/StreamCallback.h"
 #include "lldb/Utility/StreamString.h"
 
 #if defined(_WIN32)
@@ -758,8 +757,7 @@
       m_forward_listener_sp(), m_clear_once() {
   m_instance_name.SetString(llvm::formatv("debugger_{0}", GetID()).str());
   if (log_callback)
-    m_log_callback_stream_sp =
-        std::make_shared<StreamCallback>(log_callback, baton);
+    m_callback_handler_sp = CallbackLogHandler::Create(log_callback, baton);
   m_command_interpreter_up->Initialize();
   // Always add our default platform to the platform list
   PlatformSP default_platform_sp(Platform::GetHostPlatform());
@@ -1292,8 +1290,7 @@
   // For simplicity's sake, I am not going to deal with how to close down any
   // open logging streams, I just redirect everything from here on out to the
   // callback.
-  m_log_callback_stream_sp =
-      std::make_shared<StreamCallback>(log_callback, baton);
+  m_callback_handler_sp = CallbackLogHandler::Create(log_callback, baton);
 }
 
 static void PrivateReportProgress(Debugger &debugger, uint64_t progress_id,
@@ -1412,22 +1409,21 @@
                          llvm::StringRef log_file, uint32_t log_options,
                          llvm::raw_ostream &error_stream) {
   const bool should_close = true;
-  const bool unbuffered = true;
 
-  std::shared_ptr<llvm::raw_ostream> log_stream_sp;
-  if (m_log_callback_stream_sp) {
-    log_stream_sp = m_log_callback_stream_sp;
+  std::shared_ptr<LogHandler> log_handler_sp;
+  if (m_callback_handler_sp) {
+    log_handler_sp = m_callback_handler_sp;
     // For now when using the callback mode you always get thread & timestamp.
     log_options |=
         LLDB_LOG_OPTION_PREPEND_TIMESTAMP | LLDB_LOG_OPTION_PREPEND_THREAD_NAME;
   } else if (log_file.empty()) {
-    log_stream_sp = std::make_shared<llvm::raw_fd_ostream>(
-        GetOutputFile().GetDescriptor(), !should_close, unbuffered);
+    log_handler_sp = StreamLogHandler::Create(GetOutputFile().GetDescriptor(),
+                                              !should_close);
   } else {
-    auto pos = m_log_streams.find(log_file);
-    if (pos != m_log_streams.end())
-      log_stream_sp = pos->second.lock();
-    if (!log_stream_sp) {
+    auto pos = m_stream_handlers.find(log_file);
+    if (pos != m_stream_handlers.end())
+      log_handler_sp = pos->second.lock();
+    if (!log_handler_sp) {
       File::OpenOptions flags =
           File::eOpenOptionWriteOnly | File::eOpenOptionCanCreate;
       if (log_options & LLDB_LOG_OPTION_APPEND)
@@ -1442,18 +1438,18 @@
         return false;
       }
 
-      log_stream_sp = std::make_shared<llvm::raw_fd_ostream>(
-          (*file)->GetDescriptor(), should_close, unbuffered);
-      m_log_streams[log_file] = log_stream_sp;
+      log_handler_sp =
+          StreamLogHandler::Create((*file)->GetDescriptor(), should_close);
+      m_stream_handlers[log_file] = log_handler_sp;
     }
   }
-  assert(log_stream_sp);
+  assert(log_handler_sp);
 
   if (log_options == 0)
     log_options =
         LLDB_LOG_OPTION_PREPEND_THREAD_NAME | LLDB_LOG_OPTION_THREADSAFE;
 
-  return Log::EnableLogChannel(log_stream_sp, log_options, channel, categories,
+  return Log::EnableLogChannel(log_handler_sp, log_options, channel, categories,
                                error_stream);
 }
 
Index: lldb/include/lldb/Utility/StreamCallback.h
===================================================================
--- lldb/include/lldb/Utility/StreamCallback.h
+++ /dev/null
@@ -1,35 +0,0 @@
-//===-- StreamCallback.h -----------------------------------*- C++ -*-===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLDB_UTILITY_STREAMCALLBACK_H
-#define LLDB_UTILITY_STREAMCALLBACK_H
-
-#include "lldb/lldb-types.h"
-#include "llvm/Support/raw_ostream.h"
-
-#include <cstddef>
-#include <cstdint>
-
-namespace lldb_private {
-
-class StreamCallback : public llvm::raw_ostream {
-public:
-  StreamCallback(lldb::LogOutputCallback callback, void *baton);
-  ~StreamCallback() override = default;
-
-private:
-  lldb::LogOutputCallback m_callback;
-  void *m_baton;
-
-  void write_impl(const char *Ptr, size_t Size) override;
-  uint64_t current_pos() const override;
-};
-
-} // namespace lldb_private
-
-#endif // LLDB_UTILITY_STREAMCALLBACK_H
Index: lldb/include/lldb/Utility/Log.h
===================================================================
--- lldb/include/lldb/Utility/Log.h
+++ lldb/include/lldb/Utility/Log.h
@@ -45,6 +45,41 @@
 // Logging Functions
 namespace lldb_private {
 
+class LogHandler {
+public:
+  virtual ~LogHandler() = default;
+  virtual void Emit(std::string message) = 0;
+  virtual void Flush() = 0;
+};
+
+class StreamLogHandler : public LogHandler {
+public:
+  StreamLogHandler(int fd, bool should_close, bool unbuffered);
+
+  void Emit(std::string message) override;
+  void Flush() override;
+
+  static std::shared_ptr<StreamLogHandler> Create(int fd, bool unbuffered);
+
+private:
+  llvm::raw_fd_ostream m_stream;
+};
+
+class CallbackLogHandler : public LogHandler {
+public:
+  CallbackLogHandler(lldb::LogOutputCallback callback, void *baton);
+
+  void Emit(std::string message) override;
+  void Flush() override;
+
+  static std::shared_ptr<CallbackLogHandler>
+  Create(lldb::LogOutputCallback callback, void *baton);
+
+private:
+  lldb::LogOutputCallback m_callback;
+  void *m_baton;
+};
+
 class Log final {
 public:
   /// The underlying type of all log channel enums. Declare them as:
@@ -111,7 +146,7 @@
   static void Unregister(llvm::StringRef name);
 
   static bool
-  EnableLogChannel(const std::shared_ptr<llvm::raw_ostream> &log_stream_sp,
+  EnableLogChannel(const std::shared_ptr<LogHandler> &log_handler_sp,
                    uint32_t log_options, llvm::StringRef channel,
                    llvm::ArrayRef<const char *> categories,
                    llvm::raw_ostream &error_stream);
@@ -188,7 +223,7 @@
   // Their modification however, is still protected by this mutex.
   llvm::sys::RWMutex m_mutex;
 
-  std::shared_ptr<llvm::raw_ostream> m_stream_sp;
+  std::shared_ptr<LogHandler> m_handler;
   std::atomic<uint32_t> m_options{0};
   std::atomic<MaskType> m_mask{0};
 
@@ -199,13 +234,13 @@
   void Format(llvm::StringRef file, llvm::StringRef function,
               const llvm::formatv_object_base &payload);
 
-  std::shared_ptr<llvm::raw_ostream> GetStream() {
+  std::shared_ptr<LogHandler> GetHandler() {
     llvm::sys::ScopedReader lock(m_mutex);
-    return m_stream_sp;
+    return m_handler;
   }
 
-  void Enable(const std::shared_ptr<llvm::raw_ostream> &stream_sp,
-              uint32_t options, uint32_t flags);
+  void Enable(const std::shared_ptr<LogHandler> &handler_sp, uint32_t options,
+              uint32_t flags);
 
   void Disable(uint32_t flags);
 
Index: lldb/include/lldb/Core/Debugger.h
===================================================================
--- lldb/include/lldb/Core/Debugger.h
+++ lldb/include/lldb/Core/Debugger.h
@@ -53,6 +53,8 @@
 }
 
 namespace lldb_private {
+class LogHandler;
+class CallbackLogHandler;
 class Address;
 class CommandInterpreter;
 class Process;
@@ -553,8 +555,8 @@
 
   llvm::Optional<uint64_t> m_current_event_id;
 
-  llvm::StringMap<std::weak_ptr<llvm::raw_ostream>> m_log_streams;
-  std::shared_ptr<llvm::raw_ostream> m_log_callback_stream_sp;
+  llvm::StringMap<std::weak_ptr<LogHandler>> m_stream_handlers;
+  std::shared_ptr<CallbackLogHandler> m_callback_handler_sp;
   ConstString m_instance_name;
   static LoadPluginCallbackType g_load_plugin_callback;
   typedef std::vector<llvm::sys::DynamicLibrary> LoadedPluginsList;
_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to