<commit_before>// //////////////////////////////////////////////////////////////////////
// Import section
// //////////////////////////////////////////////////////////////////////
// STL
#include <cassert>
#include <sstream>
#include <fstream>
#include <vector>
#include <list>
#include <string>
//  //// Boost (Extended STL) ////
// Boost Tokeniser
#include <boost/tokenizer.hpp>
// Boost Program Options
#include <boost/program_options.hpp>
// Boost Accumulators
#include <boost/accumulators/accumulators.hpp>
#include <boost/accumulators/statistics.hpp>
// Boost Progress
//#include <boost/progress.hpp>
// StdAir
#include <stdair/stdair_basic_types.hpp>
#include <stdair/basic/ProgressStatusSet.hpp>
#include <stdair/bom/EventStruct.hpp>
#include <stdair/bom/EventQueue.hpp>
#include <stdair/bom/BookingRequestStruct.hpp>
#include <stdair/bom/BomDisplay.hpp>
#include <stdair/service/Logger.hpp>
// TraDemGen
#include <trademgen/TRADEMGEN_Service.hpp>
#include <trademgen/config/trademgen-paths.hpp>
#include <trademgen/config/trademgen-paths.hpp>

// Aliases for namespaces
namespace ba = boost::accumulators;

// //////// Specific type definitions ///////
typedef unsigned int NbOfRuns_T;

/** Type definition to gather statistics. */
typedef ba::accumulator_set<double,
                            ba::stats<ba::tag::min, ba::tag::max,
                                      ba::tag::mean (ba::immediate),
                                      ba::tag::sum,
                                      ba::tag::variance> > stat_acc_type;

// //////// Constants //////
/** Default name and location for the log file. */
const stdair::Filename_T K_TRADEMGEN_DEFAULT_LOG_FILENAME ("trademgen.log");

/** Default name and location for the (CSV) input file. */
const stdair::Filename_T K_TRADEMGEN_DEFAULT_INPUT_FILENAME (STDAIR_SAMPLE_DIR
                                                             "/demand01.csv");

/** Default name and location for the (CSV) output file. */
const stdair::Filename_T K_TRADEMGEN_DEFAULT_OUTPUT_FILENAME ("request.csv");

/** Default number of random draws to be generated (best if over 100). */
const NbOfRuns_T K_TRADEMGEN_DEFAULT_RANDOM_DRAWS = 1;

/** Default for the input type. It can be either built-in or provided by an
    input file. That latter must then be given with the -i option. */
const bool K_TRADEMGEN_DEFAULT_BUILT_IN_INPUT = false;

/** Early return status (so that it can be differentiated from an error). */
const int K_TRADEMGEN_EARLY_RETURN_STATUS = 99;

/** Display the statistics held by the dedicated accumulator. */
void stat_display (std::ostream& oStream, const stat_acc_type& iStatAcc) {

  // Store current formatting flags of the output stream
  std::ios::fmtflags oldFlags = oStream.flags();

  //
  oStream.setf (std::ios::fixed);

  //
  oStream << "Statistics for the demand generation runs: " << std::endl;
  oStream << "  minimum   = " << ba::min (iStatAcc) << std::endl;
  oStream << "  mean      = " << ba::mean (iStatAcc) << std::endl;
  oStream << "  maximum   = " << ba::max (iStatAcc) << std::endl;
  oStream << "  count     = " << ba::count (iStatAcc) << std::endl;
  oStream << "  variance  = " << ba::variance (iStatAcc) << std::endl;

  // Reset formatting flags of output stream
  oStream.flags (oldFlags);
}

// ///////// Parsing of Options & Configuration /////////
// A helper function to simplify the main part.
template<class T> std::ostream& operator<< (std::ostream& os,
                                            const std::vector<T>& v) {
  std::copy (v.begin(), v.end(), std::ostream_iterator<T> (std::cout, " "));
  return os;
}

/** Read and parse the command line options. */
int readConfiguration (int argc, char* argv[], bool& ioIsBuiltin,
                       NbOfRuns_T& ioRandomRuns,
                       stdair::Filename_T& ioInputFilename,
                       stdair::Filename_T& ioOutputFilename,
                       stdair::Filename_T& ioLogFilename) {

  // Default for the built-in input
  ioIsBuiltin = K_TRADEMGEN_DEFAULT_BUILT_IN_INPUT;

  // Declare a group of options that will be allowed only on command line
  boost::program_options::options_description generic ("Generic options");
  generic.add_options()
    ("prefix", "print installation prefix")
    ("version,v", "print version string")
    ("help,h", "produce help message");

  // Declare a group of options that will be allowed both on command
  // line and in config file
  boost::program_options::options_description config ("Configuration");
  config.add_options()
    ("builtin,b",
     "The sample BOM tree can be either built-in or parsed from an input file. That latter must then be given with the -i/--input option")
    ("draws,d",
     boost::program_options::value<NbOfRuns_T>(&ioRandomRuns)->default_value(K_TRADEMGEN_DEFAULT_RANDOM_DRAWS),
     "Number of runs for the demand generations")
    ("input,i",
     boost::program_options::value< std::string >(&ioInputFilename)->default_value(K_TRADEMGEN_DEFAULT_INPUT_FILENAME),
     "(CVS) input file for the demand distributions")
    ("output,o",
     boost::program_options::value< std::string >(&ioOutputFilename)->default_value(K_TRADEMGEN_DEFAULT_OUTPUT_FILENAME),
     "(CVS) output file for the generated requests")
    ("log,l",
     boost::program_options::value< std::string >(&ioLogFilename)->default_value(K_TRADEMGEN_DEFAULT_LOG_FILENAME),
     "Filepath for the logs")
    ;

  // Hidden options, will be allowed both on command line and
  // in config file, but will not be shown to the user.
  boost::program_options::options_description hidden ("Hidden options");
  hidden.add_options()
    ("copyright",
     boost::program_options::value< std::vector<std::string> >(),
     "Show the copyright (license)");

  boost::program_options::options_description cmdline_options;
  cmdline_options.add(generic).add(config).add(hidden);

  boost::program_options::options_description config_file_options;
  config_file_options.add(config).add(hidden);

  boost::program_options::options_description visible ("Allowed options");
  visible.add(generic).add(config);

  boost::program_options::positional_options_description p;
  p.add ("copyright", -1);

  boost::program_options::variables_map vm;
  boost::program_options::
    store (boost::program_options::command_line_parser (argc, argv).
           options (cmdline_options).positional(p).run(), vm);

  std::ifstream ifs ("trademgen.cfg");
  boost::program_options::store (parse_config_file (ifs, config_file_options),
                                 vm);
  boost::program_options::notify (vm);

  if (vm.count ("help")) {
    std::cout << visible << std::endl;
    return K_TRADEMGEN_EARLY_RETURN_STATUS;
  }

  if (vm.count ("version")) {
    std::cout << PACKAGE_NAME << ", version " << PACKAGE_VERSION << std::endl;
    return K_TRADEMGEN_EARLY_RETURN_STATUS;
  }

  if (vm.count ("prefix")) {
    std::cout << "Installation prefix: " << PREFIXDIR << std::endl;
    return K_TRADEMGEN_EARLY_RETURN_STATUS;
  }

  if (vm.count ("builtin")) {
    ioIsBuiltin = true;
  }
  const std::string isBuiltinStr = (ioIsBuiltin == true)?"yes":"no";
  std::cout << "The BOM should be built-in? " << isBuiltinStr << std::endl;

  if (ioIsBuiltin == false) {

    // The BOM tree should be built from parsing a demand input file
    if (vm.count ("input")) {
      ioInputFilename = vm["input"].as< std::string >();
      std::cout << "Input filename is: " << ioInputFilename << std::endl;

    } else {
      // The built-in option is not selected. However, no demand input file
      // is specified
      std::cerr << "Either one among the -b/--builtin and -i/--input "
                << "options must be specified" << std::endl;
    }
  }

  if (vm.count ("output")) {
    ioOutputFilename = vm["output"].as< std::string >();
    std::cout << "Output filename is: " << ioOutputFilename << std::endl;
  }

  if (vm.count ("log")) {
    ioLogFilename = vm["log"].as< std::string >();
    std::cout << "Log filename is: " << ioLogFilename << std::endl;
  }

  //
  std::cout << "The number of runs is: " << ioRandomRuns << std::endl;

  return 0;
}

// /////////////////////////////////////////////////////////////////////////
void generateDemand (TRADEMGEN::TRADEMGEN_Service& ioTrademgenService,
                     const stdair::Filename_T& iOutputFilename,
                     const NbOfRuns_T& iNbOfRuns) {

  // Open and clean the .csv output file
  std::ofstream output;
  output.open (iOutputFilename.c_str());
  output.clear();

  // Initialise the statistics collector/accumulator
  stat_acc_type lStatAccumulator;

  // Retrieve the expected (mean value of the) number of events to be
  // generated
  const stdair::Count_T& lExpectedNbOfEventsToBeGenerated =
    ioTrademgenService.getExpectedTotalNumberOfRequestsToBeGenerated();

  // Initialise the (Boost) progress display object
  boost::progress_display lProgressDisplay (lExpectedNbOfEventsToBeGenerated
                                            * iNbOfRuns);

  // Choose the algorithm to generate booking requests dates.
  const bool lGenerateDemandWithStatisticOrder = false;

  for (NbOfRuns_T runIdx = 1; runIdx <= iNbOfRuns; ++runIdx) {
    // /////////////////////////////////////////////////////
    output << "Run number: " << runIdx << std::endl;

    /**
       Initialisation step.

Generate the first event for each demand stream.
    */
    const stdair::Count_T& lActualNbOfEventsToBeGenerated =
      ioTrademgenService.generateFirstRequests(lGenerateDemandWithStatisticOrder);

    // DEBUG
    STDAIR_LOG_DEBUG ("[" << runIdx << "] Expected: "
                      << lExpectedNbOfEventsToBeGenerated << ", actual: "
                      << lActualNbOfEventsToBeGenerated);

    /**
       Main loop.

Pop a request and get its associated type/demand stream.

Generate the next request for the same type/demand stream.

    */
    while (ioTrademgenService.isQueueDone() == false) {

      // Extract the next event from the event queue
      stdair::EventStruct lEventStruct;
      stdair::ProgressStatusSet lProgressStatusSet =
        ioTrademgenService.popEvent (lEventStruct);

      // DEBUG
      // STDAIR_LOG_DEBUG ("[" << runIdx << "] Poped event: '"
      //                   << lEventStruct.describe() << "'.");

      // Extract the corresponding demand/booking request
      const stdair::BookingRequestStruct& lPoppedRequest =
        lEventStruct.getBookingRequest();

      // DEBUG
      STDAIR_LOG_DEBUG ("[" << runIdx << "] Poped booking request: '"
                        << lPoppedRequest.describe() << "'.");

      // Dump the request into the dedicated CSV file
      // stdair::BomDisplay::csvDisplay (output, lPoppedRequest);

      // Retrieve the corresponding demand stream key
      const stdair::DemandGeneratorKey_T& lDemandStreamKey =
        lPoppedRequest.getDemandGeneratorKey();

      // Assess whether more events should be generated for that demand stream
      const bool stillHavingRequestsToBeGenerated = ioTrademgenService.
        stillHavingRequestsToBeGenerated (lDemandStreamKey,
                                          lProgressStatusSet,
                                          lGenerateDemandWithStatisticOrder);

      // DEBUG
      STDAIR_LOG_DEBUG (lProgressStatusSet.describe());
      STDAIR_LOG_DEBUG ("=> [" << lDemandStreamKey << "] is now processed. "
                        << "Still generate events for that demand stream? "
                        << stillHavingRequestsToBeGenerated);

      // If there are still events to be generated for that demand stream,
      // generate and add them to the event queue
      if (stillHavingRequestsToBeGenerated == true) {

        stdair::BookingRequestPtr_T lNextRequest_ptr =
          ioTrademgenService.generateNextRequest (lDemandStreamKey,
                                                  lGenerateDemandWithStatisticOrder);
        assert (lNextRequest_ptr != NULL);

        // Sanity check
        const stdair::Duration_T lDuration =
          lNextRequest_ptr->getRequestDateTime()
          - lPoppedRequest.getRequestDateTime();
        if (lDuration.total_milliseconds() < 0) {
          STDAIR_LOG_ERROR ("[" << lDemandStreamKey
                            << "] The date-time of the generated event ("
                            << lNextRequest_ptr->getRequestDateTime()
                            << ") is lower than the date-time "
                            << "of the current event ("
                            << lPoppedRequest.getRequestDateTime() << ")");
          assert (false);
        }

        // DEBUG
        STDAIR_LOG_DEBUG ("[" << lDemandStreamKey << "] Added request: '"
                          << lNextRequest_ptr->describe()
                          << "'. Is queue done? "
                          << ioTrademgenService.isQueueDone());
      }
      // DEBUG
      STDAIR_LOG_DEBUG ("");

      // Update the progress display
      ++lProgressDisplay;
    }

    // Add the number of events to the statistics accumulator
    lStatAccumulator (lActualNbOfEventsToBeGenerated);

    // Reset the service (including the event queue) for the next run
    ioTrademgenService.reset();
  }

  // DEBUG
  STDAIR_LOG_DEBUG ("End of the simulation. Let us see some statistics for the "
                    << iNbOfRuns << " runs.");
  std::ostringstream oStatStr;
  stat_display (oStatStr, lStatAccumulator);
  STDAIR_LOG_DEBUG (oStatStr.str());

  // DEBUG
  const std::string& lBOMStr = ioTrademgenService.csvDisplay();
  STDAIR_LOG_DEBUG (lBOMStr);

  // Close the output file
  output.close();
}

// /////////////// M A I N /////////////////
int main (int argc, char* argv[]) {

  // State whether the BOM tree should be built-in or parsed from an input file
  bool isBuiltin;

  // Number of random draws to be generated (best if greater than 100)
  NbOfRuns_T lNbOfRuns;

  // Input file name
  stdair::Filename_T lInputFilename;

  // Output file name
  stdair::Filename_T lOutputFilename;

  // Output log File
  stdair::Filename_T lLogFilename;

  // Call the command-line option parser
  const int lOptionParserStatus =
    readConfiguration (argc, argv, isBuiltin, lNbOfRuns, lInputFilename,
                       lOutputFilename, lLogFilename);

  if (lOptionParserStatus == K_TRADEMGEN_EARLY_RETURN_STATUS) {
    return 0;
  }

  // Set the log parameters
  std::ofstream logOutputFile;
  // Open and clean the log outputfile
  logOutputFile.open (lLogFilename.c_str());
  logOutputFile.clear();

  // Set up the log parameters
  const stdair::BasLogParams lLogParams (stdair::LOG::DEBUG, logOutputFile);

  // Initialise the TraDemGen service object
  TRADEMGEN::TRADEMGEN_Service trademgenService (lLogParams);

  // Check wether or not a (CSV) input file should be read
  if (isBuiltin == true) {
    // Create a sample DemandStream object, and insert it within the BOM tree
    trademgenService.buildSampleBom();

  } else {
    // Create the DemandStream objects, and insert them within the BOM tree
    trademgenService.parseAndLoad (lInputFilename);
  }

  // Calculate the expected number of events to be generated.
  generateDemand (trademgenService, lOutputFilename, lNbOfRuns);

  // Close the Log outputFile
  logOutputFile.close();

  /*
    \note: as that program is not intended to be run on a server in
    production, it is better not to catch the exceptions. When it
    happens (that an exception is throwned), that way we get the
    call stack.
  */

  return 0;
}
<commit_msg>[TraDemGen] [dev] Updated the batch to the new trademgen API (the date time request generation method is no longer determined thanks to a boolean).<commit_after>// //////////////////////////////////////////////////////////////////////
// Import section
// //////////////////////////////////////////////////////////////////////
// STL
#include <cassert>
#include <sstream>
#include <fstream>
#include <vector>
#include <list>
#include <string>
//  //// Boost (Extended STL) ////
// Boost Tokeniser
#include <boost/tokenizer.hpp>
// Boost Program Options
#include <boost/program_options.hpp>
// Boost Accumulators
#include <boost/accumulators/accumulators.hpp>
#include <boost/accumulators/statistics.hpp>
// Boost Progress
//#include <boost/progress.hpp>
// StdAir
#include <stdair/stdair_basic_types.hpp>
#include <stdair/basic/ProgressStatusSet.hpp>
#include <stdair/basic/DateGenerationMethod.hpp>
#include <stdair/bom/EventStruct.hpp>
#include <stdair/bom/EventQueue.hpp>
#include <stdair/bom/BookingRequestStruct.hpp>
#include <stdair/bom/BomDisplay.hpp>
#include <stdair/service/Logger.hpp>
// TraDemGen
#include <trademgen/TRADEMGEN_Service.hpp>
#include <trademgen/config/trademgen-paths.hpp>
#include <trademgen/config/trademgen-paths.hpp>

// Aliases for namespaces
namespace ba = boost::accumulators;

// //////// Specific type definitions ///////
typedef unsigned int NbOfRuns_T;

/** Type definition to gather statistics. */
typedef ba::accumulator_set<double,
                            ba::stats<ba::tag::min, ba::tag::max,
                                      ba::tag::mean (ba::immediate),
                                      ba::tag::sum,
                                      ba::tag::variance> > stat_acc_type;

// //////// Constants //////
/** Default name and location for the log file. */
const stdair::Filename_T K_TRADEMGEN_DEFAULT_LOG_FILENAME ("trademgen.log");

/** Default name and location for the (CSV) input file. */
const stdair::Filename_T K_TRADEMGEN_DEFAULT_INPUT_FILENAME (STDAIR_SAMPLE_DIR
                                                             "/demand01.csv");

/** Default name and location for the (CSV) output file. */
const stdair::Filename_T K_TRADEMGEN_DEFAULT_OUTPUT_FILENAME ("request.csv");

/** Default number of random draws to be generated (best if over 100). */
const NbOfRuns_T K_TRADEMGEN_DEFAULT_RANDOM_DRAWS = 1;

/** Default for the input type. It can be either built-in or provided by an
    input file. That latter must then be given with the -i option. */
const bool K_TRADEMGEN_DEFAULT_BUILT_IN_INPUT = false;

/** Early return status (so that it can be differentiated from an error). */
const int K_TRADEMGEN_EARLY_RETURN_STATUS = 99;

/** Display the statistics held by the dedicated accumulator. */
void stat_display (std::ostream& oStream, const stat_acc_type& iStatAcc) {

  // Store current formatting flags of the output stream
  std::ios::fmtflags oldFlags = oStream.flags();

  //
  oStream.setf (std::ios::fixed);

  //
  oStream << "Statistics for the demand generation runs: " << std::endl;
  oStream << "  minimum   = " << ba::min (iStatAcc) << std::endl;
  oStream << "  mean      = " << ba::mean (iStatAcc) << std::endl;
  oStream << "  maximum   = " << ba::max (iStatAcc) << std::endl;
  oStream << "  count     = " << ba::count (iStatAcc) << std::endl;
  oStream << "  variance  = " << ba::variance (iStatAcc) << std::endl;

  // Reset formatting flags of output stream
  oStream.flags (oldFlags);
}

// ///////// Parsing of Options & Configuration /////////
// A helper function to simplify the main part.
template<class T> std::ostream& operator<< (std::ostream& os,
                                            const std::vector<T>& v) {
  std::copy (v.begin(), v.end(), std::ostream_iterator<T> (std::cout, " "));
  return os;
}

