<commit_before>/*
** Copyright 2013-2014 Merethis
**
** This file is part of Centreon Broker.
**
** Centreon Broker is free software: you can redistribute it and/or
** modify it under the terms of the GNU General Public License version 2
** as published by the Free Software Foundation.
**
** Centreon Broker 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
** General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with Centreon Broker. If not, see
** <http://www.gnu.org/licenses/>.
*/

#include <cerrno>
#include <cstdio>
#include <cstring>
#include <fcntl.h>
#include <rrd.h>
#include <sstream>
#ifdef __linux__
#  include <sys/sendfile.h>
#endif // Linux
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include "com/centreon/broker/exceptions/msg.hh"
#include "com/centreon/broker/logging/logging.hh"
#include "com/centreon/broker/rrd/creator.hh"
#include "com/centreon/broker/rrd/exceptions/open.hh"
#include "com/centreon/broker/storage/perfdata.hh"

using namespace com::centreon::broker;
using namespace com::centreon::broker::rrd;

/**
 *  Constructor.
 *
 *  @param[in] tmpl_path  The template path.
 *  @param[in] cache_size The maximum number of cache element.
 */
creator::creator(
           std::string const& tmpl_path,
           unsigned int cache_size)
  : _cache_size(cache_size), _tmpl_path(tmpl_path) {}

/**
 *  Copy constructor.
 *
 *  @param[in] right The object to copy.
 */
creator::creator(creator const& right) {
  operator=(right);
}

/**
 *  Destructor.
 */
creator::~creator() {
  clear();
}

/**
 *  Copy operator.
 *
 *  @param[in] right The object to copy.
 *
 *  @return This object.
 */
creator& creator::operator=(creator const& right) {
  if (this != &right) {
    _cache_size = right._cache_size;
    _fds = right._fds;
    _tmpl_path = right._tmpl_path;
  }
  return (*this);
}

/**
 *  Clear cache and remove template file.
 */
void creator::clear() {
  for (std::map<tmpl_info, fd_info>::const_iterator
         it(_fds.begin()), end(_fds.end());
       it != end;
       ++it) {
    tmpl_info info(it->first);
    ::close(it->second.fd);
    std::ostringstream oss;
    oss << _tmpl_path << "/tmpl_" << info.length << "_" << info.step
        << "_" << info.value_type << ".rrd";
    ::remove(oss.str().c_str());
  }
  _fds.clear();
  return ;
}

/**
 *  Create a RRD file if it does not exists.
 *
 *  @param[in] filename   Path to the RRD file.
 *  @param[in] length     Number of recording in the RRD file.
 *  @param[in] from       Timestamp of the first record.
 *  @param[in] step       Specifies the base interval in seconds with
 *                        which data will be fed into the RRD.
 *  @param[in] value_type Type of the metric.
 */
void creator::create(
                std::string const& filename,
                unsigned int length,
                time_t from,
                unsigned int step,
                short value_type) {
  // Fill template informations.
  tmpl_info info;
  info.length = length;
  info.step = step;
  info.value_type = value_type;

  // Find fd informations.
  std::map<tmpl_info, fd_info>::const_iterator it(_fds.find(info));
  // Is in the cache, just duplicate file.
  if (it != _fds.end())
    _duplicate(filename, it->second);
  // Not is the cache, but we have enough space in the cache.
  // Create new entry.
  else if (_fds.size() < _cache_size) {
    std::ostringstream oss;
    oss << _tmpl_path << "/tmpl_" << length << "_" << step
        << "_" << value_type << ".rrd";
    std::string tmpl_filename(oss.str());

    // Create new template.
    _open(tmpl_filename, length, from, step, value_type);

    // Get template file size.
    struct stat s;
    if (stat(tmpl_filename.c_str(), &s) < 0) {
      char const* msg(strerror(errno));
      throw (exceptions::open() << "RRD: could not create template file '"
             << tmpl_filename << "': " << msg);
    }

    // Get template file fd.
    int in_fd(open(tmpl_filename.c_str(), O_RDONLY));
    if (in_fd < 0) {
      char const* msg(strerror(errno));
      throw (exceptions::open() << "RRD: could not open template file '"
             << tmpl_filename << "': " << msg);
    }

    // Store fd informations into the cache.
    fd_info fdinfo;
    fdinfo.fd = in_fd;
    fdinfo.size = s.st_size;
    _fds[info] = fdinfo;

    _duplicate(filename, fdinfo);
  }
  // No more space in the cache, juste create rrd file.
  else
    _open(filename, length, from, step, value_type);
}

/**
 *  Duplicate file.
 *
 *  @param[in] filename The file name to save data.
 *  @param[in] in_fd    The fd informations to duplicate file.
 */
void creator::_duplicate(std::string const& filename, fd_info const& in_fd) {
  // Remove previous file.
  remove(filename.c_str());

  int out_fd(open(
               filename.c_str(),
               O_CREAT | O_TRUNC | O_WRONLY,
               S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH));
  if (out_fd < 0) {
    char const* msg(strerror(errno));
    throw (exceptions::open() << "RRD: could not create file '"
           << filename << "': " << msg);
  }

#ifdef __linux__
  // First call(s) to sendfile detect if the kernel support the syscall
  // on any FD (Linux < 2.6.33 only supports writing to socket FD).
  off_t offset(0);
  ssize_t ret;
  do {
    ret = ::sendfile(out_fd, in_fd.fd, &offset, in_fd.size);
  } while ((ret < 0) && (errno == EAGAIN));
  bool fallback((ret < 0) && ((errno == EINVAL) || (errno == ENOSYS)));
  if (!fallback) {
    if (ret < 0) {
      char const* msg(strerror(errno));
      throw (exceptions::open() << "RRD: could not create file '"
             << filename << "': " << msg);
    }
    // Good to go with the sendfile syscall.
    _sendfile(out_fd, in_fd.fd, ret, in_fd.size, filename);
  }
  else
#endif // Linux
    // We must fallback to the read/write combo.
    _read_write(out_fd, in_fd.fd, in_fd.size, filename);

  ::close(out_fd);
}

/**
 *  Open a RRD file and create it if it does not exists.
 *
 *  @param[in] filename   Path to the RRD file.
 *  @param[in] length     Number of recording in the RRD file.
 *  @param[in] from       Timestamp of the first record.
 *  @param[in] step       Time interval between each record.
 *  @param[in] value_type Type of the metric.
 */
void creator::_open(
                std::string const& filename,
                unsigned int length,
                time_t from,
                unsigned int step,
                short value_type) {
  /* Find step of RRD file if already existing. */
  /* XXX : why is it here ?
  rrd_info_t* rrdinfo(rrd_info_r(_filename));
  time_t interval_offset(0);
  for (rrd_info_t* tmp = rrdinfo; tmp; tmp = tmp->next)
    if (!strcmp(rrdinfo->key, "step"))
      if (interval < static_cast<time_t>(rrdinfo->value.u_cnt))
        interval_offset = rrdinfo->value.u_cnt / interval - 1;
  rrd_info_free(rrdinfo);
  */

  // Set parameters.
  if (!step)
    step = 5 * 60 * 60;
  std::ostringstream ds_oss;
  std::ostringstream rra1_oss;
  std::ostringstream rra2_oss;
  ds_oss << "DS:value:";
  switch (value_type) {
  case storage::perfdata::absolute:
    ds_oss << "ABSOLUTE";
    break ;
  case storage::perfdata::counter:
    ds_oss << "COUNTER";
    break ;
  case storage::perfdata::derive:
    ds_oss << "DERIVE";
    break ;
  default:
    ds_oss << "GAUGE";
  };
  ds_oss << ":"<< step * 10 << ":U:U";
  rra1_oss << "RRA:AVERAGE:0.5:1:" << length + 1;
  rra2_oss << "RRA:AVERAGE:0.5:12:" << length / 12 + 1;
  std::string ds(ds_oss.str());
  std::string rra1(rra1_oss.str());
  std::string rra2(rra2_oss.str());
  char const* argv[5];
  argv[0] = ds.c_str();
  argv[1] = rra1.c_str();
  argv[2] = rra2.c_str();
  argv[3] = NULL;

  // Debug message.
  logging::debug(logging::high) << "RRD: opening file '" << filename
    << "' (" << argv[0] << ", " << argv[1] << ", " << argv[2]
    << ", step " << step << ", from " << from << ")";

  // Create RRD file.
  rrd_clear_error();
  if (rrd_create_r(
        filename.c_str(),
        step,
        from,
        3,
        argv))
    throw (exceptions::open() << "RRD: could not create file '"
             << filename << "': " << rrd_get_error());

  return ;
}

/**
 *  Transfer file between two FDs using read and write.
 *
 *  @param[in] out_fd   Output FD.
 *  @param[in] in_fd    Input FD.
 *  @param[in] size     Size to transfer.
 *  @param[in] filename Path to the file being created.
 */
void creator::_read_write(
                int out_fd,
                int in_fd,
                ssize_t size,
                std::string const& filename) {
  // Reset position of in_fd.
  if (lseek(in_fd, 0, SEEK_SET) == (off_t)-1) {
    char const* msg(strerror(errno));
    throw (exceptions::open() << "RRD: could not create file '"
           << filename << "': " << msg);
  }

  char buffer[4096];
  ssize_t transfered(0);
  while (transfered < size) {
    // Read from in_fd.
    ssize_t rb(::read(in_fd, buffer, sizeof(buffer)));
    if (rb <= 0) {
      if (errno != EAGAIN) {
        char const* msg(strerror(errno));
        throw (exceptions::open() << "RRD: could not create file '"
               << filename << "': " << msg);
      }
      continue ;
    }

    // Write to out_fd.
    ssize_t wb(0);
    while (wb < rb) {
      ssize_t ret(::write(out_fd, buffer + wb, rb - wb));
      if (ret <= 0) {
        if (errno != EAGAIN) {
          char const* msg(strerror(errno));
          throw (exceptions::open() << "RRD: could not create file '"
                 << filename << "': " << msg);
        }
      }
      else
        wb += ret;
    }

    // Update total transfered bytes.
    transfered += wb;
  }
  return ;
}

#ifdef __linux__
/**
 *  Transfer file between two FDs using sendfile.
 *
 *  @param[in] out_fd             Output FD.
 *  @param[in] in_fd              Input FD.
 *  @param[in] already_transfered Number of bytes already transfered.
 *  @param[in] size               Total size to transfer.
 *  @param[in] filename           Path to the file being created.
 */
void creator::_sendfile(
                 int out_fd,
                 int in_fd,
                 off_t already_transfered,
                 ssize_t size,
                 std::string const& filename) {
  ssize_t total(already_transfered);
  while (total < size) {
    already_transfered = total;
    ssize_t ret = ::sendfile(
                      out_fd,
                      in_fd,
                      &already_transfered,
                      size - already_transfered);
    if ((ret <= 0) && (errno != EAGAIN)) {
      char const* msg(strerror(errno));
      throw (exceptions::open() << "RRD: could not create file '"
             << filename << "': " << msg);
    }
    else if (ret > 0)
      total += ret;
  }
  return ;
}
#endif // Linux
<commit_msg>RRD: sanitize RRD file creation parameters.<commit_after>/*
** Copyright 2013-2014 Merethis
**
** This file is part of Centreon Broker.
**
** Centreon Broker is free software: you can redistribute it and/or
** modify it under the terms of the GNU General Public License version 2
** as published by the Free Software Foundation.
**
** Centreon Broker 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
** General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with Centreon Broker. If not, see
** <http://www.gnu.org/licenses/>.
*/

#include <cerrno>
#include <cstdio>
#include <cstring>
#include <fcntl.h>
#include <rrd.h>
#include <sstream>
#ifdef __linux__
#  include <sys/sendfile.h>
#endif // Linux
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include "com/centreon/broker/exceptions/msg.hh"
#include "com/centreon/broker/logging/logging.hh"
#include "com/centreon/broker/rrd/creator.hh"
#include "com/centreon/broker/rrd/exceptions/open.hh"
#include "com/centreon/broker/storage/perfdata.hh"

using namespace com::centreon::broker;
using namespace com::centreon::broker::rrd;

/**
 *  Constructor.
 *
 *  @param[in] tmpl_path  The template path.
 *  @param[in] cache_size The maximum number of cache element.
 */
creator::creator(
           std::string const& tmpl_path,
           unsigned int cache_size)
  : _cache_size(cache_size), _tmpl_path(tmpl_path) {}

/**
 *  Copy constructor.
 *
 *  @param[in] right The object to copy.
 */
creator::creator(creator const& right) {
  operator=(right);
}

/**
 *  Destructor.
 */
creator::~creator() {
  clear();
}

/**
 *  Copy operator.
 *
 *  @param[in] right The object to copy.
 *
 *  @return This object.
 */
creator& creator::operator=(creator const& right) {
  if (this != &right) {
    _cache_size = right._cache_size;
    _fds = right._fds;
    _tmpl_path = right._tmpl_path;
  }
  return (*this);
}

