block.h 6.0 KB
Newer Older
1 2 3 4 5
//  Copyright (c) 2013, Facebook, Inc.  All rights reserved.
//  This source code is licensed under the BSD-style license found in the
//  LICENSE file in the root directory of this source tree. An additional grant
//  of patent rights can be found in the PATENTS file in the same directory.
//
J
jorlow@chromium.org 已提交
6 7 8 9
// Copyright (c) 2011 The LevelDB Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. See the AUTHORS file for names of contributors.

10
#pragma once
J
jorlow@chromium.org 已提交
11 12
#include <stddef.h>
#include <stdint.h>
13

14
#include "rocksdb/iterator.h"
15
#include "rocksdb/options.h"
16
#include "db/dbformat.h"
17 18 19 20
#include "table/block_prefix_index.h"
#include "table/block_hash_index.h"

#include "format.h"
J
jorlow@chromium.org 已提交
21

22
namespace rocksdb {
J
jorlow@chromium.org 已提交
23

S
Sanjay Ghemawat 已提交
24
struct BlockContents;
J
jorlow@chromium.org 已提交
25
class Comparator;
26
class BlockIter;
27
class BlockHashIndex;
28
class BlockPrefixIndex;
J
jorlow@chromium.org 已提交
29 30 31 32

class Block {
 public:
  // Initialize the block with the specified contents.
33
  explicit Block(BlockContents&& contents);
S
Sanjay Ghemawat 已提交
34
  explicit Block(const BlockContents& contents);
J
jorlow@chromium.org 已提交
35

36
  ~Block() = default;
J
jorlow@chromium.org 已提交
37 38

  size_t size() const { return size_; }
39
  const char* data() const { return data_; }
40
  bool cachable() const { return contents_.cachable; }
41
  uint32_t NumRestarts() const;
42
  CompressionType compression_type() const { return contents_.compression_type; }
43 44 45 46 47 48 49

  // If hash index lookup is enabled and `use_hash_index` is true. This block
  // will do hash lookup for the key prefix.
  //
  // NOTE: for the hash based lookup, if a key prefix doesn't match any key,
  // the iterator will simply be set as "invalid", rather than returning
  // the key that is just pass the target key.
50 51 52
  //
  // If iter is null, return new Iterator
  // If iter is not null, update this one and return it as Iterator*
53 54 55 56
  //
  // If total_order_seek is true, hash_index_ and prefix_index_ are ignored.
  // This option only applies for index block. For data block, hash_index_
  // and prefix_index_ are null, so this option does not matter.
57
  Iterator* NewIterator(const Comparator* comparator,
58
      BlockIter* iter = nullptr, bool total_order_seek = true);
59
  void SetBlockHashIndex(BlockHashIndex* hash_index);
60
  void SetBlockPrefixIndex(BlockPrefixIndex* prefix_index);
J
jorlow@chromium.org 已提交
61

62 63 64
  // Report an approximation of how much memory has been used.
  size_t ApproximateMemoryUsage() const;

J
jorlow@chromium.org 已提交
65
 private:
66
  BlockContents contents_;
J
jorlow@chromium.org 已提交
67 68 69
  const char* data_;
  size_t size_;
  uint32_t restart_offset_;     // Offset in data_ of restart array
70
  std::unique_ptr<BlockHashIndex> hash_index_;
71
  std::unique_ptr<BlockPrefixIndex> prefix_index_;
J
jorlow@chromium.org 已提交
72 73 74 75

  // No copying allowed
  Block(const Block&);
  void operator=(const Block&);
76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194
};

class BlockIter : public Iterator {
 public:
  BlockIter()
      : comparator_(nullptr),
        data_(nullptr),
        restarts_(0),
        num_restarts_(0),
        current_(0),
        restart_index_(0),
        status_(Status::OK()),
        hash_index_(nullptr),
        prefix_index_(nullptr) {}

  BlockIter(const Comparator* comparator, const char* data, uint32_t restarts,
       uint32_t num_restarts, BlockHashIndex* hash_index,
       BlockPrefixIndex* prefix_index)
      : BlockIter() {
    Initialize(comparator, data, restarts, num_restarts,
        hash_index, prefix_index);
  }

  void Initialize(const Comparator* comparator, const char* data,
      uint32_t restarts, uint32_t num_restarts, BlockHashIndex* hash_index,
      BlockPrefixIndex* prefix_index) {
    assert(data_ == nullptr);           // Ensure it is called only once
    assert(num_restarts > 0);           // Ensure the param is valid

    comparator_ = comparator;
    data_ = data;
    restarts_ = restarts;
    num_restarts_ = num_restarts;
    current_ = restarts_;
    restart_index_ = num_restarts_;
    hash_index_ = hash_index;
    prefix_index_ = prefix_index;
  }

  void SetStatus(Status s) {
    status_ = s;
  }

  virtual bool Valid() const override { return current_ < restarts_; }
  virtual Status status() const override { return status_; }
  virtual Slice key() const override {
    assert(Valid());
    return key_.GetKey();
  }
  virtual Slice value() const override {
    assert(Valid());
    return value_;
  }

  virtual void Next() override;

  virtual void Prev() override;

  virtual void Seek(const Slice& target) override;

  virtual void SeekToFirst() override;

  virtual void SeekToLast() override;

 private:
  const Comparator* comparator_;
  const char* data_;       // underlying block contents
  uint32_t restarts_;      // Offset of restart array (list of fixed32)
  uint32_t num_restarts_;  // Number of uint32_t entries in restart array

  // current_ is offset in data_ of current entry.  >= restarts_ if !Valid
  uint32_t current_;
  uint32_t restart_index_;  // Index of restart block in which current_ falls
  IterKey key_;
  Slice value_;
  Status status_;
  BlockHashIndex* hash_index_;
  BlockPrefixIndex* prefix_index_;

  inline int Compare(const Slice& a, const Slice& b) const {
    return comparator_->Compare(a, b);
  }

  // Return the offset in data_ just past the end of the current entry.
  inline uint32_t NextEntryOffset() const {
    return (value_.data() + value_.size()) - data_;
  }

  uint32_t GetRestartPoint(uint32_t index) {
    assert(index < num_restarts_);
    return DecodeFixed32(data_ + restarts_ + index * sizeof(uint32_t));
  }

  void SeekToRestartPoint(uint32_t index) {
    key_.Clear();
    restart_index_ = index;
    // current_ will be fixed by ParseNextKey();

    // ParseNextKey() starts at the end of value_, so set value_ accordingly
    uint32_t offset = GetRestartPoint(index);
    value_ = Slice(data_ + offset, 0);
  }

  void CorruptionError();

  bool ParseNextKey();

  bool BinarySeek(const Slice& target, uint32_t left, uint32_t right,
                  uint32_t* index);

  int CompareBlockKey(uint32_t block_index, const Slice& target);

  bool BinaryBlockIndexSeek(const Slice& target, uint32_t* block_ids,
                            uint32_t left, uint32_t right,
                            uint32_t* index);

  bool HashSeek(const Slice& target, uint32_t* index);

  bool PrefixSeek(const Slice& target, uint32_t* index);
J
jorlow@chromium.org 已提交
195 196 197

};

198
}  // namespace rocksdb