text:
/*
# Copyright 2018 HyphaROS Workshop.
# Latest Modifier: HaoChih, LIN (hypha.ros@gmail.com)
# Original Author: ChanYuan KUO & YoRu LU
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
*/

#include <iostream>
#include <map>
#include <math.h>
#include "ros/ros.h"
#include <geometry_msgs/PoseWithCovarianceStamped.h>
#include <geometry_msgs/PoseStamped.h>
#include <geometry_msgs/Twist.h>
#include <tf/transform_listener.h>
#include <tf/transform_datatypes.h>
#include <nav_msgs/Path.h>
#include <nav_msgs/Odometry.h>
#include <ackermann_msgs/AckermannDriveStamped.h>
#include <visualization_msgs/Marker.h>

#include <Eigen/Core>
#include <Eigen/QR>
#include <vector>

#include <string>
#include <fstream>

using namespace std;
using std::string;

/********************/
/* CLASS DEFINITION */
/********************/
class PurePursuit
{
    public:
        PurePursuit();
        void initMarker();
        bool isForwardWayPt(const geometry_msgs::Point& wayPt, const geometry_msgs::Pose& carPose);
        bool isWayPtAwayFromLfwDist(const geometry_msgs::Point& wayPt, const geometry_msgs::Point& car_pos);
        double getYawFromPose(const geometry_msgs::Pose& carPose);

        double polyeval(Eigen::VectorXd coeffs, double x);
        Eigen::VectorXd polyfit(Eigen::VectorXd xvals, Eigen::VectorXd yvals, int order);

        double getCar2GoalDist();

	double getW(double _alpha);

        double get_alpha(const geometry_msgs::Pose& carPose);

    private:

        ros::NodeHandle n_;
        ros::Subscriber odom_sub, path_sub, goal_sub, amcl_sub;
        ros::Publisher ackermann_pub, cmdvel_pub, marker_pub;
        ros::Timer timer1, timer2;
        tf::TransformListener tf_listener;

        ros::Time tracking_stime;
        ros::Time tracking_etime;
        ros::Time tracking_time;
        int tracking_time_sec;
        int tracking_time_nsec;

        //time flag
        bool start_timef = false;
        bool end_timef = false;

        std::ofstream file;

        double _waypointsDist = -1.0;
        double _pathLength = 8.0;
        bool _path_computed = false;

        string _map_frame, _odom_frame, _car_frame;

        unsigned int idx = 0;

        visualization_msgs::Marker points, line_strip, goal_circle;
        geometry_msgs::Point odom_goal_pos, goal_pos;
        geometry_msgs::Twist cmd_vel;
        ackermann_msgs::AckermannDriveStamped ackermann_cmd;
        nav_msgs::Odometry odom;
        nav_msgs::Path map_path, odom_path, odom_path_w, _odom_path;

        int _downSampling;

        double L, Lfw, Vcmd, lfw, steering, velocity;
        double w;
        double steering_gain, max_w, base_angle, goal_radius, speed_incremental;
        int controller_freq;
        bool foundForwardPt, goal_received, goal_reached, cmd_vel_mode, debug_mode, smooth_accel;

        void odomCB(const nav_msgs::Odometry::ConstPtr& odomMsg);
        void pathCB(const nav_msgs::Path::ConstPtr& pathMsg);
        void goalCB(const geometry_msgs::PoseStamped::ConstPtr& goalMsg);
        void amclCB(const geometry_msgs::PoseWithCovarianceStamped::ConstPtr& amclMsg);
        void controlLoopCB(const ros::TimerEvent&);

}; // end of class

PurePursuit::PurePursuit()
{
    //Private parameters handler
    ros::NodeHandle pn("~");

    //Car parameter
    pn.param("L", L, 0.26); // length of car
    pn.param("Vcmd", Vcmd, 1.0);// reference speed (m/s)
    pn.param("Lfw", Lfw, 0.5); // forward look ahead distance (m)
    pn.param("lfw", lfw, 0.13); // distance between front the center of car

    //Controller parameter
    pn.param("controller_freq", controller_freq, 20);
    pn.param("steering_gain", steering_gain, 1.0);
    pn.param("max_w", max_w, 1.0);
    pn.param("goal_radius", goal_radius, 0.5); // goal radius (m)
    pn.param("base_angle", base_angle, 0.0); // neutral point of servo (rad)
    pn.param("cmd_vel_mode", cmd_vel_mode, false); // whether or not publishing cmd_vel
    pn.param("debug_mode", debug_mode, false); // debug mode
    pn.param("smooth_accel", smooth_accel, true); // smooth the acceleration of car
    pn.param("speed_incremental", speed_incremental, 0.5); // speed incremental value (discrete acceleraton), unit: m/s

    //Parameter for topics & Frame name
    pn.param<std::string>("map_frame", _map_frame, "map" ); //*****for mpc, "odom"
    pn.param<std::string>("odom_frame", _odom_frame, "odom");
    pn.param<std::string>("car_frame", _car_frame, "base_footprint" );

    //Publishers and Subscribers
    odom_sub = n_.subscribe("/odom", 1, &PurePursuit::odomCB, this);
    //path_sub = n_.subscribe("/pure_pursuit/global_planner", 1, &PurePursuit::pathCB, this);
    //goal_sub = n_.subscribe("/pure_pursuit/goal", 1, &PurePursuit::goalCB, this);
    path_sub = n_.subscribe("/move_base/TrajectoryPlannerROS/global_plan", 1, &PurePursuit::pathCB, this);
    goal_sub = n_.subscribe("/move_base_simple/goal", 1, &PurePursuit::goalCB, this);
    amcl_sub = n_.subscribe("/amcl_pose", 5, &PurePursuit::amclCB, this);
    marker_pub = n_.advertise<visualization_msgs::Marker>("/pure_pursuit/path_marker", 10);
    ackermann_pub = n_.advertise<ackermann_msgs::AckermannDriveStamped>("/pure_pursuit/ackermann_cmd", 1);
    if(cmd_vel_mode) cmdvel_pub = n_.advertise<geometry_msgs::Twist>("/cmd_vel", 1);

    //Timer
    timer1 = n_.createTimer(ros::Duration((1.0)/controller_freq), &PurePursuit::controlLoopCB, this); // Duration(0.05) -> 20Hz

    //Init variables
    foundForwardPt = false;
    goal_received = false;
    goal_reached = false;
    velocity = 0.0;
    w = 0.0;
    steering = base_angle;

    idx = 0;
    file.open("/home/nscl1016/catkin_ws/src/mpc_ros/pure_pursuit.csv");

    //Show info
    ROS_INFO("[param] base_angle: %f", base_angle);
    ROS_INFO("[param] Vcmd: %f", Vcmd);
    ROS_INFO("[param] Lfw: %f", Lfw);

    //Visualization Marker Settings
    initMarker();

    cmd_vel = geometry_msgs::Twist();
    ackermann_cmd = ackermann_msgs::AckermannDriveStamped();

}

void PurePursuit::initMarker()
{
    points.header.frame_id = line_strip.header.frame_id = goal_circle.header.frame_id = "odom";
    points.ns = line_strip.ns = goal_circle.ns = "Markers";
    points.action = line_strip.action = goal_circle.action = visualization_msgs::Marker::ADD;
    points.pose.orientation.w = line_strip.pose.orientation.w = goal_circle.pose.orientation.w = 1.0;
    points.id = 0;
    line_strip.id = 1;
    goal_circle.id = 2;

    points.type = visualization_msgs::Marker::POINTS;
    line_strip.type = visualization_msgs::Marker::LINE_STRIP;
    goal_circle.type = visualization_msgs::Marker::CYLINDER;
    // POINTS markers use x and y scale for width/height respectively
    points.scale.x = 0.2;
    points.scale.y = 0.2;

    //LINE_STRIP markers use only the x component of scale, for the line width
    line_strip.scale.x = 0.1;

    goal_circle.scale.x = goal_radius;
    goal_circle.scale.y = goal_radius;
    goal_circle.scale.z = 0.1;

    // Points are green
    points.color.g = 1.0f;
    points.color.a = 1.0;

    // Line strip is blue
    line_strip.color.b = 1.0;
    line_strip.color.a = 1.0;

    //goal_circle is yellow
    goal_circle.color.r = 1.0;
    goal_circle.color.g = 1.0;
    goal_circle.color.b = 0.0;
    goal_circle.color.a = 0.5;
}

void PurePursuit::odomCB(const nav_msgs::Odometry::ConstPtr& odomMsg)
{
    this->odom = *odomMsg;
}

void PurePursuit::pathCB(const nav_msgs::Path::ConstPtr& pathMsg) //jaewan
{
    this->map_path = *pathMsg;

    if(goal_received && !goal_reached)
    {
        nav_msgs::Path odom_path = nav_msgs::Path();
        try
        {
            double total_length = 0.0;
            int sampling = _downSampling;

            //find waypoints distance
            if(_waypointsDist <=0.0)
            {
                double dx = pathMsg->poses[1].pose.position.x - pathMsg->poses[0].pose.position.x;
                double dy = pathMsg->poses[1].pose.position.y - pathMsg->poses[0].pose.position.y;
                _waypointsDist = sqrt(dx*dx + dy*dy);
                _downSampling = int(_pathLength/10.0/_waypointsDist);
            }

            // Cut and downsampling the path
            for(int i =0; i< pathMsg->poses.size(); i++)
            {
                if(total_length > _pathLength)
                    break;

                if(sampling == _downSampling)
                {
                    geometry_msgs::PoseStamped tempPose;
                    tf_listener.transformPose(_odom_frame, ros::Time(0) , pathMsg->poses[i], _map_frame, tempPose);
                    odom_path.poses.push_back(tempPose);
                    sampling = 0;
                }
                total_length = total_length + _waypointsDist;
                sampling = sampling + 1;
            }

            if(odom_path.poses.size() >= 6 )
            {
                _odom_path = odom_path; // Path waypoints in odom frame
                _path_computed = true;
                // publish odom path
                odom_path.header.frame_id = _odom_frame;
                odom_path.header.stamp = ros::Time::now();
            }
            else
            {
                cout << "Failed to path generation" << endl;
                _waypointsDist = -1;
            }
            //DEBUG
            //cout << endl << "N: " << odom_path.poses.size() << endl
            //<<  "Car path[0]: " << odom_path.poses[0];
            // << ", path[N]: " << _odom_path.poses[_odom_path.poses.size()-1] << endl;
        }
        catch(tf::TransformException &ex)
        {
            ROS_ERROR("%s",ex.what());
            ros::Duration(1.0).sleep();
        }
    }

}

