#include "errorhandler.h"
#include "gadget.h"
#include "global.h"
#ifndef GADGET_NETWORK
//JMB dont access runid on a network run
#include "runid.h"
#endif
ErrorHandler::ErrorHandler() {
files = new StrStack();
uselog = 0;
numwarn = 0;
runopt = 0;
nanflag = 0;
loglevel = LOGINFO;
}
ErrorHandler::~ErrorHandler() {
delete files;
}
void ErrorHandler::setLogLevel(int level) {
switch (level) {
case 0:
//no messages displayed at all - only used for paramin runs
loglevel = LOGNONE;
break;
case 1:
//only get the failure messages written to std::cerr
//gadget will exit with exit(EXIT_FAILURE) once it receives a message here
loglevel = LOGFAIL;
break;
case 2:
//also get the information messages written to std::cout
loglevel = LOGINFO;
break;
case 3:
//also get the warning messages written to std::cerr
loglevel = LOGWARN;
break;
case 4:
//also get debug messages to be written to the logfile (if it exists)
loglevel = LOGDEBUG;
break;
case 5:
//also get information messages to be written to the logfile (if it exists)
loglevel = LOGMESSAGE;
break;
case 6:
//also get more detailed messages to be written to the logfile (if it exists)
loglevel = LOGDETAIL;
break;
default:
cerr << "Error in errorhandler - invalid log level " << level << endl;
break;
}
}
void ErrorHandler::setLogFile(const char* filename) {
uselog = 1;
logfile.open(filename, ios::out);
this->checkIfFailure(logfile, filename);
#ifndef GADGET_NETWORK
RUNID.Print(logfile);
#endif
logfile << "Log file to record Gadget actions that take place during this run\n\n";
logfile.flush();
}
void ErrorHandler::Open(const char* filename) {
this->logMessage(LOGMESSAGE, "Opening file", filename);
files->storeString(filename);
}
void ErrorHandler::Close() {
if (loglevel >= LOGMESSAGE) {
char* strFilename = files->sendTop();
this->logMessage(LOGMESSAGE, "Closing file", strFilename);
delete[] strFilename;
}
files->clearString();
}
void ErrorHandler::logMessage(LogLevel mlevel, const char* msg) {
if (mlevel > loglevel)
return;
#pragma omp critical (logchar)
switch (mlevel) {
case LOGNONE:
break;
case LOGFAIL:
if (uselog) {
logfile << msg << endl;
logfile.flush();
}
cerr << msg << endl;
exit(EXIT_FAILURE);
break;
case LOGINFO:
if (uselog) {
logfile << msg << endl;
logfile.flush();
}
cout << msg << endl;
break;
case LOGWARN:
numwarn++;
if (uselog) {
logfile << msg << endl;
logfile.flush();
}
cerr << msg << endl;
break;
case LOGDEBUG:
case LOGMESSAGE:
case LOGDETAIL:
if (uselog) {
logfile << msg << endl;
logfile.flush();
}
break;
default:
cerr << "Error in errorhandler - invalid log level " << mlevel << endl;
break;
}
}
void ErrorHandler::logMessage(LogLevel mlevel, const char* msg1, const char* msg2) {
if (mlevel > loglevel)
return;
#pragma omp critical (logcharchar)
switch (mlevel) {
case LOGNONE:
break;
case LOGFAIL:
if (uselog) {
logfile << msg1 << sep << msg2 << endl;
logfile.flush();
}
cerr << msg1 << sep << msg2 << endl;
exit(EXIT_FAILURE);
break;
case LOGINFO:
if (uselog) {
logfile << msg1 << sep << msg2 << endl;
logfile.flush();
}
cout << msg1 << sep << msg2 << endl;
break;
case LOGWARN:
numwarn++;
if (uselog) {
logfile << msg1 << sep << msg2 << endl;
logfile.flush();
}
cerr << msg1 << sep << msg2 << endl;
break;
case LOGDEBUG:
case LOGMESSAGE:
case LOGDETAIL:
if (uselog) {
logfile << msg1 << sep << msg2 << endl;
logfile.flush();
}
break;
default:
cerr << "Error in errorhandler - invalid log level " << mlevel << endl;
break;
}
}
void ErrorHandler::logMessage(LogLevel mlevel, const char* msg, int number) {
if (mlevel > loglevel)
return;
#pragma omp critical (logCharInt)
switch (mlevel) {
case LOGNONE:
break;
case LOGFAIL:
if (uselog) {
logfile << msg << sep << number << endl;
logfile.flush();
}
cerr << msg << sep << number << endl;
exit(EXIT_FAILURE);
break;
case LOGINFO:
if (uselog) {
logfile << msg << sep << number << endl;
logfile.flush();
}
cout << msg << sep << number << endl;
break;
case LOGWARN:
numwarn++;
if (uselog) {
logfile << msg << sep << number << endl;
logfile.flush();
}
cerr << msg << sep << number << endl;
break;
case LOGDEBUG:
case LOGMESSAGE:
case LOGDETAIL:
if (uselog) {
logfile << msg << sep << number << endl;
logfile.flush();
}
break;
default:
cerr << "Error in errorhandler - invalid log level " << mlevel << endl;
break;
}
}
void ErrorHandler::logMessage(LogLevel mlevel, const char* msg, double number) {
if (mlevel > loglevel)
return;
switch (mlevel) {
case LOGNONE:
break;
case LOGFAIL:
if (uselog) {
logfile << msg << sep << number << endl;
logfile.flush();
}
cerr << msg << sep << number << endl;
exit(EXIT_FAILURE);
break;
case LOGINFO:
if (uselog) {
logfile << msg << sep << number << endl;
logfile.flush();
}
cout << msg << sep << number << endl;
break;
case LOGWARN:
numwarn++;
if (uselog) {
logfile << msg << sep << number << endl;
logfile.flush();
}
cerr << msg << sep << number << endl;
break;
case LOGDEBUG:
case LOGMESSAGE:
case LOGDETAIL:
if (uselog) {
logfile << msg << sep << number << endl;
logfile.flush();
}
break;
default:
cerr << "Error in errorhandler - invalid log level " << mlevel << endl;
break;
}
}
void ErrorHandler::logMessage(LogLevel mlevel, const char* msg1, int number, const char* msg2) {
if (mlevel > loglevel)
return;
switch (mlevel) {
case LOGNONE:
break;
case LOGFAIL:
if (uselog) {
logfile << msg1 << sep << number << sep << msg2 << endl;
logfile.flush();
}
cerr << msg1 << sep << number << sep << msg2 << endl;
exit(EXIT_FAILURE);
break;
case LOGINFO:
if (uselog) {
logfile << msg1 << sep << number << sep << msg2 << endl;
logfile.flush();
}
cout << msg1 << sep << number << sep << msg2 << endl;
break;
case LOGWARN:
numwarn++;
if (uselog) {
logfile << msg1 << sep << number << sep << msg2 << endl;
logfile.flush();
}
cerr << msg1 << sep << number << sep << msg2 << endl;
break;
case LOGDEBUG:
case LOGMESSAGE:
case LOGDETAIL:
if (uselog) {
logfile << msg1 << sep << number << sep << msg2 << endl;
logfile.flush();
}
break;
default:
cerr << "Error in errorhandler - invalid log level " << mlevel << endl;
break;
}
}
void ErrorHandler::logMessage(LogLevel mlevel, const char* msg1, double number, const char* msg2) {
if (mlevel > loglevel)
return;
switch (mlevel) {
case LOGNONE:
break;
case LOGFAIL:
if (uselog) {
logfile << msg1 << sep << number << sep << msg2 << endl;
logfile.flush();
}
cerr << msg1 << sep << number << sep << msg2 << endl;
exit(EXIT_FAILURE);
break;
case LOGINFO:
if (uselog) {
logfile << msg1 << sep << number << sep << msg2 << endl;
logfile.flush();
}
cout << msg1 << sep << number << sep << msg2 << endl;
break;
case LOGWARN:
numwarn++;
if (uselog) {
logfile << msg1 << sep << number << sep << msg2 << endl;
logfile.flush();
}
cerr << msg1 << sep << number << sep << msg2 << endl;
break;
case LOGDEBUG:
case LOGMESSAGE:
case LOGDETAIL:
if (uselog) {
logfile << msg1 << sep << number << sep << msg2 << endl;
logfile.flush();
}
break;
default:
cerr << "Error in errorhandler - invalid log level " << mlevel << endl;
break;
}
}
void ErrorHandler::logMessage(LogLevel mlevel, DoubleVector vec) {
if (mlevel > loglevel)
return;
int i;
switch (mlevel) {
case LOGNONE:
break;
case LOGFAIL:
if (uselog) {
for (i = 0; i < vec.Size(); i++)
logfile << vec[i] << sep;
logfile << endl;
logfile.flush();
}
for (i = 0; i < vec.Size(); i++)
cerr << vec[i] << sep;
cerr << endl;
exit(EXIT_FAILURE);
break;
case LOGINFO:
if (uselog) {
for (i = 0; i < vec.Size(); i++)
logfile << vec[i] << sep;
logfile << endl;
logfile.flush();
}
for (i = 0; i < vec.Size(); i++)
cout << vec[i] << sep;
cout << endl;
break;
case LOGWARN:
numwarn++;
if (uselog) {
for (i = 0; i < vec.Size(); i++)
logfile << vec[i] << sep;
logfile << endl;
logfile.flush();
}
for (i = 0; i < vec.Size(); i++)
cerr << vec[i] << sep;
cerr << endl;
break;
case LOGDEBUG:
case LOGMESSAGE:
case LOGDETAIL:
if (uselog) {
for (i = 0; i < vec.Size(); i++)
logfile << vec[i] << sep;
logfile << endl;
logfile.flush();
}
break;
default:
cerr << "Error in errorhandler - invalid log level " << mlevel << endl;
break;
}
}
void ErrorHandler::logMessageNaN(LogLevel mlevel, const char* msg) {
nanflag = 1;
if (mlevel > loglevel)
return;
switch (mlevel) {
case LOGNONE:
break;
case LOGFAIL:
if (uselog) {
logfile << "Error in model - NaN found" << sep << msg << endl;
logfile.flush();
}
cerr << "Error in model - NaN found" << sep << msg << endl;
exit(EXIT_FAILURE);
break;
case LOGINFO:
if (uselog) {
logfile << "Error in model - NaN found" << sep << msg << endl;
logfile.flush();
}
cout << "Error in model - NaN found" << sep << msg << endl;
break;
case LOGWARN:
numwarn++;
if (uselog) {
logfile << "Error in model - NaN found" << sep << msg << endl;
logfile.flush();
}
cerr << "Error in model - NaN found" << sep << msg << endl;
break;
case LOGDEBUG:
case LOGMESSAGE:
case LOGDETAIL:
if (uselog) {
logfile << "Error in model - NaN found" << sep << msg << endl;
logfile.flush();
}
break;
default:
cerr << "Error in errorhandler - invalid log level " << mlevel << endl;
break;
}
}
void ErrorHandler::logFileMessage(LogLevel mlevel, const char* msg) {
if (mlevel > loglevel)
return;
char* strFilename = files->sendTop();
switch (mlevel) {
case LOGNONE:
case LOGINFO:
break;
case LOGFAIL:
if (uselog) {
if (files->getSize() == 0)
logfile << "Error on commandline - " << msg << endl;
else
logfile << "Error in file " << strFilename << " - " << msg << endl;
logfile.flush();
}
if (files->getSize() == 0)
cerr << "Error on commandline - " << msg << endl;
else
cerr << "Error in file " << strFilename << " - " << msg << endl;
delete[] strFilename;
exit(EXIT_FAILURE);
break;
case LOGWARN:
numwarn++;
if (uselog) {
if (files->getSize() == 0)
logfile << "Warning on commandline - " << msg << endl;
else
logfile << "Warning in file " << strFilename << " - " << msg << endl;
logfile.flush();
}
if (files->getSize() == 0)
cerr << "Warning on commandline - " << msg << endl;
else
cerr << "Warning in file " << strFilename << " - " << msg << endl;
break;
case LOGDEBUG:
case LOGMESSAGE:
case LOGDETAIL:
if (uselog) {
logfile << "Message in file " << strFilename << " - " << msg << endl;
logfile.flush();
}
break;
default:
cerr << "Error in errorhandler - invalid log level " << mlevel << endl;
break;
}
delete[] strFilename;
}
void ErrorHandler::logFileMessage(LogLevel mlevel, const char* msg, int number) {
if (mlevel > loglevel)
return;
char* strFilename = files->sendTop();
switch (mlevel) {
case LOGNONE:
case LOGINFO:
break;
case LOGFAIL:
if (uselog) {
if (files->getSize() == 0)
logfile << "Error on commandline - " << msg << sep << number << endl;
else
logfile << "Error in file " << strFilename << " - " << msg << sep << number << endl;
logfile.flush();
}
if (files->getSize() == 0)
cerr << "Error on commandline - " << msg << sep << number << endl;
else
cerr << "Error in file " << strFilename << " - " << msg << sep << number << endl;
delete[] strFilename;
exit(EXIT_FAILURE);
break;
case LOGWARN:
numwarn++;
if (uselog) {
if (files->getSize() == 0)
logfile << "Warning on commandline - " << msg << sep << number << endl;
else
logfile << "Warning in file " << strFilename << " - " << msg << sep << number << endl;
logfile.flush();
}
if (files->getSize() == 0)
cerr << "Warning on commandline - " << msg << sep << number << endl;
else
cerr << "Warning in file " << strFilename << " - " << msg << sep << number << endl;
break;
case LOGDEBUG:
case LOGMESSAGE:
case LOGDETAIL:
if (uselog) {
logfile << "Message in file " << strFilename << " - " << msg << sep << number << endl;
logfile.flush();
}
break;
default:
cerr << "Error in errorhandler - invalid log level " << mlevel << endl;
break;
}
delete[] strFilename;
}
void ErrorHandler::logFileMessage(LogLevel mlevel, const char* msg, double number) {
if (mlevel > loglevel)
return;
char* strFilename = files->sendTop();
switch (mlevel) {
case LOGNONE:
case LOGINFO:
break;
case LOGFAIL:
if (uselog) {
if (files->getSize() == 0)
logfile << "Error on commandline - " << msg << sep << number << endl;
else
logfile << "Error in file " << strFilename << " - " << msg << sep << number << endl;
logfile.flush();
}
if (files->getSize() == 0)
cerr << "Error on commandline - " << msg << sep << number << endl;
else
cerr << "Error in file " << strFilename << " - " << msg << sep << number << endl;
delete[] strFilename;
exit(EXIT_FAILURE);
break;
case LOGWARN:
numwarn++;
if (uselog) {
if (files->getSize() == 0)
logfile << "Warning on commandline - " << msg << sep << number << endl;
else
logfile << "Warning in file " << strFilename << " - " << msg << sep << number << endl;
logfile.flush();
}
if (files->getSize() == 0)
cerr << "Warning on commandline - " << msg << sep << number << endl;
else
cerr << "Warning in file " << strFilename << " - " << msg << sep << number << endl;
break;
case LOGDEBUG:
case LOGMESSAGE:
case LOGDETAIL:
if (uselog) {
logfile << "Message in file " << strFilename << " - " << msg << sep << number << endl;
logfile.flush();
}
break;
default:
cerr << "Error in errorhandler - invalid log level " << mlevel << endl;
break;
}
delete[] strFilename;
}
void ErrorHandler::logFileMessage(LogLevel mlevel, const char* msg1, const char* msg2) {
if (mlevel > loglevel)
return;
char* strFilename = files->sendTop();
switch (mlevel) {
case LOGNONE:
case LOGINFO:
break;
case LOGFAIL:
if (uselog) {
if (files->getSize() == 0)
logfile << "Error on commandline - " << msg1 << sep << msg2 << endl;
else
logfile << "Error in file " << strFilename << " - " << msg1 << sep << msg2 << endl;
logfile.flush();
}
if (files->getSize() == 0)
cerr << "Error on commandline - " << msg1 << sep << msg2 << endl;
else
cerr << "Error in file " << strFilename << " - " << msg1 << sep << msg2 << endl;
delete[] strFilename;
exit(EXIT_FAILURE);
break;
case LOGWARN:
numwarn++;
if (uselog) {
if (files->getSize() == 0)
logfile << "Warning on commandline - " << msg1 << sep << msg2 << endl;
else
logfile << "Warning in file " << strFilename << " - " << msg1 << sep << msg2 << endl;
logfile.flush();
}
if (files->getSize() == 0)
cerr << "Warning on commandline - " << msg1 << sep << msg2 << endl;
else
cerr << "Warning in file " << strFilename << " - " << msg1 << sep << msg2 << endl;
break;
case LOGDEBUG:
case LOGMESSAGE:
case LOGDETAIL:
if (uselog) {
logfile << "Message in file " << strFilename << " - " << msg1 << sep << msg2 << endl;
logfile.flush();
}
break;
default:
cerr << "Error in errorhandler - invalid log level " << mlevel << endl;
break;
}
delete[] strFilename;
}
void ErrorHandler::logFileEOFMessage(LogLevel mlevel) {
if (mlevel > loglevel)
return;
char* strFilename = files->sendTop();
switch (mlevel) {
case LOGNONE:
case LOGINFO:
break;
case LOGFAIL:
if (uselog) {
logfile << "Unexpected end of file " << strFilename << endl;
logfile.flush();
}
cerr << "Unexpected end of file " << strFilename << endl;
delete[] strFilename;
exit(EXIT_FAILURE);
break;
case LOGWARN:
numwarn++;
if (uselog) {
logfile << "Unexpected end of file " << strFilename << endl;
logfile.flush();
}
cerr << "Unexpected end of file " << strFilename << endl;
break;
case LOGDEBUG:
case LOGMESSAGE:
case LOGDETAIL:
if (uselog) {
logfile << "Unexpected end of file " << strFilename << endl;
logfile.flush();
}
break;
default:
cerr << "Error in errorhandler - invalid log level " << mlevel << endl;
break;
}
delete[] strFilename;
}
void ErrorHandler::logFileUnexpected(LogLevel mlevel, const char* msg1, const char* msg2) {
if (mlevel > loglevel)
return;
char* strFilename = files->sendTop();
switch (mlevel) {
case LOGNONE:
case LOGINFO:
break;
case LOGFAIL:
if (uselog) {
logfile << "Error in file " << strFilename << endl
<< "Expected " << msg1 << " but found instead " << msg2 << endl;
logfile.flush();
}
cerr << "Error in file " << strFilename << endl
<< "Expected " << msg1 << " but found instead " << msg2 << endl;
delete[] strFilename;
exit(EXIT_FAILURE);
break;
case LOGWARN:
numwarn++;
if (uselog) {
logfile << "Warning in file " << strFilename << endl
<< "Expected " << msg1 << " but found instead " << msg2 << endl;
logfile.flush();
}
cerr << "Warning in file " << strFilename << endl
<< "Expected " << msg1 << " but found instead " << msg2 << endl;
break;
case LOGDEBUG:
case LOGMESSAGE:
case LOGDETAIL:
if (uselog) {
logfile << "Message in file " << strFilename << endl
<< "Expected " << msg1 << " but found instead " << msg2 << endl;
logfile.flush();
}
break;
default:
cerr << "Error in errorhandler - invalid log level " << mlevel << endl;
break;
}
delete[] strFilename;
}
void ErrorHandler::checkIfFailure(ios& infile, const char* text) {
if (infile.fail()) {
if ((uselog) && (loglevel >= LOGMESSAGE)) {
logfile << "Checking to see if file " << text << " can be opened ... failed" << endl;
logfile.flush();
}
this->logFileMessage(LOGFAIL, "failed to open datafile", text);
}
if ((uselog) && (loglevel >= LOGMESSAGE)) {
logfile << "Checking to see if file " << text << " can be opened ... OK" << endl;
logfile.flush();
}
}
void ErrorHandler::logFinish() {
if (numwarn > 0)
this->logMessage(LOGINFO, "\nTotal number of warnings was", numwarn);
if (uselog) {
if (runopt)
logfile << "\nGadget optimisation finished OK - runtime was ";
else
logfile << "\nGadget simulation finished OK - runtime was ";
logfile.flush();
#ifndef GADGET_NETWORK
RUNID.printTime(logfile);
#endif
logfile.close();
logfile.clear();
uselog = 0;
}
if (loglevel >= LOGINFO) {
if (runopt) {
cout << "\nGadget optimisation finished OK - runtime was ";
#ifndef GADGET_NETWORK
RUNID.printTime(cout);
#endif
} else
cout << "\nGadget simulation finished OK\n";
cout << endl;
}
}