<commit_before>/******************************************************************************
 * Copyright 2017 The Apollo Authors. All Rights Reserved.
 *
 * 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.
 *****************************************************************************/

/**
 * @file
 **/

#include "modules/planning/lattice/trajectory_generation/end_condition_sampler.h"

#include <algorithm>
#include <utility>

#include "modules/common/log.h"
#include "modules/planning/common/planning_gflags.h"

namespace apollo {
namespace planning {

EndConditionSampler::EndConditionSampler(
    const std::array<double, 3>& init_s, const std::array<double, 3>& init_d,
    std::shared_ptr<PathTimeGraph> ptr_path_time_graph,
    std::shared_ptr<PredictionQuerier> ptr_prediction_querier)
    : init_s_(init_s),
      init_d_(init_d),
      feasible_region_(init_s),
      ptr_path_time_graph_(std::move(ptr_path_time_graph)),
      ptr_prediction_querier_(std::move(ptr_prediction_querier)) {}

std::vector<std::pair<std::array<double, 3>, double>>
EndConditionSampler::SampleLatEndConditions() const {
  std::vector<std::pair<std::array<double, 3>, double>> end_d_conditions;
  std::array<double, 3> end_d_candidates = {0.0, -0.5, 0.5};
  std::array<double, 4> end_s_candidates = {10.0, 20.0, 40.0, 80.0};

  for (const auto& s : end_s_candidates) {
    for (const auto& d : end_d_candidates) {
      std::array<double, 3> end_d_state = {d, 0.0, 0.0};
      end_d_conditions.emplace_back(end_d_state, s);
    }
  }
  return end_d_conditions;
}

std::vector<std::pair<std::array<double, 3>, double>>
EndConditionSampler::SampleLonEndConditionsForCruising(
    const double ref_cruise_speed) const {
  CHECK_GT(FLAGS_num_velocity_sample, 1);

  // time interval is one second plus the last one 0.01
  constexpr std::size_t num_of_time_samples = 9;
  std::array<double, num_of_time_samples> time_samples;
  for (std::size_t i = 0; i + 1 < num_of_time_samples; ++i) {
    time_samples[i] = FLAGS_trajectory_time_length - i;
  }
  time_samples[num_of_time_samples - 1] = FLAGS_polynomial_minimal_param;

  std::vector<std::pair<std::array<double, 3>, double>> end_s_conditions;
  for (const auto& time : time_samples) {
    double v_upper = std::min(feasible_region_.VUpper(time), ref_cruise_speed);
    double v_lower = feasible_region_.VLower(time);

    std::array<double, 3> lower_end_s = {0.0, v_lower, 0.0};
    end_s_conditions.emplace_back(lower_end_s, time);

    std::array<double, 3> upper_end_s = {0.0, v_upper, 0.0};
    end_s_conditions.emplace_back(upper_end_s, time);

    double v_range = v_upper - v_lower;
    // Number of sample velocities
    std::size_t num_of_mid_points = std::min(
        static_cast<std::size_t>(FLAGS_num_velocity_sample - 2),
        static_cast<std::size_t>(v_range / FLAGS_min_velocity_sample_gap));

    if (num_of_mid_points > 0) {
      double velocity_seg = v_range / (num_of_mid_points + 1);
      for (std::size_t i = 1; i <= num_of_mid_points; ++i) {
        std::array<double, 3> end_s = {0.0, v_lower + velocity_seg * i, 0.0};
        end_s_conditions.emplace_back(end_s, time);
      }
    }
  }
  return end_s_conditions;
}

std::vector<std::pair<std::array<double, 3>, double>>
EndConditionSampler::SampleLonEndConditionsForStopping(
    const double ref_stop_point) const {
  // time interval is one second plus the last one 0.01
  constexpr std::size_t num_time_section = 9;
  std::array<double, num_time_section> time_sections;
  for (std::size_t i = 0; i + 1 < num_time_section; ++i) {
    time_sections[i] = FLAGS_trajectory_time_length - i;
  }
  time_sections[num_time_section - 1] = FLAGS_polynomial_minimal_param;

  constexpr std::size_t num_stop_section = 3;
  std::array<double, num_stop_section> s_offsets;
  for (std::size_t i = 0; i < num_stop_section; ++i) {
    s_offsets[i] = -static_cast<double>(i);
  }

  std::vector<std::pair<std::array<double, 3>, double>> end_s_conditions;
  for (const auto& time : time_sections) {
    if (time < FLAGS_polynomial_minimal_param) {
      continue;
    }
    for (const auto& s_offset : s_offsets) {
      std::array<double, 3> end_s = {
          std::max(init_s_[0], ref_stop_point + s_offset), 0.0, 0.0};
      end_s_conditions.emplace_back(end_s, time);
    }
  }
  return end_s_conditions;
}

std::vector<std::pair<std::array<double, 3>, double>>
EndConditionSampler::SampleLonEndConditionsForPathTimePoints() const {
  std::vector<SamplePoint> sample_points = QueryPathTimeObstacleSamplePoints();
  std::vector<std::pair<std::array<double, 3>, double>> end_s_conditions;
  for (const SamplePoint& sample_point : sample_points) {
    if (sample_point.path_time_point().t() < FLAGS_polynomial_minimal_param) {
      continue;
    }
    double s = sample_point.path_time_point().s();
    double v = sample_point.ref_v();
    double t = sample_point.path_time_point().t();
    if (s > feasible_region_.SUpper(t) || s < feasible_region_.SLower(t)) {
      continue;
    }
    std::array<double, 3> end_state = {s, v, 0.0};
    end_s_conditions.emplace_back(end_state, t);
  }
  return end_s_conditions;
}

std::vector<SamplePoint>
EndConditionSampler::QueryPathTimeObstacleSamplePoints() const {
  const auto& vehicle_config =
      common::VehicleConfigHelper::instance()->GetConfig();
  std::vector<SamplePoint> sample_points;
  for (const auto& path_time_obstacle :
       ptr_path_time_graph_->GetPathTimeObstacles()) {
    std::string obstacle_id = path_time_obstacle.obstacle_id();
    QueryFollowPathTimePoints(vehicle_config, obstacle_id, &sample_points);
    QueryOvertakePathTimePoints(vehicle_config, obstacle_id, &sample_points);
  }
  return sample_points;
}

void EndConditionSampler::QueryFollowPathTimePoints(
    const apollo::common::VehicleConfig& vehicle_config,
    const std::string& obstacle_id,
    std::vector<SamplePoint>* const sample_points) const {
  std::vector<PathTimePoint> follow_path_time_points =
      ptr_path_time_graph_->GetObstacleSurroundingPoints(
          obstacle_id, -FLAGS_lattice_epsilon, FLAGS_time_min_density);
  for (const PathTimePoint& path_time_point : follow_path_time_points) {
    double v = ptr_prediction_querier_->ProjectVelocityAlongReferenceLine(
        obstacle_id, path_time_point.s(), path_time_point.t());
    // Generate candidate s
    double s_upper = path_time_point.s() -
                     vehicle_config.vehicle_param().front_edge_to_center();
    double s_lower = s_upper - FLAGS_default_lon_buffer;
    CHECK_GE(FLAGS_num_sample_follow_per_timestamp, 2);
    double s_gap = FLAGS_default_lon_buffer /
                   static_cast<double>(FLAGS_num_sample_follow_per_timestamp);
    for (std::size_t i = 0; i < FLAGS_num_sample_follow_per_timestamp; ++i) {
      double s = s_lower + s_gap * static_cast<double>(i);
      SamplePoint sample_point;
      sample_point.mutable_path_time_point()->CopyFrom(path_time_point);
      sample_point.mutable_path_time_point()->set_s(s);
      sample_point.set_ref_v(v);
      sample_points->push_back(std::move(sample_point));
    }
  }
}

void EndConditionSampler::QueryOvertakePathTimePoints(
    const apollo::common::VehicleConfig& vehicle_config,
    const std::string& obstacle_id,
    std::vector<SamplePoint>* sample_points) const {
  std::vector<PathTimePoint> overtake_path_time_points =
      ptr_path_time_graph_->GetObstacleSurroundingPoints(
          obstacle_id, FLAGS_lattice_epsilon, FLAGS_time_min_density);
  for (const PathTimePoint& path_time_point : overtake_path_time_points) {
    double v = ptr_prediction_querier_->ProjectVelocityAlongReferenceLine(
        obstacle_id, path_time_point.s(), path_time_point.t());
    SamplePoint sample_point;
    sample_point.mutable_path_time_point()->CopyFrom(path_time_point);
    sample_point.mutable_path_time_point()->set_s(path_time_point.s() +
                                                  FLAGS_default_lon_buffer);
    sample_point.set_ref_v(v);
    sample_points->push_back(std::move(sample_point));
  }
}

}  // namespace planning
}  // namespace apollo
<commit_msg>planning: restructured end_condition_sampler<commit_after>/******************************************************************************
 * Copyright 2017 The Apollo Authors. All Rights Reserved.
 *
 * 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.
 *****************************************************************************/

/**
 * @file
 **/

#include "modules/planning/lattice/trajectory_generation/end_condition_sampler.h"

#include <algorithm>
#include <utility>

#include "modules/common/log.h"
#include "modules/planning/common/planning_gflags.h"

