metrics library: move event file location from /var/log to /var/run

The event file, which is used for communicating metric events
from chrome os to chrome, has been living in the very non-kosher
location /var/log/metrics/uma-events.  This change duplicates it
in /var/run/metrics/uma-events.  A later chrome change will pick
up the metrics from there.

I also opened crbug.com/373833 to remove the duplication once
Chrome has switched over.

BUG=chromium:361331
TEST=tested with unit tests and manually

Change-Id: I98b741798aa0481b7987f93f087239ad214b759f
Reviewed-on: https://chromium-review.googlesource.com/200091
Tested-by: Luigi Semenzato <semenzato@chromium.org>
Reviewed-by: Daniel Erat <derat@chromium.org>
Commit-Queue: Luigi Semenzato <semenzato@chromium.org>
diff --git a/init/metrics_daemon.conf b/init/metrics_daemon.conf
index 9b1e2a5..885ab0f 100644
--- a/init/metrics_daemon.conf
+++ b/init/metrics_daemon.conf
@@ -12,8 +12,11 @@
 respawn
 
 pre-start script
-  # Make the directory, but don't die on error.  Let someone else complain.
-  mkdir -p /var/lib/metrics || :
+  # Make directories, but don't die on error.  Let someone else complain.
+  LIBDIR=/var/lib/metrics
+  RUNDIR=/var/run/metrics
+  mkdir -p $LIBDIR || logger "metrics_daemon: cannot create $LIBDIR"
+  mkdir -p $RUNDIR || logger "metrics_daemon: cannot create $RUNDIR"
 end script
 
 expect fork
diff --git a/metrics_library.cc b/metrics_library.cc
index 97cb278..c71234e 100644
--- a/metrics_library.cc
+++ b/metrics_library.cc
@@ -25,6 +25,7 @@
 
 static const char kAutotestPath[] = "/var/log/metrics/autotest-events";
 static const char kUMAEventsPath[] = "/var/log/metrics/uma-events";
+static const char kNewUMAEventsPath[] = "/var/run/metrics/uma-events";
 static const char kConsentFile[] = "/home/chronos/Consent To Send Stats";
 static const int32_t kBufferSize = 1024;
 static const char kCrosEventHistogramName[] = "Platform.CrOSEvent";
@@ -171,7 +172,8 @@
   return cached_enabled_;
 }
 
-bool MetricsLibrary::SendMessageToChrome(const std::string& message) {
+bool MetricsLibrary::StoreMessageInFile(const std::string& message,
+                                        const std::string& events_file) {
   int size = static_cast<int>(message.size());
   if (size > kBufferSize) {
     LOG(ERROR) << "chrome message too big (" << size << " bytes)";
@@ -179,12 +181,12 @@
   }
   // Use libc here instead of chromium base classes because we need a UNIX fd
   // for flock.
-  int chrome_fd = HANDLE_EINTR(open(uma_events_file_.c_str(),
+  int chrome_fd = HANDLE_EINTR(open(events_file.c_str(),
                                     O_WRONLY | O_APPEND | O_CREAT,
                                     READ_WRITE_ALL_FILE_FLAGS));
   // If we failed to open it, return.
   if (chrome_fd < 0) {
-    PLOG(ERROR) << uma_events_file_ << ": open";
+    PLOG(ERROR) << events_file << ": open";
     return false;
   }
 
@@ -196,14 +198,14 @@
   // Grab an exclusive lock to protect Chrome from truncating
   // underneath us.
   if (HANDLE_EINTR(flock(chrome_fd, LOCK_EX)) < 0) {
-    PLOG(ERROR) << uma_events_file_ << ": flock";
+    PLOG(ERROR) << events_file << ": flock";
     IGNORE_EINTR(close(chrome_fd));
     return false;
   }
 
   bool success = true;
   if (WriteFileDescriptor(chrome_fd, message.c_str(), size) != size) {
-    PLOG(ERROR) << uma_events_file_ << ": write";
+    PLOG(ERROR) << events_file << ": write";
     success = false;
   }
 
@@ -212,6 +214,17 @@
   return success;
 }
 
+bool MetricsLibrary::SendMessageToChrome(const std::string& message) {
+  // TEMPORARY: store to both new and old file, to facilitate change if the
+  // Chrome side is out of sync with this.  See crbug.com/373833.
+
+  // If one store fails, we'll be cool... hey man it's OK, you know, whatever.
+  // If both stores fail, then definitely something is wrong.
+  bool success = StoreMessageInFile(message, uma_events_file_);
+  success |= StoreMessageInFile(message, new_uma_events_file_);
+  return success;
+}
+
 const std::string MetricsLibrary::FormatChromeMessage(
     const std::string& name,
     const std::string& value) {
@@ -228,6 +241,7 @@
 
 void MetricsLibrary::Init() {
   uma_events_file_ = kUMAEventsPath;
+  new_uma_events_file_ = kNewUMAEventsPath;
 }
 
 bool MetricsLibrary::SendToAutotest(const std::string& name, int value) {
diff --git a/metrics_library.h b/metrics_library.h
index 74f5de2..a3f43c5 100644
--- a/metrics_library.h
+++ b/metrics_library.h
@@ -131,8 +131,12 @@
                        char* buffer, int buffer_size,
                        bool* result);
 
-  // Sends message of size |length| to Chrome for transport to UMA and
-  // returns true on success.
+  // TEMPORARY (see crbug.com/373833).  Stores a message to Chrome in the
+  // events file.
+  bool StoreMessageInFile(const std::string& message,
+                          const std::string& events_file);
+
+  // Sends message to Chrome for transport to UMA and returns true on success.
   bool SendMessageToChrome(const std::string& message);
 
   // Serializes a name/value pair into a message buffer.
@@ -154,6 +158,7 @@
   static bool cached_enabled_;
 
   std::string uma_events_file_;
+  std::string new_uma_events_file_;  // TEMPORARY see crbug.com/373833.
   std::string consent_file_;
 
   scoped_ptr<policy::PolicyProvider> policy_provider_;