void PurePursuit::goalCB(const geometry_msgs::PoseStamped::ConstPtr& goalMsg)
{
    this->goal_pos = goalMsg->pose.position;
    try
    {
        geometry_msgs::PoseStamped odom_goal;
        tf_listener.transformPose("odom", ros::Time(0) , *goalMsg, "map" ,odom_goal);
        odom_goal_pos = odom_goal.pose.position;
        goal_received = true;
        goal_reached = false;

        /*Draw Goal on RVIZ*/
        goal_circle.pose = odom_goal.pose;
        marker_pub.publish(goal_circle);
    }
    catch(tf::TransformException &ex)
    {
        ROS_ERROR("%s",ex.what());
        ros::Duration(1.0).sleep();
    }
}

double PurePursuit::getYawFromPose(const geometry_msgs::Pose& carPose)
{
    float x = carPose.orientation.x;
    float y = carPose.orientation.y;
    float z = carPose.orientation.z;
    float w = carPose.orientation.w;

    double tmp,yaw;
    tf::Quaternion q(x,y,z,w);
    tf::Matrix3x3 quaternion(q);
    quaternion.getRPY(tmp,tmp, yaw);

    return yaw;
}

bool PurePursuit::isForwardWayPt(const geometry_msgs::Point& wayPt, const geometry_msgs::Pose& carPose)
{
    float car2wayPt_x = wayPt.x - carPose.position.x;
    float car2wayPt_y = wayPt.y - carPose.position.y;
    double car_theta = getYawFromPose(carPose);

    float car_car2wayPt_x = cos(car_theta)*car2wayPt_x + sin(car_theta)*car2wayPt_y;
    float car_car2wayPt_y = -sin(car_theta)*car2wayPt_x + cos(car_theta)*car2wayPt_y;

    if(car_car2wayPt_x >0) /*is Forward WayPt*/
        return true;
    else
        return false;
}

bool PurePursuit::isWayPtAwayFromLfwDist(const geometry_msgs::Point& wayPt, const geometry_msgs::Point& car_pos)
{
    double dx = wayPt.x - car_pos.x;
    double dy = wayPt.y - car_pos.y;
    double dist = sqrt(dx*dx + dy*dy);

    if(dist < Lfw)
        return false;
    else if(dist >= Lfw)
        return true;
}

double PurePursuit::get_alpha(const geometry_msgs::Pose& carPose)
{
    geometry_msgs::Point carPose_pos = carPose.position;
    double carPose_yaw = getYawFromPose(carPose);
    geometry_msgs::Point odom_path_wayPt;
    geometry_msgs::Point forwardPt;
    geometry_msgs::Point odom_car2WayPtVec;
    foundForwardPt = false;

    if(!goal_reached){

        for(int i =0; i< _odom_path.poses.size(); i++)
        {
            geometry_msgs::PoseStamped map_path_pose = _odom_path.poses[i];
            geometry_msgs::PoseStamped odom_path_pose;

            try
            {
                tf_listener.transformPose("odom", ros::Time(0) , map_path_pose, "map" ,odom_path_pose);
                odom_path_wayPt = odom_path_pose.pose.position;
                bool _isForwardWayPt = isForwardWayPt(odom_path_wayPt,carPose);

                if(_isForwardWayPt)
                {
                    bool _isWayPtAwayFromLfwDist = isWayPtAwayFromLfwDist(odom_path_wayPt,carPose_pos);
                    if(_isWayPtAwayFromLfwDist)
                    {
                        forwardPt = odom_path_wayPt;
                        foundForwardPt = true;
                        break;
                    }
                }
            }
            catch(tf::TransformException &ex)
            {
                ROS_ERROR("%s",ex.what());
                ros::Duration(1.0).sleep();
            }
        }

    }
    else if(goal_reached)
    {
        forwardPt = odom_goal_pos;
        foundForwardPt = false;
        //ROS_INFO("goal REACHED!");
    }

    /*Visualized Target Point on RVIZ*/
    /*Clear former target point Marker*/
    points.points.clear();
    line_strip.points.clear();

    if(foundForwardPt && !goal_reached)
    {
        points.points.push_back(carPose_pos);
        points.points.push_back(odom_path_wayPt);
        line_strip.points.push_back(carPose_pos);
        line_strip.points.push_back(odom_path_wayPt);
    }

    marker_pub.publish(points);
    marker_pub.publish(line_strip);

    double alpha_t = atan2(odom_path_wayPt.y - carPose_pos.y,odom_path_wayPt.x - carPose_pos.x) - carPose_yaw;

    return alpha_t;
}

double PurePursuit::getCar2GoalDist()
{
    geometry_msgs::Point car_pose = this->odom.pose.pose.position;
    double car2goal_x = this->odom_goal_pos.x - car_pose.x;
    double car2goal_y = this->odom_goal_pos.y - car_pose.y;

    return sqrt(car2goal_x*car2goal_x + car2goal_y*car2goal_y);
}

double PurePursuit::getW(double _alpha)
{
    return 2*sin(_alpha)/Lfw;
}

double PurePursuit::polyeval(Eigen::VectorXd coeffs, double x)
{
    double result = 0.0;
    for (int i = 0; i < coeffs.size(); i++)
    {
        result += coeffs[i] * pow(x, i);
    }
    return result;
}

Eigen::VectorXd PurePursuit::polyfit(Eigen::VectorXd xvals, Eigen::VectorXd yvals, int order)
{
    assert(xvals.size() == yvals.size());
    assert(order >= 1 && order <= xvals.size() - 1);
    Eigen::MatrixXd A(xvals.size(), order + 1);

    for (int i = 0; i < xvals.size(); i++)
        A(i, 0) = 1.0;

    for (int j = 0; j < xvals.size(); j++)
    {
        for (int i = 0; i < order; i++)
            A(j, i + 1) = A(j, i) * xvals(j);
    }

    auto Q = A.householderQr();
    auto result = Q.solve(yvals);
    return result;
}
void PurePursuit::amclCB(const geometry_msgs::PoseWithCovarianceStamped::ConstPtr& amclMsg)
{

    if(this->goal_received)
    {
        double car2goal_x = this->goal_pos.x - amclMsg->pose.pose.position.x;
        double car2goal_y = this->goal_pos.y - amclMsg->pose.pose.position.y;
        double dist2goal = sqrt(car2goal_x*car2goal_x + car2goal_y*car2goal_y);
        if(dist2goal < this->goal_radius)
        {
            if(start_timef)
            {
                tracking_etime = ros::Time::now();
                tracking_time_sec = tracking_etime.sec - tracking_stime.sec;
                tracking_time_nsec = tracking_etime.nsec - tracking_stime.nsec;

                file << "tracking time"<< "," << tracking_time_sec << "," <<  tracking_time_nsec << "\n";

                file.close();

                start_timef = false;
            }
            this->goal_reached = true;
            this->goal_received = false;
            this->_path_computed = false;

            ROS_INFO("Goal Reached !");
            cout << "tracking time: " << tracking_time_sec << "." << tracking_time_nsec << endl;

        }
    }
}

void PurePursuit::controlLoopCB(const ros::TimerEvent&)
{

    geometry_msgs::Pose carPose = this->odom.pose.pose;
    geometry_msgs::Twist carVel = this->odom.twist.twist;

    tf::Pose pose;
    tf::poseMsgToTF(carPose, pose);
    double alpha = tf::getYaw(pose.getRotation());

    if(this->goal_received && !this->goal_reached && this->_path_computed)
    {
        if(!start_timef)
        {
            tracking_stime == ros::Time::now();

            start_timef = true;
        }

        double alpha = get_alpha(carPose);

	    this->w = this->base_angle + getW(alpha)*this->steering_gain;

        if(this->w > max_w)
        {
            this->w = max_w;
        }
        else if(this->w < -max_w)
        {
            this->w = -max_w;
        }

        nav_msgs::Odometry odom_w = odom;
        nav_msgs::Path odom_path_w = _odom_path;

        // Update system states: X=[x, y, theta, v]
        const double px = odom_w.pose.pose.position.x; //pose: odom frame
        const double py = odom_w.pose.pose.position.y;
        tf::Pose pose;
        tf::poseMsgToTF(odom_w.pose.pose, pose);
        const double theta = tf::getYaw(pose.getRotation());

        // Waypoints related parameters
        const int N = odom_path_w.poses.size(); // Number of waypoints
        const double costheta = cos(theta);
        const double sintheta = sin(theta);

        // Convert to the vehicle coordinate system
        Eigen::VectorXd x_veh(N);
        Eigen::VectorXd y_veh(N);
        for(int i = 0; i < N; i++)
        {
            const double dx = odom_path_w.poses[i].pose.position.x - px;
            const double dy = odom_path_w.poses[i].pose.position.y - py;
            x_veh[i] = dx * costheta + dy * sintheta;
            y_veh[i] = dy * costheta - dx * sintheta;
        }

        // Fit waypoints
        auto coeffs = polyfit(x_veh, y_veh, 3);

        const double cte  = polyeval(coeffs, 0.0);
        const double etheta = atan(coeffs[1]);

        cout << "cte: " << cte << endl;
        cout << "etheta: " << etheta << endl;
        cout << "v : " << cmd_vel.linear.x  << endl;
        cout << "w : " << cmd_vel.angular.z  << endl;

        idx++;
        file << idx<< "," << cte << "," <<  etheta << "," << cmd_vel.linear.x << "," << cmd_vel.angular.z << "\n";

            /*Estimate Gas Input*/
        if(!this->goal_reached)
        {
            if(this->smooth_accel)
                this->velocity = std::min(this->velocity + this->speed_incremental, this->Vcmd);
            else
                this->velocity = this->Vcmd;
            if(debug_mode) ROS_INFO("Velocity = %.2f, w = %.2f", this->velocity, this->w);
        }

    }

    else
    {
        this->velocity = 0.0;
		this->w = 0;
    }

    if(this->cmd_vel_mode)
    {
        this->cmd_vel.linear.x = this->velocity;
        this->cmd_vel.angular.z = this->w;
	    this->cmdvel_pub.publish(this->cmd_vel);
    }
}

/*****************/
/* MAIN FUNCTION */
/*****************/
int main(int argc, char **argv)
{
    //Initiate ROS
    ros::init(argc, argv, "PurePursuit");
    PurePursuit controller;
    ros::AsyncSpinner spinner(2); // Use multi threads
    spinner.start();
    ros::waitForShutdown();
    return 0;
}

ext: cpp


