<commit_before>/* -*- Mode: C++; c-file-style: "gnu" -*- */
/*
 * Copyright 2014 Waseda University, Sato Laboratory
 *   Author: Jairo Eduardo Lopez <jairo@ruri.waseda.jp>
 *
 *  nnn-do.cc is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU Affero Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  nnn-do.cc is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU Affero Public License for more details.
 *
 *  You should have received a copy of the GNU Affero Public License
 *  along with nnn-do.cc.  If not, see <http://www.gnu.org/licenses/>.
 *
 */

#include <ns3-dev/ns3/log.h>
#include <ns3-dev/ns3/unused.h>

#include "nnn-do.h"

NS_LOG_COMPONENT_DEFINE ("nnn.DO");

namespace ns3 {
  namespace nnn {

    DO::DO () : NNNPacket (DO_NNN, Seconds (0))
    , m_payload  (Create<Packet> ())
    , m_PDUdatatype (NDN_NNN)
    {
    }

    DO::DO (Ptr<NNNAddress> name, Ptr<Packet> payload)
    : NNNPacket (DO_NNN, Seconds (0))
    , m_name     (name)
    , m_PDUdatatype (NDN_NNN)
    {
      if (m_payload == 0)
	{
	  m_payload = Create<Packet> ();
	} else
	  {
	    m_payload = payload;
	  }
    }

    DO::DO (const NNNAddress &name, Ptr<Packet> payload)
    : NNNPacket (DO_NNN, Seconds(0))
    , m_name     (Create<NNNAddress> (name))
    , m_PDUdatatype (NDN_NNN)
    {
      if (m_payload == 0)
	{
	  m_payload = Create<Packet> ();
	} else
	  {
	    m_payload = payload;
	  }
    }

    DO::DO (const DO &do_p)
    : NNNPacket (DO_NNN, do_p.GetLifetime ())
    , m_name     (Create<NNNAddress> (do_p.GetName()))
    , m_payload  (do_p.GetPayload ()->Copy ())
    , m_PDUdatatype (do_p.GetPDUPayloadType ())
    {
      NS_LOG_FUNCTION("DO correct copy constructor");

      SetWire (do_p.GetWire ());
    }

    const NNNAddress&
    DO::GetName () const
    {
      if (m_name == 0) throw DOException ();
      return *m_name;
    }

    Ptr<const NNNAddress>
    DO::GetNamePtr () const
    {
      return m_name;
    }

    void
    DO::SetName (Ptr<NNNAddress> name)
    {
      m_name = name;
      SetWire(0);
    }

    void
    DO::SetName (const NNNAddress &name)
    {
      m_name = Create<NNNAddress> (name);
      SetWire(0);
    }

    uint16_t
    DO::GetPDUPayloadType() const
    {
      return m_PDUdatatype;
    }

    void
    DO::SetPDUPayloadType (uint16_t pdu_type)
    {
      m_PDUdatatype = pdu_type;
    }

    void
    DO::SetPayload (Ptr<Packet> payload)
    {
      m_payload = payload;
      SetWire(0);
    }

    Ptr<const Packet>
    DO::GetPayload () const
    {
      return m_payload;
    }

    void
    DO::Print (std::ostream &os) const
    {
      os << "<DO>\n";
      os << "  <TTL>" << GetLifetime () << "</TTL>\n";
      os << "  <Name>" << GetName () << "</Name>\n";
      if (m_payload != 0)
	{
	  os << "  <Payload>Yes</Payload>\n";
	} else
	  {
	    os << "  <Payload>No</Payload>\n";
	  }
      os << "</DO>";
    }

  } // namespace nnn
} // namespace ns3
<commit_msg>Modified DO package printing method<commit_after>/* -*- Mode: C++; c-file-style: "gnu" -*- */
/*
 * Copyright 2014 Waseda University, Sato Laboratory
 *   Author: Jairo Eduardo Lopez <jairo@ruri.waseda.jp>
 *
 *  nnn-do.cc is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU Affero Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  nnn-do.cc is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU Affero Public License for more details.
 *
 *  You should have received a copy of the GNU Affero Public License
 *  along with nnn-do.cc.  If not, see <http://www.gnu.org/licenses/>.
 *
 */

#include <ns3-dev/ns3/log.h>
#include <ns3-dev/ns3/unused.h>

#include "nnn-do.h"

NS_LOG_COMPONENT_DEFINE ("nnn.DO");

namespace ns3 {
  namespace nnn {

    DO::DO () : NNNPacket (DO_NNN, Seconds (0))
    , m_payload  (Create<Packet> ())
    , m_PDUdatatype (NDN_NNN)
    {
    }

    DO::DO (Ptr<NNNAddress> name, Ptr<Packet> payload)
    : NNNPacket (DO_NNN, Seconds (0))
    , m_name     (name)
    , m_PDUdatatype (NDN_NNN)
    {
      if (m_payload == 0)
	{
	  m_payload = Create<Packet> ();
	} else
	  {
	    m_payload = payload;
	  }
    }

    DO::DO (const NNNAddress &name, Ptr<Packet> payload)
    : NNNPacket (DO_NNN, Seconds(0))
    , m_name     (Create<NNNAddress> (name))
    , m_PDUdatatype (NDN_NNN)
    {
      if (m_payload == 0)
	{
	  m_payload = Create<Packet> ();
	} else
	  {
	    m_payload = payload;
	  }
    }

    DO::DO (const DO &do_p)
    : NNNPacket (DO_NNN, do_p.GetLifetime ())
    , m_name     (Create<NNNAddress> (do_p.GetName()))
    , m_payload  (do_p.GetPayload ()->Copy ())
    , m_PDUdatatype (do_p.GetPDUPayloadType ())
    {
      NS_LOG_FUNCTION("DO correct copy constructor");

      SetWire (do_p.GetWire ());
    }

    const NNNAddress&
    DO::GetName () const
    {
      if (m_name == 0) throw DOException ();
      return *m_name;
    }

    Ptr<const NNNAddress>
    DO::GetNamePtr () const
    {
      return m_name;
    }

    void
    DO::SetName (Ptr<NNNAddress> name)
    {
      m_name = name;
      SetWire(0);
    }

    void
    DO::SetName (const NNNAddress &name)
    {
      m_name = Create<NNNAddress> (name);
      SetWire(0);
    }

    uint16_t
    DO::GetPDUPayloadType() const
    {
      return m_PDUdatatype;
    }

    void
    DO::SetPDUPayloadType (uint16_t pdu_type)
    {
      m_PDUdatatype = pdu_type;
    }

    void
    DO::SetPayload (Ptr<Packet> payload)
    {
      m_payload = payload;
      SetWire(0);
    }

    Ptr<const Packet>
    DO::GetPayload () const
    {
      return m_payload;
    }

    void
    DO::Print (std::ostream &os) const
    {
      os << "<DO>" << std::endl;
      os << "  <TTL>" << GetLifetime () << "</TTL>" << std::endl;
      os << "  <Version>" << GetVersion () << "</Version>" << std::endl;
      os << "  <Name>" << GetName () << "</Name>" << std::endl;
      os << "  <PDU Type>" << GetPDUPayloadType() << "</PDU Type>" << std::endl;
      if (m_payload != 0)
	{
	  os << "  <Payload>Yes</Payload>" << std::endl;
	}
      else
	{
	  os << "  <Payload>No</Payload>" << std::endl;
	}
      os << "</DO>" << std::endl;
    }

  } // namespace nnn
} // namespace ns3
<|endoftext|>


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

#include "SliceWidget.h"

SliceWidget::SliceWidget(std::vector<OSPModel> models,
                         osp::box3f volumeBounds)
  : models(models),
    volumeBounds(volumeBounds),
    triangleMesh(NULL),
    originSliderAnimationDirection(1)
{
  //! Check parameters.
  if(models.size() == 0)
    throw std::runtime_error("must be constructed with existing model(s)");

  if(volume(volumeBounds) <= 0.f)
    throw std::runtime_error("invalid volume bounds");

  //! Setup UI elements.
  QVBoxLayout * layout = new QVBoxLayout();
  setLayout(layout);

  //! Save and load buttons.
  QWidget * saveLoadWidget = new QWidget();
  QHBoxLayout * hboxLayout = new QHBoxLayout();
  saveLoadWidget->setLayout(hboxLayout);

  QPushButton * saveButton = new QPushButton("Save");
  connect(saveButton, SIGNAL(clicked()), this, SLOT(save()));
  hboxLayout->addWidget(saveButton);

  QPushButton * loadButton = new QPushButton("Load");
  connect(loadButton, SIGNAL(clicked()), this, SLOT(load()));
  hboxLayout->addWidget(loadButton);

  layout->addWidget(saveLoadWidget);

  //! Form layout for the rest of the UI elements.
  QWidget * formWidget = new QWidget();
  QFormLayout * formLayout = new QFormLayout();
  formWidget->setLayout(formLayout);
  layout->addWidget(formWidget);

  //! Origin parameters with default values.
  QWidget * originWidget = new QWidget();
  hboxLayout = new QHBoxLayout();
  originWidget->setLayout(hboxLayout);

  originXSpinBox.setRange(volumeBounds.lower.x, volumeBounds.upper.x);
  originYSpinBox.setRange(volumeBounds.lower.y, volumeBounds.upper.y);
  originZSpinBox.setRange(volumeBounds.lower.z, volumeBounds.upper.z);

  originXSpinBox.setValue(0.5 * (volumeBounds.lower.x + volumeBounds.upper.x));
  originYSpinBox.setValue(0.5 * (volumeBounds.lower.y + volumeBounds.upper.y));
  originZSpinBox.setValue(0.5 * (volumeBounds.lower.z + volumeBounds.upper.z));

  connect(&originXSpinBox, SIGNAL(valueChanged(double)), this, SLOT(autoApply()));
  connect(&originYSpinBox, SIGNAL(valueChanged(double)), this, SLOT(autoApply()));
  connect(&originZSpinBox, SIGNAL(valueChanged(double)), this, SLOT(autoApply()));

  hboxLayout->addWidget(&originXSpinBox);
  hboxLayout->addWidget(&originYSpinBox);
  hboxLayout->addWidget(&originZSpinBox);

  formLayout->addRow("Origin", originWidget);

  //! Normal parameters with default values.
  QWidget * normalWidget = new QWidget();
  hboxLayout = new QHBoxLayout();
  normalWidget->setLayout(hboxLayout);

  normalXSpinBox.setRange(-1., 1.);
  normalYSpinBox.setRange(-1., 1.);
  normalZSpinBox.setRange(-1., 1.);

  normalXSpinBox.setValue(1.);
  normalYSpinBox.setValue(0.);
  normalZSpinBox.setValue(0.);

  connect(&normalXSpinBox, SIGNAL(valueChanged(double)), this, SLOT(autoApply()));
  connect(&normalYSpinBox, SIGNAL(valueChanged(double)), this, SLOT(autoApply()));
  connect(&normalZSpinBox, SIGNAL(valueChanged(double)), this, SLOT(autoApply()));

  hboxLayout->addWidget(&normalXSpinBox);
  hboxLayout->addWidget(&normalYSpinBox);
  hboxLayout->addWidget(&normalZSpinBox);

  formLayout->addRow("Normal", normalWidget);

  //! Add a slider and animate button for the origin location along the normal.
  QWidget * originSliderWidget = new QWidget();
  hboxLayout = new QHBoxLayout();
  originSliderWidget->setLayout(hboxLayout);

  originSlider.setOrientation(Qt::Horizontal);
  connect(&originSlider, SIGNAL(valueChanged(int)), this, SLOT(originSliderValueChanged(int)));
  hboxLayout->addWidget(&originSlider);

  originSliderAnimateButton.setText("Animate");
  originSliderAnimateButton.setCheckable(true);
  connect(&originSliderAnimateButton, SIGNAL(toggled(bool)), this, SLOT(setAnimation(bool)));
  hboxLayout->addWidget(&originSliderAnimateButton);

  formLayout->addRow("", originSliderWidget);

  //! Connect animation timer signal / slot.
  connect(&originSliderAnimationTimer, SIGNAL(timeout()), this, SLOT(animate()));

  //! Auto-apply checkbox, Delete, and Apply buttons.
  QWidget * buttonsWidget = new QWidget();
  hboxLayout = new QHBoxLayout();
  buttonsWidget->setLayout(hboxLayout);

  autoApplyCheckBox.setText("Auto update");
  autoApplyCheckBox.setChecked(true);
  hboxLayout->addWidget(&autoApplyCheckBox);

  QPushButton * deleteButton = new QPushButton("Delete");
  connect(deleteButton, SIGNAL(clicked()), this, SLOT(deleteLater()));
  hboxLayout->addWidget(deleteButton);

  QPushButton * applyButton = new QPushButton("Apply");
  connect(applyButton, SIGNAL(clicked()), this, SLOT(apply()));
  hboxLayout->addWidget(applyButton);

  layout->addWidget(buttonsWidget);

  //! Frame style for the widget.
  setFrameStyle(QFrame::Panel | QFrame::Raised);

  //! Minimum width for the widget.
  setMinimumWidth(240);

  //! Auto-apply (if enabled)
  autoApply();
}