/**
 *  Clear cache and remove template file.
 */
void creator::clear() {
  for (std::map<tmpl_info, fd_info>::const_iterator
         it(_fds.begin()), end(_fds.end());
       it != end;
       ++it) {
    tmpl_info info(it->first);
    ::close(it->second.fd);
    std::ostringstream oss;
    oss << _tmpl_path << "/tmpl_" << info.length << "_" << info.step
        << "_" << info.value_type << ".rrd";
    ::remove(oss.str().c_str());
  }
  _fds.clear();
  return ;
}

/**
 *  Create a RRD file if it does not exists.
 *
 *  @param[in] filename   Path to the RRD file.
 *  @param[in] length     Number of recording in the RRD file.
 *  @param[in] from       Timestamp of the first record.
 *  @param[in] step       Specifies the base interval in seconds with
 *                        which data will be fed into the RRD.
 *  @param[in] value_type Type of the metric.
 */
void creator::create(
                std::string const& filename,
                unsigned int length,
                time_t from,
                unsigned int step,
                short value_type) {
  // Fill template informations.
  if (!step)
    step = 5 * 60 * 60; // Default to every 5 minutes.
  if (!length)
    length = 31 * 24 * 60 * 60 / step; // Default to one month long.
  tmpl_info info;
  info.length = length;
  info.step = step;
  info.value_type = value_type;

  // Find fd informations.
  std::map<tmpl_info, fd_info>::const_iterator it(_fds.find(info));
  // Is in the cache, just duplicate file.
  if (it != _fds.end())
    _duplicate(filename, it->second);
  // Not is the cache, but we have enough space in the cache.
  // Create new entry.
  else if (_fds.size() < _cache_size) {
    std::ostringstream oss;
    oss << _tmpl_path << "/tmpl_" << length << "_" << step
        << "_" << value_type << ".rrd";
    std::string tmpl_filename(oss.str());

    // Create new template.
    _open(tmpl_filename, length, from, step, value_type);

    // Get template file size.
    struct stat s;
    if (stat(tmpl_filename.c_str(), &s) < 0) {
      char const* msg(strerror(errno));
      throw (exceptions::open() << "RRD: could not create template file '"
             << tmpl_filename << "': " << msg);
    }

    // Get template file fd.
    int in_fd(open(tmpl_filename.c_str(), O_RDONLY));
    if (in_fd < 0) {
      char const* msg(strerror(errno));
      throw (exceptions::open() << "RRD: could not open template file '"
             << tmpl_filename << "': " << msg);
    }

    // Store fd informations into the cache.
    fd_info fdinfo;
    fdinfo.fd = in_fd;
    fdinfo.size = s.st_size;
    _fds[info] = fdinfo;

    _duplicate(filename, fdinfo);
  }
  // No more space in the cache, juste create rrd file.
  else
    _open(filename, length, from, step, value_type);
}

/**
 *  Duplicate file.
 *
 *  @param[in] filename The file name to save data.
 *  @param[in] in_fd    The fd informations to duplicate file.
 */
void creator::_duplicate(std::string const& filename, fd_info const& in_fd) {
  // Remove previous file.
  remove(filename.c_str());

  int out_fd(open(
               filename.c_str(),
               O_CREAT | O_TRUNC | O_WRONLY,
               S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH));
  if (out_fd < 0) {
    char const* msg(strerror(errno));
    throw (exceptions::open() << "RRD: could not create file '"
           << filename << "': " << msg);
  }

#ifdef __linux__
  // First call(s) to sendfile detect if the kernel support the syscall
  // on any FD (Linux < 2.6.33 only supports writing to socket FD).
  off_t offset(0);
  ssize_t ret;
  do {
    ret = ::sendfile(out_fd, in_fd.fd, &offset, in_fd.size);
  } while ((ret < 0) && (errno == EAGAIN));
  bool fallback((ret < 0) && ((errno == EINVAL) || (errno == ENOSYS)));
  if (!fallback) {
    if (ret < 0) {
      char const* msg(strerror(errno));
      throw (exceptions::open() << "RRD: could not create file '"
             << filename << "': " << msg);
    }
    // Good to go with the sendfile syscall.
    _sendfile(out_fd, in_fd.fd, ret, in_fd.size, filename);
  }
  else
#endif // Linux
    // We must fallback to the read/write combo.
    _read_write(out_fd, in_fd.fd, in_fd.size, filename);

  ::close(out_fd);
}

/**
 *  Open a RRD file and create it if it does not exists.
 *
 *  @param[in] filename   Path to the RRD file.
 *  @param[in] length     Number of recording in the RRD file.
 *  @param[in] from       Timestamp of the first record.
 *  @param[in] step       Time interval between each record.
 *  @param[in] value_type Type of the metric.
 */
void creator::_open(
                std::string const& filename,
                unsigned int length,
                time_t from,
                unsigned int step,
                short value_type) {
  /* Find step of RRD file if already existing. */
  /* XXX : why is it here ?
  rrd_info_t* rrdinfo(rrd_info_r(_filename));
  time_t interval_offset(0);
  for (rrd_info_t* tmp = rrdinfo; tmp; tmp = tmp->next)
    if (!strcmp(rrdinfo->key, "step"))
      if (interval < static_cast<time_t>(rrdinfo->value.u_cnt))
        interval_offset = rrdinfo->value.u_cnt / interval - 1;
  rrd_info_free(rrdinfo);
  */

  // Set parameters.
  std::ostringstream ds_oss;
  std::ostringstream rra1_oss;
  std::ostringstream rra2_oss;
  ds_oss << "DS:value:";
  switch (value_type) {
  case storage::perfdata::absolute:
    ds_oss << "ABSOLUTE";
    break ;
  case storage::perfdata::counter:
    ds_oss << "COUNTER";
    break ;
  case storage::perfdata::derive:
    ds_oss << "DERIVE";
    break ;
  default:
    ds_oss << "GAUGE";
  };
  ds_oss << ":"<< step * 10 << ":U:U";
  rra1_oss << "RRA:AVERAGE:0.5:1:" << length + 1;
  rra2_oss << "RRA:AVERAGE:0.5:12:" << length / 12 + 1;
  std::string ds(ds_oss.str());
  std::string rra1(rra1_oss.str());
  std::string rra2(rra2_oss.str());
  char const* argv[5];
  argv[0] = ds.c_str();
  argv[1] = rra1.c_str();
  argv[2] = rra2.c_str();
  argv[3] = NULL;

  // Debug message.
  logging::debug(logging::high) << "RRD: opening file '" << filename
    << "' (" << argv[0] << ", " << argv[1] << ", " << argv[2]
    << ", step " << step << ", from " << from << ")";

  // Create RRD file.
  rrd_clear_error();
  if (rrd_create_r(
        filename.c_str(),
        step,
        from,
        3,
        argv))
    throw (exceptions::open() << "RRD: could not create file '"
             << filename << "': " << rrd_get_error());

  return ;
}

/**
 *  Transfer file between two FDs using read and write.
 *
 *  @param[in] out_fd   Output FD.
 *  @param[in] in_fd    Input FD.
 *  @param[in] size     Size to transfer.
 *  @param[in] filename Path to the file being created.
 */
void creator::_read_write(
                int out_fd,
                int in_fd,
                ssize_t size,
                std::string const& filename) {
  // Reset position of in_fd.
  if (lseek(in_fd, 0, SEEK_SET) == (off_t)-1) {
    char const* msg(strerror(errno));
    throw (exceptions::open() << "RRD: could not create file '"
           << filename << "': " << msg);
  }

  char buffer[4096];
  ssize_t transfered(0);
  while (transfered < size) {
    // Read from in_fd.
    ssize_t rb(::read(in_fd, buffer, sizeof(buffer)));
    if (rb <= 0) {
      if (errno != EAGAIN) {
        char const* msg(strerror(errno));
        throw (exceptions::open() << "RRD: could not create file '"
               << filename << "': " << msg);
      }
      continue ;
    }

    // Write to out_fd.
    ssize_t wb(0);
    while (wb < rb) {
      ssize_t ret(::write(out_fd, buffer + wb, rb - wb));
      if (ret <= 0) {
        if (errno != EAGAIN) {
          char const* msg(strerror(errno));
          throw (exceptions::open() << "RRD: could not create file '"
                 << filename << "': " << msg);
        }
      }
      else
        wb += ret;
    }

    // Update total transfered bytes.
    transfered += wb;
  }
  return ;
}

#ifdef __linux__
/**
 *  Transfer file between two FDs using sendfile.
 *
 *  @param[in] out_fd             Output FD.
 *  @param[in] in_fd              Input FD.
 *  @param[in] already_transfered Number of bytes already transfered.
 *  @param[in] size               Total size to transfer.
 *  @param[in] filename           Path to the file being created.
 */
void creator::_sendfile(
                 int out_fd,
                 int in_fd,
                 off_t already_transfered,
                 ssize_t size,
                 std::string const& filename) {
  ssize_t total(already_transfered);
  while (total < size) {
    already_transfered = total;
    ssize_t ret = ::sendfile(
                      out_fd,
                      in_fd,
                      &already_transfered,
                      size - already_transfered);
    if ((ret <= 0) && (errno != EAGAIN)) {
      char const* msg(strerror(errno));
      throw (exceptions::open() << "RRD: could not create file '"
             << filename << "': " << msg);
    }
    else if (ret > 0)
      total += ret;
  }
  return ;
}
#endif // Linux
<|endoftext|>


<commit_before><commit_msg>Update LoadProfile so it doesn't display Guest profile<commit_after><|endoftext|>


<commit_before>#include <PrecompiledHeader.h>
#include "Macro.h"

using namespace BWAPI;

UnitCompositionProducer* infantryProducer = NULL; // TODO remove

Macro::Macro()
: expands(0)
, addedGates(0)
{
	TheArbitrator = & arbitrator;
	MacroManager::create();
	MacroSupplyManager::create();
	MacroDependencyResolver::create();
	ResourceRates::create();
	InformationManager::create();
	BorderManager::create();
	MacroBaseManager::create();
	UnitGroupManager::create();
	MacroWorkerManager::create();
	ReservedMap::create();

	TaskStream* ts = new TaskStream();
	TheMacroManager->taskStreams.push_back(ts);
	Unit* worker = NULL;
	for each(Unit* u in Broodwar->self()->getUnits())
	{
		if (u->getType().isResourceDepot())
			worker = u;
	}
	ts->setWorker(worker);
	ts->attach(BasicTaskExecutor::getInstance(),false);
	ts->attach(new UnitPump(Broodwar->self()->getRace().getWorker()),true);
	ts->attach(new TerminateIfWorkerLost(),true);
	if (Broodwar->self()->getRace() == Races::Protoss)
	{
		buildOrderAdd(UnitTypes::Protoss_Gateway);
		buildOrderAdd(UnitTypes::Protoss_Cybernetics_Core);
		buildOrderAdd(UnitTypes::Protoss_Assimilator);
		buildOrderAdd(UnitTypes::Protoss_Gateway);
		addedGates = 2;
		infantryProducer = new UnitCompositionProducer(UnitTypes::Protoss_Gateway);
		infantryProducer->setUnitWeight(UnitTypes::Protoss_Dragoon, 3.0);
		infantryProducer->setUnitWeight(UnitTypes::Protoss_Zealot, 1.0);
		upgradeAdd(UpgradeTypes::Singularity_Charge);
	}
	else if (Broodwar->self()->getRace() == Races::Terran)
	{
		buildOrderAdd(UnitTypes::Terran_Supply_Depot);
		buildOrderAdd(UnitTypes::Terran_Barracks);
		buildOrderAdd(UnitTypes::Terran_Refinery);
		buildOrderAdd(UnitTypes::Terran_Academy);
		buildOrderAdd(UnitTypes::Terran_Barracks);
		buildOrderAdd(UnitTypes::Terran_Barracks);
		infantryProducer = new UnitCompositionProducer(UnitTypes::Terran_Barracks);
		infantryProducer->setUnitWeight(UnitTypes::Terran_Marine, 3.0);
		infantryProducer->setUnitWeight(UnitTypes::Terran_Medic, 1.0);
		techAdd(TechTypes::Stim_Packs);
	}
	{
		Broodwar->printf("Race not implemented");
	}
}

Macro::~Macro()
{
	MacroManager::destroy();
	MacroSupplyManager::destroy();
	MacroDependencyResolver::destroy();
	ResourceRates::destroy();
	InformationManager::destroy();
	BorderManager::destroy();
	MacroBaseManager::destroy();
	UnitGroupManager::destroy();
	MacroWorkerManager::destroy();
	ReservedMap::destroy();
}

void Macro::buildOrderAdd(UnitType type)
{
	TaskStream* ts = new TaskStream(Task(type));
	TheMacroManager->taskStreams.push_back(ts);
	ts->attach(new BasicWorkerFinder(),true);
	ts->attach(BasicTaskExecutor::getInstance(),false);
	ts->attach(new TerminateIfEmpty(),true);
	ts->attach(SimCityBuildingPlacer::getInstance(),false);
}

void Macro::techAdd(TechType type)
{
	TaskStream* ts = new TaskStream(Task(type));
	TheMacroManager->taskStreams.push_back(ts);
	ts->attach(new BasicWorkerFinder(),true);
	ts->attach(BasicTaskExecutor::getInstance(),false);
	ts->attach(new TerminateIfEmpty(),true);
	ts->attach(SimCityBuildingPlacer::getInstance(),false);
}

void Macro::upgradeAdd(UpgradeType type)
{
	TaskStream* ts = new TaskStream(Task(type));
	TheMacroManager->taskStreams.push_back(ts);
	ts->attach(new BasicWorkerFinder(),true);
	ts->attach(BasicTaskExecutor::getInstance(),false);
	ts->attach(new TerminateIfEmpty(),true);
	ts->attach(SimCityBuildingPlacer::getInstance(),false);
}

void Macro::update()
{
    if (infantryProducer)
		infantryProducer->update();
	TheMacroSupplyManager->update();
	TheMacroManager->update();
	TheResourceRates->update();
	TheBorderManager->update();
	TheMacroBaseManager->update();
	TheMacroWorkerManager->update();
	TheArbitrator->update();

	if (!expands && Broodwar->self()->completedUnitCount(UnitTypes::Protoss_Dragoon) > 2)
	{
		++expands;
		TheMacroBaseManager->expandWhenPossible();
		++addedGates;
		//buildOrderAdd(UnitTypes::Protoss_Assimilator);
	}
	else if (expands == 1 && Broodwar->self()->completedUnitCount(UnitTypes::Protoss_Observer))
	{
		++expands;
		TheMacroBaseManager->expandWhenPossible();
		//buildOrderAdd(UnitTypes::Protoss_Assimilator);
	}
	if (addedGates < 3 && Broodwar->self()->completedUnitCount(UnitTypes::Protoss_Dragoon) > 1)
		buildOrderAdd(UnitTypes::Protoss_Gateway);

	/*if (Broodwar->self()->completedUnitCount(UnitTypes::Protoss_Nexus) > 1)
	{
		buildOrderAdd(UnitTypes::Protoss_Observatory);
		upgradeAdd(UpgradeTypes::Protoss_Ground_Weapons);
		upgradeAdd(UpgradeTypes::Protoss_Ground_Armor);
	}*/
	/*
	if (Broodwar->self()->minerals() > 500 && addedGates < 8)
	{
        ++addedGates;
		buildOrderAdd(UnitTypes::Protoss_Gateway);
	}*/
}

void Macro::onUnitDiscover(BWAPI::Unit* unit)
{
  TheInformationManager->onUnitDiscover(unit);
  TheUnitGroupManager->onUnitDiscover(unit);
}

void Macro::onUnitEvade(BWAPI::Unit* unit)
{
  TheInformationManager->onUnitEvade(unit);
  TheUnitGroupManager->onUnitEvade(unit);
}

void Macro::onUnitDestroy(BWAPI::Unit* unit)
{
  TheArbitrator->onRemoveObject(unit);
  TheInformationManager->onUnitDestroy(unit);
  TheMacroBaseManager->onUnitDestroy(unit);
  TheMacroWorkerManager->onRemoveUnit(unit);
}

void Macro::onUnitMorph(BWAPI::Unit* unit)
{
  TheUnitGroupManager->onUnitMorph(unit);
}

void Macro::onUnitRenegade(BWAPI::Unit* unit)
{
  TheUnitGroupManager->onUnitRenegade(unit);
}
<commit_msg>minor correction<commit_after>#include <PrecompiledHeader.h>
#include "Macro.h"

using namespace BWAPI;

UnitCompositionProducer* infantryProducer = NULL; // TODO remove

Macro::Macro()
: expands(0)
, addedGates(0)
{
	TheArbitrator = & arbitrator;
	MacroManager::create();
	MacroSupplyManager::create();
	MacroDependencyResolver::create();
	ResourceRates::create();
	InformationManager::create();
	BorderManager::create();
	MacroBaseManager::create();
	UnitGroupManager::create();
	MacroWorkerManager::create();
	ReservedMap::create();

	TaskStream* ts = new TaskStream();
	TheMacroManager->taskStreams.push_back(ts);
	Unit* worker = NULL;
	for each(Unit* u in Broodwar->self()->getUnits())
	{
		if (u->getType().isResourceDepot())
			worker = u;
	}
	ts->setWorker(worker);
	ts->attach(BasicTaskExecutor::getInstance(),false);
	ts->attach(new UnitPump(Broodwar->self()->getRace().getWorker()),true);
	ts->attach(new TerminateIfWorkerLost(),true);
	if (Broodwar->self()->getRace() == Races::Protoss)
	{
		buildOrderAdd(UnitTypes::Protoss_Gateway);
		buildOrderAdd(UnitTypes::Protoss_Cybernetics_Core);
		buildOrderAdd(UnitTypes::Protoss_Assimilator);
		buildOrderAdd(UnitTypes::Protoss_Gateway);
		addedGates = 2;
		infantryProducer = new UnitCompositionProducer(UnitTypes::Protoss_Gateway);
		infantryProducer->setUnitWeight(UnitTypes::Protoss_Dragoon, 3.0);
		infantryProducer->setUnitWeight(UnitTypes::Protoss_Zealot, 1.0);
		upgradeAdd(UpgradeTypes::Singularity_Charge);
	}
	else if (Broodwar->self()->getRace() == Races::Terran)
	{
		buildOrderAdd(UnitTypes::Terran_Supply_Depot);
		buildOrderAdd(UnitTypes::Terran_Barracks);
		buildOrderAdd(UnitTypes::Terran_Refinery);
		buildOrderAdd(UnitTypes::Terran_Academy);
		buildOrderAdd(UnitTypes::Terran_Barracks);
		buildOrderAdd(UnitTypes::Terran_Barracks);
		infantryProducer = new UnitCompositionProducer(UnitTypes::Terran_Barracks);
		infantryProducer->setUnitWeight(UnitTypes::Terran_Marine, 3.0);
		infantryProducer->setUnitWeight(UnitTypes::Terran_Medic, 1.0);
		techAdd(TechTypes::Stim_Packs);
	}
	{
		Broodwar->printf("Race not implemented");
	}
}

Macro::~Macro()
{
	MacroManager::destroy();
	MacroSupplyManager::destroy();
	MacroDependencyResolver::destroy();
	ResourceRates::destroy();
	InformationManager::destroy();
	BorderManager::destroy();
	MacroBaseManager::destroy();
	UnitGroupManager::destroy();
	MacroWorkerManager::destroy();
	ReservedMap::destroy();
}

void Macro::buildOrderAdd(UnitType type)
{
	TaskStream* ts = new TaskStream(Task(type));
	TheMacroManager->taskStreams.push_back(ts);
	ts->attach(new BasicWorkerFinder(),true);
	ts->attach(BasicTaskExecutor::getInstance(),false);
	ts->attach(new TerminateIfEmpty(),true);
	ts->attach(SimCityBuildingPlacer::getInstance(),false);
}

void Macro::techAdd(TechType type)
{
	TaskStream* ts = new TaskStream(Task(type));
	TheMacroManager->taskStreams.push_back(ts);
	ts->attach(new BasicWorkerFinder(),true);
	ts->attach(BasicTaskExecutor::getInstance(),false);
	ts->attach(new TerminateIfEmpty(),true);
	ts->attach(SimCityBuildingPlacer::getInstance(),false);
}

void Macro::upgradeAdd(UpgradeType type)
{
	TaskStream* ts = new TaskStream(Task(type));
	TheMacroManager->taskStreams.push_back(ts);
	ts->attach(new BasicWorkerFinder(),true);
	ts->attach(BasicTaskExecutor::getInstance(),false);
	ts->attach(new TerminateIfEmpty(),true);
	ts->attach(SimCityBuildingPlacer::getInstance(),false);
}

void Macro::update()
{
    if (infantryProducer)
		infantryProducer->update();
	TheMacroSupplyManager->update();
	TheMacroManager->update();
	TheResourceRates->update();
	TheBorderManager->update();
	TheMacroBaseManager->update();
	TheMacroWorkerManager->update();
	TheArbitrator->update();

	if (!expands && Broodwar->self()->completedUnitCount(UnitTypes::Protoss_Dragoon) > 2)
	{
		++expands;
		TheMacroBaseManager->expandWhenPossible();
		//buildOrderAdd(UnitTypes::Protoss_Assimilator);
	}
	else if (expands == 1 && Broodwar->self()->completedUnitCount(UnitTypes::Protoss_Observer))
	{
		++expands;
		TheMacroBaseManager->expandWhenPossible();
		//buildOrderAdd(UnitTypes::Protoss_Assimilator);
	}
	if (addedGates < 3 && Broodwar->self()->completedUnitCount(UnitTypes::Protoss_Dragoon) > 1)
	{
		buildOrderAdd(UnitTypes::Protoss_Gateway);
		++addedGates;
	}

	/*if (Broodwar->self()->completedUnitCount(UnitTypes::Protoss_Nexus) > 1)
	{
		buildOrderAdd(UnitTypes::Protoss_Observatory);
		upgradeAdd(UpgradeTypes::Protoss_Ground_Weapons);
		upgradeAdd(UpgradeTypes::Protoss_Ground_Armor);
	}*/
	/*
	if (Broodwar->self()->minerals() > 500 && addedGates < 8)
	{
        ++addedGates;
		buildOrderAdd(UnitTypes::Protoss_Gateway);
	}*/
}

void Macro::onUnitDiscover(BWAPI::Unit* unit)
{
  TheInformationManager->onUnitDiscover(unit);
  TheUnitGroupManager->onUnitDiscover(unit);
}

void Macro::onUnitEvade(BWAPI::Unit* unit)
{
  TheInformationManager->onUnitEvade(unit);
  TheUnitGroupManager->onUnitEvade(unit);
}

void Macro::onUnitDestroy(BWAPI::Unit* unit)
{
  TheArbitrator->onRemoveObject(unit);
  TheInformationManager->onUnitDestroy(unit);
  TheMacroBaseManager->onUnitDestroy(unit);
  TheMacroWorkerManager->onRemoveUnit(unit);
}

void Macro::onUnitMorph(BWAPI::Unit* unit)
{
  TheUnitGroupManager->onUnitMorph(unit);
}

void Macro::onUnitRenegade(BWAPI::Unit* unit)
{
  TheUnitGroupManager->onUnitRenegade(unit);
}
<|endoftext|>


<commit_before>#include "Pit.h"
#include "../Variables/Variable.h"
#include "../Distribution.h"
MetricPit::MetricPit(const Options& iOptions, const Data& iData) : Metric(iOptions, iData) {

}
float MetricPit::computeCore(const Obs& iObs, const Forecast& iForecast) const {
   float       obsValue = iObs.getValue();
   const Variable* var = Variable::get(iObs.getVariable());

   Distribution::ptr dist = iForecast.getDistribution();
   float pit = dist->getCdf(obsValue);

   // Randomize pit if on the lower boundary

   if(!Global::isValid(pit)) {
      return Global::MV;
   }
   if(var->isLowerDiscrete() && var->getMin() == obsValue) {
      pit = Global::getRand() * pit;
   }
   else if(var->isUpperDiscrete() && var->getMax() == obsValue) {
      pit = 1 - Global::getRand() * (1-pit);
   }
   if(pit == 1 || pit == 0) {
      std::stringstream ss;
      ss << "MetricPit: Pit value of " << pit << " for D" << iObs.getDate() << " O" << iObs.getOffset() << " L" << iObs.getLocation().getId() << " V" << iObs.getVariable() << " obs = " << obsValue << std::endl;
      Global::logger->write(ss.str(), Logger::warning);
   }
   return pit;
}
<commit_msg>Don't warn when PIT values are 0 or 1<commit_after>#include "Pit.h"
#include "../Variables/Variable.h"
#include "../Distribution.h"
MetricPit::MetricPit(const Options& iOptions, const Data& iData) : Metric(iOptions, iData) {

}
float MetricPit::computeCore(const Obs& iObs, const Forecast& iForecast) const {
   float       obsValue = iObs.getValue();
   const Variable* var = Variable::get(iObs.getVariable());

   Distribution::ptr dist = iForecast.getDistribution();
   float pit = dist->getCdf(obsValue);

   // Randomize pit if on the lower boundary

   if(!Global::isValid(pit)) {
      return Global::MV;
   }
   if(var->isLowerDiscrete() && var->getMin() == obsValue) {
      pit = Global::getRand() * pit;
   }
   else if(var->isUpperDiscrete() && var->getMax() == obsValue) {
      pit = 1 - Global::getRand() * (1-pit);
   }
   if(pit == 1 || pit == 0) {
      std::stringstream ss;
      ss << "MetricPit: Pit value of " << pit << " for D" << iObs.getDate() << " O" << iObs.getOffset() << " L" << iObs.getLocation().getId() << " V" << iObs.getVariable() << " obs = " << obsValue << std::endl;
      Global::logger->write(ss.str(), Logger::message);
   }
   return pit;
}
<|endoftext|>