text:
/*
BSD 3-Clause License

Copyright (c) 2017, Alibaba Cloud
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 the copyright holder nor the names of its
  contributors may be used to endorse or promote products derived from
  this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "timestamp.hpp"
#include "tablestore/util/prettyprint.hpp"
#include <boost/chrono/chrono.hpp>
#include <boost/thread/thread.hpp>
#include <boost/system/error_code.hpp>
#include <deque>

using namespace std;
using namespace boost::chrono;

namespace aliyun {
namespace tablestore {
namespace util {

void sleepFor(const Duration& d)
{
    boost::this_thread::sleep_for(microseconds(d.toUsec()));
}

void sleepUntil(const MonotonicTime& target)
{
    Duration d = target - MonotonicTime::now();
    if (d > Duration::fromUsec(0)) {
        sleepFor(d);
    }
}

namespace {

void fill(string& out, int64_t val, int64_t width)
{
    deque<char> digits;
    int64_t i = 0;
    for(; val > 0; ++i, val /= 10) {
        digits.push_back('0' + (val % 10));
    }
    for(; i < width; ++i) {
        digits.push_back('0');
    }

    for(; !digits.empty(); digits.pop_back()) {
        out.push_back(digits.back());
    }
}

} // namespace

void Duration::prettyPrint(string& out) const
{
    pp::prettyPrint(out, mValue / kUsecPerHour);
    out.push_back(':');
    fill(out, (mValue % kUsecPerHour) / kUsecPerMin, 2);
    out.push_back(':');
    fill(out, (mValue % kUsecPerMin) / kUsecPerSec, 2);
    out.push_back('.');
    fill(out, mValue % kUsecPerSec, 6);
}

void MonotonicTime::prettyPrint(string& out) const
{
    pp::prettyPrint(out, mValue / kUsecPerHour);
    out.push_back(':');
    fill(out, (mValue % kUsecPerHour) / kUsecPerMin, 2);
    out.push_back(':');
    fill(out, (mValue % kUsecPerMin) / kUsecPerSec, 2);
    out.push_back('.');
    fill(out, mValue % kUsecPerSec, 6);
}

MonotonicTime MonotonicTime::now()
{
    boost::system::error_code err;
    steady_clock::time_point sc = steady_clock::now(err);
    OTS_ASSERT(!err)(err.message());
    steady_clock::duration d = sc.time_since_epoch();
    microseconds usec = duration_cast<microseconds>(d);
    return MonotonicTime(usec.count());
}

namespace {

struct TimeComponent
{
    TimeComponent()
      : mYear(0), mMonth(0), mDay(0), mHour(0),
        mMinute(0), mSec(0), mUsec(0)
    {}

    int mYear;
    int mMonth;
    int mDay;
    int mHour;
    int mMinute;
    int mSec;
    int mUsec;
};

TimeComponent decompose(const UtcTime& tm)
{
    TimeComponent result;
    int64_t t = tm.toUsec();
    int64_t q = t / kUsecPerSec;
    result.mUsec = t % kUsecPerSec;
    time_t x = q;
    struct tm ti;
    struct tm* r = gmtime_r(&x, &ti);
    OTS_ASSERT(r != NULL).what("time out of range");
    result.mYear = ti.tm_year + 1900;
    result.mMonth = ti.tm_mon + 1;
    result.mDay = ti.tm_mday;
    result.mHour = ti.tm_hour;
    result.mMinute = ti.tm_min;
    result.mSec = ti.tm_sec;
    return result;
}

} // namespace

void UtcTime::toIso8601(string& out) const
{
    const TimeComponent& tc = decompose(*this);
    fill(out, tc.mYear, 4);
    out.push_back('-');
    fill(out, tc.mMonth, 2);
    out.push_back('-');
    fill(out, tc.mDay, 2);
    out.push_back('T');
    fill(out, tc.mHour, 2);
    out.push_back(':');
    fill(out, tc.mMinute, 2);
    out.push_back(':');
    fill(out, tc.mSec, 2);
    out.push_back('.');
    fill(out, tc.mUsec, 6);
    out.push_back('Z');
}

string UtcTime::toIso8601() const
{
    string res;
    res.reserve(sizeof("1970-01-01T00:00:00.000000Z"));
    toIso8601(res);
    return res;
}

void UtcTime::prettyPrint(string& out) const
{
    out.push_back('"');
    toIso8601(out);
    out.push_back('"');
}

UtcTime UtcTime::now()
{
    boost::system::error_code err;
    system_clock::time_point sc = system_clock::now(err);
    OTS_ASSERT(!err)(err.message());
    system_clock::duration d = sc.time_since_epoch();
    microseconds usec = duration_cast<microseconds>(d);
    return UtcTime(usec.count());
}

} // namespace util
} // namespace tablestore
} // namespace aliyun

max_stars_repo_name: TimeExceed/aliyun-tablestore-cpp-sdk

max_issues_repo_name: TimeExceed/aliyun-tablestore-cpp-sdk

max_forks_repo_name: TimeExceed/aliyun-tablestore-cpp-sdk


text:
/*=========================================================================

  Program:   Visualization Toolkit
  Module:    vtkPBGLDistributedGraphHelper.cxx

  Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
  All rights reserved.
  See Copyright.txt or http://www.kitware.com/Copyright.htm for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notice for more information.

=========================================================================*/
/*
 * Copyright (C) 2008 The Trustees of Indiana University.
 * Use, modification and distribution is subject to the Boost Software
 * License, Version 1.0. (See http://www.boost.org/LICENSE_1_0.txt)
 */
#include "vtkPBGLDistributedGraphHelper.h"

#include "assert.h"
#include "vtkGraph.h"
#include "vtkGraphInternals.h"
#include "vtkInformation.h"
#include "vtkObjectFactory.h"
#include "vtkPBGLGraphAdapter.h"
#include "vtkDataSetAttributes.h"
#include "vtkVariantArray.h"
#include "vtkVariantBoostSerialization.h"
#include "vtkDataArray.h"
#include "vtkStringArray.h"
#include <boost/graph/distributed/mpi_process_group.hpp>
#include <boost/bind.hpp>
#include <vtkstd/utility>

//----------------------------------------------------------------------------
// private class vtkPBGLDistributedGraphHelperInternals
//----------------------------------------------------------------------------
class vtkPBGLDistributedGraphHelperInternals : public vtkObject
{
public:
  static vtkPBGLDistributedGraphHelperInternals *New();
  vtkTypeRevisionMacro(vtkPBGLDistributedGraphHelperInternals, vtkObject);

  // Description:
  // Handle a FIND_VERTEX_TAG messagae.
  vtkIdType HandleFindVertex(const vtkVariant& pedigreeId);

  // Description:
  // Handle a FIND_EDGE_SOURCE_TARGET_TAG message.
  vtkstd::pair<vtkIdType, vtkIdType> HandleFindEdgeSourceTarget(vtkIdType id);

  // Description:
  // Add a vertex with the given pedigree, if a vertex with that
  // pedigree ID does not already exist. Returns the ID for that
  // vertex.
  vtkIdType HandleAddVertex(const vtkVariant& pedigreeId);

  // Description:
  // Add a vertex with properties, if a vertex with the
  // pedigree ID (assuming there is one in the properties) does
  // not already exist.  Returns the ID for that vertex.
  vtkIdType HandleAddVertexProps(vtkVariantArray *propArray);

  // Description:
  // Handle a ADD_DIRECTED_BACK_EDGE_TAG or ADD_UNDIRECTED_BACK_END_TAG
  // message.
  void HandleAddBackEdge(vtkEdgeType edge, bool directed);

  // Description:
  // Handle ADD_*DIRECTED_EDGE_*_REPLY_TAG messages.
  vtkEdgeType
  HandleAddEdge(const vtkstd::pair<vtkIdType, vtkIdType>& msg, bool directed);

  // Description:
  // Handle ADD_*DIRECTED_EDGE_NI_*_REPLY_TAG messages.
  vtkEdgeType
  HandleAddEdgeNI(const vtkstd::pair<vtkVariant, vtkIdType>& msg,
                  bool directed);

  // Description:
  // Handle ADD_*DIRECTED_EDGE_IN_*_REPLY_TAG messages
  vtkEdgeType
  HandleAddEdgeIN(const vtkstd::pair<vtkIdType, vtkVariant>& msg,
                  bool directed);

  // Description:
  // Handle ADD_*DIRECTED_EDGE_NN_*_REPLY_TAG messages
  vtkEdgeType
  HandleAddEdgeNN(const vtkstd::pair<vtkVariant, vtkVariant>& msg,
                  bool directed);

  // Description:
  // The helper class of which this structure is a part.
  vtkPBGLDistributedGraphHelper *Helper;

  // Description:
  // Process group used by this helper
  boost::graph::distributed::mpi_process_group process_group;

private:
  vtkPBGLDistributedGraphHelperInternals()
    : process_group(GetRootProcessGroup()) { }

  // Retrieve the root process group.
  static boost::graph::distributed::mpi_process_group&
  GetRootProcessGroup()
  {
    if (!root_process_group)
      {
      root_process_group = new boost::graph::distributed::mpi_process_group();
      }
    return *root_process_group;
  }

  // Description:
  // The "root" process group, to which all of the process groups in
  // VTK's distributed graphs will eventually attach.
  static boost::graph::distributed::mpi_process_group *root_process_group;
};

// Definition
boost::graph::distributed::mpi_process_group *
vtkPBGLDistributedGraphHelperInternals::root_process_group;

vtkStandardNewMacro(vtkPBGLDistributedGraphHelperInternals);
vtkCxxRevisionMacro(vtkPBGLDistributedGraphHelperInternals, "1.6");

//----------------------------------------------------------------------------
// class vtkPBGLDistributedGraphHelper
//----------------------------------------------------------------------------
vtkCxxRevisionMacro(vtkPBGLDistributedGraphHelper, "1.6");
vtkStandardNewMacro(vtkPBGLDistributedGraphHelper);

//----------------------------------------------------------------------------
vtkPBGLDistributedGraphHelper::vtkPBGLDistributedGraphHelper()
{
  this->Internals = vtkPBGLDistributedGraphHelperInternals::New();
  this->Internals->Helper = this;
}

//----------------------------------------------------------------------------
vtkPBGLDistributedGraphHelper::~vtkPBGLDistributedGraphHelper()
{
  this->Internals->Delete();
}

//----------------------------------------------------------------------------
void vtkPBGLDistributedGraphHelper::Synchronize()
{
  synchronize(this->Internals->process_group);
}

//----------------------------------------------------------------------------
vtkDistributedGraphHelper *vtkPBGLDistributedGraphHelper::Clone()
{
  return vtkPBGLDistributedGraphHelper::New();
}

