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// 5179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org// We recover the contents of the descriptor from the other files we find. 6179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org// (1) Any log files are first converted to tables 7179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org// (2) We scan every table to compute 8179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org// (a) smallest/largest for the table 91511be6edb54b6ade2bfad94256f76bc191e92ecdgrogan@chromium.org// (b) largest sequence number in the table 10179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org// (3) We generate descriptor contents: 11179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org// - log number is set to zero 12179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org// - next-file-number is set to 1 + largest file number we found 13179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org// - last-sequence-number is set to largest sequence# found across 14179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org// all tables (see 2c) 15179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org// - compaction pointers are cleared 16179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org// - every table file is added at level 0 17179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org// 18179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org// Possible optimization 1: 19179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org// (a) Compute total size and use to pick appropriate max-level M 20179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org// (b) Sort tables by largest sequence# in the table 21179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org// (c) For each table: if it overlaps earlier table, place in level-0, 22179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org// else place in level-M. 23179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org// Possible optimization 2: 241511be6edb54b6ade2bfad94256f76bc191e92ecdgrogan@chromium.org// Store per-table metadata (smallest, largest, largest-seq#, ...) 251511be6edb54b6ade2bfad94256f76bc191e92ecdgrogan@chromium.org// in the table's meta section to speed up ScanTable. 26179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org 27179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org#include "db/builder.h" 28179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org#include "db/db_impl.h" 29179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org#include "db/dbformat.h" 30179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org#include "db/filename.h" 31179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org#include "db/log_reader.h" 32179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org#include "db/log_writer.h" 33179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org#include "db/memtable.h" 34179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org#include "db/table_cache.h" 35179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org#include "db/version_edit.h" 36179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org#include "db/write_batch_internal.h" 37fbd97aa4c5325eace57d24b89845b9581bac9324jorlow@chromium.org#include "leveldb/comparator.h" 38fbd97aa4c5325eace57d24b89845b9581bac9324jorlow@chromium.org#include "leveldb/db.h" 39fbd97aa4c5325eace57d24b89845b9581bac9324jorlow@chromium.org#include "leveldb/env.h" 40179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org 41179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.orgnamespace leveldb { 42179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org 43179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.orgnamespace { 44179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org 45179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.orgclass Repairer { 46179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org public: 47179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org Repairer(const std::string& dbname, const Options& options) 48179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org : dbname_(dbname), 49179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org env_(options.env), 50179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org icmp_(options.comparator), 5199a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com ipolicy_(options.filter_policy), 5299a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com options_(SanitizeOptions(dbname, &icmp_, &ipolicy_, options)), 53179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org owns_info_log_(options_.info_log != options.info_log), 5451f892d349df9ed408f5a0e6e012667e5eae5f8bgabor@google.com owns_cache_(options_.block_cache != options.block_cache), 55179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org next_file_number_(1) { 56179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org // TableCache can be small since we expect each table to be opened once. 57179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org table_cache_ = new TableCache(dbname_, &options_, 10); 58179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org } 59179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org 60179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org ~Repairer() { 61179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org delete table_cache_; 62179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org if (owns_info_log_) { 63179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org delete options_.info_log; 64179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org } 6551f892d349df9ed408f5a0e6e012667e5eae5f8bgabor@google.com if (owns_cache_) { 6651f892d349df9ed408f5a0e6e012667e5eae5f8bgabor@google.com delete options_.block_cache; 6751f892d349df9ed408f5a0e6e012667e5eae5f8bgabor@google.com } 68179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org } 69179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org 70179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org Status Run() { 71179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org Status status = FindFiles(); 72179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org if (status.ok()) { 73179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org ConvertLogFilesToTables(); 74179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org ExtractMetaData(); 75179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org status = WriteDescriptor(); 76179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org } 77179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org if (status.ok()) { 78179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org unsigned long long bytes = 0; 791511be6edb54b6ade2bfad94256f76bc191e92ecdgrogan@chromium.org for (size_t i = 0; i < tables_.size(); i++) { 80179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org bytes += tables_[i].meta.file_size; 81179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org } 82f65a55c8d0744b95be29a65d06b59b22b012f37bgabor@google.com Log(options_.info_log, 83179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org "**** Repaired leveldb %s; " 84179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org "recovered %d files; %llu bytes. " 85179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org "Some data may have been lost. " 86179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org "****", 87179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org dbname_.c_str(), 88179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org static_cast<int>(tables_.size()), 89179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org bytes); 90179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org } 91179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org return status; 92179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org } 93179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org 94179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org private: 95179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org struct TableInfo { 96179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org FileMetaData meta; 97179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org SequenceNumber max_sequence; 98179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org }; 99179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org 100179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org std::string const dbname_; 101179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org Env* const env_; 102179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org InternalKeyComparator const icmp_; 10399a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com InternalFilterPolicy const ipolicy_; 104179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org Options const options_; 105179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org bool owns_info_log_; 10651f892d349df9ed408f5a0e6e012667e5eae5f8bgabor@google.com bool owns_cache_; 107179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org TableCache* table_cache_; 108179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org VersionEdit edit_; 109179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org 110179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org std::vector<std::string> manifests_; 111179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org std::vector<uint64_t> table_numbers_; 112179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org std::vector<uint64_t> logs_; 113179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org std::vector<TableInfo> tables_; 114179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org uint64_t next_file_number_; 115179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org 116179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org Status FindFiles() { 117179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org std::vector<std::string> filenames; 118179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org Status status = env_->GetChildren(dbname_, &filenames); 119179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org if (!status.ok()) { 120179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org return status; 121179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org } 122179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org if (filenames.empty()) { 123179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org return Status::IOError(dbname_, "repair found no files"); 124179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org } 125179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org 126179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org uint64_t number; 127179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org FileType type; 1281511be6edb54b6ade2bfad94256f76bc191e92ecdgrogan@chromium.org for (size_t i = 0; i < filenames.size(); i++) { 1291511be6edb54b6ade2bfad94256f76bc191e92ecdgrogan@chromium.org if (ParseFileName(filenames[i], &number, &type)) { 1301511be6edb54b6ade2bfad94256f76bc191e92ecdgrogan@chromium.org if (type == kDescriptorFile) { 131179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org manifests_.push_back(filenames[i]); 132179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org } else { 133179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org if (number + 1 > next_file_number_) { 134179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org next_file_number_ = number + 1; 135179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org } 136179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org if (type == kLogFile) { 137179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org logs_.push_back(number); 138179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org } else if (type == kTableFile) { 139179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org table_numbers_.push_back(number); 140179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org } else { 141179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org // Ignore other files 142179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org } 143179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org } 144179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org } 145179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org } 146179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org return status; 147179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org } 148179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org 149179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org void ConvertLogFilesToTables() { 1501511be6edb54b6ade2bfad94256f76bc191e92ecdgrogan@chromium.org for (size_t i = 0; i < logs_.size(); i++) { 151179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org std::string logname = LogFileName(dbname_, logs_[i]); 152179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org Status status = ConvertLogToTable(logs_[i]); 153179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org if (!status.ok()) { 154f65a55c8d0744b95be29a65d06b59b22b012f37bgabor@google.com Log(options_.info_log, "Log #%llu: ignoring conversion error: %s", 155179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org (unsigned long long) logs_[i], 156179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org status.ToString().c_str()); 157179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org } 158179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org ArchiveFile(logname); 159179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org } 160179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org } 161179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org 162179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org Status ConvertLogToTable(uint64_t log) { 163179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org struct LogReporter : public log::Reader::Reporter { 164179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org Env* env; 165f65a55c8d0744b95be29a65d06b59b22b012f37bgabor@google.com Logger* info_log; 166179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org uint64_t lognum; 167179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org virtual void Corruption(size_t bytes, const Status& s) { 168179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org // We print error messages for corruption, but continue repairing. 169f65a55c8d0744b95be29a65d06b59b22b012f37bgabor@google.com Log(info_log, "Log #%llu: dropping %d bytes; %s", 170179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org (unsigned long long) lognum, 171179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org static_cast<int>(bytes), 172179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org s.ToString().c_str()); 173179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org } 174179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org }; 175179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org 176179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org // Open the log file 177179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org std::string logname = LogFileName(dbname_, log); 178179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org SequentialFile* lfile; 179179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org Status status = env_->NewSequentialFile(logname, &lfile); 180179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org if (!status.ok()) { 181179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org return status; 182179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org } 183179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org 184179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org // Create the log reader. 185179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org LogReporter reporter; 186179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org reporter.env = env_; 187179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org reporter.info_log = options_.info_log; 188179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org reporter.lognum = log; 189179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org // We intentially make log::Reader do checksumming so that 190179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org // corruptions cause entire commits to be skipped instead of 191179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org // propagating bad information (like overly large sequence 192179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org // numbers). 193a5b4129c0a8c01158cde2244a5811f15b9d45ec0dgrogan@chromium.org log::Reader reader(lfile, &reporter, false/*do not checksum*/, 194a5b4129c0a8c01158cde2244a5811f15b9d45ec0dgrogan@chromium.org 0/*initial_offset*/); 195179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org 196179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org // Read all the records and add to a memtable 197179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org std::string scratch; 198179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org Slice record; 199179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org WriteBatch batch; 200a5b4129c0a8c01158cde2244a5811f15b9d45ec0dgrogan@chromium.org MemTable* mem = new MemTable(icmp_); 201a5b4129c0a8c01158cde2244a5811f15b9d45ec0dgrogan@chromium.org mem->Ref(); 202179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org int counter = 0; 203179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org while (reader.ReadRecord(&record, &scratch)) { 204179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org if (record.size() < 12) { 205179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org reporter.Corruption( 206179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org record.size(), Status::Corruption("log record too small")); 207179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org continue; 208179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org } 209179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org WriteBatchInternal::SetContents(&batch, record); 210a5b4129c0a8c01158cde2244a5811f15b9d45ec0dgrogan@chromium.org status = WriteBatchInternal::InsertInto(&batch, mem); 211179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org if (status.ok()) { 212179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org counter += WriteBatchInternal::Count(&batch); 213179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org } else { 214f65a55c8d0744b95be29a65d06b59b22b012f37bgabor@google.com Log(options_.info_log, "Log #%llu: ignoring %s", 215179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org (unsigned long long) log, 216179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org status.ToString().c_str()); 217179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org status = Status::OK(); // Keep going with rest of file 218179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org } 219179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org } 220179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org delete lfile; 221179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org 2228cd4ab8303620197cf24282ae8639060efbb326egabor@google.com // Do not record a version edit for this conversion to a Table 223179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org // since ExtractMetaData() will also generate edits. 224179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org FileMetaData meta; 225179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org meta.number = next_file_number_++; 226a5b4129c0a8c01158cde2244a5811f15b9d45ec0dgrogan@chromium.org Iterator* iter = mem->NewIterator(); 2278cd4ab8303620197cf24282ae8639060efbb326egabor@google.com status = BuildTable(dbname_, env_, options_, table_cache_, iter, &meta); 228179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org delete iter; 229a5b4129c0a8c01158cde2244a5811f15b9d45ec0dgrogan@chromium.org mem->Unref(); 230a5b4129c0a8c01158cde2244a5811f15b9d45ec0dgrogan@chromium.org mem = NULL; 231179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org if (status.ok()) { 232179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org if (meta.file_size > 0) { 233179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org table_numbers_.push_back(meta.number); 234179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org } 235179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org } 236f65a55c8d0744b95be29a65d06b59b22b012f37bgabor@google.com Log(options_.info_log, "Log #%llu: %d ops saved to Table #%llu %s", 237179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org (unsigned long long) log, 238179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org counter, 239179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org (unsigned long long) meta.number, 240179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org status.ToString().c_str()); 241179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org return status; 242179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org } 243179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org 244179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org void ExtractMetaData() { 2451511be6edb54b6ade2bfad94256f76bc191e92ecdgrogan@chromium.org for (size_t i = 0; i < table_numbers_.size(); i++) { 2464935bf087b28aa308c0a820720b85ef695e236aedgrogan@chromium.org ScanTable(table_numbers_[i]); 247179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org } 248179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org } 249179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org 2504935bf087b28aa308c0a820720b85ef695e236aedgrogan@chromium.org Iterator* NewTableIterator(const FileMetaData& meta) { 2514935bf087b28aa308c0a820720b85ef695e236aedgrogan@chromium.org // Same as compaction iterators: if paranoid_checks are on, turn 2524935bf087b28aa308c0a820720b85ef695e236aedgrogan@chromium.org // on checksum verification. 2534935bf087b28aa308c0a820720b85ef695e236aedgrogan@chromium.org ReadOptions r; 2544935bf087b28aa308c0a820720b85ef695e236aedgrogan@chromium.org r.verify_checksums = options_.paranoid_checks; 2554935bf087b28aa308c0a820720b85ef695e236aedgrogan@chromium.org return table_cache_->NewIterator(r, meta.number, meta.file_size); 2564935bf087b28aa308c0a820720b85ef695e236aedgrogan@chromium.org } 2574935bf087b28aa308c0a820720b85ef695e236aedgrogan@chromium.org 2584935bf087b28aa308c0a820720b85ef695e236aedgrogan@chromium.org void ScanTable(uint64_t number) { 2594935bf087b28aa308c0a820720b85ef695e236aedgrogan@chromium.org TableInfo t; 2604935bf087b28aa308c0a820720b85ef695e236aedgrogan@chromium.org t.meta.number = number; 2614935bf087b28aa308c0a820720b85ef695e236aedgrogan@chromium.org std::string fname = TableFileName(dbname_, number); 2624935bf087b28aa308c0a820720b85ef695e236aedgrogan@chromium.org Status status = env_->GetFileSize(fname, &t.meta.file_size); 2632d749ea62f0e47281e82794c8e00eb588cd66616dgrogan@chromium.org if (!status.ok()) { 2644935bf087b28aa308c0a820720b85ef695e236aedgrogan@chromium.org // Try alternate file name. 2654935bf087b28aa308c0a820720b85ef695e236aedgrogan@chromium.org fname = SSTTableFileName(dbname_, number); 2664935bf087b28aa308c0a820720b85ef695e236aedgrogan@chromium.org Status s2 = env_->GetFileSize(fname, &t.meta.file_size); 2674935bf087b28aa308c0a820720b85ef695e236aedgrogan@chromium.org if (s2.ok()) { 2682d749ea62f0e47281e82794c8e00eb588cd66616dgrogan@chromium.org status = Status::OK(); 2694935bf087b28aa308c0a820720b85ef695e236aedgrogan@chromium.org } 2704935bf087b28aa308c0a820720b85ef695e236aedgrogan@chromium.org } 2714935bf087b28aa308c0a820720b85ef695e236aedgrogan@chromium.org if (!status.ok()) { 2724935bf087b28aa308c0a820720b85ef695e236aedgrogan@chromium.org ArchiveFile(TableFileName(dbname_, number)); 2734935bf087b28aa308c0a820720b85ef695e236aedgrogan@chromium.org ArchiveFile(SSTTableFileName(dbname_, number)); 2744935bf087b28aa308c0a820720b85ef695e236aedgrogan@chromium.org Log(options_.info_log, "Table #%llu: dropped: %s", 2754935bf087b28aa308c0a820720b85ef695e236aedgrogan@chromium.org (unsigned long long) t.meta.number, 2764935bf087b28aa308c0a820720b85ef695e236aedgrogan@chromium.org status.ToString().c_str()); 2774935bf087b28aa308c0a820720b85ef695e236aedgrogan@chromium.org return; 2782d749ea62f0e47281e82794c8e00eb588cd66616dgrogan@chromium.org } 279179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org 2804935bf087b28aa308c0a820720b85ef695e236aedgrogan@chromium.org // Extract metadata by scanning through table. 2814935bf087b28aa308c0a820720b85ef695e236aedgrogan@chromium.org int counter = 0; 2824935bf087b28aa308c0a820720b85ef695e236aedgrogan@chromium.org Iterator* iter = NewTableIterator(t.meta); 2834935bf087b28aa308c0a820720b85ef695e236aedgrogan@chromium.org bool empty = true; 2844935bf087b28aa308c0a820720b85ef695e236aedgrogan@chromium.org ParsedInternalKey parsed; 2854935bf087b28aa308c0a820720b85ef695e236aedgrogan@chromium.org t.max_sequence = 0; 2864935bf087b28aa308c0a820720b85ef695e236aedgrogan@chromium.org for (iter->SeekToFirst(); iter->Valid(); iter->Next()) { 2874935bf087b28aa308c0a820720b85ef695e236aedgrogan@chromium.org Slice key = iter->key(); 2884935bf087b28aa308c0a820720b85ef695e236aedgrogan@chromium.org if (!ParseInternalKey(key, &parsed)) { 2894935bf087b28aa308c0a820720b85ef695e236aedgrogan@chromium.org Log(options_.info_log, "Table #%llu: unparsable key %s", 2904935bf087b28aa308c0a820720b85ef695e236aedgrogan@chromium.org (unsigned long long) t.meta.number, 2914935bf087b28aa308c0a820720b85ef695e236aedgrogan@chromium.org EscapeString(key).c_str()); 2924935bf087b28aa308c0a820720b85ef695e236aedgrogan@chromium.org continue; 293179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org } 2944935bf087b28aa308c0a820720b85ef695e236aedgrogan@chromium.org 2954935bf087b28aa308c0a820720b85ef695e236aedgrogan@chromium.org counter++; 2964935bf087b28aa308c0a820720b85ef695e236aedgrogan@chromium.org if (empty) { 2974935bf087b28aa308c0a820720b85ef695e236aedgrogan@chromium.org empty = false; 2984935bf087b28aa308c0a820720b85ef695e236aedgrogan@chromium.org t.meta.smallest.DecodeFrom(key); 2994935bf087b28aa308c0a820720b85ef695e236aedgrogan@chromium.org } 3004935bf087b28aa308c0a820720b85ef695e236aedgrogan@chromium.org t.meta.largest.DecodeFrom(key); 3014935bf087b28aa308c0a820720b85ef695e236aedgrogan@chromium.org if (parsed.sequence > t.max_sequence) { 3024935bf087b28aa308c0a820720b85ef695e236aedgrogan@chromium.org t.max_sequence = parsed.sequence; 303179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org } 304179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org } 3054935bf087b28aa308c0a820720b85ef695e236aedgrogan@chromium.org if (!iter->status().ok()) { 3064935bf087b28aa308c0a820720b85ef695e236aedgrogan@chromium.org status = iter->status(); 3074935bf087b28aa308c0a820720b85ef695e236aedgrogan@chromium.org } 3084935bf087b28aa308c0a820720b85ef695e236aedgrogan@chromium.org delete iter; 309f65a55c8d0744b95be29a65d06b59b22b012f37bgabor@google.com Log(options_.info_log, "Table #%llu: %d entries %s", 3104935bf087b28aa308c0a820720b85ef695e236aedgrogan@chromium.org (unsigned long long) t.meta.number, 311179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org counter, 312179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org status.ToString().c_str()); 3134935bf087b28aa308c0a820720b85ef695e236aedgrogan@chromium.org 3144935bf087b28aa308c0a820720b85ef695e236aedgrogan@chromium.org if (status.ok()) { 3154935bf087b28aa308c0a820720b85ef695e236aedgrogan@chromium.org tables_.push_back(t); 3164935bf087b28aa308c0a820720b85ef695e236aedgrogan@chromium.org } else { 3174935bf087b28aa308c0a820720b85ef695e236aedgrogan@chromium.org RepairTable(fname, t); // RepairTable archives input file. 3184935bf087b28aa308c0a820720b85ef695e236aedgrogan@chromium.org } 3194935bf087b28aa308c0a820720b85ef695e236aedgrogan@chromium.org } 3204935bf087b28aa308c0a820720b85ef695e236aedgrogan@chromium.org 3214935bf087b28aa308c0a820720b85ef695e236aedgrogan@chromium.org void RepairTable(const std::string& src, TableInfo t) { 3224935bf087b28aa308c0a820720b85ef695e236aedgrogan@chromium.org // We will copy src contents to a new table and then rename the 3234935bf087b28aa308c0a820720b85ef695e236aedgrogan@chromium.org // new table over the source. 3244935bf087b28aa308c0a820720b85ef695e236aedgrogan@chromium.org 3254935bf087b28aa308c0a820720b85ef695e236aedgrogan@chromium.org // Create builder. 3264935bf087b28aa308c0a820720b85ef695e236aedgrogan@chromium.org std::string copy = TableFileName(dbname_, next_file_number_++); 3274935bf087b28aa308c0a820720b85ef695e236aedgrogan@chromium.org WritableFile* file; 3284935bf087b28aa308c0a820720b85ef695e236aedgrogan@chromium.org Status s = env_->NewWritableFile(copy, &file); 3294935bf087b28aa308c0a820720b85ef695e236aedgrogan@chromium.org if (!s.ok()) { 3304935bf087b28aa308c0a820720b85ef695e236aedgrogan@chromium.org return; 3314935bf087b28aa308c0a820720b85ef695e236aedgrogan@chromium.org } 3324935bf087b28aa308c0a820720b85ef695e236aedgrogan@chromium.org TableBuilder* builder = new TableBuilder(options_, file); 3334935bf087b28aa308c0a820720b85ef695e236aedgrogan@chromium.org 3344935bf087b28aa308c0a820720b85ef695e236aedgrogan@chromium.org // Copy data. 3354935bf087b28aa308c0a820720b85ef695e236aedgrogan@chromium.org Iterator* iter = NewTableIterator(t.meta); 3364935bf087b28aa308c0a820720b85ef695e236aedgrogan@chromium.org int counter = 0; 3374935bf087b28aa308c0a820720b85ef695e236aedgrogan@chromium.org for (iter->SeekToFirst(); iter->Valid(); iter->Next()) { 3384935bf087b28aa308c0a820720b85ef695e236aedgrogan@chromium.org builder->Add(iter->key(), iter->value()); 3394935bf087b28aa308c0a820720b85ef695e236aedgrogan@chromium.org counter++; 3404935bf087b28aa308c0a820720b85ef695e236aedgrogan@chromium.org } 3414935bf087b28aa308c0a820720b85ef695e236aedgrogan@chromium.org delete iter; 3424935bf087b28aa308c0a820720b85ef695e236aedgrogan@chromium.org 3434935bf087b28aa308c0a820720b85ef695e236aedgrogan@chromium.org ArchiveFile(src); 3444935bf087b28aa308c0a820720b85ef695e236aedgrogan@chromium.org if (counter == 0) { 3454935bf087b28aa308c0a820720b85ef695e236aedgrogan@chromium.org builder->Abandon(); // Nothing to save 3464935bf087b28aa308c0a820720b85ef695e236aedgrogan@chromium.org } else { 3474935bf087b28aa308c0a820720b85ef695e236aedgrogan@chromium.org s = builder->Finish(); 3484935bf087b28aa308c0a820720b85ef695e236aedgrogan@chromium.org if (s.ok()) { 3494935bf087b28aa308c0a820720b85ef695e236aedgrogan@chromium.org t.meta.file_size = builder->FileSize(); 3504935bf087b28aa308c0a820720b85ef695e236aedgrogan@chromium.org } 3514935bf087b28aa308c0a820720b85ef695e236aedgrogan@chromium.org } 3524935bf087b28aa308c0a820720b85ef695e236aedgrogan@chromium.org delete builder; 3534935bf087b28aa308c0a820720b85ef695e236aedgrogan@chromium.org builder = NULL; 3544935bf087b28aa308c0a820720b85ef695e236aedgrogan@chromium.org 3554935bf087b28aa308c0a820720b85ef695e236aedgrogan@chromium.org if (s.ok()) { 3564935bf087b28aa308c0a820720b85ef695e236aedgrogan@chromium.org s = file->Close(); 3574935bf087b28aa308c0a820720b85ef695e236aedgrogan@chromium.org } 3584935bf087b28aa308c0a820720b85ef695e236aedgrogan@chromium.org delete file; 3594935bf087b28aa308c0a820720b85ef695e236aedgrogan@chromium.org file = NULL; 3604935bf087b28aa308c0a820720b85ef695e236aedgrogan@chromium.org 3614935bf087b28aa308c0a820720b85ef695e236aedgrogan@chromium.org if (counter > 0 && s.ok()) { 3624935bf087b28aa308c0a820720b85ef695e236aedgrogan@chromium.org std::string orig = TableFileName(dbname_, t.meta.number); 3634935bf087b28aa308c0a820720b85ef695e236aedgrogan@chromium.org s = env_->RenameFile(copy, orig); 3644935bf087b28aa308c0a820720b85ef695e236aedgrogan@chromium.org if (s.ok()) { 3654935bf087b28aa308c0a820720b85ef695e236aedgrogan@chromium.org Log(options_.info_log, "Table #%llu: %d entries repaired", 3664935bf087b28aa308c0a820720b85ef695e236aedgrogan@chromium.org (unsigned long long) t.meta.number, counter); 3674935bf087b28aa308c0a820720b85ef695e236aedgrogan@chromium.org tables_.push_back(t); 3684935bf087b28aa308c0a820720b85ef695e236aedgrogan@chromium.org } 3694935bf087b28aa308c0a820720b85ef695e236aedgrogan@chromium.org } 3704935bf087b28aa308c0a820720b85ef695e236aedgrogan@chromium.org if (!s.ok()) { 3714935bf087b28aa308c0a820720b85ef695e236aedgrogan@chromium.org env_->DeleteFile(copy); 3724935bf087b28aa308c0a820720b85ef695e236aedgrogan@chromium.org } 373179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org } 374179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org 375179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org Status WriteDescriptor() { 376179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org std::string tmp = TempFileName(dbname_, 1); 377179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org WritableFile* file; 378179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org Status status = env_->NewWritableFile(tmp, &file); 379179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org if (!status.ok()) { 380179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org return status; 381179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org } 382179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org 383179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org SequenceNumber max_sequence = 0; 3841511be6edb54b6ade2bfad94256f76bc191e92ecdgrogan@chromium.org for (size_t i = 0; i < tables_.size(); i++) { 385179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org if (max_sequence < tables_[i].max_sequence) { 386179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org max_sequence = tables_[i].max_sequence; 387179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org } 388179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org } 389179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org 390179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org edit_.SetComparatorName(icmp_.user_comparator()->Name()); 391179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org edit_.SetLogNumber(0); 392179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org edit_.SetNextFile(next_file_number_); 393179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org edit_.SetLastSequence(max_sequence); 394179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org 3951511be6edb54b6ade2bfad94256f76bc191e92ecdgrogan@chromium.org for (size_t i = 0; i < tables_.size(); i++) { 396179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org // TODO(opt): separate out into multiple levels 397179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org const TableInfo& t = tables_[i]; 398179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org edit_.AddFile(0, t.meta.number, t.meta.file_size, 399179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org t.meta.smallest, t.meta.largest); 400179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org } 401179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org 402179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org //fprintf(stderr, "NewDescriptor:\n%s\n", edit_.DebugString().c_str()); 403179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org { 404179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org log::Writer log(file); 405179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org std::string record; 406179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org edit_.EncodeTo(&record); 407179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org status = log.AddRecord(record); 408179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org } 409179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org if (status.ok()) { 410179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org status = file->Close(); 411179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org } 412179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org delete file; 413179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org file = NULL; 414179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org 415179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org if (!status.ok()) { 416179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org env_->DeleteFile(tmp); 417179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org } else { 418179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org // Discard older manifests 4191511be6edb54b6ade2bfad94256f76bc191e92ecdgrogan@chromium.org for (size_t i = 0; i < manifests_.size(); i++) { 420179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org ArchiveFile(dbname_ + "/" + manifests_[i]); 421179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org } 422179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org 423179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org // Install new manifest 424179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org status = env_->RenameFile(tmp, DescriptorFileName(dbname_, 1)); 425179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org if (status.ok()) { 426179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org status = SetCurrentFile(env_, dbname_, 1); 427179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org } else { 428179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org env_->DeleteFile(tmp); 429179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org } 430179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org } 431179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org return status; 432179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org } 433179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org 434179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org void ArchiveFile(const std::string& fname) { 435179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org // Move into another directory. E.g., for 436179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org // dir/foo 437179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org // rename to 438179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org // dir/lost/foo 439179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org const char* slash = strrchr(fname.c_str(), '/'); 440179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org std::string new_dir; 441179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org if (slash != NULL) { 442179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org new_dir.assign(fname.data(), slash - fname.data()); 443179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org } 444179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org new_dir.append("/lost"); 445179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org env_->CreateDir(new_dir); // Ignore error 446179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org std::string new_file = new_dir; 447179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org new_file.append("/"); 448179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org new_file.append((slash == NULL) ? fname.c_str() : slash + 1); 449179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org Status s = env_->RenameFile(fname, new_file); 450f65a55c8d0744b95be29a65d06b59b22b012f37bgabor@google.com Log(options_.info_log, "Archiving %s: %s\n", 451179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org fname.c_str(), s.ToString().c_str()); 452179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org } 453179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org}; 45445b9940be332834440bd5299419f396e38085ebehans@chromium.org} // namespace 455179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org 456179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.orgStatus RepairDB(const std::string& dbname, const Options& options) { 457179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org Repairer repairer(dbname, options); 458179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org return repairer.Run(); 459179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org} 460179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org 46145b9940be332834440bd5299419f396e38085ebehans@chromium.org} // namespace leveldb 462