<commit_before>#include "throttle.hpp"
#include <unistd.h>

/*
 * Constructor of a Throttle object. The argument config_fn
 * should be the name of the configuration file.
 */
Throttle::Throttle(const char *config_fn, const char* pipe_fn) : queue(this, pipe_fn), term(false)
{
	// open the configuration file
	Conf conf(config_fn);

	// read all variables
	conf.GetAttr("cores", &cores);
	conf.GetAttr("temp_file", &temp_fn);
	conf.GetAttr("freq_set_prefix", &freq_fn_prefix);
	conf.GetAttr("freq_set_suffix", &freq_fn_suffix);
	conf.GetAttr("freq_list", &freqs);
	conf.GetAttr("temp_min", &temp_min);
	conf.GetAttr("temp_max", &temp_max);
	conf.GetAttr("wait", &wait_after_adjust);

	// multiply temperatures with 1000
	temp_min *= 1000;
	temp_max *= 1000;

	// read the current frequency (is that the right thing to do?)
	std::ifstream freq_file(freq_fn_prefix + "0" + freq_fn_suffix);
	freq_file >> freq;

#ifdef DEBUG
	std::cout << "[Throttle] Initial frequency: " << (float)freq/1000 << " MHz" << std::endl;
#endif
}

/*
 * Adjust the frequency according to the current temperature.
 * Returns the number of seconds to wait until the next adjustment.
 */
int Throttle::adjust()
{
	int temp = readTemp();
	std::set<int>::iterator new_freq = freqs.end();

#ifdef DEBUG
	std::cout << "[Throttle] Temperature: " << (float)temp/1000 << "°C"<< std::endl;
#endif

	// If the temperature exceeds a threshold, find the next best frequency.
	if (temp > temp_max)
		new_freq = --freqs.lower_bound(freq);
	if (temp < temp_min)
		new_freq = freqs.upper_bound(freq);

	// Have we found one? Then adjust.
	if (new_freq != freqs.end()) {
		freq = *new_freq;
		writeFreq();
		return wait_after_adjust;
	}
	else
		return wait;
}

/*
 * Read and return the current CPU temperature.
 */
int Throttle::readTemp() const
{
	int temp;
	std::ifstream temp_file(temp_fn);
	temp_file >> temp;
	return temp;
}

/*
 * Write the determined frequency to the specific files.
 */
void Throttle::writeFreq() const
{
#ifdef DEBUG
	std::cout << "[Throttle] New frequency: " << (float)freq/1000 << " MHz" << std::endl;
#endif

	// loop over the files, write the frequency in each
	for (int core=0; core<cores; ++core) {
		std::ostringstream freq_fn;
		freq_fn << freq_fn_prefix << core << freq_fn_suffix;
		std::ofstream freq_file(freq_fn.str());
		freq_file << freq;
	}
}

/*
 * Run the throttle daemon. We stop if someone writes "quit" to the command pipe.
 */
void Throttle::run()
{
	while (!term) {
		int waitsec = wait;
		if (!override)
			waitsec = adjust();
		sleep(waitsec);
	}
}
<commit_msg>Just to be sure: initialize override flag<commit_after>#include "throttle.hpp"
#include <unistd.h>

/*
 * Constructor of a Throttle object. The argument config_fn
 * should be the name of the configuration file.
 */
Throttle::Throttle(const char *config_fn, const char* pipe_fn) : queue(this, pipe_fn), term(false), override(false)
{
	// open the configuration file
	Conf conf(config_fn);

	// read all variables
	conf.GetAttr("cores", &cores);
	conf.GetAttr("temp_file", &temp_fn);
	conf.GetAttr("freq_set_prefix", &freq_fn_prefix);
	conf.GetAttr("freq_set_suffix", &freq_fn_suffix);
	conf.GetAttr("freq_list", &freqs);
	conf.GetAttr("temp_min", &temp_min);
	conf.GetAttr("temp_max", &temp_max);
	conf.GetAttr("wait", &wait_after_adjust);

	// multiply temperatures with 1000
	temp_min *= 1000;
	temp_max *= 1000;

	// read the current frequency (is that the right thing to do?)
	std::ifstream freq_file(freq_fn_prefix + "0" + freq_fn_suffix);
	freq_file >> freq;

#ifdef DEBUG
	std::cout << "[Throttle] Initial frequency: " << (float)freq/1000 << " MHz" << std::endl;
#endif
}

/*
 * Adjust the frequency according to the current temperature.
 * Returns the number of seconds to wait until the next adjustment.
 */
int Throttle::adjust()
{
	int temp = readTemp();
	std::set<int>::iterator new_freq = freqs.end();

#ifdef DEBUG
	std::cout << "[Throttle] Temperature: " << (float)temp/1000 << "°C"<< std::endl;
#endif

	// If the temperature exceeds a threshold, find the next best frequency.
	if (temp > temp_max)
		new_freq = --freqs.lower_bound(freq);
	if (temp < temp_min)
		new_freq = freqs.upper_bound(freq);

	// Have we found one? Then adjust.
	if (new_freq != freqs.end()) {
		freq = *new_freq;
		writeFreq();
		return wait_after_adjust;
	}
	else
		return wait;
}

/*
 * Read and return the current CPU temperature.
 */
int Throttle::readTemp() const
{
	int temp;
	std::ifstream temp_file(temp_fn);
	temp_file >> temp;
	return temp;
}

/*
 * Write the determined frequency to the specific files.
 */
void Throttle::writeFreq() const
{
#ifdef DEBUG
	std::cout << "[Throttle] New frequency: " << (float)freq/1000 << " MHz" << std::endl;
#endif

	// loop over the files, write the frequency in each
	for (int core=0; core<cores; ++core) {
		std::ostringstream freq_fn;
		freq_fn << freq_fn_prefix << core << freq_fn_suffix;
		std::ofstream freq_file(freq_fn.str());
		freq_file << freq;
	}
}

/*
 * Run the throttle daemon. We stop if someone writes "quit" to the command pipe.
 */
void Throttle::run()
{
	while (!term) {
		int waitsec = wait;
		if (!override)
			waitsec = adjust();
		sleep(waitsec);
	}
}
<|endoftext|>


<commit_before>#include "throttle.hpp"
#include <unistd.h>

/*
 * Constructor of a Throttle object. The argument config_fn
 * sould be the name of the configuration file.
 */
Throttle::Throttle(const char *config_fn, const char* pipe_fn) : queue(this, pipe_fn), term(false)
{
	// open the configuration file
	Conf conf(config_fn);

	// read all variables
	conf.GetAttr("cores", &cores);
	conf.GetAttr("temp_file", &temp_fn);
	conf.GetAttr("freq_set_prefix", &freq_fn_prefix);
	conf.GetAttr("freq_set_suffix", &freq_fn_suffix);
	conf.GetAttr("freq_list", &freqs);
	conf.GetAttr("temp_min", &temp_min);
	conf.GetAttr("temp_max", &temp_max);
	conf.GetAttr("wait", &wait_after_adjust);

	// multiply temperatures with 1000
	temp_min *= 1000;
	temp_max *= 1000;

	// read the current frequency (is that the right thing to do?)
	std::ifstream freq_file(freq_fn_prefix + "0" + freq_fn_suffix);
	freq_file >> freq;

#ifdef DEBUG
	std::cout << "[Throttle] Initial frequency: " << freq << std::endl;
#endif
}

/*
 * Adjust the frequency according to the current temperature.
 * Returns the number of seconds to wait until the next adjustment.
 */
int Throttle::adjust()
{
	int temp = readTemp();
	std::set<int>::iterator new_freq;

#ifdef DEBUG
	std::cout << "[Throttle] Temperature: " << temp << std::endl;
#endif

	// If the temperature exceeds a threshold, find the next best frequency.
	if (temp > temp_max)
		new_freq = freqs.lower_bound(freq)--;
	if (temp < temp_min)
		new_freq = freqs.upper_bound(freq);

	// Have we found one? Then adjust.
	if (new_freq != freqs.end()) {
		freq = *new_freq;
		writeFreq();
		return wait_after_adjust;
	}
	else
		return wait;
}

/*
 * Read and return the current CPU temperature.
 */
int Throttle::readTemp() const
{
	int temp;
	std::ifstream temp_file(temp_fn);
	temp_file >> temp;
	return temp;
}

/*
 * Write the determined frequency to the specific files.
 */
void Throttle::writeFreq()
{
#ifdef DEBUG
	std::cout << "[Throttle] New frequency: " << freq << std::endl;
#endif

	// loop over the files, write the frequency in each
	for (int core=0; core<cores; ++core) {
		std::ostringstream freq_fn;
		freq_fn << freq_fn_prefix << core << freq_fn_suffix;
		std::ofstream freq_file(freq_fn.str());
		freq_file << freq;
	}
}

/*
 * Run the throttle daemon. This function is unlikely to stop on its own.
 */
void Throttle::run()
{
	while (!term) {
		sleep(adjust());
	}
}
<commit_msg>Initialize frequency set iterator<commit_after>#include "throttle.hpp"
#include <unistd.h>

/*
 * Constructor of a Throttle object. The argument config_fn
 * sould be the name of the configuration file.
 */
Throttle::Throttle(const char *config_fn, const char* pipe_fn) : queue(this, pipe_fn), term(false)
{
	// open the configuration file
	Conf conf(config_fn);

	// read all variables
	conf.GetAttr("cores", &cores);
	conf.GetAttr("temp_file", &temp_fn);
	conf.GetAttr("freq_set_prefix", &freq_fn_prefix);
	conf.GetAttr("freq_set_suffix", &freq_fn_suffix);
	conf.GetAttr("freq_list", &freqs);
	conf.GetAttr("temp_min", &temp_min);
	conf.GetAttr("temp_max", &temp_max);
	conf.GetAttr("wait", &wait_after_adjust);

	// multiply temperatures with 1000
	temp_min *= 1000;
	temp_max *= 1000;

	// read the current frequency (is that the right thing to do?)
	std::ifstream freq_file(freq_fn_prefix + "0" + freq_fn_suffix);
	freq_file >> freq;

#ifdef DEBUG
	std::cout << "[Throttle] Initial frequency: " << freq << std::endl;
#endif
}

/*
 * Adjust the frequency according to the current temperature.
 * Returns the number of seconds to wait until the next adjustment.
 */
int Throttle::adjust()
{
	int temp = readTemp();
	std::set<int>::iterator new_freq = freqs.end();

#ifdef DEBUG
	std::cout << "[Throttle] Temperature: " << temp << std::endl;
#endif

	// If the temperature exceeds a threshold, find the next best frequency.
	if (temp > temp_max)
		new_freq = freqs.lower_bound(freq)--;
	if (temp < temp_min)
		new_freq = freqs.upper_bound(freq);

	// Have we found one? Then adjust.
	if (new_freq != freqs.end()) {
		freq = *new_freq;
		writeFreq();
		return wait_after_adjust;
	}
	else
		return wait;
}

/*
 * Read and return the current CPU temperature.
 */
int Throttle::readTemp() const
{
	int temp;
	std::ifstream temp_file(temp_fn);
	temp_file >> temp;
	return temp;
}

/*
 * Write the determined frequency to the specific files.
 */
void Throttle::writeFreq()
{
#ifdef DEBUG
	std::cout << "[Throttle] New frequency: " << freq << std::endl;
#endif

	// loop over the files, write the frequency in each
	for (int core=0; core<cores; ++core) {
		std::ostringstream freq_fn;
		freq_fn << freq_fn_prefix << core << freq_fn_suffix;
		std::ofstream freq_file(freq_fn.str());
		freq_file << freq;
	}
}

/*
 * Run the throttle daemon. This function is unlikely to stop on its own.
 */
void Throttle::run()
{
	while (!term) {
		int waitsec = adjust();
		sleep(waitsec);
	}
}
<|endoftext|>


<commit_before>#include "throttle.hpp"
#include <unistd.h>

/*
 * Constructor of a Throttle object. The argument config_fn
 * sould be the name of the configuration file.
 */
Throttle::Throttle(const char *config_fn, const char* pipe_fn) : queue(this, pipe_fn), term(false)
{
	// open the configuration file
	Conf conf(config_fn);

	// read all variables
	conf.GetAttr("cores", &cores);
	conf.GetAttr("temp_file", &temp_fn);
	conf.GetAttr("freq_set_prefix", &freq_fn_prefix);
	conf.GetAttr("freq_set_suffix", &freq_fn_suffix);
	conf.GetAttr("freq_list", &freqs);
	conf.GetAttr("temp_min", &temp_min);
	conf.GetAttr("temp_max", &temp_max);
	conf.GetAttr("wait", &wait_after_adjust);

	// multiply temperatures with 1000
	temp_min *= 1000;
	temp_max *= 1000;

	// read the current frequency (is that the right thing to do?)
	std::ifstream freq_file(freq_fn_prefix + "0" + freq_fn_suffix);
	freq_file >> freq;

#ifdef DEBUG
	std::cout << "[Throttle] Initial frequency: " << (float)freq/1000 << " MHz" << std::endl;
#endif
}

/*
 * Adjust the frequency according to the current temperature.
 * Returns the number of seconds to wait until the next adjustment.
 */
