damaris-backends/core/core_config.cpp
2014-06-26 11:10:51 +00:00

180 lines
6.0 KiB
C++

/* **************************************************************************
Author: Achim Gaedke
Created: June 2004
****************************************************************************/
#include "core_config.h"
#include "core_exception.h"
#include "xml_result.h"
#include "core.h"
#include <cerrno>
#include <unistd.h>
#include <expat.h>
#include <math.h>
core_config::core_config(const char** argv, int argc) {
spool_directory=".";
result_filename_pattern="job.%09lu.result";
job_filename_pattern="job.%09lu";
job_poll_wait=0.1;
result_encoding=xml_result_writer::base64;
// find spool directory argument
for (int i=1; i<argc; ++i) {
if (strncmp(argv[i],"--spool",7)==0) {
if (argv[i][7]==0) {
if (i>=argc || argv[i+1]==NULL) {
throw core_exception("spool directory not specified after --spool argument");
}
++i;
spool_directory=argv[i];
} else if (argv[i][7]=='=') {
spool_directory=(argv[i]+8);
} else {
throw core_exception("spool directory not specified after --spool argument");
}
} else {
fprintf(stderr, "ignoring argument %s\n", argv[i]);
}
}
}
int core_config::xml_write_core_config_lines(FILE* f) const {
fprintf(f,"<jobs spool=\"%s\" pattern=\"%s\" polltime=\"%g\"/>\n", spool_directory.c_str(), job_filename_pattern.c_str(), job_poll_wait);
std::string encoding_name;
switch (result_encoding) {
case xml_result_writer::defaultmode:
encoding_name="default"; break;
case xml_result_writer::separate_file:
encoding_name="separate_file"; break;
case xml_result_writer::base64:
encoding_name="base64"; break;
case xml_result_writer::ascii:
encoding_name="ascii"; break;
case xml_result_writer::csv:
encoding_name="csv"; break;
case xml_result_writer::hex:
encoding_name="hex"; break;
default:
encoding_name="unknown";
}
fprintf(f,"<results spool=\"%s\" pattern=\"%s\" encoding=\"%s\"/>\n", spool_directory.c_str(), result_filename_pattern.c_str(),encoding_name.c_str());
return 0;
}
int core_config::xml_read_core_config_startElement(const std::string& name, const xml_attrs& attrs) {
if (name=="jobs") {
xml_attrs::const_iterator spool_attr=attrs.find("spool");
xml_attrs::const_iterator pattern_attr=attrs.find("pattern");
xml_attrs::const_iterator polltime_attr=attrs.find("polltime");
if (spool_attr!=attrs.end()) spool_directory=spool_attr->second;
if (pattern_attr!=attrs.end()) job_filename_pattern=pattern_attr->second;
char* polltime_char;
job_poll_wait=(size_t)floor(1e6*strtod(polltime_attr->second.c_str(),&polltime_char));
if (polltime_char==polltime_attr->second.c_str())
throw core_exception("polltime is no valid number");
}
else if (name=="results") {
xml_attrs::const_iterator spool_attr=attrs.find("spool");
xml_attrs::const_iterator pattern_attr=attrs.find("pattern");
if (spool_attr!=attrs.end()) spool_directory=spool_attr->second;
if (pattern_attr!=attrs.end()) result_filename_pattern=pattern_attr->second;
/* todo: result encoding */
}
return 0;
}
void xml_core_status_startelement_handler(core_state* cs, const char* name, char* const* attrs) {
size_t i;
xml_attrs the_attrs;
for (i=0;attrs[i]!=0;i+=2) {
the_attrs[attrs[i]]=attrs[i+1];
}
cs->xml_read_core_state_startElement(std::string(name),the_attrs);
}
int core_state::xml_read_core_state_startElement(const std::string& name, const xml_attrs& attrs) {
if (name=="state") {
xml_attrs::const_iterator pid_attr=attrs.find("pid");
if (pid_attr==attrs.end()) throw core_exception("no pid attribute found");
char* pid_char;
pid=strtol(pid_attr->second.c_str(),&pid_char,10);
if (pid_char==pid_attr->second.c_str()) throw core_exception("pid attribute did not contain a number");
xml_attrs::const_iterator name_attr=attrs.find("name");
if (name_attr!=attrs.end()) core_name=name_attr->second;
}
else
xml_read_core_config_startElement(name,attrs);
return 0;
}
int core_state::dump_state(const std::string& statefilename) const {
// first delete old state file
int unlink_result=unlink(statefilename.c_str());
if (unlink_result!=0 && errno!=ENOENT) {
throw core_exception("could not remove state file "+statefilename+"\"");
}
//then try to write new state file
FILE* configfile=fopen(statefilename.c_str(),"w");
if (configfile==0) throw core_exception("could not write core configuration file \""+statefilename+"\"");
fprintf(configfile,"<?xml version=\"1.0\"?>\n");
fprintf(configfile,"<state name=\"%s\" pid=\"%d\" starttime=\"%ld\">\n", core_name.c_str(), pid, start_time);
xml_write_core_config_lines(configfile);
fprintf(configfile,"</state>\n");
fclose(configfile);
return 0;
}
core_state::core_state(const core& the_core): core_config(the_core.the_configuration) {
pid=getpid();
core_name=the_core.core_name();
start_time=the_core.start_time;
}
core_state::core_state(const std::string& filename): core_config() {
if (access(filename.c_str(),R_OK)!=0)
throw core_exception("could not open status file "+filename);
FILE* configfile=fopen(filename.c_str(),"r");
/* parse document */
XML_Parser p=XML_ParserCreate(NULL);
/* set handler and user data*/
XML_SetStartElementHandler(p,(XML_StartElementHandler)&xml_core_status_startelement_handler);
XML_SetUserData(p,(void*)this);
/* read buffer */
for (;;) {
const size_t BUFF_SIZE=4000;
int bytes_read;
void *buff = XML_GetBuffer(p,BUFF_SIZE);
if (buff == NULL) {
/* handle error */
}
bytes_read = fread(buff, 1, BUFF_SIZE, configfile);
if (bytes_read < 0) {
fclose(configfile);
XML_ParserFree(p);
throw core_exception("error while reading file "+filename);
}
if (! XML_ParseBuffer(p, bytes_read, bytes_read == 0)) {
/* handle parse error */
fclose(configfile);
XML_ParserFree(p);
throw core_exception("error while parsing file "+filename);
}
if (bytes_read == 0)
break;
}
XML_ParserFree(p);
fclose(configfile);
}