SliceWidget::~SliceWidget() {

  if(triangleMesh) {

    for(unsigned int i=0; i<models.size(); i++) {

      ospRemoveGeometry(models[i], triangleMesh);
      ospCommit(models[i]);
    }
  }

  emit(sliceChanged());
}

void SliceWidget::apply() {

  //! Get the origin and normal values.
  osp::vec3f origin(float(originXSpinBox.value()), float(originYSpinBox.value()), float(originZSpinBox.value()));
  osp::vec3f normal = osp::vec3f(float(normalXSpinBox.value()), float(normalYSpinBox.value()), float(normalZSpinBox.value()));

  if(normal == osp::vec3f(0.f))
    return;
  else
    normal = normalize(normal);

  //! Create the OSPRay geometry on the first apply().
  bool newGeometry = false;

  if(!triangleMesh) {

    triangleMesh = ospNewTriangleMesh();
    newGeometry = true;
  }

  //! Compute basis vectors.
  osp::vec3f c(1.f,0.f,0.f);

  if(dot(c, normal) > 0.9f)
    c = osp::vec3f(0.f,1.f,0.f);

  osp::vec3f b1 = cross(c, normal);
  osp::vec3f b2 = cross(b1, normal);

  //! For now just make a slice sufficiently large to span the volume.
  const float size = sqrtf(2.f);

  //! Create the triangles forming the slice.
  osp::vec3f lowerLeft(origin - size*b1 - size*b2);
  osp::vec3f span1(2.f*size*b1);
  osp::vec3f span2(2.f*size*b2);

  //! Subdivide the plane into a larger set of triangles to help with performance when combined with other geometries.
  const size_t numSubdivisions = 32;

  std::vector<osp::vec3fa> positions;

  for(size_t i=0; i<numSubdivisions; i++)
    for(size_t j=0; j<numSubdivisions; j++)
      positions.push_back(lowerLeft + float(i)/float(numSubdivisions-1)*span1 + float(j)/float(numSubdivisions-1)*span2);

  std::vector<osp::vec3i> indices;

  for(size_t i=0; i<numSubdivisions-1; i++) {
    for(size_t j=0; j<numSubdivisions-1; j++) {

      indices.push_back(osp::vec3i(i*numSubdivisions+j, (i+1)*numSubdivisions+j, i*numSubdivisions+j+1));
      indices.push_back(osp::vec3i((i+1)*numSubdivisions+j, (i+1)*numSubdivisions+j+1, i*numSubdivisions+j+1));
    }
  }

  //! Update the OSPRay geometry.
  OSPData positionData = ospNewData(positions.size(), OSP_FLOAT3A, &positions[0].x);
  ospSetData(triangleMesh, "position", positionData);

  OSPData indexData = ospNewData(indices.size(), OSP_INT3, &indices[0].x);
  ospSetData(triangleMesh, "index", indexData);

  ospCommit(triangleMesh);

  if(newGeometry)
    for(unsigned int i=0; i<models.size(); i++)
      ospAddGeometry(models[i], triangleMesh);

  for(unsigned int i=0; i<models.size(); i++)
    ospCommit(models[i]);

  emit(sliceChanged());
}

void SliceWidget::load(std::string filename) {

  //! Get filename if not specified.
  if(filename.empty())
    filename = QFileDialog::getOpenFileName(this, tr("Load slice"), ".", "Slice files (*.slc)").toStdString();

  if(filename.empty())
    return;

  //! Get serialized slice state from file.
  QFile file(filename.c_str());
  bool success = file.open(QIODevice::ReadOnly);

  if(!success)
    {
      std::cerr << "unable to open " << filename << std::endl;
      return;
    }

  QDataStream in(&file);

  bool autoApply;
  in >> autoApply;

  double originX, originY, originZ;
  in >> originX >> originY >> originZ;

  double normalX, normalY, normalZ;
  in >> normalX >> normalY >> normalZ;

  int sliderPosition;
  in >> sliderPosition;

  bool sliderAnimating;
  in >> sliderAnimating;

  in >> originSliderAnimationDirection;

  //! Update slice state. Update values of the UI elements directly to signal appropriate slots.
  autoApplyCheckBox.setChecked(autoApply);
  originXSpinBox.setValue(originX);
  originYSpinBox.setValue(originY);
  originZSpinBox.setValue(originZ);
  normalXSpinBox.setValue(normalX);
  normalYSpinBox.setValue(normalY);
  normalZSpinBox.setValue(normalZ);
  originSlider.setValue(sliderPosition);
  originSliderAnimateButton.setChecked(sliderAnimating);
}

void SliceWidget::save() {

  //! Get filename.
  QString filename = QFileDialog::getSaveFileName(this, "Save slice", ".", "Slice files (*.slc)");

  if(filename.isNull())
    return;

  //! Make sure the filename has the proper extension.
  if(filename.endsWith(".slc") != true)
    filename += ".slc";

  //! Serialize slice state to file.
  QFile file(filename);
  bool success = file.open(QIODevice::WriteOnly);

  if(!success)
    {
      std::cerr << "unable to open " << filename.toStdString() << std::endl;
      return;
    }

  QDataStream out(&file);

  out << autoApplyCheckBox.isChecked();
  out << originXSpinBox.value() << originXSpinBox.value() << originXSpinBox.value();
  out << normalXSpinBox.value() << normalYSpinBox.value() << normalZSpinBox.value();
  out << originSlider.value();
  out << originSliderAnimateButton.isChecked();
  out << originSliderAnimationDirection;
}

void SliceWidget::autoApply() {

  if(autoApplyCheckBox.isChecked())
    apply();
}

void SliceWidget::originSliderValueChanged(int value) {

  //! Slider position in [0, 1].
  float sliderPosition = float(value) / float(originSlider.maximum() - originSlider.minimum());

  //! Get origin and (normalized) normal vectors.
  osp::vec3f origin(originXSpinBox.value(), originYSpinBox.value(), originZSpinBox.value());
  osp::vec3f normal = normalize(osp::vec3f(normalXSpinBox.value(), normalYSpinBox.value(), normalZSpinBox.value()));

  //! Compute allowed range along normal for the volume bounds.
  osp::vec3f upper(normal.x >= 0.f ? volumeBounds.upper.x : volumeBounds.lower.x,
                   normal.y >= 0.f ? volumeBounds.upper.y : volumeBounds.lower.y,
                   normal.z >= 0.f ? volumeBounds.upper.z : volumeBounds.lower.z);

  osp::vec3f lower(normal.x >= 0.f ? volumeBounds.lower.x : volumeBounds.upper.x,
                   normal.y >= 0.f ? volumeBounds.lower.y : volumeBounds.upper.y,
                   normal.z >= 0.f ? volumeBounds.lower.z : volumeBounds.upper.z);

  float tMax = dot(abs(upper - origin), abs(normal));
  float tMin = -dot(abs(lower - origin), abs(normal));

  //! Get t value within this range.
  float t = tMin + sliderPosition * (tMax - tMin);

  //! Clamp t within epsilon of the minimum and maximum, to prevent artifacts rendering near the bounds of the volume.
  const float epsilon = 0.01;
  t = std::max(std::min(t, tMax-epsilon), tMin+epsilon);

  //! Compute updated origin, clamped within the volume bounds.
  osp::vec3f updatedOrigin = clamp(origin + t*normal, volumeBounds.lower, volumeBounds.upper);

  //! Finally, set the new origin value.
  originXSpinBox.setValue(updatedOrigin.x);
  originYSpinBox.setValue(updatedOrigin.y);
  originZSpinBox.setValue(updatedOrigin.z);
}

void SliceWidget::setAnimation(bool set) {

  //! Start or stop the animation timer.
  if(set)
    originSliderAnimationTimer.start(100);
  else
    originSliderAnimationTimer.stop();
}

void SliceWidget::animate() {

  int value = originSlider.value();

  //! Check if we need to reverse direction.
  if(value + originSliderAnimationDirection < originSlider.minimum() || value + originSliderAnimationDirection > originSlider.maximum())
    originSliderAnimationDirection *= -1;

  //! Increment slider position.
  originSlider.setValue(value + originSliderAnimationDirection);
}
<commit_msg>fix for volume viewer slice coloring with new DifferentialGeometry color defaults.<commit_after>// ======================================================================== //
// Copyright 2009-2015 Intel Corporation                                    //
//                                                                          //
// Licensed under the Apache License, Version 2.0 (the "License");          //
// you may not use this file except in compliance with the License.         //
// You may obtain a copy of the License at                                  //
//                                                                          //
//     http://www.apache.org/licenses/LICENSE-2.0                           //
//                                                                          //
// Unless required by applicable law or agreed to in writing, software      //
// distributed under the License is distributed on an "AS IS" BASIS,        //
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. //
// See the License for the specific language governing permissions and      //
// limitations under the License.                                           //
// ======================================================================== //

#include "SliceWidget.h"

