<commit_before>/***************************************************************
 *
 * Copyright (C) 1990-2007, Condor Team, Computer Sciences Department,
 * University of Wisconsin-Madison, WI.
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you
 * may not use this file except in compliance with the License.  You may
 * obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 ***************************************************************/

#ifdef _NO_CONDOR_
#include <sys/types.h> // for fstat, struct stat
#include <sys/stat.h> // for fstat, struct stat
#include <unistd.h> // for fstat, struct stat
#include <limits.h> // for _POSIX_PATH_MAX
#include <string.h> // for strcpy
#include <stdlib.h> // for atol
#include <assert.h> // for assert
#include <errno.h> // for errno
#include <syslog.h> // for syslog, LOG_ERR, LOG_DEBUG
#else
#include "condor_common.h"
#endif

#include "ClassAdLogEntry.h"
#include "ClassAdLogProber.h"
#include "ClassAdLogParser.h"

//! constructor
ClassAdLogProber::ClassAdLogProber()
{
	last_mod_time = 0;
	last_size = 0;
	last_seq_num = 0;
	last_creation_time = 0;

	cur_probed_mod_time = 0;
	cur_probed_size = 0;
	cur_probed_seq_num = 0;
	cur_probed_creation_time = 0;
	job_queue_name[0] = '\0';
}

//! destructor
ClassAdLogProber::~ClassAdLogProber()
{}

//**************************************************************************
// Accessors
//**************************************************************************
void
ClassAdLogProber::setJobQueueName(const char* jqn)
{
	assert(jqn);
	strcpy(job_queue_name, jqn);
}

char*
ClassAdLogProber::getJobQueueName()
{
	return job_queue_name;
}

void
ClassAdLogProber::setLastModifiedTime(time_t t)
{
	last_mod_time = t;
}

time_t
ClassAdLogProber::getLastModifiedTime()
{
	return last_mod_time;
}

void
ClassAdLogProber::setLastSize(size_t s)
{
	last_size = s;
}

size_t
ClassAdLogProber::getLastSize()
{
	return last_size;
}

long int
ClassAdLogProber::getLastSequenceNumber()
{
	return last_seq_num;
}

void
ClassAdLogProber::setLastSequenceNumber(long int seq_num)
{
	last_seq_num = seq_num;
}

time_t
ClassAdLogProber::getLastCreationTime()
{
	return last_creation_time;
}

void
ClassAdLogProber::setLastCreationTime(time_t ctime)
{
	last_creation_time = ctime;
}

long int
ClassAdLogProber::getCurProbedSequenceNumber() {
	return cur_probed_seq_num;
}

long int
ClassAdLogProber::getCurProbedCreationTime() {
	return cur_probed_creation_time;
}

//! probe job_queue.log file
ProbeResultType
ClassAdLogProber::probe(ClassAdLogEntry *curCALogEntry,
			  FILE * job_queue_fp)
{
	FileOpErrCode   st;
	int op_type;
	struct stat filestat;
	int job_queue_fd = fileno(job_queue_fp);
	//TODO: uncomment and possibly change
	/*
	if (job_queue_fd == -1) {
		return PROBE_ERROR;
	}
	*/

	//TODO: should use condor's StatInfo instead.
	if (fstat(job_queue_fd, &filestat) == -1)
#ifdef _NO_CONDOR_
		syslog(LOG_ERR, "ERROR: calling stat(): errno=%d (%m)", errno);

	syslog(LOG_DEBUG, "=== Current Probing Information ===");
	syslog(LOG_DEBUG,
		   "fsize: %ld\t\tmtime: %ld",
		   (long)filestat.st_size, (long)filestat.st_mtime);
#else
		dprintf(D_ALWAYS,"ERROR: calling stat() on %p - %s (errno=%d)\n", job_queue_fp, strerror(errno), errno);

	dprintf(D_FULLDEBUG, "=== Current Probing Information ===\n");
	dprintf(D_FULLDEBUG, "fsize: %ld\t\tmtime: %ld\n",
				(long)filestat.st_size, (long)filestat.st_mtime);
#endif

	// get the new state
	cur_probed_mod_time = filestat.st_mtime;
	cur_probed_size = filestat.st_size;

	ClassAdLogParser caLogParser;

	caLogParser.setFilePointer(job_queue_fp);
	caLogParser.setNextOffset(0);
	st = caLogParser.readLogEntry(op_type);

	if (FILE_FATAL_ERROR == st) {
		return PROBE_FATAL_ERROR;
	}
	if (st != FILE_READ_SUCCESS) {
		return PROBE_ERROR;
	}

	if ( caLogParser.getCurCALogEntry()->op_type !=
		 CondorLogOp_LogHistoricalSequenceNumber )
	{
#ifdef _NO_CONDOR_
		syslog(LOG_ERR,
			   "ERROR: prober expects first classad log entry to be "
			   "type %d, but sees %d instead.",
			   CondorLogOp_LogHistoricalSequenceNumber,
			   caLogParser.getCurCALogEntry()->op_type);
#else
		dprintf(D_ALWAYS,
				"ERROR: quill prober expects first classad log entry to be "
				"type %d, but sees %d instead.",
				CondorLogOp_LogHistoricalSequenceNumber,
				caLogParser.getCurCALogEntry()->op_type);
#endif
		return PROBE_FATAL_ERROR;
	}

#ifdef _NO_CONDOR_
	syslog(LOG_DEBUG,
		   "first log entry: %s %s %s",
		   ((ClassAdLogEntry *)caLogParser.getCurCALogEntry())->key,
		   ((ClassAdLogEntry *)caLogParser.getCurCALogEntry())->name,
		   ((ClassAdLogEntry *)caLogParser.getCurCALogEntry())->value);
#else
	dprintf(D_FULLDEBUG, "first log entry: %s %s %s\n",
			((ClassAdLogEntry *)caLogParser.getCurCALogEntry())->key,
			((ClassAdLogEntry *)caLogParser.getCurCALogEntry())->name,
			((ClassAdLogEntry *)caLogParser.getCurCALogEntry())->value);
#endif
	cur_probed_seq_num =
		atol(((ClassAdLogEntry *)caLogParser.getCurCALogEntry())->key);
	cur_probed_creation_time =
		atol(((ClassAdLogEntry *)caLogParser.getCurCALogEntry())->value);

	if (last_size == 0) {
			// starting phase
		return INIT_QUILL;
	}

	if(cur_probed_seq_num != last_seq_num) {
		return COMPRESSED;
	}

	caLogParser.setNextOffset(curCALogEntry->offset);
	st = caLogParser.readLogEntry(op_type);

	if (FILE_FATAL_ERROR == st) {
		return PROBE_FATAL_ERROR;
	}
	if (st != FILE_READ_EOF && st != FILE_READ_SUCCESS) {
		return PROBE_ERROR;
	}

	if((filestat.st_size == last_size) &&
	   caLogParser.getCurCALogEntry()->equal(curCALogEntry)) {
			// File size and contents stay the same
		return NO_CHANGE;
	}
	else if((filestat.st_size > last_size) &&
			caLogParser.getCurCALogEntry()->equal(curCALogEntry)) {
			// File has been increased and new entries have been added
		return ADDITION;
	}
		//if it wasn't captured by any of the above cases,
		//it must have been an error
	return PROBE_ERROR;
}

void
ClassAdLogProber::incrementProbeInfo() {
	// store the currently probed stat
	last_mod_time = cur_probed_mod_time;
	last_size = cur_probed_size;

	last_seq_num = cur_probed_seq_num;
	last_creation_time = cur_probed_creation_time;
}
<commit_msg>initialize uninitialized variable<commit_after>/***************************************************************
 *
 * Copyright (C) 1990-2007, Condor Team, Computer Sciences Department,
 * University of Wisconsin-Madison, WI.
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you
 * may not use this file except in compliance with the License.  You may
 * obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 ***************************************************************/

#ifdef _NO_CONDOR_
#include <sys/types.h> // for fstat, struct stat
#include <sys/stat.h> // for fstat, struct stat
#include <unistd.h> // for fstat, struct stat
#include <limits.h> // for _POSIX_PATH_MAX
#include <string.h> // for strcpy
#include <stdlib.h> // for atol
#include <assert.h> // for assert
#include <errno.h> // for errno
#include <syslog.h> // for syslog, LOG_ERR, LOG_DEBUG
#else
#include "condor_common.h"
#endif

#include "ClassAdLogEntry.h"
#include "ClassAdLogProber.h"
#include "ClassAdLogParser.h"

//! constructor
ClassAdLogProber::ClassAdLogProber()
{
	last_mod_time = 0;
	last_size = 0;
	last_seq_num = 0;
	last_creation_time = 0;

	cur_probed_mod_time = 0;
	cur_probed_size = 0;
	cur_probed_seq_num = 0;
	cur_probed_creation_time = 0;
	job_queue_name[0] = '\0';
}

//! destructor
ClassAdLogProber::~ClassAdLogProber()
{}

//**************************************************************************
// Accessors
//**************************************************************************
void
ClassAdLogProber::setJobQueueName(const char* jqn)
{
	assert(jqn);
	strcpy(job_queue_name, jqn);
}

char*
ClassAdLogProber::getJobQueueName()
{
	return job_queue_name;
}

void
ClassAdLogProber::setLastModifiedTime(time_t t)
{
	last_mod_time = t;
}

time_t
ClassAdLogProber::getLastModifiedTime()
{
	return last_mod_time;
}

void
ClassAdLogProber::setLastSize(size_t s)
{
	last_size = s;
}

size_t
ClassAdLogProber::getLastSize()
{
	return last_size;
}

long int
ClassAdLogProber::getLastSequenceNumber()
{
	return last_seq_num;
}

void
ClassAdLogProber::setLastSequenceNumber(long int seq_num)
{
	last_seq_num = seq_num;
}

time_t
ClassAdLogProber::getLastCreationTime()
{
	return last_creation_time;
}

void
ClassAdLogProber::setLastCreationTime(time_t ctime)
{
	last_creation_time = ctime;
}

long int
ClassAdLogProber::getCurProbedSequenceNumber() {
	return cur_probed_seq_num;
}

long int
ClassAdLogProber::getCurProbedCreationTime() {
	return cur_probed_creation_time;
}

