<commit_before>#include "bamliquidator.h"
#include "threadsafe_queue.h"

#include <cmath>
#include <fstream>
#include <iostream>
#include <map>
#include <stdexcept>
#include <sstream>
#include <thread>

#include <boost/atomic.hpp>
#include <boost/algorithm/string.hpp>
#include <boost/lexical_cast.hpp>

#include <hdf5.h>
#include <hdf5_hl.h>

struct ChromosomeCounts
{
  const std::string chromosome; // e.g. chr1
  const std::string bam_file_name; // e.g. L228_121_DHL6_RNA_POL2.hg18.bwt.sorted.bam
  const std::string cell_type; // e.g. dhl6
  const unsigned int bin_size; // e.g. 100000 base pairs per bin
  const std::vector<double> bin_counts;
};

class ChromosomeLengths
{
public:
  ChromosomeLengths(const std::string &chrom_size_file)
  {
    const size_t chromosome_column = 0;
    const size_t type_column = 2;
    const size_t length_column = 4;

    std::ifstream size_file(chrom_size_file);
    if (!size_file.is_open())
    {
      throw std::runtime_error("failed to open chrom_size_file " + chrom_size_file);
    }

    for(std::string line; std::getline(size_file, line); )
    {
      std::vector<std::string> columns;
      boost::split(columns, line, boost::is_any_of("\t"));
      if (columns.size() < length_column + 1)
      {
        throw std::runtime_error("error parsing chrom_size_file");
      }
      m_type_to_chromosome_to_count[columns[type_column]][columns[chromosome_column]] =
        boost::lexical_cast<size_t>(columns[length_column]);
    }
  }

  size_t operator()(const std::string &bam_file, const std::string& chromosome) const
  {
    for (const auto type : m_type_to_chromosome_to_count)
    {
      if (bam_file.find(type.first) != std::string::npos)
      {
        const auto count = type.second.find(chromosome);
        if (count == type.second.end())
        {
          throw std::runtime_error("failed to find chromosome " + chromosome
                                   + " for " + type.first);
        }
        return count->second;
      }
    }
    throw std::runtime_error("failed to determine type of " + bam_file);
  }

private:
  typedef std::map<std::string, std::map<std::string, size_t>> TypeToChromosomeToCount;
  TypeToChromosomeToCount m_type_to_chromosome_to_count;
};

struct CountH5Record
{
  uint32_t bin_number;
  char cell_type[16];
  char chromosome[16];
  uint64_t count;
  char file_name[64];
};

void write_to_hdf5(threadsafe_queue<ChromosomeCounts> &computed_counts)
{
  hid_t file = H5Fopen("bin_counts.h5", H5F_ACC_RDWR, H5P_DEFAULT);

  const size_t record_size = sizeof(CountH5Record);

  size_t record_offset[] = { HOFFSET(CountH5Record, bin_number),
                             HOFFSET(CountH5Record, cell_type),
                             HOFFSET(CountH5Record, chromosome),
                             HOFFSET(CountH5Record, count),
                             HOFFSET(CountH5Record, file_name) };

  size_t field_sizes[] = { sizeof(CountH5Record::bin_number),
                           sizeof(CountH5Record::cell_type),
                           sizeof(CountH5Record::chromosome),
                           sizeof(CountH5Record::count),
                           sizeof(CountH5Record::file_name) };

  std::cout << "writer...\n";
  while (true)
  {
    std::shared_ptr<ChromosomeCounts> counts = computed_counts.wait_and_pop();

    if (counts == nullptr) return;

    CountH5Record record;
    record.bin_number = 0;
    strncpy(record.cell_type,  counts->cell_type.c_str(),     sizeof(CountH5Record::cell_type));
    strncpy(record.chromosome, counts->chromosome.c_str(),    sizeof(CountH5Record::chromosome));
    strncpy(record.file_name,  counts->bam_file_name.c_str(), sizeof(CountH5Record::file_name));

    std::cout << "writing " << counts->bin_counts.size() << " from "
              << counts->chromosome << std::endl;
    for (auto count : counts->bin_counts)
    {
      record.count = count;
      herr_t status = H5TBappend_records(file, "counts", 1, record_size, record_offset,
                                         field_sizes, &record);
      if (status != 0)
      {
        std::cerr << "Error appending record, status = " << status << std::endl;
      }

      ++record.bin_number;
    }
  }

  H5Fclose(file);
}

void count(threadsafe_queue<ChromosomeCounts> &computed_counts)
{
  const std::string bam_file_path("../copied_from_tod/");
  const std::string bam_file_name("04032013_D1L57ACXX_4.TTAGGC.hg18.bwt.sorted.bam");
  const std::string bam_file = bam_file_path+bam_file_name;
  const std::vector<std::string> chromosomes {"chr1", "chr2", "chr3", "chr4", "chr5",
    "chr6", "chr8", "chr9", "chr10", "chr11", "chr12", "chr13", "chr14", "chr15", "chr16",
    "chr17", "chr18", "chr19", "chr20", "chr21", "chr22", "chrX"};

  const int bin_size = 100000; // 100K

  const ChromosomeLengths lengths("../copied_from_tod/ucsc_chromSize.txt");

  for (auto chr : chromosomes)
  {
    int base_pairs = lengths(bam_file, chr);
    int bins = std::ceil(base_pairs / (double) bin_size);
    int max_base_pair = bins * bin_size;
    std::cout << "counting chromosome " << chr << std::endl;
    // pickup here: first just try a single thread counting from file,
    // and a single thread recording counts in hdf5
    // I'm not sure if samtools is thread safe -- try after I confirm 1 thread working
    // I need to write a script to compare hdf5 and mysql results or something
    // maybe I should just write both to txt and diff them
    computed_counts.push(ChromosomeCounts {chr, bam_file_name, "dhl6", bin_size,
      liquidate(bam_file, chr, 0, max_base_pair, '+', bins, 0)});
  }

  computed_counts.push(nullptr); // insert "poison pill" to signal to writer to stop
}

int main()
{
  threadsafe_queue<ChromosomeCounts> computed_counts;
  std::thread counter_thread(count, std::ref(computed_counts));
  std::thread writer_thread(write_to_hdf5, std::ref(computed_counts));

  counter_thread.join();
  writer_thread.join();

  return 0;
}

/* The MIT License (MIT)

   Copyright (c) 2013 John DiMatteo

   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.
 */
<commit_msg>Counting both strands now, spot checked to confirm counts match old counting method<commit_after>#include "bamliquidator.h"
#include "threadsafe_queue.h"

#include <cmath>
#include <fstream>
#include <iostream>
#include <map>
#include <stdexcept>
#include <sstream>
#include <thread>

#include <boost/atomic.hpp>
#include <boost/algorithm/string.hpp>
#include <boost/lexical_cast.hpp>

#include <hdf5.h>
#include <hdf5_hl.h>

/* todo:

   - don't store strings in table records, e.g. have seperate tables for chromosomes, file names,
     and cell types.  in the count table records, just store integers representing the strings.
     this should speed up the writing and cut the file sizes
   - don't use seperate structs for counting and writing.  prepare the structs while counting,
     then write them in bulk
   - multithread the counting, and see if that improves performance (probably using a boost
     thread_group and asio to implement a thread pool)
 */

struct ChromosomeCounts
{
  const std::string chromosome; // e.g. chr1
  const std::string bam_file_name; // e.g. L228_121_DHL6_RNA_POL2.hg18.bwt.sorted.bam
  const std::string cell_type; // e.g. dhl6
  const unsigned int bin_size; // e.g. 100000 base pairs per bin
  const std::vector<double> bin_counts;
};

class ChromosomeLengths
{
public:
  ChromosomeLengths(const std::string &chrom_size_file)
  {
    const size_t chromosome_column = 0;
    const size_t type_column = 2;
    const size_t length_column = 4;

    std::ifstream size_file(chrom_size_file);
    if (!size_file.is_open())
    {
      throw std::runtime_error("failed to open chrom_size_file " + chrom_size_file);
    }

    for(std::string line; std::getline(size_file, line); )
    {
      std::vector<std::string> columns;
      boost::split(columns, line, boost::is_any_of("\t"));
      if (columns.size() < length_column + 1)
      {
        throw std::runtime_error("error parsing chrom_size_file");
      }
      m_type_to_chromosome_to_count[columns[type_column]][columns[chromosome_column]] =
        boost::lexical_cast<size_t>(columns[length_column]);
    }
  }

  size_t operator()(const std::string &bam_file, const std::string& chromosome) const
  {
    for (const auto type : m_type_to_chromosome_to_count)
    {
      if (bam_file.find(type.first) != std::string::npos)
      {
        const auto count = type.second.find(chromosome);
        if (count == type.second.end())
        {
          throw std::runtime_error("failed to find chromosome " + chromosome
                                   + " for " + type.first);
        }
        return count->second;
      }
    }
    throw std::runtime_error("failed to determine type of " + bam_file);
  }

private:
  typedef std::map<std::string, std::map<std::string, size_t>> TypeToChromosomeToCount;
  TypeToChromosomeToCount m_type_to_chromosome_to_count;
};

struct CountH5Record
{
  uint32_t bin_number;
  char cell_type[16];
  char chromosome[16];
  uint64_t count;
  char file_name[64];
};

void write_to_hdf5(threadsafe_queue<ChromosomeCounts> &computed_counts)
{
  hid_t file = H5Fopen("bin_counts.h5", H5F_ACC_RDWR, H5P_DEFAULT);

  const size_t record_size = sizeof(CountH5Record);

  size_t record_offset[] = { HOFFSET(CountH5Record, bin_number),
                             HOFFSET(CountH5Record, cell_type),
                             HOFFSET(CountH5Record, chromosome),
                             HOFFSET(CountH5Record, count),
                             HOFFSET(CountH5Record, file_name) };

  size_t field_sizes[] = { sizeof(CountH5Record::bin_number),
                           sizeof(CountH5Record::cell_type),
                           sizeof(CountH5Record::chromosome),
                           sizeof(CountH5Record::count),
                           sizeof(CountH5Record::file_name) };

  std::cout << "writer...\n";
  while (true)
  {
    std::shared_ptr<ChromosomeCounts> counts = computed_counts.wait_and_pop();

    if (counts == nullptr) return;

    CountH5Record record;
    record.bin_number = 0;
    strncpy(record.cell_type,  counts->cell_type.c_str(),     sizeof(CountH5Record::cell_type));
    strncpy(record.chromosome, counts->chromosome.c_str(),    sizeof(CountH5Record::chromosome));
    strncpy(record.file_name,  counts->bam_file_name.c_str(), sizeof(CountH5Record::file_name));

    std::cout << "writing " << counts->bin_counts.size() << " from "
              << counts->chromosome << std::endl;
    for (auto count : counts->bin_counts)
    {
      record.count = count;
      herr_t status = H5TBappend_records(file, "counts", 1, record_size, record_offset,
                                         field_sizes, &record);
      if (status != 0)
      {
        std::cerr << "Error appending record, status = " << status << std::endl;
      }

      ++record.bin_number;
    }
  }

  H5Fclose(file);
}

void count(threadsafe_queue<ChromosomeCounts> &computed_counts)
{
  const std::string bam_file_path("../copied_from_tod/");
  const std::string bam_file_name("04032013_D1L57ACXX_4.TTAGGC.hg18.bwt.sorted.bam");
  const std::string bam_file = bam_file_path+bam_file_name;
  const std::vector<std::string> chromosomes {"chr1", "chr2", "chr3", "chr4", "chr5",
    "chr6", "chr8", "chr9", "chr10", "chr11", "chr12", "chr13", "chr14", "chr15", "chr16",
    "chr17", "chr18", "chr19", "chr20", "chr21", "chr22", "chrX"};

  const int bin_size = 100000; // 100K

  const ChromosomeLengths lengths("../copied_from_tod/ucsc_chromSize.txt");

  for (auto chr : chromosomes)
  {
    int base_pairs = lengths(bam_file, chr);
    int bins = std::ceil(base_pairs / (double) bin_size);
    int max_base_pair = bins * bin_size;
    std::cout << "counting chromosome " << chr << std::endl;
    // pickup here: first just try a single thread counting from file,
    // and a single thread recording counts in hdf5
    // I'm not sure if samtools is thread safe -- try after I confirm 1 thread working
    // I need to write a script to compare hdf5 and mysql results or something
    // maybe I should just write both to txt and diff them
    computed_counts.push(ChromosomeCounts {chr, bam_file_name, "dhl6", bin_size,
      liquidate(bam_file, chr, 0, max_base_pair, '.', bins, 0)});
  }

  computed_counts.push(nullptr); // insert "poison pill" to signal to writer to stop
}

int main()
{
  threadsafe_queue<ChromosomeCounts> computed_counts;
  std::thread counter_thread(count, std::ref(computed_counts));
  std::thread writer_thread(write_to_hdf5, std::ref(computed_counts));

  counter_thread.join();
  writer_thread.join();

  return 0;
}

/* The MIT License (MIT)

   Copyright (c) 2013 John DiMatteo

   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.
 */
<|endoftext|>


<commit_before>#include <iostream>

using std::cout; using std::endl;

int main()
{
    int ia[10];
    for (auto i = 0; i < 10; ++i)
        ia[i] = i;

    for (auto i : ia)
        cout << i << " ";
    cout << endl;
}

<commit_msg>Update ex3_31.cpp<commit_after>#include <iostream>
using std::cout; using std::endl;

int main()
{
    int arr[10];
    for (auto i = 0; i < 10; ++i) arr[i] = i;
    for (auto i : arr) cout << i << " ";
    cout << endl;

    return 0;
}
<|endoftext|>


<commit_before>#include <iostream>

using std::cin; using std::cout; using std::endl;

