Skip to content

Commit ff85fd1

Browse files
authored
Check blob cache before getting blob file reader (#312)
Signed-off-by: Connor1996 <[email protected]>
1 parent 5a9cee8 commit ff85fd1

18 files changed

+157
-130
lines changed

include/titan/options.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ struct TitanCFOptions : public ColumnFamilyOptions {
9898
// If non-NULL use the specified cache for blob records.
9999
//
100100
// Default: nullptr
101-
std::shared_ptr<Cache> blob_cache;
101+
std::shared_ptr<Cache> blob_cache{nullptr};
102102

103103
// Max batch size for GC.
104104
//

src/blob_file_cache.cc

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,13 +27,13 @@ BlobFileCache::BlobFileCache(const TitanDBOptions& db_options,
2727

2828
Status BlobFileCache::Get(const ReadOptions& options, uint64_t file_number,
2929
const BlobHandle& handle, BlobRecord* record,
30-
PinnableSlice* value) {
30+
OwnedSlice* buffer) {
3131
Cache::Handle* cache_handle = nullptr;
3232
Status s = GetBlobFileReaderHandle(file_number, &cache_handle);
3333
if (!s.ok()) return s;
3434

3535
auto reader = reinterpret_cast<BlobFileReader*>(cache_->Value(cache_handle));
36-
s = reader->Get(options, handle, record, value);
36+
s = reader->Get(options, handle, record, buffer);
3737
cache_->Release(cache_handle);
3838
return s;
3939
}

src/blob_file_cache.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,7 @@ class BlobFileCache {
2222
// bytes. The provided buffer is used to store the record data, so
2323
// the buffer must be valid when the record is used.
2424
Status Get(const ReadOptions& options, uint64_t file_number,
25-
const BlobHandle& handle, BlobRecord* record,
26-
PinnableSlice* value);
25+
const BlobHandle& handle, BlobRecord* record, OwnedSlice* buffer);
2726

2827
// Creates a prefetcher for the specified file number.
2928
Status NewPrefetcher(uint64_t file_number,

src/blob_file_reader.cc

Lines changed: 6 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88

99
#include "file/filename.h"
1010
#include "file/readahead_raf.h"
11+
#include "rocksdb/cache.h"
1112
#include "table/block_based/block.h"
1213
#include "table/internal_iterator.h"
1314
#include "table/meta_blocks.h"
@@ -44,22 +45,6 @@ const uint64_t kMaxReadaheadSize = 256 << 10;
4445

4546
namespace {
4647

47-
void GenerateCachePrefix(std::string* dst, Cache* cc,
48-
FSRandomAccessFile* file) {
49-
char buffer[kMaxVarint64Length * 3 + 1];
50-
auto size = file->GetUniqueId(buffer, sizeof(buffer));
51-
if (size == 0) {
52-
auto end = EncodeVarint64(buffer, cc->NewId());
53-
size = end - buffer;
54-
}
55-
dst->assign(buffer, size);
56-
}
57-
58-
void EncodeBlobCache(std::string* dst, const Slice& prefix, uint64_t offset) {
59-
dst->assign(prefix.data(), prefix.size());
60-
PutVarint64(dst, offset);
61-
}
62-
6348
// Seek to the specified meta block.
6449
// Return true if it successfully seeks to that block.
6550
Status SeekToMetaBlock(InternalIterator* meta_iter,
@@ -140,62 +125,13 @@ Status BlobFileReader::ReadHeader(std::unique_ptr<RandomAccessFileReader>& file,
140125

141126
BlobFileReader::BlobFileReader(const TitanCFOptions& options,
142127
std::unique_ptr<RandomAccessFileReader> file,
143-
TitanStats* stats)
144-
: options_(options),
145-
file_(std::move(file)),
146-
cache_(options.blob_cache),
147-
stats_(stats) {
148-
if (cache_) {
149-
GenerateCachePrefix(&cache_prefix_, cache_.get(), file_->file());
150-
}
151-
}
128+
TitanStats* _stats)
129+
: options_(options), file_(std::move(file)) {}
152130

153-
Status BlobFileReader::Get(const ReadOptions& /*options*/,
131+
Status BlobFileReader::Get(const ReadOptions& _options,
154132
const BlobHandle& handle, BlobRecord* record,
155-
PinnableSlice* value) {
133+
OwnedSlice* buffer) {
156134
TEST_SYNC_POINT("BlobFileReader::Get");
157-
158-
std::string cache_key;
159-
Cache::Handle* cache_handle = nullptr;
160-
if (cache_) {
161-
EncodeBlobCache(&cache_key, cache_prefix_, handle.offset);
162-
cache_handle = cache_->Lookup(cache_key);
163-
if (cache_handle) {
164-
RecordTick(statistics(stats_), TITAN_BLOB_CACHE_HIT);
165-
auto blob = reinterpret_cast<OwnedSlice*>(cache_->Value(cache_handle));
166-
Status s = DecodeInto(*blob, record);
167-
if (!s.ok()) return s;
168-
value->PinSlice(record->value, UnrefCacheHandle, cache_.get(),
169-
cache_handle);
170-
return s;
171-
}
172-
}
173-
RecordTick(statistics(stats_), TITAN_BLOB_CACHE_MISS);
174-
175-
OwnedSlice blob;
176-
Status s = ReadRecord(handle, record, &blob);
177-
if (!s.ok()) {
178-
return s;
179-
}
180-
181-
if (cache_) {
182-
auto cache_value = new OwnedSlice(std::move(blob));
183-
auto cache_size = cache_value->size() + sizeof(*cache_value);
184-
cache_->Insert(cache_key, cache_value, cache_size,
185-
&DeleteCacheValue<OwnedSlice>, &cache_handle,
186-
Cache::Priority::BOTTOM);
187-
value->PinSlice(record->value, UnrefCacheHandle, cache_.get(),
188-
cache_handle);
189-
} else {
190-
value->PinSlice(record->value, OwnedSlice::CleanupFunc, blob.release(),
191-
nullptr);
192-
}
193-
194-
return Status::OK();
195-
}
196-
197-
Status BlobFileReader::ReadRecord(const BlobHandle& handle, BlobRecord* record,
198-
OwnedSlice* buffer) {
199135
Slice blob;
200136
CacheAllocationPtr ubuf =
201137
AllocateBlock(handle.size, options_.memory_allocator());
@@ -224,7 +160,7 @@ Status BlobFileReader::ReadRecord(const BlobHandle& handle, BlobRecord* record,
224160

225161
Status BlobFilePrefetcher::Get(const ReadOptions& options,
226162
const BlobHandle& handle, BlobRecord* record,
227-
PinnableSlice* buffer) {
163+
OwnedSlice* buffer) {
228164
if (handle.offset == last_offset_) {
229165
last_offset_ = handle.offset + handle.size;
230166
if (handle.offset + handle.size > readahead_limit_) {

src/blob_file_reader.h

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ class BlobFileReader {
2828
// of the record is stored in the value slice underlying, so the value slice
2929
// must be valid when the record is used.
3030
Status Get(const ReadOptions& options, const BlobHandle& handle,
31-
BlobRecord* record, PinnableSlice* value);
31+
BlobRecord* record, OwnedSlice* buffer);
3232

3333
private:
3434
friend class BlobFilePrefetcher;
@@ -37,23 +37,18 @@ class BlobFileReader {
3737
std::unique_ptr<RandomAccessFileReader> file,
3838
TitanStats* stats);
3939

40-
Status ReadRecord(const BlobHandle& handle, BlobRecord* record,
41-
OwnedSlice* buffer);
4240
static Status ReadHeader(std::unique_ptr<RandomAccessFileReader>& file,
4341
BlobFileHeader* header);
4442

4543
TitanCFOptions options_;
4644
std::unique_ptr<RandomAccessFileReader> file_;
4745

48-
std::shared_ptr<Cache> cache_;
49-
std::string cache_prefix_;
50-
5146
// Information read from the file.
5247
BlobFileFooter footer_;
5348

5449
std::unique_ptr<UncompressionDict> uncompression_dict_ = nullptr;
5550

56-
TitanStats* stats_;
51+
// TitanStats* stats_;
5752
};
5853

5954
// Performs readahead on continuous reads.
@@ -64,7 +59,7 @@ class BlobFilePrefetcher : public Cleanable {
6459
BlobFilePrefetcher(BlobFileReader* reader) : reader_(reader) {}
6560

6661
Status Get(const ReadOptions& options, const BlobHandle& handle,
67-
BlobRecord* record, PinnableSlice* buffer);
62+
BlobRecord* record, OwnedSlice* buffer);
6863

6964
private:
7065
BlobFileReader* reader_;

src/blob_file_set.cc

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,10 @@ BlobFileSet::BlobFileSet(const TitanDBOptions& options, TitanStats* stats,
2727
}
2828

2929
Status BlobFileSet::Open(
30-
const std::map<uint32_t, TitanCFOptions>& column_families) {
30+
const std::map<uint32_t, TitanCFOptions>& column_families,
31+
const std::string& cache_prefix) {
3132
// Sets up initial column families.
32-
AddColumnFamilies(column_families);
33+
AddColumnFamilies(column_families, cache_prefix);
3334

3435
Status s = env_->FileExists(CurrentFileName(dirname_));
3536
if (s.ok()) {
@@ -314,12 +315,14 @@ Status BlobFileSet::LogAndApply(VersionEdit& edit) {
314315
}
315316

316317
void BlobFileSet::AddColumnFamilies(
317-
const std::map<uint32_t, TitanCFOptions>& column_families) {
318+
const std::map<uint32_t, TitanCFOptions>& column_families,
319+
const std::string& cache_prefix) {
318320
for (auto& cf : column_families) {
319321
auto file_cache = std::make_shared<BlobFileCache>(db_options_, cf.second,
320322
file_cache_, stats_);
321323
auto blob_storage = std::make_shared<BlobStorage>(
322-
db_options_, cf.second, cf.first, file_cache, stats_, initialized_);
324+
db_options_, cf.second, cf.first, cache_prefix, file_cache, stats_,
325+
initialized_);
323326
if (stats_ != nullptr) {
324327
stats_->InitializeCF(cf.first, blob_storage);
325328
}

src/blob_file_set.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,8 @@ class BlobFileSet {
4141
// If the manifest exists, it will recover from the latest one.
4242
// It is a corruption if the persistent storage contains data
4343
// outside of the provided column families.
44-
Status Open(const std::map<uint32_t, TitanCFOptions>& column_families);
44+
Status Open(const std::map<uint32_t, TitanCFOptions>& column_families,
45+
const std::string& cache_prefix);
4546

4647
// Applies *edit and saved to the manifest.
4748
// REQUIRES: mutex is held
@@ -50,7 +51,8 @@ class BlobFileSet {
5051
// Adds some column families with the specified options.
5152
// REQUIRES: mutex is held
5253
void AddColumnFamilies(
53-
const std::map<uint32_t, TitanCFOptions>& column_families);
54+
const std::map<uint32_t, TitanCFOptions>& column_families,
55+
const std::string& cache_prefix);
5456

5557
// Drops some column families. The obsolete files will be deleted in
5658
// background when they will not be accessed anymore.

src/blob_file_test.cc

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -107,17 +107,14 @@ class BlobFileTest : public testing::Test {
107107
expect.key = key;
108108
expect.value = value;
109109
BlobRecord record;
110-
PinnableSlice buffer;
110+
OwnedSlice buffer;
111111
BlobHandle blob_handle = contexts[i]->new_blob_index.blob_handle;
112112
ASSERT_OK(cache.Get(ro, file_number_, blob_handle, &record, &buffer));
113113
ASSERT_EQ(record, expect);
114-
buffer.Reset();
115114
ASSERT_OK(cache.Get(ro, file_number_, blob_handle, &record, &buffer));
116115
ASSERT_EQ(record, expect);
117-
buffer.Reset();
118116
ASSERT_OK(prefetcher->Get(ro, blob_handle, &record, &buffer));
119117
ASSERT_EQ(record, expect);
120-
buffer.Reset();
121118
ASSERT_OK(prefetcher->Get(ro, blob_handle, &record, &buffer));
122119
ASSERT_EQ(record, expect);
123120
}
@@ -187,17 +184,14 @@ class BlobFileTest : public testing::Test {
187184
expect.key = key;
188185
expect.value = value;
189186
BlobRecord record;
190-
PinnableSlice buffer;
187+
OwnedSlice buffer;
191188
BlobHandle blob_handle = contexts[i]->new_blob_index.blob_handle;
192189
ASSERT_OK(cache.Get(ro, file_number_, blob_handle, &record, &buffer));
193190
ASSERT_EQ(record, expect);
194-
buffer.Reset();
195191
ASSERT_OK(cache.Get(ro, file_number_, blob_handle, &record, &buffer));
196192
ASSERT_EQ(record, expect);
197-
buffer.Reset();
198193
ASSERT_OK(blob_file_reader->Get(ro, blob_handle, &record, &buffer));
199194
ASSERT_EQ(record, expect);
200-
buffer.Reset();
201195
ASSERT_OK(blob_file_reader->Get(ro, blob_handle, &record, &buffer));
202196
ASSERT_EQ(record, expect);
203197
}

src/blob_gc_picker_test.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ class BlobGCPickerTest : public testing::Test {
2424
auto blob_file_cache = std::make_shared<BlobFileCache>(
2525
titan_db_options, titan_cf_options, NewLRUCache(128), nullptr);
2626
blob_storage_.reset(new BlobStorage(titan_db_options, titan_cf_options, 0,
27-
blob_file_cache, nullptr, nullptr));
27+
"", blob_file_cache, nullptr, nullptr));
2828
basic_blob_gc_picker_.reset(
2929
new BasicBlobGCPicker(titan_db_options, titan_cf_options, nullptr));
3030
}

src/blob_storage.cc

Lines changed: 58 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,66 @@
66
namespace rocksdb {
77
namespace titandb {
88

9+
std::string BlobStorage::EncodeBlobCache(const BlobIndex& index) {
10+
std::string cache_key(cache_prefix_);
11+
PutVarint64(&cache_key, index.file_number);
12+
PutVarint64(&cache_key, index.blob_handle.offset);
13+
return cache_key;
14+
}
15+
16+
Status BlobStorage::TryGetBlobCache(const std::string& cache_key,
17+
BlobRecord* record, PinnableSlice* value,
18+
bool* cache_hit) {
19+
Status s;
20+
Cache::Handle* cache_handle = blob_cache_->Lookup(cache_key);
21+
if (cache_handle) {
22+
*cache_hit = true;
23+
RecordTick(statistics(stats_), TITAN_BLOB_CACHE_HIT);
24+
auto blob = reinterpret_cast<OwnedSlice*>(blob_cache_->Value(cache_handle));
25+
s = DecodeInto(*blob, record);
26+
if (!s.ok()) return s;
27+
28+
value->PinSlice(record->value, UnrefCacheHandle, blob_cache_.get(),
29+
cache_handle);
30+
return s;
31+
}
32+
*cache_hit = false;
33+
RecordTick(statistics(stats_), TITAN_BLOB_CACHE_MISS);
34+
return s;
35+
}
36+
937
Status BlobStorage::Get(const ReadOptions& options, const BlobIndex& index,
1038
BlobRecord* record, PinnableSlice* value) {
11-
return file_cache_->Get(options, index.file_number, index.blob_handle, record,
12-
value);
39+
std::string cache_key;
40+
41+
if (blob_cache_) {
42+
cache_key = EncodeBlobCache(index);
43+
bool cache_hit;
44+
Status s = TryGetBlobCache(cache_key, record, value, &cache_hit);
45+
if (!s.ok()) return s;
46+
if (cache_hit) return s;
47+
}
48+
49+
OwnedSlice blob;
50+
Status s = file_cache_->Get(options, index.file_number, index.blob_handle,
51+
record, &blob);
52+
if (!s.ok()) {
53+
return s;
54+
}
55+
56+
if (blob_cache_ && options.fill_cache) {
57+
Cache::Handle* cache_handle = nullptr;
58+
auto cache_value = new OwnedSlice(std::move(blob));
59+
blob_cache_->Insert(
60+
cache_key, cache_value, cache_value->size() + sizeof(*cache_value),
61+
&DeleteCacheValue<OwnedSlice>, &cache_handle, Cache::Priority::BOTTOM);
62+
value->PinSlice(record->value, UnrefCacheHandle, blob_cache_.get(),
63+
cache_handle);
64+
} else {
65+
value->PinSlice(record->value, OwnedSlice::CleanupFunc, blob.release(),
66+
nullptr);
67+
}
68+
return s;
1369
}
1470

1571
Status BlobStorage::NewPrefetcher(uint64_t file_number,

0 commit comments

Comments
 (0)