Created
July 20, 2012 21:33
-
-
Save apage43/3153392 to your computer and use it in GitHub Desktop.
btdump.cc
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <libcouchstore/couch_db.h> | |
#include "internal.h" | |
#include <stdio.h> | |
#include <vector> | |
#include <stdlib.h> | |
#include "util.h" | |
#include "couch_btree.h" | |
#include "bitfield.h" | |
#include <iostream> | |
#include <numeric> | |
using std::vector; | |
using std::cout; | |
using std::endl; | |
using std::cerr; | |
void error_die(couchstore_error_t err) { | |
if(err == COUCHSTORE_SUCCESS) { | |
return; | |
} | |
fprintf(stderr, "Couchstore error: %s\n", couchstore_strerror(err)); | |
exit(1); | |
} | |
vector<int> leafdepths; | |
couchstore_error_t dump_node(uint64_t diskpos, Db* db, uint64_t parent, int i, int depth) { | |
int bufpos = 1, nodebuflen = 0; | |
int count = 0; | |
couchstore_error_t errcode = COUCHSTORE_SUCCESS; | |
char *nodebuf = NULL; | |
nodebuflen = pread_compressed(db, diskpos, &nodebuf); | |
if(nodebuflen < 0) { | |
errcode = (couchstore_error_t) nodebuflen; | |
goto cleanup; | |
} | |
if (nodebuf[0] == 0) { //KP Node | |
while (bufpos < nodebuflen) { | |
uint32_t klen, vlen; | |
get_kvlen(nodebuf + bufpos, &klen, &vlen); | |
sized_buf cmp_key = {nodebuf + bufpos + 5, klen}; | |
sized_buf val_buf = {nodebuf + bufpos + 5 + klen, vlen}; | |
bufpos += 5 + klen + vlen; | |
uint64_t pointer = 0; | |
//Descend into the pointed to node. | |
pointer = get_48(val_buf.buf); | |
error_pass(dump_node(pointer, db, diskpos, count, depth + 1)); | |
count ++; | |
} | |
cout << "node" << diskpos << "[label = \"KP\"];" << endl; | |
} else if (nodebuf[0] == 1) { //KV Node | |
while (bufpos < nodebuflen) { | |
uint32_t klen, vlen; | |
get_kvlen(nodebuf + bufpos, &klen, &vlen); | |
sized_buf cmp_key = {nodebuf + bufpos + 5, klen}; | |
sized_buf val_buf = {nodebuf + bufpos + 5 + klen, vlen}; | |
bufpos += 5 + klen + vlen; | |
//Leaf found | |
count ++; | |
leafdepths.push_back(depth); | |
} | |
cout << "node" << diskpos << "[label = \""; | |
cout << count << " KVs\"];" << endl; | |
} | |
if(parent) { | |
cout << "\"node" << parent << "\" -> \"node" << diskpos | |
<< "\";" << endl; | |
} | |
cleanup: | |
free(nodebuf); | |
return errcode; | |
} | |
double mean(const vector<int> &list) { | |
return std::accumulate(list.begin(), list.end(), 0.0) / list.size(); | |
} | |
int main(int argc, char** argv) { | |
Db *db; | |
couchstore_error_t errcode; | |
errcode = couchstore_open_db(argv[1], 0, &db); | |
error_die(errcode); | |
node_pointer* bt_ex = NULL; | |
if(argv[2][0] == 's') { | |
bt_ex = db->header.by_seq_root; | |
} | |
if(argv[2][0] == 'i') { | |
bt_ex = db->header.by_id_root; | |
} | |
if(argv[2][0] == 'l') { | |
bt_ex = db->header.local_docs_root; | |
} | |
if(bt_ex == NULL) { | |
fprintf(stderr, "What btree?\n"); | |
exit(1); | |
} | |
cout << "digraph g {" << endl; | |
cout << "node [shape = record, height=.1];" << endl; | |
dump_node(bt_ex->pointer, db, 0, 0, 0); | |
cout << "}" << endl; | |
cerr << "Mean leaf depth: " << mean(leafdepths) << endl; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment