Commandline tool to compace LevelDB databases.

Summary:
A simple CLI which calles DB->CompactRange()
Can take String key's as range.

Test Plan:
Inserted data into a table.
Waited for a minute, used compact tool on it. File modification time's
changed so Compact did something on the files.

Existing unit tests work.

Reviewers: heyongqiang, dhruba

Reviewed By: dhruba

Differential Revision: https://reviews.facebook.net/D5697
main
Abhishek Kona 12 years ago
parent a321d5be9e
commit fec81318b0
  1. 202
      tools/ldb.cc

@ -7,9 +7,11 @@
#include <sstream> #include <sstream>
#include "leveldb/db.h" #include "leveldb/db.h"
#include "leveldb/options.h"
#include "leveldb/iterator.h" #include "leveldb/iterator.h"
#include "leveldb/slice.h"
std::string HexToString(std::string str) { std::string HexToString(const std::string& str) {
std::string parsed; std::string parsed;
for (int i = 0; i < str.length(); ) { for (int i = 0; i < str.length(); ) {
int c; int c;
@ -20,73 +22,58 @@ std::string HexToString(std::string str) {
return parsed; return parsed;
} }
static void print_help() {
static void print_usage() {
fprintf(stderr, fprintf(stderr,
"db_dump " "ldb [compact|dump] "
"--start=[START_KEY] " "--db-path=database_path "
"--end=[END_KEY] " "[--from=START KEY] "
"--max_keys=[NUM] " "[--to=END KEY ] "
"--hex " "[--max_keys=[NUM] (only for dump)] "
"--count_only " "[--hex ] "
"--stats " "[--count_only (only for dump)] "
"[PATH]\n"); "[--stats (only for dump) ] \n");
} }
int main(int argc, char** argv) {
std::string db_path;
std::string start;
std::string end;
uint64_t max_keys = -1;
bool print_stats = false;
bool count_only = false;
uint64_t count = 0;
bool hex = false;
// Parse command line args static void safe_open_db(const std::string& dbname, leveldb::DB** db) {
char junk; leveldb::Options options;
uint64_t n; options.create_if_missing = false;
for (int i = 1; i < argc; i++) { leveldb::Status status = leveldb::DB::Open(options, dbname, db);
if (strncmp(argv[i], "--start=", 8) == 0) {
start= argv[i] + 8; if(!status.ok()) {
} else if (strncmp(argv[i], "--end=", 6) == 0) { fprintf(
end = argv[i] + 6; stderr,
} else if (sscanf(argv[i], "--max_keys=%ld%c", &n, &junk) == 1) { "Could not open db at %s\nERROR: %s",
max_keys = n; dbname.data(),
} else if (strncmp(argv[i], "--stats", 7) == 0) { status.ToString().data()
print_stats = true; );
} else if (strncmp(argv[i], "--count_only", 12) == 0) { exit(1);
count_only = true;
} else if (strncmp(argv[i], "--hex", 5) == 0) {
hex = true;
} else if (i == (argc - 1)) {
db_path = argv[i];
} else {
print_help();
exit(1);
}
} }
}
static void dump_db(
const std::string& db_path,
std::string& start,
std::string& end,
int64_t max_keys,
const bool hex,
const bool print_stats,
const bool count_only
) {
// Parse command line args
uint64_t count = 0;
if (hex) { if (hex) {
start = HexToString(start); start = HexToString(start);
end = HexToString(end); end = HexToString(end);
} }
if (db_path.empty()) {
print_help();
exit(1);
}
// Open DB
leveldb::Options options;
leveldb::DB *db; leveldb::DB *db;
leveldb::Status status = leveldb::DB::Open(options, db_path, &db); safe_open_db(db_path, &db);
if (!status.ok()) {
fprintf(stderr, "%s\n", status.ToString().c_str());
exit(1);
}
// Print DB stats if desired
if (print_stats) { if (print_stats) {
std::string stats; std::string stats;
if (db->GetProperty("leveldb.stats", &stats)) { if (db->GetProperty("leveldb.stats", &stats)) {
@ -96,7 +83,7 @@ int main(int argc, char** argv) {
// Setup key iterator // Setup key iterator
leveldb::Iterator* iter = db->NewIterator(leveldb::ReadOptions()); leveldb::Iterator* iter = db->NewIterator(leveldb::ReadOptions());
status = iter->status(); leveldb::Status status = iter->status();
if (!status.ok()) { if (!status.ok()) {
fprintf(stderr, "%s\n", status.ToString().c_str()); fprintf(stderr, "%s\n", status.ToString().c_str());
delete db; delete db;
@ -140,7 +127,108 @@ int main(int argc, char** argv) {
// Clean up // Clean up
delete iter; delete iter;
delete db; delete db;
}
return 0; static void compact(
const std::string dbname,
std::string from,
std::string to,
const bool hex
) {
leveldb::DB* db;
safe_open_db(dbname, &db);
if(hex) {
from = HexToString(from);
to = HexToString(to);
}
leveldb::Slice* begin = from.empty() ? NULL : new leveldb::Slice(from);
leveldb::Slice* end = to.empty() ? NULL : new leveldb::Slice(to);
db->CompactRange(begin, end);
delete db;
} }
int main(int argc, char** argv) {
enum {
DUMP, COMPACT
} command;
if (argc < 2) {
print_usage();
exit(1);
}
size_t n;
const std::string dbnameKey = "--db-path=";
const std::string toKey = "--to=";
const std::string fromKey = "--from=";
std::string dbname;
bool dbnameFound = false;
std::string from;
std::string to;
int64_t temp;
int64_t max_keys = -1;
bool print_stats = false;
bool count_only = false;
bool hex = false;
char junk;
std::string commandString = argv[1];
if (commandString == "dump") {
command = DUMP;
} else if (commandString == "compact") {
command = COMPACT;
} else {
print_usage();
exit(1);
}
for (int i = 2; i < argc; i++) {
std::string param(argv[i]);
if ((n = param.find(dbnameKey)) != std::string::npos) {
dbname = param.substr(dbnameKey.size());
dbnameFound = true;
} else if ((n = param.find(fromKey)) != std::string::npos) {
from = param.substr(fromKey.size());
} else if ((n = param.find(toKey)) != std::string::npos) {
to = param.substr(toKey.size());
} else if (sscanf(argv[i], "--max_keys=%ld%c", &temp, &junk) == 1) {
max_keys = temp;
} else if (strncmp(argv[i], "--stats", 7) == 0) {
print_stats = true;
} else if (strncmp(argv[i], "--count_only", 12) == 0) {
count_only = true;
} else if (strncmp(argv[i], "--hex", 5) == 0) {
hex = true;
} else {
print_usage();
exit(1);
}
}
if (!dbnameFound || dbname.empty()) {
fprintf(stderr, "DB path required. See help\n");
print_usage();
exit(1);
}
switch(command) {
case DUMP:
dump_db(dbname, from, to, max_keys, hex, print_stats, count_only);
break;
case COMPACT:
compact(dbname, from, to, hex);
break;
default:
print_usage();
exit(1);
}
return 0;
}

Loading…
Cancel
Save