Support reading logs without a matching peer

If you only have log files from one node, but timestamps which need data
from another node, we CHECK.  Instead, propegate this as an error up the
chain.

Change-Id: I897e584c615a2d0d49d2c2b750a1311954529220
diff --git a/aos/events/logging/logfile_utils.cc b/aos/events/logging/logfile_utils.cc
index 3f85cc7..8f0b1d4 100644
--- a/aos/events/logging/logfile_utils.cc
+++ b/aos/events/logging/logfile_utils.cc
@@ -834,12 +834,6 @@
 }
 
 Message TimestampMapper::MatchingMessageFor(const Message &message) {
-  TimestampMapper *peer =
-      CHECK_NOTNULL(nodes_data_[source_node_[message.channel_index]].peer);
-  // The queue which will have the matching data, if available.
-  std::deque<Message> *data_queue =
-      &peer->nodes_data_[node()].channels[message.channel_index].messages;
-
   // Figure out what queue index we are looking for.
   CHECK(message.data.message().has_remote_queue_index());
   const uint32_t remote_queue_index =
@@ -853,6 +847,23 @@
   const realtime_clock::time_point realtime_remote_time(
       std::chrono::nanoseconds(message.data.message().realtime_remote_time()));
 
+  TimestampMapper *peer = nodes_data_[source_node_[message.channel_index]].peer;
+
+  // We only register the peers which we have data for.  So, if we are being
+  // asked to pull a timestamp from a peer which doesn't exist, return an empty
+  // message.
+  if (peer == nullptr) {
+    return Message{
+        .channel_index = message.channel_index,
+        .queue_index = remote_queue_index,
+        .timestamp = monotonic_remote_time,
+        .data = SizePrefixedFlatbufferVector<MessageHeader>::Empty()};
+  }
+
+  // The queue which will have the matching data, if available.
+  std::deque<Message> *data_queue =
+      &peer->nodes_data_[node()].channels[message.channel_index].messages;
+
   peer->QueueUntil(monotonic_remote_time);
 
   if (data_queue->empty()) {