blob: 5b1dc38c4c665e26433e14de7dda013c3a473deb [file] [log] [blame]
Austin Schuhf2a50ba2016-12-24 16:16:26 -08001#include <dirent.h>
2#include <errno.h>
3#include <fcntl.h>
4#include <mntent.h>
5#include <pwd.h>
brians343bc112013-02-10 01:53:46 +00006#include <stdio.h>
7#include <stdlib.h>
brians343bc112013-02-10 01:53:46 +00008#include <string.h>
brians343bc112013-02-10 01:53:46 +00009#include <sys/types.h>
Austin Schuhf2a50ba2016-12-24 16:16:26 -080010#include <time.h>
11#include <unistd.h>
12#include <string>
brians343bc112013-02-10 01:53:46 +000013
Austin Schuhf2a50ba2016-12-24 16:16:26 -080014#include <chrono>
brians343bc112013-02-10 01:53:46 +000015#include <map>
Brian Silverman88471dc2014-02-15 22:35:42 -080016#include <unordered_set>
brians343bc112013-02-10 01:53:46 +000017
John Park33858a32018-09-28 23:05:48 -070018#include "aos/die.h"
19#include "aos/logging/binary_log_file.h"
20#include "aos/logging/implementations.h"
John Park33858a32018-09-28 23:05:48 -070021#include "aos/time/time.h"
John Park398c74a2018-10-20 21:17:39 -070022#include "aos/configuration.h"
23#include "aos/init.h"
24#include "aos/ipc_lib/queue.h"
brians343bc112013-02-10 01:53:46 +000025
Brian Silvermanf665d692013-02-17 22:11:39 -080026namespace aos {
27namespace logging {
Brian Silverman14fd0fb2014-01-14 21:42:01 -080028namespace linux_code {
Brian Silvermanf665d692013-02-17 22:11:39 -080029namespace {
brians343bc112013-02-10 01:53:46 +000030
Ben Fredricksona04c1752014-03-02 22:54:07 +000031void AllocateLogName(char **filename, const char *directory) {
32 int fileindex = 0;
Brian Silverman2adb1452014-05-13 08:43:38 -070033 DIR *const d = opendir(directory);
34 if (d == nullptr) {
35 PDie("could not open directory %s", directory);
36 }
37 int index = 0;
38 while (true) {
39 errno = 0;
40 struct dirent *const dir = readdir(d);
41 if (dir == nullptr) {
42 if (errno == 0) {
43 break;
44 } else {
Austin Schuhf257f3c2019-10-27 21:00:43 -070045 AOS_PLOG(FATAL, "readdir(%p) failed", d);
Brian Silverman2adb1452014-05-13 08:43:38 -070046 }
47 } else {
Ben Fredricksona04c1752014-03-02 22:54:07 +000048 if (sscanf(dir->d_name, "aos_log-%d", &index) == 1) {
49 if (index >= fileindex) {
50 fileindex = index + 1;
51 }
52 }
53 }
Ben Fredricksona04c1752014-03-02 22:54:07 +000054 }
Brian Silverman2adb1452014-05-13 08:43:38 -070055 closedir(d);
Ben Fredricksona04c1752014-03-02 22:54:07 +000056
57 char previous[512];
Brian Silvermanf574e732014-03-02 17:35:04 -080058 ::std::string path = ::std::string(directory) + "/aos_log-current";
59 ssize_t len = ::readlink(path.c_str(), previous, sizeof(previous));
Ben Fredricksona04c1752014-03-02 22:54:07 +000060 if (len != -1) {
61 previous[len] = '\0';
62 } else {
Brian Silvermanf574e732014-03-02 17:35:04 -080063 previous[0] = '\0';
Austin Schuhf257f3c2019-10-27 21:00:43 -070064 AOS_LOG(INFO, "Could not find aos_log-current\n");
Brian Silvermanf574e732014-03-02 17:35:04 -080065 printf("Could not find aos_log-current\n");
Ben Fredricksona04c1752014-03-02 22:54:07 +000066 }
Brian Silverman09e85ed2014-03-15 08:26:29 -070067 if (asprintf(filename, "%s/aos_log-%03d", directory, fileindex) == -1) {
Brian Silverman01be0002014-05-10 15:44:38 -070068 PDie("couldn't create final name");
Ben Fredricksona04c1752014-03-02 22:54:07 +000069 }
Austin Schuhf257f3c2019-10-27 21:00:43 -070070 AOS_LOG(INFO,
71 "Created log file (aos_log-%d) in directory (%s). Previous file "
72 "was (%s).\n",
73 fileindex, directory, previous);
Brian Silvermanf574e732014-03-02 17:35:04 -080074 printf("Created log file (aos_log-%d) in directory (%s). Previous file was "
75 "(%s).\n",
76 fileindex, directory, previous);
Ben Fredricksona04c1752014-03-02 22:54:07 +000077}
78
Brian Silverman9f330492015-03-01 17:37:02 -050079#ifdef AOS_ARCHITECTURE_arm_frc
Austin Schuhc5982cb2014-10-25 18:04:36 -070080bool FoundThumbDrive(const char *path) {
81 FILE *mnt_fp = setmntent("/etc/mtab", "r");
82 if (mnt_fp == nullptr) {
83 Die("Could not open /etc/mtab");
84 }
85
86 bool found = false;
87 struct mntent mntbuf;
88 char buf[256];
89 while (!found) {
90 struct mntent *mount_list = getmntent_r(mnt_fp, &mntbuf, buf, sizeof(buf));
91 if (mount_list == nullptr) {
92 break;
93 }
94 if (strcmp(mount_list->mnt_dir, path) == 0) {
95 found = true;
96 }
97 }
98 endmntent(mnt_fp);
99 return found;
100}
101
102bool FindDevice(char *device, size_t device_size) {
103 char test_device[10];
104 for (char i = 'a'; i < 'z'; ++i) {
105 snprintf(test_device, sizeof(test_device), "/dev/sd%c", i);
Austin Schuhf257f3c2019-10-27 21:00:43 -0700106 AOS_LOG(INFO, "Trying to access %s\n", test_device);
Austin Schuhc5982cb2014-10-25 18:04:36 -0700107 if (access(test_device, F_OK) != -1) {
108 snprintf(device, device_size, "sd%c", i);
109 return true;
110 }
111 }
112 return false;
113}
114#endif
115
Brian Silvermanab6615c2013-03-05 20:29:29 -0800116int BinaryLogReaderMain() {
Brian Silvermanf665d692013-02-17 22:11:39 -0800117 InitNRT();
brians343bc112013-02-10 01:53:46 +0000118
Brian Silverman9f330492015-03-01 17:37:02 -0500119#ifdef AOS_ARCHITECTURE_arm_frc
Austin Schuhc5982cb2014-10-25 18:04:36 -0700120 char folder[128];
121
122 {
123 char dev_name[8];
124 while (!FindDevice(dev_name, sizeof(dev_name))) {
Austin Schuhf257f3c2019-10-27 21:00:43 -0700125 AOS_LOG(INFO, "Waiting for a device\n");
Austin Schuhc5982cb2014-10-25 18:04:36 -0700126 printf("Waiting for a device\n");
127 sleep(5);
128 }
129 snprintf(folder, sizeof(folder), "/media/%s1", dev_name);
130 while (!FoundThumbDrive(folder)) {
Austin Schuhf257f3c2019-10-27 21:00:43 -0700131 AOS_LOG(INFO, "Waiting for %s\n", folder);
Austin Schuhc5982cb2014-10-25 18:04:36 -0700132 printf("Waiting for %s\n", folder);
133 sleep(1);
134 }
135 snprintf(folder, sizeof(folder), "/media/%s1/", dev_name);
136 }
137
138 if (access(folder, F_OK) == -1) {
139#else
Brian Silvermanf665d692013-02-17 22:11:39 -0800140 const char *folder = configuration::GetLoggingDirectory();
brians343bc112013-02-10 01:53:46 +0000141 if (access(folder, R_OK | W_OK) == -1) {
Austin Schuhc5982cb2014-10-25 18:04:36 -0700142#endif
Austin Schuhf257f3c2019-10-27 21:00:43 -0700143 AOS_LOG(FATAL, "folder '%s' does not exist. please create it\n", folder);
brians343bc112013-02-10 01:53:46 +0000144 }
Austin Schuhf257f3c2019-10-27 21:00:43 -0700145 AOS_LOG(INFO, "logging to folder '%s'\n", folder);
brians343bc112013-02-10 01:53:46 +0000146
brians343bc112013-02-10 01:53:46 +0000147 char *tmp;
Ben Fredricksona04c1752014-03-02 22:54:07 +0000148 AllocateLogName(&tmp, folder);
brians343bc112013-02-10 01:53:46 +0000149 char *tmp2;
150 if (asprintf(&tmp2, "%s/aos_log-current", folder) == -1) {
Austin Schuhf257f3c2019-10-27 21:00:43 -0700151 AOS_PLOG(WARNING, "couldn't create current symlink name");
brians343bc112013-02-10 01:53:46 +0000152 } else {
153 if (unlink(tmp2) == -1 && (errno != EROFS && errno != ENOENT)) {
Austin Schuhf257f3c2019-10-27 21:00:43 -0700154 AOS_LOG(WARNING, "unlink('%s') failed", tmp2);
brians343bc112013-02-10 01:53:46 +0000155 }
156 if (symlink(tmp, tmp2) == -1) {
Austin Schuhf257f3c2019-10-27 21:00:43 -0700157 AOS_PLOG(WARNING, "symlink('%s', '%s') failed", tmp, tmp2);
brians343bc112013-02-10 01:53:46 +0000158 }
159 free(tmp2);
160 }
161 int fd = open(tmp, O_SYNC | O_APPEND | O_RDWR | O_CREAT,
162 S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);
163 free(tmp);
164 if (fd == -1) {
Austin Schuhf257f3c2019-10-27 21:00:43 -0700165 AOS_PLOG(FATAL, "opening file '%s' failed", tmp);
brians343bc112013-02-10 01:53:46 +0000166 }
Brian Silvermanab5ba472014-04-18 15:26:14 -0700167 LogFileWriter writer(fd);
brians343bc112013-02-10 01:53:46 +0000168
Brian Silvermancb5da1f2015-12-05 22:19:58 -0500169 RawQueue *queue = GetLoggingQueue();
170
Brian Silvermanf5ca4d02015-03-01 16:52:24 -0500171 ::std::unordered_set<uint32_t> written_type_ids;
Brian Silvermanf5ca4d02015-03-01 16:52:24 -0500172
brians343bc112013-02-10 01:53:46 +0000173 while (true) {
Brian Silvermancb5da1f2015-12-05 22:19:58 -0500174 const LogMessage *const msg =
Brian Silverman18c2c362016-01-02 14:18:32 -0800175 static_cast<const LogMessage *>(queue->ReadMessage(RawQueue::kNonBlock));
176 if (msg == NULL) {
177 // If we've emptied the queue, then wait for a bit before starting to read
178 // again so the queue can buffer up some logs. This avoids lots of context
179 // switches and mutex contention which happens if we're constantly reading
180 // new messages as they come in.
Austin Schuhf2a50ba2016-12-24 16:16:26 -0800181 ::std::this_thread::sleep_for(::std::chrono::milliseconds(100));
Brian Silverman18c2c362016-01-02 14:18:32 -0800182 continue;
183 }
brians343bc112013-02-10 01:53:46 +0000184
Brian Silverman664db1a2014-03-20 17:06:29 -0700185 const size_t raw_output_length =
Brian Silverman88471dc2014-02-15 22:35:42 -0800186 sizeof(LogFileMessageHeader) + msg->name_length + msg->message_length;
Brian Silverman664db1a2014-03-20 17:06:29 -0700187 size_t output_length = raw_output_length;
Brian Silverman91660632014-03-21 20:52:03 -0700188 LogFileMessageHeader *const output = writer.GetWritePosition(output_length);
brians343bc112013-02-10 01:53:46 +0000189 char *output_strings = reinterpret_cast<char *>(output) + sizeof(*output);
Brian Silverman88471dc2014-02-15 22:35:42 -0800190 output->name_size = msg->name_length;
191 output->message_size = msg->message_length;
brians343bc112013-02-10 01:53:46 +0000192 output->source = msg->source;
Brian Silvermanf665d692013-02-17 22:11:39 -0800193 output->level = msg->level;
194 output->time_sec = msg->seconds;
195 output->time_nsec = msg->nseconds;
196 output->sequence = msg->sequence;
Brian Silverman88471dc2014-02-15 22:35:42 -0800197 memcpy(output_strings, msg->name, msg->name_length);
198
199 switch (msg->type) {
200 case LogMessage::Type::kString:
201 memcpy(output_strings + msg->name_length, msg->message,
202 msg->message_length);
203 output->type = LogFileMessageHeader::MessageType::kString;
204 break;
Brian Silverman88471dc2014-02-15 22:35:42 -0800205 }
206
Brian Silverman664db1a2014-03-20 17:06:29 -0700207 if (output->message_size - msg->message_length !=
208 output_length - raw_output_length) {
Austin Schuhf257f3c2019-10-27 21:00:43 -0700209 AOS_LOG(FATAL, "%zu != %zu\n", output->message_size - msg->message_length,
210 output_length - raw_output_length);
Brian Silverman664db1a2014-03-20 17:06:29 -0700211 }
212
Brian Silvermanaf221b82013-09-01 13:57:50 -0700213 futex_set(&output->marker);
brians343bc112013-02-10 01:53:46 +0000214
Brian Silvermancb5da1f2015-12-05 22:19:58 -0500215 queue->FreeMessage(msg);
brians343bc112013-02-10 01:53:46 +0000216 }
217
Brian Silvermanf665d692013-02-17 22:11:39 -0800218 Cleanup();
219 return 0;
220}
221
222} // namespace
Brian Silverman14fd0fb2014-01-14 21:42:01 -0800223} // namespace linux_code
Brian Silvermanf665d692013-02-17 22:11:39 -0800224} // namespace logging
225} // namespace aos
226
227int main() {
Brian Silverman14fd0fb2014-01-14 21:42:01 -0800228 return ::aos::logging::linux_code::BinaryLogReaderMain();
brians343bc112013-02-10 01:53:46 +0000229}