int Throttle::adjust()
{
	int temp = readTemp();
	std::set<int>::iterator new_freq = freqs.end();

#ifdef DEBUG
	std::cout << "[Throttle] Temperature: " << (float)temp/1000 << "°C"<< std::endl;
#endif

	// If the temperature exceeds a threshold, find the next best frequency.
	if (temp > temp_max)
		new_freq = freqs.lower_bound(freq)--;
	if (temp < temp_min)
		new_freq = freqs.upper_bound(freq);

	// Have we found one? Then adjust.
	if (new_freq != freqs.end()) {
		freq = *new_freq;
		writeFreq();
		return wait_after_adjust;
	}
	else
		return wait;
}

/*
 * Read and return the current CPU temperature.
 */
int Throttle::readTemp() const
{
	int temp;
	std::ifstream temp_file(temp_fn);
	temp_file >> temp;
	return temp;
}

/*
 * Write the determined frequency to the specific files.
 */
void Throttle::writeFreq()
{
#ifdef DEBUG
	std::cout << "[Throttle] New frequency: " << (float)freq/1000 << " MHz" << std::endl;
#endif

	// loop over the files, write the frequency in each
	for (int core=0; core<cores; ++core) {
		std::ostringstream freq_fn;
		freq_fn << freq_fn_prefix << core << freq_fn_suffix;
		std::ofstream freq_file(freq_fn.str());
		freq_file << freq;
	}
}

/*
 * Run the throttle daemon. This function is unlikely to stop on its own.
 */
void Throttle::run()
{
	while (!term) {
		int waitsec = adjust();
		sleep(waitsec);
	}
}
<commit_msg>Ugly mistake: obviously we need a prefix increment<commit_after>#include "throttle.hpp"
#include <unistd.h>

/*
 * Constructor of a Throttle object. The argument config_fn
 * sould be the name of the configuration file.
 */
Throttle::Throttle(const char *config_fn, const char* pipe_fn) : queue(this, pipe_fn), term(false)
{
	// open the configuration file
	Conf conf(config_fn);

	// read all variables
	conf.GetAttr("cores", &cores);
	conf.GetAttr("temp_file", &temp_fn);
	conf.GetAttr("freq_set_prefix", &freq_fn_prefix);
	conf.GetAttr("freq_set_suffix", &freq_fn_suffix);
	conf.GetAttr("freq_list", &freqs);
	conf.GetAttr("temp_min", &temp_min);
	conf.GetAttr("temp_max", &temp_max);
	conf.GetAttr("wait", &wait_after_adjust);

	// multiply temperatures with 1000
	temp_min *= 1000;
	temp_max *= 1000;

	// read the current frequency (is that the right thing to do?)
	std::ifstream freq_file(freq_fn_prefix + "0" + freq_fn_suffix);
	freq_file >> freq;

#ifdef DEBUG
	std::cout << "[Throttle] Initial frequency: " << (float)freq/1000 << " MHz" << std::endl;
#endif
}

/*
 * Adjust the frequency according to the current temperature.
 * Returns the number of seconds to wait until the next adjustment.
 */
int Throttle::adjust()
{
	int temp = readTemp();
	std::set<int>::iterator new_freq = freqs.end();

#ifdef DEBUG
	std::cout << "[Throttle] Temperature: " << (float)temp/1000 << "°C"<< std::endl;
#endif

	// If the temperature exceeds a threshold, find the next best frequency.
	if (temp > temp_max)
		new_freq = --freqs.lower_bound(freq);
	if (temp < temp_min)
		new_freq = freqs.upper_bound(freq);

	// Have we found one? Then adjust.
	if (new_freq != freqs.end()) {
		freq = *new_freq;
		writeFreq();
		return wait_after_adjust;
	}
	else
		return wait;
}

/*
 * Read and return the current CPU temperature.
 */
int Throttle::readTemp() const
{
	int temp;
	std::ifstream temp_file(temp_fn);
	temp_file >> temp;
	return temp;
}

/*
 * Write the determined frequency to the specific files.
 */
void Throttle::writeFreq()
{
#ifdef DEBUG
	std::cout << "[Throttle] New frequency: " << (float)freq/1000 << " MHz" << std::endl;
#endif

	// loop over the files, write the frequency in each
	for (int core=0; core<cores; ++core) {
		std::ostringstream freq_fn;
		freq_fn << freq_fn_prefix << core << freq_fn_suffix;
		std::ofstream freq_file(freq_fn.str());
		freq_file << freq;
	}
}

/*
 * Run the throttle daemon. This function is unlikely to stop on its own.
 */
void Throttle::run()
{
	while (!term) {
		int waitsec = adjust();
		sleep(waitsec);
	}
}
<|endoftext|>


<commit_before>//=====================================================
// Copyright (C) 2008 Gael Guennebaud <g.gael@free.fr>
//=====================================================
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
//
#ifndef EIGEN2_INTERFACE_HH
#define EIGEN2_INTERFACE_HH
// #include <cblas.h>
#include <Eigen/Array>
#include <Eigen/Cholesky>
#include <Eigen/LU>
#include <Eigen/QR>
#include <vector>
#include "btl.hh"

using namespace Eigen;

template<class real, int SIZE=Dynamic>
class eigen2_interface
{

public :

  enum {IsFixedSize = (SIZE!=Dynamic)};

  typedef real real_type;

  typedef std::vector<real> stl_vector;
  typedef std::vector<stl_vector> stl_matrix;

  typedef Eigen::Matrix<real,SIZE,SIZE> gene_matrix;
  typedef Eigen::Matrix<real,SIZE,1> gene_vector;

  static inline std::string name( void )
  {
    return EIGEN_MAKESTRING(BTL_PREFIX);
  }

  static void free_matrix(gene_matrix & A, int N) {}

  static void free_vector(gene_vector & B) {}

  static BTL_DONT_INLINE void matrix_from_stl(gene_matrix & A, stl_matrix & A_stl){
    A.resize(A_stl[0].size(), A_stl.size());

    for (int j=0; j<A_stl.size() ; j++){
      for (int i=0; i<A_stl[j].size() ; i++){
        A.coeffRef(i,j) = A_stl[j][i];
      }
    }
  }

  static BTL_DONT_INLINE  void vector_from_stl(gene_vector & B, stl_vector & B_stl){
    B.resize(B_stl.size(),1);

    for (int i=0; i<B_stl.size() ; i++){
      B.coeffRef(i) = B_stl[i];
    }
  }

  static BTL_DONT_INLINE  void vector_to_stl(gene_vector & B, stl_vector & B_stl){
    for (int i=0; i<B_stl.size() ; i++){
      B_stl[i] = B.coeff(i);
    }
  }

  static BTL_DONT_INLINE  void matrix_to_stl(gene_matrix & A, stl_matrix & A_stl){
    int N=A_stl.size();

    for (int j=0;j<N;j++){
      A_stl[j].resize(N);
      for (int i=0;i<N;i++){
        A_stl[j][i] = A.coeff(i,j);
      }
    }
  }

  static inline void matrix_matrix_product(const gene_matrix & A, const gene_matrix & B, gene_matrix & X, int N){
    X = (A*B).lazy();
  }

  static inline void transposed_matrix_matrix_product(const gene_matrix & A, const gene_matrix & B, gene_matrix & X, int N){
    X = (A.transpose()*B.transpose()).lazy();
  }

  static inline void ata_product(const gene_matrix & A, gene_matrix & X, int N){
    X = (A.transpose()*A).lazy();
  }

  static inline void aat_product(const gene_matrix & A, gene_matrix & X, int N){
    X = (A*A.transpose()).lazy();
  }

  static inline void matrix_vector_product(const gene_matrix & A, const gene_vector & B, gene_vector & X, int N){
    X = (A*B).lazy();
  }

  static inline void symv(const gene_matrix & A, const gene_vector & B, gene_vector & X, int N){
    X = (A.template selfadjointView<LowerTriangular>() * B)/*.lazy()*/;
//     ei_product_selfadjoint_vector<real,0,LowerTriangularBit,false,false>(N,A.data(),N, B.data(), 1, X.data(), 1);
  }

  template<typename Dest, typename Src> static void triassign(Dest& dst, const Src& src)
  {
    typedef typename Dest::Scalar Scalar;
    typedef typename ei_packet_traits<Scalar>::type Packet;
    const int PacketSize = sizeof(Packet)/sizeof(Scalar);
    int size = dst.cols();
    for(int j=0; j<size; j+=1)
    {
//       const int alignedEnd = alignedStart + ((innerSize-alignedStart) & ~packetAlignedMask);
      Scalar* A0 = dst.data() + j*dst.stride();
      int starti = j;
      int alignedEnd = starti;
      int alignedStart = (starti) + ei_first_aligned(&A0[starti], size-starti);
      alignedEnd = alignedStart + ((size-alignedStart)/(2*PacketSize))*(PacketSize*2);

      // do the non-vectorizable part of the assignment
      for (int index = starti; index<alignedStart ; ++index)
      {
        if(Dest::Flags&RowMajorBit)
          dst.copyCoeff(j, index, src);
        else
          dst.copyCoeff(index, j, src);
      }

      // do the vectorizable part of the assignment
      for (int index = alignedStart; index<alignedEnd; index+=PacketSize)
      {
        if(Dest::Flags&RowMajorBit)
          dst.template copyPacket<Src, Aligned, Unaligned>(j, index, src);
        else
          dst.template copyPacket<Src, Aligned, Unaligned>(index, j, src);
      }

      // do the non-vectorizable part of the assignment
      for (int index = alignedEnd; index<size; ++index)
      {
        if(Dest::Flags&RowMajorBit)
          dst.copyCoeff(j, index, src);
        else
          dst.copyCoeff(index, j, src);
      }
      //dst.col(j).tail(N-j) = src.col(j).tail(N-j);
    }
  }

  static EIGEN_DONT_INLINE void syr2(gene_matrix & A,  gene_vector & X, gene_vector & Y, int N){
    // ei_product_selfadjoint_rank2_update<real,0,LowerTriangularBit>(N,A.data(),N, X.data(), 1, Y.data(), 1, -1);
    for(int j=0; j<N; ++j)
      A.col(j).tail(N-j) += X[j] * Y.tail(N-j) + Y[j] * X.tail(N-j);
  }

  static EIGEN_DONT_INLINE void ger(gene_matrix & A,  gene_vector & X, gene_vector & Y, int N){
    for(int j=0; j<N; ++j)
      A.col(j) += X * Y[j];
  }

  static EIGEN_DONT_INLINE void rot(gene_vector & A,  gene_vector & B, real c, real s, int N){
    ei_apply_rotation_in_the_plane(A, B, c, s);
  }

  static inline void atv_product(gene_matrix & A, gene_vector & B, gene_vector & X, int N){
    X = (A.transpose()*B).lazy();
  }

  static inline void axpy(real coef, const gene_vector & X, gene_vector & Y, int N){
    Y += coef * X;
  }

  static inline void axpby(real a, const gene_vector & X, real b, gene_vector & Y, int N){
    Y = a*X + b*Y;
  }

  static EIGEN_DONT_INLINE void copy_matrix(const gene_matrix & source, gene_matrix & cible, int N){
    cible = source;
  }

  static EIGEN_DONT_INLINE void copy_vector(const gene_vector & source, gene_vector & cible, int N){
    cible = source;
  }

  static inline void trisolve_lower(const gene_matrix & L, const gene_vector& B, gene_vector& X, int N){
    X = L.template triangularView<LowerTriangular>().solve(B);
  }

  static inline void trisolve_lower_matrix(const gene_matrix & L, const gene_matrix& B, gene_matrix& X, int N){
    X = L.template triangularView<LowerTriangular>().solve(B);
  }

  static inline void cholesky(const gene_matrix & X, gene_matrix & C, int N){
    C = X;
    ei_llt_inplace<LowerTriangular>::blocked(C);
    //C = X.llt().matrixL();
//     C = X;
//     Cholesky<gene_matrix>::computeInPlace(C);
//     Cholesky<gene_matrix>::computeInPlaceBlock(C);
  }

  static inline void lu_decomp(const gene_matrix & X, gene_matrix & C, int N){
    RowVectorXi piv(N);
    int nb;
    C = X;
    ei_partial_lu_inplace(C,piv,nb);
    //C = X.lu().matrixLU();
  }

  static inline void partial_lu_decomp(const gene_matrix & X, gene_matrix & C, int N){
    C = X.partialPivLu().matrixLU();
  }

  static inline void tridiagonalization(const gene_matrix & X, gene_matrix & C, int N){
    typename Tridiagonalization<gene_matrix>::CoeffVectorType aux(N-1);
    C = X;
    Tridiagonalization<gene_matrix>::_compute(C, aux);
//     C = Tridiagonalization<gene_matrix>(X).packedMatrix();
  }

  static inline void hessenberg(const gene_matrix & X, gene_matrix & C, int N){
    C = HessenbergDecomposition<gene_matrix>(X).packedMatrix();
  }

};

#endif
<commit_msg>fix BTL's eigen interface<commit_after>//=====================================================
// Copyright (C) 2008 Gael Guennebaud <g.gael@free.fr>
//=====================================================
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
//
#ifndef EIGEN2_INTERFACE_HH
#define EIGEN2_INTERFACE_HH

#include <Eigen/Eigen>
#include <vector>
#include "btl.hh"

using namespace Eigen;

template<class real, int SIZE=Dynamic>
class eigen2_interface
{

public :

  enum {IsFixedSize = (SIZE!=Dynamic)};

  typedef real real_type;

  typedef std::vector<real> stl_vector;
  typedef std::vector<stl_vector> stl_matrix;

