leveldb
Classes | Public Member Functions | Private Member Functions | Private Attributes | List of all members
leveldb::anonymous_namespace{repair.cc}::Repairer Class Reference
Collaboration diagram for leveldb::anonymous_namespace{repair.cc}::Repairer:
Collaboration graph
[legend]

Classes

struct  TableInfo
 

Public Member Functions

 Repairer (const std::string &dbname, const Options &options)
 
 ~Repairer ()
 
Status Run ()
 

Private Member Functions

Status FindFiles ()
 
void ConvertLogFilesToTables ()
 
Status ConvertLogToTable (uint64_t log)
 
void ExtractMetaData ()
 
IteratorNewTableIterator (const FileMetaData &meta)
 
void ScanTable (uint64_t number)
 
void RepairTable (const std::string &src, TableInfo t)
 
Status WriteDescriptor ()
 
void ArchiveFile (const std::string &fname)
 

Private Attributes

std::string const dbname_
 
Env *const env_
 
InternalKeyComparator const icmp_
 
InternalFilterPolicy const ipolicy_
 
Options const options_
 
bool owns_info_log_
 
bool owns_cache_
 
TableCachetable_cache_
 
VersionEdit edit_
 
std::vector< std::string > manifests_
 
std::vector< uint64_t > table_numbers_
 
std::vector< uint64_t > logs_
 
std::vector< TableInfotables_
 
uint64_t next_file_number_
 

Detailed Description

Definition at line 45 of file repair.cc.


Class Documentation

§ leveldb::anonymous_namespace{repair.cc}::Repairer::TableInfo

struct leveldb::anonymous_namespace{repair.cc}::Repairer::TableInfo

Definition at line 95 of file repair.cc.

Collaboration diagram for leveldb::anonymous_namespace{repair.cc}::Repairer::TableInfo:
Class Members
SequenceNumber max_sequence
FileMetaData meta

Constructor & Destructor Documentation

§ Repairer()

leveldb::anonymous_namespace{repair.cc}::Repairer::Repairer ( const std::string &  dbname,
const Options options 
)
inline

Definition at line 47 of file repair.cc.

48  : dbname_(dbname),
49  env_(options.env),
50  icmp_(options.comparator),
51  ipolicy_(options.filter_policy),
53  owns_info_log_(options_.info_log != options.info_log),
54  owns_cache_(options_.block_cache != options.block_cache),
56  // TableCache can be small since we expect each table to be opened once.
57  table_cache_ = new TableCache(dbname_, &options_, 10);
58  }
static char dbname[200]
Definition: c_test.c:15
Logger * info_log
Definition: options.h:68
Cache * block_cache
Definition: options.h:98
Options SanitizeOptions(const std::string &dbname, const InternalKeyComparator *icmp, const InternalFilterPolicy *ipolicy, const Options &src)
Definition: db_impl.cc:90

§ ~Repairer()

leveldb::anonymous_namespace{repair.cc}::Repairer::~Repairer ( )
inline

Definition at line 60 of file repair.cc.

Member Function Documentation

§ ArchiveFile()

void leveldb::anonymous_namespace{repair.cc}::Repairer::ArchiveFile ( const std::string &  fname)
inlineprivate

Definition at line 434 of file repair.cc.

434  {
435  // Move into another directory. E.g., for
436  // dir/foo
437  // rename to
438  // dir/lost/foo
439  const char* slash = strrchr(fname.c_str(), '/');
440  std::string new_dir;
441  if (slash != NULL) {
442  new_dir.assign(fname.data(), slash - fname.data());
443  }
444  new_dir.append("/lost");
445  env_->CreateDir(new_dir); // Ignore error
446  std::string new_file = new_dir;
447  new_file.append("/");
448  new_file.append((slash == NULL) ? fname.c_str() : slash + 1);
449  Status s = env_->RenameFile(fname, new_file);
450  Log(options_.info_log, "Archiving %s: %s\n",
451  fname.c_str(), s.ToString().c_str());
452  }
void Log(Logger *info_log, const char *format,...)
Definition: env.cc:31
virtual Status CreateDir(const std::string &dirname)=0
virtual Status RenameFile(const std::string &src, const std::string &target)=0
Logger * info_log
Definition: options.h:68
Here is the call graph for this function:

