Coverage Report

Created: 2025-07-11 07:01

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