//----------------------------------------------------------------------------
boost::graph::distributed::mpi_process_group vtkPBGLDistributedGraphHelper::GetProcessGroup()
{
  return this->Internals->process_group.base();
}

//----------------------------------------------------------------------------
void vtkPBGLDistributedGraphHelper::AddVertexInternal(vtkVariantArray *propertyArr,
                                                      vtkIdType *vertex)
{
  vtkIdType rank
    = this->Graph->GetInformation()->Get(vtkDataObject::DATA_PIECE_NUMBER());
  vtkAbstractArray *peds = this->Graph->GetVertexData()->GetPedigreeIds();
  vtkIdType owner = -1;
  if (peds != NULL) {
    vtkIdType pedIdx = this->Graph->GetVertexData()->SetPedigreeIds(peds);
    vtkVariant pedigreeId = propertyArr->GetValue(pedIdx);
    owner = this->GetVertexOwnerByPedigreeId(pedigreeId);
  }

  if ((peds != NULL) && (owner == rank))
    {
    // This little dance keeps us from having to make
    // vtkPBGLDistributedGraphHelper a friend of vtkGraph. It also
    // makes sure that users don't try to be sneaky about adding
    // vertices to non-mutable vtkGraphs.
    if (vtkMutableDirectedGraph *graph
          = vtkMutableDirectedGraph::SafeDownCast(this->Graph))
      {
        if (vertex)
          {
          *vertex = graph->AddVertex(propertyArr);
          }
        else
          {
          graph->LazyAddVertex(propertyArr);
          }
      }
    else if (vtkMutableUndirectedGraph *graph
               = vtkMutableUndirectedGraph::SafeDownCast(this->Graph))
      {
        if (vertex)
          {
          *vertex = graph->AddVertex(propertyArr);
          }
        else
          {
          graph->LazyAddVertex(propertyArr);
          }
      }
    else
      {
      vtkErrorMacro("Cannot add vertices to a non-mutable, distributed graph");
      }
    return;
    }

  if (vertex)
    {
    // Request immediate addition of the vertex, with a reply.
    send_oob_with_reply(this->Internals->process_group, owner,
                        ADD_VERTEX_PROPS_WITH_REPLY_TAG, propertyArr, *vertex);
    }
  else
    {
    // Request addition of the vertex, eventually.
    send(this->Internals->process_group, owner, ADD_VERTEX_PROPS_NO_REPLY_TAG, propertyArr);
    }
}

//----------------------------------------------------------------------------
void vtkPBGLDistributedGraphHelper::AddVertexInternal(const vtkVariant& pedigreeId,
                                                      vtkIdType *vertex)
{
  vtkIdType rank
    = this->Graph->GetInformation()->Get(vtkDataObject::DATA_PIECE_NUMBER());
  vtkIdType owner = this->GetVertexOwnerByPedigreeId(pedigreeId);
  if (owner == rank)
    {
    // This little dance keeps us from having to make
    // vtkPBGLDistributedGraphHelper a friend of vtkGraph. It also
    // makes sure that users don't try to be sneaky about adding
    // vertices to non-mutable vtkGraphs.
    if (vtkMutableDirectedGraph *graph
          = vtkMutableDirectedGraph::SafeDownCast(this->Graph))
      {
        if (vertex)
          {
          *vertex = graph->AddVertex(pedigreeId);
          }
        else
          {
          graph->LazyAddVertex(pedigreeId);
          }
      }
    else if (vtkMutableUndirectedGraph *graph
               = vtkMutableUndirectedGraph::SafeDownCast(this->Graph))
      {
        if (vertex)
          {
          *vertex = graph->AddVertex(pedigreeId);
          }
        else
          {
          graph->LazyAddVertex(pedigreeId);
          }
      }
    else
      {
      vtkErrorMacro("Cannot add vertices to a non-mutable, distributed graph");
      }
    return;
    }

  if (vertex)
    {
    // Request immediate addition of the vertex, with a reply.
    send_oob_with_reply(this->Internals->process_group, owner,
                        ADD_VERTEX_WITH_REPLY_TAG, pedigreeId, *vertex);
    }
  else
    {
    // Request addition of the vertex, eventually.
    send(this->Internals->process_group, owner, ADD_VERTEX_NO_REPLY_TAG, pedigreeId);
    }
}

//----------------------------------------------------------------------------
void
vtkPBGLDistributedGraphHelper::AddEdgeInternal(vtkIdType u,
                                               vtkIdType v,
                                               bool directed,
                                               vtkVariantArray *propertyArr,
                                               vtkEdgeType *edge)
{
  int rank = this->Graph->GetInformation()->Get(vtkDataObject::DATA_PIECE_NUMBER());
  int numProcs = this->Graph->GetInformation()->Get(vtkDataObject::DATA_NUMBER_OF_PIECES());
  int uOwner = this->GetVertexOwner (u);

  if (uOwner == rank)
    {
    // The source of the edge is local.
    vtkGraphInternals* GraphInternals = this->Graph->GetGraphInternals(true);

    // The edge ID involves our rank and the local number of edges.
    vtkIdType edgeId
      = this->MakeDistributedId(rank, GraphInternals->NumberOfEdges);

    if (propertyArr)      // Add edge properties
      {
      vtkDataSetAttributes *edgeData = this->Graph->GetEdgeData();
      int numProps = propertyArr->GetNumberOfValues();   // # of properties = # of arrays
      assert(numProps == edgeData->GetNumberOfArrays());
      for (int iprop=0; iprop<numProps; iprop++)
        {
        vtkAbstractArray* arr = edgeData->GetAbstractArray(iprop);
        if (vtkDataArray::SafeDownCast(arr))
          {
          vtkDataArray::SafeDownCast(arr)->InsertNextTuple1(propertyArr->GetPointer(iprop)->ToDouble());
          }
        else if (vtkStringArray::SafeDownCast(arr))
          {
          vtkStringArray::SafeDownCast(arr)->InsertNextValue(propertyArr->GetPointer(iprop)->ToString());
          }
        else
          {
          vtkErrorMacro("Unsupported array type");
          }
        }
      }

    // Add the forward edge.
    GraphInternals->Adjacency[this->GetVertexIndex(u)]
      .OutEdges.push_back(vtkOutEdgeType(v, edgeId));

    // We've added an edge.
    GraphInternals->NumberOfEdges++;

    int vOwner = this->GetVertexOwner(v);
    if (vOwner == rank)
      {
        // The target vertex is local. Add the appropriate back edge.
        if (directed)
          {
          GraphInternals->Adjacency[this->GetVertexIndex(v)]
            .InEdges.push_back(vtkInEdgeType(u, edgeId));
          }
        else if (u != v)
          {
          // Avoid storing self-loops twice in undirected graphs
          GraphInternals->Adjacency[this->GetVertexIndex(v)]
            .OutEdges.push_back(vtkOutEdgeType(u, edgeId));
          }
      }
    else
      {
      // The target vertex is remote: send a message asking its
      // owner to add the back edge.
      send(this->Internals->process_group, vOwner,
           directed? ADD_DIRECTED_BACK_EDGE_TAG : ADD_UNDIRECTED_BACK_EDGE_TAG,
           vtkEdgeType(u, v, edgeId));
      }

    if (edge)
      {
      *edge = vtkEdgeType(u, v, edgeId);
      }
    }
  else
    {
    // The source of the edge is non-local.
      if (edge)
        {
        // Send an AddEdge request to the owner of "u", and wait
        // patiently for the reply.
        send_oob_with_reply(this->Internals->process_group, uOwner,
                            directed? ADD_DIRECTED_EDGE_WITH_REPLY_TAG
                                    : ADD_UNDIRECTED_EDGE_WITH_REPLY_TAG,
                            vtkstd::pair<vtkIdType, vtkIdType>(u, v),
                            *edge);
        }
      else
        {
        // We're adding a remote edge, but we don't need to wait
        // until the edge has been added. Just send a message to the
        // owner of the source; we don't need (or want) a reply.
        send(this->Internals->process_group, uOwner,
             directed? ADD_DIRECTED_EDGE_NO_REPLY_TAG
                     : ADD_UNDIRECTED_EDGE_NO_REPLY_TAG,
             vtkstd::pair<vtkIdType, vtkIdType>(u, v));
        }
    }
}

//----------------------------------------------------------------------------
void
vtkPBGLDistributedGraphHelper::AddEdgeInternal(const vtkVariant& uPedigreeId,
                                               vtkIdType v,
                                               bool directed,
                                               vtkVariantArray *propertyArr,
                                               vtkEdgeType *edge)
{
  vtkIdType rank
    = this->Graph->GetInformation()->Get(vtkDataObject::DATA_PIECE_NUMBER());
  vtkIdType uOwner = this->GetVertexOwnerByPedigreeId(uPedigreeId);

  if (uOwner == rank)
    {
    // Resolve the pedigreeId for u immediately and add the edge locally.
    vtkIdType u;
    this->AddVertexInternal(uPedigreeId, &u);
    this->AddEdgeInternal(u, v, directed, propertyArr, edge);
    return;
    }

  // Edge is remote: request its addition.
  if (edge)
    {
    send_oob_with_reply(this->Internals->process_group, uOwner,
                        directed? ADD_DIRECTED_EDGE_NI_WITH_REPLY_TAG
                                : ADD_UNDIRECTED_EDGE_NI_WITH_REPLY_TAG,
                        vtkstd::pair<vtkVariant, vtkIdType>(uPedigreeId, v),
                        *edge);
    }
  else
    {
    send(this->Internals->process_group, uOwner,
         directed? ADD_DIRECTED_EDGE_NI_NO_REPLY_TAG
                 : ADD_UNDIRECTED_EDGE_NI_NO_REPLY_TAG,
         vtkstd::pair<vtkVariant, vtkIdType>(uPedigreeId, v));
    }
}

//----------------------------------------------------------------------------
void
vtkPBGLDistributedGraphHelper::AddEdgeInternal(vtkIdType u,
                                               const vtkVariant& vPedigreeId,
                                               bool directed,
                                               vtkVariantArray *propertyArr,
                                               vtkEdgeType *edge)
{
  vtkIdType rank
    = this->Graph->GetInformation()->Get(vtkDataObject::DATA_PIECE_NUMBER());
  vtkIdType vOwner = this->GetVertexOwnerByPedigreeId(vPedigreeId);

  if (vOwner == rank || edge)
    {
    // Resolve the pedigree ID for v immediately and add the edge.
    vtkIdType v;
    this->AddVertexInternal(vPedigreeId, &v);
    this->AddEdgeInternal(u, v, directed, propertyArr, edge);
    return;
    }

  // v is remote and we don't care when the edge is added. Ask the
  // owner of v to resolve the pedigree ID of v and add the edge.
  send(this->Internals->process_group, vOwner,
       directed? ADD_DIRECTED_EDGE_IN_NO_REPLY_TAG
               : ADD_UNDIRECTED_EDGE_IN_NO_REPLY_TAG,
       vtkstd::pair<vtkIdType, vtkVariant>(u, vPedigreeId));
}

