From 3a5dc285ab4f680b6d07e0e55380d4fe0d50012a Mon Sep 17 00:00:00 2001 From: Christian Dietrich Date: Thu, 21 Mar 2013 15:32:44 +0100 Subject: [PATCH] tools/prune-trace: fault-space pruning tool This tool creates the fault-space pruning pilot and group entries. Those are used by the generic campaign to do fault experiments. Currently prune-trace only implements conventional def/use pruning (--prune-method "basic"). Change-Id: I1dfb431e3b1d3cd2ee891a49a3b6ac01210be11f --- tools/CMakeLists.txt | 6 ++ tools/prune-trace/BasicPruner.cc | 50 ++++++++++++++++ tools/prune-trace/BasicPruner.hpp | 11 ++++ tools/prune-trace/CMakeLists.txt | 9 +++ tools/prune-trace/Pruner.cc | 63 ++++++++++++++++++++ tools/prune-trace/Pruner.hpp | 24 ++++++++ tools/prune-trace/main.cc | 98 +++++++++++++++++++++++++++++++ 7 files changed, 261 insertions(+) create mode 100644 tools/prune-trace/BasicPruner.cc create mode 100644 tools/prune-trace/BasicPruner.hpp create mode 100644 tools/prune-trace/CMakeLists.txt create mode 100644 tools/prune-trace/Pruner.cc create mode 100644 tools/prune-trace/Pruner.hpp create mode 100644 tools/prune-trace/main.cc diff --git a/tools/CMakeLists.txt b/tools/CMakeLists.txt index 1c37bfb6..b24126e1 100644 --- a/tools/CMakeLists.txt +++ b/tools/CMakeLists.txt @@ -1,4 +1,6 @@ option(BUILD_IMPORT_TRACE "Build the trace import tool?" OFF) +option(BUILD_PRUNE_TRACE "Build the trace prune tool?" OFF) + ### Setup search paths for headers ## include_directories(${CMAKE_CURRENT_BINARY_DIR}/../src/core) @@ -7,3 +9,7 @@ include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../src/core) if(BUILD_IMPORT_TRACE) add_subdirectory(import-trace) endif(BUILD_IMPORT_TRACE) + +if(BUILD_PRUNE_TRACE) + add_subdirectory(prune-trace) +endif(BUILD_PRUNE_TRACE) diff --git a/tools/prune-trace/BasicPruner.cc b/tools/prune-trace/BasicPruner.cc new file mode 100644 index 00000000..4d9eae7d --- /dev/null +++ b/tools/prune-trace/BasicPruner.cc @@ -0,0 +1,50 @@ +#include +#include "BasicPruner.hpp" +#include "util/Logger.hpp" +static fail::Logger log ("BasicPruner"); + + +bool BasicPruner::prune_all() { + std::stringstream ss; + + ss << "INSERT INTO fsppilot (known_outcome, variant_id, instr2, data_address, fspmethod_id) " + "SELECT 0, variant_id, instr2, data_address, " << m_method_id << " " + "FROM trace " + "WHERE variant_id = " << m_variant_id << " AND accesstype = 'R'"; + if (!db->query(ss.str().c_str())) return false; + ss.str(""); + + int rows = db->affected_rows(); + // single entry for known outcome (write access) + ss << "INSERT INTO fsppilot (known_outcome, variant_id, instr2, data_address, fspmethod_id) " + "SELECT 1, variant_id, instr2, data_address, " << m_method_id << " " + "FROM trace " + "WHERE variant_id = " << m_variant_id << " AND accesstype = 'W' " + "LIMIT 1"; + if (!db->query(ss.str().c_str())) return false; + ss.str(""); + rows += db->affected_rows(); + + log << "created " << rows << " fsppilot entries" << std::endl; + + ss << "INSERT INTO fspgroup (variant_id, instr2, data_address, fspmethod_id, pilot_id) " + "SELECT variant_id, instr2, data_address, fspmethod_id, id " + "FROM fsppilot " + "WHERE known_outcome = 0 AND fspmethod_id = " << m_method_id << " AND variant_id = " << m_variant_id; + if (!db->query(ss.str().c_str())) return false; + ss.str(""); + rows = db->affected_rows(); + ss << "INSERT INTO fspgroup (variant_id, instr2, data_address, fspmethod_id, pilot_id) " + "SELECT t.variant_id, t.instr2, t.data_address, p.fspmethod_id, p.id " + "FROM trace t " + "JOIN fsppilot p " + "ON t.variant_id = p.variant_id AND p.fspmethod_id = " << m_method_id << " AND p.known_outcome = 1 " + "WHERE t.variant_id = " << m_variant_id << " AND t.accesstype = 'W'"; + if (!db->query(ss.str().c_str())) return false; + ss.str(""); + rows += db->affected_rows(); + + log << "created " << rows << " fspgroup entries" << std::endl; + + return true; +} diff --git a/tools/prune-trace/BasicPruner.hpp b/tools/prune-trace/BasicPruner.hpp new file mode 100644 index 00000000..730f955b --- /dev/null +++ b/tools/prune-trace/BasicPruner.hpp @@ -0,0 +1,11 @@ +#ifndef __BASIC_PRUNER_H__ +#define __BASIC_PRUNER_H__ + +#include "Pruner.hpp" + +class BasicPruner : public Pruner { + virtual std::string method_name() { return "basic"; } + virtual bool prune_all(); +}; + +#endif diff --git a/tools/prune-trace/CMakeLists.txt b/tools/prune-trace/CMakeLists.txt new file mode 100644 index 00000000..32328f6d --- /dev/null +++ b/tools/prune-trace/CMakeLists.txt @@ -0,0 +1,9 @@ +set(SRCS + Pruner.cc + BasicPruner.cc +) + +## This is the example's campaign server distributing experiment parameters +add_executable(prune-trace main.cc ${SRCS}) +target_link_libraries(prune-trace -lmysqlclient fail-util) +install(TARGETS prune-trace RUNTIME DESTINATION bin) diff --git a/tools/prune-trace/Pruner.cc b/tools/prune-trace/Pruner.cc new file mode 100644 index 00000000..e598917d --- /dev/null +++ b/tools/prune-trace/Pruner.cc @@ -0,0 +1,63 @@ +#include +#include +#include "util/Logger.hpp" + +using namespace fail; +static Logger log ("Pruner"); + +#include "Pruner.hpp" + +bool Pruner::init(const std::string &variant, const std::string &benchmark, Database *db) { + this->db = db; + if (!(m_variant_id = db->get_variant_id(variant, benchmark))) { + return false; + } + if (!(m_method_id = db->get_fspmethod_id(method_name()))) { + return false; + } + log << "Pruning variant " + << variant << "/" << benchmark << " (ID: " << m_variant_id << ")" + << " with method " << method_name() << " (ID: " << m_method_id << ")" + << std::endl; + return true; +} + +bool Pruner::create_database() { + std::string create_statement = "CREATE TABLE IF NOT EXISTS fsppilot (" + " id int(11) NOT NULL AUTO_INCREMENT," + " known_outcome tinyint(4) NOT NULL," + " variant_id int(11) NOT NULL," + " instr2 int(10) unsigned NOT NULL," + " data_address int(10) unsigned NOT NULL," + " fspmethod_id int(11) NOT NULL," + " PRIMARY KEY (id)," + " KEY fspmethod_id (fspmethod_id,variant_id,instr2,data_address)" + ") engine=MyISAM "; + bool success = (bool) db->query(create_statement.c_str()); + if (!success) return false; + + create_statement = "CREATE TABLE IF NOT EXISTS fspgroup (" + " variant_id int(11) NOT NULL," + " instr2 int(10) unsigned NOT NULL," + " data_address int(10) unsigned NOT NULL," + " fspmethod_id int(11) NOT NULL," + " pilot_id int(11) NOT NULL," + " PRIMARY KEY (variant_id, instr2, data_address, fspmethod_id, pilot_id)," + " KEY joinresults (pilot_id,fspmethod_id))"; + + return db->query(create_statement.c_str()); +} + +bool Pruner::clear_database() { + std::stringstream ss; + ss << "DELETE FROM fsppilot WHERE variant_id = " << m_variant_id << " AND fspmethod_id = " << m_method_id; + bool ret = (bool) db->query(ss.str().c_str()); + log << "deleted " << db->affected_rows() << " rows from fsppilot table" << std::endl; + ss.str(""); + + ss << "DELETE FROM fspgroup WHERE variant_id = " << m_variant_id << " AND fspmethod_id = " << m_method_id; + ret = ret && (bool) db->query(ss.str().c_str()); + log << "deleted " << db->affected_rows() << " rows from fspgroup table" << std::endl; + + return ret; +} diff --git a/tools/prune-trace/Pruner.hpp b/tools/prune-trace/Pruner.hpp new file mode 100644 index 00000000..bcafa295 --- /dev/null +++ b/tools/prune-trace/Pruner.hpp @@ -0,0 +1,24 @@ +#ifndef __PRUNER_H__ +#define __PRUNER_H__ + +#include "util/Database.hpp" + +class Pruner { +protected: + int m_variant_id; + int m_method_id; + fail::Database *db; + +public: + bool init(const std::string &variant, const std::string &benchmark, + fail::Database *sql); + + virtual std::string method_name() = 0; + + virtual bool create_database(); + virtual bool clear_database(); + + virtual bool prune_all() = 0; +}; + +#endif diff --git a/tools/prune-trace/main.cc b/tools/prune-trace/main.cc new file mode 100644 index 00000000..33e28f05 --- /dev/null +++ b/tools/prune-trace/main.cc @@ -0,0 +1,98 @@ +#include +#include +#include + +#include "util/CommandLine.hpp" +#include "util/Logger.hpp" +static fail::Logger log("prune-trace", true); + +using namespace fail; +using std::endl; + +#include "Pruner.hpp" +#include "BasicPruner.hpp" + +int main(int argc, char *argv[]) { + std::string username, hostname, database, benchmark, variant; + + // Manually fill the command line option parser + CommandLine &cmd = CommandLine::Inst(); + for (int i = 1; i < argc; ++i) + cmd.add_args(argv[i]); + + CommandLine::option_handle IGNORE = cmd.addOption("", "", Arg::None, "USAGE: import-trace [options]"); + CommandLine::option_handle HELP = cmd.addOption("h", "help", Arg::None, "-h,--help\t Print usage and exit"); + + Database::cmdline_setup(); + + CommandLine::option_handle VARIANT = cmd.addOption("v", "variant", Arg::Required, + "-v/--variant\t Variant label (default: \"none\")"); + CommandLine::option_handle BENCHMARK = cmd.addOption("b", "benchmark", Arg::Required, + "-b/--benchmark\t Benchmark label (default: \"none\")\n"); + + CommandLine::option_handle PRUNER = cmd.addOption("p", "prune-method", Arg::Required, + "-p/--prune-method\t Which import method to use (default: basic)"); + + if(!cmd.parse()) { + std::cerr << "Error parsing arguments." << std::endl; + exit(-1); + } + + Pruner *pruner; + if (cmd[PRUNER].count() > 0) { + std::string imp(cmd[PRUNER].first()->arg); + if (imp == "basic") { + log << "Using BasicPruner" << endl; + pruner = new BasicPruner(); + } else { + log << "Unkown import method: " << imp << endl; + exit(-1); + } + + } else { + log << "Using BasicPruner" << endl; + pruner = new BasicPruner(); + } + + if (cmd[HELP]) { + cmd.printUsage(); + exit(0); + } + + Database *db = Database::cmdline_connect(); + + if (cmd[VARIANT].count() > 0) + variant = std::string(cmd[VARIANT].first()->arg); + else + variant = "none"; + + if (cmd[BENCHMARK].count() > 0) + benchmark = std::string(cmd[BENCHMARK].first()->arg); + else + benchmark = "none"; + + if (!pruner->init(variant, benchmark, db)) { + log << "pruner->init() failed" << endl; + exit(-1); + } + + //////////////////////////////////////////////////////////////// + // Do the actual import + //////////////////////////////////////////////////////////////// + if (!pruner->create_database()) { + log << "create_database() failed" << endl; + exit(-1); + } + + if (!pruner->clear_database()) { + log << "clear_database() failed" << endl; + exit(-1); + } + + if (!pruner->prune_all()) { + log << "prune_all() failed" << endl; + exit(-1); + } + + return 0; +}