<commit_before>/*
 * KVH 1750 IMU
 * Eric L. Hahn <erichahn@vt.edu>
 * 12/5/2014
 * Copyright 2014. All Rights Reserved.
 */
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wshadow"
#include <ros/ros.h>
#include <tf/tf.h>
#pragma GCC diagnostic pop

#include "kvh1750/tov_file.h"
#include <trooper_mlc_msgs/CachedRawIMUData.h>
#include <sensor_msgs/Temperature.h>
#include <sensor_msgs/Imu.h>

#include <sched.h>

namespace
{
  const std::string DefaultImuLink = "torso";
  const std::string DefaultAddress = "/dev/ttyS4";
  const size_t ImuCacheSize = 15;
  int Rate;
  bool IsDA = true;
  double Ahrs_gyro_x = 0;
  double Ahrs_gyro_y = 0;
  double Ahrs_gyro_z = 0;
  double Prev_stamp = 0;
  size_t CachedMsgCounter = 0;
}

/**
 * Converts KVH1750Message into the standard ROS messages corresponding
 * to the same set of data, namely an Imu and Temperature message.
 */
void to_ros(const kvh::Message& msg, sensor_msgs::Imu& imu,
  sensor_msgs::Temperature& temp)
{
  msg.time(imu.header.stamp.sec, imu.header.stamp.nsec);

  imu.angular_velocity.x = msg.gyro_x();
  imu.angular_velocity.y = msg.gyro_y();
  imu.angular_velocity.z = msg.gyro_z();
  imu.linear_acceleration.x = msg.accel_x();
  imu.linear_acceleration.y = msg.accel_y();
  imu.linear_acceleration.z = msg.accel_z();

  //scale for ROS if delta angles are enabled
  if(IsDA)
  {
    Ahrs_gyro_x += msg.gyro_x();
    Ahrs_gyro_y += msg.gyro_y();
    Ahrs_gyro_z += msg.gyro_z();

    imu.angular_velocity.x *= Rate;
    imu.angular_velocity.y *= Rate;
    imu.angular_velocity.z *= Rate;
  }
  else
  {
    double current_stamp = imu.header.stamp.sec + imu.header.stamp.nsec * 1E-9;
    double deltatime;
    if (Prev_stamp)
    {
      deltatime = current_stamp - Prev_stamp;
    }
    else
    {
      deltatime = 1/Rate;
    }
    Ahrs_gyro_x += msg.gyro_x()*deltatime;
    Ahrs_gyro_y += msg.gyro_y()*deltatime;
    Ahrs_gyro_z += msg.gyro_z()*deltatime;
    Prev_stamp = current_stamp;
  }

  imu.orientation = tf::createQuaternionMsgFromRollPitchYaw(Ahrs_gyro_x,
    Ahrs_gyro_y, Ahrs_gyro_z);
  temp.header.stamp = imu.header.stamp;
  temp.temperature = msg.temp();
}

/**
 * Adds a single IMU reading to the cached value. If the cache is full, this
 * resets the counter and returns true.
 */
bool cache_imu(const kvh::Message& msg, trooper_mlc_msgs::CachedRawIMUData& cache,
  size_t& counter)
{
  if(counter >= ImuCacheSize)
  {
    counter = 0;
  }

  trooper_mlc_msgs::RawIMUData& imu = cache.data[counter];
  uint32_t secs = 0;
  uint32_t nsecs = 0;
  msg.time(secs, nsecs);
  imu.imu_timestamp = static_cast<uint64_t>(secs * 1.0E6) +
    static_cast<uint64_t>(nsecs * 1.0E-3);
  imu.packet_count = CachedMsgCounter++;
  imu.dax = msg.gyro_x();
  imu.day = msg.gyro_y();
  imu.daz = msg.gyro_z();
  imu.ddx = msg.accel_x();
  imu.ddy = msg.accel_y();
  imu.ddz = msg.accel_z();

  //if the pre-increment sets it to 15, will be set to 0 and return true
  return (++counter % ImuCacheSize) == 0;
}

int main(int argc, char **argv)
{
  //Name of node
  ros::init(argc, argv, "kvh_1750_imu");
  //Node handle
  ros::NodeHandle nh("~");
  ros::Publisher imu_pub = nh.advertise<sensor_msgs::Imu>("imu", 1);
  ros::Publisher temp_pub = nh.advertise<sensor_msgs::Temperature>("temp", 1);
  ros::Publisher cache_pub = nh.advertise<trooper_mlc_msgs::CachedRawIMUData>("cached", 1);
  std::string imu_link_name = DefaultImuLink;
  nh.getParam("link_name", imu_link_name);

  nh.param("rate", Rate, 100);

  bool use_delta_angles = true;

  nh.getParam("use_delta_angles", use_delta_angles);

  size_t cache_counter = 0;
  trooper_mlc_msgs::CachedRawIMUData cached_imu;
  sensor_msgs::Imu current_imu;
  sensor_msgs::Temperature current_temp;

  int priority = 99;
  bool use_rt = true;

  nh.getParam("priority", priority);
  nh.getParam("use_rt", use_rt);

  int policy = (use_rt ? SCHED_RR : SCHED_OTHER);

  priority = std::min(sched_get_priority_max(policy),
    std::max(sched_get_priority_min(policy), priority));

  struct sched_param params;
  params.sched_priority = (use_rt ? static_cast<int>(priority) : 0);

  int rc = sched_setscheduler(0, policy, &params);
  if(rc != 0)
  {
    ROS_ERROR("Setting schedule priority produced error: \"%s\"", strerror(errno));
    return 1;
  }

  std::vector<double> ahrs_cov;
  std::vector<double> ang_cov;
  std::vector<double> lin_cov;

  nh.param<std::vector<double>>("orientation_covariance", ahrs_cov, {1, 0, 0, 0, 1, 0, 0, 0, 1});
  std::copy(ahrs_cov.begin(), ahrs_cov.end(),
    current_imu.orientation_covariance.begin());

  if(nh.getParam("angular_covariance", ang_cov))
  {
    std::copy(ang_cov.begin(), ang_cov.end(),
      current_imu.angular_velocity_covariance.begin());
  }
  else
  {
    current_imu.angular_velocity_covariance[0] = 1;
    current_imu.angular_velocity_covariance[4] = 1;
    current_imu.angular_velocity_covariance[8] = 1;
  }

  if(nh.getParam("linear_covariance", lin_cov))
  {
    std::copy(lin_cov.begin(), lin_cov.end(),
      current_imu.linear_acceleration_covariance.begin());
  }
  else
  {
    current_imu.linear_acceleration_covariance[0] = 1;
    current_imu.linear_acceleration_covariance[4] = 1;
    current_imu.linear_acceleration_covariance[8] = 1;
  }

  //IMU link locations
  current_temp.header.frame_id = imu_link_name;
  current_imu.header.frame_id = imu_link_name;
  cached_imu.header.frame_id = imu_link_name;

  std::string addr = DefaultAddress;
  nh.getParam("address", addr);

  std::string tov_addr = "";
  nh.getParam("tov_address", tov_addr);

  uint32_t baud = 921600;
  int read_baud; //Because rosparam can't provide unsigned ints
  nh.getParam("baudrate", read_baud);
  baud = static_cast<uint32_t>(read_baud);

  int max_temp = kvh::MaxTemp_C;

  nh.getParam("max_temp", max_temp);

  uint32_t wait = 100;
  std::shared_ptr<kvh::IOModule> mod(new kvh::TOVFile(addr, baud, wait,
    tov_addr));
  kvh::IMU1750 imu(mod);

  imu.set_temp_limit(max_temp);
  if(!imu.set_angle_units(use_delta_angles))
  {
    ROS_ERROR("Could not set angle units.");
  }
  if(Rate > 0)
  {
    if(!imu.set_data_rate(Rate))
    {
      ROS_ERROR("Could not set data rate to %d", Rate);
    }
  }

  imu.query_data_rate(Rate);
  imu.query_angle_units(IsDA);

  bool keep_reading = true;
  while(ros::ok() && keep_reading)
  {
    kvh::Message msg;
    switch(imu.read(msg))
    {
      case kvh::IMU1750::VALID:
        to_ros(msg, current_imu, current_temp);
        if(cache_imu(msg, cached_imu, cache_counter))
        {
          msg.time(cached_imu.header.stamp.sec, cached_imu.header.stamp.nsec);
          cache_pub.publish(cached_imu);
        }
        imu_pub.publish(current_imu);
        temp_pub.publish(current_temp);
        break;
      case kvh::IMU1750::BAD_READ:
      case kvh::IMU1750::BAD_CRC:
        ROS_ERROR("Bad data from KVH, ignoring.");
        break;
      case kvh::IMU1750::FATAL_ERROR:
        ROS_FATAL("Lost connection to IMU!"); //should reconnect
        keep_reading = false;
        break;
      case kvh::IMU1750::OVER_TEMP:
        ROS_FATAL("IMU is overheating!");
        keep_reading = false;
        break;
      case kvh::IMU1750::PARTIAL_READ:
      default:
      break;
    }
    ros::spinOnce();
  }

  return 0;
}
<commit_msg>Apparently batch message is a LIFO sliding buffer of 15 elements.<commit_after>/*
 * KVH 1750 IMU
 * Eric L. Hahn <erichahn@vt.edu>
 * 12/5/2014
 * Copyright 2014. All Rights Reserved.
 */
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wshadow"
#include <ros/ros.h>
#include <tf/tf.h>
#pragma GCC diagnostic pop

#include "kvh1750/tov_file.h"
#include <trooper_mlc_msgs/CachedRawIMUData.h>
#include <sensor_msgs/Temperature.h>
#include <sensor_msgs/Imu.h>
#include <boost/circular_buffer.hpp>
#include <sched.h>

namespace
{
  const std::string DefaultImuLink = "torso";
  const std::string DefaultAddress = "/dev/ttyS4";
  const size_t ImuCacheSize = 15;
  int Rate;
  bool IsDA = true;
  double Ahrs_gyro_x = 0;
  double Ahrs_gyro_y = 0;
  double Ahrs_gyro_z = 0;
  double Prev_stamp = 0;
  size_t CachedMsgCounter = 0;
  boost::circular_buffer<trooper_mlc_msgs::RawIMUData> ImuCache(ImuCacheSize);
}

/**
 * Converts KVH1750Message into the standard ROS messages corresponding
 * to the same set of data, namely an Imu and Temperature message.
 */
void to_ros(const kvh::Message& msg, sensor_msgs::Imu& imu,
  sensor_msgs::Temperature& temp)
{
  msg.time(imu.header.stamp.sec, imu.header.stamp.nsec);

  imu.angular_velocity.x = msg.gyro_x();
  imu.angular_velocity.y = msg.gyro_y();
  imu.angular_velocity.z = msg.gyro_z();
  imu.linear_acceleration.x = msg.accel_x();
  imu.linear_acceleration.y = msg.accel_y();
  imu.linear_acceleration.z = msg.accel_z();

  //scale for ROS if delta angles are enabled
  if(IsDA)
  {
    Ahrs_gyro_x += msg.gyro_x();
    Ahrs_gyro_y += msg.gyro_y();
    Ahrs_gyro_z += msg.gyro_z();

    imu.angular_velocity.x *= Rate;
    imu.angular_velocity.y *= Rate;
    imu.angular_velocity.z *= Rate;
  }
  else
  {
    double current_stamp = imu.header.stamp.sec + imu.header.stamp.nsec * 1E-9;
    double deltatime;
    if (Prev_stamp)
    {
      deltatime = current_stamp - Prev_stamp;
    }
    else
    {
      deltatime = 1/Rate;
    }
    Ahrs_gyro_x += msg.gyro_x()*deltatime;
    Ahrs_gyro_y += msg.gyro_y()*deltatime;
    Ahrs_gyro_z += msg.gyro_z()*deltatime;
    Prev_stamp = current_stamp;
  }

  imu.orientation = tf::createQuaternionMsgFromRollPitchYaw(Ahrs_gyro_x,
    Ahrs_gyro_y, Ahrs_gyro_z);
  temp.header.stamp = imu.header.stamp;
  temp.temperature = msg.temp();
}

/**
 * Adds a single IMU reading to the cached value. If the cache is full, this
 * resets the counter and returns true.
 */
void cache_imu(const kvh::Message& msg)
{
  trooper_mlc_msgs::RawIMUData imu;
  uint32_t secs = 0;
  uint32_t nsecs = 0;
  msg.time(secs, nsecs);
  imu.imu_timestamp = static_cast<uint64_t>(secs * 1.0E6) +
    static_cast<uint64_t>(nsecs * 1.0E-3);
  imu.packet_count = CachedMsgCounter++;
  imu.dax = msg.gyro_x();
  imu.day = msg.gyro_y();
  imu.daz = msg.gyro_z();
  imu.ddx = msg.accel_x();
  imu.ddy = msg.accel_y();
  imu.ddz = msg.accel_z();

  ImuCache.push_back(imu);
}