//----------------------------------------------------------------------------
void
vtkPBGLDistributedGraphHelper::AddEdgeInternal(const vtkVariant& uPedigreeId,
                                               const vtkVariant& vPedigreeId,
                                               bool directed,
                                               vtkVariantArray *propertyArr,
                                               vtkEdgeType *edge)
{
  vtkIdType rank
    = this->Graph->GetInformation()->Get(vtkDataObject::DATA_PIECE_NUMBER());
  vtkIdType uOwner = this->GetVertexOwnerByPedigreeId(vPedigreeId);
  if (uOwner == rank)
    {
    // Resolve the pedigree ID for u immediately and add the edge.
    vtkIdType u;
    this->AddVertexInternal(uPedigreeId, &u);
    this->AddEdgeInternal(u, vPedigreeId, directed, propertyArr, edge);
    return;
    }

  vtkIdType vOwner = this->GetVertexOwnerByPedigreeId(vPedigreeId);
  if (vOwner == rank || edge)
    {
    // Resolve the pedigree ID for v immediately and add the edge.
    vtkIdType v;
    this->AddVertexInternal(vPedigreeId, &v);
    this->AddEdgeInternal(uPedigreeId, v, directed, propertyArr, edge);
    return;
    }

  // Neither u nor v is local, and we don't care when the edge is
  // added, so ask the owner of v to resolve the pedigree ID of v and
  // add the edge.
  send(this->Internals->process_group, vOwner,
       directed? ADD_DIRECTED_EDGE_NN_NO_REPLY_TAG
               : ADD_UNDIRECTED_EDGE_NN_NO_REPLY_TAG,
       vtkstd::pair<vtkVariant, vtkVariant>(uPedigreeId, vPedigreeId));
}

//----------------------------------------------------------------------------
vtkIdType
vtkPBGLDistributedGraphHelper::FindVertex(const vtkVariant& pedigreeId)
{
  vtkIdType rank
    = this->Graph->GetInformation()->Get(vtkDataObject::DATA_PIECE_NUMBER());
  vtkIdType owner = this->GetVertexOwnerByPedigreeId(pedigreeId);
  if (owner == rank)
    {
    // The vertex is local; just ask the local part of the graph.
    return this->Graph->FindVertex(pedigreeId);
    }

  // The vertex is remote; Send a message looking for this
  // vertex.
  vtkIdType result;
  send_oob_with_reply(this->Internals->process_group, owner,
                      FIND_VERTEX_TAG, pedigreeId, result);
  return result;
}

//----------------------------------------------------------------------------
void
vtkPBGLDistributedGraphHelper::FindEdgeSourceAndTarget(vtkIdType id,
                                                       vtkIdType *source,
                                                       vtkIdType *target)
{
  vtkIdType rank
    = this->Graph->GetInformation()->Get(vtkDataObject::DATA_PIECE_NUMBER());
  vtkIdType owner = this->GetEdgeOwner(id);

  if (owner == rank)
    {
    if (source)
      {
      *source = this->Graph->GetSourceVertex(id);
      }
    if (target)
      {
      *target = this->Graph->GetTargetVertex(id);
      }
    return;
    }

  vtkstd::pair<vtkIdType, vtkIdType> result;
  send_oob_with_reply(this->Internals->process_group, owner,
                      FIND_EDGE_SOURCE_TARGET_TAG, id, result);

  if (source)
    {
    *source = result.first;
    }
  if (target)
    {
    *target = result.second;
    }
}

//----------------------------------------------------------------------------
void vtkPBGLDistributedGraphHelper::AttachToGraph(vtkGraph *graph)
{
  this->Graph = graph;

  if (graph &&
      (graph->GetNumberOfVertices() != 0 || graph->GetNumberOfEdges() != 0))
    {
    vtkErrorMacro("Cannot attach a distributed graph helper to a non-empty vtkGraph");
    }

  if (this->Graph)
    {
    // Set the piece number and number of pieces so that the
    // vtkGraph knows the layout of the graph.
    this->Graph->GetInformation()->Set(
      vtkDataObject::DATA_PIECE_NUMBER(),
      process_id(this->Internals->process_group));
    this->Graph->GetInformation()->Set(
      vtkDataObject::DATA_NUMBER_OF_PIECES(),
      num_processes(this->Internals->process_group));

    // Add our triggers to the process group
    typedef vtkstd::pair<vtkIdType, vtkIdType> IdPair;
    this->Internals->process_group.make_distributed_object();
    this->Internals->process_group.trigger_with_reply<vtkVariant>
      (FIND_VERTEX_TAG,
       boost::bind(&vtkPBGLDistributedGraphHelperInternals::HandleFindVertex,
                   this->Internals, _3));
    this->Internals->process_group.trigger_with_reply<vtkIdType>
      (FIND_EDGE_SOURCE_TARGET_TAG,
       boost::bind(&vtkPBGLDistributedGraphHelperInternals
                     ::HandleFindEdgeSourceTarget,
                   this->Internals, _3));
    this->Internals->process_group.trigger<vtkVariant>
      (ADD_VERTEX_NO_REPLY_TAG,
       boost::bind(&vtkPBGLDistributedGraphHelperInternals::HandleAddVertex,
                   this->Internals, _3));
    this->Internals->process_group.trigger_with_reply<vtkVariant>
      (ADD_VERTEX_WITH_REPLY_TAG,
       boost::bind(&vtkPBGLDistributedGraphHelperInternals::HandleAddVertex,
                   this->Internals, _3));
    this->Internals->process_group.trigger<vtkVariantArray *>
      (ADD_VERTEX_PROPS_NO_REPLY_TAG,
       boost::bind(&vtkPBGLDistributedGraphHelperInternals::HandleAddVertexProps,
                   this->Internals, _3));
    this->Internals->process_group.trigger_with_reply<vtkVariantArray *>
      (ADD_VERTEX_PROPS_WITH_REPLY_TAG,
       boost::bind(&vtkPBGLDistributedGraphHelperInternals::HandleAddVertexProps,
                   this->Internals, _3));
    this->Internals->process_group.trigger<vtkEdgeType>
      (ADD_DIRECTED_BACK_EDGE_TAG,
       boost::bind(&vtkPBGLDistributedGraphHelperInternals::HandleAddBackEdge,
                   this->Internals, _3, true));
    this->Internals->process_group.trigger<vtkEdgeType>
      (ADD_UNDIRECTED_BACK_EDGE_TAG,
       boost::bind(&vtkPBGLDistributedGraphHelperInternals::HandleAddBackEdge,
                   this->Internals, _3, false));

    // Add edge for (id, id) pairs
    this->Internals->process_group.trigger<IdPair>
      (ADD_DIRECTED_EDGE_NO_REPLY_TAG,
       boost::bind(&vtkPBGLDistributedGraphHelperInternals::HandleAddEdge,
                   this->Internals, _3, true));
    this->Internals->process_group.trigger<IdPair>
      (ADD_UNDIRECTED_EDGE_NO_REPLY_TAG,
       boost::bind(&vtkPBGLDistributedGraphHelperInternals::HandleAddEdge,
                   this->Internals, _3, false));
    this->Internals->process_group.trigger_with_reply<IdPair>
      (ADD_DIRECTED_EDGE_WITH_REPLY_TAG,
       boost::bind(&vtkPBGLDistributedGraphHelperInternals::HandleAddEdge,
                   this->Internals, _3, true));
    this->Internals->process_group.trigger_with_reply<IdPair>
      (ADD_UNDIRECTED_EDGE_WITH_REPLY_TAG,
       boost::bind(&vtkPBGLDistributedGraphHelperInternals::HandleAddEdge,
                   this->Internals, _3, false));

    // Add edge for (pedigree, id) pairs
    typedef vtkstd::pair<vtkVariant, vtkIdType> PedigreeIdPair;
    this->Internals->process_group.trigger<PedigreeIdPair>
      (ADD_DIRECTED_EDGE_NI_NO_REPLY_TAG,
       boost::bind(&vtkPBGLDistributedGraphHelperInternals::HandleAddEdgeNI,
                   this->Internals, _3, true));
    this->Internals->process_group.trigger<PedigreeIdPair>
      (ADD_UNDIRECTED_EDGE_NI_NO_REPLY_TAG,
       boost::bind(&vtkPBGLDistributedGraphHelperInternals::HandleAddEdgeNI,
                   this->Internals, _3, false));
    this->Internals->process_group.trigger_with_reply<PedigreeIdPair>
      (ADD_DIRECTED_EDGE_NI_WITH_REPLY_TAG,
       boost::bind(&vtkPBGLDistributedGraphHelperInternals::HandleAddEdgeNI,
                   this->Internals, _3, true));
    this->Internals->process_group.trigger_with_reply<PedigreeIdPair>
      (ADD_UNDIRECTED_EDGE_NI_WITH_REPLY_TAG,
       boost::bind(&vtkPBGLDistributedGraphHelperInternals::HandleAddEdgeNI,
                   this->Internals, _3, false));

    // Add edge for (id, pedigree) pairs
    typedef vtkstd::pair<vtkIdType, vtkVariant> IdPedigreePair;
    this->Internals->process_group.trigger<IdPedigreePair>
      (ADD_DIRECTED_EDGE_IN_NO_REPLY_TAG,
       boost::bind(&vtkPBGLDistributedGraphHelperInternals::HandleAddEdgeIN,
                   this->Internals, _3, true));
    this->Internals->process_group.trigger<IdPedigreePair>
      (ADD_UNDIRECTED_EDGE_IN_NO_REPLY_TAG,
       boost::bind(&vtkPBGLDistributedGraphHelperInternals::HandleAddEdgeIN,
                   this->Internals, _3, false));

    // Add edge for (pedigree, pedigree) pairs
    typedef vtkstd::pair<vtkVariant, vtkVariant> PedigreePedigreePair;
    this->Internals->process_group.trigger<PedigreePedigreePair>
      (ADD_DIRECTED_EDGE_NN_NO_REPLY_TAG,
       boost::bind(&vtkPBGLDistributedGraphHelperInternals::HandleAddEdgeNN,
                   this->Internals, _3, true));
    this->Internals->process_group.trigger<PedigreePedigreePair>
      (ADD_UNDIRECTED_EDGE_NN_NO_REPLY_TAG,
       boost::bind(&vtkPBGLDistributedGraphHelperInternals::HandleAddEdgeNN,
                   this->Internals, _3, false));
    }

  // vtkDistributedGraphHelper will set up the appropriate masks.
  this->Superclass::AttachToGraph(graph);
}

