blob: 3333507b2e4b1aa99166557170887d1fb2571670 [file] [log] [blame]
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/**
* Copyright (c) 2013-2017, Regents of the University of California.
*
* This file is part of ChronoShare, a decentralized file sharing application over NDN.
*
* ChronoShare is free software: you can redistribute it and/or modify it under the terms
* of the GNU General Public License as published by the Free Software Foundation, either
* version 3 of the License, or (at your option) any later version.
*
* ChronoShare is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
* PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received copies of the GNU General Public License along with
* ChronoShare, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
*
* See AUTHORS.md for complete list of ChronoShare authors and contributors.
*/
#include "ccnx-wrapper.hpp"
#include "dispatcher.hpp"
#include "fs-watcher.hpp"
#include "logging.hpp"
#include <boost/lexical_cast.hpp>
#include <boost/make_shared.hpp>
using namespace boost;
using namespace std;
using namespace Ndnx;
_LOG_INIT(DumpDb);
class StateLogDumper : public DbHelper
{
public:
StateLogDumper(const filesystem::path& path)
: DbHelper(path / ".chronoshare", "sync-log.db")
{
}
void
DumpState()
{
sqlite3_stmt* stmt;
sqlite3_prepare_v2(m_db,
"SELECT hash(device_name, seq_no) FROM (SELECT * FROM SyncNodes ORDER BY device_name)",
-1, &stmt, 0);
sqlite3_step(stmt);
Hash hash(sqlite3_column_blob(stmt, 0), sqlite3_column_bytes(stmt, 0));
sqlite3_finalize(stmt);
sqlite3_prepare_v2(m_db, "SELECT device_name, seq_no, last_known_locator, last_update "
" FROM SyncNodes "
" ORDER BY device_name",
-1, &stmt, 0);
cout.setf(std::ios::left, std::ios::adjustfield);
cout << ">> SYNC NODES (" << hash.shortHash() << ") <<" << endl;
cout << "===================================================================================="
<< endl;
cout << setw(30) << "device_name"
<< " | seq_no | " << setw(20) << "locator"
<< " | last_update " << endl;
cout << "===================================================================================="
<< endl;
while (sqlite3_step(stmt) == SQLITE_ROW) {
cout << setw(30)
<< lexical_cast<string>(Name(sqlite3_column_blob(stmt, 0), sqlite3_column_bytes(stmt, 0)))
<< " | "; // device_name
cout << setw(6) << sqlite3_column_int64(stmt, 1) << " | "; // seq_no
cout << setw(20)
<< lexical_cast<string>(Name(sqlite3_column_blob(stmt, 2), sqlite3_column_bytes(stmt, 2)))
<< " | "; // locator
if (sqlite3_column_bytes(stmt, 3) > 0) {
cout << setw(10) << sqlite3_column_text(stmt, 3) << endl;
}
else {
cout << "unknown" << endl;
}
}
sqlite3_finalize(stmt);
}
void
DumpLog()
{
sqlite3_stmt* stmt;
sqlite3_prepare_v2(m_db, "SELECT state_hash, last_update, state_id "
" FROM SyncLog "
" ORDER BY last_update",
-1, &stmt, 0);
cout.setf(std::ios::left, std::ios::adjustfield);
cout << ">> SYNC LOG <<" << endl;
cout << "===================================================================================="
<< endl;
cout << setw(10) << "state_hash"
<< " | state details " << endl;
cout << "===================================================================================="
<< endl;
while (sqlite3_step(stmt) == SQLITE_ROW) {
cout << setw(10)
<< Hash(sqlite3_column_blob(stmt, 0), sqlite3_column_bytes(stmt, 0)).shortHash()
<< " | "; // state hash
sqlite3_stmt* stmt2;
sqlite3_prepare_v2(m_db,
"SELECT device_name, ss.seq_no "
" FROM SyncStateNodes ss JOIN SyncNodes sn ON ss.device_id = sn.device_id "
" WHERE state_id=? "
" ORDER BY device_name",
-1, &stmt2, 0);
_LOG_DEBUG_COND(sqlite3_errcode(m_db) != SQLITE_OK, sqlite3_errmsg(m_db));
sqlite3_bind_int64(stmt2, 1, sqlite3_column_int64(stmt, 2));
while (sqlite3_step(stmt2) == SQLITE_ROW) {
cout << lexical_cast<string>(
Name(sqlite3_column_blob(stmt2, 0), sqlite3_column_bytes(stmt2, 0)))
<< "(" << sqlite3_column_int64(stmt2, 1) << "); ";
}
sqlite3_finalize(stmt2);
cout << endl;
}
sqlite3_finalize(stmt);
}
};
class ActionLogDumper : public DbHelper
{
public:
ActionLogDumper(const filesystem::path& path)
: DbHelper(path / ".chronoshare", "action-log.db")
{
}
void
Dump()
{
sqlite3_stmt* stmt;
sqlite3_prepare_v2(m_db,
"SELECT device_name, seq_no, action, filename, version, file_hash, file_seg_num, parent_device_name, parent_seq_no "
" FROM ActionLog "
" ORDER BY action_timestamp",
-1, &stmt, 0);
cout.setf(std::ios::left, std::ios::adjustfield);
cout << ">> ACTION LOG <<" << endl;
cout << "============================================================================================================================================================================="
<< endl;
cout << setw(30) << "device_name"
<< " | seq_no | action |" << setw(40) << " filename "
<< " | version | file_hash | seg_num | parent_device_name | parent_seq_no"
<< endl;
cout << "============================================================================================================================================================================="
<< endl;
while (sqlite3_step(stmt) == SQLITE_ROW) {
cout << setw(30)
<< lexical_cast<string>(Name(sqlite3_column_blob(stmt, 0), sqlite3_column_bytes(stmt, 0)))
<< " | "; // device_name
cout << setw(6) << sqlite3_column_int64(stmt, 1) << " | "; // seq_no
cout << setw(6) << (sqlite3_column_int(stmt, 2) == 0 ? "UPDATE" : "DELETE") << " | "; // action
cout << setw(40) << sqlite3_column_text(stmt, 3) << " | "; // filename
cout << setw(7) << sqlite3_column_int64(stmt, 4) << " | "; // version
if (sqlite3_column_int(stmt, 2) == 0) {
cout << setw(10)
<< Hash(sqlite3_column_blob(stmt, 5), sqlite3_column_bytes(stmt, 5)).shortHash()
<< " | ";
cout << setw(7) << sqlite3_column_int64(stmt, 6) << " | "; // seg_num
}
else
cout << " | | ";
if (sqlite3_column_bytes(stmt, 7) > 0) {
cout << setw(30) << lexical_cast<string>(
Name(sqlite3_column_blob(stmt, 7), sqlite3_column_bytes(stmt, 7)))
<< " | "; // parent_device_name
cout << setw(5) << sqlite3_column_int64(stmt, 8); // seq_no
}
else
cout << setw(30) << " "
<< " | ";
cout << endl;
}
sqlite3_finalize(stmt);
}
void
DumpActionData(const Ccnx::Name& deviceName, int64_t seqno)
{
sqlite3_stmt* stmt;
sqlite3_prepare_v2(m_db,
"SELECT action_content_object, action_name FROM ActionLog WHERE device_name = ? and seq_no = ?",
-1, &stmt, 0);
Ccnx::CcnxCharbufPtr device_name = deviceName.toCcnxCharbuf();
sqlite3_bind_blob(stmt, 1, device_name->buf(), device_name->length(), SQLITE_STATIC);
sqlite3_bind_int64(stmt, 2, seqno);
cout << "Dumping action data for: [" << deviceName << ", " << seqno << "]" << endl;
if (sqlite3_step(stmt) == SQLITE_ROW) {
PcoPtr pco = make_shared<ParsedContentObject>(reinterpret_cast<const unsigned char*>(
sqlite3_column_blob(stmt, 0)),
sqlite3_column_bytes(stmt, 0));
Ccnx::Name actionName = Ccnx::Name(sqlite3_column_blob(stmt, 1), sqlite3_column_bytes(stmt, 0));
if (pco) {
ActionItemPtr action = deserializeMsg<ActionItem>(pco->content());
if (action) {
cout << "Action data size : " << pco->content().size() << endl;
cout << "Action data name : " << actionName << endl;
string type = action->action() == ActionItem::UPDATE ? "UPDATE" : "DELETE";
cout << "Action Type = " << type << endl;
cout << "Timestamp = " << action->timestamp() << endl;
string filename = action->filename();
cout << "Filename = " << filename << endl;
if (action->has_seg_num()) {
cout << "Segment number = " << action->seg_num() << endl;
}
if (action->has_file_hash()) {
cout << "File hash = " << Hash(action->file_hash().c_str(), action->file_hash().size())
<< endl;
}
}
else {
cerr << "Error! Failed to parse action from pco! " << endl;
}
}
else {
cerr << "Error! Invalid pco! " << endl;
}
}
else {
cerr << "Error! Can not find the requested action" << endl;
}
sqlite3_finalize(stmt);
}
};
class FileStateDumper : public DbHelper
{
public:
FileStateDumper(const filesystem::path& path)
: DbHelper(path / ".chronoshare", "file-state.db")
{
}
void
Dump()
{
sqlite3_stmt* stmt;
sqlite3_prepare_v2(m_db,
"SELECT filename,device_name,seq_no,file_hash,strftime('%s', file_mtime),file_chmod,file_seg_num,directory,is_complete "
" FROM FileState "
" WHERE type = 0 ORDER BY filename",
-1, &stmt, 0);
cout.setf(std::ios::left, std::ios::adjustfield);
cout << ">> FILE STATE <<" << endl;
cout << "==================================================================================================================================="
<< endl;
cout << "filename | device_name | seq_no | file_hash | seg_num | directory | is_complete"
<< endl;
cout << "==================================================================================================================================="
<< endl;
while (sqlite3_step(stmt) == SQLITE_ROW) {
cout << setw(40) << sqlite3_column_text(stmt, 0) << " | ";
cout << setw(30)
<< lexical_cast<string>(Name(sqlite3_column_blob(stmt, 1), sqlite3_column_bytes(stmt, 1)))
<< " | ";
cout << setw(6) << sqlite3_column_int64(stmt, 2) << " | ";
cout << setw(10)
<< Hash(sqlite3_column_blob(stmt, 3), sqlite3_column_bytes(stmt, 3)).shortHash() << " | ";
cout << setw(6) << sqlite3_column_int64(stmt, 6) << " | ";
if (sqlite3_column_bytes(stmt, 7) == 0)
cout << setw(20) << "<NULL>"
<< " | ";
else
cout << setw(20) << sqlite3_column_text(stmt, 7) << " | ";
if (sqlite3_column_int(stmt, 8) == 0)
cout << setw(20) << "no" << endl;
else
cout << setw(20) << "yes" << endl;
}
sqlite3_finalize(stmt);
}
};
int
main(int argc, char* argv[])
{
if (argc != 3 && !(argc == 5 && string(argv[1]) == "action")) {
cerr << "Usage: ./dump-db state|action|file|all <path-to-shared-folder>" << endl;
cerr << " or: ./dump-db action <path-to-shared-folder> <device-name> <seq-no>" << endl;
return 1;
}
string type = argv[1];
if (type == "state") {
StateLogDumper dumper(argv[2]);
dumper.DumpState();
dumper.DumpLog();
}
else if (type == "action") {
ActionLogDumper dumper(argv[2]);
if (argc == 5) {
dumper.DumpActionData(string(argv[3]), boost::lexical_cast<int64_t>(argv[4]));
}
else {
dumper.Dump();
}
}
else if (type == "file") {
FileStateDumper dumper(argv[2]);
dumper.Dump();
}
else if (type == "all") {
{
StateLogDumper dumper(argv[2]);
dumper.DumpState();
dumper.DumpLog();
}
{
ActionLogDumper dumper(argv[2]);
dumper.Dump();
}
{
FileStateDumper dumper(argv[2]);
dumper.Dump();
}
}
else {
cerr << "ERROR: Wrong database type" << endl;
cerr << "\nUsage: ./dump-db state|action|file|all <path-to-shared-folder>" << endl;
return 1;
}
return 0;
}