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