@nxtedition/rocksdb 7.0.12 → 7.0.13

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (105) hide show
  1. package/deps/rocksdb/rocksdb/CMakeLists.txt +1 -0
  2. package/deps/rocksdb/rocksdb/Makefile +3 -0
  3. package/deps/rocksdb/rocksdb/TARGETS +6 -0
  4. package/deps/rocksdb/rocksdb/cache/cache_bench_tool.cc +12 -7
  5. package/deps/rocksdb/rocksdb/cache/cache_key.h +2 -0
  6. package/deps/rocksdb/rocksdb/cache/fast_lru_cache.cc +18 -6
  7. package/deps/rocksdb/rocksdb/cache/fast_lru_cache.h +13 -5
  8. package/deps/rocksdb/rocksdb/cache/lru_cache_test.cc +89 -0
  9. package/deps/rocksdb/rocksdb/db/blob/blob_file_reader.cc +18 -28
  10. package/deps/rocksdb/rocksdb/db/blob/blob_source.cc +147 -2
  11. package/deps/rocksdb/rocksdb/db/blob/blob_source.h +30 -0
  12. package/deps/rocksdb/rocksdb/db/blob/blob_source_test.cc +403 -30
  13. package/deps/rocksdb/rocksdb/db/c.cc +159 -5
  14. package/deps/rocksdb/rocksdb/db/c_test.c +108 -0
  15. package/deps/rocksdb/rocksdb/db/column_family.cc +2 -1
  16. package/deps/rocksdb/rocksdb/db/column_family.h +7 -5
  17. package/deps/rocksdb/rocksdb/db/compaction/compaction.cc +22 -0
  18. package/deps/rocksdb/rocksdb/db/compaction/compaction.h +8 -0
  19. package/deps/rocksdb/rocksdb/db/compaction/compaction_iterator.cc +6 -3
  20. package/deps/rocksdb/rocksdb/db/compaction/compaction_iterator_test.cc +15 -0
  21. package/deps/rocksdb/rocksdb/db/compaction/compaction_job.cc +35 -2
  22. package/deps/rocksdb/rocksdb/db/compaction/compaction_picker_test.cc +55 -0
  23. package/deps/rocksdb/rocksdb/db/db_basic_test.cc +21 -19
  24. package/deps/rocksdb/rocksdb/db/db_compaction_test.cc +60 -1
  25. package/deps/rocksdb/rocksdb/db/db_flush_test.cc +247 -6
  26. package/deps/rocksdb/rocksdb/db/db_impl/compacted_db_impl.h +10 -0
  27. package/deps/rocksdb/rocksdb/db/db_impl/db_impl.cc +6 -33
  28. package/deps/rocksdb/rocksdb/db/db_impl/db_impl.h +10 -2
  29. package/deps/rocksdb/rocksdb/db/db_impl/db_impl_compaction_flush.cc +7 -15
  30. package/deps/rocksdb/rocksdb/db/db_impl/db_impl_files.cc +17 -3
  31. package/deps/rocksdb/rocksdb/db/db_impl/db_impl_open.cc +10 -4
  32. package/deps/rocksdb/rocksdb/db/db_impl/db_impl_readonly.h +9 -0
  33. package/deps/rocksdb/rocksdb/db/db_impl/db_impl_secondary.h +8 -0
  34. package/deps/rocksdb/rocksdb/db/db_impl/db_impl_write.cc +32 -0
  35. package/deps/rocksdb/rocksdb/db/db_inplace_update_test.cc +54 -0
  36. package/deps/rocksdb/rocksdb/db/db_iter.cc +50 -2
  37. package/deps/rocksdb/rocksdb/db/db_iter.h +2 -0
  38. package/deps/rocksdb/rocksdb/db/db_kv_checksum_test.cc +56 -25
  39. package/deps/rocksdb/rocksdb/db/db_options_test.cc +1 -1
  40. package/deps/rocksdb/rocksdb/db/db_test.cc +9 -0
  41. package/deps/rocksdb/rocksdb/db/flush_job.cc +17 -8
  42. package/deps/rocksdb/rocksdb/db/flush_job.h +1 -1
  43. package/deps/rocksdb/rocksdb/db/log_writer.h +1 -1
  44. package/deps/rocksdb/rocksdb/db/memtable.cc +103 -93
  45. package/deps/rocksdb/rocksdb/db/memtable.h +3 -3
  46. package/deps/rocksdb/rocksdb/db/merge_helper.cc +7 -2
  47. package/deps/rocksdb/rocksdb/db/version_edit.h +1 -1
  48. package/deps/rocksdb/rocksdb/db/version_set.cc +13 -5
  49. package/deps/rocksdb/rocksdb/db/version_set_sync_and_async.h +5 -0
  50. package/deps/rocksdb/rocksdb/db/wide/db_wide_basic_test.cc +213 -0
  51. package/deps/rocksdb/rocksdb/db/wide/wide_column_serialization.cc +6 -7
  52. package/deps/rocksdb/rocksdb/db/wide/wide_column_serialization_test.cc +16 -0
  53. package/deps/rocksdb/rocksdb/db/write_batch.cc +154 -2
  54. package/deps/rocksdb/rocksdb/db/write_batch_internal.h +3 -0
  55. package/deps/rocksdb/rocksdb/db_stress_tool/db_stress_common.h +4 -0
  56. package/deps/rocksdb/rocksdb/db_stress_tool/db_stress_compaction_filter.h +8 -3
  57. package/deps/rocksdb/rocksdb/db_stress_tool/db_stress_gflags.cc +21 -1
  58. package/deps/rocksdb/rocksdb/db_stress_tool/db_stress_test_base.cc +31 -4
  59. package/deps/rocksdb/rocksdb/env/env_test.cc +2 -2
  60. package/deps/rocksdb/rocksdb/env/fs_remap.cc +4 -0
  61. package/deps/rocksdb/rocksdb/file/random_access_file_reader.h +1 -1
  62. package/deps/rocksdb/rocksdb/include/rocksdb/advanced_options.h +17 -0
  63. package/deps/rocksdb/rocksdb/include/rocksdb/c.h +136 -0
  64. package/deps/rocksdb/rocksdb/include/rocksdb/db.h +6 -0
  65. package/deps/rocksdb/rocksdb/include/rocksdb/env.h +1 -1
  66. package/deps/rocksdb/rocksdb/include/rocksdb/file_system.h +1 -1
  67. package/deps/rocksdb/rocksdb/include/rocksdb/options.h +23 -23
  68. package/deps/rocksdb/rocksdb/include/rocksdb/utilities/stackable_db.h +7 -0
  69. package/deps/rocksdb/rocksdb/include/rocksdb/utilities/write_batch_with_index.h +11 -0
  70. package/deps/rocksdb/rocksdb/include/rocksdb/write_batch.h +14 -0
  71. package/deps/rocksdb/rocksdb/include/rocksdb/write_batch_base.h +5 -0
  72. package/deps/rocksdb/rocksdb/options/cf_options.cc +7 -0
  73. package/deps/rocksdb/rocksdb/options/cf_options.h +19 -0
  74. package/deps/rocksdb/rocksdb/options/db_options.cc +1 -6
  75. package/deps/rocksdb/rocksdb/options/db_options.h +0 -1
  76. package/deps/rocksdb/rocksdb/options/options.cc +4 -1
  77. package/deps/rocksdb/rocksdb/options/options_helper.cc +2 -0
  78. package/deps/rocksdb/rocksdb/options/options_settable_test.cc +1 -0
  79. package/deps/rocksdb/rocksdb/options/options_test.cc +4 -4
  80. package/deps/rocksdb/rocksdb/port/win/env_win.cc +1 -1
  81. package/deps/rocksdb/rocksdb/src.mk +1 -0
  82. package/deps/rocksdb/rocksdb/table/block_based/block.cc +5 -3
  83. package/deps/rocksdb/rocksdb/table/block_based/block_based_table_factory.cc +2 -2
  84. package/deps/rocksdb/rocksdb/table/block_based/block_based_table_reader.cc +16 -9
  85. package/deps/rocksdb/rocksdb/table/block_based/block_based_table_reader.h +4 -2
  86. package/deps/rocksdb/rocksdb/table/block_based/block_based_table_reader_sync_and_async.h +1 -1
  87. package/deps/rocksdb/rocksdb/table/block_based/filter_block.h +13 -7
  88. package/deps/rocksdb/rocksdb/table/block_based/filter_block_reader_common.cc +7 -3
  89. package/deps/rocksdb/rocksdb/table/block_based/filter_block_reader_common.h +4 -2
  90. package/deps/rocksdb/rocksdb/table/block_based/full_filter_block.cc +28 -17
  91. package/deps/rocksdb/rocksdb/table/block_based/full_filter_block.h +15 -9
  92. package/deps/rocksdb/rocksdb/table/block_based/full_filter_block_test.cc +32 -16
  93. package/deps/rocksdb/rocksdb/table/block_based/partitioned_filter_block.cc +28 -18
  94. package/deps/rocksdb/rocksdb/table/block_based/partitioned_filter_block.h +15 -6
  95. package/deps/rocksdb/rocksdb/table/block_based/partitioned_filter_block_test.cc +16 -7
  96. package/deps/rocksdb/rocksdb/table/block_fetcher.cc +1 -1
  97. package/deps/rocksdb/rocksdb/table/get_context.cc +27 -6
  98. package/deps/rocksdb/rocksdb/table/get_context.h +2 -0
  99. package/deps/rocksdb/rocksdb/table/table_test.cc +5 -5
  100. package/deps/rocksdb/rocksdb/tools/db_bench_tool.cc +46 -0
  101. package/deps/rocksdb/rocksdb/util/filter_bench.cc +3 -1
  102. package/deps/rocksdb/rocksdb/util/mutexlock.h +1 -1
  103. package/deps/rocksdb/rocksdb/utilities/backup/backup_engine_test.cc +1 -1
  104. package/package.json +1 -1
  105. package/prebuilds/linux-x64/node.napi.node +0 -0