  typedef Eigen::Matrix<real,SIZE,SIZE> gene_matrix;
  typedef Eigen::Matrix<real,SIZE,1> gene_vector;

  static inline std::string name( void )
  {
    return EIGEN_MAKESTRING(BTL_PREFIX);
  }

  static void free_matrix(gene_matrix & A, int N) {}

  static void free_vector(gene_vector & B) {}

  static BTL_DONT_INLINE void matrix_from_stl(gene_matrix & A, stl_matrix & A_stl){
    A.resize(A_stl[0].size(), A_stl.size());

    for (int j=0; j<A_stl.size() ; j++){
      for (int i=0; i<A_stl[j].size() ; i++){
        A.coeffRef(i,j) = A_stl[j][i];
      }
    }
  }

  static BTL_DONT_INLINE  void vector_from_stl(gene_vector & B, stl_vector & B_stl){
    B.resize(B_stl.size(),1);

    for (int i=0; i<B_stl.size() ; i++){
      B.coeffRef(i) = B_stl[i];
    }
  }

  static BTL_DONT_INLINE  void vector_to_stl(gene_vector & B, stl_vector & B_stl){
    for (int i=0; i<B_stl.size() ; i++){
      B_stl[i] = B.coeff(i);
    }
  }

  static BTL_DONT_INLINE  void matrix_to_stl(gene_matrix & A, stl_matrix & A_stl){
    int N=A_stl.size();

    for (int j=0;j<N;j++){
      A_stl[j].resize(N);
      for (int i=0;i<N;i++){
        A_stl[j][i] = A.coeff(i,j);
      }
    }
  }

  static inline void matrix_matrix_product(const gene_matrix & A, const gene_matrix & B, gene_matrix & X, int N){
    X.noalias() = A*B;
  }

  static inline void transposed_matrix_matrix_product(const gene_matrix & A, const gene_matrix & B, gene_matrix & X, int N){
    X.noalias() = A.transpose()*B.transpose();
  }

  static inline void ata_product(const gene_matrix & A, gene_matrix & X, int N){
    X.noalias() = A.transpose()*A;
  }

  static inline void aat_product(const gene_matrix & A, gene_matrix & X, int N){
    X.noalias() = A*A.transpose();
  }

  static inline void matrix_vector_product(const gene_matrix & A, const gene_vector & B, gene_vector & X, int N){
    X.noalias() = A*B;
  }

  static inline void symv(const gene_matrix & A, const gene_vector & B, gene_vector & X, int N){
    X.noalias() = (A.template selfadjointView<Lower>() * B);
//     ei_product_selfadjoint_vector<real,0,LowerTriangularBit,false,false>(N,A.data(),N, B.data(), 1, X.data(), 1);
  }

  template<typename Dest, typename Src> static void triassign(Dest& dst, const Src& src)
  {
    typedef typename Dest::Scalar Scalar;
    typedef typename ei_packet_traits<Scalar>::type Packet;
    const int PacketSize = sizeof(Packet)/sizeof(Scalar);
    int size = dst.cols();
    for(int j=0; j<size; j+=1)
    {
//       const int alignedEnd = alignedStart + ((innerSize-alignedStart) & ~packetAlignedMask);
      Scalar* A0 = dst.data() + j*dst.stride();
      int starti = j;
      int alignedEnd = starti;
      int alignedStart = (starti) + ei_first_aligned(&A0[starti], size-starti);
      alignedEnd = alignedStart + ((size-alignedStart)/(2*PacketSize))*(PacketSize*2);

      // do the non-vectorizable part of the assignment
      for (int index = starti; index<alignedStart ; ++index)
      {
        if(Dest::Flags&RowMajorBit)
          dst.copyCoeff(j, index, src);
        else
          dst.copyCoeff(index, j, src);
      }

      // do the vectorizable part of the assignment
      for (int index = alignedStart; index<alignedEnd; index+=PacketSize)
      {
        if(Dest::Flags&RowMajorBit)
          dst.template copyPacket<Src, Aligned, Unaligned>(j, index, src);
        else
          dst.template copyPacket<Src, Aligned, Unaligned>(index, j, src);
      }

      // do the non-vectorizable part of the assignment
      for (int index = alignedEnd; index<size; ++index)
      {
        if(Dest::Flags&RowMajorBit)
          dst.copyCoeff(j, index, src);
        else
          dst.copyCoeff(index, j, src);
      }
      //dst.col(j).tail(N-j) = src.col(j).tail(N-j);
    }
  }

  static EIGEN_DONT_INLINE void syr2(gene_matrix & A,  gene_vector & X, gene_vector & Y, int N){
    // ei_product_selfadjoint_rank2_update<real,0,LowerTriangularBit>(N,A.data(),N, X.data(), 1, Y.data(), 1, -1);
    for(int j=0; j<N; ++j)
      A.col(j).tail(N-j) += X[j] * Y.tail(N-j) + Y[j] * X.tail(N-j);
  }

  static EIGEN_DONT_INLINE void ger(gene_matrix & A,  gene_vector & X, gene_vector & Y, int N){
    for(int j=0; j<N; ++j)
      A.col(j) += X * Y[j];
  }

  static EIGEN_DONT_INLINE void rot(gene_vector & A,  gene_vector & B, real c, real s, int N){
    ei_apply_rotation_in_the_plane(A, B, c, s);
  }

  static inline void atv_product(gene_matrix & A, gene_vector & B, gene_vector & X, int N){
    X.noalias() = (A.transpose()*B);
  }

  static inline void axpy(real coef, const gene_vector & X, gene_vector & Y, int N){
    Y += coef * X;
  }

  static inline void axpby(real a, const gene_vector & X, real b, gene_vector & Y, int N){
    Y = a*X + b*Y;
  }

  static EIGEN_DONT_INLINE void copy_matrix(const gene_matrix & source, gene_matrix & cible, int N){
    cible = source;
  }

  static EIGEN_DONT_INLINE void copy_vector(const gene_vector & source, gene_vector & cible, int N){
    cible = source;
  }

  static inline void trisolve_lower(const gene_matrix & L, const gene_vector& B, gene_vector& X, int N){
    X = L.template triangularView<Lower>().solve(B);
  }

  static inline void trisolve_lower_matrix(const gene_matrix & L, const gene_matrix& B, gene_matrix& X, int N){
    X = L.template triangularView<Lower>().solve(B);
  }

  static inline void cholesky(const gene_matrix & X, gene_matrix & C, int N){
    C = X;
    ei_llt_inplace<Lower>::blocked(C);
    //C = X.llt().matrixL();
//     C = X;
//     Cholesky<gene_matrix>::computeInPlace(C);
//     Cholesky<gene_matrix>::computeInPlaceBlock(C);
  }

  static inline void lu_decomp(const gene_matrix & X, gene_matrix & C, int N){
    RowVectorXi piv(N);
    int nb;
    C = X;
    ei_partial_lu_inplace(C,piv,nb);
    //C = X.lu().matrixLU();
  }

  static inline void partial_lu_decomp(const gene_matrix & X, gene_matrix & C, int N){
    C = X.partialPivLu().matrixLU();
  }

  static inline void tridiagonalization(const gene_matrix & X, gene_matrix & C, int N){
    typename Tridiagonalization<gene_matrix>::CoeffVectorType aux(N-1);
    C = X;
    Tridiagonalization<gene_matrix>::_compute(C, aux);
//     C = Tridiagonalization<gene_matrix>(X).packedMatrix();
  }

  static inline void hessenberg(const gene_matrix & X, gene_matrix & C, int N){
    C = HessenbergDecomposition<gene_matrix>(X).packedMatrix();
  }

};

#endif
<|endoftext|>


<commit_before>#include "treenode.h"

TreeNode::TreeNode(int type, TreeNode *parent) :
    _name(),
    _type(type),
    _flags(TreeFlags::NoNodeFlags),
    _parent(parent),
    _children()
{
    if (_parent != NULL)
        if (!_parent->addChild(this))
            _parent = NULL;
}

TreeNode::TreeNode(const std::string &name, int type, TreeNode *parent) :
    _name(name),
    _type(type),
    _flags(TreeFlags::NoNodeFlags),
    _parent(parent),
    _children()
{
    if (_parent != NULL)
        if (!_parent->addChild(this))
            _parent = NULL;
}

TreeNode::~TreeNode()
{
    if (_parent != NULL)
        _parent->_childDestroyed(this);

    std::set<TreeNode*>::const_iterator itr;
    for (itr = _children.begin(); itr != _children.end(); ++itr)
        delete *itr;
}

TreeFlags TreeNode::flags() const
{
    return _flags;
}

void TreeNode::setFlags(TreeFlags flags)
{
    _flags = flags;

    if (_flags & TreeFlags::NodeNeverHasChildren)
        _children.clear();
}

bool TreeNode::addChild(TreeNode *child)
{
    if (_flags & TreeFlags::NodeNeverHasChildren)
        return false;
    else if (child == NULL || child->_parent != NULL)
        return false;

    child->_parent = this;
    _children.insert(child);
    return true;
}

bool TreeNode::moveChild(TreeNode *child)
{
    if (_flags & TreeFlags::NodeNeverHasChildren)
        return false;
    else if (child == NULL)
        return false;

    if (child->_parent != NULL)
        child->_parent->removeChild(child);
    child->_parent = this;
    _children.insert(child);
    return true;
}

bool TreeNode::removeChild(TreeNode *child)
{
    return _children.erase(child);
}

const std::set<TreeNode*>& TreeNode::children() const
{
    return _children;
}

const TreeNode* TreeNode::findChild(const std::string &name) const
{
    std::set<TreeNode*>::const_iterator itr;
    for (itr = _children.begin(); itr != _children.end(); ++itr)
    {
        const TreeNode *child = *itr;
        if (child->_name == name)
            return child;
    }

    return NULL;
}

const TreeNode* TreeNode::findChildRecursively(const std::string &name, int maxDepth) const
{
    if (maxDepth == 0)
        return NULL;

    std::set<TreeNode*>::const_iterator itr;
    for (itr = _children.begin(); itr != _children.end(); ++itr)
    {
        const TreeNode *child = *itr;
        if (child->_name == name)
            return child;

        const TreeNode *res = child->findChildRecursively(name, maxDepth - 1);
        if (res != NULL)
            return res;
    }

    return NULL;
}

TreeNode* TreeNode::findChild(const std::string &name)
{
    std::set<TreeNode*>::iterator itr;
    for (itr = _children.begin(); itr != _children.end(); ++itr)
    {
        TreeNode *child = *itr;
        if (child->_name == name)
            return child;
    }

    return NULL;
}

TreeNode* TreeNode::findChildRecursively(const std::string &name, int maxDepth)
{
    if (maxDepth == 0)
        return NULL;

    std::set<TreeNode*>::iterator itr;
    for (itr = _children.begin(); itr != _children.end(); ++itr)
    {
        TreeNode *child = *itr;
        if (child->_name == name)
            return child;

        TreeNode *res = child->findChildRecursively(name, maxDepth - 1);
        if (res != NULL)
            return res;
    }

    return NULL;
}

bool TreeNode::isLeaf() const
{
    return _children.empty();
}

bool TreeNode::isRoot() const
{
    return _parent == NULL;
}

int TreeNode::depth() const
{
    if (_children.empty())
        return 0;

    int max = 0;
    std::set<TreeNode*>::const_iterator itr;
    for (itr = _children.begin(); itr != _children.end(); ++itr)
        max = std::max(max, (*itr)->depth());

    return max + 1;
}

void TreeNode::_childDestroyed(TreeNode *child)
{
    removeChild(child);
}
<commit_msg>Bug correction in TreeNode constructors<commit_after>#include "treenode.h"

TreeNode::TreeNode(int type, TreeNode *parent) :
    _name(),
    _type(type),
    _flags(TreeFlags::NoNodeFlags),
    _parent(NULL),
    _children()
{
    if (parent != NULL)
        _parent = parent->addChild(this) ? parent : NULL;
}

TreeNode::TreeNode(const std::string &name, int type, TreeNode *parent) :
    _name(name),
    _type(type),
    _flags(TreeFlags::NoNodeFlags),
    _parent(NULL),
    _children()
{
    if (parent != NULL)
        _parent = parent->addChild(this) ? parent : NULL;
}

TreeNode::~TreeNode()
{
    if (_parent != NULL)
        _parent->_childDestroyed(this);

    std::set<TreeNode*>::const_iterator itr;
    for (itr = _children.begin(); itr != _children.end(); ++itr)
        delete *itr;
}

TreeFlags TreeNode::flags() const
{
    return _flags;
}

void TreeNode::setFlags(TreeFlags flags)
{
    _flags = flags;

    if (_flags & TreeFlags::NodeNeverHasChildren)
        _children.clear();
}

bool TreeNode::addChild(TreeNode *child)
{
    if (_flags & TreeFlags::NodeNeverHasChildren)
        return false;
    else if (child == NULL || child->_parent != NULL)
        return false;

    child->_parent = this;
    _children.insert(child);
    return true;
}

bool TreeNode::moveChild(TreeNode *child)
{
    if (_flags & TreeFlags::NodeNeverHasChildren)
        return false;
    else if (child == NULL)
        return false;

    if (child->_parent != NULL)
        child->_parent->removeChild(child);
    child->_parent = this;
    _children.insert(child);
    return true;
}

bool TreeNode::removeChild(TreeNode *child)
{
    return _children.erase(child);
}

const std::set<TreeNode*>& TreeNode::children() const
{
    return _children;
}

