Coverage Report

Created: 2026-09-14 06:40

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/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
88
static void DeleteEntry(const Slice& key, void* value) {
20
88
  TableAndFile* tf = reinterpret_cast<TableAndFile*>(value);
21
88
  delete tf->table;
22
88
  delete tf->file;
23
88
  delete tf;
24
88
}
25
26
126
static void UnrefEntry(void* arg1, void* arg2) {
27
126
  Cache* cache = reinterpret_cast<Cache*>(arg1);
28
126
  Cache::Handle* h = reinterpret_cast<Cache::Handle*>(arg2);
29
126
  cache->Release(h);
30
126
}
31
32
TableCache::TableCache(const std::string& dbname, const Options& options,
33
                       int entries)
34
108
    : env_(options.env),
35
108
      dbname_(dbname),
36
108
      options_(options),
37
108
      cache_(NewLRUCache(entries)) {}
38
39
108
TableCache::~TableCache() { delete cache_; }
40
41
Status TableCache::FindTable(uint64_t file_number, uint64_t file_size,
42
141
                             Cache::Handle** handle) {
43
141
  Status s;
44
141
  char buf[sizeof(file_number)];
45
141
  EncodeFixed64(buf, file_number);
46
141
  Slice key(buf, sizeof(buf));
47
141
  *handle = cache_->Lookup(key);
48
141
  if (*handle == nullptr) {
49
88
    std::string fname = TableFileName(dbname_, file_number);
50
88
    RandomAccessFile* file = nullptr;
51
88
    Table* table = nullptr;
52
88
    s = env_->NewRandomAccessFile(fname, &file);
53
88
    if (!s.ok()) {
54
0
      std::string old_fname = SSTTableFileName(dbname_, file_number);
55
0
      if (env_->NewRandomAccessFile(old_fname, &file).ok()) {
56
0
        s = Status::OK();
57
0
      }
58
0
    }
59
88
    if (s.ok()) {
60
88
      s = Table::Open(options_, file, file_size, &table);
61
88
    }
62
63
88
    if (!s.ok()) {
64
0
      assert(table == nullptr);
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
88
    } else {
69
88
      TableAndFile* tf = new TableAndFile;
70
88
      tf->file = file;
71
88
      tf->table = table;
72
88
      *handle = cache_->Insert(key, tf, 1, &DeleteEntry);
73
88
    }
74
88
  }
75
141
  return s;
76
141
}
77
78
Iterator* TableCache::NewIterator(const ReadOptions& options,
79
                                  uint64_t file_number, uint64_t file_size,
80
126
                                  Table** tableptr) {
81
126
  if (tableptr != nullptr) {
82
0
    *tableptr = nullptr;
83
0
  }
84
85
126
  Cache::Handle* handle = nullptr;
86
126
  Status s = FindTable(file_number, file_size, &handle);
87
126
  if (!s.ok()) {
88
0
    return NewErrorIterator(s);
89
0
  }
90
91
126
  Table* table = reinterpret_cast<TableAndFile*>(cache_->Value(handle))->table;
92
126
  Iterator* result = table->NewIterator(options);
93
126
  result->RegisterCleanup(&UnrefEntry, cache_, handle);
94
126
  if (tableptr != nullptr) {
95
0
    *tableptr = table;
96
0
  }
97
126
  return result;
98
126
}
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
15
                                             const Slice&)) {
104
15
  Cache::Handle* handle = nullptr;
105
15
  Status s = FindTable(file_number, file_size, &handle);
106
15
  if (s.ok()) {
107
15
    Table* t = reinterpret_cast<TableAndFile*>(cache_->Value(handle))->table;
108
15
    s = t->InternalGet(options, k, arg, handle_result);
109
15
    cache_->Release(handle);
110
15
  }
111
15
  return s;
112
15
}
113
114
28
void TableCache::Evict(uint64_t file_number) {
115
28
  char buf[sizeof(file_number)];
116
28
  EncodeFixed64(buf, file_number);
117
28
  cache_->Erase(Slice(buf, sizeof(buf)));
118
28
}
119
120
}  // namespace leveldb