§ ConvertLogFilesToTables()

void leveldb::anonymous_namespace{repair.cc}::Repairer::ConvertLogFilesToTables ( )
inlineprivate

Definition at line 149 of file repair.cc.

149  {
150  for (size_t i = 0; i < logs_.size(); i++) {
151  std::string logname = LogFileName(dbname_, logs_[i]);
152  Status status = ConvertLogToTable(logs_[i]);
153  if (!status.ok()) {
154  Log(options_.info_log, "Log #%llu: ignoring conversion error: %s",
155  (unsigned long long) logs_[i],
156  status.ToString().c_str());
157  }
158  ArchiveFile(logname);
159  }
160  }
void ArchiveFile(const std::string &fname)
Definition: repair.cc:434
void Log(Logger *info_log, const char *format,...)
Definition: env.cc:31
Logger * info_log
Definition: options.h:68
std::string LogFileName(const std::string &name, uint64_t number)
Definition: filename.cc:27
Here is the call graph for this function:

§ ConvertLogToTable()

Status leveldb::anonymous_namespace{repair.cc}::Repairer::ConvertLogToTable ( uint64_t  log)
inlineprivate

Definition at line 162 of file repair.cc.

162  {
163  struct LogReporter : public log::Reader::Reporter {
164  Env* env;
165  Logger* info_log;
166  uint64_t lognum;
167  virtual void Corruption(size_t bytes, const Status& s) {
168  // We print error messages for corruption, but continue repairing.
169  Log(info_log, "Log #%llu: dropping %d bytes; %s",
170  (unsigned long long) lognum,
171  static_cast<int>(bytes),
172  s.ToString().c_str());
173  }
174  };
175 
176  // Open the log file
177  std::string logname = LogFileName(dbname_, log);
178  SequentialFile* lfile;
179  Status status = env_->NewSequentialFile(logname, &lfile);
180  if (!status.ok()) {
181  return status;
182  }
183 
184  // Create the log reader.
185  LogReporter reporter;
186  reporter.env = env_;
187  reporter.info_log = options_.info_log;
188  reporter.lognum = log;
189  // We intentionally make log::Reader do checksumming so that
190  // corruptions cause entire commits to be skipped instead of
191  // propagating bad information (like overly large sequence
192  // numbers).
193  log::Reader reader(lfile, &reporter, false/*do not checksum*/,
194  0/*initial_offset*/);
195 
196  // Read all the records and add to a memtable
197  std::string scratch;
198  Slice record;
199  WriteBatch batch;
200  MemTable* mem = new MemTable(icmp_);
201  mem->Ref();
202  int counter = 0;
203  while (reader.ReadRecord(&record, &scratch)) {
204  if (record.size() < 12) {
205  reporter.Corruption(
206  record.size(), Status::Corruption("log record too small"));
207  continue;
208  }
209  WriteBatchInternal::SetContents(&batch, record);
210  status = WriteBatchInternal::InsertInto(&batch, mem);
211  if (status.ok()) {
212  counter += WriteBatchInternal::Count(&batch);
213  } else {
214  Log(options_.info_log, "Log #%llu: ignoring %s",
215  (unsigned long long) log,
216  status.ToString().c_str());
217  status = Status::OK(); // Keep going with rest of file
218  }
219  }
220  delete lfile;
221 
222  // Do not record a version edit for this conversion to a Table
223  // since ExtractMetaData() will also generate edits.
224  FileMetaData meta;
225  meta.number = next_file_number_++;
226  Iterator* iter = mem->NewIterator();
227  status = BuildTable(dbname_, env_, options_, table_cache_, iter, &meta);
228  delete iter;
229  mem->Unref();
230  mem = NULL;
231  if (status.ok()) {
232  if (meta.file_size > 0) {
233  table_numbers_.push_back(meta.number);
234  }
235  }
236  Log(options_.info_log, "Log #%llu: %d ops saved to Table #%llu %s",
237  (unsigned long long) log,
238  counter,
239  (unsigned long long) meta.number,
240  status.ToString().c_str());
241  return status;
242  }
static Status InsertInto(const WriteBatch *batch, MemTable *memtable)
Definition: write_batch.cc:128
void Log(Logger *info_log, const char *format,...)
Definition: env.cc:31
static Status Corruption(const Slice &msg, const Slice &msg2=Slice())
Definition: status.h:38
static Status OK()
Definition: status.h:32
static void SetContents(WriteBatch *batch, const Slice &contents)
Definition: write_batch.cc:136
Logger * info_log
Definition: options.h:68
static int Count(const WriteBatch *batch)
Definition: write_batch.cc:82
virtual Status NewSequentialFile(const std::string &fname, SequentialFile **result)=0
std::string LogFileName(const std::string &name, uint64_t number)
Definition: filename.cc:27
Status BuildTable(const std::string &dbname, Env *env, const Options &options, TableCache *table_cache, Iterator *iter, FileMetaData *meta)
Definition: builder.cc:17
Here is the call graph for this function:

