<commit_before>/******************************************************************************
* Copyright (c) 2011, Michael P. Gerlek (mpg@flaxen.com)
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following
* conditions are met:
*
*     * Redistributions of source code must retain the above copyright
*       notice, this list of conditions and the following disclaimer.
*     * 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.
*     * Neither the name of Hobu, Inc. or Flaxen Geo Consulting nor the
*       names of its contributors may be used to endorse or promote
*       products derived from this software without specific prior
*       written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS 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
* COPYRIGHT OWNER OR 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.
****************************************************************************/

#include <pdal/kernel/Pipeline.hpp>

#include <boost/scoped_ptr.hpp>
namespace pdal { namespace kernel {

Pipeline::Pipeline(int argc, const char* argv[])
    : Application(argc, argv, "pipeline")
    , m_inputFile("")
    , m_validate(false)
    , m_numPointsToWrite(0)
    , m_numSkipPoints(0)
{
    return;
}

void Pipeline::validateSwitches()
{
    if (m_usestdin)
        m_inputFile = "STDIN";

    if (m_inputFile == "")
    {
        throw app_usage_error("input file name required");
    }

    return;
}

void Pipeline::addSwitches()
{
    po::options_description* file_options = new po::options_description("file options");

    file_options->add_options()
        ("input,i", po::value<std::string>(&m_inputFile)->default_value(""), "input file name")
        ("pipeline-serialization", po::value<std::string>(&m_pipelineFile)->default_value(""), "")
        ("validate", po::value<bool>(&m_validate)->zero_tokens()->implicit_value(true), "Validate the pipeline (including serialization), but do not execute writing of points")
        ("count", po::value<boost::uint64_t>(&m_numPointsToWrite)->default_value(0), "How many points should we write?")
        ("skip", po::value<boost::uint64_t>(&m_numSkipPoints)->default_value(0), "How many points should we skip?")
        ;

    addSwitchSet(file_options);
    addPositionalSwitch("input", 1);
}

int Pipeline::execute()
{
    if (!FileUtils::fileExists(m_inputFile))
        throw app_runtime_error("file not found: " + m_inputFile);

    pdal::PipelineManager manager;

    pdal::PipelineReader reader(manager, isDebug(), getVerboseLevel());
    bool isWriter = reader.readPipeline(m_inputFile);
    if (!isWriter)
        std::cerr << "Pipeline file is not a writer.\n";
    else
    {
/**
    if (!getProgressShellCommand().size())
        if (m_numPointsToWrite == 0)
            callback = static_cast<pdal::UserCallback*>(new HeartbeatCallback);
        else
            callback = static_cast<pdal::UserCallback*>(new PercentageCallback);
    else
        callback = static_cast<pdal::UserCallback*>(new ShellScriptCallback(getProgressShellCommand()));
    manager.getWriter()->setUserCallback(callback);
**/
    }

    PointContext ctx;
    manager.getWriter()->prepare(ctx);
    manager.getWriter()->execute(ctx);
    if (m_pipelineFile.size() > 0)
    {
        pdal::PipelineWriter writer(manager);
        writer.writePipeline(m_pipelineFile);
    }
    return 0;
}

}} // pdal::kernel
<commit_msg>throw an exception if pipeline does not have a writer and it is called with 'pdal pipeline'<commit_after>/******************************************************************************
* Copyright (c) 2011, Michael P. Gerlek (mpg@flaxen.com)
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following
* conditions are met:
*
*     * Redistributions of source code must retain the above copyright
*       notice, this list of conditions and the following disclaimer.
*     * 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.
*     * Neither the name of Hobu, Inc. or Flaxen Geo Consulting nor the
*       names of its contributors may be used to endorse or promote
*       products derived from this software without specific prior
*       written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS 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
* COPYRIGHT OWNER OR 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.
****************************************************************************/

#include <pdal/kernel/Pipeline.hpp>

#include <boost/scoped_ptr.hpp>
namespace pdal { namespace kernel {

Pipeline::Pipeline(int argc, const char* argv[])
    : Application(argc, argv, "pipeline")
    , m_inputFile("")
    , m_validate(false)
    , m_numPointsToWrite(0)
    , m_numSkipPoints(0)
{
    return;
}

void Pipeline::validateSwitches()
{
    if (m_usestdin)
        m_inputFile = "STDIN";

    if (m_inputFile == "")
    {
        throw app_usage_error("input file name required");
    }

    return;
}

void Pipeline::addSwitches()
{
    po::options_description* file_options = new po::options_description("file options");

    file_options->add_options()
        ("input,i", po::value<std::string>(&m_inputFile)->default_value(""), "input file name")
        ("pipeline-serialization", po::value<std::string>(&m_pipelineFile)->default_value(""), "")
        ("validate", po::value<bool>(&m_validate)->zero_tokens()->implicit_value(true), "Validate the pipeline (including serialization), but do not execute writing of points")
        ("count", po::value<boost::uint64_t>(&m_numPointsToWrite)->default_value(0), "How many points should we write?")
        ("skip", po::value<boost::uint64_t>(&m_numSkipPoints)->default_value(0), "How many points should we skip?")
        ;

    addSwitchSet(file_options);
    addPositionalSwitch("input", 1);
}

int Pipeline::execute()
{
    if (!FileUtils::fileExists(m_inputFile))
        throw app_runtime_error("file not found: " + m_inputFile);

    pdal::PipelineManager manager;

    pdal::PipelineReader reader(manager, isDebug(), getVerboseLevel());
    bool isWriter = reader.readPipeline(m_inputFile);
    if (!isWriter)
        throw app_runtime_error("Pipeline file does not contain a writer. Use 'pdal info' to read the data.");
    else
    {
/**
    if (!getProgressShellCommand().size())
        if (m_numPointsToWrite == 0)
            callback = static_cast<pdal::UserCallback*>(new HeartbeatCallback);
        else
            callback = static_cast<pdal::UserCallback*>(new PercentageCallback);
    else
        callback = static_cast<pdal::UserCallback*>(new ShellScriptCallback(getProgressShellCommand()));
    manager.getWriter()->setUserCallback(callback);
**/
    }

    PointContext ctx;
    manager.getWriter()->prepare(ctx);
    manager.getWriter()->execute(ctx);
    if (m_pipelineFile.size() > 0)
    {
        pdal::PipelineWriter writer(manager);
        writer.writePipeline(m_pipelineFile);
    }
    return 0;
}

}} // pdal::kernel
<|endoftext|>


<commit_before>// Copyright 2008, Google Inc. 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. Neither the name of Google Inc. nor the names of its contributors may be
//     used to endorse or promote products derived from this software without
//     specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS 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 AUTHOR 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 file contains the implementation of the abstract element Geometry
// and the concrete elements coordinates, Point, LineString, LinearRing,
// outerBoundaryIs, innerBoundaryIs and Polygon.

//#include <iostream>
#include "kml/dom/geometry.h"
#include <ctype.h>
#include <stdlib.h>
#include <string>
#include "kml/dom/attributes.h"
#include "kml/dom/element.h"
#include "kml/dom/kml22.h"
#include "kml/dom/serializer.h"

