Put channel name in allocation error

The prior error didn't tell us which channel tried to build a message
which was too big.  This fixes that to make it easier to debug.

Change-Id: I56aa891d79be679db5f9932d5bb23d2f3db359c3
diff --git a/aos/events/BUILD b/aos/events/BUILD
index a905728..d35f206 100644
--- a/aos/events/BUILD
+++ b/aos/events/BUILD
@@ -64,6 +64,7 @@
         "event_loop_tmpl.h",
     ],
     hdrs = [
+        "channel_preallocated_allocator.h",
         "event_loop.h",
     ],
     visibility = ["//visibility:public"],
diff --git a/aos/events/channel_preallocated_allocator.h b/aos/events/channel_preallocated_allocator.h
new file mode 100644
index 0000000..8a5d68f
--- /dev/null
+++ b/aos/events/channel_preallocated_allocator.h
@@ -0,0 +1,77 @@
+#ifndef AOS_EVENTS_CHANNEL_PREALLOCATED_ALLOCATOR_
+#define AOS_EVENTS_CHANNEL_PREALLOCATED_ALLOCATOR_
+
+#include "aos/configuration.h"
+#include "aos/configuration_generated.h"
+#include "flatbuffers/flatbuffers.h"
+
+namespace aos {
+
+class ChannelPreallocatedAllocator : public flatbuffers::Allocator {
+ public:
+  ChannelPreallocatedAllocator(uint8_t *data, size_t size,
+                               const Channel *channel)
+      : data_(data), size_(size), channel_(channel) {}
+
+  ChannelPreallocatedAllocator(const ChannelPreallocatedAllocator &) = delete;
+  ChannelPreallocatedAllocator(ChannelPreallocatedAllocator &&other)
+      : data_(other.data_), size_(other.size_), channel_(other.channel_) {
+    CHECK(!is_allocated());
+    CHECK(!other.is_allocated());
+  }
+
+  ChannelPreallocatedAllocator &operator=(
+      const ChannelPreallocatedAllocator &) = delete;
+  ChannelPreallocatedAllocator &operator=(
+      ChannelPreallocatedAllocator &&other) {
+    CHECK(!is_allocated());
+    CHECK(!other.is_allocated());
+    data_ = other.data_;
+    size_ = other.size_;
+    channel_ = other.channel_;
+    return *this;
+  }
+  ~ChannelPreallocatedAllocator() override { CHECK(!is_allocated_); }
+
+  // TODO(austin): Read the contract for these.
+  uint8_t *allocate(size_t /*size*/) override {
+    if (is_allocated_) {
+      LOG(FATAL) << "Can't allocate more memory with a fixed size allocator.  "
+                    "Increase the memory reserved.";
+    }
+
+    is_allocated_ = true;
+    return data_;
+  }
+
+  void deallocate(uint8_t *, size_t) override { is_allocated_ = false; }
+
+  uint8_t *reallocate_downward(uint8_t * /*old_p*/, size_t /*old_size*/,
+                               size_t new_size, size_t /*in_use_back*/,
+                               size_t /*in_use_front*/) override {
+    LOG(FATAL) << "Requested " << new_size << " bytes, max size "
+               << channel_->max_size() << " for channel "
+               << configuration::CleanedChannelToString(channel_)
+               << ".  Increase the memory reserved to at least " << new_size
+               << ".";
+    return nullptr;
+  }
+
+  void Reset() { is_allocated_ = false; }
+  bool is_allocated() const { return is_allocated_; }
+
+  bool allocated() { return is_allocated_; }
+
+  size_t size() const { return size_; }
+  const uint8_t *data() const { return data_; }
+
+ private:
+  bool is_allocated_ = false;
+  uint8_t *data_;
+  size_t size_;
+  const Channel *channel_;
+};
+
+}  // namespace aos
+
+#endif  // AOS_EVENTS_CHANNEL_PREALLOCATED_ALLOCATOR_
diff --git a/aos/events/event_loop.h b/aos/events/event_loop.h
index d0ca196..4ea6724 100644
--- a/aos/events/event_loop.h
+++ b/aos/events/event_loop.h
@@ -1,5 +1,4 @@
 #ifndef AOS_EVENTS_EVENT_LOOP_H_
-
 #define AOS_EVENTS_EVENT_LOOP_H_
 
 #include <atomic>
@@ -8,6 +7,7 @@
 
 #include "aos/configuration.h"
 #include "aos/configuration_generated.h"
+#include "aos/events/channel_preallocated_allocator.h"
 #include "aos/events/event_loop_event.h"
 #include "aos/events/event_loop_generated.h"
 #include "aos/events/timing_statistics.h"
@@ -145,8 +145,9 @@
 
   // Returns the associated flatbuffers-style allocator. This must be
   // deallocated before the message is sent.
-  PreallocatedAllocator *fbb_allocator() {
-    fbb_allocator_ = PreallocatedAllocator(data(), size());
+  ChannelPreallocatedAllocator *fbb_allocator() {
+    fbb_allocator_ = ChannelPreallocatedAllocator(
+        reinterpret_cast<uint8_t *>(data()), size(), channel());
     return &fbb_allocator_;
   }
 
@@ -176,7 +177,7 @@
 
   internal::RawSenderTiming timing_;
 
-  PreallocatedAllocator fbb_allocator_{nullptr, 0};
+  ChannelPreallocatedAllocator fbb_allocator_{nullptr, 0, nullptr};
 };
 
 // Fetches the newest message from a channel.
@@ -247,7 +248,7 @@
   // builder.Send(t_builder.Finish());
   class Builder {
    public:
-    Builder(RawSender *sender, PreallocatedAllocator *allocator)
+    Builder(RawSender *sender, ChannelPreallocatedAllocator *allocator)
         : fbb_(allocator->size(), allocator),
           allocator_(allocator),
           sender_(sender) {
@@ -283,7 +284,7 @@
 
    private:
     flatbuffers::FlatBufferBuilder fbb_;
-    PreallocatedAllocator *allocator_;
+    ChannelPreallocatedAllocator *allocator_;
     RawSender *sender_;
   };