int main()
{
    unsigned aCnt = 0, eCnt = 0, iCnt = 0, oCnt = 0, uCnt = 0;
    char ch;
    while (cin >> ch)
        switch (ch)
        {
            case 'a':
            case 'A':
                ++aCnt;
                break;
            case 'e':
            case 'E':
                ++eCnt;
                break;
            case 'i':
            case 'I':
                ++iCnt;
                break;
            case 'o':
            case 'O':
                ++oCnt;
                break;
            case 'u':
            case 'U':
                ++uCnt;
                break;
        }

    cout << "Number of vowel a(A): \t" << aCnt << '\n'
        << "Number of vowel e(E): \t" << eCnt << '\n'
        << "Number of vowel i(I): \t" << iCnt << '\n'
        << "Number of vowel o(O): \t" << oCnt << '\n'
        << "Number of vowel u(U): \t" << uCnt << endl;

    return 0;
}
<commit_msg>Update ex5_10.cpp<commit_after>#include <iostream>

using std::cin; using std::cout; using std::endl;

int main()
{
    unsigned aCnt = 0, eCnt = 0, iCnt = 0, oCnt = 0, uCnt = 0;
    char ch;
    while (cin >> ch)
        switch (ch)
        {
            case 'a':
            case 'A':
                ++aCnt;
                break;
            case 'e':
            case 'E':
                ++eCnt;
                break;
            case 'i':
            case 'I':
                ++iCnt;
                break;
            case 'o':
            case 'O':
                ++oCnt;
                break;
            case 'u':
            case 'U':
                ++uCnt;
                break;
        }
//another way to solve it
/*	while (cin >> ch)
	{
		ch = tolower(ch);
		switch (ch)
		{
    		case 'a':
    			++aCnt;
    			break;
    		case 'e':
    			++eCnt;
    			break;
    		case 'i':
    			++iCnt;
    			break;
    		case 'o':
    			++oCnt;
    			break;
    		case 'u':
    			++uCnt;
    			break;
		}
	}
*/
    cout << "Number of vowel a(A): \t" << aCnt << '\n'
        << "Number of vowel e(E): \t" << eCnt << '\n'
        << "Number of vowel i(I): \t" << iCnt << '\n'
        << "Number of vowel o(O): \t" << oCnt << '\n'
        << "Number of vowel u(U): \t" << uCnt << endl;

    return 0;
}
<|endoftext|>


<commit_before>//! @Alan
//!
//! Exercise 6.21:
//! Write a function that takes an int and a pointer to an int and
//! returns the larger of the int value or the value to which the
//! pointer points. What type should you use for the pointer?
//!

#include <iostream>
using std::cout;

int LargerOne(const int i, const int *ip)
{
    return (i > *ip) ? i : *ip;
}

int main()
{
    int c = 6;
    cout << LargerOne(7, &c);

    return 0;
}

<commit_msg>Update ex6_21.cpp<commit_after>//! @Yue Wang
//!
//! Exercise 6.21:
//! Write a function that takes an int and a pointer to an int and
//! returns the larger of the int value or the value to which the
//! pointer points. What type should you use for the pointer?
//!

#include <iostream>
using std::cout;

int LargerOne(const int i, const int *ip)
{
    return (i > *ip) ? i : *ip;
}

int main()
{
    int c = 6;
    cout << LargerOne(7, &c);

    return 0;
}

<|endoftext|>


<commit_before>//
//  ex9_32.cpp
//  Exercise 9.32
//
//  Created by pezy on 12/3/14.
//  Copyright (c) 2014 pezy. All rights reserved.
//
//  @Brief  Assuming vi is a container of ints that includes even and odd values,
//          predict the behavior of the following loop.
//          After you've analyzed this loop, write a program to test whether your expectations were correct.
//  @Answer "infinite loop". Casue the `++iter` out of the `while` loop. But even through add brackets it is still infinite loop.
//          Fixed following.

#include <iostream>
#include <vector>

using std::vector; using std::cout; using std::endl;

int main()
{
    vector<int> vi = {0,1,2,3,4,5,6,7,8,9};
    auto iter = vi.begin();
    while (iter != vi.end())
    {
        if (*iter % 2)
            iter = vi.insert(iter, *iter++);
        ++iter;
    }

    for (auto i : vi)
        cout << i << " ";

    return 0;
}

<commit_msg>fixed #136<commit_after>//
//  ex9_32.cpp
//  Exercise 9.32
//
//  Created by pezy on 12/3/14.
//  Copyright (c) 2014 pezy. All rights reserved.
//
//  @Brief  Assuming vi is a container of ints that includes even and odd values,
//          predict the behavior of the following loop.
//          After you've analyzed this loop, write a program to test whether your expectations were correct.
//
//			iter = vi.begin();
//			while (iter != vi.end())
//				if (*iter % 2)
//					iter = vi.insert(iter, *iter);
//				++iter;
//
//  @Answer "infinite loop". Casue the `++iter` out of the `while` loop. But even through add brackets it is still infinite loop.
//          Fixed following.

#include <iostream>
using std::cout; using std::endl;

#include <vector>
using std::vector;

int main()
{
	vector<int> vi = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
	auto iter = vi.begin();
	while (iter != vi.end()) {
		if (*iter % 2) {
			iter = vi.insert(iter, *iter);
			++iter;
		}
		++iter;
	}

	for (auto i : vi)
		cout << i << " ";

	return 0;
}

<|endoftext|>


<commit_before>#include <dlfcn.h>
#include <signal.h>
#include <cassert>
#include <fstream>
#include <cppzmq/zmq.h>
#include <quidpp.h>
#include <package.h>
#include <Python.h>
#include "common/util.h"
#include "ace/interface.h"
#include "protoc/processjob.pb.h"
#include "dirent.h"
#include "wal.h"
#include "localenv.h"
#include "package.h"
#include "exec.h"

void Execute::init(int workerid, const std::string& masterIPC, const std::string& masterProvision, Indexer *db) {
	DIR *dir = nullptr;
	struct dirent *ent = nullptr;

	Execute& exec = Execute::getInstance();
	exec.workerid = workerid;
	exec.masterIPC = masterIPC;
	exec.masterProvision = masterProvision;
	exec.db = db;

	if ((dir = opendir(WALDIR)) != NULL) {

		/* print all the files and directories within directory */
		while ((ent = readdir(dir)) != NULL) {
			if (!strcmp(ent->d_name, ".") || !strcmp(ent->d_name, ".."))
				continue;

			Wal::rollback(ent->d_name, [](const std::string & name, Execute::Parameter & param) {

				/* Run procedure */
				Execute::run(name, param, false);

				/* Setup subjobs if any */
				Execute::prospect(name);
			});
		}

		closedir(dir);
	}
}

bool Execute::run(const std::string& name, Parameter& param, bool canfork) {
	if (canfork) {
		signal(SIGCHLD, SIG_IGN);
		pid_t pid = fork();
		if (pid > 0)
			return false;
	}

	Wal *executionLog = new Wal(name, param);

	struct timeval t1, t2;
	char buff[PATH_MAX + 1];

	Execute& exec = Execute::getInstance();

	ControlClient control;
	control.setMaster(exec.masterIPC);
	control.setWorker(exec.workerid);
	control.setJob(param.jobquid, param.jobid);
	control.start();
	exec.jobcontrol = &control;

	std::cout << "Running package " << name << std::endl;

	/* Move worker in accept mode */
	exec.jobcontrol->setStateAccepted();

	/* Set members of shared object via callback */
	exec.clusterjobs = exec.jobcontrol->clusterJobs();
	exec.module = name;
	exec.jobid = param.jobid;
	exec.jobname = param.jobname;
	exec.jobquid = param.jobquid;
	exec.jobpartition = param.jobpartition;
	exec.jobpartition_count = param.jobpartition_count;
	exec.jobstate = param.jobstate;
	exec.jobparent = param.jobparent;
	char *cwd = getcwd(buff, PATH_MAX + 1);

	exec.jobcontrol->resetInternalState();

	/* Ensure package exist */
	if (!file_exist((PKGDIR "/" + name).c_str())) {
		exec.jobcontrol->setStateIdle();
		std::cerr << "Package does not exist" << std::endl;
		return true;
	}

	LocalEnv jobenv(LOCALDIR "/" + name, exec.jobid, exec.workerid);
	while (jobenv.isLocked()) {
		std::cerr << "Directory busy, waiting on mutex" << std::endl;
		exec.jobcontrol->setStateAwaiting();
		sleep(5);
	}

	if (!jobenv.hasHome()) {
		/* Extract package in job directory */
		Package pack(PKGDIR "/" + name);
		pack.extract(LOCALDIR "/" + name);

		/* Setup job home */
		if (!jobenv.setupHome())
			return true;
	} else {
		std::cout << "Job environment already in cluster" << std::endl;
	}

	/* Setup job home */
	jobenv.setLock();
	if (!jobenv.setupEnv())
		return true;

	auto packageMain = jobenv.packageMain();
	auto packageInvoke = jobenv.packageInvoke();
	if (packageMain.empty() || packageInvoke.empty())
		return true;

	/* Move WAL forward */
	executionLog->setCheckpoint(Wal::Checkpoint::INIT);

	wchar_t *program = Py_DecodeLocale("Chella Worker", NULL);
	if (!program) {
		std::cerr << "Cannot decode name" << std::endl;
		return true;
	}

	/* Move to job home and prepare python */
	auto streamStdOut = jobenv.openStream(LocalEnv::STDOUT);
	auto streamStdErr = jobenv.openStream(LocalEnv::STDERR);
	chdir((std::string(cwd) + "/" + LOCALDIR "/" + name).c_str());
	setenv("PYTHONPATH", ".", 1);

	Py_SetProgramName(program);
	Py_Initialize();

	PyObject *pModuleJob = PyImport_ImportModule(packageMain.c_str());
	if (!pModuleJob) {
		PyErr_Print();
		return true;
	}

	/* Initialize Ace modules */
	PyObject *pMethodConfig = Ace::Config::PyAce_ModuleClass();
	PyObject *pMethodCallback = Ace::IPC::PyAce_ModuleClass(exec.jobcontrol);
	PyObject *pModuleAsysStream1 = Ace::Asys::PyAce_ModuleClass(streamStdOut);
	PyObject *pModuleAsysStream2 = Ace::Asys::PyAce_ModuleClass(streamStdErr);
	PyObject *pMethodDB = Ace::DB::PyAce_ModuleClass(exec.db);

	/* Move WAL forward */
	executionLog->setCheckpoint(Wal::Checkpoint::LOAD);
	gettimeofday(&t1, NULL);

	/* Set system settings */
	PySys_SetObject("stdout", pModuleAsysStream1);
	PySys_SetObject("stderr", pModuleAsysStream2);
	PySys_SetObject("stdin", pModuleAsysStream2);

	/* Create Ace config instance */
	PyObject *pInstanceConfig = PyObject_CallObject(pMethodConfig, NULL);
	if (!pInstanceConfig) {
		PyErr_Print();
		return true;
	}
	Py_DECREF(pMethodConfig);

	/* Create Ace callback instance */
	PyObject *pInstanceCallback = PyObject_CallObject(pMethodCallback, NULL);
	if (!pInstanceCallback) {
		PyErr_Print();
		return true;
	}
	Py_DECREF(pMethodCallback);

	/* Create Ace DB instance */
	PyObject *pInstanceDB = PyObject_CallObject(pMethodDB, NULL);
	if (!pInstanceDB) {
		PyErr_Print();
		return true;
	}
	Py_DECREF(pMethodDB);

	/* Locate job init and call routine */
	PyObject *pFuncJobInit = PyObject_GetAttrString(pModuleJob, packageInvoke.c_str());
	if (!pFuncJobInit || !PyCallable_Check(pFuncJobInit)) {
		PyErr_Print();
		return true;
	}
	Py_DECREF(pModuleJob);

	PyObject *pArgsJobInit = Py_BuildValue("(O)", pInstanceConfig);
	PyObject *pInstanceJobInit = PyObject_CallObject(pFuncJobInit, pArgsJobInit);
	if (!pInstanceJobInit) {
		PyErr_Print();
		return true;
	}
	Py_DECREF(pFuncJobInit);
	Py_DECREF(pArgsJobInit);

	PyObject *pFuncJobInvoke = PyObject_GetAttrString(pInstanceJobInit, "invoke");
	if (!pFuncJobInvoke || !PyCallable_Check(pFuncJobInvoke)) {
		PyErr_Print();
		return true;
	}
	Py_DECREF(pInstanceJobInit);

	/* Instantiate job class */
	PyObject *pInstanceJob = PyObject_CallObject(pFuncJobInvoke, NULL);
	if (!pInstanceJob) {
		PyErr_Print();
		return true;
	}
	Py_DECREF(pFuncJobInvoke);

	/* Inject module instances into job instance */
	if (PyObject_SetAttrString(pInstanceJob, "cfg", pInstanceConfig) < 0) {
		PyErr_Print();
		return true;
	}

	if (PyObject_SetAttrString(pInstanceJob, "__ipc__", pInstanceCallback) < 0) {
		PyErr_Print();
		return true;
	}

	if (PyObject_SetAttrString(pInstanceJob, "__db__", pInstanceDB) < 0) {
		PyErr_Print();
		return true;
	}

	Py_DECREF(pInstanceConfig);
	Py_DECREF(pInstanceCallback);
	Py_DECREF(pInstanceDB);

	PyObject *pMemberChains = NULL;
	PyObject *pResult = NULL;
	pResult = PyObject_CallMethod(pInstanceJob, "inject", "(isssii)",
		exec.jobid,
		exec.jobname.c_str(),
		name.c_str(),
		exec.jobquid.c_str(),
		exec.jobpartition,
		exec.jobpartition_count);
	if (!pResult) {
		PyErr_Print();
		exec.jobcontrol->setStateFailed();
		goto py_failed;
	}

	/* Move WAL forward */
	executionLog->setCheckpoint(Wal::Checkpoint::INJECT);

	pResult = PyObject_CallMethod(pInstanceJob, "setup_once", NULL);
	if (!pResult) {
		PyErr_Print();
		exec.jobcontrol->setStateFailed();
		goto py_failed;
	}

	/* Move WAL forward */
	executionLog->setCheckpoint(Wal::Checkpoint::SETUP_ONCE);

	exec.jobcontrol->setStateSetup();
	pResult = PyObject_CallMethod(pInstanceJob, "setup", NULL);
	if (!pResult) {
		PyErr_Print();
		exec.jobcontrol->setStateFailed();
		goto py_failed;
	}

	/* Move WAL forward */
	executionLog->setCheckpoint(Wal::Checkpoint::SETUP);

	exec.jobcontrol->setStateRunning();
	pResult = PyObject_CallMethod(pInstanceJob, "run", "(y#)", param.jobdata.data(), param.jobdata.size());
	if (!pResult) {
		PyErr_Print();
		exec.jobcontrol->setStateFailed();
		goto py_failed;
	}

	/* Move WAL forward */
	executionLog->setCheckpoint(Wal::Checkpoint::RUN);

	exec.jobcontrol->setStateTeardown();
	pResult = PyObject_CallMethod(pInstanceJob, "teardown", NULL);
	if (!pResult) {
		PyErr_Print();
		exec.jobcontrol->setStateFailed();
		goto py_failed;
	}

	/* Move WAL forward */
	executionLog->setCheckpoint(Wal::Checkpoint::TEARDOWN);

	pResult = PyObject_CallMethod(pInstanceJob, "teardown_once", NULL);
	if (!pResult) {
		PyErr_Print();
		exec.jobcontrol->setStateFailed();
		goto py_failed;
	}

	/* Move WAL forward */
	executionLog->setCheckpoint(Wal::Checkpoint::TEARDOWN_ONCE);

	pMemberChains = PyObject_GetAttrString(pInstanceJob, "chains");
	if (!pMemberChains) {
		PyErr_Print();
		exec.jobcontrol->setStateFailed();
		goto py_failed;
	}

	//TODO: handle chains

	/* Move WAL forward */
	executionLog->setCheckpoint(Wal::Checkpoint::PULLCHAIN);
py_failed:
	gettimeofday(&t2, NULL);

	/* Release resources allocated for this job */
	Py_Finalize();
	exec.sessionCleanup();
	chdir(cwd);

	/* Close output streams */
	streamStdOut->close();
	streamStdErr->close();
	delete streamStdOut;
	delete streamStdErr;

	/* Mark WAL done */
	executionLog->markDone();

	double runtime = (t2.tv_sec - t1.tv_sec) * 1000.0;
	runtime += (t2.tv_usec - t1.tv_usec) / 1000.0;

	/* Write to disk */
	std::cout << "Job routine reached end" << std::endl;
	std::cout << "Total runtime: " << runtime << "ms" << std::endl;

	/* Teardown */
	jobenv.teardown(runtime);

	/* Move worker in idle mode */
	exec.jobcontrol->setStateIdle();

	control.stop();

	delete executionLog;
	std::cout << "Exit clean" << std::endl;

	return true;
}

