Pull log naming code out of binary_log_writer and use in new logger

Flatbuffer logs will now be at /media/sda1/fbs_log-XYZ.

Change-Id: I7cfbc797cf8da415ff065387bf1867885c67c65d
diff --git a/aos/events/logging/BUILD b/aos/events/logging/BUILD
index f2012da..553016c 100644
--- a/aos/events/logging/BUILD
+++ b/aos/events/logging/BUILD
@@ -52,6 +52,7 @@
         "//aos:configuration",
         "//aos:init",
         "//aos/events:shm_event_loop",
+        "//aos/logging:log_namer",
         "@com_github_gflags_gflags//:gflags",
         "@com_github_google_glog//:glog",
     ],
diff --git a/aos/events/logging/logger_main.cc b/aos/events/logging/logger_main.cc
index 6049f41..74e9f65 100644
--- a/aos/events/logging/logger_main.cc
+++ b/aos/events/logging/logger_main.cc
@@ -1,14 +1,11 @@
 #include "aos/configuration.h"
 #include "aos/events/logging/logger.h"
 #include "aos/events/shm_event_loop.h"
+#include "aos/logging/log_namer.h"
 #include "aos/init.h"
 #include "gflags/gflags.h"
 #include "glog/logging.h"
 
-// TODO(james): Write code for managing logfile names.
-DEFINE_string(logfile, "/media/sda1/logfile.bfbs",
-              "Name of the logfile to write to.");
-
 DEFINE_string(config, "config.json", "Config file to use.");
 
 int main(int argc, char *argv[]) {
@@ -25,7 +22,7 @@
 
   aos::ShmEventLoop event_loop(&config.message());
 
-  aos::logger::DetachedBufferWriter writer(FLAGS_logfile);
+  aos::logger::DetachedBufferWriter writer(aos::logging::GetLogName("fbs_log"));
   aos::logger::Logger logger(&writer, &event_loop);
 
   event_loop.Run();
diff --git a/aos/logging/BUILD b/aos/logging/BUILD
index 6157e52..d56cf8e 100644
--- a/aos/logging/BUILD
+++ b/aos/logging/BUILD
@@ -20,6 +20,18 @@
     ],
 )
 
