<commit_before>// __BEGIN_LICENSE__
// Copyright (C) 2006-2010 United States Government as represented by
// the Administrator of the National Aeronautics and Space Administration.
// All Rights Reserved.
// __END_LICENSE__

/// Options:
///
///  <none> - If no options are supplied, this utility will create a
///          snapshot of the entire platefile starting with
///          read_cursor and going to the most recent transaction_id.
///          In this mode, the snapshot tool starts and finishes a
///          transaction ID automatically.
///
///  --start - Starts a new multi-part snapshot.  Returns the
///          transaction_id for this snapshot as a return value.
///
///  --finish <transaction_id> - Finish a multi-part snapshot.
///
///   --snapshot <t_begin>:<t_end>:<t_write>@<level> - Creates a
///          snapshot of the mosaic by compositing together tiles from
///          the transaction_id's in the range [t_begin, t_end] and
///          the level specified (the range is inclusive).  New tiles
///          in the snapshot are written using the t_write
///          transaction_id.
///
///  --region <ul_x>,<ul_y>:<lr_x>,<lr_y> - Limit the snapshot to the
///          region bounded by these upper left (ul) and lower right
///          (lr) coordinates.
///

#include <vw/Plate/PlateFile.h>
#include <vw/Plate/SnapshotManager.h>
using namespace vw;
using namespace vw::platefile;

#include <boost/tokenizer.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/program_options.hpp>
namespace po = boost::program_options;

class SnapshotParameters {

  void error(std::string arg, std::string const& params) {
    vw_out(ErrorMessage) << "Error parsing arguments for --" << arg << " : " << params << "\n";
    exit(1);
  }

public:

  // Public variables.  You access these directly.
  int level;
  TransactionOrNeg begin_transaction_id;
  TransactionOrNeg end_transaction_id;
  TransactionOrNeg write_transaction_id;
  bool tweak_settings_for_terrain;
  BBox2i region;

  // Constructor
  SnapshotParameters(std::string const& range_string,
                     std::string const& region_string,
                     TransactionOrNeg write_transaction_id,
                     bool terrain) :
    write_transaction_id(write_transaction_id),
    tweak_settings_for_terrain(terrain) {
    typedef boost::tokenizer<boost::char_separator<char> > tokenizer;
    boost::char_separator<char> sep(",:@");

    // STEP 1 : PARSE RANGE STRING

    if (range_string.empty()) {
      std::cout << "Error: You must specify a transaction_id range "
                << "with the --range option.\n";
      exit(1);

    } else {

      // If the range string is not empty, we attempt to parse the
      // two parameters out from the range string.
      tokenizer tokens(range_string, sep);
      tokenizer::iterator tok_iter = tokens.begin();

      if (tok_iter == tokens.end()) this->error("snapshot", range_string);
      begin_transaction_id = boost::lexical_cast<TransactionOrNeg>(*tok_iter);
      ++tok_iter;

      if (tok_iter == tokens.end()) this->error("snapshot", range_string);
      end_transaction_id = boost::lexical_cast<TransactionOrNeg>(*tok_iter);
      ++tok_iter;

      if (tok_iter != tokens.end()) this->error("snapshot", range_string);

    }

    // STEP 2 : PARSE REGION STRING

    if (region_string.empty()) {

      // If the region string is empty, then the user has not
      // specified the region.  We record this by setting the level to
      // -1;
      level = -1;

    } else {

      // If the argument string is not empty, we attempt to parse the
      // three parameters out from the snapshot string.
      tokenizer tokens(region_string, sep);
      tokenizer::iterator tok_iter = tokens.begin();

      if (tok_iter == tokens.end()) this->error("region", region_string);
      region.min()[0] = boost::lexical_cast<int>(*tok_iter);
      ++tok_iter;

      if (tok_iter == tokens.end()) this->error("region", region_string);
      region.min()[1] = boost::lexical_cast<int>(*tok_iter);
      ++tok_iter;

      if (tok_iter == tokens.end()) this->error("region", region_string);
      region.max()[0] = boost::lexical_cast<int>(*tok_iter);
      ++tok_iter;

      if (tok_iter == tokens.end()) this->error("region", region_string);
      region.max()[1] = boost::lexical_cast<int>(*tok_iter);
      ++tok_iter;

      if (tok_iter == tokens.end()) this->error("snapshot", region_string);
      level = boost::lexical_cast<int>(*tok_iter);
      ++tok_iter;

      if (tok_iter != tokens.end()) this->error("region", region_string);
    }

  }
};

// --------------------------------------------------------------------------
//                                DO_MOSAIC
// --------------------------------------------------------------------------

template <class PixelT>
void do_snapshot(boost::shared_ptr<PlateFile> platefile,
                 SnapshotParameters snapshot_parameters) {

  SnapshotManager<PixelT> sm( platefile );
  if (snapshot_parameters.level != -1) {

    if (snapshot_parameters.write_transaction_id == -1) {
      vw_out(ErrorMessage) << "Error: you must specify a transaction_id for this snapshot "
                           << "using the --transaction_id flag.";
      exit(1);
    }

    std::ostringstream log_description;
    log_description << "Started multi-part snapshot (t_id = "
                    << snapshot_parameters.write_transaction_id
                    << ") -- level:" << snapshot_parameters.level
                    << " region: " << snapshot_parameters.region << "\n";
    platefile->log(log_description.str());

    // Grab a lock on a blob file to use for writing tiles during
    // the two operations below.
    platefile->write_request();

    // If the user has specified a region, then we
    sm.snapshot(snapshot_parameters.level, snapshot_parameters.region,
                snapshot_parameters.begin_transaction_id,
                snapshot_parameters.end_transaction_id,
                snapshot_parameters.write_transaction_id.promote(),
                snapshot_parameters.tweak_settings_for_terrain);

    // Release the blob id lock.
    platefile->write_complete();

    std::ostringstream log_description2;
    log_description2 << "Finished multi-part snapshot (t_id = "
                    << snapshot_parameters.write_transaction_id
                    << ") -- level:" << snapshot_parameters.level
                    << " region: " << snapshot_parameters.region << "\n";
    platefile->log(log_description2.str());

  } else {

    // If no region was specified, then we build a snapshot of the entire
    // platefile.

    // Request a transaction (write_transaction_id might be -1, and that's okay)
    const std::string description = "Full snapshot (requested t_id:  " + vw::stringify(snapshot_parameters.write_transaction_id) + ")";
    Transaction t_id = platefile->transaction_request(description, snapshot_parameters.write_transaction_id);

    // Grab a lock on a blob file to use for writing tiles during
    // the two operations below.
    platefile->write_request();

    // Do a full snapshot
    sm.full_snapshot(snapshot_parameters.begin_transaction_id,
                     snapshot_parameters.end_transaction_id,
                     t_id,
                     snapshot_parameters.tweak_settings_for_terrain);

    // Release the blob id lock and note that the transaction is finished.
    platefile->write_complete();
    platefile->transaction_complete(t_id, true);
  }

}

// --------------------------------------------------------------------------
//                                    MAIN
// --------------------------------------------------------------------------

int main( int argc, char *argv[] ) {

  Url url;
  std::string start_description;
  std::string output_mode;
  std::string range_string;
  std::string region_string;
  TransactionOrNeg transaction_id = -1;

  po::options_description general_options("\nCreate a snapshot of a quadtree.  If no options are supplied, this utility will create a snapshot of the entire platefile starting with read_cursor and going to the max transaction_id.\n\nGeneral options");
  general_options.add_options()
    ("start", po::value<std::string>(&start_description), "where arg = <description> - Starts a new multi-part snapshot.  Returns the transaction_id for this snapshot as a return value.")
    ("finish", "Finish a multi-part snapshot.")
    ("transaction-id,t", po::value(&transaction_id), "Transaction ID to use for starting/finishing/or snapshotting.")
    ("transaction-range", po::value<std::string>(&range_string), "where arg = <t_begin>:<t_end> - Creates a snapshot of the mosaic by compositing together tiles from the transaction_ids in the range [t_begin, t_end] (inclusive).")
    ("region", po::value<std::string>(&region_string), "where arg = <ul_x>,<ul_y>:<lr_x>,<lr_y>@<level> - Limit the snapshot to the region bounded by these upper left (ul) and lower right (lr) coordinates at the level specified.")
    ("terrain", "Tweak settings for terrain.")
    ("help,h", "Display this help message");

  po::options_description hidden_options("");
  hidden_options.add_options()
    ("input-file", po::value(&url), "");

  po::options_description options("Allowed Options");
  options.add(general_options).add(hidden_options);

  po::positional_options_description p;
  p.add("input-file", -1);

  std::ostringstream usage;
  usage << "Usage: " << argv[0] << " <plate_filename> [options]\n";
  usage << general_options << std::endl;

  po::variables_map vm;
  try {
    po::store( po::command_line_parser( argc, argv ).options(options).positional(p).run(), vm );
    po::notify( vm );
  } catch (po::error &e) {
    std::cout << "An error occured while parsing command line arguments.\n";
    std::cout << "\t" << e.what() << "\n\n";
    std::cout << usage.str();
    return 1;
  }

  if( vm.count("help") ) {
    std::cout << usage.str();
    return 1;
  }

  if (vm.count("input-file") != 1) {
    std::cout << usage.str();
    return 1;
  }

  try {

    //--------------------------- OPEN THE PLATE FILE -----------------------------

    std::cout << "\nOpening input plate file: " << url.string() << "\n";
    boost::shared_ptr<PlateFile> platefile =
      boost::shared_ptr<PlateFile>( new PlateFile(url) );

    // std::cout << "\nOpening output plate file: " << output_url << "\n";
    // boost::shared_ptr<PlateFile> output_platefile =
    //   boost::shared_ptr<PlateFile>( new PlateFile(output_url,
    //                                               input_platefile->index_header().type(),
    //                                               input_platefile->index_header().description(),
    //                                               input_platefile->default_tile_size(),
    //                                               input_platefile->default_file_type(),
    //                                               input_platefile->pixel_format(),
    //                                               input_platefile->channel_type()) );

    //------------------------ START/FINISH TRANSACTION ---------------------------

    if (vm.count("start")) {
      if (!vm.count("transaction-id")) {
        std::cout << "You must specify a transaction-id if you use --start.\n";
        exit(1);
      }

      Transaction t = platefile->transaction_request(start_description, transaction_id);
      vw_out() << "Transaction started with ID = " << t << "\n";
      vw_out() << "Plate has " << platefile->num_levels() << " levels.\n";
      exit(0);
    }

    if (vm.count("finish")) {
      if (transaction_id.newest()) {
        vw_out() << "You must specify a transaction-id if you use --finish.\n";
        exit(1);
      }
      // Update the read cursor when the snapshot is complete!
      platefile->transaction_complete(transaction_id.promote(), true);
      vw_out() << "Transaction " << transaction_id << " complete.\n";
      exit(0);
    }

    //---------------------------- SNAPSHOT REQUEST -------------------------------

    // Parse out the rest of the command line options into a special
    // SnapshotParameters class.
    SnapshotParameters snapshot_params(range_string, region_string,
                                       transaction_id, vm.count("terrain"));

    // Dispatch to the compositer based on the pixel type of this mosaic.
    switch(platefile->pixel_format()) {
    case VW_PIXEL_GRAYA:
      switch(platefile->channel_type()) {
      case VW_CHANNEL_UINT8:
        do_snapshot<PixelGrayA<uint8> >(platefile, snapshot_params);
        break;
      case VW_CHANNEL_INT16:
        do_snapshot<PixelGrayA<int16> >(platefile, snapshot_params);
        break;
      case VW_CHANNEL_FLOAT32:
        do_snapshot<PixelGrayA<float32> >(platefile, snapshot_params);
        break;
      default:
        vw_throw(ArgumentErr() << "Image contains a channel type not supported by snapshot.\n");
        exit(1);
      }
      break;

    case VW_PIXEL_RGBA:
      switch(platefile->channel_type()) {
      case VW_CHANNEL_UINT8:
        do_snapshot<PixelRGBA<uint8> >(platefile, snapshot_params);
        break;
      default:
        std::cout << "Platefile contains a channel type not supported by snapshot.\n";
        exit(1);
      }
      break;
    default:
      std::cout << "Image contains a pixel type not supported by snapshot.\n";
      exit(1);
    }

  }  catch (vw::Exception &e) {
    std::cout << "An error occured: " << e.what() << "\nExiting.\n\n";
    exit(1);
  }

}
<commit_msg>snapshot.cc: Fixes the error text that requires a --transaction-range argument<commit_after>// __BEGIN_LICENSE__
// Copyright (C) 2006-2010 United States Government as represented by
// the Administrator of the National Aeronautics and Space Administration.
// All Rights Reserved.
// __END_LICENSE__