//----------------------------------------------------------------------------
vtkIdType
vtkPBGLDistributedGraphHelperInternals::
HandleFindVertex(const vtkVariant& pedigreeId)
{
  return this->Helper->FindVertex(pedigreeId);
}

//----------------------------------------------------------------------------
vtkstd::pair<vtkIdType, vtkIdType>
vtkPBGLDistributedGraphHelperInternals::
HandleFindEdgeSourceTarget(vtkIdType id)
{
  vtkstd::pair<vtkIdType, vtkIdType> result;
  this->Helper->FindEdgeSourceAndTarget(id, &result.first, &result.second);
  return result;
}

//----------------------------------------------------------------------------
vtkIdType
vtkPBGLDistributedGraphHelperInternals::
HandleAddVertexProps(vtkVariantArray *propArr)
{
  vtkIdType result;
  this->Helper->AddVertexInternal(propArr, &result);
  return result;
}

//----------------------------------------------------------------------------
vtkIdType
vtkPBGLDistributedGraphHelperInternals::
HandleAddVertex(const vtkVariant& pedigreeId)
{
  vtkIdType result;
  this->Helper->AddVertexInternal(pedigreeId, &result);
  return result;
}

//----------------------------------------------------------------------------
void
vtkPBGLDistributedGraphHelperInternals::HandleAddBackEdge
  (vtkEdgeType edge, bool directed)
{
  assert(edge.Source != edge.Target);
  assert(this->Helper->GetVertexOwner(edge.Target)
         == this->Helper->Graph->GetInformation()->Get(vtkDataObject::DATA_PIECE_NUMBER()));
  vtkGraphInternals *GraphInternals = this->Helper->Graph->GetGraphInternals(true);
  if (directed)
    {
    GraphInternals->Adjacency[this->Helper->GetVertexIndex(edge.Target)]
      .InEdges.push_back(vtkInEdgeType(edge.Source, edge.Id));
    }
  else
    {
    GraphInternals->Adjacency[this->Helper->GetVertexIndex(edge.Target)]
      .OutEdges.push_back(vtkOutEdgeType(edge.Source, edge.Id));
    }
}

//----------------------------------------------------------------------------
vtkEdgeType
vtkPBGLDistributedGraphHelperInternals::HandleAddEdge
  (const vtkstd::pair<vtkIdType, vtkIdType>& msg, bool directed)
{
  vtkEdgeType result;
  this->Helper->AddEdgeInternal(msg.first, msg.second, directed, 0, &result);
  return result;
}

//----------------------------------------------------------------------------
vtkEdgeType
vtkPBGLDistributedGraphHelperInternals::HandleAddEdgeNI
  (const vtkstd::pair<vtkVariant, vtkIdType>& msg, bool directed)
{
  vtkEdgeType result;
  this->Helper->AddEdgeInternal(msg.first, msg.second, directed, 0, &result);
  return result;
}

//----------------------------------------------------------------------------
vtkEdgeType
vtkPBGLDistributedGraphHelperInternals::HandleAddEdgeIN
  (const vtkstd::pair<vtkIdType, vtkVariant>& msg, bool directed)
{
  vtkEdgeType result;
  this->Helper->AddEdgeInternal(msg.first, msg.second, directed, 0, &result);
  return result;
}

//----------------------------------------------------------------------------
vtkEdgeType
vtkPBGLDistributedGraphHelperInternals::HandleAddEdgeNN
  (const vtkstd::pair<vtkVariant, vtkVariant>& msg, bool directed)
{
  vtkEdgeType result;
  this->Helper->AddEdgeInternal(msg.first, msg.second, directed, 0, &result);
  return result;
}

//----------------------------------------------------------------------------
// Parallel BGL interface functions
//----------------------------------------------------------------------------

//----------------------------------------------------------------------------
boost::graph::distributed::mpi_process_group
process_group(vtkGraph *graph)
{
  vtkDistributedGraphHelper *helper = graph->GetDistributedGraphHelper();
  if (!helper)
    {
    vtkErrorWithObjectMacro(graph, "A vtkGraph without a distributed graph helper is not a distributed graph");
    return boost::graph::distributed::mpi_process_group();
    }

  vtkPBGLDistributedGraphHelper *pbglHelper
    = vtkPBGLDistributedGraphHelper::SafeDownCast(helper);
  if (!pbglHelper)
    {
    vtkErrorWithObjectMacro(graph, "A vtkGraph with a non-Parallel BGL distributed graph helper cannot be used with the Parallel BGL");
    return boost::graph::distributed::mpi_process_group();
    }

  return pbglHelper->Internals->process_group.base();
}

ext: cxx


text:
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
 * Copyright (c) 2013-2020 Regents of the University of California.
 *
 * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
 *
 * ndn-cxx library is free software: you can redistribute it and/or modify it under the
 * terms of the GNU Lesser General Public License as published by the Free Software
 * Foundation, either version 3 of the License, or (at your option) any later version.
 *
 * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
 * PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more details.
 *
 * You should have received copies of the GNU General Public License and GNU Lesser
 * General Public License along with ndn-cxx, e.g., in COPYING.md file.  If not, see
 * <http://www.gnu.org/licenses/>.
 *
 * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
 */

#ifndef NDN_TESTS_TEST_HOME_FIXTURE_HPP
#define NDN_TESTS_TEST_HOME_FIXTURE_HPP

#include "ndn-cxx/security/key-chain.hpp"

#include <cstdlib>
#include <fstream>
#include <initializer_list>

#include <boost/algorithm/string/replace.hpp>
#include <boost/filesystem.hpp>

#ifdef _WIN32
#define setenv(A, B, C) _putenv_s(A, B)
#define unsetenv(A) _putenv_s(A, "")
#endif

namespace ndn {
namespace tests {

/**
 * @brief Fixture to adjust/restore NDN_CLIENT_PIB and NDN_CLIENT_TPM paths
 *
 * Note that the specified PATH will be removed after fixture is destroyed.
 * **Do not specify non-temporary paths.**
 */
template<class Path>
class PibDirFixture
{
public:
  PibDirFixture()
    : m_pibDir(Path().PATH)
  {
    if (std::getenv("NDN_CLIENT_PIB") != nullptr) {
      m_oldPib = std::getenv("NDN_CLIENT_PIB");
    }
    if (std::getenv("NDN_CLIENT_TPM") != nullptr) {
      m_oldTpm = std::getenv("NDN_CLIENT_TPM");
    }

    /// @todo Consider change to an in-memory PIB/TPM
    setenv("NDN_CLIENT_PIB", ("pib-sqlite3:" + m_pibDir).c_str(), true);
    setenv("NDN_CLIENT_TPM", ("tpm-file:" + m_pibDir).c_str(), true);
  }

  ~PibDirFixture()
  {
    if (!m_oldPib.empty()) {
      setenv("NDN_CLIENT_PIB", m_oldPib.data(), true);
    }
    else {
      unsetenv("NDN_CLIENT_PIB");
    }

    if (!m_oldTpm.empty()) {
      setenv("NDN_CLIENT_TPM", m_oldTpm.data(), true);
    }
    else {
      unsetenv("NDN_CLIENT_TPM");
    }

    boost::filesystem::remove_all(m_pibDir);
    const_cast<std::string&>(KeyChain::getDefaultPibLocator()).clear();
    const_cast<std::string&>(KeyChain::getDefaultTpmLocator()).clear();
  }

protected:
  const std::string m_pibDir;

private:
  std::string m_oldPib;
  std::string m_oldTpm;
};

/**
 * @brief Extension of PibDirFixture to set TEST_HOME variable and allow config file creation
 */
template<class Path>
class TestHomeFixture : public PibDirFixture<Path>
{
public:
  TestHomeFixture()
  {
    setenv("TEST_HOME", this->m_pibDir.c_str(), true);
  }

  ~TestHomeFixture()
  {
    unsetenv("TEST_HOME");
  }

  void
  createClientConf(std::initializer_list<std::string> lines) const
  {
    boost::filesystem::create_directories(boost::filesystem::path(this->m_pibDir) / ".ndn");
    std::ofstream of((boost::filesystem::path(this->m_pibDir) / ".ndn" / "client.conf").c_str());
    for (auto line : lines) {
      boost::replace_all(line, "%PATH%", this->m_pibDir);
      of << line << std::endl;
    }
  }
};

struct DefaultPibDir
{
  const std::string PATH = "build/keys";
};

} // namespace tests
} // namespace ndn

#endif // NDN_TESTS_TEST_HOME_FIXTURE_HPP

ext: hpp

max_stars_repo_name: pulsejet/ndn-cxx

max_issues_repo_name: pulsejet/ndn-cxx

max_forks_repo_name: pulsejet/ndn-cxx


text:
#include "scenebase.hpp"
#include "../text/text.hpp"
#include "../input/input.hpp"
#include "../effect/if.hpp"
#include "../systeminfo.hpp"
#include "../effect/clear.hpp"
#include <boost/format.hpp>

namespace rev::test {
	TestScene::TestScene() {
		_textTech = rev::detail::TextObj::GetDefaultTech();
		{
			// フォント初期化
			FontId fid(16, 0, FontId::CharFlag_AA, false, 100, FontId::SizeType_Pixel);
			fid = mgr_text.appendFaceId("IPAGothic", fid);
			_fps.setFontId(fid);
			_fps.setDepth(0);
			_fps.setWindowOffset({10,30});
		}
		{
			const auto hKb = Keyboard::OpenKeyboard();
			// 終了ボタン定義
			_act[Act::Quit] = mgr_input.makeAction("quit");
			_act[Act::Quit]->addLink(hKb, InputFlag::Button, VKey::Escape);
			// ポーズボタン定義
			_act[Act::Pause] = mgr_input.makeAction("pause");
			_act[Act::Pause]->addLink(hKb, InputFlag::Button, VKey::F1);
		}
	}
	void TestScene::_showFPS(IEffect& e) const {
		// FPSを左上に表示
		e.setTechnique(_textTech);
		_fps.setText((boost::format("FPS: %1%") % mgr_info.getFPS()).str().c_str());
		_fps.draw(e);
	}
	void TestScene::_clearBg(IEffect& e) const {
		// 適当に背景をベタ塗り
		e.clearFramebuffer({frea::Vec4{0.6,0.6,1,0}, 1.f, 0});
	}
}