+cc_library(
+    name = "log_namer",
+    srcs = ["log_namer.cc"],
+    hdrs = ["log_namer.h"],
+    copts = ["-Wno-format-nonliteral"],
+    visibility = ["//visibility:public"],
+    deps = [
+        "//aos:configuration",
+        "@com_github_google_glog//:glog",
+    ],
+)
+
 cc_binary(
     name = "binary_log_writer",
     srcs = [
@@ -29,6 +41,7 @@
     deps = [
         ":binary_log_file",
         ":implementations",
+        ":log_namer",
         ":logging",
         "//aos:configuration",
         "//aos:die",
diff --git a/aos/logging/binary_log_writer.cc b/aos/logging/binary_log_writer.cc
index 5b1dc38..d4dea64 100644
--- a/aos/logging/binary_log_writer.cc
+++ b/aos/logging/binary_log_writer.cc
@@ -18,6 +18,7 @@
 #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"
@@ -28,141 +29,14 @@
 namespace linux_code {
 namespace {
 
-void AllocateLogName(char **filename, const char *directory) {
-  int fileindex = 0;
-  DIR *const d = opendir(directory);
-  if (d == nullptr) {
-    PDie("could not open directory %s", directory);
-  }
-  int index = 0;
-  while (true) {
-    errno = 0;
-    struct dirent *const dir = readdir(d);
-    if (dir == nullptr) {
-      if (errno == 0) {
-        break;
-      } else {
-        AOS_PLOG(FATAL, "readdir(%p) failed", d);
-      }
-    } else {
-      if (sscanf(dir->d_name, "aos_log-%d", &index) == 1) {
-        if (index >= fileindex) {
-          fileindex = index + 1;
-        }
-      }
-    }
-  }
-  closedir(d);
-
-  char previous[512];
-  ::std::string path = ::std::string(directory) + "/aos_log-current";
-  ssize_t len = ::readlink(path.c_str(), previous, sizeof(previous));
-  if (len != -1) {
-    previous[len] = '\0';
-  } else {
-    previous[0] = '\0';
-    AOS_LOG(INFO, "Could not find aos_log-current\n");
-    printf("Could not find aos_log-current\n");
-  }
-  if (asprintf(filename, "%s/aos_log-%03d", directory, fileindex) == -1) {
-    PDie("couldn't create final name");
-  }
-  AOS_LOG(INFO,
-          "Created log file (aos_log-%d) in directory (%s). Previous file "
-          "was (%s).\n",
-          fileindex, directory, previous);
-  printf("Created log file (aos_log-%d) in directory (%s). Previous file was "
-         "(%s).\n",
-         fileindex, directory, previous);
-}
-
-#ifdef AOS_ARCHITECTURE_arm_frc
-bool FoundThumbDrive(const char *path) {
-  FILE *mnt_fp = setmntent("/etc/mtab", "r");
-  if (mnt_fp == nullptr) {
-    Die("Could not open /etc/mtab");
-  }
-
-  bool found = false;
-  struct mntent mntbuf;
-  char buf[256];
-  while (!found) {
-    struct mntent *mount_list = getmntent_r(mnt_fp, &mntbuf, buf, sizeof(buf));
-    if (mount_list == nullptr) {
-      break;
-    }
-    if (strcmp(mount_list->mnt_dir, path) == 0) {
-      found = true;
-    }
-  }
-  endmntent(mnt_fp);
-  return found;
-}
-
-bool FindDevice(char *device, size_t device_size) {
-  char test_device[10];
-  for (char i = 'a'; i < 'z'; ++i) {
-    snprintf(test_device, sizeof(test_device), "/dev/sd%c", i);
-    AOS_LOG(INFO, "Trying to access %s\n", test_device);
-    if (access(test_device, F_OK) != -1) {
-      snprintf(device, device_size, "sd%c", i);
-      return true;
-    }
-  }
-  return false;
-}
-#endif
-
 int BinaryLogReaderMain() {
   InitNRT();
 
-#ifdef AOS_ARCHITECTURE_arm_frc
-  char folder[128];
-
-  {
-    char dev_name[8];
-    while (!FindDevice(dev_name, sizeof(dev_name))) {
-      AOS_LOG(INFO, "Waiting for a device\n");
-      printf("Waiting for a device\n");
-      sleep(5);
-    }
-    snprintf(folder, sizeof(folder), "/media/%s1", dev_name);
-    while (!FoundThumbDrive(folder)) {
-      AOS_LOG(INFO, "Waiting for %s\n", folder);
-      printf("Waiting for %s\n", folder);
-      sleep(1);
-    }
-    snprintf(folder, sizeof(folder), "/media/%s1/", dev_name);
-  }
-
-  if (access(folder, F_OK) == -1) {
-#else
-  const char *folder = configuration::GetLoggingDirectory();
-  if (access(folder, R_OK | W_OK) == -1) {
-#endif
-    AOS_LOG(FATAL, "folder '%s' does not exist. please create it\n", folder);
-  }
-  AOS_LOG(INFO, "logging to folder '%s'\n", folder);
-
-  char *tmp;
-  AllocateLogName(&tmp, folder);
-  char *tmp2;
-  if (asprintf(&tmp2, "%s/aos_log-current", folder) == -1) {
-    AOS_PLOG(WARNING, "couldn't create current symlink name");
-  } else {
-    if (unlink(tmp2) == -1 && (errno != EROFS && errno != ENOENT)) {
-      AOS_LOG(WARNING, "unlink('%s') failed", tmp2);
-    }
-    if (symlink(tmp, tmp2) == -1) {
-      AOS_PLOG(WARNING, "symlink('%s', '%s') failed", tmp, tmp2);
-    }
-    free(tmp2);
-  }
-  int fd = open(tmp, O_SYNC | O_APPEND | O_RDWR | O_CREAT,
+  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);
-  free(tmp);
   if (fd == -1) {
-    AOS_PLOG(FATAL, "opening file '%s' failed", tmp);
+    AOS_PLOG(FATAL, "opening file '%s' failed", file_name.c_str());
   }
   LogFileWriter writer(fd);
 
diff --git a/aos/logging/log_namer.cc b/aos/logging/log_namer.cc
new file mode 100644
index 0000000..d4584ef
--- /dev/null
+++ b/aos/logging/log_namer.cc
@@ -0,0 +1,153 @@
+#include "aos/logging/log_namer.h"
+
+#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 "aos/configuration.h"
+#include "glog/logging.h"
+
+namespace aos {
+namespace logging {
+namespace {
+void AllocateLogName(char **filename, const char *directory,
+                     const char *basename) {
+  int fileindex = 0;
+  DIR *const d = opendir(directory);
+  if (d == nullptr) {
+    PLOG(FATAL) << "could not open directory" << directory;
+  }
+  int index = 0;
+  while (true) {
+    errno = 0;
+    struct dirent *const dir = readdir(d);
+    if (dir == nullptr) {
+      if (errno == 0) {
+        break;
+      } else {
+        PLOG(FATAL) << "readdir(" << d << ") failed";
+      }
+    } else {
+      const std::string format_string = std::string(basename) + "-%d";
+      if (sscanf(dir->d_name, format_string.c_str(), &index) == 1) {
+        if (index >= fileindex) {
+          fileindex = index + 1;
+        }
+      }
+    }
+  }
+  closedir(d);
+
+  char previous[512];
+  ::std::string path = ::std::string(directory) + "/" + basename + "-current";
+  ssize_t len = ::readlink(path.c_str(), previous, sizeof(previous));
+  if (len != -1) {
+    previous[len] = '\0';
+  } else {
+    previous[0] = '\0';
+    LOG(INFO) << "Could not find " << path;
+  }
+  if (asprintf(filename, "%s/%s-%03d", directory, basename, fileindex) == -1) {
+    PLOG(FATAL) << "couldn't create final name";
+  }
+  LOG(INFO) << "Created log file (" << basename << "-" << fileindex
+            << ") in directory (" << directory
+            << "). Previous file "
+               "was ("
+            << previous << ").";
+}
+
+#ifdef AOS_ARCHITECTURE_arm_frc
+bool FoundThumbDrive(const char *path) {
+  FILE *mnt_fp = setmntent("/etc/mtab", "r");
+  if (mnt_fp == nullptr) {
+    LOG(FATAL) << "Could not open /etc/mtab";
+  }
+
+  bool found = false;
+  struct mntent mntbuf;
+  char buf[256];
+  while (!found) {
+    struct mntent *mount_list = getmntent_r(mnt_fp, &mntbuf, buf, sizeof(buf));
+    if (mount_list == nullptr) {
+      break;
+    }
+    if (strcmp(mount_list->mnt_dir, path) == 0) {
+      found = true;
+    }
+  }
+  endmntent(mnt_fp);
+  return found;
+}
+
+bool FindDevice(char *device, size_t device_size) {
+  char test_device[10];
+  for (char i = 'a'; i < 'z'; ++i) {
+    snprintf(test_device, sizeof(test_device), "/dev/sd%c", i);
+    LOG(INFO) << "Trying to access" << test_device;
+    if (access(test_device, F_OK) != -1) {
+      snprintf(device, device_size, "sd%c", i);
+      return true;
+    }
+  }
+  return false;
+}
+#endif
+}  // namespace
+
+std::string GetLogName(const char *basename) {
+#ifdef AOS_ARCHITECTURE_arm_frc
+  char folder[128];
+  {
+    char dev_name[8];
+    while (!FindDevice(dev_name, sizeof(dev_name))) {
+      LOG(INFO) <<  "Waiting for a device";
+      sleep(5);
+    }
+    snprintf(folder, sizeof(folder), "/media/%s1", dev_name);
+    while (!FoundThumbDrive(folder)) {
+      LOG(INFO) << "Waiting for" << folder;
+      sleep(1);
+    }
+    snprintf(folder, sizeof(folder), "/media/%s1/", dev_name);
+  }
+
+  if (access(folder, F_OK) == -1) {
+#else
+  const char *folder = configuration::GetLoggingDirectory();
+  if (access(folder, R_OK | W_OK) == -1) {
+#endif
+    LOG(FATAL) << "folder '" << folder << "' does not exist. please create it.";
+  }
+  LOG(INFO) << "logging to folder '" << folder << "'";
+
+  char *tmp;
+  AllocateLogName(&tmp, folder, basename);
+  char *tmp2;
+  if (asprintf(&tmp2, "%s/%s-current", folder, basename) == -1) {
+    PLOG(WARNING) << "couldn't create current symlink name";
+  } else {
+    if (unlink(tmp2) == -1 && (errno != EROFS && errno != ENOENT)) {
+      LOG(WARNING) << "unlink('" << tmp2 << "') failed";
+    }
+    if (symlink(tmp, tmp2) == -1) {
+      PLOG(WARNING) << "symlink('" << tmp << "', '" << tmp2 << "') failed";
+    }
+    free(tmp2);
+  }
+  std::string result = tmp;
+  free(tmp);
+  return result;
+}
+
+}  // namespace logging
+}  // namespace aos
diff --git a/aos/logging/log_namer.h b/aos/logging/log_namer.h
new file mode 100644
index 0000000..72abf12
--- /dev/null
+++ b/aos/logging/log_namer.h
@@ -0,0 +1,19 @@
+#ifndef AOS_LOGGING_LOG_NAMER_H_
+#define AOS_LOGGING_LOG_NAMER_H_
+
+#include <string>
+
+namespace aos {
+namespace logging {
+// Returns the correct filename to log to, blocking until the usb drive
+// filesystem mounts, incrementing the number on the end of the filename, and
+// setting up a symlink at basename-current.
+// basename is the prefix to use for the logs within the usb drive. E.g., on a
+// typical roborio setup, calling GetLogName("abc") will return a filename of
+// the form "/media/sda1/abc-123" and setup a symlink pointing to it at
+// "/media/sda1/abc-current".
+std::string GetLogName(const char *basename);
+}  // namespace logging
+}  // namespace aos
+
+#endif  // AOS_LOGGING_LOG_NAMER_H_