SliceWidget::SliceWidget(std::vector<OSPModel> models,
                         osp::box3f volumeBounds)
  : models(models),
    volumeBounds(volumeBounds),
    triangleMesh(NULL),
    originSliderAnimationDirection(1)
{
  //! Check parameters.
  if(models.size() == 0)
    throw std::runtime_error("must be constructed with existing model(s)");

  if(volume(volumeBounds) <= 0.f)
    throw std::runtime_error("invalid volume bounds");

  //! Setup UI elements.
  QVBoxLayout * layout = new QVBoxLayout();
  setLayout(layout);

  //! Save and load buttons.
  QWidget * saveLoadWidget = new QWidget();
  QHBoxLayout * hboxLayout = new QHBoxLayout();
  saveLoadWidget->setLayout(hboxLayout);

  QPushButton * saveButton = new QPushButton("Save");
  connect(saveButton, SIGNAL(clicked()), this, SLOT(save()));
  hboxLayout->addWidget(saveButton);

  QPushButton * loadButton = new QPushButton("Load");
  connect(loadButton, SIGNAL(clicked()), this, SLOT(load()));
  hboxLayout->addWidget(loadButton);

  layout->addWidget(saveLoadWidget);

  //! Form layout for the rest of the UI elements.
  QWidget * formWidget = new QWidget();
  QFormLayout * formLayout = new QFormLayout();
  formWidget->setLayout(formLayout);
  layout->addWidget(formWidget);

  //! Origin parameters with default values.
  QWidget * originWidget = new QWidget();
  hboxLayout = new QHBoxLayout();
  originWidget->setLayout(hboxLayout);

  originXSpinBox.setRange(volumeBounds.lower.x, volumeBounds.upper.x);
  originYSpinBox.setRange(volumeBounds.lower.y, volumeBounds.upper.y);
  originZSpinBox.setRange(volumeBounds.lower.z, volumeBounds.upper.z);

  originXSpinBox.setValue(0.5 * (volumeBounds.lower.x + volumeBounds.upper.x));
  originYSpinBox.setValue(0.5 * (volumeBounds.lower.y + volumeBounds.upper.y));
  originZSpinBox.setValue(0.5 * (volumeBounds.lower.z + volumeBounds.upper.z));

  connect(&originXSpinBox, SIGNAL(valueChanged(double)), this, SLOT(autoApply()));
  connect(&originYSpinBox, SIGNAL(valueChanged(double)), this, SLOT(autoApply()));
  connect(&originZSpinBox, SIGNAL(valueChanged(double)), this, SLOT(autoApply()));

  hboxLayout->addWidget(&originXSpinBox);
  hboxLayout->addWidget(&originYSpinBox);
  hboxLayout->addWidget(&originZSpinBox);

  formLayout->addRow("Origin", originWidget);

  //! Normal parameters with default values.
  QWidget * normalWidget = new QWidget();
  hboxLayout = new QHBoxLayout();
  normalWidget->setLayout(hboxLayout);

  normalXSpinBox.setRange(-1., 1.);
  normalYSpinBox.setRange(-1., 1.);
  normalZSpinBox.setRange(-1., 1.);

  normalXSpinBox.setValue(1.);
  normalYSpinBox.setValue(0.);
  normalZSpinBox.setValue(0.);

  connect(&normalXSpinBox, SIGNAL(valueChanged(double)), this, SLOT(autoApply()));
  connect(&normalYSpinBox, SIGNAL(valueChanged(double)), this, SLOT(autoApply()));
  connect(&normalZSpinBox, SIGNAL(valueChanged(double)), this, SLOT(autoApply()));

  hboxLayout->addWidget(&normalXSpinBox);
  hboxLayout->addWidget(&normalYSpinBox);
  hboxLayout->addWidget(&normalZSpinBox);

  formLayout->addRow("Normal", normalWidget);

  //! Add a slider and animate button for the origin location along the normal.
  QWidget * originSliderWidget = new QWidget();
  hboxLayout = new QHBoxLayout();
  originSliderWidget->setLayout(hboxLayout);

  originSlider.setOrientation(Qt::Horizontal);
  connect(&originSlider, SIGNAL(valueChanged(int)), this, SLOT(originSliderValueChanged(int)));
  hboxLayout->addWidget(&originSlider);

  originSliderAnimateButton.setText("Animate");
  originSliderAnimateButton.setCheckable(true);
  connect(&originSliderAnimateButton, SIGNAL(toggled(bool)), this, SLOT(setAnimation(bool)));
  hboxLayout->addWidget(&originSliderAnimateButton);

  formLayout->addRow("", originSliderWidget);

  //! Connect animation timer signal / slot.
  connect(&originSliderAnimationTimer, SIGNAL(timeout()), this, SLOT(animate()));

  //! Auto-apply checkbox, Delete, and Apply buttons.
  QWidget * buttonsWidget = new QWidget();
  hboxLayout = new QHBoxLayout();
  buttonsWidget->setLayout(hboxLayout);

  autoApplyCheckBox.setText("Auto update");
  autoApplyCheckBox.setChecked(true);
  hboxLayout->addWidget(&autoApplyCheckBox);

  QPushButton * deleteButton = new QPushButton("Delete");
  connect(deleteButton, SIGNAL(clicked()), this, SLOT(deleteLater()));
  hboxLayout->addWidget(deleteButton);

  QPushButton * applyButton = new QPushButton("Apply");
  connect(applyButton, SIGNAL(clicked()), this, SLOT(apply()));
  hboxLayout->addWidget(applyButton);

  layout->addWidget(buttonsWidget);

  //! Frame style for the widget.
  setFrameStyle(QFrame::Panel | QFrame::Raised);

  //! Minimum width for the widget.
  setMinimumWidth(240);

  //! Auto-apply (if enabled)
  autoApply();
}

SliceWidget::~SliceWidget() {

  if(triangleMesh) {

    for(unsigned int i=0; i<models.size(); i++) {

      ospRemoveGeometry(models[i], triangleMesh);
      ospCommit(models[i]);
    }
  }

  emit(sliceChanged());
}

void SliceWidget::apply() {

  //! Get the origin and normal values.
  osp::vec3f origin(float(originXSpinBox.value()), float(originYSpinBox.value()), float(originZSpinBox.value()));
  osp::vec3f normal = osp::vec3f(float(normalXSpinBox.value()), float(normalYSpinBox.value()), float(normalZSpinBox.value()));

  if(normal == osp::vec3f(0.f))
    return;
  else
    normal = normalize(normal);

  //! Create the OSPRay geometry on the first apply().
  bool newGeometry = false;

  if(!triangleMesh) {

    triangleMesh = ospNewTriangleMesh();
    newGeometry = true;
  }

  //! Compute basis vectors.
  osp::vec3f c(1.f,0.f,0.f);

  if(dot(c, normal) > 0.9f)
    c = osp::vec3f(0.f,1.f,0.f);

  osp::vec3f b1 = cross(c, normal);
  osp::vec3f b2 = cross(b1, normal);

  //! For now just make a slice sufficiently large to span the volume.
  const float size = sqrtf(2.f);

  //! Create the triangles forming the slice.
  osp::vec3f lowerLeft(origin - size*b1 - size*b2);
  osp::vec3f span1(2.f*size*b1);
  osp::vec3f span2(2.f*size*b2);

  //! Subdivide the plane into a larger set of triangles to help with performance when combined with other geometries.
  const size_t numSubdivisions = 32;

  std::vector<osp::vec3fa> positions;

  for(size_t i=0; i<numSubdivisions; i++)
    for(size_t j=0; j<numSubdivisions; j++)
      positions.push_back(lowerLeft + float(i)/float(numSubdivisions-1)*span1 + float(j)/float(numSubdivisions-1)*span2);

  std::vector<osp::vec3i> indices;

  for(size_t i=0; i<numSubdivisions-1; i++) {
    for(size_t j=0; j<numSubdivisions-1; j++) {

      indices.push_back(osp::vec3i(i*numSubdivisions+j, (i+1)*numSubdivisions+j, i*numSubdivisions+j+1));
      indices.push_back(osp::vec3i((i+1)*numSubdivisions+j, (i+1)*numSubdivisions+j+1, i*numSubdivisions+j+1));
    }
  }

  //! Update the OSPRay geometry.
  OSPData positionData = ospNewData(positions.size(), OSP_FLOAT3A, &positions[0].x);
  ospSetData(triangleMesh, "position", positionData);

  OSPData indexData = ospNewData(indices.size(), OSP_INT3, &indices[0].x);
  ospSetData(triangleMesh, "index", indexData);

  //! For now, vertex colors of (-1,-1,-1) indicate coloring should be mapped through the volume transfer function.
  //! Transfer function / volume information will be soon be included as material parameters.
  std::vector<osp::vec3fa> colors(positions.size(), osp::vec3f(-1.f));
  OSPData colorData = ospNewData(colors.size(), OSP_FLOAT3A, &colors[0].x);
  ospSetData(triangleMesh, "color", colorData);

  ospCommit(triangleMesh);

  if(newGeometry)
    for(unsigned int i=0; i<models.size(); i++)
      ospAddGeometry(models[i], triangleMesh);

  for(unsigned int i=0; i<models.size(); i++)
    ospCommit(models[i]);

  emit(sliceChanged());
}

void SliceWidget::load(std::string filename) {

  //! Get filename if not specified.
  if(filename.empty())
    filename = QFileDialog::getOpenFileName(this, tr("Load slice"), ".", "Slice files (*.slc)").toStdString();

  if(filename.empty())
    return;

  //! Get serialized slice state from file.
  QFile file(filename.c_str());
  bool success = file.open(QIODevice::ReadOnly);

  if(!success)
    {
      std::cerr << "unable to open " << filename << std::endl;
      return;
    }

  QDataStream in(&file);

  bool autoApply;
  in >> autoApply;

  double originX, originY, originZ;
  in >> originX >> originY >> originZ;

  double normalX, normalY, normalZ;
  in >> normalX >> normalY >> normalZ;

  int sliderPosition;
  in >> sliderPosition;

  bool sliderAnimating;
  in >> sliderAnimating;

  in >> originSliderAnimationDirection;

  //! Update slice state. Update values of the UI elements directly to signal appropriate slots.
  autoApplyCheckBox.setChecked(autoApply);
  originXSpinBox.setValue(originX);
  originYSpinBox.setValue(originY);
  originZSpinBox.setValue(originZ);
  normalXSpinBox.setValue(normalX);
  normalYSpinBox.setValue(normalY);
  normalZSpinBox.setValue(normalZ);
  originSlider.setValue(sliderPosition);
  originSliderAnimateButton.setChecked(sliderAnimating);
}

void SliceWidget::save() {

  //! Get filename.
  QString filename = QFileDialog::getSaveFileName(this, "Save slice", ".", "Slice files (*.slc)");

  if(filename.isNull())
    return;

  //! Make sure the filename has the proper extension.
  if(filename.endsWith(".slc") != true)
    filename += ".slc";

  //! Serialize slice state to file.
  QFile file(filename);
  bool success = file.open(QIODevice::WriteOnly);

  if(!success)
    {
      std::cerr << "unable to open " << filename.toStdString() << std::endl;
      return;
    }

  QDataStream out(&file);

  out << autoApplyCheckBox.isChecked();
  out << originXSpinBox.value() << originXSpinBox.value() << originXSpinBox.value();
  out << normalXSpinBox.value() << normalYSpinBox.value() << normalZSpinBox.value();
  out << originSlider.value();
  out << originSliderAnimateButton.isChecked();
  out << originSliderAnimationDirection;
}

void SliceWidget::autoApply() {

  if(autoApplyCheckBox.isChecked())
    apply();
}