namespace apollo {
namespace planning {

using State = std::array<double, 3>;
using Condition = std::pair<State, double>;

EndConditionSampler::EndConditionSampler(
    const State& init_s, const State& init_d,
    std::shared_ptr<PathTimeGraph> ptr_path_time_graph,
    std::shared_ptr<PredictionQuerier> ptr_prediction_querier)
    : init_s_(init_s),
      init_d_(init_d),
      feasible_region_(init_s),
      ptr_path_time_graph_(std::move(ptr_path_time_graph)),
      ptr_prediction_querier_(std::move(ptr_prediction_querier)) {}

std::vector<Condition> EndConditionSampler::SampleLatEndConditions() const {
  std::vector<Condition> end_d_conditions;
  std::array<double, 3> end_d_candidates = {0.0, -0.5, 0.5};
  std::array<double, 4> end_s_candidates = {10.0, 20.0, 40.0, 80.0};

  for (const auto& s : end_s_candidates) {
    for (const auto& d : end_d_candidates) {
      State end_d_state = {d, 0.0, 0.0};
      end_d_conditions.emplace_back(end_d_state, s);
    }
  }
  return end_d_conditions;
}

std::vector<Condition> EndConditionSampler::SampleLonEndConditionsForCruising(
    const double ref_cruise_speed) const {
  CHECK_GT(FLAGS_num_velocity_sample, 1);

  // time interval is one second plus the last one 0.01
  constexpr std::size_t num_of_time_samples = 9;
  std::array<double, num_of_time_samples> time_samples;
  for (std::size_t i = 0; i + 1 < num_of_time_samples; ++i) {
    time_samples[i] = FLAGS_trajectory_time_length - i;
  }
  time_samples[num_of_time_samples - 1] = FLAGS_polynomial_minimal_param;

  std::vector<Condition> end_s_conditions;
  for (const auto& time : time_samples) {
    double v_upper = std::min(feasible_region_.VUpper(time), ref_cruise_speed);
    double v_lower = feasible_region_.VLower(time);

    State lower_end_s = {0.0, v_lower, 0.0};
    end_s_conditions.emplace_back(lower_end_s, time);

    State upper_end_s = {0.0, v_upper, 0.0};
    end_s_conditions.emplace_back(upper_end_s, time);

    double v_range = v_upper - v_lower;
    // Number of sample velocities
    std::size_t num_of_mid_points = std::min(
        static_cast<std::size_t>(FLAGS_num_velocity_sample - 2),
        static_cast<std::size_t>(v_range / FLAGS_min_velocity_sample_gap));

    if (num_of_mid_points > 0) {
      double velocity_seg = v_range / (num_of_mid_points + 1);
      for (std::size_t i = 1; i <= num_of_mid_points; ++i) {
        State end_s = {0.0, v_lower + velocity_seg * i, 0.0};
        end_s_conditions.emplace_back(end_s, time);
      }
    }
  }
  return end_s_conditions;
}

std::vector<Condition> EndConditionSampler::SampleLonEndConditionsForStopping(
    const double ref_stop_point) const {
  // time interval is one second plus the last one 0.01
  constexpr std::size_t num_time_section = 9;
  std::array<double, num_time_section> time_sections;
  for (std::size_t i = 0; i + 1 < num_time_section; ++i) {
    time_sections[i] = FLAGS_trajectory_time_length - i;
  }
  time_sections[num_time_section - 1] = FLAGS_polynomial_minimal_param;

  std::vector<Condition> end_s_conditions;
  for (const auto& time : time_sections) {
    State end_s = {std::max(init_s_[0], ref_stop_point), 0.0, 0.0};
    end_s_conditions.emplace_back(end_s, time);
  }
  return end_s_conditions;
}

std::vector<Condition>
EndConditionSampler::SampleLonEndConditionsForPathTimePoints() const {
  std::vector<Condition> end_s_conditions;

  std::vector<SamplePoint> sample_points = QueryPathTimeObstacleSamplePoints();
  for (const SamplePoint& sample_point : sample_points) {
    if (sample_point.path_time_point().t() < FLAGS_polynomial_minimal_param) {
      continue;
    }
    double s = sample_point.path_time_point().s();
    double v = sample_point.ref_v();
    double t = sample_point.path_time_point().t();
    if (s > feasible_region_.SUpper(t) || s < feasible_region_.SLower(t)) {
      continue;
    }
    State end_state = {s, v, 0.0};
    end_s_conditions.emplace_back(end_state, t);
  }
  return end_s_conditions;
}

std::vector<SamplePoint>
EndConditionSampler::QueryPathTimeObstacleSamplePoints() const {
  const auto& vehicle_config =
      common::VehicleConfigHelper::instance()->GetConfig();
  std::vector<SamplePoint> sample_points;
  for (const auto& path_time_obstacle :
       ptr_path_time_graph_->GetPathTimeObstacles()) {
    std::string obstacle_id = path_time_obstacle.obstacle_id();
    QueryFollowPathTimePoints(vehicle_config, obstacle_id, &sample_points);
    QueryOvertakePathTimePoints(vehicle_config, obstacle_id, &sample_points);
  }
  return sample_points;
}

void EndConditionSampler::QueryFollowPathTimePoints(
    const common::VehicleConfig& vehicle_config,
    const std::string& obstacle_id,
    std::vector<SamplePoint>* const sample_points) const {
  std::vector<PathTimePoint> follow_path_time_points =
      ptr_path_time_graph_->GetObstacleSurroundingPoints(
          obstacle_id, -FLAGS_lattice_epsilon, FLAGS_time_min_density);

  for (const auto& path_time_point : follow_path_time_points) {
    double v = ptr_prediction_querier_->ProjectVelocityAlongReferenceLine(
        obstacle_id, path_time_point.s(), path_time_point.t());
    // Generate candidate s
    double s_upper = path_time_point.s() -
                     vehicle_config.vehicle_param().front_edge_to_center();
    double s_lower = s_upper - FLAGS_default_lon_buffer;
    CHECK_GE(FLAGS_num_sample_follow_per_timestamp, 2);
    double s_gap = FLAGS_default_lon_buffer
        / static_cast<double>(FLAGS_num_sample_follow_per_timestamp - 1);
    for (std::size_t i = 0; i < FLAGS_num_sample_follow_per_timestamp; ++i) {
      double s = s_lower + s_gap * static_cast<double>(i);
      SamplePoint sample_point;
      sample_point.mutable_path_time_point()->CopyFrom(path_time_point);
      sample_point.mutable_path_time_point()->set_s(s);
      sample_point.set_ref_v(v);
      sample_points->push_back(std::move(sample_point));
    }
  }
}

void EndConditionSampler::QueryOvertakePathTimePoints(
    const common::VehicleConfig& vehicle_config,
    const std::string& obstacle_id,
    std::vector<SamplePoint>* sample_points) const {
  std::vector<PathTimePoint> overtake_path_time_points =
      ptr_path_time_graph_->GetObstacleSurroundingPoints(
          obstacle_id, FLAGS_lattice_epsilon, FLAGS_time_min_density);

  for (const auto& path_time_point : overtake_path_time_points) {
    double v = ptr_prediction_querier_->ProjectVelocityAlongReferenceLine(
        obstacle_id, path_time_point.s(), path_time_point.t());
    SamplePoint sample_point;
    sample_point.mutable_path_time_point()->CopyFrom(path_time_point);
    sample_point.mutable_path_time_point()->set_s(path_time_point.s() +
                                                  FLAGS_default_lon_buffer);
    sample_point.set_ref_v(v);
    sample_points->push_back(std::move(sample_point));
  }
}

}  // namespace planning
}  // namespace apollo
<|endoftext|>


<commit_before>#define NEW_MIB_COMPLIANT true

#include <iomanip>
#include <iostream>
#include <stdint.h>
#include <cstdlib>
#include <string>
#include <sstream>
#include <vector>

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

#include <unistd.h>
#include <stropts.h>

#include <cstring>

#include <sys/tihdr.h>
#include <inet/mib2.h>

class buffer_t
{
	public:
		char buffer[512];
		strbuf buf;

		buffer_t()
		{
			memset(buffer,0,512);
			buf.buf=(char*)buffer;
			buf.len=512;
		}
};

struct request_t
{
	public:
		request_t()
		{
			req_header.PRIM_type=T_SVR4_OPTMGMT_REQ;
			req_header.OPT_length=sizeof(opt_header);
			req_header.OPT_offset=offsetof(request_t,opt_header);
			req_header.MGMT_flags=T_CURRENT;
			opt_header.level=MIB2_IP;
			opt_header.name=0;
			opt_header.len=0;
		}

		T_optmgmt_req req_header;
		opthdr opt_header;
};

struct reply_t
{
	T_optmgmt_ack ack_header;
	opthdr opt_header;
};

std::string uint32_t_to_ipv4(const uint32_t address)
{
        std::ostringstream ostr;
        ostr<<(uint32_t)((uint8_t*)&address)[0]<<"."<<
                (uint32_t)((uint8_t*)&address)[1]<<"."<<
                (uint32_t)((uint8_t*)&address)[2]<<"."<<
                (uint32_t)((uint8_t*)&address)[3];
        return ostr.str();
}

std::string uint8_t_16_to_ipv6(const uint8_t address[16])
{
        std::ostringstream ostr;
        for(int ii=0;ii<16;ii+=2)
        {
                ostr<<std::hex<<std::setw(2)<<std::setfill('0')<<(unsigned int)(unsigned char)address[ii+0];
                ostr<<std::hex<<std::setw(2)<<std::setfill('0')<<(unsigned int)(unsigned char)address[ii+1];

                if(ii<14)
                        ostr<<":";
        }

        return ostr.str();
}

std::string dword_to_port(const uint32_t port)
{
        std::ostringstream ostr;
        ostr<<((((uint32_t)((uint8_t*)&port)[0])<<8)+((uint8_t*)&port)[1]);
        return ostr.str();
}

std::string to_string(const uint32_t val)
{
        std::ostringstream ostr;
        ostr<<val;
        return ostr.str();
}

std::string state_int_to_string(const uint32_t state)
{
	if(state==MIB2_TCP_established)
		return "ESTABLISHED";
	if(state==MIB2_TCP_synSent)
		return "SYN_SENT";
	if(state==MIB2_TCP_synReceived)
		return "SYN_RECV";
	if(state==MIB2_TCP_finWait1)
		return "FIN_WAIT1";
	if(state==MIB2_TCP_finWait2)
		return "FIN_WAIT2";
	if(state==MIB2_TCP_timeWait)
		return "TIME_WAIT";
	if(state==MIB2_TCP_closed)
		return "CLOSE";
	if(state==MIB2_TCP_closeWait)
		return "CLOSE_WAIT";
	if(state==MIB2_TCP_lastAck)
		return "LAST_ACK";
	if(state==MIB2_TCP_listen)
		return "LISTEN";
	if(state==MIB2_TCP_closing||state==MIB2_TCP_deleteTCB)
		return "CLOSING";

	return "UNKNOWN";
}

struct netstat_t
{
        std::string proto;
        std::string local_address;
        std::string foreign_address;
        std::string local_port;
        std::string foreign_port;
        std::string state;
        std::string inode;
        std::string pid;
};

typedef std::vector<netstat_t> netstat_list_t;

void netstat_print(const netstat_t& netstat)
{
        std::cout<<
                std::setw(4)<<netstat.proto<<" "<<
                std::setw(64)<<netstat.local_address+":"+netstat.local_port<<" "<<
                std::setw(64)<<netstat.foreign_address+":"+netstat.foreign_port<<" "<<
                std::setw(16)<<netstat.state<<" "<<
                std::setw(8)<<netstat.pid<<" "<<
                std::endl;
}

void netstat_list_print(const netstat_list_t& netstats)
{
        std::cout<<
                std::setw(4)<<"proto "<<
                std::setw(64)<<"local_address "<<
                std::setw(64)<<"foreign_address "<<
                std::setw(16)<<"state "<<
                std::setw(8)<<"pid "<<
                std::endl;

        for(size_t ii=0;ii<netstats.size();++ii)
                netstat_print(netstats[ii]);
}

