LCOV - code coverage report
Current view: top level - src/leveldb/db - dumpfile.cc (source / functions) Coverage Total Hit
Test: test_bitcoin_coverage.info Lines: 0.0 % 149 0
Test Date: 2026-02-04 04:43:42 Functions: 0.0 % 11 0
Branches: 0.0 % 252 0

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

Generated by: LCOV version 2.0-1