小组成员:谢瑞阳、徐翔宇
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

120 regels
3.5 KiB

  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. #include "db/table_cache.h"
  5. #include "db/filename.h"
  6. #include "leveldb/env.h"
  7. #include "leveldb/table.h"
  8. #include "util/coding.h"
  9. namespace leveldb {
  10. struct TableAndFile {
  11. RandomAccessFile* file;
  12. Table* table;
  13. };
  14. static void DeleteEntry(const Slice& key, void* value) {
  15. TableAndFile* tf = reinterpret_cast<TableAndFile*>(value);
  16. delete tf->table;
  17. delete tf->file;
  18. delete tf;
  19. }
  20. static void UnrefEntry(void* arg1, void* arg2) {
  21. Cache* cache = reinterpret_cast<Cache*>(arg1);
  22. Cache::Handle* h = reinterpret_cast<Cache::Handle*>(arg2);
  23. cache->Release(h);
  24. }
  25. TableCache::TableCache(const std::string& dbname, const Options& options,
  26. int entries)
  27. : env_(options.env),
  28. dbname_(dbname),
  29. options_(options),
  30. cache_(NewLRUCache(entries)) {}
  31. TableCache::~TableCache() { delete cache_; }
  32. Status TableCache::FindTable(uint64_t file_number, uint64_t file_size,
  33. Cache::Handle** handle) {
  34. Status s;
  35. char buf[sizeof(file_number)];
  36. EncodeFixed64(buf, file_number);
  37. Slice key(buf, sizeof(buf));
  38. *handle = cache_->Lookup(key);
  39. if (*handle == nullptr) {
  40. std::string fname = TableFileName(dbname_, file_number);
  41. RandomAccessFile* file = nullptr;
  42. Table* table = nullptr;
  43. s = env_->NewRandomAccessFile(fname, &file);
  44. if (!s.ok()) {
  45. std::string old_fname = SSTTableFileName(dbname_, file_number);
  46. if (env_->NewRandomAccessFile(old_fname, &file).ok()) {
  47. s = Status::OK();
  48. }
  49. }
  50. if (s.ok()) {
  51. s = Table::Open(options_, file, file_size, &table);
  52. }
  53. if (!s.ok()) {
  54. assert(table == nullptr);
  55. delete file;
  56. // We do not cache error results so that if the error is transient,
  57. // or somebody repairs the file, we recover automatically.
  58. } else {
  59. TableAndFile* tf = new TableAndFile;
  60. tf->file = file;
  61. tf->table = table;
  62. *handle = cache_->Insert(key, tf, 1, &DeleteEntry);
  63. }
  64. }
  65. return s;
  66. }
  67. Iterator* TableCache::NewIterator(const ReadOptions& options,
  68. uint64_t file_number, uint64_t file_size,
  69. Table** tableptr) {
  70. if (tableptr != nullptr) {
  71. *tableptr = nullptr;
  72. }
  73. Cache::Handle* handle = nullptr;
  74. Status s = FindTable(file_number, file_size, &handle);
  75. if (!s.ok()) {
  76. return NewErrorIterator(s);
  77. }
  78. Table* table = reinterpret_cast<TableAndFile*>(cache_->Value(handle))->table;
  79. Iterator* result = table->NewIterator(options);
  80. result->RegisterCleanup(&UnrefEntry, cache_, handle);
  81. if (tableptr != nullptr) {
  82. *tableptr = table;
  83. }
  84. return result;
  85. }
  86. Status TableCache::Get(const ReadOptions& options, uint64_t file_number,
  87. uint64_t file_size, const Slice& k, void* arg,
  88. void (*handle_result)(void*, const Slice&,
  89. const Slice&)) {
  90. Cache::Handle* handle = nullptr;
  91. Status s = FindTable(file_number, file_size, &handle);
  92. if (s.ok()) {
  93. Table* t = reinterpret_cast<TableAndFile*>(cache_->Value(handle))->table;
  94. s = t->InternalGet(options, k, arg, handle_result);
  95. cache_->Release(handle);
  96. }
  97. return s;
  98. }
  99. void TableCache::Evict(uint64_t file_number) {
  100. char buf[sizeof(file_number)];
  101. EncodeFixed64(buf, file_number);
  102. cache_->Erase(Slice(buf, sizeof(buf)));
  103. }
  104. } // namespace leveldb