/** Read and parse the command line options. */
int readConfiguration (int argc, char* argv[], bool& ioIsBuiltin,
                       NbOfRuns_T& ioRandomRuns,
                       stdair::Filename_T& ioInputFilename,
                       stdair::Filename_T& ioOutputFilename,
                       stdair::Filename_T& ioLogFilename) {

  // Default for the built-in input
  ioIsBuiltin = K_TRADEMGEN_DEFAULT_BUILT_IN_INPUT;

  // Declare a group of options that will be allowed only on command line
  boost::program_options::options_description generic ("Generic options");
  generic.add_options()
    ("prefix", "print installation prefix")
    ("version,v", "print version string")
    ("help,h", "produce help message");

  // Declare a group of options that will be allowed both on command
  // line and in config file
  boost::program_options::options_description config ("Configuration");
  config.add_options()
    ("builtin,b",
     "The sample BOM tree can be either built-in or parsed from an input file. That latter must then be given with the -i/--input option")
    ("draws,d",
     boost::program_options::value<NbOfRuns_T>(&ioRandomRuns)->default_value(K_TRADEMGEN_DEFAULT_RANDOM_DRAWS),
     "Number of runs for the demand generations")
    ("input,i",
     boost::program_options::value< std::string >(&ioInputFilename)->default_value(K_TRADEMGEN_DEFAULT_INPUT_FILENAME),
     "(CVS) input file for the demand distributions")
    ("output,o",
     boost::program_options::value< std::string >(&ioOutputFilename)->default_value(K_TRADEMGEN_DEFAULT_OUTPUT_FILENAME),
     "(CVS) output file for the generated requests")
    ("log,l",
     boost::program_options::value< std::string >(&ioLogFilename)->default_value(K_TRADEMGEN_DEFAULT_LOG_FILENAME),
     "Filepath for the logs")
    ;

  // Hidden options, will be allowed both on command line and
  // in config file, but will not be shown to the user.
  boost::program_options::options_description hidden ("Hidden options");
  hidden.add_options()
    ("copyright",
     boost::program_options::value< std::vector<std::string> >(),
     "Show the copyright (license)");

  boost::program_options::options_description cmdline_options;
  cmdline_options.add(generic).add(config).add(hidden);

  boost::program_options::options_description config_file_options;
  config_file_options.add(config).add(hidden);

  boost::program_options::options_description visible ("Allowed options");
  visible.add(generic).add(config);

  boost::program_options::positional_options_description p;
  p.add ("copyright", -1);

  boost::program_options::variables_map vm;
  boost::program_options::
    store (boost::program_options::command_line_parser (argc, argv).
           options (cmdline_options).positional(p).run(), vm);

  std::ifstream ifs ("trademgen.cfg");
  boost::program_options::store (parse_config_file (ifs, config_file_options),
                                 vm);
  boost::program_options::notify (vm);

  if (vm.count ("help")) {
    std::cout << visible << std::endl;
    return K_TRADEMGEN_EARLY_RETURN_STATUS;
  }

  if (vm.count ("version")) {
    std::cout << PACKAGE_NAME << ", version " << PACKAGE_VERSION << std::endl;
    return K_TRADEMGEN_EARLY_RETURN_STATUS;
  }

  if (vm.count ("prefix")) {
    std::cout << "Installation prefix: " << PREFIXDIR << std::endl;
    return K_TRADEMGEN_EARLY_RETURN_STATUS;
  }

  if (vm.count ("builtin")) {
    ioIsBuiltin = true;
  }
  const std::string isBuiltinStr = (ioIsBuiltin == true)?"yes":"no";
  std::cout << "The BOM should be built-in? " << isBuiltinStr << std::endl;

  if (ioIsBuiltin == false) {

    // The BOM tree should be built from parsing a demand input file
    if (vm.count ("input")) {
      ioInputFilename = vm["input"].as< std::string >();
      std::cout << "Input filename is: " << ioInputFilename << std::endl;

    } else {
      // The built-in option is not selected. However, no demand input file
      // is specified
      std::cerr << "Either one among the -b/--builtin and -i/--input "
                << "options must be specified" << std::endl;
    }
  }

  if (vm.count ("output")) {
    ioOutputFilename = vm["output"].as< std::string >();
    std::cout << "Output filename is: " << ioOutputFilename << std::endl;
  }

  if (vm.count ("log")) {
    ioLogFilename = vm["log"].as< std::string >();
    std::cout << "Log filename is: " << ioLogFilename << std::endl;
  }

  //
  std::cout << "The number of runs is: " << ioRandomRuns << std::endl;

  return 0;
}

// /////////////////////////////////////////////////////////////////////////
void generateDemand (TRADEMGEN::TRADEMGEN_Service& ioTrademgenService,
                     const stdair::Filename_T& iOutputFilename,
                     const NbOfRuns_T& iNbOfRuns) {

  // Open and clean the .csv output file
  std::ofstream output;
  output.open (iOutputFilename.c_str());
  output.clear();

  // Initialise the statistics collector/accumulator
  stat_acc_type lStatAccumulator;

  // Retrieve the expected (mean value of the) number of events to be
  // generated
  const stdair::Count_T& lExpectedNbOfEventsToBeGenerated =
    ioTrademgenService.getExpectedTotalNumberOfRequestsToBeGenerated();

  // Initialise the (Boost) progress display object
  boost::progress_display lProgressDisplay (lExpectedNbOfEventsToBeGenerated
                                            * iNbOfRuns);

  // Choose the algorithm to generate booking requests dates.
  stdair::DateGenerationMethod lDateGenerationMethod ('P');
  stdair::DateGenerationMethod::EN_DateGenerationMethod lENDateGenerationMethod =
    lDateGenerationMethod.getMethod();

  for (NbOfRuns_T runIdx = 1; runIdx <= iNbOfRuns; ++runIdx) {
    // /////////////////////////////////////////////////////
    output << "Run number: " << runIdx << std::endl;

    /**
       Initialisation step.

Generate the first event for each demand stream.
    */
    const stdair::Count_T& lActualNbOfEventsToBeGenerated =
      ioTrademgenService.generateFirstRequests(lENDateGenerationMethod);

    // DEBUG
    STDAIR_LOG_DEBUG ("[" << runIdx << "] Expected: "
                      << lExpectedNbOfEventsToBeGenerated << ", actual: "
                      << lActualNbOfEventsToBeGenerated);

    /**
       Main loop.

Pop a request and get its associated type/demand stream.

Generate the next request for the same type/demand stream.

    */
    while (ioTrademgenService.isQueueDone() == false) {

      // Extract the next event from the event queue
      stdair::EventStruct lEventStruct;
      stdair::ProgressStatusSet lProgressStatusSet =
        ioTrademgenService.popEvent (lEventStruct);

      // DEBUG
      // STDAIR_LOG_DEBUG ("[" << runIdx << "] Poped event: '"
      //                   << lEventStruct.describe() << "'.");

      // Extract the corresponding demand/booking request
      const stdair::BookingRequestStruct& lPoppedRequest =
        lEventStruct.getBookingRequest();

      // DEBUG
      STDAIR_LOG_DEBUG ("[" << runIdx << "] Poped booking request: '"
                        << lPoppedRequest.describe() << "'.");

      // Dump the request into the dedicated CSV file
      // stdair::BomDisplay::csvDisplay (output, lPoppedRequest);

      // Retrieve the corresponding demand stream key
      const stdair::DemandGeneratorKey_T& lDemandStreamKey =
        lPoppedRequest.getDemandGeneratorKey();

      // Assess whether more events should be generated for that demand stream
      const bool stillHavingRequestsToBeGenerated = ioTrademgenService.
        stillHavingRequestsToBeGenerated (lDemandStreamKey,
                                          lProgressStatusSet,
                                          lENDateGenerationMethod);

      // DEBUG
      STDAIR_LOG_DEBUG (lProgressStatusSet.describe());
      STDAIR_LOG_DEBUG ("=> [" << lDemandStreamKey << "] is now processed. "
                        << "Still generate events for that demand stream? "
                        << stillHavingRequestsToBeGenerated);

      // If there are still events to be generated for that demand stream,
      // generate and add them to the event queue
      if (stillHavingRequestsToBeGenerated == true) {

        stdair::BookingRequestPtr_T lNextRequest_ptr =
          ioTrademgenService.generateNextRequest (lDemandStreamKey,
                                                  lENDateGenerationMethod);

        assert (lNextRequest_ptr != NULL);

        // Sanity check
        const stdair::Duration_T lDuration =
          lNextRequest_ptr->getRequestDateTime()
          - lPoppedRequest.getRequestDateTime();
        if (lDuration.total_milliseconds() < 0) {
          STDAIR_LOG_ERROR ("[" << lDemandStreamKey
                            << "] The date-time of the generated event ("
                            << lNextRequest_ptr->getRequestDateTime()
                            << ") is lower than the date-time "
                            << "of the current event ("
                            << lPoppedRequest.getRequestDateTime() << ")");
          assert (false);
        }

        // DEBUG
        STDAIR_LOG_DEBUG ("[" << lDemandStreamKey << "] Added request: '"
                          << lNextRequest_ptr->describe()
                          << "'. Is queue done? "
                          << ioTrademgenService.isQueueDone());
      }
      // DEBUG
      STDAIR_LOG_DEBUG ("");

      // Update the progress display
      ++lProgressDisplay;
    }

    // Add the number of events to the statistics accumulator
    lStatAccumulator (lActualNbOfEventsToBeGenerated);

    // Reset the service (including the event queue) for the next run
    ioTrademgenService.reset();
  }

  // DEBUG
  STDAIR_LOG_DEBUG ("End of the simulation. Let us see some statistics for the "
                    << iNbOfRuns << " runs.");
  std::ostringstream oStatStr;
  stat_display (oStatStr, lStatAccumulator);
  STDAIR_LOG_DEBUG (oStatStr.str());

  // DEBUG
  const std::string& lBOMStr = ioTrademgenService.csvDisplay();
  STDAIR_LOG_DEBUG (lBOMStr);

  // Close the output file
  output.close();
}

// /////////////// M A I N /////////////////
int main (int argc, char* argv[]) {

  // State whether the BOM tree should be built-in or parsed from an input file
  bool isBuiltin;

  // Number of random draws to be generated (best if greater than 100)
  NbOfRuns_T lNbOfRuns;

  // Input file name
  stdair::Filename_T lInputFilename;

  // Output file name
  stdair::Filename_T lOutputFilename;

  // Output log File
  stdair::Filename_T lLogFilename;

  // Call the command-line option parser
  const int lOptionParserStatus =
    readConfiguration (argc, argv, isBuiltin, lNbOfRuns, lInputFilename,
                       lOutputFilename, lLogFilename);

  if (lOptionParserStatus == K_TRADEMGEN_EARLY_RETURN_STATUS) {
    return 0;
  }

  // Set the log parameters
  std::ofstream logOutputFile;
  // Open and clean the log outputfile
  logOutputFile.open (lLogFilename.c_str());
  logOutputFile.clear();

  // Set up the log parameters
  const stdair::BasLogParams lLogParams (stdair::LOG::DEBUG, logOutputFile);

  // Initialise the TraDemGen service object
  TRADEMGEN::TRADEMGEN_Service trademgenService (lLogParams);

  // Check wether or not a (CSV) input file should be read
  if (isBuiltin == true) {
    // Create a sample DemandStream object, and insert it within the BOM tree
    trademgenService.buildSampleBom();

  } else {
    // Create the DemandStream objects, and insert them within the BOM tree
    trademgenService.parseAndLoad (lInputFilename);
  }

  // Calculate the expected number of events to be generated.
  generateDemand (trademgenService, lOutputFilename, lNbOfRuns);

  // Close the Log outputFile
  logOutputFile.close();

  /*
    \note: as that program is not intended to be run on a server in
    production, it is better not to catch the exceptions. When it
    happens (that an exception is throwned), that way we get the
    call stack.
  */

  return 0;
}
<|endoftext|>


<commit_before>/*
 * The Apache Software License, Version 1.1
 *
 *
 * Copyright (c) 1999 The Apache Software Foundation.  All rights
 * reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 *
 * 3. The end-user documentation included with the redistribution,
 *    if any, must include the following acknowledgment:
 *       "This product includes software developed by the
 *        Apache Software Foundation (http://www.apache.org/)."
 *    Alternately, this acknowledgment may appear in the software itself,
 *    if and wherever such third-party acknowledgments normally appear.
 *
 * 4. The names "Xalan" and "Apache Software Foundation" must
 *    not be used to endorse or promote products derived from this
 *    software without prior written permission. For written
 *    permission, please contact apache@apache.org.
 *
 * 5. Products derived from this software may not be called "Apache",
 *    nor may "Apache" appear in their name, without prior written
 *    permission of the Apache Software Foundation.
 *
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 * ====================================================================
 *
 * This software consists of voluntary contributions made by many
 * individuals on behalf of the Apache Software Foundation and was
 * originally based on software copyright (c) 1999, International
 * Business Machines, Inc., http://www.ibm.com.  For more
 * information on the Apache Software Foundation, please see
 * <http://www.apache.org/>.
 */
#if !defined(DOUBLESUPPORT_HEADER_GUARD_1357924680)
#define DOUBLESUPPORT_HEADER_GUARD_1357924680

// Base include file.  Must be first.
#include <PlatformSupport/PlatformSupportDefinitions.hpp>

#include <functional>

#include <XalanDOM/XalanDOMString.hpp>

// A class to help us support IEEE 754.
class XALAN_PLATFORMSUPPORT_EXPORT DoubleSupport
{
public:

	// Use these functions to determine if a value represents one of these
	// values.  It seems that under some architectures, NaN will compare
	// as equal to any number, which is a big problem.  Hence these helper
	// functions.

	/**
	 * Determine if target is not a number
	 *
	 * @param theNumber target number
	 * @return true if target represents the "not a number" value
	 */
	static bool
	isNaN(double	theNumber)
	{
		// Compare the two DWORDs of the double as unsigned longs.
		const unsigned long* const	theFirstDWORD =
			reinterpret_cast<const unsigned long*>(&theNumber);

		const unsigned long* const	theSecondDWORD =
							theFirstDWORD + 1;

		return *theFirstDWORD == *s_NaNFirstDWORD &&
			   *theSecondDWORD == *s_NaNSecondDWORD;
	}

	/**
	 * Determine if target is positive infinity
	 *
	 * @param theNumber target number
	 * @return true if target represents the value for positive infinity
	 */
	static bool
	isPositiveInfinity(double	theNumber)
	{
		return !isNaN(theNumber) && theNumber == s_positiveInfinity;
	}

	/**
	 * Determine if target is negative infinity
	 *
	 * @param theNumber target number
	 * @return true if target represents the value for negative infinity
	 */
	static bool
	isNegativeInfinity(double	theNumber)
	{
		return !isNaN(theNumber) && theNumber == s_negativeInfinity;
	}

	// These can be used to initialize values, but should not
	// be used to do equality comparisons, as == may fail on
	// some platforms.
	//

	/**
	 * Double value that represents "not a number"
	 *
	 * @return "not a number" value
	 */
	static double
	getNaN()
	{
		return s_NaN;
	}

	/**
	 * Double value that represents positive infinity
	 *
	 * @return positive infinity value
	 */
	static double
	getPositiveInfinity()
	{
		return s_positiveInfinity;
	}

	/**
	 * Double value that represents negative infinity
	 *
	 * @return negative infinity value
	 */
	static double
	getNegativeInfinity()
	{
		return s_negativeInfinity;
	}

	/**
	 * Compare two double values, taking into account
	 * the fact that we must support IEEE 754
	 *
	 * @param theLHS a number to compare
	 * @param theRHS a number to compare
	 * @return the result of the compare
	 */
	static bool
	equal(
			double	theLHS,
			double	theRHS);

	/**
	 * Compare two double values, taking into account
	 * the fact that we must support IEEE 754
	 *
	 * @param theLHS a number to compare
	 * @param theRHS a number to compare
	 * @return the result of the compare
	 */
	static bool
	notEqual(
			double	theLHS,
			double	theRHS);

	/**
	 * Compare two double values, taking into account
	 * the fact that we must support IEEE 754
	 *
	 * @param theLHS a number to compare
	 * @param theRHS a number to compare
	 * @return the result of the compare
	 */
	static bool
	lessThan(
			double	theLHS,
			double	theRHS);

	/**
	 * Compare two double values, taking into account
	 * the fact that we must support IEEE 754
	 *
	 * @param theLHS a number to compare
	 * @param theRHS a number to compare
	 * @return the result of the compare
	 */
	static bool
	lessThanOrEqual(
			double	theLHS,
			double	theRHS);

	/**
	 * Compare two double values, taking into account
	 * the fact that we must support IEEE 754
	 *
	 * @param theLHS a number to compare
	 * @param theRHS a number to compare
	 * @return the result of the compare
	 */
	static bool
	greaterThan(
			double	theLHS,
			double	theRHS);

	/**
	 * Compare two double values, taking into account
	 * the fact that we must support IEEE 754
	 *
	 * @param theLHS a number to compare
	 * @param theRHS a number to compare
	 * @return the result of the compare
	 */
	static bool
	greaterThanOrEqual(
			double	theLHS,
			double	theRHS);

	/**
	 * Add two double values, taking into account
	 * the fact that we must support IEEE 754
	 *
	 * @param theLHS a number to add
	 * @param theRHS a number to add
	 * @return the result of the addition
	 */
	static double
	add(
			double	theLHS,
			double	theRHS);

	/**
	 * Subtract two double values, taking into account
	 * the fact that we must support IEEE 754
	 *
	 * @param theLHS a number to subtract
	 * @param theRHS a number to subtract
	 * @return the result of the subtraction
	 */
	static double
	subtract(
			double	theLHS,
			double	theRHS);

	/**
	 * Multiply two double values, taking into account
	 * the fact that we must support IEEE 754
	 *
	 * @param theLHS a number to multiply
	 * @param theRHS a number to multiply
	 * @return the result of the multiplication
	 */
	static double
	multiply(
			double	theLHS,
			double	theRHS);

	/**
	 * Divide two double values, taking into account
	 * the fact that we must support IEEE 754
	 *
	 * @param theLHS a number to divide
	 * @param theRHS a number to divide
	 * @return the result of the division
	 */
	static double
	divide(
			double	theLHS,
			double	theRHS);

	/**
	 * Determine the modulus two double values,
	 * taking into account the fact that we must
	 * support IEEE 754
	 *
	 * @param theLHS a number to divide
	 * @param theRHS a number to divide
	 * @return the result of the modulus
	 */
	static double
	modulus(
			double	theLHS,
			double	theRHS);

	/**
	 * Determine the negative of a double value,
	 * taking into account the fact that we must
	 * support IEEE 754
	 *
	 * @param theDouble a number to negate
	 * @return the result of the negation
	 */
	static double
	negative(double	theDouble);

	// Some functors to do the same thing.  This is for
	// STL integration...
	#if defined(XALAN_NO_NAMESPACES)
	struct equalFunction : public binary_function<const double&, const double&, bool>
	#else
	struct equalFunction : public std::binary_function<const double&, const double&, bool>
	#endif
	{
		result_type
		operator()(
			first_argument_type		theLHS,
			second_argument_type	theRHS) const
		{
			return equal(theLHS, theRHS);
		}
	};

	#if defined(XALAN_NO_NAMESPACES)
	struct notEqualFunction : public binary_function<const double&, const double&, bool>
	#else
	struct notEqualFunction : public std::binary_function<const double&, const double&, bool>
	#endif
	{
		result_type
		operator()(
			first_argument_type		theLHS,
			second_argument_type	theRHS) const
		{
			return notEqual(theLHS, theRHS);
		}
	};

	#if defined(XALAN_NO_NAMESPACES)
	struct lessThanFunction : public binary_function<const double&, const double&, bool>
	#else
	struct lessThanFunction : public std::binary_function<const double&, const double&, bool>
	#endif
	{
		result_type
		operator()(
			first_argument_type		theLHS,
			second_argument_type	theRHS) const
		{
			return lessThan(theLHS, theRHS);
		}
	};

	#if defined(XALAN_NO_NAMESPACES)
	struct lessThanOrEqualFunction : public binary_function<const double&, const double&, bool>
	#else
	struct lessThanOrEqualFunction : public std::binary_function<const double&, const double&, bool>
	#endif
	{
		result_type
		operator()(
			first_argument_type		theLHS,
			second_argument_type	theRHS) const
		{
			return lessThanOrEqual(theLHS, theRHS);
		}
	};

	#if defined(XALAN_NO_NAMESPACES)
	struct greaterThanFunction : public binary_function<const double&, const double&, bool>
	#else
	struct greaterThanFunction : public std::binary_function<const double&, const double&, bool>
	#endif
	{
		result_type
		operator()(
			first_argument_type		theLHS,
			second_argument_type	theRHS) const
		{
			return greaterThan(theLHS, theRHS);
		}
	};

