blob: 2bd5bcefa3d7a553e72575ec4486ccc4024d90ec [file] [log] [blame]
Brian Silverman14fd0fb2014-01-14 21:42:01 -08001#include "aos/linux_code/logging/linux_logging.h"
Brian Silvermanf665d692013-02-17 22:11:39 -08002
3#include <stdarg.h>
4#include <stdio.h>
5#include <string.h>
6#include <time.h>
7#include <sys/types.h>
8#include <errno.h>
9#include <unistd.h>
10#include <limits.h>
Brian Silvermana33af742014-03-08 12:44:12 -080011#include <inttypes.h>
Brian Silvermanf665d692013-02-17 22:11:39 -080012
13#include <algorithm>
14
15#include "aos/common/die.h"
16#include "aos/common/logging/logging_impl.h"
Brian Silverman14fd0fb2014-01-14 21:42:01 -080017#include "aos/linux_code/ipc_lib/queue.h"
Brian Silverman78968542014-03-05 17:03:43 -080018#include "aos/common/time.h"
Brian Silvermanf665d692013-02-17 22:11:39 -080019
20namespace aos {
21namespace logging {
Brian Silverman14fd0fb2014-01-14 21:42:01 -080022namespace linux_code {
Brian Silvermanf665d692013-02-17 22:11:39 -080023namespace {
24
Brian Silverman78968542014-03-05 17:03:43 -080025RawQueue *queue = NULL;
Brian Silvermanf665d692013-02-17 22:11:39 -080026
Brian Silverman78968542014-03-05 17:03:43 -080027int dropped_messages = 0;
Brian Silvermana33af742014-03-08 12:44:12 -080028int32_t dropped_start_seconds, dropped_start_nseconds;
Brian Silverman78968542014-03-05 17:03:43 -080029
30LogMessage *GetMessageOrDie() {
31 LogMessage *message = static_cast<LogMessage *>(queue->GetMessage());
32 if (message == NULL) {
33 LOG(FATAL, "%p->GetMessage() failed\n", queue);
34 } else {
35 return message;
36 }
37}
38
39class LinuxQueueLogImplementation : public LogImplementation {
Brian Silvermanf7986142014-04-21 17:42:35 -070040 __attribute__((format(GOOD_PRINTF_FORMAT_TYPE, 3, 0)))
Brian Silverman88471dc2014-02-15 22:35:42 -080041 virtual void DoLog(log_level level, const char *format, va_list ap) override {
42 LogMessage *message = GetMessageOrDie();
Brian Silvermanf665d692013-02-17 22:11:39 -080043 internal::FillInMessage(level, format, ap, message);
Brian Silverman88471dc2014-02-15 22:35:42 -080044 Write(message);
45 }
Brian Silvermanf665d692013-02-17 22:11:39 -080046
Brian Silverman88471dc2014-02-15 22:35:42 -080047 virtual void LogStruct(log_level level, const ::std::string &message_string,
48 size_t size, const MessageType *type,
49 const ::std::function<size_t(char *)> &serialize)
50 override {
51 LogMessage *message = GetMessageOrDie();
52 internal::FillInMessageStructure(level, message_string, size, type,
53 serialize, message);
Brian Silvermanf665d692013-02-17 22:11:39 -080054 Write(message);
55 }
Brian Silverman664db1a2014-03-20 17:06:29 -070056
57 virtual void LogMatrix(log_level level, const ::std::string &message_string,
58 uint32_t type_id, int rows, int cols, const void *data)
59 override {
60 LogMessage *message = GetMessageOrDie();
61 internal::FillInMessageMatrix(level, message_string, type_id, rows, cols,
62 data, message);
63 Write(message);
64 }
Brian Silvermanf665d692013-02-17 22:11:39 -080065};
66
67} // namespace
68
69void Register() {
70 Init();
71
Brian Silvermana70144e2014-03-01 22:38:54 -080072 queue = RawQueue::Fetch("LoggingQueue", sizeof(LogMessage), 1323, 80000);
Brian Silvermanf665d692013-02-17 22:11:39 -080073 if (queue == NULL) {
74 Die("logging: couldn't fetch queue\n");
75 }
76
Brian Silverman88471dc2014-02-15 22:35:42 -080077 AddImplementation(new LinuxQueueLogImplementation());
Brian Silvermanf665d692013-02-17 22:11:39 -080078}
79
Brian Silverman7faaec72014-05-26 16:25:38 -070080const LogMessage *ReadNext(Options<RawQueue> flags, int *index) {
Brian Silvermana6d1b562013-09-01 14:39:39 -070081 return static_cast<const LogMessage *>(queue->ReadMessageIndex(flags, index));
Brian Silvermanf665d692013-02-17 22:11:39 -080082}
83
84const LogMessage *ReadNext() {
Brian Silverman08661c72013-09-01 17:24:38 -070085 return ReadNext(RawQueue::kBlock);
Brian Silvermanf665d692013-02-17 22:11:39 -080086}
87
Brian Silverman7faaec72014-05-26 16:25:38 -070088const LogMessage *ReadNext(Options<RawQueue> flags) {
Brian Silvermanf665d692013-02-17 22:11:39 -080089 const LogMessage *r = NULL;
90 do {
Brian Silvermana6d1b562013-09-01 14:39:39 -070091 r = static_cast<const LogMessage *>(queue->ReadMessage(flags));
Brian Silvermanf665d692013-02-17 22:11:39 -080092 // not blocking means return a NULL if that's what it gets
Brian Silverman08661c72013-09-01 17:24:38 -070093 } while ((flags & RawQueue::kBlock) && r == NULL);
Brian Silvermanf665d692013-02-17 22:11:39 -080094 return r;
95}
96
97LogMessage *Get() {
Brian Silvermana6d1b562013-09-01 14:39:39 -070098 return static_cast<LogMessage *>(queue->GetMessage());
Brian Silvermanf665d692013-02-17 22:11:39 -080099}
100
101void Free(const LogMessage *msg) {
Brian Silvermana6d1b562013-09-01 14:39:39 -0700102 queue->FreeMessage(msg);
Brian Silvermanf665d692013-02-17 22:11:39 -0800103}
104
105void Write(LogMessage *msg) {
Brian Silverman78968542014-03-05 17:03:43 -0800106 if (__builtin_expect(dropped_messages > 0, 0)) {
107 LogMessage *dropped_message = GetMessageOrDie();
Brian Silvermana33af742014-03-08 12:44:12 -0800108 internal::FillInMessageVarargs(
109 ERROR, dropped_message,
110 "%d logs starting at %" PRId32 ".%" PRId32 " dropped\n",
111 dropped_messages, dropped_start_seconds, dropped_start_nseconds);
Brian Silverman78968542014-03-05 17:03:43 -0800112 if (queue->WriteMessage(dropped_message, RawQueue::kNonBlock)) {
113 dropped_messages = 0;
114 } else {
115 // Don't even bother trying to write this message because it's not likely
116 // to work and it would be confusing to have one log in the middle of a
117 // string of failures get through.
118 ++dropped_messages;
Brian Silvermana33af742014-03-08 12:44:12 -0800119 queue->FreeMessage(msg);
Brian Silverman78968542014-03-05 17:03:43 -0800120 return;
121 }
122 }
123 if (!queue->WriteMessage(msg, RawQueue::kNonBlock)) {
124 if (dropped_messages == 0) {
Brian Silvermana33af742014-03-08 12:44:12 -0800125 dropped_start_seconds = msg->seconds;
126 dropped_start_nseconds = msg->nseconds;
Brian Silverman78968542014-03-05 17:03:43 -0800127 }
128 ++dropped_messages;
Brian Silvermanf665d692013-02-17 22:11:39 -0800129 }
130}
131
Brian Silverman14fd0fb2014-01-14 21:42:01 -0800132} // namespace linux_code
Brian Silvermanf665d692013-02-17 22:11:39 -0800133} // namespace logging
134} // namespace aos