§ ExtractMetaData()

void leveldb::anonymous_namespace{repair.cc}::Repairer::ExtractMetaData ( )
inlineprivate

Definition at line 244 of file repair.cc.

244  {
245  for (size_t i = 0; i < table_numbers_.size(); i++) {
247  }
248  }

§ FindFiles()

Status leveldb::anonymous_namespace{repair.cc}::Repairer::FindFiles ( )
inlineprivate

Definition at line 116 of file repair.cc.

116  {
117  std::vector<std::string> filenames;
118  Status status = env_->GetChildren(dbname_, &filenames);
119  if (!status.ok()) {
120  return status;
121  }
122  if (filenames.empty()) {
123  return Status::IOError(dbname_, "repair found no files");
124  }
125 
126  uint64_t number;
127  FileType type;
128  for (size_t i = 0; i < filenames.size(); i++) {
129  if (ParseFileName(filenames[i], &number, &type)) {
130  if (type == kDescriptorFile) {
131  manifests_.push_back(filenames[i]);
132  } else {
133  if (number + 1 > next_file_number_) {
134  next_file_number_ = number + 1;
135  }
136  if (type == kLogFile) {
137  logs_.push_back(number);
138  } else if (type == kTableFile) {
139  table_numbers_.push_back(number);
140  } else {
141  // Ignore other files
142  }
143  }
144  }
145  }
146  return status;
147  }
bool ParseFileName(const std::string &fname, uint64_t *number, FileType *type)
Definition: filename.cc:80
FileType
Definition: filename.h:20
static Status IOError(const Slice &msg, const Slice &msg2=Slice())
Definition: status.h:47
virtual Status GetChildren(const std::string &dir, std::vector< std::string > *result)=0
Here is the call graph for this function:

§ NewTableIterator()

Iterator* leveldb::anonymous_namespace{repair.cc}::Repairer::NewTableIterator ( const FileMetaData meta)
inlineprivate

Definition at line 250 of file repair.cc.

250  {
251  // Same as compaction iterators: if paranoid_checks are on, turn
252  // on checksum verification.
253  ReadOptions r;
254  r.verify_checksums = options_.paranoid_checks;
255  return table_cache_->NewIterator(r, meta.number, meta.file_size);
256  }
Iterator * NewIterator(const ReadOptions &options, uint64_t file_number, uint64_t file_size, Table **tableptr=NULL)
Definition: table_cache.cc:82
bool paranoid_checks
Definition: options.h:57
Here is the call graph for this function:

§ RepairTable()

void leveldb::anonymous_namespace{repair.cc}::Repairer::RepairTable ( const std::string &  src,
TableInfo  t 
)
inlineprivate

Definition at line 321 of file repair.cc.