namespace kmldom {

void Vec3::Serialize(Serializer& serializer) const {
    serializer.Indent();
    serializer.SaveContent(ToString(longitude()) + "," +
                           ToString(latitude()) + "," +
                           ToString(altitude()) + "\n");
}

Coordinates::Coordinates() {}

Coordinates::~Coordinates() {
//std::cerr << "Coordinates dtor " << coordinates_array_.size() << std::endl;
}

// This parses off a Vec3 from the given string and returns a pointer
// to the end of chars consumed.  The purpose is for use in the inner loop
// of the overall parse of a <coordinates> string.  This handles both 2d and
// 3d points and handles any form of whitespace around the commas between
// coordinates.  The general formula is commas between 2 or 3 coordinates
// with any form of whitespace permitted around the commas and whitespace
// between tuples including before the first and after the last.
// Here are some example 3d cstr's which all set the Vec3(1.1, 2.2, 3.3)
// Comma separated coords, space only between tuples:
// "1.1,2.2,3.3 4.4,5.5,6.6"
// Comma separated coords, leading whitespace:
// " 1.1,2.2,3.3 4.4,5.5,6.6"
// "\n 1.1,2.2,3.3 4.4,5.5,6.6"
// Whitespace between coordinates:
// "\t1.1 , 2.2 , 3.3  4.4 , 5.5,6.6"
// Here are some 2d cstr's which all parse to Vec3(1.1, 2.2, 0.0).
// Note that lack of altitude is represented as altitude = 0.0.
// (Actual use of the altitude typeically depends on altitudeMode).
// No spaces. Comma separated as might be common for Point:
// "1.1,2.2"
// A couple of tuples with comma-separated coordinates and single space
// separatting the tuples as might be used in LineString:
// "1.1,2.2 4.4,5.5"
// Leading newlines and tabs as might created by a pretty printer:
// "\n\t1.1, 2.2\t\t4.4, 5.5\n"
// Bad separators are simply discarded and we move to the next comma. A string
// like this: "1.1*2.2,3,3" will become "1.1,3.3,0.0". This precisely matches
// the precent for parsing of bad coordinate strings set by Google Earth.
bool Coordinates::ParseVec3(const char* cstr, char** nextp, Vec3* vec) {
  if (!cstr || !vec) {  // Not much to do w/o input or output.
    return false;
  }
  bool done = false;
  char* endp = const_cast<char*>(cstr);

  // Longitude first.  strtod() eats leading whitespace.
  vec->set(0, strtod(endp, &endp));
  if (endp) {

    // Latitude next.
    while (isspace(*endp) || *endp != ',') {
      // Eat whitespace between double and comma.
      ++endp;
    }
    vec->set(1, strtod(endp+1, &endp));
    done = true;  // Need at least lon,lat to be valid.

    // If no altitude set to 0
    while (isspace(*endp)) {  // Eat whitespace between double and comma.
      ++endp;
    }
    double altitude = 0.0;
    if (*endp == ',') {
      altitude = strtod(endp+1, &endp);
    }
    vec->set(2, altitude);
  }
  if (nextp) {
    while (isspace(*endp)) {  // Eat the remaining whitespace before return.
      *endp++;
    }
    *nextp = endp;
  }
  return done;
}

// The char_data is everything between <coordinates> elements including
// leading and trailing whitespace.
void Coordinates::Parse(const std::string& char_data) {
  const char* cstr = char_data.c_str();
  const char* endp = cstr + char_data.size();
  char* next = const_cast<char*>(cstr);
  while (next != endp) {
    Vec3 vec;
    if (ParseVec3(next, &next, &vec)) {
      coordinates_array_.push_back(vec);
    }
  }
}

// Coordinates essentially parses itself.
void Coordinates::AddElement(Element* element) {
  Parse(char_data());
}

void Coordinates::Serialize(Serializer& serializer) const {
  Attributes attributes;  // dummy
  serializer.BeginById(Type(), attributes);
  for (size_t i = 0; i < coordinates_array_.size(); ++i) {
    coordinates_array_[i].Serialize(serializer);
  }
  serializer.End();
}

Geometry::Geometry() {}

Geometry::~Geometry() {}

AltitudeGeometryCommon::AltitudeGeometryCommon()
  : altitudemode_(ALTITUDEMODE_CLAMPTOGROUND),
    has_altitudemode_(false) {
}

AltitudeGeometryCommon::~AltitudeGeometryCommon() {
}

void AltitudeGeometryCommon::AddElement(Element* element) {
  if (!element) {
    return;
  }
  if (element->Type() == Type_altitudeMode) {
     has_altitudemode_ = element->SetEnum(&altitudemode_);
     return;
  }
  Geometry::AddElement(element);
}

ExtrudeGeometryCommon::ExtrudeGeometryCommon()
  : extrude_(false),
    has_extrude_(false) {
}

ExtrudeGeometryCommon::~ExtrudeGeometryCommon() {
}

void ExtrudeGeometryCommon::AddElement(Element* element) {
  if (!element) {
    return;
  }
  if (element->Type() == Type_extrude) {
    has_extrude_ = element->SetBool(&extrude_);
    return;
  }
  AltitudeGeometryCommon::AddElement(element);
}

CoordinatesGeometryCommon::CoordinatesGeometryCommon()
  : coordinates_(NULL) {
}

CoordinatesGeometryCommon::~CoordinatesGeometryCommon() {
  delete coordinates_;
}

void CoordinatesGeometryCommon::AddElement(Element* element) {
  if (!element) {
    return;
  }
  if (element->Type() == Type_coordinates) {
    set_coordinates(static_cast<Coordinates*>(element));
    return;
  }
  ExtrudeGeometryCommon::AddElement(element);
}

Point::Point() {
}

Point::~Point() {
}

void Point::Serialize(Serializer& serializer) const {
  Attributes attributes;
  Geometry::GetAttributes(&attributes);
  serializer.BeginById(Type(), attributes);
  Geometry::Serialize(serializer);
  if (has_extrude()) {
    serializer.SaveFieldById(Type_extrude, extrude());
  }
  if (has_altitudemode()) {
    serializer.SaveEnum(Type_altitudeMode, altitudemode());
  }
  if (has_coordinates()) {
    serializer.SaveElement(*coordinates());
  }
  SerializeUnknown(serializer);
  serializer.End();
}

LineCommon::LineCommon()
  : tessellate_(false),
    has_tessellate_(false) {
}

LineCommon::~LineCommon() {
}

void LineCommon::AddElement(Element* element) {
  if (!element) {
    return;
  }
  if (element->Type() == Type_tessellate) {
    has_tessellate_ = element->SetBool(&tessellate_);
    return;
  }
  CoordinatesGeometryCommon::AddElement(element);
}

void LineCommon::Serialize(Serializer& serializer) const {
  Attributes attributes;
  Geometry::GetAttributes(&attributes);
  serializer.BeginById(Type(), attributes);
  Geometry::Serialize(serializer);
  if (has_extrude()) {
    serializer.SaveFieldById(Type_extrude, extrude());
  }
  if (has_tessellate()) {
    serializer.SaveFieldById(Type_tessellate, tessellate());
  }
  if (has_altitudemode()) {
    serializer.SaveEnum(Type_altitudeMode, altitudemode());
  }
  if (coordinates()) {
    serializer.SaveElement(*coordinates());
  }
  SerializeUnknown(serializer);
  serializer.End();
}

LineString::LineString() {}

LineString::~LineString() {}

LinearRing::LinearRing() {}

LinearRing::~LinearRing() {}

BoundaryCommon::BoundaryCommon()
  : linearring_(NULL) {
}

BoundaryCommon::~BoundaryCommon() {
  delete linearring_;
}

void BoundaryCommon::AddElement(Element* element) {
  if (element && element->IsA(Type_LinearRing)) {
    set_linearring(static_cast<LinearRing*>(element));
    return;
  }
  Element::AddElement(element);
}

void BoundaryCommon::Serialize(Serializer& serializer) const {
  Attributes attributes;  // None.
  serializer.BeginById(Type(), attributes);
  if (linearring_) {
    serializer.SaveElement(*linearring_);
  }
  SerializeUnknown(serializer);
  serializer.End();
}

OuterBoundaryIs::OuterBoundaryIs() {}

OuterBoundaryIs::~OuterBoundaryIs() {}

InnerBoundaryIs::InnerBoundaryIs() {}

InnerBoundaryIs::~InnerBoundaryIs() {}

Polygon::Polygon()
  : tessellate_(false),
    has_tessellate_(false),
    outerboundaryis_(NULL) {
}

Polygon::~Polygon() {
  delete outerboundaryis_;
  for (size_t i = 0; i < innerboundaryis_array_.size(); ++i) {
    delete innerboundaryis_array_[i];
  }
}

void Polygon::AddElement(Element* element) {
  if (!element) {
    return;
  }
  switch (element->Type()) {
    case Type_tessellate:
      has_tessellate_ = element->SetBool(&tessellate_);
      break;
    case Type_outerBoundaryIs:
      set_outerboundaryis(static_cast<OuterBoundaryIs*>(element));
      break;
    case Type_innerBoundaryIs:
      add_innerboundaryis(static_cast<InnerBoundaryIs*>(element));
      break;
    default:
      ExtrudeGeometryCommon::AddElement(element);
  }
}

void Polygon::Serialize(Serializer& serializer) const {
  Attributes attributes;
  Geometry::GetAttributes(&attributes);
  serializer.BeginById(Type(), attributes);
  Geometry::Serialize(serializer);
  if (has_extrude()) {
    serializer.SaveFieldById(Type_extrude, extrude());
  }
  if (has_tessellate()) {
    serializer.SaveFieldById(Type_tessellate, tessellate());
  }
  if (has_altitudemode()) {
    serializer.SaveEnum(Type_altitudeMode, altitudemode());
  }
  if (outerboundaryis()) {
    serializer.SaveElement(*outerboundaryis());
  }
  for (size_t i = 0; i < innerboundaryis_array_.size(); ++i) {
    serializer.SaveElement(*innerboundaryis_array_[i]);
  }
  SerializeUnknown(serializer);
  serializer.End();
}

MultiGeometry::MultiGeometry() {}

MultiGeometry::~MultiGeometry() {
  for (size_t i = 0; i < geometry_array_.size(); ++i) {
    delete geometry_array_[i];
  }
}

void MultiGeometry::add_geometry(Geometry* geometry) {
  if (geometry && geometry->IsA(Type_Geometry) && geometry->set_parent(this)) {
    geometry_array_.push_back(geometry);
  }
}

void MultiGeometry::AddElement(Element* element) {
  if (!element) {
    return;
  }
  if (element->IsA(Type_Geometry)) {
    add_geometry(static_cast<Geometry*>(element));
    return;
  }
  Geometry::AddElement(element);
}

void MultiGeometry::Serialize(Serializer& serializer) const {
  Attributes attributes;
  Geometry::GetAttributes(&attributes);
  serializer.BeginById(Type(), attributes);
  Geometry::Serialize(serializer);
  for (size_t i = 0; i < geometry_array_.size(); ++i) {
    serializer.SaveElement(*geometry_array_[i]);
  }
  SerializeUnknown(serializer);
  serializer.End();
}

}  // end namespace kmldom
<commit_msg>Removed commented out debug cruft<commit_after>// Copyright 2008, Google Inc. 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. Neither the name of Google Inc. nor the names of its contributors may be
//     used to endorse or promote products derived from this software without
//     specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS 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 AUTHOR 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 file contains the implementation of the abstract element Geometry
// and the concrete elements coordinates, Point, LineString, LinearRing,
// outerBoundaryIs, innerBoundaryIs and Polygon.