const TreeNode* TreeNode::findChild(const std::string &name) const
{
    std::set<TreeNode*>::const_iterator itr;
    for (itr = _children.begin(); itr != _children.end(); ++itr)
    {
        const TreeNode *child = *itr;
        if (child->_name == name)
            return child;
    }

    return NULL;
}

const TreeNode* TreeNode::findChildRecursively(const std::string &name, int maxDepth) const
{
    if (maxDepth == 0)
        return NULL;

    std::set<TreeNode*>::const_iterator itr;
    for (itr = _children.begin(); itr != _children.end(); ++itr)
    {
        const TreeNode *child = *itr;
        if (child->_name == name)
            return child;

        const TreeNode *res = child->findChildRecursively(name, maxDepth - 1);
        if (res != NULL)
            return res;
    }

    return NULL;
}

TreeNode* TreeNode::findChild(const std::string &name)
{
    std::set<TreeNode*>::iterator itr;
    for (itr = _children.begin(); itr != _children.end(); ++itr)
    {
        TreeNode *child = *itr;
        if (child->_name == name)
            return child;
    }

    return NULL;
}

TreeNode* TreeNode::findChildRecursively(const std::string &name, int maxDepth)
{
    if (maxDepth == 0)
        return NULL;

    std::set<TreeNode*>::iterator itr;
    for (itr = _children.begin(); itr != _children.end(); ++itr)
    {
        TreeNode *child = *itr;
        if (child->_name == name)
            return child;

        TreeNode *res = child->findChildRecursively(name, maxDepth - 1);
        if (res != NULL)
            return res;
    }

    return NULL;
}

bool TreeNode::isLeaf() const
{
    return _children.empty();
}

bool TreeNode::isRoot() const
{
    return _parent == NULL;
}

int TreeNode::depth() const
{
    if (_children.empty())
        return 0;

    int max = 0;
    std::set<TreeNode*>::const_iterator itr;
    for (itr = _children.begin(); itr != _children.end(); ++itr)
        max = std::max(max, (*itr)->depth());

    return max + 1;
}

void TreeNode::_childDestroyed(TreeNode *child)
{
    removeChild(child);
}
<|endoftext|>


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

#include <bitcoinaddressvalidator.h>

#include <base58.h>

/* Base58 characters are:
     "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"

  This is:
  - All numbers except for '0'
  - All upper-case letters except for 'I' and 'O'
  - All lower-case letters except for 'l'
*/

BitcoinAddressEntryValidator::BitcoinAddressEntryValidator(QObject *parent) :
    QValidator(parent)
{
}

QValidator::State BitcoinAddressEntryValidator::validate(QString &input, int &pos) const
{
    Q_UNUSED(pos);

    // Empty address is "intermediate" input
    if (input.isEmpty())
        return QValidator::Intermediate;

    // Correction
    for (int idx = 0; idx < input.size();)
    {
        bool removeChar = false;
        QChar ch = input.at(idx);
        // Corrections made are very conservative on purpose, to avoid
        // users unexpectedly getting away with typos that would normally
        // be detected, and thus sending to the wrong address.
        switch(ch.unicode())
        {
        // Qt categorizes these as "Other_Format" not "Separator_Space"
        case 0x200B: // ZERO WIDTH SPACE
        case 0xFEFF: // ZERO WIDTH NO-BREAK SPACE
            removeChar = true;
            break;
        default:
            break;
        }

        // Remove whitespace
        if (ch.isSpace())
            removeChar = true;

        // To next character
        if (removeChar)
            input.remove(idx, 1);
        else
            ++idx;
    }

    // Validation
    QValidator::State state = QValidator::Acceptable;
    for (int idx = 0; idx < input.size(); ++idx)
    {
        int ch = input.at(idx).unicode();

        if (((ch >= '0' && ch<='9') ||
            (ch >= 'a' && ch<='z') ||
            (ch >= 'A' && ch<='Z')) &&
            ch != 'l' && ch != 'I' && ch != '0' && ch != 'O')
        {
            // Alphanumeric and not a 'forbidden' character
        }
        else
        {
            state = QValidator::Invalid;
        }
    }

    return state;
}

BitcoinAddressCheckValidator::BitcoinAddressCheckValidator(QObject *parent) :
    QValidator(parent)
{
}

QValidator::State BitcoinAddressCheckValidator::validate(QString &input, int &pos) const
{
    Q_UNUSED(pos);
    // Validate the passed Chaincoin address
    if (IsValidDestinationString(input.toStdString())) {
        return QValidator::Acceptable;
    }

    return QValidator::Invalid;
}
<commit_msg>[Qt] tolerate BIP173/bech32 addresses during input validation<commit_after>// Copyright (c) 2011-2018 The Bitcoin Core developers
// Copyright (c) 2014-2017 The Dash Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include <bitcoinaddressvalidator.h>

#include <base58.h>

/* Base58 characters are:
     "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"

  This is:
  - All numbers except for '0'
  - All upper-case letters except for 'I' and 'O'
  - All lower-case letters except for 'l'
*/

BitcoinAddressEntryValidator::BitcoinAddressEntryValidator(QObject *parent) :
    QValidator(parent)
{
}

QValidator::State BitcoinAddressEntryValidator::validate(QString &input, int &pos) const
{
    Q_UNUSED(pos);

    // Empty address is "intermediate" input
    if (input.isEmpty())
        return QValidator::Intermediate;

    // Correction
    for (int idx = 0; idx < input.size();)
    {
        bool removeChar = false;
        QChar ch = input.at(idx);
        // Corrections made are very conservative on purpose, to avoid
        // users unexpectedly getting away with typos that would normally
        // be detected, and thus sending to the wrong address.
        switch(ch.unicode())
        {
        // Qt categorizes these as "Other_Format" not "Separator_Space"
        case 0x200B: // ZERO WIDTH SPACE
        case 0xFEFF: // ZERO WIDTH NO-BREAK SPACE
            removeChar = true;
            break;
        default:
            break;
        }

        // Remove whitespace
        if (ch.isSpace())
            removeChar = true;

        // To next character
        if (removeChar)
            input.remove(idx, 1);
        else
            ++idx;
    }

    // Validation
    QValidator::State state = QValidator::Acceptable;
    for (int idx = 0; idx < input.size(); ++idx)
    {
        int ch = input.at(idx).unicode();

        if (((ch >= '0' && ch<='9') ||
            (ch >= 'a' && ch<='z') ||
            (ch >= 'A' && ch<='Z')) &&
            ch != 'I' && ch != 'O') // Characters invalid in both Base58 and Bech32
        {
            // Alphanumeric and not a 'forbidden' character
        }
        else
        {
            state = QValidator::Invalid;
        }
    }

    return state;
}

BitcoinAddressCheckValidator::BitcoinAddressCheckValidator(QObject *parent) :
    QValidator(parent)
{
}

QValidator::State BitcoinAddressCheckValidator::validate(QString &input, int &pos) const
{
    Q_UNUSED(pos);
    // Validate the passed Chaincoin address
    if (IsValidDestinationString(input.toStdString())) {
        return QValidator::Acceptable;
    }

    return QValidator::Invalid;
}
<|endoftext|>


<commit_before>//===-- shm.cpp -----------------------------------------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// Save/restore via shared memory to survive exec*()
//
//===----------------------------------------------------------------------===//

#include "shm.h"

#include "ipcreg_internal.h"
#include "magic_socket_nums.h"
#include "real.h"
#include "rename_fd.h"

#include <sys/mman.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <string.h>

static char buf[100];
const char *getShmName() {
  sprintf(buf, "/ipcd.%d\n", getpid());
  return buf;
}

int get_shm(int flags, mode_t mode) {
  int fd = shm_open(getShmName(), flags, mode);
  if (fd != -1) {
    int ret = fchmod(fd, mode);
    if (ret == -1) {
      ipclog("Failure setting shared memory permissions: %s\n", strerror(errno));
    }
  }
  return fd;
}

void shm_state_save() {
  // Create shared memory segment
  int fd = get_shm(O_RDWR | O_CREAT | O_EXCL, 0600);
  assert(fd != -1);

  bool success = rename_fd(fd, MAGIC_SHM_FD, /* cloexec */ false);
  assert(success && "Failed to rename SHM fd!");

  // Do *not* close on exec! :)
  int flags = __real_fcntl(MAGIC_SHM_FD, F_GETFD, /* kludge */ 0);
  assert(flags >= 0);
  flags &= ~FD_CLOEXEC;
  int ret = __real_fcntl_int(MAGIC_SHM_FD, F_SETFD, flags);
  assert(ret != -1);

  // Size the memory segment:
  ret = ftruncate(MAGIC_SHM_FD, sizeof(libipc_state));
  assert(ret != -1);

  void *stateptr = mmap(NULL, sizeof(libipc_state), PROT_READ | PROT_WRITE,
                  MAP_SHARED, MAGIC_SHM_FD, 0);
  assert(stateptr != MAP_FAILED);

  // Copy state to shared memory segment
  *(libipc_state*)stateptr = state;

  // Unmap, but don't unlink the shared memory
  ret = munmap(stateptr, sizeof(libipc_state));
  assert(ret != -1);

  ipclog("State saved!\n");
}

bool is_valid_fd(int fd) {
  return __real_fcntl(fd, F_GETFD, /* kludge */ 0) >= 0;
}

void shm_state_restore() {
  // If we have memory to restore, it'll be in our magic FD!
  if (!is_valid_fd(MAGIC_SHM_FD))
    return;

  ipclog("Inherited ipc state FD, starting state restoration...\n");

  void *stateptr = mmap(NULL, sizeof(libipc_state), PROT_READ | PROT_WRITE,
                        MAP_SHARED, MAGIC_SHM_FD, 0);
  // If our FD is still open, the memory better still be there!
  assert(stateptr != MAP_FAILED);

  // Copy state to shared memory segment
  // Copy state from shared memory segment
  state = *(libipc_state*)stateptr;

  int ret = munmap(stateptr, sizeof(libipc_state));
  assert(ret != -1);

  // Done with the shared segment, thank you!
  ret = __real_close(MAGIC_SHM_FD);
  assert(ret != -1);
  ret = shm_unlink(getShmName());
  assert(ret != -1);

  ipclog("State restored!\n");

  // TODO!!
  ipclog("TODO: Process all close-on-exec fd's!\n");

}

void shm_state_destroy() {
  // If we have memory to restore, it'll be in our magic FD!
  assert(is_valid_fd(MAGIC_SHM_FD));

  int ret = __real_close(MAGIC_SHM_FD);
  assert(ret == 0);

  ret = shm_unlink(getShmName());
  assert(ret != -1);

  ipclog("Destroyed saved state!\n");
}
<commit_msg>libipc: Remove TODO about cloexec processing, done! :)<commit_after>//===-- shm.cpp -----------------------------------------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// Save/restore via shared memory to survive exec*()
//
//===----------------------------------------------------------------------===//

#include "shm.h"

#include "ipcreg_internal.h"
#include "magic_socket_nums.h"
#include "real.h"
#include "rename_fd.h"

#include <sys/mman.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <string.h>

static char buf[100];
const char *getShmName() {
  sprintf(buf, "/ipcd.%d\n", getpid());
  return buf;
}

int get_shm(int flags, mode_t mode) {
  int fd = shm_open(getShmName(), flags, mode);
  if (fd != -1) {
    int ret = fchmod(fd, mode);
    if (ret == -1) {
      ipclog("Failure setting shared memory permissions: %s\n", strerror(errno));
    }
  }
  return fd;
}

void shm_state_save() {
  // Create shared memory segment
  int fd = get_shm(O_RDWR | O_CREAT | O_EXCL, 0600);
  assert(fd != -1);

  bool success = rename_fd(fd, MAGIC_SHM_FD, /* cloexec */ false);
  assert(success && "Failed to rename SHM fd!");

  // Do *not* close on exec! :)
  int flags = __real_fcntl(MAGIC_SHM_FD, F_GETFD, /* kludge */ 0);
  assert(flags >= 0);
  flags &= ~FD_CLOEXEC;
  int ret = __real_fcntl_int(MAGIC_SHM_FD, F_SETFD, flags);
  assert(ret != -1);

  // Size the memory segment:
  ret = ftruncate(MAGIC_SHM_FD, sizeof(libipc_state));
  assert(ret != -1);

  void *stateptr = mmap(NULL, sizeof(libipc_state), PROT_READ | PROT_WRITE,
                  MAP_SHARED, MAGIC_SHM_FD, 0);
  assert(stateptr != MAP_FAILED);

  // Copy state to shared memory segment
  *(libipc_state*)stateptr = state;

  // Unmap, but don't unlink the shared memory
  ret = munmap(stateptr, sizeof(libipc_state));
  assert(ret != -1);

  ipclog("State saved!\n");
}

bool is_valid_fd(int fd) {
  return __real_fcntl(fd, F_GETFD, /* kludge */ 0) >= 0;
}

void shm_state_restore() {
  // If we have memory to restore, it'll be in our magic FD!
  if (!is_valid_fd(MAGIC_SHM_FD))
    return;

  ipclog("Inherited ipc state FD, starting state restoration...\n");

  void *stateptr = mmap(NULL, sizeof(libipc_state), PROT_READ | PROT_WRITE,
                        MAP_SHARED, MAGIC_SHM_FD, 0);
  // If our FD is still open, the memory better still be there!
  assert(stateptr != MAP_FAILED);

  // Copy state to shared memory segment
  // Copy state from shared memory segment
  state = *(libipc_state*)stateptr;

  int ret = munmap(stateptr, sizeof(libipc_state));
  assert(ret != -1);

  // Done with the shared segment, thank you!
  ret = __real_close(MAGIC_SHM_FD);
  assert(ret != -1);
  ret = shm_unlink(getShmName());
  assert(ret != -1);

  ipclog("State restored!\n");
}

