LCOV - code coverage report
Current view: top level - src/leveldb/db - dumpfile.cc (source / functions) Hit Total Coverage
Test: total_coverage.info Lines: 0 99 0.0 %
Date: 2015-10-12 22:39:14 Functions: 0 4 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : // Copyright (c) 2012 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 <stdio.h>
       6             : #include "db/dbformat.h"
       7             : #include "db/filename.h"
       8             : #include "db/log_reader.h"
       9             : #include "db/version_edit.h"
      10             : #include "db/write_batch_internal.h"
      11             : #include "leveldb/env.h"
      12             : #include "leveldb/iterator.h"
      13             : #include "leveldb/options.h"
      14             : #include "leveldb/status.h"
      15             : #include "leveldb/table.h"
      16             : #include "leveldb/write_batch.h"
      17             : #include "util/logging.h"
      18             : 
      19             : namespace leveldb {
      20             : 
      21             : namespace {
      22             : 
      23           0 : bool GuessType(const std::string& fname, FileType* type) {
      24           0 :   size_t pos = fname.rfind('/');
      25             :   std::string basename;
      26           0 :   if (pos == std::string::npos) {
      27             :     basename = fname;
      28             :   } else {
      29           0 :     basename = std::string(fname.data() + pos + 1, fname.size() - pos - 1);
      30             :   }
      31             :   uint64_t ignored;
      32           0 :   return ParseFileName(basename, &ignored, type);
      33             : }
      34             : 
      35             : // Notified when log reader encounters corruption.
      36           0 : class CorruptionReporter : public log::Reader::Reporter {
      37             :  public:
      38             :   WritableFile* dst_;
      39           0 :   virtual void Corruption(size_t bytes, const Status& status) {
      40           0 :     std::string r = "corruption: ";
      41           0 :     AppendNumberTo(&r, bytes);
      42             :     r += " bytes; ";
      43           0 :     r += status.ToString();
      44           0 :     r.push_back('\n');
      45           0 :     dst_->Append(r);
      46           0 :   }
      47             : };
      48             : 
      49             : // Print contents of a log file. (*func)() is called on every record.
      50           0 : Status PrintLogContents(Env* env, const std::string& fname,
      51             :                         void (*func)(uint64_t, Slice, WritableFile*),
      52             :                         WritableFile* dst) {
      53             :   SequentialFile* file;
      54           0 :   Status s = env->NewSequentialFile(fname, &file);
      55           0 :   if (!s.ok()) {
      56             :     return s;
      57             :   }
      58             :   CorruptionReporter reporter;
      59           0 :   reporter.dst_ = dst;
      60           0 :   log::Reader reader(file, &reporter, true, 0);
      61             :   Slice record;
      62             :   std::string scratch;
      63           0 :   while (reader.ReadRecord(&record, &scratch)) {
      64           0 :     (*func)(reader.LastRecordOffset(), record, dst);
      65             :   }
      66           0 :   delete file;
      67             :   return Status::OK();
      68             : }
      69             : 
      70             : // Called on every item found in a WriteBatch.
      71           0 : class WriteBatchItemPrinter : public WriteBatch::Handler {
      72             :  public:
      73             :   WritableFile* dst_;
      74           0 :   virtual void Put(const Slice& key, const Slice& value) {
      75           0 :     std::string r = "  put '";
      76           0 :     AppendEscapedStringTo(&r, key);
      77             :     r += "' '";
      78           0 :     AppendEscapedStringTo(&r, value);
      79             :     r += "'\n";
      80           0 :     dst_->Append(r);
      81           0 :   }
      82           0 :   virtual void Delete(const Slice& key) {
      83           0 :     std::string r = "  del '";
      84           0 :     AppendEscapedStringTo(&r, key);
      85             :     r += "'\n";
      86           0 :     dst_->Append(r);
      87           0 :   }
      88             : };
      89             : 
      90             : 
      91             : // Called on every log record (each one of which is a WriteBatch)
      92             : // found in a kLogFile.
      93           0 : static void WriteBatchPrinter(uint64_t pos, Slice record, WritableFile* dst) {
      94           0 :   std::string r = "--- offset ";
      95           0 :   AppendNumberTo(&r, pos);
      96             :   r += "; ";
      97           0 :   if (record.size() < 12) {
      98             :     r += "log record length ";
      99           0 :     AppendNumberTo(&r, record.size());
     100             :     r += " is too small\n";
     101           0 :     dst->Append(r);
     102           0 :     return;
     103             :   }
     104           0 :   WriteBatch batch;
     105           0 :   WriteBatchInternal::SetContents(&batch, record);
     106             :   r += "sequence ";
     107           0 :   AppendNumberTo(&r, WriteBatchInternal::Sequence(&batch));
     108           0 :   r.push_back('\n');
     109           0 :   dst->Append(r);
     110             :   WriteBatchItemPrinter batch_item_printer;
     111           0 :   batch_item_printer.dst_ = dst;
     112           0 :   Status s = batch.Iterate(&batch_item_printer);
     113           0 :   if (!s.ok()) {
     114           0 :     dst->Append("  error: " + s.ToString() + "\n");
     115             :   }
     116             : }
     117             : 
     118             : Status DumpLog(Env* env, const std::string& fname, WritableFile* dst) {
     119           0 :   return PrintLogContents(env, fname, WriteBatchPrinter, dst);
     120             : }
     121             : 
     122             : // Called on every log record (each one of which is a WriteBatch)
     123             : // found in a kDescriptorFile.
     124           0 : static void VersionEditPrinter(uint64_t pos, Slice record, WritableFile* dst) {
     125           0 :   std::string r = "--- offset ";
     126           0 :   AppendNumberTo(&r, pos);
     127             :   r += "; ";
     128           0 :   VersionEdit edit;
     129           0 :   Status s = edit.DecodeFrom(record);
     130           0 :   if (!s.ok()) {
     131           0 :     r += s.ToString();
     132           0 :     r.push_back('\n');
     133             :   } else {
     134           0 :     r += edit.DebugString();
     135             :   }
     136           0 :   dst->Append(r);
     137           0 : }
     138             : 
     139             : Status DumpDescriptor(Env* env, const std::string& fname, WritableFile* dst) {
     140           0 :   return PrintLogContents(env, fname, VersionEditPrinter, dst);
     141             : }
     142             : 
     143           0 : Status DumpTable(Env* env, const std::string& fname, WritableFile* dst) {
     144             :   uint64_t file_size;
     145           0 :   RandomAccessFile* file = NULL;
     146           0 :   Table* table = NULL;
     147           0 :   Status s = env->GetFileSize(fname, &file_size);
     148           0 :   if (s.ok()) {
     149           0 :     s = env->NewRandomAccessFile(fname, &file);
     150             :   }
     151           0 :   if (s.ok()) {
     152             :     // We use the default comparator, which may or may not match the
     153             :     // comparator used in this database. However this should not cause
     154             :     // problems since we only use Table operations that do not require
     155             :     // any comparisons.  In particular, we do not call Seek or Prev.
     156           0 :     s = Table::Open(Options(), file, file_size, &table);
     157             :   }
     158           0 :   if (!s.ok()) {
     159           0 :     delete table;
     160           0 :     delete file;
     161             :     return s;
     162             :   }
     163             : 
     164             :   ReadOptions ro;
     165           0 :   ro.fill_cache = false;
     166           0 :   Iterator* iter = table->NewIterator(ro);
     167             :   std::string r;
     168           0 :   for (iter->SeekToFirst(); iter->Valid(); iter->Next()) {
     169             :     r.clear();
     170             :     ParsedInternalKey key;
     171           0 :     if (!ParseInternalKey(iter->key(), &key)) {
     172             :       r = "badkey '";
     173           0 :       AppendEscapedStringTo(&r, iter->key());
     174             :       r += "' => '";
     175           0 :       AppendEscapedStringTo(&r, iter->value());
     176             :       r += "'\n";
     177           0 :       dst->Append(r);
     178             :     } else {
     179             :       r = "'";
     180           0 :       AppendEscapedStringTo(&r, key.user_key);
     181             :       r += "' @ ";
     182           0 :       AppendNumberTo(&r, key.sequence);
     183             :       r += " : ";
     184           0 :       if (key.type == kTypeDeletion) {
     185             :         r += "del";
     186           0 :       } else if (key.type == kTypeValue) {
     187             :         r += "val";
     188             :       } else {
     189           0 :         AppendNumberTo(&r, key.type);
     190             :       }
     191             :       r += " => '";
     192           0 :       AppendEscapedStringTo(&r, iter->value());
     193             :       r += "'\n";
     194           0 :       dst->Append(r);
     195             :     }
     196             :   }
     197           0 :   s = iter->status();
     198           0 :   if (!s.ok()) {
     199           0 :     dst->Append("iterator error: " + s.ToString() + "\n");
     200             :   }
     201             : 
     202           0 :   delete iter;
     203           0 :   delete table;
     204           0 :   delete file;
     205             :   return Status::OK();
     206             : }
     207             : 
     208             : }  // namespace
     209             : 
     210           0 : Status DumpFile(Env* env, const std::string& fname, WritableFile* dst) {
     211             :   FileType ftype;
     212           0 :   if (!GuessType(fname, &ftype)) {
     213           0 :     return Status::InvalidArgument(fname + ": unknown file type");
     214             :   }
     215           0 :   switch (ftype) {
     216             :     case kLogFile:         return DumpLog(env, fname, dst);
     217             :     case kDescriptorFile:  return DumpDescriptor(env, fname, dst);
     218           0 :     case kTableFile:       return DumpTable(env, fname, dst);
     219             :     default:
     220             :       break;
     221             :   }
     222           0 :   return Status::InvalidArgument(fname + ": not a dump-able file type");
     223             : }
     224             : 
     225             : }  // namespace leveldb

Generated by: LCOV version 1.11