blob: f539caa3e5cd6645d3d3bb444d3e78067684f88b [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 Silvermanf665d692013-02-17 22:11:39 -080011
12#include <algorithm>
13
14#include "aos/common/die.h"
15#include "aos/common/logging/logging_impl.h"
Brian Silverman14fd0fb2014-01-14 21:42:01 -080016#include "aos/linux_code/ipc_lib/queue.h"
Brian Silverman78968542014-03-05 17:03:43 -080017#include "aos/common/time.h"
Brian Silvermanf665d692013-02-17 22:11:39 -080018
19namespace aos {
20namespace logging {
Brian Silverman14fd0fb2014-01-14 21:42:01 -080021namespace linux_code {
Brian Silvermanf665d692013-02-17 22:11:39 -080022namespace {
23
Brian Silverman78968542014-03-05 17:03:43 -080024RawQueue *queue = NULL;
Brian Silvermanf665d692013-02-17 22:11:39 -080025
Brian Silverman78968542014-03-05 17:03:43 -080026int dropped_messages = 0;
27::aos::time::Time dropped_start(0, 0);
28
29LogMessage *GetMessageOrDie() {
30 LogMessage *message = static_cast<LogMessage *>(queue->GetMessage());
31 if (message == NULL) {
32 LOG(FATAL, "%p->GetMessage() failed\n", queue);
33 } else {
34 return message;
35 }
36}
37
38class LinuxQueueLogImplementation : public LogImplementation {
Brian Silverman88471dc2014-02-15 22:35:42 -080039 virtual void DoLog(log_level level, const char *format, va_list ap) override {
40 LogMessage *message = GetMessageOrDie();
Brian Silvermanf665d692013-02-17 22:11:39 -080041 internal::FillInMessage(level, format, ap, message);
Brian Silverman88471dc2014-02-15 22:35:42 -080042 Write(message);
43 }
Brian Silvermanf665d692013-02-17 22:11:39 -080044
Brian Silverman88471dc2014-02-15 22:35:42 -080045 virtual void LogStruct(log_level level, const ::std::string &message_string,
46 size_t size, const MessageType *type,
47 const ::std::function<size_t(char *)> &serialize)
48 override {
49 LogMessage *message = GetMessageOrDie();
50 internal::FillInMessageStructure(level, message_string, size, type,
51 serialize, message);
Brian Silvermanf665d692013-02-17 22:11:39 -080052 Write(message);
53 }
54};
55
56} // namespace
57
58void Register() {
59 Init();
60
Brian Silvermana70144e2014-03-01 22:38:54 -080061 queue = RawQueue::Fetch("LoggingQueue", sizeof(LogMessage), 1323, 80000);
Brian Silvermanf665d692013-02-17 22:11:39 -080062 if (queue == NULL) {
63 Die("logging: couldn't fetch queue\n");
64 }
65
Brian Silverman88471dc2014-02-15 22:35:42 -080066 AddImplementation(new LinuxQueueLogImplementation());
Brian Silvermanf665d692013-02-17 22:11:39 -080067}
68
69const LogMessage *ReadNext(int flags, int *index) {
Brian Silvermana6d1b562013-09-01 14:39:39 -070070 return static_cast<const LogMessage *>(queue->ReadMessageIndex(flags, index));
Brian Silvermanf665d692013-02-17 22:11:39 -080071}
72
73const LogMessage *ReadNext() {
Brian Silverman08661c72013-09-01 17:24:38 -070074 return ReadNext(RawQueue::kBlock);
Brian Silvermanf665d692013-02-17 22:11:39 -080075}
76
77const LogMessage *ReadNext(int flags) {
78 const LogMessage *r = NULL;
79 do {
Brian Silvermana6d1b562013-09-01 14:39:39 -070080 r = static_cast<const LogMessage *>(queue->ReadMessage(flags));
Brian Silvermanf665d692013-02-17 22:11:39 -080081 // not blocking means return a NULL if that's what it gets
Brian Silverman08661c72013-09-01 17:24:38 -070082 } while ((flags & RawQueue::kBlock) && r == NULL);
Brian Silvermanf665d692013-02-17 22:11:39 -080083 return r;
84}
85
86LogMessage *Get() {
Brian Silvermana6d1b562013-09-01 14:39:39 -070087 return static_cast<LogMessage *>(queue->GetMessage());
Brian Silvermanf665d692013-02-17 22:11:39 -080088}
89
90void Free(const LogMessage *msg) {
Brian Silvermana6d1b562013-09-01 14:39:39 -070091 queue->FreeMessage(msg);
Brian Silvermanf665d692013-02-17 22:11:39 -080092}
93
94void Write(LogMessage *msg) {
Brian Silverman78968542014-03-05 17:03:43 -080095 if (__builtin_expect(dropped_messages > 0, 0)) {
96 LogMessage *dropped_message = GetMessageOrDie();
97 internal::FillInMessageVarargs(ERROR, dropped_message,
98 "%d logs starting at %f dropped\n",
99 dropped_messages, dropped_start.ToSeconds());
100 if (queue->WriteMessage(dropped_message, RawQueue::kNonBlock)) {
101 dropped_messages = 0;
102 } else {
103 // Don't even bother trying to write this message because it's not likely
104 // to work and it would be confusing to have one log in the middle of a
105 // string of failures get through.
106 ++dropped_messages;
107 return;
108 }
109 }
110 if (!queue->WriteMessage(msg, RawQueue::kNonBlock)) {
111 if (dropped_messages == 0) {
112 dropped_start = ::aos::time::Time::Now();
113 }
114 ++dropped_messages;
Brian Silvermanf665d692013-02-17 22:11:39 -0800115 }
116}
117
Brian Silverman14fd0fb2014-01-14 21:42:01 -0800118} // namespace linux_code
Brian Silvermanf665d692013-02-17 22:11:39 -0800119} // namespace logging
120} // namespace aos