void SliceWidget::originSliderValueChanged(int value) {

  //! Slider position in [0, 1].
  float sliderPosition = float(value) / float(originSlider.maximum() - originSlider.minimum());

  //! Get origin and (normalized) normal vectors.
  osp::vec3f origin(originXSpinBox.value(), originYSpinBox.value(), originZSpinBox.value());
  osp::vec3f normal = normalize(osp::vec3f(normalXSpinBox.value(), normalYSpinBox.value(), normalZSpinBox.value()));

  //! Compute allowed range along normal for the volume bounds.
  osp::vec3f upper(normal.x >= 0.f ? volumeBounds.upper.x : volumeBounds.lower.x,
                   normal.y >= 0.f ? volumeBounds.upper.y : volumeBounds.lower.y,
                   normal.z >= 0.f ? volumeBounds.upper.z : volumeBounds.lower.z);

  osp::vec3f lower(normal.x >= 0.f ? volumeBounds.lower.x : volumeBounds.upper.x,
                   normal.y >= 0.f ? volumeBounds.lower.y : volumeBounds.upper.y,
                   normal.z >= 0.f ? volumeBounds.lower.z : volumeBounds.upper.z);

  float tMax = dot(abs(upper - origin), abs(normal));
  float tMin = -dot(abs(lower - origin), abs(normal));

  //! Get t value within this range.
  float t = tMin + sliderPosition * (tMax - tMin);

  //! Clamp t within epsilon of the minimum and maximum, to prevent artifacts rendering near the bounds of the volume.
  const float epsilon = 0.01;
  t = std::max(std::min(t, tMax-epsilon), tMin+epsilon);

  //! Compute updated origin, clamped within the volume bounds.
  osp::vec3f updatedOrigin = clamp(origin + t*normal, volumeBounds.lower, volumeBounds.upper);

  //! Finally, set the new origin value.
  originXSpinBox.setValue(updatedOrigin.x);
  originYSpinBox.setValue(updatedOrigin.y);
  originZSpinBox.setValue(updatedOrigin.z);
}

void SliceWidget::setAnimation(bool set) {

  //! Start or stop the animation timer.
  if(set)
    originSliderAnimationTimer.start(100);
  else
    originSliderAnimationTimer.stop();
}

void SliceWidget::animate() {

  int value = originSlider.value();

  //! Check if we need to reverse direction.
  if(value + originSliderAnimationDirection < originSlider.minimum() || value + originSliderAnimationDirection > originSlider.maximum())
    originSliderAnimationDirection *= -1;

  //! Increment slider position.
  originSlider.setValue(value + originSliderAnimationDirection);
}
<|endoftext|>


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

#include "AgentActivator.h"

#include "Agency/Agent.h"
#include "Agency/ActivationCallback.h"
#include "Basics/ConditionLocker.h"

#include <chrono>
#include <thread>

using namespace arangodb::consensus;

AgentActivator::AgentActivator() : Thread("AgentActivator"), _agent(nullptr) {}

AgentActivator::AgentActivator(Agent* agent, std::string const& peerId)
  : Thread("AgentActivator"), _agent(agent), _peerId(peerId) {}

// Shutdown if not already
AgentActivator::~AgentActivator() { shutdown(); }

void AgentActivator::beginShutdown() { Thread::beginShutdown(); }

bool AgentActivator::start() { return Thread::start(); }

void AgentActivator::run() {

  LOG_TOPIC(DEBUG, Logger::AGENCY) << "Starting activation of " << _peerId;

  std::string const path = privApiPrefix + "activate";

  while (!this->isStopping()) {

    auto const& pool = _agent->config().pool();
    Builder builder;
    size_t highest = 0;

    auto headerFields =
      std::make_unique<std::unordered_map<std::string, std::string>>();
    arangodb::ClusterComm::instance()->asyncRequest(
      "1", 1, pool.at(_peerId), GeneralRequest::RequestType::POST,
      path, std::make_shared<std::string>(builder.toJson()), headerFields,
      std::make_shared<ActivationCallback>(_agent, _peerId, highest), 5.0, true,
      1.0);

  }

  LOG_TOPIC(DEBUG, Logger::AGENCY) << "Done activating " << _peerId;

}
<commit_msg>fix error after merge<commit_after>////////////////////////////////////////////////////////////////////////////////
/// DISCLAIMER
///
/// Copyright 2014-2016 ArangoDB GmbH, Cologne, Germany
/// Copyright 2004-2014 triAGENS GmbH, Cologne, Germany
///
/// Licensed under the Apache License, Version 2.0 (the "License");
/// you may not use this file except in compliance with the License.
/// You may obtain a copy of the License at
///
///     http://www.apache.org/licenses/LICENSE-2.0
///
/// Unless required by applicable law or agreed to in writing, software
/// distributed under the License is distributed on an "AS IS" BASIS,
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
/// See the License for the specific language governing permissions and
/// limitations under the License.
///
/// Copyright holder is ArangoDB GmbH, Cologne, Germany
///
/// @author Kaveh Vahedipour
////////////////////////////////////////////////////////////////////////////////

#include "AgentActivator.h"

#include "Agency/Agent.h"
#include "Agency/ActivationCallback.h"
#include "Basics/ConditionLocker.h"

#include <chrono>
#include <thread>

using namespace arangodb::consensus;

AgentActivator::AgentActivator() : Thread("AgentActivator"), _agent(nullptr) {}

AgentActivator::AgentActivator(Agent* agent, std::string const& peerId)
  : Thread("AgentActivator"), _agent(agent), _peerId(peerId) {}

// Shutdown if not already
AgentActivator::~AgentActivator() { shutdown(); }

void AgentActivator::beginShutdown() { Thread::beginShutdown(); }

bool AgentActivator::start() { return Thread::start(); }

void AgentActivator::run() {

  LOG_TOPIC(DEBUG, Logger::AGENCY) << "Starting activation of " << _peerId;

  std::string const path = privApiPrefix + "activate";

  while (!this->isStopping()) {

    auto const& pool = _agent->config().pool();
    Builder builder;
    size_t highest = 0;

    auto headerFields =
      std::make_unique<std::unordered_map<std::string, std::string>>();
    arangodb::ClusterComm::instance()->asyncRequest(
      "1", 1, pool.at(_peerId), rest::RequestType::POST,
      path, std::make_shared<std::string>(builder.toJson()), headerFields,
      std::make_shared<ActivationCallback>(_agent, _peerId, highest), 5.0, true,
      1.0);

  }

  LOG_TOPIC(DEBUG, Logger::AGENCY) << "Done activating " << _peerId;

}
<|endoftext|>


<commit_before>////////////////////////////////////////////////////////////////////////////////
/// DISCLAIMER
///
/// Copyright 2014-2016 ArangoDB GmbH, Cologne, Germany
/// Copyright 2004-2014 triAGENS GmbH, Cologne, Germany
///
/// Licensed under the Apache License, Version 2.0 (the "License");
/// you may not use this file except in compliance with the License.
/// You may obtain a copy of the License at
///
///     http://www.apache.org/licenses/LICENSE-2.0
///
/// Unless required by applicable law or agreed to in writing, software
/// distributed under the License is distributed on an "AS IS" BASIS,
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
/// See the License for the specific language governing permissions and
/// limitations under the License.
///
/// Copyright holder is ArangoDB GmbH, Cologne, Germany
///
/// @author Dr. Frank Celler
/// @author Achim Brandt
////////////////////////////////////////////////////////////////////////////////

#include "HttpServer.h"

#include "Basics/MutexLocker.h"
#include "Basics/WorkMonitor.h"
#include "Dispatcher/Dispatcher.h"
#include "Endpoint/EndpointList.h"
#include "HttpServer/AsyncJobManager.h"
#include "HttpServer/HttpCommTask.h"
#include "HttpServer/HttpHandler.h"
#include "HttpServer/HttpListenTask.h"
#include "HttpServer/HttpServerJob.h"
#include "Logger/Logger.h"
#include "Scheduler/ListenTask.h"
#include "Scheduler/Scheduler.h"
#include "Scheduler/SchedulerFeature.h"

using namespace arangodb;
using namespace arangodb::basics;
using namespace arangodb::rest;

////////////////////////////////////////////////////////////////////////////////
/// @brief destroys an endpoint server
////////////////////////////////////////////////////////////////////////////////

int HttpServer::sendChunk(uint64_t taskId, std::string const& data) {
  auto taskData = std::make_unique<TaskData>();

  taskData->_taskId = taskId;
  taskData->_loop = SchedulerFeature::SCHEDULER->lookupLoopById(taskId);
  taskData->_type = TaskData::TASK_DATA_CHUNK;
  taskData->_data = data;

  SchedulerFeature::SCHEDULER->signalTask(taskData);

  return TRI_ERROR_NO_ERROR;
}

////////////////////////////////////////////////////////////////////////////////
/// @brief constructs a new general server with dispatcher and job manager
////////////////////////////////////////////////////////////////////////////////

HttpServer::HttpServer(Scheduler* scheduler, Dispatcher* dispatcher,
                       HttpHandlerFactory* handlerFactory,
                       AsyncJobManager* jobManager, double keepAliveTimeout,
                       std::vector<std::string> const& accessControlAllowOrigins)
    : _scheduler(scheduler),
      _dispatcher(dispatcher),
      _handlerFactory(handlerFactory),
      _jobManager(jobManager),
      _listenTasks(),
      _endpointList(nullptr),
      _commTasks(),
      _keepAliveTimeout(keepAliveTimeout),
      _accessControlAllowOrigins(accessControlAllowOrigins) {}

////////////////////////////////////////////////////////////////////////////////
/// @brief destructs a general server
////////////////////////////////////////////////////////////////////////////////

HttpServer::~HttpServer() { stopListening(); }

////////////////////////////////////////////////////////////////////////////////
/// @brief generates a suitable communication task
////////////////////////////////////////////////////////////////////////////////

HttpCommTask* HttpServer::createCommTask(TRI_socket_t s,
                                         ConnectionInfo&& info) {
  return new HttpCommTask(this, s, std::move(info), _keepAliveTimeout);
}

////////////////////////////////////////////////////////////////////////////////
/// @brief add the endpoint list
////////////////////////////////////////////////////////////////////////////////

void HttpServer::setEndpointList(EndpointList const* list) {
  _endpointList = list;
}

////////////////////////////////////////////////////////////////////////////////
/// @brief starts listening
////////////////////////////////////////////////////////////////////////////////

void HttpServer::startListening() {
  auto endpoints =
      _endpointList->matching(Endpoint::TransportType::HTTP, encryptionType());

  for (auto& it : endpoints) {
    LOG(TRACE) << "trying to bind to endpoint '" << it.first << "' for requests";

    bool ok = openEndpoint(it.second);

    if (ok) {
      LOG(DEBUG) << "bound to endpoint '" << it.first << "'";
    } else {
      LOG(FATAL) << "failed to bind to endpoint '" << it.first
                 << "'. Please check whether another instance is already "
                    "running using this endpint and review your endpoints configuration.";
      FATAL_ERROR_EXIT();
    }
  }
}

////////////////////////////////////////////////////////////////////////////////
/// @brief stops listening
////////////////////////////////////////////////////////////////////////////////

void HttpServer::stopListening() {
  for (auto& task : _listenTasks) {
    _scheduler->destroyTask(task);
  }

  _listenTasks.clear();
}

////////////////////////////////////////////////////////////////////////////////
/// @brief removes all listen and comm tasks
////////////////////////////////////////////////////////////////////////////////

void HttpServer::stop() {
  while (true) {
    HttpCommTask* task = nullptr;

    {
      MUTEX_LOCKER(mutexLocker, _commTasksLock);

      if (_commTasks.empty()) {
        break;
      }

      task = *_commTasks.begin();
      _commTasks.erase(task);
    }

    _scheduler->destroyTask(task);
  }
}

////////////////////////////////////////////////////////////////////////////////
/// @brief handles connection request
////////////////////////////////////////////////////////////////////////////////