/// Options:
///
///  <none> - If no options are supplied, this utility will create a
///          snapshot of the entire platefile starting with
///          read_cursor and going to the most recent transaction_id.
///          In this mode, the snapshot tool starts and finishes a
///          transaction ID automatically.
///
///  --start - Starts a new multi-part snapshot.  Returns the
///          transaction_id for this snapshot as a return value.
///
///  --finish <transaction_id> - Finish a multi-part snapshot.
///
///   --snapshot <t_begin>:<t_end>:<t_write>@<level> - Creates a
///          snapshot of the mosaic by compositing together tiles from
///          the transaction_id's in the range [t_begin, t_end] and
///          the level specified (the range is inclusive).  New tiles
///          in the snapshot are written using the t_write
///          transaction_id.
///
///  --region <ul_x>,<ul_y>:<lr_x>,<lr_y> - Limit the snapshot to the
///          region bounded by these upper left (ul) and lower right
///          (lr) coordinates.
///

#include <vw/Plate/PlateFile.h>
#include <vw/Plate/SnapshotManager.h>
using namespace vw;
using namespace vw::platefile;

#include <boost/tokenizer.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/program_options.hpp>
namespace po = boost::program_options;

class SnapshotParameters {

  void error(std::string arg, std::string const& params) {
    vw_out(ErrorMessage) << "Error parsing arguments for --" << arg << " : " << params << "\n";
    exit(1);
  }

public:

  // Public variables.  You access these directly.
  int level;
  TransactionOrNeg begin_transaction_id;
  TransactionOrNeg end_transaction_id;
  TransactionOrNeg write_transaction_id;
  bool tweak_settings_for_terrain;
  BBox2i region;

  // Constructor
  SnapshotParameters(std::string const& range_string,
                     std::string const& region_string,
                     TransactionOrNeg write_transaction_id,
                     bool terrain) :
    write_transaction_id(write_transaction_id),
    tweak_settings_for_terrain(terrain) {
    typedef boost::tokenizer<boost::char_separator<char> > tokenizer;
    boost::char_separator<char> sep(",:@");

    // STEP 1 : PARSE RANGE STRING

    if (range_string.empty()) {
      std::cout << "Error: You must specify a transaction_id range "
                << "with the --transaction-range option.\n";
      exit(1);

    } else {

      // If the range string is not empty, we attempt to parse the
      // two parameters out from the range string.
      tokenizer tokens(range_string, sep);
      tokenizer::iterator tok_iter = tokens.begin();

      if (tok_iter == tokens.end()) this->error("snapshot", range_string);
      begin_transaction_id = boost::lexical_cast<TransactionOrNeg>(*tok_iter);
      ++tok_iter;

      if (tok_iter == tokens.end()) this->error("snapshot", range_string);
      end_transaction_id = boost::lexical_cast<TransactionOrNeg>(*tok_iter);
      ++tok_iter;

      if (tok_iter != tokens.end()) this->error("snapshot", range_string);

    }

    // STEP 2 : PARSE REGION STRING

    if (region_string.empty()) {

      // If the region string is empty, then the user has not
      // specified the region.  We record this by setting the level to
      // -1;
      level = -1;

    } else {

      // If the argument string is not empty, we attempt to parse the
      // three parameters out from the snapshot string.
      tokenizer tokens(region_string, sep);
      tokenizer::iterator tok_iter = tokens.begin();

      if (tok_iter == tokens.end()) this->error("region", region_string);
      region.min()[0] = boost::lexical_cast<int>(*tok_iter);
      ++tok_iter;

      if (tok_iter == tokens.end()) this->error("region", region_string);
      region.min()[1] = boost::lexical_cast<int>(*tok_iter);
      ++tok_iter;

      if (tok_iter == tokens.end()) this->error("region", region_string);
      region.max()[0] = boost::lexical_cast<int>(*tok_iter);
      ++tok_iter;

      if (tok_iter == tokens.end()) this->error("region", region_string);
      region.max()[1] = boost::lexical_cast<int>(*tok_iter);
      ++tok_iter;

      if (tok_iter == tokens.end()) this->error("snapshot", region_string);
      level = boost::lexical_cast<int>(*tok_iter);
      ++tok_iter;

      if (tok_iter != tokens.end()) this->error("region", region_string);
    }

  }
};

// --------------------------------------------------------------------------
//                                DO_MOSAIC
// --------------------------------------------------------------------------

template <class PixelT>
void do_snapshot(boost::shared_ptr<PlateFile> platefile,
                 SnapshotParameters snapshot_parameters) {

  SnapshotManager<PixelT> sm( platefile );
  if (snapshot_parameters.level != -1) {

    if (snapshot_parameters.write_transaction_id == -1) {
      vw_out(ErrorMessage) << "Error: you must specify a transaction_id for this snapshot "
                           << "using the --transaction_id flag.";
      exit(1);
    }

    std::ostringstream log_description;
    log_description << "Started multi-part snapshot (t_id = "
                    << snapshot_parameters.write_transaction_id
                    << ") -- level:" << snapshot_parameters.level
                    << " region: " << snapshot_parameters.region << "\n";
    platefile->log(log_description.str());

    // Grab a lock on a blob file to use for writing tiles during
    // the two operations below.
    platefile->write_request();

    // If the user has specified a region, then we
    sm.snapshot(snapshot_parameters.level, snapshot_parameters.region,
                snapshot_parameters.begin_transaction_id,
                snapshot_parameters.end_transaction_id,
                snapshot_parameters.write_transaction_id.promote(),
                snapshot_parameters.tweak_settings_for_terrain);

    // Release the blob id lock.
    platefile->write_complete();

    std::ostringstream log_description2;
    log_description2 << "Finished multi-part snapshot (t_id = "
                    << snapshot_parameters.write_transaction_id
                    << ") -- level:" << snapshot_parameters.level
                    << " region: " << snapshot_parameters.region << "\n";
    platefile->log(log_description2.str());

  } else {

    // If no region was specified, then we build a snapshot of the entire
    // platefile.

    // Request a transaction (write_transaction_id might be -1, and that's okay)
    const std::string description = "Full snapshot (requested t_id:  " + vw::stringify(snapshot_parameters.write_transaction_id) + ")";
    Transaction t_id = platefile->transaction_request(description, snapshot_parameters.write_transaction_id);

    // Grab a lock on a blob file to use for writing tiles during
    // the two operations below.
    platefile->write_request();

    // Do a full snapshot
    sm.full_snapshot(snapshot_parameters.begin_transaction_id,
                     snapshot_parameters.end_transaction_id,
                     t_id,
                     snapshot_parameters.tweak_settings_for_terrain);

    // Release the blob id lock and note that the transaction is finished.
    platefile->write_complete();
    platefile->transaction_complete(t_id, true);
  }

}

// --------------------------------------------------------------------------
//                                    MAIN
// --------------------------------------------------------------------------

int main( int argc, char *argv[] ) {

  Url url;
  std::string start_description;
  std::string output_mode;
  std::string range_string;
  std::string region_string;
  TransactionOrNeg transaction_id = -1;

  po::options_description general_options("\nCreate a snapshot of a quadtree.  If no options are supplied, this utility will create a snapshot of the entire platefile starting with read_cursor and going to the max transaction_id.\n\nGeneral options");
  general_options.add_options()
    ("start", po::value<std::string>(&start_description), "where arg = <description> - Starts a new multi-part snapshot.  Returns the transaction_id for this snapshot as a return value.")
    ("finish", "Finish a multi-part snapshot.")
    ("transaction-id,t", po::value(&transaction_id), "Transaction ID to use for starting/finishing/or snapshotting.")
    ("transaction-range", po::value<std::string>(&range_string), "where arg = <t_begin>:<t_end> - Creates a snapshot of the mosaic by compositing together tiles from the transaction_ids in the range [t_begin, t_end] (inclusive).")
    ("region", po::value<std::string>(&region_string), "where arg = <ul_x>,<ul_y>:<lr_x>,<lr_y>@<level> - Limit the snapshot to the region bounded by these upper left (ul) and lower right (lr) coordinates at the level specified.")
    ("terrain", "Tweak settings for terrain.")
    ("help,h", "Display this help message");

  po::options_description hidden_options("");
  hidden_options.add_options()
    ("input-file", po::value(&url), "");

  po::options_description options("Allowed Options");
  options.add(general_options).add(hidden_options);

  po::positional_options_description p;
  p.add("input-file", -1);

  std::ostringstream usage;
  usage << "Usage: " << argv[0] << " <plate_filename> [options]\n";
  usage << general_options << std::endl;

  po::variables_map vm;
  try {
    po::store( po::command_line_parser( argc, argv ).options(options).positional(p).run(), vm );
    po::notify( vm );
  } catch (po::error &e) {
    std::cout << "An error occured while parsing command line arguments.\n";
    std::cout << "\t" << e.what() << "\n\n";
    std::cout << usage.str();
    return 1;
  }

  if( vm.count("help") ) {
    std::cout << usage.str();
    return 1;
  }

  if (vm.count("input-file") != 1) {
    std::cout << usage.str();
    return 1;
  }

  try {

    //--------------------------- OPEN THE PLATE FILE -----------------------------

    std::cout << "\nOpening input plate file: " << url.string() << "\n";
    boost::shared_ptr<PlateFile> platefile =
      boost::shared_ptr<PlateFile>( new PlateFile(url) );

    // std::cout << "\nOpening output plate file: " << output_url << "\n";
    // boost::shared_ptr<PlateFile> output_platefile =
    //   boost::shared_ptr<PlateFile>( new PlateFile(output_url,
    //                                               input_platefile->index_header().type(),
    //                                               input_platefile->index_header().description(),
    //                                               input_platefile->default_tile_size(),
    //                                               input_platefile->default_file_type(),
    //                                               input_platefile->pixel_format(),
    //                                               input_platefile->channel_type()) );

    //------------------------ START/FINISH TRANSACTION ---------------------------

    if (vm.count("start")) {
      if (!vm.count("transaction-id")) {
        std::cout << "You must specify a transaction-id if you use --start.\n";
        exit(1);
      }

      Transaction t = platefile->transaction_request(start_description, transaction_id);
      vw_out() << "Transaction started with ID = " << t << "\n";
      vw_out() << "Plate has " << platefile->num_levels() << " levels.\n";
      exit(0);
    }

    if (vm.count("finish")) {
      if (transaction_id.newest()) {
        vw_out() << "You must specify a transaction-id if you use --finish.\n";
        exit(1);
      }
      // Update the read cursor when the snapshot is complete!
      platefile->transaction_complete(transaction_id.promote(), true);
      vw_out() << "Transaction " << transaction_id << " complete.\n";
      exit(0);
    }

    //---------------------------- SNAPSHOT REQUEST -------------------------------

    // Parse out the rest of the command line options into a special
    // SnapshotParameters class.
    SnapshotParameters snapshot_params(range_string, region_string,
                                       transaction_id, vm.count("terrain"));

    // Dispatch to the compositer based on the pixel type of this mosaic.
    switch(platefile->pixel_format()) {
    case VW_PIXEL_GRAYA:
      switch(platefile->channel_type()) {
      case VW_CHANNEL_UINT8:
        do_snapshot<PixelGrayA<uint8> >(platefile, snapshot_params);
        break;
      case VW_CHANNEL_INT16:
        do_snapshot<PixelGrayA<int16> >(platefile, snapshot_params);
        break;
      case VW_CHANNEL_FLOAT32:
        do_snapshot<PixelGrayA<float32> >(platefile, snapshot_params);
        break;
      default:
        vw_throw(ArgumentErr() << "Image contains a channel type not supported by snapshot.\n");
        exit(1);
      }
      break;

    case VW_PIXEL_RGBA:
      switch(platefile->channel_type()) {
      case VW_CHANNEL_UINT8:
        do_snapshot<PixelRGBA<uint8> >(platefile, snapshot_params);
        break;
      default:
        std::cout << "Platefile contains a channel type not supported by snapshot.\n";
        exit(1);
      }
      break;
    default:
      std::cout << "Image contains a pixel type not supported by snapshot.\n";
      exit(1);
    }

  }  catch (vw::Exception &e) {
    std::cout << "An error occured: " << e.what() << "\nExiting.\n\n";
    exit(1);
  }

}
<|endoftext|>