int main()
{
	int fd=open("/dev/arp",O_RDWR);

	if(fd==-1)
		return 1;

	if(ioctl(fd,I_PUSH,"tcp")==-1)
		return 1;

	if(ioctl(fd,I_PUSH,"udp")==-1)
		return 1;

	request_t request;

	strbuf buf;
	buf.len=sizeof(request);
	buf.buf=(char*)&request;

	if(putmsg(fd,&buf,NULL,0)<0)
		return 1;

	netstat_list_t tcp4;
	netstat_list_t tcp6;
	netstat_list_t udp4;
	netstat_list_t udp6;

	while(true)
	{
		strbuf buf2;
		int flags=0;
		reply_t reply;
		buf2.maxlen=sizeof(reply);
		buf2.buf=(char*)&reply;
		int ret=getmsg(fd,&buf2,NULL,&flags);

		if(ret<0)
		{
			std::cout<<"ret<0"<<std::endl;
			return 1;
		}

		if(ret!=MOREDATA)
			break;

		if(reply.ack_header.PRIM_type!=T_OPTMGMT_ACK)
		{
			std::cout<<"primtype"<<std::endl;
			return 1;
		}

		if((unsigned int)buf2.len<sizeof(reply.ack_header))
		{
			std::cout<<"buf2len"<<std::endl;
			return 1;
		}

		if((unsigned int)reply.ack_header.OPT_length<sizeof(reply.opt_header))
		{
			std::cout<<"optlength"<<std::endl;
			return 1;
		}

		void* data=malloc(reply.opt_header.len);

		if(data==NULL)
			return 1;

		buf2.maxlen=reply.opt_header.len;
		buf2.buf=(char*)data;
		flags=0;

		if(getmsg(fd,NULL,&buf2,&flags)>=0)
		{
			if(reply.opt_header.level==MIB2_TCP&&reply.opt_header.name==MIB2_TCP_CONN)
			{
				for(int ii=0;ii<buf2.len;ii+=sizeof(mib2_tcpConnEntry_t)+4)
				{
					mib2_tcpConnEntry_t* entry=(mib2_tcpConnEntry_t*)((char*)data+ii);

					netstat_t netstat;
					netstat.proto="tcp4";
					netstat.local_address=uint32_t_to_ipv4(entry->tcpConnLocalAddress);
					netstat.foreign_address=uint32_t_to_ipv4(entry->tcpConnRemAddress);
					netstat.local_port=dword_to_port(htons(entry->tcpConnLocalPort));
					netstat.foreign_port=dword_to_port(htons(entry->tcpConnRemPort));
					netstat.state=state_int_to_string(entry->tcpConnState);
					netstat.pid="-";

					#if(defined(NEW_MIB_COMPLIANT)||defined(_KERNEL))
						netstat.pid=to_string(entry->tcpConnCreationProcess);
					#endif

					/*tcp4.push_back(netstat);
					for(int jj=15;jj>=0;--jj)
						std::cout<<std::hex<<std::setw(2)<<std::setfill('0')<<(unsigned int)(unsigned char)((char*)entry)[sizeof(mib2_tcpConnEntry_t)+jj];
					std::cout<<std::setfill(' ')<<std::endl;*/
				}
			}

			#if(defined(MIB2_TCP6))
				if(reply.opt_header.level==MIB2_TCP6&&reply.opt_header.name==MIB2_TCP6_CONN)
				{
					for(int ii=0;ii<buf2.len;ii+=sizeof(mib2_tcp6ConnEntry_t)+4)
					{
						mib2_tcp6ConnEntry_t* entry=(mib2_tcp6ConnEntry_t*)((char*)data+ii);

						netstat_t netstat;
						netstat.proto="tcp6";
						netstat.local_address=uint8_t_16_to_ipv6(entry->tcp6ConnLocalAddress.s6_addr);
						netstat.foreign_address=uint8_t_16_to_ipv6(entry->tcp6ConnRemAddress.s6_addr);
						netstat.local_port=dword_to_port(htons(entry->tcp6ConnLocalPort));
						netstat.foreign_port=dword_to_port(htons(entry->tcp6ConnRemPort));
						netstat.state=state_int_to_string(entry->tcp6ConnState);
						netstat.pid="-";

						#if(defined(NEW_MIB_COMPLIANT)||defined(_KERNEL))
							netstat.pid=to_string(entry->tcp6ConnCreationProcess);
						#endif

						tcp6.push_back(netstat);
					}
				}
			#endif

			if(reply.opt_header.level==MIB2_UDP&&reply.opt_header.name==MIB2_UDP_ENTRY)
			{
				for(int ii=0;ii<buf2.len;ii+=sizeof(mib2_udpEntry_t)+4)
				{
					mib2_udpEntry_t* entry=(mib2_udpEntry_t*)((char*)data+ii);

					netstat_t netstat;
					netstat.proto="udp4";
					netstat.local_address=uint32_t_to_ipv4(entry->udpLocalAddress);
					netstat.foreign_address="0.0.0.0";
					netstat.local_port=dword_to_port(htons(entry->udpLocalPort));
					netstat.foreign_port="0";
					netstat.state="-";
					netstat.pid="-";

					#if(defined(NEW_MIB_COMPLIANT)||defined(_KERNEL))
						netstat.pid=to_string(entry->udpCreationProcess);
					#endif

					udp4.push_back(netstat);
				}
			}

			#if(defined(MIB2_UDP6))
				if(reply.opt_header.level==MIB2_UDP6&&reply.opt_header.name==MIB2_UDP6_ENTRY)
				{
					for(int ii=0;ii<buf2.len;ii+=sizeof(mib2_udp6Entry_t)+4)
					{
						mib2_udp6Entry_t* entry=(mib2_udp6Entry_t*)((char*)data+ii);

						netstat_t netstat;
						netstat.proto="udp6";
						netstat.local_address=uint8_t_16_to_ipv6(entry->udp6LocalAddress.s6_addr);
						netstat.foreign_address="0000:0000:0000:0000:0000:0000:0000:0000";
						netstat.local_port=dword_to_port(htons(entry->udp6LocalPort));
						netstat.foreign_port="0";
						netstat.state="-";
						netstat.pid="-";

						#if(defined(NEW_MIB_COMPLIANT)||defined(_KERNEL))
							netstat.pid=to_string(entry->udp6CreationProcess);
						#endif

						udp6.push_back(netstat);
					}
				}
			#endif
		}

		free(data);
	}

	netstat_list_t netstats;

        for(size_t ii=0;ii<tcp4.size();++ii)
                netstats.push_back(tcp4[ii]);
        for(size_t ii=0;ii<tcp6.size();++ii)
                netstats.push_back(tcp6[ii]);
        for(size_t ii=0;ii<udp4.size();++ii)
                netstats.push_back(udp4[ii]);
        for(size_t ii=0;ii<udp6.size();++ii)
                netstats.push_back(udp6[ii]);

	netstat_list_print(netstats);

	return 0;
}
<commit_msg>Padding issue seemed to be a bad install of g++ on solaris 11.2...<commit_after>#include <iomanip>
#include <iostream>
#include <stdint.h>
#include <cstdlib>
#include <string>
#include <sstream>
#include <vector>

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

#include <unistd.h>
#include <stropts.h>

#include <cstring>

#include <sys/tihdr.h>
#include <inet/mib2.h>

class buffer_t
{
	public:
		char buffer[512];
		strbuf buf;

		buffer_t()
		{
			memset(buffer,0,512);
			buf.buf=(char*)buffer;
			buf.len=512;
		}
};

struct request_t
{
	public:
		request_t()
		{
			req_header.PRIM_type=T_SVR4_OPTMGMT_REQ;
			req_header.OPT_length=sizeof(opt_header);
			req_header.OPT_offset=offsetof(request_t,opt_header);
			req_header.MGMT_flags=T_CURRENT;
			opt_header.level=MIB2_IP;
			opt_header.name=0;
			opt_header.len=0;
		}

		T_optmgmt_req req_header;
		opthdr opt_header;
};

struct reply_t
{
	T_optmgmt_ack ack_header;
	opthdr opt_header;
};

std::string uint32_t_to_ipv4(const uint32_t address)
{
        std::ostringstream ostr;
        ostr<<(uint32_t)((uint8_t*)&address)[0]<<"."<<
                (uint32_t)((uint8_t*)&address)[1]<<"."<<
                (uint32_t)((uint8_t*)&address)[2]<<"."<<
                (uint32_t)((uint8_t*)&address)[3];
        return ostr.str();
}

std::string uint8_t_16_to_ipv6(const uint8_t address[16])
{
        std::ostringstream ostr;
        for(int ii=0;ii<16;ii+=2)
        {
                ostr<<std::hex<<std::setw(2)<<std::setfill('0')<<(unsigned int)(unsigned char)address[ii+0];
                ostr<<std::hex<<std::setw(2)<<std::setfill('0')<<(unsigned int)(unsigned char)address[ii+1];

                if(ii<14)
                        ostr<<":";
        }

        return ostr.str();
}

std::string dword_to_port(const uint32_t port)
{
        std::ostringstream ostr;
        ostr<<((((uint32_t)((uint8_t*)&port)[0])<<8)+((uint8_t*)&port)[1]);
        return ostr.str();
}

std::string to_string(const uint32_t val)
{
        std::ostringstream ostr;
        ostr<<val;
        return ostr.str();
}

std::string state_int_to_string(const uint32_t state)
{
	if(state==MIB2_TCP_established)
		return "ESTABLISHED";
	if(state==MIB2_TCP_synSent)
		return "SYN_SENT";
	if(state==MIB2_TCP_synReceived)
		return "SYN_RECV";
	if(state==MIB2_TCP_finWait1)
		return "FIN_WAIT1";
	if(state==MIB2_TCP_finWait2)
		return "FIN_WAIT2";
	if(state==MIB2_TCP_timeWait)
		return "TIME_WAIT";
	if(state==MIB2_TCP_closed)
		return "CLOSE";
	if(state==MIB2_TCP_closeWait)
		return "CLOSE_WAIT";
	if(state==MIB2_TCP_lastAck)
		return "LAST_ACK";
	if(state==MIB2_TCP_listen)
		return "LISTEN";
	if(state==MIB2_TCP_closing||state==MIB2_TCP_deleteTCB)
		return "CLOSING";

	return "UNKNOWN";
}

struct netstat_t
{
        std::string proto;
        std::string local_address;
        std::string foreign_address;
        std::string local_port;
        std::string foreign_port;
        std::string state;
        std::string inode;
        std::string pid;
};

typedef std::vector<netstat_t> netstat_list_t;

void netstat_print(const netstat_t& netstat)
{
        std::cout<<
                std::setw(4)<<netstat.proto<<" "<<
                std::setw(64)<<netstat.local_address+":"+netstat.local_port<<" "<<
                std::setw(64)<<netstat.foreign_address+":"+netstat.foreign_port<<" "<<
                std::setw(16)<<netstat.state<<" "<<
                std::setw(8)<<netstat.pid<<" "<<
                std::endl;
}

void netstat_list_print(const netstat_list_t& netstats)
{
        std::cout<<
                std::setw(4)<<"proto "<<
                std::setw(64)<<"local_address "<<
                std::setw(64)<<"foreign_address "<<
                std::setw(16)<<"state "<<
                std::setw(8)<<"pid "<<
                std::endl;

        for(size_t ii=0;ii<netstats.size();++ii)
                netstat_print(netstats[ii]);
}

int main()
{
	int fd=open("/dev/arp",O_RDWR);

	if(fd==-1)
		return 1;

	if(ioctl(fd,I_PUSH,"tcp")==-1)
		return 1;

	if(ioctl(fd,I_PUSH,"udp")==-1)
		return 1;

	request_t request;

	strbuf buf;
	buf.len=sizeof(request);
	buf.buf=(char*)&request;

	if(putmsg(fd,&buf,NULL,0)<0)
		return 1;

	netstat_list_t tcp4;
	netstat_list_t tcp6;
	netstat_list_t udp4;
	netstat_list_t udp6;

	while(true)
	{
		strbuf buf2;
		int flags=0;
		reply_t reply;
		buf2.maxlen=sizeof(reply);
		buf2.buf=(char*)&reply;
		int ret=getmsg(fd,&buf2,NULL,&flags);

		if(ret<0)
		{
			std::cout<<"ret<0"<<std::endl;
			return 1;
		}

		if(ret!=MOREDATA)
			break;

		if(reply.ack_header.PRIM_type!=T_OPTMGMT_ACK)
		{
			std::cout<<"primtype"<<std::endl;
			return 1;
		}

		if((unsigned int)buf2.len<sizeof(reply.ack_header))
		{
			std::cout<<"buf2len"<<std::endl;
			return 1;
		}

		if((unsigned int)reply.ack_header.OPT_length<sizeof(reply.opt_header))
		{
			std::cout<<"optlength"<<std::endl;
			return 1;
		}

		void* data=malloc(reply.opt_header.len);

		if(data==NULL)
			return 1;

		buf2.maxlen=reply.opt_header.len;
		buf2.buf=(char*)data;
		flags=0;

		if(getmsg(fd,NULL,&buf2,&flags)>=0)
		{
			if(reply.opt_header.level==MIB2_TCP&&reply.opt_header.name==MIB2_TCP_CONN)
			{
				for(int ii=0;ii<buf2.len;ii+=sizeof(mib2_tcpConnEntry_t))
				{
					mib2_tcpConnEntry_t* entry=(mib2_tcpConnEntry_t*)((char*)data+ii);

					netstat_t netstat;
					netstat.proto="tcp4";
					netstat.local_address=uint32_t_to_ipv4(entry->tcpConnLocalAddress);
					netstat.foreign_address=uint32_t_to_ipv4(entry->tcpConnRemAddress);
					netstat.local_port=dword_to_port(htons(entry->tcpConnLocalPort));
					netstat.foreign_port=dword_to_port(htons(entry->tcpConnRemPort));
					netstat.state=state_int_to_string(entry->tcpConnState);
					netstat.pid="-";

					#if(defined(NEW_MIB_COMPLIANT)||defined(_KERNEL))
						netstat.pid=to_string(entry->tcpConnCreationProcess);
					#endif
				}
			}

			#if(defined(MIB2_TCP6))
				if(reply.opt_header.level==MIB2_TCP6&&reply.opt_header.name==MIB2_TCP6_CONN)
				{
					for(int ii=0;ii<buf2.len;ii+=sizeof(mib2_tcp6ConnEntry_t))
					{
						mib2_tcp6ConnEntry_t* entry=(mib2_tcp6ConnEntry_t*)((char*)data+ii);

						netstat_t netstat;
						netstat.proto="tcp6";
						netstat.local_address=uint8_t_16_to_ipv6(entry->tcp6ConnLocalAddress.s6_addr);
						netstat.foreign_address=uint8_t_16_to_ipv6(entry->tcp6ConnRemAddress.s6_addr);
						netstat.local_port=dword_to_port(htons(entry->tcp6ConnLocalPort));
						netstat.foreign_port=dword_to_port(htons(entry->tcp6ConnRemPort));
						netstat.state=state_int_to_string(entry->tcp6ConnState);
						netstat.pid="-";

						#if(defined(NEW_MIB_COMPLIANT)||defined(_KERNEL))
							netstat.pid=to_string(entry->tcp6ConnCreationProcess);
						#endif

						tcp6.push_back(netstat);
					}
				}
			#endif

			if(reply.opt_header.level==MIB2_UDP&&reply.opt_header.name==MIB2_UDP_ENTRY)
			{
				for(int ii=0;ii<buf2.len;ii+=sizeof(mib2_udpEntry_t))
				{
					mib2_udpEntry_t* entry=(mib2_udpEntry_t*)((char*)data+ii);

					netstat_t netstat;
					netstat.proto="udp4";
					netstat.local_address=uint32_t_to_ipv4(entry->udpLocalAddress);
					netstat.foreign_address="0.0.0.0";
					netstat.local_port=dword_to_port(htons(entry->udpLocalPort));
					netstat.foreign_port="0";
					netstat.state="-";
					netstat.pid="-";

					#if(defined(NEW_MIB_COMPLIANT)||defined(_KERNEL))
						netstat.pid=to_string(entry->udpCreationProcess);
					#endif

					udp4.push_back(netstat);
				}
			}

			#if(defined(MIB2_UDP6))
				if(reply.opt_header.level==MIB2_UDP6&&reply.opt_header.name==MIB2_UDP6_ENTRY)
				{
					for(int ii=0;ii<buf2.len;ii+=sizeof(mib2_udp6Entry_t))
					{
						mib2_udp6Entry_t* entry=(mib2_udp6Entry_t*)((char*)data+ii);

						netstat_t netstat;
						netstat.proto="udp6";
						netstat.local_address=uint8_t_16_to_ipv6(entry->udp6LocalAddress.s6_addr);
						netstat.foreign_address="0000:0000:0000:0000:0000:0000:0000:0000";
						netstat.local_port=dword_to_port(htons(entry->udp6LocalPort));
						netstat.foreign_port="0";
						netstat.state="-";
						netstat.pid="-";

						#if(defined(NEW_MIB_COMPLIANT)||defined(_KERNEL))
							netstat.pid=to_string(entry->udp6CreationProcess);
						#endif

						udp6.push_back(netstat);
					}
				}
			#endif
		}

		free(data);
	}

	netstat_list_t netstats;

        for(size_t ii=0;ii<tcp4.size();++ii)
                netstats.push_back(tcp4[ii]);
        for(size_t ii=0;ii<tcp6.size();++ii)
                netstats.push_back(tcp6[ii]);
        for(size_t ii=0;ii<udp4.size();++ii)
                netstats.push_back(udp4[ii]);
        for(size_t ii=0;ii<udp6.size();++ii)
                netstats.push_back(udp6[ii]);

	netstat_list_print(netstats);

	return 0;
}
<|endoftext|>