#include "kml/dom/geometry.h"
#include <ctype.h>
#include <stdlib.h>
#include <string>
#include "kml/dom/attributes.h"
#include "kml/dom/element.h"
#include "kml/dom/kml22.h"
#include "kml/dom/serializer.h"

namespace kmldom {

void Vec3::Serialize(Serializer& serializer) const {
    serializer.Indent();
    serializer.SaveContent(ToString(longitude()) + "," +
                           ToString(latitude()) + "," +
                           ToString(altitude()) + "\n");
}

Coordinates::Coordinates() {}

Coordinates::~Coordinates() {}

// This parses off a Vec3 from the given string and returns a pointer
// to the end of chars consumed.  The purpose is for use in the inner loop
// of the overall parse of a <coordinates> string.  This handles both 2d and
// 3d points and handles any form of whitespace around the commas between
// coordinates.  The general formula is commas between 2 or 3 coordinates
// with any form of whitespace permitted around the commas and whitespace
// between tuples including before the first and after the last.
// Here are some example 3d cstr's which all set the Vec3(1.1, 2.2, 3.3)
// Comma separated coords, space only between tuples:
// "1.1,2.2,3.3 4.4,5.5,6.6"
// Comma separated coords, leading whitespace:
// " 1.1,2.2,3.3 4.4,5.5,6.6"
// "\n 1.1,2.2,3.3 4.4,5.5,6.6"
// Whitespace between coordinates:
// "\t1.1 , 2.2 , 3.3  4.4 , 5.5,6.6"
// Here are some 2d cstr's which all parse to Vec3(1.1, 2.2, 0.0).
// Note that lack of altitude is represented as altitude = 0.0.
// (Actual use of the altitude typeically depends on altitudeMode).
// No spaces. Comma separated as might be common for Point:
// "1.1,2.2"
// A couple of tuples with comma-separated coordinates and single space
// separatting the tuples as might be used in LineString:
// "1.1,2.2 4.4,5.5"
// Leading newlines and tabs as might created by a pretty printer:
// "\n\t1.1, 2.2\t\t4.4, 5.5\n"
// Bad separators are simply discarded and we move to the next comma. A string
// like this: "1.1*2.2,3,3" will become "1.1,3.3,0.0". This precisely matches
// the precent for parsing of bad coordinate strings set by Google Earth.
bool Coordinates::ParseVec3(const char* cstr, char** nextp, Vec3* vec) {
  if (!cstr || !vec) {  // Not much to do w/o input or output.
    return false;
  }
  bool done = false;
  char* endp = const_cast<char*>(cstr);

  // Longitude first.  strtod() eats leading whitespace.
  vec->set(0, strtod(endp, &endp));
  if (endp) {

    // Latitude next.
    while (isspace(*endp) || *endp != ',') {
      // Eat whitespace between double and comma.
      ++endp;
    }
    vec->set(1, strtod(endp+1, &endp));
    done = true;  // Need at least lon,lat to be valid.

    // If no altitude set to 0
    while (isspace(*endp)) {  // Eat whitespace between double and comma.
      ++endp;
    }
    double altitude = 0.0;
    if (*endp == ',') {
      altitude = strtod(endp+1, &endp);
    }
    vec->set(2, altitude);
  }
  if (nextp) {
    while (isspace(*endp)) {  // Eat the remaining whitespace before return.
      *endp++;
    }
    *nextp = endp;
  }
  return done;
}

// The char_data is everything between <coordinates> elements including
// leading and trailing whitespace.
void Coordinates::Parse(const std::string& char_data) {
  const char* cstr = char_data.c_str();
  const char* endp = cstr + char_data.size();
  char* next = const_cast<char*>(cstr);
  while (next != endp) {
    Vec3 vec;
    if (ParseVec3(next, &next, &vec)) {
      coordinates_array_.push_back(vec);
    }
  }
}

// Coordinates essentially parses itself.
void Coordinates::AddElement(Element* element) {
  Parse(char_data());
}

void Coordinates::Serialize(Serializer& serializer) const {
  Attributes attributes;  // dummy
  serializer.BeginById(Type(), attributes);
  for (size_t i = 0; i < coordinates_array_.size(); ++i) {
    coordinates_array_[i].Serialize(serializer);
  }
  serializer.End();
}

Geometry::Geometry() {}

Geometry::~Geometry() {}

AltitudeGeometryCommon::AltitudeGeometryCommon()
  : altitudemode_(ALTITUDEMODE_CLAMPTOGROUND),
    has_altitudemode_(false) {
}

AltitudeGeometryCommon::~AltitudeGeometryCommon() {
}

void AltitudeGeometryCommon::AddElement(Element* element) {
  if (!element) {
    return;
  }
  if (element->Type() == Type_altitudeMode) {
     has_altitudemode_ = element->SetEnum(&altitudemode_);
     return;
  }
  Geometry::AddElement(element);
}

ExtrudeGeometryCommon::ExtrudeGeometryCommon()
  : extrude_(false),
    has_extrude_(false) {
}

ExtrudeGeometryCommon::~ExtrudeGeometryCommon() {
}

void ExtrudeGeometryCommon::AddElement(Element* element) {
  if (!element) {
    return;
  }
  if (element->Type() == Type_extrude) {
    has_extrude_ = element->SetBool(&extrude_);
    return;
  }
  AltitudeGeometryCommon::AddElement(element);
}

CoordinatesGeometryCommon::CoordinatesGeometryCommon()
  : coordinates_(NULL) {
}

CoordinatesGeometryCommon::~CoordinatesGeometryCommon() {
  delete coordinates_;
}

void CoordinatesGeometryCommon::AddElement(Element* element) {
  if (!element) {
    return;
  }
  if (element->Type() == Type_coordinates) {
    set_coordinates(static_cast<Coordinates*>(element));
    return;
  }
  ExtrudeGeometryCommon::AddElement(element);
}

Point::Point() {
}

Point::~Point() {
}

void Point::Serialize(Serializer& serializer) const {
  Attributes attributes;
  Geometry::GetAttributes(&attributes);
  serializer.BeginById(Type(), attributes);
  Geometry::Serialize(serializer);
  if (has_extrude()) {
    serializer.SaveFieldById(Type_extrude, extrude());
  }
  if (has_altitudemode()) {
    serializer.SaveEnum(Type_altitudeMode, altitudemode());
  }
  if (has_coordinates()) {
    serializer.SaveElement(*coordinates());
  }
  SerializeUnknown(serializer);
  serializer.End();
}

LineCommon::LineCommon()
  : tessellate_(false),
    has_tessellate_(false) {
}

LineCommon::~LineCommon() {
}

void LineCommon::AddElement(Element* element) {
  if (!element) {
    return;
  }
  if (element->Type() == Type_tessellate) {
    has_tessellate_ = element->SetBool(&tessellate_);
    return;
  }
  CoordinatesGeometryCommon::AddElement(element);
}

void LineCommon::Serialize(Serializer& serializer) const {
  Attributes attributes;
  Geometry::GetAttributes(&attributes);
  serializer.BeginById(Type(), attributes);
  Geometry::Serialize(serializer);
  if (has_extrude()) {
    serializer.SaveFieldById(Type_extrude, extrude());
  }
  if (has_tessellate()) {
    serializer.SaveFieldById(Type_tessellate, tessellate());
  }
  if (has_altitudemode()) {
    serializer.SaveEnum(Type_altitudeMode, altitudemode());
  }
  if (coordinates()) {
    serializer.SaveElement(*coordinates());
  }
  SerializeUnknown(serializer);
  serializer.End();
}

LineString::LineString() {}

LineString::~LineString() {}

LinearRing::LinearRing() {}

LinearRing::~LinearRing() {}

BoundaryCommon::BoundaryCommon()
  : linearring_(NULL) {
}

BoundaryCommon::~BoundaryCommon() {
  delete linearring_;
}

void BoundaryCommon::AddElement(Element* element) {
  if (element && element->IsA(Type_LinearRing)) {
    set_linearring(static_cast<LinearRing*>(element));
    return;
  }
  Element::AddElement(element);
}

void BoundaryCommon::Serialize(Serializer& serializer) const {
  Attributes attributes;  // None.
  serializer.BeginById(Type(), attributes);
  if (linearring_) {
    serializer.SaveElement(*linearring_);
  }
  SerializeUnknown(serializer);
  serializer.End();
}

OuterBoundaryIs::OuterBoundaryIs() {}

OuterBoundaryIs::~OuterBoundaryIs() {}

InnerBoundaryIs::InnerBoundaryIs() {}

InnerBoundaryIs::~InnerBoundaryIs() {}

Polygon::Polygon()
  : tessellate_(false),
    has_tessellate_(false),
    outerboundaryis_(NULL) {
}

Polygon::~Polygon() {
  delete outerboundaryis_;
  for (size_t i = 0; i < innerboundaryis_array_.size(); ++i) {
    delete innerboundaryis_array_[i];
  }
}

void Polygon::AddElement(Element* element) {
  if (!element) {
    return;
  }
  switch (element->Type()) {
    case Type_tessellate:
      has_tessellate_ = element->SetBool(&tessellate_);
      break;
    case Type_outerBoundaryIs:
      set_outerboundaryis(static_cast<OuterBoundaryIs*>(element));
      break;
    case Type_innerBoundaryIs:
      add_innerboundaryis(static_cast<InnerBoundaryIs*>(element));
      break;
    default:
      ExtrudeGeometryCommon::AddElement(element);
  }
}

void Polygon::Serialize(Serializer& serializer) const {
  Attributes attributes;
  Geometry::GetAttributes(&attributes);
  serializer.BeginById(Type(), attributes);
  Geometry::Serialize(serializer);
  if (has_extrude()) {
    serializer.SaveFieldById(Type_extrude, extrude());
  }
  if (has_tessellate()) {
    serializer.SaveFieldById(Type_tessellate, tessellate());
  }
  if (has_altitudemode()) {
    serializer.SaveEnum(Type_altitudeMode, altitudemode());
  }
  if (outerboundaryis()) {
    serializer.SaveElement(*outerboundaryis());
  }
  for (size_t i = 0; i < innerboundaryis_array_.size(); ++i) {
    serializer.SaveElement(*innerboundaryis_array_[i]);
  }
  SerializeUnknown(serializer);
  serializer.End();
}

MultiGeometry::MultiGeometry() {}

MultiGeometry::~MultiGeometry() {
  for (size_t i = 0; i < geometry_array_.size(); ++i) {
    delete geometry_array_[i];
  }
}

void MultiGeometry::add_geometry(Geometry* geometry) {
  if (geometry && geometry->IsA(Type_Geometry) && geometry->set_parent(this)) {
    geometry_array_.push_back(geometry);
  }
}

void MultiGeometry::AddElement(Element* element) {
  if (!element) {
    return;
  }
  if (element->IsA(Type_Geometry)) {
    add_geometry(static_cast<Geometry*>(element));
    return;
  }
  Geometry::AddElement(element);
}

void MultiGeometry::Serialize(Serializer& serializer) const {
  Attributes attributes;
  Geometry::GetAttributes(&attributes);
  serializer.BeginById(Type(), attributes);
  Geometry::Serialize(serializer);
  for (size_t i = 0; i < geometry_array_.size(); ++i) {
    serializer.SaveElement(*geometry_array_[i]);
  }
  SerializeUnknown(serializer);
  serializer.End();
}

}  // end namespace kmldom
<|endoftext|>