	#if defined(XALAN_NO_NAMESPACES)
	struct greaterThanOrEqualFunction : public binary_function<const double&, const double&, bool>
	#else
	struct greaterThanOrEqualFunction : public std::binary_function<const double&, const double&, bool>
	#endif
	{
		result_type
		operator()(
			first_argument_type		theLHS,
			second_argument_type	theRHS) const
		{
			return greaterThanOrEqual(theLHS, theRHS);
		}
	};

	#if defined(XALAN_NO_NAMESPACES)
	struct addFunction : public binary_function<const double&, const double&, double>
	#else
	struct addFunction : public std::binary_function<const double&, const double&, double>
	#endif
	{
		result_type
		operator()(
			first_argument_type		theLHS,
			second_argument_type	theRHS) const
		{
			return add(theLHS, theRHS);
		}
	};

	#if defined(XALAN_NO_NAMESPACES)
	struct subtractFunction : public binary_function<const double&, const double&, double>
	#else
	struct subtractFunction : public std::binary_function<const double&, const double&, double>
	#endif
	{
		result_type
		operator()(
			first_argument_type		theLHS,
			second_argument_type	theRHS) const
		{
			return subtract(theLHS, theRHS);
		}
	};

	#if defined(XALAN_NO_NAMESPACES)
	struct multiplyFunction : public binary_function<const double&, const double&, double>
	#else
	struct multiplyFunction : public std::binary_function<const double&, const double&, double>
	#endif
	{
		result_type
		operator()(
			first_argument_type		theLHS,
			second_argument_type	theRHS) const
		{
			return multiply(theLHS, theRHS);
		}
	};

	#if defined(XALAN_NO_NAMESPACES)
	struct divideFunction : public binary_function<const double&, const double&, double>
	#else
	struct divideFunction : public std::binary_function<const double&, const double&, double>
	#endif
	{
		result_type
		operator()(
			first_argument_type		theLHS,
			second_argument_type	theRHS) const
		{
			return divide(theLHS, theRHS);
		}
	};

	#if defined(XALAN_NO_NAMESPACES)
	struct modulusFunction : public binary_function<const double&, const double&, double>
	#else
	struct modulusFunction : public std::binary_function<const double&, const double&, double>
	#endif
	{
		result_type
		operator()(
			first_argument_type		theLHS,
			second_argument_type	theRHS) const
		{
			return modulus(theLHS, theRHS);
		}
	};

	#if defined(XALAN_NO_NAMESPACES)
	struct negativeFunction : public unary_function<const double&, double>
	#else
	struct negativeFunction : public std::unary_function<const double&, double>
	#endif
	{
		result_type
		operator()(argument_type	theDouble) const
		{
			return negative(theDouble);
		}
	};

	static double
	toDouble(const XalanDOMString&	theString);

	static double
	toDouble(const XalanDOMChar*	theString);

private:

	static const double				s_NaN;
	static const double				s_positiveInfinity;
	static const double				s_negativeInfinity;

#if defined(XALAN_NEED_SPECIAL_NAN_SUPPORT)
	static const unsigned long*		s_NaNFirstDWORD;
	static const unsigned long*		s_NaNSecondDWORD;
#endif
};

#endif	// DOUBLESUPPORT_HEADER_GUARD_1357924680
<commit_msg>Added ifdef for old-style cast.<commit_after>/*
 * The Apache Software License, Version 1.1
 *
 *
 * Copyright (c) 1999 The Apache Software Foundation.  All rights
 * reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 *
 * 3. The end-user documentation included with the redistribution,
 *    if any, must include the following acknowledgment:
 *       "This product includes software developed by the
 *        Apache Software Foundation (http://www.apache.org/)."
 *    Alternately, this acknowledgment may appear in the software itself,
 *    if and wherever such third-party acknowledgments normally appear.
 *
 * 4. The names "Xalan" and "Apache Software Foundation" must
 *    not be used to endorse or promote products derived from this
 *    software without prior written permission. For written
 *    permission, please contact apache@apache.org.
 *
 * 5. Products derived from this software may not be called "Apache",
 *    nor may "Apache" appear in their name, without prior written
 *    permission of the Apache Software Foundation.
 *
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 * ====================================================================
 *
 * This software consists of voluntary contributions made by many
 * individuals on behalf of the Apache Software Foundation and was
 * originally based on software copyright (c) 1999, International
 * Business Machines, Inc., http://www.ibm.com.  For more
 * information on the Apache Software Foundation, please see
 * <http://www.apache.org/>.
 */
#if !defined(DOUBLESUPPORT_HEADER_GUARD_1357924680)
#define DOUBLESUPPORT_HEADER_GUARD_1357924680

// Base include file.  Must be first.
#include <PlatformSupport/PlatformSupportDefinitions.hpp>

#include <functional>

#include <XalanDOM/XalanDOMString.hpp>

// A class to help us support IEEE 754.
class XALAN_PLATFORMSUPPORT_EXPORT DoubleSupport
{
public:

	// Use these functions to determine if a value represents one of these
	// values.  It seems that under some architectures, NaN will compare
	// as equal to any number, which is a big problem.  Hence these helper
	// functions.

	/**
	 * Determine if target is not a number
	 *
	 * @param theNumber target number
	 * @return true if target represents the "not a number" value
	 */
	static bool
	isNaN(double	theNumber)
	{
		// Compare the two DWORDs of the double as unsigned longs.
		const unsigned long* const	theFirstDWORD =
#if defined(XALAN_OLD_STYLE_CASTS)
			(const unsigned long*)&theNumber;
#else
			reinterpret_cast<const unsigned long*>(&theNumber);
#endif

		const unsigned long* const	theSecondDWORD =
							theFirstDWORD + 1;

		return *theFirstDWORD == *s_NaNFirstDWORD &&
			   *theSecondDWORD == *s_NaNSecondDWORD;
	}

	/**
	 * Determine if target is positive infinity
	 *
	 * @param theNumber target number
	 * @return true if target represents the value for positive infinity
	 */
	static bool
	isPositiveInfinity(double	theNumber)
	{
		return !isNaN(theNumber) && theNumber == s_positiveInfinity;
	}

	/**
	 * Determine if target is negative infinity
	 *
	 * @param theNumber target number
	 * @return true if target represents the value for negative infinity
	 */
	static bool
	isNegativeInfinity(double	theNumber)
	{
		return !isNaN(theNumber) && theNumber == s_negativeInfinity;
	}

	// These can be used to initialize values, but should not
	// be used to do equality comparisons, as == may fail on
	// some platforms.
	//

	/**
	 * Double value that represents "not a number"
	 *
	 * @return "not a number" value
	 */
	static double
	getNaN()
	{
		return s_NaN;
	}

	/**
	 * Double value that represents positive infinity
	 *
	 * @return positive infinity value
	 */
	static double
	getPositiveInfinity()
	{
		return s_positiveInfinity;
	}

	/**
	 * Double value that represents negative infinity
	 *
	 * @return negative infinity value
	 */
	static double
	getNegativeInfinity()
	{
		return s_negativeInfinity;
	}

	/**
	 * Compare two double values, taking into account
	 * the fact that we must support IEEE 754
	 *
	 * @param theLHS a number to compare
	 * @param theRHS a number to compare
	 * @return the result of the compare
	 */
	static bool
	equal(
			double	theLHS,
			double	theRHS);

	/**
	 * Compare two double values, taking into account
	 * the fact that we must support IEEE 754
	 *
	 * @param theLHS a number to compare
	 * @param theRHS a number to compare
	 * @return the result of the compare
	 */
	static bool
	notEqual(
			double	theLHS,
			double	theRHS);

	/**
	 * Compare two double values, taking into account
	 * the fact that we must support IEEE 754
	 *
	 * @param theLHS a number to compare
	 * @param theRHS a number to compare
	 * @return the result of the compare
	 */
	static bool
	lessThan(
			double	theLHS,
			double	theRHS);

	/**
	 * Compare two double values, taking into account
	 * the fact that we must support IEEE 754
	 *
	 * @param theLHS a number to compare
	 * @param theRHS a number to compare
	 * @return the result of the compare
	 */
	static bool
	lessThanOrEqual(
			double	theLHS,
			double	theRHS);

	/**
	 * Compare two double values, taking into account
	 * the fact that we must support IEEE 754
	 *
	 * @param theLHS a number to compare
	 * @param theRHS a number to compare
	 * @return the result of the compare
	 */
	static bool
	greaterThan(
			double	theLHS,
			double	theRHS);

	/**
	 * Compare two double values, taking into account
	 * the fact that we must support IEEE 754
	 *
	 * @param theLHS a number to compare
	 * @param theRHS a number to compare
	 * @return the result of the compare
	 */
	static bool
	greaterThanOrEqual(
			double	theLHS,
			double	theRHS);

	/**
	 * Add two double values, taking into account
	 * the fact that we must support IEEE 754
	 *
	 * @param theLHS a number to add
	 * @param theRHS a number to add
	 * @return the result of the addition
	 */
	static double
	add(
			double	theLHS,
			double	theRHS);

	/**
	 * Subtract two double values, taking into account
	 * the fact that we must support IEEE 754
	 *
	 * @param theLHS a number to subtract
	 * @param theRHS a number to subtract
	 * @return the result of the subtraction
	 */
	static double
	subtract(
			double	theLHS,
			double	theRHS);

	/**
	 * Multiply two double values, taking into account
	 * the fact that we must support IEEE 754
	 *
	 * @param theLHS a number to multiply
	 * @param theRHS a number to multiply
	 * @return the result of the multiplication
	 */
	static double
	multiply(
			double	theLHS,
			double	theRHS);

	/**
	 * Divide two double values, taking into account
	 * the fact that we must support IEEE 754
	 *
	 * @param theLHS a number to divide
	 * @param theRHS a number to divide
	 * @return the result of the division
	 */
	static double
	divide(
			double	theLHS,
			double	theRHS);

	/**
	 * Determine the modulus two double values,
	 * taking into account the fact that we must
	 * support IEEE 754
	 *
	 * @param theLHS a number to divide
	 * @param theRHS a number to divide
	 * @return the result of the modulus
	 */
	static double
	modulus(
			double	theLHS,
			double	theRHS);

