This is an automated email from the ASF dual-hosted git repository.
twice pushed a commit to branch unstable
in repository https://gitbox.apache.org/repos/asf/kvrocks.git
The following commit(s) were added to refs/heads/unstable by this push:
new 398b94794 fix(storage): don't try to commit empty write batches (#3015)
398b94794 is described below
commit 398b947949d105a6d35165153e77ac9059213aef
Author: Nathan <[email protected]>
AuthorDate: Thu Jun 5 23:00:19 2025 -0400
fix(storage): don't try to commit empty write batches (#3015)
Co-authored-by: Twice <[email protected]>
---
src/storage/storage.cc | 5 +++++
tests/cppunit/storage_test.cc | 45 +++++++++++++++++++++++++++++++++++++++++++
2 files changed, 50 insertions(+)
diff --git a/src/storage/storage.cc b/src/storage/storage.cc
index 124fbfc78..b35c9aa03 100644
--- a/src/storage/storage.cc
+++ b/src/storage/storage.cc
@@ -700,6 +700,11 @@ rocksdb::Status Storage::Write(engine::Context &ctx, const
rocksdb::WriteOptions
rocksdb::Status Storage::writeToDB(engine::Context &ctx, const
rocksdb::WriteOptions &options,
rocksdb::WriteBatch *updates) {
+ // No point trying to commit an empty write batch: in fact this will fail on
read-only DBs
+ // even if the write batch is empty.
+ if (updates->Count() == 0) {
+ return rocksdb::Status::OK();
+ }
// Put replication id logdata at the end of `updates`.
if (replid_.length() == kReplIdLength) {
updates->PutLogData(ServerLogData(kReplIdLog, replid_).Encode());
diff --git a/tests/cppunit/storage_test.cc b/tests/cppunit/storage_test.cc
index 503d2515c..96fffd335 100644
--- a/tests/cppunit/storage_test.cc
+++ b/tests/cppunit/storage_test.cc
@@ -58,3 +58,48 @@ TEST(Storage, CreateBackup) {
std::filesystem::remove_all(config.db_dir, ec);
ASSERT_TRUE(!ec);
}
+
+TEST(Storage, ReadOnlyTransactions) {
+ std::error_code ec;
+
+ Config config;
+ config.db_dir = "test_backup_dir";
+ config.slot_id_encoded = false;
+
+ std::filesystem::remove_all(config.db_dir, ec);
+ ASSERT_TRUE(!ec);
+
+ // Populate a DB with some test data so opening the read-only snapshot
succeeds
+ {
+ auto storage = std::make_unique<engine::Storage>(&config);
+ auto s = storage->Open();
+ ASSERT_TRUE(s.IsOK());
+
+ auto ctx = engine::Context(storage.get());
+ rocksdb::WriteBatch batch;
+ batch.Put("k", "v");
+ ASSERT_TRUE(storage->Write(ctx, rocksdb::WriteOptions(), &batch).ok());
+ }
+
+ // Now load that DB in in read-only mode and try to write to it
+ {
+ auto storage = std::make_unique<engine::Storage>(&config);
+ auto s = storage->Open(DBOpenMode::kDBOpenModeForReadOnly);
+ std::cout << s.Msg() << std::endl;
+ ASSERT_TRUE(s.IsOK());
+
+ auto ctx = engine::Context(storage.get());
+
+ // An empty write batch should not cause any error, even if the storage is
opened in
+ // read-only mode
+ rocksdb::WriteBatch readonly_batch;
+ ASSERT_TRUE(storage->Write(ctx, rocksdb::WriteOptions(),
&readonly_batch).ok());
+
+ rocksdb::WriteBatch read_write_batch;
+ read_write_batch.Put("k", "v");
+ ASSERT_FALSE(storage->Write(ctx, rocksdb::WriteOptions(),
&read_write_batch).ok());
+ }
+
+ std::filesystem::remove_all(config.db_dir, ec);
+ ASSERT_TRUE(!ec);
+}