<commit_before>// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  The ASF licenses this file
// to you 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 <signal.h> // For sigaction(), sigemptyset().
#include <string.h> // For strsignal().

#include <glog/logging.h>
#include <glog/raw_logging.h>

#include <string>

#include <process/once.hpp>

#include <stout/error.hpp>
#include <stout/exit.hpp>
#include <stout/os.hpp>
#include <stout/path.hpp>
#include <stout/stringify.hpp>
#include <stout/try.hpp>

#ifndef __WINDOWS__
#include <stout/os/signals.hpp>
#endif // __WINDOWS__

#include "logging/logging.hpp"

#ifdef __linux__
// Declare FLAGS_drop_log_memory flag for glog. This declaration is based on the
// the DECLARE_XXX macros from glog/logging.h.
namespace fLB {
  extern GOOGLE_GLOG_DLL_DECL bool FLAGS_drop_log_memory;
}
using fLB::FLAGS_drop_log_memory;
#endif

using process::Once;

using std::string;

// Captures the stack trace and exits when a pure virtual method is
// called.
// This interface is part of C++ ABI.
//   -Linux c++abi:
//    http://refspecs.linuxbase.org/cxxabi-1.83.html#vcall
//      "This routine will only be called if the user calls a
//       non-overridden pure virtual function, which has undefined
//       behavior according to the C++ Standard".
//   -OSX libc++abi:
//    http://libcxxabi.llvm.org/spec.html
// This usage has been tested on Linux & OSX and on gcc & clang.
extern "C" void __cxa_pure_virtual()
{
  RAW_LOG(FATAL, "Pure virtual method called");
}

namespace mesos {
namespace internal {
namespace logging {

// Persistent copy of argv0 since InitGoogleLogging requires the
// string we pass to it to be accessible indefinitely.
string argv0;

// NOTE: We use RAW_LOG instead of LOG because RAW_LOG doesn't
// allocate any memory or grab locks. And according to
// https://code.google.com/p/google-glog/issues/detail?id=161
// it should work in 'most' cases in signal handlers.
#ifndef __WINDOWS__
inline void handler(int signal, siginfo_t *siginfo, void *context)
{
  if (signal == SIGTERM) {
    if (siginfo->si_code == SI_USER ||
        siginfo->si_code == SI_QUEUE ||
        siginfo->si_code <= 0) {
      RAW_LOG(WARNING, "Received signal SIGTERM from process %d of user %d; "
                       "exiting", siginfo->si_pid, siginfo->si_uid);
    } else {
      RAW_LOG(WARNING, "Received signal SIGTERM; exiting");
    }

    // Setup the default handler for SIGTERM so that we don't print
    // a stack trace.
    os::signals::reset(signal);
    raise(signal);
  } else {
    RAW_LOG(FATAL, "Unexpected signal in signal handler: %d", signal);
  }
}
#endif // __WINDOWS__

google::LogSeverity getLogSeverity(const string& logging_level)
{
  if (logging_level == "INFO") {
    return google::INFO;
  } else if (logging_level == "WARNING") {
    return google::WARNING;
  } else if (logging_level == "ERROR") {
    return google::ERROR;
  } else {
    // TODO(bmahler): Consider an error here.
    return google::INFO;
  }
}

void initialize(
    const string& _argv0,
    const Flags& flags,
    bool installFailureSignalHandler)
{
  static Once* initialized = new Once();

  if (initialized->once()) {
    return;
  }

  argv0 = _argv0;

  if (flags.logging_level != "INFO" &&
      flags.logging_level != "WARNING" &&
      flags.logging_level != "ERROR") {
    EXIT(EXIT_FAILURE)
      << "'" << flags.logging_level
      << "' is not a valid logging level. Possible values for"
      << " 'logging_level' flag are: 'INFO', 'WARNING', 'ERROR'.";
  }

  FLAGS_minloglevel = getLogSeverity(flags.logging_level);

  if (flags.log_dir.isSome()) {
    Try<Nothing> mkdir = os::mkdir(flags.log_dir.get());
    if (mkdir.isError()) {
      EXIT(EXIT_FAILURE)
        << "Could not initialize logging: Failed to create directory "
        << flags.log_dir.get() << ": " << mkdir.error();
    }
    FLAGS_log_dir = flags.log_dir.get();
    // Do not log to stderr instead of log files.
    FLAGS_logtostderr = false;
  } else {
    // Log to stderr instead of log files.
    FLAGS_logtostderr = true;
  }

  // Log everything to stderr IN ADDITION to log files unless
  // otherwise specified.
  if (flags.quiet) {
    FLAGS_stderrthreshold = 3; // FATAL.

    // FLAGS_stderrthreshold is ignored when logging to stderr instead
    // of log files. Setting the minimum log level gets around this issue.
    if (FLAGS_logtostderr) {
      FLAGS_minloglevel = 3; // FATAL.
    }
  } else {
    FLAGS_stderrthreshold = FLAGS_minloglevel;
  }

  FLAGS_logbufsecs = flags.logbufsecs;

#ifdef __linux__
  // Do not drop in-memory buffers of log contents. When set to true, this flag
  // can significantly slow down the master. The slow down is attributed to
  // several hundred `posix_fadvise(..., POSIX_FADV_DONTNEED)` calls per second
  // to advise the kernel to drop in-memory buffers related to log contents.
  // We set this flag to 'false' only if the corresponding environment variable
  // is not set.
  if (os::getenv("GLOG_drop_log_memory").isNone()) {
    FLAGS_drop_log_memory = false;
  }
#endif

  google::InitGoogleLogging(argv0.c_str());
  if (flags.log_dir.isSome()) {
    // Log this message in order to create the log file; this is because GLOG
    // creates the log file once the first log message occurs; also recreate
    // the file if it has been created on a previous run.
    LOG_AT_LEVEL(FLAGS_minloglevel)
      << google::GetLogSeverityName(FLAGS_minloglevel)
      << " level logging started!";
  }

  VLOG(1) << "Logging to " <<
    (flags.log_dir.isSome() ? flags.log_dir.get() : "STDERR");

  if (installFailureSignalHandler) {
  // glog on Windows does not support `InstallFailureSignalHandler`.
#ifndef __WINDOWS__
    // Handles SIGSEGV, SIGILL, SIGFPE, SIGABRT, SIGBUS, SIGTERM
    // by default.
    google::InstallFailureSignalHandler();

    // The code below sets the SIGTERM signal handler to the `handle` function
    // declared above. While this is useful on POSIX systems, SIGTERM is
    // generated and handled differently on Windows[1], so this code would
    // not work.
    // [1] https://msdn.microsoft.com/en-us/library/xdkz3x12.aspx

    // Set up our custom signal handlers.
    //
    // NOTE: The code below sets the SIGTERM signal handler to the `handle`
    // function declared above. While this is useful on POSIX systems, SIGTERM
    // is generated and handled differently on Windows[1], so this code would
    // not work.
    //
    // [1] https://msdn.microsoft.com/en-us/library/xdkz3x12.aspx
    struct sigaction action;
    action.sa_sigaction = handler;

    // Do not block additional signals while in the handler.
    sigemptyset(&action.sa_mask);

    // The SA_SIGINFO flag tells sigaction() to use
    // the sa_sigaction field, not sa_handler.
    action.sa_flags = SA_SIGINFO;

    // We also do not want SIGTERM to dump a stacktrace, as this
    // can imply that we crashed, when we were in fact terminated
    // by user request.
    if (sigaction(SIGTERM, &action, nullptr) < 0) {
      PLOG(FATAL) << "Failed to set sigaction";
    }
#endif // __WINDOWS__
  }

  initialized->done();
}

Try<string> getLogFile(google::LogSeverity severity)
{
  if (FLAGS_log_dir.empty()) {
    return Error("The 'log_dir' option was not specified");
  }

  if (severity < 0 || google::NUM_SEVERITIES <= severity) {
    return Error("Unknown log severity: " + stringify(severity));
  }

  return path::join(FLAGS_log_dir, Path(argv0).basename()) + "." +
         google::GetLogSeverityName(severity);
}

} // namespace logging {
} // namespace internal {
} // namespace mesos {
<commit_msg>Removed duplicate note.<commit_after>// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  The ASF licenses this file
// to you 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 <signal.h> // For sigaction(), sigemptyset().
#include <string.h> // For strsignal().