void shm_state_destroy() {
  // If we have memory to restore, it'll be in our magic FD!
  assert(is_valid_fd(MAGIC_SHM_FD));

  int ret = __real_close(MAGIC_SHM_FD);
  assert(ret == 0);

  ret = shm_unlink(getShmName());
  assert(ret != -1);

  ipclog("Destroyed saved state!\n");
}
<|endoftext|>


<commit_before>/*
 * nghttp2 - HTTP/2 C Library
 *
 * Copyright (c) 2015 Tatsuhiro Tsujikawa
 *
 * Permission is hereby granted, free of charge, to any person obtaining
 * a copy of this software and associated documentation files (the
 * "Software"), to deal in the Software without restriction, including
 * without limitation the rights to use, copy, modify, merge, publish,
 * distribute, sublicense, and/or sell copies of the Software, and to
 * permit persons to whom the Software is furnished to do so, subject to
 * the following conditions:
 *
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */
#include "shrpx_mruby_module_response.h"

#include <mruby/variable.h>
#include <mruby/string.h>
#include <mruby/hash.h>
#include <mruby/array.h>

#include "shrpx_downstream.h"
#include "shrpx_upstream.h"
#include "shrpx_client_handler.h"
#include "shrpx_mruby.h"
#include "shrpx_mruby_module.h"
#include "util.h"
#include "http2.h"

namespace shrpx {

namespace mruby {

namespace {
mrb_value response_init(mrb_state *mrb, mrb_value self) { return self; }
} // namespace

namespace {
mrb_value response_get_http_version_major(mrb_state *mrb, mrb_value self) {
  auto data = static_cast<MRubyAssocData *>(mrb->ud);
  auto downstream = data->downstream;
  return mrb_fixnum_value(downstream->get_response_major());
}
} // namespace

namespace {
mrb_value response_get_http_version_minor(mrb_state *mrb, mrb_value self) {
  auto data = static_cast<MRubyAssocData *>(mrb->ud);
  auto downstream = data->downstream;
  return mrb_fixnum_value(downstream->get_response_minor());
}
} // namespace

namespace {
mrb_value response_get_status(mrb_state *mrb, mrb_value self) {
  auto data = static_cast<MRubyAssocData *>(mrb->ud);
  auto downstream = data->downstream;

  return mrb_fixnum_value(downstream->get_response_http_status());
}
} // namespace

namespace {
mrb_value response_set_status(mrb_state *mrb, mrb_value self) {
  auto data = static_cast<MRubyAssocData *>(mrb->ud);
  auto downstream = data->downstream;

  mrb_int status;
  mrb_get_args(mrb, "i", &status);
  // We don't support 1xx status code for mruby scripting yet.
  if (status < 200 || status > 999) {
    mrb_raise(mrb, E_RUNTIME_ERROR,
              "invalid status; it should be [200, 999], inclusive");
  }

  downstream->set_response_http_status(status);

  return self;
}
} // namespace

namespace {
mrb_value response_get_headers(mrb_state *mrb, mrb_value self) {
  auto data = static_cast<MRubyAssocData *>(mrb->ud);
  auto downstream = data->downstream;
  return create_headers_hash(mrb, downstream->get_response_headers());
}
} // namespace

namespace {
mrb_value response_mod_header(mrb_state *mrb, mrb_value self, bool repl) {
  auto data = static_cast<MRubyAssocData *>(mrb->ud);
  auto downstream = data->downstream;

  mrb_value key, values;
  mrb_get_args(mrb, "oo", &key, &values);

  if (RSTRING_LEN(key) == 0) {
    mrb_raise(mrb, E_RUNTIME_ERROR, "empty key is not allowed");
  }

  key = mrb_funcall(mrb, key, "downcase", 0);

  if (repl) {
    size_t p = 0;
    auto &headers = downstream->get_response_headers();
    for (size_t i = 0; i < headers.size(); ++i) {
      auto &hd = headers[i];
      if (util::streq(std::begin(hd.name), hd.name.size(), RSTRING_PTR(key),
                      RSTRING_LEN(key))) {
        continue;
      }
      if (i != p) {
        headers[p++] = std::move(hd);
      }
    }
    headers.resize(p);
  }

  if (mrb_obj_is_instance_of(mrb, values, mrb->array_class)) {
    auto n = mrb_ary_len(mrb, values);
    for (int i = 0; i < n; ++i) {
      auto value = mrb_ary_entry(values, i);
      downstream->add_response_header(
          std::string(RSTRING_PTR(key), RSTRING_LEN(key)),
          std::string(RSTRING_PTR(value), RSTRING_LEN(value)));
    }
  } else if (!mrb_nil_p(values)) {
    downstream->add_response_header(
        std::string(RSTRING_PTR(key), RSTRING_LEN(key)),
        std::string(RSTRING_PTR(values), RSTRING_LEN(values)));
  }

  data->response_headers_dirty = true;

  return mrb_nil_value();
}
} // namespace

namespace {
mrb_value response_set_header(mrb_state *mrb, mrb_value self) {
  return response_mod_header(mrb, self, true);
}
} // namespace

namespace {
mrb_value response_add_header(mrb_state *mrb, mrb_value self) {
  return response_mod_header(mrb, self, false);
}
} // namespace

namespace {
mrb_value response_clear_headers(mrb_state *mrb, mrb_value self) {
  auto data = static_cast<MRubyAssocData *>(mrb->ud);
  auto downstream = data->downstream;

  downstream->clear_response_headers();

  return mrb_nil_value();
}
} // namespace

namespace {
mrb_value response_return(mrb_state *mrb, mrb_value self) {
  auto data = static_cast<MRubyAssocData *>(mrb->ud);
  auto downstream = data->downstream;
  int rv;

  if (downstream->get_response_state() == Downstream::MSG_COMPLETE) {
    mrb_raise(mrb, E_RUNTIME_ERROR, "response has already been committed");
  }

  mrb_value val;
  mrb_get_args(mrb, "|o", &val);

  const uint8_t *body = nullptr;
  size_t bodylen = 0;

  if (downstream->get_response_http_status() == 0) {
    downstream->set_response_http_status(200);
  }

  if (data->response_headers_dirty) {
    downstream->index_response_headers();
    data->response_headers_dirty = false;
  }

  if (downstream->expect_response_body() && !mrb_nil_p(val)) {
    body = reinterpret_cast<const uint8_t *>(RSTRING_PTR(val));
    bodylen = RSTRING_LEN(val);
  }

  auto cl = downstream->get_response_header(http2::HD_CONTENT_LENGTH);
  if (cl) {
    cl->value = util::utos(bodylen);
  } else {
    downstream->add_response_header("content-length", util::utos(bodylen),
                                    http2::HD_CONTENT_LENGTH);
  }
  downstream->set_response_content_length(bodylen);

  auto upstream = downstream->get_upstream();

  rv = upstream->send_reply(downstream, body, bodylen);
  if (rv != 0) {
    mrb_raise(mrb, E_RUNTIME_ERROR, "could not send response");
  }

  auto handler = upstream->get_client_handler();

  handler->signal_write();

  return self;
}
} // namespace

void init_response_class(mrb_state *mrb, RClass *module) {
  auto response_class =
      mrb_define_class_under(mrb, module, "Response", mrb->object_class);

  mrb_define_method(mrb, response_class, "initialize", response_init,
                    MRB_ARGS_NONE());
  mrb_define_method(mrb, response_class, "http_version_major",
                    response_get_http_version_major, MRB_ARGS_NONE());
  mrb_define_method(mrb, response_class, "http_version_minor",
                    response_get_http_version_minor, MRB_ARGS_NONE());
  mrb_define_method(mrb, response_class, "status", response_get_status,
                    MRB_ARGS_NONE());
  mrb_define_method(mrb, response_class, "status=", response_set_status,
                    MRB_ARGS_REQ(1));
  mrb_define_method(mrb, response_class, "headers", response_get_headers,
                    MRB_ARGS_NONE());
  mrb_define_method(mrb, response_class, "add_header", response_add_header,
                    MRB_ARGS_REQ(2));
  mrb_define_method(mrb, response_class, "set_header", response_set_header,
                    MRB_ARGS_REQ(2));
  mrb_define_method(mrb, response_class, "clear_headers",
                    response_clear_headers, MRB_ARGS_NONE());
  mrb_define_method(mrb, response_class, "return", response_return,
                    MRB_ARGS_OPT(1));
}

} // namespace mruby

} // namespace shrpx
<commit_msg>nghttpx: Use 's' for param of Response::return<commit_after>/*
 * nghttp2 - HTTP/2 C Library
 *
 * Copyright (c) 2015 Tatsuhiro Tsujikawa
 *
 * Permission is hereby granted, free of charge, to any person obtaining
 * a copy of this software and associated documentation files (the
 * "Software"), to deal in the Software without restriction, including
 * without limitation the rights to use, copy, modify, merge, publish,
 * distribute, sublicense, and/or sell copies of the Software, and to
 * permit persons to whom the Software is furnished to do so, subject to
 * the following conditions:
 *
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */
#include "shrpx_mruby_module_response.h"

#include <mruby/variable.h>
#include <mruby/string.h>
#include <mruby/hash.h>
#include <mruby/array.h>

#include "shrpx_downstream.h"
#include "shrpx_upstream.h"
#include "shrpx_client_handler.h"
#include "shrpx_mruby.h"
#include "shrpx_mruby_module.h"
#include "util.h"
#include "http2.h"

namespace shrpx {

namespace mruby {

namespace {
mrb_value response_init(mrb_state *mrb, mrb_value self) { return self; }
} // namespace

namespace {
mrb_value response_get_http_version_major(mrb_state *mrb, mrb_value self) {
  auto data = static_cast<MRubyAssocData *>(mrb->ud);
  auto downstream = data->downstream;
  return mrb_fixnum_value(downstream->get_response_major());
}
} // namespace

namespace {
mrb_value response_get_http_version_minor(mrb_state *mrb, mrb_value self) {
  auto data = static_cast<MRubyAssocData *>(mrb->ud);
  auto downstream = data->downstream;
  return mrb_fixnum_value(downstream->get_response_minor());
}
} // namespace

namespace {
mrb_value response_get_status(mrb_state *mrb, mrb_value self) {
  auto data = static_cast<MRubyAssocData *>(mrb->ud);
  auto downstream = data->downstream;

  return mrb_fixnum_value(downstream->get_response_http_status());
}
} // namespace

namespace {
mrb_value response_set_status(mrb_state *mrb, mrb_value self) {
  auto data = static_cast<MRubyAssocData *>(mrb->ud);
  auto downstream = data->downstream;

  mrb_int status;
  mrb_get_args(mrb, "i", &status);
  // We don't support 1xx status code for mruby scripting yet.
  if (status < 200 || status > 999) {
    mrb_raise(mrb, E_RUNTIME_ERROR,
              "invalid status; it should be [200, 999], inclusive");
  }

  downstream->set_response_http_status(status);

  return self;
}
} // namespace

namespace {
mrb_value response_get_headers(mrb_state *mrb, mrb_value self) {
  auto data = static_cast<MRubyAssocData *>(mrb->ud);
  auto downstream = data->downstream;
  return create_headers_hash(mrb, downstream->get_response_headers());
}
} // namespace

namespace {
mrb_value response_mod_header(mrb_state *mrb, mrb_value self, bool repl) {
  auto data = static_cast<MRubyAssocData *>(mrb->ud);
  auto downstream = data->downstream;

  mrb_value key, values;
  mrb_get_args(mrb, "oo", &key, &values);

  if (RSTRING_LEN(key) == 0) {
    mrb_raise(mrb, E_RUNTIME_ERROR, "empty key is not allowed");
  }

  key = mrb_funcall(mrb, key, "downcase", 0);

  if (repl) {
    size_t p = 0;
    auto &headers = downstream->get_response_headers();
    for (size_t i = 0; i < headers.size(); ++i) {
      auto &hd = headers[i];
      if (util::streq(std::begin(hd.name), hd.name.size(), RSTRING_PTR(key),
                      RSTRING_LEN(key))) {
        continue;
      }
      if (i != p) {
        headers[p++] = std::move(hd);
      }
    }
    headers.resize(p);
  }

  if (mrb_obj_is_instance_of(mrb, values, mrb->array_class)) {
    auto n = mrb_ary_len(mrb, values);
    for (int i = 0; i < n; ++i) {
      auto value = mrb_ary_entry(values, i);
      downstream->add_response_header(
          std::string(RSTRING_PTR(key), RSTRING_LEN(key)),
          std::string(RSTRING_PTR(value), RSTRING_LEN(value)));
    }
  } else if (!mrb_nil_p(values)) {
    downstream->add_response_header(
        std::string(RSTRING_PTR(key), RSTRING_LEN(key)),
        std::string(RSTRING_PTR(values), RSTRING_LEN(values)));
  }

  data->response_headers_dirty = true;

  return mrb_nil_value();
}
} // namespace

namespace {
mrb_value response_set_header(mrb_state *mrb, mrb_value self) {
  return response_mod_header(mrb, self, true);
}
} // namespace

namespace {
mrb_value response_add_header(mrb_state *mrb, mrb_value self) {
  return response_mod_header(mrb, self, false);
}
} // namespace

namespace {
mrb_value response_clear_headers(mrb_state *mrb, mrb_value self) {
  auto data = static_cast<MRubyAssocData *>(mrb->ud);
  auto downstream = data->downstream;

  downstream->clear_response_headers();

  return mrb_nil_value();
}
} // namespace

namespace {
mrb_value response_return(mrb_state *mrb, mrb_value self) {
  auto data = static_cast<MRubyAssocData *>(mrb->ud);
  auto downstream = data->downstream;
  int rv;

  if (downstream->get_response_state() == Downstream::MSG_COMPLETE) {
    mrb_raise(mrb, E_RUNTIME_ERROR, "response has already been committed");
  }

  const char *val;
  mrb_int vallen;
  mrb_get_args(mrb, "|s", &val, &vallen);

  const uint8_t *body = nullptr;
  size_t bodylen = 0;

  if (downstream->get_response_http_status() == 0) {
    downstream->set_response_http_status(200);
  }

  if (data->response_headers_dirty) {
    downstream->index_response_headers();
    data->response_headers_dirty = false;
  }

  if (downstream->expect_response_body() && vallen > 0) {
    body = reinterpret_cast<const uint8_t *>(val);
    bodylen = vallen;
  }

  auto cl = downstream->get_response_header(http2::HD_CONTENT_LENGTH);
  if (cl) {
    cl->value = util::utos(bodylen);
  } else {
    downstream->add_response_header("content-length", util::utos(bodylen),
                                    http2::HD_CONTENT_LENGTH);
  }
  downstream->set_response_content_length(bodylen);

  auto upstream = downstream->get_upstream();

  rv = upstream->send_reply(downstream, body, bodylen);
  if (rv != 0) {
    mrb_raise(mrb, E_RUNTIME_ERROR, "could not send response");
  }

  auto handler = upstream->get_client_handler();

  handler->signal_write();

  return self;
}
} // namespace

void init_response_class(mrb_state *mrb, RClass *module) {
  auto response_class =
      mrb_define_class_under(mrb, module, "Response", mrb->object_class);

  mrb_define_method(mrb, response_class, "initialize", response_init,
                    MRB_ARGS_NONE());
  mrb_define_method(mrb, response_class, "http_version_major",
                    response_get_http_version_major, MRB_ARGS_NONE());
  mrb_define_method(mrb, response_class, "http_version_minor",
                    response_get_http_version_minor, MRB_ARGS_NONE());
  mrb_define_method(mrb, response_class, "status", response_get_status,
                    MRB_ARGS_NONE());
  mrb_define_method(mrb, response_class, "status=", response_set_status,
                    MRB_ARGS_REQ(1));
  mrb_define_method(mrb, response_class, "headers", response_get_headers,
                    MRB_ARGS_NONE());
  mrb_define_method(mrb, response_class, "add_header", response_add_header,
                    MRB_ARGS_REQ(2));
  mrb_define_method(mrb, response_class, "set_header", response_set_header,
                    MRB_ARGS_REQ(2));
  mrb_define_method(mrb, response_class, "clear_headers",
                    response_clear_headers, MRB_ARGS_NONE());
  mrb_define_method(mrb, response_class, "return", response_return,
                    MRB_ARGS_OPT(1));
}

} // namespace mruby

} // namespace shrpx
<|endoftext|>