void HttpServer::handleConnected(TRI_socket_t s, ConnectionInfo&& info) {
  HttpCommTask* task = createCommTask(s, std::move(info));

  try {
    MUTEX_LOCKER(mutexLocker, _commTasksLock);
    _commTasks.emplace(task);
  } catch (...) {
    // destroy the task to prevent a leak
    deleteTask(task);
    throw;
  }

  // registers the task and get the number of the scheduler thread
  ssize_t n;
  _scheduler->registerTask(task, &n);
}

////////////////////////////////////////////////////////////////////////////////
/// @brief handles a connection close
////////////////////////////////////////////////////////////////////////////////

void HttpServer::handleCommunicationClosed(HttpCommTask* task) {
  MUTEX_LOCKER(mutexLocker, _commTasksLock);
  _commTasks.erase(task);
}

////////////////////////////////////////////////////////////////////////////////
/// @brief handles a connection failure
////////////////////////////////////////////////////////////////////////////////

void HttpServer::handleCommunicationFailure(HttpCommTask* task) {
  MUTEX_LOCKER(mutexLocker, _commTasksLock);
  _commTasks.erase(task);
}

////////////////////////////////////////////////////////////////////////////////
/// @brief create a job for asynchronous execution (using the dispatcher)
////////////////////////////////////////////////////////////////////////////////

bool HttpServer::handleRequestAsync(HttpCommTask* task,
                                    WorkItem::uptr<HttpHandler>& handler,
                                    uint64_t* jobId) {
  bool startThread = task->startThread();

  // extract the coordinator flag
  bool found;
  std::string const& hdrStr = handler->getRequest()->header(StaticStrings::Coordinator, found);
  char const* hdr = found ? hdrStr.c_str() : nullptr;

  // execute the handler using the dispatcher
  std::unique_ptr<Job> job =
      std::make_unique<HttpServerJob>(this, handler, true);
  task->RequestStatisticsAgent::transferTo(job.get());

  // register the job with the job manager
  if (jobId != nullptr) {
    _jobManager->initAsyncJob(static_cast<HttpServerJob*>(job.get()), hdr);
    *jobId = job->jobId();
  }

  // execute the handler using the dispatcher
  int res = _dispatcher->addJob(job, startThread);

  // could not add job to job queue
  if (res != TRI_ERROR_NO_ERROR) {
    job->requestStatisticsAgentSetExecuteError();
    job->RequestStatisticsAgent::transferTo(task);
    if (res != TRI_ERROR_DISPATCHER_IS_STOPPING) {
      LOG(WARN) << "unable to add job to the job queue: "
                << TRI_errno_string(res);
    }
    // todo send info to async work manager?
    return false;
  }

  // job is in queue now
  return res == TRI_ERROR_NO_ERROR;
}

////////////////////////////////////////////////////////////////////////////////
/// @brief executes the handler directly or add it to the queue
////////////////////////////////////////////////////////////////////////////////

bool HttpServer::handleRequest(HttpCommTask* task,
                               WorkItem::uptr<HttpHandler>& handler) {
  // direct handlers
  if (handler->isDirect()) {
    HandlerWorkStack work(handler);
    handleRequestDirectly(task, work.handler());

    return true;
  }

  bool startThread = task->startThread();

  // use a dispatcher queue, handler belongs to the job
  std::unique_ptr<Job> job = std::make_unique<HttpServerJob>(this, handler);
  task->RequestStatisticsAgent::transferTo(job.get());

  LOG(TRACE) << "HttpCommTask " << (void*)task << " created HttpServerJob "
             << (void*)job.get();

  // add the job to the dispatcher

  int res = _dispatcher->addJob(job, startThread);

  // job is in queue now
  return res == TRI_ERROR_NO_ERROR;
}

////////////////////////////////////////////////////////////////////////////////
/// @brief opens a listen port
////////////////////////////////////////////////////////////////////////////////

bool HttpServer::openEndpoint(Endpoint* endpoint) {
  ListenTask* task = new HttpListenTask(this, endpoint);

  // ...................................................................
  // For some reason we have failed in our endeavor to bind to the socket -
  // this effectively terminates the server
  // ...................................................................

  if (!task->isBound()) {
    deleteTask(task);
    return false;
  }

  int res = _scheduler->registerTask(task);

  if (res == TRI_ERROR_NO_ERROR) {
    _listenTasks.emplace_back(task);
    return true;
  }

  return false;
}

////////////////////////////////////////////////////////////////////////////////
/// @brief handle request directly
////////////////////////////////////////////////////////////////////////////////

void HttpServer::handleRequestDirectly(HttpCommTask* task,
                                       HttpHandler* handler) {
  task->RequestStatisticsAgent::transferTo(handler);
  HttpHandler::status_t status = handler->executeFull();
  handler->RequestStatisticsAgent::transferTo(task);

  switch (status._status) {
    case HttpHandler::HANDLER_FAILED:
    case HttpHandler::HANDLER_DONE:
      task->handleResponse(handler->getResponse());
      break;

    case HttpHandler::HANDLER_ASYNC:
      // do nothing, just wait
      break;
  }
}
<commit_msg>Fix a typo in an error message.<commit_after>////////////////////////////////////////////////////////////////////////////////
/// DISCLAIMER
///
/// Copyright 2014-2016 ArangoDB GmbH, Cologne, Germany
/// Copyright 2004-2014 triAGENS GmbH, Cologne, Germany
///
/// Licensed under the Apache License, Version 2.0 (the "License");
/// you may not use this file except in compliance with the License.
/// You may obtain a copy of the License at
///
///     http://www.apache.org/licenses/LICENSE-2.0
///
/// Unless required by applicable law or agreed to in writing, software
/// distributed under the License is distributed on an "AS IS" BASIS,
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
/// See the License for the specific language governing permissions and
/// limitations under the License.
///
/// Copyright holder is ArangoDB GmbH, Cologne, Germany
///
/// @author Dr. Frank Celler
/// @author Achim Brandt
////////////////////////////////////////////////////////////////////////////////

#include "HttpServer.h"

#include "Basics/MutexLocker.h"
#include "Basics/WorkMonitor.h"
#include "Dispatcher/Dispatcher.h"
#include "Endpoint/EndpointList.h"
#include "HttpServer/AsyncJobManager.h"
#include "HttpServer/HttpCommTask.h"
#include "HttpServer/HttpHandler.h"
#include "HttpServer/HttpListenTask.h"
#include "HttpServer/HttpServerJob.h"
#include "Logger/Logger.h"
#include "Scheduler/ListenTask.h"
#include "Scheduler/Scheduler.h"
#include "Scheduler/SchedulerFeature.h"

using namespace arangodb;
using namespace arangodb::basics;
using namespace arangodb::rest;

////////////////////////////////////////////////////////////////////////////////
/// @brief destroys an endpoint server
////////////////////////////////////////////////////////////////////////////////

int HttpServer::sendChunk(uint64_t taskId, std::string const& data) {
  auto taskData = std::make_unique<TaskData>();

  taskData->_taskId = taskId;
  taskData->_loop = SchedulerFeature::SCHEDULER->lookupLoopById(taskId);
  taskData->_type = TaskData::TASK_DATA_CHUNK;
  taskData->_data = data;

  SchedulerFeature::SCHEDULER->signalTask(taskData);

  return TRI_ERROR_NO_ERROR;
}

////////////////////////////////////////////////////////////////////////////////
/// @brief constructs a new general server with dispatcher and job manager
////////////////////////////////////////////////////////////////////////////////

HttpServer::HttpServer(Scheduler* scheduler, Dispatcher* dispatcher,
                       HttpHandlerFactory* handlerFactory,
                       AsyncJobManager* jobManager, double keepAliveTimeout,
                       std::vector<std::string> const& accessControlAllowOrigins)
    : _scheduler(scheduler),
      _dispatcher(dispatcher),
      _handlerFactory(handlerFactory),
      _jobManager(jobManager),
      _listenTasks(),
      _endpointList(nullptr),
      _commTasks(),
      _keepAliveTimeout(keepAliveTimeout),
      _accessControlAllowOrigins(accessControlAllowOrigins) {}

////////////////////////////////////////////////////////////////////////////////
/// @brief destructs a general server
////////////////////////////////////////////////////////////////////////////////

HttpServer::~HttpServer() { stopListening(); }

////////////////////////////////////////////////////////////////////////////////
/// @brief generates a suitable communication task
////////////////////////////////////////////////////////////////////////////////

HttpCommTask* HttpServer::createCommTask(TRI_socket_t s,
                                         ConnectionInfo&& info) {
  return new HttpCommTask(this, s, std::move(info), _keepAliveTimeout);
}

////////////////////////////////////////////////////////////////////////////////
/// @brief add the endpoint list
////////////////////////////////////////////////////////////////////////////////

void HttpServer::setEndpointList(EndpointList const* list) {
  _endpointList = list;
}

////////////////////////////////////////////////////////////////////////////////
/// @brief starts listening
////////////////////////////////////////////////////////////////////////////////

void HttpServer::startListening() {
  auto endpoints =
      _endpointList->matching(Endpoint::TransportType::HTTP, encryptionType());

  for (auto& it : endpoints) {
    LOG(TRACE) << "trying to bind to endpoint '" << it.first << "' for requests";

    bool ok = openEndpoint(it.second);

    if (ok) {
      LOG(DEBUG) << "bound to endpoint '" << it.first << "'";
    } else {
      LOG(FATAL) << "failed to bind to endpoint '" << it.first
                 << "'. Please check whether another instance is already "
                    "running using this endpoint and review your endpoints configuration.";
      FATAL_ERROR_EXIT();
    }
  }
}

////////////////////////////////////////////////////////////////////////////////
/// @brief stops listening
////////////////////////////////////////////////////////////////////////////////

void HttpServer::stopListening() {
  for (auto& task : _listenTasks) {
    _scheduler->destroyTask(task);
  }

  _listenTasks.clear();
}

////////////////////////////////////////////////////////////////////////////////
/// @brief removes all listen and comm tasks
////////////////////////////////////////////////////////////////////////////////

void HttpServer::stop() {
  while (true) {
    HttpCommTask* task = nullptr;

    {
      MUTEX_LOCKER(mutexLocker, _commTasksLock);

      if (_commTasks.empty()) {
        break;
      }

      task = *_commTasks.begin();
      _commTasks.erase(task);
    }

    _scheduler->destroyTask(task);
  }
}

////////////////////////////////////////////////////////////////////////////////
/// @brief handles connection request
////////////////////////////////////////////////////////////////////////////////

void HttpServer::handleConnected(TRI_socket_t s, ConnectionInfo&& info) {
  HttpCommTask* task = createCommTask(s, std::move(info));

  try {
    MUTEX_LOCKER(mutexLocker, _commTasksLock);
    _commTasks.emplace(task);
  } catch (...) {
    // destroy the task to prevent a leak
    deleteTask(task);
    throw;
  }

  // registers the task and get the number of the scheduler thread
  ssize_t n;
  _scheduler->registerTask(task, &n);
}

////////////////////////////////////////////////////////////////////////////////
/// @brief handles a connection close
////////////////////////////////////////////////////////////////////////////////

void HttpServer::handleCommunicationClosed(HttpCommTask* task) {
  MUTEX_LOCKER(mutexLocker, _commTasksLock);
  _commTasks.erase(task);
}

////////////////////////////////////////////////////////////////////////////////
/// @brief handles a connection failure
////////////////////////////////////////////////////////////////////////////////

void HttpServer::handleCommunicationFailure(HttpCommTask* task) {
  MUTEX_LOCKER(mutexLocker, _commTasksLock);
  _commTasks.erase(task);
}

