150 lines
4.6 KiB
C++
Executable File
150 lines
4.6 KiB
C++
Executable File
#include "initialize_stack.hpp"
|
|
#include <getopt.h>
|
|
|
|
using namespace std;
|
|
using namespace IRDB_SDK;
|
|
using namespace InitStack;
|
|
|
|
//
|
|
// Print usage info
|
|
//
|
|
void usage(char *p_name) {
|
|
cerr << "Usage: " << p_name << " <variant_id>\n";
|
|
cerr << "\t[--functions <file> | -f <file>] Read in the functions to "
|
|
"auto-initialize "
|
|
<< endl;
|
|
cerr << "\t[--initvalue <value> | -i <value>] Specify stack "
|
|
"initialization value (default=0)"
|
|
<< endl;
|
|
cerr << "\t[--verbose | -v] Verbose mode "
|
|
" "
|
|
<< endl;
|
|
cerr << "\t[--help,--usage,-?,-h] Display this message "
|
|
" "
|
|
<< endl;
|
|
}
|
|
|
|
//
|
|
// The entry point for a stand-alone executable transform.
|
|
// Note: Thanos-enabled transforms are easier to write, faster to execute, and
|
|
// generally preferred. Stand-alone transforms may be useful if the transform
|
|
// has issues with memory leaks and/or memory errors. Memory issues in a stand
|
|
// alone transform cannot affect correctness of other transforms.
|
|
//
|
|
int main(int argc, char **argv) {
|
|
//
|
|
// Sanity check that the command line has at least a variant ID, otherwise we
|
|
// won't know what variant to operate on.
|
|
//
|
|
if (argc < 2) {
|
|
usage(argv[0]);
|
|
exit(1);
|
|
}
|
|
|
|
// constant parameters read from argv
|
|
const auto program_name = string(argv[0]);
|
|
const auto variantID = atoi(argv[1]);
|
|
|
|
// initial values of parameters to parse
|
|
auto verbose = false;
|
|
auto funcs_filename = string();
|
|
auto init_value = 0;
|
|
|
|
// declare some options for the transform
|
|
const char *short_opts = "f:i:v?h";
|
|
struct option long_options[] = {{"functions", required_argument, 0, 'f'},
|
|
{"initvalue", required_argument, 0, 'i'},
|
|
{"verbose", no_argument, 0, 'v'},
|
|
{"help", no_argument, 0, 'h'},
|
|
{"usage", no_argument, 0, '?'},
|
|
{0, 0, 0, 0}};
|
|
|
|
// parse the options in a standard getopts_long loop
|
|
while (true) {
|
|
int c = getopt_long(argc, argv, short_opts, long_options, nullptr);
|
|
if (c == -1)
|
|
break;
|
|
switch (c) {
|
|
case 'f':
|
|
funcs_filename = optarg;
|
|
cout << "Reading file with function specifiers: " << funcs_filename
|
|
<< endl;
|
|
break;
|
|
case 'i':
|
|
init_value = strtoll(optarg, NULL, 0);
|
|
cout << " Stack initialization value: " << hex << init_value << endl;
|
|
break;
|
|
case 'v':
|
|
verbose = true;
|
|
break;
|
|
case '?':
|
|
case 'h':
|
|
usage(argv[0]);
|
|
exit(1);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
// stand alone transforms must setup the interface to the sql server
|
|
auto pqxx_interface = pqxxDB_t::factory();
|
|
BaseObj_t::setInterface(pqxx_interface.get());
|
|
|
|
// stand alone transforms must create and read a variant ID from the database
|
|
auto pidp = VariantID_t::factory(variantID);
|
|
assert(pidp->isRegistered() == true);
|
|
|
|
// stand alone transforms must create and read the main file's IR from the
|
|
// datatbase
|
|
auto this_file = pidp->getMainFile();
|
|
auto url = this_file->getURL();
|
|
|
|
// declare for later so we can return the right value
|
|
auto success = false;
|
|
|
|
// now try to load the IR and execute a transform
|
|
try {
|
|
// Create and download the file's IR.
|
|
// Note: this is achieved differently with thanos-enabled plugins
|
|
auto firp = FileIR_t::factory(pidp.get(), this_file);
|
|
|
|
// sanity
|
|
assert(firp && pidp);
|
|
|
|
// log
|
|
cout << "Transforming " << this_file->getURL() << endl;
|
|
|
|
// create and invoke the transform
|
|
InitStack_t is(firp.get(), funcs_filename, init_value, verbose);
|
|
success = is.execute();
|
|
|
|
// conditionally write the IR back to the database on success
|
|
if (success) {
|
|
cout << "Writing changes for " << url << endl;
|
|
|
|
// Stand alone trnasforms must manually write the IR back to the IRDB and
|
|
// commit the transactions
|
|
firp->writeToDB();
|
|
|
|
// and commit the the transaction to postgres
|
|
pqxx_interface->commit();
|
|
} else {
|
|
cout << "Skipping write back on failure. " << url << endl;
|
|
}
|
|
} catch (const DatabaseError_t &db_error) {
|
|
// log any databse errors that might come up in the transform process
|
|
cerr << program_name << ": Unexpected database error: " << db_error
|
|
<< "file url: " << url << endl;
|
|
} catch (...) {
|
|
// log any other errors
|
|
cerr << program_name << ": Unexpected error file url: " << url << endl;
|
|
}
|
|
|
|
//
|
|
// return success code to driver (as a shell-style return value). 0=success,
|
|
// 1=warnings, 2=errors
|
|
//
|
|
return success ? 0 : 2;
|
|
}
|