diff --git a/utilities/blob_db/blob_db_impl.cc b/utilities/blob_db/blob_db_impl.cc index 166f11009d3e4ca52f9c05e30f77f07b717973db..8e69a0bde77356bf32c8c7167785dd79bf4607f7 100644 --- a/utilities/blob_db/blob_db_impl.cc +++ b/utilities/blob_db/blob_db_impl.cc @@ -1050,6 +1050,14 @@ uint64_t BlobDBImpl::ExtractExpiration(const Slice& key, const Slice& value, Status BlobDBImpl::AppendBlob(const std::shared_ptr& bfile, const std::string& headerbuf, const Slice& key, const Slice& value, std::string* index_entry) { + auto size_put = BlobLogRecord::kHeaderSize + key.size() + value.size(); + if (bdb_options_.blob_dir_size > 0 && + (total_blob_space_.load() + size_put) > bdb_options_.blob_dir_size) { + if (!bdb_options_.is_fifo) { + return Status::NoSpace("Blob DB reached the maximum configured size."); + } + } + Status s; uint64_t blob_offset = 0; @@ -1073,7 +1081,6 @@ Status BlobDBImpl::AppendBlob(const std::shared_ptr& bfile, // increment blob count bfile->blob_count_++; - auto size_put = BlobLogRecord::kHeaderSize + key.size() + value.size(); bfile->file_size_ += size_put; last_period_write_ += size_put; diff --git a/utilities/blob_db/blob_db_test.cc b/utilities/blob_db/blob_db_test.cc index b4907eef1fd8fab08ec7c5ee9fe7925488ba827c..592ee609cffbed411d10728df73147ba613b1e70 100644 --- a/utilities/blob_db/blob_db_test.cc +++ b/utilities/blob_db/blob_db_test.cc @@ -653,6 +653,7 @@ TEST_F(BlobDBTest, GCOldestSimpleBlobFileWhenOutOfSpace) { Options options; options.env = mock_env_.get(); BlobDBOptions bdb_options; + bdb_options.is_fifo = true; bdb_options.blob_dir_size = 100; bdb_options.blob_file_size = 100; bdb_options.disable_background_tasks = true; @@ -870,6 +871,29 @@ TEST_F(BlobDBTest, MigrateFromPlainRocksDB) { delete db; } +// Test to verify that a NoSpace IOError Status is returned on reaching +// blob_dir_size limit. +TEST_F(BlobDBTest, OutOfSpace) { + // Use mock env to stop wall clock. + Options options; + options.env = mock_env_.get(); + BlobDBOptions bdb_options; + bdb_options.blob_dir_size = 150; + bdb_options.disable_background_tasks = true; + Open(bdb_options); + + // Each stored blob has an overhead of about 42 bytes currently. + // So a small key + a 100 byte blob should take up ~150 bytes in the db. + std::string value(100, 'v'); + ASSERT_OK(blob_db_->PutWithTTL(WriteOptions(), "key1", value, 60)); + + // Putting another blob should fail as ading it would exceed the blob_dir_size + // limit. + Status s = blob_db_->PutWithTTL(WriteOptions(), "key2", value, 60); + ASSERT_TRUE(s.IsIOError()); + ASSERT_TRUE(s.IsNoSpace()); +} + } // namespace blob_db } // namespace rocksdb