void Execute::prospect(const std::string& name) {
	zmq::context_t context(1);
	zmq::socket_t socket(context, ZMQ_REQ);
	Execute& exec = Execute::getInstance();

	if (!exec.chain) {
		return;
	}

	if (!file_exist((PKGDIR "/" + name).c_str())) {
		std::cerr << "Cannot access library" << std::endl;
		return;
	}

	std::ifstream ifs(PKGDIR "/" + name);
	std::string content((std::istreambuf_iterator<char>(ifs)),
						(std::istreambuf_iterator<char>()));

	socket.connect(("tcp://" + exec.masterProvision).c_str());
	std::cout << "Connect to master " << exec.masterProvision << std::endl;

	for (unsigned int i = 0; i < exec.chain->size(); ++i) {
		auto subjob = exec.chain->at(i);

		ProcessJob job;
		job.set_name(subjob->name);
		job.set_id(i);
		job.set_quid(quidpp::Quid().toString(true));
		job.set_content(content);
		job.set_partition(i);
		job.set_partition_count(exec.chain->size());
		job.set_state(ProcessJob::PARTITION);
		job.set_quid_parent(exec.chain->parentQuid());
		job.set_data(subjob->data);

		std::cout << "Submit subjob " << i << " linked to parent " << exec.chain->parentQuid() + "(" + exec.chain->parentName() + ")" << std::endl;

		std::string serialized;
		job.SerializeToString(&serialized);

		zmq::message_t request(serialized.size());
		memcpy(reinterpret_cast<void *>(request.data()), serialized.c_str(), serialized.size());
		socket.send(request);

		/* Get the reply */
		zmq::message_t reply;
		socket.recv(&reply);
	}

	delete exec.chain;
	exec.chain = nullptr;
}

void Execute::dispose() {
	DIR *dir = nullptr;
	struct dirent *ent = nullptr;

	std::cout << "Clear caches" << std::endl;

	if ((dir = opendir(PKGDIR)) != NULL) {

		/* print all the files and directories within directory */
		while ((ent = readdir(dir)) != NULL) {
			if (!strcmp(ent->d_name, ".") || !strcmp(ent->d_name, ".."))
				continue;
			remove((PKGDIR "/" + std::string(ent->d_name)).c_str());
		}

		closedir(dir);
	}
}
<commit_msg>Loop subjobs<commit_after>#include <dlfcn.h>
#include <signal.h>
#include <cassert>
#include <fstream>
#include <cppzmq/zmq.h>
#include <quidpp.h>
#include <package.h>
#include <Python.h>
#include "common/util.h"
#include "ace/interface.h"
#include "protoc/processjob.pb.h"
#include "dirent.h"
#include "wal.h"
#include "localenv.h"
#include "package.h"
#include "exec.h"

void Execute::init(int workerid, const std::string& masterIPC, const std::string& masterProvision, Indexer *db) {
	DIR *dir = nullptr;
	struct dirent *ent = nullptr;

	Execute& exec = Execute::getInstance();
	exec.workerid = workerid;
	exec.masterIPC = masterIPC;
	exec.masterProvision = masterProvision;
	exec.db = db;

	if ((dir = opendir(WALDIR)) != NULL) {

		/* print all the files and directories within directory */
		while ((ent = readdir(dir)) != NULL) {
			if (!strcmp(ent->d_name, ".") || !strcmp(ent->d_name, ".."))
				continue;

			Wal::rollback(ent->d_name, [](const std::string & name, Execute::Parameter & param) {

				/* Run procedure */
				Execute::run(name, param, false);

				/* Setup subjobs if any */
				Execute::prospect(name);
			});
		}

		closedir(dir);
	}
}

bool Execute::run(const std::string& name, Parameter& param, bool canfork) {
	if (canfork) {
		signal(SIGCHLD, SIG_IGN);
		pid_t pid = fork();
		if (pid > 0)
			return false;
	}

	Wal *executionLog = new Wal(name, param);

	int i, j;
	struct timeval t1, t2;
	char buff[PATH_MAX + 1];

	Execute& exec = Execute::getInstance();

	ControlClient control;
	control.setMaster(exec.masterIPC);
	control.setWorker(exec.workerid);
	control.setJob(param.jobquid, param.jobid);
	control.start();
	exec.jobcontrol = &control;

	std::cout << "Running package " << name << std::endl;

	/* Move worker in accept mode */
	exec.jobcontrol->setStateAccepted();

	/* Set members of shared object via callback */
	exec.clusterjobs = exec.jobcontrol->clusterJobs();
	exec.module = name;
	exec.jobid = param.jobid;
	exec.jobname = param.jobname;
	exec.jobquid = param.jobquid;
	exec.jobpartition = param.jobpartition;
	exec.jobpartition_count = param.jobpartition_count;
	exec.jobstate = param.jobstate;
	exec.jobparent = param.jobparent;
	char *cwd = getcwd(buff, PATH_MAX + 1);

	exec.jobcontrol->resetInternalState();

	/* Ensure package exist */
	if (!file_exist((PKGDIR "/" + name).c_str())) {
		exec.jobcontrol->setStateIdle();
		std::cerr << "Package does not exist" << std::endl;
		return true;
	}

	LocalEnv jobenv(LOCALDIR "/" + name, exec.jobid, exec.workerid);
	while (jobenv.isLocked()) {
		std::cerr << "Directory busy, waiting on mutex" << std::endl;
		exec.jobcontrol->setStateAwaiting();
		sleep(5);
	}

	if (!jobenv.hasHome()) {
		/* Extract package in job directory */
		Package pack(PKGDIR "/" + name);
		pack.extract(LOCALDIR "/" + name);

		/* Setup job home */
		if (!jobenv.setupHome())
			return true;
	} else {
		std::cout << "Job environment already in cluster" << std::endl;
	}

	/* Setup job home */
	jobenv.setLock();
	if (!jobenv.setupEnv())
		return true;

	auto packageMain = jobenv.packageMain();
	auto packageInvoke = jobenv.packageInvoke();
	if (packageMain.empty() || packageInvoke.empty())
		return true;

	/* Move WAL forward */
	executionLog->setCheckpoint(Wal::Checkpoint::INIT);

	wchar_t *program = Py_DecodeLocale("Chella Worker", NULL);
	if (!program) {
		std::cerr << "Cannot decode name" << std::endl;
		return true;
	}

	/* Move to job home and prepare python */
	auto streamStdOut = jobenv.openStream(LocalEnv::STDOUT);
	auto streamStdErr = jobenv.openStream(LocalEnv::STDERR);
	chdir((std::string(cwd) + "/" + LOCALDIR "/" + name).c_str());
	setenv("PYTHONPATH", ".", 1);

	Py_SetProgramName(program);
	Py_Initialize();

	PyObject *pModuleJob = PyImport_ImportModule(packageMain.c_str());
	if (!pModuleJob) {
		PyErr_Print();
		return true;
	}

	/* Initialize Ace modules */
	PyObject *pMethodConfig = Ace::Config::PyAce_ModuleClass();
	PyObject *pMethodCallback = Ace::IPC::PyAce_ModuleClass(exec.jobcontrol);
	PyObject *pModuleAsysStream1 = Ace::Asys::PyAce_ModuleClass(streamStdOut);
	PyObject *pModuleAsysStream2 = Ace::Asys::PyAce_ModuleClass(streamStdErr);
	PyObject *pMethodDB = Ace::DB::PyAce_ModuleClass(exec.db);

	/* Move WAL forward */
	executionLog->setCheckpoint(Wal::Checkpoint::LOAD);
	gettimeofday(&t1, NULL);

	/* Set system settings */
	PySys_SetObject("stdout", pModuleAsysStream1);
	PySys_SetObject("stderr", pModuleAsysStream2);
	PySys_SetObject("stdin", pModuleAsysStream2);

	/* Create Ace config instance */
	PyObject *pInstanceConfig = PyObject_CallObject(pMethodConfig, NULL);
	if (!pInstanceConfig) {
		PyErr_Print();
		return true;
	}
	Py_DECREF(pMethodConfig);

	/* Create Ace callback instance */
	PyObject *pInstanceCallback = PyObject_CallObject(pMethodCallback, NULL);
	if (!pInstanceCallback) {
		PyErr_Print();
		return true;
	}
	Py_DECREF(pMethodCallback);

	/* Create Ace DB instance */
	PyObject *pInstanceDB = PyObject_CallObject(pMethodDB, NULL);
	if (!pInstanceDB) {
		PyErr_Print();
		return true;
	}
	Py_DECREF(pMethodDB);

	/* Locate job init and call routine */
	PyObject *pFuncJobInit = PyObject_GetAttrString(pModuleJob, packageInvoke.c_str());
	if (!pFuncJobInit || !PyCallable_Check(pFuncJobInit)) {
		PyErr_Print();
		return true;
	}
	Py_DECREF(pModuleJob);

	PyObject *pArgsJobInit = Py_BuildValue("(O)", pInstanceConfig);
	PyObject *pInstanceJobInit = PyObject_CallObject(pFuncJobInit, pArgsJobInit);
	if (!pInstanceJobInit) {
		PyErr_Print();
		return true;
	}
	Py_DECREF(pFuncJobInit);
	Py_DECREF(pArgsJobInit);

	PyObject *pFuncJobInvoke = PyObject_GetAttrString(pInstanceJobInit, "invoke");
	if (!pFuncJobInvoke || !PyCallable_Check(pFuncJobInvoke)) {
		PyErr_Print();
		return true;
	}
	Py_DECREF(pInstanceJobInit);

	/* Instantiate job class */
	PyObject *pInstanceJob = PyObject_CallObject(pFuncJobInvoke, NULL);
	if (!pInstanceJob) {
		PyErr_Print();
		return true;
	}
	Py_DECREF(pFuncJobInvoke);

	/* Inject module instances into job instance */
	if (PyObject_SetAttrString(pInstanceJob, "cfg", pInstanceConfig) < 0) {
		PyErr_Print();
		return true;
	}

	if (PyObject_SetAttrString(pInstanceJob, "__ipc__", pInstanceCallback) < 0) {
		PyErr_Print();
		return true;
	}

	if (PyObject_SetAttrString(pInstanceJob, "__db__", pInstanceDB) < 0) {
		PyErr_Print();
		return true;
	}

	Py_DECREF(pInstanceConfig);
	Py_DECREF(pInstanceCallback);
	Py_DECREF(pInstanceDB);

	PyObject *pMemberChains = NULL;
	PyObject *pResult = NULL;
	pResult = PyObject_CallMethod(pInstanceJob, "inject", "(isssii)",
		exec.jobid,
		exec.jobname.c_str(),
		name.c_str(),
		exec.jobquid.c_str(),
		exec.jobpartition,
		exec.jobpartition_count);
	if (!pResult) {
		PyErr_Print();
		exec.jobcontrol->setStateFailed();
		goto py_failed;
	}

	/* Move WAL forward */
	executionLog->setCheckpoint(Wal::Checkpoint::INJECT);

	pResult = PyObject_CallMethod(pInstanceJob, "setup_once", NULL);
	if (!pResult) {
		PyErr_Print();
		exec.jobcontrol->setStateFailed();
		goto py_failed;
	}

	/* Move WAL forward */
	executionLog->setCheckpoint(Wal::Checkpoint::SETUP_ONCE);

	exec.jobcontrol->setStateSetup();
	pResult = PyObject_CallMethod(pInstanceJob, "setup", NULL);
	if (!pResult) {
		PyErr_Print();
		exec.jobcontrol->setStateFailed();
		goto py_failed;
	}

	/* Move WAL forward */
	executionLog->setCheckpoint(Wal::Checkpoint::SETUP);

	exec.jobcontrol->setStateRunning();
	pResult = PyObject_CallMethod(pInstanceJob, "run", "(y#)", param.jobdata.data(), param.jobdata.size());
	if (!pResult) {
		PyErr_Print();
		exec.jobcontrol->setStateFailed();
		goto py_failed;
	}

	/* Move WAL forward */
	executionLog->setCheckpoint(Wal::Checkpoint::RUN);

	exec.jobcontrol->setStateTeardown();
	pResult = PyObject_CallMethod(pInstanceJob, "teardown", NULL);
	if (!pResult) {
		PyErr_Print();
		exec.jobcontrol->setStateFailed();
		goto py_failed;
	}

	/* Move WAL forward */
	executionLog->setCheckpoint(Wal::Checkpoint::TEARDOWN);

	pResult = PyObject_CallMethod(pInstanceJob, "teardown_once", NULL);
	if (!pResult) {
		PyErr_Print();
		exec.jobcontrol->setStateFailed();
		goto py_failed;
	}

	/* Move WAL forward */
	executionLog->setCheckpoint(Wal::Checkpoint::TEARDOWN_ONCE);

	pMemberChains = PyObject_GetAttrString(pInstanceJob, "chains");
	if (!pMemberChains) {
		PyErr_Print();
		exec.jobcontrol->setStateFailed();
		goto py_failed;
	}

	if (!PyList_Check(pMemberChains)) {
		PyErr_Print();
		exec.jobcontrol->setStateFailed();
		goto py_failed;
	}

	for (i = 0; i < PyList_Size(pMemberChains); ++i) {
		PyObject *pListChain = PyList_GetItem(pMemberChains, i);
		if (!pListChain) {
			PyErr_Print();
			continue;
		}

		PyObject *pListSubjobs = PyObject_GetAttrString(pListChain, "subjobs");
		if (!PyList_Check(pListSubjobs)) {
			PyErr_Print();
			continue;
		}

		for (j = 0; j < PyList_Size(pListSubjobs); ++j) {
			PyObject *pObjectSubjob = PyList_GetItem(pListSubjobs, j);
			if (!pObjectSubjob) {
				PyErr_Print();
				continue;
			}

			/* Get name */
			PyObject *pyItemName = PyDict_GetItemString(pObjectSubjob, "name");
			if (!pyItemName) {
				PyErr_Print();
				continue;
			}

			PyObject *pyStrObject = PyUnicode_AsEncodedString(pyItemName, "ASCII", "strict");
			if (!pyStrObject) {
				PyErr_Print();
				continue;
			}

			const char *strSubjobName = PyBytes_AS_STRING(pyStrObject);
			printf("name: %s\n", strSubjobName);

			//

			Py_DECREF(pyStrObject);
			Py_DECREF(pyItemName);
		}
	}

	/* Move WAL forward */
	executionLog->setCheckpoint(Wal::Checkpoint::PULLCHAIN);
py_failed:
	gettimeofday(&t2, NULL);

	/* Release resources allocated for this job */
	Py_Finalize();
	exec.sessionCleanup();
	chdir(cwd);

	/* Close output streams */
	streamStdOut->close();
	streamStdErr->close();
	delete streamStdOut;
	delete streamStdErr;

	/* Mark WAL done */
	executionLog->markDone();

	double runtime = (t2.tv_sec - t1.tv_sec) * 1000.0;
	runtime += (t2.tv_usec - t1.tv_usec) / 1000.0;

	/* Write to disk */
	std::cout << "Job routine reached end" << std::endl;
	std::cout << "Total runtime: " << runtime << "ms" << std::endl;

	/* Teardown */
	jobenv.teardown(runtime);

	/* Move worker in idle mode */
	exec.jobcontrol->setStateIdle();

	control.stop();

	delete executionLog;
	std::cout << "Exit clean" << std::endl;

	return true;
}

