Feathercoin  0.5.0
P2P Digital Currency
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros
leveldb_main.cc
Go to the documentation of this file.
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"
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 bool GuessType(const std::string& fname, FileType* type) {
24  size_t pos = fname.rfind('/');
25  std::string basename;
26  if (pos == std::string::npos) {
27  basename = fname;
28  } else {
29  basename = std::string(fname.data() + pos + 1, fname.size() - pos - 1);
30  }
31  uint64_t ignored;
32  return ParseFileName(basename, &ignored, type);
33 }
34 
35 // Notified when log reader encounters corruption.
36 class CorruptionReporter : public log::Reader::Reporter {
37  public:
38  virtual void Corruption(size_t bytes, const Status& status) {
39  printf("corruption: %d bytes; %s\n",
40  static_cast<int>(bytes),
41  status.ToString().c_str());
42  }
43 };
44 
45 // Print contents of a log file. (*func)() is called on every record.
46 bool PrintLogContents(Env* env, const std::string& fname,
47  void (*func)(Slice)) {
48  SequentialFile* file;
49  Status s = env->NewSequentialFile(fname, &file);
50  if (!s.ok()) {
51  fprintf(stderr, "%s\n", s.ToString().c_str());
52  return false;
53  }
54  CorruptionReporter reporter;
55  log::Reader reader(file, &reporter, true, 0);
56  Slice record;
57  std::string scratch;
58  while (reader.ReadRecord(&record, &scratch)) {
59  printf("--- offset %llu; ",
60  static_cast<unsigned long long>(reader.LastRecordOffset()));
61  (*func)(record);
62  }
63  delete file;
64  return true;
65 }
66 
67 // Called on every item found in a WriteBatch.
68 class WriteBatchItemPrinter : public WriteBatch::Handler {
69  public:
72 
73  virtual void Put(const Slice& key, const Slice& value) {
74  printf(" put '%s' '%s'\n",
75  EscapeString(key).c_str(),
76  EscapeString(value).c_str());
77  }
78  virtual void Delete(const Slice& key) {
79  printf(" del '%s'\n",
80  EscapeString(key).c_str());
81  }
82 };
83 
84 
85 // Called on every log record (each one of which is a WriteBatch)
86 // found in a kLogFile.
87 static void WriteBatchPrinter(Slice record) {
88  if (record.size() < 12) {
89  printf("log record length %d is too small\n",
90  static_cast<int>(record.size()));
91  return;
92  }
93  WriteBatch batch;
94  WriteBatchInternal::SetContents(&batch, record);
95  printf("sequence %llu\n",
96  static_cast<unsigned long long>(WriteBatchInternal::Sequence(&batch)));
97  WriteBatchItemPrinter batch_item_printer;
98  Status s = batch.Iterate(&batch_item_printer);
99  if (!s.ok()) {
100  printf(" error: %s\n", s.ToString().c_str());
101  }
102 }
103 
104 bool DumpLog(Env* env, const std::string& fname) {
105  return PrintLogContents(env, fname, WriteBatchPrinter);
106 }
107 
108 // Called on every log record (each one of which is a WriteBatch)
109 // found in a kDescriptorFile.
110 static void VersionEditPrinter(Slice record) {
111  VersionEdit edit;
112  Status s = edit.DecodeFrom(record);
113  if (!s.ok()) {
114  printf("%s\n", s.ToString().c_str());
115  return;
116  }
117  printf("%s", edit.DebugString().c_str());
118 }
119 
120 bool DumpDescriptor(Env* env, const std::string& fname) {
121  return PrintLogContents(env, fname, VersionEditPrinter);
122 }
123 
124 bool DumpTable(Env* env, const std::string& fname) {
125  uint64_t file_size;
126  RandomAccessFile* file = NULL;
127  Table* table = NULL;
128  Status s = env->GetFileSize(fname, &file_size);
129  if (s.ok()) {
130  s = env->NewRandomAccessFile(fname, &file);
131  }
132  if (s.ok()) {
133  // We use the default comparator, which may or may not match the
134  // comparator used in this database. However this should not cause
135  // problems since we only use Table operations that do not require
136  // any comparisons. In particular, we do not call Seek or Prev.
137  s = Table::Open(Options(), file, file_size, &table);
138  }
139  if (!s.ok()) {
140  fprintf(stderr, "%s\n", s.ToString().c_str());
141  delete table;
142  delete file;
143  return false;
144  }
145 
146  ReadOptions ro;
147  ro.fill_cache = false;
148  Iterator* iter = table->NewIterator(ro);
149  for (iter->SeekToFirst(); iter->Valid(); iter->Next()) {
150  ParsedInternalKey key;
151  if (!ParseInternalKey(iter->key(), &key)) {
152  printf("badkey '%s' => '%s'\n",
153  EscapeString(iter->key()).c_str(),
154  EscapeString(iter->value()).c_str());
155  } else {
156  char kbuf[20];
157  const char* type;
158  if (key.type == kTypeDeletion) {
159  type = "del";
160  } else if (key.type == kTypeValue) {
161  type = "val";
162  } else {
163  snprintf(kbuf, sizeof(kbuf), "%d", static_cast<int>(key.type));
164  type = kbuf;
165  }
166  printf("'%s' @ %8llu : %s => '%s'\n",
167  EscapeString(key.user_key).c_str(),
168  static_cast<unsigned long long>(key.sequence),
169  type,
170  EscapeString(iter->value()).c_str());
171  }
172  }
173  s = iter->status();
174  if (!s.ok()) {
175  printf("iterator error: %s\n", s.ToString().c_str());
176  }
177 
178  delete iter;
179  delete table;
180  delete file;
181  return true;
182 }
183 
184 bool DumpFile(Env* env, const std::string& fname) {
185  FileType ftype;
186  if (!GuessType(fname, &ftype)) {
187  fprintf(stderr, "%s: unknown file type\n", fname.c_str());
188  return false;
189  }
190  switch (ftype) {
191  case kLogFile: return DumpLog(env, fname);
192  case kDescriptorFile: return DumpDescriptor(env, fname);
193  case kTableFile: return DumpTable(env, fname);
194 
195  default: {
196  fprintf(stderr, "%s: not a dump-able file type\n", fname.c_str());
197  break;
198  }
199  }
200  return false;
201 }
202 
203 bool HandleDumpCommand(Env* env, char** files, int num) {
204  bool ok = true;
205  for (int i = 0; i < num; i++) {
206  ok &= DumpFile(env, files[i]);
207  }
208  return ok;
209 }
210 
211 }
212 } // namespace leveldb
213 
214 static void Usage() {
215  fprintf(
216  stderr,
217  "Usage: leveldbutil command...\n"
218  " dump files... -- dump contents of specified files\n"
219  );
220 }
221 
222 int main(int argc, char** argv) {
224  bool ok = true;
225  if (argc < 2) {
226  Usage();
227  ok = false;
228  } else {
229  std::string command = argv[1];
230  if (command == "dump") {
231  ok = leveldb::HandleDumpCommand(env, argv+2, argc-2);
232  } else {
233  Usage();
234  ok = false;
235  }
236  }
237  return (ok ? 0 : 1);
238 }
int main(int argc, char **argv)
std::string * value
Definition: version_set.cc:270
static void SetContents(WriteBatch *batch, const Slice &contents)
Definition: write_batch.cc:136
bool ParseFileName(const std::string &fname, uint64_t *number, FileType *type)
Definition: filename.cc:75
uint64_t offset_
Definition: leveldb_main.cc:70
bool ParseInternalKey(const Slice &internal_key, ParsedInternalKey *result)
Definition: dbformat.h:176
#define printf
Definition: rpcdump.cpp:12
unsigned long long uint64_t
Definition: stdint.h:22
std::string EscapeString(const Slice &value)
Definition: logging.cc:42
uint64_t sequence_
Definition: leveldb_main.cc:71
static SequenceNumber Sequence(const WriteBatch *batch)
Definition: write_batch.cc:90
void(* func)()
Definition: testharness.cc:19
static Status Open(const Options &options, RandomAccessFile *file, uint64_t file_size, Table **table)
Definition: table.cc:38
FileType
Definition: filename.h:20
static Env * Default()
Definition: env_posix.cc:800