<commit_before>#include <string.h>
#include <errno.h>
#include <dirent.h>
#include <unistd.h>
#include <fcntl.h>

#include "ProcFsTools.hpp"

namespace {

typedef bool (*TokenizerCb) (
		int idx,
		const char *start,
		const char *end,
		void *userdata);

enum ProcStatIdx {
	STAT_IDX_PID = 0,
	STAT_IDX_NAME = 1,
	STAT_IDX_UTIME = 13,
	STAT_IDX_STIME = 14,
	STAT_IDX_THREADCOUNT= 19,
	STAT_IDX_VSIZE = 22,
	STAT_IDX_RSS = 23
};

enum ParserState {
	PARSER_STATE_IDLE = 0,
	PARSER_STATE_INT,
	PARSER_STATE_STR
};

struct PidTestCtx {
	const char *mName;
	bool mMatch;
};

int tokenizeStats(int fd, TokenizerCb cb, void *userdata)
{
	bool doParse;
	const char *s;
	char strstat[1024];
	ssize_t readRet;
	const char *start = NULL;
	ParserState state;
	int idx = 0;
	int ret;

	if (fd == -1 || !cb)
		return -EINVAL;

	readRet = pread(fd, strstat, sizeof(strstat), 0);
	if (readRet == -1) {
		ret = -errno;
		printf("read() failed : %d(%m)", errno);
		return ret;
	}

	// Remove trailing '\n'
	strstat[readRet - 1] = '\0';

	s = strstat;
	state = PARSER_STATE_IDLE;
	while (*s != '\0') {
		switch (state) {
		case PARSER_STATE_IDLE:
			if (*s == '(') {
				state = PARSER_STATE_STR;
				start = s;
			} else if (*s != ' ') {
				state = PARSER_STATE_INT;
				start = s;
			}
			break;

		case PARSER_STATE_INT:
			if (*s == ' ') {
				doParse = cb(idx, start, s - 1, userdata);
				if (!doParse)
					return 0;

				state = PARSER_STATE_IDLE;
				idx++;
			}
			break;

		case PARSER_STATE_STR:
			if (*s == ')') {
				doParse = cb(idx, start, s, userdata);
				if (!doParse)
					return 0;

				state = PARSER_STATE_IDLE;
				idx++;
			}
			break;

		default:
			break;
		}

		s++;
	}

	switch (state) {
	case PARSER_STATE_INT:
		cb(idx, start, s - 1, userdata);
		break;

	case PARSER_STATE_STR:
		cb(idx, start, s - 1, userdata);
		break;

	default:
		break;
	}

	return 0;
}

bool processStatsCb(int idx,
		     const char *start,
		     const char *end,
		     void *userdata)
{
	SystemMonitor::ProcessStats *stats = (SystemMonitor::ProcessStats *) userdata;
	char buf[64];
	bool ret = true;

	if ((size_t) (end - start + 1) > sizeof(buf))
		return false;

	memcpy(buf, start, end - start + 1);
	buf[end - start + 1] = '\0';

	switch (idx) {
	case STAT_IDX_PID:
		stats->mPid = atoi(buf);
		break;

	case STAT_IDX_NAME:
		strncpy(stats->mName, buf, sizeof(stats->mName));
		break;

	case STAT_IDX_UTIME:
		stats->mUtime = atoll(buf);
		break;

	case STAT_IDX_STIME:
		stats->mStime = atoll(buf);
		break;

	case STAT_IDX_THREADCOUNT:
		stats->mThreadCount = atoi(buf);
		break;

	case STAT_IDX_VSIZE:
		stats->mVsize = atoi(buf);
		break;

	case STAT_IDX_RSS:
		stats->mRss = atoi(buf);
		ret = false;
		break;

	default:
		break;
	}

	return ret;
}

bool threadStatsCb(int idx,
		   const char *start,
		   const char *end,
		   void *userdata)
{
	SystemMonitor::ThreadStats *stats = (SystemMonitor::ThreadStats *) userdata;
	char buf[64];
	bool ret = true;

	if ((size_t) (end - start + 1) > sizeof(buf))
		return false;

	memcpy(buf, start, end - start + 1);
	buf[end - start + 1] = '\0';

	switch (idx) {
	case STAT_IDX_PID:
		stats->mTid = atoi(buf);
		break;

	case STAT_IDX_NAME:
		strncpy(stats->mName, buf, sizeof(stats->mName));
		break;

	case STAT_IDX_UTIME:
		stats->mUtime = atoll(buf);
		break;

	case STAT_IDX_STIME:
		stats->mStime = atoll(buf);
		ret = false;
		break;

	default:
		break;
	}

	return ret;
}

bool pidTestCb(int idx,
		      const char *start,
		      const char *end,
		      void *userdata)
{
	PidTestCtx *ctx = (PidTestCtx *) userdata;
	char buf[64];

	if (idx != STAT_IDX_NAME)
		return true;

	if ((size_t) (end - start + 1) > sizeof(buf))
		return false;

	memcpy(buf, start, end - start + 1);
	buf[end - start + 1] = '\0';

	ctx->mMatch = (strncmp(buf + 1, ctx->mName, strlen(buf) - 2) == 0);

	return false;
}

bool testPidName(int pid, const char *name)
{
	PidTestCtx testCtx;
	char path[128];
	int fd;
	int ret;

	snprintf(path, sizeof(path), "/proc/%d/stat", pid);

	fd = open(path, O_RDONLY|O_CLOEXEC);
	if (fd == -1) {
		ret = -errno;
		printf("Fail to open %s : %d(%m)\n", path, errno);
		return ret;
	}

	testCtx.mName = name;
	testCtx.mMatch = false;

	ret = tokenizeStats(fd, pidTestCb, &testCtx);
	close(fd);
	if (ret < 0) {
		return false;
	}

	return testCtx.mMatch;
}

} // anonymous namespace

namespace pfstools {

int findProcess(const char *name, int *outPid)
{
	DIR *d;
	struct dirent entry;
	struct dirent *result = nullptr;
	int pid;
	char *endptr;
	int ret;
	bool found = false;

	d = opendir("/proc");
	if (!d) {
		ret = -errno;
		printf("Fail to open /proc : %d(%m)\n", errno);
		return ret;
	}

	while (!found) {
		ret = readdir_r(d, &entry, &result);
		if (ret == 0 && !result)
			break;

		pid = strtol(entry.d_name, &endptr, 10);
		if (errno == ERANGE) {
			printf("Ignore %s\n", entry.d_name);
			continue;
		} else if (*endptr != '\0') {
			continue;
		}

		found = testPidName(pid, name);
	}

	closedir(d);

	if (found)
		*outPid = pid;

	return found ? 0 : -ENOENT;
}

int readProcessStats(int fd, SystemMonitor::ProcessStats *stats)
{
	if (!stats)
		return -EINVAL;

	return tokenizeStats(fd, processStatsCb, stats);
}

int readThreadStats(int fd, SystemMonitor::ThreadStats *stats)
{
	if (!stats)
			return -EINVAL;

	return tokenizeStats(fd, threadStatsCb, stats);
}

} // namespace pfstools
<commit_msg>Fix build for gcc 4.6<commit_after>#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <dirent.h>
#include <unistd.h>
#include <fcntl.h>

#include "ProcFsTools.hpp"

namespace {

typedef bool (*TokenizerCb) (
		int idx,
		const char *start,
		const char *end,
		void *userdata);

enum ProcStatIdx {
	STAT_IDX_PID = 0,
	STAT_IDX_NAME = 1,
	STAT_IDX_UTIME = 13,
	STAT_IDX_STIME = 14,
	STAT_IDX_THREADCOUNT= 19,
	STAT_IDX_VSIZE = 22,
	STAT_IDX_RSS = 23
};

enum ParserState {
	PARSER_STATE_IDLE = 0,
	PARSER_STATE_INT,
	PARSER_STATE_STR
};

struct PidTestCtx {
	const char *mName;
	bool mMatch;
};

int tokenizeStats(int fd, TokenizerCb cb, void *userdata)
{
	bool doParse;
	const char *s;
	char strstat[1024];
	ssize_t readRet;
	const char *start = NULL;
	ParserState state;
	int idx = 0;
	int ret;

	if (fd == -1 || !cb)
		return -EINVAL;

	readRet = pread(fd, strstat, sizeof(strstat), 0);
	if (readRet == -1) {
		ret = -errno;
		printf("read() failed : %d(%m)", errno);
		return ret;
	}

	// Remove trailing '\n'
	strstat[readRet - 1] = '\0';

	s = strstat;
	state = PARSER_STATE_IDLE;
	while (*s != '\0') {
		switch (state) {
		case PARSER_STATE_IDLE:
			if (*s == '(') {
				state = PARSER_STATE_STR;
				start = s;
			} else if (*s != ' ') {
				state = PARSER_STATE_INT;
				start = s;
			}
			break;

		case PARSER_STATE_INT:
			if (*s == ' ') {
				doParse = cb(idx, start, s - 1, userdata);
				if (!doParse)
					return 0;

				state = PARSER_STATE_IDLE;
				idx++;
			}
			break;

		case PARSER_STATE_STR:
			if (*s == ')') {
				doParse = cb(idx, start, s, userdata);
				if (!doParse)
					return 0;

				state = PARSER_STATE_IDLE;
				idx++;
			}
			break;

		default:
			break;
		}

		s++;
	}

	switch (state) {
	case PARSER_STATE_INT:
		cb(idx, start, s - 1, userdata);
		break;

	case PARSER_STATE_STR:
		cb(idx, start, s - 1, userdata);
		break;

	default:
		break;
	}

	return 0;
}

bool processStatsCb(int idx,
		     const char *start,
		     const char *end,
		     void *userdata)
{
	SystemMonitor::ProcessStats *stats = (SystemMonitor::ProcessStats *) userdata;
	char buf[64];
	bool ret = true;

	if ((size_t) (end - start + 1) > sizeof(buf))
		return false;

	memcpy(buf, start, end - start + 1);
	buf[end - start + 1] = '\0';

	switch (idx) {
	case STAT_IDX_PID:
		stats->mPid = atoi(buf);
		break;

	case STAT_IDX_NAME:
		strncpy(stats->mName, buf, sizeof(stats->mName));
		break;

	case STAT_IDX_UTIME:
		stats->mUtime = atoll(buf);
		break;

	case STAT_IDX_STIME:
		stats->mStime = atoll(buf);
		break;

	case STAT_IDX_THREADCOUNT:
		stats->mThreadCount = atoi(buf);
		break;

	case STAT_IDX_VSIZE:
		stats->mVsize = atoi(buf);
		break;

	case STAT_IDX_RSS:
		stats->mRss = atoi(buf);
		ret = false;
		break;

	default:
		break;
	}

	return ret;
}

bool threadStatsCb(int idx,
		   const char *start,
		   const char *end,
		   void *userdata)
{
	SystemMonitor::ThreadStats *stats = (SystemMonitor::ThreadStats *) userdata;
	char buf[64];
	bool ret = true;

	if ((size_t) (end - start + 1) > sizeof(buf))
		return false;

	memcpy(buf, start, end - start + 1);
	buf[end - start + 1] = '\0';

	switch (idx) {
	case STAT_IDX_PID:
		stats->mTid = atoi(buf);
		break;

	case STAT_IDX_NAME:
		strncpy(stats->mName, buf, sizeof(stats->mName));
		break;

	case STAT_IDX_UTIME:
		stats->mUtime = atoll(buf);
		break;

	case STAT_IDX_STIME:
		stats->mStime = atoll(buf);
		ret = false;
		break;

	default:
		break;
	}

	return ret;
}

bool pidTestCb(int idx,
		      const char *start,
		      const char *end,
		      void *userdata)
{
	PidTestCtx *ctx = (PidTestCtx *) userdata;
	char buf[64];

	if (idx != STAT_IDX_NAME)
		return true;

	if ((size_t) (end - start + 1) > sizeof(buf))
		return false;

	memcpy(buf, start, end - start + 1);
	buf[end - start + 1] = '\0';

	ctx->mMatch = (strncmp(buf + 1, ctx->mName, strlen(buf) - 2) == 0);

	return false;
}

bool testPidName(int pid, const char *name)
{
	PidTestCtx testCtx;
	char path[128];
	int fd;
	int ret;

	snprintf(path, sizeof(path), "/proc/%d/stat", pid);

	fd = open(path, O_RDONLY|O_CLOEXEC);
	if (fd == -1) {
		ret = -errno;
		printf("Fail to open %s : %d(%m)\n", path, errno);
		return ret;
	}

	testCtx.mName = name;
	testCtx.mMatch = false;

	ret = tokenizeStats(fd, pidTestCb, &testCtx);
	close(fd);
	if (ret < 0) {
		return false;
	}

	return testCtx.mMatch;
}

} // anonymous namespace