#include <glog/logging.h>
#include <glog/raw_logging.h>

#include <string>

#include <process/once.hpp>

#include <stout/error.hpp>
#include <stout/exit.hpp>
#include <stout/os.hpp>
#include <stout/path.hpp>
#include <stout/stringify.hpp>
#include <stout/try.hpp>

#ifndef __WINDOWS__
#include <stout/os/signals.hpp>
#endif // __WINDOWS__

#include "logging/logging.hpp"

#ifdef __linux__
// Declare FLAGS_drop_log_memory flag for glog. This declaration is based on the
// the DECLARE_XXX macros from glog/logging.h.
namespace fLB {
  extern GOOGLE_GLOG_DLL_DECL bool FLAGS_drop_log_memory;
}
using fLB::FLAGS_drop_log_memory;
#endif

using process::Once;

using std::string;

// Captures the stack trace and exits when a pure virtual method is
// called.
// This interface is part of C++ ABI.
//   -Linux c++abi:
//    http://refspecs.linuxbase.org/cxxabi-1.83.html#vcall
//      "This routine will only be called if the user calls a
//       non-overridden pure virtual function, which has undefined
//       behavior according to the C++ Standard".
//   -OSX libc++abi:
//    http://libcxxabi.llvm.org/spec.html
// This usage has been tested on Linux & OSX and on gcc & clang.
extern "C" void __cxa_pure_virtual()
{
  RAW_LOG(FATAL, "Pure virtual method called");
}

namespace mesos {
namespace internal {
namespace logging {

// Persistent copy of argv0 since InitGoogleLogging requires the
// string we pass to it to be accessible indefinitely.
string argv0;

// NOTE: We use RAW_LOG instead of LOG because RAW_LOG doesn't
// allocate any memory or grab locks. And according to
// https://code.google.com/p/google-glog/issues/detail?id=161
// it should work in 'most' cases in signal handlers.
#ifndef __WINDOWS__
inline void handler(int signal, siginfo_t *siginfo, void *context)
{
  if (signal == SIGTERM) {
    if (siginfo->si_code == SI_USER ||
        siginfo->si_code == SI_QUEUE ||
        siginfo->si_code <= 0) {
      RAW_LOG(WARNING, "Received signal SIGTERM from process %d of user %d; "
                       "exiting", siginfo->si_pid, siginfo->si_uid);
    } else {
      RAW_LOG(WARNING, "Received signal SIGTERM; exiting");
    }

    // Setup the default handler for SIGTERM so that we don't print
    // a stack trace.
    os::signals::reset(signal);
    raise(signal);
  } else {
    RAW_LOG(FATAL, "Unexpected signal in signal handler: %d", signal);
  }
}
#endif // __WINDOWS__

google::LogSeverity getLogSeverity(const string& logging_level)
{
  if (logging_level == "INFO") {
    return google::INFO;
  } else if (logging_level == "WARNING") {
    return google::WARNING;
  } else if (logging_level == "ERROR") {
    return google::ERROR;
  } else {
    // TODO(bmahler): Consider an error here.
    return google::INFO;
  }
}

void initialize(
    const string& _argv0,
    const Flags& flags,
    bool installFailureSignalHandler)
{
  static Once* initialized = new Once();

  if (initialized->once()) {
    return;
  }

  argv0 = _argv0;

  if (flags.logging_level != "INFO" &&
      flags.logging_level != "WARNING" &&
      flags.logging_level != "ERROR") {
    EXIT(EXIT_FAILURE)
      << "'" << flags.logging_level
      << "' is not a valid logging level. Possible values for"
      << " 'logging_level' flag are: 'INFO', 'WARNING', 'ERROR'.";
  }

  FLAGS_minloglevel = getLogSeverity(flags.logging_level);

  if (flags.log_dir.isSome()) {
    Try<Nothing> mkdir = os::mkdir(flags.log_dir.get());
    if (mkdir.isError()) {
      EXIT(EXIT_FAILURE)
        << "Could not initialize logging: Failed to create directory "
        << flags.log_dir.get() << ": " << mkdir.error();
    }
    FLAGS_log_dir = flags.log_dir.get();
    // Do not log to stderr instead of log files.
    FLAGS_logtostderr = false;
  } else {
    // Log to stderr instead of log files.
    FLAGS_logtostderr = true;
  }

  // Log everything to stderr IN ADDITION to log files unless
  // otherwise specified.
  if (flags.quiet) {
    FLAGS_stderrthreshold = 3; // FATAL.

    // FLAGS_stderrthreshold is ignored when logging to stderr instead
    // of log files. Setting the minimum log level gets around this issue.
    if (FLAGS_logtostderr) {
      FLAGS_minloglevel = 3; // FATAL.
    }
  } else {
    FLAGS_stderrthreshold = FLAGS_minloglevel;
  }

  FLAGS_logbufsecs = flags.logbufsecs;

#ifdef __linux__
  // Do not drop in-memory buffers of log contents. When set to true, this flag
  // can significantly slow down the master. The slow down is attributed to
  // several hundred `posix_fadvise(..., POSIX_FADV_DONTNEED)` calls per second
  // to advise the kernel to drop in-memory buffers related to log contents.
  // We set this flag to 'false' only if the corresponding environment variable
  // is not set.
  if (os::getenv("GLOG_drop_log_memory").isNone()) {
    FLAGS_drop_log_memory = false;
  }
#endif

  google::InitGoogleLogging(argv0.c_str());
  if (flags.log_dir.isSome()) {
    // Log this message in order to create the log file; this is because GLOG
    // creates the log file once the first log message occurs; also recreate
    // the file if it has been created on a previous run.
    LOG_AT_LEVEL(FLAGS_minloglevel)
      << google::GetLogSeverityName(FLAGS_minloglevel)
      << " level logging started!";
  }

  VLOG(1) << "Logging to " <<
    (flags.log_dir.isSome() ? flags.log_dir.get() : "STDERR");

  if (installFailureSignalHandler) {
  // glog on Windows does not support `InstallFailureSignalHandler`.
#ifndef __WINDOWS__
    // Handles SIGSEGV, SIGILL, SIGFPE, SIGABRT, SIGBUS, SIGTERM
    // by default.
    google::InstallFailureSignalHandler();

    // Set up our custom signal handlers.
    //
    // NOTE: The code below sets the SIGTERM signal handler to the `handle`
    // function declared above. While this is useful on POSIX systems, SIGTERM
    // is generated and handled differently on Windows[1], so this code would
    // not work.
    //
    // [1] https://msdn.microsoft.com/en-us/library/xdkz3x12.aspx
    struct sigaction action;
    action.sa_sigaction = handler;

    // Do not block additional signals while in the handler.
    sigemptyset(&action.sa_mask);

    // The SA_SIGINFO flag tells sigaction() to use
    // the sa_sigaction field, not sa_handler.
    action.sa_flags = SA_SIGINFO;

    // We also do not want SIGTERM to dump a stacktrace, as this
    // can imply that we crashed, when we were in fact terminated
    // by user request.
    if (sigaction(SIGTERM, &action, nullptr) < 0) {
      PLOG(FATAL) << "Failed to set sigaction";
    }
#endif // __WINDOWS__
  }

  initialized->done();
}

Try<string> getLogFile(google::LogSeverity severity)
{
  if (FLAGS_log_dir.empty()) {
    return Error("The 'log_dir' option was not specified");
  }

  if (severity < 0 || google::NUM_SEVERITIES <= severity) {
    return Error("Unknown log severity: " + stringify(severity));
  }

  return path::join(FLAGS_log_dir, Path(argv0).basename()) + "." +
         google::GetLogSeverityName(severity);
}

} // namespace logging {
} // namespace internal {
} // namespace mesos {
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2017 ARM Limited
 * All rights reserved
 *
 * The license below extends only to copyright in the software and shall
 * not be construed as granting a license to any other intellectual
 * property including but not limited to intellectual property relating
 * to a hardware implementation of the functionality of the software
 * licensed hereunder.  You may use the software subject to the license
 * terms below provided that you ensure that this notice is replicated
 * unmodified and in its entirety in all distributions of the software,
 * modified or unmodified, in source code or in binary form.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met: redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer;
 * 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;
 * neither the name of the copyright holders nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS 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 COPYRIGHT
 * OWNER OR 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.
 *
 * Authors: Matteo Andreozzi
 */