	/**
	 * Determine the negative of a double value,
	 * taking into account the fact that we must
	 * support IEEE 754
	 *
	 * @param theDouble a number to negate
	 * @return the result of the negation
	 */
	static double
	negative(double	theDouble);

	// Some functors to do the same thing.  This is for
	// STL integration...
	#if defined(XALAN_NO_NAMESPACES)
	struct equalFunction : public binary_function<const double&, const double&, bool>
	#else
	struct equalFunction : public std::binary_function<const double&, const double&, bool>
	#endif
	{
		result_type
		operator()(
			first_argument_type		theLHS,
			second_argument_type	theRHS) const
		{
			return equal(theLHS, theRHS);
		}
	};

	#if defined(XALAN_NO_NAMESPACES)
	struct notEqualFunction : public binary_function<const double&, const double&, bool>
	#else
	struct notEqualFunction : public std::binary_function<const double&, const double&, bool>
	#endif
	{
		result_type
		operator()(
			first_argument_type		theLHS,
			second_argument_type	theRHS) const
		{
			return notEqual(theLHS, theRHS);
		}
	};

	#if defined(XALAN_NO_NAMESPACES)
	struct lessThanFunction : public binary_function<const double&, const double&, bool>
	#else
	struct lessThanFunction : public std::binary_function<const double&, const double&, bool>
	#endif
	{
		result_type
		operator()(
			first_argument_type		theLHS,
			second_argument_type	theRHS) const
		{
			return lessThan(theLHS, theRHS);
		}
	};

	#if defined(XALAN_NO_NAMESPACES)
	struct lessThanOrEqualFunction : public binary_function<const double&, const double&, bool>
	#else
	struct lessThanOrEqualFunction : public std::binary_function<const double&, const double&, bool>
	#endif
	{
		result_type
		operator()(
			first_argument_type		theLHS,
			second_argument_type	theRHS) const
		{
			return lessThanOrEqual(theLHS, theRHS);
		}
	};

	#if defined(XALAN_NO_NAMESPACES)
	struct greaterThanFunction : public binary_function<const double&, const double&, bool>
	#else
	struct greaterThanFunction : public std::binary_function<const double&, const double&, bool>
	#endif
	{
		result_type
		operator()(
			first_argument_type		theLHS,
			second_argument_type	theRHS) const
		{
			return greaterThan(theLHS, theRHS);
		}
	};

	#if defined(XALAN_NO_NAMESPACES)
	struct greaterThanOrEqualFunction : public binary_function<const double&, const double&, bool>
	#else
	struct greaterThanOrEqualFunction : public std::binary_function<const double&, const double&, bool>
	#endif
	{
		result_type
		operator()(
			first_argument_type		theLHS,
			second_argument_type	theRHS) const
		{
			return greaterThanOrEqual(theLHS, theRHS);
		}
	};

	#if defined(XALAN_NO_NAMESPACES)
	struct addFunction : public binary_function<const double&, const double&, double>
	#else
	struct addFunction : public std::binary_function<const double&, const double&, double>
	#endif
	{
		result_type
		operator()(
			first_argument_type		theLHS,
			second_argument_type	theRHS) const
		{
			return add(theLHS, theRHS);
		}
	};

	#if defined(XALAN_NO_NAMESPACES)
	struct subtractFunction : public binary_function<const double&, const double&, double>
	#else
	struct subtractFunction : public std::binary_function<const double&, const double&, double>
	#endif
	{
		result_type
		operator()(
			first_argument_type		theLHS,
			second_argument_type	theRHS) const
		{
			return subtract(theLHS, theRHS);
		}
	};

	#if defined(XALAN_NO_NAMESPACES)
	struct multiplyFunction : public binary_function<const double&, const double&, double>
	#else
	struct multiplyFunction : public std::binary_function<const double&, const double&, double>
	#endif
	{
		result_type
		operator()(
			first_argument_type		theLHS,
			second_argument_type	theRHS) const
		{
			return multiply(theLHS, theRHS);
		}
	};

	#if defined(XALAN_NO_NAMESPACES)
	struct divideFunction : public binary_function<const double&, const double&, double>
	#else
	struct divideFunction : public std::binary_function<const double&, const double&, double>
	#endif
	{
		result_type
		operator()(
			first_argument_type		theLHS,
			second_argument_type	theRHS) const
		{
			return divide(theLHS, theRHS);
		}
	};

	#if defined(XALAN_NO_NAMESPACES)
	struct modulusFunction : public binary_function<const double&, const double&, double>
	#else
	struct modulusFunction : public std::binary_function<const double&, const double&, double>
	#endif
	{
		result_type
		operator()(
			first_argument_type		theLHS,
			second_argument_type	theRHS) const
		{
			return modulus(theLHS, theRHS);
		}
	};

	#if defined(XALAN_NO_NAMESPACES)
	struct negativeFunction : public unary_function<const double&, double>
	#else
	struct negativeFunction : public std::unary_function<const double&, double>
	#endif
	{
		result_type
		operator()(argument_type	theDouble) const
		{
			return negative(theDouble);
		}
	};

	static double
	toDouble(const XalanDOMString&	theString);

	static double
	toDouble(const XalanDOMChar*	theString);

private:

	static const double				s_NaN;
	static const double				s_positiveInfinity;
	static const double				s_negativeInfinity;

#if defined(XALAN_NEED_SPECIAL_NAN_SUPPORT)
	static const unsigned long*		s_NaNFirstDWORD;
	static const unsigned long*		s_NaNSecondDWORD;
#endif
};

#endif	// DOUBLESUPPORT_HEADER_GUARD_1357924680
<|endoftext|>


<commit_before>#define FASTLED_INTERNAL
#include "FastLED.h"

#if defined(__SAM3X8E__)
volatile uint32_t fuckit;
#endif

FASTLED_NAMESPACE_BEGIN

void *pSmartMatrix = NULL;

CFastLED FastLED;

CLEDController *CLEDController::m_pHead = NULL;
CLEDController *CLEDController::m_pTail = NULL;
static uint32_t lastshow = 0;

// uint32_t CRGB::Squant = ((uint32_t)((__TIME__[4]-'0') * 28))<<16 | ((__TIME__[6]-'0')*50)<<8 | ((__TIME__[7]-'0')*28);

CFastLED::CFastLED() {
	// clear out the array of led controllers
	// m_nControllers = 0;
	m_Scale = 255;
	m_nFPS = 0;
	setMaxRefreshRate(400);
}

CLEDController &CFastLED::addLeds(CLEDController *pLed,
									   struct CRGB *data,
									   int nLedsOrOffset, int nLedsIfOffset) {
	int nOffset = (nLedsIfOffset > 0) ? nLedsOrOffset : 0;
	int nLeds = (nLedsIfOffset > 0) ? nLedsIfOffset : nLedsOrOffset;

	pLed->init();
	pLed->setLeds(data + nOffset, nLeds);
	return *pLed;
}

void CFastLED::show(uint8_t scale) {
	// guard against showing too rapidly
	while(m_nMinMicros && ((micros()-lastshow) < m_nMinMicros));
	lastshow = micros();

	CLEDController *pCur = CLEDController::head();
	while(pCur) {
		uint8_t d = pCur->getDither();
		if(m_nFPS < 100) { pCur->setDither(0); }
		pCur->showLeds(scale);
		pCur->setDither(d);
		pCur = pCur->next();
	}
	countFPS();
}

int CFastLED::count() {
    int x = 0;
	CLEDController *pCur = CLEDController::head();
	while( pCur) {
        x++;
		pCur = pCur->next();
	}
    return x;
}

CLEDController & CFastLED::operator[](int x) {
	CLEDController *pCur = CLEDController::head();
	while(x-- && pCur) {
		pCur = pCur->next();
	}
	if(pCur == NULL) {
		return *(CLEDController::head());
	} else {
		return *pCur;
	}
}

void CFastLED::showColor(const struct CRGB & color, uint8_t scale) {
	while(m_nMinMicros && ((micros()-lastshow) < m_nMinMicros));
	lastshow = micros();

	CLEDController *pCur = CLEDController::head();
	while(pCur) {
		uint8_t d = pCur->getDither();
		if(m_nFPS < 100) { pCur->setDither(0); }
		pCur->showColor(color, scale);
		pCur->setDither(d);
		pCur = pCur->next();
	}
	countFPS();
}

void CFastLED::clear(boolean writeData) {
	if(writeData) {
		showColor(CRGB(0,0,0), 0);
	}
    clearData();
}

void CFastLED::clearData() {
	CLEDController *pCur = CLEDController::head();
	while(pCur) {
		pCur->clearLedData();
		pCur = pCur->next();
	}
}

void CFastLED::delay(unsigned long ms) {
	unsigned long start = millis();
	while((millis()-start) < ms) {
#ifndef FASTLED_ACCURATE_CLOCK
		// make sure to allow at least one ms to pass to ensure the clock moves
		// forward
		::delay(1);
#endif
		show();
	}
}

void CFastLED::setTemperature(const struct CRGB & temp) {
	CLEDController *pCur = CLEDController::head();
	while(pCur) {
		pCur->setTemperature(temp);
		pCur = pCur->next();
	}
}

void CFastLED::setCorrection(const struct CRGB & correction) {
	CLEDController *pCur = CLEDController::head();
	while(pCur) {
		pCur->setCorrection(correction);
		pCur = pCur->next();
	}
}

void CFastLED::setDither(uint8_t ditherMode)  {
	CLEDController *pCur = CLEDController::head();
	while(pCur) {
		pCur->setDither(ditherMode);
		pCur = pCur->next();
	}
}

//
// template<int m, int n> void transpose8(unsigned char A[8], unsigned char B[8]) {
// 	uint32_t x, y, t;
//
// 	// Load the array and pack it into x and y.
//   	y = *(unsigned int*)(A);
// 	x = *(unsigned int*)(A+4);
//
// 	// x = (A[0]<<24)   | (A[m]<<16)   | (A[2*m]<<8) | A[3*m];
// 	// y = (A[4*m]<<24) | (A[5*m]<<16) | (A[6*m]<<8) | A[7*m];
//
        // // pre-transform x
        // t = (x ^ (x >> 7)) & 0x00AA00AA;  x = x ^ t ^ (t << 7);
        // t = (x ^ (x >>14)) & 0x0000CCCC;  x = x ^ t ^ (t <<14);
				//
        // // pre-transform y
        // t = (y ^ (y >> 7)) & 0x00AA00AA;  y = y ^ t ^ (t << 7);
        // t = (y ^ (y >>14)) & 0x0000CCCC;  y = y ^ t ^ (t <<14);
				//
        // // final transform
        // t = (x & 0xF0F0F0F0) | ((y >> 4) & 0x0F0F0F0F);
        // y = ((x << 4) & 0xF0F0F0F0) | (y & 0x0F0F0F0F);
        // x = t;