int main(int argc, char **argv)
{
  //Name of node
  ros::init(argc, argv, "kvh_1750_imu");
  //Node handle
  ros::NodeHandle nh("~");
  ros::Publisher imu_pub = nh.advertise<sensor_msgs::Imu>("imu", 1);
  ros::Publisher temp_pub = nh.advertise<sensor_msgs::Temperature>("temp", 1);
  ros::Publisher cache_pub = nh.advertise<trooper_mlc_msgs::CachedRawIMUData>("cached", 1);
  std::string imu_link_name = DefaultImuLink;
  nh.getParam("link_name", imu_link_name);

  nh.param("rate", Rate, 100);

  bool use_delta_angles = true;

  nh.getParam("use_delta_angles", use_delta_angles);

  trooper_mlc_msgs::CachedRawIMUData cached_imu;
  sensor_msgs::Imu current_imu;
  sensor_msgs::Temperature current_temp;

  int priority = 99;
  bool use_rt = true;

  nh.getParam("priority", priority);
  nh.getParam("use_rt", use_rt);

  int policy = (use_rt ? SCHED_RR : SCHED_OTHER);

  priority = std::min(sched_get_priority_max(policy),
    std::max(sched_get_priority_min(policy), priority));

  struct sched_param params;
  params.sched_priority = (use_rt ? static_cast<int>(priority) : 0);

  int rc = sched_setscheduler(0, policy, &params);
  if(rc != 0)
  {
    ROS_ERROR("Setting schedule priority produced error: \"%s\"", strerror(errno));
    return 1;
  }

  std::vector<double> ahrs_cov;
  std::vector<double> ang_cov;
  std::vector<double> lin_cov;

  nh.param<std::vector<double>>("orientation_covariance",
    ahrs_cov, {1, 0, 0, 0, 1, 0, 0, 0, 1});
  std::copy(ahrs_cov.begin(), ahrs_cov.end(),
    current_imu.orientation_covariance.begin());

  if(nh.getParam("angular_covariance", ang_cov))
  {
    std::copy(ang_cov.begin(), ang_cov.end(),
      current_imu.angular_velocity_covariance.begin());
  }
  else
  {
    current_imu.angular_velocity_covariance[0] = 1;
    current_imu.angular_velocity_covariance[4] = 1;
    current_imu.angular_velocity_covariance[8] = 1;
  }

  if(nh.getParam("linear_covariance", lin_cov))
  {
    std::copy(lin_cov.begin(), lin_cov.end(),
      current_imu.linear_acceleration_covariance.begin());
  }
  else
  {
    current_imu.linear_acceleration_covariance[0] = 1;
    current_imu.linear_acceleration_covariance[4] = 1;
    current_imu.linear_acceleration_covariance[8] = 1;
  }

  //IMU link locations
  current_temp.header.frame_id = imu_link_name;
  current_imu.header.frame_id = imu_link_name;
  cached_imu.header.frame_id = imu_link_name;

  std::string addr = DefaultAddress;
  nh.getParam("address", addr);

  std::string tov_addr = "";
  nh.getParam("tov_address", tov_addr);

  uint32_t baud = 921600;
  int read_baud; //Because rosparam can't provide unsigned ints
  nh.getParam("baudrate", read_baud);
  baud = static_cast<uint32_t>(read_baud);

  int max_temp = kvh::MaxTemp_C;

  nh.getParam("max_temp", max_temp);

  uint32_t wait = 100;
  std::shared_ptr<kvh::IOModule> mod(new kvh::TOVFile(addr, baud, wait,
    tov_addr));
  kvh::IMU1750 imu(mod);

  imu.set_temp_limit(max_temp);
  if(!imu.set_angle_units(use_delta_angles))
  {
    ROS_ERROR("Could not set angle units.");
  }
  if(Rate > 0)
  {
    if(!imu.set_data_rate(Rate))
    {
      ROS_ERROR("Could not set data rate to %d", Rate);
    }
  }

  imu.query_data_rate(Rate);
  imu.query_angle_units(IsDA);

  bool keep_reading = true;
  while(ros::ok() && keep_reading)
  {
    kvh::Message msg;
    switch(imu.read(msg))
    {
      case kvh::IMU1750::VALID:
        to_ros(msg, current_imu, current_temp);
        cache_imu(msg);
        if(CachedMsgCounter >= ImuCacheSize)
        {
          msg.time(cached_imu.header.stamp.sec, cached_imu.header.stamp.nsec);
          std::reverse_copy(ImuCache.begin(), ImuCache.end(),
            cached_imu.data.begin());
          cache_pub.publish(cached_imu);
        }
        imu_pub.publish(current_imu);
        temp_pub.publish(current_temp);
        break;
      case kvh::IMU1750::BAD_READ:
      case kvh::IMU1750::BAD_CRC:
        ROS_ERROR("Bad data from KVH, ignoring.");
        break;
      case kvh::IMU1750::FATAL_ERROR:
        ROS_FATAL("Lost connection to IMU!"); //should reconnect
        keep_reading = false;
        break;
      case kvh::IMU1750::OVER_TEMP:
        ROS_FATAL("IMU is overheating!");
        keep_reading = false;
        break;
      case kvh::IMU1750::PARTIAL_READ:
      default:
      break;
    }
    ros::spinOnce();
  }

  return 0;
}
<|endoftext|>


<commit_before>// Copyright (c) 2009-2010 Satoshi Nakamoto
// Copyright (c) 2009-2014 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include "chain.h"

using namespace std;

/**
 * CChain implementation
 */
void CChain::SetTip(CBlockIndex *pindex) {
    if (pindex == NULL) {
        vChain.clear();
        return;
    }
    vChain.resize(pindex->nHeight + 1);
    while (pindex && vChain[pindex->nHeight] != pindex) {
        vChain[pindex->nHeight] = pindex;
        pindex = pindex->pprev;
    }
}

CBlockLocator CChain::GetLocator(const CBlockIndex *pindex) const {
    int nStep = 1;
    std::vector<uint256> vHave;
    vHave.reserve(32);

    if (!pindex)
        pindex = Tip();
    while (pindex) {
        vHave.push_back(pindex->GetBlockHash());
        // Stop when we have added the genesis block.
        if (pindex->nHeight == 0)
            break;
        // Exponentially larger steps back, plus the genesis block.
        int nHeight = std::max(pindex->nHeight - nStep, 0);
        if (Contains(pindex)) {
            // Use O(1) CChain index if possible.
            pindex = (*this)[nHeight];
        } else {
            // Otherwise, use O(log n) skiplist.
            pindex = pindex->GetAncestor(nHeight);
        }
        if (vHave.size() > 10)
            nStep *= 2;
    }

    return CBlockLocator(vHave);
}

const CBlockIndex *CChain::FindFork(const CBlockIndex *pindex) const {
    if (pindex->nHeight > Height())
        pindex = pindex->GetAncestor(Height());
    while (pindex && !Contains(pindex))
        pindex = pindex->pprev;
    return pindex;
}

/** Turn the lowest '1' bit in the binary representation of a number into a '0'. */
int static inline InvertLowestOne(int n) { return n & (n - 1); }

/** Compute what height to jump back to with the CBlockIndex::pskip pointer. */
int static inline GetSkipHeight(int height) {
    if (height < 2)
        return 0;

    // Determine which height to jump back to. Any number strictly lower than height is acceptable,
    // but the following expression seems to perform well in simulations (max 110 steps to go back
    // up to 2**18 blocks).
    return (height & 1) ? InvertLowestOne(InvertLowestOne(height - 1)) + 1 : InvertLowestOne(height);
}

CBlockIndex* CBlockIndex::GetAncestor(int height)
{
    if (height > nHeight || height < 0)
        return NULL;

    CBlockIndex* pindexWalk = this;
    int heightWalk = nHeight;
    while (heightWalk > height) {
        int heightSkip = GetSkipHeight(heightWalk);
        int heightSkipPrev = GetSkipHeight(heightWalk - 1);
        if (heightSkip == height ||
            (heightSkip > height && !(heightSkipPrev < heightSkip - 2 &&
                                      heightSkipPrev >= height))) {
            // Only follow pskip if pprev->pskip isn't better than pskip->pprev.
            pindexWalk = pindexWalk->pskip;
            heightWalk = heightSkip;
        } else {
            pindexWalk = pindexWalk->pprev;
            heightWalk--;
        }
    }
    return pindexWalk;
}

const CBlockIndex* CBlockIndex::GetAncestor(int height) const
{
    return const_cast<CBlockIndex*>(this)->GetAncestor(height);
}

void CBlockIndex::BuildSkip()
{
    if (pprev)
        pskip = pprev->GetAncestor(GetSkipHeight(nHeight));
}
<commit_msg>[UNIFYING][CORE]Start re-implementing AUXPOW function<commit_after>// Copyright (c) 2009-2010 Satoshi Nakamoto
// Copyright (c) 2009-2014 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include "chain.h"
#include "auxpow.h"
#include "txdb.h"

using namespace std;

/**
 * CChain implementation
 */
void CChain::SetTip(CBlockIndex *pindex) {
    if (pindex == NULL) {
        vChain.clear();
        return;
    }
    vChain.resize(pindex->nHeight + 1);
    while (pindex && vChain[pindex->nHeight] != pindex) {
        vChain[pindex->nHeight] = pindex;
        pindex = pindex->pprev;
    }
}

CBlockLocator CChain::GetLocator(const CBlockIndex *pindex) const {
    int nStep = 1;
    std::vector<uint256> vHave;
    vHave.reserve(32);

    if (!pindex)
        pindex = Tip();
    while (pindex) {
        vHave.push_back(pindex->GetBlockHash());
        // Stop when we have added the genesis block.
        if (pindex->nHeight == 0)
            break;
        // Exponentially larger steps back, plus the genesis block.
        int nHeight = std::max(pindex->nHeight - nStep, 0);
        if (Contains(pindex)) {
            // Use O(1) CChain index if possible.
            pindex = (*this)[nHeight];
        } else {
            // Otherwise, use O(log n) skiplist.
            pindex = pindex->GetAncestor(nHeight);
        }
        if (vHave.size() > 10)
            nStep *= 2;
    }

    return CBlockLocator(vHave);
}

const CBlockIndex *CChain::FindFork(const CBlockIndex *pindex) const {
    if (pindex->nHeight > Height())
        pindex = pindex->GetAncestor(Height());
    while (pindex && !Contains(pindex))
        pindex = pindex->pprev;
    return pindex;
}

std::string CDiskBlockIndex::ToString() const
{
    std::string str = "CDiskBlockIndex(";
    str += CBlockIndex::ToString();
    str += strprintf("\n                hashBlock=%s, hashPrev=%s, hashParentBlock=%s)",
        GetBlockHash().ToString(),
        hashPrev.ToString(),
        (auxpow.get() != NULL) ? auxpow->GetParentBlockHash().ToString() : "-");
    return str;
}

CBlockHeader CBlockIndex::GetBlockHeader(const std::map<uint256, boost::shared_ptr<CAuxPow> >& mapDirtyAuxPow) const
{
    CBlockHeader block;

    if (nVersion & BLOCK_VERSION_AUXPOW) {
        bool foundInDirty = false;
        {
            LOCK(cs_main);
            std::map<uint256, boost::shared_ptr<CAuxPow> >::const_iterator it = mapDirtyAuxPow.find(*phashBlock);
            if (it != mapDirtyAuxPow.end()) {
                block.auxpow = it->second;
                foundInDirty = true;
            }
        }
        if (!foundInDirty) {
            CDiskBlockIndex diskblockindex;
            // auxpow is not in memory, load CDiskBlockHeader
            // from database to get it

            pblocktree->ReadDiskBlockIndex(*phashBlock, diskblockindex);
            block.auxpow = diskblockindex.auxpow;
        }
    }

    block.nVersion       = nVersion;
    if (pprev)
        block.hashPrevBlock = pprev->GetBlockHash();
    block.hashMerkleRoot = hashMerkleRoot;
    block.nTime          = nTime;
    block.nBits          = nBits;
    block.nNonce         = nNonce;
    return block;
}

/** Turn the lowest '1' bit in the binary representation of a number into a '0'. */
int static inline InvertLowestOne(int n) { return n & (n - 1); }

/** Compute what height to jump back to with the CBlockIndex::pskip pointer. */
int static inline GetSkipHeight(int height) {
    if (height < 2)
        return 0;

    // Determine which height to jump back to. Any number strictly lower than height is acceptable,
    // but the following expression seems to perform well in simulations (max 110 steps to go back
    // up to 2**18 blocks).
    return (height & 1) ? InvertLowestOne(InvertLowestOne(height - 1)) + 1 : InvertLowestOne(height);
}

CBlockIndex* CBlockIndex::GetAncestor(int height)
{
    if (height > nHeight || height < 0)
        return NULL;

    CBlockIndex* pindexWalk = this;
    int heightWalk = nHeight;
    while (heightWalk > height) {
        int heightSkip = GetSkipHeight(heightWalk);
        int heightSkipPrev = GetSkipHeight(heightWalk - 1);
        if (heightSkip == height ||
            (heightSkip > height && !(heightSkipPrev < heightSkip - 2 &&
                                      heightSkipPrev >= height))) {
            // Only follow pskip if pprev->pskip isn't better than pskip->pprev.
            pindexWalk = pindexWalk->pskip;
            heightWalk = heightSkip;
        } else {
            pindexWalk = pindexWalk->pprev;
            heightWalk--;
        }
    }
    return pindexWalk;
}

const CBlockIndex* CBlockIndex::GetAncestor(int height) const
{
    return const_cast<CBlockIndex*>(this)->GetAncestor(height);
}

void CBlockIndex::BuildSkip()
{
    if (pprev)
        pskip = pprev->GetAncestor(GetSkipHeight(nHeight));
}
<|endoftext|>