<commit_before>/*

    OF-TangibleFramework . Framework for Taller de Sistemes Interactius I
    Universitat Pompeu Fabra

    Copyright (c) 2009 Carles F. Julià <carles.fernandez@upf.edu>

    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.

*/

#ifndef INPUTGESTUREDIRECTFINGERS_H_INCLUDED
#define INPUTGESTUREDIRECTFINGERS_H_INCLUDED

#include "InputGesture.hpp"
#include "TEvent.hpp"
#include "tuioApp.hpp"
#include "DirectPoint.hpp"
#include "InputGestureBasicFingers.hpp"
#include <map>

using namespace osc;

namespace tuio
{

class DirectFinger: public DirectPoint
{
    public:
    int32 s_id;
    float xspeed, yspeed, maccel;
};

class TeventDirectFingersRemoveFinger : public TTEvent<TeventDirectFingersRemoveFinger>
{
    public:
    int32 s_id;
};

class TeventDirectFingersNewFinger : public TTEvent<TeventDirectFingersNewFinger>
{
    public:
    int32 s_id;
    DirectFinger * df;
};

class InputGestureDirectFingers : public CanBasicFingers < CompositeGesture >
{
    std::map<int32,DirectFinger *> fingers;
    public:
        InputGestureDirectFingers(){}
        void addTuioCursor(int32 id, float xpos,float ypos,float xspeed,float yspeed,float maccel)
        {
            DirectFinger * e = new DirectFinger();
            e->s_id = id;
            e->setX(xpos);
            e->setY(ypos);
            e->xspeed = xspeed;
            e->yspeed = yspeed;
            e->maccel = maccel;
            fingers[id]=e;
            TeventDirectFingersNewFinger * evt = new TeventDirectFingersNewFinger();
            evt->s_id = id;
            evt->df = e;
            events.push_back(evt);
        }
        void updateTuioCursor(int32 id, float xpos,float ypos,float xspeed,float yspeed,float maccel)
        {
             DirectFinger * e = fingers[id];
            e->s_id = id;
            e->set(xpos,ypos);
            e->xspeed = xspeed;
            e->yspeed = yspeed;
            e->maccel = maccel;
        }
        void removeTuioCursor(int32 id)
        {
             TeventDirectFingersRemoveFinger * evt = new TeventDirectFingersRemoveFinger();
             evt->s_id = id;
             events.push_back(evt);
        }
};

template <class Base>
class CanDirectFingers : public  Base
{
    public:
    //Interface redefined by ofApp
    virtual void newCursor(int32 id, DirectFinger *){}
    virtual void removeCursor(int32 id){}

    //processing events callbacks

    TEventHandler(TeventDirectFingersRemoveFinger)
    {
        TeventDirectFingersRemoveFinger * e = static_cast<TeventDirectFingersRemoveFinger *>(evt);
        removeCursor(e->s_id);
    }
    TEventHandler(TeventDirectFingersNewFinger)
    {
        TeventDirectFingersNewFinger * e = static_cast<TeventDirectFingersNewFinger *>(evt);
        newCursor(e->s_id,e->df);
    }

    //registering
    CanDirectFingers()
    {
        TRegistraCallback(CanDirectFingers,TeventDirectFingersRemoveFinger);
        TRegistraCallback(CanDirectFingers,TeventDirectFingersNewFinger);
        Base::registerInputGesture(Singleton<InputGestureDirectFingers>::get());
    }

};

}
#endif // INPUTGESTUREDIRECTFINGERS_H_INCLUDED
<commit_msg>Adapting InputGestureDirectFingers to the new event system<commit_after>/*

    OF-TangibleFramework . Framework for Taller de Sistemes Interactius I
    Universitat Pompeu Fabra

    Copyright (c) 2009 Carles F. Julià <carles.fernandez@upf.edu>

    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.

*/

#ifndef INPUTGESTUREDIRECTFINGERS_H_INCLUDED
#define INPUTGESTUREDIRECTFINGERS_H_INCLUDED

#include "InputGesture.hpp"
#include "TEvent.hpp"
#include "tuioApp.hpp"
#include "DirectPoint.hpp"
#include "InputGestureBasicFingers.hpp"
#include <map>

using namespace osc;

namespace tuio
{

class DirectFinger: public DirectPoint
{
    public:
    int32 s_id;
    float xspeed, yspeed, maccel;
};

DeclareEvent(TeventDirectFingersRemoveFinger,int32);
DeclareEvent(TeventDirectFingersNewFinger,int32,DirectFinger *);
DeclareEvent(TeventDirectFingersUpdateFinger,int32);

class InputGestureDirectFingers : public CanBasicFingers < CompositeGesture >
{
    std::map<int32,DirectFinger *> fingers;
    public:
        InputGestureDirectFingers(){}
        void addTuioCursor(int32 id, float xpos,float ypos,float xspeed,float yspeed,float maccel)
        {
            DirectFinger * e = new DirectFinger();
            e->s_id = id;
            e->setX(xpos);
            e->setY(ypos);
            e->xspeed = xspeed;
            e->yspeed = yspeed;
            e->maccel = maccel;
            fingers[id]=e;
            TeventDirectFingersNewFinger * evt = makeEvent(TeventDirectFingersNewFinger,(id,e));
            events.push_back(evt);
        }
        void updateTuioCursor(int32 id, float xpos,float ypos,float xspeed,float yspeed,float maccel)
        {
             DirectFinger * e = fingers[id];
            e->s_id = id;
            e->set(xpos,ypos);
            e->xspeed = xspeed;
            e->yspeed = yspeed;
            e->maccel = maccel;
            events.push_back(makeEvent(TeventDirectFingersUpdateFinger,(id)));
        }
        void removeTuioCursor(int32 id)
        {
             TeventDirectFingersRemoveFinger * evt = makeEvent(TeventDirectFingersRemoveFinger,(id));
             events.push_back(evt);
        }
};

template <class Base>
class CanDirectFingers : public  Base
{
    public:
    //Interface redefined by ofApp
    virtual void newCursor(int32 id, DirectFinger *){}
    virtual void removeCursor(int32 id){}
    virtual void updateCursor(int32 id){}

    //registering
    CanDirectFingers()
    {
        TeventDirectFingersRemoveFinger::registerCallback(this,&CanDirectFingers::removeCursor);
        TeventDirectFingersNewFinger::registerCallback(this,&CanDirectFingers::newCursor);
        TeventDirectFingersUpdateFinger::registerCallback(this,&CanDirectFingers::updateCursor);
        Base::template registerIG<InputGestureDirectFingers>();
    }

};

}
#endif // INPUTGESTUREDIRECTFINGERS_H_INCLUDED
<|endoftext|>


<commit_before>/*
This file is part of Groho, a simulator for inter-planetary travel and warfare.
Copyright (c) 2017, 2018 by Kaushik Ghose. Some rights reserved, see LICENSE

This handles the downsampling of the data
*/

#pragma once

#include "vector.hpp"

#define LOGURU_WITH_STREAMS 1
#include "loguru.hpp"

namespace sim {

class FractalDownsampler {
public:
    FractalDownsampler(double rt = 1.001, double lt = 1e6)
        : ratio_threshold(rt)
        , linear_threshold(lt)
    {
    }

    bool operator()(const Vector& v)
    {
        cumulative_curve_dist += (v - last_v).norm();
        double linear_dist = (v - last_sample_v).norm();

        if (((cumulative_curve_dist / linear_dist) > ratio_threshold)
            | (abs(cumulative_curve_dist - linear_dist) > linear_threshold)) {
            accept_sample(v);
            return true;
        }
        last_v = v;
        return false;
    }

private:
    void accept_sample(const Vector& v)
    {
        cumulative_curve_dist = 0;
        last_sample_v         = v;
        last_v                = v;
    }

    double cumulative_curve_dist = 0;
    Vector last_sample_v         = { 0, 0, 0 };
    Vector last_v                = { 0, 0, 0 };
    double ratio_threshold       = 1.001;
    double linear_threshold      = 1e6;
};

} // namespace sim<commit_msg>Update to work with V3d<commit_after>/*
This file is part of Groho, a simulator for inter-planetary travel and warfare.
Copyright (c) 2017, 2018 by Kaushik Ghose. Some rights reserved, see LICENSE

This handles the downsampling of the data
*/

#pragma once

#include "v3d.hpp"

#define LOGURU_WITH_STREAMS 1
#include "loguru.hpp"

namespace groho {

class FractalDownsampler {
public:
    FractalDownsampler(double rt = 1.001, double lt = 1e6)
        : ratio_threshold(rt)
        , linear_threshold(lt)
    {
    }

    bool operator()(const V3d& v)
    {
        cumulative_curve_dist += (v - last_v).norm();
        double linear_dist = (v - last_sample_v).norm();

        if (((cumulative_curve_dist / linear_dist) > ratio_threshold)
            | (abs(cumulative_curve_dist - linear_dist) > linear_threshold)) {
            accept_sample(v);
            return true;
        }
        last_v = v;
        return false;
    }

private:
    void accept_sample(const V3d& v)
    {
        cumulative_curve_dist = 0;
        last_sample_v         = v;
        last_v                = v;
    }

    double cumulative_curve_dist = 0;
    V3d    last_sample_v         = { 0, 0, 0 };
    V3d    last_v                = { 0, 0, 0 };
    double ratio_threshold       = 1.001;
    double linear_threshold      = 1e6;
};

} // namespace sim<|endoftext|>


<commit_before>/*
 * Copyright (C) 2008-2012, Gostai S.A.S.
 *
 * This software is provided "as is" without warranty of any kind,
 * either expressed or implied, including but not limited to the
 * implied warranties of fitness for a particular purpose.
 *
 * See the LICENSE file for more information.
 */

#include <kernel/config.h>
#if HAVE_SYS_INOTIFY_H
# include <sys/inotify.h>
#endif

#include <libport/cassert>
#include <libport/compiler.hh>
#include <libport/dirent.h>
#include <libport/exception.hh>
#include <libport/format.hh>
#include <libport/lockable.hh>
#include <libport/path.hh>
#include <libport/sys/types.h>
#include <libport/thread.hh>

#include <urbi/kernel/userver.hh>

#include <urbi/object/date.hh>
#include <urbi/object/directory.hh>
#include <urbi/object/global.hh>
#include <urbi/object/path.hh>
#include <urbi/object/symbols.hh>

#include <urbi/runner/raise.hh>

#include <libport/cstdio>

