Support nodes rebooting

We have log files which span a reboot.  We want to be able to replay the
timeline across that reboot so we can run simulations and everything
else interesting.

This requires a bunch of stuff, unfortunately.

The most visible one is that we need to be able to "reboot" a node.
This means we need a way of starting it up and stopping it.  There are
now OnStartup and OnShutdown handlers in NodeEventLoopFactory to serve
this purpose, and better application context tracking to make it easier
to start and stop applications through a virtual starter.

This requires LogReader and the simulated network bridge to be
refactored to support nodes coming and going while the main application
continues to run.

From there, everything else is just a massive amount of plumbing of the
BootTimestamp through everything just short of the user.  Boot UUIDs
were put in TimeConverter so everything related to rebooting is all
nicely together.

Change-Id: I2cfb659c5764c1dd80dc66f33cfab3937159e324
Signed-off-by: Austin Schuh <austin.schuh@bluerivertech.com>
diff --git a/aos/network/testing_time_converter.h b/aos/network/testing_time_converter.h
index 5ffdc01..20b8e16 100644
--- a/aos/network/testing_time_converter.h
+++ b/aos/network/testing_time_converter.h
@@ -6,6 +6,7 @@
 #include <tuple>
 
 #include "aos/events/event_scheduler.h"
+#include "aos/events/logging/boot_timestamp.h"
 #include "aos/network/multinode_timestamp_filter.h"
 #include "aos/time/time.h"
 
@@ -34,6 +35,8 @@
   std::chrono::nanoseconds AddMonotonic(
       std::vector<logger::BootTimestamp> times);
 
+  void RebootAt(size_t node_index, distributed_clock::time_point t);
+
   // Adds a distributed to monotonic clock mapping to the queue.
   void AddNextTimestamp(distributed_clock::time_point time,
                         std::vector<logger::BootTimestamp> times);
@@ -42,6 +45,23 @@
                            std::vector<logger::BootTimestamp>>>
   NextTimestamp() override;
 
+  void set_boot_uuid(size_t node_index, size_t boot_count, UUID uuid) {
+    CHECK(boot_uuids_
+              .emplace(std::make_pair(node_index, boot_count), std ::move(uuid))
+              .second)
+        << ": Duplicate boot";
+  }
+
+  UUID boot_uuid(size_t node_index, size_t boot_count) override {
+    auto it = boot_uuids_.find(std::make_pair(node_index, boot_count));
+    if (it != boot_uuids_.end()) return it->second;
+
+    auto new_it = boot_uuids_.emplace(std::make_pair(node_index, boot_count),
+                                      UUID::Random());
+    CHECK(new_it.second);
+    return new_it.first->second;
+  }
+
  private:
   // List of timestamps.
   std::deque<std::tuple<distributed_clock::time_point,
@@ -53,6 +73,8 @@
   // The last times returned on all clocks.
   distributed_clock::time_point last_distributed_ = distributed_clock::epoch();
   std::vector<logger::BootTimestamp> last_monotonic_;
+
+  std::map<std::pair<size_t, size_t>, UUID> boot_uuids_;
 };
 
 }  // namespace message_bridge