Commit 4f25511e authored by Giovanni La Mura's avatar Giovanni La Mura
Browse files

Implement recursive message stacking management

parent 50e8c729
Loading
Loading
Loading
Loading
+23 −12
Original line number Diff line number Diff line
@@ -17,6 +17,10 @@
#include "../include/errors.h"
#endif

#ifndef INCLUDE_LOGGING_H_
#include "../include/logging.h"
#endif

#ifndef INCLUDE_CONFIGURATION_H_
#include "../include/Configuration.h"
#endif
@@ -50,13 +54,15 @@ using namespace std;
 *  \param output_path: `string` Directory to write the output files in.
 */
void cluster(string config_file, string data_file, string output_path) {
  printf("INFO: making legacy configuration...");
  Logger logger(LOG_INFO);
  logger.log("INFO: making legacy configuration...", LOG_INFO);
  ScattererConfiguration *sconf = NULL;
  try {
    sconf = ScattererConfiguration::from_dedfb(config_file);
  } catch(const OpenConfigurationFileException &ex) {
    printf("\nERROR: failed to open scatterer configuration file.\n");
    printf("FILE: %s\n", ex.what());
    logger.err("\nERROR: failed to open scatterer configuration file.\n");
    string message = "FILE: " + string(ex.what()) + "\n";
    logger.err(message);
    exit(1);
  }
  sconf->write_formatted(output_path + "/c_OEDFB");
@@ -66,12 +72,13 @@ void cluster(string config_file, string data_file, string output_path) {
  try {
    gconf = GeometryConfiguration::from_legacy(data_file);
  } catch (const OpenConfigurationFileException &ex) {
    printf("\nERROR: failed to open geometry configuration file.\n");
    printf("FILE: %s\n", ex.what());
    logger.err("\nERROR: failed to open geometry configuration file.\n");
    string message = "FILE: " + string(ex.what()) + "\n";
    logger.err(message);
    if (sconf) delete sconf;
    exit(1);
  }
  printf(" done.\n");
  logger.log(" done.\n", LOG_INFO);
  if (sconf->number_of_spheres == gconf->number_of_spheres) {
    // Shortcuts to variables stored in configuration objects
    int nsph = gconf->number_of_spheres;
@@ -279,9 +286,9 @@ void cluster(string config_file, string data_file, string output_path) {
    tppoan.open(tppoan_name.c_str(), ios::out | ios::binary);
    if (tppoan.is_open()) {
#ifdef USE_LAPACK
      printf("INFO: using LAPACK calls.\n");
      logger.log("INFO: using LAPACK calls.\n", LOG_INFO);
#else
      printf("INFO: using fall-back lucin() calls.\n");
      logger.log("INFO: using fall-back lucin() calls.\n", LOG_INFO);
#endif
      tppoan.write(reinterpret_cast<char *>(&iavm), sizeof(int));
      tppoan.write(reinterpret_cast<char *>(&isam), sizeof(int));
@@ -299,7 +306,9 @@ void cluster(string config_file, string data_file, string output_path) {
	fprintf(output, " \n");
      }
      for (int jxi488 = 1; jxi488 <= nxi; jxi488++) {
	printf("INFO: running scale iteration %d of %d...", jxi488, nxi);
	string message = ("INFO: running scale iteration " + to_string(jxi488)
			  + " of " + to_string(nxi) + "...");
	logger.log(message, LOG_INFO);
	int jaw = 1;
	fprintf(output, "========== JXI =%3d ====================\n", jxi488);
	double xi = sconf->scale_vec[jxi488 - 1];
@@ -349,6 +358,7 @@ void cluster(string config_file, string data_file, string output_path) {
	  }
	  if (jer != 0) break;
	} // i132 loop
	logger.push("DEBUG: " + TOSTRING(cms(am, c1, c1ao, c4, c6);));
	cms(am, c1, c1ao, c4, c6);
	invert_matrix(am, ndit, jer, mxndm);
	if (jer != 0) break; // jxi488 loop: goes to memory clean
@@ -904,11 +914,11 @@ void cluster(string config_file, string data_file, string output_path) {
	  } // jph484 loop
	  th += thstp;
	} // jth486 loop
	printf(" done.\n");
	logger.log(" done.\n", LOG_INFO);
      } // jxi488 loop
      tppoan.close();
    } else { // In case TPPOAN could not be opened. Should never happen.
      printf("\nERROR: failed to open TPPOAN file.\n");
      logger.err("\nERROR: failed to open TPPOAN file.\n");
    }
    fclose(output);
    // Clean memory
@@ -992,5 +1002,6 @@ void cluster(string config_file, string data_file, string output_path) {
  }
  delete sconf;
  delete gconf;
  printf("Finished: output written to %s.\n", (output_path + "/c_OCLU").c_str());
  logger.flush(LOG_INFO);
  logger.log("Finished: output written to " + output_path + "/c_OCLU\n");
}
+33 −1
Original line number Diff line number Diff line
@@ -7,11 +7,18 @@
#ifndef INCLUDE_LOGGING_H_
#define INCLUDE_LOGGING_H_

//! \brief Debug level logging (maximum verbosity).
#define LOG_DEBG 0
//! \brief Standard information level logging (default).
#define LOG_INFO 1
//! \brief Warning level logging (almost quiet).
#define LOG_WARN 2
//! \brief Error level logging (silent, unless in pain).
#define LOG_ERRO 3

//! \brief Macro to stringize code lines
#define TOSTRING(ARG) string(#ARG)

/*! \brief Logger class.
 *
 * Loggers are objects used to track the execution of a code, reporting activities
@@ -23,9 +30,16 @@
 */
class Logger {
 protected:
  FILE *log_output;
  //! \brief Pointer to error stream.
  FILE *err_output;
  //! \brief Pointer to logging stream.
  FILE *log_output;
  //! \brief Last logged message.
  std::string last_message;
  //! \brief Threshold of logging level.
  int log_threshold;
  //! \brief Number of identical message repetitions.
  long repetitions;

 public:
  /*! \brief Logger instance constructor.
@@ -47,12 +61,30 @@ class Logger {
   */
  void err(std::string message);

  /*! \brief Print a summary of recurrent messages and clear the stack.
   *
   * \param level: `int` The priority level (default is `LOG_DEBG = 0`).
   */
  void flush(int level=LOG_DEBG);

  /*! \brief Print a message, depending on its logging level.
   *
   * \param message: `string` The message to be printed.
   * \param level: `int` The priority level (default is `LOG_INFO = 1`).
   */
  void log(std::string message, int level=LOG_INFO);
  
  /*! \brief Push a recurrent message to the message stack.
   *
   * When a long stream of identical messages is expected, it may be more
   * convenient to put them in a stack. The stack is the error output stream,
   * so that no memory is consumed. After the call stack is over, or is the
   * message changes, the stack is flushed, meaning that a summary message
   * is written to the logging output and the stack counter is reset to 0.
   *
   * \param message: `string` The message to be stacked.
   */
  void push(std::string message);
};

#endif
+26 −2
Original line number Diff line number Diff line
@@ -14,18 +14,42 @@
using namespace std;

Logger::Logger(int threshold, FILE *logging_output, FILE *error_output) {
  last_message = "";
  log_threshold = threshold;
  log_output = logging_output;
  err_output = error_output;
  repetitions = 0;
}

void Logger::err(std::string message) {
  fprintf(err_output, "%s\n", message.c_str());
  fprintf(err_output, "%s", message.c_str());
}

void Logger::flush(int level) {
  string summary = "\"" + last_message + "\" issued " + to_string(repetitions);
  if (repetitions == 1) summary += " time.\n";
  else summary += " times.\n";
  if (level == LOG_ERRO) err(summary);
  else {
    if (level >= log_threshold) fprintf(log_output, "%s", summary.c_str());
  }
  repetitions = 0;
}

void Logger::log(std::string message, int level) {
  if (level == LOG_ERRO) err(message);
  else {
    if (level >= log_threshold) fprintf(log_output, "%s\n", message.c_str());
    if (level >= log_threshold) fprintf(log_output, "%s", message.c_str());
  }
}

void Logger::push(std::string message) {
  if (repetitions > 0) {
    if (message.compare(last_message) != 0) {
      flush(LOG_DEBG);
    }
  }
  log(message, LOG_DEBG);
  last_message = message;
  repetitions++;
}