Convert an index iterator value (i.e., an encoded BlockHandle) into an iterator over the contents of the corresponding block.
| 153 | // Convert an index iterator value (i.e., an encoded BlockHandle) |
| 154 | // into an iterator over the contents of the corresponding block. |
| 155 | Iterator* Table::BlockReader(void* arg, const ReadOptions& options, |
| 156 | const Slice& index_value) { |
| 157 | Table* table = reinterpret_cast<Table*>(arg); |
| 158 | Cache* block_cache = table->rep_->options.block_cache; |
| 159 | Block* block = nullptr; |
| 160 | Cache::Handle* cache_handle = nullptr; |
| 161 | |
| 162 | BlockHandle handle; |
| 163 | Slice input = index_value; |
| 164 | Status s = handle.DecodeFrom(&input); |
| 165 | // We intentionally allow extra stuff in index_value so that we |
| 166 | // can add more features in the future. |
| 167 | |
| 168 | if (s.ok()) { |
| 169 | BlockContents contents; |
| 170 | if (block_cache != nullptr) { |
| 171 | char cache_key_buffer[16]; |
| 172 | EncodeFixed64(cache_key_buffer, table->rep_->cache_id); |
| 173 | EncodeFixed64(cache_key_buffer + 8, handle.offset()); |
| 174 | Slice key(cache_key_buffer, sizeof(cache_key_buffer)); |
| 175 | cache_handle = block_cache->Lookup(key); |
| 176 | if (cache_handle != nullptr) { |
| 177 | block = reinterpret_cast<Block*>(block_cache->Value(cache_handle)); |
| 178 | } else { |
| 179 | s = ReadBlock(table->rep_->file, options, handle, &contents); |
| 180 | if (s.ok()) { |
| 181 | block = new Block(contents); |
| 182 | if (contents.cachable && options.fill_cache) { |
| 183 | cache_handle = block_cache->Insert(key, block, block->size(), |
| 184 | &DeleteCachedBlock); |
| 185 | } |
| 186 | } |
| 187 | } |
| 188 | } else { |
| 189 | s = ReadBlock(table->rep_->file, options, handle, &contents); |
| 190 | if (s.ok()) { |
| 191 | block = new Block(contents); |
| 192 | } |
| 193 | } |
| 194 | } |
| 195 | |
| 196 | Iterator* iter; |
| 197 | if (block != nullptr) { |
| 198 | iter = block->NewIterator(table->rep_->options.comparator); |
| 199 | if (cache_handle == nullptr) { |
| 200 | iter->RegisterCleanup(&DeleteBlock, block, nullptr); |
| 201 | } else { |
| 202 | iter->RegisterCleanup(&ReleaseBlock, block_cache, cache_handle); |
| 203 | } |
| 204 | } else { |
| 205 | iter = NewErrorIterator(s); |
| 206 | } |
| 207 | return iter; |
| 208 | } |
| 209 | |
| 210 | Iterator* Table::NewIterator(const ReadOptions& options) const { |
| 211 | return NewTwoLevelIterator( |
nothing calls this directly
no test coverage detected