copying branch over from other 2013 repo
diff --git a/aos/atom_code/atom_code.gyp b/aos/atom_code/atom_code.gyp
new file mode 100644
index 0000000..8253588
--- /dev/null
+++ b/aos/atom_code/atom_code.gyp
@@ -0,0 +1,16 @@
+{
+ 'targets': [
+ {
+ 'target_name': 'init',
+ 'type': 'static_library',
+ 'sources': [
+ '<(AOS)/atom_code/init.cc',
+ ],
+ 'dependencies': [
+ '<(AOS)/atom_code/ipc_lib/ipc_lib.gyp:ipc_lib',
+ '<(AOS)/common/common.gyp:die',
+ '<(AOS)/build/aos.gyp:logging',
+ ],
+ },
+ ],
+}
diff --git a/aos/atom_code/camera/Buffers.cpp b/aos/atom_code/camera/Buffers.cpp
index 22b7337..f580f89 100644
--- a/aos/atom_code/camera/Buffers.cpp
+++ b/aos/atom_code/camera/Buffers.cpp
@@ -1,8 +1,10 @@
-#include "Buffers.h"
-#include "V4L2.h"
+#include "aos/atom_code/camera/Buffers.h"
#include <sys/mman.h>
+#include "aos/atom_code/camera/V4L2.h"
+#include "aos/common/logging/logging.h"
+
namespace aos {
namespace camera {
diff --git a/aos/atom_code/camera/Buffers.h b/aos/atom_code/camera/Buffers.h
index 7f1206d..b72cd3e 100644
--- a/aos/atom_code/camera/Buffers.h
+++ b/aos/atom_code/camera/Buffers.h
@@ -6,7 +6,7 @@
#include <string>
-#include "aos/aos_core.h"
+#include "aos/atom_code/ipc_lib/queue.h"
#include "aos/common/type_traits.h"
namespace aos {
diff --git a/aos/atom_code/camera/camera.gyp b/aos/atom_code/camera/camera.gyp
index e94a6ac..b8e8dd3 100644
--- a/aos/atom_code/camera/camera.gyp
+++ b/aos/atom_code/camera/camera.gyp
@@ -43,13 +43,28 @@
'hard_dependency': 1,
},
{
+ 'target_name': 'buffers',
+ 'type': 'static_library',
+ 'sources': [
+ 'Buffers.cpp',
+ ],
+ 'dependencies': [
+ '<(AOS)/atom_code/ipc_lib/ipc_lib.gyp:ipc_lib',
+ '<(AOS)/build/aos.gyp:logging',
+ ],
+ 'export_dependent_settings': [
+ '<(AOS)/atom_code/ipc_lib/ipc_lib.gyp:ipc_lib',
+ ],
+ },
+ {
'target_name': 'CameraHTTPStreamer',
'type': 'executable',
'sources': [
'HTTPStreamer.cpp',
],
'dependencies': [
- '<(AOS)/build/aos.gyp:libaos',
+ 'buffers',
+ '<(AOS)/atom_code/atom_code.gyp:init',
],
},
{
@@ -59,7 +74,8 @@
'Reader.cpp',
],
'dependencies': [
- '<(AOS)/build/aos.gyp:libaos',
+ 'buffers',
+ '<(AOS)/atom_code/atom_code.gyp:init',
],
},
],
diff --git a/aos/atom_code/camera/jni.cpp b/aos/atom_code/camera/jni.cpp
index 7b7eafa..ad5177a 100644
--- a/aos/atom_code/camera/jni.cpp
+++ b/aos/atom_code/camera/jni.cpp
@@ -3,6 +3,8 @@
#include "jni/aos_Natives.h"
#include "aos/atom_code/camera/Buffers.h"
#include "aos/externals/libjpeg/include/jpeglib.h"
+#include "aos/common/logging/logging_impl.h"
+#include "aos/atom_code/init.h"
using aos::camera::Buffers;
@@ -248,8 +250,8 @@
} else {
level = DEBUG;
}
- // can't use Get/ReleaseStringCritical because log_do might block waiting to
- // put its message into the queue
+ // Can't use Get/ReleaseStringCritical because log_do might block waiting to
+ // put its message into the queue.
const char *const message_chars = env->GetStringUTFChars(message, NULL);
if (message_chars == NULL) return;
log_do(level, "%s\n", message_chars);
diff --git a/aos/atom_code/core/BinaryLogReader.cpp b/aos/atom_code/core/BinaryLogReader.cpp
index b673c26..7027d21 100644
--- a/aos/atom_code/core/BinaryLogReader.cpp
+++ b/aos/atom_code/core/BinaryLogReader.cpp
@@ -11,16 +11,20 @@
#include <map>
-#include "aos/aos_core.h"
+#include "aos/atom_code/logging/atom_logging.h"
#include "aos/atom_code/core/LogFileCommon.h"
#include "aos/common/Configuration.h"
+#include "aos/atom_code/init.h"
-static const char *const kCRIOName = "CRIO";
+namespace aos {
+namespace logging {
+namespace atom {
+namespace {
-int main() {
- aos::InitNRT();
+int binary_log_reader_main() {
+ InitNRT();
- const char *folder = aos::configuration::GetLoggingDirectory();
+ const char *folder = configuration::GetLoggingDirectory();
if (access(folder, R_OK | W_OK) == -1) {
LOG(FATAL, "folder '%s' does not exist. please create it\n", folder);
}
@@ -28,19 +32,24 @@
const time_t t = time(NULL);
char *tmp;
- if (asprintf(&tmp, "%s/aos_log-%jd", folder, static_cast<uintmax_t>(t)) == -1) {
- fprintf(stderr, "BinaryLogReader: couldn't create final name because of %d (%s)."
+ if (asprintf(&tmp, "%s/aos_log-%jd", folder, static_cast<uintmax_t>(t)) ==
+ -1) {
+ fprintf(stderr,
+ "BinaryLogReader: couldn't create final name because of %d (%s)."
" exiting\n", errno, strerror(errno));
return EXIT_FAILURE;
}
char *tmp2;
if (asprintf(&tmp2, "%s/aos_log-current", folder) == -1) {
- fprintf(stderr, "BinaryLogReader: couldn't create symlink name because of %d (%s)."
+ fprintf(stderr,
+ "BinaryLogReader: couldn't create symlink name because of %d (%s)."
" not creating current symlink\n", errno, strerror(errno));
} else {
if (unlink(tmp2) == -1 && (errno != EROFS && errno != ENOENT)) {
- fprintf(stderr, "BinaryLogReader: warning: unlink('%s') failed because of %d (%s)\n",
- tmp2, errno, strerror(errno));
+ fprintf(stderr,
+ "BinaryLogReader: warning: unlink('%s') failed"
+ " because of %d (%s)\n",
+ tmp2, errno, strerror(errno));
}
if (symlink(tmp, tmp2) == -1) {
fprintf(stderr, "BinaryLogReader: warning: symlink('%s', '%s') failed"
@@ -52,11 +61,12 @@
S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);
free(tmp);
if (fd == -1) {
- fprintf(stderr, "BinaryLogReader: couldn't open file '%s' because of %d (%s)."
+ fprintf(stderr,
+ "BinaryLogReader: couldn't open file '%s' because of %d (%s)."
" exiting\n", tmp, errno, strerror(errno));
return EXIT_FAILURE;
}
- aos::LogFileAccessor writer(fd, true);
+ LogFileAccessor writer(fd, true);
struct timespec timespec;
time_t last_sec = 0;
@@ -68,47 +78,39 @@
writer.Sync();
}
- const log_message *const msg = log_read_next();
+ const LogMessage *const msg = ReadNext();
if (msg == NULL) continue;
- const log_crio_message *const crio_msg = reinterpret_cast<const log_crio_message *>(
- msg);
- size_t name_size, message_size;
- if (msg->source == -1) {
- name_size = strlen(kCRIOName);
- message_size = strlen(crio_msg->message);
- } else {
- name_size = strlen(msg->name);
- message_size = strlen(msg->message);
- }
- // add on size for terminating '\0'
- name_size += 1;
- message_size += 1;
+ // add 1 for terminating '\0'
+ size_t name_size = strlen(msg->name) + 1;
+ size_t message_size = strlen(msg->message) + 1;
- aos::LogFileMessageHeader *const output = writer.GetWritePosition(
- sizeof(aos::LogFileMessageHeader) + name_size + message_size);
+ LogFileMessageHeader *const output = writer.GetWritePosition(
+ sizeof(LogFileMessageHeader) + name_size + message_size);
char *output_strings = reinterpret_cast<char *>(output) + sizeof(*output);
output->name_size = name_size;
output->message_size = message_size;
output->source = msg->source;
- if (msg->source == -1) {
- output->level = crio_msg->level;
- // TODO(brians) figure out what time to put in
- output->sequence = crio_msg->sequence;
- memcpy(output_strings, kCRIOName, name_size);
- memcpy(output_strings + name_size, crio_msg->message, message_size);
- } else {
- output->level = msg->level;
- output->time_sec = msg->time.tv_sec;
- output->time_nsec = msg->time.tv_nsec;
- output->sequence = msg->sequence;
- memcpy(output_strings, msg->name, name_size);
- memcpy(output_strings + name_size, msg->message, message_size);
- }
+ output->level = msg->level;
+ output->time_sec = msg->seconds;
+ output->time_nsec = msg->nseconds;
+ output->sequence = msg->sequence;
+ memcpy(output_strings, msg->name, name_size);
+ memcpy(output_strings + name_size, msg->message, message_size);
condition_set(&output->marker);
- log_free_message(msg);
+ logging::atom::Free(msg);
}
- aos::Cleanup();
+ Cleanup();
+ return 0;
+}
+
+} // namespace
+} // namespace atom
+} // namespace logging
+} // namespace aos
+
+int main() {
+ return aos::logging::atom::binary_log_reader_main();
}
diff --git a/aos/atom_code/core/CRIOLogReader.cpp b/aos/atom_code/core/CRIOLogReader.cpp
index f32e21d..2aa216c 100644
--- a/aos/atom_code/core/CRIOLogReader.cpp
+++ b/aos/atom_code/core/CRIOLogReader.cpp
@@ -8,44 +8,55 @@
#include <fcntl.h>
#include <arpa/inet.h>
#include <errno.h>
+#include <string.h>
#include <map>
-#include "aos/aos_core.h"
+#include "aos/common/logging/logging_impl.h"
+#include "aos/atom_code/logging/atom_logging.h"
#include "aos/common/Configuration.h"
#include "aos/common/byteorder.h"
+#include "aos/atom_code/init.h"
+
+namespace aos {
+namespace logging {
+namespace atom {
+namespace {
struct log_buffer {
- log_crio_message msg;
+ LogMessage *msg;
size_t used;
- log_buffer() {
+ log_buffer() : msg(NULL) {
Clear();
}
void Clear() {
+ logging::atom::Free(msg);
+ msg = logging::atom::Get();
used = 0;
}
- // returns whether msg is now complete
+
+ // Returns whether msg is now complete.
bool ReceiveFrom(int sock) {
- const ssize_t ret = recv(sock, reinterpret_cast<uint8_t *>(&msg) + used,
- sizeof(msg) - used, 0);
+ const ssize_t ret = recv(sock, reinterpret_cast<uint8_t *>(msg) + used,
+ sizeof(*msg) - used, 0);
if (ret == -1) {
LOG(ERROR, "recv(%d, %p, %d) failed because of %d: %s\n",
- sock, reinterpret_cast<uint8_t *>(&msg) + used, sizeof(msg) - used,
+ sock, reinterpret_cast<uint8_t *>(msg) + used, sizeof(*msg) - used,
errno, strerror(errno));
return false;
} else {
used += ret;
- if (used > sizeof(msg)) {
- LOG(WARNING, "used(%zd) is > sizeof(msg)(%zd)\n", used, sizeof(msg));
+ if (used > sizeof(*msg)) {
+ LOG(WARNING, "used(%zd) is > sizeof(*msg)(%zd)\n", used, sizeof(*msg));
}
- return used >= sizeof(msg);
+ return used >= sizeof(*msg);
}
}
};
-int main() {
- aos::InitNRT();
+int crio_log_reader_main() {
+ InitNRT();
const int sock = socket(AF_INET, SOCK_STREAM, 0);
if (sock == -1) {
@@ -59,11 +70,11 @@
} bind_sockaddr;
memset(&bind_sockaddr, 0, sizeof(bind_sockaddr));
bind_sockaddr.in.sin_family = AF_INET;
- bind_sockaddr.in.sin_port = htons(static_cast<uint16_t>(aos::NetworkPort::kLogs));
+ bind_sockaddr.in.sin_port = htons(static_cast<uint16_t>(NetworkPort::kLogs));
bind_sockaddr.in.sin_addr.s_addr = htonl(INADDR_ANY);
if (bind(sock, &bind_sockaddr.addr, sizeof(bind_sockaddr.addr)) == -1) {
- LOG(ERROR, "bind(%d, %p) failed because of %d: %s\n", sock, &bind_sockaddr.addr,
- errno, strerror(errno));
+ LOG(ERROR, "bind(%d, %p) failed because of %d: %s\n", sock,
+ &bind_sockaddr.addr, errno, strerror(errno));
return EXIT_FAILURE;
}
if (listen(sock, 10) == -1) {
@@ -109,21 +120,35 @@
"because of %d: %s\n",
sock, SOCK_NONBLOCK, errno, strerror(errno));
} else {
- socks[new_sock]; // creates using value's default constructor
+ socks[new_sock]; // creates using value's default constructor
}
}
for (auto it = socks.begin(); it != socks.end(); ++it) {
if (FD_ISSET(it->first, &read_fds)) {
if (it->second.ReceiveFrom(it->first)) {
- it->second.msg.identifier = -1;
- it->second.msg.time = aos::ntoh(it->second.msg.time);
- log_crio_message_send(it->second.msg);
+ it->second.msg->source = ntoh(it->second.msg->source);
+ it->second.msg->sequence = ntoh(it->second.msg->sequence);
+ it->second.msg->level = ntoh(it->second.msg->level);
+ it->second.msg->seconds = ntoh(it->second.msg->seconds);
+ it->second.msg->nseconds = ntoh(it->second.msg->nseconds);
+
+ logging::atom::Write(it->second.msg);
+ it->second.msg = NULL;
it->second.Clear();
}
}
}
}
- aos::Cleanup();
+ Cleanup();
+}
+
+} // namespace
+} // namespace atom
+} // namespace logging
+} // namespace aos
+
+int main() {
+ return aos::logging::atom::crio_log_reader_main();
}
diff --git a/aos/atom_code/core/LogDisplayer.cpp b/aos/atom_code/core/LogDisplayer.cpp
index 9dee08f..d8d9f94 100644
--- a/aos/atom_code/core/LogDisplayer.cpp
+++ b/aos/atom_code/core/LogDisplayer.cpp
@@ -9,6 +9,7 @@
#include "aos/atom_code/core/LogFileCommon.h"
#include "aos/aos_core.h"
+#include "aos/common/logging/logging_impl.h"
namespace {
@@ -81,7 +82,7 @@
filter_name = optarg;
break;
case 'l':
- filter_level = str_log(optarg);
+ filter_level = aos::logging::str_log(optarg);
if (filter_level == LOG_UNKNOWN) {
fprintf(stderr, "LogDisplayer: unknown log level '%s'\n", optarg);
exit(EXIT_FAILURE);
@@ -121,7 +122,7 @@
}
fprintf(stderr, "displaying down to level %s from file '%s'\n",
- log_str(filter_level), filename);
+ aos::logging::log_str(filter_level), filename);
if (optind < argc) {
fprintf(stderr, "non-option ARGV-elements: ");
while (optind < argc) {
@@ -135,23 +136,33 @@
filename, strerror(errno));
exit(EXIT_FAILURE);
}
- aos::LogFileAccessor accessor(fd, false);
+ aos::logging::LogFileAccessor accessor(fd, false);
if (!start_at_beginning) {
accessor.MoveToEnd();
}
- const aos::LogFileMessageHeader *msg;
+ const aos::logging::LogFileMessageHeader *msg;
+ aos::logging::LogMessage log_message;
do {
msg = accessor.ReadNextMessage(follow);
if (msg == NULL) continue;
- if (log_gt_important(filter_level, msg->level)) continue;
+ if (aos::logging::log_gt_important(filter_level, msg->level)) continue;
if (filter_name != NULL &&
strcmp(filter_name, reinterpret_cast<const char *>(msg) + sizeof(*msg)) != 0) {
continue;
}
- printf("%s(%"PRId32")(%03"PRId8"): %s at %010"PRIu64"s%09"PRIu64"ns: %s",
- reinterpret_cast<const char *>(msg) + sizeof(*msg), msg->source,
- msg->sequence, log_str(msg->level), msg->time_sec, msg->time_nsec,
- reinterpret_cast<const char *>(msg) + sizeof(*msg) + msg->name_size);
+
+ log_message.source = msg->source;
+ log_message.sequence = msg->sequence;
+ log_message.level = msg->level;
+ log_message.seconds = msg->time_sec;
+ log_message.nseconds = msg->time_nsec;
+ strncpy(log_message.name,
+ reinterpret_cast<const char *>(msg) + sizeof(*msg),
+ sizeof(log_message.name));
+ strncpy(log_message.message,
+ reinterpret_cast<const char *>(msg) + sizeof(*msg) +
+ msg->name_size,
+ sizeof(log_message.message));
+ aos::logging::internal::PrintMessage(stdout, log_message);
} while (msg != NULL);
}
-
diff --git a/aos/atom_code/core/LogFileCommon.h b/aos/atom_code/core/LogFileCommon.h
index 235c55b..afb86b0 100644
--- a/aos/atom_code/core/LogFileCommon.h
+++ b/aos/atom_code/core/LogFileCommon.h
@@ -11,18 +11,22 @@
#include <algorithm>
-#include "aos/aos_core.h"
+#include "aos/common/logging/logging_impl.h"
namespace aos {
+namespace logging {
// File format: {
// LogFileMessageHeader header;
-// char *name; // of the process that wrote the message
+// char *name; // of the process that wrote the message
// char *message;
// } not crossing kPageSize boundaries into the file.
//
-// Field sizes designed to fit the various values from log_message even on
+// Field sizes designed to fit the various values from LogMessage even on
// other machines (hopefully) because they're baked into the files.
+//
+// A lot of the fields don't have comments because they're the same as the
+// identically named fields in LogMessage.
struct __attribute__((aligned)) LogFileMessageHeader {
// gets condition_set once this one has been written
// for readers keeping up with a live writer
@@ -36,18 +40,17 @@
log_level level;
static_assert(sizeof(level) == 1, "log_level changed size!");
- uint64_t time_sec;
- static_assert(sizeof(time_sec) >= sizeof(log_message::time.tv_sec), "tv_sec won't fit");
- uint64_t time_nsec;
- static_assert(sizeof(time_nsec) >= sizeof(log_message::time.tv_nsec),
+ uint32_t time_sec;
+ static_assert(sizeof(time_sec) >= sizeof(LogMessage::seconds),
+ "tv_sec won't fit");
+ uint32_t time_nsec;
+ static_assert(sizeof(time_nsec) >= sizeof(LogMessage::nseconds),
"tv_nsec won't fit");
- int32_t source; // pid or -1 for crio
- static_assert(sizeof(source) >= sizeof(log_message::source), "PIDs won't fit");
- uint8_t sequence;
- static_assert(sizeof(sequence) == sizeof(log_crio_message::sequence),
- "something changed");
- static_assert(sizeof(sequence) == sizeof(log_message::sequence),
+ int32_t source;
+ static_assert(sizeof(source) >= sizeof(LogMessage::source), "PIDs won't fit");
+ uint16_t sequence;
+ static_assert(sizeof(sequence) == sizeof(LogMessage::sequence),
"something changed");
// both including the terminating '\0'
@@ -129,7 +132,7 @@
sizeof(mutex) > kPageSize) {
char *const temp = current_;
MapNextPage();
- if (condition_set_value(reinterpret_cast<mutex *>(&temp[position_]), 2) != 0) {
+ if (condition_set_value(reinterpret_cast<mutex *>(&temp[position_]), 2) == -1) {
fprintf(stderr, "LogFileCommon: condition_set_value(%p, 2) failed with %d: %s."
" readers will hang\n", &temp[position_], errno, strerror(errno));
}
@@ -186,7 +189,7 @@
}
};
-};
+} // namespace logging
+} // namespace aos
#endif
-
diff --git a/aos/atom_code/core/LogStreamer.cpp b/aos/atom_code/core/LogStreamer.cpp
index ceec18d..ffecac8 100644
--- a/aos/atom_code/core/LogStreamer.cpp
+++ b/aos/atom_code/core/LogStreamer.cpp
@@ -10,35 +10,43 @@
#include <fcntl.h>
#include <inttypes.h>
-#include "aos/aos_core.h"
+#include "aos/atom_code/logging/atom_logging.h"
#include "aos/atom_code/core/LogFileCommon.h"
+#include "aos/atom_code/init.h"
+#include "aos/atom_code/ipc_lib/queue.h"
+#include "aos/common/logging/logging_impl.h"
-static const char *const kCRIOName = "CRIO";
+namespace aos {
+namespace logging {
+namespace atom {
+namespace {
-int main() {
- aos::InitNRT();
+int log_streamer_main() {
+ InitNRT();
const time_t t = time(NULL);
- printf("starting at %jd----------------------------------\n", static_cast<uintmax_t>(t));
+ printf("starting at %jd----------------------------------\n",
+ static_cast<uintmax_t>(t));
int index = 0;
while (true) {
- const log_message *const msg = log_read_next2(BLOCK, &index);
+ const LogMessage *const msg = ReadNext(BLOCK, &index);
if (msg == NULL) continue;
- const log_crio_message *const crio_msg = reinterpret_cast<const log_crio_message *>(
- msg);
- if (msg->source == -1) {
- printf("CRIO(%03"PRId8"): %s at %f: %s", crio_msg->sequence,
- log_str(crio_msg->level), crio_msg->time, crio_msg->message);
- } else {
- printf("%s(%"PRId32")(%03"PRId8"): %s at %010jus%09luns: %s",
- msg->name, msg->source, msg->sequence, log_str(msg->level),
- static_cast<uintmax_t>(msg->time.tv_sec), msg->time.tv_nsec, msg->message);
- }
+ internal::PrintMessage(stdout, *msg);
- log_free_message(msg);
+ logging::atom::Free(msg);
}
- aos::Cleanup();
+ Cleanup();
+ return 0;
+}
+
+} // namespace
+} // namespace atom
+} // namespace logging
+} // namespace aos
+
+int main() {
+ return aos::logging::atom::log_streamer_main();
}
diff --git a/aos/atom_code/core/core.cc b/aos/atom_code/core/core.cc
index b34169b..4179a0a 100644
--- a/aos/atom_code/core/core.cc
+++ b/aos/atom_code/core/core.cc
@@ -3,10 +3,10 @@
// Purposes: All shared memory gets allocated here.
//
-#include <stdio.h>
-#include <string.h>
-#include <unistd.h>
-#include "aos/aos_core.h"
+#include <sys/select.h>
+#include <stdlib.h>
+
+#include "aos/atom_code/init.h"
int main() {
aos::InitCreate();
diff --git a/aos/atom_code/core/core.gyp b/aos/atom_code/core/core.gyp
index 04d3cc8..4e13e51 100644
--- a/aos/atom_code/core/core.gyp
+++ b/aos/atom_code/core/core.gyp
@@ -7,7 +7,7 @@
'core.cc',
],
'dependencies': [
- '<(AOS)/build/aos.gyp:libaos',
+ '<(AOS)/atom_code/atom_code.gyp:init',
],
},
{
@@ -17,7 +17,9 @@
'BinaryLogReader.cpp',
],
'dependencies': [
- '<(AOS)/build/aos.gyp:libaos',
+ '<(AOS)/build/aos.gyp:logging',
+ '<(AOS)/atom_code/atom_code.gyp:init',
+ '<(AOS)/common/common.gyp:common',
],
},
{
@@ -27,7 +29,8 @@
'LogStreamer.cpp',
],
'dependencies': [
- '<(AOS)/build/aos.gyp:libaos',
+ '<(AOS)/build/aos.gyp:logging',
+ '<(AOS)/atom_code/atom_code.gyp:init',
],
},
{
@@ -37,7 +40,8 @@
'LogDisplayer.cpp',
],
'dependencies': [
- '<(AOS)/build/aos.gyp:libaos',
+ '<(AOS)/build/aos.gyp:logging',
+ '<(AOS)/atom_code/atom_code.gyp:init',
],
},
{
@@ -47,7 +51,8 @@
'CRIOLogReader.cpp',
],
'dependencies': [
- '<(AOS)/build/aos.gyp:libaos',
+ '<(AOS)/build/aos.gyp:logging',
+ '<(AOS)/atom_code/atom_code.gyp:init',
],
},
],
diff --git a/aos/atom_code/init.cc b/aos/atom_code/init.cc
index 4776261..7eecde3 100644
--- a/aos/atom_code/init.cc
+++ b/aos/atom_code/init.cc
@@ -12,8 +12,9 @@
#include <stdlib.h>
#include <stdint.h>
-#include "aos/aos_core.h"
#include "aos/common/die.h"
+#include "aos/atom_code/logging/atom_logging.h"
+#include "aos/atom_code/ipc_lib/shared_mem.h"
namespace aos {
@@ -69,10 +70,7 @@
Die("%s-init: creating shared memory reference failed\n",
program_invocation_short_name);
}
- if (log_init(program_invocation_short_name) != 0) {
- Die("%s-init: initializing logging failed\n",
- program_invocation_short_name);
- }
+ logging::atom::Register();
}
const char *const kNoRealtimeEnvironmentVariable = "AOS_NO_REALTIME";
diff --git a/aos/atom_code/ipc_lib/mutex.cpp b/aos/atom_code/ipc_lib/mutex.cpp
index d1f0ef2..4753e78 100644
--- a/aos/atom_code/ipc_lib/mutex.cpp
+++ b/aos/atom_code/ipc_lib/mutex.cpp
@@ -2,6 +2,8 @@
#include <inttypes.h>
#include <errno.h>
+#include <stdio.h>
+#include <string.h>
#include "aos/aos_core.h"
#include "aos/common/type_traits.h"
diff --git a/aos/atom_code/ipc_lib/queue.c b/aos/atom_code/ipc_lib/queue.c
index 5cfd2ac..2e45326 100644
--- a/aos/atom_code/ipc_lib/queue.c
+++ b/aos/atom_code/ipc_lib/queue.c
@@ -6,6 +6,8 @@
#include <errno.h>
#include <assert.h>
+#include "aos/common/logging/logging.h"
+
#define READ_DEBUG 0
#define WRITE_DEBUG 0
#define REF_DEBUG 0
@@ -36,7 +38,7 @@
abort();
}
#if REF_DEBUG
- printf("ref_free_count: %p\n", msg);
+ printf("ref free: %p\n", msg);
#endif
--pool->used;
@@ -484,10 +486,7 @@
msg = pool->pool[pool->used];
} else {
if (pool->length >= pool->mem_length) {
- //TODO(brians) log this if it isn't the log queue
- fprintf(stderr, "queue: overused_pool\n");
- msg = NULL;
- goto exit;
+ LOG(FATAL, "overused pool %p\n", pool);
}
msg = pool->pool[pool->length] = aos_alloc_msg(pool);
++pool->length;
@@ -500,7 +499,6 @@
#endif
header->index = pool->used;
++pool->used;
-exit:
mutex_unlock(&pool->pool_lock);
return msg;
}
diff --git a/aos/atom_code/logging/atom_logging.cc b/aos/atom_code/logging/atom_logging.cc
new file mode 100644
index 0000000..c9b1195
--- /dev/null
+++ b/aos/atom_code/logging/atom_logging.cc
@@ -0,0 +1,145 @@
+#include "aos/atom_code/logging/atom_logging.h"
+
+#include <stdarg.h>
+#include <stdio.h>
+#include <string.h>
+#include <time.h>
+#include <sys/types.h>
+#include <errno.h>
+#include <unistd.h>
+#include <limits.h>
+#include <sys/prctl.h>
+
+#include <algorithm>
+
+#include "aos/common/die.h"
+#include "aos/common/logging/logging_impl.h"
+#include "aos/atom_code/thread_local.h"
+#include "aos/atom_code/ipc_lib/queue.h"
+
+namespace aos {
+namespace logging {
+namespace {
+
+using internal::Context;
+
+AOS_THREAD_LOCAL Context *my_context(NULL);
+
+std::string GetMyName() {
+ // The maximum number of characters that can make up a thread name.
+ // The docs are unclear if it can be 16 characters with no '\0', so we'll be
+ // safe by adding our own where necessary.
+ static const size_t kThreadNameLength = 16;
+
+ std::string process_name(program_invocation_short_name);
+
+ char thread_name_array[kThreadNameLength + 1];
+ if (prctl(PR_GET_NAME, thread_name_array) != 0) {
+ Die("prctl(PR_GET_NAME, %p) failed with %d: %s\n",
+ thread_name_array, errno, strerror(errno));
+ }
+ thread_name_array[sizeof(thread_name_array) - 1] = '\0';
+ std::string thread_name(thread_name_array);
+
+ // If the first bunch of characters are the same.
+ // We cut off comparing at the shorter of the 2 strings because one or the
+ // other often ends up cut off.
+ if (strncmp(thread_name.c_str(), process_name.c_str(),
+ std::min(thread_name.length(), process_name.length())) == 0) {
+ // This thread doesn't have an actual name.
+ return process_name;
+ }
+
+ return process_name + '.' + thread_name;
+}
+
+static const aos_type_sig message_sig = {sizeof(LogMessage), 1234, 1500};
+static aos_queue *queue;
+
+} // namespace
+namespace internal {
+
+Context *Context::Get() {
+ if (my_context == NULL) {
+ my_context = new Context();
+ std::string name = GetMyName();
+ char *name_chars = new char[name.size() + 1];
+ my_context->name_size = std::min(name.size() + 1, sizeof(LogMessage::name));
+ memcpy(name_chars, name.c_str(), my_context->name_size);
+ name_chars[my_context->name_size - 1] = '\0';
+ my_context->name = name_chars;
+ my_context->source = getpid();
+ }
+ return my_context;
+}
+
+void Context::Delete() {
+ delete my_context;
+ my_context = NULL;
+}
+
+} // namespace internal
+namespace atom {
+namespace {
+
+class AtomLogImplementation : public LogImplementation {
+ virtual void DoLog(log_level level, const char *format, va_list ap) {
+ LogMessage *message = static_cast<LogMessage *>(aos_queue_get_msg(queue));
+ if (message == NULL) {
+ LOG(FATAL, "queue get message failed\n");
+ }
+
+ internal::FillInMessage(level, format, ap, message);
+
+ Write(message);
+ }
+};
+
+} // namespace
+
+void Register() {
+ Init();
+
+ queue = aos_fetch_queue("LoggingQueue", &message_sig);
+ if (queue == NULL) {
+ Die("logging: couldn't fetch queue\n");
+ }
+
+ AddImplementation(new AtomLogImplementation());
+}
+
+const LogMessage *ReadNext(int flags, int *index) {
+ return static_cast<const LogMessage *>(
+ aos_queue_read_msg_index(queue, flags, index));
+}
+
+const LogMessage *ReadNext() {
+ return ReadNext(BLOCK);
+}
+
+const LogMessage *ReadNext(int flags) {
+ const LogMessage *r = NULL;
+ do {
+ r = static_cast<const LogMessage *>(aos_queue_read_msg(queue, flags));
+ // not blocking means return a NULL if that's what it gets
+ } while ((flags & BLOCK) && r == NULL);
+ return r;
+}
+
+LogMessage *Get() {
+ return static_cast<LogMessage *>(aos_queue_get_msg(queue));
+}
+
+void Free(const LogMessage *msg) {
+ aos_queue_free_msg(queue, msg);
+}
+
+void Write(LogMessage *msg) {
+ if (aos_queue_write_msg_free(queue, msg, OVERRIDE) < 0) {
+ LOG(FATAL, "writing failed");
+ }
+}
+
+} // namespace atom
+} // namespace logging
+} // namespace aos
diff --git a/aos/atom_code/logging/atom_logging.cpp b/aos/atom_code/logging/atom_logging.cpp
deleted file mode 100644
index e98078b..0000000
--- a/aos/atom_code/logging/atom_logging.cpp
+++ /dev/null
@@ -1,259 +0,0 @@
-#include <stdarg.h>
-#include <stdio.h>
-#include <string.h>
-#include <time.h>
-#include <sys/types.h>
-#include <errno.h>
-#include <unistd.h>
-#include <limits.h>
-
-#include <algorithm>
-
-#include "aos/aos_core.h"
-#include "aos/common/die.h"
-
-#define DECL_LEVEL(name, value) const log_level name = value;
-DECL_LEVELS
-#undef DECL_LEVEL
-
-log_level log_min = 0;
-
-static const aos_type_sig message_sig = {sizeof(log_queue_message), 1234, 1500};
-static const char *name;
-static size_t name_size;
-static aos_queue *queue;
-static log_message corked_message;
-static int cork_line_min, cork_line_max;
-bool log_initted = false;
-
-static inline void cork_init() {
- corked_message.message[0] = '\0'; // make strlen of it 0
- cork_line_min = INT_MAX;
- cork_line_max = -1;
-}
-int log_init(const char *name_in){
- if (log_initted) {
- return 1;
- }
-
- const size_t name_in_len = strlen(name_in);
- const char *last_slash = static_cast<const char *>(memrchr(name_in,
- '/', name_in_len));
- if (last_slash == NULL) {
- name_size = name_in_len;
- last_slash = name_in - 1;
- } else {
- name_size = name_in + name_in_len - last_slash;
- }
- if (name_size >= sizeof(log_message::name)) {
- fprintf(stderr, "logging: error: name '%s' (going to use %zu bytes) is too long\n",
- name_in, name_size);
- return -1;
- }
- char *const tmp = static_cast<char *>(malloc(name_size + 1));
- if (tmp == NULL) {
- fprintf(stderr, "logging: error: couldn't malloc(%zd)\n", name_size + 1);
- return -1;
- }
- name = tmp;
- memcpy(tmp, last_slash + 1, name_size);
- tmp[name_size] = 0;
- queue = aos_fetch_queue("LoggingQueue", &message_sig);
- if (queue == NULL) {
- fprintf(stderr, "logging: error: couldn't fetch queue\n");
- return -1;
- }
-
- cork_init();
-
- log_initted = true;
- return 0;
-}
-void log_uninit() {
- free(const_cast<char *>(name));
- name = NULL;
- name_size = 0;
- queue = NULL;
- log_initted = false;
-}
-
-static inline void check_init() {
- if (!log_initted) {
- fprintf(stderr, "logging: warning: not initialized in %jd."
- " initializing using \"<null>\" as name\n", static_cast<intmax_t>(getpid()));
- log_init("<null>");
- }
-}
-
-const log_message *log_read_next2(int flags, int *index) {
- check_init();
- return static_cast<const log_message *>(aos_queue_read_msg_index(queue, flags, index));
-}
-const log_message *log_read_next1(int flags) {
- check_init();
- const log_message *r = NULL;
- do {
- r = static_cast<const log_message *>(aos_queue_read_msg(queue, flags));
- } while ((flags & BLOCK) && r == NULL); // not blocking means return a NULL if that's what it gets
- return r;
-}
-void log_free_message(const log_message *msg) {
- check_init();
- aos_queue_free_msg(queue, msg);
-}
-
-int log_crio_message_send(log_crio_message &to_send) {
- check_init();
-
- log_crio_message *msg = static_cast<log_crio_message *>(aos_queue_get_msg(queue));
- if (msg == NULL) {
- fprintf(stderr, "logging: error: couldn't get a message to send '%s'\n",
- to_send.message);
- return -1;
- }
- //*msg = to_send;
- static_assert(sizeof(to_send) == sizeof(*msg), "something is very wrong here");
- memcpy(msg, &to_send, sizeof(to_send));
- if (aos_queue_write_msg(queue, msg, OVERRIDE) < 0) {
- fprintf(stderr, "logging: error: writing crio message '%s' failed\n", msg->message);
- aos_queue_free_msg(queue, msg);
- return -1;
- }
-
- return 0;
-}
-
-// Prints format (with ap) into output and correctly deals with the message
-// being too long etc.
-// Returns whether it succeeded or not.
-static inline bool vsprintf_in(char *output, size_t output_size,
- const char *format, va_list ap) {
- static const char *continued = "...\n";
- const size_t size = output_size - strlen(continued);
- const int ret = vsnprintf(output, size, format, ap);
- if (ret < 0) {
- fprintf(stderr, "logging: error: vsnprintf failed with %d (%s)\n",
- errno, strerror(errno));
- return false;
- } else if (static_cast<uintmax_t>(ret) >= static_cast<uintmax_t>(size)) {
- // overwrite the NULL at the end of the existing one and
- // copy in the one on the end of continued
- memcpy(&output[size - 1], continued, strlen(continued) + 1);
- }
- return true;
-}
-static inline bool write_message(log_message *msg, log_level level) {
- msg->level = level;
- msg->source = getpid();
- memcpy(msg->name, name, name_size + 1);
- if (clock_gettime(CLOCK_REALTIME, &msg->time) == -1) {
- fprintf(stderr, "logging: warning: couldn't get the current time "
- "because of %d (%s)\n", errno, strerror(errno));
- msg->time.tv_sec = 0;
- msg->time.tv_nsec = 0;
- }
-
- static uint8_t local_sequence = -1;
- msg->sequence = ++local_sequence;
-
- if (aos_queue_write_msg(queue, msg, OVERRIDE) < 0) {
- fprintf(stderr, "logging: error: writing message '%s' failed\n", msg->message);
- aos_queue_free_msg(queue, msg);
- return false;
- }
- return true;
-}
-static inline int vlog_do(log_level level, const char *format, va_list ap) {
- log_message *msg = static_cast<log_message *>(aos_queue_get_msg(queue));
- if (msg == NULL) {
- fprintf(stderr, "logging: error: couldn't get a message to send '%s'\n", format);
- return -1;
- }
-
- if (!vsprintf_in(msg->message, sizeof(msg->message), format, ap)) {
- return -1;
- }
-
- if (!write_message(msg, level)) {
- return -1;
- }
-
- if (level == FATAL) {
- aos::Die("%s", msg->message);
- }
-
- return 0;
-}
-int log_do(log_level level, const char *format, ...) {
- check_init();
- va_list ap;
- va_start(ap, format);
- const int ret = vlog_do(level, format, ap);
- va_end(ap);
- return ret;
-}
-
-static inline int vlog_cork(int line, const char *format, va_list ap) {
- const size_t message_length = strlen(corked_message.message);
- if (line > cork_line_max) cork_line_max = line;
- if (line < cork_line_min) cork_line_min = line;
- return vsprintf_in(corked_message.message + message_length,
- sizeof(corked_message.message) - message_length, format, ap) ? 0 : -1;
-}
-int log_cork(int line, const char *format, ...) {
- check_init();
- va_list ap;
- va_start(ap, format);
- const int ret = vlog_cork(line, format, ap);
- va_end(ap);
- return ret;
-}
-static inline bool log_uncork_helper(char *output, size_t output_size,
- const char *format, ...) {
- check_init();
- va_list ap;
- va_start(ap, format);
- const bool ret = vsprintf_in(output, output_size, format, ap);
- va_end(ap);
- return ret;
-}
-int log_uncork(int line, log_level level, const char *begin_format,
- const char *format, ...) {
- check_init();
- va_list ap;
- va_start(ap, format);
- const int ret = vlog_cork(line, format, ap);
- va_end(ap);
- if (ret != 0) {
- return ret;
- }
-
- log_message *msg = static_cast<log_message *>(aos_queue_get_msg(queue));
- if (msg == NULL) {
- fprintf(stderr, "logging: error: couldn't get a message to send '%s'\n", format);
- cork_init();
- return -1;
- }
-
- static char new_format[LOG_MESSAGE_LEN];
- if (!log_uncork_helper(new_format, sizeof(new_format), begin_format,
- cork_line_min, cork_line_max)) {
- cork_init();
- return -1;
- }
- const size_t new_length = strlen(new_format);
- memcpy(msg->message, new_format, new_length);
- memcpy(msg->message + new_length, corked_message.message,
- std::min(strlen(corked_message.message) + 1,
- sizeof(msg->message) - new_length));
- // in case corked_message.message was too long, it'll still be NULL-terminated
- msg->message[sizeof(msg->message) - 1] = '\0';
- cork_init();
-
- if (!write_message(msg, level)) {
- return -1;
- }
-
- return 0;
-}
-
diff --git a/aos/atom_code/logging/atom_logging.h b/aos/atom_code/logging/atom_logging.h
index 6211e22..45f2a07 100644
--- a/aos/atom_code/logging/atom_logging.h
+++ b/aos/atom_code/logging/atom_logging.h
@@ -1,109 +1,30 @@
#ifndef AOS_ATOM_CODE_LOGGING_LOGGING_H_
#define AOS_ATOM_CODE_LOGGING_LOGGING_H_
-// IWYU pragma: private, include "aos/common/logging/logging.h"
+#include "aos/common/logging/logging_impl.h"
-#ifndef AOS_COMMON_LOGGING_LOGGING_H_
-#error This file may only be #included through common/logging/logging.h!!!
-#endif
+namespace aos {
+namespace logging {
+namespace atom {
-#include "aos/aos_core.h"
+// Calls AddImplementation to register the usual atom logging implementation
+// which sends the messages through a queue. This implementation relies on
+// another process(es) to read the log messages that it puts into the queue.
+// It gets called by aos::Init*.
+void Register();
-#ifdef __cplusplus
-extern "C" {
-#endif
+// Fairly simple wrappers around the raw queue calls.
-int log_init(const char *name);
-// WARNING: THIS LEAKS MEMORY AND SHARED MEMORY
-void log_uninit(void);
+// This one never returns NULL if flags contains BLOCK.
+const LogMessage *ReadNext(int flags);
+const LogMessage *ReadNext(int flags, int *index);
+const LogMessage *ReadNext();
+LogMessage *Get();
+void Free(const LogMessage *msg);
+void Write(LogMessage *msg);
-extern log_level log_min;
-
-// The basic structure that goes into the shared memory queue.
-// It is packed so the pid_t at the front is at the same location as
-// the one in log_crio_message.
-typedef struct log_message_t_ {
- pid_t source;
- log_level level;
- char message[LOG_MESSAGE_LEN];
- char name[40];
- struct timespec time;
- uint8_t sequence; // per process
-} __attribute__((packed)) log_message;
-
-#ifdef __cplusplus
-#define LOG_BOOL bool
-#else
-#define LOG_BOOL uint8_t
-#endif
-extern LOG_BOOL log_initted;
-#undef LOG_BOOL
-
-// Unless explicitly stated otherwise, format must always be a string constant
-// and args are printf-style arguments for format.
-// The validitiy of format and args together will be checked at compile time
-// using a gcc function attribute.
-
-// Logs the specified thing.
-#define LOG(level, format, args...) do { \
- if (level >= log_min) { \
- log_do(level, LOG_SOURCENAME ": " STRINGIFY(__LINE__) ": " format, ##args); \
- } \
-} while (0)
-// Allows "bottling up" multiple log fragments which can then all be logged in
-// one message with LOG_UNCORK.
-// format does not have to be a constant
-#define LOG_CORK(format, args...) do { \
- log_cork(__LINE__, format, ##args); \
-} while (0)
-// Actually logs all of the saved up log fragments (including format and args on
-// the end).
-#define LOG_UNCORK(level, format, args...) do { \
- log_uncork(__LINE__, level, LOG_SOURCENAME ": %d-%d: ", format, ##args); \
-} while (0)
-// Makes a normal logging call if possible or just prints it out on stderr.
-#define LOG_IFINIT(level, format, args...) do{ \
- if(log_initted) { \
- LOG(level, format, args); \
- } else { \
- fprintf(stderr, "%s-noinit: " format, log_str(level), ##args); \
- } \
-}while(0)
-
-// All functions return 0 for success and - for error.
-
-// Actually implements the basic logging call.
-// Does not check that level is valid.
-// TODO(brians): Fix this so it works with clang.
-int log_do(log_level level, const char *format, ...)
- __attribute__((format(gnu_printf, 2, 3)));
-
-// TODO(brians): Fix this so it works with clang.
-int log_cork(int line, const char *format, ...)
- __attribute__((format(gnu_printf, 2, 3)));
-// Implements the uncork logging call.
-// IMPORTANT: begin_format must have 2 %d formats as its only 2 format specifiers
-// which will get passed the minimum and maximum line numbers that have been
-// corked into this call.
-// TODO(brians): Fix this so it works with clang.
-int log_uncork(int line, log_level level, const char *begin_format,
- const char *format, ...)
- __attribute__((format(gnu_printf, 4, 5)));
-
-const log_message *log_read_next1(int flags);
-const log_message *log_read_next2(int flags, int *index);
-inline const log_message *log_read_next(void) { return log_read_next1(BLOCK); }
-void log_free_message(const log_message *msg);
-
-// The structure that is actually in the shared memory queue.
-union log_queue_message {
- log_message atom;
- log_crio_message crio;
-};
-
-#ifdef __cplusplus
-}
-#endif
+} // namespace atom
+} // namespace logging
+} // namespace aos
#endif
-
diff --git a/aos/atom_code/logging/atom_logging_test.cpp b/aos/atom_code/logging/atom_logging_test.cpp
deleted file mode 100644
index a97d1e9..0000000
--- a/aos/atom_code/logging/atom_logging_test.cpp
+++ /dev/null
@@ -1,146 +0,0 @@
-#include <string>
-
-#include "gtest/gtest.h"
-
-#include "aos/aos_core.h"
-#include "aos/atom_code/ipc_lib/sharedmem_test_setup.h"
-#include "aos/common/control_loop/Timing.h"
-#include "aos/common/inttypes.h"
-#include "aos/common/time.h"
-
-using ::aos::time::Time;
-using ::testing::AssertionResult;
-using ::testing::AssertionSuccess;
-using ::testing::AssertionFailure;
-
-namespace aos {
-namespace testing {
-
-static const std::string kLoggingName = "LoggingTestName";
-
-class LoggingTest : public SharedMemTestSetup {
- virtual void SetUp() {
- SharedMemTestSetup::SetUp();
- ASSERT_EQ(0, log_init(kLoggingName.c_str()));
- }
- virtual void TearDown() {
- log_uninit();
- SharedMemTestSetup::TearDown();
- }
-
- public:
- AssertionResult WasAnythingLogged() {
- const log_message *msg = log_read_next1(NON_BLOCK);
- if (msg != NULL) {
- char bad_msg[LOG_MESSAGE_LEN];
- memcpy(bad_msg, msg->message, sizeof(bad_msg));
- log_free_message(msg);
- return AssertionSuccess() << "read message '" << bad_msg << "'";
- }
- return AssertionFailure();
- }
- AssertionResult WasLogged(log_level level, const std::string value) {
- const log_message *msg = NULL;
- char bad_msg[LOG_MESSAGE_LEN];
- bad_msg[0] = '\0';
- const pid_t owner = getpid();
- while (true) {
- if (msg != NULL) {
- static_assert(sizeof(bad_msg) == sizeof(msg->message),
- "something is wrong");
- if (bad_msg[0] != '\0') {
- printf("read bad message: %s", bad_msg);
- }
- memcpy(bad_msg, msg->message, sizeof(bad_msg));
- log_free_message(msg);
- msg = NULL;
- }
- msg = log_read_next1(NON_BLOCK);
- if (msg == NULL) {
- return AssertionFailure() << "last message read was '" << bad_msg << "'"
- " instead of '" << value << "'";
- }
- if (msg->source != owner) continue;
- if (msg->level != level) continue;
- if (strcmp(msg->name, kLoggingName.c_str()) != 0) continue;
- if (strcmp(msg->message + strlen(msg->message) - value.length(),
- value.c_str()) != 0) continue;
-
- // if it's gotten this far, then the message is correct
- log_free_message(msg);
- return AssertionSuccess();
- }
- }
-};
-typedef LoggingTest LoggingDeathTest;
-
-// Tests both basic logging functionality and that the test setup works
-// correctly.
-TEST_F(LoggingTest, Basic) {
- EXPECT_FALSE(WasAnythingLogged());
- LOG(INFO, "test log 1\n");
- EXPECT_TRUE(WasLogged(INFO, "test log 1\n"));
- LOG(INFO, "test log 1.5\n");
- // there's a subtle typo on purpose...
- EXPECT_FALSE(WasLogged(INFO, "test log 15\n"));
- LOG(ERROR, "test log 2=%d\n", 55);
- EXPECT_TRUE(WasLogged(ERROR, "test log 2=55\n"));
- LOG(ERROR, "test log 3\n");
- EXPECT_FALSE(WasLogged(WARNING, "test log 3\n"));
- LOG(WARNING, "test log 4\n");
- EXPECT_TRUE(WasAnythingLogged());
-}
-TEST_F(LoggingTest, Cork) {
- static const int begin_line = __LINE__;
- LOG_CORK("first part ");
- LOG_CORK("second part (=%d) ", 19);
- EXPECT_FALSE(WasAnythingLogged());
- LOG_CORK("third part ");
- static const int end_line = __LINE__;
- LOG_UNCORK(WARNING, "last part %d\n", 5);
- char *expected;
- ASSERT_GT(asprintf(&expected, "atom_logging_test.cpp: %d-%d: "
- "first part second part (=19) third part last part 5\n",
- begin_line + 1, end_line + 1), 0);
- EXPECT_TRUE(WasLogged(WARNING, std::string(expected)));
-}
-
-TEST_F(LoggingDeathTest, Fatal) {
- ASSERT_EXIT(LOG(FATAL, "this should crash it\n"),
- ::testing::KilledBySignal(SIGABRT),
- "this should crash it");
-}
-
-TEST_F(LoggingTest, PrintfDirectives) {
- LOG(INFO, "test log %%1 %%d\n");
- EXPECT_TRUE(WasLogged(INFO, "test log %1 %d\n"));
- LOG_DYNAMIC(WARNING, "test log %%2 %%f\n");
- EXPECT_TRUE(WasLogged(WARNING, "test log %2 %f\n"));
- LOG_CORK("log 3 part %%1 %%d ");
- LOG_UNCORK(DEBUG, "log 3 part %%2 %%f\n");
- EXPECT_TRUE(WasLogged(DEBUG, "log 3 part %1 %d log 3 part %2 %f\n"));
-}
-
-// For writing only.
-TEST_F(LoggingTest, Timing) {
- static const long kTimingCycles = 5000;
- Time start = Time::Now();
- for (long i = 0; i < kTimingCycles; ++i) {
- LOG(INFO, "a\n");
- }
- Time elapsed = Time::Now() - start;
-
- printf("short message took %"PRId64" nsec for %ld\n", elapsed.ToNSec(),
- kTimingCycles);
-
- start = Time::Now();
- for (long i = 0; i < kTimingCycles; ++i) {
- LOG(INFO, "something longer than just \"a\" to log to test timing\n");
- }
- elapsed = Time::Now() - start;
- printf("long message took %"PRId64" nsec for %ld\n", elapsed.ToNSec(),
- kTimingCycles);
-}
-
-} // namespace testing
-} // namespace aos
diff --git a/aos/atom_code/logging/logging.gyp b/aos/atom_code/logging/logging.gyp
index 5d29da8..dfb189c 100644
--- a/aos/atom_code/logging/logging.gyp
+++ b/aos/atom_code/logging/logging.gyp
@@ -1,15 +1,4 @@
{
'targets': [
- {
- 'target_name': 'atom_logging_test',
- 'type': 'executable',
- 'sources': [
- 'atom_logging_test.cpp',
- ],
- 'dependencies': [
- '<(EXTERNALS):gtest',
- '<(AOS)/build/aos.gyp:libaos',
- ],
- },
],
}
diff --git a/aos/atom_code/output/HTTPServer.cpp b/aos/atom_code/output/HTTPServer.cpp
index 88e3c6f..b0d6b93 100644
--- a/aos/atom_code/output/HTTPServer.cpp
+++ b/aos/atom_code/output/HTTPServer.cpp
@@ -4,6 +4,7 @@
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
+#include <string.h>
#include <memory>
diff --git a/aos/atom_code/starter/starter.cpp b/aos/atom_code/starter/starter.cpp
index 0cfddd5..e47e213 100644
--- a/aos/atom_code/starter/starter.cpp
+++ b/aos/atom_code/starter/starter.cpp
@@ -8,54 +8,56 @@
#include <sys/inotify.h>
#include <sys/stat.h>
-#include "aos/aos_core.h"
+#include "aos/common/logging/logging.h"
+#include "aos/common/logging/logging_impl.h"
+#include "aos/atom_code/init.h"
void niceexit(int status);
pid_t start(const char *cmd, uint8_t times) {
char *which_cmd, *which_cmd_stm;
if (asprintf(&which_cmd, "which %s", cmd) == -1) {
- LOG_IFINIT(ERROR, "creating \"which %s\" failed with %d: %s\n",
- cmd, errno, strerror(errno));
+ LOG(ERROR, "creating \"which %s\" failed with %d: %s\n",
+ cmd, errno, strerror(errno));
niceexit(EXIT_FAILURE);
}
if (asprintf(&which_cmd_stm, "which %s.stm", cmd) == -1) {
- LOG_IFINIT(ERROR, "creating \"which %s.stm\" failed with %d: %s\n",
- cmd, errno, strerror(errno));
+ LOG(ERROR, "creating \"which %s.stm\" failed with %d: %s\n",
+ cmd, errno, strerror(errno));
niceexit(EXIT_FAILURE);
}
FILE *which = popen(which_cmd, "r");
char exe[CMDLEN + 5], orig_exe[CMDLEN];
size_t ret;
if ((ret = fread(orig_exe, 1, sizeof(orig_exe), which)) == CMDLEN) {
- LOG_IFINIT(ERROR, "`which %s` was too long. not starting '%s'\n", cmd, cmd);
+ LOG(ERROR, "`which %s` was too long. not starting '%s'\n", cmd, cmd);
return 0;
}
orig_exe[ret] = '\0';
if (pclose(which) == -1) {
- LOG_IFINIT(WARNING, "pclose failed with %d: %s\n", errno, strerror(errno));
+ LOG(WARNING, "pclose failed with %d: %s\n", errno, strerror(errno));
}
free(which_cmd);
if (strlen(orig_exe) == 0) { // which returned nothing; check if stm exists
- LOG_IFINIT(INFO, "%s didn't exist. trying %s.stm\n", cmd, cmd);
+ LOG(INFO, "%s didn't exist. trying %s.stm\n", cmd, cmd);
FILE *which_stm = popen(which_cmd_stm, "r");
if ((ret = fread(orig_exe, 1, sizeof(orig_exe), which_stm)) == CMDLEN) {
- LOG_IFINIT(ERROR, "`which %s.stm` was too long. not starting %s\n", cmd, cmd);
+ LOG(ERROR, "`which %s.stm` was too long. not starting %s\n", cmd, cmd);
return 0;
}
orig_exe[ret] = '\0';
if (pclose(which) == -1) {
- LOG_IFINIT(WARNING, "pclose failed with %d: %s\n", errno, strerror(errno));
+ LOG(WARNING, "pclose failed with %d: %s\n", errno, strerror(errno));
}
}
if (strlen(orig_exe) == 0) {
- LOG_IFINIT(WARNING, "couldn't find file '%s[.stm]'. not going to start it\n",
- cmd);
+ LOG(WARNING, "couldn't find file '%s[.stm]'. not going to start it\n",
+ cmd);
return 0;
}
if (orig_exe[strlen(orig_exe) - 1] != '\n') {
- LOG_IFINIT(WARNING, "no \\n on the end of `which %s[.stm]` output ('%s')\n",
- cmd, orig_exe);
+ LOG(WARNING, "no \\n on the end of `which %s[.stm]` output ('%s')\n",
+ cmd, orig_exe);
} else {
orig_exe[strlen(orig_exe) - 1] = '\0'; // get rid of the \n
}
@@ -65,11 +67,11 @@
struct stat st;
errno = 0;
if (stat(orig_exe, &st) != 0 && errno != ENOENT) {
- LOG_IFINIT(ERROR, "killing everything because stat('%s') failed with %d: %s\n",
- orig_exe, errno, strerror(errno));
+ LOG(ERROR, "killing everything because stat('%s') failed with %d: %s\n",
+ orig_exe, errno, strerror(errno));
niceexit(EXIT_FAILURE);
} else if (errno == ENOENT) {
- LOG_IFINIT(WARNING, "binary '%s' doesn't exist. not starting it\n", orig_exe);
+ LOG(WARNING, "binary '%s' doesn't exist. not starting it\n", orig_exe);
return 0;
}
struct stat st2;
@@ -78,38 +80,38 @@
if (!orig_zero) {
// if it failed and it wasn't because it was missing
if (unlink(exe) != 0 && (errno != EROFS && errno != ENOENT)) {
- LOG_IFINIT(ERROR,
- "killing everything because unlink('%s') failed with %d: %s\n",
- exe, errno, strerror(errno));
+ LOG(ERROR,
+ "killing everything because unlink('%s') failed with %d: %s\n",
+ exe, errno, strerror(errno));
niceexit(EXIT_FAILURE);
}
if (link(orig_exe, exe) != 0) {
- LOG_IFINIT(ERROR,
- "killing everything because link('%s', '%s') failed with %d: %s\n",
- orig_exe, exe, errno, strerror(errno));
+ LOG(ERROR,
+ "killing everything because link('%s', '%s') failed with %d: %s\n",
+ orig_exe, exe, errno, strerror(errno));
niceexit(EXIT_FAILURE);
}
}
if (errno == EEXIST) {
- LOG_IFINIT(INFO, "exe ('%s') already existed\n", exe);
+ LOG(INFO, "exe ('%s') already existed\n", exe);
}
pid_t child;
if ((child = fork()) == 0) {
execlp(exe, orig_exe, static_cast<char *>(NULL));
- LOG_IFINIT(ERROR,
- "killing everything because execlp('%s', '%s', NULL) "
- "failed with %d: %s\n",
- exe, cmd, errno, strerror(errno));
+ LOG(ERROR,
+ "killing everything because execlp('%s', '%s', NULL) "
+ "failed with %d: %s\n",
+ exe, cmd, errno, strerror(errno));
_exit(EXIT_FAILURE); // don't niceexit or anything because this is the child!!
}
if (child == -1) {
- LOG_IFINIT(WARNING, "fork on '%s' failed with %d: %s",
- cmd, errno, strerror(errno));
+ LOG(WARNING, "fork on '%s' failed with %d: %s",
+ cmd, errno, strerror(errno));
if (times < 100) {
return start(cmd, times + 1);
} else {
- LOG_IFINIT(ERROR, "tried to start '%s' too many times. giving up\n", cmd);
+ LOG(ERROR, "tried to start '%s' too many times. giving up\n", cmd);
return 0;
}
} else {
@@ -117,9 +119,9 @@
files[child] = orig_exe;
int ret = inotify_add_watch(notifyfd, orig_exe, IN_ATTRIB | IN_MODIFY);
if (ret < 0) {
- LOG_IFINIT(WARNING, "inotify_add_watch('%s') failed: "
- "not going to watch for changes to it because of %d: %s\n",
- orig_exe, errno, strerror(errno));
+ LOG(WARNING, "inotify_add_watch('%s') failed: "
+ "not going to watch for changes to it because of %d: %s\n",
+ orig_exe, errno, strerror(errno));
} else {
watches[ret] = child;
mtimes[ret] = st2.st_mtime;
@@ -164,6 +166,8 @@
atexit(exit_handler);
+ aos::logging::Init();
+
notifyfd = inotify_init1(IN_NONBLOCK);
pid_t core = start("core", 0);
@@ -330,18 +334,6 @@
niceexit(EXIT_FAILURE);
}
- /*// remove all of the watches assigned to the pid that just died
- for (auto it = watches.begin(); it != watches.end(); ++it) {
- if (it->second == infop.si_pid) {
- watches_to_ignore.insert(it->first);
- }
- }
- for (auto it = watches_to_ignore.begin();
- it != watches_to_ignore.end(); ++it) {
- LOG(DEBUG, "watch id %d was on PID %d\n", *it, infop.si_pid);
- watches.erase(*it);
- }*/
-
start(children[infop.si_pid], 0);
LOG(DEBUG, "erasing %d from children\n", infop.si_pid);
children.erase(infop.si_pid);
diff --git a/aos/atom_code/starter/starter.gyp b/aos/atom_code/starter/starter.gyp
index 44e4b08..cff6d07 100644
--- a/aos/atom_code/starter/starter.gyp
+++ b/aos/atom_code/starter/starter.gyp
@@ -7,7 +7,7 @@
'starter.cpp',
],
'dependencies': [
- '<(AOS)/build/aos.gyp:libaos',
+ '<(AOS)/atom_code/atom_code.gyp:init',
],
'copies': [
{
diff --git a/aos/atom_code/thread_local.h b/aos/atom_code/thread_local.h
new file mode 100644
index 0000000..9563a87
--- /dev/null
+++ b/aos/atom_code/thread_local.h
@@ -0,0 +1,13 @@
+#ifndef AOS_ATOM_CODE_THREAD_LOCAL_H_
+#define AOS_ATOM_CODE_THREAD_LOCAL_H_
+
+// The storage class to use when declaring thread-local variables. This provides
+// a single place to change it if/when we want to switch to something standard.
+//
+// Example: AOS_THREAD_LOCAL void *bla; // at namespace (aka global) scope
+//
+// C++11 has thread_local, but it's not clear whether Clang supports that as of
+// 12/18/12.
+#define AOS_THREAD_LOCAL __thread
+
+#endif // AOS_ATOM_CODE_THREAD_LOCAL_H_