//! probe job_queue.log file
ProbeResultType
ClassAdLogProber::probe(ClassAdLogEntry *curCALogEntry,
			  FILE * job_queue_fp)
{
	FileOpErrCode   st;
	int op_type = -1;
	struct stat filestat;
	int job_queue_fd = fileno(job_queue_fp);
	//TODO: uncomment and possibly change
	/*
	if (job_queue_fd == -1) {
		return PROBE_ERROR;
	}
	*/

	//TODO: should use condor's StatInfo instead.
	if (fstat(job_queue_fd, &filestat) == -1)
#ifdef _NO_CONDOR_
		syslog(LOG_ERR, "ERROR: calling stat(): errno=%d (%m)", errno);

	syslog(LOG_DEBUG, "=== Current Probing Information ===");
	syslog(LOG_DEBUG,
		   "fsize: %ld\t\tmtime: %ld",
		   (long)filestat.st_size, (long)filestat.st_mtime);
#else
		dprintf(D_ALWAYS,"ERROR: calling stat() on %p - %s (errno=%d)\n", job_queue_fp, strerror(errno), errno);

	dprintf(D_FULLDEBUG, "=== Current Probing Information ===\n");
	dprintf(D_FULLDEBUG, "fsize: %ld\t\tmtime: %ld\n",
				(long)filestat.st_size, (long)filestat.st_mtime);
#endif

	// get the new state
	cur_probed_mod_time = filestat.st_mtime;
	cur_probed_size = filestat.st_size;

	ClassAdLogParser caLogParser;

	caLogParser.setFilePointer(job_queue_fp);
	caLogParser.setNextOffset(0);
	st = caLogParser.readLogEntry(op_type);

	if (FILE_FATAL_ERROR == st) {
		return PROBE_FATAL_ERROR;
	}
	if (st != FILE_READ_SUCCESS) {
		return PROBE_ERROR;
	}

	if ( caLogParser.getCurCALogEntry()->op_type !=
		 CondorLogOp_LogHistoricalSequenceNumber )
	{
#ifdef _NO_CONDOR_
		syslog(LOG_ERR,
			   "ERROR: prober expects first classad log entry to be "
			   "type %d, but sees %d instead.",
			   CondorLogOp_LogHistoricalSequenceNumber,
			   caLogParser.getCurCALogEntry()->op_type);
#else
		dprintf(D_ALWAYS,
				"ERROR: quill prober expects first classad log entry to be "
				"type %d, but sees %d instead.",
				CondorLogOp_LogHistoricalSequenceNumber,
				caLogParser.getCurCALogEntry()->op_type);
#endif
		return PROBE_FATAL_ERROR;
	}

#ifdef _NO_CONDOR_
	syslog(LOG_DEBUG,
		   "first log entry: %s %s %s",
		   ((ClassAdLogEntry *)caLogParser.getCurCALogEntry())->key,
		   ((ClassAdLogEntry *)caLogParser.getCurCALogEntry())->name,
		   ((ClassAdLogEntry *)caLogParser.getCurCALogEntry())->value);
#else
	dprintf(D_FULLDEBUG, "first log entry: %s %s %s\n",
			((ClassAdLogEntry *)caLogParser.getCurCALogEntry())->key,
			((ClassAdLogEntry *)caLogParser.getCurCALogEntry())->name,
			((ClassAdLogEntry *)caLogParser.getCurCALogEntry())->value);
#endif
	cur_probed_seq_num =
		atol(((ClassAdLogEntry *)caLogParser.getCurCALogEntry())->key);
	cur_probed_creation_time =
		atol(((ClassAdLogEntry *)caLogParser.getCurCALogEntry())->value);

	if (last_size == 0) {
			// starting phase
		return INIT_QUILL;
	}

	if(cur_probed_seq_num != last_seq_num) {
		return COMPRESSED;
	}

	caLogParser.setNextOffset(curCALogEntry->offset);
	st = caLogParser.readLogEntry(op_type);

	if (FILE_FATAL_ERROR == st) {
		return PROBE_FATAL_ERROR;
	}
	if (st != FILE_READ_EOF && st != FILE_READ_SUCCESS) {
		return PROBE_ERROR;
	}

	if((filestat.st_size == last_size) &&
	   caLogParser.getCurCALogEntry()->equal(curCALogEntry)) {
			// File size and contents stay the same
		return NO_CHANGE;
	}
	else if((filestat.st_size > last_size) &&
			caLogParser.getCurCALogEntry()->equal(curCALogEntry)) {
			// File has been increased and new entries have been added
		return ADDITION;
	}
		//if it wasn't captured by any of the above cases,
		//it must have been an error
	return PROBE_ERROR;
}

void
ClassAdLogProber::incrementProbeInfo() {
	// store the currently probed stat
	last_mod_time = cur_probed_mod_time;
	last_size = cur_probed_size;

	last_seq_num = cur_probed_seq_num;
	last_creation_time = cur_probed_creation_time;
}
<|endoftext|>


<commit_before>/*
* Passhash9 Password Hashing
* (C) 2010 Jack Lloyd
*
* Distributed under the terms of the Botan license
*/

#include <botan/passhash9.h>
#include <botan/loadstor.h>
#include <botan/libstate.h>
#include <botan/pbkdf2.h>
#include <botan/base64.h>
#include <botan/pipe.h>

namespace Botan {

namespace {

const std::string MAGIC_PREFIX = "$9$";

const u32bit WORKFACTOR_BYTES = 2;
const u32bit ALGID_BYTES = 1;
const u32bit SALT_BYTES = 12; // 96 bits of salt
const u32bit PBKDF_OUTPUT_LEN = 24; // 192 bits output

const u32bit WORK_FACTOR_SCALE = 10000;

MessageAuthenticationCode* get_pbkdf_prf(byte alg_id)
   {
   Algorithm_Factory& af = global_state().algorithm_factory();

   if(alg_id == 0)
      return af.make_mac("HMAC(SHA-1)");

   return 0;
   }

std::pair<byte, MessageAuthenticationCode*> choose_pbkdf_prf()
   {
   for(byte alg_id = 0; alg_id != 255; ++alg_id)
      {
      MessageAuthenticationCode* prf = get_pbkdf_prf(alg_id);
      if(prf)
         return std::make_pair(alg_id, prf);
      }

   throw Internal_Error("Passhash9: No PRF available");
   }

}

std::string generate_passhash9(const std::string& pass,
                               RandomNumberGenerator& rng,
                               u16bit work_factor)
   {
   std::pair<byte, MessageAuthenticationCode*> prf = choose_pbkdf_prf();
   byte alg_id = prf.first;

   PKCS5_PBKDF2 kdf(prf.second); // takes ownership of pointer

   SecureVector<byte> salt(SALT_BYTES);
   rng.randomize(&salt[0], salt.size());

   u32bit kdf_iterations = WORK_FACTOR_SCALE * work_factor;

   SecureVector<byte> pbkdf2_output =
      kdf.derive_key(PBKDF_OUTPUT_LEN, pass,
                     &salt[0], salt.size(),
                     kdf_iterations).bits_of();

   Pipe pipe(new Base64_Encoder);
   pipe.start_msg();
   pipe.write(alg_id);
   pipe.write(get_byte(0, work_factor));
   pipe.write(get_byte(1, work_factor));
   pipe.write(salt);
   pipe.write(pbkdf2_output);
   pipe.end_msg();

   return MAGIC_PREFIX + pipe.read_all_as_string();
   }

bool check_passhash9(const std::string& pass, const std::string& hash)
   {
   const u32bit BINARY_LENGTH =
      (ALGID_BYTES + WORKFACTOR_BYTES + PBKDF_OUTPUT_LEN + SALT_BYTES);

   const u32bit BASE64_LENGTH =
      MAGIC_PREFIX.size() + (BINARY_LENGTH * 8) / 6;

   if(hash.size() != BASE64_LENGTH)
      return false;

   for(size_t i = 0; i != MAGIC_PREFIX.size(); ++i)
      if(hash[i] != MAGIC_PREFIX[i])
         return false;

   Pipe pipe(new Base64_Decoder);
   pipe.start_msg();
   pipe.write(hash.c_str() + MAGIC_PREFIX.size());
   pipe.end_msg();

   SecureVector<byte> bin = pipe.read_all();

   if(bin.size() != BINARY_LENGTH)
      return false;

   byte alg_id = bin[0];

   u32bit kdf_iterations =
      WORK_FACTOR_SCALE * load_be<u16bit>(bin + ALGID_BYTES, 0);

   if(kdf_iterations == 0)
      return false;

   MessageAuthenticationCode* pbkdf_prf = get_pbkdf_prf(alg_id);

   if(pbkdf_prf == 0)
      return false; // unknown algorithm, reject

   PKCS5_PBKDF2 kdf(pbkdf_prf); // takes ownership of pointer

   SecureVector<byte> cmp = kdf.derive_key(
      PBKDF_OUTPUT_LEN, pass,
      &bin[ALGID_BYTES + WORKFACTOR_BYTES], SALT_BYTES,
      kdf_iterations).bits_of();

   return same_mem(cmp.begin(),
                   bin.begin() + ALGID_BYTES + WORKFACTOR_BYTES + SALT_BYTES,
                   PBKDF_OUTPUT_LEN);
   }

}
<commit_msg>In get_pbkdf_prf, catch Algorithm_Not_Found and return null<commit_after>/*
* Passhash9 Password Hashing
* (C) 2010 Jack Lloyd
*
* Distributed under the terms of the Botan license
*/

#include <botan/passhash9.h>
#include <botan/loadstor.h>
#include <botan/libstate.h>
#include <botan/pbkdf2.h>
#include <botan/base64.h>
#include <botan/pipe.h>

namespace Botan {

namespace {

const std::string MAGIC_PREFIX = "$9$";

const u32bit WORKFACTOR_BYTES = 2;
const u32bit ALGID_BYTES = 1;
const u32bit SALT_BYTES = 12; // 96 bits of salt
const u32bit PBKDF_OUTPUT_LEN = 24; // 192 bits output

const u32bit WORK_FACTOR_SCALE = 10000;

MessageAuthenticationCode* get_pbkdf_prf(byte alg_id)
   {
   Algorithm_Factory& af = global_state().algorithm_factory();

   try
      {
      if(alg_id == 0)
         return af.make_mac("HMAC(SHA-1)");

      }
   catch(Algorithm_Not_Found)
      {
      return 0;
      }

   return 0;
   }

std::pair<byte, MessageAuthenticationCode*> choose_pbkdf_prf()
   {
   for(byte alg_id = 0; alg_id != 255; ++alg_id)
      {
      MessageAuthenticationCode* prf = get_pbkdf_prf(alg_id);
      if(prf)
         return std::make_pair(alg_id, prf);
      }

   throw Internal_Error("Passhash9: No PRF available");
   }

}

std::string generate_passhash9(const std::string& pass,
                               RandomNumberGenerator& rng,
                               u16bit work_factor)
   {
   std::pair<byte, MessageAuthenticationCode*> prf = choose_pbkdf_prf();
   byte alg_id = prf.first;

   PKCS5_PBKDF2 kdf(prf.second); // takes ownership of pointer

   SecureVector<byte> salt(SALT_BYTES);
   rng.randomize(&salt[0], salt.size());

   u32bit kdf_iterations = WORK_FACTOR_SCALE * work_factor;

   SecureVector<byte> pbkdf2_output =
      kdf.derive_key(PBKDF_OUTPUT_LEN, pass,
                     &salt[0], salt.size(),
                     kdf_iterations).bits_of();

   Pipe pipe(new Base64_Encoder);
   pipe.start_msg();
   pipe.write(alg_id);
   pipe.write(get_byte(0, work_factor));
   pipe.write(get_byte(1, work_factor));
   pipe.write(salt);
   pipe.write(pbkdf2_output);
   pipe.end_msg();

   return MAGIC_PREFIX + pipe.read_all_as_string();
   }

bool check_passhash9(const std::string& pass, const std::string& hash)
   {
   const u32bit BINARY_LENGTH =
      (ALGID_BYTES + WORKFACTOR_BYTES + PBKDF_OUTPUT_LEN + SALT_BYTES);

   const u32bit BASE64_LENGTH =
      MAGIC_PREFIX.size() + (BINARY_LENGTH * 8) / 6;

   if(hash.size() != BASE64_LENGTH)
      return false;

   for(size_t i = 0; i != MAGIC_PREFIX.size(); ++i)
      if(hash[i] != MAGIC_PREFIX[i])
         return false;

   Pipe pipe(new Base64_Decoder);
   pipe.start_msg();
   pipe.write(hash.c_str() + MAGIC_PREFIX.size());
   pipe.end_msg();

   SecureVector<byte> bin = pipe.read_all();

   if(bin.size() != BINARY_LENGTH)
      return false;

   byte alg_id = bin[0];

   u32bit kdf_iterations =
      WORK_FACTOR_SCALE * load_be<u16bit>(bin + ALGID_BYTES, 0);

   if(kdf_iterations == 0)
      return false;

   MessageAuthenticationCode* pbkdf_prf = get_pbkdf_prf(alg_id);

   if(pbkdf_prf == 0)
      return false; // unknown algorithm, reject

   PKCS5_PBKDF2 kdf(pbkdf_prf); // takes ownership of pointer

   SecureVector<byte> cmp = kdf.derive_key(
      PBKDF_OUTPUT_LEN, pass,
      &bin[ALGID_BYTES + WORKFACTOR_BYTES], SALT_BYTES,
      kdf_iterations).bits_of();

   return same_mem(cmp.begin(),
                   bin.begin() + ALGID_BYTES + WORKFACTOR_BYTES + SALT_BYTES,
                   PBKDF_OUTPUT_LEN);
   }

}
<|endoftext|>


<commit_before>#include "glm/gtc/matrix_transform.hpp"

#include "pixelboost/graphics/camera/camera.h"
#include "pixelboost/graphics/camera/viewport.h"
#include "pixelboost/graphics/device/device.h"
#include "pixelboost/graphics/device/indexBuffer.h"
#include "pixelboost/graphics/device/program.h"
#include "pixelboost/graphics/device/vertexBuffer.h"
#include "pixelboost/graphics/particle/particleSystem.h"
#include "pixelboost/graphics/renderer/common/renderer.h"
#include "pixelboost/graphics/renderer/particle/particleRenderer.h"
#include "pixelboost/graphics/renderer/sprite/sprite.h"
#include "pixelboost/graphics/resources/shaderResource.h"
#include "pixelboost/graphics/shader/shader.h"
#include "pixelboost/resource/resourceManager.h"

using namespace pb;

ParticleRenderer* ParticleRenderer::_Instance = 0;

ParticleRenderable::ParticleRenderable()
    : _System(0)
{

}

ParticleRenderable::~ParticleRenderable()
{

}

Uid ParticleRenderable::GetType()
{
    return ParticleRenderable::GetStaticType();
}

Uid ParticleRenderable::GetStaticType()
{
    return TypeHash("pb::ParticleRenderable");
}

void ParticleRenderable::CalculateBounds()
{
    SetBounds(BoundingSphere());
}

void ParticleRenderable::CalculateWorldMatrix()
{
    SetWorldMatrix(glm::mat4x4());
}

Shader* ParticleRenderable::GetShader()
{
    Shader* baseShader = Renderable::GetShader();
    if (baseShader)
        return baseShader;

    return ResourceManager::Instance()->GetPool("default")->GetResource<ShaderResource>("/shaders/pb_texturedColor.shc")->GetShader();
}

void ParticleRenderable::SetSystem(ParticleSystem* system)
{
    _System = system;

    if (_System)
    {
        _System->Transform = _Transform;
    }
}

ParticleSystem* ParticleRenderable::GetSystem()
{
    return _System;
}

void ParticleRenderable::SetTransform(const glm::mat4x4& transform)
{
    _Transform = transform;

    if (_System)
    {
        _System->Transform = transform;
    }
}

ParticleRenderer::ParticleRenderer()
{
    _Instance = this;

    _MaxParticles = 10000;

    _IndexBuffer = pb::GraphicsDevice::Instance()->CreateIndexBuffer(pb::kBufferFormatStatic, _MaxParticles*6);
    _VertexBuffer = pb::GraphicsDevice::Instance()->CreateVertexBuffer(pb::kBufferFormatDynamic, pb::kVertexFormat_P3_C4_UV, _MaxParticles*4);

    _IndexBuffer->Lock();
    unsigned short* indexBuffer = _IndexBuffer->GetData();
    for (int i=0; i<_MaxParticles; i++)
    {
        indexBuffer[0] = (i*4);
        indexBuffer[1] = (i*4) + 1;
        indexBuffer[2] = (i*4) + 2;
        indexBuffer[3] = (i*4) + 0;
        indexBuffer[4] = (i*4) + 2;
        indexBuffer[5] = (i*4) + 3;

        indexBuffer += 6;
    }
    _IndexBuffer->Unlock();

    Renderer::Instance()->SetHandler(ParticleRenderable::GetStaticType(), this);
}

ParticleRenderer::~ParticleRenderer()
{
    _Instance = 0;

    pb::GraphicsDevice::Instance()->DestroyIndexBuffer(_IndexBuffer);
    pb::GraphicsDevice::Instance()->DestroyVertexBuffer(_VertexBuffer);
}

ParticleRenderer* ParticleRenderer::Instance()
{
    return _Instance;
}

void ParticleRenderer::Render(int count, Renderable** renderables, Uid renderScheme, const glm::vec4& viewport, const glm::mat4x4& projectionMatrix, const glm::mat4x4& viewMatrix)
{
    Shader* shader = renderables[0]->GetShader();
    if (!shader)
        return;

    ShaderTechnique* technique = shader->GetTechnique(renderScheme);

    if (!technique)
        return;

    ShaderPass* shaderPass = technique->GetPass(0);
    shaderPass->Bind();
    shaderPass->GetShaderProgram()->SetUniform("PB_ProjectionMatrix", projectionMatrix);

    for (int i=0; i<count; i++)
    {
        ParticleRenderable& renderable = *static_cast<ParticleRenderable*>(renderables[i]);

        shaderPass->GetShaderProgram()->SetUniform("PB_ModelViewMatrix", renderable.GetModelViewMatrix());

        RenderSystem(renderable.GetSystem(), shaderPass);
    }
}

void ParticleRenderer::RenderSystem(ParticleSystem* system, ShaderPass* shaderPass)
{
    pb::Sprite* sprite = system->Definition->RenderSprite->SpriteDefinition;

    if (!sprite)
        return;

    _VertexBuffer->Lock();

    pb::Vertex_P3_C4_UV* vertexBuffer = static_cast<pb::Vertex_P3_C4_UV*>(_VertexBuffer->GetData());

    if (vertexBuffer)
    {
        int particleCount = 0;

        for (std::vector<Particle>::iterator it = system->Particles.begin(); it != system->Particles.end(); ++it, ++particleCount)
        {
            if (particleCount == _MaxParticles)
                break;

            glm::vec4 color = it->Color;
            float scale = it->Scale;
            glm::vec2 size = sprite->Size * glm::vec2(scale, scale);

            glm::mat4x4 transform = glm::translate(glm::mat4x4(), it->Position);
            transform = glm::scale(transform, glm::vec3(size, 1));
            transform = glm::rotate(transform, it->Rotation.x, glm::vec3(1,0,0));
            transform = glm::rotate(transform, it->Rotation.y, glm::vec3(0,1,0));
            transform = glm::rotate(transform, it->Rotation.z, glm::vec3(0,0,1));

            glm::vec4 a = transform * glm::vec4(-0.5, -0.5, 0, 1);
            glm::vec4 b = transform * glm::vec4(-0.5, 0.5, 0, 1);
            glm::vec4 c = transform * glm::vec4(0.5, 0.5, 0, 1);
            glm::vec4 d = transform * glm::vec4(0.5, -0.5, 0, 1);

            vertexBuffer[0].position[0] = a.x;
            vertexBuffer[0].position[1] = a.y;
            vertexBuffer[0].position[2] = a.z;
            vertexBuffer[1].position[0] = b.x;
            vertexBuffer[1].position[1] = b.y;
            vertexBuffer[1].position[2] = b.z;
            vertexBuffer[2].position[0] = c.x;
            vertexBuffer[2].position[1] = c.y;
            vertexBuffer[2].position[2] = c.z;
            vertexBuffer[3].position[0] = d.x;
            vertexBuffer[3].position[1] = d.y;
            vertexBuffer[3].position[2] = d.z;

            vertexBuffer[0].color[0] = color.r * color.a;
            vertexBuffer[0].color[1] = color.g * color.a;
            vertexBuffer[0].color[2] = color.b * color.a;
            vertexBuffer[0].color[3] = system->Definition->BlendMode == ParticleSystemDefinition::kBlendModeAdditive ? 0 : color.a;
            vertexBuffer[1].color[0] = color.r * color.a;
            vertexBuffer[1].color[1] = color.g * color.a;
            vertexBuffer[1].color[2] = color.b * color.a;
            vertexBuffer[1].color[3] = system->Definition->BlendMode == ParticleSystemDefinition::kBlendModeAdditive ? 0 : color.a;
            vertexBuffer[2].color[0] = color.r * color.a;
            vertexBuffer[2].color[1] = color.g * color.a;
            vertexBuffer[2].color[2] = color.b * color.a;
            vertexBuffer[2].color[3] = system->Definition->BlendMode == ParticleSystemDefinition::kBlendModeAdditive ? 0 : color.a;
            vertexBuffer[3].color[0] = color.r * color.a;
            vertexBuffer[3].color[1] = color.g * color.a;
            vertexBuffer[3].color[2] = color.b * color.a;
            vertexBuffer[3].color[3] = system->Definition->BlendMode == ParticleSystemDefinition::kBlendModeAdditive ? 0 : color.a;

            if (!sprite->Rotated)
            {
                glm::vec2 min = sprite->UvPosition;
                glm::vec2 max = sprite->UvPosition + sprite->UvSize;

                vertexBuffer[0].uv[0] = min[0];
                vertexBuffer[0].uv[1] = max[1],
                vertexBuffer[1].uv[0] = min[0];
                vertexBuffer[1].uv[1] = min[1];
                vertexBuffer[2].uv[0] = max[0];
                vertexBuffer[2].uv[1] = min[1];
                vertexBuffer[3].uv[0] = max[0];
                vertexBuffer[3].uv[1] = max[1];
            } else {
                glm::vec2 min = sprite->UvPosition + glm::vec2(sprite->UvSize[1], 0);
                glm::vec2 max = sprite->UvPosition + glm::vec2(0, sprite->UvSize[0]);

                vertexBuffer[0].uv[0] = max[0];
                vertexBuffer[0].uv[1] = max[1];
                vertexBuffer[1].uv[0] = min[0];
                vertexBuffer[1].uv[1] = max[1];
                vertexBuffer[2].uv[0] = min[0];
                vertexBuffer[2].uv[1] = min[1];
                vertexBuffer[3].uv[0] = max[0];
                vertexBuffer[3].uv[1] = min[1];
            }

            vertexBuffer += 4;
        }

        GraphicsDevice::Instance()->BindTexture(0, system->Definition->RenderSprite->SpriteDefinition->_Texture);

        _VertexBuffer->Unlock(particleCount*4);

        GraphicsDevice::Instance()->BindIndexBuffer(_IndexBuffer);
        GraphicsDevice::Instance()->BindVertexBuffer(_VertexBuffer);

        GraphicsDevice::Instance()->SetState(GraphicsDevice::kStateDepthTest, false);
        GraphicsDevice::Instance()->SetState(GraphicsDevice::kStateBlend, true);

        GraphicsDevice::Instance()->SetBlendMode(GraphicsDevice::kBlendOne, GraphicsDevice::kBlendOneMinusSourceAlpha);

        shaderPass->GetShaderProgram()->SetUniform("_DiffuseTexture", 0);

        GraphicsDevice::Instance()->DrawElements(GraphicsDevice::kElementTriangles, particleCount*6);

        GraphicsDevice::Instance()->BindIndexBuffer(0);
        GraphicsDevice::Instance()->BindVertexBuffer(0);

        GraphicsDevice::Instance()->SetState(GraphicsDevice::kStateDepthTest, true);
        GraphicsDevice::Instance()->SetState(GraphicsDevice::kStateBlend, false);
    }

    for (std::vector<ParticleSystem*>::iterator it = system->SubSystem.begin(); it != system->SubSystem.end(); ++it)
    {
        RenderSystem(*it, shaderPass);
    }
}
<commit_msg>Don't issue draw calls for empty particle systems<commit_after>#include "glm/gtc/matrix_transform.hpp"

#include "pixelboost/graphics/camera/camera.h"
#include "pixelboost/graphics/camera/viewport.h"
#include "pixelboost/graphics/device/device.h"
#include "pixelboost/graphics/device/indexBuffer.h"
#include "pixelboost/graphics/device/program.h"
#include "pixelboost/graphics/device/vertexBuffer.h"
#include "pixelboost/graphics/particle/particleSystem.h"
#include "pixelboost/graphics/renderer/common/renderer.h"
#include "pixelboost/graphics/renderer/particle/particleRenderer.h"
#include "pixelboost/graphics/renderer/sprite/sprite.h"
#include "pixelboost/graphics/resources/shaderResource.h"
#include "pixelboost/graphics/shader/shader.h"
#include "pixelboost/resource/resourceManager.h"