//
// 	B[7*n] = y; y >>= 8;
// 	B[6*n] = y; y >>= 8;
// 	B[5*n] = y; y >>= 8;
// 	B[4*n] = y;
//
//   B[3*n] = x; x >>= 8;
// 	B[2*n] = x; x >>= 8;
// 	B[n] = x; x >>= 8;
// 	B[0] = x;
// 	// B[0]=x>>24;    B[n]=x>>16;    B[2*n]=x>>8;  B[3*n]=x>>0;
// 	// B[4*n]=y>>24;  B[5*n]=y>>16;  B[6*n]=y>>8;  B[7*n]=y>>0;
// }
//
// void transposeLines(Lines & out, Lines & in) {
// 	transpose8<1,2>(in.bytes, out.bytes);
// 	transpose8<1,2>(in.bytes + 8, out.bytes + 1);
// }

extern int noise_min;
extern int noise_max;

void CFastLED::countFPS(int nFrames) {
  static int br = 0;
  static uint32_t lastframe = 0; // millis();

  if(br++ >= nFrames) {
		uint32_t now = millis();
		now -= lastframe;
		m_nFPS = (br * 1000) / now;
    br = 0;
    lastframe = millis();
  }
}

void CFastLED::setMaxRefreshRate(uint16_t refresh) {
		if(refresh > 0) {
			m_nMinMicros = 1000000 / refresh;
		} else {
			m_nMinMicros = 0;
		}
}

#ifdef NEED_CXX_BITS
namespace __cxxabiv1
{
	extern "C" void __cxa_pure_virtual (void) {}
	/* guard variables */

	/* The ABI requires a 64-bit type.  */
	__extension__ typedef int __guard __attribute__((mode(__DI__)));

	extern "C" int __cxa_guard_acquire (__guard *);
	extern "C" void __cxa_guard_release (__guard *);
	extern "C" void __cxa_guard_abort (__guard *);

	extern "C" int __cxa_guard_acquire (__guard *g)
	{
		return !*(char *)(g);
	}

	extern "C" void __cxa_guard_release (__guard *g)
	{
		*(char *)g = 1;
	}

	extern "C" void __cxa_guard_abort (__guard *)
	{

	}
}
#endif

FASTLED_NAMESPACE_END
<commit_msg>make sure FastLED.cpp has a definition for millis.<commit_after>#define FASTLED_INTERNAL
#include "FastLED.h"

#if defined(__SAM3X8E__)
volatile uint32_t fuckit;
#endif

#if defined(ARDUINO) || defined(SPARK)
extern uint32_t millis();
#endif

FASTLED_NAMESPACE_BEGIN

void *pSmartMatrix = NULL;

CFastLED FastLED;

CLEDController *CLEDController::m_pHead = NULL;
CLEDController *CLEDController::m_pTail = NULL;
static uint32_t lastshow = 0;

// uint32_t CRGB::Squant = ((uint32_t)((__TIME__[4]-'0') * 28))<<16 | ((__TIME__[6]-'0')*50)<<8 | ((__TIME__[7]-'0')*28);

CFastLED::CFastLED() {
	// clear out the array of led controllers
	// m_nControllers = 0;
	m_Scale = 255;
	m_nFPS = 0;
	setMaxRefreshRate(400);
}

CLEDController &CFastLED::addLeds(CLEDController *pLed,
									   struct CRGB *data,
									   int nLedsOrOffset, int nLedsIfOffset) {
	int nOffset = (nLedsIfOffset > 0) ? nLedsOrOffset : 0;
	int nLeds = (nLedsIfOffset > 0) ? nLedsIfOffset : nLedsOrOffset;

	pLed->init();
	pLed->setLeds(data + nOffset, nLeds);
	return *pLed;
}

void CFastLED::show(uint8_t scale) {
	// guard against showing too rapidly
	while(m_nMinMicros && ((micros()-lastshow) < m_nMinMicros));
	lastshow = micros();

	CLEDController *pCur = CLEDController::head();
	while(pCur) {
		uint8_t d = pCur->getDither();
		if(m_nFPS < 100) { pCur->setDither(0); }
		pCur->showLeds(scale);
		pCur->setDither(d);
		pCur = pCur->next();
	}
	countFPS();
}

int CFastLED::count() {
    int x = 0;
	CLEDController *pCur = CLEDController::head();
	while( pCur) {
        x++;
		pCur = pCur->next();
	}
    return x;
}

CLEDController & CFastLED::operator[](int x) {
	CLEDController *pCur = CLEDController::head();
	while(x-- && pCur) {
		pCur = pCur->next();
	}
	if(pCur == NULL) {
		return *(CLEDController::head());
	} else {
		return *pCur;
	}
}

void CFastLED::showColor(const struct CRGB & color, uint8_t scale) {
	while(m_nMinMicros && ((micros()-lastshow) < m_nMinMicros));
	lastshow = micros();

	CLEDController *pCur = CLEDController::head();
	while(pCur) {
		uint8_t d = pCur->getDither();
		if(m_nFPS < 100) { pCur->setDither(0); }
		pCur->showColor(color, scale);
		pCur->setDither(d);
		pCur = pCur->next();
	}
	countFPS();
}

void CFastLED::clear(boolean writeData) {
	if(writeData) {
		showColor(CRGB(0,0,0), 0);
	}
    clearData();
}

void CFastLED::clearData() {
	CLEDController *pCur = CLEDController::head();
	while(pCur) {
		pCur->clearLedData();
		pCur = pCur->next();
	}
}

void CFastLED::delay(unsigned long ms) {
	unsigned long start = millis();
	while((millis()-start) < ms) {
#ifndef FASTLED_ACCURATE_CLOCK
		// make sure to allow at least one ms to pass to ensure the clock moves
		// forward
		::delay(1);
#endif
		show();
	}
}

void CFastLED::setTemperature(const struct CRGB & temp) {
	CLEDController *pCur = CLEDController::head();
	while(pCur) {
		pCur->setTemperature(temp);
		pCur = pCur->next();
	}
}

void CFastLED::setCorrection(const struct CRGB & correction) {
	CLEDController *pCur = CLEDController::head();
	while(pCur) {
		pCur->setCorrection(correction);
		pCur = pCur->next();
	}
}

void CFastLED::setDither(uint8_t ditherMode)  {
	CLEDController *pCur = CLEDController::head();
	while(pCur) {
		pCur->setDither(ditherMode);
		pCur = pCur->next();
	}
}

//
// template<int m, int n> void transpose8(unsigned char A[8], unsigned char B[8]) {
// 	uint32_t x, y, t;
//
// 	// Load the array and pack it into x and y.
//   	y = *(unsigned int*)(A);
// 	x = *(unsigned int*)(A+4);
//
// 	// x = (A[0]<<24)   | (A[m]<<16)   | (A[2*m]<<8) | A[3*m];
// 	// y = (A[4*m]<<24) | (A[5*m]<<16) | (A[6*m]<<8) | A[7*m];
//
        // // pre-transform x
        // t = (x ^ (x >> 7)) & 0x00AA00AA;  x = x ^ t ^ (t << 7);
        // t = (x ^ (x >>14)) & 0x0000CCCC;  x = x ^ t ^ (t <<14);
				//
        // // pre-transform y
        // t = (y ^ (y >> 7)) & 0x00AA00AA;  y = y ^ t ^ (t << 7);
        // t = (y ^ (y >>14)) & 0x0000CCCC;  y = y ^ t ^ (t <<14);
				//
        // // final transform
        // t = (x & 0xF0F0F0F0) | ((y >> 4) & 0x0F0F0F0F);
        // y = ((x << 4) & 0xF0F0F0F0) | (y & 0x0F0F0F0F);
        // x = t;
//
// 	B[7*n] = y; y >>= 8;
// 	B[6*n] = y; y >>= 8;
// 	B[5*n] = y; y >>= 8;
// 	B[4*n] = y;
//
//   B[3*n] = x; x >>= 8;
// 	B[2*n] = x; x >>= 8;
// 	B[n] = x; x >>= 8;
// 	B[0] = x;
// 	// B[0]=x>>24;    B[n]=x>>16;    B[2*n]=x>>8;  B[3*n]=x>>0;
// 	// B[4*n]=y>>24;  B[5*n]=y>>16;  B[6*n]=y>>8;  B[7*n]=y>>0;
// }
//
// void transposeLines(Lines & out, Lines & in) {
// 	transpose8<1,2>(in.bytes, out.bytes);
// 	transpose8<1,2>(in.bytes + 8, out.bytes + 1);
// }

extern int noise_min;
extern int noise_max;

void CFastLED::countFPS(int nFrames) {
  static int br = 0;
  static uint32_t lastframe = 0; // millis();

  if(br++ >= nFrames) {
		uint32_t now = millis();
		now -= lastframe;
		m_nFPS = (br * 1000) / now;
    br = 0;
    lastframe = millis();
  }
}

void CFastLED::setMaxRefreshRate(uint16_t refresh) {
		if(refresh > 0) {
			m_nMinMicros = 1000000 / refresh;
		} else {
			m_nMinMicros = 0;
		}
}

#ifdef NEED_CXX_BITS
namespace __cxxabiv1
{
	extern "C" void __cxa_pure_virtual (void) {}
	/* guard variables */

	/* The ABI requires a 64-bit type.  */
	__extension__ typedef int __guard __attribute__((mode(__DI__)));

	extern "C" int __cxa_guard_acquire (__guard *);
	extern "C" void __cxa_guard_release (__guard *);
	extern "C" void __cxa_guard_abort (__guard *);

	extern "C" int __cxa_guard_acquire (__guard *g)
	{
		return !*(char *)(g);
	}

	extern "C" void __cxa_guard_release (__guard *g)
	{
		*(char *)g = 1;
	}

