diff --git a/libIRDB/include/core/transform_step.h b/libIRDB/include/core/transform_step.h index 2dc0c50b4029e7b764629a1a849c08fcb02cfc6f..4069c60f51e4d49c1d502e79645c18c2cb9213c7 100644 --- a/libIRDB/include/core/transform_step.h +++ b/libIRDB/include/core/transform_step.h @@ -12,7 +12,7 @@ namespace Transform_SDK virtual std::string getStepName(void) const = 0; // Allows all steps to parse args before any step takes time to execute - virtual int parseArgs(int argc, const char* const argv[]) + virtual int parseArgs(const std::vector<std::string> step_args) { return 0; // success } diff --git a/libIRDB/test/fill_in_cfg.cpp b/libIRDB/test/fill_in_cfg.cpp index c1f051109beffe2bbd009bcff9b1af147f85bf57..901638f121993e08248d05479da016e553e971b4 100644 --- a/libIRDB/test/fill_in_cfg.cpp +++ b/libIRDB/test/fill_in_cfg.cpp @@ -580,27 +580,23 @@ void PopulateCFG::fill_in_landing_pads(FileIR_t *firp) } -int PopulateCFG::parseArgs - ( - int argc, - const char* const argv[] - ) +int PopulateCFG::parseArgs(const vector<string> step_args) { - if(argc<2) + if(step_args.size()<1) { - cerr<<"Usage: fill_in_cfg <id> [--fix-landing-pads | --no-fix-landing-pads]"<<endl; + cerr<<"Usage: <id> [--fix-landing-pads | --no-fix-landing-pads]"<<endl; return -1; } - variant_id = atoi(argv[1]); + variant_id = stoi(step_args[0]); - for (int i = 2; i < argc; ++i) + for (unsigned int i = 1; i < step_args.size(); ++i) { - if (strcmp("--fix-landing-pads", argv[i]) == 0) + if (step_args[i]=="--fix-landing-pads") { fix_landing_pads = true; } - else if (strcmp("--no-fix-landing-pads", argv[i]) == 0) + else if (step_args[i]=="--no-fix-landing-pads") { fix_landing_pads = false; } diff --git a/libIRDB/test/fill_in_cfg.hpp b/libIRDB/test/fill_in_cfg.hpp index 658c77159048d5fee85fd253c8d1ef4537ce71ec..4925bafda9045fc015ce8ca053ad0bf9bcb0090e 100644 --- a/libIRDB/test/fill_in_cfg.hpp +++ b/libIRDB/test/fill_in_cfg.hpp @@ -34,7 +34,7 @@ class PopulateCFG : public libIRDB::Transform_SDK::TransformStep_t { return std::string("fill_in_cfg"); } - int parseArgs(int argc, const char* const argv[]) override; + int parseArgs(const std::vector<std::string> step_args) override; int executeStep(libIRDB::IRDBObjects_t *const) override; private: // methods diff --git a/libIRDB/test/fill_in_indtargs.cpp b/libIRDB/test/fill_in_indtargs.cpp index 0334551a1370bebc0e17bd0ff4ea86b4e037d093..f87e12af41a8ed56928dfbd1628cb8300c4a9738 100644 --- a/libIRDB/test/fill_in_indtargs.cpp +++ b/libIRDB/test/fill_in_indtargs.cpp @@ -2869,37 +2869,37 @@ int64_t do_unpin_opt=numeric_limits<int64_t>::max() ; db_id_t variant_id=BaseObj_t::NOT_IN_DATABASE; set<virtual_offset_t> forced_pins; -int parseArgs(int argc, const char* const argv[]) +int parseArgs(const vector<string> step_args) { - if(argc<2) + if(step_args.size()<1) { - cerr<<"Usage: fill_in_indtargs <id> [--[no-]split-eh-frame] [--[no-]unpin] [addr,...]"<<endl; + cerr<<"Usage: <id> [--[no-]split-eh-frame] [--[no-]unpin] [addr,...]"<<endl; exit(-1); } - variant_id=atoi(argv[1]); - cout<<"Parsing parameters with argc= " << argc<<endl; + variant_id=stoi(step_args[0]); + cout<<"Parsing parameters with argc= " << step_args.size()<<endl; // parse dash-style options. - auto argc_iter = (int)2; - while(argc_iter < argc && argv[argc_iter][0]=='-') + unsigned int argc_iter = 1; + while(argc_iter < step_args.size() && step_args[argc_iter][0]=='-') { - cout<<"Parsing parameter: "<< argv[argc_iter] << endl; - if(string(argv[argc_iter])=="--no-unpin") + cout<<"Parsing parameter: "<< step_args[argc_iter] << endl; + if(step_args[argc_iter]=="--no-unpin") { do_unpin_opt=-1; argc_iter++; } - else if(string(argv[argc_iter])=="--unpin") + else if(step_args[argc_iter]=="--unpin") { do_unpin_opt = numeric_limits<decltype(do_unpin_opt)>::max() ; argc_iter++; } - else if(string(argv[argc_iter])=="--max-unpin" || string(argv[argc_iter])=="--max-unpins") + else if(step_args[argc_iter]=="--max-unpin" || step_args[argc_iter]=="--max-unpins") { argc_iter++; - auto arg_as_str=argv[argc_iter]; + auto arg_as_str=step_args[argc_iter]; argc_iter++; try { @@ -2912,27 +2912,27 @@ int parseArgs(int argc, const char* const argv[]) } } - else if(string(argv[argc_iter])=="--no-split-eh-frame") + else if(step_args[argc_iter]=="--no-split-eh-frame") { split_eh_frame_opt=false; argc_iter++; } - else if(string(argv[argc_iter])=="--split-eh-frame") + else if(step_args[argc_iter]=="--split-eh-frame") { split_eh_frame_opt=true; argc_iter++; } else { - cerr<<"Unknown option: "<<argv[argc_iter]<<endl; + cerr<<"Unknown option: "<<step_args[argc_iter]<<endl; return 2; } } // parse addr argumnets - for (; argc_iter < argc; argc_iter++) + for (; argc_iter < step_args.size(); argc_iter++) { char *end_ptr; - virtual_offset_t offset = strtol(argv[argc_iter], &end_ptr, 0); + virtual_offset_t offset = strtol(step_args[argc_iter].c_str(), &end_ptr, 0); if (*end_ptr == '\0') { cout << "force pinning: 0x" << std::hex << offset << endl; diff --git a/libIRDB/test/fix_calls.cpp b/libIRDB/test/fix_calls.cpp index 6e36305c5361299f5342e1a6a913ea24c454c463..84197c3410c857b226f96d4ea2e9c1b3a60308db 100644 --- a/libIRDB/test/fix_calls.cpp +++ b/libIRDB/test/fix_calls.cpp @@ -962,12 +962,12 @@ bool fix_all=false; bool do_eh_frame=true; -int parseArgs(int argc, const char* const argv[]) +int parseArgs(const vector<string> step_args) { - if(argc<2) + if(step_args.size()<1) { - cerr<<"Usage: fix_calls <id> [--fix-all | --no-fix-all ] [--eh-frame | --no-ehframe] "<<endl; + cerr<<"Usage: <id> [--fix-all | --no-fix-all ] [--eh-frame | --no-ehframe] "<<endl; cerr<<" --eh-frame " << endl; cerr<<" --no-eh-frame Use (or dont) the eh-frame section to be compatible with exception handling." << endl; cerr<<" --fix-all " << endl; @@ -977,50 +977,50 @@ int parseArgs(int argc, const char* const argv[]) exit(-1); } - for(int argc_iter=2; argc_iter<argc; argc_iter++) + for(unsigned int argc_iter=1; argc_iter<step_args.size(); argc_iter++) { - if(strcmp("--fix-all", argv[argc_iter])==0) + if("--fix-all"==step_args[argc_iter]) { fix_all=true; } - else if(strcmp("--no-fix-all", argv[argc_iter])==0) + else if("--no-fix-all"==step_args[argc_iter]) { fix_all=false; } - else if(strcmp("--eh-frame", argv[argc_iter])==0) + else if("--eh-frame"==step_args[argc_iter]) { do_eh_frame=true; } - else if(strcmp("--no-eh-frame", argv[argc_iter])==0) + else if("--no-eh-frame"==step_args[argc_iter]) { do_eh_frame=false; } - else if(strcmp("--fix-icalls", argv[argc_iter])==0) + else if("--fix-icalls"==step_args[argc_iter]) { opt_fix_icalls = true; } - else if(strcmp("--no-fix-icalls", argv[argc_iter])==0) + else if("--no-fix-icalls"==step_args[argc_iter]) { opt_fix_icalls = false; } - else if(strcmp("--fix-safefn", argv[argc_iter])==0) + else if("--fix-safefn"==step_args[argc_iter]) { opt_fix_safefn = true; } - else if(strcmp("--no-fix-safefn", argv[argc_iter])==0) + else if("--no-fix-safefn"==step_args[argc_iter]) { opt_fix_safefn = false; } else { - cerr<<"Unrecognized option: "<<argv[argc_iter]<<endl; + cerr<<"Unrecognized option: "<<step_args[argc_iter]<<endl; return -1; } } if(getenv("FIX_CALLS_FIX_ALL_CALLS")) fix_all=true; - variant_id=atoi(argv[1]); + variant_id=stoi(step_args[0]); return 0; } diff --git a/tools/thanos/thanos.cpp b/tools/thanos/thanos.cpp index b6820d5a6faa6840b53cdf0c3a87fb1b94ae30e9..d53d3feb798909c0616571a938e12045390b1efd 100644 --- a/tools/thanos/thanos.cpp +++ b/tools/thanos/thanos.cpp @@ -1,302 +1,208 @@ #include <libIRDB-core.hpp> -#include <libIRDB-util.hpp> -#include <fcntl.h> -#include <dlfcn.h> -#include <cstdio> -#include <cstdlib> -#include <sys/stat.h> -#include <unistd.h> -#include <map> -#include <algorithm> -#include <assert.h> +#include <dlfcn.h> +#include <vector> +#include <memory> +#include <sstream> #include <iostream> - using namespace std; using namespace libIRDB; using namespace Transform_SDK; +class ThanosPlugin_t +{ + public: + static unique_ptr<ThanosPlugin_t> pluginFactory(const string plugin_details); + static int saveChanges(); + bool isOptional() + { + return step_optional; + } + string getStepName() + { + return step_name; + } + int runPlugin(); -#define MAX_BUF 1024 + private: + // methods + ThanosPlugin_t(const string p_step_name, + const bool p_step_optional, + const vector<string> p_step_args + ) + : + step_name(p_step_name), + step_optional(p_step_optional), + step_args(p_step_args) + { + } + int executeStep(TransformStep_t& the_step, const bool are_debugging); + int commitAll(); -enum class Mode { DEBUG, VERBOSE, DEFAULT }; + // data + const string step_name; + const bool step_optional; + const vector<string> step_args; + static const unique_ptr<IRDBObjects_t> shared_objects; +}; +// initialize private static data member +const unique_ptr<IRDBObjects_t> ThanosPlugin_t::shared_objects(new IRDBObjects_t()); -int execute_step(int argc, const char* const argv[], bool step_optional, Mode exec_mode, - IRDBObjects_t *const shared_objects, TransformStep_t *const the_step); +using PluginList_t = vector<unique_ptr<ThanosPlugin_t>>; +PluginList_t getPlugins(const int argc, char const *const argv[]); -// The toolchain driver script ps_analyze.sh communicates -// with this program via two pipes. This allows DB objects to be held -// in memory and shared across steps without rewriting the entire ps_analyze.sh -// script in C++. -int main(int argc, char *argv[]) +int main(int argc, char* argv[]) { - if(argc < 3) - { - cerr << "Usage: thanos.exe <input pipe name> <output pipe name>" << endl; - return 1; - } - - int in_pipe_fd=-1; - int out_pipe_fd=-1; - int num_bytes_read=0; + // get plugins + auto thanos_plugins = getPlugins(argc-1, argv+1); + if(thanos_plugins.size() == 0) + { + // for now, usage is pretty strict to enable simple + // parsing, because this program is only used by an + // automated script + cout << "Syntax error in arguments." << endl; + cout << "USAGE: (\"<step name> [-optional] [--step-args [ARGS]]\")+" << endl; + return 1; + } - const char *const input_pipe = argv[1]; - const char *const output_pipe = argv[2]; - char buf[MAX_BUF]; - buf[0] = '\0'; + for(unsigned int i = 0; i < thanos_plugins.size(); ++i) + { + ThanosPlugin_t* plugin = thanos_plugins[i].get(); - const char *const base_path = getenv("SECURITY_TRANSFORMS_HOME"); - if(base_path == NULL) - { - cerr << "Environment variables not set." << endl; - return 1; - } - const string plugin_path (string(base_path).append("/plugins_install/")); + const int result = plugin->runPlugin(); + // if that returns failure AND the step is not optional + if(result != 0 && !plugin->isOptional()) + { + cout << "A critical step failed: " << plugin->getStepName() << endl; + cout << "If DEBUG_STEPS is not on, this failure could " + << "be due to an earlier critical step." << endl; + return 1; // critical step failed, abort + } + } + // write back final changes + const int result = ThanosPlugin_t::saveChanges(); + if(result != 0) + { + cout << "A critical step failed: " << (thanos_plugins.back())->getStepName() + << endl; + cout << "If DEBUG_STEPS is not on, this failure could " + << "be due to an earlier critical step." << endl; + return 1; // critical step failed, abort + } + else + { + return 0; // success :) + } +} - in_pipe_fd = open(input_pipe, O_RDONLY); - if (in_pipe_fd == -1) { - cerr << "Not a valid pipe name." << endl; - return 1; - } - out_pipe_fd = open(output_pipe, O_WRONLY); - if (out_pipe_fd == -1) { - cerr << "Not a valid pipe name." << endl; - return 1; - } - - // Main loop where ps_analyze communicates with thanos.exe - // to execute steps that conform to the Transform Step SDK. - Mode exec_mode = Mode::DEFAULT; - unique_ptr<IRDBObjects_t> shared_objects(new IRDBObjects_t()); - string logfile_path = string(); - while (true) - { - if((num_bytes_read = read(in_pipe_fd, buf, MAX_BUF)) > 0) - { - buf[num_bytes_read] = '\0'; - if(strncmp(buf, "SET_MODE", 8) == 0) - { - if(strcmp(buf+8, " DEBUG") == 0) - { - exec_mode = Mode::DEBUG; - } - else if(strcmp(buf+8, " VERBOSE") == 0) - { - exec_mode = Mode::VERBOSE; - } - else if(strcmp(buf+8, " DEFAULT") == 0) - { - exec_mode = Mode::DEFAULT; - } - else - { - const ssize_t write_res = write(out_pipe_fd, (void*) "ERR_INVALID_CMD\n", 16); - if(write_res == -1) - return -1; - continue; - } - const ssize_t write_res = write(out_pipe_fd, (void*) "MODE_SET_OK\n", 12); - if(write_res == -1) - return -1; - } - else if(strncmp(buf, "SET_LOGFILE ", 12) == 0) - { - logfile_path.assign(buf+12); +PluginList_t getPlugins(const int argc, char const *const argv[]) +{ + PluginList_t plugins; + + for(auto i = 0; i < argc; ++i) + { + auto the_plugin = ThanosPlugin_t::pluginFactory(string(argv[i])); + if(the_plugin == nullptr) + return PluginList_t(); + plugins.push_back(move(the_plugin)); + } + return plugins; +} + - const ssize_t write_res = write(out_pipe_fd, (void*) "LOGFILE_SET_OK\n", 15); - if(write_res == -1) - return -1; - } - else if(strncmp(buf, "EXECUTE_STEP", 12) == 0) - { - if(strncmp(buf+12, " OPTIONAL ", 10) == 0 || strncmp(buf+12, " CRITICAL ", 10) == 0) - { - char *const command_start = buf+12+10; - char *const command_end = strchr(buf, '\n'); - if (!command_end || (command_end == command_start)) - { - const ssize_t write_res = write(out_pipe_fd, (void*) "ERR_INVALID_CMD\n", 16); - if(write_res == -1) - return -1; - } - else - { - // parse command string into argv, argc - // simple parsing relies on ps_analyze.sh separating - // step arguments with single spaces. - *command_end = '\0'; +// assumes that tokens are always space-separated +// (cannot be delineated by quotes, for example) +const vector<string> getTokens(const string arg_string) +{ + vector<string> tokens; + istringstream arg_stream(arg_string); + string token; + while (getline(arg_stream, token, ' ')) + { + tokens.push_back(token); + } + return tokens; +} - const size_t max_args = ((command_end - command_start) / 2)+1; - char** argv = (char**) malloc(max_args); - int argc = 0; - - //cout<<"Setting argv[0]="<<command_start<<endl; - argv[argc++] = command_start; - char* command_remaining = strchr(command_start, ' '); - while (command_remaining != NULL) - { - *command_remaining = '\0'; - //cout<<"Setting argv["<<dec<<argc<<"]="<<command_remaining+1<<endl; - argv[argc++] = command_remaining+1; - command_remaining = strchr(command_remaining+1, ' '); - } - argv = (char**) realloc(argv, argc); - // setup transform step plugin - const char *const step_name = argv[0]; - void *const dlhdl = dlopen((plugin_path+step_name).c_str(), RTLD_NOW); - if(dlhdl == NULL) - { - const auto err=dlerror(); - cout<<"Cannot open "<<step_name<<": "<<err<<endl; - const ssize_t write_res = write(out_pipe_fd, (void*) "STEP_UNSUPPORTED\n", 17); - if(write_res == -1) - return -1; - } - else - { - const void *const sym = dlsym(dlhdl, "GetTransformStep"); - if(sym == NULL) - { - const auto err=dlerror(); - cout<<"Cannot find GetTransformStep in "<<step_name<<": "<<err<<endl; - const ssize_t write_res = write(out_pipe_fd, (void*) "STEP_UNSUPPORTED\n", 17); - if(write_res == -1) - return -1; - } - else - { - using GetTransformPtr_t = shared_ptr<TransformStep_t> (*)(void); // function pointer, takes void, returns TransformStep_t shared ptr - // variables - GetTransformPtr_t func=(GetTransformPtr_t)sym; - shared_ptr<TransformStep_t> the_step = (*func)(); - assert(the_step != NULL); +unique_ptr<ThanosPlugin_t> ThanosPlugin_t::pluginFactory(const string plugin_details) +{ + auto tokens = getTokens(plugin_details); + if(tokens.size() < 1) + return unique_ptr<ThanosPlugin_t>(nullptr); - bool step_optional = true; - if(strncmp(buf+12, " CRITICAL ", 10) == 0) - { - step_optional = false; - } - - // setup logging - int saved_stdout = dup(STDOUT_FILENO); - int saved_stderr = dup(STDERR_FILENO); - FILE *log_output = NULL; - if(exec_mode == Mode::DEFAULT || exec_mode == Mode::VERBOSE) - { - log_output = fopen(logfile_path.c_str(), "a"); - int log_output_fd = fileno(log_output); - dup2(log_output_fd, STDOUT_FILENO); - dup2(log_output_fd, STDERR_FILENO); - } - - const int step_retval = execute_step(argc, argv, step_optional, exec_mode, shared_objects.get(), the_step.get()); + const auto step_name = tokens[0]; + auto step_optional = false; + vector<string> step_args; + for(unsigned int i = 1; i < tokens.size(); ++i) + { + if(tokens[i] == "--step-args") + { + if(tokens.begin()+i+1 < tokens.end()) + step_args.assign(tokens.begin()+i+1, tokens.end()); + break; + } + else if(tokens[i] == "-optional") + { + step_optional = true; + } + else + { + return unique_ptr<ThanosPlugin_t>(nullptr); + } + } + return unique_ptr<ThanosPlugin_t>(new ThanosPlugin_t(step_name, step_optional, step_args)); +} - // cleanup from logging - if(exec_mode == Mode::DEFAULT || exec_mode == Mode::VERBOSE) - { - fclose(log_output); - } - dup2(saved_stdout, STDOUT_FILENO); - close(saved_stdout); - dup2(saved_stderr, STDERR_FILENO); - close(saved_stderr); - // cleanup plugin - free(argv); - argv=nullptr; - the_step.reset(); // explicitly get rid of the handle to the library so we can close it. - dlclose(dlhdl); - - const string step_retval_str(to_string(step_retval)+"\n"); - const ssize_t write_res = write(out_pipe_fd, (void*) step_retval_str.c_str(), step_retval_str.size()); // size() excludes terminating null character in this case, which is what we want - if(write_res == -1) - return -1; - } - } - } - } - else - { - const ssize_t write_res = write(out_pipe_fd, (void*) "ERR_INVALID_CMD\n", 16); - if(write_res == -1) - return -1; - } - } - else if(strcmp(buf, "COMMIT_ALL") == 0) - { - // setup logging - int saved_stdout = dup(STDOUT_FILENO); - int saved_stderr = dup(STDERR_FILENO); - FILE *log_output = NULL; - if((exec_mode == Mode::DEFAULT || exec_mode == Mode::VERBOSE) && !logfile_path.empty()) - { - log_output = fopen(logfile_path.c_str(), "a"); - int log_output_fd = fileno(log_output); - dup2(log_output_fd, STDOUT_FILENO); - dup2(log_output_fd, STDERR_FILENO); - } +int ThanosPlugin_t::runPlugin() +{ + static const char *const base_path = getenv("SECURITY_TRANSFORMS_HOME"); + if(base_path == NULL) + { + cout << "Environment variables not set." << endl; + return -1; + } + static const auto plugin_path (string(base_path).append("/plugins_install/")); - pqxxDB_t* pqxx_interface = shared_objects->getDBInterface(); - const int error = shared_objects->writeBackAll(); - if(error) - { - const int error_retval = -1; // critical step failed, abort - const string retval_str(to_string(error_retval)+"\n"); - const ssize_t write_res = write(out_pipe_fd, (void*) retval_str.c_str(), retval_str.size()); // size() excludes terminating null character in this case, which is what we want - if(write_res == -1) - return -1; - } - else - { - // commit changes and reset interface - pqxx_interface->Commit(); - pqxx_interface = shared_objects->resetDBInterface(); - // delete all shared items - shared_objects->deleteAll(); - const ssize_t write_res = write(out_pipe_fd, (void*) "COMMIT_ALL_OK\n", 14); - if(write_res == -1) - return -1; - } - - // cleanup from logging - if((exec_mode == Mode::DEFAULT || exec_mode == Mode::VERBOSE) && !logfile_path.empty()) - { - fclose(log_output); - } - dup2(saved_stdout, STDOUT_FILENO); - close(saved_stdout); - dup2(saved_stderr, STDERR_FILENO); - close(saved_stderr); - } - else if(strcmp(buf, "TERMINATE") == 0) - { - break; - } - else - { - const ssize_t write_res = write(out_pipe_fd, (void*) "ERR_INVALID_CMD\n", 16); - if(write_res == -1) - return -1; - } + void *const dlhdl = dlopen((plugin_path+"lib"+step_name+".so").c_str(), RTLD_NOW); + if(dlhdl == NULL) + { + const auto err=dlerror(); + cout<<"Cannot open "<<step_name<<": "<<err<<endl; + return -1; } - else - sleep(1); - } + + const void *const sym = dlsym(dlhdl, "GetTransformStep"); + if(sym == NULL) + { + const auto err=dlerror(); + cout<<"Cannot find GetTransformStep in "<<step_name<<": "<<err<<endl; + return -1; + } + + using GetTransformPtr_t = shared_ptr<TransformStep_t> (*)(void); // function pointer, takes void, returns TransformStep_t shared ptr + GetTransformPtr_t func=(GetTransformPtr_t)sym; + shared_ptr<TransformStep_t> the_step = (*func)(); + assert(the_step != NULL); + + static const char *const are_debugging = getenv("DEBUG_STEPS"); + + const int step_result = executeStep(*(the_step.get()), (bool) are_debugging); + + the_step.reset(); // explicitly get rid of the handle to the library so we can close it. + dlclose(dlhdl); - close(in_pipe_fd); - close(out_pipe_fd); - - return 0; + // return status of execute method + return step_result; } -int execute_step(int argc, const char* const argv[], bool step_optional, Mode exec_mode, - IRDBObjects_t* shared_objects, TransformStep_t* the_step) +int ThanosPlugin_t::executeStep(TransformStep_t& the_step, const bool are_debugging) { - const int parse_retval = the_step->parseArgs(argc, argv); + const int parse_retval = the_step.parseArgs(step_args); if(parse_retval != 0) { return parse_retval; @@ -308,7 +214,7 @@ int execute_step(int argc, const char* const argv[], bool step_optional, Mode ex const int error = shared_objects->writeBackAll(); if(error) { - return -1; // the failure must be from a critical step, abort + return 1; // the failure must be from a critical step, abort } else { @@ -318,7 +224,7 @@ int execute_step(int argc, const char* const argv[], bool step_optional, Mode ex } } - const int step_error = the_step->executeStep(shared_objects); + const int step_error = the_step.executeStep(shared_objects.get()); if(step_error) { @@ -330,7 +236,7 @@ int execute_step(int argc, const char* const argv[], bool step_optional, Mode ex } else { - return -1; // critical step failed, abort + return 1; // critical step failed, abort } } @@ -343,20 +249,20 @@ int execute_step(int argc, const char* const argv[], bool step_optional, Mode ex // abort changes by resetting DB interface pqxx_interface = shared_objects->resetDBInterface(); } - else if(exec_mode == Mode::DEBUG) + else if(are_debugging) { // commit changes (in case next step fails) and reset interface pqxx_interface->Commit(); pqxx_interface = shared_objects->resetDBInterface(); } } - else if(exec_mode == Mode::DEBUG) + else if(are_debugging) { // write changes to DB in case next step fails const int error = shared_objects->writeBackAll(); if(error) { - return -1; // critical step failed, abort + return 1; // critical step failed, abort } else { @@ -366,5 +272,24 @@ int execute_step(int argc, const char* const argv[], bool step_optional, Mode ex } } - return step_error; + return step_error; +} + + +int ThanosPlugin_t::saveChanges() +{ + pqxxDB_t* pqxx_interface = shared_objects->getDBInterface(); + const int error = shared_objects->writeBackAll(); + if(error) + { + return 1; // critical step failed, abort + } + else + { + // commit changes and reset interface + pqxx_interface->Commit(); + pqxx_interface = shared_objects->resetDBInterface(); + return 0; + } } +