void Execute::prospect(const std::string& name) {
	zmq::context_t context(1);
	zmq::socket_t socket(context, ZMQ_REQ);
	Execute& exec = Execute::getInstance();

	if (!exec.chain) {
		return;
	}

	if (!file_exist((PKGDIR "/" + name).c_str())) {
		std::cerr << "Cannot access library" << std::endl;
		return;
	}

	std::ifstream ifs(PKGDIR "/" + name);
	std::string content((std::istreambuf_iterator<char>(ifs)),
						(std::istreambuf_iterator<char>()));

	socket.connect(("tcp://" + exec.masterProvision).c_str());
	std::cout << "Connect to master " << exec.masterProvision << std::endl;

	for (unsigned int i = 0; i < exec.chain->size(); ++i) {
		auto subjob = exec.chain->at(i);

		ProcessJob job;
		job.set_name(subjob->name);
		job.set_id(i);
		job.set_quid(quidpp::Quid().toString(true));
		job.set_content(content);
		job.set_partition(i);
		job.set_partition_count(exec.chain->size());
		job.set_state(ProcessJob::PARTITION);
		job.set_quid_parent(exec.chain->parentQuid());
		job.set_data(subjob->data);

		std::cout << "Submit subjob " << i << " linked to parent " << exec.chain->parentQuid() + "(" + exec.chain->parentName() + ")" << std::endl;

		std::string serialized;
		job.SerializeToString(&serialized);

		zmq::message_t request(serialized.size());
		memcpy(reinterpret_cast<void *>(request.data()), serialized.c_str(), serialized.size());
		socket.send(request);

		/* Get the reply */
		zmq::message_t reply;
		socket.recv(&reply);
	}

	delete exec.chain;
	exec.chain = nullptr;
}

void Execute::dispose() {
	DIR *dir = nullptr;
	struct dirent *ent = nullptr;

	std::cout << "Clear caches" << std::endl;

	if ((dir = opendir(PKGDIR)) != NULL) {

		/* print all the files and directories within directory */
		while ((ent = readdir(dir)) != NULL) {
			if (!strcmp(ent->d_name, ".") || !strcmp(ent->d_name, ".."))
				continue;
			remove((PKGDIR "/" + std::string(ent->d_name)).c_str());
		}

		closedir(dir);
	}
}
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2011, Willow Garage, Inc.
 * All rights reserved.
 *
 * Distribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 *     * Distributions of source code must retain the above copyright
 *       notice, this list of conditions and the following disclaimer.
 *     * Distributions in binary form must reproduce the above copyright
 *       notice, this list of conditions and the following disclaimer in the
 *       documentation and/or other materials provided with the distribution.
 *     * Neither the name of the Willow Garage, Inc. nor the names of its
 *       contributors may be used to endorse or promote products derived from
 *       this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

#include <ros/ros.h>

#include <actionlib/client/simple_action_client.h>
#include <turtlebot_arm_marker_manipulation/BlockDetectionAction.h>
#include <turtlebot_arm_marker_manipulation/PickAndPlaceAction.h>
//#include <turtlebot_arm_marker_manipulation/InteractiveBlockManipulationAction.h>
#include <arbotix_msgs/Relax.h>

#include <geometry_msgs/PoseArray.h>

#include <string>
#include <sstream>

const std::string gripper_param = "/gripper_controller";
const std::string pick_and_place_topic = "/pick_and_place";

namespace turtlebot_arm_marker_manipulation
{

class BlockManipulationAction
{
private:
  ros::NodeHandle nh_;

  geometry_msgs::PoseArray poseMsg;
  geometry_msgs::Pose start_pose_bumped, end_pose_bumped;

  // Actions and services
  actionlib::SimpleActionClient<BlockDetectionAction> block_detection_action_;
  //actionlib::SimpleActionClient<InteractiveBlockManipulationAction> interactive_manipulation_action_;
  actionlib::SimpleActionClient<PickAndPlaceAction> pick_and_place_action_;

  BlockDetectionGoal block_detection_goal_;
  //InteractiveBlockManipulationGoal interactive_manipulation_goal_;
  PickAndPlaceGoal pick_and_place_goal_;

  // Parameters
  std::string arm_link;
  double gripper_open, gripper_tighten, gripper_closed, z_up, z_down, block_size;

  turtlebot_arm_marker_manipulation::BlockPoseArray block_list_; //list of the positions and colors of blocks we've found

  int blockIndex;  // block we are working on
  int blockCount;  // number of blocks found

public:
    std::string armMode;
    bool auto_draw_;

  BlockManipulationAction() : nh_("~"),
    block_detection_action_("block_detection", true),
    //interactive_manipulation_action_("interactive_manipulation", true),
    pick_and_place_action_("pick_and_place", true)
  {
    // Load parameters
    nh_.param<std::string>("arm_link", arm_link, "/arm_link");
    nh_.param<double>(gripper_param + "/max_opening", gripper_open, 0.042);
    nh_.param<double>("grip_tighten", gripper_tighten, 0.004);
    nh_.param<double>("z_up", z_up, 0.06);   // amount to lift during move
    nh_.param<double>("table_height", z_down, 0.0);
    nh_.param<double>("block_size", block_size, 0.02);  // block size to detect

    nh_.param<bool>("auto_draw", auto_draw_, false); //If we should detect blocks and automatically sort them

    // Initialize goals
    block_detection_goal_.frame = arm_link;
    block_detection_goal_.table_height = z_down;
    block_detection_goal_.block_size = block_size;

    pick_and_place_goal_.frame = arm_link;
    pick_and_place_goal_.z_up = z_up;
    pick_and_place_goal_.gripper_open = gripper_open;
    pick_and_place_goal_.gripper_closed = block_size - gripper_tighten;
    pick_and_place_goal_.topic = pick_and_place_topic;

    ROS_INFO("Gripper settings: closed=%.4f block size=%.4f tighten=%.4f", (float)pick_and_place_goal_.gripper_closed, (float)block_size, (float)gripper_tighten );

    //interactive_manipulation_goal_.block_size = block_size;
    //interactive_manipulation_goal_.frame = arm_link;

    ROS_INFO("Finished initializing, waiting for servers...");

    block_detection_action_.waitForServer();
    ROS_INFO(" 1. Found block_detection server.");

    //interactive_manipulation_action_.waitForServer();
    //ROS_INFO(" 2. Found interactive_manipulation server.");

    pick_and_place_action_.waitForServer();
    ROS_INFO(" 3. Found pick_and_place server.");

  }

  void detectBlocks()
  {
  // Have Block Detection Server detect blocks and callback "addBlocks" when done
    block_detection_action_.sendGoal(block_detection_goal_, boost::bind( &BlockManipulationAction::addBlocks, this, _1, _2));
  }

  void addBlocks(const actionlib::SimpleClientGoalState& state, const BlockDetectionResultConstPtr& result)
  {
    //ROS_INFO(" Got block detection callback. Adding blocks.");
    turtlebot_arm_marker_manipulation::BlockPose block;

    if (state != actionlib::SimpleClientGoalState::SUCCEEDED)
    {
      ROS_ERROR("  Failed! %s",  state.toString().c_str());
      ros::shutdown();
    }

    blockCount = result->colored_blocks.poses.size();
    blockIndex = 0;

    // Save blocks for later use during sorting
    block_list_.poses.clear();
    for (unsigned int i=0; i < blockCount; i++)
    {
      block_list_.poses.push_back( result->colored_blocks.poses[i] );
      //ROS_INFO("Added block %d x=%f", i, blockList[i].position.x);
    }

    // Add blocks to Interactive Manipulation Server for RViz visualization
    //interactive_manipulation_action_.sendGoal(interactive_manipulation_goal_, boost::bind( &BlockManipulationAction::pickAndPlace, this, _1, _2));
  }

  void pickAndPlace(const actionlib::SimpleClientGoalState& state /*, const InteractiveBlockManipulationResultConstPtr& result*/)
  {
    if (state != actionlib::SimpleClientGoalState::SUCCEEDED)
    {
      ROS_ERROR("  Select Marker Failed! %s",  state.toString().c_str());
      ros::shutdown();
    }

    //ROS_INFO(" Got interactive marker callback.");
    ROS_INFO("Picking and placing...");

    pick_and_place_action_.sendGoal(pick_and_place_goal_, boost::bind( &BlockManipulationAction::finish, this, _1, _2));
  }

  void finish(const actionlib::SimpleClientGoalState& state, const PickAndPlaceResultConstPtr& result)
  {
    if (state == actionlib::SimpleClientGoalState::SUCCEEDED)
    {
      ROS_INFO(" Pick and place - Succeeded!");
    }
    else
    {
      ROS_INFO(" Pick and place - Failed! %s",  state.toString().c_str());
    }

    if (blockIndex < blockCount && armMode == "m")
    {
      organizeBlocks();
    }
    else
    {
      detectBlocks();
    }
  }