<commit_before>#include "formulation/cfem_diffusion_stamper.h"
#include "cfem_diffusion_stamper.h"

namespace bart {

namespace formulation {

template<int dim>
CFEM_DiffusionStamper<dim>::CFEM_DiffusionStamper(
    std::unique_ptr<formulation::scalar::CFEM_DiffusionI<dim>> diffusion_ptr,
    std::unique_ptr<domain::DefinitionI<dim>> definition_ptr)
      : diffusion_ptr_(std::move(diffusion_ptr)),
        definition_ptr_(std::move(definition_ptr)) {

  cells_ = definition_ptr_->Cells();
  diffusion_init_token_ = diffusion_ptr_->Precalculate(cells_[0]);
}

template<int dim>
void CFEM_DiffusionStamper<dim>::StampStreamingTerm(MPISparseMatrix &to_stamp,
                                                    GroupNumber group) {

  auto streaming_function =
      [&](dealii::FullMatrix<double>& matrix,
          const Cell& cell_ptr) -> void
  {
    this->diffusion_ptr_->FillCellStreamingTerm(matrix,
                                                this->diffusion_init_token_,
                                                cell_ptr,
                                                group);
  };
  StampMatrix(to_stamp, streaming_function);
}

template<int dim>
void CFEM_DiffusionStamper<dim>::StampCollisionTerm(MPISparseMatrix &to_stamp,
                                                    GroupNumber group) {

  auto collision_function =
      [&](dealii::FullMatrix<double>& matrix,
          const Cell& cell_ptr) -> void
  {
    this->diffusion_ptr_->FillCellCollisionTerm(matrix,
                                                this->diffusion_init_token_,
                                                cell_ptr,
                                                group);
  };

  StampMatrix(to_stamp, collision_function);
}

template <int dim>
void CFEM_DiffusionStamper<dim>::StampMatrix(
    MPISparseMatrix &to_stamp,
    std::function<void(dealii::FullMatrix<double>&, const Cell&)> function) {

  auto cell_matrix = definition_ptr_->GetCellMatrix();
  std::vector<dealii::types::global_dof_index> local_dof_indices(cell_matrix.n_cols());

  for (const auto& cell : cells_) {
    cell->get_dof_indices(local_dof_indices);
    function(cell_matrix, cell);
    to_stamp.add(local_dof_indices, local_dof_indices, cell_matrix);
  }
  to_stamp.compress(dealii::VectorOperation::add);
}

template class CFEM_DiffusionStamper<1>;
template class CFEM_DiffusionStamper<2>;
template class CFEM_DiffusionStamper<3>;

} // namespace formulation

} // namespace bart<commit_msg>fixed whitespace in CFEM_DiffusionStamper, added zeroing out of cell_matrix<commit_after>#include "formulation/cfem_diffusion_stamper.h"
#include "cfem_diffusion_stamper.h"

namespace bart {

namespace formulation {

template<int dim>
CFEM_DiffusionStamper<dim>::CFEM_DiffusionStamper(
    std::unique_ptr<formulation::scalar::CFEM_DiffusionI<dim>> diffusion_ptr,
    std::unique_ptr<domain::DefinitionI<dim>> definition_ptr)
      : diffusion_ptr_(std::move(diffusion_ptr)),
        definition_ptr_(std::move(definition_ptr)) {

  cells_ = definition_ptr_->Cells();
  diffusion_init_token_ = diffusion_ptr_->Precalculate(cells_[0]);
}

template<int dim>
void CFEM_DiffusionStamper<dim>::StampStreamingTerm(MPISparseMatrix &to_stamp,
                                                    GroupNumber group) {

  auto streaming_function =
      [&](dealii::FullMatrix<double>& matrix,
          const Cell& cell_ptr) -> void
      {
        this->diffusion_ptr_->FillCellStreamingTerm(matrix,
                                                    this->diffusion_init_token_,
                                                    cell_ptr,
                                                    group);
      };

  StampMatrix(to_stamp, streaming_function);
}

template<int dim>
void CFEM_DiffusionStamper<dim>::StampCollisionTerm(MPISparseMatrix &to_stamp,
                                                    GroupNumber group) {

  auto collision_function =
      [&](dealii::FullMatrix<double>& matrix,
          const Cell& cell_ptr) -> void
      {
        this->diffusion_ptr_->FillCellCollisionTerm(matrix,
                                                    this->diffusion_init_token_,
                                                    cell_ptr,
                                                    group);
      };

  StampMatrix(to_stamp, collision_function);
}

template <int dim>
void CFEM_DiffusionStamper<dim>::StampMatrix(
    MPISparseMatrix &to_stamp,
    std::function<void(dealii::FullMatrix<double>&, const Cell&)> function) {

  auto cell_matrix = definition_ptr_->GetCellMatrix();
  std::vector<dealii::types::global_dof_index> local_dof_indices(cell_matrix.n_cols());

  for (const auto& cell : cells_) {
    cell_matrix = 0;
    cell->get_dof_indices(local_dof_indices);
    function(cell_matrix, cell);
    to_stamp.add(local_dof_indices, local_dof_indices, cell_matrix);
  }
  to_stamp.compress(dealii::VectorOperation::add);
}

template class CFEM_DiffusionStamper<1>;
template class CFEM_DiffusionStamper<2>;
template class CFEM_DiffusionStamper<3>;

} // namespace formulation

} // namespace bart<|endoftext|>


<commit_before>#include "nysa.hpp"
#include <stdio.h>

Nysa::Nysa(bool debug) {
  this->debug = debug;
  this->drt = NULL;

  //DRT Settings
  this->num_devices = 0;
  this->version = 0;
}

Nysa::~Nysa(){
  if (this->drt != NULL){
    delete(this->drt);
  }
}

int Nysa::open(){
  return 1;
}
int Nysa::close(){
  return 1;
}

int Nysa::parse_drt(){
  //read the DRT Json File
  this->version = this->drt[0] << 8 | this->drt[1];
}

//Low Level interface (These must be overridden by a subclass
int Nysa::write_periph_data(uint32_t dev_addr, uint32_t addr, uint8_t *buffer, uint32_t size){
  printf ("Error: Calling function that should be subclassed!\n");
  return -1;
}

int Nysa::read_periph_data(uint32_t dev_addr, uint32_t addr, uint8_t *buffer, uint32_t size){
  printf ("Error: Calling function that should be subclassed!\n");
  return -1;
}

int Nysa::write_memory(uint32_t address, uint8_t *buffer, uint32_t size){
  printf ("Error: Calling function that should be subclassed!\n");
  return -1;
}

int Nysa::read_memory(uint32_t address, uint8_t *buffer, uint32_t size){
  printf ("Error: Calling function that should be subclassed!\n");
  return -1;
}

int Nysa::wait_for_interrupts(uint32_t timeout, uint32_t *interrupts){
  printf ("Error: Calling function that should be subclassed!\n");
  return -1;
}

int Nysa::ping(){
  printf ("Error: Calling function that should be subclassed!\n");
  return -1;
}

int Nysa::crash_report(uint32_t *buffer){
  printf ("Error: Calling function that should be subclassed!\n");
  return -1;
}

//Helper Functions
int Nysa::write_register(uint32_t dev_addr, uint32_t reg_addr, uint32_t data){
  //write to only one address in the peripheral address space
  printd("Entered\n");
  uint8_t d[4];
  d[0] = ((data >> 24) & 0xFF);
  d[1] = ((data >> 16) & 0xFF);
  d[2] = ((data >> 8)  & 0xFF);
  d[3] = ( data        & 0xFF);
  return this->write_periph_data(dev_addr, reg_addr, &d[0], 4);
}

int Nysa::read_register(uint32_t dev_addr, uint32_t reg_addr, uint32_t *data){
  //read from only one address in the peripheral address space
  printd("Entered\n");
  uint8_t d[4];
  uint32_t retval;
  retval = this->read_periph_data(dev_addr, reg_addr, &d[0], 4);
  CHECK_NYSA_ERROR("Error Reading Peripheral Data");
  //printf ("%02X %02X %02X %02X\n", d[0], d[1], d[2], d[3]);
  *data = (d[0] << 24 | d[1] << 16 | d[2] << 8 | d[3]);
  return 0;
}

int Nysa::set_register_bit(uint32_t dev_addr, uint32_t reg_addr, uint8_t bit){
  uint32_t reg;
  int retval = 0;
  printd("Entered\n");

  retval = this->read_register(dev_addr, reg_addr, &reg);
  CHECK_NYSA_ERROR("Error Reading Register");

  reg |= 1 << bit;
  retval = this->write_register(dev_addr, reg_addr, reg);
  CHECK_NYSA_ERROR("Error Writing Register");
  return 0;
}

int Nysa::clear_register_bit(uint32_t dev_addr, uint32_t reg_addr, uint8_t bit){
  uint32_t reg;
  int retval = 0;
  printd("Entered\n");
  retval = this->read_register(dev_addr, reg_addr, &reg);
  CHECK_NYSA_ERROR("Error Reading Register");
  reg &= (~(1 << bit));
  retval = this->write_register(dev_addr, reg_addr, reg);
  CHECK_NYSA_ERROR("Error Writing Register");
  return 0;
}

int Nysa::read_register_bit(uint32_t dev_addr, uint32_t reg_addr, uint8_t bit, bool * value){
  uint32_t reg;
  int retval = 0;
  printd("Entered\n");
  retval = this->read_register(dev_addr, reg_addr, &reg);
  CHECK_NYSA_ERROR("Error Reading Register");
  reg &= (1 << bit);
  if (reg > 0){
    *value = true;
  }
  else {
    *value = false;
  }
  return 0;
}

//DRT
int Nysa::pretty_print_drt(){
  return -1;
}

int Nysa::read_drt(){
  uint8_t * buffer = new uint8_t [32];
  uint32_t len = 1 * 32;
  int32_t retval;
  //We don't know the total size of the DRT so only look at the fist Block (32 bytes)
  retval = this->read_periph_data(0, 0, buffer, len);
  if (retval < 0){
    printf ("%s(): Failed to read peripheral data\n", __func__);
    return -1;
  }
  //Found out how many devices are in the DRT
  this->num_devices = buffer[4] << 24 | buffer[5] << 16 | buffer[6] << 8 | buffer[7];
  printf ("There are: %d devices\n", this->num_devices);
  delete(buffer);

  //Calculate the buffer size ( + 1 to read the DRT again)
  len = (this->num_devices + 1) * 32;
  printf ("Length of read: %d\n", len);

  this->drt = new uint8_t [len];
  retval = this->read_periph_data(0, 0, this->drt, len);
  this->parse_drt();
  return 0;
}

int Nysa::get_drt_version(){
  if (this->drt == NULL){
    return -1;
  }
  return this->version;
}

int Nysa::get_drt_device_count(){
  if (this->drt == NULL){
    return -1;
  }
  return this->num_devices;
}
uint32_t Nysa::get_drt_device_type(uint32_t index){
  uint32_t pos = 0;
  uint32_t type;
  if (this->drt == NULL){
    //XXX: Error handling
    return 0;
  }
  if (index == 0){
    //DRT has no type
    //XXX: Error handling
    return 0;
  }
  if (index > this->num_devices){
    //Out of range
    //XXX: Error handling
    return 0;
  }
  //Start of the device in question
  pos = (index) * 32;
  //Go to the start of the type
  type = this->drt[pos] << 24 | this->drt[pos + 1] << 16 | this->drt[pos + 2] << 8| this->drt[pos + 3];
  return type;
}
uint32_t Nysa::get_drt_device_size(uint32_t index){
  uint32_t size = 0;
  uint32_t pos = 0;
  if (this->drt == NULL){
    //XXX: Error handling
    return 0;
  }
  if (index == 0){
    //DRT has no type
    //XXX: Error handling
    return 0;
  }
  if (index > this->num_devices){
    //Out of range
    //XXX: Error handling
    return 0;
  }
  //Start of the device in question
  pos = (index) * 32;
  pos += 12;
  //Go to the start of the type
  size = this->drt[pos] << 24 | this->drt[pos + 1] << 16 | this->drt[pos + 2] << 8 | this->drt[pos + 3];
  return size;
}

uint32_t Nysa::get_drt_device_addr(uint32_t index){
  uint32_t pos = 0;
  uint32_t addr;
  if (this->drt == NULL){
    //XXX: Error handling
    return 0;
  }
  if (index == 0){
    //DRT has no type
    //XXX: Error handling
    return 0;
  }
  if (index > this->num_devices){
    //Out of range
    //XXX: Error handling
    return 0;
  }
  //Start of the device in question
  pos = (index) * 32;
  pos += 8;
  //Go to the start of the type
  addr = this->drt[pos] << 24 | this->drt[pos + 1] << 16 | this->drt[pos + 2] << 8 | this->drt[pos + 3];
  return addr;

}
int Nysa::get_drt_device_flags(uint32_t index, uint16_t *nysa_flags, uint16_t *dev_flags){
  uint32_t pos = 0;
  if (this->drt == NULL){
    return -1;
  }
  if (index == 0){
    //DRT has no type
    return -2;
  }
  if (index > this->num_devices){
    //Out of range
    return -3;
  }
  //Start of the device in question
  pos = (index) * 32;
  pos += 4;
  //Go to the start of the type
  *nysa_flags = (this->drt[pos] << 8)      | (this->drt[pos + 1]);
  *dev_flags  = (this->drt[pos + 2] << 8)  | (this->drt[pos + 3]);

}
bool Nysa::is_memory_device(uint32_t index){
  int retval = 0;
  uint16_t nysa_flags;
  uint16_t dev_flags;
  retval = this->get_drt_device_flags(index, &nysa_flags, &dev_flags);
  if (nysa_flags & 0x01){
    return true;
  }
  return false;
}