namespace pfstools {

int findProcess(const char *name, int *outPid)
{
	DIR *d;
	struct dirent entry;
	struct dirent *result = nullptr;
	int pid;
	char *endptr;
	int ret;
	bool found = false;

	d = opendir("/proc");
	if (!d) {
		ret = -errno;
		printf("Fail to open /proc : %d(%m)\n", errno);
		return ret;
	}

	while (!found) {
		ret = readdir_r(d, &entry, &result);
		if (ret == 0 && !result)
			break;

		pid = strtol(entry.d_name, &endptr, 10);
		if (errno == ERANGE) {
			printf("Ignore %s\n", entry.d_name);
			continue;
		} else if (*endptr != '\0') {
			continue;
		}

		found = testPidName(pid, name);
	}

	closedir(d);

	if (found)
		*outPid = pid;

	return found ? 0 : -ENOENT;
}

int readProcessStats(int fd, SystemMonitor::ProcessStats *stats)
{
	if (!stats)
		return -EINVAL;

	return tokenizeStats(fd, processStatsCb, stats);
}

int readThreadStats(int fd, SystemMonitor::ThreadStats *stats)
{
	if (!stats)
			return -EINVAL;

	return tokenizeStats(fd, threadStatsCb, stats);
}

} // namespace pfstools
<|endoftext|>


<commit_before>// PythonStuff.cpp
// Copyright (c) 2009, Dan Heeks
// This program is released under the BSD license. See the file COPYING for details.

#include "stdafx.h"
#include <wx/file.h>
#include <wx/mimetype.h>
#include <wx/stdpaths.h>
#include <wx/filename.h>
#include <wx/txtstrm.h>
#include <wx/log.h>
#include "PythonStuff.h"
#include "ProgramCanvas.h"
#include "OutputCanvas.h"
#include "Program.h"
#include "CNCConfig.h"
#include "interface/PropertyString.h"

//static
bool CPyProcess::redirect = true;

CPyProcess::CPyProcess(void)
{
  m_pid = 0;
  wxProcess(heeksCAD->GetMainFrame());
  Connect(wxEVT_TIMER, wxTimerEventHandler(CPyProcess::OnTimer));
  m_timer.SetOwner(this);

}

void CPyProcess::OnTimer(wxTimerEvent& event)
{
  HandleInput();
}

void CPyProcess::HandleInput(void) {
	wxInputStream *m_in, *m_err;

	m_in = GetInputStream();
	m_err = GetErrorStream();

	if (m_in) {
		wxString s;
		while (m_in->CanRead()) {
			char buffer[4096];
			m_in->Read(buffer, sizeof(buffer));
			s += wxString::From8BitData(buffer, m_in->LastRead());
		}
		if (s.Length() > 0) {
			wxLogMessage(_T("> %s"), s.c_str());
		}
	}
	if (m_err) {
		wxString s;
		while (m_err->CanRead()) {
			char buffer[4096];
			m_err->Read(buffer, sizeof(buffer));
			s += wxString::From8BitData(buffer, m_err->LastRead());
		}
		if (s.Length() > 0) {
			wxLogMessage(_T("! %s"), s.c_str());
		}
	}
}

void CPyProcess::Execute(const wxChar* cmd)
{
	if(redirect) {
		Redirect();
	}
	// make process group leader so Cancel kan terminate process including children
	m_pid = wxExecute(cmd, wxEXEC_ASYNC|wxEXEC_MAKE_GROUP_LEADER, this);
	if (!m_pid) {
	  wxLogMessage(_T("could not execute '%s'"),cmd);
	} else {
	  wxLogMessage(_T("starting '%s' (%d)"),cmd,m_pid);
	}
	if (redirect) {
		m_timer.Start(100);   //msec
	}
}

void CPyProcess::Cancel(void)
{
	if (m_pid)
	{
		wxKillError kerror;
		wxSignal sig = wxSIGTERM;
		int retcode;

		if ( wxProcess::Exists(m_pid) ) {
			retcode = wxKill(m_pid, sig, &kerror, wxKILL_CHILDREN);
			switch (kerror) {
			case wxKILL_OK:
				wxLogMessage(_T("sent signal %d to process %d"),sig, m_pid);
				break;
			case wxKILL_NO_PROCESS:
				wxLogMessage(_T("process %d already exited"),m_pid);
				break;
			case wxKILL_ACCESS_DENIED:
				wxLogMessage(_T("sending signal %d to process %d - access denied"),sig, m_pid);
				break;
			case wxKILL_BAD_SIGNAL:      // no such signal
				wxLogMessage(_T("no such signal: %d"),sig);
				break;
			case wxKILL_ERROR:            // another, unspecified error
				wxLogMessage(_T("unspecified error sending signal %d to process %d"),sig, m_pid);
				break;
			}
		} else {
			wxLogMessage(_T("process %d has gone away"), m_pid);
		}
		m_pid = 0;
	}
}

void CPyProcess::OnTerminate(int pid, int status)
{
	if (pid == m_pid)
	{
	  if (redirect) {
		  m_timer.Stop();
		  HandleInput();   // anything left?
	  }
	  if (status) {
		  wxLogMessage(_T("process %d exit(%d)"),pid, status);
	  } else {
		  wxLogDebug(_T("process %d exit(0)"),pid);
	  }
	  m_pid = 0;
	  ThenDo();
	}
	// else: the process already was already treated with Cancel() so m_pid is 0
}

////////////////////////////////////////////////////////

class CPyBackPlot : public CPyProcess
{
protected:
	const CProgram* m_program;
	HeeksObj* m_into;
	wxString m_filename;
	wxBusyCursor *m_busy_cursor;

	static CPyBackPlot* m_object;

public:
	CPyBackPlot(const CProgram* program, HeeksObj* into, const wxChar* filename): m_program(program), m_into(into),m_filename(filename),m_busy_cursor(NULL) { m_object = this; }
	~CPyBackPlot(void) { m_object = NULL; }

	static void StaticCancel(void) { if (m_object) m_object->Cancel(); }

	void Do(void)
	{
		if(m_busy_cursor == NULL)m_busy_cursor = new wxBusyCursor();

		if (m_program->m_machine.file_name == _T("not found"))
		{
			wxMessageBox(_T("Machine name (defined in Program Properties) not found"));
		} // End if - then
		else
		{
#ifdef WIN32
			Execute(wxString(_T("\"")) + theApp.GetDllFolder() + _T("\\nc_read.bat\" ") + m_program->m_machine.file_name + _T(" \"") + m_filename + _T("\""));
#else
#ifdef RUNINPLACE
            wxString path(_T("/nc/"));
#else
            wxString path(_T("/../heekscnc/nc/"));
#endif

			Execute(wxString(_T("python \"")) + theApp.GetDllFolder() + path + m_program->m_machine.file_name + wxString(_T("_read.py\" \"")) + m_filename + wxString(_T("\"")) );
#endif
		} // End if - else
	}
	void ThenDo(void)
	{
		// there should now be a .nc.xml written
		wxString xml_file_str = m_filename + wxString(_T(".nc.xml"));
		wxFile ofs(xml_file_str.c_str());
		if(!ofs.IsOpened())
		{
			wxMessageBox(wxString(_("Couldn't open file")) + _T(" - ") + xml_file_str);
			return;
		}

		// read the xml file, just like paste, into the program
		heeksCAD->OpenXMLFile(xml_file_str, m_into);
		heeksCAD->Repaint();

		// in Windows, at least, executing the bat file was making HeeksCAD change it's Z order
		heeksCAD->GetMainFrame()->Raise();

		delete m_busy_cursor;
		m_busy_cursor = NULL;
	}
};

CPyBackPlot* CPyBackPlot::m_object = NULL;

class CPyPostProcess : public CPyProcess
{
protected:
	const CProgram* m_program;
	wxString m_filename;
	bool m_include_backplot_processing;

	static CPyPostProcess* m_object;

public:
	CPyPostProcess(const CProgram* program,
			const wxChar* filename,
			const bool include_backplot_processing = true ) :
		m_program(program), m_filename(filename), m_include_backplot_processing(include_backplot_processing)
	{
		m_object = this;
	}

	~CPyPostProcess(void) { m_object = NULL; }

	static void StaticCancel(void) { if (m_object) m_object->Cancel(); }

	void Do(void)
	{
		wxBusyCursor wait; // show an hour glass until the end of this function
		wxStandardPaths standard_paths;
		wxFileName path( standard_paths.GetTempDir().c_str(), _T("post.py"));

#ifdef WIN32
        Execute(wxString(_T("\"")) + theApp.GetDllFolder() + wxString(_T("\\post.bat\" \"")) + path.GetFullPath() + wxString(_T("\"")));
#else

        wxString post_path = wxString(_T("python ")) + path.GetFullPath();
		Execute(post_path);
#endif
	}
	void ThenDo(void)
	{
		if (m_include_backplot_processing)
		{
			(new CPyBackPlot(m_program, (HeeksObj*)m_program, m_filename))->Do();
		}
	}
};

CPyPostProcess* CPyPostProcess::m_object = NULL;

////////////////////////////////////////////////////////

static bool write_python_file(const wxString& python_file_path)
{
	wxFile ofs(python_file_path.c_str(), wxFile::write);
	if(!ofs.IsOpened())return false;

	ofs.Write(theApp.m_program->m_python_program.c_str());

	return true;
}

bool HeeksPyPostProcess(const CProgram* program, const wxString &filepath, const bool include_backplot_processing)
{
	try{
		theApp.m_output_canvas->m_textCtrl->Clear(); // clear the output window

		// write the python file
		wxStandardPaths standard_paths;
		wxFileName file_str( standard_paths.GetTempDir().c_str(), _T("post.py"));

		if(!write_python_file(file_str.GetFullPath()))
		{
		    wxString error;
		    error << _T("couldn't write ") << file_str.GetFullPath();
		    wxMessageBox(error.c_str());
		}
		else
		{
#ifdef WIN32
			// Set the working directory to the area that contains the DLL so that
			// the system can find the post.bat file correctly.
			::wxSetWorkingDirectory(theApp.GetDllFolder());
#else
			::wxSetWorkingDirectory(standard_paths.GetTempDir());
#endif

			// call the python file
			(new CPyPostProcess(program, filepath, include_backplot_processing))->Do();

			return true;
		}
	}
	catch(...)
	{
		wxMessageBox(_T("Error while post-processing the program!"));
	}
	return false;
}

bool HeeksPyBackplot(const CProgram* program, HeeksObj* into, const wxString &filepath)
{
	try{
		theApp.m_output_canvas->m_textCtrl->Clear(); // clear the output window

		::wxSetWorkingDirectory(theApp.GetDllFolder());

		// call the python file
		(new CPyBackPlot(program, into, filepath))->Do();

		// in Windows, at least, executing the bat file was making HeeksCAD change it's Z order
		heeksCAD->GetMainFrame()->Raise();

		return true;
	}
	catch(...)
	{
		wxMessageBox(_T("Error while backplotting the program!"));
	}
	return false;
}

void HeeksPyCancel(void)
{
	CPyBackPlot::StaticCancel();
	CPyPostProcess::StaticCancel();
}

// create a temporary ngc file
// make your favorite machine load it
void CSendToMachine::Cancel(void) { CPyProcess::Cancel(); }
void CSendToMachine::SendGCode(const wxChar *gcode)
	{
		wxBusyCursor wait; // show an hour glass until the end of this function

		// write the ngc file
		wxStandardPaths standard_paths;
		wxFileName ngcpath( standard_paths.GetTempDir().c_str(), wxString::Format(_T("heekscnc-%d.ngc"), m_serial));
		m_serial++;
		{
			wxFile ofs(ngcpath.GetFullPath(), wxFile::write);
			if(!ofs.IsOpened())
			{
				wxMessageBox(wxString(_("Couldn't open file")) + _T(" - ") + ngcpath.GetFullPath());
				return;
			}
			ofs.Write(theApp.m_output_canvas->m_textCtrl->GetValue());
		}
		wxLogDebug(_T("created '%s')"), ngcpath.GetFullPath().c_str());

#ifdef WIN32
        Execute(wxString(_T("\"")) + theApp.GetDllFolder() +wxString(_T("\\")) + m_command + wxString(_T("\" \"")) + ngcpath.GetFullPath() + wxString(_T("\"")));
#else
        wxString sendto_cmdline = m_command + wxString(_T(" ")) + ngcpath.GetFullPath();
        wxLogDebug(_T("executing '%s')"), sendto_cmdline.c_str());
		Execute(sendto_cmdline);
#endif
	}

int CSendToMachine::m_serial;
wxString CSendToMachine::m_command;

static void on_set_to_machine_command(const wxChar *value, HeeksObj* object)
{
	CSendToMachine::m_command = value;
	CSendToMachine::WriteToConfig();
}

// static
void CSendToMachine::GetOptions(std::list<Property *> *list)
{
	list->push_back(new PropertyString(_("send-to-machine command"), m_command, NULL, on_set_to_machine_command));
}