<commit_before>/*
 *                         OpenSplice DDS
 *
 *   This software and documentation are Copyright 2006 to TO_YEAR PrismTech
 *   Limited, its affiliated companies and licensors. 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.
 *
 */
#include "idl.h"
#include "idl_extern.h"

#include "xbe_utils.h"
#include "xbe_globals.h"
#include "xbe_literals.h"
#include "xbe_root.h"
#include "xbe_exception.h"
#include "xbe_interface.h"
#include "xbe_sequence.h"
#include "xbe_cppfwd.h"
#include "Std.h"
#include "xbe_genlist.h"

#include "cppgen_iostream.h"

static void
sanitize(DDS_StdString& str)
{
   for (unsigned int i = 0; i < str.length(); i++)
   {
      if ( (str[i] < 0x30) ||
            ( (str[i] > 0x39) && (str[i] < 0x41) ) ||
            ( (str[i] > 0x5A) && (str[i] < 0x61) && (str[i] != 0x5F) ) ||
            (str[i] > 0x7A) )
      {
         str[i] = '_';
      }
   }
}

static DDS_StdString
main_file_identifier()
{
   DDS_StdString mainFile = BaseName(idl_global->main_filename()->get_string());
   char *dot = (char*)strrchr((const char*)mainFile, '.');

   if (dot)
   {
      *dot = 0;
   }

   sanitize(mainFile);

   return mainFile;
}

// -------------------------------------------------
//  BE_ROOT IMPLEMENTATION
// -------------------------------------------------
IMPL_NARROW_METHODS2(be_root, AST_Root, be_CodeGenerator)
IMPL_NARROW_FROM_DECL(be_root)
IMPL_NARROW_FROM_SCOPE(be_root)

TList<be_Type *> &be_root::anyOps = *new TList<be_Type *>;
TList<be_Type *> &be_root::putGetOps = *new TList<be_Type *>;
TList<be_Type *> &be_root::streamOps = *new TList<be_Type *>;
TList<be_Type *> &be_root::typecodes = *new TList<be_Type *>;
TList<be_Type *> &be_root::typesThatNeedProtoTypeCodesFinished = *new TList<be_Type *>;
TList<be_Type *> &be_root::typedefs = *new TList<be_Type *>;
TList<be_Type *> &be_root::fwdDecls = *new TList<be_Type *>;
TList<be_exception *> &be_root::globalDecls = *new TList<be_exception *> ;
TList<be_CodeGenerator *> &be_root::implementations = *new TList<be_CodeGenerator *>;
TList<be_sequence*> &be_root::deferred_seqs = *new TList<be_sequence*>;

be_root::be_root ()
{
   isAtModuleScope (pbfalse);
}

be_root::be_root (UTL_ScopedName *n, const UTL_Pragmas &p)
   : AST_Root (n, p)
{
   isAtModuleScope (pbfalse);
}

void be_root::AddAnyOps (be_Type& btype)
{
   DDS::Boolean isUniqueOp = TRUE;
   TList<be_Type*>::iterator bit;

   //
   // multiple instantiations of an anonymous type can
   // cause duplicate definitions of an op without the
   // following filter
   //

   for (bit = anyOps.begin(); bit != anyOps.end(); bit++)
   {
      be_Type& thatType = *(*bit); // YO should be const

      if (btype.any_op_id() == thatType.any_op_id())
      {
         isUniqueOp = FALSE;
      }
   }

   if (isUniqueOp)
   {
      anyOps.push_back (&btype);
   }
}

void be_root::AddPutGetOps (be_Type& btype)
{
   DDS::Boolean isUniqueOp = TRUE;

   //
   // multiple instantiations of an anonymous type can
   // cause duplicate definitions of an op without the
   // following filter
   //

   if (isUniqueOp)
   {
      putGetOps.push_back (&btype);
   }
}

void be_root::AddStreamOps (be_Type& btype)
{
   DDS::Boolean isUniqueOp = TRUE;
   TList<be_Type *>::iterator bit;

   //
   // multiple instantiations of an anonymous type can
   // cause duplicate definitions of an op without the
   // following filter
   //

   for (bit = streamOps.begin(); bit != streamOps.end(); bit++)
   {
      if (btype.any_op_id() == (*bit)->any_op_id())
      {
         isUniqueOp = FALSE;
      }
   }

   if (isUniqueOp)
   {
      streamOps.push_back (&btype);
   }
}

void be_root::AddFwdDecls (be_Type & btype)
{
   fwdDecls.push_back (&btype);
}

void be_root::RemoveFwdDecls (be_Type & btype)
{
   fwdDecls.remove (&btype);
}

void be_root::AddTypedef (be_Type& btype)
{
   typedefs.push_back (&btype);
}

void be_root::AddTypecode (be_Type& btype)
{
   typecodes.push_back (&btype);
}

void be_root::AddTypeThatNeedsProtoTypeCodeFinished (be_Type& btype)
{
   typesThatNeedProtoTypeCodesFinished.push_back (&btype);
}

void be_root::AddGlobalDeclarations (be_exception * bexcept)
{
   assert (bexcept);
   globalDecls.push_back (bexcept);
}

void be_root::AddImplementations (be_CodeGenerator& cg)
{
   implementations.push_front (&cg);
}

void be_root::DeferSequence (be_sequence* s)
{
   assert (s);
   deferred_seqs.push_back (s);
}

void be_root::GenerateGlobalTypes (be_ClientHeader& source)
{
   UTL_ScopeActiveIterator * i;
   be_CodeGenerator * cg;
   AST_Decl * d;
   be_Type * bt;
   DDS_StdString scope;
   UTL_Scope * s = (UTL_Scope*) narrow ((long) & UTL_Scope::type_id);

   if (s)
   {
      // Iterate through types

      i = new UTL_ScopeActiveIterator (s, UTL_Scope::IK_localtypes);

      while (! i->is_done ())
      {
         d = i->item ();

         if (! d->imported ())
         {
            cg = (be_CodeGenerator*) d->narrow
               ((long) & be_CodeGenerator::type_id);
            if (cg)
            {
               bt = (be_Type*) d->narrow ((long) & be_Type::type_id);

               scope = bt->EnclosingScope ();
               if (! bt->HasTypeDef () && scope == NULL)
               {
                  cg->Generate (source);
               }
            }
         }

         i->next ();
      }

      delete i;
   }
}

void be_root::GenerateGlobalDecls (be_ClientHeader & source)
{
   UTL_ScopeActiveIterator * i;
   be_CodeGenerator * cg;
   AST_Decl * d;
   UTL_Scope * s = (UTL_Scope*) narrow ((long) & UTL_Scope::type_id);

   if (s)
   {
      // Iterate through decls

      i = new UTL_ScopeActiveIterator (s, UTL_Scope::IK_decls);

      while (!(i->is_done ()))
      {
         d = i->item ();

         if (!d->imported ())
         {
            cg = (be_CodeGenerator*) d->narrow
               ((long) & be_CodeGenerator::type_id);

            if (cg)
            {
               cg->Generate (source);
            }
         }

         i->next ();
      }

      delete i;
   }
}

void be_root::Generate (be_ClientHeader & source)
{
   be_CppFwdDecl::GenerateAllWithinScope (source, be_CppEnclosingScope());

   ostream& os = source.Stream ();
   TList<be_Type *>::iterator bit;
   TList<be_exception *>::iterator git;

   for (bit = fwdDecls.begin(); bit != fwdDecls.end(); bit++)
   {
      (*bit)->GenerateFwdDecls(source);
   }

   os << nl;
   GenerateGlobalTypes (source);
   GenerateGlobalDecls (source);

   g_generatorList.GenerateGlobal (source);

   if (BE_Globals::gen_externalization)
   {
      os << nl;

      for (bit = streamOps.begin(); bit != streamOps.end(); bit++)
      {
         (*bit)->GenerateStreamOps(source);
      }
   }

   os << nl;

   for (git = globalDecls.begin(); git != globalDecls.end(); git++)
   {
      (*git)->GenerateGlobalDecls (source);
   }

   os << nl;

   for (bit = typedefs.begin(); bit != typedefs.end(); bit++)
   {
      (*bit)->GenerateGlobalTypedef (source);
   }

   os << nl;

   if(BE_Globals::isocpp_test_methods)
   {
      //Generate file to stop missing file error
      DDS_StdString BaseFilename;
      BaseFilename = StripExtension(source.Filename());
      BaseFilename += "_testmethod.h";
      be_Source testsource;
      if(!testsource.Open(BaseFilename))
        cerr << "Cannot open: " << BaseFilename << endl;
      testsource.Close();

      //os << nl << "#ifndef " << Ifndefize(BE_Globals::ClientHeaderFilename + "DCPS");
      os << nl << "#ifndef " << Ifndefize(StripExtension(FindFilename(source.Filename())) + "DCPS.h");
      os << nl << "#ifndef " << Ifndefize(StripExtension(FindFilename(source.Filename())) + "_testmethod.h");
      os << nl << "#define " << Ifndefize(StripExtension(FindFilename(source.Filename())) + "_testmethod.h");
      os << nl << "#include \"" << StripExtension(FindFilename(source.Filename())) + "_testmethod.h" << "\"";
      os << nl << "#endif " << nl << "#endif" << nl;

   }
   if (BE_Globals::UserDLL != (const char *)"") {
       os << nl << "#undef " << BE_Globals::UserDLL << nl;
   }

   if (BE_Globals::lite)
   {
       DDS_StdString BaseFilename;
       BaseFilename = StripExtension(source.Filename());

       os << "\n#include \"" << BaseFilename << "-lite.h" << "\"" << nl;
   }

   os << nl << "#endif" << nl;
   source.Close();
}

void be_root::Generate (be_ServerHeader& source)
{
   ostream & os = source.Stream();

   be_CodeGenerator::Generate (source);

   os << nl << "#endif" << nl;

   source.Close ();

#if defined(DDS_TIE_HEADER)

   ostream & tos = source.tieHeader.Stream ();
   tos << nl;
   tos << "#endif" << nl;
   tos << nl;
   source.tieHeader.Close ();
#endif

}