@@ -12,6 +12,7 @@
12
12
  #include <string>
13
13
 
14
14
  #include "db/blob/blob_file_cache.h"
15
+ #include "db/blob/blob_file_reader.h"
15
16
  #include "db/blob/blob_log_format.h"
16
17
  #include "db/blob/blob_log_writer.h"
17
18
  #include "db/db_test_util.h"
@@ -108,32 +109,34 @@ class BlobSourceTest : public DBTestBase {
108
109
  protected:
109
110
  public:
110
111
  explicit BlobSourceTest()
111
- : DBTestBase("blob_source_test", /*env_do_fsync=*/true) {}
112
+ : DBTestBase("blob_source_test", /*env_do_fsync=*/true) {
113
+ options_.env = env_;
114
+ options_.enable_blob_files = true;
115
+ options_.create_if_missing = true;
116
+
117
+ LRUCacheOptions co;
118
+ co.capacity = 2048;
119
+ co.num_shard_bits = 2;
120
+ co.metadata_charge_policy = kDontChargeCacheMetadata;
121
+ options_.blob_cache = NewLRUCache(co);
122
+ options_.lowest_used_cache_tier = CacheTier::kVolatileTier;
123
+
124
+ assert(db_->GetDbIdentity(db_id_).ok());
125
+ assert(db_->GetDbSessionId(db_session_id_).ok());
126
+ }
127
+
128
+ Options options_;
129
+ std::string db_id_;
130
+ std::string db_session_id_;
112
131
  };