  //Organize the blocks by color
  void organizeBlocks()
  {
    ROS_WARN_STREAM( "Organizing Blocks: Block # "<< blockIndex + 1 << ", RGB: " << block_list_.poses[blockIndex].color.r << ", " << block_list_.poses[blockIndex].color.g << ", " << block_list_.poses[blockIndex].color.b );
    int targetCount;

    geometry_msgs::Pose endPose;

    // // This routine calculates the target position for block.
    // // Blocks which match the target color go to one area, others go to second area
    // //if (block_list_.poses[blockIndex].color.g > 128.0f )  // Does this block match target color?
    // if ( block_list_.poses[blockIndex].color.g > block_list_.poses[blockIndex].color.r && block_list_.poses[blockIndex].color.g > block_list_.poses[blockIndex].color.b )
    // {
    //   ROS_DEBUG("Block matches target Color");
    //   endPose.position.x = target_match_x;
    //   endPose.position.y = target_match_y;
    // }
    // else  // Not target color, use alternate destination
    // {
    //   ROS_DEBUG("Block is not target Color");
    //   endPose.position.x = target_discard_x;
    //   endPose.position.y = target_discard_y;
    // }
    // endPose.position.z = target_bin_height;

    // ROS_DEBUG("Block End Pose x=%.4f y=%.4f z=%.4f", endPose.position.x, endPose.position.y, endPose.position.z);

    // Go through list of blocks and move them
    if (blockIndex < blockCount)
    {
      moveBlock(block_list_.poses[blockIndex], endPose);
      blockIndex++;
    }
  }

  void moveBlock(const turtlebot_arm_marker_manipulation::BlockPose& start_block_pose, const geometry_msgs::Pose& end_pose)
  {
    geometry_msgs::Pose start_pose;
    start_pose.position = start_block_pose.position;
    start_pose.orientation = start_block_pose.orientation;

    double bump_size = 0.005;

    // Return pickup and place poses as the result of the action

    start_pose_bumped = start_pose;
    start_pose_bumped.position.z -= block_size/2.0 - bump_size;

    end_pose_bumped = end_pose;
    end_pose_bumped.position.z -= block_size/2.0 - bump_size;

    // Publish pickup and place poses for visualizing on RViz
    poseMsg.header.frame_id = arm_link;
    poseMsg.header.stamp = ros::Time::now();
    poseMsg.poses.push_back(start_pose_bumped);
    poseMsg.poses.push_back(end_pose_bumped);
    //ROS_INFO("Demo publishing to PickNPlace.  PoseX=%.4f", (float) poseMsg.poses[0].position.x);

    pick_and_place_goal_.pickup_pose = start_pose_bumped;
    pick_and_place_goal_.place_pose = end_pose_bumped;
    pick_and_place_goal_.topic = "";

    pick_and_place_action_.sendGoal(pick_and_place_goal_, boost::bind( &BlockManipulationAction::finish, this, _1, _2));

    pick_and_place_goal_.topic = pick_and_place_topic;  // restore topic
   }
 };
};

int main(int argc, char** argv)
{
  ros::init(argc, argv, "marker_manipulation");
  turtlebot_arm_marker_manipulation::BlockManipulationAction manip;

  ros::AsyncSpinner spinner(2);
  spinner.start();

  if ( manip.auto_draw_ )
  {
    ros::Duration(2.0).sleep();
    manip.detectBlocks();
    manip.armMode="d";
    ros::Duration(5.0).sleep();
    manip.organizeBlocks();
    manip.armMode="m";
  }

  while (ros::ok())
  {
    //Allow user restarting, in case block detection fails or scene changes
    std::cout << "d - Detect, m - Move" << std::endl;

    std::string instr;
    getline (std::cin, instr );

    if (instr == "d") {manip.detectBlocks(); manip.armMode="d";}
    if (instr == "m") {manip.organizeBlocks();manip.armMode="m";}
  }

  spinner.stop();
}
<commit_msg>Fixed action client server name<commit_after>/*
 * Copyright (c) 2011, Willow Garage, Inc.
 * All rights reserved.
 *
 * Distribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 *     * Distributions of source code must retain the above copyright
 *       notice, this list of conditions and the following disclaimer.
 *     * Distributions in binary form must reproduce the above copyright
 *       notice, this list of conditions and the following disclaimer in the
 *       documentation and/or other materials provided with the distribution.
 *     * Neither the name of the Willow Garage, Inc. nor the names of its
 *       contributors may be used to endorse or promote products derived from
 *       this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

#include <ros/ros.h>

#include <actionlib/client/simple_action_client.h>
#include <turtlebot_arm_marker_manipulation/BlockDetectionAction.h>
#include <turtlebot_arm_marker_manipulation/PickAndPlaceAction.h>
//#include <turtlebot_arm_marker_manipulation/InteractiveBlockManipulationAction.h>
#include <arbotix_msgs/Relax.h>

#include <geometry_msgs/PoseArray.h>

#include <string>
#include <sstream>

const std::string gripper_param = "/gripper_controller";
const std::string pick_and_place_topic = "/pick_and_place";

namespace turtlebot_arm_marker_manipulation
{

class BlockManipulationAction
{
private:
  ros::NodeHandle nh_;

  geometry_msgs::PoseArray poseMsg;
  geometry_msgs::Pose start_pose_bumped, end_pose_bumped;

  // Actions and services
  actionlib::SimpleActionClient<BlockDetectionAction> block_detection_action_;
  //actionlib::SimpleActionClient<InteractiveBlockManipulationAction> interactive_manipulation_action_;
  actionlib::SimpleActionClient<PickAndPlaceAction> pick_and_place_action_;

  BlockDetectionGoal block_detection_goal_;
  //InteractiveBlockManipulationGoal interactive_manipulation_goal_;
  PickAndPlaceGoal pick_and_place_goal_;

  // Parameters
  std::string arm_link;
  double gripper_open, gripper_tighten, gripper_closed, z_up, z_down, block_size;

  turtlebot_arm_marker_manipulation::BlockPoseArray block_list_; //list of the positions and colors of blocks we've found

  int blockIndex;  // block we are working on
  int blockCount;  // number of blocks found

public:
    std::string armMode;
    bool auto_draw_;

  BlockManipulationAction() : nh_("~"),
    block_detection_action_("block_detection", true),
    //interactive_manipulation_action_("interactive_manipulation", true),
    pick_and_place_action_("pick_and_draw", true)
  {
    // Load parameters
    nh_.param<std::string>("arm_link", arm_link, "/arm_link");
    nh_.param<double>(gripper_param + "/max_opening", gripper_open, 0.042);
    nh_.param<double>("grip_tighten", gripper_tighten, 0.004);
    nh_.param<double>("z_up", z_up, 0.06);   // amount to lift during move
    nh_.param<double>("table_height", z_down, 0.0);
    nh_.param<double>("block_size", block_size, 0.02);  // block size to detect

    nh_.param<bool>("auto_draw", auto_draw_, false); //If we should detect blocks and automatically sort them

    // Initialize goals
    block_detection_goal_.frame = arm_link;
    block_detection_goal_.table_height = z_down;
    block_detection_goal_.block_size = block_size;

    pick_and_place_goal_.frame = arm_link;
    pick_and_place_goal_.z_up = z_up;
    pick_and_place_goal_.gripper_open = gripper_open;
    pick_and_place_goal_.gripper_closed = block_size - gripper_tighten;
    pick_and_place_goal_.topic = pick_and_place_topic;

    ROS_INFO("Gripper settings: closed=%.4f block size=%.4f tighten=%.4f", (float)pick_and_place_goal_.gripper_closed, (float)block_size, (float)gripper_tighten );

    //interactive_manipulation_goal_.block_size = block_size;
    //interactive_manipulation_goal_.frame = arm_link;

    ROS_INFO("Finished initializing, waiting for servers...");

    block_detection_action_.waitForServer();
    ROS_INFO(" 1. Found block_detection server.");

    //interactive_manipulation_action_.waitForServer();
    //ROS_INFO(" 2. Found interactive_manipulation server.");

    pick_and_place_action_.waitForServer();
    ROS_INFO(" 3. Found pick_and_place server.");

  }

  void detectBlocks()
  {
  // Have Block Detection Server detect blocks and callback "addBlocks" when done
    block_detection_action_.sendGoal(block_detection_goal_, boost::bind( &BlockManipulationAction::addBlocks, this, _1, _2));
  }

  void addBlocks(const actionlib::SimpleClientGoalState& state, const BlockDetectionResultConstPtr& result)
  {
    //ROS_INFO(" Got block detection callback. Adding blocks.");
    turtlebot_arm_marker_manipulation::BlockPose block;

    if (state != actionlib::SimpleClientGoalState::SUCCEEDED)
    {
      ROS_ERROR("  Failed! %s",  state.toString().c_str());
      ros::shutdown();
    }

    blockCount = result->colored_blocks.poses.size();
    blockIndex = 0;

    // Save blocks for later use during sorting
    block_list_.poses.clear();
    for (unsigned int i=0; i < blockCount; i++)
    {
      block_list_.poses.push_back( result->colored_blocks.poses[i] );
      //ROS_INFO("Added block %d x=%f", i, blockList[i].position.x);
    }

    // Add blocks to Interactive Manipulation Server for RViz visualization
    //interactive_manipulation_action_.sendGoal(interactive_manipulation_goal_, boost::bind( &BlockManipulationAction::pickAndPlace, this, _1, _2));
  }

  void pickAndPlace(const actionlib::SimpleClientGoalState& state /*, const InteractiveBlockManipulationResultConstPtr& result*/)
  {
    if (state != actionlib::SimpleClientGoalState::SUCCEEDED)
    {
      ROS_ERROR("  Select Marker Failed! %s",  state.toString().c_str());
      ros::shutdown();
    }

    //ROS_INFO(" Got interactive marker callback.");
    ROS_INFO("Picking and placing...");

    pick_and_place_action_.sendGoal(pick_and_place_goal_, boost::bind( &BlockManipulationAction::finish, this, _1, _2));
  }

  void finish(const actionlib::SimpleClientGoalState& state, const PickAndPlaceResultConstPtr& result)
  {
    if (state == actionlib::SimpleClientGoalState::SUCCEEDED)
    {
      ROS_INFO(" Pick and place - Succeeded!");
    }
    else
    {
      ROS_INFO(" Pick and place - Failed! %s",  state.toString().c_str());
    }

    if (blockIndex < blockCount && armMode == "m")
    {
      organizeBlocks();
    }
    else
    {
      detectBlocks();
    }
  }

  //Organize the blocks by color
  void organizeBlocks()
  {
    ROS_WARN_STREAM( "Organizing Blocks: Block # "<< blockIndex + 1 << ", RGB: " << block_list_.poses[blockIndex].color.r << ", " << block_list_.poses[blockIndex].color.g << ", " << block_list_.poses[blockIndex].color.b );
    int targetCount;

    geometry_msgs::Pose endPose;

    // // This routine calculates the target position for block.
    // // Blocks which match the target color go to one area, others go to second area
    // //if (block_list_.poses[blockIndex].color.g > 128.0f )  // Does this block match target color?
    // if ( block_list_.poses[blockIndex].color.g > block_list_.poses[blockIndex].color.r && block_list_.poses[blockIndex].color.g > block_list_.poses[blockIndex].color.b )
    // {
    //   ROS_DEBUG("Block matches target Color");
    //   endPose.position.x = target_match_x;
    //   endPose.position.y = target_match_y;
    // }
    // else  // Not target color, use alternate destination
    // {
    //   ROS_DEBUG("Block is not target Color");
    //   endPose.position.x = target_discard_x;
    //   endPose.position.y = target_discard_y;
    // }
    // endPose.position.z = target_bin_height;

    // ROS_DEBUG("Block End Pose x=%.4f y=%.4f z=%.4f", endPose.position.x, endPose.position.y, endPose.position.z);

    // Go through list of blocks and move them
    if (blockIndex < blockCount)
    {
      moveBlock(block_list_.poses[blockIndex], endPose);
      blockIndex++;
    }
  }

  void moveBlock(const turtlebot_arm_marker_manipulation::BlockPose& start_block_pose, const geometry_msgs::Pose& end_pose)
  {
    geometry_msgs::Pose start_pose;
    start_pose.position = start_block_pose.position;
    start_pose.orientation = start_block_pose.orientation;

    double bump_size = 0.005;

    // Return pickup and place poses as the result of the action

    start_pose_bumped = start_pose;
    start_pose_bumped.position.z -= block_size/2.0 - bump_size;

    end_pose_bumped = end_pose;
    end_pose_bumped.position.z -= block_size/2.0 - bump_size;

    // Publish pickup and place poses for visualizing on RViz
    poseMsg.header.frame_id = arm_link;
    poseMsg.header.stamp = ros::Time::now();
    poseMsg.poses.push_back(start_pose_bumped);
    poseMsg.poses.push_back(end_pose_bumped);
    //ROS_INFO("Demo publishing to PickNPlace.  PoseX=%.4f", (float) poseMsg.poses[0].position.x);

    pick_and_place_goal_.pickup_pose = start_pose_bumped;
    pick_and_place_goal_.place_pose = end_pose_bumped;
    pick_and_place_goal_.topic = "";

    pick_and_place_action_.sendGoal(pick_and_place_goal_, boost::bind( &BlockManipulationAction::finish, this, _1, _2));

    pick_and_place_goal_.topic = pick_and_place_topic;  // restore topic
   }
 };
};

int main(int argc, char** argv)
{
  ros::init(argc, argv, "marker_manipulation");
  turtlebot_arm_marker_manipulation::BlockManipulationAction manip;

  ros::AsyncSpinner spinner(2);
  spinner.start();

  if ( manip.auto_draw_ )
  {
    ros::Duration(2.0).sleep();
    manip.detectBlocks();
    manip.armMode="d";
    ros::Duration(5.0).sleep();
    manip.organizeBlocks();
    manip.armMode="m";
  }

  while (ros::ok())
  {
    //Allow user restarting, in case block detection fails or scene changes
    std::cout << "d - Detect, m - Move" << std::endl;

    std::string instr;
    getline (std::cin, instr );

    if (instr == "d") {manip.detectBlocks(); manip.armMode="d";}
    if (instr == "m") {manip.organizeBlocks();manip.armMode="m";}
  }

  spinner.stop();
}
<|endoftext|>


