23 bool GuessType(
const std::string& fname,
FileType* type) {
24 size_t pos = fname.rfind(
'/');
26 if (pos == std::string::npos) {
29 basename = std::string(fname.data() + pos + 1, fname.size() - pos - 1);
36 class CorruptionReporter :
public log::Reader::Reporter {
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());
46 bool PrintLogContents(Env* env,
const std::string& fname,
47 void (*
func)(Slice)) {
49 Status s = env->NewSequentialFile(fname, &file);
51 fprintf(stderr,
"%s\n", s.ToString().c_str());
54 CorruptionReporter reporter;
55 log::Reader reader(file, &reporter,
true, 0);
58 while (reader.ReadRecord(&record, &scratch)) {
59 printf(
"--- offset %llu; ",
60 static_cast<unsigned long long>(reader.LastRecordOffset()));
68 class WriteBatchItemPrinter :
public WriteBatch::Handler {
73 virtual void Put(
const Slice& key,
const Slice&
value) {
78 virtual void Delete(
const Slice& key) {
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()));
97 WriteBatchItemPrinter batch_item_printer;
98 Status s = batch.Iterate(&batch_item_printer);
100 printf(
" error: %s\n", s.ToString().c_str());
104 bool DumpLog(Env* env,
const std::string& fname) {
105 return PrintLogContents(env, fname, WriteBatchPrinter);
110 static void VersionEditPrinter(Slice record) {
112 Status s = edit.DecodeFrom(record);
114 printf(
"%s\n", s.ToString().c_str());
117 printf(
"%s", edit.DebugString().c_str());
120 bool DumpDescriptor(Env* env,
const std::string& fname) {
121 return PrintLogContents(env, fname, VersionEditPrinter);
124 bool DumpTable(Env* env,
const std::string& fname) {
126 RandomAccessFile* file = NULL;
128 Status s = env->GetFileSize(fname, &file_size);
130 s = env->NewRandomAccessFile(fname, &file);
137 s =
Table::Open(Options(), file, file_size, &table);
140 fprintf(stderr,
"%s\n", s.ToString().c_str());
147 ro.fill_cache =
false;
148 Iterator* iter = table->NewIterator(ro);
149 for (iter->SeekToFirst(); iter->Valid(); iter->Next()) {
150 ParsedInternalKey key;
152 printf(
"badkey '%s' => '%s'\n",
163 snprintf(kbuf,
sizeof(kbuf),
"%d", static_cast<int>(key.type));
166 printf(
"'%s' @ %8llu : %s => '%s'\n",
168 static_cast<unsigned long long>(key.sequence),
175 printf(
"iterator error: %s\n", s.ToString().c_str());
184 bool DumpFile(Env* env,
const std::string& fname) {
186 if (!GuessType(fname, &ftype)) {
187 fprintf(stderr,
"%s: unknown file type\n", fname.c_str());
191 case kLogFile:
return DumpLog(env, fname);
193 case kTableFile:
return DumpTable(env, fname);
196 fprintf(stderr,
"%s: not a dump-able file type\n", fname.c_str());
203 bool HandleDumpCommand(Env* env,
char** files,
int num) {
205 for (
int i = 0; i < num; i++) {
206 ok &= DumpFile(env, files[i]);
214 static void Usage() {
217 "Usage: leveldbutil command...\n"
218 " dump files... -- dump contents of specified files\n"
222 int main(
int argc,
char** argv) {
229 std::string command = argv[1];
230 if (command ==
"dump") {
231 ok = leveldb::HandleDumpCommand(env, argv+2, argc-2);
int main(int argc, char **argv)
static void SetContents(WriteBatch *batch, const Slice &contents)
bool ParseFileName(const std::string &fname, uint64_t *number, FileType *type)
bool ParseInternalKey(const Slice &internal_key, ParsedInternalKey *result)
unsigned long long uint64_t
std::string EscapeString(const Slice &value)
static SequenceNumber Sequence(const WriteBatch *batch)
static Status Open(const Options &options, RandomAccessFile *file, uint64_t file_size, Table **table)