github.com/cellofellow/gopkg@v0.0.0-20140722061823-eec0544a62ad/database/leveldb.chai2010/src/table_cache.cc (about)

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