using namespace pb;

ParticleRenderer* ParticleRenderer::_Instance = 0;

ParticleRenderable::ParticleRenderable()
    : _System(0)
{

}

ParticleRenderable::~ParticleRenderable()
{

}

Uid ParticleRenderable::GetType()
{
    return ParticleRenderable::GetStaticType();
}

Uid ParticleRenderable::GetStaticType()
{
    return TypeHash("pb::ParticleRenderable");
}

void ParticleRenderable::CalculateBounds()
{
    SetBounds(BoundingSphere());
}

void ParticleRenderable::CalculateWorldMatrix()
{
    SetWorldMatrix(glm::mat4x4());
}

Shader* ParticleRenderable::GetShader()
{
    Shader* baseShader = Renderable::GetShader();
    if (baseShader)
        return baseShader;

    return ResourceManager::Instance()->GetPool("default")->GetResource<ShaderResource>("/shaders/pb_texturedColor.shc")->GetShader();
}

void ParticleRenderable::SetSystem(ParticleSystem* system)
{
    _System = system;

    if (_System)
    {
        _System->Transform = _Transform;
    }
}

ParticleSystem* ParticleRenderable::GetSystem()
{
    return _System;
}

void ParticleRenderable::SetTransform(const glm::mat4x4& transform)
{
    _Transform = transform;

    if (_System)
    {
        _System->Transform = transform;
    }
}

ParticleRenderer::ParticleRenderer()
{
    _Instance = this;

    _MaxParticles = 10000;

    _IndexBuffer = pb::GraphicsDevice::Instance()->CreateIndexBuffer(pb::kBufferFormatStatic, _MaxParticles*6);
    _VertexBuffer = pb::GraphicsDevice::Instance()->CreateVertexBuffer(pb::kBufferFormatDynamic, pb::kVertexFormat_P3_C4_UV, _MaxParticles*4);

    _IndexBuffer->Lock();
    unsigned short* indexBuffer = _IndexBuffer->GetData();
    for (int i=0; i<_MaxParticles; i++)
    {
        indexBuffer[0] = (i*4);
        indexBuffer[1] = (i*4) + 1;
        indexBuffer[2] = (i*4) + 2;
        indexBuffer[3] = (i*4) + 0;
        indexBuffer[4] = (i*4) + 2;
        indexBuffer[5] = (i*4) + 3;

        indexBuffer += 6;
    }
    _IndexBuffer->Unlock();

    Renderer::Instance()->SetHandler(ParticleRenderable::GetStaticType(), this);
}

ParticleRenderer::~ParticleRenderer()
{
    _Instance = 0;

    pb::GraphicsDevice::Instance()->DestroyIndexBuffer(_IndexBuffer);
    pb::GraphicsDevice::Instance()->DestroyVertexBuffer(_VertexBuffer);
}

ParticleRenderer* ParticleRenderer::Instance()
{
    return _Instance;
}

void ParticleRenderer::Render(int count, Renderable** renderables, Uid renderScheme, const glm::vec4& viewport, const glm::mat4x4& projectionMatrix, const glm::mat4x4& viewMatrix)
{
    Shader* shader = renderables[0]->GetShader();
    if (!shader)
        return;

    ShaderTechnique* technique = shader->GetTechnique(renderScheme);

    if (!technique)
        return;

    ShaderPass* shaderPass = technique->GetPass(0);
    shaderPass->Bind();
    shaderPass->GetShaderProgram()->SetUniform("PB_ProjectionMatrix", projectionMatrix);

    for (int i=0; i<count; i++)
    {
        ParticleRenderable& renderable = *static_cast<ParticleRenderable*>(renderables[i]);

        shaderPass->GetShaderProgram()->SetUniform("PB_ModelViewMatrix", renderable.GetModelViewMatrix());

        RenderSystem(renderable.GetSystem(), shaderPass);
    }
}

void ParticleRenderer::RenderSystem(ParticleSystem* system, ShaderPass* shaderPass)
{
    if (system->Particles.size() == 0)
        return;

    pb::Sprite* sprite = system->Definition->RenderSprite->SpriteDefinition;

    if (!sprite)
        return;

    _VertexBuffer->Lock();

    pb::Vertex_P3_C4_UV* vertexBuffer = static_cast<pb::Vertex_P3_C4_UV*>(_VertexBuffer->GetData());

    if (vertexBuffer)
    {
        int particleCount = 0;

        for (std::vector<Particle>::iterator it = system->Particles.begin(); it != system->Particles.end(); ++it, ++particleCount)
        {
            if (particleCount == _MaxParticles)
                break;

            glm::vec4 color = it->Color;
            float scale = it->Scale;
            glm::vec2 size = sprite->Size * glm::vec2(scale, scale);

            glm::mat4x4 transform = glm::translate(glm::mat4x4(), it->Position);
            transform = glm::scale(transform, glm::vec3(size, 1));
            transform = glm::rotate(transform, it->Rotation.x, glm::vec3(1,0,0));
            transform = glm::rotate(transform, it->Rotation.y, glm::vec3(0,1,0));
            transform = glm::rotate(transform, it->Rotation.z, glm::vec3(0,0,1));

            glm::vec4 a = transform * glm::vec4(-0.5, -0.5, 0, 1);
            glm::vec4 b = transform * glm::vec4(-0.5, 0.5, 0, 1);
            glm::vec4 c = transform * glm::vec4(0.5, 0.5, 0, 1);
            glm::vec4 d = transform * glm::vec4(0.5, -0.5, 0, 1);

            vertexBuffer[0].position[0] = a.x;
            vertexBuffer[0].position[1] = a.y;
            vertexBuffer[0].position[2] = a.z;
            vertexBuffer[1].position[0] = b.x;
            vertexBuffer[1].position[1] = b.y;
            vertexBuffer[1].position[2] = b.z;
            vertexBuffer[2].position[0] = c.x;
            vertexBuffer[2].position[1] = c.y;
            vertexBuffer[2].position[2] = c.z;
            vertexBuffer[3].position[0] = d.x;
            vertexBuffer[3].position[1] = d.y;
            vertexBuffer[3].position[2] = d.z;

            vertexBuffer[0].color[0] = color.r * color.a;
            vertexBuffer[0].color[1] = color.g * color.a;
            vertexBuffer[0].color[2] = color.b * color.a;
            vertexBuffer[0].color[3] = system->Definition->BlendMode == ParticleSystemDefinition::kBlendModeAdditive ? 0 : color.a;
            vertexBuffer[1].color[0] = color.r * color.a;
            vertexBuffer[1].color[1] = color.g * color.a;
            vertexBuffer[1].color[2] = color.b * color.a;
            vertexBuffer[1].color[3] = system->Definition->BlendMode == ParticleSystemDefinition::kBlendModeAdditive ? 0 : color.a;
            vertexBuffer[2].color[0] = color.r * color.a;
            vertexBuffer[2].color[1] = color.g * color.a;
            vertexBuffer[2].color[2] = color.b * color.a;
            vertexBuffer[2].color[3] = system->Definition->BlendMode == ParticleSystemDefinition::kBlendModeAdditive ? 0 : color.a;
            vertexBuffer[3].color[0] = color.r * color.a;
            vertexBuffer[3].color[1] = color.g * color.a;
            vertexBuffer[3].color[2] = color.b * color.a;
            vertexBuffer[3].color[3] = system->Definition->BlendMode == ParticleSystemDefinition::kBlendModeAdditive ? 0 : color.a;

            if (!sprite->Rotated)
            {
                glm::vec2 min = sprite->UvPosition;
                glm::vec2 max = sprite->UvPosition + sprite->UvSize;

                vertexBuffer[0].uv[0] = min[0];
                vertexBuffer[0].uv[1] = max[1],
                vertexBuffer[1].uv[0] = min[0];
                vertexBuffer[1].uv[1] = min[1];
                vertexBuffer[2].uv[0] = max[0];
                vertexBuffer[2].uv[1] = min[1];
                vertexBuffer[3].uv[0] = max[0];
                vertexBuffer[3].uv[1] = max[1];
            } else {
                glm::vec2 min = sprite->UvPosition + glm::vec2(sprite->UvSize[1], 0);
                glm::vec2 max = sprite->UvPosition + glm::vec2(0, sprite->UvSize[0]);

                vertexBuffer[0].uv[0] = max[0];
                vertexBuffer[0].uv[1] = max[1];
                vertexBuffer[1].uv[0] = min[0];
                vertexBuffer[1].uv[1] = max[1];
                vertexBuffer[2].uv[0] = min[0];
                vertexBuffer[2].uv[1] = min[1];
                vertexBuffer[3].uv[0] = max[0];
                vertexBuffer[3].uv[1] = min[1];
            }

            vertexBuffer += 4;
        }

        GraphicsDevice::Instance()->BindTexture(0, system->Definition->RenderSprite->SpriteDefinition->_Texture);

        _VertexBuffer->Unlock(particleCount*4);

        GraphicsDevice::Instance()->BindIndexBuffer(_IndexBuffer);
        GraphicsDevice::Instance()->BindVertexBuffer(_VertexBuffer);

        GraphicsDevice::Instance()->SetState(GraphicsDevice::kStateDepthTest, false);
        GraphicsDevice::Instance()->SetState(GraphicsDevice::kStateBlend, true);

        GraphicsDevice::Instance()->SetBlendMode(GraphicsDevice::kBlendOne, GraphicsDevice::kBlendOneMinusSourceAlpha);

        shaderPass->GetShaderProgram()->SetUniform("_DiffuseTexture", 0);

        GraphicsDevice::Instance()->DrawElements(GraphicsDevice::kElementTriangles, particleCount*6);

        GraphicsDevice::Instance()->BindIndexBuffer(0);
        GraphicsDevice::Instance()->BindVertexBuffer(0);

        GraphicsDevice::Instance()->SetState(GraphicsDevice::kStateDepthTest, true);
        GraphicsDevice::Instance()->SetState(GraphicsDevice::kStateBlend, false);
    }

    for (std::vector<ParticleSystem*>::iterator it = system->SubSystem.begin(); it != system->SubSystem.end(); ++it)
    {
        RenderSystem(*it, shaderPass);
    }
}
<|endoftext|>


<commit_before>/**
 * @file
 * @brief Keeping track of the global geometry of independent detectors
 * @copyright Copyright (c) 2017 CERN and the Allpix Squared authors.
 * This software is distributed under the terms of the MIT License, copied verbatim in the file "LICENSE.md".
 * In applying this license, CERN does not waive the privileges and immunities granted to it by virtue of its status as an
 * Intergovernmental Organization or submit itself to any jurisdiction.
 */

#ifndef ALLPIX_GEOMETRY_MANAGER_H
#define ALLPIX_GEOMETRY_MANAGER_H

#include <memory>
#include <random>
#include <set>
#include <string>
#include <vector>

#include <Math/Vector3D.h>

#include "Detector.hpp"
#include "DetectorModel.hpp"
#include "core/config/ConfigManager.hpp"
#include "core/config/ConfigReader.hpp"

namespace allpix {

    /**
     * @brief Type of the magnetic field
     */
    enum class MagneticFieldType {
        NONE = 0, ///< No magnetic field is simulated
        CONSTANT, ///< Constant magnetic field (mostly for testing)
        CUSTOM,   ///< Custom magnetic field function
    };

    using MagneticFieldFunction = std::function<ROOT::Math::XYZVector(const ROOT::Math::XYZPoint&)>;

    /**
     * @ingroup Managers
     * @brief Manager responsible for the global geometry
     *
     * The framework defines the geometry as a set of independent instances of a \ref Detector "detector". Each independent
     * detector has a \ref DetectorModel "detector model". Detector and models can be added before the manager closes. The
     * manager closes as soon as \ref GeometryManager::getDetectors() or a similar method is called. Afterwards the geometry
     * is constant and cannot be changed anymore.
     */
    class GeometryManager {
    public:
        /**
         * @brief Construct the geometry manager
         */
        GeometryManager();
        /**
         * @brief Use default destructor
         */
        ~GeometryManager() = default;

        /// @{
        /**
         * @brief Copying the manager is not allowed
         */
        GeometryManager(const GeometryManager&) = delete;
        GeometryManager& operator=(const GeometryManager&) = delete;
        /// @}

        /// @{
        /**
         * @brief Disallow move because of atomic boolean
         */
        GeometryManager(GeometryManager&&) = delete;
        GeometryManager& operator=(GeometryManager&&) = delete;
        /// @}

        /**
         * @brief Loads the geometry from the global configuration
         * @param global_config Configuration manager of the framework
         * @param seeder PRNG to use for generating random misalignments
         * @warning Has to be the first function called after the constructor
         */
        void load(ConfigManager* conf_manager, std::mt19937_64& seeder);

        /**
         * @brief Returns the list of standard paths where models should be searched in
         * @return List of absolute paths to file or directories that contain models
         */
        std::vector<std::string> getModelsPath();

        /**
         * @brief Return the minimum coordinate of all detectors in the geometry
         * @return Minimum coordinate in global frame
         * @note Closes the geometry if it has not been closed yet
         */
        ROOT::Math::XYZPoint getMinimumCoordinate();
        /**
         * @brief Return the maximum coordinate of all detectors in the geometry
         * @return Maximum coordinate in global frame
         * @note Closes the geometry if it has not been closed yet
         */
        ROOT::Math::XYZPoint getMaximumCoordinate();

        /**
         * @brief Add a point to the geometry (used for the \ref GeometryManager::getMinimumCoordinate "minimum"
         *        and \ref GeometryManager::getMaximumCoordinate "maximum" coordinate)
         * @param point Point that should be included in the geometry
         * @warning Can only be used as long as the geometry is still open
         */
        // TODO: Add more details to the point and interaction with external geometry
        void addPoint(ROOT::Math::XYZPoint point);

        /**
         * @brief Return if the model is currently in the list of required models
         * @param name Type of the model to search for
         * @return True if at least one model still needs this type, false otherwise
         */
        bool needsModel(const std::string& name) const;

        /**
         * @brief Add a detector model and apply it to the registered detectors
         * @param model Pointer to the detector model
         * @warning Can only be used as long as the geometry is still open
         */
        void addModel(std::shared_ptr<DetectorModel> model);

        /**
         * @brief Check if a detector model exists
         * @param name Model type to search for
         * @return True if the model is part of the geometry, false otherwise
         */
        bool hasModel(const std::string& name) const;

        /**
         * @brief Get all added detector models
         * @returns List of all models
         * @warning The models returned might not be used in the geometry
         */
        std::vector<std::shared_ptr<DetectorModel>> getModels() const;

        /**
         * @brief Get a detector model by its name
         * @param name Name of the model to search for
         * @returns Return the model if it exists (an error is raised if it does not)
         * @warning The method \ref GeometryManager::hasModel should be used to check for existence
         */
        std::shared_ptr<DetectorModel> getModel(const std::string& name) const;

        /**
         * @brief Add a detector to the global geometry
         * @param detector Pointer to the detector to add to the geometry
         * @warning Can only be used as long as the geometry is still open
         */
        void addDetector(std::shared_ptr<Detector> detector);

        /**
         * @brief Check if a detector exists
         * @param name Model type to search for
         * @return True if the detector is part of the geometry, false otherwise
         */
        bool hasDetector(const std::string& name) const;

        /**
         * @brief Get all detectors in the geometry
         * @returns List of all detectors
         * @note Closes the geometry if it not has been closed yet
         */
        std::vector<std::shared_ptr<Detector>> getDetectors();

        /**
         * @brief Get a detector by its name
         * @param name Name of the detector to search for
         * @returns Return the detector if it exists (an error is raised if it does not)
         * @warning The method \ref GeometryManager::hasDetector should be used to check for existence
         * @note Closes the geometry if it has not been closed yet
         */
        std::shared_ptr<Detector> getDetector(const std::string& name);

        /**
         * @brief Get all detectors in the geometry of a particular model type
         * @param type Type of the detector model to search for
         * @returns List of all detectors of a particular type (an error is raised if none exist)
         * @warning This method should not be used to check if an instantiation of a model exists
         * @note Closes the geometry if it has not been closed yet
         */
        std::vector<std::shared_ptr<Detector>> getDetectorsByType(const std::string& type);

        /**
     * @brief Set the magnetic field in the volume
     * @param function Function used to retrieve the magnetic field
     * @param type Type of the magnetic field function used
     */
        void setMagneticFieldFunction(MagneticFieldFunction function, MagneticFieldType type = MagneticFieldType::CUSTOM);

        /**
         * @brief Returns if a magnetic field is present
         * @return True if the a magnetic field is present in the volume, false otherwise
         */
        bool hasMagneticField() const;
        /**
         * @brief Get the magnetic field at a global position
         * @param pos Position in the global frame
         * @return Vector of the field at the queried point
         */
        ROOT::Math::XYZVector getMagneticField(const ROOT::Math::XYZPoint& position) const;

        MagneticFieldType getMagneticFieldType() const;

    private:
        /**
         * @brief Load all standard framework models (automatically done when the geometry is closed)
         */
        void load_models();

        /**
         * @brief Parse a configuration object and instantiate the corresponding model
         * @param name Name of the model
         * @param reader Reader with the configuration for this model
         * @return Detector model instantiated from the configuration
         */
        std::shared_ptr<DetectorModel> parse_config(const std::string& name, const ConfigReader&);

        /**
         * @brief Close the geometry after which changes to the detector geometry cannot be made anymore
         */
        void close_geometry();
        std::atomic_bool closed_;

        std::vector<ROOT::Math::XYZPoint> points_;

        std::vector<std::string> model_paths_;
        std::vector<std::shared_ptr<DetectorModel>> models_;
        std::set<std::string> model_names_;

        std::map<std::string, std::vector<std::pair<Configuration, Detector*>>> nonresolved_models_;
        std::vector<std::shared_ptr<Detector>> detectors_;
        std::set<std::string> detector_names_;

        MagneticFieldType magnetic_field_type_{MagneticFieldType::NONE};
        MagneticFieldFunction magnetic_field_function_;
    };
} // namespace allpix

#endif /* ALLPIX_GEOMETRY_MANAGER_H */
<commit_msg>Add formatting fix from clang-format-6.0<commit_after>/**
 * @file
 * @brief Keeping track of the global geometry of independent detectors
 * @copyright Copyright (c) 2017 CERN and the Allpix Squared authors.
 * This software is distributed under the terms of the MIT License, copied verbatim in the file "LICENSE.md".
 * In applying this license, CERN does not waive the privileges and immunities granted to it by virtue of its status as an
 * Intergovernmental Organization or submit itself to any jurisdiction.
 */

#ifndef ALLPIX_GEOMETRY_MANAGER_H
#define ALLPIX_GEOMETRY_MANAGER_H

#include <memory>
#include <random>
#include <set>
#include <string>
#include <vector>

#include <Math/Vector3D.h>

#include "Detector.hpp"
#include "DetectorModel.hpp"
#include "core/config/ConfigManager.hpp"
#include "core/config/ConfigReader.hpp"

namespace allpix {

    /**
     * @brief Type of the magnetic field
     */
    enum class MagneticFieldType {
        NONE = 0, ///< No magnetic field is simulated
        CONSTANT, ///< Constant magnetic field (mostly for testing)
        CUSTOM,   ///< Custom magnetic field function
    };

    using MagneticFieldFunction = std::function<ROOT::Math::XYZVector(const ROOT::Math::XYZPoint&)>;

    /**
     * @ingroup Managers
     * @brief Manager responsible for the global geometry
     *
     * The framework defines the geometry as a set of independent instances of a \ref Detector "detector". Each independent
     * detector has a \ref DetectorModel "detector model". Detector and models can be added before the manager closes. The
     * manager closes as soon as \ref GeometryManager::getDetectors() or a similar method is called. Afterwards the geometry
     * is constant and cannot be changed anymore.
     */
    class GeometryManager {
    public:
        /**
         * @brief Construct the geometry manager
         */
        GeometryManager();
        /**
         * @brief Use default destructor
         */
        ~GeometryManager() = default;

        /// @{
        /**
         * @brief Copying the manager is not allowed
         */
        GeometryManager(const GeometryManager&) = delete;
        GeometryManager& operator=(const GeometryManager&) = delete;
        /// @}

        /// @{
        /**
         * @brief Disallow move because of atomic boolean
         */
        GeometryManager(GeometryManager&&) = delete;
        GeometryManager& operator=(GeometryManager&&) = delete;
        /// @}

        /**
         * @brief Loads the geometry from the global configuration
         * @param global_config Configuration manager of the framework
         * @param seeder PRNG to use for generating random misalignments
         * @warning Has to be the first function called after the constructor
         */
        void load(ConfigManager* conf_manager, std::mt19937_64& seeder);

        /**
         * @brief Returns the list of standard paths where models should be searched in
         * @return List of absolute paths to file or directories that contain models
         */
        std::vector<std::string> getModelsPath();

        /**
         * @brief Return the minimum coordinate of all detectors in the geometry
         * @return Minimum coordinate in global frame
         * @note Closes the geometry if it has not been closed yet
         */
        ROOT::Math::XYZPoint getMinimumCoordinate();
        /**
         * @brief Return the maximum coordinate of all detectors in the geometry
         * @return Maximum coordinate in global frame
         * @note Closes the geometry if it has not been closed yet
         */
        ROOT::Math::XYZPoint getMaximumCoordinate();

        /**
         * @brief Add a point to the geometry (used for the \ref GeometryManager::getMinimumCoordinate "minimum"
         *        and \ref GeometryManager::getMaximumCoordinate "maximum" coordinate)
         * @param point Point that should be included in the geometry
         * @warning Can only be used as long as the geometry is still open
         */
        // TODO: Add more details to the point and interaction with external geometry
        void addPoint(ROOT::Math::XYZPoint point);

        /**
         * @brief Return if the model is currently in the list of required models
         * @param name Type of the model to search for
         * @return True if at least one model still needs this type, false otherwise
         */
        bool needsModel(const std::string& name) const;

        /**
         * @brief Add a detector model and apply it to the registered detectors
         * @param model Pointer to the detector model
         * @warning Can only be used as long as the geometry is still open
         */
        void addModel(std::shared_ptr<DetectorModel> model);

        /**
         * @brief Check if a detector model exists
         * @param name Model type to search for
         * @return True if the model is part of the geometry, false otherwise
         */
        bool hasModel(const std::string& name) const;

        /**
         * @brief Get all added detector models
         * @returns List of all models
         * @warning The models returned might not be used in the geometry
         */
        std::vector<std::shared_ptr<DetectorModel>> getModels() const;

        /**
         * @brief Get a detector model by its name
         * @param name Name of the model to search for
         * @returns Return the model if it exists (an error is raised if it does not)
         * @warning The method \ref GeometryManager::hasModel should be used to check for existence
         */
        std::shared_ptr<DetectorModel> getModel(const std::string& name) const;

        /**
         * @brief Add a detector to the global geometry
         * @param detector Pointer to the detector to add to the geometry
         * @warning Can only be used as long as the geometry is still open
         */
        void addDetector(std::shared_ptr<Detector> detector);

        /**
         * @brief Check if a detector exists
         * @param name Model type to search for
         * @return True if the detector is part of the geometry, false otherwise
         */
        bool hasDetector(const std::string& name) const;

