blob: aed86974e49c6332651f6ddc08a618c9b1eac9e3 [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 Silverman88471dc2014-02-15 22:35:42 -080040 virtual void DoLog(log_level level, const char *format, va_list ap) override {
41 LogMessage *message = GetMessageOrDie();
Brian Silvermanf665d692013-02-17 22:11:39 -080042 internal::FillInMessage(level, format, ap, message);
Brian Silverman88471dc2014-02-15 22:35:42 -080043 Write(message);
44 }
Brian Silvermanf665d692013-02-17 22:11:39 -080045
Brian Silverman88471dc2014-02-15 22:35:42 -080046 virtual void LogStruct(log_level level, const ::std::string &message_string,
47 size_t size, const MessageType *type,
48 const ::std::function<size_t(char *)> &serialize)
49 override {
50 LogMessage *message = GetMessageOrDie();
51 internal::FillInMessageStructure(level, message_string, size, type,
52 serialize, message);
Brian Silvermanf665d692013-02-17 22:11:39 -080053 Write(message);
54 }
Brian Silverman664db1a2014-03-20 17:06:29 -070055
56 virtual void LogMatrix(log_level level, const ::std::string &message_string,
57 uint32_t type_id, int rows, int cols, const void *data)
58 override {
59 LogMessage *message = GetMessageOrDie();
60 internal::FillInMessageMatrix(level, message_string, type_id, rows, cols,
61 data, message);
62 Write(message);
63 }
Brian Silvermanf665d692013-02-17 22:11:39 -080064};
65
66} // namespace
67
68void Register() {
69 Init();
70
Brian Silvermana70144e2014-03-01 22:38:54 -080071 queue = RawQueue::Fetch("LoggingQueue", sizeof(LogMessage), 1323, 80000);
Brian Silvermanf665d692013-02-17 22:11:39 -080072 if (queue == NULL) {
73 Die("logging: couldn't fetch queue\n");
74 }
75
Brian Silverman88471dc2014-02-15 22:35:42 -080076 AddImplementation(new LinuxQueueLogImplementation());
Brian Silvermanf665d692013-02-17 22:11:39 -080077}
78
79const LogMessage *ReadNext(int flags, int *index) {
Brian Silvermana6d1b562013-09-01 14:39:39 -070080 return static_cast<const LogMessage *>(queue->ReadMessageIndex(flags, index));
Brian Silvermanf665d692013-02-17 22:11:39 -080081}
82
83const LogMessage *ReadNext() {
Brian Silverman08661c72013-09-01 17:24:38 -070084 return ReadNext(RawQueue::kBlock);
Brian Silvermanf665d692013-02-17 22:11:39 -080085}
86
87const LogMessage *ReadNext(int flags) {
88 const LogMessage *r = NULL;
89 do {
Brian Silvermana6d1b562013-09-01 14:39:39 -070090 r = static_cast<const LogMessage *>(queue->ReadMessage(flags));
Brian Silvermanf665d692013-02-17 22:11:39 -080091 // not blocking means return a NULL if that's what it gets
Brian Silverman08661c72013-09-01 17:24:38 -070092 } while ((flags & RawQueue::kBlock) && r == NULL);
Brian Silvermanf665d692013-02-17 22:11:39 -080093 return r;
94}
95
96LogMessage *Get() {
Brian Silvermana6d1b562013-09-01 14:39:39 -070097 return static_cast<LogMessage *>(queue->GetMessage());
Brian Silvermanf665d692013-02-17 22:11:39 -080098}
99
100void Free(const LogMessage *msg) {
Brian Silvermana6d1b562013-09-01 14:39:39 -0700101 queue->FreeMessage(msg);
Brian Silvermanf665d692013-02-17 22:11:39 -0800102}
103
104void Write(LogMessage *msg) {
Brian Silverman78968542014-03-05 17:03:43 -0800105 if (__builtin_expect(dropped_messages > 0, 0)) {
106 LogMessage *dropped_message = GetMessageOrDie();
Brian Silvermana33af742014-03-08 12:44:12 -0800107 internal::FillInMessageVarargs(
108 ERROR, dropped_message,
109 "%d logs starting at %" PRId32 ".%" PRId32 " dropped\n",
110 dropped_messages, dropped_start_seconds, dropped_start_nseconds);
Brian Silverman78968542014-03-05 17:03:43 -0800111 if (queue->WriteMessage(dropped_message, RawQueue::kNonBlock)) {
112 dropped_messages = 0;
Brian Silvermana33af742014-03-08 12:44:12 -0800113 internal::PrintMessage(stderr, *dropped_message);
Brian Silverman78968542014-03-05 17:03:43 -0800114 } 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