blob: d4dea64559efbc6b88d38028441a95521e9ec7ea [file] [log] [blame]
#include <dirent.h>
#include <errno.h>
#include <fcntl.h>
#include <mntent.h>
#include <pwd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <time.h>
#include <unistd.h>
#include <string>
#include <chrono>
#include <map>
#include <unordered_set>
#include "aos/die.h"
#include "aos/logging/binary_log_file.h"
#include "aos/logging/implementations.h"
#include "aos/logging/log_namer.h"
#include "aos/time/time.h"
#include "aos/configuration.h"
#include "aos/init.h"
#include "aos/ipc_lib/queue.h"
namespace aos {
namespace logging {
namespace linux_code {
namespace {
int BinaryLogReaderMain() {
InitNRT();
const std::string file_name = GetLogName("aos_log");
int fd = open(file_name.c_str(), O_SYNC | O_APPEND | O_RDWR | O_CREAT,
S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);
if (fd == -1) {
AOS_PLOG(FATAL, "opening file '%s' failed", file_name.c_str());
}
LogFileWriter writer(fd);
RawQueue *queue = GetLoggingQueue();
::std::unordered_set<uint32_t> written_type_ids;
while (true) {
const LogMessage *const msg =
static_cast<const LogMessage *>(queue->ReadMessage(RawQueue::kNonBlock));
if (msg == NULL) {
// If we've emptied the queue, then wait for a bit before starting to read
// again so the queue can buffer up some logs. This avoids lots of context
// switches and mutex contention which happens if we're constantly reading
// new messages as they come in.
::std::this_thread::sleep_for(::std::chrono::milliseconds(100));
continue;
}
const size_t raw_output_length =
sizeof(LogFileMessageHeader) + msg->name_length + msg->message_length;
size_t output_length = raw_output_length;
LogFileMessageHeader *const output = writer.GetWritePosition(output_length);
char *output_strings = reinterpret_cast<char *>(output) + sizeof(*output);
output->name_size = msg->name_length;
output->message_size = msg->message_length;
output->source = msg->source;
output->level = msg->level;
output->time_sec = msg->seconds;
output->time_nsec = msg->nseconds;
output->sequence = msg->sequence;
memcpy(output_strings, msg->name, msg->name_length);
switch (msg->type) {
case LogMessage::Type::kString:
memcpy(output_strings + msg->name_length, msg->message,
msg->message_length);
output->type = LogFileMessageHeader::MessageType::kString;
break;
}
if (output->message_size - msg->message_length !=
output_length - raw_output_length) {
AOS_LOG(FATAL, "%zu != %zu\n", output->message_size - msg->message_length,
output_length - raw_output_length);
}
futex_set(&output->marker);
queue->FreeMessage(msg);
}
Cleanup();
return 0;
}
} // namespace
} // namespace linux_code
} // namespace logging
} // namespace aos
int main() {
return ::aos::logging::linux_code::BinaryLogReaderMain();
}