binarystore: Enable maxBinarySize Feature

Fail on write() and commit() if the result will exceed the max size.

Enabled by adding the max_binary_size to the proto buffer. The new one
takes priority and will replace existing one even if it already exists.

The `max_binary_size` is the size of the total data including the size
header. It is calculated with
```
blob_.SerializeAsString().size() +
  sizeof(boost::endian::little_uint64_t)
```

Change-Id: I28a4c7a25fa066c11510b51cdfce27df4e09d3b5
Signed-off-by: Willy Tu <wltu@google.com>
diff --git a/binarystore.hpp b/binarystore.hpp
index f46f69c..792de4a 100644
--- a/binarystore.hpp
+++ b/binarystore.hpp
@@ -8,6 +8,7 @@
 #include <blobs-ipmid/blobs.hpp>
 #include <cstdint>
 #include <memory>
+#include <optional>
 #include <string>
 #include <vector>
 
@@ -42,15 +43,27 @@
     };
 
     BinaryStore() = delete;
-    BinaryStore(const std::string& baseBlobId, std::unique_ptr<SysFile> file) :
-        baseBlobId_(baseBlobId), file_(std::move(file))
+    BinaryStore(const std::string& baseBlobId, std::unique_ptr<SysFile> file,
+                std::optional<uint32_t> maxSize = std::nullopt) :
+        baseBlobId_(baseBlobId),
+        file_(std::move(file)), maxSize(maxSize)
     {
         blob_.set_blob_base_id(baseBlobId_);
+        if (maxSize)
+        {
+            blob_.set_max_size_bytes(*maxSize);
+        }
     }
 
-    BinaryStore(std::unique_ptr<SysFile> file, bool readOnly = false) :
-        readOnly_{readOnly}, file_(std::move(file))
+    BinaryStore(std::unique_ptr<SysFile> file, bool readOnly = false,
+                std::optional<uint32_t> maxSize = std::nullopt) :
+        readOnly_{readOnly},
+        file_(std::move(file)), maxSize(maxSize)
     {
+        if (maxSize)
+        {
+            blob_.set_max_size_bytes(*maxSize);
+        }
     }
 
     ~BinaryStore() = default;
@@ -80,7 +93,8 @@
      */
     static std::unique_ptr<BinaryStoreInterface>
         createFromConfig(const std::string& baseBlobId,
-                         std::unique_ptr<SysFile> file);
+                         std::unique_ptr<SysFile> file,
+                         std::optional<uint32_t> maxSize = std::nullopt);
 
     /**
      * Helper factory method to create a BinaryStore instance
@@ -91,7 +105,8 @@
      * @returns unique_ptr to constructed BinaryStore.
      */
     static std::unique_ptr<BinaryStoreInterface>
-        createFromFile(std::unique_ptr<SysFile> file, bool readOnly = true);
+        createFromFile(std::unique_ptr<SysFile> file, bool readOnly = true,
+                       std::optional<uint32_t> maxSize = std::nullopt);
 
   private:
     /* Load the serialized data from sysfile if commit state is dirty.
@@ -107,6 +122,7 @@
     bool readOnly_ = false;
     std::unique_ptr<SysFile> file_ = nullptr;
     CommitState commitState_ = CommitState::Dirty;
+    std::optional<uint32_t> maxSize;
 };
 
 } // namespace binstore