table_cache.cc 3.4 KB

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