321  {
322  // We will copy src contents to a new table and then rename the
323  // new table over the source.
324 
325  // Create builder.
326  std::string copy = TableFileName(dbname_, next_file_number_++);
327  WritableFile* file;
328  Status s = env_->NewWritableFile(copy, &file);
329  if (!s.ok()) {
330  return;
331  }
332  TableBuilder* builder = new TableBuilder(options_, file);
333 
334  // Copy data.
335  Iterator* iter = NewTableIterator(t.meta);
336  int counter = 0;
337  for (iter->SeekToFirst(); iter->Valid(); iter->Next()) {
338  builder->Add(iter->key(), iter->value());
339  counter++;
340  }
341  delete iter;
342 
343  ArchiveFile(src);
344  if (counter == 0) {
345  builder->Abandon(); // Nothing to save
346  } else {
347  s = builder->Finish();
348  if (s.ok()) {
349  t.meta.file_size = builder->FileSize();
350  }
351  }
352  delete builder;
353  builder = NULL;
354 
355  if (s.ok()) {
356  s = file->Close();
357  }
358  delete file;
359  file = NULL;
360 
361  if (counter > 0 && s.ok()) {
362  std::string orig = TableFileName(dbname_, t.meta.number);
363  s = env_->RenameFile(copy, orig);
364  if (s.ok()) {
365  Log(options_.info_log, "Table #%llu: %d entries repaired",
366  (unsigned long long) t.meta.number, counter);
367  tables_.push_back(t);
368  }
369  }
370  if (!s.ok()) {
371  env_->DeleteFile(copy);
372  }
373  }
void ArchiveFile(const std::string &fname)
Definition: repair.cc:434
void Log(Logger *info_log, const char *format,...)
Definition: env.cc:31
virtual Status NewWritableFile(const std::string &fname, WritableFile **result)=0
std::string TableFileName(const std::string &name, uint64_t number)
Definition: filename.cc:32
virtual Status RenameFile(const std::string &src, const std::string &target)=0
Iterator * NewTableIterator(const FileMetaData &meta)
Definition: repair.cc:250
Logger * info_log
Definition: options.h:68
virtual Status DeleteFile(const std::string &fname)=0
Here is the call graph for this function:

§ Run()

Status leveldb::anonymous_namespace{repair.cc}::Repairer::Run ( )
inline

Definition at line 70 of file repair.cc.

70  {
71  Status status = FindFiles();
72  if (status.ok()) {
75  status = WriteDescriptor();
76  }
77  if (status.ok()) {
78  unsigned long long bytes = 0;
79  for (size_t i = 0; i < tables_.size(); i++) {
80  bytes += tables_[i].meta.file_size;
81  }
83  "**** Repaired leveldb %s; "
84  "recovered %d files; %llu bytes. "
85  "Some data may have been lost. "
86  "****",
87  dbname_.c_str(),
88  static_cast<int>(tables_.size()),
89  bytes);
90  }
91  return status;
92  }
void Log(Logger *info_log, const char *format,...)
Definition: env.cc:31
Logger * info_log
Definition: options.h:68
Here is the call graph for this function:

§ ScanTable()

void leveldb::anonymous_namespace{repair.cc}::Repairer::ScanTable ( uint64_t  number)
inlineprivate

Definition at line 258 of file repair.cc.