int Nysa::pretty_print_crash_report(){
  return -1;
}

<commit_msg>Added function to find a device given the specified type<commit_after>#include "nysa.hpp"
#include <stdio.h>

Nysa::Nysa(bool debug) {
  this->debug = debug;
  this->drt = NULL;

  //DRT Settings
  this->num_devices = 0;
  this->version = 0;
}

Nysa::~Nysa(){
  if (this->drt != NULL){
    delete(this->drt);
  }
}

int Nysa::open(){
  return 1;
}
int Nysa::close(){
  return 1;
}

int Nysa::parse_drt(){
  //read the DRT Json File
  this->version = this->drt[0] << 8 | this->drt[1];
}

//Low Level interface (These must be overridden by a subclass
int Nysa::write_periph_data(uint32_t dev_addr, uint32_t addr, uint8_t *buffer, uint32_t size){
  printf ("Error: Calling function that should be subclassed!\n");
  return -1;
}

int Nysa::read_periph_data(uint32_t dev_addr, uint32_t addr, uint8_t *buffer, uint32_t size){
  printf ("Error: Calling function that should be subclassed!\n");
  return -1;
}

int Nysa::write_memory(uint32_t address, uint8_t *buffer, uint32_t size){
  printf ("Error: Calling function that should be subclassed!\n");
  return -1;
}

int Nysa::read_memory(uint32_t address, uint8_t *buffer, uint32_t size){
  printf ("Error: Calling function that should be subclassed!\n");
  return -1;
}

int Nysa::wait_for_interrupts(uint32_t timeout, uint32_t *interrupts){
  printf ("Error: Calling function that should be subclassed!\n");
  return -1;
}

int Nysa::ping(){
  printf ("Error: Calling function that should be subclassed!\n");
  return -1;
}

int Nysa::crash_report(uint32_t *buffer){
  printf ("Error: Calling function that should be subclassed!\n");
  return -1;
}

//Helper Functions
int Nysa::write_register(uint32_t dev_addr, uint32_t reg_addr, uint32_t data){
  //write to only one address in the peripheral address space
  printd("Entered\n");
  uint8_t d[4];
  d[0] = ((data >> 24) & 0xFF);
  d[1] = ((data >> 16) & 0xFF);
  d[2] = ((data >> 8)  & 0xFF);
  d[3] = ( data        & 0xFF);
  return this->write_periph_data(dev_addr, reg_addr, &d[0], 4);
}

int Nysa::read_register(uint32_t dev_addr, uint32_t reg_addr, uint32_t *data){
  //read from only one address in the peripheral address space
  printd("Entered\n");
  uint8_t d[4];
  uint32_t retval;
  retval = this->read_periph_data(dev_addr, reg_addr, &d[0], 4);
  CHECK_NYSA_ERROR("Error Reading Peripheral Data");
  //printf ("%02X %02X %02X %02X\n", d[0], d[1], d[2], d[3]);
  *data = (d[0] << 24 | d[1] << 16 | d[2] << 8 | d[3]);
  return 0;
}

int Nysa::set_register_bit(uint32_t dev_addr, uint32_t reg_addr, uint8_t bit){
  uint32_t reg;
  int retval = 0;
  printd("Entered\n");

  retval = this->read_register(dev_addr, reg_addr, &reg);
  CHECK_NYSA_ERROR("Error Reading Register");

  reg |= 1 << bit;
  retval = this->write_register(dev_addr, reg_addr, reg);
  CHECK_NYSA_ERROR("Error Writing Register");
  return 0;
}

int Nysa::clear_register_bit(uint32_t dev_addr, uint32_t reg_addr, uint8_t bit){
  uint32_t reg;
  int retval = 0;
  printd("Entered\n");
  retval = this->read_register(dev_addr, reg_addr, &reg);
  CHECK_NYSA_ERROR("Error Reading Register");
  reg &= (~(1 << bit));
  retval = this->write_register(dev_addr, reg_addr, reg);
  CHECK_NYSA_ERROR("Error Writing Register");
  return 0;
}

int Nysa::read_register_bit(uint32_t dev_addr, uint32_t reg_addr, uint8_t bit, bool * value){
  uint32_t reg;
  int retval = 0;
  printd("Entered\n");
  retval = this->read_register(dev_addr, reg_addr, &reg);
  CHECK_NYSA_ERROR("Error Reading Register");
  reg &= (1 << bit);
  if (reg > 0){
    *value = true;
  }
  else {
    *value = false;
  }
  return 0;
}

//DRT
int Nysa::pretty_print_drt(){
  return -1;
}

int Nysa::read_drt(){
  uint8_t * buffer = new uint8_t [32];
  uint32_t len = 1 * 32;
  int32_t retval;
  //We don't know the total size of the DRT so only look at the fist Block (32 bytes)
  retval = this->read_periph_data(0, 0, buffer, len);
  if (retval < 0){
    printf ("%s(): Failed to read peripheral data\n", __func__);
    return -1;
  }
  //Found out how many devices are in the DRT
  this->num_devices = buffer[4] << 24 | buffer[5] << 16 | buffer[6] << 8 | buffer[7];
  printf ("There are: %d devices\n", this->num_devices);
  delete(buffer);

  //Calculate the buffer size ( + 1 to read the DRT again)
  len = (this->num_devices + 1) * 32;
  printf ("Length of read: %d\n", len);

  this->drt = new uint8_t [len];
  retval = this->read_periph_data(0, 0, this->drt, len);
  this->parse_drt();
  return 0;
}

int Nysa::get_drt_version(){
  if (this->drt == NULL){
    return -1;
  }
  return this->version;
}

int Nysa::get_drt_device_count(){
  if (this->drt == NULL){
    return -1;
  }
  return this->num_devices;
}
uint32_t Nysa::get_drt_device_type(uint32_t index){
  uint32_t pos = 0;
  uint32_t type;
  if (this->drt == NULL){
    //XXX: Error handling
    return 0;
  }
  if (index == 0){
    //DRT has no type
    //XXX: Error handling
    return 0;
  }
  if (index > this->num_devices){
    //Out of range
    //XXX: Error handling
    return 0;
  }
  //Start of the device in question
  pos = (index) * 32;
  //Go to the start of the type
  type = this->drt[pos] << 24 | this->drt[pos + 1] << 16 | this->drt[pos + 2] << 8| this->drt[pos + 3];
  return type;
}
uint32_t Nysa::get_drt_device_size(uint32_t index){
  uint32_t size = 0;
  uint32_t pos = 0;
  if (this->drt == NULL){
    //XXX: Error handling
    return 0;
  }
  if (index == 0){
    //DRT has no type
    //XXX: Error handling
    return 0;
  }
  if (index > this->num_devices){
    //Out of range
    //XXX: Error handling
    return 0;
  }
  //Start of the device in question
  pos = (index) * 32;
  pos += 12;
  //Go to the start of the type
  size = this->drt[pos] << 24 | this->drt[pos + 1] << 16 | this->drt[pos + 2] << 8 | this->drt[pos + 3];
  return size;
}

uint32_t Nysa::get_drt_device_addr(uint32_t index){
  uint32_t pos = 0;
  uint32_t addr;
  if (this->drt == NULL){
    //XXX: Error handling
    return 0;
  }
  if (index == 0){
    //DRT has no type
    //XXX: Error handling
    return 0;
  }
  if (index > this->num_devices){
    //Out of range
    //XXX: Error handling
    return 0;
  }
  //Start of the device in question
  pos = (index) * 32;
  pos += 8;
  //Go to the start of the type
  addr = this->drt[pos] << 24 | this->drt[pos + 1] << 16 | this->drt[pos + 2] << 8 | this->drt[pos + 3];
  return addr;

}
int Nysa::get_drt_device_flags(uint32_t index, uint16_t *nysa_flags, uint16_t *dev_flags){
  uint32_t pos = 0;
  if (this->drt == NULL){
    return -1;
  }
  if (index == 0){
    //DRT has no type
    return -2;
  }
  if (index > this->num_devices){
    //Out of range
    return -3;
  }
  //Start of the device in question
  pos = (index) * 32;
  pos += 4;
  //Go to the start of the type
  *nysa_flags = (this->drt[pos] << 8)      | (this->drt[pos + 1]);
  *dev_flags  = (this->drt[pos + 2] << 8)  | (this->drt[pos + 3]);

}
bool Nysa::is_memory_device(uint32_t index){
  int retval = 0;
  uint16_t nysa_flags;
  uint16_t dev_flags;
  retval = this->get_drt_device_flags(index, &nysa_flags, &dev_flags);
  if (nysa_flags & 0x01){
    return true;
  }
  return false;
}

int Nysa::pretty_print_crash_report(){
  return -1;
}

uint32_t Nysa::find_device(uint32_t device_type, uint32_t subtype, uint32_t id){
  for (int i = 1; i  < this->get_drt_device_count() + 1; i ++){
    if (this->get_drt_device_type(i) == device_type){
      if (subtype > 0){
        //User has specified a subtype ID
        //XXX: Not implemented yet
      }
      if (id > 0){
        //User has specified an implimentation specific identification
        //XXX: Not implemented yet
      }
      return i;
    }
  }
  return 0;
}
<|endoftext|>


<commit_before>/*
  Copyright (c) 2012 Stuart Walsh

  Permission is hereby granted, free of charge, to any person
  obtaining a copy of this software and associated documentation
  files (the "Software"), to deal in the Software without
  restriction, including without limitation the rights to use,
  copy, modify, merge, publish, distribute, sublicense, and/or sell
  copies of the Software, and to permit persons to whom the
  Software is furnished to do so, subject to the following
  conditions:

  The above copyright notice and this permission notice shall be
  included in all copies or substantial portions of the Software.

  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
  OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
  HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
  WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  OTHER DEALINGS IN THE SOFTWARE.
*/

#include "stdinc.h"
#include <stdarg.h>
#include <iomanip>
#include <list>
#include "system.h"
#include "client.h"
#include "connection.h"
#include "numeric.h"
#include "server.h"
#include "channel.h"

using std::string;
using std::setw;
using std::setfill;
using std::list;

Event<ClientPtr> Client::connected;
Event<ClientPtr> Client::registering;
Event<ClientPtr> Client::disconnected;
Event<ClientPtr, irc_string> Client::nick_changing;
Event<ClientPtr, string> Client::nick_changed;
list<ClientPtr> Client::unregistered_list;
map<BaseClient *, ClientPtr> Client::client_list;
uv_timer_t Client::ping_timer;

Client::Client() : invisible(false), last_message(time(NULL))
{
}

void Client::add_channel(const ChannelPtr channel)
{
  channels.push_back(channel);
}

void Client::close(const string reason)
{
  BaseClient::close(reason);
  for(auto it = channels.begin(); it != channels.end(); it++)
  {
    ChannelPtr channel = *it;
    channel->remove_member(client_list[this]);
  }
}

void Client::remove_channel(const ChannelPtr channel)
{
  channels.remove(channel);
}

void Client::send(const string arg, int numeric)
{
  stringstream buffer;

  buffer << ":" << Server::get_me()->str() << " ";
  buffer << setw(3) << setfill('0') << numeric;
  buffer << " ";
  if(name.empty())
    buffer << "*";
  else
    buffer << name;

  buffer << " " << arg;

  BaseClient::send(buffer.str());
}

void Client::send(int numeric, ...)
{
  va_list args;

  va_start(args, numeric);

  send(Numeric::format(numeric, args), numeric);

  va_end(args);
}

void Client::send_channels_common(string message)
{
  unordered_map<BaseClient *, ClientPtr> sent_clients;

  for(auto it = channels.begin(); it != channels.end(); it++)
  {
    ChannelPtr channel = *it;
    map<ClientPtr, Membership> members = channel->get_members();

    for(auto mit = members.begin(); mit != members.end(); mit++)
    {
      Membership ms = mit->second;

      if(sent_clients[ms.client.get()])
        continue;

      sent_clients[ms.client.get()] = ms.client;
      ms.client->send(message);
    }
  }
}

irc_string Client::str() const
{
  stringstream buff;

  if(name.empty())
    return "*";

  buff << name << "!" << username << "@" << host;

  return irc_string(buff.str().c_str());
}

bool Client::is_invisible() const
{
  return invisible;
}

string Client::get_username() const
{
  return username;
}

string Client::get_realname() const
{
  return realname;
}

time_t Client::get_idletime() const
{
  return time(NULL) - last_message;
}

void Client::set_invisible(bool invis)
{
  invisible = invis;
}

void Client::set_username(const string user)
{
  username = user;
}

void Client::set_realname(const string real)
{
  realname = real;
}

void Client::set_last_message(time_t when)
{
  last_message = when;
}

// Statics

void Client::init()
{
  uv_timer_init(uv_default_loop(), &ping_timer);
  uv_timer_start(&ping_timer, check_pings, 0, 5);
}

