Removed Common
Change-Id: I01ea8f07220375c2ad9bc0092281d4f27c642303
diff --git a/aos/logging/implementations.h b/aos/logging/implementations.h
new file mode 100644
index 0000000..69a805b
--- /dev/null
+++ b/aos/logging/implementations.h
@@ -0,0 +1,215 @@
+#ifndef AOS_LOGGING_IMPLEMENTATIONS_H_
+#define AOS_LOGGING_IMPLEMENTATIONS_H_
+
+#include <sys/types.h>
+#include <unistd.h>
+#include <stdint.h>
+#include <limits.h>
+#include <string.h>
+#include <stdio.h>
+#include <stdarg.h>
+
+#include <string>
+#include <functional>
+#include <atomic>
+
+#include "aos/logging/context.h"
+#include "aos/logging/interface.h"
+#include "aos/logging/logging.h"
+#include "aos/logging/sizes.h"
+#include "aos/macros.h"
+#include "aos/mutex/mutex.h"
+#include "aos/type_traits/type_traits.h"
+#include "aos/once.h"
+
+namespace aos {
+
+struct MessageType;
+class RawQueue;
+
+} // namespace aos
+
+// This file has various concrete LogImplementations.
+
+namespace aos {
+namespace logging {
+
+// Unless explicitly stated otherwise, format must always be a string constant,
+// args are printf-style arguments for format, and ap is a va_list of args.
+// The validity of format and args together will be checked at compile time
+// using a function attribute.
+
+// Contains all of the information about a given logging call.
+struct LogMessage {
+ enum class Type : uint8_t {
+ kString, kStruct, kMatrix
+ };
+
+ int32_t seconds, nseconds;
+ // message_length is just the length of the actual data (which member depends
+ // on the type).
+ size_t message_length, name_length;
+ pid_t source;
+ static_assert(sizeof(source) == 4, "that's how they get printed");
+ // Per task/thread.
+ uint16_t sequence;
+ Type type;
+ log_level level;
+ char name[LOG_MESSAGE_NAME_LEN];
+ union {
+ char message[LOG_MESSAGE_LEN];
+ struct {
+ uint32_t type_id;
+ size_t string_length;
+ // The message string and then the serialized structure.
+ char serialized[LOG_MESSAGE_LEN - sizeof(type) - sizeof(string_length)];
+ } structure;
+ struct {
+ // The type ID of the element type.
+ uint32_t type;
+ int rows, cols;
+ size_t string_length;
+ // The message string and then the serialized matrix.
+ char
+ data[LOG_MESSAGE_LEN - sizeof(type) - sizeof(rows) - sizeof(cols)];
+ } matrix;
+ };
+};
+static_assert(shm_ok<LogMessage>::value, "it's going in a queue");
+
+// Returns left > right. LOG_UNKNOWN is most important.
+static inline bool log_gt_important(log_level left, log_level right) {
+ if (left == ERROR) left = 3;
+ if (right == ERROR) right = 3;
+ return left > right;
+}
+
+// Returns a string representing level or "unknown".
+static inline const char *log_str(log_level level) {
+#define DECL_LEVEL(name, value) if (level == name) return #name;
+ DECL_LEVELS;
+#undef DECL_LEVEL
+ return "unknown";
+}
+// Returns the log level represented by str or LOG_UNKNOWN.
+static inline log_level str_log(const char *str) {
+#define DECL_LEVEL(name, value) if (!strcmp(str, #name)) return name;
+ DECL_LEVELS;
+#undef DECL_LEVEL
+ return LOG_UNKNOWN;
+}
+
+// A LogImplementation where LogStruct and LogMatrix just create a string with
+// PrintMessage and then forward on to DoLog.
+class SimpleLogImplementation : public LogImplementation {
+ private:
+ void LogStruct(log_level level, const ::std::string &message, size_t size,
+ const MessageType *type,
+ const ::std::function<size_t(char *)> &serialize) override;
+ void LogMatrix(log_level level, const ::std::string &message,
+ uint32_t type_id, int rows, int cols,
+ const void *data) override;
+};
+
+// Implements all of the DoLog* methods in terms of a (pure virtual in this
+// class) HandleMessage method that takes a pointer to the message.
+class HandleMessageLogImplementation : public LogImplementation {
+ private:
+ __attribute__((format(GOOD_PRINTF_FORMAT_TYPE, 3, 0)))
+ void DoLog(log_level level, const char *format, va_list ap) override;
+ void LogStruct(log_level level, const ::std::string &message_string,
+ size_t size, const MessageType *type,
+ const ::std::function<size_t(char *)> &serialize) override;
+ void LogMatrix(log_level level, const ::std::string &message_string,
+ uint32_t type_id, int rows, int cols,
+ const void *data) override;
+
+ virtual void HandleMessage(const LogMessage &message) = 0;
+};
+
+// A log implementation that dumps all messages to a C stdio stream.
+class StreamLogImplementation : public HandleMessageLogImplementation {
+ public:
+ StreamLogImplementation(FILE *stream);
+
+ private:
+ void HandleMessage(const LogMessage &message) override;
+
+ FILE *const stream_;
+};
+
+// Adds another implementation to the stack of implementations in this
+// task/thread.
+// Any tasks/threads created after this call will also use this implementation.
+// The cutoff is when the state in a given task/thread is created (either lazily
+// when needed or by calling Load()).
+// The logging system takes ownership of implementation. It will delete it if
+// necessary, so it must be created with new.
+void AddImplementation(LogImplementation *implementation);
+
+// Must be called at least once per process/load before anything else is
+// called. This function is safe to call multiple times from multiple
+// tasks/threads.
+void Init();
+
+// Forces all of the state that is usually lazily created when first needed to
+// be created when called. Cleanup() will delete it.
+void Load();
+
+// Resets all information in this task/thread to its initial state.
+// NOTE: This is not the opposite of Init(). The state that this deletes is
+// lazily created when needed. It is actually the opposite of Load().
+void Cleanup();
+
+// Returns a queue which deals with LogMessage-sized messages.
+// The caller takes ownership.
+RawQueue *GetLoggingQueue();
+
+// Calls AddImplementation to register the standard linux logging implementation
+// which sends the messages through a queue. This implementation relies on
+// another process(es) to read the log messages that it puts into the queue.
+// This function is usually called by aos::Init*.
+void RegisterQueueImplementation();
+
+// This is where all of the code that is only used by actual LogImplementations
+// goes.
+namespace internal {
+
+// Fills in all the parts of message according to the given inputs (with type
+// kStruct).
+void FillInMessageStructure(log_level level,
+ const ::std::string &message_string, size_t size,
+ const MessageType *type,
+ const ::std::function<size_t(char *)> &serialize,
+ LogMessage *message);
+
+// Fills in all the parts of the message according to the given inputs (with
+// type kMatrix).
+void FillInMessageMatrix(log_level level,
+ const ::std::string &message_string, uint32_t type_id,
+ int rows, int cols, const void *data,
+ LogMessage *message);
+
+// Fills in *message according to the given inputs (with type kString).
+// Used for implementing LogImplementation::DoLog.
+void FillInMessage(log_level level, const char *format, va_list ap,
+ LogMessage *message)
+ __attribute__((format(GOOD_PRINTF_FORMAT_TYPE, 2, 0)));
+
+__attribute__((format(GOOD_PRINTF_FORMAT_TYPE, 3, 4)))
+static inline void FillInMessageVarargs(log_level level, LogMessage *message,
+ const char *format, ...) {
+ va_list ap;
+ va_start(ap, format);
+ FillInMessage(level, format, ap, message);
+ va_end(ap);
+}
+
+// Prints message to output.
+void PrintMessage(FILE *output, const LogMessage &message);
+
+} // namespace internal
+} // namespace logging
+} // namespace aos
+
+#endif // AOS_LOGGING_IMPLEMENTATIONS_H_