	extern "C" void __cxa_guard_abort (__guard *)
	{

	}
}
#endif

FASTLED_NAMESPACE_END
<|endoftext|>


<commit_before>// Copyright 2019 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "google/cloud/spanner/database_admin_client.h"
#include "google/cloud/bigtable/internal/grpc_error_delegate.h"
#include <algorithm>

namespace google {
namespace cloud {
namespace spanner {
inline namespace SPANNER_CLIENT_NS {

// TODO(#126) - refactor to some common place. Note that this different from
// the MakeStatusFromGrpcError function,
namespace {
StatusCode MapStatusCode(std::int32_t code) {
  if (code < 0 || code > static_cast<std::int32_t>(StatusCode::kDataLoss)) {
    return StatusCode::kUnknown;
  }
  return static_cast<StatusCode>(code);
}
}  // namespace

google::cloud::Status ToGoogleCloudStatus(google::rpc::Status const& status) {
  return google::cloud::Status(MapStatusCode(status.code()), status.message());
}

namespace gcsa = google::spanner::admin::database::v1;

DatabaseAdminClient::DatabaseAdminClient(ClientOptions const& client_options)
    : stub_(internal::CreateDefaultDatabaseAdminStub(client_options)) {}

future<StatusOr<gcsa::Database>> DatabaseAdminClient::CreateDatabase(
    std::string const& project_id, std::string const& instance_id,
    std::string const& database_id,
    std::vector<std::string> const& extra_statements) {
  grpc::ClientContext context;
  gcsa::CreateDatabaseRequest request;
  request.set_parent("projects/" + project_id + "/instances/" + instance_id);
  request.set_create_statement("CREATE DATABASE `" + database_id + "`");
  for (auto const& s : extra_statements) {
    *request.add_extra_statements() = s;
  }
  auto operation = stub_->CreateDatabase(context, request);
  if (!operation) {
    return google::cloud::make_ready_future(
        StatusOr<gcsa::Database>(operation.status()));
  }

  // TODO(#127) - use the (implicit) completion queue to run this loop.
  struct Polling {
    google::cloud::promise<StatusOr<gcsa::Database>> promise;
    google::longrunning::Operation operation;
    std::chrono::seconds wait_time = std::chrono::seconds(2);
  };
  Polling polling_state;
  polling_state.operation = *std::move(operation);

  auto f = polling_state.promise.get_future();

  // TODO(#128) - introduce a polling policy to control the polling loop.
  std::thread t(
      [](std::shared_ptr<internal::DatabaseAdminStub> const& stub,
         Polling ps) mutable {
        auto deadline =
            std::chrono::system_clock::now() + std::chrono::minutes(30);
        while (!ps.operation.done() &&
               std::chrono::system_clock::now() < deadline) {
          auto remaining = deadline - std::chrono::system_clock::now();
          auto sleep = (std::min)(
              remaining,
              std::chrono::duration_cast<decltype(remaining)>(ps.wait_time));
          std::this_thread::sleep_for(sleep);
          grpc::ClientContext poll_context;
          google::longrunning::GetOperationRequest poll_request;
          poll_request.set_name(ps.operation.name());
          auto update = stub->GetOperation(poll_context, poll_request);
          if (!update) {
            ps.promise.set_value(update.status());
            return;
          }
          using std::swap;
          swap(*update, ps.operation);
          // Increase the wait time.
          ps.wait_time *= 2;
        }
        if (ps.operation.done()) {
          if (ps.operation.has_error()) {
            // The long running operation failed, return the error to the
            // caller.
            ps.promise.set_value(ToGoogleCloudStatus(ps.operation.error()));
            return;
          }
          if (!ps.operation.has_response()) {
            ps.promise.set_value(Status(StatusCode::kUnknown,
                                        "CreateDatabase operation completed "
                                        "without error or response, name=" +
                                            ps.operation.name()));
            return;
          }
          google::protobuf::Any const& any = ps.operation.response();
          if (!any.Is<gcsa::Database>()) {
            ps.promise.set_value(Status(StatusCode::kInternal,
                                        "CreateDatabase operation completed "
                                        "with an invalid response type, name=" +
                                            ps.operation.name()));
            return;
          }
          gcsa::Database result;
          any.UnpackTo(&result);
          ps.promise.set_value(std::move(result));
          return;
        }
        ps.promise.set_value(Status(StatusCode::kDeadlineExceeded,
                                    "Deadline exceeded in longrunning "
                                    "operation for CreateDatabase, name=" +
                                        ps.operation.name()));
      },
      stub_, std::move(polling_state));
  t.detach();

  return f;
}

Status DatabaseAdminClient::DropDatabase(std::string const& project_id,
                                         std::string const& instance_id,
                                         std::string const& database_id) {
  grpc::ClientContext context;
  google::spanner::admin::database::v1::DropDatabaseRequest request;
  request.set_database("projects/" + project_id + "/instances/" + instance_id +
                       "/databases/" + database_id);

  return stub_->DropDatabase(context, request);
}

}  // namespace SPANNER_CLIENT_NS
}  // namespace spanner
}  // namespace cloud
}  // namespace google
<commit_msg>bug: Fix flake in DatabaseAdminClient unit test. (googleapis/google-cloud-cpp-spanner#148)<commit_after>// Copyright 2019 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "google/cloud/spanner/database_admin_client.h"
#include "google/cloud/bigtable/internal/grpc_error_delegate.h"
#include <algorithm>

namespace google {
namespace cloud {
namespace spanner {
inline namespace SPANNER_CLIENT_NS {

// TODO(#126) - refactor to some common place. Note that this different from
// the MakeStatusFromGrpcError function,
namespace {
StatusCode MapStatusCode(std::int32_t code) {
  if (code < 0 || code > static_cast<std::int32_t>(StatusCode::kDataLoss)) {
    return StatusCode::kUnknown;
  }
  return static_cast<StatusCode>(code);
}
}  // namespace

google::cloud::Status ToGoogleCloudStatus(google::rpc::Status const& status) {
  return google::cloud::Status(MapStatusCode(status.code()), status.message());
}

namespace gcsa = google::spanner::admin::database::v1;

DatabaseAdminClient::DatabaseAdminClient(ClientOptions const& client_options)
    : stub_(internal::CreateDefaultDatabaseAdminStub(client_options)) {}

future<StatusOr<gcsa::Database>> DatabaseAdminClient::CreateDatabase(
    std::string const& project_id, std::string const& instance_id,
    std::string const& database_id,
    std::vector<std::string> const& extra_statements) {
  grpc::ClientContext context;
  gcsa::CreateDatabaseRequest request;
  request.set_parent("projects/" + project_id + "/instances/" + instance_id);
  request.set_create_statement("CREATE DATABASE `" + database_id + "`");
  for (auto const& s : extra_statements) {
    *request.add_extra_statements() = s;
  }
  auto operation = stub_->CreateDatabase(context, request);
  if (!operation) {
    return google::cloud::make_ready_future(
        StatusOr<gcsa::Database>(operation.status()));
  }

  // TODO(#127) - use the (implicit) completion queue to run this loop.
  struct Polling {
    google::cloud::promise<StatusOr<gcsa::Database>> promise;
    google::longrunning::Operation operation;
    std::chrono::seconds wait_time = std::chrono::seconds(2);
  };
  Polling polling_state;
  polling_state.operation = *std::move(operation);

  auto f = polling_state.promise.get_future();

  // TODO(#128) - introduce a polling policy to control the polling loop.
  std::thread t(
      [](std::shared_ptr<internal::DatabaseAdminStub> stub,
         Polling ps) mutable {
        auto deadline =
            std::chrono::system_clock::now() + std::chrono::minutes(30);
        while (!ps.operation.done() &&
               std::chrono::system_clock::now() < deadline) {
          auto remaining = deadline - std::chrono::system_clock::now();
          auto sleep = (std::min)(
              remaining,
              std::chrono::duration_cast<decltype(remaining)>(ps.wait_time));
          std::this_thread::sleep_for(sleep);
          grpc::ClientContext poll_context;
          google::longrunning::GetOperationRequest poll_request;
          poll_request.set_name(ps.operation.name());
          auto update = stub->GetOperation(poll_context, poll_request);
          if (!update) {
            stub.reset();
            ps.promise.set_value(update.status());
            return;
          }
          using std::swap;
          swap(*update, ps.operation);
          // Increase the wait time.
          ps.wait_time *= 2;
        }
        if (ps.operation.done()) {
          if (ps.operation.has_error()) {
            // The long running operation failed, return the error to the
            // caller.
            stub.reset();
            ps.promise.set_value(ToGoogleCloudStatus(ps.operation.error()));
            return;
          }
          if (!ps.operation.has_response()) {
            stub.reset();
            ps.promise.set_value(Status(StatusCode::kUnknown,
                                        "CreateDatabase operation completed "
                                        "without error or response, name=" +
                                            ps.operation.name()));
            return;
          }
          google::protobuf::Any const& any = ps.operation.response();
          if (!any.Is<gcsa::Database>()) {
            stub.reset();
            ps.promise.set_value(Status(StatusCode::kInternal,
                                        "CreateDatabase operation completed "
                                        "with an invalid response type, name=" +
                                            ps.operation.name()));
            return;
          }
          gcsa::Database result;
          any.UnpackTo(&result);
          stub.reset();
          ps.promise.set_value(std::move(result));
          return;
        }
        stub.reset();
        ps.promise.set_value(Status(StatusCode::kDeadlineExceeded,
                                    "Deadline exceeded in longrunning "
                                    "operation for CreateDatabase, name=" +
                                        ps.operation.name()));
      },
      stub_, std::move(polling_state));
  t.detach();

  return f;
}

Status DatabaseAdminClient::DropDatabase(std::string const& project_id,
                                         std::string const& instance_id,
                                         std::string const& database_id) {
  grpc::ClientContext context;
  google::spanner::admin::database::v1::DropDatabaseRequest request;
  request.set_database("projects/" + project_id + "/instances/" + instance_id +
                       "/databases/" + database_id);

  return stub_->DropDatabase(context, request);
}

}  // namespace SPANNER_CLIENT_NS
}  // namespace spanner
}  // namespace cloud
}  // namespace google
<|endoftext|>