<commit_before>/**************************************************************************
 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
 *                                                                        *
 * Author: The ALICE Off-line Project.                                    *
 * Contributors are mentioned in the code where appropriate.              *
 *                                                                        *
 * Permission to use, copy, modify and distribute this software and its   *
 * documentation strictly for non-commercial purposes is hereby granted   *
 * without fee, provided that the above copyright notice appears in all   *
 * copies and that both the copyright notice and this permission notice   *
 * appear in the supporting documentation. The authors make no claims     *
 * about the suitability of this software for any purpose. It is          *
 * provided "as is" without express or implied warranty.                  *
 **************************************************************************/

///////////////////////////////////////////////////////////////////////////
/*

Origin: marian.ivanov@cern.ch
Container classes with MC infomation for V0

*/

#if !defined(__CINT__) || defined(__MAKECINT__)
#include <stdio.h>
#include <string.h>
//ROOT includes
#include "TROOT.h"
#include "Rtypes.h"
#include "TFile.h"
#include "TTree.h"
#include "TChain.h"
#include "TCut.h"
#include "TString.h"
#include "TStopwatch.h"
#include "TParticle.h"
#include "TSystem.h"
#include "TCanvas.h"
#include "TGeometry.h"
#include "TPolyLine3D.h"

//ALIROOT includes
#include "AliRun.h"
#include "AliStack.h"
#include "AliSimDigits.h"
#include "AliTPCParam.h"
#include "AliTPC.h"
#include "AliTPCLoader.h"
#include "AliDetector.h"
#include "AliTrackReference.h"
#include "AliTPCParamSR.h"
#include "AliTracker.h"
#include "AliMagF.h"
#include "AliHelix.h"
#include "AliTrackPointArray.h"

#endif
#include "AliGenV0Info.h"
//
//

ClassImp(AliGenV0Info)

/////////////////////////////////////////////////////////////////////////////////
AliGenV0Info::AliGenV0Info():
  fMCd(),      //info about daughter particle -
  fMCm(),      //info about mother particle   - first particle for V0
  fMotherP(),   //particle info about mother particle
  fMCDist1(0), //info about closest distance according closest MC - linear DCA
  fMCDist2(0),    //info about closest distance parabolic DCA
  fMCRr(0),       // rec position of the vertex
  fMCR(0),        //exact r position of the vertex
  fInvMass(0),  //reconstructed invariant mass -
  fPointAngleFi(0), //point angle fi
  fPointAngleTh(0), //point angle theta
  fPointAngle(0)   //point angle full
{
  for (Int_t i=0;i<3; i++){
   fMCPdr[i]=0;
   fMCX[i]=0;
   fMCXr[i]=0;
   fMCPm[i]=0;
   fMCAngle[i]=0;
   fMCPd[i]=0;
  }
  fMCPd[3]=0;
  for (Int_t i=0; i<2;i++){
    fPdg[i]=0;
    fLab[i]=0;
  }
}

void AliGenV0Info::Update(Float_t vertex[3])
{
  //
  // Update information - calculates derived variables
  //

  fMCPd[0] = fMCd.GetParticle().Px();
  fMCPd[1] = fMCd.GetParticle().Py();
  fMCPd[2] = fMCd.GetParticle().Pz();
  fMCPd[3] = fMCd.GetParticle().P();
  //
  fMCX[0]  = fMCd.GetParticle().Vx();
  fMCX[1]  = fMCd.GetParticle().Vy();
  fMCX[2]  = fMCd.GetParticle().Vz();
  fMCR       = TMath::Sqrt( fMCX[0]*fMCX[0]+fMCX[1]*fMCX[1]);
  //
  fPdg[0]    = fMCd.GetParticle().GetPdgCode();
  fPdg[1]    = fMCm.GetParticle().GetPdgCode();
  //
  fLab[0]    = fMCd.GetParticle().GetUniqueID();
  fLab[1]    = fMCm.GetParticle().GetUniqueID();
  //
  //
  //
  Double_t x1[3],p1[3];
  TParticle& pdaughter = fMCd.GetParticle();
  x1[0] = pdaughter.Vx();
  x1[1] = pdaughter.Vy();
  x1[2] = pdaughter.Vz();
  p1[0] = pdaughter.Px();
  p1[1] = pdaughter.Py();
  p1[2] = pdaughter.Pz();
  Double_t sign = (pdaughter.GetPDG()->Charge()>0)? -1:1;
  AliHelix dhelix1(x1,p1,sign);
  //
  //
  Double_t x2[3],p2[3];
  //
  TParticle& pmother = fMCm.GetParticle();
  x2[0] = pmother.Vx();
  x2[1] = pmother.Vy();
  x2[2] = pmother.Vz();
  p2[0] = pmother.Px();
  p2[1] = pmother.Py();
  p2[2] = pmother.Pz();
  //
  //
  sign = (pmother.GetPDG()->Charge()>0) ? -1:1;
  AliHelix mhelix(x2,p2,sign);

  //
  //
  //
  //find intersection linear
  //
  Double_t distance1, distance2;
  Double_t phase[2][2],radius[2];
  Int_t  points = dhelix1.GetRPHIintersections(mhelix, phase, radius);
  Double_t delta1=10000,delta2=10000;
  if (points>0){
    dhelix1.LinearDCA(mhelix,phase[0][0],phase[0][1],radius[0],delta1);
    dhelix1.LinearDCA(mhelix,phase[0][0],phase[0][1],radius[0],delta1);
    dhelix1.LinearDCA(mhelix,phase[0][0],phase[0][1],radius[0],delta1);
  }
  else{
    fInvMass=-1;
    return;
  }
  if (points==2){
    dhelix1.LinearDCA(mhelix,phase[1][0],phase[1][1],radius[1],delta2);
    dhelix1.LinearDCA(mhelix,phase[1][0],phase[1][1],radius[1],delta2);
    dhelix1.LinearDCA(mhelix,phase[1][0],phase[1][1],radius[1],delta2);
  }
  distance1 = TMath::Min(delta1,delta2);
  //
  //find intersection parabolic
  //
  points = dhelix1.GetRPHIintersections(mhelix, phase, radius);
  delta1=10000,delta2=10000;

  if (points>0){
    dhelix1.ParabolicDCA(mhelix,phase[0][0],phase[0][1],radius[0],delta1);
  }
  if (points==2){
    dhelix1.ParabolicDCA(mhelix,phase[1][0],phase[1][1],radius[1],delta2);
  }

  distance2 = TMath::Min(delta1,delta2);
  //
  if (delta1<delta2){
    //get V0 info
    dhelix1.Evaluate(phase[0][0],fMCXr);
    dhelix1.GetMomentum(phase[0][0],fMCPdr);
    mhelix.GetMomentum(phase[0][1],fMCPm);
    dhelix1.GetAngle(phase[0][0],mhelix,phase[0][1],fMCAngle);
    fMCRr = TMath::Sqrt(radius[0]);
  }
  else{
    dhelix1.Evaluate(phase[1][0],fMCXr);
    dhelix1.GetMomentum(phase[1][0],fMCPdr);
    mhelix.GetMomentum(phase[1][1],fMCPm);
    dhelix1.GetAngle(phase[1][0],mhelix,phase[1][1],fMCAngle);
    fMCRr = TMath::Sqrt(radius[1]);
  }
  //
  //
  fMCDist1 = TMath::Sqrt(distance1);
  fMCDist2 = TMath::Sqrt(distance2);
  //
  //
  //
  Float_t v[3] = {fMCXr[0]-vertex[0],fMCXr[1]-vertex[1],fMCXr[2]-vertex[2]};
  //Float_t v[3] = {fMCXr[0],fMCXr[1],fMCXr[2]};
  Float_t p[3] = {fMCPdr[0]+fMCPm[0], fMCPdr[1]+fMCPm[1],fMCPdr[2]+fMCPm[2]};
  Float_t vnorm2 = v[0]*v[0]+v[1]*v[1];
  Float_t vnorm3 = TMath::Sqrt(v[2]*v[2]+vnorm2);
  vnorm2 = TMath::Sqrt(vnorm2);
  Float_t pnorm2 = p[0]*p[0]+p[1]*p[1];
  Float_t pnorm3 = TMath::Sqrt(p[2]*p[2]+pnorm2);
  pnorm2 = TMath::Sqrt(pnorm2);
  //
  fPointAngleFi = (v[0]*p[0]+v[1]*p[1])/(vnorm2*pnorm2);
  fPointAngleTh = (v[2]*p[2]+vnorm2*pnorm2)/(vnorm3*pnorm3);
  fPointAngle   = (v[0]*p[0]+v[1]*p[1]+v[2]*p[2])/(vnorm3*pnorm3);
  Double_t mass1 = fMCd.GetMass();
  Double_t mass2 = fMCm.GetMass();

  Double_t e1    = TMath::Sqrt(mass1*mass1+
			      fMCPd[0]*fMCPd[0]+
			      fMCPd[1]*fMCPd[1]+
			      fMCPd[2]*fMCPd[2]);
  Double_t e2    = TMath::Sqrt(mass2*mass2+
			      fMCPm[0]*fMCPm[0]+
			      fMCPm[1]*fMCPm[1]+
			      fMCPm[2]*fMCPm[2]);

  fInvMass =
    (fMCPm[0]+fMCPd[0])*(fMCPm[0]+fMCPd[0])+
    (fMCPm[1]+fMCPd[1])*(fMCPm[1]+fMCPd[1])+
    (fMCPm[2]+fMCPd[2])*(fMCPm[2]+fMCPd[2]);

  //  fInvMass = TMath::Sqrt((e1+e2)*(e1+e2)-fInvMass);
  fInvMass = (e1+e2)*(e1+e2)-fInvMass;
  if (fInvMass>0) fInvMass = TMath::Sqrt(fInvMass);
}

<commit_msg>Additioanl protection (Marian)<commit_after>/**************************************************************************
 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
 *                                                                        *
 * Author: The ALICE Off-line Project.                                    *
 * Contributors are mentioned in the code where appropriate.              *
 *                                                                        *
 * Permission to use, copy, modify and distribute this software and its   *
 * documentation strictly for non-commercial purposes is hereby granted   *
 * without fee, provided that the above copyright notice appears in all   *
 * copies and that both the copyright notice and this permission notice   *
 * appear in the supporting documentation. The authors make no claims     *
 * about the suitability of this software for any purpose. It is          *
 * provided "as is" without express or implied warranty.                  *
 **************************************************************************/

///////////////////////////////////////////////////////////////////////////
/*

Origin: marian.ivanov@cern.ch
Container classes with MC infomation for V0

*/

#if !defined(__CINT__) || defined(__MAKECINT__)
#include <stdio.h>
#include <string.h>
//ROOT includes
#include "TROOT.h"
#include "Rtypes.h"
#include "TFile.h"
#include "TTree.h"
#include "TChain.h"
#include "TCut.h"
#include "TString.h"
#include "TStopwatch.h"
#include "TParticle.h"
#include "TSystem.h"
#include "TCanvas.h"
#include "TGeometry.h"
#include "TPolyLine3D.h"

//ALIROOT includes
#include "AliRun.h"
#include "AliStack.h"
#include "AliSimDigits.h"
#include "AliTPCParam.h"
#include "AliTPC.h"
#include "AliTPCLoader.h"
#include "AliDetector.h"
#include "AliTrackReference.h"
#include "AliTPCParamSR.h"
#include "AliTracker.h"
#include "AliMagF.h"
#include "AliHelix.h"
#include "AliTrackPointArray.h"

#endif
#include "AliGenV0Info.h"
//
//

ClassImp(AliGenV0Info)

/////////////////////////////////////////////////////////////////////////////////
AliGenV0Info::AliGenV0Info():
  fMCd(),      //info about daughter particle -
  fMCm(),      //info about mother particle   - first particle for V0
  fMotherP(),   //particle info about mother particle
  fMCDist1(0), //info about closest distance according closest MC - linear DCA
  fMCDist2(0),    //info about closest distance parabolic DCA
  fMCRr(0),       // rec position of the vertex
  fMCR(0),        //exact r position of the vertex
  fInvMass(0),  //reconstructed invariant mass -
  fPointAngleFi(0), //point angle fi
  fPointAngleTh(0), //point angle theta
  fPointAngle(0)   //point angle full
{
  for (Int_t i=0;i<3; i++){
   fMCPdr[i]=0;
   fMCX[i]=0;
   fMCXr[i]=0;
   fMCPm[i]=0;
   fMCAngle[i]=0;
   fMCPd[i]=0;
  }
  fMCPd[3]=0;
  for (Int_t i=0; i<2;i++){
    fPdg[i]=0;
    fLab[i]=0;
  }
}