void Client::add(ClientPtr ptr)
{
  shared_ptr<Client> client = dynamic_pointer_cast<Client>(ptr);

  if(!registering(client))
    return;

  client_list[ptr.get()] = ptr;
  client->set_registered();

  unregistered_list.remove(client);

  connected(client);

  client->send(001, client->str().c_str());
  client->send(002, Server::get_me()->str().c_str(), "0.0.1");
  client->send(003, System::get_built_date());
}

void Client::add_unregistered(ClientPtr client)
{
  unregistered_list.push_back(client);
}

void Client::remove(ClientPtr client)
{
  if(client->is_registered())
    client_list.erase(client.get());
  else
    unregistered_list.remove(client);
}

void Client::check_pings(uv_timer_t *handle, int status)
{
  for(auto it = client_list.begin(); it != client_list.end(); it++)
  {
    ClientPtr client = it->second;

    if(!client->check_timeout())
    {
      client->close("Ping Timeout");
    }
  }

  for(auto it = unregistered_list.begin(); it != unregistered_list.end(); it++)
  {
    ClientPtr client = *it;

    if(!client->check_timeout())
    {
      client->close("Registration timed out");
    }
  }
}
<commit_msg>send_channels_common shouldn't send to the sender<commit_after>/*
  Copyright (c) 2012 Stuart Walsh

  Permission is hereby granted, free of charge, to any person
  obtaining a copy of this software and associated documentation
  files (the "Software"), to deal in the Software without
  restriction, including without limitation the rights to use,
  copy, modify, merge, publish, distribute, sublicense, and/or sell
  copies of the Software, and to permit persons to whom the
  Software is furnished to do so, subject to the following
  conditions:

  The above copyright notice and this permission notice shall be
  included in all copies or substantial portions of the Software.

  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
  OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
  HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
  WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  OTHER DEALINGS IN THE SOFTWARE.
*/

#include "stdinc.h"
#include <stdarg.h>
#include <iomanip>
#include <list>
#include "system.h"
#include "client.h"
#include "connection.h"
#include "numeric.h"
#include "server.h"
#include "channel.h"

using std::string;
using std::setw;
using std::setfill;
using std::list;

Event<ClientPtr> Client::connected;
Event<ClientPtr> Client::registering;
Event<ClientPtr> Client::disconnected;
Event<ClientPtr, irc_string> Client::nick_changing;
Event<ClientPtr, string> Client::nick_changed;
list<ClientPtr> Client::unregistered_list;
map<BaseClient *, ClientPtr> Client::client_list;
uv_timer_t Client::ping_timer;

Client::Client() : invisible(false), last_message(time(NULL))
{
}

void Client::add_channel(const ChannelPtr channel)
{
  channels.push_back(channel);
}

void Client::close(const string reason)
{
  BaseClient::close(reason);
  for(auto it = channels.begin(); it != channels.end(); it++)
  {
    ChannelPtr channel = *it;
    channel->remove_member(client_list[this]);
  }
}

void Client::remove_channel(const ChannelPtr channel)
{
  channels.remove(channel);
}

void Client::send(const string arg, int numeric)
{
  stringstream buffer;

  buffer << ":" << Server::get_me()->str() << " ";
  buffer << setw(3) << setfill('0') << numeric;
  buffer << " ";
  if(name.empty())
    buffer << "*";
  else
    buffer << name;

  buffer << " " << arg;

  BaseClient::send(buffer.str());
}

void Client::send(int numeric, ...)
{
  va_list args;

  va_start(args, numeric);

  send(Numeric::format(numeric, args), numeric);

  va_end(args);
}

void Client::send_channels_common(string message)
{
  unordered_map<BaseClient *, ClientPtr> sent_clients;

  for(auto it = channels.begin(); it != channels.end(); it++)
  {
    ChannelPtr channel = *it;
    map<ClientPtr, Membership> members = channel->get_members();

    for(auto mit = members.begin(); mit != members.end(); mit++)
    {
      Membership ms = mit->second;

      if(sent_clients[ms.client.get()])
        continue;

      if(ms.client.get() == this)
        continue;

      sent_clients[ms.client.get()] = ms.client;
      ms.client->send(message);
    }
  }
}

irc_string Client::str() const
{
  stringstream buff;

  if(name.empty())
    return "*";

  buff << name << "!" << username << "@" << host;

  return irc_string(buff.str().c_str());
}

bool Client::is_invisible() const
{
  return invisible;
}

string Client::get_username() const
{
  return username;
}

string Client::get_realname() const
{
  return realname;
}

time_t Client::get_idletime() const
{
  return time(NULL) - last_message;
}

void Client::set_invisible(bool invis)
{
  invisible = invis;
}

void Client::set_username(const string user)
{
  username = user;
}

void Client::set_realname(const string real)
{
  realname = real;
}

void Client::set_last_message(time_t when)
{
  last_message = when;
}

// Statics

void Client::init()
{
  uv_timer_init(uv_default_loop(), &ping_timer);
  uv_timer_start(&ping_timer, check_pings, 0, 5);
}

void Client::add(ClientPtr ptr)
{
  shared_ptr<Client> client = dynamic_pointer_cast<Client>(ptr);

  if(!registering(client))
    return;

  client_list[ptr.get()] = ptr;
  client->set_registered();

  unregistered_list.remove(client);

  connected(client);

  client->send(001, client->str().c_str());
  client->send(002, Server::get_me()->str().c_str(), "0.0.1");
  client->send(003, System::get_built_date());
}

void Client::add_unregistered(ClientPtr client)
{
  unregistered_list.push_back(client);
}

void Client::remove(ClientPtr client)
{
  if(client->is_registered())
    client_list.erase(client.get());
  else
    unregistered_list.remove(client);
}

void Client::check_pings(uv_timer_t *handle, int status)
{
  for(auto it = client_list.begin(); it != client_list.end(); it++)
  {
    ClientPtr client = it->second;

    if(!client->check_timeout())
    {
      client->close("Ping Timeout");
    }
  }

  for(auto it = unregistered_list.begin(); it != unregistered_list.end(); it++)
  {
    ClientPtr client = *it;

    if(!client->check_timeout())
    {
      client->close("Registration timed out");
    }
  }
}
<|endoftext|>


<commit_before>
#include "id_func.h"
#include "list_graph.h"
#include "multi_arc.h"
#include "sort_arc.h"
#include "chain.h"
#include "flow_cutter.h"
#include "greedy_order.h"

#include "node_flow_cutter.h"
#include "contraction_graph.h"
#include "cch_order.h"
#include "tree_decomposition.h"
#include "separator.h"

#include <limits>
#include <signal.h>
#include <stdlib.h>
#include <string.h>
#include <string>
#include <sstream>
#ifdef PARALLELIZE
#include <omp.h>
#endif

#include <sys/time.h>
#include <unistd.h>
using namespace std;

ArrayIDIDFunc tail, head;
const char*volatile best_decomposition = 0;
int best_bag_size = numeric_limits<int>::max();

void ignore_return_value(int){}

int compute_max_bag_size(const ArrayIDIDFunc&order){
	auto inv_order = inverse_permutation(order);
	int current_tail = -1;
	int current_tail_up_deg = 0;
	int max_up_deg = 0;
	compute_chordal_supergraph(
		chain(tail, inv_order), chain(head, inv_order),
		[&](int x, int y){
			if(current_tail != x){
				current_tail = x;
				max_to(max_up_deg, current_tail_up_deg);
				current_tail_up_deg = 0;
			}
			++current_tail_up_deg;
		}
	);
	return max_up_deg+1;
}

unsigned long long get_milli_time(){
	struct timeval tv;
	gettimeofday(&tv, NULL);
	return (unsigned long long)(tv.tv_sec) * 1000
	   + (unsigned long long)(tv.tv_usec) / 1000;
}

const char*compute_decomposition(const ArrayIDIDFunc&order){
	ostringstream out;
	print_tree_decompostion(out, tail, head, move(order));
	char*buf = new char[out.str().length()+1];
	memcpy(buf, out.str().c_str(), out.str().length()+1);
	return buf;
}

void test_new_order(ArrayIDIDFunc order){
	int x = compute_max_bag_size(order);
	#ifdef PARALLELIZE
	#pragma omp critical
	#endif
	{
		if(x < best_bag_size){
			best_bag_size = x;
			{
				string msg = "c status "+to_string(best_bag_size)+" "+to_string(get_milli_time())+"\n";
				ignore_return_value(write(STDOUT_FILENO, msg.data(), msg.length()));
			}
			const char*old_decomposition = best_decomposition;
			best_decomposition = compute_decomposition(move(order));
			delete[]old_decomposition;
		}
	}
}

void signal_handler(int)
{
	const char*x = best_decomposition;
	if(x != 0)
		ignore_return_value(write(STDOUT_FILENO, x, strlen(x)));
	exit(0);
}

int main(int argc, char*argv[]){
	signal(SIGTERM, signal_handler);
	signal(SIGINT, signal_handler);

	signal(SIGSEGV, signal_handler);
	try{
		{
			string file_name = "-";
			if(argc == 2)
				file_name = argv[1];
			auto g = uncached_load_pace_graph(file_name);
			tail = std::move(g.tail);
			head = std::move(g.head);
		}

		test_new_order(identity_permutation(tail.image_count()));
		test_new_order(compute_greedy_min_degree_order(tail, head));
		test_new_order(compute_greedy_min_shortcut_order(tail, head));

		int random_seed = 0;

		if(argc == 3){
			if(string(argv[1]) == "-s"){
				random_seed = atoi(argv[2]);
			}
		}

		#ifdef PARALLELIZE
		#pragma omp parallel
		#endif
		{
			try{
				std::minstd_rand rand_gen;
				rand_gen.seed(
					random_seed
					#ifdef PARALLELIZE
					+ omp_get_thread_num()
					#endif
				);

				flow_cutter::Config config;
				config.cutter_count = 1;
				config.random_seed = rand_gen();

				for(int i=0;;++i){
					config.random_seed = rand_gen();
					if(i % 32 == 0)
						++config.cutter_count;

					test_new_order(cch_order::compute_cch_graph_order(tail, head, flow_cutter::ComputeSeparator(config)));
				}
			}catch(...){
				signal_handler(0);
			}
		}
	}catch(...){
		signal_handler(0);
	}
}

<commit_msg>replaced exit(0) by _Exit(0) because the former is not allowed in a signal handler<commit_after>
#include "id_func.h"
#include "list_graph.h"
#include "multi_arc.h"
#include "sort_arc.h"
#include "chain.h"
#include "flow_cutter.h"
#include "greedy_order.h"

#include "node_flow_cutter.h"
#include "contraction_graph.h"
#include "cch_order.h"
#include "tree_decomposition.h"
#include "separator.h"

#include <limits>
#include <signal.h>
#include <stdlib.h>
#include <string.h>
#include <string>
#include <sstream>
#ifdef PARALLELIZE
#include <omp.h>
#endif

#include <sys/time.h>
#include <unistd.h>
using namespace std;

ArrayIDIDFunc tail, head;
const char*volatile best_decomposition = 0;
int best_bag_size = numeric_limits<int>::max();

void ignore_return_value(int){}

int compute_max_bag_size(const ArrayIDIDFunc&order){
	auto inv_order = inverse_permutation(order);
	int current_tail = -1;
	int current_tail_up_deg = 0;
	int max_up_deg = 0;
	compute_chordal_supergraph(
		chain(tail, inv_order), chain(head, inv_order),
		[&](int x, int y){
			if(current_tail != x){
				current_tail = x;
				max_to(max_up_deg, current_tail_up_deg);
				current_tail_up_deg = 0;
			}
			++current_tail_up_deg;
		}
	);
	return max_up_deg+1;
}

unsigned long long get_milli_time(){
	struct timeval tv;
	gettimeofday(&tv, NULL);
	return (unsigned long long)(tv.tv_sec) * 1000
	   + (unsigned long long)(tv.tv_usec) / 1000;
}

const char*compute_decomposition(const ArrayIDIDFunc&order){
	ostringstream out;
	print_tree_decompostion(out, tail, head, move(order));
	char*buf = new char[out.str().length()+1];
	memcpy(buf, out.str().c_str(), out.str().length()+1);
	return buf;
}

void test_new_order(ArrayIDIDFunc order){
	int x = compute_max_bag_size(order);
	#ifdef PARALLELIZE
	#pragma omp critical
	#endif
	{
		if(x < best_bag_size){
			best_bag_size = x;
			{
				string msg = "c status "+to_string(best_bag_size)+" "+to_string(get_milli_time())+"\n";
				ignore_return_value(write(STDOUT_FILENO, msg.data(), msg.length()));
			}
			const char*old_decomposition = best_decomposition;
			best_decomposition = compute_decomposition(move(order));
			delete[]old_decomposition;
		}
	}
}

void signal_handler(int)
{
	const char*x = best_decomposition;
	if(x != 0)
		ignore_return_value(write(STDOUT_FILENO, x, strlen(x)));
	_Exit(EXIT_SUCCESS);
}