////////////////////////////////////////////////////////////////////////////////
/// @brief create a job for asynchronous execution (using the dispatcher)
////////////////////////////////////////////////////////////////////////////////

bool HttpServer::handleRequestAsync(HttpCommTask* task,
                                    WorkItem::uptr<HttpHandler>& handler,
                                    uint64_t* jobId) {
  bool startThread = task->startThread();

  // extract the coordinator flag
  bool found;
  std::string const& hdrStr = handler->getRequest()->header(StaticStrings::Coordinator, found);
  char const* hdr = found ? hdrStr.c_str() : nullptr;

  // execute the handler using the dispatcher
  std::unique_ptr<Job> job =
      std::make_unique<HttpServerJob>(this, handler, true);
  task->RequestStatisticsAgent::transferTo(job.get());

  // register the job with the job manager
  if (jobId != nullptr) {
    _jobManager->initAsyncJob(static_cast<HttpServerJob*>(job.get()), hdr);
    *jobId = job->jobId();
  }

  // execute the handler using the dispatcher
  int res = _dispatcher->addJob(job, startThread);

  // could not add job to job queue
  if (res != TRI_ERROR_NO_ERROR) {
    job->requestStatisticsAgentSetExecuteError();
    job->RequestStatisticsAgent::transferTo(task);
    if (res != TRI_ERROR_DISPATCHER_IS_STOPPING) {
      LOG(WARN) << "unable to add job to the job queue: "
                << TRI_errno_string(res);
    }
    // todo send info to async work manager?
    return false;
  }

  // job is in queue now
  return res == TRI_ERROR_NO_ERROR;
}

////////////////////////////////////////////////////////////////////////////////
/// @brief executes the handler directly or add it to the queue
////////////////////////////////////////////////////////////////////////////////

bool HttpServer::handleRequest(HttpCommTask* task,
                               WorkItem::uptr<HttpHandler>& handler) {
  // direct handlers
  if (handler->isDirect()) {
    HandlerWorkStack work(handler);
    handleRequestDirectly(task, work.handler());

    return true;
  }

  bool startThread = task->startThread();

  // use a dispatcher queue, handler belongs to the job
  std::unique_ptr<Job> job = std::make_unique<HttpServerJob>(this, handler);
  task->RequestStatisticsAgent::transferTo(job.get());

  LOG(TRACE) << "HttpCommTask " << (void*)task << " created HttpServerJob "
             << (void*)job.get();

  // add the job to the dispatcher

  int res = _dispatcher->addJob(job, startThread);

  // job is in queue now
  return res == TRI_ERROR_NO_ERROR;
}

////////////////////////////////////////////////////////////////////////////////
/// @brief opens a listen port
////////////////////////////////////////////////////////////////////////////////

bool HttpServer::openEndpoint(Endpoint* endpoint) {
  ListenTask* task = new HttpListenTask(this, endpoint);

  // ...................................................................
  // For some reason we have failed in our endeavor to bind to the socket -
  // this effectively terminates the server
  // ...................................................................

  if (!task->isBound()) {
    deleteTask(task);
    return false;
  }

  int res = _scheduler->registerTask(task);

  if (res == TRI_ERROR_NO_ERROR) {
    _listenTasks.emplace_back(task);
    return true;
  }

  return false;
}

////////////////////////////////////////////////////////////////////////////////
/// @brief handle request directly
////////////////////////////////////////////////////////////////////////////////

void HttpServer::handleRequestDirectly(HttpCommTask* task,
                                       HttpHandler* handler) {
  task->RequestStatisticsAgent::transferTo(handler);
  HttpHandler::status_t status = handler->executeFull();
  handler->RequestStatisticsAgent::transferTo(task);

  switch (status._status) {
    case HttpHandler::HANDLER_FAILED:
    case HttpHandler::HANDLER_DONE:
      task->handleResponse(handler->getResponse());
      break;

    case HttpHandler::HANDLER_ASYNC:
      // do nothing, just wait
      break;
  }
}
<|endoftext|>


<commit_before>#include <improbable/worker.h>
#include <cstdint>
#include <iostream>
#include <string>
#include <thread>
#include <eeci/building/temperature.h>

using eeci::building::Temperature;

static const std::string kWorkerType = "Thim";
static const std::string kLoggerName = "thim.cc";

void UpdateBuildingTemperature(worker::Connection& connection,
                               const worker::EntityId& entity_id,
                               worker::Entity& entity) {
  const auto building_temperature = entity.Get<Temperature>()->current_temperature();
  Temperature::Update update;
  update.set_current_temperature(building_temperature + 1);
  connection.SendComponentUpdate<Temperature>(entity_id, update);
}

int main(int argc, char** argv) {
  if (argc != 4) {
    std::cout << "Usage: " << argv[0] << " <hostname> <port> <worker id>" << std::endl;
    std::cout << "Connects to the Simulation and satisfies the "
                 "ThermalEngineConstraint." << std::endl;
    std::cout << "For example: " << argv[0] << " localhost 7777 Thim0" << std::endl;
    return 1;
  }

  const std::string hostname = argv[1];
  const std::uint16_t port = static_cast<std::uint16_t>(std::stoul(argv[2]));
  const std::string worker_id = argv[3];

  worker::ConnectionParameters params;
  params.WorkerType = kWorkerType;
  params.WorkerId = worker_id;
  params.Network.UseExternalIp = true;
  params.Network.Tcp.MultiplexLevel = 4;
  worker::Connection connection{hostname, port, params};

  worker::View view;

  static const unsigned kSecondsPerUpdate = 5;
  auto time = std::chrono::high_resolution_clock::now();
  while (true) {
    auto op_list = connection.GetOpList(0 /* non-blocking */);

    // Invoke user-provided callbacks.
    view.Process(op_list);

    auto& entities = view.Entities;
    for (auto& pair : entities) {
      UpdateBuildingTemperature(connection, pair.first, pair.second);
    }
    time += std::chrono::microseconds(kSecondsPerUpdate * 1000000);
    std::this_thread::sleep_until(time);
  }
}
<commit_msg>Fix intendation<commit_after>#include <improbable/worker.h>
#include <iostream>
#include <thread>
#include <eeci/building/temperature.h>

using eeci::building::Temperature;

static const std::string kWorkerType = "Thim";
static const std::string kLoggerName = "thim.cc";

void UpdateBuildingTemperature(worker::Connection &connection,
                               const worker::EntityId &entity_id,
                               worker::Entity &entity) {
    const auto building_temperature = entity.Get<Temperature>()->current_temperature();
    Temperature::Update update;
    update.set_current_temperature(building_temperature + 1);
    connection.SendComponentUpdate<Temperature>(entity_id, update);
}

int main(int argc, char **argv) {
    if (argc != 4) {
        std::cout << "Usage: " << argv[0] << " <hostname> <port> <worker id>" << std::endl;
        std::cout << "Connects to the Simulation and satisfies the "
                "ThermalEngineConstraint." << std::endl;
        std::cout << "For example: " << argv[0] << " localhost 7777 Thim0" << std::endl;
        return 1;
    }

    const std::string hostname = argv[1];
    const std::uint16_t port = static_cast<std::uint16_t>(std::stoul(argv[2]));
    const std::string worker_id = argv[3];

    worker::ConnectionParameters params;
    params.WorkerType = kWorkerType;
    params.WorkerId = worker_id;
    params.Network.UseExternalIp = true;
    params.Network.Tcp.MultiplexLevel = 4;
    worker::Connection connection{hostname, port, params};

    worker::View view;

    static const unsigned kSecondsPerUpdate = 5;
    auto time = std::chrono::high_resolution_clock::now();
    while (true) {
        auto op_list = connection.GetOpList(0 /* non-blocking */);

        // Invoke user-provided callbacks.
        view.Process(op_list);

        auto &entities = view.Entities;
        for (auto &pair : entities) {
            UpdateBuildingTemperature(connection, pair.first, pair.second);
        }
        time += std::chrono::microseconds(kSecondsPerUpdate * 1000000);
        std::this_thread::sleep_until(time);
    }
}
<|endoftext|>


<commit_before>// $Id$
// vim:tabstop=2
/***********************************************************************
Moses - factored phrase-based language decoder
Copyright (C) 2006 University of Edinburgh

This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.

This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
***********************************************************************/

#include <fstream>
#include <string>
#include <iterator>
#include <queue>
#include <algorithm>
#include <sys/stat.h>
#include <boost/algorithm/string/predicate.hpp>
#include <boost/thread/tss.hpp>

#include "PhraseDictionaryCompact.h"
#include "moses/FactorCollection.h"
#include "moses/Word.h"
#include "moses/Util.h"
#include "moses/InputFileStream.h"
#include "moses/StaticData.h"
#include "moses/Range.h"
#include "moses/ThreadPool.h"
#include "util/exception.hh"

using namespace std;
using namespace boost::algorithm;

