return ops.size();
}
- void dump(ceph::Formatter *f) {
+ void dump(ceph::Formatter *f, bool dump_val=false) const {
f->open_object_section("transaction");
f->open_array_section("ops");
- list<Op>::iterator it;
+ list<Op>::const_iterator it;
int op_num = 0;
for (it = ops.begin(); it != ops.end(); ++it) {
- Op& op = *it;
+ const Op& op = *it;
f->open_object_section("op");
f->dump_int("op_num", op_num++);
switch (op.type) {
f->dump_string("type", "PUT");
f->dump_string("prefix", op.prefix);
f->dump_string("key", op.key);
- ostringstream os;
- op.bl.hexdump(os);
f->dump_unsigned("length", op.bl.length());
- f->dump_string("bl", os.str());
+ if (dump_val) {
+ ostringstream os;
+ op.bl.hexdump(os);
+ f->dump_string("bl", os.str());
+ }
}
break;
case OP_ERASE:
}
};
- int apply_transaction(MonitorDBStore::Transaction& t) {
+ int apply_transaction(const MonitorDBStore::Transaction& t) {
KeyValueDB::Transaction dbt = db->get_transaction();
if (do_dump) {
}
list<string> compact_prefixes;
- for (list<Op>::iterator it = t.ops.begin(); it != t.ops.end(); ++it) {
- Op& op = *it;
+ for (list<Op>::const_iterator it = t.ops.begin(); it != t.ops.end(); ++it) {
+ const Op& op = *it;
switch (op.type) {
case Transaction::OP_PUT:
dbt->set(op.prefix, op.key, op.bl);
#include "global/global_init.h"
#include "os/LevelDBStore.h"
#include "mon/MonitorDBStore.h"
+#include "common/Formatter.h"
namespace po = boost::program_options;
using namespace std;
+class TraceIter {
+ int fd;
+ unsigned idx;
+ MonitorDBStore::Transaction t;
+public:
+ TraceIter(string fname) : fd(-1), idx(-1) {
+ fd = ::open(fname.c_str(), O_RDONLY);
+ }
+ bool valid() {
+ return fd != -1;
+ }
+ const MonitorDBStore::Transaction &cur() {
+ assert(valid());
+ return t;
+ }
+ unsigned num() { return idx; }
+ void next() {
+ ++idx;
+ bufferlist bl;
+ int r = bl.read_fd(fd, 6);
+ if (r < 0) {
+ std::cerr << "Got error: " << cpp_strerror(r) << " on read_fd"
+ << std::endl;
+ ::close(fd);
+ fd = -1;
+ return;
+ } else if ((unsigned)r < 6) {
+ std::cerr << "short read" << std::endl;
+ ::close(fd);
+ fd = -1;
+ return;
+ }
+ bufferlist::iterator bliter = bl.begin();
+ uint8_t ver, ver2;
+ ::decode(ver, bliter);
+ ::decode(ver2, bliter);
+ uint32_t len;
+ ::decode(len, bliter);
+ r = bl.read_fd(fd, len);
+ if (r < 0) {
+ std::cerr << "Got error: " << cpp_strerror(r) << " on read_fd"
+ << std::endl;
+ ::close(fd);
+ fd = -1;
+ return;
+ } else if ((unsigned)r < len) {
+ std::cerr << "short read" << std::endl;
+ ::close(fd);
+ fd = -1;
+ return;
+ }
+ bliter = bl.begin();
+ t.decode(bliter);
+ }
+ void init() {
+ next();
+ }
+ ~TraceIter() {
+ if (fd != -1) {
+ ::close(fd);
+ fd = -1;
+ }
+ }
+};
+
int main(int argc, char **argv) {
po::options_description desc("Allowed options");
int version = -1;
- string store_path, cmd, out_path;
+ string store_path, cmd, out_path, tfile;
+ unsigned dstart = 0;
+ unsigned dstop = ~0;
desc.add_options()
("help", "produce help message")
("mon-store-path", po::value<string>(&store_path),
"out path")
("version", po::value<int>(&version),
"version requested")
+ ("trace-file", po::value<string>(&tfile),
+ "trace file")
+ ("dump-start", po::value<unsigned>(&dstart),
+ "transaction num to start dumping at")
+ ("dump-end", po::value<unsigned>(&dstop),
+ "transaction num to stop dumping at")
("command", po::value<string>(&cmd),
"command")
;
}
MonitorDBStore st(store_path);
- stringstream ss;
- int r = st.open(ss);
- if (r < 0) {
- std::cerr << ss.str() << std::endl;
- goto done;
+ if (store_path.size()) {
+ stringstream ss;
+ int r = st.open(ss);
+ if (r < 0) {
+ std::cerr << ss.str() << std::endl;
+ goto done;
+ }
}
if (cmd == "getosdmap") {
+ if (!store_path.size()) {
+ std::cerr << "need mon store path" << std::endl;
+ std::cerr << desc << std::endl;
+ goto done;
+ }
version_t v;
if (version == -1) {
v = st.get("osdmap", "last_committed");
goto done;
}
bl.write_fd(fd);
+ } else if (cmd == "dump-trace") {
+ if (tfile.empty()) {
+ std::cerr << "Need trace_file" << std::endl;
+ std::cerr << desc << std::endl;
+ goto done;
+ }
+ TraceIter iter(tfile.c_str());
+ iter.init();
+ while (true) {
+ if (!iter.valid())
+ break;
+ if (iter.num() >= dstop) {
+ break;
+ }
+ if (iter.num() >= dstart) {
+ JSONFormatter f(true);
+ iter.cur().dump(&f, false);
+ f.flush(std::cout);
+ std::cout << std::endl;
+ }
+ iter.next();
+ }
+ std::cerr << "Read up to transaction " << iter.num() << std::endl;
} else {
std::cerr << "Unrecognized command: " << cmd << std::endl;
goto done;