int main(int argc, char*argv[]){
	signal(SIGTERM, signal_handler);
	signal(SIGINT, signal_handler);

	signal(SIGSEGV, signal_handler);
	try{
		{
			string file_name = "-";
			if(argc == 2)
				file_name = argv[1];
			auto g = uncached_load_pace_graph(file_name);
			tail = std::move(g.tail);
			head = std::move(g.head);
		}

		test_new_order(identity_permutation(tail.image_count()));
		test_new_order(compute_greedy_min_degree_order(tail, head));
		test_new_order(compute_greedy_min_shortcut_order(tail, head));

		int random_seed = 0;

		if(argc == 3){
			if(string(argv[1]) == "-s"){
				random_seed = atoi(argv[2]);
			}
		}

		#ifdef PARALLELIZE
		#pragma omp parallel
		#endif
		{
			try{
				std::minstd_rand rand_gen;
				rand_gen.seed(
					random_seed
					#ifdef PARALLELIZE
					+ omp_get_thread_num()
					#endif
				);

				flow_cutter::Config config;
				config.cutter_count = 1;
				config.random_seed = rand_gen();

				for(int i=0;;++i){
					config.random_seed = rand_gen();
					if(i % 32 == 0)
						++config.cutter_count;

					test_new_order(cch_order::compute_cch_graph_order(tail, head, flow_cutter::ComputeSeparator(config)));
				}
			}catch(...){
				signal_handler(0);
			}
		}
	}catch(...){
		signal_handler(0);
	}
}

<|endoftext|>


<commit_before>/****************************************************************/
/*  derived form NearestNodeLocator.C                           */
/****************************************************************/

#include "VolumeNearestNodeLocator.h"
#include "MooseMesh.h"
#include "SubProblem.h"
#include "SlaveNeighborhoodThread.h"
#include "NearestNodeThread.h"
#include "Moose.h"
// libMesh
#include "libmesh/boundary_info.h"
#include "libmesh/elem.h"
#include "libmesh/plane.h"
#include "libmesh/mesh_tools.h"

std::string _boundaryBlockFuser(BoundaryID boundary, SubdomainID block)
{
  std::stringstream ss;

  ss << boundary << "to" << block;

  return ss.str();
}

VolumeNearestNodeLocator::VolumeNearestNodeLocator(SubProblem & subproblem, MooseMesh & mesh, BoundaryID boundary, SubdomainID block) :
    Restartable(_boundaryBlockFuser(boundary, block), "VolumeNearestNodeLocator", subproblem, 0),
    _subproblem(subproblem),
    _mesh(mesh),
    _block_node_range(NULL),
    _boundary(boundary),
    _block(block),
    _first(true)
{
  //sanity check on ids
  const std::set<BoundaryID>& bids=_mesh.getBoundaryIDs();
  std::set<BoundaryID>::const_iterator sit;
  sit=bids.find(_boundary);
  if (sit == bids.end())
    mooseError("VolumeNearestNodeLocator being created for boundary "<<_boundary<<" and block "<<_block<<", but boundary "<<_boundary<<" does not exist");

  const std::set<SubdomainID>& sids=_mesh.meshSubdomains();
  std::set<SubdomainID>::const_iterator ssit;
  ssit=sids.find(_block);
  if (ssit == sids.end())
    mooseError("VolumeNearestNodeLocator being created for boundary "<<_boundary<<" and block "<<_block<<", but block "<<_block<<" does not exist");
}

VolumeNearestNodeLocator::~VolumeNearestNodeLocator()
{
  delete _block_node_range;
}

void
VolumeNearestNodeLocator::findNodes()
{
  Moose::perf_log.push("VolumeNearestNodeLocator::findNodes()","Solve");

  /**
   * If this is the first time through we're going to build up a "neighborhood" of nodes
   * surrounding each of the block nodes.  This will speed searching later.
   */
  if (_first)
  {
    _first=false;

    // Trial block nodes are all the nodes on the slave side
    // We only keep the ones that are either on this processor or are likely
    // to interact with elements on this processor (ie nodes owned by this processor
    // are in the "neighborhood" of the block node
    std::vector<unsigned int> trial_block_nodes;    // was slave
    std::vector<unsigned int> trial_boundary_nodes; // was master

    // Build a bounding box.  No reason to consider nodes outside of our inflated BB
    MeshTools::BoundingBox * my_inflated_box = NULL;

    std::vector<Real> & inflation = _mesh.getGhostedBoundaryInflation();

    // This means there was a user specified inflation... so we can build a BB
    if (inflation.size() > 0)
    {
      MeshTools::BoundingBox my_box = MeshTools::processor_bounding_box(_mesh, _mesh.processor_id());

      Real distance_x = 0;
      Real distance_y = 0;
      Real distance_z = 0;

      distance_x = inflation[0];

      if (inflation.size() > 1)
        distance_y = inflation[1];

      if (inflation.size() > 2)
        distance_z = inflation[2];

      my_inflated_box = new MeshTools::BoundingBox(Point(my_box.first(0)-distance_x,
                                                         my_box.first(1)-distance_y,
                                                         my_box.first(2)-distance_z),
                                                   Point(my_box.second(0)+distance_x,
                                                         my_box.second(1)+distance_y,
                                                         my_box.second(2)+distance_z));
    }

    // Data structures to hold the Nodal Boundary conditions
    ConstBndNodeRange & bnd_nodes = *_mesh.getBoundaryNodeRange();
    for (ConstBndNodeRange::const_iterator nd = bnd_nodes.begin() ; nd != bnd_nodes.end(); ++nd)
    {
      const BndNode * bnode = *nd;
      BoundaryID boundary_id = bnode->_bnd_id;
      unsigned int node_id = bnode->_node->id();

      // If we have a BB only consider saving this node if it's in our inflated BB
      if (boundary_id == _boundary && (!my_inflated_box || (my_inflated_box->contains_point(*bnode->_node))))
        trial_boundary_nodes.push_back(node_id);
    }

    for (libMesh::Node const *nd = *_mesh.localNodesBegin() ; nd != *_mesh.localNodesEnd(); ++nd)
    {
      const Node * node = nd;
      std::set<SubdomainID> sids = _mesh.getNodeBlockIds(*node);
      std::set<SubdomainID>::const_iterator ssit(sids.find(_block));
      unsigned int node_id = node->id();

      // If we have a BB only consider saving this node if it's in our inflated BB
      if (ssit != sids.end() && (!my_inflated_box || (my_inflated_box->contains_point(*node))))
        trial_block_nodes.push_back(node_id);
    }

    // don't need the BB anymore
    delete my_inflated_box;

    std::map<unsigned int, std::vector<unsigned int> > & node_to_elem_map = _mesh.nodeToElemMap();
    SlaveNeighborhoodThread snt(_mesh, trial_boundary_nodes, node_to_elem_map, _mesh.getPatchSize());

    NodeIdRange trial_block_node_range(trial_block_nodes.begin(), trial_block_nodes.end(), 1);
    Threads::parallel_reduce(trial_block_node_range, snt);

    _block_nodes = snt._slave_nodes;
    _neighbor_nodes = snt._neighbor_nodes;

    for (std::set<unsigned int>::iterator it = snt._ghosted_elems.begin();
        it != snt._ghosted_elems.end();
        ++it)
      _subproblem.addGhostedElem(*it);

    // Cache the blocke_node_range so we don't have to build it each time
    _block_node_range = new NodeIdRange(_block_nodes.begin(), _block_nodes.end(), 1);
  }

  _nearest_node_info.clear();

  NearestNodeThread nnt(_mesh, _neighbor_nodes);

  Threads::parallel_reduce(*_block_node_range, nnt);

  _max_patch_percentage = nnt._max_patch_percentage;

  _nearest_node_info = nnt._nearest_node_info;

  Moose::perf_log.pop("VolumeNearestNodeLocator::findNodes()","Solve");
}

void
VolumeNearestNodeLocator::reinit()
{
  // Reset all data
  delete _block_node_range;
  _block_node_range = NULL;
  _nearest_node_info.clear();

  _first = true;

  _block_nodes.clear();
  _neighbor_nodes.clear();

  // Redo the search
  findNodes();
}

Real
VolumeNearestNodeLocator::distance(unsigned int node_id)
{
  return _nearest_node_info[node_id]._distance;
}

const Node *
VolumeNearestNodeLocator::nearestNode(unsigned int node_id)
{
  return _nearest_node_info[node_id]._nearest_node;
}
<commit_msg>fixed a segfault in VolumeNearestNodeLocator due to improper use of iterators *grmpf*<commit_after>/****************************************************************/
/*  derived form NearestNodeLocator.C                           */
/****************************************************************/

#include "VolumeNearestNodeLocator.h"
#include "MooseMesh.h"
#include "SubProblem.h"
#include "SlaveNeighborhoodThread.h"
#include "NearestNodeThread.h"
#include "Moose.h"
// libMesh
#include "libmesh/boundary_info.h"
#include "libmesh/elem.h"
#include "libmesh/plane.h"
#include "libmesh/mesh_tools.h"

std::string _boundaryBlockFuser(BoundaryID boundary, SubdomainID block)
{
  std::stringstream ss;

  ss << boundary << "to" << block;

  return ss.str();
}

VolumeNearestNodeLocator::VolumeNearestNodeLocator(SubProblem & subproblem, MooseMesh & mesh, BoundaryID boundary, SubdomainID block) :
    Restartable(_boundaryBlockFuser(boundary, block), "VolumeNearestNodeLocator", subproblem, 0),
    _subproblem(subproblem),
    _mesh(mesh),
    _block_node_range(NULL),
    _boundary(boundary),
    _block(block),
    _first(true)
{
  //sanity check on ids
  const std::set<BoundaryID>& bids=_mesh.getBoundaryIDs();
  std::set<BoundaryID>::const_iterator sit;
  sit=bids.find(_boundary);
  if (sit == bids.end())
    mooseError("VolumeNearestNodeLocator being created for boundary "<<_boundary<<" and block "<<_block<<", but boundary "<<_boundary<<" does not exist");

  const std::set<SubdomainID>& sids=_mesh.meshSubdomains();
  std::set<SubdomainID>::const_iterator ssit;
  ssit=sids.find(_block);
  if (ssit == sids.end())
    mooseError("VolumeNearestNodeLocator being created for boundary "<<_boundary<<" and block "<<_block<<", but block "<<_block<<" does not exist");
}

VolumeNearestNodeLocator::~VolumeNearestNodeLocator()
{
  delete _block_node_range;
}

void
VolumeNearestNodeLocator::findNodes()
{
  Moose::perf_log.push("VolumeNearestNodeLocator::findNodes()","Solve");

  /**
   * If this is the first time through we're going to build up a "neighborhood" of nodes
   * surrounding each of the block nodes.  This will speed searching later.
   */
  if (_first)
  {
    _first=false;

    // Trial block nodes are all the nodes on the slave side
    // We only keep the ones that are either on this processor or are likely
    // to interact with elements on this processor (ie nodes owned by this processor
    // are in the "neighborhood" of the block node
    std::vector<unsigned int> trial_block_nodes;    // was slave
    std::vector<unsigned int> trial_boundary_nodes; // was master

    // Build a bounding box.  No reason to consider nodes outside of our inflated BB
    MeshTools::BoundingBox * my_inflated_box = NULL;

    std::vector<Real> & inflation = _mesh.getGhostedBoundaryInflation();

    // This means there was a user specified inflation... so we can build a BB
    if (inflation.size() > 0)
    {
      MeshTools::BoundingBox my_box = MeshTools::processor_bounding_box(_mesh, _mesh.processor_id());

      Real distance_x = 0;
      Real distance_y = 0;
      Real distance_z = 0;

      distance_x = inflation[0];

      if (inflation.size() > 1)
        distance_y = inflation[1];

      if (inflation.size() > 2)
        distance_z = inflation[2];

      my_inflated_box = new MeshTools::BoundingBox(Point(my_box.first(0)-distance_x,
                                                         my_box.first(1)-distance_y,
                                                         my_box.first(2)-distance_z),
                                                   Point(my_box.second(0)+distance_x,
                                                         my_box.second(1)+distance_y,
                                                         my_box.second(2)+distance_z));
    }

    // Data structures to hold the Nodal Boundary conditions
    ConstBndNodeRange & bnd_nodes = *_mesh.getBoundaryNodeRange();
    for (ConstBndNodeRange::const_iterator nd = bnd_nodes.begin() ; nd != bnd_nodes.end(); ++nd)
    {
      const BndNode * bnode = *nd;
      BoundaryID boundary_id = bnode->_bnd_id;
      unsigned int node_id = bnode->_node->id();

      // If we have a BB only consider saving this node if it's in our inflated BB
      if (boundary_id == _boundary && (!my_inflated_box || (my_inflated_box->contains_point(*bnode->_node))))
        trial_boundary_nodes.push_back(node_id);
    }

    for (MeshBase::const_node_iterator nd = _mesh.localNodesBegin(); nd != _mesh.localNodesEnd(); ++nd)
    {
      const Node * node = *nd;
      std::set<SubdomainID> sids = _mesh.getNodeBlockIds(*node);
      std::set<SubdomainID>::const_iterator ssit(sids.find(_block));
      unsigned int node_id = node->id();

      // If we have a BB only consider saving this node if it's in our inflated BB
      if (ssit != sids.end() && (!my_inflated_box || (my_inflated_box->contains_point(*node))))
        trial_block_nodes.push_back(node_id);
    }

    // don't need the BB anymore
    delete my_inflated_box;

    std::map<unsigned int, std::vector<unsigned int> > & node_to_elem_map = _mesh.nodeToElemMap();
    SlaveNeighborhoodThread snt(_mesh, trial_boundary_nodes, node_to_elem_map, _mesh.getPatchSize());

    NodeIdRange trial_block_node_range(trial_block_nodes.begin(), trial_block_nodes.end(), 1);
    Threads::parallel_reduce(trial_block_node_range, snt);

    _block_nodes = snt._slave_nodes;
    _neighbor_nodes = snt._neighbor_nodes;

    for (std::set<unsigned int>::iterator it = snt._ghosted_elems.begin();
        it != snt._ghosted_elems.end();
        ++it)
      _subproblem.addGhostedElem(*it);

    // Cache the blocke_node_range so we don't have to build it each time
    _block_node_range = new NodeIdRange(_block_nodes.begin(), _block_nodes.end(), 1);
  }

  _nearest_node_info.clear();

  NearestNodeThread nnt(_mesh, _neighbor_nodes);

  Threads::parallel_reduce(*_block_node_range, nnt);

  _max_patch_percentage = nnt._max_patch_percentage;

  _nearest_node_info = nnt._nearest_node_info;

  Moose::perf_log.pop("VolumeNearestNodeLocator::findNodes()","Solve");
}