max_stars_repo_name: degarashi/revenant

max_issues_repo_name: degarashi/revenant

max_forks_repo_name: degarashi/revenant


text:
#ifndef CAFFE_HP_NET_H_
#define CAFFE_HP_NET_H_

#include "caffe/caffe.hpp"
#include "caffe/proto/caffe.pb.h"
#include <boost/shared_ptr.hpp>

#include "caffe/tracker/bounding_box.hpp"

#include <opencv2/core/core.hpp>
#include <opencv2/opencv.hpp>

namespace caffe {

class HPNetWrapper {
public:
  HPNetWrapper(const std::string& proto, const std::string& model);
  HPNetWrapper(const std::string& proto, const std::string& model, float scale);

  int hpmode(const cv::Mat& image, const BoundingBox<float>& roi, float* score);
  void getPoints(const cv::Mat& image, const BoundingBox<float>& roi, float& x1_r, float& y1_r, float& x2_r, float& y2_r);
  void getInputPatch(const cv::Mat& image, cv::Mat& rsz_patch, const BoundingBox<float>& roi);

  float kContextFactor;

private:
  void getCropPatch(const cv::Mat& image, const BoundingBox<float>& roi, cv::Mat* patch);
  void load(const cv::Mat& image);

  boost::shared_ptr<caffe::Net<float> > net_;
};

}

#endif


text:
/**
 * Copyright (c) 2015, Daniella Niyonkuru
 * Carleton 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:
 * 1. Redistributions of source code must retain the above copyright notice,
 * this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright notice,
 * this list of conditions and the following disclaimer in the documentation
 * and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

#ifndef BOOST_SIMULATION_PDEVS_DRIVER_H
#define BOOST_SIMULATION_PDEVS_DRIVER_H
#include <boost/simulation/pdevs/port.hpp>
#include <boost/simulation/model.hpp>
#include "mbed.h"
#include "SWO.h"

namespace boost {
namespace simulation {
namespace pdevs {

/**
 * @brief The coupled class represents PDEVS coupled models
 */
template<class TIME, class MSG>
class driver
{
protected:
    /**
     * @brief The topports_description struct provides the necessary data to retrieve the top ports
     */
	int numberInputPorts;
	std::vector<TIME> previousEventTime;
    struct topports_description{
        std::vector<std::pair<std::shared_ptr<port<TIME,MSG>>, std::shared_ptr<model<TIME>>>> input_ports; //port to model
        std::vector<std::pair<std::shared_ptr<port<TIME,MSG>>, std::shared_ptr<model<TIME>>>> output_ports; // model to port
    };

    topports_description _ports_desc;
public:
    using time_type=TIME;
    using message_type=MSG;
    using description_type=topports_description;
    using Value=int;

    /**
     * @brief driver receives the whole port structure by pointers to ports
     */
    driver( std::vector<std::pair<std::shared_ptr<port<TIME,MSG>>, std::shared_ptr<model<TIME>>>> ip,
		     std::vector<std::pair<std::shared_ptr<port<TIME,MSG>>, std::shared_ptr<model<TIME>>>> op
          ) noexcept
    {
        _ports_desc.input_ports = ip;
        _ports_desc.output_ports = op;
        numberInputPorts = _ports_desc.input_ports.size();
        previousEventTime.assign(numberInputPorts,TIME::currentTime());
        //SWO_PrintString("GLOBAL DRIVER CREATED \n");
    }
    /**
     * @brief get_description provides the ports in a way a coordinator
     * can read to construct the port connection.
     */
    topports_description get_description() noexcept {
        //this is a good place for an assert that port structure is well constructed
        return _ports_desc;
    }

    bool get_hardware_event(MSG& input_message){
        Value portValue;
        std::shared_ptr<model<TIME>> to_model;
        std::shared_ptr<port<TIME,MSG>> current_port;

        bool foundEvent = false;
    	for (auto& ip : _ports_desc.input_ports){
    	    current_port = std::dynamic_pointer_cast<port<TIME, MSG>>(ip.first);

    	    int portIndex = &ip - &_ports_desc.input_ports[0]; // pos contains the position in the vector

    	    if(TIME::currentTime() < previousEventTime[portIndex] + current_port->getPollingPeriod())
    	    	continue; // Go to the next port - it's not time to poll this port yet ;)

    		if(current_port->pDriver(portValue)){
    			to_model = std::dynamic_pointer_cast<model<TIME>>(ip.second);
    			foundEvent = true;
    			previousEventTime[portIndex] = TIME::currentTime();
    			break;
    		}
    	}
    	if(foundEvent){
    		input_message.tm = TIME::currentTime();
    		input_message.to = to_model;
    		input_message.port = current_port->asString();
    		input_message.val = portValue;
    		// Debugging purposes
    		// SWO_PrintString("DRIVER: INPUT MESSAGE \n");
    		input_message.print();

    		return true;
    	}
    	else {
    		return false;
    	}
    }

    bool send_hardware_command(MSG& output_message){
    	std::string port_name = output_message.port;
    	// For debug purposes only
    	// SWO_PrintString("DRIVER: OUTPUT MESSAGE \n");
		output_message.print();

    	Value portValue = output_message.val;
    	for(auto& op : _ports_desc.output_ports){
    		if(op.first->asString() == port_name){
    			op.first->pDriver(portValue);
    		}
    	}
    	return true;
    }

    void initHardware();
    void closeHardware();

};

}
}
}

#endif // BOOST_SIMULATION_PDEVS_COUPLED_H

max_stars_repo_name: romancardenas/cdboost

max_issues_repo_name: romancardenas/cdboost

max_forks_repo_name: romancardenas/cdboost


text:
// Client for basic TCP/IP benchmarks.

#include <arpa/inet.h>
#include <getopt.h>
#include <netdb.h>
#include <netinet/tcp.h>
#include <pthread.h>
#include <sys/epoll.h>
#include <sys/socket.h>
#include <unistd.h>
#include <atomic>
#include <boost/shared_ptr.hpp>
#include <cstring>
#include <iostream>
#include <string>
#include <thread>
#include <unordered_set>
#include <vector>

#include "BenchmarkUtil.h"

// Number of senders.
static int numSenders = 1;

// Number of broadcast receivers.
static int numReceivers = 1;

// Number of parallel ping-pong messages.
static int numMessages = 1;

// Base receiver port.
static int basePort = 8080;

// Message size.
static int msg_size = 2048;

// Power multiplier for the latency array.
// We can record at most 2^26 = 67108864 latencies
static const int kArrayExp = 26;
static const size_t kMaxEntries = (1L << kArrayExp);

// Report latency/throughput stats every interval.
static int measureIntervalMsec = 2000;  // 2sec in ms.

// Total benchmarking time.
static int totalExecTimeMsec = 10000;  // 10sec in ms.

// Broadcast flag.
static bool broadcast = false;

static bool mainFinished = false;  // Control whether to stop the experiment.

// Record latencies in a single big array.
static double* msgLatencies;
// The current index of the msgLatencies array.
static std::atomic<uint32_t> msgLatsArrayIndex;
// The indices for each interval boundary (add a new one every interval).
static std::vector<uint32_t> msgIndices;
// Timestamp of each interval starts, in usec.
static std::vector<uint64_t> timeStampsUsec;

// Barrier used for thread synchronization.
pthread_barrier_t barrier;

/*
 * Setup connections.
 */
int setup_connections(std::vector<int>& socks, const int serverPort,
                      const std::string& serverAddr) {
  // Create epoll fd.
  int epoll_fd = epoll_create1(0);
  if (epoll_fd == -1) {
    std::cerr << "Failed to create epoll file descriptor\n";
    exit(-1);
  }

  // Connect to each receiver.
  for (int i = 0; i < numReceivers; ++i) {
    int sock = socket(AF_INET, SOCK_STREAM, 0);
    struct sockaddr_in serv_addr;
    if (sock < 0) {
      std::cerr << "Socket creation error" << std::endl;
      exit(-1);
    }

    serv_addr.sin_family = AF_INET;
    serv_addr.sin_port = htons(serverPort + i);
    if (inet_pton(AF_INET, serverAddr.c_str(), &serv_addr.sin_addr) <= 0) {
      std::cerr << "Invalid address/ Address not supported" << std::endl;
      exit(-1);
    }

    if (connect(sock, (struct sockaddr*)&serv_addr, sizeof(serv_addr)) < 0) {
      std::cerr << "Connection failed" << std::endl;
      exit(-1);
    }

    // Save socket for later on.
    socks.push_back(sock);

    // Add connection to epoll.
    struct epoll_event event;
    event.events = EPOLLIN;
    event.data.fd = sock;
    if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, sock, &event)) {
      std::cerr << "Failed to add file descriptor to epoll\n";
      exit(-1);
    }
  }

  return epoll_fd;
}

static void BroadcasterThread(const int serverPort,
                              const std::string& serverAddr) {
  std::vector<int> socks;
  struct epoll_event event, events[numReceivers];

  char buffer[msg_size] = {0};

  int epoll_fd = setup_connections(socks, serverPort, serverAddr);

  do {
    uint64_t startTime = BenchmarkUtil::getCurrTimeUsec();

    // Send to all receivers.
    for (int i = 0; i < numReceivers; ++i) {
      int total_sent = 0;
      while (total_sent < msg_size) {
        int sent = write(socks[i], buffer + total_sent, msg_size - total_sent);
        if (sent < 0) {
          std::cerr << "Send failed" << std::endl;
          exit(-1);
        }
        total_sent += sent;
      }
    }

    // Read reply from all receivers.
    int replied = 0;
    while (replied < numReceivers) {
      int event_count = epoll_wait(epoll_fd, events, numReceivers, 600000);
      for (int i = 0; i < event_count; i++) {
        int total_read = 0;
        while (total_read < msg_size) {
          int recvd = read(events[i].data.fd, buffer + total_read,
                           msg_size - total_read);
          if (recvd < 0) {
            std::cerr << "Receive failed" << std::endl;
            exit(-1);
          }
          total_read += recvd;
        }
        ++replied;
      }
    }

    uint64_t endTime = BenchmarkUtil::getCurrTimeUsec();

    // Record the latency.
    auto aryIndex = msgLatsArrayIndex.fetch_add(1);
    if (aryIndex >= kMaxEntries) {
      std::cerr << "Array msgLatencies out of bounds: " << aryIndex
                << std::endl;
      exit(1);
    }
    msgLatencies[aryIndex] = double(endTime - startTime);
  } while (!mainFinished);

  return;
}