<commit_before>#include <munin/button.hpp>
#include <munin/compass_layout.hpp>
#include <munin/filled_box.hpp>
#include <munin/image.hpp>
#include <munin/view.hpp>
#include <munin/window.hpp>
#include <terminalpp/canvas.hpp>
#include <terminalpp/string.hpp>
#include <terminalpp/terminal.hpp>
#include <consolepp/console.hpp>
#include <boost/asio/io_context.hpp>

using namespace terminalpp::literals;

struct window_event_dispatcher : public boost::static_visitor<>
{
    explicit window_event_dispatcher(munin::window &window)
      : window_(window)
    {
    }

    template <class Event>
    void operator()(Event const &event)
    {
        window_.event(event);
    }

    munin::window &window_;
};

void schedule_read(consolepp::console &console, terminalpp::terminal &terminal)
{
    console.async_read(
        [&](consolepp::bytes data)
        {
            terminal >> data;
            schedule_read(console, terminal);
        });
}

auto make_content(auto &button)
{
    return munin::view(
        munin::make_compass_layout(),
        munin::make_image("Hello, \\p-world!"_ets),
        munin::compass_layout::heading::centre,
        munin::view(
            munin::make_compass_layout(),
            munin::make_fill(' '),
            munin::compass_layout::heading::centre,
            button,
            munin::compass_layout::heading::east
        ),
        munin::compass_layout::heading::south);
}

auto make_behaviour()
{
    terminalpp::behaviour behaviour;
    behaviour.supports_basic_mouse_tracking = true;
    behaviour.supports_window_title_bel = true;
    return behaviour;
}

int main()
{
    auto button = munin::make_button(" OK ");
    munin::window window{make_content(button)};

    boost::asio::io_context io_context;
    consolepp::console console{io_context};
    terminalpp::canvas canvas{{console.size().width, console.size().height}};
    window_event_dispatcher event_dispatcher{window};

    terminalpp::terminal terminal{
        [&](terminalpp::tokens tokens) {
            for (const auto& token : tokens)
            {
                boost::apply_visitor(event_dispatcher, token);
            }
        },
        [&](terminalpp::bytes data) {
            console.write(data);
        },
        make_behaviour()
    };

    auto const &repaint_window = [&]() { window.repaint(canvas, terminal); };

    window.on_repaint_request.connect(repaint_window);
    console.on_size_changed.connect(
        [&]
        {
            auto const new_size = console.size();
            canvas.resize({new_size.width, new_size.height});
            repaint_window();
        });

    terminal
        << terminalpp::enable_mouse()
        << terminalpp::hide_cursor()
        << terminalpp::use_alternate_screen_buffer()
        << terminalpp::set_window_title("hello_console");

    auto work_guard = boost::asio::make_work_guard(io_context);
    button->on_click.connect([&]{
        io_context.stop();
        work_guard.reset();
    });
    button->set_focus();

    schedule_read(console, terminal);

    io_context.run();
    terminal
        << terminalpp::use_normal_screen_buffer()
        << terminalpp::show_cursor()
        << terminalpp::disable_mouse();
}
<commit_msg>Updated console program as well.<commit_after>#include <munin/button.hpp>
#include <munin/compass_layout.hpp>
#include <munin/filled_box.hpp>
#include <munin/image.hpp>
#include <munin/view.hpp>
#include <munin/window.hpp>
#include <terminalpp/canvas.hpp>
#include <terminalpp/string.hpp>
#include <terminalpp/terminal.hpp>
#include <consolepp/console.hpp>
#include <boost/asio/io_context.hpp>

using namespace terminalpp::literals;

namespace {

struct window_event_dispatcher : public boost::static_visitor<>
{
    window_event_dispatcher(munin::window &window)
      : window_{window}
    {
    }

    template <class Event>
    void operator()(Event const &event)
    {
        window_.event(event);
    }

    munin::window &window_;
};

void schedule_read(consolepp::console &console, terminalpp::terminal &terminal)
{
    console.async_read(
        [&](consolepp::bytes data)
        {
            terminal >> data;
            schedule_read(console, terminal);
        });
}

auto make_content(auto &button)
{
    return munin::view(
        munin::make_compass_layout(),
        munin::make_image("Hello, \\p-world!"_ets),
        munin::compass_layout::heading::centre,
        munin::view(
            munin::make_compass_layout(),
            munin::make_fill(' '),
            munin::compass_layout::heading::centre,
            button,
            munin::compass_layout::heading::east
        ),
        munin::compass_layout::heading::south);
}

auto make_behaviour()
{
    terminalpp::behaviour behaviour;
    behaviour.supports_basic_mouse_tracking = true;
    behaviour.supports_window_title_bel = true;
    return behaviour;
}

class hello_console
{
public:
    void run()
    {
        terminalpp::canvas canvas{{
            console_.size().width, console_.size().height}};

        auto const &repaint_window = [&]() { window_.repaint(canvas); };
        window_.on_repaint_request.connect(repaint_window);

        console_.on_size_changed.connect(
            [&]
            {
                auto const new_size = console_.size();
                canvas.resize({new_size.width, new_size.height});
                repaint_window();
            });

        terminal_
            << terminalpp::enable_mouse()
            << terminalpp::hide_cursor()
            << terminalpp::use_alternate_screen_buffer()
            << terminalpp::set_window_title("hello_console");

        auto work_guard = boost::asio::make_work_guard(io_context_);
        button_->on_click.connect([&]{
            io_context_.stop();
            work_guard.reset();
        });
        button_->set_focus();

        schedule_read(console_, terminal_);

        io_context_.run();
        terminal_
            << terminalpp::use_normal_screen_buffer()
            << terminalpp::show_cursor()
            << terminalpp::disable_mouse();
    }

private:
    boost::asio::io_context io_context_;
    consolepp::console console_{io_context_};

    terminalpp::terminal terminal_{
        [this](terminalpp::tokens tokens) {
            for (const auto &token : tokens)
            {
                boost::apply_visitor(event_dispatcher_, token);
            }
        },
        [this](terminalpp::bytes data) {
            console_.write(data);
        },
        make_behaviour()
    };

    std::shared_ptr<munin::button> button_{munin::make_button(" OK ")};
    munin::window window_{terminal_, make_content(button_)};
    window_event_dispatcher event_dispatcher_{window_};
};

}

int main()
{
    hello_console app;
    app.run();
}
<|endoftext|>


<commit_before>#ifndef DUNE_STUFF_TUPLE_HH
#define DUNE_STUFF_TUPLE_HH

#include <dune/common/tuples.hh>
//#include <dune/fem/misc/femtuples.hh>

namespace Stuff {

//! split our function wrapper into sep pointers for Datawriter input
template < class T1, class T2 = T1, class T3 = T2, class T4 = T3>
struct TupleSerializer {
	typedef Dune::Tuple<	const typename T1::DiscreteVelocityFunctionType*,
							const typename T1::DiscretePressureFunctionType*,
							const typename T2::DiscreteVelocityFunctionType*,
							const typename T2::DiscretePressureFunctionType*,
							const typename T3::DiscreteVelocityFunctionType*,
							const typename T3::DiscretePressureFunctionType*,
							const typename T4::DiscreteVelocityFunctionType*,
							const typename T4::DiscretePressureFunctionType*>
		TupleType;