namespace Moses
{

PhraseDictionaryCompact::SentenceCache PhraseDictionaryCompact::m_sentenceCache;

PhraseDictionaryCompact::PhraseDictionaryCompact(const std::string &line)
  :PhraseDictionary(line, true)
  ,m_inMemory(true)//(s_inMemoryByDefault)
  ,m_useAlignmentInfo(true)
  ,m_hash(10, 16)
  ,m_phraseDecoder(0)
{
  ReadParameters();
}

void PhraseDictionaryCompact::Load(AllOptions::ptr const& opts)
{
  m_options = opts;
  const StaticData &staticData = StaticData::Instance();

  SetFeaturesToApply();

  std::string tFilePath = m_filePath;

  std::string suffix = ".minphr";
  if (!ends_with(tFilePath, suffix)) tFilePath += suffix;
  if (!FileExists(tFilePath))
    throw runtime_error("Error: File " + tFilePath + " does not exist.");

  m_phraseDecoder
  = new PhraseDecoder(*this, &m_input, &m_output, m_numScoreComponents);

  std::FILE* pFile = std::fopen(tFilePath.c_str() , "r");

  size_t indexSize;
  //if(m_inMemory)
  // Load source phrase index into memory
  indexSize = m_hash.Load(pFile);
  // else
  // Keep source phrase index on disk
  //indexSize = m_hash.LoadIndex(pFile);

  size_t coderSize = m_phraseDecoder->Load(pFile);

  size_t phraseSize;
  if(m_inMemory)
    // Load target phrase collections into memory
    phraseSize = m_targetPhrasesMemory.load(pFile, false);
  else
    // Keep target phrase collections on disk
    phraseSize = m_targetPhrasesMapped.load(pFile, true);

  UTIL_THROW_IF2(indexSize == 0 || coderSize == 0 || phraseSize == 0,
                 "Not successfully loaded");
}

TargetPhraseCollection::shared_ptr
PhraseDictionaryCompact::
GetTargetPhraseCollectionNonCacheLEGACY(const Phrase &sourcePhrase) const
{

  TargetPhraseCollection::shared_ptr ret;
  // There is no souch source phrase if source phrase is longer than longest
  // observed source phrase during compilation
  if(sourcePhrase.GetSize() > m_phraseDecoder->GetMaxSourcePhraseLength())
    return ret;

  // Retrieve target phrase collection from phrase table
  TargetPhraseVectorPtr decodedPhraseColl
  = m_phraseDecoder->CreateTargetPhraseCollection(sourcePhrase, true, true);

  if(decodedPhraseColl != NULL && decodedPhraseColl->size()) {
    TargetPhraseVectorPtr tpv(new TargetPhraseVector(*decodedPhraseColl));
    TargetPhraseCollection::shared_ptr  phraseColl(new TargetPhraseCollection);

    // Score phrases and if possible apply ttable_limit
    TargetPhraseVector::iterator nth =
      (m_tableLimit == 0 || tpv->size() < m_tableLimit) ?
      tpv->end() : tpv->begin() + m_tableLimit;
    NTH_ELEMENT4(tpv->begin(), nth, tpv->end(), CompareTargetPhrase());
    for(TargetPhraseVector::iterator it = tpv->begin(); it != nth; it++) {
      TargetPhrase *tp = new TargetPhrase(*it);
      phraseColl->Add(tp);
    }

    // Cache phrase pair for clean-up or retrieval with PREnc
    const_cast<PhraseDictionaryCompact*>(this)->CacheForCleanup(phraseColl);

    return phraseColl;
  } else
    return ret;
}

TargetPhraseVectorPtr
PhraseDictionaryCompact::
GetTargetPhraseCollectionRaw(const Phrase &sourcePhrase) const
{

  // There is no such source phrase if source phrase is longer than longest
  // observed source phrase during compilation
  if(sourcePhrase.GetSize() > m_phraseDecoder->GetMaxSourcePhraseLength())
    return TargetPhraseVectorPtr();

  // Retrieve target phrase collection from phrase table
  return m_phraseDecoder->CreateTargetPhraseCollection(sourcePhrase, true, false);
}

PhraseDictionaryCompact::
~PhraseDictionaryCompact()
{
  if(m_phraseDecoder)
    delete m_phraseDecoder;
}

void
PhraseDictionaryCompact::
CacheForCleanup(TargetPhraseCollection::shared_ptr  tpc)
{
  if(!m_sentenceCache.get())
    m_sentenceCache.reset(new PhraseCache());
  m_sentenceCache->push_back(tpc);
}

void
PhraseDictionaryCompact::
AddEquivPhrase(const Phrase &source, const TargetPhrase &targetPhrase)
{ }

void
PhraseDictionaryCompact::
CleanUpAfterSentenceProcessing(const InputType &source)
{
  if(!m_sentenceCache.get())
    m_sentenceCache.reset(new PhraseCache());

  m_phraseDecoder->PruneCache();
  m_sentenceCache->clear();

  ReduceCache();
}

bool PhraseDictionaryCompact::s_inMemoryByDefault = false;
void
PhraseDictionaryCompact::
SetStaticDefaultParameters(Parameter const& param)
{
  param.SetParameter(s_inMemoryByDefault, "minphr-memory", true);
}
}

<commit_msg>reversing change: now compact phrase table memory mapping is turned on by default, can be turned off with -minphr-memory (as before 2015-12-12)<commit_after>// $Id$
// vim:tabstop=2
/***********************************************************************
Moses - factored phrase-based language decoder
Copyright (C) 2006 University of Edinburgh

This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.

This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
***********************************************************************/

#include <fstream>
#include <string>
#include <iterator>
#include <queue>
#include <algorithm>
#include <sys/stat.h>
#include <boost/algorithm/string/predicate.hpp>
#include <boost/thread/tss.hpp>

#include "PhraseDictionaryCompact.h"
#include "moses/FactorCollection.h"
#include "moses/Word.h"
#include "moses/Util.h"
#include "moses/InputFileStream.h"
#include "moses/StaticData.h"
#include "moses/Range.h"
#include "moses/ThreadPool.h"
#include "util/exception.hh"

using namespace std;
using namespace boost::algorithm;

namespace Moses
{

PhraseDictionaryCompact::SentenceCache PhraseDictionaryCompact::m_sentenceCache;

PhraseDictionaryCompact::PhraseDictionaryCompact(const std::string &line)
  :PhraseDictionary(line, true)
  ,m_inMemory(s_inMemoryByDefault)
  ,m_useAlignmentInfo(true)
  ,m_hash(10, 16)
  ,m_phraseDecoder(0)
{
  ReadParameters();
}

void PhraseDictionaryCompact::Load(AllOptions::ptr const& opts)
{
  m_options = opts;
  const StaticData &staticData = StaticData::Instance();

  SetFeaturesToApply();

  std::string tFilePath = m_filePath;

  std::string suffix = ".minphr";
  if (!ends_with(tFilePath, suffix)) tFilePath += suffix;
  if (!FileExists(tFilePath))
    throw runtime_error("Error: File " + tFilePath + " does not exist.");

  m_phraseDecoder
  = new PhraseDecoder(*this, &m_input, &m_output, m_numScoreComponents);

  std::FILE* pFile = std::fopen(tFilePath.c_str() , "r");

  size_t indexSize;
  //if(m_inMemory)
  // Load source phrase index into memory
  indexSize = m_hash.Load(pFile);
  // else
  // Keep source phrase index on disk
  //indexSize = m_hash.LoadIndex(pFile);

  size_t coderSize = m_phraseDecoder->Load(pFile);

  size_t phraseSize;
  if(m_inMemory)
    // Load target phrase collections into memory
    phraseSize = m_targetPhrasesMemory.load(pFile, false);
  else
    // Keep target phrase collections on disk
    phraseSize = m_targetPhrasesMapped.load(pFile, true);

  UTIL_THROW_IF2(indexSize == 0 || coderSize == 0 || phraseSize == 0,
                 "Not successfully loaded");
}

TargetPhraseCollection::shared_ptr
PhraseDictionaryCompact::
GetTargetPhraseCollectionNonCacheLEGACY(const Phrase &sourcePhrase) const
{

  TargetPhraseCollection::shared_ptr ret;
  // There is no souch source phrase if source phrase is longer than longest
  // observed source phrase during compilation
  if(sourcePhrase.GetSize() > m_phraseDecoder->GetMaxSourcePhraseLength())
    return ret;

  // Retrieve target phrase collection from phrase table
  TargetPhraseVectorPtr decodedPhraseColl
  = m_phraseDecoder->CreateTargetPhraseCollection(sourcePhrase, true, true);

  if(decodedPhraseColl != NULL && decodedPhraseColl->size()) {
    TargetPhraseVectorPtr tpv(new TargetPhraseVector(*decodedPhraseColl));
    TargetPhraseCollection::shared_ptr  phraseColl(new TargetPhraseCollection);

    // Score phrases and if possible apply ttable_limit
    TargetPhraseVector::iterator nth =
      (m_tableLimit == 0 || tpv->size() < m_tableLimit) ?
      tpv->end() : tpv->begin() + m_tableLimit;
    NTH_ELEMENT4(tpv->begin(), nth, tpv->end(), CompareTargetPhrase());
    for(TargetPhraseVector::iterator it = tpv->begin(); it != nth; it++) {
      TargetPhrase *tp = new TargetPhrase(*it);
      phraseColl->Add(tp);
    }

    // Cache phrase pair for clean-up or retrieval with PREnc
    const_cast<PhraseDictionaryCompact*>(this)->CacheForCleanup(phraseColl);

    return phraseColl;
  } else
    return ret;
}

TargetPhraseVectorPtr
PhraseDictionaryCompact::
GetTargetPhraseCollectionRaw(const Phrase &sourcePhrase) const
{

  // There is no such source phrase if source phrase is longer than longest
  // observed source phrase during compilation
  if(sourcePhrase.GetSize() > m_phraseDecoder->GetMaxSourcePhraseLength())
    return TargetPhraseVectorPtr();

  // Retrieve target phrase collection from phrase table
  return m_phraseDecoder->CreateTargetPhraseCollection(sourcePhrase, true, false);
}

PhraseDictionaryCompact::
~PhraseDictionaryCompact()
{
  if(m_phraseDecoder)
    delete m_phraseDecoder;
}

void
PhraseDictionaryCompact::
CacheForCleanup(TargetPhraseCollection::shared_ptr  tpc)
{
  if(!m_sentenceCache.get())
    m_sentenceCache.reset(new PhraseCache());
  m_sentenceCache->push_back(tpc);
}

void
PhraseDictionaryCompact::
AddEquivPhrase(const Phrase &source, const TargetPhrase &targetPhrase)
{ }

void
PhraseDictionaryCompact::
CleanUpAfterSentenceProcessing(const InputType &source)
{
  if(!m_sentenceCache.get())
    m_sentenceCache.reset(new PhraseCache());

  m_phraseDecoder->PruneCache();
  m_sentenceCache->clear();

  ReduceCache();
}

bool PhraseDictionaryCompact::s_inMemoryByDefault = false;
void
PhraseDictionaryCompact::
SetStaticDefaultParameters(Parameter const& param)
{
  param.SetParameter(s_inMemoryByDefault, "minphr-memory", false);
}
}

<|endoftext|>


<commit_before>/*
* (C) 2009 Jack Lloyd
*
* Distributed under the terms of the Botan license
*/

#include <botan/filters.h>

#if defined(BOTAN_HAS_RSA)
  #include <botan/rsa.h>
#endif

#if defined(BOTAN_HAS_DSA)
  #include <botan/dsa.h>
#endif

#if defined(BOTAN_HAS_ECDSA)
  #include <botan/ecdsa.h>
#endif

#ifdef BOTAN_HAS_X509
  #include <botan/x509self.h>
  #include <botan/x509stor.h>
  #include <botan/x509_ca.h>
  #include <botan/pkcs10.h>
#endif

using namespace Botan;

#include <iostream>
#include <memory>

#include "validate.h"
#include "common.h"

#if defined(BOTAN_HAS_X509) && defined(BOTAN_HAS_RSA) && defined(BOTAN_HAS_DSA)

namespace {

u64bit key_id(const Public_Key* key)
   {
   Pipe pipe(new Hash_Filter("SHA-1", 8));
   pipe.start_msg();
   pipe.write(key->algo_name());
   pipe.write(key->algorithm_identifier().parameters);
   pipe.write(key->x509_subject_public_key());
   pipe.end_msg();

   SecureVector<byte> output = pipe.read_all();

   if(output.size() != 8)
      throw Internal_Error("Public_Key::key_id: Incorrect output size");

   u64bit id = 0;
   for(u32bit j = 0; j != 8; ++j)
      id = (id << 8) | output[j];
   return id;
   }

/* Return some option sets */
X509_Cert_Options ca_opts()
   {
   X509_Cert_Options opts("Test CA/US/Botan Project/Testing");

   opts.uri = "http://botan.randombit.net";
   opts.dns = "botan.randombit.net";
   opts.email = "testing@randombit.net";

   opts.CA_key(1);

   return opts;
   }

X509_Cert_Options req_opts1()
   {
   X509_Cert_Options opts("Test User 1/US/Botan Project/Testing");

   opts.uri = "http://botan.randombit.net";
   opts.dns = "botan.randombit.net";
   opts.email = "testing@randombit.net";

   return opts;
   }

X509_Cert_Options req_opts2()
   {
   X509_Cert_Options opts("Test User 2/US/Botan Project/Testing");

   opts.uri = "http://botan.randombit.net";
   opts.dns = "botan.randombit.net";
   opts.email = "testing@randombit.net";

   opts.add_ex_constraint("PKIX.EmailProtection");

   return opts;
   }

u32bit check_against_copy(const Private_Key& orig,
                          RandomNumberGenerator& rng)
   {
   Private_Key* copy_priv = PKCS8::copy_key(orig, rng);
   Public_Key* copy_pub = X509::copy_key(orig);

   const std::string passphrase= "I need work! -Mr. T";
   DataSource_Memory enc_source(PKCS8::PEM_encode(orig, rng, passphrase));
   Private_Key* copy_priv_enc = PKCS8::load_key(enc_source, rng,
                                                passphrase);

   u64bit orig_id = key_id(&orig);
   u64bit pub_id = key_id(copy_pub);
   u64bit priv_id = key_id(copy_priv);
   u64bit priv_enc_id = key_id(copy_priv_enc);

   delete copy_pub;
   delete copy_priv;
   delete copy_priv_enc;

   if(orig_id != pub_id || orig_id != priv_id || orig_id != priv_enc_id)
      {
      std::cout << "Failed copy check\n";
      return 1;
      }
   return 0;
   }

}