// static
void CSendToMachine::ReadFromConfig()
{
        CNCConfig config(CSendToMachine::ConfigScope());
        config.Read(_T("SendToMachineCommand"), &m_command , _T("axis-remote"));
}
// static
void CSendToMachine::WriteToConfig()
{
        CNCConfig config(CSendToMachine::ConfigScope());
        config.Write(_T("SendToMachineCommand"), m_command);
}

static CSendToMachine *sendto;

bool HeeksSendToMachine(const wxString &gcode)
{
	if (sendto != NULL) {
		sendto->Cancel();
		delete sendto;
	}
	sendto = new CSendToMachine;
	sendto->SendGCode(gcode);

	return false;
}

<commit_msg>I fixed a compile error on Windows; seems like "sento" was already defined in "winsock.h", so I changed it to "send_to"<commit_after>// PythonStuff.cpp
// Copyright (c) 2009, Dan Heeks
// This program is released under the BSD license. See the file COPYING for details.

#include "stdafx.h"
#include <wx/file.h>
#include <wx/mimetype.h>
#include <wx/stdpaths.h>
#include <wx/filename.h>
#include <wx/txtstrm.h>
#include <wx/log.h>
#include "PythonStuff.h"
#include "ProgramCanvas.h"
#include "OutputCanvas.h"
#include "Program.h"
#include "CNCConfig.h"
#include "interface/PropertyString.h"

//static
bool CPyProcess::redirect = true;

CPyProcess::CPyProcess(void)
{
  m_pid = 0;
  wxProcess(heeksCAD->GetMainFrame());
  Connect(wxEVT_TIMER, wxTimerEventHandler(CPyProcess::OnTimer));
  m_timer.SetOwner(this);

}

void CPyProcess::OnTimer(wxTimerEvent& event)
{
  HandleInput();
}

void CPyProcess::HandleInput(void) {
	wxInputStream *m_in, *m_err;

	m_in = GetInputStream();
	m_err = GetErrorStream();

	if (m_in) {
		wxString s;
		while (m_in->CanRead()) {
			char buffer[4096];
			m_in->Read(buffer, sizeof(buffer));
			s += wxString::From8BitData(buffer, m_in->LastRead());
		}
		if (s.Length() > 0) {
			wxLogMessage(_T("> %s"), s.c_str());
		}
	}
	if (m_err) {
		wxString s;
		while (m_err->CanRead()) {
			char buffer[4096];
			m_err->Read(buffer, sizeof(buffer));
			s += wxString::From8BitData(buffer, m_err->LastRead());
		}
		if (s.Length() > 0) {
			wxLogMessage(_T("! %s"), s.c_str());
		}
	}
}

void CPyProcess::Execute(const wxChar* cmd)
{
	if(redirect) {
		Redirect();
	}
	// make process group leader so Cancel kan terminate process including children
	m_pid = wxExecute(cmd, wxEXEC_ASYNC|wxEXEC_MAKE_GROUP_LEADER, this);
	if (!m_pid) {
	  wxLogMessage(_T("could not execute '%s'"),cmd);
	} else {
	  wxLogMessage(_T("starting '%s' (%d)"),cmd,m_pid);
	}
	if (redirect) {
		m_timer.Start(100);   //msec
	}
}

void CPyProcess::Cancel(void)
{
	if (m_pid)
	{
		wxKillError kerror;
		wxSignal sig = wxSIGTERM;
		int retcode;

		if ( wxProcess::Exists(m_pid) ) {
			retcode = wxKill(m_pid, sig, &kerror, wxKILL_CHILDREN);
			switch (kerror) {
			case wxKILL_OK:
				wxLogMessage(_T("sent signal %d to process %d"),sig, m_pid);
				break;
			case wxKILL_NO_PROCESS:
				wxLogMessage(_T("process %d already exited"),m_pid);
				break;
			case wxKILL_ACCESS_DENIED:
				wxLogMessage(_T("sending signal %d to process %d - access denied"),sig, m_pid);
				break;
			case wxKILL_BAD_SIGNAL:      // no such signal
				wxLogMessage(_T("no such signal: %d"),sig);
				break;
			case wxKILL_ERROR:            // another, unspecified error
				wxLogMessage(_T("unspecified error sending signal %d to process %d"),sig, m_pid);
				break;
			}
		} else {
			wxLogMessage(_T("process %d has gone away"), m_pid);
		}
		m_pid = 0;
	}
}

void CPyProcess::OnTerminate(int pid, int status)
{
	if (pid == m_pid)
	{
	  if (redirect) {
		  m_timer.Stop();
		  HandleInput();   // anything left?
	  }
	  if (status) {
		  wxLogMessage(_T("process %d exit(%d)"),pid, status);
	  } else {
		  wxLogDebug(_T("process %d exit(0)"),pid);
	  }
	  m_pid = 0;
	  ThenDo();
	}
	// else: the process already was already treated with Cancel() so m_pid is 0
}

////////////////////////////////////////////////////////

class CPyBackPlot : public CPyProcess
{
protected:
	const CProgram* m_program;
	HeeksObj* m_into;
	wxString m_filename;
	wxBusyCursor *m_busy_cursor;

	static CPyBackPlot* m_object;

public:
	CPyBackPlot(const CProgram* program, HeeksObj* into, const wxChar* filename): m_program(program), m_into(into),m_filename(filename),m_busy_cursor(NULL) { m_object = this; }
	~CPyBackPlot(void) { m_object = NULL; }

	static void StaticCancel(void) { if (m_object) m_object->Cancel(); }

	void Do(void)
	{
		if(m_busy_cursor == NULL)m_busy_cursor = new wxBusyCursor();

		if (m_program->m_machine.file_name == _T("not found"))
		{
			wxMessageBox(_T("Machine name (defined in Program Properties) not found"));
		} // End if - then
		else
		{
#ifdef WIN32
			Execute(wxString(_T("\"")) + theApp.GetDllFolder() + _T("\\nc_read.bat\" ") + m_program->m_machine.file_name + _T(" \"") + m_filename + _T("\""));
#else
#ifdef RUNINPLACE
            wxString path(_T("/nc/"));
#else
            wxString path(_T("/../heekscnc/nc/"));
#endif

			Execute(wxString(_T("python \"")) + theApp.GetDllFolder() + path + m_program->m_machine.file_name + wxString(_T("_read.py\" \"")) + m_filename + wxString(_T("\"")) );
#endif
		} // End if - else
	}
	void ThenDo(void)
	{
		// there should now be a .nc.xml written
		wxString xml_file_str = m_filename + wxString(_T(".nc.xml"));
		wxFile ofs(xml_file_str.c_str());
		if(!ofs.IsOpened())
		{
			wxMessageBox(wxString(_("Couldn't open file")) + _T(" - ") + xml_file_str);
			return;
		}

		// read the xml file, just like paste, into the program
		heeksCAD->OpenXMLFile(xml_file_str, m_into);
		heeksCAD->Repaint();

		// in Windows, at least, executing the bat file was making HeeksCAD change it's Z order
		heeksCAD->GetMainFrame()->Raise();

		delete m_busy_cursor;
		m_busy_cursor = NULL;
	}
};

CPyBackPlot* CPyBackPlot::m_object = NULL;

class CPyPostProcess : public CPyProcess
{
protected:
	const CProgram* m_program;
	wxString m_filename;
	bool m_include_backplot_processing;

	static CPyPostProcess* m_object;

public:
	CPyPostProcess(const CProgram* program,
			const wxChar* filename,
			const bool include_backplot_processing = true ) :
		m_program(program), m_filename(filename), m_include_backplot_processing(include_backplot_processing)
	{
		m_object = this;
	}

	~CPyPostProcess(void) { m_object = NULL; }

	static void StaticCancel(void) { if (m_object) m_object->Cancel(); }

	void Do(void)
	{
		wxBusyCursor wait; // show an hour glass until the end of this function
		wxStandardPaths standard_paths;
		wxFileName path( standard_paths.GetTempDir().c_str(), _T("post.py"));

#ifdef WIN32
        Execute(wxString(_T("\"")) + theApp.GetDllFolder() + wxString(_T("\\post.bat\" \"")) + path.GetFullPath() + wxString(_T("\"")));
#else

        wxString post_path = wxString(_T("python ")) + path.GetFullPath();
		Execute(post_path);
#endif
	}
	void ThenDo(void)
	{
		if (m_include_backplot_processing)
		{
			(new CPyBackPlot(m_program, (HeeksObj*)m_program, m_filename))->Do();
		}
	}
};

CPyPostProcess* CPyPostProcess::m_object = NULL;

////////////////////////////////////////////////////////

static bool write_python_file(const wxString& python_file_path)
{
	wxFile ofs(python_file_path.c_str(), wxFile::write);
	if(!ofs.IsOpened())return false;

	ofs.Write(theApp.m_program->m_python_program.c_str());

	return true;
}

bool HeeksPyPostProcess(const CProgram* program, const wxString &filepath, const bool include_backplot_processing)
{
	try{
		theApp.m_output_canvas->m_textCtrl->Clear(); // clear the output window

		// write the python file
		wxStandardPaths standard_paths;
		wxFileName file_str( standard_paths.GetTempDir().c_str(), _T("post.py"));

		if(!write_python_file(file_str.GetFullPath()))
		{
		    wxString error;
		    error << _T("couldn't write ") << file_str.GetFullPath();
		    wxMessageBox(error.c_str());
		}
		else
		{
#ifdef WIN32
			// Set the working directory to the area that contains the DLL so that
			// the system can find the post.bat file correctly.
			::wxSetWorkingDirectory(theApp.GetDllFolder());
#else
			::wxSetWorkingDirectory(standard_paths.GetTempDir());
#endif

			// call the python file
			(new CPyPostProcess(program, filepath, include_backplot_processing))->Do();

			return true;
		}
	}
	catch(...)
	{
		wxMessageBox(_T("Error while post-processing the program!"));
	}
	return false;
}

bool HeeksPyBackplot(const CProgram* program, HeeksObj* into, const wxString &filepath)
{
	try{
		theApp.m_output_canvas->m_textCtrl->Clear(); // clear the output window

		::wxSetWorkingDirectory(theApp.GetDllFolder());

		// call the python file
		(new CPyBackPlot(program, into, filepath))->Do();

		// in Windows, at least, executing the bat file was making HeeksCAD change it's Z order
		heeksCAD->GetMainFrame()->Raise();

		return true;
	}
	catch(...)
	{
		wxMessageBox(_T("Error while backplotting the program!"));
	}
	return false;
}

void HeeksPyCancel(void)
{
	CPyBackPlot::StaticCancel();
	CPyPostProcess::StaticCancel();
}

// create a temporary ngc file
// make your favorite machine load it
void CSendToMachine::Cancel(void) { CPyProcess::Cancel(); }
void CSendToMachine::SendGCode(const wxChar *gcode)
	{
		wxBusyCursor wait; // show an hour glass until the end of this function

		// write the ngc file
		wxStandardPaths standard_paths;
		wxFileName ngcpath( standard_paths.GetTempDir().c_str(), wxString::Format(_T("heekscnc-%d.ngc"), m_serial));
		m_serial++;
		{
			wxFile ofs(ngcpath.GetFullPath(), wxFile::write);
			if(!ofs.IsOpened())
			{
				wxMessageBox(wxString(_("Couldn't open file")) + _T(" - ") + ngcpath.GetFullPath());
				return;
			}
			ofs.Write(theApp.m_output_canvas->m_textCtrl->GetValue());
		}
		wxLogDebug(_T("created '%s')"), ngcpath.GetFullPath().c_str());

#ifdef WIN32
        Execute(wxString(_T("\"")) + theApp.GetDllFolder() +wxString(_T("\\")) + m_command + wxString(_T("\" \"")) + ngcpath.GetFullPath() + wxString(_T("\"")));
#else
        wxString sendto_cmdline = m_command + wxString(_T(" ")) + ngcpath.GetFullPath();
        wxLogDebug(_T("executing '%s')"), sendto_cmdline.c_str());
		Execute(sendto_cmdline);
#endif
	}

int CSendToMachine::m_serial;
wxString CSendToMachine::m_command;

static void on_set_to_machine_command(const wxChar *value, HeeksObj* object)
{
	CSendToMachine::m_command = value;
	CSendToMachine::WriteToConfig();
}

// static
void CSendToMachine::GetOptions(std::list<Property *> *list)
{
	list->push_back(new PropertyString(_("send-to-machine command"), m_command, NULL, on_set_to_machine_command));
}

// static
void CSendToMachine::ReadFromConfig()
{
        CNCConfig config(CSendToMachine::ConfigScope());
        config.Read(_T("SendToMachineCommand"), &m_command , _T("axis-remote"));
}
// static
void CSendToMachine::WriteToConfig()
{
        CNCConfig config(CSendToMachine::ConfigScope());
        config.Write(_T("SendToMachineCommand"), m_command);
}

static CSendToMachine *send_to;