258  {
259  TableInfo t;
260  t.meta.number = number;
261  std::string fname = TableFileName(dbname_, number);
262  Status status = env_->GetFileSize(fname, &t.meta.file_size);
263  if (!status.ok()) {
264  // Try alternate file name.
265  fname = SSTTableFileName(dbname_, number);
266  Status s2 = env_->GetFileSize(fname, &t.meta.file_size);
267  if (s2.ok()) {
268  status = Status::OK();
269  }
270  }
271  if (!status.ok()) {
274  Log(options_.info_log, "Table #%llu: dropped: %s",
275  (unsigned long long) t.meta.number,
276  status.ToString().c_str());
277  return;
278  }
279 
280  // Extract metadata by scanning through table.
281  int counter = 0;
282  Iterator* iter = NewTableIterator(t.meta);
283  bool empty = true;
284  ParsedInternalKey parsed;
285  t.max_sequence = 0;
286  for (iter->SeekToFirst(); iter->Valid(); iter->Next()) {
287  Slice key = iter->key();
288  if (!ParseInternalKey(key, &parsed)) {
289  Log(options_.info_log, "Table #%llu: unparsable key %s",
290  (unsigned long long) t.meta.number,
291  EscapeString(key).c_str());
292  continue;
293  }
294 
295  counter++;
296  if (empty) {
297  empty = false;
298  t.meta.smallest.DecodeFrom(key);
299  }
300  t.meta.largest.DecodeFrom(key);
301  if (parsed.sequence > t.max_sequence) {
302  t.max_sequence = parsed.sequence;
303  }
304  }
305  if (!iter->status().ok()) {
306  status = iter->status();
307  }
308  delete iter;
309  Log(options_.info_log, "Table #%llu: %d entries %s",
310  (unsigned long long) t.meta.number,
311  counter,
312  status.ToString().c_str());
313 
314  if (status.ok()) {
315  tables_.push_back(t);
316  } else {
317  RepairTable(fname, t); // RepairTable archives input file.
318  }
319  }
void ArchiveFile(const std::string &fname)
Definition: repair.cc:434
void Log(Logger *info_log, const char *format,...)
Definition: env.cc:31
virtual Status GetFileSize(const std::string &fname, uint64_t *file_size)=0
bool ParseInternalKey(const Slice &internal_key, ParsedInternalKey *result)
Definition: dbformat.h:176
std::string TableFileName(const std::string &name, uint64_t number)
Definition: filename.cc:32
static Status OK()
Definition: status.h:32
std::string EscapeString(const Slice &value)
Definition: logging.cc:42
Iterator * NewTableIterator(const FileMetaData &meta)
Definition: repair.cc:250
Logger * info_log
Definition: options.h:68
void RepairTable(const std::string &src, TableInfo t)
Definition: repair.cc:321
std::string SSTTableFileName(const std::string &name, uint64_t number)
Definition: filename.cc:37
Here is the call graph for this function:

§ WriteDescriptor()

Status leveldb::anonymous_namespace{repair.cc}::Repairer::WriteDescriptor ( )
inlineprivate

Definition at line 375 of file repair.cc.