void do_x509_tests(RandomNumberGenerator& rng)
   {
   std::cout << "Testing X.509 CA/CRL/cert/cert request: " << std::flush;

   std::string hash_fn = "SHA-256";

   /* Create the CA's key and self-signed cert */
   std::cout << '.' << std::flush;
   RSA_PrivateKey ca_key(rng, 1024);

   std::cout << '.' << std::flush;
   X509_Certificate ca_cert = X509::create_self_signed_cert(ca_opts(),
                                                            ca_key,
                                                            hash_fn,
                                                            rng);
   std::cout << '.' << std::flush;

   /* Create user #1's key and cert request */
   std::cout << '.' << std::flush;
   DSA_PrivateKey user1_key(rng, DL_Group("dsa/jce/1024"));

   std::cout << '.' << std::flush;
   PKCS10_Request user1_req = X509::create_cert_req(req_opts1(),
                                                    user1_key,
                                                    "SHA-1",
                                                    rng);

   /* Create user #2's key and cert request */
   std::cout << '.' << std::flush;
#if defined(BOTAN_HAS_ECDSA)
   EC_Domain_Params ecc_domain(OID("1.2.840.10045.3.1.7"));
   ECDSA_PrivateKey user2_key(rng, ecc_domain);
#else
   RSA_PrivateKey user2_key(rng, 1024);
#endif

   std::cout << '.' << std::flush;
   PKCS10_Request user2_req = X509::create_cert_req(req_opts2(),
                                                    user2_key,
                                                    hash_fn,
                                                    rng);

   /* Create the CA object */
   std::cout << '.' << std::flush;
   X509_CA ca(ca_cert, ca_key, hash_fn);
   std::cout << '.' << std::flush;

   /* Sign the requests to create the certs */
   std::cout << '.' << std::flush;
   X509_Certificate user1_cert =
      ca.sign_request(user1_req, rng,
                      X509_Time("2008-01-01"), X509_Time("2100-01-01"));

   std::cout << '.' << std::flush;
   X509_Certificate user2_cert = ca.sign_request(user2_req, rng,
                                                 X509_Time("2008-01-01"),
                                                 X509_Time("2100-01-01"));
   std::cout << '.' << std::flush;

   X509_CRL crl1 = ca.new_crl(rng);

   /* Verify the certs */
   X509_Store store;

   store.add_cert(ca_cert, true); // second arg == true: trusted CA cert

   std::cout << '.' << std::flush;
   if(store.validate_cert(user1_cert) != VERIFIED)
      std::cout << "\nFAILED: User cert #1 did not validate" << std::endl;

   if(store.validate_cert(user2_cert) != VERIFIED)
      std::cout << "\nFAILED: User cert #2 did not validate" << std::endl;

   if(store.add_crl(crl1) != VERIFIED)
      std::cout << "\nFAILED: CRL #1 did not validate" << std::endl;

   std::vector<CRL_Entry> revoked;
   revoked.push_back(user2_cert);

   X509_CRL crl2 = ca.update_crl(crl1, revoked, rng);

   if(store.add_crl(crl2) != VERIFIED)
      std::cout << "\nFAILED: CRL #2 did not validate" << std::endl;

   if(store.validate_cert(user2_cert) != CERT_IS_REVOKED)
      std::cout << "\nFAILED: User cert #2 was not revoked" << std::endl;

   check_against_copy(ca_key, rng);
   check_against_copy(user1_key, rng);
   check_against_copy(user2_key, rng);

   std::cout << std::endl;
   }

#else

void do_x509_tests(RandomNumberGenerator&)
   {
   std::cout << "Skipping Botan X.509 tests (disabled in build)\n";
   }

#endif

<commit_msg>If check against copy fails, print algo name<commit_after>/*
* (C) 2009 Jack Lloyd
*
* Distributed under the terms of the Botan license
*/

#include <botan/filters.h>

#if defined(BOTAN_HAS_RSA)
  #include <botan/rsa.h>
#endif

#if defined(BOTAN_HAS_DSA)
  #include <botan/dsa.h>
#endif

#if defined(BOTAN_HAS_ECDSA)
  #include <botan/ecdsa.h>
#endif

#ifdef BOTAN_HAS_X509
  #include <botan/x509self.h>
  #include <botan/x509stor.h>
  #include <botan/x509_ca.h>
  #include <botan/pkcs10.h>
#endif

using namespace Botan;

#include <iostream>
#include <memory>

#include "validate.h"
#include "common.h"

#if defined(BOTAN_HAS_X509) && defined(BOTAN_HAS_RSA) && defined(BOTAN_HAS_DSA)

namespace {

u64bit key_id(const Public_Key* key)
   {
   Pipe pipe(new Hash_Filter("SHA-1", 8));
   pipe.start_msg();
   pipe.write(key->algo_name());
   pipe.write(key->algorithm_identifier().parameters);
   pipe.write(key->x509_subject_public_key());
   pipe.end_msg();

   SecureVector<byte> output = pipe.read_all();

   if(output.size() != 8)
      throw Internal_Error("Public_Key::key_id: Incorrect output size");

   u64bit id = 0;
   for(u32bit j = 0; j != 8; ++j)
      id = (id << 8) | output[j];
   return id;
   }

/* Return some option sets */
X509_Cert_Options ca_opts()
   {
   X509_Cert_Options opts("Test CA/US/Botan Project/Testing");

   opts.uri = "http://botan.randombit.net";
   opts.dns = "botan.randombit.net";
   opts.email = "testing@randombit.net";

   opts.CA_key(1);

   return opts;
   }

X509_Cert_Options req_opts1()
   {
   X509_Cert_Options opts("Test User 1/US/Botan Project/Testing");

   opts.uri = "http://botan.randombit.net";
   opts.dns = "botan.randombit.net";
   opts.email = "testing@randombit.net";

   return opts;
   }

X509_Cert_Options req_opts2()
   {
   X509_Cert_Options opts("Test User 2/US/Botan Project/Testing");

   opts.uri = "http://botan.randombit.net";
   opts.dns = "botan.randombit.net";
   opts.email = "testing@randombit.net";

   opts.add_ex_constraint("PKIX.EmailProtection");

   return opts;
   }

u32bit check_against_copy(const Private_Key& orig,
                          RandomNumberGenerator& rng)
   {
   Private_Key* copy_priv = PKCS8::copy_key(orig, rng);
   Public_Key* copy_pub = X509::copy_key(orig);

   const std::string passphrase= "I need work! -Mr. T";
   DataSource_Memory enc_source(PKCS8::PEM_encode(orig, rng, passphrase));
   Private_Key* copy_priv_enc = PKCS8::load_key(enc_source, rng,
                                                passphrase);

   u64bit orig_id = key_id(&orig);
   u64bit pub_id = key_id(copy_pub);
   u64bit priv_id = key_id(copy_priv);
   u64bit priv_enc_id = key_id(copy_priv_enc);

   delete copy_pub;
   delete copy_priv;
   delete copy_priv_enc;

   if(orig_id != pub_id || orig_id != priv_id || orig_id != priv_enc_id)
      {
      std::cout << "Failed copy check for " << orig.algo_name() << "\n";
      return 1;
      }
   return 0;
   }

}

void do_x509_tests(RandomNumberGenerator& rng)
   {
   std::cout << "Testing X.509 CA/CRL/cert/cert request: " << std::flush;

   std::string hash_fn = "SHA-256";

   /* Create the CA's key and self-signed cert */
   std::cout << '.' << std::flush;
   RSA_PrivateKey ca_key(rng, 1024);

   std::cout << '.' << std::flush;
   X509_Certificate ca_cert = X509::create_self_signed_cert(ca_opts(),
                                                            ca_key,
                                                            hash_fn,
                                                            rng);
   std::cout << '.' << std::flush;

   /* Create user #1's key and cert request */
   std::cout << '.' << std::flush;
   DSA_PrivateKey user1_key(rng, DL_Group("dsa/jce/1024"));

   std::cout << '.' << std::flush;
   PKCS10_Request user1_req = X509::create_cert_req(req_opts1(),
                                                    user1_key,
                                                    "SHA-1",
                                                    rng);

   /* Create user #2's key and cert request */
   std::cout << '.' << std::flush;
#if defined(BOTAN_HAS_ECDSA)
   EC_Domain_Params ecc_domain(OID("1.2.840.10045.3.1.7"));
   ECDSA_PrivateKey user2_key(rng, ecc_domain);
#else
   RSA_PrivateKey user2_key(rng, 1024);
#endif

   std::cout << '.' << std::flush;
   PKCS10_Request user2_req = X509::create_cert_req(req_opts2(),
                                                    user2_key,
                                                    hash_fn,
                                                    rng);

   /* Create the CA object */
   std::cout << '.' << std::flush;
   X509_CA ca(ca_cert, ca_key, hash_fn);
   std::cout << '.' << std::flush;

   /* Sign the requests to create the certs */
   std::cout << '.' << std::flush;
   X509_Certificate user1_cert =
      ca.sign_request(user1_req, rng,
                      X509_Time("2008-01-01"), X509_Time("2100-01-01"));

   std::cout << '.' << std::flush;
   X509_Certificate user2_cert = ca.sign_request(user2_req, rng,
                                                 X509_Time("2008-01-01"),
                                                 X509_Time("2100-01-01"));
   std::cout << '.' << std::flush;

   X509_CRL crl1 = ca.new_crl(rng);

   /* Verify the certs */
   X509_Store store;

   store.add_cert(ca_cert, true); // second arg == true: trusted CA cert

   std::cout << '.' << std::flush;
   if(store.validate_cert(user1_cert) != VERIFIED)
      std::cout << "\nFAILED: User cert #1 did not validate" << std::endl;

   if(store.validate_cert(user2_cert) != VERIFIED)
      std::cout << "\nFAILED: User cert #2 did not validate" << std::endl;

   if(store.add_crl(crl1) != VERIFIED)
      std::cout << "\nFAILED: CRL #1 did not validate" << std::endl;

   std::vector<CRL_Entry> revoked;
   revoked.push_back(user2_cert);

   X509_CRL crl2 = ca.update_crl(crl1, revoked, rng);

   if(store.add_crl(crl2) != VERIFIED)
      std::cout << "\nFAILED: CRL #2 did not validate" << std::endl;

   if(store.validate_cert(user2_cert) != CERT_IS_REVOKED)
      std::cout << "\nFAILED: User cert #2 was not revoked" << std::endl;

   check_against_copy(ca_key, rng);
   check_against_copy(user1_key, rng);
   check_against_copy(user2_key, rng);

   std::cout << std::endl;
   }

#else

void do_x509_tests(RandomNumberGenerator&)
   {
   std::cout << "Skipping Botan X.509 tests (disabled in build)\n";
   }

#endif

<|endoftext|>