/*
 * Sender thread.
 */
static void SenderThread(const int serverPort, const std::string& serverAddr) {
  int ret, sock = 0;
  struct sockaddr_in serv_addr;
  char buffer[msg_size] = {0};

  int opt = 1;
  // Connect to the server.
  if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
    std::cerr << "Socket creation error" << std::endl;
    exit(-1);
  }

  if (setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, &opt, sizeof(opt))) {
    std::cerr << "setsockopt error" << std::endl;
    exit(-1);
  }

  serv_addr.sin_family = AF_INET;
  serv_addr.sin_port = htons(serverPort);
  if (inet_pton(AF_INET, serverAddr.c_str(), &serv_addr.sin_addr) <= 0) {
    std::cerr << "Invalid address/ Address not supported" << std::endl;
    exit(-1);
  }

  if (connect(sock, (struct sockaddr*)&serv_addr, sizeof(serv_addr)) < 0) {
    std::cerr << "Connection failed" << std::endl;
    exit(-1);
  }

  // Wait until all senders have connected.
  pthread_barrier_wait(&barrier);

  // Run a ping-pong loop.
  do {
    uint64_t startTime = BenchmarkUtil::getCurrTimeUsec();
    for (int i = 0; i < numMessages; ++i) {
      int bytes_sent = 0;
      while (bytes_sent < msg_size) {
        int sent = write(sock, buffer + bytes_sent, msg_size - bytes_sent);
        if (sent < 0) {
          std::cerr << "Send failed" << std::endl;
          exit(-1);
        }
        bytes_sent += sent;
      }
    }

    for (int i = 0; i < numMessages; ++i) {
      int bytes_read = 0;
      while (bytes_read < msg_size) {
        int recvd = read(sock, buffer + bytes_read, msg_size - bytes_read);
        if (recvd < 0) {
          std::cerr << "Receive failed" << std::endl;
          exit(-1);
        }
        bytes_read += recvd;
      }
    }
    uint64_t endTime = BenchmarkUtil::getCurrTimeUsec();

    // Record the latency.
    auto aryIndex = msgLatsArrayIndex.fetch_add(1);
    if (aryIndex >= kMaxEntries) {
      std::cerr << "Array msgLatencies out of bounds: " << aryIndex
                << std::endl;
      exit(1);
    }
    msgLatencies[aryIndex] = double(endTime - startTime);
  } while (!mainFinished);

  return;
}

/*
 * Actually run the benchmark.
 */
static bool runBenchmark(const std::string& serverAddr,
                         const std::string& outputFile) {
  mainFinished = false;

  std::vector<std::thread*> senderThreads;  // Parallel senders.

  // Initialize measurement arrays.
  uint64_t currTime = BenchmarkUtil::getCurrTimeUsec();
  timeStampsUsec.push_back(currTime);
  msgLatencies = new double[kMaxEntries];
  memset(msgLatencies, 0, kMaxEntries * sizeof(double));
  msgLatsArrayIndex.store(0);
  msgIndices.push_back(0);

  // Initialize barrier.
  pthread_barrier_init(&barrier, NULL, numSenders);

  // Start sender threads.
  if (broadcast) {
    for (int i = 0; i < numSenders; ++i) {
      senderThreads.push_back(
          new std::thread(&BroadcasterThread, basePort + i, serverAddr));
    }
  } else {
    for (int i = 0; i < numSenders; ++i) {
      senderThreads.push_back(
          new std::thread(&SenderThread, basePort + i, serverAddr));
    }
  }

  currTime = BenchmarkUtil::getCurrTimeUsec();
  uint64_t endTime = currTime + (totalExecTimeMsec * 1000);
  do {
    std::this_thread::sleep_for(std::chrono::milliseconds(measureIntervalMsec));
    std::cerr << "runBenchmark recording performance...\n";
    currTime = BenchmarkUtil::getCurrTimeUsec();
    msgIndices.push_back(msgLatsArrayIndex.load());
    timeStampsUsec.push_back(currTime);
  } while (currTime < endTime);

  mainFinished = true;
  for (int i = 0; i < numSenders; ++i) {
    senderThreads[i]->join();
    delete senderThreads[i];
  }

  // Processing the results.
  std::cerr << "Post processing results...\n";
  bool res = BenchmarkUtil::processResults(
      msgLatencies, msgIndices, timeStampsUsec, outputFile, "TCP/IP ping-pong");
  if (!res) {
    std::cerr << "[Warning]: failed to write results to " << outputFile << "\n";
  }

  // Clean up.
  delete[] msgLatencies;
  msgLatencies = nullptr;
  timeStampsUsec.clear();
  return true;
}

static void Usage(char** argv, const std::string& msg = "") {
  if (!msg.empty()) { std::cerr << "ERROR: " << msg << std::endl; }
  std::cerr << "Usage: " << argv[0] << "[options]\n";
  std::cerr << "\t-h: show this message\n";
  std::cerr << "\t-b: run broadcast benchmark\n";
  std::cerr << "\t-o <output log file path>: default "
            << "message_results.csv\n";
  std::cerr << "\t-s <comma-separated list of servers>: default 'localhost'\n";
  std::cerr << "\t-p <port number>: default " << basePort << std::endl;
  std::cerr << "\t-i <measurement interval>: default " << measureIntervalMsec
            << " msec\n";
  std::cerr << "\t-t <total execution time>: default " << totalExecTimeMsec
            << " msec\n";
  std::cerr << "\t-N <number of parallel senders (threads)>: default "
            << numSenders << "\n";
  std::cerr << "\t-M <number of parallel ping-pong messages>: default "
            << numMessages << "\n";
  std::cerr << "\t-m <message size>: default " << msg_size << std::endl;
  std::cerr
      << "\t-R <number of receivers> used only when broadcasting: default "
      << numReceivers << "\n";
  // Print all options here.

  std::cerr << std::endl;
  exit(1);
}

int main(int argc, char** argv) {
  std::string serverAddr("127.0.0.1");
  std::string outputFile("message_results.csv");

  // Parse input arguments and prepare for the experiment.
  int opt;
  while ((opt = getopt(argc, argv, "hbo:s:p:i:t:N:M:m:R:")) != -1) {
    switch (opt) {
      case 'o':
        outputFile = optarg;
        break;
      case 's':
        serverAddr = optarg;
        break;
      case 'p':
        basePort = atoi(optarg);
        break;
      case 'i':
        measureIntervalMsec = atoi(optarg);
        break;
      case 't':
        totalExecTimeMsec = atoi(optarg);
        break;
      case 'N':
        numSenders = atoi(optarg);
        break;
      case 'M':
        numMessages = atoi(optarg);
        break;
      case 'm':
        msg_size = atoi(optarg);
        break;
      case 'b':
        broadcast = true;
        break;
      case 'R':
        numReceivers = atoi(optarg);
        break;
      case 'h':
      default:
        Usage(argv);
        break;
    }
  }

  std::cerr << "Parallel sender threads: " << numSenders << std::endl;
  std::cerr << "Parallel outstanding messages: " << numMessages << std::endl;
  std::cerr << "Message size: " << msg_size << " bytes" << std::endl;
  std::cerr << "Output log file: " << outputFile << std::endl;
  std::cerr << "Server address: " << serverAddr << std::endl;
  std::cerr << "Base port: " << basePort << std::endl;
  std::cerr << "Measurement interval: " << measureIntervalMsec << " msec\n";
  std::cerr << "Total execution time: " << totalExecTimeMsec << " msec\n";
  if (broadcast) {
    std::cerr << "Broadcasting to " << numReceivers << " receivers\n";
  }

  // Run experiments and parse results.
  bool res = runBenchmark(serverAddr, outputFile);
  if (!res) {
    std::cerr << "Failed to run benchmark." << std::endl;
    exit(1);
  }

  return 0;
}

ext: cc

max_stars_repo_name: DBOS-project/dbos-scheduler

max_issues_repo_name: DBOS-project/dbos-scheduler

max_forks_repo_name: DBOS-project/dbos-scheduler


text:
#include "catch.hpp"

#undef NDEBUG

#include <boost/numeric/ublas/io.hpp>
#include "IntaRNA/AccessibilityBasePair.h"

using namespace IntaRNA;

TEST_CASE("AccessibilityBasePair", "[AccessibilityBasePair]") {

	// setup easylogging++ stuff if not already done
	#include "testEasyLoggingSetup.icc"

  SECTION("ED test long") {

	const std::string seq = "gguccacguccaa";
	RnaSequence rna("test", seq);
	AccessibilityBasePair acc(rna, 10, NULL);

//    std::cout <<"\n\n########\n";
//    for (int i =0; i<acc.getSequence().size(); i++) {
//    	std::cout <<(i);
//    	for (int j=0; j <acc.getSequence().size(); j++) {
//    		if (j<i) {
//    			std::cout <<" ---";
//    		} else {
//    			std::cout <<" "<<acc.getED(i,j);
//    		}
//    	}
//    	std::cout <<std::endl;
//    }
//    std::cout <<"########\n";

    REQUIRE( E_equal( acc.getED(0, 6), 452 ) );
    REQUIRE( E_equal( acc.getED(0, 12), 584 ) );
    REQUIRE( E_equal( acc.getED(1, 3), 237 ) );
    REQUIRE( E_equal( acc.getED(1, 5), 275 ) );
    REQUIRE( E_equal( acc.getED(3, 4), 51 ) );
    REQUIRE( E_equal( acc.getED(4, 7), 197 ) );
    REQUIRE( E_equal( acc.getED(4, 12), 584 ) );
    REQUIRE( E_equal( acc.getED(5, 5), 0) );
    REQUIRE( E_equal( acc.getED(5, 10), 362 ) );
    REQUIRE( E_equal( acc.getED(6, 6), 13 ) );
    REQUIRE( E_equal( acc.getED(10, 11), 55 ) );
    REQUIRE( E_equal( acc.getED(11, 12), 19 ) );

  }

  SECTION("ED test short") {

	const std::string seq = "GG";
	RnaSequence rna("test", seq);
	AccessibilityBasePair acc(rna, 2, NULL);

	REQUIRE( E_equal( acc.getED(0, 0), 0 ) );
	REQUIRE( E_equal( acc.getED(1, 1), 0 ) );
	REQUIRE( E_equal( acc.getED(0, 1), 0 ) );

  }
}

max_stars_repo_name: simonbray/IntaRNA

max_issues_repo_name: simonbray/IntaRNA

max_forks_repo_name: BackofenLab/IntaRNA