Coverage Report

Created: 2025-06-10 13:21

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/bitcoin/src/leveldb/db/table_cache.cc
Line
Count
Source
1
// Copyright (c) 2011 The LevelDB Authors. All rights reserved.
2
// Use of this source code is governed by a BSD-style license that can be
3
// found in the LICENSE file. See the AUTHORS file for names of contributors.
4
5
#include "db/table_cache.h"
6
7
#include "db/filename.h"
8
#include "leveldb/env.h"
9
#include "leveldb/table.h"
10
#include "util/coding.h"
11
12
namespace leveldb {
13
14
struct TableAndFile {
15
  RandomAccessFile* file;
16
  Table* table;
17
};
18
19
24
static void DeleteEntry(const Slice& key, void* value) {
20
24
  TableAndFile* tf = reinterpret_cast<TableAndFile*>(value);
21
24
  delete tf->table;
22
24
  delete tf->file;
23
24
  delete tf;
24
24
}
25
26
31
static void UnrefEntry(void* arg1, void* arg2) {
27
31
  Cache* cache = reinterpret_cast<Cache*>(arg1);
28
31
  Cache::Handle* h = reinterpret_cast<Cache::Handle*>(arg2);
29
31
  cache->Release(h);
30
31
}
31
32
TableCache::TableCache(const std::string& dbname, const Options& options,
33
                       int entries)
34
33.2k
    : env_(options.env),
35
33.2k
      dbname_(dbname),
36
33.2k
      options_(options),
37
33.2k
      cache_(NewLRUCache(entries)) {}
38
39
33.2k
TableCache::~TableCache() { delete cache_; }
40
41
Status TableCache::FindTable(uint64_t file_number, uint64_t file_size,
42
36
                             Cache::Handle** handle) {
43
36
  Status s;
44
36
  char buf[sizeof(file_number)];
45
36
  EncodeFixed64(buf, file_number);
46
36
  Slice key(buf, sizeof(buf));
47
36
  *handle = cache_->Lookup(key);
48
36
  if (*handle == nullptr) {
  Branch (48:7): [True: 24, False: 12]
49
24
    std::string fname = TableFileName(dbname_, file_number);
50
24
    RandomAccessFile* file = nullptr;
51
24
    Table* table = nullptr;
52
24
    s = env_->NewRandomAccessFile(fname, &file);
53
24
    if (!s.ok()) {
  Branch (53:9): [True: 0, False: 24]
54
0
      std::string old_fname = SSTTableFileName(dbname_, file_number);
55
0
      if (env_->NewRandomAccessFile(old_fname, &file).ok()) {
  Branch (55:11): [True: 0, False: 0]
56
0
        s = Status::OK();
57
0
      }
58
0
    }
59
24
    if (s.ok()) {
  Branch (59:9): [True: 24, False: 0]
60
24
      s = Table::Open(options_, file, file_size, &table);
61
24
    }
62
63
24
    if (!s.ok()) {
  Branch (63:9): [True: 0, False: 24]
64
0
      assert(table == nullptr);
  Branch (64:7): [True: 0, False: 0]
65
0
      delete file;
66
      // We do not cache error results so that if the error is transient,
67
      // or somebody repairs the file, we recover automatically.
68
24
    } else {
69
24
      TableAndFile* tf = new TableAndFile;
70
24
      tf->file = file;
71
24
      tf->table = table;
72
24
      *handle = cache_->Insert(key, tf, 1, &DeleteEntry);
73
24
    }
74
24
  }
75
36
  return s;
76
36
}
77
78
Iterator* TableCache::NewIterator(const ReadOptions& options,
79
                                  uint64_t file_number, uint64_t file_size,
80
31
                                  Table** tableptr) {
81
31
  if (tableptr != nullptr) {
  Branch (81:7): [True: 0, False: 31]
82
0
    *tableptr = nullptr;
83
0
  }
84
85
31
  Cache::Handle* handle = nullptr;
86
31
  Status s = FindTable(file_number, file_size, &handle);
87
31
  if (!s.ok()) {
  Branch (87:7): [True: 0, False: 31]
88
0
    return NewErrorIterator(s);
89
0
  }
90
91
31
  Table* table = reinterpret_cast<TableAndFile*>(cache_->Value(handle))->table;
92
31
  Iterator* result = table->NewIterator(options);
93
31
  result->RegisterCleanup(&UnrefEntry, cache_, handle);
94
31
  if (tableptr != nullptr) {
  Branch (94:7): [True: 0, False: 31]
95
0
    *tableptr = table;
96
0
  }
97
31
  return result;
98
31
}
99
100
Status TableCache::Get(const ReadOptions& options, uint64_t file_number,
101
                       uint64_t file_size, const Slice& k, void* arg,
102
                       void (*handle_result)(void*, const Slice&,
103
5
                                             const Slice&)) {
104
5
  Cache::Handle* handle = nullptr;
105
5
  Status s = FindTable(file_number, file_size, &handle);
106
5
  if (s.ok()) {
  Branch (106:7): [True: 5, False: 0]
107
5
    Table* t = reinterpret_cast<TableAndFile*>(cache_->Value(handle))->table;
108
5
    s = t->InternalGet(options, k, arg, handle_result);
109
5
    cache_->Release(handle);
110
5
  }
111
5
  return s;
112
5
}
113
114
0
void TableCache::Evict(uint64_t file_number) {
115
0
  char buf[sizeof(file_number)];
116
0
  EncodeFixed64(buf, file_number);
117
0
  cache_->Erase(Slice(buf, sizeof(buf)));
118
0
}
119
120
}  // namespace leveldb