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/builder.h"
6
7#include "db/filename.h"
8#include "db/dbformat.h"
9#include "db/table_cache.h"
10#include "db/version_edit.h"
11#include "leveldb/db.h"
12#include "leveldb/env.h"
13#include "leveldb/iterator.h"
14
15namespace leveldb {
16
17Status BuildTable(const std::string& dbname,
18                  Env* env,
19                  const Options& options,
20                  TableCache* table_cache,
21                  Iterator* iter,
22                  FileMetaData* meta) {
23  Status s;
24  meta->file_size = 0;
25  iter->SeekToFirst();
26
27  std::string fname = TableFileName(dbname, meta->number);
28  if (iter->Valid()) {
29    WritableFile* file;
30    s = env->NewWritableFile(fname, &file);
31    if (!s.ok()) {
32      return s;
33    }
34
35    TableBuilder* builder = new TableBuilder(options, file);
36    meta->smallest.DecodeFrom(iter->key());
37    for (; iter->Valid(); iter->Next()) {
38      Slice key = iter->key();
39      meta->largest.DecodeFrom(key);
40      builder->Add(key, iter->value());
41    }
42
43    // Finish and check for builder errors
44    if (s.ok()) {
45      s = builder->Finish();
46      if (s.ok()) {
47        meta->file_size = builder->FileSize();
48        assert(meta->file_size > 0);
49      }
50    } else {
51      builder->Abandon();
52    }
53    delete builder;
54
55    // Finish and check for file errors
56    if (s.ok()) {
57      s = file->Sync();
58    }
59    if (s.ok()) {
60      s = file->Close();
61    }
62    delete file;
63    file = NULL;
64
65    if (s.ok()) {
66      // Verify that the table is usable
67      Iterator* it = table_cache->NewIterator(ReadOptions(),
68                                              meta->number,
69                                              meta->file_size);
70      s = it->status();
71      delete it;
72    }
73  }
74
75  // Check for input iterator errors
76  if (!iter->status().ok()) {
77    s = iter->status();
78  }
79
80  if (s.ok() && meta->file_size > 0) {
81    // Keep it
82  } else {
83    env->DeleteFile(fname);
84  }
85  return s;
86}
87
88}  // namespace leveldb
89