pw_blob_store: Add BlobWriterWithBuffer
Adds a helper BlobWriterWithBuffer so users don't need to manually call
RequiredMetadataBufferSize() and allocate an array with the result.
Change-Id: I909c3290993492fc4613fdc1ad1baee9bdbb5e95
Reviewed-on: https://pigweed-review.googlesource.com/c/pigweed/pigweed/+/63164
Pigweed-Auto-Submit: Armando Montanez <amontanez@google.com>
Reviewed-by: Ewout van Bekkum <ewout@google.com>
Commit-Queue: Auto-Submit <auto-submit@pigweed.google.com.iam.gserviceaccount.com>
diff --git a/pw_blob_store/blob_store_deferred_write_test.cc b/pw_blob_store/blob_store_deferred_write_test.cc
index 161ea9f..11b335e 100644
--- a/pw_blob_store/blob_store_deferred_write_test.cc
+++ b/pw_blob_store/blob_store_deferred_write_test.cc
@@ -67,7 +67,7 @@
name, partition_, &checksum, kvs::TestKvs(), kWriteSize);
EXPECT_EQ(OkStatus(), blob.Init());
- BlobStore::DeferredWriter writer(blob, metadata_buffer_);
+ BlobStore::DeferredWriterWithBuffer writer(blob);
EXPECT_EQ(OkStatus(), writer.Open());
ByteSpan source = buffer_;
@@ -117,12 +117,9 @@
static constexpr size_t kSectorSize = 1024;
static constexpr size_t kSectorCount = 4;
static constexpr size_t kBufferSize = 2 * kSectorSize;
- static constexpr size_t kMetadataBufferSize =
- BlobStore::BlobWriter::RequiredMetadataBufferSize(0);
kvs::FakeFlashMemoryBuffer<kSectorSize, kSectorCount> flash_;
kvs::FlashPartition partition_;
- std::array<std::byte, kMetadataBufferSize> metadata_buffer_;
std::array<std::byte, kSectorCount * kSectorSize> buffer_;
};
diff --git a/pw_blob_store/blob_store_test.cc b/pw_blob_store/blob_store_test.cc
index 38f34e2..6e28c4d 100644
--- a/pw_blob_store/blob_store_test.cc
+++ b/pw_blob_store/blob_store_test.cc
@@ -77,7 +77,7 @@
kBlobTitle, partition_, &checksum, kvs::TestKvs(), kBufferSize);
EXPECT_EQ(OkStatus(), blob.Init());
- BlobStore::BlobWriter writer(blob, metadata_buffer_);
+ BlobStore::BlobWriterWithBuffer writer(blob);
EXPECT_EQ(OkStatus(), writer.Open());
ASSERT_EQ(OkStatus(), writer.Write(write_data));
EXPECT_EQ(OkStatus(), writer.Close());
@@ -151,12 +151,9 @@
static constexpr size_t kSectorSize = 2048;
static constexpr size_t kSectorCount = 2;
static constexpr size_t kBlobDataSize = (kSectorCount * kSectorSize);
- static constexpr size_t kMetadataBufferSize =
- BlobStore::BlobWriter::RequiredMetadataBufferSize(0);
kvs::FakeFlashMemoryBuffer<kSectorSize, kSectorCount> flash_;
kvs::FlashPartition partition_;
- std::array<std::byte, kMetadataBufferSize> metadata_buffer_;
std::array<std::byte, kBlobDataSize> source_buffer_;
};
@@ -175,13 +172,13 @@
"Blob_OK", partition_, nullptr, kvs::TestKvs(), kBufferSize);
ASSERT_EQ(OkStatus(), blob.Init());
- BlobStore::BlobWriter writer(blob, metadata_buffer_);
+ BlobStore::BlobWriterWithBuffer writer(blob);
ASSERT_EQ(OkStatus(), writer.Open());
EXPECT_EQ(writer.ConservativeReadLimit(), 0u);
EXPECT_EQ(writer.ConservativeWriteLimit(), kSectorSize * kSectorCount);
ASSERT_EQ(OkStatus(), writer.Close());
- BlobStore::DeferredWriter deferred_writer(blob, metadata_buffer_);
+ BlobStore::DeferredWriterWithBuffer deferred_writer(blob);
ASSERT_EQ(OkStatus(), deferred_writer.Open());
EXPECT_EQ(deferred_writer.ConservativeReadLimit(), 0u);
EXPECT_EQ(deferred_writer.ConservativeWriteLimit(), kBufferSize);
@@ -209,14 +206,14 @@
"Blob_open", partition_, nullptr, kvs::TestKvs(), kBufferSize);
EXPECT_EQ(OkStatus(), blob.Init());
- BlobStore::DeferredWriter deferred_writer(blob, metadata_buffer_);
+ BlobStore::DeferredWriterWithBuffer deferred_writer(blob);
EXPECT_EQ(false, deferred_writer.IsOpen());
EXPECT_EQ(OkStatus(), deferred_writer.Open());
EXPECT_EQ(true, deferred_writer.IsOpen());
EXPECT_EQ(OkStatus(), deferred_writer.Close());
EXPECT_EQ(false, deferred_writer.IsOpen());
- BlobStore::BlobWriter writer(blob, metadata_buffer_);
+ BlobStore::BlobWriterWithBuffer writer(blob);
EXPECT_EQ(false, writer.IsOpen());
EXPECT_EQ(OkStatus(), writer.Open());
EXPECT_EQ(true, writer.IsOpen());
@@ -239,9 +236,6 @@
InitSourceBufferToRandom(0x8675309);
WriteTestBlock();
constexpr std::string_view kFileName("my_file_1.bin");
- constexpr size_t kEncodeBufferSize =
- BlobStore::BlobWriter::RequiredMetadataBufferSize(kFileName.size());
- std::array<std::byte, kEncodeBufferSize> metadata_buffer = {};
std::array<std::byte, 64> tmp_buffer = {};
static_assert(kFileName.size() <= tmp_buffer.size());
kvs::ChecksumCrc16 checksum;
@@ -253,7 +247,7 @@
kBlobTitle, partition_, &checksum, kvs::TestKvs(), kBufferSize);
EXPECT_EQ(OkStatus(), blob.Init());
- BlobStore::BlobWriter writer(blob, metadata_buffer);
+ BlobStore::BlobWriterWithBuffer<kFileName.size()> writer(blob);
EXPECT_EQ(OkStatus(), writer.Open());
EXPECT_EQ(OkStatus(), writer.SetFileName(kFileName));
@@ -283,9 +277,6 @@
InitSourceBufferToRandom(0x8675309);
WriteTestBlock();
constexpr std::string_view kFileName("my_file_1.bin");
- constexpr size_t kEncodeBufferSize =
- BlobStore::BlobWriter::RequiredMetadataBufferSize(kFileName.size());
- std::array<std::byte, kEncodeBufferSize> metadata_buffer = {};
std::array<std::byte, 4> tmp_buffer = {};
static_assert(kFileName.size() > tmp_buffer.size());
@@ -295,7 +286,7 @@
kBlobTitle, partition_, &checksum, kvs::TestKvs(), kBufferSize);
EXPECT_EQ(OkStatus(), blob.Init());
- BlobStore::BlobWriter writer(blob, metadata_buffer);
+ BlobStore::BlobWriterWithBuffer<kFileName.size()> writer(blob);
EXPECT_EQ(OkStatus(), writer.Open());
EXPECT_EQ(OkStatus(), writer.SetFileName(kFileName));
@@ -318,9 +309,6 @@
InitSourceBufferToRandom(0x8675309);
WriteTestBlock();
constexpr std::string_view kFileName("my_file_1.bin");
- constexpr size_t kEncodeBufferSize =
- BlobStore::BlobWriter::RequiredMetadataBufferSize(2);
- std::array<std::byte, kEncodeBufferSize> metadata_buffer = {};
kvs::ChecksumCrc16 checksum;
constexpr size_t kBufferSize = 256;
@@ -328,7 +316,7 @@
kBlobTitle, partition_, &checksum, kvs::TestKvs(), kBufferSize);
EXPECT_EQ(OkStatus(), blob.Init());
- BlobStore::BlobWriter writer(blob, metadata_buffer);
+ BlobStore::BlobWriterWithBuffer<2> writer(blob);
EXPECT_EQ(OkStatus(), writer.Open());
EXPECT_EQ(Status::ResourceExhausted(), writer.SetFileName(kFileName));
@@ -340,9 +328,6 @@
WriteTestBlock();
constexpr std::string_view kFileName("sliced_cheese.png");
- constexpr size_t kEncodeBufferSize =
- BlobStore::BlobWriter::RequiredMetadataBufferSize(kFileName.size());
- std::array<std::byte, kEncodeBufferSize> metadata_buffer = {};
std::array<std::byte, 64> tmp_buffer = {};
static_assert(kFileName.size() <= tmp_buffer.size());
@@ -352,7 +337,7 @@
kBlobTitle, partition_, &checksum, kvs::TestKvs(), kBufferSize);
EXPECT_EQ(OkStatus(), blob.Init());
- BlobStore::BlobWriter writer(blob, metadata_buffer);
+ BlobStore::BlobWriterWithBuffer<kFileName.size()> writer(blob);
EXPECT_EQ(OkStatus(), writer.Open());
EXPECT_EQ(OkStatus(), writer.SetFileName(kFileName));
@@ -434,7 +419,7 @@
blob_title, partition_, &checksum, kvs::TestKvs(), kBufferSize);
EXPECT_EQ(OkStatus(), blob.Init());
- BlobStore::BlobWriter writer(blob, metadata_buffer_);
+ BlobStore::BlobWriterWithBuffer writer(blob);
EXPECT_EQ(OkStatus(), writer.Open());
EXPECT_EQ(OkStatus(), writer.Write(tmp_buffer));
@@ -460,7 +445,7 @@
"Blob_OK", partition_, nullptr, kvs::TestKvs(), kBufferSize);
EXPECT_EQ(OkStatus(), blob.Init());
- BlobStore::BlobWriter writer(blob, metadata_buffer_);
+ BlobStore::BlobWriterWithBuffer writer(blob);
EXPECT_EQ(OkStatus(), writer.Open());
EXPECT_EQ(OkStatus(), writer.Erase());
diff --git a/pw_blob_store/docs.rst b/pw_blob_store/docs.rst
index f83d4e7..4421d58 100644
--- a/pw_blob_store/docs.rst
+++ b/pw_blob_store/docs.rst
@@ -27,7 +27,7 @@
.. code-block:: cpp
- BlobStore::BlobWriter writer(my_blob_store);
+ BlobStore::BlobWriterWithBuffer writer(my_blob_store);
writer.Open();
writer.Write(my_data);
@@ -63,8 +63,8 @@
.. code-block:: cpp
- std::array<std::byte, 48> metadata_encode_buffer;
- BlobStore::BlobWriter writer(my_blob_store, metadata_encode_buffer);
+ constexpr size_t kMaxFileNameLength = 48;
+ BlobStore::BlobWriterWithBuffer<kMaxFileNameLength> writer(my_blob_store);
writer.Open();
writer.SetFileName("stonks.jpg");
writer.Write(my_data);
diff --git a/pw_blob_store/public/pw_blob_store/blob_store.h b/pw_blob_store/public/pw_blob_store/blob_store.h
index b3b8495..f519f07 100644
--- a/pw_blob_store/public/pw_blob_store/blob_store.h
+++ b/pw_blob_store/public/pw_blob_store/blob_store.h
@@ -183,12 +183,22 @@
}
};
+ template <size_t kMaxFileNameSize = 0>
+ class BlobWriterWithBuffer final : public BlobWriter {
+ public:
+ constexpr BlobWriterWithBuffer(BlobStore& store)
+ : BlobWriter(store, buffer_), buffer_() {}
+
+ private:
+ std::array<std::byte, RequiredMetadataBufferSize(kMaxFileNameSize)> buffer_;
+ };
+
// Implement the stream::Writer and erase interface with deferred action for a
// BlobStore. If not already erased, the Flush will do any needed erase.
//
// Only one writter (of either type) is allowed to be open at a time.
// Additionally, writters are unable to open if a reader is already open.
- class DeferredWriter final : public BlobWriter {
+ class DeferredWriter : public BlobWriter {
public:
constexpr DeferredWriter(BlobStore& store, ByteSpan metadata_buffer)
: BlobWriter(store, metadata_buffer) {}
@@ -208,7 +218,7 @@
// be written. This is not necessarily the full number of bytes remaining in
// the blob. Returns zero if, in the current state, Write would return
// status other than OK. See stream.h for additional details.
- size_t ConservativeLimit(LimitType limit) const override {
+ size_t ConservativeLimit(LimitType limit) const final {
if (limit == LimitType::kWrite) {
PW_DASSERT(open_);
// Deferred writes need to fit in the write buffer.
@@ -218,12 +228,22 @@
}
private:
- Status DoWrite(ConstByteSpan data) override {
+ Status DoWrite(ConstByteSpan data) final {
PW_DASSERT(open_);
return store_.AddToWriteBuffer(data);
}
};
+ template <size_t kMaxFileNameSize = 0>
+ class DeferredWriterWithBuffer final : public DeferredWriter {
+ public:
+ constexpr DeferredWriterWithBuffer(BlobStore& store)
+ : DeferredWriter(store, buffer_), buffer_() {}
+
+ private:
+ std::array<std::byte, RequiredMetadataBufferSize(kMaxFileNameSize)> buffer_;
+ };
+
// Implement stream::Reader interface for BlobStore. Multiple readers may be
// open at the same time, but readers may not be open with a writer open.
class BlobReader final : public stream::SeekableReader {