375  {
376  std::string tmp = TempFileName(dbname_, 1);
377  WritableFile* file;
378  Status status = env_->NewWritableFile(tmp, &file);
379  if (!status.ok()) {
380  return status;
381  }
382 
383  SequenceNumber max_sequence = 0;
384  for (size_t i = 0; i < tables_.size(); i++) {
385  if (max_sequence < tables_[i].max_sequence) {
386  max_sequence = tables_[i].max_sequence;
387  }
388  }
389 
391  edit_.SetLogNumber(0);
393  edit_.SetLastSequence(max_sequence);
394 
395  for (size_t i = 0; i < tables_.size(); i++) {
396  // TODO(opt): separate out into multiple levels
397  const TableInfo& t = tables_[i];
398  edit_.AddFile(0, t.meta.number, t.meta.file_size,
399  t.meta.smallest, t.meta.largest);
400  }
401 
402  //fprintf(stderr, "NewDescriptor:\n%s\n", edit_.DebugString().c_str());
403  {
404  log::Writer log(file);
405  std::string record;
406  edit_.EncodeTo(&record);
407  status = log.AddRecord(record);
408  }
409  if (status.ok()) {
410  status = file->Close();
411  }
412  delete file;
413  file = NULL;
414 
415  if (!status.ok()) {
416  env_->DeleteFile(tmp);
417  } else {
418  // Discard older manifests
419  for (size_t i = 0; i < manifests_.size(); i++) {
420  ArchiveFile(dbname_ + "/" + manifests_[i]);
421  }
422 
423  // Install new manifest
424  status = env_->RenameFile(tmp, DescriptorFileName(dbname_, 1));
425  if (status.ok()) {
426  status = SetCurrentFile(env_, dbname_, 1);
427  } else {
428  env_->DeleteFile(tmp);
429  }
430  }
431  return status;
432  }
void ArchiveFile(const std::string &fname)
Definition: repair.cc:434
void SetLastSequence(SequenceNumber seq)
Definition: version_edit.h:51
void SetLogNumber(uint64_t num)
Definition: version_edit.h:39
void SetComparatorName(const Slice &name)
Definition: version_edit.h:35
void SetNextFile(uint64_t num)
Definition: version_edit.h:47
const Comparator * user_comparator() const
Definition: dbformat.h:125
std::string TempFileName(const std::string &dbname, uint64_t number)
Definition: filename.cc:58
virtual Status NewWritableFile(const std::string &fname, WritableFile **result)=0
uint64_t SequenceNumber
Definition: dbformat.h:63
virtual const char * Name() const =0
std::string DescriptorFileName(const std::string &dbname, uint64_t number)
Definition: filename.cc:42
Status SetCurrentFile(Env *env, const std::string &dbname, uint64_t descriptor_number)
Definition: filename.cc:126
void EncodeTo(std::string *dst) const
Definition: version_edit.cc:41
virtual Status RenameFile(const std::string &src, const std::string &target)=0
void AddFile(int level, uint64_t file, uint64_t file_size, const InternalKey &smallest, const InternalKey &largest)
Definition: version_edit.h:62
virtual Status DeleteFile(const std::string &fname)=0
Here is the call graph for this function:

Member Data Documentation

§ dbname_

std::string const leveldb::anonymous_namespace{repair.cc}::Repairer::dbname_
private

Definition at line 100 of file repair.cc.

§ edit_

VersionEdit leveldb::anonymous_namespace{repair.cc}::Repairer::edit_
private

Definition at line 108 of file repair.cc.

§ env_

Env* const leveldb::anonymous_namespace{repair.cc}::Repairer::env_
private

Definition at line 101 of file repair.cc.

§ icmp_

InternalKeyComparator const leveldb::anonymous_namespace{repair.cc}::Repairer::icmp_
private

Definition at line 102 of file repair.cc.

§ ipolicy_

InternalFilterPolicy const leveldb::anonymous_namespace{repair.cc}::Repairer::ipolicy_
private

Definition at line 103 of file repair.cc.

§ logs_

std::vector<uint64_t> leveldb::anonymous_namespace{repair.cc}::Repairer::logs_
private

Definition at line 112 of file repair.cc.

§ manifests_

std::vector<std::string> leveldb::anonymous_namespace{repair.cc}::Repairer::manifests_
private

Definition at line 110 of file repair.cc.

§ next_file_number_

uint64_t leveldb::anonymous_namespace{repair.cc}::Repairer::next_file_number_
private

Definition at line 114 of file repair.cc.

§ options_

Options const leveldb::anonymous_namespace{repair.cc}::Repairer::options_
private

Definition at line 104 of file repair.cc.

§ owns_cache_

bool leveldb::anonymous_namespace{repair.cc}::Repairer::owns_cache_
private

Definition at line 106 of file repair.cc.

§ owns_info_log_

bool leveldb::anonymous_namespace{repair.cc}::Repairer::owns_info_log_
private

Definition at line 105 of file repair.cc.

§ table_cache_

TableCache* leveldb::anonymous_namespace{repair.cc}::Repairer::table_cache_
private

Definition at line 107 of file repair.cc.

§ table_numbers_

std::vector<uint64_t> leveldb::anonymous_namespace{repair.cc}::Repairer::table_numbers_
private

Definition at line 111 of file repair.cc.

§ tables_

std::vector<TableInfo> leveldb::anonymous_namespace{repair.cc}::Repairer::tables_
private

Definition at line 113 of file repair.cc.


The documentation for this class was generated from the following file: