blob: 8ebafc08dd2877e8cce28a6e0280e8ec5e49ae64 [file] [log] [blame]
brians343bc112013-02-10 01:53:46 +00001#include <string.h>
2
3#include "WPILib/Timer.h"
4#include "WPILib/Task.h"
5
6#include "aos/aos_core.h"
7#include "aos/common/network/SendSocket.h"
8#include "aos/common/Configuration.h"
9#include "aos/common/die.h"
10
11#undef ERROR
12#define DECL_LEVEL(name, value) const log_level name = value;
13DECL_LEVELS
14#undef DECL_LEVEL
15
16//#define fprintf(...)
17
18namespace aos {
19namespace logging {
20namespace {
21
22MSG_Q_ID queue;
23uint8_t sequence = 0;
24
25// This gets run in a low-priority task to take the logs from the queue and send
26// them to the atom over a TCP socket.
27void DoTask() {
28 SendSocket sock;
29 log_crio_message msg;
30 while (true) {
31 const int ret = msgQReceive(queue, reinterpret_cast<char *>(&msg),
32 sizeof(msg), WAIT_FOREVER);
33 if (ret == ERROR) {
34 fprintf(stderr, "logging: warning: receiving a message failed"
35 " with %d (%s)", errno, strerror(errno));
36 continue;
37 }
38 if (ret != sizeof(msg)) {
39 fprintf(stderr, "logging: warning: received a message of size %d "
40 "instead of %zd\n", ret, sizeof(msg));
41 continue;
42 }
43
44 if (sock.LastStatus() != 0) {
45 if (sock.Connect(NetworkPort::kLogs,
46 configuration::GetIPAddress(
47 configuration::NetworkDevice::kAtom),
48 SOCK_STREAM) != 0) {
49 fprintf(stderr, "logging: warning: connecting failed"
50 " because of %d: %s\n", errno, strerror(errno));
51 }
52 }
53 sock.Send(&msg, sizeof(msg));
54 if (sock.LastStatus() != 0) {
55 fprintf(stderr, "logging: warning: sending '%s' failed"
56 " because of %d: %s\n", msg.message, errno, strerror(errno));
57 }
58 }
59}
60
61} // namespace
62
63void Start() {
64 queue = msgQCreate(100, // max messages
65 sizeof(log_crio_message),
66 MSG_Q_PRIORITY);
67 Task *task = new Task("LogSender",
68 (FUNCPTR)(DoTask),
69 150); // priority
70 task->Start();
71}
72
73int Do(log_level level, const char *format, ...) {
74 log_crio_message msg;
75 msg.time = Timer::GetFPGATimestamp();
76 msg.level = level;
77 msg.sequence = __sync_fetch_and_add(&sequence, 1);
78
79 const char *continued = "...";
80 const size_t size = sizeof(msg.message) - strlen(continued);
81 va_list ap;
82 va_start(ap, format);
83 const int ret = vsnprintf(msg.message, size, format, ap);
84 va_end(ap);
85
86 if (ret < 0) {
87 fprintf(stderr, "logging: error: vsnprintf failed with %d (%s)\n",
88 errno, strerror(errno));
89 return -1;
90 } else if (static_cast<uintmax_t>(ret) >= static_cast<uintmax_t>(size)) {
91 // overwrite the NULL at the end of the existing one and
92 // copy in the one on the end of continued
93 memcpy(&msg.message[size - 1], continued, strlen(continued) + 1);
94 }
95 if (msgQSend(queue, reinterpret_cast<char *>(&msg), sizeof(msg),
96 NO_WAIT, MSG_PRI_NORMAL) == ERROR) {
97 fprintf(stderr, "logging: warning: sending message '%s'"
98 " failed with %d (%s)", msg.message, errno, strerror(errno));
99 return -1;
100 }
101
102 if (level == FATAL) {
103 aos::Die("%s", msg.message);
104 }
105
106 return 0;
107}
108
109} // namespace logging
110} // namespace aos