void AliGenV0Info::Update(Float_t vertex[3])
{
  //
  // Update information - calculates derived variables
  //

  fMCPd[0] = fMCd.GetParticle().Px();
  fMCPd[1] = fMCd.GetParticle().Py();
  fMCPd[2] = fMCd.GetParticle().Pz();
  fMCPd[3] = fMCd.GetParticle().P();
  //
  fMCX[0]  = fMCd.GetParticle().Vx();
  fMCX[1]  = fMCd.GetParticle().Vy();
  fMCX[2]  = fMCd.GetParticle().Vz();
  fMCR       = TMath::Sqrt( fMCX[0]*fMCX[0]+fMCX[1]*fMCX[1]);
  //
  fPdg[0]    = fMCd.GetParticle().GetPdgCode();
  fPdg[1]    = fMCm.GetParticle().GetPdgCode();
  //
  fLab[0]    = fMCd.GetParticle().GetUniqueID();
  fLab[1]    = fMCm.GetParticle().GetUniqueID();
  //
  //
  //
  Double_t x1[3],p1[3];
  TParticle& pdaughter = fMCd.GetParticle();
  x1[0] = pdaughter.Vx();
  x1[1] = pdaughter.Vy();
  x1[2] = pdaughter.Vz();
  p1[0] = pdaughter.Px();
  p1[1] = pdaughter.Py();
  p1[2] = pdaughter.Pz();
  Double_t sign = (pdaughter.GetPDG()->Charge()>0)? -1:1;
  AliHelix dhelix1(x1,p1,sign);
  //
  //
  Double_t x2[3],p2[3];
  //
  TParticle& pmother = fMCm.GetParticle();
  x2[0] = pmother.Vx();
  x2[1] = pmother.Vy();
  x2[2] = pmother.Vz();
  p2[0] = pmother.Px();
  p2[1] = pmother.Py();
  p2[2] = pmother.Pz();
  //
  //
  sign = (pmother.GetPDG()->Charge()>0) ? -1:1;
  AliHelix mhelix(x2,p2,sign);

  //
  //
  //
  //find intersection linear
  //
  Double_t distance1, distance2;
  Double_t phase[2][2],radius[2];
  Int_t  points = dhelix1.GetRPHIintersections(mhelix, phase, radius);
  Double_t delta1=10000,delta2=10000;
  if (points>0){
    dhelix1.LinearDCA(mhelix,phase[0][0],phase[0][1],radius[0],delta1);
    dhelix1.LinearDCA(mhelix,phase[0][0],phase[0][1],radius[0],delta1);
    dhelix1.LinearDCA(mhelix,phase[0][0],phase[0][1],radius[0],delta1);
  }
  else{
    fInvMass=-1;
    return;
  }
  if (points==2){
    dhelix1.LinearDCA(mhelix,phase[1][0],phase[1][1],radius[1],delta2);
    dhelix1.LinearDCA(mhelix,phase[1][0],phase[1][1],radius[1],delta2);
    dhelix1.LinearDCA(mhelix,phase[1][0],phase[1][1],radius[1],delta2);
  }
  distance1 = TMath::Min(delta1,delta2);
  //
  //find intersection parabolic
  //
  points = dhelix1.GetRPHIintersections(mhelix, phase, radius);
  delta1=10000,delta2=10000;

  if (points>0){
    dhelix1.ParabolicDCA(mhelix,phase[0][0],phase[0][1],radius[0],delta1);
  }
  if (points==2){
    dhelix1.ParabolicDCA(mhelix,phase[1][0],phase[1][1],radius[1],delta2);
  }

  distance2 = TMath::Min(delta1,delta2);
  //
  if (delta1<delta2){
    //get V0 info
    dhelix1.Evaluate(phase[0][0],fMCXr);
    dhelix1.GetMomentum(phase[0][0],fMCPdr);
    mhelix.GetMomentum(phase[0][1],fMCPm);
    dhelix1.GetAngle(phase[0][0],mhelix,phase[0][1],fMCAngle);
    fMCRr = TMath::Sqrt(radius[0]);
  }
  else{
    dhelix1.Evaluate(phase[1][0],fMCXr);
    dhelix1.GetMomentum(phase[1][0],fMCPdr);
    mhelix.GetMomentum(phase[1][1],fMCPm);
    dhelix1.GetAngle(phase[1][0],mhelix,phase[1][1],fMCAngle);
    fMCRr = TMath::Sqrt(radius[1]);
  }
  //
  //
  fMCDist1 = TMath::Sqrt(distance1);
  fMCDist2 = TMath::Sqrt(distance2);
  //
  //
  //
  Float_t v[3] = {fMCXr[0]-vertex[0],fMCXr[1]-vertex[1],fMCXr[2]-vertex[2]};
  //Float_t v[3] = {fMCXr[0],fMCXr[1],fMCXr[2]};
  Float_t p[3] = {fMCPdr[0]+fMCPm[0], fMCPdr[1]+fMCPm[1],fMCPdr[2]+fMCPm[2]};
  Float_t vnorm2 = v[0]*v[0]+v[1]*v[1];
  Float_t vnorm3 = TMath::Sqrt(v[2]*v[2]+vnorm2);
  vnorm2 = TMath::Sqrt(vnorm2);
  Float_t pnorm2 = p[0]*p[0]+p[1]*p[1];
  Float_t pnorm3 = TMath::Sqrt(p[2]*p[2]+pnorm2);
  pnorm2 = TMath::Sqrt(pnorm2);
  //
  if (vnorm2>0){
    fPointAngleFi = (v[0]*p[0]+v[1]*p[1])/(vnorm2*pnorm2);
    fPointAngleTh = (v[2]*p[2]+vnorm2*pnorm2)/(vnorm3*pnorm3);
    fPointAngle   = (v[0]*p[0]+v[1]*p[1]+v[2]*p[2])/(vnorm3*pnorm3);
  }else{
    fPointAngleFi = 1;
    fPointAngleTh = 1;
    fPointAngle   = 1;
  }
  Double_t mass1 = fMCd.GetMass();
  Double_t mass2 = fMCm.GetMass();

  Double_t e1    = TMath::Sqrt(mass1*mass1+
			      fMCPd[0]*fMCPd[0]+
			      fMCPd[1]*fMCPd[1]+
			      fMCPd[2]*fMCPd[2]);
  Double_t e2    = TMath::Sqrt(mass2*mass2+
			      fMCPm[0]*fMCPm[0]+
			      fMCPm[1]*fMCPm[1]+
			      fMCPm[2]*fMCPm[2]);

  fInvMass =
    (fMCPm[0]+fMCPd[0])*(fMCPm[0]+fMCPd[0])+
    (fMCPm[1]+fMCPd[1])*(fMCPm[1]+fMCPd[1])+
    (fMCPm[2]+fMCPd[2])*(fMCPm[2]+fMCPd[2]);

  //  fInvMass = TMath::Sqrt((e1+e2)*(e1+e2)-fInvMass);
  fInvMass = (e1+e2)*(e1+e2)-fInvMass;
  if (fInvMass>0) fInvMass = TMath::Sqrt(fInvMass);
}

<|endoftext|>


<commit_before>/*

	compute the Restricted Voronoi Diagram in CPU

*/

//RVD computing part
#include "Command_line.h"
#include "Mesh_io.h"
#include "Mesh.h"
#include "Points.h"
#include "Mesh_repair.h"

// Cuda part
#include "CudaHelper.h"
#include <time.h>

// Renderring part
#include "Glut_generator.h"
#include "DrawGraphics.h"

#include "RVD.h"

#define WINDOWS_WIDTH 1000
#define WINDOWS_HEIGHT 800

using namespace P_RVD;

GraphicsDrawer* m_GraphicsDrawer = new GraphicsDrawer();
Points p_in, p_out;
Mesh M_in;

/*
	call the cuda function
	pass the data to the device
*/
extern "C" void runCuda(double* host_seeds_pointer, double* host_mesh_vertex_pointer,
	int* host_facet_index, int points_nb, int mesh_vertex_nb, int mesh_facet_number);

void RenderCB(void)
{
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
	glClearColor(0.1f, 0.1f, 0.2f, 0.0f);

	glDisable(GL_COLOR_MATERIAL);
	glDisable(GL_LIGHTING);
	glColor3f(1.0f, 0.0f, 0.0f);
	m_GraphicsDrawer->DrawPoints(p_in);

	glColor3f(0.0f, 1.0f, 0.0f);
	m_GraphicsDrawer->DrawPoints(p_out);

	glEnable(GL_LIGHTING);
	glEnable(GL_COLOR_MATERIAL);
	glColor3f(0.8f, 0.8f, 0.8f);
	glPolygonMode(GL_FRONT, GL_LINE);
	m_GraphicsDrawer->DrawMesh(M_in);

	glFlush();
	glutSwapBuffers();
	glutPostRedisplay();
}

void myResize(int width, int height)
{

	//get the viewport of GLUI and then set the viewport back to that after the resize
	glViewport(0, 0, width, height);//viewportڴ趨һӽǵĴСһڻΪӽ
	glMatrixMode(GL_PROJECTION);

	glPushMatrix();
	glLoadIdentity();
	gluPerspective(60.0, (float)width / height, 0.5f, 20.0f);//趨ӽ
	glPopMatrix();
	gluLookAt(1.0f, 0.0f, 0.0f, 0.0f, 0.f, 0.0f, 0.0f, 1.0f, 0.0f);
	glClearColor((GLclampf)1 / 255, (GLclampf)1 / 255, (GLclampf)1 / 255, 0.0);//ˢɻɫ
	glEnable(GL_DEPTH_TEST);
}

int main(int argc, char** argv)
{
	std::vector<std::string> filenames;
	if (!Cmd::parse_argu(argc, argv, filenames))
	{
		fprintf(stderr, "cannot parse the argument into filenames!");
		return -1;
	}

	std::string mesh_filename = filenames[0];
	std::string points_filename = filenames[0];
	std::string output_filename;
	if (filenames.size() >= 2) {
		points_filename = filenames[1];
	}
	output_filename = (filenames.size() == 3) ? filenames[2] : "out.eobj";

	Mesh  M_out, points_in;
	FileType mesh_type = OBJfile;

	if (!mesh_load(mesh_filename, M_in))
	{
		fprintf(stderr, "cannot load Mesh into M_in!");
		return -1;
	}

	if (!mesh_load(points_filename, points_in, false))
	{
		fprintf(stderr, "cannot load points into points_in!");
		return -1;
	}

	mesh_repair(M_in);
	Points points(points_in);
	Points points_out(points_in);

	/*
		Kdtree
	*/

	/*
		trans the data from host to device
	*/
	double* host_points = NULL;

	trans_points(points, host_points);

	double* host_mesh_vertex = NULL;
	int* host_facet_index = NULL;

	trans_mesh(M_in, host_mesh_vertex, host_facet_index);

	long t1 = clock();
	runCuda(host_points, host_mesh_vertex, host_facet_index, points.getPointsNumber(),
		M_in.meshVertices.getPointNumber(), M_in.meshFacets.getFacetsNumber());

	printf("GPU running time : %lfms\n", (double)(clock() - t1));

	/*
		Compute the RVD in CPU
	*/
	long t2 = clock();
	RestrictedVoronoiDiagram *m_RVD = new RestrictedVoronoiDiagram(&M_in, &points_out);
	m_RVD->compute_RVD();
	printf("CPU running time : %lfms\n", (double)(clock() - t2));

	/*
		Set the Windows
		Use the GLUT lib
	*/
	GLUTBackendInit(argc, argv, true, false);
	GLUTBackendCreateWindow(WINDOWS_WIDTH, WINDOWS_HEIGHT, false, "Rvd");

	//GraphicsDrawer* m_GraphicsDrawer = new GraphicsDrawer();
	m_GraphicsDrawer->Init();
	m_GraphicsDrawer->Run();

	//p_in  records the position before
	//p_out records the position after compute RVD
	p_in = points;
	p_out = points_out;

	//glutDisplayFunc(&RenderCB);
	//glutReshapeFunc(&myResize);

	//glutPostRedisplay();
	//glutMainLoop();

	delete m_GraphicsDrawer;

	return 0;
}
<commit_msg>add comment<commit_after>/*

	compute the Restricted Voronoi Diagram in CPU

*/

//RVD computing part
#include "Command_line.h"
#include "Mesh_io.h"
#include "Mesh.h"
#include "Points.h"
#include "Mesh_repair.h"

// Cuda part
#include "CudaHelper.h"
#include <time.h>

// Renderring part
#include "Glut_generator.h"
#include "DrawGraphics.h"

#include "RVD.h"

#define WINDOWS_WIDTH 1000
#define WINDOWS_HEIGHT 800

using namespace P_RVD;

GraphicsDrawer* m_GraphicsDrawer = new GraphicsDrawer();
Points p_in, p_out;
Mesh M_in;

/*
	call the cuda function
	pass the data to the device
*/
extern "C" void runCuda(double* host_seeds_pointer, double* host_mesh_vertex_pointer,
	int* host_facet_index, int points_nb, int mesh_vertex_nb, int mesh_facet_number);

void RenderCB(void)
{
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
	glClearColor(0.1f, 0.1f, 0.2f, 0.0f);

	glDisable(GL_COLOR_MATERIAL);
	glDisable(GL_LIGHTING);
	glColor3f(1.0f, 0.0f, 0.0f);
	m_GraphicsDrawer->DrawPoints(p_in);

	glColor3f(0.0f, 1.0f, 0.0f);
	m_GraphicsDrawer->DrawPoints(p_out);

	glEnable(GL_LIGHTING);
	glEnable(GL_COLOR_MATERIAL);
	glColor3f(0.8f, 0.8f, 0.8f);
	glPolygonMode(GL_FRONT, GL_LINE);
	m_GraphicsDrawer->DrawMesh(M_in);

	glFlush();
	glutSwapBuffers();
	glutPostRedisplay();
}

void myResize(int width, int height)
{

	//get the viewport of GLUI and then set the viewport back to that after the resize
	glViewport(0, 0, width, height);//viewportڴ趨һӽǵĴСһڻΪӽ
	glMatrixMode(GL_PROJECTION);

	glPushMatrix();
	glLoadIdentity();
	gluPerspective(60.0, (float)width / height, 0.5f, 20.0f);//趨ӽ
	glPopMatrix();
	gluLookAt(1.0f, 0.0f, 0.0f, 0.0f, 0.f, 0.0f, 0.0f, 1.0f, 0.0f);
	glClearColor((GLclampf)1 / 255, (GLclampf)1 / 255, (GLclampf)1 / 255, 0.0);//ˢɻɫ
	glEnable(GL_DEPTH_TEST);
}