113
132
 
114
133
  TEST_F(BlobSourceTest, GetBlobsFromCache) {
115
- Options options;
116
- options.env = env_;
117
- options.cf_paths.emplace_back(
134
+ options_.cf_paths.emplace_back(
118
135
  test::PerThreadDBPath(env_, "BlobSourceTest_GetBlobsFromCache"), 0);
119
- options.enable_blob_files = true;
120
-
121
- LRUCacheOptions co;
122
- co.capacity = 2048;
123
- co.num_shard_bits = 2;
124
- co.metadata_charge_policy = kDontChargeCacheMetadata;
125
- options.blob_cache = NewLRUCache(co);
126
- options.lowest_used_cache_tier = CacheTier::kVolatileTier;
127
-
128
- Reopen(options);
129
136
 
130
- std::string db_id;
131
- ASSERT_OK(db_->GetDbIdentity(db_id));
137
+ DestroyAndReopen(options_);
132
138
 
133
- std::string db_session_id;
134
- ASSERT_OK(db_->GetDbSessionId(db_session_id));
135
-
136
- ImmutableOptions immutable_options(options);
139
+ ImmutableOptions immutable_options(options_);
137
140
 
138
141
  constexpr uint32_t column_family_id = 1;
139
142
  constexpr bool has_ttl = false;
@@ -178,7 +181,7 @@ TEST_F(BlobSourceTest, GetBlobsFromCache) {
178
181
  backing_cache.get(), &immutable_options, &file_options, column_family_id,
179
182
  blob_file_read_hist, nullptr /*IOTracer*/));
180
183
 
181
- BlobSource blob_source(&immutable_options, db_id, db_session_id,
184
+ BlobSource blob_source(&immutable_options, db_id_, db_session_id_,
182
185
  blob_file_cache.get());
183
186
 
184
187
  ReadOptions read_options;
@@ -203,7 +206,7 @@ TEST_F(BlobSourceTest, GetBlobsFromCache) {
203
206
  &bytes_read));
204
207
  ASSERT_EQ(values[i], blobs[i]);
205
208
  ASSERT_EQ(bytes_read,
206
- blob_sizes[i] + keys[i].size() + BlobLogRecord::kHeaderSize);
209
+ BlobLogRecord::kHeaderSize + keys[i].size() + blob_sizes[i]);
207
210
 