void
VolumeNearestNodeLocator::reinit()
{
  // Reset all data
  delete _block_node_range;
  _block_node_range = NULL;
  _nearest_node_info.clear();

  _first = true;

  _block_nodes.clear();
  _neighbor_nodes.clear();

  // Redo the search
  findNodes();
}

Real
VolumeNearestNodeLocator::distance(unsigned int node_id)
{
  return _nearest_node_info[node_id]._distance;
}

const Node *
VolumeNearestNodeLocator::nearestNode(unsigned int node_id)
{
  return _nearest_node_info[node_id]._nearest_node;
}
<|endoftext|>


<commit_before>// $Id$
// -*-C++-*-
// * BeginRiceCopyright *****************************************************
//
// Copyright ((c)) 2002, Rice University
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
//   notice, this list of conditions and the following disclaimer.
//
// * Redistributions in binary form must reproduce the above copyright
//   notice, this list of conditions and the following disclaimer in the
//   documentation and/or other materials provided with the distribution.
//
// * Neither the name of Rice University (RICE) nor the names of its
//   contributors may be used to endorse or promote products derived from
//   this software without specific prior written permission.
//
// This software is provided by RICE and contributors "as is" and any
// express or implied warranties, including, but not limited to, the
// implied warranties of merchantability and fitness for a particular
// purpose are disclaimed. In no event shall RICE or contributors be
// liable for any direct, indirect, incidental, special, exemplary, or
// consequential damages (including, but not limited to, procurement of
// substitute goods or services; loss of use, data, or profits; or
// business interruption) however caused and on any theory of liability,
// whether in contract, strict liability, or tort (including negligence
// or otherwise) arising in any way out of the use of this software, even
// if advised of the possibility of such damage.
//
// ******************************************************* EndRiceCopyright *

//***************************************************************************
//
// File:
//    CSProfileUtils.C
//
// Purpose:
//    [The purpose of this file]
//
// Description:
//    [The set of functions, macros, etc. defined in the file]
//
//***************************************************************************

//************************* System Include Files ****************************

#include <iostream>
#include <fstream>

#ifdef NO_STD_CHEADERS  // FIXME
# include <string.h>
#else
# include <cstring>
using namespace std; // For compatibility with non-std C headers
#endif

//*************************** User Include Files ****************************

#include "CSProfileUtils.h"
#include <lib/binutils/LoadModule.h>
#include <lib/binutils/PCToSrcLineMap.h>
#include <lib/binutils/LoadModuleInfo.h>
#include <lib/xml/xml.h>
#include <lib/support/String.h>
#include <lib/support/Assertion.h>

#include <lib/hpcfile/hpcfile_csproflib.h>

//*************************** Forward Declarations ***************************

using namespace xml;

extern "C" {
  static void* cstree_create_node_CB(void* tree,
				     hpcfile_cstree_nodedata_t* data);
  static void  cstree_link_parent_CB(void* tree, void* node, void* parent);

  static void* hpcfile_alloc_CB(size_t sz);
  static void  hpcfile_free_CB(void* mem);
}

bool AddPGMToCSProfTree(CSProfTree* tree, const char* progName);

void ConvertOpIPToIP(Addr opIP, Addr& ip, ushort& opIdx);

//****************************************************************************
// Dump a CSProfTree and collect source file information
//****************************************************************************

const char *CSPROFILEdtd =
#include <lib/xml/CSPROFILE.dtd.h>

void
WriteCSProfile(CSProfile* prof, std::ostream& os, bool prettyPrint)
{
  os << "<?xml version=\"1.0\"?>" << std::endl;
  os << "<!DOCTYPE CSPROFILE [\n" << CSPROFILEdtd << "]>" << std::endl;
  os.flush();

  CSProfileMetric* metric = prof->GetMetric();
  os << "<CSPROFILE version=\"1.0\">\n";
  os << "<CSPROFILEHDR>\n</CSPROFILEHDR>\n";
  os << "<CSPROFILEPARAMS>\n";
  {
    os << "<TARGET name"; WriteAttrStr(os, prof->GetTarget()); os << "/>\n";

    os << "<METRIC shortName"; WriteAttrNum(os, 0);
    os << " nativeName";       WriteAttrNum(os, metric->GetName());
    os << " period";           WriteAttrNum(os, metric->GetPeriod());
    os << "/>\n";

    os << "</CSPROFILEPARAMS>\n";
  }
  os.flush();

  int dumpFlags = (CSProfTree::XML_TRUE); // CSProfTree::XML_NO_ESC_CHARS
  if (!prettyPrint) { dumpFlags |= CSProfTree::COMPRESSED_OUTPUT; }

  prof->GetTree()->Dump(os, dumpFlags);
}

bool
AddSourceFileInfoToCSProfile(CSProfile* prof, LoadModuleInfo* lm)
{
  bool noError = true;

  CSProfTree* tree = prof->GetTree();
  CSProfNode* root = tree->GetRoot();

  for (CSProfNodeIterator it(root); it.CurNode(); ++it) {
    CSProfNode* n = it.CurNode();
    AddSourceFileInfoToCSTreeNode(n, lm);
  }

  return noError;
}

bool
AddSourceFileInfoToCSTreeNode(CSProfNode* node, LoadModuleInfo* lm)
{
  bool noError = true;

  CSProfCallSiteNode* n = dynamic_cast<CSProfCallSiteNode*>(node);
  if (n) {
    String func, file;
    SrcLineX srcLn;
    lm->GetSymbolicInfo(n->GetIP(), n->GetOpIndex(), func, file, srcLn);

    n->SetFile(file);
    n->SetProc(func);
    n->SetLine(srcLn.GetSrcLine());
  }

  return noError;
}

//****************************************************************************
// Set of routines to build a scope tree while reading data file
//****************************************************************************

CSProfile*
ReadCSProfileFile_HCSPROFILE(const char* fnm)
{
  hpcfile_csprof_data_t data;
  int ret1, ret2;

  CSProfile* prof = new CSProfile;

  // Read profile
  FILE* fs = hpcfile_open_for_read(fnm);
  ret1 = hpcfile_csprof_read(fs, &data, hpcfile_alloc_CB, hpcfile_free_CB);
  ret2 = hpcfile_cstree_read(fs, prof->GetTree(),
			     cstree_create_node_CB, cstree_link_parent_CB,
			     hpcfile_alloc_CB, hpcfile_free_CB);
  hpcfile_close(fs);

  if ( !(ret1 == HPCFILE_OK && ret2 == HPCFILE_OK) ) {
    delete prof;
    return NULL;
  }

  // Extract profiling info
  prof->SetTarget(data.target);
  CSProfileMetric* metric = prof->GetMetric();
  metric->SetName(data.event);
  metric->SetPeriod(data.sample_period);

  // We must deallocate pointer-data
  hpcfile_free_CB(data.target);
  hpcfile_free_CB(data.event);

  // Add PGM node to tree
  AddPGMToCSProfTree(prof->GetTree(), prof->GetTarget());

  return prof;
}

static void*
cstree_create_node_CB(void* tree, hpcfile_cstree_nodedata_t* data)
{
  CSProfTree* t = (CSProfTree*)tree;

  Addr ip;
  ushort opIdx;
  ConvertOpIPToIP((Addr)data->ip, ip, opIdx);

  CSProfCallSiteNode* n =
    new CSProfCallSiteNode(NULL, ip, opIdx, (suint)data->weight);

  // Initialize the tree, if necessary
  if (t->IsEmpty()) {
    t->SetRoot(n);
  }

  return n;
}

static void
cstree_link_parent_CB(void* tree, void* node, void* parent)
{
  CSProfCallSiteNode* p = (CSProfCallSiteNode*)parent;
  CSProfCallSiteNode* n = (CSProfCallSiteNode*)node;
  n->Link(p);
}

static void*
hpcfile_alloc_CB(size_t sz)
{
  return (new char[sz]);
}

static void
hpcfile_free_CB(void* mem)
{
  delete[] (char*)mem;
}

// ConvertOpIPToIP: Find the instruction pointer 'ip' and operation
// index 'opIdx' from the operation pointer 'opIP'.  The operation
// pointer is represented by adding 0, 1, or 2 to the instruction
// pointer for the first, second and third operation, respectively.
void
ConvertOpIPToIP(Addr opIP, Addr& ip, ushort& opIdx)
{
  opIdx = (ushort)(opIP & 0x3); // the mask ...00011 covers 0, 1 and 2
  ip = opIP - opIdx;
}

bool
AddPGMToCSProfTree(CSProfTree* tree, const char* progName)
{
  bool noError = true;

  // Add PGM node
  CSProfNode* n = tree->GetRoot();
  if (!n || n->GetType() != CSProfNode::PGM) {
    CSProfNode* root = new CSProfPgmNode(progName);
    if (n) {
      n->Link(root); // 'root' is parent of 'n'
    }
    tree->SetRoot(root);
  }

  return noError;
}

//***************************************************************************
// Routines for normalizing the ScopeTree
//***************************************************************************

bool CoalesceCallsiteLeaves(CSProfile* prof);

bool
NormalizeCSProfile(CSProfile* prof)
{
  // Remove duplicate/inplied file and procedure information from tree
  bool pass1 = true;

  bool pass2 = CoalesceCallsiteLeaves(prof);

  return (pass1 && pass2);
}

// FIXME
// If pc values from the leaves map to the same source file info,
// coalese these leaves into one.
bool CoalesceCallsiteLeaves(CSProfNode* node);

bool
CoalesceCallsiteLeaves(CSProfile* prof)
{
  CSProfTree* csproftree = prof->GetTree();
  if (!csproftree) { return true; }

  return CoalesceCallsiteLeaves(csproftree->GetRoot());
}

// FIXME
typedef std::map<String, CSProfCallSiteNode*, StringLt> StringToCallSiteMap;
typedef std::map<String, CSProfCallSiteNode*, StringLt>::iterator
  StringToCallSiteMapIt;
typedef std::map<String, CSProfCallSiteNode*, StringLt>::value_type
  StringToCallSiteMapVal;

bool
CoalesceCallsiteLeaves(CSProfNode* node)
{
  bool noError = true;

  if (!node) { return noError; }

  // FIXME: Use this set to determine if we have a duplicate source line
  StringToCallSiteMap sourceInfoMap;

  // For each immediate child of this node...
  for (CSProfNodeChildIterator it(node); it.Current(); /* */) {
    CSProfCodeNode* child = dynamic_cast<CSProfCodeNode*>(it.CurNode());
    BriefAssertion(child); // always true (FIXME)
    it++; // advance iterator -- it is pointing at 'child'

    bool inspect = (child->IsLeaf()
		    && (child->GetType() == CSProfNode::CALLSITE));

    if (inspect) {

      // This child is a leaf. Test for duplicate source line info.
      CSProfCallSiteNode* c = dynamic_cast<CSProfCallSiteNode*>(child);
      String myid = String(c->GetFile()) + String(c->GetProc())
	+ String(c->GetLine());

      StringToCallSiteMapIt it = sourceInfoMap.find(myid);
      if (it != sourceInfoMap.end()) {
	// found -- we have a duplicate
	CSProfCallSiteNode* c1 = (*it).second;

	// add weights of 'c' and 'c1'
	suint newWeight = c->GetWeight() + c1->GetWeight();
	c1->SetWeight(newWeight);

	// remove 'child' from tree
	child->Unlink();
	delete child;
      } else {
	// no entry found -- add
	sourceInfoMap.insert(StringToCallSiteMapVal(myid, c));
      }

    } else if (!child->IsLeaf()) {
      // Recur:
      noError = noError && CoalesceCallsiteLeaves(child);
    }

  }

  return noError;
}
<commit_msg>fixed CSProfileUtils.C to add </CSPROFILE> tag<commit_after>// $Id$
// -*-C++-*-
// * BeginRiceCopyright *****************************************************
//
// Copyright ((c)) 2002, Rice University
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
//   notice, this list of conditions and the following disclaimer.
//
// * Redistributions in binary form must reproduce the above copyright
//   notice, this list of conditions and the following disclaimer in the
//   documentation and/or other materials provided with the distribution.
//
// * Neither the name of Rice University (RICE) nor the names of its
//   contributors may be used to endorse or promote products derived from
//   this software without specific prior written permission.
//
// This software is provided by RICE and contributors "as is" and any
// express or implied warranties, including, but not limited to, the
// implied warranties of merchantability and fitness for a particular
// purpose are disclaimed. In no event shall RICE or contributors be
// liable for any direct, indirect, incidental, special, exemplary, or
// consequential damages (including, but not limited to, procurement of
// substitute goods or services; loss of use, data, or profits; or
// business interruption) however caused and on any theory of liability,
// whether in contract, strict liability, or tort (including negligence
// or otherwise) arising in any way out of the use of this software, even
// if advised of the possibility of such damage.
//
// ******************************************************* EndRiceCopyright *