bool HeeksSendToMachine(const wxString &gcode)
{
	if (send_to != NULL) {
		send_to->Cancel();
		delete send_to;
	}
	send_to = new CSendToMachine;
	send_to->SendGCode(gcode);

	return false;
}

<|endoftext|>


<commit_before>// PythonStuff.cpp
// Copyright (c) 2009, Dan Heeks
// This program is released under the BSD license. See the file COPYING for details.

#include "stdafx.h"
#include <wx/file.h>
#include <wx/mimetype.h>
#include <wx/process.h>
#include <wx/stdpaths.h>
#include <wx/filename.h>
#include "PythonStuff.h"
#include "ProgramCanvas.h"
#include "OutputCanvas.h"
#include "Program.h"

class CPyProcess : public wxProcess
{
protected:
	int m_pid;

public:
	CPyProcess(void): wxProcess(heeksCAD->GetMainFrame()), m_pid(0) { }

	void Execute(const wxChar* cmd);
	void Cancel(void);
	void OnTerminate(int pid, int status);

	virtual void ThenDo(void) { }
};

void CPyProcess::Execute(const wxChar* cmd)
{
	m_pid = wxExecute(cmd, wxEXEC_ASYNC, this);
}

void CPyProcess::Cancel(void)
{
	if (m_pid)
	{
		wxProcess::Kill(m_pid);
		m_pid = 0;
	}
}

void CPyProcess::OnTerminate(int pid, int status)
{
	if (pid == m_pid)
	{
		m_pid = 0;
		ThenDo();
	}
}

////////////////////////////////////////////////////////

class CPyBackPlot : public CPyProcess
{
protected:
	const CProgram* m_program;
	HeeksObj* m_into;
	wxString m_filename;
	wxBusyCursor *m_busy_cursor;

	static CPyBackPlot* m_object;

public:
	CPyBackPlot(const CProgram* program, HeeksObj* into, const wxChar* filename): m_program(program), m_into(into),m_filename(filename),m_busy_cursor(NULL) { m_object = this; }
	~CPyBackPlot(void) { m_object = NULL; }

	static void StaticCancel(void) { if (m_object) m_object->Cancel(); }

	void Do(void)
	{
		if(m_busy_cursor == NULL)m_busy_cursor = new wxBusyCursor();

		if (m_program->m_machine.file_name == _T("not found"))
		{
			wxMessageBox(_T("Machine name (defined in Program Properties) not found"));
		} // End if - then
		else
		{
#ifdef WIN32
			Execute(wxString(_T("\"")) + theApp.GetDllFolder() + _T("\\nc_read.bat\" ") + m_program->m_machine.file_name + _T(" \"") + m_filename + _T("\""));
#else
#ifdef RUNINPLACE
            wxString path(_T("/nc/"));
#else
            wxString path(_T("/../heekscnc/nc/"));
#endif

			Execute(wxString(_T("python \"")) + theApp.GetDllFolder() + path + m_program->m_machine.file_name + wxString(_T("_read.py\" \"")) + m_filename + wxString(_T("\"")) );
#endif
		} // End if - else
	}
	void ThenDo(void)
	{
		// there should now be a .nc.xml written
		wxString xml_file_str = m_filename + wxString(_T(".nc.xml"));
		wxFile ofs(xml_file_str.c_str());
		if(!ofs.IsOpened())
		{
			wxMessageBox(wxString(_("Couldn't open file")) + _T(" - ") + xml_file_str);
			return;
		}

		// read the xml file, just like paste, into the program
		heeksCAD->OpenXMLFile(xml_file_str, m_into);
		heeksCAD->Repaint();

		// in Windows, at least, executing the bat file was making HeeksCAD change it's Z order
		heeksCAD->GetMainFrame()->Raise();

		delete m_busy_cursor;
		m_busy_cursor = NULL;
	}
};

CPyBackPlot* CPyBackPlot::m_object = NULL;

class CPyPostProcess : public CPyProcess
{
protected:
	const CProgram* m_program;
	wxString m_filename;
	bool m_include_backplot_processing;

	static CPyPostProcess* m_object;

public:
	CPyPostProcess(const CProgram* program,
			const wxChar* filename,
			const bool include_backplot_processing = true ) :
		m_program(program), m_filename(filename), m_include_backplot_processing(include_backplot_processing)
	{
		m_object = this;
	}

	~CPyPostProcess(void) { m_object = NULL; }

	static void StaticCancel(void) { if (m_object) m_object->Cancel(); }

	void Do(void)
	{
		wxBusyCursor wait; // show an hour glass until the end of this function
		wxStandardPaths standard_paths;
		wxFileName path( standard_paths.GetTempDir().c_str(), _T("post.py"));

#ifdef WIN32
        Execute(wxString(_T("\"")) + theApp.GetDllFolder() + wxString(_T("\\post.bat\" \"")) + path.GetFullPath() + wxString(_T("\"")));
#else

        wxString path = wxString(_T("python ")) + path.GetFullPath();
		cout<<path.c_str();
		Execute(path);
#endif
	}
	void ThenDo(void)
	{
		if (m_include_backplot_processing)
		{
			(new CPyBackPlot(m_program, (HeeksObj*)m_program, m_filename))->Do();
		}
	}
};

CPyPostProcess* CPyPostProcess::m_object = NULL;

////////////////////////////////////////////////////////

static bool write_python_file(const wxString& python_file_path)
{
	wxFile ofs(python_file_path.c_str(), wxFile::write);
	if(!ofs.IsOpened())return false;

	ofs.Write(theApp.m_program->m_python_program.c_str());

	return true;
}

bool HeeksPyPostProcess(const CProgram* program, const wxString &filepath, const bool include_backplot_processing)
{
	try{
		theApp.m_output_canvas->m_textCtrl->Clear(); // clear the output window

		// write the python file
		wxStandardPaths standard_paths;
		wxFileName file_str( standard_paths.GetTempDir().c_str(), _T("post.py"));

		if(!write_python_file(file_str.GetFullPath()))
		{
		    wxString error;
		    error << _T("couldn't write ") << file_str.GetFullPath();
		    wxMessageBox(error.c_str());
		}
		else
		{
#ifdef WIN32
			// Set the working directory to the area that contains the DLL so that
			// the system can find the post.bat file correctly.
			::wxSetWorkingDirectory(theApp.GetDllFolder());
#else
			::wxSetWorkingDirectory(standard_paths.GetTempDir());
#endif

			// call the python file
			(new CPyPostProcess(program, filepath, include_backplot_processing))->Do();

			return true;
		}
	}
	catch(...)
	{
		wxMessageBox(_T("Error while post-processing the program!"));
	}
	return false;
}

bool HeeksPyBackplot(const CProgram* program, HeeksObj* into, const wxString &filepath)
{
	try{
		theApp.m_output_canvas->m_textCtrl->Clear(); // clear the output window

		::wxSetWorkingDirectory(theApp.GetDllFolder());

		// call the python file
		(new CPyBackPlot(program, into, filepath))->Do();

		// in Windows, at least, executing the bat file was making HeeksCAD change it's Z order
		heeksCAD->GetMainFrame()->Raise();

		return true;
	}
	catch(...)
	{
		wxMessageBox(_T("Error while backplotting the program!"));
	}
	return false;
}

void HeeksPyCancel(void)
{
	CPyBackPlot::StaticCancel();
	CPyPostProcess::StaticCancel();
}

<commit_msg>I accidentally committed a test bit of code with "cout<<" in it, which didn't compile!<commit_after>// PythonStuff.cpp
// Copyright (c) 2009, Dan Heeks
// This program is released under the BSD license. See the file COPYING for details.

#include "stdafx.h"
#include <wx/file.h>
#include <wx/mimetype.h>
#include <wx/process.h>
#include <wx/stdpaths.h>
#include <wx/filename.h>
#include "PythonStuff.h"
#include "ProgramCanvas.h"
#include "OutputCanvas.h"
#include "Program.h"

class CPyProcess : public wxProcess
{
protected:
	int m_pid;

public:
	CPyProcess(void): wxProcess(heeksCAD->GetMainFrame()), m_pid(0) { }

	void Execute(const wxChar* cmd);
	void Cancel(void);
	void OnTerminate(int pid, int status);

	virtual void ThenDo(void) { }
};

void CPyProcess::Execute(const wxChar* cmd)
{
	m_pid = wxExecute(cmd, wxEXEC_ASYNC, this);
}

void CPyProcess::Cancel(void)
{
	if (m_pid)
	{
		wxProcess::Kill(m_pid);
		m_pid = 0;
	}
}

void CPyProcess::OnTerminate(int pid, int status)
{
	if (pid == m_pid)
	{
		m_pid = 0;
		ThenDo();
	}
}

////////////////////////////////////////////////////////

class CPyBackPlot : public CPyProcess
{
protected:
	const CProgram* m_program;
	HeeksObj* m_into;
	wxString m_filename;
	wxBusyCursor *m_busy_cursor;

	static CPyBackPlot* m_object;

public:
	CPyBackPlot(const CProgram* program, HeeksObj* into, const wxChar* filename): m_program(program), m_into(into),m_filename(filename),m_busy_cursor(NULL) { m_object = this; }
	~CPyBackPlot(void) { m_object = NULL; }

	static void StaticCancel(void) { if (m_object) m_object->Cancel(); }

	void Do(void)
	{
		if(m_busy_cursor == NULL)m_busy_cursor = new wxBusyCursor();

		if (m_program->m_machine.file_name == _T("not found"))
		{
			wxMessageBox(_T("Machine name (defined in Program Properties) not found"));
		} // End if - then
		else
		{
#ifdef WIN32
			Execute(wxString(_T("\"")) + theApp.GetDllFolder() + _T("\\nc_read.bat\" ") + m_program->m_machine.file_name + _T(" \"") + m_filename + _T("\""));
#else
#ifdef RUNINPLACE
            wxString path(_T("/nc/"));
#else
            wxString path(_T("/../heekscnc/nc/"));
#endif

			Execute(wxString(_T("python \"")) + theApp.GetDllFolder() + path + m_program->m_machine.file_name + wxString(_T("_read.py\" \"")) + m_filename + wxString(_T("\"")) );
#endif
		} // End if - else
	}
	void ThenDo(void)
	{
		// there should now be a .nc.xml written
		wxString xml_file_str = m_filename + wxString(_T(".nc.xml"));
		wxFile ofs(xml_file_str.c_str());
		if(!ofs.IsOpened())
		{
			wxMessageBox(wxString(_("Couldn't open file")) + _T(" - ") + xml_file_str);
			return;
		}

		// read the xml file, just like paste, into the program
		heeksCAD->OpenXMLFile(xml_file_str, m_into);
		heeksCAD->Repaint();

		// in Windows, at least, executing the bat file was making HeeksCAD change it's Z order
		heeksCAD->GetMainFrame()->Raise();

		delete m_busy_cursor;
		m_busy_cursor = NULL;
	}
};

CPyBackPlot* CPyBackPlot::m_object = NULL;

class CPyPostProcess : public CPyProcess
{
protected:
	const CProgram* m_program;
	wxString m_filename;
	bool m_include_backplot_processing;

	static CPyPostProcess* m_object;

public:
	CPyPostProcess(const CProgram* program,
			const wxChar* filename,
			const bool include_backplot_processing = true ) :
		m_program(program), m_filename(filename), m_include_backplot_processing(include_backplot_processing)
	{
		m_object = this;
	}

	~CPyPostProcess(void) { m_object = NULL; }

	static void StaticCancel(void) { if (m_object) m_object->Cancel(); }

	void Do(void)
	{
		wxBusyCursor wait; // show an hour glass until the end of this function
		wxStandardPaths standard_paths;
		wxFileName path( standard_paths.GetTempDir().c_str(), _T("post.py"));

#ifdef WIN32
        Execute(wxString(_T("\"")) + theApp.GetDllFolder() + wxString(_T("\\post.bat\" \"")) + path.GetFullPath() + wxString(_T("\"")));
#else

        wxString path = wxString(_T("python ")) + path.GetFullPath();
		Execute(path);
#endif
	}
	void ThenDo(void)
	{
		if (m_include_backplot_processing)
		{
			(new CPyBackPlot(m_program, (HeeksObj*)m_program, m_filename))->Do();
		}
	}
};

CPyPostProcess* CPyPostProcess::m_object = NULL;

////////////////////////////////////////////////////////

static bool write_python_file(const wxString& python_file_path)
{
	wxFile ofs(python_file_path.c_str(), wxFile::write);
	if(!ofs.IsOpened())return false;

	ofs.Write(theApp.m_program->m_python_program.c_str());

	return true;
}