208
211
  ASSERT_FALSE(blob_source.TEST_BlobInCache(blob_file_number, file_size,
209
212
  blob_offsets[i]));
@@ -221,7 +224,7 @@ TEST_F(BlobSourceTest, GetBlobsFromCache) {
221
224
  &bytes_read));
222
225
  ASSERT_EQ(values[i], blobs[i]);
223
226
  ASSERT_EQ(bytes_read,
224
- blob_sizes[i] + keys[i].size() + BlobLogRecord::kHeaderSize);
227
+ BlobLogRecord::kHeaderSize + keys[i].size() + blob_sizes[i]);
225
228
 
226
229
  ASSERT_TRUE(blob_source.TEST_BlobInCache(blob_file_number, file_size,
227
230
  blob_offsets[i]));
@@ -238,7 +241,8 @@ TEST_F(BlobSourceTest, GetBlobsFromCache) {
238
241
  kNoCompression, prefetch_buffer, &values[i],
239
242
  &bytes_read));
240
243
  ASSERT_EQ(values[i], blobs[i]);
241
- ASSERT_EQ(bytes_read, blob_sizes[i]);
244
+ ASSERT_EQ(bytes_read,
245
+ BlobLogRecord::kHeaderSize + keys[i].size() + blob_sizes[i]);
242
246
 
243
247
  ASSERT_TRUE(blob_source.TEST_BlobInCache(blob_file_number, file_size,
244
248
  blob_offsets[i]));
@@ -256,14 +260,15 @@ TEST_F(BlobSourceTest, GetBlobsFromCache) {
256
260
  kNoCompression, prefetch_buffer, &values[i],
257
261
  &bytes_read));
258
262
  ASSERT_EQ(values[i], blobs[i]);
259
- ASSERT_EQ(bytes_read, blob_sizes[i]);
263
+ ASSERT_EQ(bytes_read,
264
+ BlobLogRecord::kHeaderSize + keys[i].size() + blob_sizes[i]);
260
265
 
261
266
  ASSERT_TRUE(blob_source.TEST_BlobInCache(blob_file_number, file_size,
262
267
  blob_offsets[i]));
263
268
  }
264
269
  }
265
270
 
266
- options.blob_cache->EraseUnRefEntries();
271
+ options_.blob_cache->EraseUnRefEntries();
267
272
 
268
273
  {
269
274
  // Cache-only GetBlob
@@ -277,10 +282,12 @@ TEST_F(BlobSourceTest, GetBlobsFromCache) {
277
282
  ASSERT_FALSE(blob_source.TEST_BlobInCache(blob_file_number, file_size,
278
283
  blob_offsets[i]));
279
284
 
280
- ASSERT_NOK(blob_source.GetBlob(read_options, keys[i], blob_file_number,
281
- blob_offsets[i], file_size, blob_sizes[i],
282
- kNoCompression, prefetch_buffer,
283
- &values[i], &bytes_read));
285
+ ASSERT_TRUE(blob_source
286
+ .GetBlob(read_options, keys[i], blob_file_number,
287
+ blob_offsets[i], file_size, blob_sizes[i],
288
+ kNoCompression, prefetch_buffer, &values[i],
289
+ &bytes_read)
290
+ .IsIncomplete());
284
291
  ASSERT_TRUE(values[i].empty());
285
292
  ASSERT_EQ(bytes_read, 0);
286
293
 
@@ -288,6 +295,372 @@ TEST_F(BlobSourceTest, GetBlobsFromCache) {
288
295
  blob_offsets[i]));
289
296
  }
290
297
  }
