1179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org// Copyright (c) 2011 The LevelDB Authors. All rights reserved.
2179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org// Use of this source code is governed by a BSD-style license that can be
3179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org// found in the LICENSE file. See the AUTHORS file for names of contributors.
4179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org
5fbd97aa4c5325eace57d24b89845b9581bac9324jorlow@chromium.org#include "leveldb/table_builder.h"
6179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org
7179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org#include <assert.h>
8fbd97aa4c5325eace57d24b89845b9581bac9324jorlow@chromium.org#include "leveldb/comparator.h"
9fbd97aa4c5325eace57d24b89845b9581bac9324jorlow@chromium.org#include "leveldb/env.h"
1099a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com#include "leveldb/filter_policy.h"
1199a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com#include "leveldb/options.h"
12179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org#include "table/block_builder.h"
1399a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com#include "table/filter_block.h"
14179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org#include "table/format.h"
15179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org#include "util/coding.h"
16179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org#include "util/crc32c.h"
17179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org
18179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.orgnamespace leveldb {
19179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org
20179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.orgstruct TableBuilder::Rep {
21179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  Options options;
22179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  Options index_block_options;
23179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  WritableFile* file;
24179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  uint64_t offset;
25179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  Status status;
26179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  BlockBuilder data_block;
27179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  BlockBuilder index_block;
28179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  std::string last_key;
29179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  int64_t num_entries;
30179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  bool closed;          // Either Finish() or Abandon() has been called.
3199a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com  FilterBlockBuilder* filter_block;
32179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org
33179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  // We do not emit the index entry for a block until we have seen the
34179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  // first key for the next data block.  This allows us to use shorter
35179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  // keys in the index block.  For example, consider a block boundary
36179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  // between the keys "the quick brown fox" and "the who".  We can use
37179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  // "the r" as the key for the index block entry since it is >= all
38179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  // entries in the first block and < all entries in subsequent
39179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  // blocks.
40179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  //
41179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  // Invariant: r->pending_index_entry is true only if data_block is empty.
42179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  bool pending_index_entry;
43179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  BlockHandle pending_handle;  // Handle to add to index block
44179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org
45179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  std::string compressed_output;
46179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org
47179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  Rep(const Options& opt, WritableFile* f)
48179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org      : options(opt),
49179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org        index_block_options(opt),
50179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org        file(f),
51179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org        offset(0),
52179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org        data_block(&options),
53179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org        index_block(&index_block_options),
54179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org        num_entries(0),
55179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org        closed(false),
5699a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com        filter_block(opt.filter_policy == NULL ? NULL
5799a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com                     : new FilterBlockBuilder(opt.filter_policy)),
58179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org        pending_index_entry(false) {
59179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org    index_block_options.block_restart_interval = 1;
60179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  }
61179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org};
62179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org
63179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.orgTableBuilder::TableBuilder(const Options& options, WritableFile* file)
64179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org    : rep_(new Rep(options, file)) {
6599a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com  if (rep_->filter_block != NULL) {
6699a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    rep_->filter_block->StartBlock(0);
6799a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com  }
68179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org}
69179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org
70179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.orgTableBuilder::~TableBuilder() {
71179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  assert(rep_->closed);  // Catch errors where caller forgot to call Finish()
7299a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com  delete rep_->filter_block;
73179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  delete rep_;
74179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org}
75179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org
76179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.orgStatus TableBuilder::ChangeOptions(const Options& options) {
77179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  // Note: if more fields are added to Options, update
78179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  // this function to catch changes that should not be allowed to
79179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  // change in the middle of building a Table.
80179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  if (options.comparator != rep_->options.comparator) {
81179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org    return Status::InvalidArgument("changing comparator while building table");
82179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  }
83179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org
84179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  // Note that any live BlockBuilders point to rep_->options and therefore
85179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  // will automatically pick up the updated options.
86179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  rep_->options = options;
87179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  rep_->index_block_options = options;
88179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  rep_->index_block_options.block_restart_interval = 1;
89179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  return Status::OK();
90179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org}
91179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org
92179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.orgvoid TableBuilder::Add(const Slice& key, const Slice& value) {
93179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  Rep* r = rep_;
94179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  assert(!r->closed);
95179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  if (!ok()) return;
96179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  if (r->num_entries > 0) {
97179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org    assert(r->options.comparator->Compare(key, Slice(r->last_key)) > 0);
98179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  }
99179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org
100179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  if (r->pending_index_entry) {
101179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org    assert(r->data_block.empty());
102179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org    r->options.comparator->FindShortestSeparator(&r->last_key, key);
103179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org    std::string handle_encoding;
104179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org    r->pending_handle.EncodeTo(&handle_encoding);
105179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org    r->index_block.Add(r->last_key, Slice(handle_encoding));
106179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org    r->pending_index_entry = false;
107179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  }
108179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org
10999a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com  if (r->filter_block != NULL) {
11099a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    r->filter_block->AddKey(key);
11199a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com  }
11299a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com
113179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  r->last_key.assign(key.data(), key.size());
114179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  r->num_entries++;
115179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  r->data_block.Add(key, value);
116179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org
117179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  const size_t estimated_block_size = r->data_block.CurrentSizeEstimate();
118179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  if (estimated_block_size >= r->options.block_size) {
119179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org    Flush();
120179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  }
121179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org}
122179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org
123179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.orgvoid TableBuilder::Flush() {
124179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  Rep* r = rep_;
125179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  assert(!r->closed);
126179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  if (!ok()) return;
127179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  if (r->data_block.empty()) return;
128179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  assert(!r->pending_index_entry);
129179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  WriteBlock(&r->data_block, &r->pending_handle);
130179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  if (ok()) {
131179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org    r->pending_index_entry = true;
132179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org    r->status = r->file->Flush();
133179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  }
13499a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com  if (r->filter_block != NULL) {
13599a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    r->filter_block->StartBlock(r->offset);
13699a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com  }
137179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org}
138179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org
139179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.orgvoid TableBuilder::WriteBlock(BlockBuilder* block, BlockHandle* handle) {
140179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  // File format contains a sequence of blocks where each block has:
141179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  //    block_data: uint8[n]
142179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  //    type: uint8
143179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  //    crc: uint32
144179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  assert(ok());
145179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  Rep* r = rep_;
146179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  Slice raw = block->Finish();
147179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org
148179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  Slice block_contents;
149179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  CompressionType type = r->options.compression;
150179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  // TODO(postrelease): Support more compression options: zlib?
151179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  switch (type) {
152179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org    case kNoCompression:
153179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org      block_contents = raw;
154179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org      break;
155179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org
15607f3bcfb9764be2a339cc02cf0a0d6edb151defbjorlow@chromium.org    case kSnappyCompression: {
15707f3bcfb9764be2a339cc02cf0a0d6edb151defbjorlow@chromium.org      std::string* compressed = &r->compressed_output;
15807f3bcfb9764be2a339cc02cf0a0d6edb151defbjorlow@chromium.org      if (port::Snappy_Compress(raw.data(), raw.size(), compressed) &&
15907f3bcfb9764be2a339cc02cf0a0d6edb151defbjorlow@chromium.org          compressed->size() < raw.size() - (raw.size() / 8u)) {
16007f3bcfb9764be2a339cc02cf0a0d6edb151defbjorlow@chromium.org        block_contents = *compressed;
16107f3bcfb9764be2a339cc02cf0a0d6edb151defbjorlow@chromium.org      } else {
16207f3bcfb9764be2a339cc02cf0a0d6edb151defbjorlow@chromium.org        // Snappy not supported, or compressed less than 12.5%, so just
16307f3bcfb9764be2a339cc02cf0a0d6edb151defbjorlow@chromium.org        // store uncompressed form
164179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org        block_contents = raw;
165179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org        type = kNoCompression;
166179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org      }
167179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org      break;
168179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org    }
169179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  }
17099a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com  WriteRawBlock(block_contents, type, handle);
17199a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com  r->compressed_output.clear();
17299a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com  block->Reset();
17399a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com}
17499a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com
17599a7585544fc162a5f8dd39a6add00776a981efesanjay@google.comvoid TableBuilder::WriteRawBlock(const Slice& block_contents,
17699a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com                                 CompressionType type,
17799a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com                                 BlockHandle* handle) {
17899a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com  Rep* r = rep_;
179179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  handle->set_offset(r->offset);
180179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  handle->set_size(block_contents.size());
181179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  r->status = r->file->Append(block_contents);
182179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  if (r->status.ok()) {
183179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org    char trailer[kBlockTrailerSize];
184179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org    trailer[0] = type;
185179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org    uint32_t crc = crc32c::Value(block_contents.data(), block_contents.size());
186179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org    crc = crc32c::Extend(crc, trailer, 1);  // Extend crc to cover block type
187179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org    EncodeFixed32(trailer+1, crc32c::Mask(crc));
188179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org    r->status = r->file->Append(Slice(trailer, kBlockTrailerSize));
189179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org    if (r->status.ok()) {
190179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org      r->offset += block_contents.size() + kBlockTrailerSize;
191179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org    }
192179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  }
193179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org}
194179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org
195179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.orgStatus TableBuilder::status() const {
196179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  return rep_->status;
197179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org}
198179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org
199179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.orgStatus TableBuilder::Finish() {
200179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  Rep* r = rep_;
201179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  Flush();
202179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  assert(!r->closed);
203179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  r->closed = true;
20499a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com
20599a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com  BlockHandle filter_block_handle, metaindex_block_handle, index_block_handle;
20699a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com
20799a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com  // Write filter block
20899a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com  if (ok() && r->filter_block != NULL) {
20999a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    WriteRawBlock(r->filter_block->Finish(), kNoCompression,
21099a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com                  &filter_block_handle);
21199a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com  }
21299a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com
21399a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com  // Write metaindex block
214179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  if (ok()) {
215179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org    BlockBuilder meta_index_block(&r->options);
21699a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    if (r->filter_block != NULL) {
21799a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com      // Add mapping from "filter.Name" to location of filter data
21899a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com      std::string key = "filter.";
21999a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com      key.append(r->options.filter_policy->Name());
22099a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com      std::string handle_encoding;
22199a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com      filter_block_handle.EncodeTo(&handle_encoding);
22299a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com      meta_index_block.Add(key, handle_encoding);
22399a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    }
22499a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com
225179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org    // TODO(postrelease): Add stats and other meta blocks
226179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org    WriteBlock(&meta_index_block, &metaindex_block_handle);
227179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  }
22899a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com
22999a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com  // Write index block
230179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  if (ok()) {
231179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org    if (r->pending_index_entry) {
232179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org      r->options.comparator->FindShortSuccessor(&r->last_key);
233179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org      std::string handle_encoding;
234179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org      r->pending_handle.EncodeTo(&handle_encoding);
235179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org      r->index_block.Add(r->last_key, Slice(handle_encoding));
236179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org      r->pending_index_entry = false;
237179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org    }
238179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org    WriteBlock(&r->index_block, &index_block_handle);
239179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  }
24099a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com
24199a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com  // Write footer
242179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  if (ok()) {
243179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org    Footer footer;
244179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org    footer.set_metaindex_handle(metaindex_block_handle);
245179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org    footer.set_index_handle(index_block_handle);
246179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org    std::string footer_encoding;
247179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org    footer.EncodeTo(&footer_encoding);
248179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org    r->status = r->file->Append(footer_encoding);
249179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org    if (r->status.ok()) {
250179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org      r->offset += footer_encoding.size();
251179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org    }
252179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  }
253179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  return r->status;
254179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org}
255179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org
256179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.orgvoid TableBuilder::Abandon() {
257179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  Rep* r = rep_;
258179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  assert(!r->closed);
259179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  r->closed = true;
260179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org}
261179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org
262179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.orguint64_t TableBuilder::NumEntries() const {
263179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  return rep_->num_entries;
264179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org}
265179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org
266179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.orguint64_t TableBuilder::FileSize() const {
267179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  return rep_->offset;
268179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org}
269179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org
27045b9940be332834440bd5299419f396e38085ebehans@chromium.org}  // namespace leveldb
271