	static TupleType& getTuple( T1& t1,
								T2& t2,
								T3& t3,
								T4& t4)
	{
		//yay for dangling pointers, but using a local static here fubared sequential runs with diff grid
		TupleType* t = new  TupleType( &(t1.discreteVelocity()),
							&(t1.discretePressure()),
							&(t2.discreteVelocity()),
							&(t2.discretePressure()),
							&(t3.discreteVelocity()),
							&(t3.discretePressure()),
							&(t4.discreteVelocity()),
							&(t4.discretePressure()));
		return *t;
	}
	static TupleType& getTuple( T1& t1,
								T2& t2,
								T3& t3)
	{
		//yay for dangling pointers, but using a local static here fubared sequential runs with diff grid
		TupleType* t = new  TupleType( &(t1.discreteVelocity()),
							&(t1.discretePressure()),
							&(t2.discreteVelocity()),
							&(t2.discretePressure()),
							&(t3.discreteVelocity()),
							&(t3.discretePressure()),
							NULL, NULL);
		return *t;
	}
	static TupleType& getTuple( T1& t1,
								T2& t2 )
	{
		//yay for dangling pointers, but using a local static here fubared sequential runs with diff grid
		TupleType* t = new  TupleType( &(t1.discreteVelocity()),
							&(t1.discretePressure()),
							&(t2.discreteVelocity()),
							&(t2.discretePressure()),
							NULL, NULL, NULL, NULL );
		return *t;
	}
	static TupleType& getTuple( T1& t1 )
	{
		//yay for dangling pointers, but using a local static here fubared sequential runs with diff grid
		TupleType* t = new  TupleType( &(t1.discreteVelocity()),
							&(t1.discretePressure()),
							NULL, NULL, NULL, NULL, NULL, NULL );
		return *t;
	}
};

template <	class T1, class T2 = T1, class T3 = T1,
			class T4 = T1, class T5 = T1, class T6 = T1,
			class T7 = T1, class T8 = T1, class T9 = T1 >
struct FullTuple : public Dune::Tuple<T1,T2,T3,T4,T5,T6,T7,T8,T9>
{
	FullTuple( T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6, T7 t7, T8 t8, T9 t9 )
		: Dune::Tuple<T1,T2,T3,T4,T5,T6,T7,T8,T9>(t1,t2,t3,t4,t5,t6,t7,t8,t9)
	{}
};

template < class T1 >
Dune::Tuple<T1> makeTuple( T1& t1 )
{ return Dune::Tuple<T1>(t1); }

template < class T1, class T2 >
Dune::Tuple<T1,T2> makeTuple( T1& t1, T2& t2 )
{ return Dune::Tuple<T1,T2>(t1,t2); }

} //namespace Stuff {
#endif // DUNE_STUFF_TUPLE_HH
<commit_msg>use Dune::tuple instead of Dune::Tuple<commit_after>#ifndef DUNE_STUFF_TUPLE_HH
#define DUNE_STUFF_TUPLE_HH

#include <dune/common/tuples.hh>
//#include <dune/fem/misc/femtuples.hh>

namespace Stuff {

//! split our function wrapper into sep pointers for Datawriter input
template < class T1, class T2 = T1, class T3 = T2, class T4 = T3>
struct TupleSerializer {
	typedef Dune::tuple<	const typename T1::DiscreteVelocityFunctionType*,
							const typename T1::DiscretePressureFunctionType*,
							const typename T2::DiscreteVelocityFunctionType*,
							const typename T2::DiscretePressureFunctionType*,
							const typename T3::DiscreteVelocityFunctionType*,
							const typename T3::DiscretePressureFunctionType*,
							const typename T4::DiscreteVelocityFunctionType*,
							const typename T4::DiscretePressureFunctionType*>
		TupleType;

	static TupleType& getTuple( T1& t1,
								T2& t2,
								T3& t3,
								T4& t4)
	{
		//yay for dangling pointers, but using a local static here fubared sequential runs with diff grid
		TupleType* t = new  TupleType( &(t1.discreteVelocity()),
							&(t1.discretePressure()),
							&(t2.discreteVelocity()),
							&(t2.discretePressure()),
							&(t3.discreteVelocity()),
							&(t3.discretePressure()),
							&(t4.discreteVelocity()),
							&(t4.discretePressure()));
		return *t;
	}
	static TupleType& getTuple( T1& t1,
								T2& t2,
								T3& t3)
	{
		//yay for dangling pointers, but using a local static here fubared sequential runs with diff grid
		TupleType* t = new  TupleType( &(t1.discreteVelocity()),
							&(t1.discretePressure()),
							&(t2.discreteVelocity()),
							&(t2.discretePressure()),
							&(t3.discreteVelocity()),
							&(t3.discretePressure()),
							nullptr, nullptr);
		return *t;
	}
	static TupleType& getTuple( T1& t1,
								T2& t2 )
	{
		//yay for dangling pointers, but using a local static here fubared sequential runs with diff grid
		TupleType* t = new  TupleType( &(t1.discreteVelocity()),
							&(t1.discretePressure()),
							&(t2.discreteVelocity()),
							&(t2.discretePressure()),
							nullptr, nullptr, nullptr, nullptr );
		return *t;
	}
	static TupleType& getTuple( T1& t1 )
	{
		//yay for dangling pointers, but using a local static here fubared sequential runs with diff grid
		TupleType* t = new  TupleType( &(t1.discreteVelocity()),
							&(t1.discretePressure()),
							nullptr, nullptr, nullptr, nullptr, nullptr, nullptr );
		return *t;
	}
};

template <	class T1, class T2 = T1, class T3 = T1,
			class T4 = T1, class T5 = T1, class T6 = T1,
			class T7 = T1, class T8 = T1, class T9 = T1 >
struct FullTuple : public Dune::tuple<T1,T2,T3,T4,T5,T6,T7,T8,T9>
{
	FullTuple( T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6, T7 t7, T8 t8, T9 t9 )
		: Dune::tuple<T1,T2,T3,T4,T5,T6,T7,T8,T9>(t1,t2,t3,t4,t5,t6,t7,t8,t9)
	{}
};

template < class T1 >
Dune::Tuple<T1> makeTuple( T1& t1 )
{ return Dune::tuple<T1>(t1); }

template < class T1, class T2 >
Dune::Tuple<T1,T2> makeTuple( T1& t1, T2& t2 )
{ return Dune::tuple<T1,T2>(t1,t2); }

} //namespace Stuff {
#endif // DUNE_STUFF_TUPLE_HH
<|endoftext|>


<commit_before>#include <iostream>
#include <string>
#include <vector>

using namespace std;

//util classes
struct Input {
	int r, c, l, h;
	vector<vector<bool>> tomatoes;
};

struct Slice {
	int r1, c1, r2, c2;
};

struct Output {
	vector<Slice> slices;
};

bool checkSliceHorizontal(Input &input, Slice &s)
{
	bool t = false;
	bool f = false;
	for (int j = s.c1; j <= s.c2; j++)
	{
		if (input.tomatoes[s.r1][j])
			t = true;
		else
			f = true;

		if (t == true && f == true)
			return true;
	}
	return false;
}

bool checkSliceVertical(Input &input, Slice &s)
{
	bool t = false;
	bool f = false;
	for (int i = s.r1; i <= s.r2; i++)
	{
		if (input.tomatoes[i][s.c1])
			t = true;
		else
			f = true;

		if (t == true && f == true)
			return true;
	}
	return false;
}

void solveSimpleHorizontal(Input& input, Output& output) {
	for (int i = 0; i < input.r; i++)
	{
		for (int j = 0; j < input.c; j += input.h)
		{
			Slice s;
			s.r1 = i;
			s.c1 = j;
			s.r2 = i;
			s.c2 = min(j+input.h-1, input.c-1);
			if (checkSliceHorizontal(input, s))
				output.slices.push_back(s);
		}
	}
}

void solveSimpleVertical(Input& input, Output& output) {
	for (int j = 0; j < input.c; j++)
	{
		for (int i = 0; i < input.r; i += input.h)
		{
			Slice s;
			s.r1 = i;
			s.c1 = j;
			s.r2 = min(i+input.h-1, input.r-1);
			s.c2 = j;
			if (checkSliceVertical(input, s))
				output.slices.push_back(s);
		}
	}
}

int add_slice(const vector<bool> &a, int l, int r, int cnt_min)	{
	int cnt1 = 0, cnt2 = 0;
	for (int i = l; i <= r; i++)
		if (a[i])
			cnt1++;
		else
			cnt2++;

	if (cnt1 >= cnt_min && cnt2 >= cnt_min)
		return r-l+1;
	return 0;
}

void solve_row(const vector<bool> &a, int row_num, int n, int l, int h, vector<Slice> &ans)	{
	vector<int> d(n,0), prev(n,0);

	for (int i = 0; i < n; i++)
		for (int j = 2*l; j <= h; j++)
			 if (i-j+1 >= 0)
			 {
			 	int temp = add_slice(a,i-j+1,i,l);
			 	int prev_res = (i-j >= 0 ? d[i-j] : 0);
				if (d[i] < prev_res + temp)
				{
			 		d[i] = prev_res + temp;
					prev[i] = i-j+1;
			 	}
			}

	//for (int i = 0; i < n; i++)
	//	cerr << d[i] << ' ' << prev[i] << endl;;
	//cerr << endl;

	int i_max = 0;
	for (int i = 0; i < n; i++)
		if (d[i] > d[i_max])
			i_max = i;

	Slice c;
	c.r1 = c.r2 = row_num;

	for (int i = i_max; i > 0;)
	{
		c.c1 = prev[i]; c.c2 = i;
		i = prev[i]-1;
		ans.push_back(c);
	}
}

void solveDP(Input& input, Output& output) {

	for (int i = 0; i < input.r; i++)
		solve_row(input.tomatoes[i],i,input.c,input.l,input.h,output.slices);
}

//input/output code
int main(int argc, char* argv[]) {
	ios::sync_with_stdio(false);

	//read input
	Input input;
	cin >> input.r >> input.c >> input.l >> input.h;
	for(int i = 0; i < input.r; i++) {
		vector<bool> row(input.c);
		for(int j = 0; j < input.c; j++) {
			char cell;
			cin >> cell;
			row[j] = cell == 'T';
		}
		input.tomatoes.push_back(row);
		//TODO do we read line breaks?
	}

	//read command line args
	string algorithm = "simplehorizontal";
	if(argc > 1) {
		algorithm = argv[1];
	}

	//solve problem
	Output output;
	cerr << "using algorithm " << algorithm << endl;
	if(algorithm == "simplehorizontal") {
		solveSimpleHorizontal(input, output);
	}
	else if(algorithm == "simplevertical") {
		solveSimpleVertical(input, output);
	}
	else if(algorithm == "dp") {
		solveDP(input, output);
	}
	else {
		cerr << "unknown algorithm" << endl;
		return 1;
	}

	//print output
	cout << output.slices.size() << endl;
	int area = 0;
	for(Slice slice: output.slices) {
		area += (slice.r2 - slice.r1 + 1) * (slice.c2 - slice.c1 + 1);
		cout << slice.r1 << ' ' << slice.c1 << ' ' << slice.r2 << ' ' << slice.c2 << endl;
	}
	cerr << area << endl;
};
<commit_msg>improve debug output<commit_after>#include <iostream>
#include <string>
#include <vector>

using namespace std;

//util classes
struct Input {
	int r, c, l, h;
	vector<vector<bool>> tomatoes;
};

struct Slice {
	int r1, c1, r2, c2;
};

struct Output {
	vector<Slice> slices;
};

bool checkSliceHorizontal(Input &input, Slice &s)
{
	bool t = false;
	bool f = false;
	for (int j = s.c1; j <= s.c2; j++)
	{
		if (input.tomatoes[s.r1][j])
			t = true;
		else
			f = true;

		if (t == true && f == true)
			return true;
	}
	return false;
}

bool checkSliceVertical(Input &input, Slice &s)
{
	bool t = false;
	bool f = false;
	for (int i = s.r1; i <= s.r2; i++)
	{
		if (input.tomatoes[i][s.c1])
			t = true;
		else
			f = true;

		if (t == true && f == true)
			return true;
	}
	return false;
}

void solveSimpleHorizontal(Input& input, Output& output) {
	for (int i = 0; i < input.r; i++)
	{
		for (int j = 0; j < input.c; j += input.h)
		{
			Slice s;
			s.r1 = i;
			s.c1 = j;
			s.r2 = i;
			s.c2 = min(j+input.h-1, input.c-1);
			if (checkSliceHorizontal(input, s))
				output.slices.push_back(s);
		}
	}
}

void solveSimpleVertical(Input& input, Output& output) {
	for (int j = 0; j < input.c; j++)
	{
		for (int i = 0; i < input.r; i += input.h)
		{
			Slice s;
			s.r1 = i;
			s.c1 = j;
			s.r2 = min(i+input.h-1, input.r-1);
			s.c2 = j;
			if (checkSliceVertical(input, s))
				output.slices.push_back(s);
		}
	}
}

int add_slice(const vector<bool> &a, int l, int r, int cnt_min)	{
	int cnt1 = 0, cnt2 = 0;
	for (int i = l; i <= r; i++)
		if (a[i])
			cnt1++;
		else
			cnt2++;

	if (cnt1 >= cnt_min && cnt2 >= cnt_min)
		return r-l+1;
	return 0;
}

void solve_row(const vector<bool> &a, int row_num, int n, int l, int h, vector<Slice> &ans)	{
	vector<int> d(n,0), prev(n,0);

	for (int i = 0; i < n; i++)
		for (int j = 2*l; j <= h; j++)
			 if (i-j+1 >= 0)
			 {
			 	int temp = add_slice(a,i-j+1,i,l);
			 	int prev_res = (i-j >= 0 ? d[i-j] : 0);
				if (d[i] < prev_res + temp)
				{
			 		d[i] = prev_res + temp;
					prev[i] = i-j+1;
			 	}
			}

	//for (int i = 0; i < n; i++)
	//	cerr << d[i] << ' ' << prev[i] << endl;;
	//cerr << endl;

	int i_max = 0;
	for (int i = 0; i < n; i++)
		if (d[i] > d[i_max])
			i_max = i;

	Slice c;
	c.r1 = c.r2 = row_num;

	for (int i = i_max; i > 0;)
	{
		c.c1 = prev[i]; c.c2 = i;
		i = prev[i]-1;
		ans.push_back(c);
	}
}

void solveDP(Input& input, Output& output) {

	for (int i = 0; i < input.r; i++)
		solve_row(input.tomatoes[i],i,input.c,input.l,input.h,output.slices);
}

//input/output code
int main(int argc, char* argv[]) {
	ios::sync_with_stdio(false);

	//read input
	Input input;
	cin >> input.r >> input.c >> input.l >> input.h;
	for(int i = 0; i < input.r; i++) {
		vector<bool> row(input.c);
		for(int j = 0; j < input.c; j++) {
			char cell;
			cin >> cell;
			row[j] = cell == 'T';
		}
		input.tomatoes.push_back(row);
		//TODO do we read line breaks?
	}

	//read command line args
	string algorithm = "simplehorizontal";
	if(argc > 1) {
		algorithm = argv[1];
	}

	//solve problem
	Output output;
	cerr << "using algorithm " << algorithm << endl;
	if(algorithm == "simplehorizontal") {
		solveSimpleHorizontal(input, output);
	}
	else if(algorithm == "simplevertical") {
		solveSimpleVertical(input, output);
	}
	else if(algorithm == "dp") {
		solveDP(input, output);
	}
	else {
		cerr << "unknown algorithm" << endl;
		return 1;
	}

	//print output
	cout << output.slices.size() << endl;
	int area = 0;
	for(Slice slice: output.slices) {
		area += (slice.r2 - slice.r1 + 1) * (slice.c2 - slice.c1 + 1);
		cout << slice.r1 << ' ' << slice.c1 << ' ' << slice.r2 << ' ' << slice.c2 << endl;
	}
	cerr << "cells used: " << area << endl;
};
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2013 Juniper Networks, Inc. All rights reserved.
 */

#include <boost/bind.hpp>
#include <boost/function.hpp>
#include "base/util.h"
#include "base/test/task_test_util.h"
#include <iomanip>
#include <ctype.h>
#include <iostream>
#include <algorithm>
#include <sstream>
#include <unistd.h>
#include <stdlib.h>
#include <rapidjson/stringbuffer.h>
#include <boost/algorithm/string.hpp>
#include <boost/algorithm/string/predicate.hpp>

#include "vncapi.h"

RespBlock::RespBlock(HttpConnection *c, std::string uri,
            boost::function<void(rapidjson::Document&,
                boost::system::error_code&, std::string, int, std::string,
                std::map<std::string, std::string>*)> cb):
        conn_(c), uri_(uri), cb_(cb)
{
}

HttpConnection *
RespBlock::GetConnection()
{
    return conn_;
}

void
RespBlock::AddBody(std::string s)
{
    body_ += s;
}

void
RespBlock::Clear(HttpConnection *c)
{
    body_.clear();
    if (c)
        conn_ = c;
}

std::string
RespBlock::GetBody()
{
    return body_;
}

std::string
RespBlock::GetUri()
{
    return uri_;
}

void
RespBlock::ShowDetails()
{
    std::cout << conn_->Version() << "->"
        << conn_->Reason() << "(" << conn_->Status() << ")\n";
}

boost::function<void(rapidjson::Document&, boost::system::error_code&,
        std::string, int, std::string, std::map<std::string, std::string>*)>
RespBlock::GetCallBack()
{
    return cb_;
}

#define CHR_PER_LN 16
void
VncApi::hex_dump(std::string s)
{
//#define __DEBUG__ 1
#ifdef __DEBUG__
    unsigned long a = 0;
    int rem = s.length();
    const char *p = s.c_str();
    while (rem > 0) {
        std::cout << std::setfill('0') << std::setw(8) << std::hex << a;
        for (int i = 0; i < CHR_PER_LN; i++) {
            if( i % 8 == 0 ) std::cout << ' ';
            if ( i < rem )
                std::cout << ' ' << std::setfill('0') << std::setw(2) <<
                    std::hex << (unsigned) p[i];
            else
                std::cout << "   ";
        }
        std::cout << "   ";
        for (int i = 0; i < rem && i < CHR_PER_LN; i++)
            if (isprint(p[i]))
                std::cout << p[i];
            else
                std::cout << '.';
        std::cout << '\n';
        a += CHR_PER_LN;
        p += CHR_PER_LN;
        rem -= CHR_PER_LN;
    }
    std::cout << std::dec;
#endif
}

void
VncApi::Reauthenticate(RespBlock *orb)
{
    RespBlock *rb = new RespBlock(client_->CreateConnection(ks_ep_),
            "v2.0/tokens", 0);
    std::ostringstream pstrm;
    pstrm << "{\"auth\": {\"passwordCredentials\": {\"username\": \"" <<
        cfg_->user << "\", \"password\": \"" << cfg_->password <<
        "\"}, \"tenantName\": \"" << cfg_->tenant << "\"}}";
    rb->GetConnection()->HttpPost(pstrm.str(), rb->GetUri(), false, false,
            true, kshdr_, boost::bind(&VncApi::KsRespHandler,
            shared_from_this(), rb, orb, _1, _2));
}

bool
VncApi::CondTest(std::string s)
//VncApi::CondTest(std::string s)
{
    return boost::starts_with(s, "X-AUTH-TOKEN:");
}

void
VncApi::KsRespHandler(RespBlock *rb, RespBlock *orb, std::string &str,
        boost::system::error_code &ec)
{
    if (str == "") {
        if (rb->GetConnection()->Status() == 200) {
            rapidjson::Document jdoc;
            jdoc.Parse<0>(rb->GetBody().c_str());
            if (jdoc.IsObject() && jdoc.HasMember("access")) {
                std::string token = jdoc["access"]["token"]["id"].GetString();
                if (!token.empty()) {
                    hdr_.erase(std::remove_if(hdr_.begin(), hdr_.end(),
                        boost::bind(&VncApi::CondTest,
                            shared_from_this(), _1)), hdr_.end());
                    hdr_.push_back(std::string("X-AUTH-TOKEN: ") + token);
                    orb->GetConnection()->HttpGet(orb->GetUri(), false, false,
                            true, hdr_, boost::bind(&VncApi::RespHandler,
                            shared_from_this(), orb, _1, _2));
                    client_->RemoveConnection(rb->GetConnection());
                    delete rb;
                    return;
                }
            }
        }
        client_->RemoveConnection(orb->GetConnection());
        delete orb;
        client_->RemoveConnection(rb->GetConnection());
        delete rb;
    } else {
        rb->AddBody(str);
    }
}

void
VncApi::Add2URI(std::ostringstream &uri, std::string &qadded, std::string key,
        std::vector<std::string> data)
{
    if (data.size() > 0) {
        uri << qadded << key << "=";
        qadded = "&";
        for (std::vector<std::string>::iterator i = data.begin();
                i != data.end(); i++) {
            uri << *i;
            if (i + 1 != data.end())
                uri << ",";
        }
    }
}

std::string
VncApi::MakeUri(std::string type, std::vector<std::string> ids,
        std::vector<std::string> filters, std::vector<std::string> parents,
        std::vector<std::string> refs, std::vector<std::string> fields)
{
    std::ostringstream uri;
    uri << type << "s";
    std::string qadded = "?";
    Add2URI(uri, qadded, "id", ids);
    Add2URI(uri, qadded, "filters", filters);
    Add2URI(uri, qadded, "parent_id", parents);
    Add2URI(uri, qadded, "refs", refs);
    Add2URI(uri, qadded, "fields", fields);

    return uri.str();
}

VncApi::VncApi(EventManager *evm, VncApiConfig *cfg) : evm_(evm), cfg_(cfg),
        client_(new HttpClient(evm_))
{
    client_->Init();
    hdr_.push_back(std::string(
                "Content-Type: application/json; charset=\"UTF-8\""));
    hdr_.push_back(std::string("X-Contrail-Useragent: a7s30:vncapi.cc"));
    //hdr_.push_back(std::string("X-AUTH-TOKEN: ") + GetTokenFromKeystone());
    //hdr_.push_back(std::string("X-AUTH-TOKEN: some junk"));
    kshdr_ = hdr_;

    boost::system::error_code ec;
    api_ep_.address(boost::asio::ip::address::from_string(cfg_->cfg_srv_ip, ec));
    api_ep_.port(cfg_->cfg_srv_port);
    ks_ep_.address(boost::asio::ip::address::from_string(cfg_->ks_srv_ip, ec));
    ks_ep_.port(cfg_->ks_srv_port);
}

void
VncApi::Stop()
{
    std::cout  << "VncApi::Stop\n";
    TcpServerManager::DeleteServer(client_);
    {
        hdr_.clear();
        kshdr_.clear();
    }
}

void
VncApi::GetConfig(std::string type, std::vector<std::string> ids,
        std::vector<std::string> filters, std::vector<std::string> parents,
        std::vector<std::string> refs, std::vector<std::string> fields,
        boost::function<void(rapidjson::Document&,
            boost::system::error_code &ec, std::string version, int status,
            std::string reason,
            std::map<std::string, std::string> *headers)> cb)
{
    RespBlock *rb = new RespBlock(client_->CreateConnection(api_ep_),
            MakeUri(type, ids, filters, parents, refs, fields), cb);
    rb->GetConnection()->HttpGet(rb->GetUri(), false, false, true, hdr_,
            boost::bind(&VncApi::RespHandler, shared_from_this(),
                        rb, _1, _2));
}

void
VncApi::RespHandler(RespBlock *rb, std::string &str,
        boost::system::error_code &ec)
{
    hex_dump(str);
#ifdef __DEBUG__
    rb->ShowDetails();
    std::cout << "\n" << str << "\nErr: " << ec << std::endl;
#endif // __DEBUG__
    if (str == "") {
        if (rb->GetConnection()->Status() == 401) {
            // retry
            // client_->RemoveConnection(rb->GetConnection());
            // rb->Clear(client_->CreateConnection(api_ep_));
            rb->Clear();
            Reauthenticate(rb);
        } else {
            rapidjson::Document jdoc;
            if (rb->GetConnection()->Status() == 200)
                jdoc.Parse<0>(rb->GetBody().c_str());
            rb->GetCallBack()(jdoc, ec,
                    rb->GetConnection()->Version(),
                    rb->GetConnection()->Status(),
                    rb->GetConnection()->Reason(),
                    rb->GetConnection()->Headers());
            client_->RemoveConnection(rb->GetConnection());
            delete rb;
        }
    } else {
        rb->AddBody(str);
    }
}
<commit_msg>contrail-collector core continuously in ha setup<commit_after>/*
 * Copyright (c) 2013 Juniper Networks, Inc. All rights reserved.
 */

#include <boost/bind.hpp>
#include <boost/function.hpp>
#include "base/util.h"
#include "base/test/task_test_util.h"
#include <iomanip>
#include <ctype.h>
#include <iostream>
#include <algorithm>
#include <sstream>
#include <unistd.h>
#include <stdlib.h>
#include <rapidjson/stringbuffer.h>
#include <boost/algorithm/string.hpp>
#include <boost/algorithm/string/predicate.hpp>

#include "vncapi.h"

RespBlock::RespBlock(HttpConnection *c, std::string uri,
            boost::function<void(rapidjson::Document&,
                boost::system::error_code&, std::string, int, std::string,
                std::map<std::string, std::string>*)> cb):
        conn_(c), uri_(uri), cb_(cb)
{
}

HttpConnection *
RespBlock::GetConnection()
{
    return conn_;
}

void
RespBlock::AddBody(std::string s)
{
    body_ += s;
}

void
RespBlock::Clear(HttpConnection *c)
{
    body_.clear();
    if (c)
        conn_ = c;
}

std::string
RespBlock::GetBody()
{
    return body_;
}

std::string
RespBlock::GetUri()
{
    return uri_;
}

void
RespBlock::ShowDetails()
{
    std::cout << conn_->Version() << "->"
        << conn_->Reason() << "(" << conn_->Status() << ")\n";
}

boost::function<void(rapidjson::Document&, boost::system::error_code&,
        std::string, int, std::string, std::map<std::string, std::string>*)>
RespBlock::GetCallBack()
{
    return cb_;
}

#define CHR_PER_LN 16
void
VncApi::hex_dump(std::string s)
{
//#define __DEBUG__ 1
#ifdef __DEBUG__
    unsigned long a = 0;
    int rem = s.length();
    const char *p = s.c_str();
    while (rem > 0) {
        std::cout << std::setfill('0') << std::setw(8) << std::hex << a;
        for (int i = 0; i < CHR_PER_LN; i++) {
            if( i % 8 == 0 ) std::cout << ' ';
            if ( i < rem )
                std::cout << ' ' << std::setfill('0') << std::setw(2) <<
                    std::hex << (unsigned) p[i];
            else
                std::cout << "   ";
        }
        std::cout << "   ";
        for (int i = 0; i < rem && i < CHR_PER_LN; i++)
            if (isprint(p[i]))
                std::cout << p[i];
            else
                std::cout << '.';
        std::cout << '\n';
        a += CHR_PER_LN;
        p += CHR_PER_LN;
        rem -= CHR_PER_LN;
    }
    std::cout << std::dec;
#endif
}

void
VncApi::Reauthenticate(RespBlock *orb)
{
    if (client_) {
        RespBlock *rb = new RespBlock(client_->CreateConnection(ks_ep_),
                "v2.0/tokens", 0);
        std::ostringstream pstrm;
        pstrm << "{\"auth\": {\"passwordCredentials\": {\"username\": \"" <<
            cfg_->user << "\", \"password\": \"" << cfg_->password <<
            "\"}, \"tenantName\": \"" << cfg_->tenant << "\"}}";
        rb->GetConnection()->HttpPost(pstrm.str(), rb->GetUri(), false, false,
                true, kshdr_, boost::bind(&VncApi::KsRespHandler,
                shared_from_this(), rb, orb, _1, _2));
    }
}

bool
VncApi::CondTest(std::string s)
//VncApi::CondTest(std::string s)
{
    return boost::starts_with(s, "X-AUTH-TOKEN:");
}

void
VncApi::KsRespHandler(RespBlock *rb, RespBlock *orb, std::string &str,
        boost::system::error_code &ec)
{
    if (client_) {
        if (str == "") {
            if (rb->GetConnection()->Status() == 200) {
                rapidjson::Document jdoc;
                jdoc.Parse<0>(rb->GetBody().c_str());
                if (jdoc.IsObject() && jdoc.HasMember("access")) {
                    std::string token = jdoc["access"]["token"]["id"]
                        .GetString();
                    if (!token.empty()) {
                        hdr_.erase(std::remove_if(hdr_.begin(), hdr_.end(),
                            boost::bind(&VncApi::CondTest,
                                shared_from_this(), _1)), hdr_.end());
                        hdr_.push_back(std::string("X-AUTH-TOKEN: ") + token);
                        orb->GetConnection()->HttpGet(orb->GetUri(), false,
                                false, true, hdr_, boost::bind(
                                    &VncApi::RespHandler,
                                shared_from_this(), orb, _1, _2));
                        client_->RemoveConnection(rb->GetConnection());
                        delete rb;
                        return;
                    }
                }
            }
            client_->RemoveConnection(orb->GetConnection());
            delete orb;
            client_->RemoveConnection(rb->GetConnection());
            delete rb;
        } else {
            rb->AddBody(str);
        }
    } else {
        delete orb;
        delete rb;
    }
}

void
VncApi::Add2URI(std::ostringstream &uri, std::string &qadded, std::string key,
        std::vector<std::string> data)
{
    if (data.size() > 0) {
        uri << qadded << key << "=";
        qadded = "&";
        for (std::vector<std::string>::iterator i = data.begin();
                i != data.end(); i++) {
            uri << *i;
            if (i + 1 != data.end())
                uri << ",";
        }
    }
}

std::string
VncApi::MakeUri(std::string type, std::vector<std::string> ids,
        std::vector<std::string> filters, std::vector<std::string> parents,
        std::vector<std::string> refs, std::vector<std::string> fields)
{
    std::ostringstream uri;
    uri << type << "s";
    std::string qadded = "?";
    Add2URI(uri, qadded, "id", ids);
    Add2URI(uri, qadded, "filters", filters);
    Add2URI(uri, qadded, "parent_id", parents);
    Add2URI(uri, qadded, "refs", refs);
    Add2URI(uri, qadded, "fields", fields);

    return uri.str();
}

VncApi::VncApi(EventManager *evm, VncApiConfig *cfg) : evm_(evm), cfg_(cfg),
        client_(new HttpClient(evm_))
{
    client_->Init();
    hdr_.push_back(std::string(
                "Content-Type: application/json; charset=\"UTF-8\""));
    hdr_.push_back(std::string("X-Contrail-Useragent: a7s30:vncapi.cc"));
    //hdr_.push_back(std::string("X-AUTH-TOKEN: ") + GetTokenFromKeystone());
    //hdr_.push_back(std::string("X-AUTH-TOKEN: some junk"));
    kshdr_ = hdr_;

    boost::system::error_code ec;
    api_ep_.address(boost::asio::ip::address::from_string(cfg_->cfg_srv_ip, ec));
    api_ep_.port(cfg_->cfg_srv_port);
    ks_ep_.address(boost::asio::ip::address::from_string(cfg_->ks_srv_ip, ec));
    ks_ep_.port(cfg_->ks_srv_port);
}

void
VncApi::Stop()
{
    std::cout  << "VncApi::Stop\n";
    TcpServerManager::DeleteServer(client_);
    client_ = 0;
    {
        hdr_.clear();
        kshdr_.clear();
    }
}

void
VncApi::GetConfig(std::string type, std::vector<std::string> ids,
        std::vector<std::string> filters, std::vector<std::string> parents,
        std::vector<std::string> refs, std::vector<std::string> fields,
        boost::function<void(rapidjson::Document&,
            boost::system::error_code &ec, std::string version, int status,
            std::string reason,
            std::map<std::string, std::string> *headers)> cb)
{
    if (client_) {
        RespBlock *rb = new RespBlock(client_->CreateConnection(api_ep_),
                MakeUri(type, ids, filters, parents, refs, fields), cb);
        rb->GetConnection()->HttpGet(rb->GetUri(), false, false, true, hdr_,
                boost::bind(&VncApi::RespHandler, shared_from_this(),
                        rb, _1, _2));
    }
}

void
VncApi::RespHandler(RespBlock *rb, std::string &str,
        boost::system::error_code &ec)
{
#ifdef __DEBUG__
    hex_dump(str);
    rb->ShowDetails();
    std::cout << "\n" << str << "\nErr: " << ec << std::endl;
#endif // __DEBUG__
    if (client_) {
        if (str == "") {
            if (rb->GetConnection()->Status() == 401) {
                // retry
                // client_->RemoveConnection(rb->GetConnection());
                // rb->Clear(client_->CreateConnection(api_ep_));
                rb->Clear();
                Reauthenticate(rb);
            } else {
                rapidjson::Document jdoc;
                if (rb->GetConnection()->Status() == 200)
                    jdoc.Parse<0>(rb->GetBody().c_str());
                rb->GetCallBack()(jdoc, ec,
                        rb->GetConnection()->Version(),
                        rb->GetConnection()->Status(),
                        rb->GetConnection()->Reason(),
                        rb->GetConnection()->Headers());
                client_->RemoveConnection(rb->GetConnection());
                delete rb;
            }
        } else {
            rb->AddBody(str);
        }
    } else {
        delete rb;
    }
}
<|endoftext|>


<commit_before><commit_msg>cyber: improve io server<commit_after><|endoftext|>


<commit_before>// @(#)root/memstat:$Id$
// Author: Anar Manafov (A.Manafov@gsi.de) 2008-03-02

/*************************************************************************
* Copyright (C) 1995-2010, Rene Brun and Fons Rademakers.               *
* All rights reserved.                                                  *
*                                                                       *
* For the licensing terms see $ROOTSYS/LICENSE.                         *
* For the list of contributors see $ROOTSYS/README/CREDITS.             *
*************************************************************************/
// STD
#include <cstdlib>
// ROOT
#include "TSystem.h"
#include "TEnv.h"
#include "TError.h"
#include "Riostream.h"
#include "TObject.h"
#include "TFile.h"
#include "TTree.h"
#include "TArrayL64.h"
#include "TH1.h"
#include "TMD5.h"
// Memstat
#include "TMemStatBacktrace.h"
#include "TMemStatMng.h"

using namespace memstat;

ClassImp(TMemStatMng)

TMemStatMng* TMemStatMng::fgInstance = NULL;

//****************************************************************************//
//
//****************************************************************************//

TMemStatMng::TMemStatMng():
   TObject(),
#if !defined(__APPLE__)
   fPreviousMallocHook(TMemStatHook::GetMallocHook()),
   fPreviousFreeHook(TMemStatHook::GetFreeHook()),
#endif
   fDumpTree(NULL),
   fUseGNUBuiltinBacktrace(kFALSE),
   fBeginTime(0),
   fPos(0),
   fTimems(0),
   fNBytes(0),
   fN(0),
   fBtID(0),
   fBTCount(0)
{
   // Default constructor
}

//______________________________________________________________________________
void TMemStatMng::Init()
{
   //Initialize MemStat manager - used only by instance method

   fBeginTime = fTimeStamp.AsDouble();

   //fDumpFile = new TFile(Form("yams_%d.root", gSystem->GetPid()), "recreate");
   fDumpFile = new TFile(g_cszFileName, "recreate");
   Int_t opt = 200000;
   if(!fDumpTree) {
      fDumpTree = new TTree("T", "Memory Statistics");
      fDumpTree->Branch("pos",   &fPos,   "pos/l", opt);
      fDumpTree->Branch("time",  &fTimems, "time/I", opt);
      fDumpTree->Branch("nbytes", &fNBytes, "nbytes/I", opt);
      fDumpTree->Branch("btid",  &fBtID,  "btid/I", opt);
   }

   fBTCount = 0;

   fBTIDCount = 0;

   fFAddrsList = new TObjArray();
   fFAddrsList->SetOwner(kTRUE);

   fHbtids  = new TH1I("btids", "table of btids", 10000, 0, 1);   //where fHbtids is a member of the manager class
   fHbtids->SetDirectory(0);
   fDumpTree->GetUserInfo()->Add(fHbtids);
}

//______________________________________________________________________________
TMemStatMng* TMemStatMng::GetInstance()
{
   // GetInstance - a static function
   // Initialize a singleton of MemStat manager

   if(!fgInstance) {
      fgInstance = new TMemStatMng;
      fgInstance->Init();
   }
   return fgInstance;
}

//______________________________________________________________________________
void TMemStatMng::Close()
{
   // Close - a static function
   // This method stops the manager,
   // flashes all the buffered data and closes the output tree.

   // TODO: This is a temporary solution until we find a properalgorithm for SaveData
   fgInstance->fDumpFile->WriteObject(fgInstance->fFAddrsList, "FAddrsList");

   // to be documented
   fgInstance->fDumpTree->AutoSave();

   delete fgInstance->fFAddrsList;

   delete fgInstance;
   fgInstance = NULL;
}

//______________________________________________________________________________
TMemStatMng::~TMemStatMng()
{
   // if an instance is destructed - the hooks are reseted to old hooks

   if(this != TMemStatMng::GetInstance())
      return;

   Info("~TMemStatMng", ">>> All free/malloc calls count: %d", fBTIDCount);
   Info("~TMemStatMng", ">>> Unique BTIDs count: %lu", fBTChecksums.size());

   Disable();
}

//______________________________________________________________________________
void TMemStatMng::Enable()
{
   // Enable memory hooks

   if(this != GetInstance())
      return;
#if defined(__APPLE__)
   TMemStatHook::trackZoneMalloc(MacAllocHook, MacFreeHook);
#else
   // set hook to our functions
   TMemStatHook::SetMallocHook(AllocHook);
   TMemStatHook::SetFreeHook(FreeHook);
#endif
}

//______________________________________________________________________________
void TMemStatMng::Disable()
{
   // Disble memory hooks

   if(this != GetInstance())
      return;
#if defined(__APPLE__)
   TMemStatHook::untrackZoneMalloc();
#else
   // set hook to our functions
   TMemStatHook::SetMallocHook(fPreviousMallocHook);
   TMemStatHook::SetFreeHook(fPreviousFreeHook);
#endif
}

//______________________________________________________________________________
void TMemStatMng::MacAllocHook(void *ptr, size_t size)
{
   // AllocHook - a static function
   // a special memory hook for Mac OS X memory zones.
   // Triggered when memory is allocated.

   TMemStatMng* instance = TMemStatMng::GetInstance();
   // Restore all old hooks
   instance->Disable();

   // Call our routine
   instance->AddPointer(ptr, Int_t(size));

   // Restore our own hooks
   instance->Enable();
}

//______________________________________________________________________________
void TMemStatMng::MacFreeHook(void *ptr)
{
   // AllocHook - a static function
   // a special memory hook for Mac OS X memory zones.
   // Triggered when memory is deallocated.

   TMemStatMng* instance = TMemStatMng::GetInstance();
   // Restore all old hooks
   instance->Disable();

   // Call our routine
   instance->AddPointer(ptr, -1);

   // Restore our own hooks
   instance->Enable();
}

//______________________________________________________________________________
void *TMemStatMng::AllocHook(size_t size, const void* /*caller*/)
{
   // AllocHook - a static function
   // A glibc memory allocation hook.

   TMemStatMng* instance = TMemStatMng::GetInstance();
   // Restore all old hooks
   instance->Disable();

   // Call recursively
   void *result = malloc(size);
   // Call our routine
   instance->AddPointer(result, Int_t(size));
   //  TTimer::SingleShot(0, "TYamsMemMng", instance, "SaveData()");

   // Restore our own hooks
   instance->Enable();

   return result;
}

//______________________________________________________________________________
void TMemStatMng::FreeHook(void* ptr, const void* /*caller*/)
{
   // FreeHook - a static function
   // A glibc memory deallocation hook.

   TMemStatMng* instance = TMemStatMng::GetInstance();
   // Restore all old hooks
   instance->Disable();

   // Call recursively
   free(ptr);

   // Call our routine
   instance->AddPointer(ptr, -1);

   // Restore our own hooks
   instance->Enable();
}

//______________________________________________________________________________
void TMemStatMng::AddPointer(void *ptr, Int_t size)
{
   // Add pointer to table.
   // This method is called every time when any of the hooks are triggered.
   // The memory de-/allocation information will is recorded.

   void *stptr[g_BTStackLevel + 1];
   const int stackentries = getBacktrace(stptr, g_BTStackLevel, fUseGNUBuiltinBacktrace);

   // save only unique BTs
   TMD5 md5;
   md5.Update(reinterpret_cast<UChar_t*>(stptr), sizeof(void*) * stackentries);
   md5.Final();
   string crc_digest(md5.AsString());

   // for Debug. A counter of all (de)allacations.
   ++fBTIDCount;

   CRCSet_t::const_iterator found = fBTChecksums.find(crc_digest);
   // TODO: define a proper default value
   Int_t btid = -1;
   if(fBTChecksums.end() == found) {

      // check the size of the BT array container
      const int nbins = fHbtids->GetNbinsX();
      //check that the current allocation in fHbtids is enough, otherwise expend it with
      if(fBTCount + stackentries + 1 >= nbins) {
         fHbtids->SetBins(nbins * 2, 0, 1);
      }

      int *btids = fHbtids->GetArray();
      // A first value is a number of entries in a given stack
      btids[fBTCount++] = stackentries;
      btid = fBTCount;
      if(stackentries <= 0) {
         Warning("AddPointer",
                 "A number of stack entries is equal or less than zero. For btid %d", btid);
      }

      // add new BT's CRC value
      pair<CRCSet_t::iterator, bool> res = fBTChecksums.insert(CRCSet_t::value_type(crc_digest, btid));
      if(!res.second)
         Error("AddPointer", "Can't added a new BTID to the container.");

      for(int i = 0; i < stackentries; ++i) {
         pointer_t func_addr = reinterpret_cast<pointer_t>(stptr[i]);

         // save all functions of this BT
         if(fFAddrs.find(func_addr) < 0) {
            TString strFuncAddr;
            strFuncAddr += func_addr;
            TString strSymbolInfo;
            getSymbolFullInfo(stptr[i], &strSymbolInfo);
            TNamed *nm = new TNamed(strFuncAddr, strSymbolInfo);
            fFAddrsList->Add(nm);
            fFAddrs.add(func_addr, fFAddrsList->GetSize() - 1);
         }

         // add BT to the container
         Int_t idx = fFAddrs.find(reinterpret_cast<pointer_t>(stptr[i]));
         //TODO: in the error code prtint the address.
         // Acutally there must not be a case, when we can't find an index
         if(idx < 0)
            Error("AddPointer", "There is no index for a given BT function return address.");
         // even if we have -1 as an index we add it to the container
         btids[fBTCount++] = idx;
      }

   } else {
      // reuse an existing BT
      btid = found->second;
   }

   if(btid <= 0)
      Error("AddPointer", "bad BT id");

   fTimeStamp.Set();
   Double_t CurTime = fTimeStamp.AsDouble();
   fTimems = Int_t(10000.*(CurTime - fBeginTime));
   fPos    =  reinterpret_cast<pointer_t>(ptr);
   fNBytes = size;
   fN      = 0;
   fBtID   = btid;
   fDumpTree->Fill();
}
<commit_msg>fixed a size_t format specifier<commit_after>// @(#)root/memstat:$Id$
// Author: Anar Manafov (A.Manafov@gsi.de) 2008-03-02

/*************************************************************************
* Copyright (C) 1995-2010, Rene Brun and Fons Rademakers.               *
* All rights reserved.                                                  *
*                                                                       *
* For the licensing terms see $ROOTSYS/LICENSE.                         *
* For the list of contributors see $ROOTSYS/README/CREDITS.             *
*************************************************************************/
// STD
#include <cstdlib>
// ROOT
#include "TSystem.h"
#include "TEnv.h"
#include "TError.h"
#include "Riostream.h"
#include "TObject.h"
#include "TFile.h"
#include "TTree.h"
#include "TArrayL64.h"
#include "TH1.h"
#include "TMD5.h"
// Memstat
#include "TMemStatBacktrace.h"
#include "TMemStatMng.h"

using namespace memstat;

ClassImp(TMemStatMng)

TMemStatMng* TMemStatMng::fgInstance = NULL;

//****************************************************************************//
//
//****************************************************************************//

TMemStatMng::TMemStatMng():
   TObject(),
#if !defined(__APPLE__)
   fPreviousMallocHook(TMemStatHook::GetMallocHook()),
   fPreviousFreeHook(TMemStatHook::GetFreeHook()),
#endif
   fDumpTree(NULL),
   fUseGNUBuiltinBacktrace(kFALSE),
   fBeginTime(0),
   fPos(0),
   fTimems(0),
   fNBytes(0),
   fN(0),
   fBtID(0),
   fBTCount(0)
{
   // Default constructor
}

//______________________________________________________________________________
void TMemStatMng::Init()
{
   //Initialize MemStat manager - used only by instance method

   fBeginTime = fTimeStamp.AsDouble();

   //fDumpFile = new TFile(Form("yams_%d.root", gSystem->GetPid()), "recreate");
   fDumpFile = new TFile(g_cszFileName, "recreate");
   Int_t opt = 200000;
   if(!fDumpTree) {
      fDumpTree = new TTree("T", "Memory Statistics");
      fDumpTree->Branch("pos",   &fPos,   "pos/l", opt);
      fDumpTree->Branch("time",  &fTimems, "time/I", opt);
      fDumpTree->Branch("nbytes", &fNBytes, "nbytes/I", opt);
      fDumpTree->Branch("btid",  &fBtID,  "btid/I", opt);
   }

   fBTCount = 0;

   fBTIDCount = 0;

   fFAddrsList = new TObjArray();
   fFAddrsList->SetOwner(kTRUE);

   fHbtids  = new TH1I("btids", "table of btids", 10000, 0, 1);   //where fHbtids is a member of the manager class
   fHbtids->SetDirectory(0);
   fDumpTree->GetUserInfo()->Add(fHbtids);
}

//______________________________________________________________________________
TMemStatMng* TMemStatMng::GetInstance()
{
   // GetInstance - a static function
   // Initialize a singleton of MemStat manager

   if(!fgInstance) {
      fgInstance = new TMemStatMng;
      fgInstance->Init();
   }
   return fgInstance;
}

//______________________________________________________________________________
void TMemStatMng::Close()
{
   // Close - a static function
   // This method stops the manager,
   // flashes all the buffered data and closes the output tree.

   // TODO: This is a temporary solution until we find a properalgorithm for SaveData
   fgInstance->fDumpFile->WriteObject(fgInstance->fFAddrsList, "FAddrsList");

   // to be documented
   fgInstance->fDumpTree->AutoSave();

   delete fgInstance->fFAddrsList;

   delete fgInstance;
   fgInstance = NULL;
}

//______________________________________________________________________________
TMemStatMng::~TMemStatMng()
{
   // if an instance is destructed - the hooks are reseted to old hooks

   if(this != TMemStatMng::GetInstance())
      return;

   Info("~TMemStatMng", ">>> All free/malloc calls count: %d", fBTIDCount);
   Info("~TMemStatMng", ">>> Unique BTIDs count: %Zu", fBTChecksums.size());

   Disable();
}

//______________________________________________________________________________
void TMemStatMng::Enable()
{
   // Enable memory hooks

   if(this != GetInstance())
      return;
#if defined(__APPLE__)
   TMemStatHook::trackZoneMalloc(MacAllocHook, MacFreeHook);
#else
   // set hook to our functions
   TMemStatHook::SetMallocHook(AllocHook);
   TMemStatHook::SetFreeHook(FreeHook);
#endif
}

//______________________________________________________________________________
void TMemStatMng::Disable()
{
   // Disble memory hooks

   if(this != GetInstance())
      return;
#if defined(__APPLE__)
   TMemStatHook::untrackZoneMalloc();
#else
   // set hook to our functions
   TMemStatHook::SetMallocHook(fPreviousMallocHook);
   TMemStatHook::SetFreeHook(fPreviousFreeHook);
#endif
}

//______________________________________________________________________________
void TMemStatMng::MacAllocHook(void *ptr, size_t size)
{
   // AllocHook - a static function
   // a special memory hook for Mac OS X memory zones.
   // Triggered when memory is allocated.

   TMemStatMng* instance = TMemStatMng::GetInstance();
   // Restore all old hooks
   instance->Disable();

   // Call our routine
   instance->AddPointer(ptr, Int_t(size));

   // Restore our own hooks
   instance->Enable();
}

//______________________________________________________________________________
void TMemStatMng::MacFreeHook(void *ptr)
{
   // AllocHook - a static function
   // a special memory hook for Mac OS X memory zones.
   // Triggered when memory is deallocated.

   TMemStatMng* instance = TMemStatMng::GetInstance();
   // Restore all old hooks
   instance->Disable();

   // Call our routine
   instance->AddPointer(ptr, -1);

   // Restore our own hooks
   instance->Enable();
}

//______________________________________________________________________________
void *TMemStatMng::AllocHook(size_t size, const void* /*caller*/)
{
   // AllocHook - a static function
   // A glibc memory allocation hook.

   TMemStatMng* instance = TMemStatMng::GetInstance();
   // Restore all old hooks
   instance->Disable();

   // Call recursively
   void *result = malloc(size);
   // Call our routine
   instance->AddPointer(result, Int_t(size));
   //  TTimer::SingleShot(0, "TYamsMemMng", instance, "SaveData()");

   // Restore our own hooks
   instance->Enable();

   return result;
}

//______________________________________________________________________________
void TMemStatMng::FreeHook(void* ptr, const void* /*caller*/)
{
   // FreeHook - a static function
   // A glibc memory deallocation hook.

   TMemStatMng* instance = TMemStatMng::GetInstance();
   // Restore all old hooks
   instance->Disable();

   // Call recursively
   free(ptr);

   // Call our routine
   instance->AddPointer(ptr, -1);

   // Restore our own hooks
   instance->Enable();
}

//______________________________________________________________________________
void TMemStatMng::AddPointer(void *ptr, Int_t size)
{
   // Add pointer to table.
   // This method is called every time when any of the hooks are triggered.
   // The memory de-/allocation information will is recorded.

   void *stptr[g_BTStackLevel + 1];
   const int stackentries = getBacktrace(stptr, g_BTStackLevel, fUseGNUBuiltinBacktrace);

   // save only unique BTs
   TMD5 md5;
   md5.Update(reinterpret_cast<UChar_t*>(stptr), sizeof(void*) * stackentries);
   md5.Final();
   string crc_digest(md5.AsString());

   // for Debug. A counter of all (de)allacations.
   ++fBTIDCount;

   CRCSet_t::const_iterator found = fBTChecksums.find(crc_digest);
   // TODO: define a proper default value
   Int_t btid = -1;
   if(fBTChecksums.end() == found) {

      // check the size of the BT array container
      const int nbins = fHbtids->GetNbinsX();
      //check that the current allocation in fHbtids is enough, otherwise expend it with
      if(fBTCount + stackentries + 1 >= nbins) {
         fHbtids->SetBins(nbins * 2, 0, 1);
      }

      int *btids = fHbtids->GetArray();
      // A first value is a number of entries in a given stack
      btids[fBTCount++] = stackentries;
      btid = fBTCount;
      if(stackentries <= 0) {
         Warning("AddPointer",
                 "A number of stack entries is equal or less than zero. For btid %d", btid);
      }

      // add new BT's CRC value
      pair<CRCSet_t::iterator, bool> res = fBTChecksums.insert(CRCSet_t::value_type(crc_digest, btid));
      if(!res.second)
         Error("AddPointer", "Can't added a new BTID to the container.");

      for(int i = 0; i < stackentries; ++i) {
         pointer_t func_addr = reinterpret_cast<pointer_t>(stptr[i]);

         // save all functions of this BT
         if(fFAddrs.find(func_addr) < 0) {
            TString strFuncAddr;
            strFuncAddr += func_addr;
            TString strSymbolInfo;
            getSymbolFullInfo(stptr[i], &strSymbolInfo);
            TNamed *nm = new TNamed(strFuncAddr, strSymbolInfo);
            fFAddrsList->Add(nm);
            fFAddrs.add(func_addr, fFAddrsList->GetSize() - 1);
         }

         // add BT to the container
         Int_t idx = fFAddrs.find(reinterpret_cast<pointer_t>(stptr[i]));
         //TODO: in the error code prtint the address.
         // Acutally there must not be a case, when we can't find an index
         if(idx < 0)
            Error("AddPointer", "There is no index for a given BT function return address.");
         // even if we have -1 as an index we add it to the container
         btids[fBTCount++] = idx;
      }

   } else {
      // reuse an existing BT
      btid = found->second;
   }

   if(btid <= 0)
      Error("AddPointer", "bad BT id");

   fTimeStamp.Set();
   Double_t CurTime = fTimeStamp.AsDouble();
   fTimems = Int_t(10000.*(CurTime - fBeginTime));
   fPos    =  reinterpret_cast<pointer_t>(ptr);
   fNBytes = size;
   fN      = 0;
   fBtID   = btid;
   fDumpTree->Fill();
}
<|endoftext|>


<commit_before>#include <catch.hpp>
#include <rapidcheck/catch.h>

#include "rapidcheck/gen/Chrono.h"

#include "util/Util.h"
#include "util/Meta.h"
#include "util/GenUtils.h"
#include "util/ShrinkableUtils.h"

using namespace rc;
using namespace rc::test;

namespace {

struct DurationProperties {
  template <typename T>
  static void exec() {
    templatedProp<T>("equivalent to generator of underlying type",
                     [](const GenParams &params) {
                       const auto gen = gen::map(gen::arbitrary<T>(),
                                                 [](T x) { return x.count(); });
                       const auto repGen = gen::arbitrary<typename T::rep>();
                       assertEquivalent(gen(params.random, params.size),
                                        repGen(params.random, params.size));
                     });
  }
};

} // namespace

TEST_CASE("arbitrary duration") {
  prop("equivalent",
       [] {
         forEachType<DurationProperties,
                     std::chrono::nanoseconds,
                     std::chrono::microseconds,
                     std::chrono::milliseconds,
                     std::chrono::seconds,
                     std::chrono::minutes,
                     std::chrono::hours>();
       });
}

TEST_CASE("arbitrary time_point") {
  prop("equivalent",
       [](const GenParams &params) {
         using TimePoint = std::chrono::system_clock::time_point;
         const auto gen =
             gen::map(gen::arbitrary<TimePoint>(),
                      [](TimePoint x) { return x.time_since_epoch().count(); });
         const auto repGen =
             gen::arbitrary<typename TimePoint::duration::rep>();
         assertEquivalent(gen(params.random, params.size),
                          repGen(params.random, params.size));
       });
}
<commit_msg>Fix some weirdness in ChronoTests<commit_after>#include <catch.hpp>
#include <rapidcheck/catch.h>

#include "rapidcheck/gen/Chrono.h"

#include "util/Util.h"
#include "util/Meta.h"
#include "util/GenUtils.h"
#include "util/ShrinkableUtils.h"

using namespace rc;
using namespace rc::test;

namespace {

struct DurationProperties {
  template <typename T>
  static void exec() {
    templatedProp<T>("equivalent to generator of underlying type",
                     [](const GenParams &params) {
                       const auto gen = gen::map(gen::arbitrary<T>(),
                                                 [](T x) { return x.count(); });
                       const auto repGen = gen::arbitrary<typename T::rep>();
                       assertEquivalent(gen(params.random, params.size),
                                        repGen(params.random, params.size));
                     });
  }
};

} // namespace

TEST_CASE("arbitrary duration") {
  forEachType<DurationProperties,
              std::chrono::nanoseconds,
              std::chrono::microseconds,
              std::chrono::milliseconds,
              std::chrono::seconds,
              std::chrono::minutes,
              std::chrono::hours>();
}

TEST_CASE("arbitrary time_point") {
  prop("equivalent to generator of underlying type",
       [](const GenParams &params) {
         using TimePoint = std::chrono::system_clock::time_point;
         const auto gen =
             gen::map(gen::arbitrary<TimePoint>(),
                      [](TimePoint x) { return x.time_since_epoch().count(); });
         const auto repGen =
             gen::arbitrary<typename TimePoint::duration::rep>();
         assertEquivalent(gen(params.random, params.size),
                          repGen(params.random, params.size));
       });
}
<|endoftext|>