        /**
         * @brief Get all detectors in the geometry
         * @returns List of all detectors
         * @note Closes the geometry if it not has been closed yet
         */
        std::vector<std::shared_ptr<Detector>> getDetectors();

        /**
         * @brief Get a detector by its name
         * @param name Name of the detector to search for
         * @returns Return the detector if it exists (an error is raised if it does not)
         * @warning The method \ref GeometryManager::hasDetector should be used to check for existence
         * @note Closes the geometry if it has not been closed yet
         */
        std::shared_ptr<Detector> getDetector(const std::string& name);

        /**
         * @brief Get all detectors in the geometry of a particular model type
         * @param type Type of the detector model to search for
         * @returns List of all detectors of a particular type (an error is raised if none exist)
         * @warning This method should not be used to check if an instantiation of a model exists
         * @note Closes the geometry if it has not been closed yet
         */
        std::vector<std::shared_ptr<Detector>> getDetectorsByType(const std::string& type);

        /**
         * @brief Set the magnetic field in the volume
         * @param function Function used to retrieve the magnetic field
         * @param type Type of the magnetic field function used
         */
        void setMagneticFieldFunction(MagneticFieldFunction function, MagneticFieldType type = MagneticFieldType::CUSTOM);

        /**
         * @brief Returns if a magnetic field is present
         * @return True if the a magnetic field is present in the volume, false otherwise
         */
        bool hasMagneticField() const;
        /**
         * @brief Get the magnetic field at a global position
         * @param pos Position in the global frame
         * @return Vector of the field at the queried point
         */
        ROOT::Math::XYZVector getMagneticField(const ROOT::Math::XYZPoint& position) const;

        MagneticFieldType getMagneticFieldType() const;

    private:
        /**
         * @brief Load all standard framework models (automatically done when the geometry is closed)
         */
        void load_models();

        /**
         * @brief Parse a configuration object and instantiate the corresponding model
         * @param name Name of the model
         * @param reader Reader with the configuration for this model
         * @return Detector model instantiated from the configuration
         */
        std::shared_ptr<DetectorModel> parse_config(const std::string& name, const ConfigReader&);

        /**
         * @brief Close the geometry after which changes to the detector geometry cannot be made anymore
         */
        void close_geometry();
        std::atomic_bool closed_;

        std::vector<ROOT::Math::XYZPoint> points_;

        std::vector<std::string> model_paths_;
        std::vector<std::shared_ptr<DetectorModel>> models_;
        std::set<std::string> model_names_;

        std::map<std::string, std::vector<std::pair<Configuration, Detector*>>> nonresolved_models_;
        std::vector<std::shared_ptr<Detector>> detectors_;
        std::set<std::string> detector_names_;

        MagneticFieldType magnetic_field_type_{MagneticFieldType::NONE};
        MagneticFieldFunction magnetic_field_function_;
    };
} // namespace allpix

#endif /* ALLPIX_GEOMETRY_MANAGER_H */
<|endoftext|>


<commit_before>/*
 *
 * Copyright 2015 gRPC authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

#include <grpc/support/port_platform.h>

#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
#include "src/core/lib/channel/channel_stack.h"
#include "src/core/lib/gpr/alloc.h"

#include <stdlib.h>
#include <string.h>

grpc_core::TraceFlag grpc_trace_channel(false, "channel");

/* Memory layouts.

   Channel stack is laid out as: {
     grpc_channel_stack stk;
     padding to GPR_MAX_ALIGNMENT
     grpc_channel_element[stk.count];
     per-filter memory, aligned to GPR_MAX_ALIGNMENT
   }

   Call stack is laid out as: {
     grpc_call_stack stk;
     padding to GPR_MAX_ALIGNMENT
     grpc_call_element[stk.count];
     per-filter memory, aligned to GPR_MAX_ALIGNMENT
   } */

size_t grpc_channel_stack_size(const grpc_channel_filter** filters,
                               size_t filter_count) {
  /* always need the header, and size for the channel elements */
  size_t size = GPR_ROUND_UP_TO_ALIGNMENT_SIZE(sizeof(grpc_channel_stack)) +
                GPR_ROUND_UP_TO_ALIGNMENT_SIZE(filter_count *
                                               sizeof(grpc_channel_element));
  size_t i;

  GPR_ASSERT((GPR_MAX_ALIGNMENT & (GPR_MAX_ALIGNMENT - 1)) == 0 &&
             "GPR_MAX_ALIGNMENT must be a power of two");

  /* add the size for each filter */
  for (i = 0; i < filter_count; i++) {
    size += GPR_ROUND_UP_TO_ALIGNMENT_SIZE(filters[i]->sizeof_channel_data);
  }

  return size;
}

#define CHANNEL_ELEMS_FROM_STACK(stk)                                     \
  ((grpc_channel_element*)((char*)(stk) + GPR_ROUND_UP_TO_ALIGNMENT_SIZE( \
                                              sizeof(grpc_channel_stack))))

#define CALL_ELEMS_FROM_STACK(stk)                                     \
  ((grpc_call_element*)((char*)(stk) + GPR_ROUND_UP_TO_ALIGNMENT_SIZE( \
                                           sizeof(grpc_call_stack))))

grpc_channel_element* grpc_channel_stack_element(
    grpc_channel_stack* channel_stack, size_t index) {
  return CHANNEL_ELEMS_FROM_STACK(channel_stack) + index;
}

grpc_channel_element* grpc_channel_stack_last_element(
    grpc_channel_stack* channel_stack) {
  return grpc_channel_stack_element(channel_stack, channel_stack->count - 1);
}

grpc_call_element* grpc_call_stack_element(grpc_call_stack* call_stack,
                                           size_t index) {
  return CALL_ELEMS_FROM_STACK(call_stack) + index;
}

grpc_error* grpc_channel_stack_init(
    int initial_refs, grpc_iomgr_cb_func destroy, void* destroy_arg,
    const grpc_channel_filter** filters, size_t filter_count,
    const grpc_channel_args* channel_args, grpc_transport* optional_transport,
    const char* name, grpc_channel_stack* stack) {
  size_t call_size =
      GPR_ROUND_UP_TO_ALIGNMENT_SIZE(sizeof(grpc_call_stack)) +
      GPR_ROUND_UP_TO_ALIGNMENT_SIZE(filter_count * sizeof(grpc_call_element));
  grpc_channel_element* elems;
  grpc_channel_element_args args;
  char* user_data;
  size_t i;

  stack->count = filter_count;
  GRPC_STREAM_REF_INIT(&stack->refcount, initial_refs, destroy, destroy_arg,
                       name);
  elems = CHANNEL_ELEMS_FROM_STACK(stack);
  user_data = (reinterpret_cast<char*>(elems)) +
              GPR_ROUND_UP_TO_ALIGNMENT_SIZE(filter_count *
                                             sizeof(grpc_channel_element));

  /* init per-filter data */
  grpc_error* first_error = GRPC_ERROR_NONE;
  for (i = 0; i < filter_count; i++) {
    args.channel_stack = stack;
    args.channel_args = channel_args;
    args.optional_transport = optional_transport;
    args.is_first = i == 0;
    args.is_last = i == (filter_count - 1);
    elems[i].filter = filters[i];
    elems[i].channel_data = user_data;
    grpc_error* error = elems[i].filter->init_channel_elem(&elems[i], &args);
    if (error != GRPC_ERROR_NONE) {
      if (first_error == GRPC_ERROR_NONE) {
        first_error = error;
      } else {
        GRPC_ERROR_UNREF(error);
      }
    }
    user_data +=
        GPR_ROUND_UP_TO_ALIGNMENT_SIZE(filters[i]->sizeof_channel_data);
    call_size += GPR_ROUND_UP_TO_ALIGNMENT_SIZE(filters[i]->sizeof_call_data);
  }

  GPR_ASSERT(user_data > (char*)stack);
  GPR_ASSERT((uintptr_t)(user_data - (char*)stack) ==
             grpc_channel_stack_size(filters, filter_count));

  stack->call_stack_size = call_size;
  return first_error;
}

void grpc_channel_stack_destroy(grpc_channel_stack* stack) {
  grpc_channel_element* channel_elems = CHANNEL_ELEMS_FROM_STACK(stack);
  size_t count = stack->count;
  size_t i;

  /* destroy per-filter data */
  for (i = 0; i < count; i++) {
    channel_elems[i].filter->destroy_channel_elem(&channel_elems[i]);
  }
}

grpc_error* grpc_call_stack_init(grpc_channel_stack* channel_stack,
                                 int initial_refs, grpc_iomgr_cb_func destroy,
                                 void* destroy_arg,
                                 const grpc_call_element_args* elem_args) {
  grpc_channel_element* channel_elems = CHANNEL_ELEMS_FROM_STACK(channel_stack);
  size_t count = channel_stack->count;
  grpc_call_element* call_elems;
  char* user_data;
  size_t i;

  elem_args->call_stack->count = count;
  GRPC_STREAM_REF_INIT(&elem_args->call_stack->refcount, initial_refs, destroy,
                       destroy_arg, "CALL_STACK");
  call_elems = CALL_ELEMS_FROM_STACK(elem_args->call_stack);
  user_data = (reinterpret_cast<char*>(call_elems)) +
              GPR_ROUND_UP_TO_ALIGNMENT_SIZE(count * sizeof(grpc_call_element));

  /* init per-filter data */
  grpc_error* first_error = GRPC_ERROR_NONE;
  for (i = 0; i < count; i++) {
    call_elems[i].filter = channel_elems[i].filter;
    call_elems[i].channel_data = channel_elems[i].channel_data;
    call_elems[i].call_data = user_data;
    grpc_error* error =
        call_elems[i].filter->init_call_elem(&call_elems[i], elem_args);
    if (error != GRPC_ERROR_NONE) {
      if (first_error == GRPC_ERROR_NONE) {
        first_error = error;
      } else {
        GRPC_ERROR_UNREF(error);
      }
    }
    user_data +=
        GPR_ROUND_UP_TO_ALIGNMENT_SIZE(call_elems[i].filter->sizeof_call_data);
  }
  return first_error;
}

void grpc_call_stack_set_pollset_or_pollset_set(grpc_call_stack* call_stack,
                                                grpc_polling_entity* pollent) {
  size_t count = call_stack->count;
  grpc_call_element* call_elems;
  size_t i;

  call_elems = CALL_ELEMS_FROM_STACK(call_stack);

  /* init per-filter data */
  for (i = 0; i < count; i++) {
    call_elems[i].filter->set_pollset_or_pollset_set(&call_elems[i], pollent);
  }
}

void grpc_call_stack_ignore_set_pollset_or_pollset_set(
    grpc_call_element* elem, grpc_polling_entity* pollent) {}

void grpc_call_stack_destroy(grpc_call_stack* stack,
                             const grpc_call_final_info* final_info,
                             grpc_closure* then_schedule_closure) {
  grpc_call_element* elems = CALL_ELEMS_FROM_STACK(stack);
  size_t count = stack->count;
  size_t i;

  /* destroy per-filter data */
  for (i = 0; i < count; i++) {
    elems[i].filter->destroy_call_elem(
        &elems[i], final_info,
        i == count - 1 ? then_schedule_closure : nullptr);
  }
}

void grpc_call_next_op(grpc_call_element* elem,
                       grpc_transport_stream_op_batch* op) {
  grpc_call_element* next_elem = elem + 1;
  GRPC_CALL_LOG_OP(GPR_INFO, next_elem, op);
  next_elem->filter->start_transport_stream_op_batch(next_elem, op);
}

void grpc_channel_next_get_info(grpc_channel_element* elem,
                                const grpc_channel_info* channel_info) {
  grpc_channel_element* next_elem = elem + 1;
  next_elem->filter->get_channel_info(next_elem, channel_info);
}