void be_root::Generate (be_ClientImplementation & source)
{
   ostream & os = source.Stream ();
   TList<be_CodeGenerator*>::iterator iit;
   TList<be_Type*>::iterator bit;

   for (iit = implementations.begin(); iit != implementations.end(); iit++)
   {
      (*iit)->Generate(source);
   }

   os << nl;

   be_CodeGenerator::Generate (source);

   os << nl;

   if (BE_Globals::lite)
   {
       DDS_StdString BaseFilename;
       BaseFilename = StripExtension(source.Filename());

       os << "#include \"" << BaseFilename << "-lite.c" << "\"" << nl;
   }
   os << nl;
   source.Close();
}

void be_root::Generate (be_ServerImplementation& source)
{
   const DDS_StdString corbaException = BE_Globals::CorbaScope("Exception");
   ostream & os = source.Stream ();

   be_CodeGenerator::Generate (source);

   os << nl << endl;
   source.Close();
}

void be_root::GenerateDependants
(
   be_ClientHeader & source,
   const char* dep,
   const char * scope
)
{
   DDS_StdString depname (dep);
   DDS_StdString nuScope (scope);

   TList<be_sequence*>::iterator it = be_root::deferred_seqs.begin ();

   while (it != be_root::deferred_seqs.end ())
   {
      be_sequence& sequence = *(*it);

      if (sequence.BaseTypeName () == depname)
      {
         sequence.SetName (nuScope, sequence.LocalName());
         sequence.Generate (source);

         GenerateDependants (source, sequence.LocalName(), scope);
      }

      ++it;
   }
}

void be_root::FinishAllProtoTypeCodes ()
{
   TList<be_Type*>::iterator iter;

   for
   (
      iter = typesThatNeedProtoTypeCodesFinished.begin ();
      iter != typesThatNeedProtoTypeCodesFinished.end ();
      ++iter
   )
   {
      be_Type & beType = *(*iter);
      beType.FinishProtoTypeCode ();
   }
}
<commit_msg>OSPL-10810 Remove undef of dll_macro_name given to idlpp -P<commit_after>/*
 *                         OpenSplice DDS
 *
 *   This software and documentation are Copyright 2006 to TO_YEAR PrismTech
 *   Limited, its affiliated companies and licensors. 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.
 *
 */
#include "idl.h"
#include "idl_extern.h"

#include "xbe_utils.h"
#include "xbe_globals.h"
#include "xbe_literals.h"
#include "xbe_root.h"
#include "xbe_exception.h"
#include "xbe_interface.h"
#include "xbe_sequence.h"
#include "xbe_cppfwd.h"
#include "Std.h"
#include "xbe_genlist.h"

#include "cppgen_iostream.h"

static void
sanitize(DDS_StdString& str)
{
   for (unsigned int i = 0; i < str.length(); i++)
   {
      if ( (str[i] < 0x30) ||
            ( (str[i] > 0x39) && (str[i] < 0x41) ) ||
            ( (str[i] > 0x5A) && (str[i] < 0x61) && (str[i] != 0x5F) ) ||
            (str[i] > 0x7A) )
      {
         str[i] = '_';
      }
   }
}

static DDS_StdString
main_file_identifier()
{
   DDS_StdString mainFile = BaseName(idl_global->main_filename()->get_string());
   char *dot = (char*)strrchr((const char*)mainFile, '.');

   if (dot)
   {
      *dot = 0;
   }

   sanitize(mainFile);

   return mainFile;
}

// -------------------------------------------------
//  BE_ROOT IMPLEMENTATION
// -------------------------------------------------
IMPL_NARROW_METHODS2(be_root, AST_Root, be_CodeGenerator)
IMPL_NARROW_FROM_DECL(be_root)
IMPL_NARROW_FROM_SCOPE(be_root)

TList<be_Type *> &be_root::anyOps = *new TList<be_Type *>;
TList<be_Type *> &be_root::putGetOps = *new TList<be_Type *>;
TList<be_Type *> &be_root::streamOps = *new TList<be_Type *>;
TList<be_Type *> &be_root::typecodes = *new TList<be_Type *>;
TList<be_Type *> &be_root::typesThatNeedProtoTypeCodesFinished = *new TList<be_Type *>;
TList<be_Type *> &be_root::typedefs = *new TList<be_Type *>;
TList<be_Type *> &be_root::fwdDecls = *new TList<be_Type *>;
TList<be_exception *> &be_root::globalDecls = *new TList<be_exception *> ;
TList<be_CodeGenerator *> &be_root::implementations = *new TList<be_CodeGenerator *>;
TList<be_sequence*> &be_root::deferred_seqs = *new TList<be_sequence*>;

be_root::be_root ()
{
   isAtModuleScope (pbfalse);
}

be_root::be_root (UTL_ScopedName *n, const UTL_Pragmas &p)
   : AST_Root (n, p)
{
   isAtModuleScope (pbfalse);
}

void be_root::AddAnyOps (be_Type& btype)
{
   DDS::Boolean isUniqueOp = TRUE;
   TList<be_Type*>::iterator bit;

   //
   // multiple instantiations of an anonymous type can
   // cause duplicate definitions of an op without the
   // following filter
   //

   for (bit = anyOps.begin(); bit != anyOps.end(); bit++)
   {
      be_Type& thatType = *(*bit); // YO should be const

      if (btype.any_op_id() == thatType.any_op_id())
      {
         isUniqueOp = FALSE;
      }
   }

   if (isUniqueOp)
   {
      anyOps.push_back (&btype);
   }
}

void be_root::AddPutGetOps (be_Type& btype)
{
   DDS::Boolean isUniqueOp = TRUE;

   //
   // multiple instantiations of an anonymous type can
   // cause duplicate definitions of an op without the
   // following filter
   //

   if (isUniqueOp)
   {
      putGetOps.push_back (&btype);
   }
}

void be_root::AddStreamOps (be_Type& btype)
{
   DDS::Boolean isUniqueOp = TRUE;
   TList<be_Type *>::iterator bit;

   //
   // multiple instantiations of an anonymous type can
   // cause duplicate definitions of an op without the
   // following filter
   //

   for (bit = streamOps.begin(); bit != streamOps.end(); bit++)
   {
      if (btype.any_op_id() == (*bit)->any_op_id())
      {
         isUniqueOp = FALSE;
      }
   }

   if (isUniqueOp)
   {
      streamOps.push_back (&btype);
   }
}

void be_root::AddFwdDecls (be_Type & btype)
{
   fwdDecls.push_back (&btype);
}

void be_root::RemoveFwdDecls (be_Type & btype)
{
   fwdDecls.remove (&btype);
}

void be_root::AddTypedef (be_Type& btype)
{
   typedefs.push_back (&btype);
}

void be_root::AddTypecode (be_Type& btype)
{
   typecodes.push_back (&btype);
}

void be_root::AddTypeThatNeedsProtoTypeCodeFinished (be_Type& btype)
{
   typesThatNeedProtoTypeCodesFinished.push_back (&btype);
}

void be_root::AddGlobalDeclarations (be_exception * bexcept)
{
   assert (bexcept);
   globalDecls.push_back (bexcept);
}

void be_root::AddImplementations (be_CodeGenerator& cg)
{
   implementations.push_front (&cg);
}

void be_root::DeferSequence (be_sequence* s)
{
   assert (s);
   deferred_seqs.push_back (s);
}

void be_root::GenerateGlobalTypes (be_ClientHeader& source)
{
   UTL_ScopeActiveIterator * i;
   be_CodeGenerator * cg;
   AST_Decl * d;
   be_Type * bt;
   DDS_StdString scope;
   UTL_Scope * s = (UTL_Scope*) narrow ((long) & UTL_Scope::type_id);

   if (s)
   {
      // Iterate through types

      i = new UTL_ScopeActiveIterator (s, UTL_Scope::IK_localtypes);

      while (! i->is_done ())
      {
         d = i->item ();

         if (! d->imported ())
         {
            cg = (be_CodeGenerator*) d->narrow
               ((long) & be_CodeGenerator::type_id);
            if (cg)
            {
               bt = (be_Type*) d->narrow ((long) & be_Type::type_id);

               scope = bt->EnclosingScope ();
               if (! bt->HasTypeDef () && scope == NULL)
               {
                  cg->Generate (source);
               }
            }
         }

         i->next ();
      }

      delete i;
   }
}

void be_root::GenerateGlobalDecls (be_ClientHeader & source)
{
   UTL_ScopeActiveIterator * i;
   be_CodeGenerator * cg;
   AST_Decl * d;
   UTL_Scope * s = (UTL_Scope*) narrow ((long) & UTL_Scope::type_id);

   if (s)
   {
      // Iterate through decls

      i = new UTL_ScopeActiveIterator (s, UTL_Scope::IK_decls);

      while (!(i->is_done ()))
      {
         d = i->item ();

         if (!d->imported ())
         {
            cg = (be_CodeGenerator*) d->narrow
               ((long) & be_CodeGenerator::type_id);

            if (cg)
            {
               cg->Generate (source);
            }
         }

         i->next ();
      }

      delete i;
   }
}

void be_root::Generate (be_ClientHeader & source)
{
   be_CppFwdDecl::GenerateAllWithinScope (source, be_CppEnclosingScope());

   ostream& os = source.Stream ();
   TList<be_Type *>::iterator bit;
   TList<be_exception *>::iterator git;

   for (bit = fwdDecls.begin(); bit != fwdDecls.end(); bit++)
   {
      (*bit)->GenerateFwdDecls(source);
   }

   os << nl;
   GenerateGlobalTypes (source);
   GenerateGlobalDecls (source);

   g_generatorList.GenerateGlobal (source);

   if (BE_Globals::gen_externalization)
   {
      os << nl;

      for (bit = streamOps.begin(); bit != streamOps.end(); bit++)
      {
         (*bit)->GenerateStreamOps(source);
      }
   }

   os << nl;

   for (git = globalDecls.begin(); git != globalDecls.end(); git++)
   {
      (*git)->GenerateGlobalDecls (source);
   }

   os << nl;

   for (bit = typedefs.begin(); bit != typedefs.end(); bit++)
   {
      (*bit)->GenerateGlobalTypedef (source);
   }

   os << nl;

   if(BE_Globals::isocpp_test_methods)
   {
      //Generate file to stop missing file error
      DDS_StdString BaseFilename;
      BaseFilename = StripExtension(source.Filename());
      BaseFilename += "_testmethod.h";
      be_Source testsource;
      if(!testsource.Open(BaseFilename))
        cerr << "Cannot open: " << BaseFilename << endl;
      testsource.Close();

      //os << nl << "#ifndef " << Ifndefize(BE_Globals::ClientHeaderFilename + "DCPS");
      os << nl << "#ifndef " << Ifndefize(StripExtension(FindFilename(source.Filename())) + "DCPS.h");
      os << nl << "#ifndef " << Ifndefize(StripExtension(FindFilename(source.Filename())) + "_testmethod.h");
      os << nl << "#define " << Ifndefize(StripExtension(FindFilename(source.Filename())) + "_testmethod.h");
      os << nl << "#include \"" << StripExtension(FindFilename(source.Filename())) + "_testmethod.h" << "\"";
      os << nl << "#endif " << nl << "#endif" << nl;

   }

   if (BE_Globals::lite)
   {
       DDS_StdString BaseFilename;
       BaseFilename = StripExtension(source.Filename());

       os << "\n#include \"" << BaseFilename << "-lite.h" << "\"" << nl;
   }

   os << nl << "#endif" << nl;
   source.Close();
}

void be_root::Generate (be_ServerHeader& source)
{
   ostream & os = source.Stream();

   be_CodeGenerator::Generate (source);

   os << nl << "#endif" << nl;

   source.Close ();

#if defined(DDS_TIE_HEADER)

   ostream & tos = source.tieHeader.Stream ();
   tos << nl;
   tos << "#endif" << nl;
   tos << nl;
   source.tieHeader.Close ();
#endif

}

void be_root::Generate (be_ClientImplementation & source)
{
   ostream & os = source.Stream ();
   TList<be_CodeGenerator*>::iterator iit;
   TList<be_Type*>::iterator bit;

   for (iit = implementations.begin(); iit != implementations.end(); iit++)
   {
      (*iit)->Generate(source);
   }

   os << nl;

   be_CodeGenerator::Generate (source);

   os << nl;

   if (BE_Globals::lite)
   {
       DDS_StdString BaseFilename;
       BaseFilename = StripExtension(source.Filename());

       os << "#include \"" << BaseFilename << "-lite.c" << "\"" << nl;
   }
   os << nl;
   source.Close();
}

void be_root::Generate (be_ServerImplementation& source)
{
   const DDS_StdString corbaException = BE_Globals::CorbaScope("Exception");
   ostream & os = source.Stream ();

   be_CodeGenerator::Generate (source);

   os << nl << endl;
   source.Close();
}

void be_root::GenerateDependants
(
   be_ClientHeader & source,
   const char* dep,
   const char * scope
)
{
   DDS_StdString depname (dep);
   DDS_StdString nuScope (scope);

   TList<be_sequence*>::iterator it = be_root::deferred_seqs.begin ();

   while (it != be_root::deferred_seqs.end ())
   {
      be_sequence& sequence = *(*it);

      if (sequence.BaseTypeName () == depname)
      {
         sequence.SetName (nuScope, sequence.LocalName());
         sequence.Generate (source);

         GenerateDependants (source, sequence.LocalName(), scope);
      }

      ++it;
   }
}