namespace boostfs = boost::filesystem;

using libport::BlockLock;

namespace urbi
{
  namespace object
  {
    /*----------.
    | Helpers.  |
    `----------*/

    ATTRIBUTE_NORETURN
    static void
    raise_boost_fs_error(boostfs::filesystem_error& e)
    {
      RAISE(libport::format_error(e));
    }

    static void
    check_empty(const Directory& dir)
    {
      if (!dir.empty())
        FRAISE("directory not empty: %s", dir.as_string());
    }

    /*--------------.
    | C++ methods.  |
    `--------------*/

    Directory::value_type
    Directory::value_get()
    {
      return path_;
    }

    /*---------------------.
    | urbiscript methods.  |
    `---------------------*/

#if HAVE_SYS_INOTIFY_H
    // Event polling thread
    typedef std::pair<rObject, rObject> _watch_map_elem_t;
    typedef boost::unordered_map<unsigned, _watch_map_elem_t> _watch_map_t;
    static _watch_map_t _watch_map;
    static libport::Lockable _watch_map_lock;
    static int _watch_fd;

    ATTRIBUTE_NORETURN
    static
    void poll()
    {
      while (true)
      {
        static const size_t name_size_max = 1024;
        static const size_t evt_size = sizeof(inotify_event);
        static const size_t buf_size = evt_size + name_size_max;

        char buffer[buf_size];
        const int len = read(_watch_fd, &buffer, buf_size);
        if (len < 0)
        {
          if (errno == EINTR)
            continue;
          else
            errnoabort("read failed");
        }
        int i = 0;
        {
          KERNEL_BLOCK_LOCK();
          while (i < len)
          {
            inotify_event& evt = reinterpret_cast<inotify_event&>(buffer[i]);
            i += evt_size + evt.len;

            rObject event;
            {
              // TODO: This lock doesn't seems to be needed because the
              // kernel lock is already locked by the synchronization point.
              BlockLock lock(_watch_map_lock);
              aver(libport::has(_watch_map, evt.wd));
              if (evt.mask & IN_CREATE)
                event = _watch_map[evt.wd].first;
              else if (evt.mask & IN_DELETE)
                event = _watch_map[evt.wd].second;
              //FIXME: Do something with those...
              else if (evt.mask & IN_DELETE_SELF)
                ;
              else if (evt.mask & IN_MOVED_FROM)
                ;
              else if (evt.mask & IN_MOVED_TO)
                ;
              else if (evt.mask & IN_MODIFY)
                ;
              else if (evt.mask & IN_IGNORED)
                ;
              else
                GD_FWARN("unrecognized inotify event %s", evt.mask);
            }

            if (event)
            {
              // FIXME: objects are refcounted and urbiserver->schedule is not
              // thread safe.
              object::objects_type args;
              args << new object::String(evt.name);
              ::kernel::urbiserver->schedule(event, SYMBOL(emit), args);
            }
          }
        }
      }
    }
#endif

    // Construction

    Directory::Directory()
      : path_(new Path("/"))
    {
      proto_add(proto);
    }

    Directory::Directory(rDirectory model)
      : path_(model.get()->path_)
    {
      proto_add(model);
      create_events();
    }

    Directory::Directory(const std::string& value)
      : path_(new Path(value))
    {
      proto_add(proto ? rObject(proto) : Object::proto);
    }

    Directory::Directory(rPath path)
      : path_(path)
    {
      proto_add(proto ? rObject(proto) : Object::proto);
    }

    OVERLOAD_TYPE(directory_init_bouncer, 1, 1,
                  Path,
                  (void (Directory::*)(rPath)) &Directory::init,
                  String,
                  (void (Directory::*)(const std::string&)) &Directory::init);

    URBI_CXX_OBJECT_INIT(Directory)
      : path_(new Path())
    {
      BIND(asList, list<&directory_mk_path>);
      BIND(asPath, as_path);
      BIND(asPrintable, as_printable);
      BIND(asString, as_string);
      BIND(clear);
      BINDG(current);
      BINDG(content, list<&directory_mk_string>);
      BIND(create);
      BIND(createAll, create_all);
      BINDG(empty);
      BINDG(exists);
      BINDG(parent);
      BIND(remove);
      BIND(removeAll_, remove_all);

      setSlot(SYMBOL(init),   new Primitive(&directory_init_bouncer));
    }

    void Directory::init(rPath path)
    {
      path->check_directory();

      path_ = path;

#if HAVE_SYS_INOTIFY_H
      static bool started = false;
      if (!started)
      {
        _watch_fd = inotify_init();
        if (_watch_fd == -1)
          FRAISE("cannot start inotify: %s", libport::strerror(errno));
        libport::startThread(boost::function0<void>(poll),
                             PTHREAD_STACK_MIN);
        started = true;
      }

      int watch = inotify_add_watch(_watch_fd, path->as_string().c_str(),
                                    IN_CREATE | IN_DELETE);
      if (watch == -1)
        FRAISE("cannot watch directory: %s", libport::strerror(errno));
      {
        _watch_map_elem_t events(on_file_created_, on_file_deleted_);
        libport::BlockLock lock(_watch_map_lock);
        std::pair<_watch_map_t::iterator, bool> res =
          _watch_map.insert(_watch_map_t::value_type(watch, events));

        // inotify return a uniq identifier per path.  If events are
        // registered we just re-use them instead.  This is fine as long as
        // Directory are not mutable.
        if (!res.second)
        {
          // Update the directory references.
          events = res.first->second;
          on_file_created_ = events.first;
          on_file_deleted_ = events.second;
          // update the slots to make the modification visible in Urbiscript.
          slot_update(SYMBOL(fileCreated), on_file_created_, false);
          slot_update(SYMBOL(fileDeleted), on_file_deleted_, false);
        }
      }
#endif
    }

    void
    Directory::init(const std::string& path)
    {
      init(new Path(path));
    }

    rObject
    Directory::create(rObject, rPath path)
    {
      return create_directory(path);
    }

    rDirectory
    Directory::create_directory(rPath path)
    {
      bool created = false;
      path->check_directory(false);

      try
      {
        created = boostfs::create_directory(path->as_string().c_str());
      }
      catch (boostfs::filesystem_error& e)
      {
        raise_boost_fs_error(e);
      }

      // Should not be raised as check is done before creating directory.
      if (!created)
        FRAISE("no directory was effectively created: %s",
               path->as_string());

      return instanciate_directory(path->as_string());
    }

    void
    Directory::create_all_recursive(rPath path)
    {
      if (path->exists())
        path->check_directory();
      if (!path->is_root())
      {
        rPath parent = path->parent();
        if (parent->as_string() != Path::cwd()->as_string())
          create_all_recursive(parent);
      }
      if (!path->exists())
        create_directory(path);
    }

    rObject
    Directory::create_all(rObject, rPath path)
    {
      create_all_recursive(path);
      return instanciate_directory(path);
    }

    // Modifiers
    rPath
    Directory::as_path() const
    {
      return path_;
    }

    void
    Directory::clear()
    {
      boostfs::path p = path_->as_string().c_str();
      boostfs::directory_iterator end_itr;
      for (boostfs::directory_iterator itr(p);
           itr != end_itr;
           ++itr)
        boostfs::remove_all(itr->path());
    }

    bool
    Directory::empty() const
    {
      try
      {
        return boostfs::is_empty(path_->as_string().c_str());
      }
      catch (boostfs::filesystem_error& e)
      {
        raise_boost_fs_error(e);
      }
    }

    bool
    Directory::exists() const
    {
      return path_->exists();
    }

    rDirectory
    Directory::parent() const
    {
      return instanciate_directory(new Path(path_->parent()));
    }

    void
    Directory::remove()
    {
      check_empty(*this);
      try
      {
        boostfs::remove_all(path_->as_string());
      }
      catch (boostfs::filesystem_error& e)
      {
        raise_boost_fs_error(e);
      }
    }

    void
    Directory::remove_all()
    {
      path_->check_exists();
      boostfs::remove_all(boostfs::path(path_->as_string()));
    }

    /*---------------------.
    | Global information.  |
    `---------------------*/

    rDirectory
    Directory::current()
    {
      return instanciate_directory(Path::cwd());
    }

    rDirectory
    Directory::instanciate_directory(rPath path)
    {
      rDirectory dir = new Directory;
      dir->create_events();
      dir->init(path);
      return dir;
    }

    rDirectory
    Directory::instanciate_directory(const std::string& name)
    {
      return instanciate_directory(new Path(name));
    }

    void
    Directory::create_events()
    {
#if HAVE_SYS_INOTIFY_H
      CAPTURE_GLOBAL(Event);
      on_file_created_ = Event->call("new");
      slot_set_value(SYMBOL(fileCreated), on_file_created_);
      on_file_deleted_ = Event->call("new");
      slot_set_value(SYMBOL(fileDeleted), on_file_deleted_);
#endif
    }

    /*--------------.
    | Conversions.  |
    `--------------*/

    std::string
    Directory::as_string() const
    {
      return path_->as_string();
    }

    std::string
    Directory::as_printable() const
    {
      return libport::format("Directory(\"%s\")", path_->as_string());
    }

    // Stat
    template <rObject (*F) (Directory& d, const std::string& entry)>
    rList Directory::list()
    {
      List::value_type res;
      DIR* dir = opendir(path_->value_get().to_string().c_str());

      // There is already an appropriate error handling done for Path.
      // We can use it if we need it.
      if (!dir)
        path_->handle_any_error();

      while (dirent* entry = readdir(dir))
      {
        if (!entry)
          path_->handle_any_error();
        std::string name = entry->d_name;
        if (name == "." || name == "..")
          continue;
        res << F(*this, name);
      }

      closedir(dir);
      return new List(res);
    }

    rObject
    directory_mk_string(Directory&, const std::string& entry)
    {
      return new String(entry);
    }

    rObject
    directory_mk_path(Directory& d, const std::string& entry)
    {
      return new Path(d.value_get()->value_get() / entry);
    }

    template
    rList Directory::list<directory_mk_string>();
    template
    rList Directory::list<directory_mk_path>();
  }
}
<commit_msg>Directory: Add missing GD.<commit_after>/*
 * Copyright (C) 2008-2012, Gostai S.A.S.
 *
 * This software is provided "as is" without warranty of any kind,
 * either expressed or implied, including but not limited to the
 * implied warranties of fitness for a particular purpose.
 *
 * See the LICENSE file for more information.
 */

#include <kernel/config.h>
#if HAVE_SYS_INOTIFY_H
# include <sys/inotify.h>
#endif

#include <libport/cassert>
#include <libport/compiler.hh>
#include <libport/dirent.h>
#include <libport/exception.hh>
#include <libport/format.hh>
#include <libport/lockable.hh>
#include <libport/path.hh>
#include <libport/sys/types.h>
#include <libport/thread.hh>

#include <urbi/kernel/userver.hh>

#include <urbi/object/date.hh>
#include <urbi/object/directory.hh>
#include <urbi/object/global.hh>
#include <urbi/object/path.hh>
#include <urbi/object/symbols.hh>

#include <urbi/runner/raise.hh>

#include <libport/cstdio>

namespace boostfs = boost::filesystem;

using libport::BlockLock;

GD_CATEGORY(Urbi.Directory);

namespace urbi
{
  namespace object
  {
    /*----------.
    | Helpers.  |
    `----------*/

    ATTRIBUTE_NORETURN
    static void
    raise_boost_fs_error(boostfs::filesystem_error& e)
    {
      RAISE(libport::format_error(e));
    }

    static void
    check_empty(const Directory& dir)
    {
      if (!dir.empty())
        FRAISE("directory not empty: %s", dir.as_string());
    }

    /*--------------.
    | C++ methods.  |
    `--------------*/

    Directory::value_type
    Directory::value_get()
    {
      return path_;
    }

    /*---------------------.
    | urbiscript methods.  |
    `---------------------*/

#if HAVE_SYS_INOTIFY_H
    // Event polling thread
    typedef std::pair<rObject, rObject> _watch_map_elem_t;
    typedef boost::unordered_map<unsigned, _watch_map_elem_t> _watch_map_t;
    static _watch_map_t _watch_map;
    static libport::Lockable _watch_map_lock;
    static int _watch_fd;

