Skip to content

Instantly share code, notes, and snippets.

@apage43
Created July 20, 2012 21:33
Show Gist options
  • Save apage43/3153392 to your computer and use it in GitHub Desktop.
Save apage43/3153392 to your computer and use it in GitHub Desktop.
btdump.cc
#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