bool HeeksPyPostProcess(const CProgram* program, const wxString &filepath, const bool include_backplot_processing)
{
	try{
		theApp.m_output_canvas->m_textCtrl->Clear(); // clear the output window

		// write the python file
		wxStandardPaths standard_paths;
		wxFileName file_str( standard_paths.GetTempDir().c_str(), _T("post.py"));

		if(!write_python_file(file_str.GetFullPath()))
		{
		    wxString error;
		    error << _T("couldn't write ") << file_str.GetFullPath();
		    wxMessageBox(error.c_str());
		}
		else
		{
#ifdef WIN32
			// Set the working directory to the area that contains the DLL so that
			// the system can find the post.bat file correctly.
			::wxSetWorkingDirectory(theApp.GetDllFolder());
#else
			::wxSetWorkingDirectory(standard_paths.GetTempDir());
#endif

			// call the python file
			(new CPyPostProcess(program, filepath, include_backplot_processing))->Do();

			return true;
		}
	}
	catch(...)
	{
		wxMessageBox(_T("Error while post-processing the program!"));
	}
	return false;
}

bool HeeksPyBackplot(const CProgram* program, HeeksObj* into, const wxString &filepath)
{
	try{
		theApp.m_output_canvas->m_textCtrl->Clear(); // clear the output window

		::wxSetWorkingDirectory(theApp.GetDllFolder());

		// call the python file
		(new CPyBackPlot(program, into, filepath))->Do();

		// in Windows, at least, executing the bat file was making HeeksCAD change it's Z order
		heeksCAD->GetMainFrame()->Raise();

		return true;
	}
	catch(...)
	{
		wxMessageBox(_T("Error while backplotting the program!"));
	}
	return false;
}

void HeeksPyCancel(void)
{
	CPyBackPlot::StaticCancel();
	CPyPostProcess::StaticCancel();
}

<|endoftext|>


<commit_before>#pragma once

#include <cilantro/core/space_transformations.hpp>
#include <cilantro/core/common_pair_evaluators.hpp>
#include <cilantro/core/kd_tree.hpp>

namespace cilantro {
    template <class TransformT, class WeightEvaluatorT = UnityWeightEvaluator<typename TransformT::Scalar,typename TransformT::Scalar>>
    typename std::enable_if<internal::HasLinear<TransformT>::value && internal::HasTranslation<TransformT>::value,void>::type
    resampleTransforms(const TransformSet<TransformT> &old_transforms,
                       const NeighborhoodSet<typename WeightEvaluatorT::InputScalar> &new_to_old_map,
                       TransformSet<TransformT> &new_transforms,
                       const WeightEvaluatorT &weight_evaluator = WeightEvaluatorT())
    {
        new_transforms.resize(new_to_old_map.size());

#pragma omp parallel for shared (new_transforms)
        for (size_t i = 0; i < new_transforms.size(); i++) {
            typename TransformT::Scalar total_weight = (typename TransformT::Scalar)0.0;
            new_transforms[i].linear().setZero();
            new_transforms[i].translation().setZero();
            for (size_t j = 0; j < new_to_old_map[i].size(); j++) {
                const typename TransformT::Scalar weight = weight_evaluator(i, new_to_old_map[i][j].index, new_to_old_map[i][j].value);
                total_weight += weight;
                new_transforms[i].linear().noalias() += weight*old_transforms[new_to_old_map[i][j].index].linear();
                new_transforms[i].translation().noalias() += weight*old_transforms[new_to_old_map[i][j].index].translation();
            }

            if (total_weight == (typename TransformT::Scalar)0.0) {
                new_transforms[i].setIdentity();
            } else {
                total_weight = (typename TransformT::Scalar)(1.0)/total_weight;
                new_transforms[i].linear() *= total_weight;
                if (int(TransformT::Mode) == int(Eigen::Isometry)) {
                    new_transforms[i].linear() = new_transforms[i].rotation();
                }
                new_transforms[i].translation() *= total_weight;
            }
        }
    }

    template <class TransformT, class WeightEvaluatorT = UnityWeightEvaluator<typename TransformT::Scalar,typename TransformT::Scalar>>
    inline TransformSet<TransformT> resampleTransforms(const TransformSet<TransformT> &old_transforms,
                                                       const NeighborhoodSet<typename WeightEvaluatorT::InputScalar> &new_to_old_map,
                                                       const WeightEvaluatorT &weight_evaluator = WeightEvaluatorT())
    {
        TransformSet<TransformT> new_transforms;
        resampleTransforms<TransformT,WeightEvaluatorT>(old_transforms, new_to_old_map, new_transforms, weight_evaluator);
        return new_transforms;
    }

    template <class TransformT, class NeighborhoodSpecT, class WeightEvaluatorT = UnityWeightEvaluator<typename TransformT::Scalar,typename TransformT::Scalar>>
    typename std::enable_if<internal::HasLinear<TransformT>::value && internal::HasTranslation<TransformT>::value,void>::type
    resampleTransforms(const KDTree<typename TransformT::Scalar,TransformT::Dim,KDTreeDistanceAdaptors::L2> &old_support_kd_tree,
                       const TransformSet<TransformT> &old_transforms,
                       const ConstVectorSetMatrixMap<typename TransformT::Scalar,TransformT::Dim> &new_support,
                       const NeighborhoodSpecT &nh,
                       TransformSet<TransformT> &new_transforms,
                       const WeightEvaluatorT &weight_evaluator = WeightEvaluatorT())
    {
        new_transforms.resize(new_support.cols());

        Neighborhood<typename TransformT::Scalar> nn;
#pragma omp parallel for shared (new_transforms) private (nn)
        for (size_t i = 0; i < new_transforms.size(); i++) {
            old_support_kd_tree.template search<NeighborhoodSpecT>(new_support.col(i), nh, nn);
            typename TransformT::Scalar total_weight = (typename TransformT::Scalar)0.0;
            new_transforms[i].linear().setZero();
            new_transforms[i].translation().setZero();
            for (size_t j = 0; j < nn.size(); j++) {
                const typename TransformT::Scalar weight = weight_evaluator(i, nn[j].index, nn[j].value);
                total_weight += weight;
                new_transforms[i].linear().noalias() += weight*old_transforms[nn[j].index].linear();
                new_transforms[i].translation().noalias() += weight*old_transforms[nn[j].index].translation();
            }

            if (total_weight == (typename TransformT::Scalar)0.0) {
                new_transforms[i].setIdentity();
            } else {
                total_weight = (typename TransformT::Scalar)(1.0)/total_weight;
                new_transforms[i].linear() *= total_weight;
                if (int(TransformT::Mode) == int(Eigen::Isometry)) {
                    new_transforms[i].linear() = new_transforms[i].rotation();
                }
                new_transforms[i].translation() *= total_weight;
            }
        }
    }

    template <class TransformT, class NeighborhoodSpecT, class WeightEvaluatorT = UnityWeightEvaluator<typename TransformT::Scalar,typename TransformT::Scalar>>
    inline TransformSet<TransformT> resampleTransforms(const KDTree<typename TransformT::Scalar,TransformT::Dim,KDTreeDistanceAdaptors::L2> &old_support_kd_tree,
                                                       const TransformSet<TransformT> &old_transforms,
                                                       const ConstVectorSetMatrixMap<typename TransformT::Scalar,TransformT::Dim> &new_support,
                                                       const NeighborhoodSpecT &nh,
                                                       const WeightEvaluatorT &weight_evaluator = WeightEvaluatorT())
    {
        TransformSet<TransformT> new_transforms;
        resampleTransforms<TransformT,NeighborhoodSpecT,WeightEvaluatorT>(old_support_kd_tree, old_transforms, new_support, nh, new_transforms, weight_evaluator);
        return new_transforms;
    }
}
<commit_msg>Some template argument changes in warp field utilities<commit_after>#pragma once

#include <cilantro/core/space_transformations.hpp>
#include <cilantro/core/common_pair_evaluators.hpp>

namespace cilantro {
    template <class TransformT, class NeighborhoodSetT, class WeightEvaluatorT = UnityWeightEvaluator<typename TransformT::Scalar,typename TransformT::Scalar>>
    typename std::enable_if<internal::HasLinear<TransformT>::value && internal::HasTranslation<TransformT>::value,void>::type
    resampleTransforms(const TransformSet<TransformT> &old_transforms,
                       const NeighborhoodSetT &new_to_old_map,
                       TransformSet<TransformT> &new_transforms,
                       const WeightEvaluatorT &weight_evaluator = WeightEvaluatorT())
    {
        new_transforms.resize(new_to_old_map.size());

#pragma omp parallel for shared (new_transforms)
        for (size_t i = 0; i < new_transforms.size(); i++) {
            typename TransformT::Scalar total_weight = (typename TransformT::Scalar)0.0;
            new_transforms[i].linear().setZero();
            new_transforms[i].translation().setZero();
            for (size_t j = 0; j < new_to_old_map[i].size(); j++) {
                const typename TransformT::Scalar weight = weight_evaluator(i, new_to_old_map[i][j].index, new_to_old_map[i][j].value);
                total_weight += weight;
                new_transforms[i].linear().noalias() += weight*old_transforms[new_to_old_map[i][j].index].linear();
                new_transforms[i].translation().noalias() += weight*old_transforms[new_to_old_map[i][j].index].translation();
            }

            if (total_weight == (typename TransformT::Scalar)0.0) {
                new_transforms[i].setIdentity();
            } else {
                total_weight = (typename TransformT::Scalar)(1.0)/total_weight;
                new_transforms[i].linear() *= total_weight;
                if (int(TransformT::Mode) == int(Eigen::Isometry)) {
                    new_transforms[i].linear() = new_transforms[i].rotation();
                }
                new_transforms[i].translation() *= total_weight;
            }
        }
    }

    template <class TransformT, class NeighborhoodSetT, class WeightEvaluatorT = UnityWeightEvaluator<typename TransformT::Scalar,typename TransformT::Scalar>>
    inline TransformSet<TransformT> resampleTransforms(const TransformSet<TransformT> &old_transforms,
                                                       const NeighborhoodSetT &new_to_old_map,
                                                       const WeightEvaluatorT &weight_evaluator = WeightEvaluatorT())
    {
        TransformSet<TransformT> new_transforms;
        resampleTransforms<TransformT,NeighborhoodSetT,WeightEvaluatorT>(old_transforms, new_to_old_map, new_transforms, weight_evaluator);
        return new_transforms;
    }

    template <class TransformT, class KDTreeT, class NeighborhoodSpecT, class WeightEvaluatorT = UnityWeightEvaluator<typename TransformT::Scalar,typename TransformT::Scalar>>
    typename std::enable_if<internal::HasLinear<TransformT>::value && internal::HasTranslation<TransformT>::value,void>::type
    resampleTransforms(const KDTreeT &old_support_kd_tree,
                       const TransformSet<TransformT> &old_transforms,
                       const ConstVectorSetMatrixMap<typename TransformT::Scalar,TransformT::Dim> &new_support,
                       const NeighborhoodSpecT &nh,
                       TransformSet<TransformT> &new_transforms,
                       const WeightEvaluatorT &weight_evaluator = WeightEvaluatorT())
    {
        new_transforms.resize(new_support.cols());

#pragma omp parallel for shared (new_transforms)
        for (size_t i = 0; i < new_transforms.size(); i++) {
            auto nn = old_support_kd_tree.search(new_support.col(i), nh);
            typename TransformT::Scalar total_weight = (typename TransformT::Scalar)0.0;
            new_transforms[i].linear().setZero();
            new_transforms[i].translation().setZero();
            for (size_t j = 0; j < nn.size(); j++) {
                const typename TransformT::Scalar weight = weight_evaluator(i, nn[j].index, nn[j].value);
                total_weight += weight;
                new_transforms[i].linear().noalias() += weight*old_transforms[nn[j].index].linear();
                new_transforms[i].translation().noalias() += weight*old_transforms[nn[j].index].translation();
            }

            if (total_weight == (typename TransformT::Scalar)0.0) {
                new_transforms[i].setIdentity();
            } else {
                total_weight = (typename TransformT::Scalar)(1.0)/total_weight;
                new_transforms[i].linear() *= total_weight;
                if (int(TransformT::Mode) == int(Eigen::Isometry)) {
                    new_transforms[i].linear() = new_transforms[i].rotation();
                }
                new_transforms[i].translation() *= total_weight;
            }
        }
    }

    template <class TransformT, class KDTreeT, class NeighborhoodSpecT, class WeightEvaluatorT = UnityWeightEvaluator<typename TransformT::Scalar,typename TransformT::Scalar>>
    inline TransformSet<TransformT> resampleTransforms(const KDTreeT &old_support_kd_tree,
                                                       const TransformSet<TransformT> &old_transforms,
                                                       const ConstVectorSetMatrixMap<typename TransformT::Scalar,TransformT::Dim> &new_support,
                                                       const NeighborhoodSpecT &nh,
                                                       const WeightEvaluatorT &weight_evaluator = WeightEvaluatorT())
    {
        TransformSet<TransformT> new_transforms;
        resampleTransforms<TransformT,KDTreeT,NeighborhoodSpecT,WeightEvaluatorT>(old_support_kd_tree, old_transforms, new_support, nh, new_transforms, weight_evaluator);
        return new_transforms;
    }
}
<|endoftext|>