blob: dc322ed60363679377a567f1706226792942a847 [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 }
55};
56
57} // namespace
58
59void Register() {
60 Init();
61
Brian Silvermana70144e2014-03-01 22:38:54 -080062 queue = RawQueue::Fetch("LoggingQueue", sizeof(LogMessage), 1323, 80000);
Brian Silvermanf665d692013-02-17 22:11:39 -080063 if (queue == NULL) {
64 Die("logging: couldn't fetch queue\n");
65 }
66
Brian Silverman88471dc2014-02-15 22:35:42 -080067 AddImplementation(new LinuxQueueLogImplementation());
Brian Silvermanf665d692013-02-17 22:11:39 -080068}
69
70const LogMessage *ReadNext(int flags, int *index) {
Brian Silvermana6d1b562013-09-01 14:39:39 -070071 return static_cast<const LogMessage *>(queue->ReadMessageIndex(flags, index));
Brian Silvermanf665d692013-02-17 22:11:39 -080072}
73
74const LogMessage *ReadNext() {
Brian Silverman08661c72013-09-01 17:24:38 -070075 return ReadNext(RawQueue::kBlock);
Brian Silvermanf665d692013-02-17 22:11:39 -080076}
77
78const LogMessage *ReadNext(int flags) {
79 const LogMessage *r = NULL;
80 do {
Brian Silvermana6d1b562013-09-01 14:39:39 -070081 r = static_cast<const LogMessage *>(queue->ReadMessage(flags));
Brian Silvermanf665d692013-02-17 22:11:39 -080082 // not blocking means return a NULL if that's what it gets
Brian Silverman08661c72013-09-01 17:24:38 -070083 } while ((flags & RawQueue::kBlock) && r == NULL);
Brian Silvermanf665d692013-02-17 22:11:39 -080084 return r;
85}
86
87LogMessage *Get() {
Brian Silvermana6d1b562013-09-01 14:39:39 -070088 return static_cast<LogMessage *>(queue->GetMessage());
Brian Silvermanf665d692013-02-17 22:11:39 -080089}
90
91void Free(const LogMessage *msg) {
Brian Silvermana6d1b562013-09-01 14:39:39 -070092 queue->FreeMessage(msg);
Brian Silvermanf665d692013-02-17 22:11:39 -080093}
94
95void Write(LogMessage *msg) {
Brian Silverman78968542014-03-05 17:03:43 -080096 if (__builtin_expect(dropped_messages > 0, 0)) {
97 LogMessage *dropped_message = GetMessageOrDie();
Brian Silvermana33af742014-03-08 12:44:12 -080098 internal::FillInMessageVarargs(
99 ERROR, dropped_message,
100 "%d logs starting at %" PRId32 ".%" PRId32 " dropped\n",
101 dropped_messages, dropped_start_seconds, dropped_start_nseconds);
Brian Silverman78968542014-03-05 17:03:43 -0800102 if (queue->WriteMessage(dropped_message, RawQueue::kNonBlock)) {
103 dropped_messages = 0;
Brian Silvermana33af742014-03-08 12:44:12 -0800104 internal::PrintMessage(stderr, *dropped_message);
Brian Silverman78968542014-03-05 17:03:43 -0800105 } else {
106 // Don't even bother trying to write this message because it's not likely
107 // to work and it would be confusing to have one log in the middle of a
108 // string of failures get through.
109 ++dropped_messages;
Brian Silvermana33af742014-03-08 12:44:12 -0800110 queue->FreeMessage(msg);
Brian Silverman78968542014-03-05 17:03:43 -0800111 return;
112 }
113 }
114 if (!queue->WriteMessage(msg, RawQueue::kNonBlock)) {
115 if (dropped_messages == 0) {
Brian Silvermana33af742014-03-08 12:44:12 -0800116 dropped_start_seconds = msg->seconds;
117 dropped_start_nseconds = msg->nseconds;
Brian Silverman78968542014-03-05 17:03:43 -0800118 }
119 ++dropped_messages;
Brian Silvermanf665d692013-02-17 22:11:39 -0800120 }
121}
122
Brian Silverman14fd0fb2014-01-14 21:42:01 -0800123} // namespace linux_code
Brian Silvermanf665d692013-02-17 22:11:39 -0800124} // namespace logging
125} // namespace aos