298
+
299
+ {
300
+ // GetBlob from non-existing file
301
+ std::vector<PinnableSlice> values(keys.size());
302
+ uint64_t bytes_read = 0;
303
+ uint64_t file_number = 100; // non-existing file
304
+
305
+ read_options.read_tier = ReadTier::kReadAllTier;
306
+ read_options.fill_cache = true;
307
+
308
+ for (size_t i = 0; i < num_blobs; ++i) {
309
+ ASSERT_FALSE(blob_source.TEST_BlobInCache(file_number, file_size,
310
+ blob_offsets[i]));
311
+
312
+ ASSERT_TRUE(blob_source
313
+ .GetBlob(read_options, keys[i], file_number,
314
+ blob_offsets[i], file_size, blob_sizes[i],
315
+ kNoCompression, prefetch_buffer, &values[i],
316
+ &bytes_read)
317
+ .IsIOError());
318
+ ASSERT_TRUE(values[i].empty());
319
+ ASSERT_EQ(bytes_read, 0);
320
+
321
+ ASSERT_FALSE(blob_source.TEST_BlobInCache(file_number, file_size,
322
+ blob_offsets[i]));
323
+ }
324
+ }
325
+ }
326
+
327
+ TEST_F(BlobSourceTest, GetCompressedBlobs) {
328
+ if (!Snappy_Supported()) {
329
+ return;
330
+ }
331
+
332
+ const CompressionType compression = kSnappyCompression;
333
+
334
+ options_.cf_paths.emplace_back(
335
+ test::PerThreadDBPath(env_, "BlobSourceTest_GetCompressedBlobs"), 0);
336
+
337
+ DestroyAndReopen(options_);
338
+
339
+ ImmutableOptions immutable_options(options_);
340
+
341
+ constexpr uint32_t column_family_id = 1;
342
+ constexpr bool has_ttl = false;
343
+ constexpr ExpirationRange expiration_range;
344
+ constexpr size_t num_blobs = 256;
345
+
346
+ std::vector<std::string> key_strs;
347
+ std::vector<std::string> blob_strs;
348
+
349
+ for (size_t i = 0; i < num_blobs; ++i) {
350
+ key_strs.push_back("key" + std::to_string(i));
351
+ blob_strs.push_back("blob" + std::to_string(i));
352
+ }
353
+
354
+ std::vector<Slice> keys;
355
+ std::vector<Slice> blobs;
356
+
357
+ for (size_t i = 0; i < num_blobs; ++i) {
358
+ keys.push_back({key_strs[i]});
359
+ blobs.push_back({blob_strs[i]});
360
+ }
361
+
362
+ std::vector<uint64_t> blob_offsets(keys.size());
363
+ std::vector<uint64_t> blob_sizes(keys.size());
364
+
365
+ constexpr size_t capacity = 1024;
366
+ auto backing_cache = NewLRUCache(capacity); // Blob file cache
367
+
368
+ FileOptions file_options;
369
+ std::unique_ptr<BlobFileCache> blob_file_cache(new BlobFileCache(
370
+ backing_cache.get(), &immutable_options, &file_options, column_family_id,
371
+ nullptr /*HistogramImpl*/, nullptr /*IOTracer*/));
372
+
373
+ BlobSource blob_source(&immutable_options, db_id_, db_session_id_,
374
+ blob_file_cache.get());
375
+
376
+ ReadOptions read_options;
377
+ read_options.verify_checksums = true;
378
+
379
+ uint64_t bytes_read = 0;
380
+ std::vector<PinnableSlice> values(keys.size());
381
+
382
+ {
383
+ // Snappy Compression
384
+ const uint64_t file_number = 1;
385
+
386
+ read_options.read_tier = ReadTier::kReadAllTier;
387
+
388
+ WriteBlobFile(immutable_options, column_family_id, has_ttl,
389
+ expiration_range, expiration_range, file_number, keys, blobs,
390
+ compression, blob_offsets, blob_sizes);
391
+
392
+ CacheHandleGuard<BlobFileReader> blob_file_reader;
393
+ ASSERT_OK(blob_source.GetBlobFileReader(file_number, &blob_file_reader));
394
+ ASSERT_NE(blob_file_reader.GetValue(), nullptr);
395
+
396
+ const uint64_t file_size = blob_file_reader.GetValue()->GetFileSize();
397
+ ASSERT_EQ(blob_file_reader.GetValue()->GetCompressionType(), compression);
398
+
399
+ for (size_t i = 0; i < num_blobs; ++i) {
400
+ ASSERT_NE(blobs[i].size() /*uncompressed size*/,
401
+ blob_sizes[i] /*compressed size*/);
402
+ }
403
+
404
+ read_options.fill_cache = true;
405
+ read_options.read_tier = ReadTier::kReadAllTier;
406
+
407
+ for (size_t i = 0; i < num_blobs; ++i) {
408
+ ASSERT_FALSE(blob_source.TEST_BlobInCache(file_number, file_size,
409
+ blob_offsets[i]));
410
+ ASSERT_OK(blob_source.GetBlob(read_options, keys[i], file_number,
411
+ blob_offsets[i], file_size, blob_sizes[i],
412
+ compression, nullptr /*prefetch_buffer*/,
413
+ &values[i], &bytes_read));
414
+ ASSERT_EQ(values[i], blobs[i] /*uncompressed blob*/);
415
+ ASSERT_NE(values[i].size(), blob_sizes[i] /*compressed size*/);
416
+ ASSERT_EQ(bytes_read,
417
+ BlobLogRecord::kHeaderSize + keys[i].size() + blob_sizes[i]);
418
+
419
+ ASSERT_TRUE(blob_source.TEST_BlobInCache(file_number, file_size,
420
+ blob_offsets[i]));
421
+ }
422
+
423
+ read_options.read_tier = ReadTier::kBlockCacheTier;
424
+
425
+ for (size_t i = 0; i < num_blobs; ++i) {
426
+ ASSERT_TRUE(blob_source.TEST_BlobInCache(file_number, file_size,
427
+ blob_offsets[i]));
428
+
429
+ // Compressed blob size is passed in GetBlob
430
+ ASSERT_OK(blob_source.GetBlob(read_options, keys[i], file_number,
431
+ blob_offsets[i], file_size, blob_sizes[i],
432
+ compression, nullptr /*prefetch_buffer*/,
433
+ &values[i], &bytes_read));
434
+ ASSERT_EQ(values[i], blobs[i] /*uncompressed blob*/);
435
+ ASSERT_NE(values[i].size(), blob_sizes[i] /*compressed size*/);
436
+ ASSERT_EQ(bytes_read,
437
+ BlobLogRecord::kHeaderSize + keys[i].size() + blob_sizes[i]);
438
+
439
+ ASSERT_TRUE(blob_source.TEST_BlobInCache(file_number, file_size,
440
+ blob_offsets[i]));
441
+ }
442
+ }
443
+ }
444
+
445
+ TEST_F(BlobSourceTest, MultiGetBlobsFromCache) {
446
+ options_.cf_paths.emplace_back(
447
+ test::PerThreadDBPath(env_, "BlobSourceTest_MultiGetBlobsFromCache"), 0);
448
+
449
+ DestroyAndReopen(options_);
450
+
451
+ ImmutableOptions immutable_options(options_);
452
+
453
+ constexpr uint32_t column_family_id = 1;
454
+ constexpr bool has_ttl = false;
455
+ constexpr ExpirationRange expiration_range;
456
+ constexpr uint64_t blob_file_number = 1;
457
+ constexpr size_t num_blobs = 16;
458
+
459
+ std::vector<std::string> key_strs;
460
+ std::vector<std::string> blob_strs;
461
+
462
+ for (size_t i = 0; i < num_blobs; ++i) {
463
+ key_strs.push_back("key" + std::to_string(i));
464
+ blob_strs.push_back("blob" + std::to_string(i));
465
+ }
466
+
467
+ std::vector<Slice> keys;
468
+ std::vector<Slice> blobs;
469
+
470
+ uint64_t file_size = BlobLogHeader::kSize;
471
+ for (size_t i = 0; i < num_blobs; ++i) {
472
+ keys.push_back({key_strs[i]});
473
+ blobs.push_back({blob_strs[i]});
474
+ file_size += BlobLogRecord::kHeaderSize + keys[i].size() + blobs[i].size();
475
+ }
476
+ file_size += BlobLogFooter::kSize;
477
+
478
+ std::vector<uint64_t> blob_offsets(keys.size());
479
+ std::vector<uint64_t> blob_sizes(keys.size());
480
+
481
+ WriteBlobFile(immutable_options, column_family_id, has_ttl, expiration_range,
482
+ expiration_range, blob_file_number, keys, blobs, kNoCompression,
483
+ blob_offsets, blob_sizes);
484
+
485
+ constexpr size_t capacity = 10;
486
+ std::shared_ptr<Cache> backing_cache =
487
+ NewLRUCache(capacity); // Blob file cache
488
+
489
+ FileOptions file_options;
490
+ constexpr HistogramImpl* blob_file_read_hist = nullptr;
491
+
492
+ std::unique_ptr<BlobFileCache> blob_file_cache(new BlobFileCache(
493
+ backing_cache.get(), &immutable_options, &file_options, column_family_id,
494
+ blob_file_read_hist, nullptr /*IOTracer*/));
495
+
496
+ BlobSource blob_source(&immutable_options, db_id_, db_session_id_,
497
+ blob_file_cache.get());
498
+
499
+ ReadOptions read_options;
500
+ read_options.verify_checksums = true;
501
+
502
+ constexpr FilePrefetchBuffer* prefetch_buffer = nullptr;
503
+
504
+ {
505
+ // MultiGetBlob
506
+ uint64_t bytes_read = 0;
507
+
508
+ autovector<std::reference_wrapper<const Slice>> key_refs;
509
+ autovector<uint64_t> offsets;
510
+ autovector<uint64_t> sizes;
511
+ std::array<Status, num_blobs> statuses_buf;
512
+ autovector<Status*> statuses;
513
+ std::array<PinnableSlice, num_blobs> value_buf;
514
+ autovector<PinnableSlice*> values;
515
+
516
+ for (size_t i = 0; i < num_blobs; i += 2) { // even index
517
+ key_refs.emplace_back(std::cref(keys[i]));
518
+ offsets.push_back(blob_offsets[i]);
519
+ sizes.push_back(blob_sizes[i]);
520
+ statuses.push_back(&statuses_buf[i]);
521
+ values.push_back(&value_buf[i]);
522
+ ASSERT_FALSE(blob_source.TEST_BlobInCache(blob_file_number, file_size,
523
+ blob_offsets[i]));
524
+ }
525
+
526
+ read_options.fill_cache = true;
527
+ read_options.read_tier = ReadTier::kReadAllTier;
528
+
529
+ // Get half of blobs
530
+ blob_source.MultiGetBlob(read_options, key_refs, blob_file_number,
531
+ file_size, offsets, sizes, statuses, values,
532
+ &bytes_read);
533
+
534
+ for (size_t i = 0; i < num_blobs; ++i) {
535
+ if (i % 2 == 0) {
536
+ ASSERT_OK(statuses_buf[i]);
537
+ ASSERT_EQ(value_buf[i], blobs[i]);
538
+ ASSERT_TRUE(blob_source.TEST_BlobInCache(blob_file_number, file_size,
539
+ blob_offsets[i]));
540
+ } else {
541
+ statuses_buf[i].PermitUncheckedError();
542
+ ASSERT_TRUE(value_buf[i].empty());
543
+ ASSERT_FALSE(blob_source.TEST_BlobInCache(blob_file_number, file_size,
544
+ blob_offsets[i]));
545
+ }
546
+ }
547
+
548
+ // Get the rest of blobs
549
+ for (size_t i = 1; i < num_blobs; i += 2) { // odd index
550
+ ASSERT_FALSE(blob_source.TEST_BlobInCache(blob_file_number, file_size,
551
+ blob_offsets[i]));
552
+
553
+ ASSERT_OK(blob_source.GetBlob(read_options, keys[i], blob_file_number,
554
+ blob_offsets[i], file_size, blob_sizes[i],
555
+ kNoCompression, prefetch_buffer,
556
+ &value_buf[i], &bytes_read));
557
+ ASSERT_EQ(value_buf[i], blobs[i]);
558
+ ASSERT_EQ(bytes_read,
559
+ BlobLogRecord::kHeaderSize + keys[i].size() + blob_sizes[i]);
560
+
561
+ ASSERT_TRUE(blob_source.TEST_BlobInCache(blob_file_number, file_size,
562
+ blob_offsets[i]));
563
+ }
564
+
565
+ // Cache-only MultiGetBlob
566
+ read_options.read_tier = ReadTier::kBlockCacheTier;
567
+
568
+ key_refs.clear();
569
+ offsets.clear();
570
+ sizes.clear();
571
+ statuses.clear();
572
+ values.clear();
573
+ for (size_t i = 0; i < num_blobs; ++i) {
574
+ key_refs.emplace_back(std::cref(keys[i]));
575
+ offsets.push_back(blob_offsets[i]);
576
+ sizes.push_back(blob_sizes[i]);
577
+ statuses.push_back(&statuses_buf[i]);
578
+ values.push_back(&value_buf[i]);
579
+ }
580
+
581
+ blob_source.MultiGetBlob(read_options, key_refs, blob_file_number,
582
+ file_size, offsets, sizes, statuses, values,
583
+ &bytes_read);
584
+
585
+ for (size_t i = 0; i < num_blobs; ++i) {
586
+ ASSERT_OK(statuses_buf[i]);
587
+ ASSERT_EQ(value_buf[i], blobs[i]);
588
+ ASSERT_TRUE(blob_source.TEST_BlobInCache(blob_file_number, file_size,
589
+ blob_offsets[i]));
590
+ }
591
+ }
592
+
593
+ options_.blob_cache->EraseUnRefEntries();
594
+
595
+ {
596
+ // Cache-only MultiGetBlob
597
+ uint64_t bytes_read = 0;
598
+ read_options.read_tier = ReadTier::kBlockCacheTier;
599
+
600
+ autovector<std::reference_wrapper<const Slice>> key_refs;
601
+ autovector<uint64_t> offsets;
602
+ autovector<uint64_t> sizes;
603
+ std::array<Status, num_blobs> statuses_buf;
604
+ autovector<Status*> statuses;
605
+ std::array<PinnableSlice, num_blobs> value_buf;
606
+ autovector<PinnableSlice*> values;
607
+
608
+ for (size_t i = 0; i < num_blobs; i++) {
609
+ key_refs.emplace_back(std::cref(keys[i]));
610
+ offsets.push_back(blob_offsets[i]);
611
+ sizes.push_back(blob_sizes[i]);
612
+ statuses.push_back(&statuses_buf[i]);
613
+ values.push_back(&value_buf[i]);
614
+ ASSERT_FALSE(blob_source.TEST_BlobInCache(blob_file_number, file_size,
615
+ blob_offsets[i]));
616
+ }
617
+
618
+ blob_source.MultiGetBlob(read_options, key_refs, blob_file_number,
619
+ file_size, offsets, sizes, statuses, values,
620
+ &bytes_read);
621
+
622
+ for (size_t i = 0; i < num_blobs; ++i) {
623
+ ASSERT_TRUE(statuses_buf[i].IsIncomplete());
624
+ ASSERT_TRUE(value_buf[i].empty());
625
+ ASSERT_FALSE(blob_source.TEST_BlobInCache(blob_file_number, file_size,
626
+ blob_offsets[i]));
627
+ }
628
+ }
629
+
630
+ {
631
+ // MultiGetBlob from non-existing file
632
+ uint64_t bytes_read = 0;
633
+ uint64_t file_number = 100; // non-existing file
634
+ read_options.read_tier = ReadTier::kReadAllTier;
635
+
636
+ autovector<std::reference_wrapper<const Slice>> key_refs;
637
+ autovector<uint64_t> offsets;
638
+ autovector<uint64_t> sizes;
639
+ std::array<Status, num_blobs> statuses_buf;
640
+ autovector<Status*> statuses;
641
+ std::array<PinnableSlice, num_blobs> value_buf;
642
+ autovector<PinnableSlice*> values;
643
+
644
+ for (size_t i = 0; i < num_blobs; i++) {
645
+ key_refs.emplace_back(std::cref(keys[i]));
646
+ offsets.push_back(blob_offsets[i]);
647
+ sizes.push_back(blob_sizes[i]);
648
+ statuses.push_back(&statuses_buf[i]);
649
+ values.push_back(&value_buf[i]);
650
+ ASSERT_FALSE(blob_source.TEST_BlobInCache(file_number, file_size,
651
+ blob_offsets[i]));
652
+ }
653
+
654
+ blob_source.MultiGetBlob(read_options, key_refs, file_number, file_size,
655
+ offsets, sizes, statuses, values, &bytes_read);
656
+
657
+ for (size_t i = 0; i < num_blobs; ++i) {
658
+ ASSERT_TRUE(statuses_buf[i].IsIOError());
659
+ ASSERT_TRUE(value_buf[i].empty());
660
+ ASSERT_FALSE(blob_source.TEST_BlobInCache(file_number, file_size,
661
+ blob_offsets[i]));
662
+ }
663
+ }
291
664
  }
292
665
 
293
666
  } // namespace ROCKSDB_NAMESPACE