int main(int argc, char** argv)
{
	std::vector<std::string> filenames;
	if (!Cmd::parse_argu(argc, argv, filenames))
	{
		fprintf(stderr, "cannot parse the argument into filenames!");
		return -1;
	}

	std::string mesh_filename = filenames[0];
	std::string points_filename = filenames[0];
	std::string output_filename;
	if (filenames.size() >= 2) {
		points_filename = filenames[1];
	}
	output_filename = (filenames.size() == 3) ? filenames[2] : "out.eobj";

	Mesh  M_out, points_in;
	FileType mesh_type = OBJfile;

	if (!mesh_load(mesh_filename, M_in))
	{
		fprintf(stderr, "cannot load Mesh into M_in!");
		return -1;
	}

	if (!mesh_load(points_filename, points_in, false))
	{
		fprintf(stderr, "cannot load points into points_in!");
		return -1;
	}

	mesh_repair(M_in);
	Points points(points_in);
	Points points_out(points_in);

	/*
		Kdtree
	*/

	/*
		trans the data from host to device
	*/
	double* host_points = NULL;

	trans_points(points, host_points);

	double* host_mesh_vertex = NULL;
	int* host_facet_index = NULL;

	trans_mesh(M_in, host_mesh_vertex, host_facet_index);

	long t1 = clock();
	//runCuda(host_points, host_mesh_vertex, host_facet_index, points.getPointsNumber(),
	//  M_in.meshVertices.getPointNumber(), M_in.meshFacets.getFacetsNumber());

	printf("GPU running time : %lfms\n", (double)(clock() - t1));

	/*
		Compute the RVD in CPU
	*/
	long t2 = clock();
	RestrictedVoronoiDiagram *m_RVD = new RestrictedVoronoiDiagram(&M_in, &points_out);
	m_RVD->compute_RVD();
	printf("CPU running time : %lfms\n", (double)(clock() - t2));

	/*
		Set the Windows
		Use the GLUT lib
	*/
	GLUTBackendInit(argc, argv, true, false);
	GLUTBackendCreateWindow(WINDOWS_WIDTH, WINDOWS_HEIGHT, false, "Rvd");

	//GraphicsDrawer* m_GraphicsDrawer = new GraphicsDrawer();
	m_GraphicsDrawer->Init();
	m_GraphicsDrawer->Run();

	//p_in  records the position before
	//p_out records the position after compute RVD
	p_in = points;
	p_out = points_out;

	//glutDisplayFunc(&RenderCB);
	//glutReshapeFunc(&myResize);

	//glutPostRedisplay();
	//glutMainLoop();

	delete m_GraphicsDrawer;

	return 0;
}
<|endoftext|>


<commit_before>#include <cassert>
#include <cstdio>
#include <ctype.h>
#include <windows.h>
#include <vector>

struct Property
{
	char type[32];
	char scene[32];
	char object[32];
	char property[32];
};

template <typename F>
struct privDefer {
	F f;
	privDefer(F f) : f(f) {}
	~privDefer() { f(); }
};

template <typename F>
privDefer<F> defer_func(F f) {
	return privDefer<F>(f);
}

#define DEFER_1(x, y) x##y
#define DEFER_2(x, y) DEFER_1(x, y)
#define DEFER_3(x)    DEFER_2(x, __COUNTER__)
#define defer(code)   auto DEFER_3(_defer_) = defer_func([&](){code;})

template <int N>
const char* copyIdentifier(char(&out)[N], const char* src)
{
	char* c = out;
	while (*src != ',' && *src != ')')
	{
		*c = *src;
		++c;
		++src;
	}
	*c = '\0';
	while (!isalnum(*src) && *src != '_') ++src;
	return src;
}

bool addProperty(const char* str, std::vector<Property>& properties)
{
	assert(str);

	Property prop;
	const char* c = str + strlen("CSHARP_PROPERTY(");
	c = copyIdentifier(prop.type, c);
	if (strcmp(prop.type, "Type") == 0) return true;
	if (!*c) return false;
	c = copyIdentifier(prop.scene, c);
	if (!*c) return false;
	c = copyIdentifier(prop.object, c);
	if (!*c) return false;
	copyIdentifier(prop.property, c);
	properties.push_back(prop);
	return true;
}

bool parse(const char* path, std::vector<Property>& properties)
{
	FILE* fp = fopen(path, "rb");
	if (!fp) return false;

	defer(fclose(fp));

	fseek(fp, 0, SEEK_END);
	int size = (int)ftell(fp);
	fseek(fp, 0, SEEK_SET);

	std::vector<char> text;
	text.resize(size + 1);

	if (fread(&text[0], 1, size, fp) != size) return false;

	text[size] = 0;

	const char* prop_str = &text[0];
	while (prop_str = strstr(prop_str, "CSHARP_PROPERTY("))
	{
		if (!addProperty(prop_str, properties)) return false;
		++prop_str;
	}
	return true;
}

void writeCSharpFooter(FILE* fp)
{
	fprintf(fp, "\t}\n\n}\n");
}

void writeCSharpHeader(FILE* fp, const char* obj)
{
	static const char* header =
		"using System;\n"
		"using System.Runtime.InteropServices;\n"
		"using System.Runtime.CompilerServices;\n"
		"\n"
		"\n"
		"namespace Lumix\n"
		"{\n"
		"\n"
		"\n"
		"	public class %s : NativeComponent\n"
		"	{\n"
		"		private int component_id;\n"
		"		private IntPtr scene;\n"
		"\n"
		"\n"
		"		public override void create()\n"
		"		{\n"
		"			component_id = create(entity._universe, entity._entity_id, \"%s\");\n"
		"			scene = getScene(entity._universe, \"%s\");\n"
		"		}\n"
		"\n"
		"\n";

	char cmp_name[128];
	char* c = cmp_name;
	const char* in = obj;
	while (*in && c - cmp_name < sizeof(cmp_name) - 3)
	{
		if (isupper(*in))
		{
			if (in != obj)
			{
				*c = '_';
				++c;
			}
			*c = *in - 'A' + 'a';
		}
		else
		{
			*c = *in;
		}
		++c;
		++in;
	}
	*c = '\0';

	fprintf(fp, header, obj, cmp_name, cmp_name);
}

void writeCSharpProperty(FILE* fp, const Property& prop)
{
	const char* text =
		"		/* %s */\n"
		"		[MethodImplAttribute(MethodImplOptions.InternalCall)]\n"
		"		private extern static void set%s(IntPtr scene, int cmp, %s source);\n"
		"		\n"
		"		[MethodImplAttribute(MethodImplOptions.InternalCall)]\n"
		"		private extern static %s get%s(IntPtr scene, int cmp);\n"
		"		\n"
		"		public %s %s\n"
		"		{\n"
		"			get{ return get%s(scene, component_id); }\n"
		"			set{ set%s(scene, component_id, value); }\n"
		"		}\n"
		"\n"
		"\n";

	const char* type = prop.type;
	if (strcmp(type, "const char*") == 0) type = "string";
	else if (strcmp(type, "Path") == 0) type = "string";
	const char* name = prop.property;
	fprintf(fp, text, name, name, type, type, name, type, name, name, name);
}

bool writeCSharp(const char* out_dir, std::vector<Property>& properties)
{
	auto cmp = [](const void* a, const void* b) -> int {
		auto* prop_a = (Property*)a;
		auto* prop_b = (Property*)b;
		return strcmp(prop_a->object, prop_b->object);
	};
	qsort(&properties[0], properties.size(), sizeof(properties[0]), cmp);

	FILE* fp = nullptr;
	const char* last_obj = "";
	for (const Property& prop : properties)
	{
		if (strcmp(last_obj, prop.object) != 0)
		{
			if (fp)
			{
				writeCSharpFooter(fp);
				fclose(fp);
			}
			char path[256];
			strcpy_s(path, out_dir);
			strcat_s(path, prop.object);
			strcat_s(path, ".cs");
			fp = fopen(path, "wb");
			last_obj = prop.object;
			if (!fp) return false;

			writeCSharpHeader(fp, prop.object);
		}
		writeCSharpProperty(fp, prop);
	}
	writeCSharpFooter(fp);
	if (fp) fclose(fp);
	return true;
}

int main()
{
	std::vector<Property> properties;
	parse("C:\\projects\\lumixengine_csharp\\src\\csharp.cpp", properties);
	writeCSharp("C:\\projects\\lumixengine_csharp\\cs\\", properties);
}<commit_msg>exception when trying to create native component that already exists<commit_after>#include <cassert>
#include <cstdio>
#include <ctype.h>
#include <windows.h>
#include <vector>

struct Property
{
	char type[32];
	char scene[32];
	char object[32];
	char property[32];
};

template <typename F>
struct privDefer {
	F f;
	privDefer(F f) : f(f) {}
	~privDefer() { f(); }
};

template <typename F>
privDefer<F> defer_func(F f) {
	return privDefer<F>(f);
}

#define DEFER_1(x, y) x##y
#define DEFER_2(x, y) DEFER_1(x, y)
#define DEFER_3(x)    DEFER_2(x, __COUNTER__)
#define defer(code)   auto DEFER_3(_defer_) = defer_func([&](){code;})

template <int N>
const char* copyIdentifier(char(&out)[N], const char* src)
{
	char* c = out;
	while (*src != ',' && *src != ')')
	{
		*c = *src;
		++c;
		++src;
	}
	*c = '\0';
	while (!isalnum(*src) && *src != '_') ++src;
	return src;
}

bool addProperty(const char* str, std::vector<Property>& properties)
{
	assert(str);

	Property prop;
	const char* c = str + strlen("CSHARP_PROPERTY(");
	c = copyIdentifier(prop.type, c);
	if (strcmp(prop.type, "Type") == 0) return true;
	if (!*c) return false;
	c = copyIdentifier(prop.scene, c);
	if (!*c) return false;
	c = copyIdentifier(prop.object, c);
	if (!*c) return false;
	copyIdentifier(prop.property, c);
	properties.push_back(prop);
	return true;
}

bool parse(const char* path, std::vector<Property>& properties)
{
	FILE* fp = fopen(path, "rb");
	if (!fp) return false;

	defer(fclose(fp));

	fseek(fp, 0, SEEK_END);
	int size = (int)ftell(fp);
	fseek(fp, 0, SEEK_SET);

	std::vector<char> text;
	text.resize(size + 1);

	if (fread(&text[0], 1, size, fp) != size) return false;

	text[size] = 0;

	const char* prop_str = &text[0];
	while (prop_str = strstr(prop_str, "CSHARP_PROPERTY("))
	{
		if (!addProperty(prop_str, properties)) return false;
		++prop_str;
	}
	return true;
}

void writeCSharpFooter(FILE* fp)
{
	fprintf(fp, "\t}\n\n}\n");
}

void writeCSharpHeader(FILE* fp, const char* obj)
{
	static const char* header =
		"using System;\n"
		"using System.Runtime.InteropServices;\n"
		"using System.Runtime.CompilerServices;\n"
		"\n"
		"\n"
		"namespace Lumix\n"
		"{\n"
		"\n"
		"\n"
		"	public class %s : NativeComponent\n"
		"	{\n"
		"		private int component_id;\n"
		"		private IntPtr scene;\n"
		"\n"
		"\n"
		"		public override void create()\n"
		"		{\n"
		"			component_id = create(entity._universe, entity._entity_id, \"%s\");\n"
		"			if (component_id < 0) throw new Exception(\"Failed to create component\");\n"
		"			scene = getScene(entity._universe, \"%s\");\n"
		"		}\n"
		"\n"
		"\n";

	char cmp_name[128];
	char* c = cmp_name;
	const char* in = obj;
	while (*in && c - cmp_name < sizeof(cmp_name) - 3)
	{
		if (isupper(*in))
		{
			if (in != obj)
			{
				*c = '_';
				++c;
			}
			*c = *in - 'A' + 'a';
		}
		else
		{
			*c = *in;
		}
		++c;
		++in;
	}
	*c = '\0';

	fprintf(fp, header, obj, cmp_name, cmp_name);
}

void writeCSharpProperty(FILE* fp, const Property& prop)
{
	const char* text =
		"		/* %s */\n"
		"		[MethodImplAttribute(MethodImplOptions.InternalCall)]\n"
		"		private extern static void set%s(IntPtr scene, int cmp, %s source);\n"
		"		\n"
		"		[MethodImplAttribute(MethodImplOptions.InternalCall)]\n"
		"		private extern static %s get%s(IntPtr scene, int cmp);\n"
		"		\n"
		"		public %s %s\n"
		"		{\n"
		"			get{ return get%s(scene, component_id); }\n"
		"			set{ set%s(scene, component_id, value); }\n"
		"		}\n"
		"\n"
		"\n";

	const char* type = prop.type;
	if (strcmp(type, "const char*") == 0) type = "string";
	else if (strcmp(type, "Path") == 0) type = "string";
	const char* name = prop.property;
	fprintf(fp, text, name, name, type, type, name, type, name, name, name);
}

bool writeCSharp(const char* out_dir, std::vector<Property>& properties)
{
	auto cmp = [](const void* a, const void* b) -> int {
		auto* prop_a = (Property*)a;
		auto* prop_b = (Property*)b;
		return strcmp(prop_a->object, prop_b->object);
	};
	qsort(&properties[0], properties.size(), sizeof(properties[0]), cmp);

	FILE* fp = nullptr;
	const char* last_obj = "";
	for (const Property& prop : properties)
	{
		if (strcmp(last_obj, prop.object) != 0)
		{
			if (fp)
			{
				writeCSharpFooter(fp);
				fclose(fp);
			}
			char path[256];
			strcpy_s(path, out_dir);
			strcat_s(path, prop.object);
			strcat_s(path, ".cs");
			fp = fopen(path, "wb");
			last_obj = prop.object;
			if (!fp) return false;

			writeCSharpHeader(fp, prop.object);
		}
		writeCSharpProperty(fp, prop);
	}
	writeCSharpFooter(fp);
	if (fp) fclose(fp);
	return true;
}

int main()
{
	std::vector<Property> properties;
	parse("C:\\projects\\lumixengine_csharp\\src\\csharp.cpp", properties);
	writeCSharp("C:\\projects\\lumixengine_csharp\\cs\\", properties);
}<|endoftext|>