#include "mem_ctrl.hh"

#include "turnaround_policy.hh"

namespace QoS {

MemCtrl::MemCtrl(const QoSMemCtrlParams * p)
  : AbstractMemory(p),
    policy(p->qos_policy),
    turnPolicy(p->qos_turnaround_policy),
    queuePolicy(QueuePolicy::create(p)),
    _numPriorities(p->qos_priorities),
    qosPriorityEscalation(p->qos_priority_escalation),
    qosSyncroScheduler(p->qos_syncro_scheduler),
    totalReadQueueSize(0), totalWriteQueueSize(0),
    busState(READ), busStateNext(READ)
{
    // Set the priority policy
    if (policy) {
        policy->setMemCtrl(this);
    }

    // Set the queue priority policy
    if (queuePolicy) {
        queuePolicy->setMemCtrl(this);
    }

    // Set the bus turnaround policy
    if (turnPolicy) {
        turnPolicy->setMemCtrl(this);
    }

    readQueueSizes.resize(_numPriorities);
    writeQueueSizes.resize(_numPriorities);
    serviceTick.resize(_numPriorities);
}

MemCtrl::~MemCtrl()
{}

void
MemCtrl::init()
{
    AbstractMemory::init();
}

void
MemCtrl::logRequest(BusState dir, MasterID m_id, uint8_t qos,
                    Addr addr, uint64_t entries)
{
    // If needed, initialize all counters and statistics
    // for this master
    addMaster(m_id);

    DPRINTF(QOS,
            "QoSMemCtrl::logRequest MASTER %s [id %d] address %d"
            " prio %d this master q packets %d"
            " - queue size %d - requested entries %d\n",
            masters[m_id], m_id, addr, qos, packetPriorities[m_id][qos],
            (dir == READ) ? readQueueSizes[qos]: writeQueueSizes[qos],
            entries);

    if (dir == READ) {
        readQueueSizes[qos] += entries;
        totalReadQueueSize += entries;
    } else if (dir == WRITE) {
        writeQueueSizes[qos] += entries;
        totalWriteQueueSize += entries;
    }

    packetPriorities[m_id][qos] += entries;
    for (auto j = 0; j < entries; ++j) {
        requestTimes[m_id][addr].push_back(curTick());
    }

    // Record statistics
    avgPriority[m_id].sample(qos);

    // Compute avg priority distance

    for (uint8_t i = 0; i < packetPriorities[m_id].size(); ++i) {
        uint8_t distance =
            (abs(int(qos) - int(i))) * packetPriorities[m_id][i];

        if (distance > 0) {
            avgPriorityDistance[m_id].sample(distance);
            DPRINTF(QOS,
                    "QoSMemCtrl::logRequest MASTER %s [id %d]"
                    " registering priority distance %d for priority %d"
                    " (packets %d)\n",
                    masters[m_id], m_id, distance, i,
                    packetPriorities[m_id][i]);
        }
    }

    DPRINTF(QOS,
            "QoSMemCtrl::logRequest MASTER %s [id %d] prio %d "
            "this master q packets %d - new queue size %d\n",
            masters[m_id], m_id, qos, packetPriorities[m_id][qos],
            (dir == READ) ? readQueueSizes[qos]: writeQueueSizes[qos]);

}

void
MemCtrl::logResponse(BusState dir, MasterID m_id, uint8_t qos,
                     Addr addr, uint64_t entries, double delay)
{
    panic_if(!hasMaster(m_id),
        "Logging response with invalid master\n");

    DPRINTF(QOS,
            "QoSMemCtrl::logResponse MASTER %s [id %d] address %d prio"
            " %d this master q packets %d"
            " - queue size %d - requested entries %d\n",
            masters[m_id], m_id, addr, qos, packetPriorities[m_id][qos],
            (dir == READ) ? readQueueSizes[qos]: writeQueueSizes[qos],
            entries);

    if (dir == READ) {
        readQueueSizes[qos] -= entries;
        totalReadQueueSize -= entries;
    } else if (dir == WRITE) {
        writeQueueSizes[qos] -= entries;
        totalWriteQueueSize -= entries;
    }

    panic_if(packetPriorities[m_id][qos] == 0,
             "QoSMemCtrl::logResponse master %s negative packets for priority"
             " %d", masters[m_id], qos);

    packetPriorities[m_id][qos] -= entries;

    for (auto j = 0; j < entries; ++j) {
        auto it = requestTimes[m_id].find(addr);
        panic_if(it == requestTimes[m_id].end(),
                 "QoSMemCtrl::logResponse master %s unmatched response for"
                 " address %d received", masters[m_id], addr);

        // Load request time
        uint64_t requestTime = it->second.front();

        // Remove request entry
        it->second.pop_front();

        // Remove whole address entry if last one
        if (it->second.empty()) {
            requestTimes[m_id].erase(it);
        }
        // Compute latency
        double latency = (double) (curTick() + delay - requestTime)
                / SimClock::Float::s;

        if (latency > 0) {
            // Record per-priority latency stats
            if (priorityMaxLatency[qos].value() < latency) {
                priorityMaxLatency[qos] = latency;
            }

            if (priorityMinLatency[qos].value() > latency
                    || priorityMinLatency[qos].value() == 0) {
                priorityMinLatency[qos] = latency;
            }
        }
    }

    DPRINTF(QOS,
            "QoSMemCtrl::logResponse MASTER %s [id %d] prio %d "
            "this master q packets %d - new queue size %d\n",
            masters[m_id], m_id, qos, packetPriorities[m_id][qos],
            (dir == READ) ? readQueueSizes[qos]: writeQueueSizes[qos]);
}

uint8_t
MemCtrl::schedule(MasterID m_id, uint64_t data)
{
    if (policy) {
        return policy->schedule(m_id, data);
    } else {
        DPRINTF(QOS,
                "QoSScheduler::schedule master ID [%d] "
                "data received [%d], but QoS scheduler not initialized\n",
                m_id,data);
        return 0;
    }
}

uint8_t
MemCtrl::schedule(const PacketPtr pkt)
{
    assert(pkt->req);

    if (policy) {
        return schedule(pkt->req->masterId(), pkt->getSize());
    } else {
        DPRINTF(QOS, "QoSScheduler::schedule Packet received [Qv %d], "
                "but QoS scheduler not initialized\n",
                pkt->qosValue());
        return pkt->qosValue();
    }
}

MemCtrl::BusState
MemCtrl::selectNextBusState()
{
    auto bus_state = getBusState();

    if (turnPolicy) {
        DPRINTF(QOS,
                "QoSMemoryTurnaround::selectBusState running policy %s\n",
                turnPolicy->name());

        bus_state = turnPolicy->selectBusState();
    } else {
        DPRINTF(QOS,
                "QoSMemoryTurnaround::selectBusState running "
                "default bus direction selection policy\n");

        if ((!getTotalReadQueueSize() && bus_state == MemCtrl::READ) ||
            (!getTotalWriteQueueSize() && bus_state == MemCtrl::WRITE)) {
            // READ/WRITE turnaround
            bus_state = (bus_state == MemCtrl::READ) ? MemCtrl::WRITE :
                                                       MemCtrl::READ;

        }
    }

    return bus_state;
}

void
MemCtrl::addMaster(MasterID m_id)
{
    if (!hasMaster(m_id)) {
        masters.emplace(m_id, _system->getMasterName(m_id));
        packetPriorities[m_id].resize(numPriorities(), 0);

        DPRINTF(QOS,
                "QoSMemCtrl::addMaster registering"
                " Master %s [id %d]\n",
                masters[m_id], m_id);
    }
}

void
MemCtrl::regStats()
{
    AbstractMemory::regStats();

    using namespace Stats;

    // Initializes per master statistics
    avgPriority.init(_system->maxMasters()).name(name() + ".avgPriority")
        .desc("Average QoS priority value for accepted requests")
        .flags(nozero | nonan).precision(2);

    avgPriorityDistance.init(_system->maxMasters())
        .name(name() + ".avgPriorityDistance")
        .desc("Average QoS priority distance between assigned and "
        "queued values").flags(nozero | nonan);

    priorityMinLatency.init(numPriorities())
        .name(name() + ".priorityMinLatency")
        .desc("per QoS priority minimum request to response latency (s)")
        .precision(12);

    priorityMaxLatency.init(numPriorities())
        .name(name() + ".priorityMaxLatency")
        .desc("per QoS priority maximum request to response latency (s)")
        .precision(12);

    numReadWriteTurnArounds.name(name() + ".numReadWriteTurnArounds")
        .desc("Number of turnarounds from READ to WRITE");

    numWriteReadTurnArounds.name(name() + ".numWriteReadTurnArounds")
        .desc("Number of turnarounds from WRITE to READ");

    numStayReadState.name(name() + ".numStayReadState")
        .desc("Number of times bus staying in READ state");

    numStayWriteState.name(name() + ".numStayWriteState")
        .desc("Number of times bus staying in WRITE state");

    for (int i = 0; i < _system->maxMasters(); i++) {
        const std::string master = _system->getMasterName(i);
        avgPriority.subname(i, master);
        avgPriorityDistance.subname(i, master);
    }

    for (int j = 0; j < numPriorities(); ++j) {
        priorityMinLatency.subname(j, std::to_string(j));
        priorityMaxLatency.subname(j, std::to_string(j));
    }

    if (policy)
        policy->regStats();
}

void
MemCtrl::recordTurnaroundStats()
{
    if (busStateNext != busState) {
        if (busState == READ) {
            numWriteReadTurnArounds++;
        } else if (busState == WRITE) {
            numReadWriteTurnArounds++;
        }
    } else {
        if (busState == READ) {
            numStayReadState++;
        } else if (busState == WRITE) {
            numStayWriteState++;
        }
    }
}

} // namespace QoS
<commit_msg>mem: avoid calling regStat twice on a QoSPolicy<commit_after>/*
 * Copyright (c) 2017-2018 ARM Limited
 * All rights reserved
 *
 * The license below extends only to copyright in the software and shall
 * not be construed as granting a license to any other intellectual
 * property including but not limited to intellectual property relating
 * to a hardware implementation of the functionality of the software
 * licensed hereunder.  You may use the software subject to the license
 * terms below provided that you ensure that this notice is replicated
 * unmodified and in its entirety in all distributions of the software,
 * modified or unmodified, in source code or in binary form.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met: redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer;
 * 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;
 * neither the name of the copyright holders nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS 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 COPYRIGHT
 * OWNER OR 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.
 *
 * Authors: Matteo Andreozzi
 */

#include "mem_ctrl.hh"

#include "turnaround_policy.hh"

namespace QoS {

MemCtrl::MemCtrl(const QoSMemCtrlParams * p)
  : AbstractMemory(p),
    policy(p->qos_policy),
    turnPolicy(p->qos_turnaround_policy),
    queuePolicy(QueuePolicy::create(p)),
    _numPriorities(p->qos_priorities),
    qosPriorityEscalation(p->qos_priority_escalation),
    qosSyncroScheduler(p->qos_syncro_scheduler),
    totalReadQueueSize(0), totalWriteQueueSize(0),
    busState(READ), busStateNext(READ)
{
    // Set the priority policy
    if (policy) {
        policy->setMemCtrl(this);
    }

    // Set the queue priority policy
    if (queuePolicy) {
        queuePolicy->setMemCtrl(this);
    }

    // Set the bus turnaround policy
    if (turnPolicy) {
        turnPolicy->setMemCtrl(this);
    }

    readQueueSizes.resize(_numPriorities);
    writeQueueSizes.resize(_numPriorities);
    serviceTick.resize(_numPriorities);
}

MemCtrl::~MemCtrl()
{}

void
MemCtrl::init()
{
    AbstractMemory::init();
}

void
MemCtrl::logRequest(BusState dir, MasterID m_id, uint8_t qos,
                    Addr addr, uint64_t entries)
{
    // If needed, initialize all counters and statistics
    // for this master
    addMaster(m_id);

    DPRINTF(QOS,
            "QoSMemCtrl::logRequest MASTER %s [id %d] address %d"
            " prio %d this master q packets %d"
            " - queue size %d - requested entries %d\n",
            masters[m_id], m_id, addr, qos, packetPriorities[m_id][qos],
            (dir == READ) ? readQueueSizes[qos]: writeQueueSizes[qos],
            entries);

    if (dir == READ) {
        readQueueSizes[qos] += entries;
        totalReadQueueSize += entries;
    } else if (dir == WRITE) {
        writeQueueSizes[qos] += entries;
        totalWriteQueueSize += entries;
    }

    packetPriorities[m_id][qos] += entries;
    for (auto j = 0; j < entries; ++j) {
        requestTimes[m_id][addr].push_back(curTick());
    }

    // Record statistics
    avgPriority[m_id].sample(qos);

    // Compute avg priority distance

    for (uint8_t i = 0; i < packetPriorities[m_id].size(); ++i) {
        uint8_t distance =
            (abs(int(qos) - int(i))) * packetPriorities[m_id][i];

        if (distance > 0) {
            avgPriorityDistance[m_id].sample(distance);
            DPRINTF(QOS,
                    "QoSMemCtrl::logRequest MASTER %s [id %d]"
                    " registering priority distance %d for priority %d"
                    " (packets %d)\n",
                    masters[m_id], m_id, distance, i,
                    packetPriorities[m_id][i]);
        }
    }

    DPRINTF(QOS,
            "QoSMemCtrl::logRequest MASTER %s [id %d] prio %d "
            "this master q packets %d - new queue size %d\n",
            masters[m_id], m_id, qos, packetPriorities[m_id][qos],
            (dir == READ) ? readQueueSizes[qos]: writeQueueSizes[qos]);

}

void
MemCtrl::logResponse(BusState dir, MasterID m_id, uint8_t qos,
                     Addr addr, uint64_t entries, double delay)
{
    panic_if(!hasMaster(m_id),
        "Logging response with invalid master\n");

    DPRINTF(QOS,
            "QoSMemCtrl::logResponse MASTER %s [id %d] address %d prio"
            " %d this master q packets %d"
            " - queue size %d - requested entries %d\n",
            masters[m_id], m_id, addr, qos, packetPriorities[m_id][qos],
            (dir == READ) ? readQueueSizes[qos]: writeQueueSizes[qos],
            entries);

    if (dir == READ) {
        readQueueSizes[qos] -= entries;
        totalReadQueueSize -= entries;
    } else if (dir == WRITE) {
        writeQueueSizes[qos] -= entries;
        totalWriteQueueSize -= entries;
    }

    panic_if(packetPriorities[m_id][qos] == 0,
             "QoSMemCtrl::logResponse master %s negative packets for priority"
             " %d", masters[m_id], qos);

    packetPriorities[m_id][qos] -= entries;

    for (auto j = 0; j < entries; ++j) {
        auto it = requestTimes[m_id].find(addr);
        panic_if(it == requestTimes[m_id].end(),
                 "QoSMemCtrl::logResponse master %s unmatched response for"
                 " address %d received", masters[m_id], addr);

        // Load request time
        uint64_t requestTime = it->second.front();

        // Remove request entry
        it->second.pop_front();

        // Remove whole address entry if last one
        if (it->second.empty()) {
            requestTimes[m_id].erase(it);
        }
        // Compute latency
        double latency = (double) (curTick() + delay - requestTime)
                / SimClock::Float::s;

        if (latency > 0) {
            // Record per-priority latency stats
            if (priorityMaxLatency[qos].value() < latency) {
                priorityMaxLatency[qos] = latency;
            }

            if (priorityMinLatency[qos].value() > latency
                    || priorityMinLatency[qos].value() == 0) {
                priorityMinLatency[qos] = latency;
            }
        }
    }

    DPRINTF(QOS,
            "QoSMemCtrl::logResponse MASTER %s [id %d] prio %d "
            "this master q packets %d - new queue size %d\n",
            masters[m_id], m_id, qos, packetPriorities[m_id][qos],
            (dir == READ) ? readQueueSizes[qos]: writeQueueSizes[qos]);
}

uint8_t
MemCtrl::schedule(MasterID m_id, uint64_t data)
{
    if (policy) {
        return policy->schedule(m_id, data);
    } else {
        DPRINTF(QOS,
                "QoSScheduler::schedule master ID [%d] "
                "data received [%d], but QoS scheduler not initialized\n",
                m_id,data);
        return 0;
    }
}

uint8_t
MemCtrl::schedule(const PacketPtr pkt)
{
    assert(pkt->req);

    if (policy) {
        return schedule(pkt->req->masterId(), pkt->getSize());
    } else {
        DPRINTF(QOS, "QoSScheduler::schedule Packet received [Qv %d], "
                "but QoS scheduler not initialized\n",
                pkt->qosValue());
        return pkt->qosValue();
    }
}

MemCtrl::BusState
MemCtrl::selectNextBusState()
{
    auto bus_state = getBusState();

    if (turnPolicy) {
        DPRINTF(QOS,
                "QoSMemoryTurnaround::selectBusState running policy %s\n",
                turnPolicy->name());

        bus_state = turnPolicy->selectBusState();
    } else {
        DPRINTF(QOS,
                "QoSMemoryTurnaround::selectBusState running "
                "default bus direction selection policy\n");

        if ((!getTotalReadQueueSize() && bus_state == MemCtrl::READ) ||
            (!getTotalWriteQueueSize() && bus_state == MemCtrl::WRITE)) {
            // READ/WRITE turnaround
            bus_state = (bus_state == MemCtrl::READ) ? MemCtrl::WRITE :
                                                       MemCtrl::READ;

        }
    }

    return bus_state;
}

void
MemCtrl::addMaster(MasterID m_id)
{
    if (!hasMaster(m_id)) {
        masters.emplace(m_id, _system->getMasterName(m_id));
        packetPriorities[m_id].resize(numPriorities(), 0);

        DPRINTF(QOS,
                "QoSMemCtrl::addMaster registering"
                " Master %s [id %d]\n",
                masters[m_id], m_id);
    }
}

void
MemCtrl::regStats()
{
    AbstractMemory::regStats();

    using namespace Stats;

    // Initializes per master statistics
    avgPriority.init(_system->maxMasters()).name(name() + ".avgPriority")
        .desc("Average QoS priority value for accepted requests")
        .flags(nozero | nonan).precision(2);

    avgPriorityDistance.init(_system->maxMasters())
        .name(name() + ".avgPriorityDistance")
        .desc("Average QoS priority distance between assigned and "
        "queued values").flags(nozero | nonan);

    priorityMinLatency.init(numPriorities())
        .name(name() + ".priorityMinLatency")
        .desc("per QoS priority minimum request to response latency (s)")
        .precision(12);

    priorityMaxLatency.init(numPriorities())
        .name(name() + ".priorityMaxLatency")
        .desc("per QoS priority maximum request to response latency (s)")
        .precision(12);

    numReadWriteTurnArounds.name(name() + ".numReadWriteTurnArounds")
        .desc("Number of turnarounds from READ to WRITE");

    numWriteReadTurnArounds.name(name() + ".numWriteReadTurnArounds")
        .desc("Number of turnarounds from WRITE to READ");

    numStayReadState.name(name() + ".numStayReadState")
        .desc("Number of times bus staying in READ state");

    numStayWriteState.name(name() + ".numStayWriteState")
        .desc("Number of times bus staying in WRITE state");

    for (int i = 0; i < _system->maxMasters(); i++) {
        const std::string master = _system->getMasterName(i);
        avgPriority.subname(i, master);
        avgPriorityDistance.subname(i, master);
    }

    for (int j = 0; j < numPriorities(); ++j) {
        priorityMinLatency.subname(j, std::to_string(j));
        priorityMaxLatency.subname(j, std::to_string(j));
    }
}

void
MemCtrl::recordTurnaroundStats()
{
    if (busStateNext != busState) {
        if (busState == READ) {
            numWriteReadTurnArounds++;
        } else if (busState == WRITE) {
            numReadWriteTurnArounds++;
        }
    } else {
        if (busState == READ) {
            numStayReadState++;
        } else if (busState == WRITE) {
            numStayWriteState++;
        }
    }
}

} // namespace QoS
<|endoftext|>