void be_root::FinishAllProtoTypeCodes ()
{
   TList<be_Type*>::iterator iter;

   for
   (
      iter = typesThatNeedProtoTypeCodesFinished.begin ();
      iter != typesThatNeedProtoTypeCodesFinished.end ();
      ++iter
   )
   {
      be_Type & beType = *(*iter);
      beType.FinishProtoTypeCode ();
   }
}
<|endoftext|>


<commit_before>// Copyright (c) 2016 Mirants Lu. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "log/checkpoint_sender.h"

#include <vector>

#include "log/checkpoint_manager.h"
#include "paxos/config.h"
#include "skywalker/file.h"
#include "skywalker/logging.h"
#include "util/mutexlock.h"

namespace skywalker {

CheckpointSender::CheckpointSender(Config* config, CheckpointManager* manager)
    : config_(config),
      manager_(manager),
      receiver_node_id_(0),
      sequence_id_(0),
      mutex_(),
      cond_(&mutex_),
      ack_sequence_id_(0),
      flag_(true) {}

CheckpointSender::~CheckpointSender() {}

bool CheckpointSender::SendCheckpoint(uint64_t node_id) {
  receiver_node_id_ = node_id;
  sequence_id_ = 0;
  ack_sequence_id_ = 0;
  flag_ = true;
  bool res = config_->GetCheckpoint()->LockCheckpoint(config_->GetGroupId());
  if (res) {
    uint64_t instance_id = manager_->GetCheckpointInstanceId();
    BeginToSend(instance_id);

    res = SendCheckpointFiles(instance_id);

    if (res) {
      EndToSend(instance_id);
    } else {
      LOG_ERROR("Group %u - send checkpoint failed.", config_->GetGroupId());
    }
    config_->GetCheckpoint()->UnLockCheckpoint(config_->GetGroupId());
  } else {
    LOG_WARN("Group %u - lock checkpoint failed.", config_->GetGroupId());
  }
  return res;
}

void CheckpointSender::BeginToSend(uint64_t instance_id) {
  Content content;
  content.set_type(CHECKPOINT_MESSAGE);
  content.set_group_id(config_->GetGroupId());
  CheckpointMessage* begin = content.mutable_checkpoint_msg();
  begin->set_type(CHECKPOINT_BEGIN);
  begin->set_node_id(config_->GetNodeId());
  begin->set_instance_id(instance_id);
  begin->set_sequence_id(sequence_id_++);
  config_->GetMessager()->SendMessage(receiver_node_id_, content);
}

bool CheckpointSender::SendCheckpointFiles(uint64_t instance_id) {
  bool res = true;
  std::string dir;
  std::vector<std::string> files;

  const std::vector<StateMachine*>& machines = config_->GetStateMachines();
  for (auto& machine : machines) {
    files.clear();
    res = config_->GetCheckpoint()->GetCheckpoint(
        config_->GetGroupId(), machine->machine_id(), &dir, &files);
    if (!res) {
      LOG_ERROR("Group %u - get checkpoint failed, the machine_id=%d.",
                config_->GetGroupId(), machine->machine_id());
      return res;
    }

    if (dir.empty() || files.empty()) {
      continue;
    }
    if (dir[dir.size() - 1] != '/') {
      dir += '/';
    }
    for (auto& file : files) {
      res = SendFile(instance_id, machine->machine_id(), dir, file);
      if (!res) {
        LOG_ERROR("Group %u - send file failed, the file=%s%s.",
                  config_->GetGroupId(), dir.c_str(), file.c_str());
        break;
      }
    }
  }
  return res;
}

bool CheckpointSender::SendFile(uint64_t instance_id, int machine_id,
                                const std::string& dir,
                                const std::string& file) {
  std::string fname = dir + file;
  SequentialFile* seq_file;
  Status s = FileManager::Instance()->NewSequentialFile(fname, &seq_file);
  if (!s.ok()) {
    LOG_ERROR("Group %u - %s", config_->GetGroupId(), s.ToString().c_str());
    return false;
  }
  bool res = true;
  size_t offset = 0;

  Content content;
  content.set_type(CHECKPOINT_MESSAGE);
  content.set_group_id(config_->GetGroupId());

  while (res) {
    Slice fragmenet;
    s = seq_file->Read(kBufferSize, &fragmenet, buffer_);
    if (!s.ok()) {
      res = false;
      LOG_ERROR("Group %u - %s", config_->GetGroupId(), s.ToString().c_str());
      break;
    }
    if (fragmenet.empty()) {
      break;
    }

    offset += fragmenet.size();

    CheckpointMessage* msg = content.mutable_checkpoint_msg();
    msg->set_type(CHECKPOINT_FILE);
    msg->set_node_id(config_->GetNodeId());
    msg->set_instance_id(instance_id);
    msg->set_sequence_id(sequence_id_++);
    msg->set_machine_id(machine_id);
    msg->set_file(file);
    msg->set_offset(offset);
    msg->set_data(fragmenet.data(), fragmenet.size());
    config_->GetMessager()->SendMessage(receiver_node_id_, content);
    res = CheckReceive();
  }
  delete seq_file;

  return res;
}

void CheckpointSender::EndToSend(uint64_t instance_id) {
  Content content;
  content.set_type(CHECKPOINT_MESSAGE);
  content.set_group_id(config_->GetGroupId());
  CheckpointMessage* end = content.mutable_checkpoint_msg();
  end->set_type(CHECKPOINT_END);
  end->set_node_id(config_->GetNodeId());
  end->set_instance_id(instance_id);
  end->set_sequence_id(sequence_id_);
  config_->GetMessager()->SendMessage(receiver_node_id_, content);
}

void CheckpointSender::OnComfirmReceive(const CheckpointMessage& msg) {
  MutexLock lock(&mutex_);
  if (msg.node_id() == receiver_node_id_ &&
      msg.sequence_id() == ack_sequence_id_) {
    ++ack_sequence_id_;
    flag_ = msg.flag();
    cond_.Signal();
  } else {
    LOG_WARN(
        "Group %u - receive a confirm message, "
        "which node_id = %llu, sequence_id=%d, "
        "but my sender_node_id_=%llu, ack_sequence_id_=%d.",
        config_->GetGroupId(), (unsigned long long)msg.node_id(),
        msg.sequence_id(), (unsigned long long)receiver_node_id_,
        ack_sequence_id_);
  }
}

bool CheckpointSender::CheckReceive() {
  bool res = true;
  MutexLock lock(&mutex_);
  while (flag_ && (sequence_id_ > ack_sequence_id_ + 16)) {
    res = cond_.Wait(10 * 1000 * 1000);
    if (!res) {
      LOG_ERROR("Group %u - receive comfirm message timeout!",
                config_->GetGroupId());
      break;
    }
  }
  if (!flag_) {
    LOG_ERROR("Group %u - error happen.", config_->GetGroupId());
    res = false;
  }
  return res;
}

}  // namespace skywalker
<commit_msg>Update how to send checkpoint files.<commit_after>// Copyright (c) 2016 Mirants Lu. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "log/checkpoint_sender.h"

#include <vector>

#include "log/checkpoint_manager.h"
#include "paxos/config.h"
#include "skywalker/file.h"
#include "skywalker/logging.h"
#include "util/mutexlock.h"

namespace skywalker {

CheckpointSender::CheckpointSender(Config* config, CheckpointManager* manager)
    : config_(config),
      manager_(manager),
      receiver_node_id_(0),
      sequence_id_(0),
      mutex_(),
      cond_(&mutex_),
      ack_sequence_id_(0),
      flag_(true) {}

CheckpointSender::~CheckpointSender() {}

bool CheckpointSender::SendCheckpoint(uint64_t node_id) {
  receiver_node_id_ = node_id;
  sequence_id_ = 0;
  ack_sequence_id_ = 0;
  flag_ = true;
  bool res = config_->GetCheckpoint()->LockCheckpoint(config_->GetGroupId());
  if (res) {
    uint64_t instance_id = manager_->GetCheckpointInstanceId();
    BeginToSend(instance_id);

    res = SendCheckpointFiles(instance_id);

    if (res) {
      EndToSend(instance_id);
    } else {
      LOG_ERROR("Group %u - send checkpoint failed.", config_->GetGroupId());
    }
    config_->GetCheckpoint()->UnLockCheckpoint(config_->GetGroupId());
  } else {
    LOG_WARN("Group %u - lock checkpoint failed.", config_->GetGroupId());
  }
  return res;
}

void CheckpointSender::BeginToSend(uint64_t instance_id) {
  Content content;
  content.set_type(CHECKPOINT_MESSAGE);
  content.set_group_id(config_->GetGroupId());
  CheckpointMessage* begin = content.mutable_checkpoint_msg();
  begin->set_type(CHECKPOINT_BEGIN);
  begin->set_node_id(config_->GetNodeId());
  begin->set_instance_id(instance_id);
  begin->set_sequence_id(sequence_id_++);
  config_->GetMessager()->SendMessage(receiver_node_id_, content);
}

bool CheckpointSender::SendCheckpointFiles(uint64_t instance_id) {
  bool res = true;
  std::string dir;
  std::vector<std::string> files;

  const std::vector<StateMachine*>& machines = config_->GetStateMachines();
  for (auto& machine : machines) {
    files.clear();
    res = config_->GetCheckpoint()->GetCheckpoint(
        config_->GetGroupId(), machine->machine_id(), &dir, &files);
    if (!res) {
      LOG_ERROR("Group %u - get checkpoint failed, the machine_id=%d.",
                config_->GetGroupId(), machine->machine_id());
      return res;
    }

    if (dir.empty() || files.empty()) {
      continue;
    }
    if (dir[dir.size() - 1] != '/') {
      dir += '/';
    }
    for (auto& file : files) {
      res = SendFile(instance_id, machine->machine_id(), dir, file);
      if (!res) {
        LOG_ERROR("Group %u - send file failed, the file=%s%s.",
                  config_->GetGroupId(), dir.c_str(), file.c_str());
        break;
      }
    }
  }
  return res;
}

bool CheckpointSender::SendFile(uint64_t instance_id, int machine_id,
                                const std::string& dir,
                                const std::string& file) {
  std::string fname = dir + file;
  SequentialFile* seq_file;
  Status s = FileManager::Instance()->NewSequentialFile(fname, &seq_file);
  if (!s.ok()) {
    LOG_ERROR("Group %u - %s", config_->GetGroupId(), s.ToString().c_str());
    return false;
  }
  bool res = true;
  size_t offset = 0;

  Content content;
  content.set_type(CHECKPOINT_MESSAGE);
  content.set_group_id(config_->GetGroupId());
  CheckpointMessage* msg = content.mutable_checkpoint_msg();
  msg->set_type(CHECKPOINT_FILE);
  msg->set_node_id(config_->GetNodeId());
  msg->set_instance_id(instance_id);
  msg->set_machine_id(machine_id);
  msg->set_file(file);

  while (res) {
    Slice fragmenet;
    s = seq_file->Read(kBufferSize, &fragmenet, buffer_);
    if (!s.ok()) {
      res = false;
      LOG_ERROR("Group %u - %s", config_->GetGroupId(), s.ToString().c_str());
      break;
    }
    if (fragmenet.empty()) {
      break;
    }

    offset += fragmenet.size();
    msg->set_sequence_id(sequence_id_++);
    msg->set_offset(offset);
    msg->set_data(fragmenet.data(), fragmenet.size());
    config_->GetMessager()->SendMessage(receiver_node_id_, content);
    res = CheckReceive();
  }
  delete seq_file;

  return res;
}

void CheckpointSender::EndToSend(uint64_t instance_id) {
  Content content;
  content.set_type(CHECKPOINT_MESSAGE);
  content.set_group_id(config_->GetGroupId());
  CheckpointMessage* end = content.mutable_checkpoint_msg();
  end->set_type(CHECKPOINT_END);
  end->set_node_id(config_->GetNodeId());
  end->set_instance_id(instance_id);
  end->set_sequence_id(sequence_id_);
  config_->GetMessager()->SendMessage(receiver_node_id_, content);
}

void CheckpointSender::OnComfirmReceive(const CheckpointMessage& msg) {
  MutexLock lock(&mutex_);
  if (msg.node_id() == receiver_node_id_ &&
      msg.sequence_id() == ack_sequence_id_) {
    ++ack_sequence_id_;
    flag_ = msg.flag();
    cond_.Signal();
  } else {
    LOG_WARN(
        "Group %u - receive a confirm message, "
        "which node_id = %llu, sequence_id=%d, "
        "but my sender_node_id_=%llu, ack_sequence_id_=%d.",
        config_->GetGroupId(), (unsigned long long)msg.node_id(),
        msg.sequence_id(), (unsigned long long)receiver_node_id_,
        ack_sequence_id_);
  }
}

bool CheckpointSender::CheckReceive() {
  bool res = true;
  MutexLock lock(&mutex_);
  while (flag_ && (sequence_id_ > ack_sequence_id_ + 16)) {
    res = cond_.Wait(10 * 1000 * 1000);
    if (!res) {
      LOG_ERROR("Group %u - receive comfirm message timeout!",
                config_->GetGroupId());
      break;
    }
  }
  if (!flag_) {
    LOG_ERROR("Group %u - error happen.", config_->GetGroupId());
    res = false;
  }
  return res;
}

}  // namespace skywalker
<|endoftext|>