    ATTRIBUTE_NORETURN
    static
    void poll()
    {
      while (true)
      {
        static const size_t name_size_max = 1024;
        static const size_t evt_size = sizeof(inotify_event);
        static const size_t buf_size = evt_size + name_size_max;

        char buffer[buf_size];
        const int len = read(_watch_fd, &buffer, buf_size);
        if (len < 0)
        {
          if (errno == EINTR)
            continue;
          else
            errnoabort("read failed");
        }
        int i = 0;
        {
          KERNEL_BLOCK_LOCK();
          while (i < len)
          {
            inotify_event& evt = reinterpret_cast<inotify_event&>(buffer[i]);
            i += evt_size + evt.len;

            rObject event;
            {
              // TODO: This lock doesn't seems to be needed because the
              // kernel lock is already locked by the synchronization point.
              BlockLock lock(_watch_map_lock);
              aver(libport::has(_watch_map, evt.wd));
              if (evt.mask & IN_CREATE)
                event = _watch_map[evt.wd].first;
              else if (evt.mask & IN_DELETE)
                event = _watch_map[evt.wd].second;
              //FIXME: Do something with those...
              else if (evt.mask & IN_DELETE_SELF)
                ;
              else if (evt.mask & IN_MOVED_FROM)
                ;
              else if (evt.mask & IN_MOVED_TO)
                ;
              else if (evt.mask & IN_MODIFY)
                ;
              else if (evt.mask & IN_IGNORED)
                ;
              else
                GD_FWARN("unrecognized inotify event %s", evt.mask);
            }

            if (event)
            {
              // FIXME: objects are refcounted and urbiserver->schedule is not
              // thread safe.
              object::objects_type args;
              args << new object::String(evt.name);
              ::kernel::urbiserver->schedule(event, SYMBOL(emit), args);
            }
          }
        }
      }
    }
#endif

    // Construction

    Directory::Directory()
      : path_(new Path("/"))
    {
      proto_add(proto);
    }

    Directory::Directory(rDirectory model)
      : path_(model.get()->path_)
    {
      proto_add(model);
      create_events();
    }

    Directory::Directory(const std::string& value)
      : path_(new Path(value))
    {
      proto_add(proto ? rObject(proto) : Object::proto);
    }

    Directory::Directory(rPath path)
      : path_(path)
    {
      proto_add(proto ? rObject(proto) : Object::proto);
    }

    OVERLOAD_TYPE(directory_init_bouncer, 1, 1,
                  Path,
                  (void (Directory::*)(rPath)) &Directory::init,
                  String,
                  (void (Directory::*)(const std::string&)) &Directory::init);

    URBI_CXX_OBJECT_INIT(Directory)
      : path_(new Path())
    {
      BIND(asList, list<&directory_mk_path>);
      BIND(asPath, as_path);
      BIND(asPrintable, as_printable);
      BIND(asString, as_string);
      BIND(clear);
      BINDG(current);
      BINDG(content, list<&directory_mk_string>);
      BIND(create);
      BIND(createAll, create_all);
      BINDG(empty);
      BINDG(exists);
      BINDG(parent);
      BIND(remove);
      BIND(removeAll_, remove_all);

      setSlot(SYMBOL(init),   new Primitive(&directory_init_bouncer));
    }

    void Directory::init(rPath path)
    {
      path->check_directory();

      path_ = path;

#if HAVE_SYS_INOTIFY_H
      static bool started = false;
      if (!started)
      {
        _watch_fd = inotify_init();
        if (_watch_fd == -1)
          FRAISE("cannot start inotify: %s", libport::strerror(errno));
        libport::startThread(boost::function0<void>(poll),
                             PTHREAD_STACK_MIN);
        started = true;
      }

      int watch = inotify_add_watch(_watch_fd, path->as_string().c_str(),
                                    IN_CREATE | IN_DELETE);
      if (watch == -1)
        FRAISE("cannot watch directory: %s", libport::strerror(errno));
      {
        _watch_map_elem_t events(on_file_created_, on_file_deleted_);
        libport::BlockLock lock(_watch_map_lock);
        std::pair<_watch_map_t::iterator, bool> res =
          _watch_map.insert(_watch_map_t::value_type(watch, events));

        // inotify return a uniq identifier per path.  If events are
        // registered we just re-use them instead.  This is fine as long as
        // Directory are not mutable.
        if (!res.second)
        {
          // Update the directory references.
          events = res.first->second;
          on_file_created_ = events.first;
          on_file_deleted_ = events.second;
          // update the slots to make the modification visible in Urbiscript.
          slot_update(SYMBOL(fileCreated), on_file_created_, false);
          slot_update(SYMBOL(fileDeleted), on_file_deleted_, false);
        }
      }
#endif
    }

    void
    Directory::init(const std::string& path)
    {
      init(new Path(path));
    }

    rObject
    Directory::create(rObject, rPath path)
    {
      return create_directory(path);
    }

    rDirectory
    Directory::create_directory(rPath path)
    {
      bool created = false;
      path->check_directory(false);

      try
      {
        created = boostfs::create_directory(path->as_string().c_str());
      }
      catch (boostfs::filesystem_error& e)
      {
        raise_boost_fs_error(e);
      }

      // Should not be raised as check is done before creating directory.
      if (!created)
        FRAISE("no directory was effectively created: %s",
               path->as_string());

      return instanciate_directory(path->as_string());
    }

    void
    Directory::create_all_recursive(rPath path)
    {
      if (path->exists())
        path->check_directory();
      if (!path->is_root())
      {
        rPath parent = path->parent();
        if (parent->as_string() != Path::cwd()->as_string())
          create_all_recursive(parent);
      }
      if (!path->exists())
        create_directory(path);
    }

    rObject
    Directory::create_all(rObject, rPath path)
    {
      create_all_recursive(path);
      return instanciate_directory(path);
    }

    // Modifiers
    rPath
    Directory::as_path() const
    {
      return path_;
    }

    void
    Directory::clear()
    {
      boostfs::path p = path_->as_string().c_str();
      boostfs::directory_iterator end_itr;
      for (boostfs::directory_iterator itr(p);
           itr != end_itr;
           ++itr)
        boostfs::remove_all(itr->path());
    }

    bool
    Directory::empty() const
    {
      try
      {
        return boostfs::is_empty(path_->as_string().c_str());
      }
      catch (boostfs::filesystem_error& e)
      {
        raise_boost_fs_error(e);
      }
    }

    bool
    Directory::exists() const
    {
      return path_->exists();
    }

    rDirectory
    Directory::parent() const
    {
      return instanciate_directory(new Path(path_->parent()));
    }

    void
    Directory::remove()
    {
      check_empty(*this);
      try
      {
        boostfs::remove_all(path_->as_string());
      }
      catch (boostfs::filesystem_error& e)
      {
        raise_boost_fs_error(e);
      }
    }

    void
    Directory::remove_all()
    {
      path_->check_exists();
      boostfs::remove_all(boostfs::path(path_->as_string()));
    }

    /*---------------------.
    | Global information.  |
    `---------------------*/

    rDirectory
    Directory::current()
    {
      return instanciate_directory(Path::cwd());
    }

    rDirectory
    Directory::instanciate_directory(rPath path)
    {
      rDirectory dir = new Directory;
      dir->create_events();
      dir->init(path);
      return dir;
    }

    rDirectory
    Directory::instanciate_directory(const std::string& name)
    {
      return instanciate_directory(new Path(name));
    }

    void
    Directory::create_events()
    {
#if HAVE_SYS_INOTIFY_H
      CAPTURE_GLOBAL(Event);
      on_file_created_ = Event->call("new");
      slot_set_value(SYMBOL(fileCreated), on_file_created_);
      on_file_deleted_ = Event->call("new");
      slot_set_value(SYMBOL(fileDeleted), on_file_deleted_);
#endif
    }

    /*--------------.
    | Conversions.  |
    `--------------*/

    std::string
    Directory::as_string() const
    {
      return path_->as_string();
    }

    std::string
    Directory::as_printable() const
    {
      return libport::format("Directory(\"%s\")", path_->as_string());
    }

    // Stat
    template <rObject (*F) (Directory& d, const std::string& entry)>
    rList Directory::list()
    {
      List::value_type res;
      DIR* dir = opendir(path_->value_get().to_string().c_str());

      // There is already an appropriate error handling done for Path.
      // We can use it if we need it.
      if (!dir)
        path_->handle_any_error();

      while (dirent* entry = readdir(dir))
      {
        if (!entry)
          path_->handle_any_error();
        std::string name = entry->d_name;
        if (name == "." || name == "..")
          continue;
        res << F(*this, name);
      }

      closedir(dir);
      return new List(res);
    }

    rObject
    directory_mk_string(Directory&, const std::string& entry)
    {
      return new String(entry);
    }

    rObject
    directory_mk_path(Directory& d, const std::string& entry)
    {
      return new Path(d.value_get()->value_get() / entry);
    }

    template
    rList Directory::list<directory_mk_string>();
    template
    rList Directory::list<directory_mk_path>();
  }
}
<|endoftext|>


<commit_before>/*
 * modelchecker.cc : part of the Mace toolkit for building distributed systems
 *
 * Copyright (c) 2007, Charles Killian, James W. Anderson
 * 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 names of Duke University nor The University of
 *      California, San Diego, nor the names of the authors or contributors
 *      may be used to endorse or promote products derived from
 *      this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
 * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * ----END-OF-LEGAL-STUFF---- */
#include <unistd.h>
#include <sys/types.h>
#include "mace_constants.h"
#include <string>
#include <sstream>
#include "NumberGen.h"
#include "Log.h"
#include "pip_includer.h"
#include "mace.h"

#include "MaceTime.h"

#include "Event.h"
#include "Sim.h"
#include "SimNetwork.h"
#include "RouteTransportWrapper.h"
typedef RouteTransportWrapper_namespace::RouteTransportWrapperService RouteTransportWrapper;
#include "SimScheduler.h"
#include "SimApplication.h"
#include "ThreadCreate.h"
#include "SysUtil.h"
#include "Properties.h"
#include "Simulator.h"
#include "macemc-getmtime.h"
#include "LoadTest.h"
using namespace macemc;

#undef exit
// #undef ASSERT
// #define ASSERT(x)  if(!x) { Log::log("ERROR::ASSERT") << *randomUtil << Log::endl; std::ofstream out(("error"+lexical_cast<std::string>(error_path++)+".path").c_str()); randomUtil->printVSErrorPath(out); out.close(); abort(); }

const int APP_EVENT = 0;
const int NET_EVENT = 1;
const int SCHED_EVENT = 2;

int base_port;
std::string* nodeString;

using boost::lexical_cast;

// namespace macemc {
//   void addRandTree();
// }

void* monitor(void* dud) {
  ADD_FUNC_SELECTORS;
  bool divergence_assert = params::containsKey("divergence_assert");
  maceout << "monitor begun" << Log::endl;
  int timeout = params::get("divergence_timeout", 5);
  __Simulator__::expireMonitor();
  while(true) {
    SysUtil::sleep(timeout);
    if(__Simulator__::expireMonitor()) {
      Log::enableLogging();
      __Simulator__::Error("DIVERGENCE", divergence_assert);
    }
  }
  return NULL;
}

void sigHandler(int sig) {
//   std::cerr << "received signal " << sig << " my pid=" << getpid() << std::endl;
  if(sig == SIGINT && __Simulator__::randomUtil->handleInt()) {
    return;
  }
  Log::enableLogging();
  Log::log("ERROR::SIM::SIGNAL") << "Caught Signal " << sig << ", terminating" << Log::endl;
  __Simulator__::Error("SIGNAL");
}