<commit_before>/*
Copyright (c) 2015, Wator Vapor
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

* Redistributions of source code must retain the above copyright notice, this
  list of conditions and the following disclaimer.

* 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.

* Neither the name of wator nor the names of its
  contributors may be used to endorse or promote products derived from
  this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS 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 COPYRIGHT HOLDER OR 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.
*/
#include "wator.hpp"
using namespace Wator;

#include <boost/property_tree/ptree.hpp>
#include <boost/property_tree/json_parser.hpp>
using namespace boost::property_tree;

/**
 * Constructor
 **/
ImplicitMemory::ImplicitMemory()
{
}
/**
 * Constructor
 * @param [in] info layer parameter.
 **/
ImplicitMemory::ImplicitMemory(const pt::ptree& info)
:serial_(info)
{
}

/**
 * update
 **/
void ImplicitMemory::update(int pinch,uint64_t index,int ground)
{
    std::bitset<64> memBit(index);
    if (memBit.count() < ground) {
        return;
    }

    // add hold space
    for(int i = memory_.size();i < pinch + 1 ;i++) {
        memory_.push_back({});
    }
    INFO_VAR(memory_.size());
    auto &memory = memory_.at(pinch);
    auto it = memory.find(index);
    if (it != memory.end()) {
        it->second++;
   } else {
        memory.insert({index,1});
    }
}

/**
 * sort
 **/
void ImplicitMemory::sort()
{
    for(int index = memRanking_.size(); index < memory_.size();index++) {
        memRanking_.push_back({});
    }
    for(int index = 0; index < memory_.size();index++) {
        //        map<uint64_t,vector<uint64_t>> sortByCount;
        auto &memory = memory_[index];
        for (auto it:memory) {
            auto memCount = it.second;
            std::bitset<25> memBit(it.first);
            TRACE_VAR(memBit);
            TRACE_VAR(it.second);
            auto itSort = memRanking_[index].find(memCount);
            if (memRanking_[index].end() != itSort) {
                itSort->second.push_back(it.first);
            } else {
                memRanking_[index][memCount] = {it.first};
            }
        }
        for (auto it:memRanking_[index]) {
            auto memCount = it.first;
            TRACE_VAR(memCount);
            TRACE_VAR(it.second.size());
            for (auto mem:it.second)
            {
                std::bitset<25> memBit(mem);
                TRACE_VAR(memBit);
            }
        }
        TRACE_VAR(memory.size());
        TRACE_VAR(memRanking_[index].size());
    }
    INFO_VAR(memory_.size());
    for(const auto &memory :memory_){
        INFO_VAR(memory.size());
        for(const auto &pair:memory){
            std::bitset<25> memBit(pair.first);
            INFO_VAR(memBit);
            INFO_VAR(pair.second);
        }
    }
}

/*
 1000010000100000000000000
 1000010000100000000000000
 */

<commit_msg>memory module<commit_after>/*
Copyright (c) 2015, Wator Vapor
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

* Redistributions of source code must retain the above copyright notice, this
  list of conditions and the following disclaimer.

* 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.

* Neither the name of wator nor the names of its
  contributors may be used to endorse or promote products derived from
  this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS 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 COPYRIGHT HOLDER OR 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.
*/
#include "wator.hpp"
using namespace Wator;

#include <boost/property_tree/ptree.hpp>
#include <boost/property_tree/json_parser.hpp>
using namespace boost::property_tree;

/**
 * Constructor
 **/
ImplicitMemory::ImplicitMemory()
{
}
/**
 * Constructor
 * @param [in] info layer parameter.
 **/
ImplicitMemory::ImplicitMemory(const pt::ptree& info)
:serial_(info)
{
}

/**
 * update
 **/
void ImplicitMemory::update(int pinch,uint64_t index,int ground)
{
    std::bitset<64> memBit(index);
    if (memBit.count() < ground) {
        return;
    }

    // add hold space
    for(int i = memory_.size();i < pinch + 1 ;i++) {
        memory_.push_back({});
    }
    INFO_VAR(memory_.size());
    auto &memory = memory_.at(pinch);
    auto it = memory.find(index);
    if (it != memory.end()) {
        it->second++;
   } else {
        memory.insert({index,1});
    }
}

/**
 * sort
 **/
void ImplicitMemory::sort()
{
    memRanking_.clear();
    for(int index = 0; index < memory_.size();index++) {
        memRanking_.push_back({});
    }
    for(int index = 0; index < memory_.size();index++) {
        //        map<uint64_t,vector<uint64_t>> sortByCount;
        auto &memory = memory_[index];
        for (auto it:memory) {
            auto memCount = it.second;
            std::bitset<25> memBit(it.first);
            TRACE_VAR(memBit);
            TRACE_VAR(it.second);
            auto itSort = memRanking_[index].find(memCount);
            if (memRanking_[index].end() != itSort) {
                itSort->second.push_back(it.first);
            } else {
                memRanking_[index][memCount] = {it.first};
            }
        }
        for (auto it:memRanking_[index]) {
            auto memCount = it.first;
            INFO_VAR(it.second.size());
            INFO_VAR(memCount);
            for (auto mem:it.second)
            {
                std::bitset<25> memBit(mem);
                INFO_VAR(memBit);
            }
        }
        TRACE_VAR(memory.size());
        TRACE_VAR(memRanking_[index].size());
    }
    INFO_VAR(memory_.size());
    for(const auto &memory :memory_){
        INFO_VAR(memory.size());
#if 0
        for(const auto &pair:memory){
            std::bitset<25> memBit(pair.first);
            INFO_VAR(memBit);
            INFO_VAR(pair.second);
        }
#endif
    }
}

/*
 1000010000100000000000000
 1000010000100000000000000
 */

<|endoftext|>