void grpc_channel_next_op(grpc_channel_element* elem, grpc_transport_op* op) {
  grpc_channel_element* next_elem = elem + 1;
  next_elem->filter->start_transport_op(next_elem, op);
}

grpc_channel_stack* grpc_channel_stack_from_top_element(
    grpc_channel_element* elem) {
  return reinterpret_cast<grpc_channel_stack*>(
      reinterpret_cast<char*>(elem) -
      GPR_ROUND_UP_TO_ALIGNMENT_SIZE(sizeof(grpc_channel_stack)));
}

grpc_call_stack* grpc_call_stack_from_top_element(grpc_call_element* elem) {
  return reinterpret_cast<grpc_call_stack*>(
      reinterpret_cast<char*>(elem) -
      GPR_ROUND_UP_TO_ALIGNMENT_SIZE(sizeof(grpc_call_stack)));
}
<commit_msg>Optimize `grpc_call_stack_init` for cache coherency.<commit_after>/*
 *
 * Copyright 2015 gRPC authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

#include <grpc/support/port_platform.h>

#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
#include "src/core/lib/channel/channel_stack.h"
#include "src/core/lib/gpr/alloc.h"

#include <stdlib.h>
#include <string.h>

grpc_core::TraceFlag grpc_trace_channel(false, "channel");

/* Memory layouts.

   Channel stack is laid out as: {
     grpc_channel_stack stk;
     padding to GPR_MAX_ALIGNMENT
     grpc_channel_element[stk.count];
     per-filter memory, aligned to GPR_MAX_ALIGNMENT
   }

   Call stack is laid out as: {
     grpc_call_stack stk;
     padding to GPR_MAX_ALIGNMENT
     grpc_call_element[stk.count];
     per-filter memory, aligned to GPR_MAX_ALIGNMENT
   } */

size_t grpc_channel_stack_size(const grpc_channel_filter** filters,
                               size_t filter_count) {
  /* always need the header, and size for the channel elements */
  size_t size = GPR_ROUND_UP_TO_ALIGNMENT_SIZE(sizeof(grpc_channel_stack)) +
                GPR_ROUND_UP_TO_ALIGNMENT_SIZE(filter_count *
                                               sizeof(grpc_channel_element));
  size_t i;

  GPR_ASSERT((GPR_MAX_ALIGNMENT & (GPR_MAX_ALIGNMENT - 1)) == 0 &&
             "GPR_MAX_ALIGNMENT must be a power of two");

  /* add the size for each filter */
  for (i = 0; i < filter_count; i++) {
    size += GPR_ROUND_UP_TO_ALIGNMENT_SIZE(filters[i]->sizeof_channel_data);
  }

  return size;
}

#define CHANNEL_ELEMS_FROM_STACK(stk)                                     \
  ((grpc_channel_element*)((char*)(stk) + GPR_ROUND_UP_TO_ALIGNMENT_SIZE( \
                                              sizeof(grpc_channel_stack))))

#define CALL_ELEMS_FROM_STACK(stk)                                     \
  ((grpc_call_element*)((char*)(stk) + GPR_ROUND_UP_TO_ALIGNMENT_SIZE( \
                                           sizeof(grpc_call_stack))))

grpc_channel_element* grpc_channel_stack_element(
    grpc_channel_stack* channel_stack, size_t index) {
  return CHANNEL_ELEMS_FROM_STACK(channel_stack) + index;
}

grpc_channel_element* grpc_channel_stack_last_element(
    grpc_channel_stack* channel_stack) {
  return grpc_channel_stack_element(channel_stack, channel_stack->count - 1);
}

grpc_call_element* grpc_call_stack_element(grpc_call_stack* call_stack,
                                           size_t index) {
  return CALL_ELEMS_FROM_STACK(call_stack) + index;
}

grpc_error* grpc_channel_stack_init(
    int initial_refs, grpc_iomgr_cb_func destroy, void* destroy_arg,
    const grpc_channel_filter** filters, size_t filter_count,
    const grpc_channel_args* channel_args, grpc_transport* optional_transport,
    const char* name, grpc_channel_stack* stack) {
  size_t call_size =
      GPR_ROUND_UP_TO_ALIGNMENT_SIZE(sizeof(grpc_call_stack)) +
      GPR_ROUND_UP_TO_ALIGNMENT_SIZE(filter_count * sizeof(grpc_call_element));
  grpc_channel_element* elems;
  grpc_channel_element_args args;
  char* user_data;
  size_t i;

  stack->count = filter_count;
  GRPC_STREAM_REF_INIT(&stack->refcount, initial_refs, destroy, destroy_arg,
                       name);
  elems = CHANNEL_ELEMS_FROM_STACK(stack);
  user_data = (reinterpret_cast<char*>(elems)) +
              GPR_ROUND_UP_TO_ALIGNMENT_SIZE(filter_count *
                                             sizeof(grpc_channel_element));

  /* init per-filter data */
  grpc_error* first_error = GRPC_ERROR_NONE;
  for (i = 0; i < filter_count; i++) {
    args.channel_stack = stack;
    args.channel_args = channel_args;
    args.optional_transport = optional_transport;
    args.is_first = i == 0;
    args.is_last = i == (filter_count - 1);
    elems[i].filter = filters[i];
    elems[i].channel_data = user_data;
    grpc_error* error = elems[i].filter->init_channel_elem(&elems[i], &args);
    if (error != GRPC_ERROR_NONE) {
      if (first_error == GRPC_ERROR_NONE) {
        first_error = error;
      } else {
        GRPC_ERROR_UNREF(error);
      }
    }
    user_data +=
        GPR_ROUND_UP_TO_ALIGNMENT_SIZE(filters[i]->sizeof_channel_data);
    call_size += GPR_ROUND_UP_TO_ALIGNMENT_SIZE(filters[i]->sizeof_call_data);
  }

  GPR_ASSERT(user_data > (char*)stack);
  GPR_ASSERT((uintptr_t)(user_data - (char*)stack) ==
             grpc_channel_stack_size(filters, filter_count));

  stack->call_stack_size = call_size;
  return first_error;
}

void grpc_channel_stack_destroy(grpc_channel_stack* stack) {
  grpc_channel_element* channel_elems = CHANNEL_ELEMS_FROM_STACK(stack);
  size_t count = stack->count;
  size_t i;

  /* destroy per-filter data */
  for (i = 0; i < count; i++) {
    channel_elems[i].filter->destroy_channel_elem(&channel_elems[i]);
  }
}

grpc_error* grpc_call_stack_init(grpc_channel_stack* channel_stack,
                                 int initial_refs, grpc_iomgr_cb_func destroy,
                                 void* destroy_arg,
                                 const grpc_call_element_args* elem_args) {
  grpc_channel_element* channel_elems = CHANNEL_ELEMS_FROM_STACK(channel_stack);
  size_t count = channel_stack->count;
  grpc_call_element* call_elems;
  char* user_data;

  elem_args->call_stack->count = count;
  GRPC_STREAM_REF_INIT(&elem_args->call_stack->refcount, initial_refs, destroy,
                       destroy_arg, "CALL_STACK");
  call_elems = CALL_ELEMS_FROM_STACK(elem_args->call_stack);
  user_data = (reinterpret_cast<char*>(call_elems)) +
              GPR_ROUND_UP_TO_ALIGNMENT_SIZE(count * sizeof(grpc_call_element));

  /* init per-filter data */
  grpc_error* first_error = GRPC_ERROR_NONE;
  for (size_t i = 0; i < count; i++) {
    call_elems[i].filter = channel_elems[i].filter;
    call_elems[i].channel_data = channel_elems[i].channel_data;
    call_elems[i].call_data = user_data;
    user_data +=
        GPR_ROUND_UP_TO_ALIGNMENT_SIZE(call_elems[i].filter->sizeof_call_data);
  }
  for (size_t i = 0; i < count; i++) {
    grpc_error* error =
        call_elems[i].filter->init_call_elem(&call_elems[i], elem_args);
    if (error != GRPC_ERROR_NONE) {
      if (first_error == GRPC_ERROR_NONE) {
        first_error = error;
      } else {
        GRPC_ERROR_UNREF(error);
      }
    }
  }
  return first_error;
}

void grpc_call_stack_set_pollset_or_pollset_set(grpc_call_stack* call_stack,
                                                grpc_polling_entity* pollent) {
  size_t count = call_stack->count;
  grpc_call_element* call_elems;
  size_t i;

  call_elems = CALL_ELEMS_FROM_STACK(call_stack);

  /* init per-filter data */
  for (i = 0; i < count; i++) {
    call_elems[i].filter->set_pollset_or_pollset_set(&call_elems[i], pollent);
  }
}

void grpc_call_stack_ignore_set_pollset_or_pollset_set(
    grpc_call_element* elem, grpc_polling_entity* pollent) {}

void grpc_call_stack_destroy(grpc_call_stack* stack,
                             const grpc_call_final_info* final_info,
                             grpc_closure* then_schedule_closure) {
  grpc_call_element* elems = CALL_ELEMS_FROM_STACK(stack);
  size_t count = stack->count;
  size_t i;

  /* destroy per-filter data */
  for (i = 0; i < count; i++) {
    elems[i].filter->destroy_call_elem(
        &elems[i], final_info,
        i == count - 1 ? then_schedule_closure : nullptr);
  }
}

void grpc_call_next_op(grpc_call_element* elem,
                       grpc_transport_stream_op_batch* op) {
  grpc_call_element* next_elem = elem + 1;
  GRPC_CALL_LOG_OP(GPR_INFO, next_elem, op);
  next_elem->filter->start_transport_stream_op_batch(next_elem, op);
}

void grpc_channel_next_get_info(grpc_channel_element* elem,
                                const grpc_channel_info* channel_info) {
  grpc_channel_element* next_elem = elem + 1;
  next_elem->filter->get_channel_info(next_elem, channel_info);
}

void grpc_channel_next_op(grpc_channel_element* elem, grpc_transport_op* op) {
  grpc_channel_element* next_elem = elem + 1;
  next_elem->filter->start_transport_op(next_elem, op);
}

grpc_channel_stack* grpc_channel_stack_from_top_element(
    grpc_channel_element* elem) {
  return reinterpret_cast<grpc_channel_stack*>(
      reinterpret_cast<char*>(elem) -
      GPR_ROUND_UP_TO_ALIGNMENT_SIZE(sizeof(grpc_channel_stack)));
}

grpc_call_stack* grpc_call_stack_from_top_element(grpc_call_element* elem) {
  return reinterpret_cast<grpc_call_stack*>(
      reinterpret_cast<char*>(elem) -
      GPR_ROUND_UP_TO_ALIGNMENT_SIZE(sizeof(grpc_call_stack)));
}
<|endoftext|>


<commit_before>#include "itkCommandLineArgumentParser.h"
#include "CommandLineArgumentHelper.h"

#include "mainhelper.h"
#include <itksys/SystemTools.hxx>

#include "Erosion.h"
#include "Dilation.h"
#include "Opening.h"
#include "Closing.h"

//-------------------------------------------------------------------------------------