int main(int argc, char **argv)
{
  //   addRandTree();
//   BaseMaceService::_printLower = true;
  BaseMaceService::_printLower = false;
  SysUtil::signal(SIGABRT, sigHandler);
  SysUtil::signal(SIGINT, sigHandler);
  //   SysUtil::signal(SIGINT, sigHandler);

  // First load running parameters
  params::addRequired("num_nodes", "Number of nodes to simulate");
  params::addRequired("CHECKED_SERVICE", "Which service string to use");
  params::loadparams(argc, argv);
  params::set("MACE_SIMULATE_NODES", "MaceMC");
  params::print(stdout);

  { //logging
    Log::configure();
    Log::disableDefaultWarning();
    Log::disableDefaultError();
    //   LogSelectorTimestamp printTime = LOG_TIMESTAMP_HUMAN;
    LogSelectorTimestamp printTime = LOG_TIMESTAMP_DISABLED;
    LogSelectorThreadId printThreadId = LOG_THREADID_DISABLED;
    Log::add("ERROR",stdout,printTime,LOG_NAME_ENABLED,printThreadId);
    Log::autoAdd(".*ERROR::SIM.*",stdout,printTime,LOG_NAME_ENABLED,printThreadId);
    Log::add("SearchRandomUtil::next",stdout,printTime,LOG_NAME_ENABLED,printThreadId);
    Log::add("SearchStepRandomUtil::next",stdout,printTime,LOG_NAME_ENABLED,printThreadId);
    Log::add("BestFirstRandomUtil::next",stdout,printTime,LOG_NAME_ENABLED,printThreadId);
    Log::add("HALT",stdout,printTime,LOG_NAME_ENABLED,printThreadId);
    Log::add("MCTest",stdout,printTime,LOG_NAME_ENABLED,printThreadId);
    Log::autoAdd(".*monitor\\(void.*",stdout,printTime,LOG_NAME_ENABLED,printThreadId);
    Log::add("Sim::pathComplete",stdout,printTime,LOG_NAME_ENABLED);
    Log::add("Sim::printStats",stdout,printTime,LOG_NAME_ENABLED);
    //   Log::add("DEBUG::static bool __Simulator__::isDuplicateState()",stdout,printTime,LOG_NAME_ENABLED);
    Log::autoAdd(".*LastNailRandomUtil::hasNext.*",stdout,printTime,LOG_NAME_ENABLED,printThreadId);
    Log::add("LastNailRandomUtil::next",stdout,printTime,LOG_NAME_ENABLED,printThreadId);
    Log::autoAdd(".*LastNailRandomUtil::dumpState.*",stdout,printTime,LOG_NAME_ENABLED,printThreadId);
    if(params::containsKey("TRACE_ALL")) {
      Log::autoAddAll(stdout,printTime,LOG_NAME_ENABLED,printThreadId);
    }
    if(params::containsKey("TRACE_ALL_SQL")) {
      Log::autoAddAll(stdout,printTime,LOG_NAME_ENABLED,printThreadId, LOG_PGSQL);
    }
    if(params::containsKey("TRACE_SIMULATOR")) {
      Log::add("BestFirstRandomUtil::hasNext",stdout,printTime,LOG_NAME_ENABLED,printThreadId);
      Log::add("main",stdout,printTime,LOG_NAME_ENABLED,printThreadId);
      //     Log::autoAdd("Simulator");
      Log::add("__Simulator__::getReadyEvents",stdout,printTime,LOG_NAME_ENABLED,printThreadId);
      Log::autoAdd(".*__Simulator__::isDuplicateState.*",stdout,printTime,LOG_NAME_ENABLED,printThreadId);
      Log::autoAdd(".*__Simulator__::initState.*",stdout,printTime,LOG_NAME_ENABLED,printThreadId);
      Log::autoAdd(".*simulateNode.*",stdout,printTime,LOG_NAME_ENABLED,printThreadId);
      Log::add("SearchRandomUtil::randInt",stdout,printTime,LOG_NAME_ENABLED,printThreadId);
      Log::add("SearchStepRandomUtil::randInt",stdout,printTime,LOG_NAME_ENABLED,printThreadId);
      Log::add("BestFirstRandomUtil::randInt",stdout,printTime,LOG_NAME_ENABLED,printThreadId);
      Log::add("LastNailRandomUtil::randInt",stdout,printTime,LOG_NAME_ENABLED,printThreadId);
      Log::add("ReplayRandomUtil::randInt",stdout,printTime,LOG_NAME_ENABLED,printThreadId);
    }
    if(params::containsKey("TRACE_SUBST")) {
      std::istringstream in(params::get<std::string>("TRACE_SUBST"));
      while(in) {
        std::string s;
        in >> s;
        if(s.length() == 0) { break; }
        Log::autoAdd(s,stdout,printTime,LOG_NAME_ENABLED,printThreadId);
      }
    }
    if(params::containsKey("TRACE_STATE")) {
      Log::autoAdd(".*__Simulator__::dumpState.*");
    }
    if(params::containsKey("TRACE_STEP")) {
      Log::add("main",stdout,printTime,LOG_NAME_ENABLED,printThreadId);
    }
  } //end logging

  Log::log("MCTest") << "Registered tests: " << MCTest::getRegisteredTests() << Log::endl;
  MCTest* test = MCTest::getTest(params::get<std::string>("CHECKED_SERVICE"));
  if (test == NULL) {
    Log::err() << "Invalid checked service type " << params::get<std::string>("CHECKED_SERVICE") << " specified!" << Log::endl;
    ASSERT(0);
  }

  // Make sure the running scheduler is our simulator one.
  SimScheduler::Instance();
  __Simulator__::initializeVars();

  if(__Simulator__::divergenceMonitor) {
    pthread_t tid;
    runNewThread(&tid, monitor, NULL, NULL);
  }

  int num_nodes = __Simulator__::num_nodes;
  base_port = params::get("MACE_PORT", 5377);
  mace::MonotoneTimeImpl::mt = macemc::MonotoneTimeImpl::mt = new MonotoneTimeImpl(num_nodes);
  Sim::init(num_nodes);
  nodeString = new std::string[num_nodes];
  Sim::maxStep = params::get("max_num_steps", UINT_MAX);
  SimNetwork::SetInstance(base_port);

  params::StringMap paramCopy = params::getParams();

  for(int i = 0; i < num_nodes; i++) {
    nodeString[i] = boost::lexical_cast<std::string>(i);
  }

  __Simulator__::logAddresses();
  Log::log("main") << "Starting simulation" << Log::endl;

  int num_dead_paths = 0;
  unsigned maxPaths = (params::containsKey("MAX_PATHS")?params::get<int>("MAX_PATHS"):UINT_MAX);
  mace::string description;
  do {
    ADD_SELECTORS("main");

    if(__Simulator__::randomUtil->next()) {
      __Simulator__::disableMonitor();
      Sim::printStats(__Simulator__::randomUtil->getPhase());
      __Simulator__::enableMonitor();
    }

    Sim::clearGusto();

    TestPropertyList propertiesToTest;
    ServiceList servicesToDelete;
    NodeServiceClassList servicesToPrint;
    SimApplicationServiceClass** appNodes = new SimApplicationServiceClass*[num_nodes];

    MonotoneTimeImpl::mt->reset();

    test->loadTest(propertiesToTest, servicesToDelete, servicesToPrint, appNodes, num_nodes);

    SimApplication::SetInstance(appNodes, servicesToPrint);

    if(__Simulator__::use_hash) {
      __Simulator__::initState();
    }

    if(__Simulator__::loggingStartStep > 0) {
      Log::disableLogging();
    }

    Sim::PathEndCause cause = Sim::TOO_MANY_STEPS;
    for(Sim::step = 0; Sim::step < Sim::maxStep; Sim::step++) {
      if(Sim::step == __Simulator__::loggingStartStep) {
        Log::enableLogging();
      }
      maceout << "Now on simulator step " << Sim::step << " (Rem, maxStep = " << Sim::maxStep << ")" << Log::endl;
      __Simulator__::signalMonitor();
      EventList readyEvents = __Simulator__::getReadyEvents();
      macedbg(0) << "Ready Events--size=" << readyEvents.size();
      if(readyEvents.size()) {
        macedbg(0) << std::endl << readyEvents;
      }
      macedbg(0) << Log::endl;
      if(readyEvents.size() > 0) {
        Event e = RandomUtil::random(readyEvents);
        try {
          __Simulator__::simulateNode(e);
        } catch(const Exception& e) {
          maceerr << "Uncaught Mace Exception " << e << Log::endl;
          ABORT("Uncaught Mace Exception");
        } catch(const std::exception& se) {
          maceerr << "Uncaught std::exception " << se.what() << Log::endl;
          ABORT("Uncaught std::exception");
        } catch(...) {
          maceerr << "Uncaught unknown throw" << Log::endl;
          ABORT("Uncaught unknown throw");
        }
        __Simulator__::dumpState();
        Sim::updateGusto();
        if(__Simulator__::isDuplicateState()) {
          cause = Sim::DUPLICATE_STATE;
          break;
        }
        else if(__Simulator__::stoppingCondition(Sim::isLive, Sim::isSafe, propertiesToTest, description)) {
          cause = Sim::STOPPING_CONDITION;
          break;
        }
      } else {
        __Simulator__::stoppingCondition(Sim::isLive, Sim::isSafe, propertiesToTest, description);
        cause = Sim::NO_MORE_EVENTS;
        break;
      }
    }

    Sim::pathComplete(cause, Sim::isLive, Sim::isSafe, Sim::step, __Simulator__::randomUtil->pathDepth(), __Simulator__::randomUtil, description);

    //this could certainly move to Sim
    if(cause == Sim::NO_MORE_EVENTS && !Sim::isLive) {
      __Simulator__::Error(mace::string("NO_MORE_STEPS::")+description, ++num_dead_paths >= __Simulator__::max_dead_paths);
    } else if( cause == Sim::TOO_MANY_STEPS && __Simulator__::max_steps_error && !Sim::isLive ) {
      __Simulator__::Error(mace::string("MAX_STEPS::")+description, ++num_dead_paths >= __Simulator__::max_dead_paths);
    }

    for (int i = 0; i < num_nodes; i++) {
      appNodes[i]->maceExit();
    }

    for (size_t i = 0; i < servicesToDelete.size(); i++) {
      delete servicesToDelete[i];
    }

    SimScheduler::Instance().reset();
    SimNetwork::Instance().reset();
    SimApplication::reset();
    NumberGen::Reset();

    params::setParams(paramCopy);

    delete[] appNodes;

    for (size_t i = 0; i < propertiesToTest.size(); i++) {
      delete propertiesToTest[i];
    }
  } while(Sim::getPathNum() < maxPaths && __Simulator__::randomUtil->hasNext(Sim::isLive));
  Log::enableLogging();
  Log::log("HALT") << "Simulation complete!" << Log::endl;
  __Simulator__::disableMonitor();
  Sim::printStats(__Simulator__::randomUtil->getPhase() + " -- possibly incomplete");
  __Simulator__::enableMonitor();
  Log::log("HALT") << "Final RandomUtil State: " << *__Simulator__::randomUtil << Log::endl;
  __Simulator__::randomUtil->dumpState();

  printf("***falling out of main***\n");
  return 0;

}

<commit_msg>prevent problems with people using old params files ------------------------------------------------------------------------ r1141 | ckillian | 2011-06-13 23:53:41 -0400 (Mon, 13 Jun 2011) | 1 line<commit_after>/*
 * modelchecker.cc : part of the Mace toolkit for building distributed systems
 *
 * Copyright (c) 2007, Charles Killian, James W. Anderson
 * 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 names of Duke University nor The University of
 *      California, San Diego, nor the names of the authors or contributors
 *      may be used to endorse or promote products derived from
 *      this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
 * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * ----END-OF-LEGAL-STUFF---- */
#include <unistd.h>
#include <sys/types.h>
#include "mace_constants.h"
#include <string>
#include <sstream>
#include "NumberGen.h"
#include "Log.h"
#include "pip_includer.h"
#include "mace.h"

#include "MaceTime.h"

#include "Event.h"
#include "Sim.h"
#include "SimNetwork.h"
#include "RouteTransportWrapper.h"
typedef RouteTransportWrapper_namespace::RouteTransportWrapperService RouteTransportWrapper;
#include "SimScheduler.h"
#include "SimApplication.h"
#include "ThreadCreate.h"
#include "SysUtil.h"
#include "Properties.h"
#include "Simulator.h"
#include "macemc-getmtime.h"
#include "LoadTest.h"
using namespace macemc;

#undef exit
// #undef ASSERT
// #define ASSERT(x)  if(!x) { Log::log("ERROR::ASSERT") << *randomUtil << Log::endl; std::ofstream out(("error"+lexical_cast<std::string>(error_path++)+".path").c_str()); randomUtil->printVSErrorPath(out); out.close(); abort(); }

const int APP_EVENT = 0;
const int NET_EVENT = 1;
const int SCHED_EVENT = 2;

int base_port;
std::string* nodeString;

using boost::lexical_cast;

// namespace macemc {
//   void addRandTree();
// }

void* monitor(void* dud) {
  ADD_FUNC_SELECTORS;
  bool divergence_assert = params::containsKey("divergence_assert");
  maceout << "monitor begun" << Log::endl;
  int timeout = params::get("divergence_timeout", 5);
  __Simulator__::expireMonitor();
  while(true) {
    SysUtil::sleep(timeout);
    if(__Simulator__::expireMonitor()) {
      Log::enableLogging();
      __Simulator__::Error("DIVERGENCE", divergence_assert);
    }
  }
  return NULL;
}