//***************************************************************************
//
// File:
//    CSProfileUtils.C
//
// Purpose:
//    [The purpose of this file]
//
// Description:
//    [The set of functions, macros, etc. defined in the file]
//
//***************************************************************************

//************************* System Include Files ****************************

#include <iostream>
#include <fstream>

#ifdef NO_STD_CHEADERS  // FIXME
# include <string.h>
#else
# include <cstring>
using namespace std; // For compatibility with non-std C headers
#endif

//*************************** User Include Files ****************************

#include "CSProfileUtils.h"
#include <lib/binutils/LoadModule.h>
#include <lib/binutils/PCToSrcLineMap.h>
#include <lib/binutils/LoadModuleInfo.h>
#include <lib/xml/xml.h>
#include <lib/support/String.h>
#include <lib/support/Assertion.h>

#include <lib/hpcfile/hpcfile_csproflib.h>

//*************************** Forward Declarations ***************************

using namespace xml;

extern "C" {
  static void* cstree_create_node_CB(void* tree,
				     hpcfile_cstree_nodedata_t* data);
  static void  cstree_link_parent_CB(void* tree, void* node, void* parent);

  static void* hpcfile_alloc_CB(size_t sz);
  static void  hpcfile_free_CB(void* mem);
}

bool AddPGMToCSProfTree(CSProfTree* tree, const char* progName);

void ConvertOpIPToIP(Addr opIP, Addr& ip, ushort& opIdx);

//****************************************************************************
// Dump a CSProfTree and collect source file information
//****************************************************************************

const char *CSPROFILEdtd =
#include <lib/xml/CSPROFILE.dtd.h>

void
WriteCSProfile(CSProfile* prof, std::ostream& os, bool prettyPrint)
{
  os << "<?xml version=\"1.0\"?>" << std::endl;
  os << "<!DOCTYPE CSPROFILE [\n" << CSPROFILEdtd << "]>" << std::endl;
  os.flush();

  CSProfileMetric* metric = prof->GetMetric();
  os << "<CSPROFILE version=\"1.0\">\n";
  os << "<CSPROFILEHDR>\n</CSPROFILEHDR>\n";

  {
  	os << "<CSPROFILEPARAMS>\n";
  	os << "<TARGET name"; WriteAttrStr(os, prof->GetTarget()); os << "/>\n";

  	os << "<METRIC shortName"; WriteAttrNum(os, 0);
  	os << " nativeName";       WriteAttrNum(os, metric->GetName());
  	os << " period";           WriteAttrNum(os, metric->GetPeriod());
  	os << "/>\n";

  	os << "</CSPROFILEPARAMS>\n";
  }

  os.flush();

  int dumpFlags = (CSProfTree::XML_TRUE); // CSProfTree::XML_NO_ESC_CHARS
  if (!prettyPrint) { dumpFlags |= CSProfTree::COMPRESSED_OUTPUT; }

  prof->GetTree()->Dump(os, dumpFlags);

  os << "</CSPROFILE>\n";
  os.flush();
}

bool
AddSourceFileInfoToCSProfile(CSProfile* prof, LoadModuleInfo* lm)
{
  bool noError = true;

  CSProfTree* tree = prof->GetTree();
  CSProfNode* root = tree->GetRoot();

  for (CSProfNodeIterator it(root); it.CurNode(); ++it) {
    CSProfNode* n = it.CurNode();
    AddSourceFileInfoToCSTreeNode(n, lm);
  }

  return noError;
}

bool
AddSourceFileInfoToCSTreeNode(CSProfNode* node, LoadModuleInfo* lm)
{
  bool noError = true;

  CSProfCallSiteNode* n = dynamic_cast<CSProfCallSiteNode*>(node);
  if (n) {
    String func, file;
    SrcLineX srcLn;
    lm->GetSymbolicInfo(n->GetIP(), n->GetOpIndex(), func, file, srcLn);

    n->SetFile(file);
    n->SetProc(func);
    n->SetLine(srcLn.GetSrcLine());
  }

  return noError;
}

//****************************************************************************
// Set of routines to build a scope tree while reading data file
//****************************************************************************

CSProfile*
ReadCSProfileFile_HCSPROFILE(const char* fnm)
{
  hpcfile_csprof_data_t data;
  int ret1, ret2;

  CSProfile* prof = new CSProfile;

  // Read profile
  FILE* fs = hpcfile_open_for_read(fnm);
  ret1 = hpcfile_csprof_read(fs, &data, hpcfile_alloc_CB, hpcfile_free_CB);
  ret2 = hpcfile_cstree_read(fs, prof->GetTree(),
			     cstree_create_node_CB, cstree_link_parent_CB,
			     hpcfile_alloc_CB, hpcfile_free_CB);
  hpcfile_close(fs);

  if ( !(ret1 == HPCFILE_OK && ret2 == HPCFILE_OK) ) {
    delete prof;
    return NULL;
  }

  // Extract profiling info
  prof->SetTarget(data.target);
  CSProfileMetric* metric = prof->GetMetric();
  metric->SetName(data.event);
  metric->SetPeriod(data.sample_period);

  // We must deallocate pointer-data
  hpcfile_free_CB(data.target);
  hpcfile_free_CB(data.event);

  // Add PGM node to tree
  AddPGMToCSProfTree(prof->GetTree(), prof->GetTarget());

  return prof;
}

static void*
cstree_create_node_CB(void* tree, hpcfile_cstree_nodedata_t* data)
{
  CSProfTree* t = (CSProfTree*)tree;

  Addr ip;
  ushort opIdx;
  ConvertOpIPToIP((Addr)data->ip, ip, opIdx);

  CSProfCallSiteNode* n =
    new CSProfCallSiteNode(NULL, ip, opIdx, (suint)data->weight);

  // Initialize the tree, if necessary
  if (t->IsEmpty()) {
    t->SetRoot(n);
  }

  return n;
}

static void
cstree_link_parent_CB(void* tree, void* node, void* parent)
{
  CSProfCallSiteNode* p = (CSProfCallSiteNode*)parent;
  CSProfCallSiteNode* n = (CSProfCallSiteNode*)node;
  n->Link(p);
}

static void*
hpcfile_alloc_CB(size_t sz)
{
  return (new char[sz]);
}

static void
hpcfile_free_CB(void* mem)
{
  delete[] (char*)mem;
}

// ConvertOpIPToIP: Find the instruction pointer 'ip' and operation
// index 'opIdx' from the operation pointer 'opIP'.  The operation
// pointer is represented by adding 0, 1, or 2 to the instruction
// pointer for the first, second and third operation, respectively.
void
ConvertOpIPToIP(Addr opIP, Addr& ip, ushort& opIdx)
{
  opIdx = (ushort)(opIP & 0x3); // the mask ...00011 covers 0, 1 and 2
  ip = opIP - opIdx;
}

bool
AddPGMToCSProfTree(CSProfTree* tree, const char* progName)
{
  bool noError = true;

  // Add PGM node
  CSProfNode* n = tree->GetRoot();
  if (!n || n->GetType() != CSProfNode::PGM) {
    CSProfNode* root = new CSProfPgmNode(progName);
    if (n) {
      n->Link(root); // 'root' is parent of 'n'
    }
    tree->SetRoot(root);
  }

  return noError;
}

//***************************************************************************
// Routines for normalizing the ScopeTree
//***************************************************************************

bool CoalesceCallsiteLeaves(CSProfile* prof);

bool
NormalizeCSProfile(CSProfile* prof)
{
  // Remove duplicate/inplied file and procedure information from tree
  bool pass1 = true;

  bool pass2 = CoalesceCallsiteLeaves(prof);

  return (pass1 && pass2);
}

// FIXME
// If pc values from the leaves map to the same source file info,
// coalese these leaves into one.
bool CoalesceCallsiteLeaves(CSProfNode* node);

bool
CoalesceCallsiteLeaves(CSProfile* prof)
{
  CSProfTree* csproftree = prof->GetTree();
  if (!csproftree) { return true; }

  return CoalesceCallsiteLeaves(csproftree->GetRoot());
}

// FIXME
typedef std::map<String, CSProfCallSiteNode*, StringLt> StringToCallSiteMap;
typedef std::map<String, CSProfCallSiteNode*, StringLt>::iterator
  StringToCallSiteMapIt;
typedef std::map<String, CSProfCallSiteNode*, StringLt>::value_type
  StringToCallSiteMapVal;

bool
CoalesceCallsiteLeaves(CSProfNode* node)
{
  bool noError = true;

  if (!node) { return noError; }

  // FIXME: Use this set to determine if we have a duplicate source line
  StringToCallSiteMap sourceInfoMap;

  // For each immediate child of this node...
  for (CSProfNodeChildIterator it(node); it.Current(); /* */) {
    CSProfCodeNode* child = dynamic_cast<CSProfCodeNode*>(it.CurNode());
    BriefAssertion(child); // always true (FIXME)
    it++; // advance iterator -- it is pointing at 'child'

    bool inspect = (child->IsLeaf()
		    && (child->GetType() == CSProfNode::CALLSITE));

    if (inspect) {

      // This child is a leaf. Test for duplicate source line info.
      CSProfCallSiteNode* c = dynamic_cast<CSProfCallSiteNode*>(child);
      String myid = String(c->GetFile()) + String(c->GetProc())
	+ String(c->GetLine());

      StringToCallSiteMapIt it = sourceInfoMap.find(myid);
      if (it != sourceInfoMap.end()) {
	// found -- we have a duplicate
	CSProfCallSiteNode* c1 = (*it).second;

	// add weights of 'c' and 'c1'
	suint newWeight = c->GetWeight() + c1->GetWeight();
	c1->SetWeight(newWeight);

	// remove 'child' from tree
	child->Unlink();
	delete child;
      } else {
	// no entry found -- add
	sourceInfoMap.insert(StringToCallSiteMapVal(myid, c));
      }

    } else if (!child->IsLeaf()) {
      // Recur:
      noError = noError && CoalesceCallsiteLeaves(child);
    }

  }

  return noError;
}
<|endoftext|>


<commit_before>#include "stdafx.h"
#include <tcp_server.h>
#include "asio_service_deamon.h"
#include "io_dispatcher.h"

AsioServiceDeamon::AsioServiceDeamon()
{
}

AsioServiceDeamon::~AsioServiceDeamon()
{
    delete _service;
    delete _server;
    //delete _network_service;
}

void AsioServiceDeamon::start(const std::string& serviceName,
                              const uint32_t& threadNum/* = irene::net_params::smart_thread_nums()*/)
{
    _serviceName = serviceName;

    //create io service instance
    _service = new IOService;

    //create tcp server instance
    _server = new TcpServer(InetAddress(48360), *_service, 1);

    //create network service instance
    //_network_service = new NetworkService();

    //register io events
    IODispatcher io_dispatcher;
    _server->setNewConnectionCallback(
        std::bind(&IODispatcher::NewConnectionHandler, &io_dispatcher, std::placeholders::_1, std::placeholders::_2)
        );

    _server->setWriteCompletedCallback(
        std::bind(&IODispatcher::WriteCompletedHandler, &io_dispatcher, std::placeholders::_1, std::placeholders::_2)
        );

    _server->setReadCompletedCallback(
        std::bind(&IODispatcher::ReadCompletedHandler, &io_dispatcher, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4)
        );

    _server->setConnectionClosedCallback(
        std::bind(&IODispatcher::ConnectionClosed, &io_dispatcher, std::placeholders::_1)
        );

    _server->start();
}

void AsioServiceDeamon::stop()
{

}<commit_msg>* 修改一个无法从最外部传入线程数的编写失误<commit_after>#include "stdafx.h"
#include <tcp_server.h>
#include "asio_service_deamon.h"
#include "io_dispatcher.h"

AsioServiceDeamon::AsioServiceDeamon()
{
}

AsioServiceDeamon::~AsioServiceDeamon()
{
    delete _service;
    delete _server;
    //delete _network_service;
}

void AsioServiceDeamon::start(const std::string& serviceName,
                              const uint32_t& threadNum/* = irene::net_params::smart_thread_nums()*/)
{
    _serviceName = serviceName;

    //create io service instance
    _service = new IOService;

    //create tcp server instance
    _server = new TcpServer(InetAddress(48360), *_service, threadNum);

    //create network service instance
    //_network_service = new NetworkService();

    //register io events
    IODispatcher io_dispatcher;
    _server->setNewConnectionCallback(
        std::bind(&IODispatcher::NewConnectionHandler, &io_dispatcher, std::placeholders::_1, std::placeholders::_2)
        );

    _server->setWriteCompletedCallback(
        std::bind(&IODispatcher::WriteCompletedHandler, &io_dispatcher, std::placeholders::_1, std::placeholders::_2)
        );

    _server->setReadCompletedCallback(
        std::bind(&IODispatcher::ReadCompletedHandler, &io_dispatcher, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4)
        );

    _server->setConnectionClosedCallback(
        std::bind(&IODispatcher::ConnectionClosed, &io_dispatcher, std::placeholders::_1)
        );

    _server->start();
}

void AsioServiceDeamon::stop()
{

}<|endoftext|>