<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    小明思考

    Just a software engineer
    posts - 124, comments - 36, trackbacks - 0, articles - 0
      BlogJava :: 首頁 :: 新隨筆 :: 聯系 :: 聚合  :: 管理

    leveldb研究11- 流程分析:讀數據

    Posted on 2012-03-21 17:30 小明 閱讀(2729) 評論(0)  編輯  收藏 所屬分類: 分布式計算
    leveldb讀數據

    先看看ReadOptions有哪些參數可以指定:
    // Options that control read operations
    struct ReadOptions {
      
    // 是否檢查checksum
      
    // Default: false
      bool verify_checksums;

      
    // 是否將此次結果放入cache
      
    // Default: true
      bool fill_cache;

      
    //是否指定snapshot,否則讀取當前版本
      
    // Default: NULL
      const Snapshot* snapshot;

      ReadOptions()
          : verify_checksums(
    false),
            fill_cache(
    true),
            snapshot(NULL) {
      }
    };

    下面看看讀取的詳細過程:
    查詢memtable=>查詢previous memtable(imm_)=>查詢文件(緩沖)

    Status DBImpl::Get(const ReadOptions& options,
                       
    const Slice& key,
                       std::
    string* value) {
      Status s;
      MutexLock l(
    &mutex_);
      SequenceNumber snapshot;
      
    //設置snapshot
      if (options.snapshot != NULL) {
        snapshot 
    = reinterpret_cast<const SnapshotImpl*>(options.snapshot)->number_;
      } 
    else {
        snapshot 
    = versions_->LastSequence();
      }

      MemTable
    * mem = mem_;
      MemTable
    * imm = imm_;
      Version
    * current = versions_->current();
      mem
    ->Ref();
      
    if (imm != NULL) imm->Ref();
      current
    ->Ref();

      
    bool have_stat_update = false;
      Version::GetStats stats;

      
    // Unlock while reading from files and memtables
      {
        mutex_.Unlock();
        LookupKey lkey(key, snapshot);
        
    //先查詢memtable
        if (mem->Get(lkey, value, &s)) {
          
    // Done
        } else if (imm != NULL && imm->Get(lkey, value, &s)) { //然后查詢previous memtable:imm_
          
    // Done
        } else {
          
    //從文件中讀取
          s = current->Get(options, lkey, value, &stats);
          have_stat_update 
    = true;
        }
        mutex_.Lock();
      }

      
    //是否有文件需要被compaction,參見allowed_seek
      if (have_stat_update && current->UpdateStats(stats)) {
        MaybeScheduleCompaction();
      }
      mem
    ->Unref();
      
    if (imm != NULL) imm->Unref();
      current
    ->Unref();
      
    return s;
    }


    重點來看看從version中讀?。?br />
    Status Version::Get(const ReadOptions& options,
                        
    const LookupKey& k,
                        std::
    string* value,
                        GetStats
    * stats) {
      Slice ikey 
    = k.internal_key();
      Slice user_key 
    = k.user_key();
      
    const Comparator* ucmp = vset_->icmp_.user_comparator();
      Status s;

      stats
    ->seek_file = NULL;
      stats
    ->seek_file_level = -1;
      FileMetaData
    * last_file_read = NULL;
      
    int last_file_read_level = -1;

      
    //從level0向高層查找,如果再低級level中查到,則不再查詢
      std::vector<FileMetaData*> tmp;
      FileMetaData
    * tmp2;
      
    for (int level = 0; level < config::kNumLevels; level++) {
        size_t num_files 
    = files_[level].size();
        
    //本層文件數為空,則返回
        if (num_files == 0continue;

        
    // Get the list of files to search in this level
        FileMetaData* const* files = &files_[level][0];
        
    if (level == 0) {
          
    //level0特殊處理,因為key是重疊,所有符合條件的文件必須被查找
          tmp.reserve(num_files);
          
    for (uint32_t i = 0; i < num_files; i++) {
            FileMetaData
    * f = files[i];
            
    if (ucmp->Compare(user_key, f->smallest.user_key()) >= 0 &&
                ucmp
    ->Compare(user_key, f->largest.user_key()) <= 0) {
              tmp.push_back(f);
            }
          }
          
    if (tmp.empty()) continue;

          std::sort(tmp.begin(), tmp.end(), NewestFirst);
          files 
    = &tmp[0];
          num_files 
    = tmp.size();
        } 
    else {
          
    // 二分法查找,某個key只可能屬于一個文件
          uint32_t index = FindFile(vset_->icmp_, files_[level], ikey);
          
    //沒有查到
          if (index >= num_files) {
            files 
    = NULL;
            num_files 
    = 0;
          } 
    else {
            tmp2 
    = files[index];
            
    if (ucmp->Compare(user_key, tmp2->smallest.user_key()) < 0) {
              
    // All of "tmp2" is past any data for user_key
              files = NULL;
              num_files 
    = 0;
            } 
    else {
              files 
    = &tmp2;
              num_files 
    = 1;
            }
          }
        }

        
    for (uint32_t i = 0; i < num_files; ++i) { //遍歷本層符合條件的文件
          if (last_file_read != NULL && stats->seek_file == NULL) {
            
    //seek_file只記錄第一個
            stats->seek_file = last_file_read;
            stats
    ->seek_file_level = last_file_read_level;
          }

          FileMetaData
    * f = files[i];
          last_file_read 
    = f;
          last_file_read_level 
    = level;
          
          
    //從table cache中讀取
          Iterator* iter = vset_->table_cache_->NewIterator(
              options,
              f
    ->number,
              f
    ->file_size);
          iter
    ->Seek(ikey);
          
    const bool done = GetValue(ucmp, iter, user_key, value, &s);
          
    if (!iter->status().ok()) { //查找到
            s = iter->status();
            delete iter;
            
    return s;
          } 
    else {
            delete iter;
            
    if (done) {
              
    return s;
            }
          }
        }
      }

      
    return Status::NotFound(Slice());  // Use an empty error message for speed
    }

    繼續跟蹤:TableCache

    Iterator* TableCache::NewIterator(const ReadOptions& options,
                                      uint64_t file_number,
                                      uint64_t file_size,
                                      Table
    ** tableptr) {
      
    if (tableptr != NULL) {
        
    *tableptr = NULL;
      }

      
    char buf[sizeof(file_number)];
      EncodeFixed64(buf, file_number);
      Slice key(buf, 
    sizeof(buf));

      
    //從LRU cache中查找
      Cache::Handle* handle = cache_->Lookup(key);
      
    if (handle == NULL) { 
        
    /加載文件
        std::
    string fname = TableFileName(dbname_, file_number);
        RandomAccessFile
    * file = NULL;
        Table
    * table = NULL;
        Status s 
    = env_->NewRandomAccessFile(fname, &file);
        
    if (s.ok()) {
          s 
    = Table::Open(*options_, file, file_size, &table);
        }

        
    if (!s.ok()) {
          assert(table 
    == NULL);
          delete file;
          
    // We do not cache error results so that if the error is transient,
          
    // or somebody repairs the file, we recover automatically.
          return NewErrorIterator(s);
        }

        
    //插入Cache
        TableAndFile* tf = new TableAndFile;
        tf
    ->file = file;
        tf
    ->table = table;
        handle 
    = cache_->Insert(key, tf, 1&DeleteEntry);
      }

      Table
    * table = reinterpret_cast<TableAndFile*>(cache_->Value(handle))->table;
      
    //從Table對象中生成iterator
      Iterator* result = table->NewIterator(options);
      result
    ->RegisterCleanup(&UnrefEntry, cache_, handle);
      
    if (tableptr != NULL) {
        
    *tableptr = table;
      }
      
    return result;
    }


    主站蜘蛛池模板: 最近2019年免费中文字幕高清| 在线观看的免费网站| 亚洲日本香蕉视频| 成人最新午夜免费视频| 一个人看的免费观看日本视频www 一个人看的免费视频www在线高清动漫 | 久久青草免费91线频观看不卡| 亚洲精品中文字幕麻豆| 亚洲日本国产综合高清| 国产男女猛烈无遮挡免费视频网站 | 在线观看免费a∨网站| 亚洲人成网站在线观看播放青青| 国产精品久免费的黄网站| 青柠影视在线观看免费高清| 超清首页国产亚洲丝袜| 91九色视频无限观看免费| 青娱乐在线视频免费观看| 免费激情视频网站| 拍拍拍无挡免费视频网站| 97se亚洲国产综合自在线 | 伊人久久大香线蕉亚洲| 亚洲精品在线免费观看视频| 美国毛片亚洲社区在线观看| 亚洲avav天堂av在线不卡| 午夜视频免费在线观看| 亚洲aⅴ无码专区在线观看| 亚洲AV中文无码乱人伦| 最新黄色免费网站| 9久热这里只有精品免费| 亚洲日本va一区二区三区| 亚洲综合婷婷久久| 亚洲午夜精品第一区二区8050| 国产区在线免费观看| 亚洲精品欧美综合四区| 亚洲视频一区二区三区| 亚洲精品乱码久久久久66| 久久免费观看国产精品| 九九久久精品国产免费看小说 | 中文字幕的电影免费网站| 亚洲av永久无码精品秋霞电影秋| 亚洲经典在线中文字幕| 国产精品亚洲A∨天堂不卡|