void sigHandler(int sig) {
//   std::cerr << "received signal " << sig << " my pid=" << getpid() << std::endl;
  if(sig == SIGINT && __Simulator__::randomUtil->handleInt()) {
    return;
  }
  Log::enableLogging();
  Log::log("ERROR::SIM::SIGNAL") << "Caught Signal " << sig << ", terminating" << Log::endl;
  __Simulator__::Error("SIGNAL");
}

int main(int argc, char **argv)
{
  //   addRandTree();
//   BaseMaceService::_printLower = true;
  BaseMaceService::_printLower = false;
  SysUtil::signal(SIGABRT, sigHandler);
  SysUtil::signal(SIGINT, sigHandler);
  //   SysUtil::signal(SIGINT, sigHandler);

  // First load running parameters
  params::addRequired("num_nodes", "Number of nodes to simulate");
  params::addRequired("CHECKED_SERVICE", "Which service string to use");
  params::loadparams(argc, argv);
  params::set("MACE_SIMULATE_NODES", "MaceMC");
  params::print(stdout);

  { //logging
    Log::configure();
    Log::disableDefaultWarning();
    Log::disableDefaultError();
    //   LogSelectorTimestamp printTime = LOG_TIMESTAMP_HUMAN;
    LogSelectorTimestamp printTime = LOG_TIMESTAMP_DISABLED;
    LogSelectorThreadId printThreadId = LOG_THREADID_DISABLED;
    Log::add("ERROR",stdout,printTime,LOG_NAME_ENABLED,printThreadId);
    Log::autoAdd(".*ERROR::SIM.*",stdout,printTime,LOG_NAME_ENABLED,printThreadId);
    Log::add("SearchRandomUtil::next",stdout,printTime,LOG_NAME_ENABLED,printThreadId);
    Log::add("SearchStepRandomUtil::next",stdout,printTime,LOG_NAME_ENABLED,printThreadId);
    Log::add("BestFirstRandomUtil::next",stdout,printTime,LOG_NAME_ENABLED,printThreadId);
    Log::add("HALT",stdout,printTime,LOG_NAME_ENABLED,printThreadId);
    Log::add("MCTest",stdout,printTime,LOG_NAME_ENABLED,printThreadId);
    Log::autoAdd(".*monitor\\(void.*",stdout,printTime,LOG_NAME_ENABLED,printThreadId);
    Log::add("Sim::pathComplete",stdout,printTime,LOG_NAME_ENABLED);
    Log::add("Sim::printStats",stdout,printTime,LOG_NAME_ENABLED);
    //   Log::add("DEBUG::static bool __Simulator__::isDuplicateState()",stdout,printTime,LOG_NAME_ENABLED);
    Log::autoAdd(".*LastNailRandomUtil::hasNext.*",stdout,printTime,LOG_NAME_ENABLED,printThreadId);
    Log::add("LastNailRandomUtil::next",stdout,printTime,LOG_NAME_ENABLED,printThreadId);
    Log::autoAdd(".*LastNailRandomUtil::dumpState.*",stdout,printTime,LOG_NAME_ENABLED,printThreadId);
    if(params::containsKey("TRACE_ALL")) {
      Log::autoAddAll(stdout,printTime,LOG_NAME_ENABLED,printThreadId);
    }
    if(params::containsKey("TRACE_ALL_SQL")) {
      Log::autoAddAll(stdout,printTime,LOG_NAME_ENABLED,printThreadId, LOG_PGSQL);
    }
    if(params::containsKey("TRACE_SIMULATOR")) {
      Log::add("BestFirstRandomUtil::hasNext",stdout,printTime,LOG_NAME_ENABLED,printThreadId);
      Log::add("main",stdout,printTime,LOG_NAME_ENABLED,printThreadId);
      //     Log::autoAdd("Simulator");
      Log::add("__Simulator__::getReadyEvents",stdout,printTime,LOG_NAME_ENABLED,printThreadId);
      Log::autoAdd(".*__Simulator__::isDuplicateState.*",stdout,printTime,LOG_NAME_ENABLED,printThreadId);
      Log::autoAdd(".*__Simulator__::initState.*",stdout,printTime,LOG_NAME_ENABLED,printThreadId);
      Log::autoAdd(".*simulateNode.*",stdout,printTime,LOG_NAME_ENABLED,printThreadId);
      Log::add("SearchRandomUtil::randInt",stdout,printTime,LOG_NAME_ENABLED,printThreadId);
      Log::add("SearchStepRandomUtil::randInt",stdout,printTime,LOG_NAME_ENABLED,printThreadId);
      Log::add("BestFirstRandomUtil::randInt",stdout,printTime,LOG_NAME_ENABLED,printThreadId);
      Log::add("LastNailRandomUtil::randInt",stdout,printTime,LOG_NAME_ENABLED,printThreadId);
      Log::add("ReplayRandomUtil::randInt",stdout,printTime,LOG_NAME_ENABLED,printThreadId);
    }
    if(params::containsKey("TRACE_SUBST")) {
      std::istringstream in(params::get<std::string>("TRACE_SUBST"));
      while(in) {
        std::string s;
        in >> s;
        if(s.length() == 0) { break; }
        Log::autoAdd(s,stdout,printTime,LOG_NAME_ENABLED,printThreadId);
      }
    }
    if(params::containsKey("TRACE_STATE")) {
      Log::autoAdd(".*__Simulator__::dumpState.*");
    }
    if(params::containsKey("TRACE_STEP")) {
      Log::add("main",stdout,printTime,LOG_NAME_ENABLED,printThreadId);
    }
  } //end logging

  Log::log("MCTest") << "Registered tests: " << MCTest::getRegisteredTests() << Log::endl;
  MCTest* test = MCTest::getTest(params::get<std::string>("CHECKED_SERVICE"));
  if (test == NULL) {
    Log::err() << "Invalid checked service type " << params::get<std::string>("CHECKED_SERVICE") << " specified!" << Log::endl;
    ASSERT(0);
  }

  if (params::containsKey("SIM_NODE_FAILURE")) {
    ABORT("Parameter SIM_NODE_FAILURE removed.  Instead, use SIM_NUM_FAILURES (-1 means any number,m 0 means none, other gives maximum number.");
  }
  if (params::containsKey("USE_NET_ERRORS")) {
    ABORT("Parameter USE_NET_ERRORS removed.  Instead, use SIM_NUM_NET_ERRORS (-1 means any number,m 0 means none, other gives maximum number.");
  }

  // Make sure the running scheduler is our simulator one.
  SimScheduler::Instance();
  __Simulator__::initializeVars();

  if(__Simulator__::divergenceMonitor) {
    pthread_t tid;
    runNewThread(&tid, monitor, NULL, NULL);
  }

  int num_nodes = __Simulator__::num_nodes;
  base_port = params::get("MACE_PORT", 5377);
  mace::MonotoneTimeImpl::mt = macemc::MonotoneTimeImpl::mt = new MonotoneTimeImpl(num_nodes);
  Sim::init(num_nodes);
  nodeString = new std::string[num_nodes];
  Sim::maxStep = params::get("max_num_steps", UINT_MAX);
  SimNetwork::SetInstance(base_port);

  params::StringMap paramCopy = params::getParams();

  for(int i = 0; i < num_nodes; i++) {
    nodeString[i] = boost::lexical_cast<std::string>(i);
  }

  __Simulator__::logAddresses();
  Log::log("main") << "Starting simulation" << Log::endl;

  int num_dead_paths = 0;
  unsigned maxPaths = (params::containsKey("MAX_PATHS")?params::get<int>("MAX_PATHS"):UINT_MAX);
  mace::string description;
  do {
    ADD_SELECTORS("main");

    if(__Simulator__::randomUtil->next()) {
      __Simulator__::disableMonitor();
      Sim::printStats(__Simulator__::randomUtil->getPhase());
      __Simulator__::enableMonitor();
    }

    Sim::clearGusto();

    TestPropertyList propertiesToTest;
    ServiceList servicesToDelete;
    NodeServiceClassList servicesToPrint;
    SimApplicationServiceClass** appNodes = new SimApplicationServiceClass*[num_nodes];

    MonotoneTimeImpl::mt->reset();

    test->loadTest(propertiesToTest, servicesToDelete, servicesToPrint, appNodes, num_nodes);

    SimApplication::SetInstance(appNodes, servicesToPrint);

    if(__Simulator__::use_hash) {
      __Simulator__::initState();
    }

    if(__Simulator__::loggingStartStep > 0) {
      Log::disableLogging();
    }

    Sim::PathEndCause cause = Sim::TOO_MANY_STEPS;
    for(Sim::step = 0; Sim::step < Sim::maxStep; Sim::step++) {
      if(Sim::step == __Simulator__::loggingStartStep) {
        Log::enableLogging();
      }
      maceout << "Now on simulator step " << Sim::step << " (Rem, maxStep = " << Sim::maxStep << ")" << Log::endl;
      __Simulator__::signalMonitor();
      EventList readyEvents = __Simulator__::getReadyEvents();
      macedbg(0) << "Ready Events--size=" << readyEvents.size();
      if(readyEvents.size()) {
        macedbg(0) << std::endl << readyEvents;
      }
      macedbg(0) << Log::endl;
      if(readyEvents.size() > 0) {
        Event e = RandomUtil::random(readyEvents);
        try {
          __Simulator__::simulateNode(e);
        } catch(const Exception& e) {
          maceerr << "Uncaught Mace Exception " << e << Log::endl;
          ABORT("Uncaught Mace Exception");
        } catch(const std::exception& se) {
          maceerr << "Uncaught std::exception " << se.what() << Log::endl;
          ABORT("Uncaught std::exception");
        } catch(...) {
          maceerr << "Uncaught unknown throw" << Log::endl;
          ABORT("Uncaught unknown throw");
        }
        __Simulator__::dumpState();
        Sim::updateGusto();
        if(__Simulator__::isDuplicateState()) {
          cause = Sim::DUPLICATE_STATE;
          break;
        }
        else if(__Simulator__::stoppingCondition(Sim::isLive, Sim::isSafe, propertiesToTest, description)) {
          cause = Sim::STOPPING_CONDITION;
          break;
        }
      } else {
        __Simulator__::stoppingCondition(Sim::isLive, Sim::isSafe, propertiesToTest, description);
        cause = Sim::NO_MORE_EVENTS;
        break;
      }
    }

    Sim::pathComplete(cause, Sim::isLive, Sim::isSafe, Sim::step, __Simulator__::randomUtil->pathDepth(), __Simulator__::randomUtil, description);

    //this could certainly move to Sim
    if(cause == Sim::NO_MORE_EVENTS && !Sim::isLive) {
      __Simulator__::Error(mace::string("NO_MORE_STEPS::")+description, ++num_dead_paths >= __Simulator__::max_dead_paths);
    } else if( cause == Sim::TOO_MANY_STEPS && __Simulator__::max_steps_error && !Sim::isLive ) {
      __Simulator__::Error(mace::string("MAX_STEPS::")+description, ++num_dead_paths >= __Simulator__::max_dead_paths);
    }

    for (int i = 0; i < num_nodes; i++) {
      appNodes[i]->maceExit();
    }

    for (size_t i = 0; i < servicesToDelete.size(); i++) {
      delete servicesToDelete[i];
    }

    SimScheduler::Instance().reset();
    SimNetwork::Instance().reset();
    SimApplication::reset();
    NumberGen::Reset();

    params::setParams(paramCopy);

    delete[] appNodes;

    for (size_t i = 0; i < propertiesToTest.size(); i++) {
      delete propertiesToTest[i];
    }
  } while(Sim::getPathNum() < maxPaths && __Simulator__::randomUtil->hasNext(Sim::isLive));
  Log::enableLogging();
  Log::log("HALT") << "Simulation complete!" << Log::endl;
  __Simulator__::disableMonitor();
  Sim::printStats(__Simulator__::randomUtil->getPhase() + " -- possibly incomplete");
  __Simulator__::enableMonitor();
  Log::log("HALT") << "Final RandomUtil State: " << *__Simulator__::randomUtil << Log::endl;
  __Simulator__::randomUtil->dumpState();

  printf("***falling out of main***\n");
  return 0;

}

<|endoftext|>