int main( int argc, char *argv[] )
{
  /** Check arguments for help. */
  if ( argc < 5 )
  {
    PrintHelp();
    return 1;
  }

  /** Create a command line argument parser. */
  itk::CommandLineArgumentParser::Pointer parser = itk::CommandLineArgumentParser::New();
  parser->SetCommandLineArguments( argc, argv );

  /** Get arguments. */
  std::string inputFileName = "";
  bool retin = parser->GetCommandLineArgument( "-in", inputFileName );

  std::string operation = "";
  bool retop = parser->GetCommandLineArgument( "-op", operation );
  operation = itksys::SystemTools::UnCapitalizedWords( operation );

  std::string type = "Grayscale";
  bool rettype = parser->GetCommandLineArgument( "-type", type );
  type = itksys::SystemTools::UnCapitalizedWords( type );

  std::string boundaryCondition = "";
  bool retbc = parser->GetCommandLineArgument( "-bc", boundaryCondition );

  std::vector<unsigned int> radius;
  bool retr = parser->GetCommandLineArgument( "-r", radius );

  std::string outputFileName =
    itksys::SystemTools::GetFilenameWithoutLastExtension( inputFileName );
  std::string ext =
    itksys::SystemTools::GetFilenameLastExtension( inputFileName );
  outputFileName += "_" + operation + "_" + type + ext;
  bool retout = parser->GetCommandLineArgument( "-out", outputFileName );

  std::vector<std::string> bin;
  bool retbin = parser->GetCommandLineArgument( "-bin", bin );

  /** Check if the required arguments are given. */
  if ( !retin )
  {
    std::cerr << "ERROR: You should specify \"-in\"." << std::endl;
    return 1;
  }
  if ( !retop )
  {
    std::cerr << "ERROR: You should specify \"-op\"." << std::endl;
    return 1;
  }
  if ( !retr )
  {
    std::cerr << "ERROR: You should specify \"-r\"." << std::endl;
    return 1;
  }

  /** Check for valid input options. */
  if ( operation != "erosion"
    && operation != "dilation"
    && operation != "opening"
    && operation != "closing" )
  {
    std::cerr << "ERROR: \"-op\" should be one of {erosion, dilation, opening, closing}." << std::endl;
    return 1;
  }
  if ( type != "grayscale"
    && type != "binary" )
  {
    std::cerr << "ERROR: \"-type\" should be one of {grayscale, binary}." << std::endl;
    return 1;
  }
  if ( retbin && bin.size() != 3 )
  {
    std::cerr << "ERROR: \"-bin\" should contain three value: foreground, background, erosion." << std::endl;
    return 1;
  }

  /** Determine image properties. */
  std::string ComponentType = "short";
  std::string PixelType; //we don't use this
  unsigned int Dimension = 3;
  unsigned int NumberOfComponents = 1;
  std::vector<unsigned int> imagesize( Dimension, 0 );
  int retgip = GetImageProperties(
    inputFileName,
    PixelType,
    ComponentType,
    Dimension,
    NumberOfComponents,
    imagesize );
  if ( retgip !=0 )
  {
    return 1;
  }

  /** Let the user overrule this */
  bool retopct = parser->GetCommandLineArgument( "-opct", ComponentType );

  if ( NumberOfComponents > 1 )
  {
    std::cerr << "ERROR: The NumberOfComponents is larger than 1!" << std::endl;
    std::cerr << "Vector images are not supported!" << std::endl;
    return 1;
  }

  /** Get rid of the possible "_" in ComponentType. */
  ReplaceUnderscoreWithSpace( ComponentType );

  /** Check radius. */
  if ( retr )
  {
    if ( radius.size() != Dimension && radius.size() != 1 )
    {
      std::cout << "ERROR: The number of radii should be 1 or Dimension." << std::endl;
      return 1;
    }
  }

  /** Get the radius. */
  std::vector<unsigned int> Radius( Dimension, radius[ 0 ] );
  if ( retr && radius.size() == Dimension )
  {
    for ( unsigned int i = 1; i < Dimension; i++ )
    {
      Radius[ i ] = radius[ i ];
      if ( Radius[ i ] < 1 )
      {
        std::cout << "ERROR: No nonpositive numbers are allowed in radius." << std::endl;
        return 1;
      }
    }
  }

  /** Run the program. */
  bool supported = false;
  try
  {
    /** Erosion. */
    run( erosion, unsigned char, 2 );
    run( erosion, char, 2 );
    run( erosion, unsigned short, 2 );
    run( erosion, short, 2 );

    run( erosion, unsigned char, 3 );
    run( erosion, char, 3 );
    run( erosion, unsigned short, 3 );
    run( erosion, short, 3 );

    /** Dilation. */
    run( dilation, unsigned char, 2 );
    run( dilation, char, 2 );
    run( dilation, unsigned short, 2 );
    run( dilation, short, 2 );

    run( dilation, unsigned char, 3 );
    run( dilation, char, 3 );
    run( dilation, unsigned short, 3 );
    run( dilation, short, 3 );

    /** Opening. */
    run( opening, unsigned char, 2 );
    run( opening, char, 2 );
    run( opening, unsigned short, 2 );
    run( opening, short, 2 );

    run( opening, unsigned char, 3 );
    run( opening, char, 3 );
    run( opening, unsigned short, 3 );
    run( opening, short, 3 );

    /** Closing. */
    run( closing, unsigned char, 2 );
    run( closing, char, 2 );
    run( closing, unsigned short, 2 );
    run( closing, short, 2 );

    run( closing, unsigned char, 3 );
    run( closing, char, 3 );
    run( closing, unsigned short, 3 );
    run( closing, short, 3 );
  }
  catch( itk::ExceptionObject & e )
  {
    std::cerr << "Caught ITK exception: " << e << std::endl;
    return 1;
  }

  /** Check if this image type was supported. */
  if ( !supported )
  {
    std::cerr << "ERROR: this combination of pixel type and dimension is not supported!" << std::endl;
    std::cerr
      << "pixel (component) type = " << ComponentType
      << " ; dimension = " << Dimension
      << std::endl;
    return 1;
  }

  /** End program. */
  return 0;

} // end main
<commit_msg><commit_after>#include "itkCommandLineArgumentParser.h"
#include "CommandLineArgumentHelper.h"

#include "mainhelper.h"
#include <itksys/SystemTools.hxx>

#include "erosion.h"
#include "dilation.h"
#include "opening.h"
#include "closing.h"

//-------------------------------------------------------------------------------------

int main( int argc, char *argv[] )
{
  /** Check arguments for help. */
  if ( argc < 5 )
  {
    PrintHelp();
    return 1;
  }

  /** Create a command line argument parser. */
  itk::CommandLineArgumentParser::Pointer parser = itk::CommandLineArgumentParser::New();
  parser->SetCommandLineArguments( argc, argv );

  /** Get arguments. */
  std::string inputFileName = "";
  bool retin = parser->GetCommandLineArgument( "-in", inputFileName );

  std::string operation = "";
  bool retop = parser->GetCommandLineArgument( "-op", operation );
  operation = itksys::SystemTools::UnCapitalizedWords( operation );

  std::string type = "Grayscale";
  bool rettype = parser->GetCommandLineArgument( "-type", type );
  type = itksys::SystemTools::UnCapitalizedWords( type );

  std::string boundaryCondition = "";
  bool retbc = parser->GetCommandLineArgument( "-bc", boundaryCondition );

  std::vector<unsigned int> radius;
  bool retr = parser->GetCommandLineArgument( "-r", radius );

  std::string outputFileName =
    itksys::SystemTools::GetFilenameWithoutLastExtension( inputFileName );
  std::string ext =
    itksys::SystemTools::GetFilenameLastExtension( inputFileName );
  outputFileName += "_" + operation + "_" + type + ext;
  bool retout = parser->GetCommandLineArgument( "-out", outputFileName );

  std::vector<std::string> bin;
  bool retbin = parser->GetCommandLineArgument( "-bin", bin );

  /** Check if the required arguments are given. */
  if ( !retin )
  {
    std::cerr << "ERROR: You should specify \"-in\"." << std::endl;
    return 1;
  }
  if ( !retop )
  {
    std::cerr << "ERROR: You should specify \"-op\"." << std::endl;
    return 1;
  }
  if ( !retr )
  {
    std::cerr << "ERROR: You should specify \"-r\"." << std::endl;
    return 1;
  }

  /** Check for valid input options. */
  if ( operation != "erosion"
    && operation != "dilation"
    && operation != "opening"
    && operation != "closing" )
  {
    std::cerr << "ERROR: \"-op\" should be one of {erosion, dilation, opening, closing}." << std::endl;
    return 1;
  }
  if ( type != "grayscale"
    && type != "binary" )
  {
    std::cerr << "ERROR: \"-type\" should be one of {grayscale, binary}." << std::endl;
    return 1;
  }
  if ( retbin && bin.size() != 3 )
  {
    std::cerr << "ERROR: \"-bin\" should contain three value: foreground, background, erosion." << std::endl;
    return 1;
  }

  /** Determine image properties. */
  std::string ComponentType = "short";
  std::string PixelType; //we don't use this
  unsigned int Dimension = 3;
  unsigned int NumberOfComponents = 1;
  std::vector<unsigned int> imagesize( Dimension, 0 );
  int retgip = GetImageProperties(
    inputFileName,
    PixelType,
    ComponentType,
    Dimension,
    NumberOfComponents,
    imagesize );
  if ( retgip !=0 )
  {
    return 1;
  }

  /** Let the user overrule this */
  bool retopct = parser->GetCommandLineArgument( "-opct", ComponentType );

  if ( NumberOfComponents > 1 )
  {
    std::cerr << "ERROR: The NumberOfComponents is larger than 1!" << std::endl;
    std::cerr << "Vector images are not supported!" << std::endl;
    return 1;
  }

  /** Get rid of the possible "_" in ComponentType. */
  ReplaceUnderscoreWithSpace( ComponentType );

  /** Check radius. */
  if ( retr )
  {
    if ( radius.size() != Dimension && radius.size() != 1 )
    {
      std::cout << "ERROR: The number of radii should be 1 or Dimension." << std::endl;
      return 1;
    }
  }

  /** Get the radius. */
  std::vector<unsigned int> Radius( Dimension, radius[ 0 ] );
  if ( retr && radius.size() == Dimension )
  {
    for ( unsigned int i = 1; i < Dimension; i++ )
    {
      Radius[ i ] = radius[ i ];
      if ( Radius[ i ] < 1 )
      {
        std::cout << "ERROR: No nonpositive numbers are allowed in radius." << std::endl;
        return 1;
      }
    }
  }

  /** Run the program. */
  bool supported = false;
  try
  {
    /** Erosion. */
    run( erosion, unsigned char, 2 );
    run( erosion, char, 2 );
    run( erosion, unsigned short, 2 );
    run( erosion, short, 2 );

    run( erosion, unsigned char, 3 );
    run( erosion, char, 3 );
    run( erosion, unsigned short, 3 );
    run( erosion, short, 3 );

    /** Dilation. */
    run( dilation, unsigned char, 2 );
    run( dilation, char, 2 );
    run( dilation, unsigned short, 2 );
    run( dilation, short, 2 );

    run( dilation, unsigned char, 3 );
    run( dilation, char, 3 );
    run( dilation, unsigned short, 3 );
    run( dilation, short, 3 );

    /** Opening. */
    run( opening, unsigned char, 2 );
    run( opening, char, 2 );
    run( opening, unsigned short, 2 );
    run( opening, short, 2 );

    run( opening, unsigned char, 3 );
    run( opening, char, 3 );
    run( opening, unsigned short, 3 );
    run( opening, short, 3 );

    /** Closing. */
    run( closing, unsigned char, 2 );
    run( closing, char, 2 );
    run( closing, unsigned short, 2 );
    run( closing, short, 2 );

    run( closing, unsigned char, 3 );
    run( closing, char, 3 );
    run( closing, unsigned short, 3 );
    run( closing, short, 3 );
  }
  catch( itk::ExceptionObject & e )
  {
    std::cerr << "Caught ITK exception: " << e << std::endl;
    return 1;
  }

  /** Check if this image type was supported. */
  if ( !supported )
  {
    std::cerr << "ERROR: this combination of pixel type and dimension is not supported!" << std::endl;
    std::cerr
      << "pixel (component) type = " << ComponentType
      << " ; dimension = " << Dimension
      << std::endl;
    return 1;
  }

  /** End program. */
  return 0;

} // end main
<|endoftext|>


<commit_before><commit_msg>Core: ProcessorNetwork bugfix<commit_after><|endoftext|>