<commit_before>//----------------------------  data_out.cc  ---------------------------
//    $Id$
//    Version: $Name$
//
//    Copyright (C) 1998, 1999, 2000 by the deal.II authors
//
//    This file is subject to QPL and may not be  distributed
//    without copyright and license information. Please refer
//    to the file deal.II/doc/license.html for the  text  and
//    further information on this license.
//
//----------------------------  data_out.cc  ---------------------------

#include <base/quadrature_lib.h>
#include <lac/vector.h>
#include <numerics/data_out.h>
#include <grid/tria.h>
#include <dofs/dof_handler.h>
#include <dofs/dof_accessor.h>
#include <grid/tria_iterator.h>
#include <fe/fe.h>
#include <fe/fe_values.h>

#ifdef DEAL_II_USE_MT
#include <base/thread_management.h>
#endif

#include <strstream>

template <int dim>
DataOut_DoFData<dim>::DataEntry::DataEntry (const Vector<double> *data,
					    const vector<string> &names) :
		data(data),
		names(names)
{};

template <int dim>
DataOut_DoFData<dim>::DataOut_DoFData () :
		dofs(0)
{};

template <int dim>
DataOut_DoFData<dim>::~DataOut_DoFData ()
{
  clear ();
};

template <int dim>
void DataOut_DoFData<dim>::attach_dof_handler (const DoFHandler<dim> &d)
{
  Assert (dof_data.size() == 0, ExcOldDataStillPresent());
  Assert (cell_data.size() == 0, ExcOldDataStillPresent());

  if (dofs != 0)
    dofs->unsubscribe ();

  dofs = &d;
  if (dofs != 0)
    dofs->subscribe ();
};

template <int dim>
void DataOut_DoFData<dim>::add_data_vector (const Vector<double> &vec,
					    const vector<string> &names)
{
  Assert (dofs != 0, ExcNoDoFHandlerSelected ());

				   // check for allowed sizes of
				   // vectors
  Assert ((vec.size() == dofs->get_tria().n_active_cells()) ||
	  (vec.size() == dofs->n_dofs()),
	  ExcInvalidVectorSize(vec.size(), dofs->get_tria().n_active_cells(), dofs->n_dofs()));

				   // either cell data and one name,
				   // or dof data and n_components names
  if (vec.size() == dofs->get_tria().n_active_cells())
    Assert (names.size() == 1,
	    ExcInvalidNumberOfNames (names.size(), 1));
  if (vec.size() == dofs->n_dofs())
    Assert (names.size() == dofs->get_fe().n_components(),
	    ExcInvalidNumberOfNames (names.size(), dofs->get_fe().n_components()));
  for (unsigned int i=0; i<names.size(); ++i)
    Assert (names[i].find_first_not_of("abcdefghijklmnopqrstuvwxyz"
				       "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
				       "0123456789_<>()") == string::npos,
	    ExcInvalidCharacter (names[i]));

  DataEntry new_entry (&vec, names);
  if (vec.size() == dofs->n_dofs())
    dof_data.push_back (new_entry);
  else
    if (vec.size() == dofs->get_tria().n_active_cells())
      cell_data.push_back (new_entry);
    else
      Assert (false,
	      ExcInvalidVectorSize (vec.size(),
				    dofs->n_dofs(),
				    dofs->get_tria().n_active_cells()));
};

template <int dim>
void DataOut_DoFData<dim>::add_data_vector (const Vector<double> &vec,
					    const string         &name)
{
  unsigned int n_components = dofs->get_fe().n_components ();

  vector<string> names;
				   // if only one component or vector
				   // is cell vector: we only need one
				   // name
  if ((n_components == 1) ||
      (vec.size() == dofs->get_tria().n_active_cells()))
    {
      names.resize (1, name);
    }
  else
				     // otherwise append _i to the
				     // given name
    {
      names.resize (n_components);
      for (unsigned int i=0; i<n_components; ++i)
	{
	  ostrstream namebuf;
	  namebuf << name << '_' << i << ends;
  	  names[i] = namebuf.str();
  	};
    };

  add_data_vector (vec, names);
}

template <int dim>
void DataOut_DoFData<dim>::clear_data_vectors ()
{
  dof_data.erase (dof_data.begin(), dof_data.end());
  cell_data.erase (cell_data.begin(), cell_data.end());

				   // delete patches
  vector<DataOutBase::Patch<dim> > dummy;
  patches.swap (dummy);
}

template <int dim>
void DataOut_DoFData<dim>::clear ()
{
  dof_data.erase (dof_data.begin(), dof_data.end());
  cell_data.erase (cell_data.begin(), cell_data.end());

  if (dofs != 0)
    {
      dofs->unsubscribe ();
      dofs = 0;
    };

				   // delete patches
  vector<DataOutBase::Patch<dim> > dummy;
  patches.swap (dummy);
}

template <int dim>
vector<string> DataOut_DoFData<dim>::get_dataset_names () const
{
  vector<string> names;
				   // collect the names of dof
				   // and cell data
  for (typename vector<DataEntry>::const_iterator d=dof_data.begin();
       d!=dof_data.end(); ++d)
    for (unsigned int i=0; i<d->names.size(); ++i)
      names.push_back (d->names[i]);
  for (typename vector<DataEntry>::const_iterator d=cell_data.begin();
       d!=cell_data.end(); ++d)
    {
      Assert (d->names.size() == 1, ExcInternalError());
      names.push_back (d->names[0]);
    };

  return names;
};

template <int dim>
const vector<typename DataOutBase::Patch<dim> > &
DataOut_DoFData<dim>::get_patches () const
{
  return patches;
};

template <int dim>
void DataOut<dim>::build_some_patches (Data data)
{
  QTrapez<1>     q_trapez;
  QIterated<dim> patch_points (q_trapez, data.n_subdivisions);

  FEValues<dim> fe_patch_values(dofs->get_fe(),
				patch_points,
				update_values);

  const unsigned int n_q_points = patch_points.n_quadrature_points;

  unsigned int cell_number = 0;
  typename vector<DataOutBase::Patch<dim> >::iterator patch = patches.begin();
  DoFHandler<dim>::cell_iterator cell=first_cell();

				   // get first cell in this thread
  for (unsigned int i=0; (i<data.this_thread)&&(cell != dofs->end()); ++i)
    {
      ++patch;
      ++cell_number;
      cell=next_cell(cell);
    }

  				   // now loop over all cells and
				   // actually create the patches
  for (;cell != dofs->end();)
    {
      Assert (patch != patches.end(), ExcInternalError());

      for (unsigned int vertex=0; vertex<GeometryInfo<dim>::vertices_per_cell; ++vertex)
	patch->vertices[vertex] = cell->vertex(vertex);

      if (data.n_datasets > 0)
	{
	  fe_patch_values.reinit (cell);

					   // first fill dof_data
	  for (unsigned int dataset=0; dataset<dof_data.size(); ++dataset)
	    {
	      if (data.n_components == 1)
		{
		  fe_patch_values.get_function_values (*dof_data[dataset].data,
						       data.patch_values);
		  for (unsigned int q=0; q<n_q_points; ++q)
		    patch->data(dataset,q) = data.patch_values[q];
		}
	      else
						 // system of components
		{
		  fe_patch_values.get_function_values (*dof_data[dataset].data,
						       data.patch_values_system);
		  for (unsigned int component=0; component<data.n_components;
		       ++component)
		    for (unsigned int q=0; q<n_q_points; ++q)
		      patch->data(dataset*data.n_components+component,q) =
			data.patch_values_system[q](component);
		};
	    };

					   // then do the cell data
	  for (unsigned int dataset=0; dataset<cell_data.size(); ++dataset)
	    {
	      const double value = (*cell_data[dataset].data)(cell_number);
	      for (unsigned int q=0; q<n_q_points; ++q)
		patch->data(dataset+dof_data.size()*data.n_components,q) =
		  value;
	    };
	};
      				       // next cell (patch) in this thread
      for (unsigned int i=0;
	   (i<data.n_threads)&&(cell != dofs->end()); ++i)
	{
	  ++patch;
	  ++cell_number;
	  cell=next_cell(cell);
	}
    };
}

template <int dim>
void DataOut<dim>::build_patches (const unsigned int n_subdivisions,
				  const unsigned int n_threads_)
{
  Assert (dofs != 0, typename DataOut_DoFData<dim>::ExcNoDoFHandlerSelected());

#ifdef DEAL_II_USE_MT
  const unsigned int n_threads = n_threads_;
#else
				   // access this variable to avoid
				   // compiler warning about unused
				   // var:
  (void)n_threads_;
  const unsigned int n_threads = 1;
#endif

				   // before we start the loop:
				   // create a quadrature rule that
				   // actually has the points on this
				   // patch
  QTrapez<1>     q_trapez;
  QIterated<dim> patch_points (q_trapez, n_subdivisions);

  const unsigned int n_q_points     = patch_points.n_quadrature_points;
  const unsigned int n_components   = dofs->get_fe().n_components();
  const unsigned int n_datasets     = dof_data.size() * n_components +
				      cell_data.size();

				   // clear the patches array
  if (true)
    {
      vector<DataOutBase::Patch<dim> > dummy;
      patches.swap (dummy);
    };

				   // first count the cells we want to
				   // create patches of and make sure
				   // there is enough memory for that
  unsigned int n_patches = 0;
  for (DoFHandler<dim>::cell_iterator cell=first_cell();
       cell != dofs->end();
       cell = next_cell(cell))
    ++n_patches;

  vector<Data> thread_data(n_threads);

				   // init data for the threads
  for (unsigned int i=0;i<n_threads;++i)
    {
      thread_data[i].n_threads      = n_threads;
      thread_data[i].this_thread    = i;
      thread_data[i].n_components   = n_components;
      thread_data[i].n_datasets     = n_datasets;
      thread_data[i].n_subdivisions = n_subdivisions;
      thread_data[i].patch_values.resize (n_q_points);
      thread_data[i].patch_values_system.resize (n_q_points);

      for (unsigned int k=0; k<n_q_points; ++k)
	thread_data[i].patch_values_system[k].reinit(n_components);
    }

				   // create the patches with
				   // default values
  DataOutBase::Patch<dim>  default_patch;
  default_patch.n_subdivisions = n_subdivisions;
  default_patch.data.reinit (n_datasets, n_q_points);
  patches.insert (patches.end(), n_patches, default_patch);

#ifdef DEAL_II_USE_MT

  Threads::ThreadManager thread_manager;
  for (unsigned int l=0;l<n_threads;++l)
    Threads::spawn (thread_manager,
		    Threads::encapsulate (&DataOut<dim>::build_some_patches)
		    .collect_args (this, thread_data[l]));
  thread_manager.wait();

				   // just one thread
#else
  build_some_patches(thread_data[0]);
#endif
};

template <int dim>
typename DoFHandler<dim>::cell_iterator
DataOut<dim>::first_cell ()
{
  return dofs->begin_active ();
};

template <int dim>
typename DoFHandler<dim>::cell_iterator
DataOut<dim>::next_cell (const typename DoFHandler<dim>::cell_iterator &cell)
{
				   // convert the iterator to an
				   // active_iterator and advance
				   // this to the next active cell
  typename DoFHandler<dim>::active_cell_iterator active_cell = cell;
  ++active_cell;
  return active_cell;
};

// explicit instantiations
template class DataOut_DoFData<deal_II_dimension>;
template class DataOut<deal_II_dimension>;

<commit_msg>Fix bug: forgot that we can't delete the names and units of data.<commit_after>//----------------------------  data_out.cc  ---------------------------
//    $Id$
//    Version: $Name$
//
//    Copyright (C) 1998, 1999, 2000 by the deal.II authors
//
//    This file is subject to QPL and may not be  distributed
//    without copyright and license information. Please refer
//    to the file deal.II/doc/license.html for the  text  and
//    further information on this license.
//
//----------------------------  data_out.cc  ---------------------------

#include <base/quadrature_lib.h>
#include <lac/vector.h>
#include <numerics/data_out.h>
#include <grid/tria.h>
#include <dofs/dof_handler.h>
#include <dofs/dof_accessor.h>
#include <grid/tria_iterator.h>
#include <fe/fe.h>
#include <fe/fe_values.h>

#ifdef DEAL_II_USE_MT
#include <base/thread_management.h>
#endif

#include <strstream>

template <int dim>
DataOut_DoFData<dim>::DataEntry::DataEntry (const Vector<double> *data,
					    const vector<string> &names) :
		data(data),
		names(names)
{};

template <int dim>
DataOut_DoFData<dim>::DataOut_DoFData () :
		dofs(0)
{};

template <int dim>
DataOut_DoFData<dim>::~DataOut_DoFData ()
{
  clear ();
};

template <int dim>
void DataOut_DoFData<dim>::attach_dof_handler (const DoFHandler<dim> &d)
{
  Assert (dof_data.size() == 0, ExcOldDataStillPresent());
  Assert (cell_data.size() == 0, ExcOldDataStillPresent());

  if (dofs != 0)
    dofs->unsubscribe ();

  dofs = &d;
  if (dofs != 0)
    dofs->subscribe ();
};

template <int dim>
void DataOut_DoFData<dim>::add_data_vector (const Vector<double> &vec,
					    const vector<string> &names)
{
  Assert (dofs != 0, ExcNoDoFHandlerSelected ());

				   // check for allowed sizes of
				   // vectors
  Assert ((vec.size() == dofs->get_tria().n_active_cells()) ||
	  (vec.size() == dofs->n_dofs()),
	  ExcInvalidVectorSize(vec.size(), dofs->get_tria().n_active_cells(), dofs->n_dofs()));

				   // either cell data and one name,
				   // or dof data and n_components names
  if (vec.size() == dofs->get_tria().n_active_cells())
    Assert (names.size() == 1,
	    ExcInvalidNumberOfNames (names.size(), 1));
  if (vec.size() == dofs->n_dofs())
    Assert (names.size() == dofs->get_fe().n_components(),
	    ExcInvalidNumberOfNames (names.size(), dofs->get_fe().n_components()));
  for (unsigned int i=0; i<names.size(); ++i)
    Assert (names[i].find_first_not_of("abcdefghijklmnopqrstuvwxyz"
				       "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
				       "0123456789_<>()") == string::npos,
	    ExcInvalidCharacter (names[i]));

  DataEntry new_entry (&vec, names);
  if (vec.size() == dofs->n_dofs())
    dof_data.push_back (new_entry);
  else
    if (vec.size() == dofs->get_tria().n_active_cells())
      cell_data.push_back (new_entry);
    else
      Assert (false,
	      ExcInvalidVectorSize (vec.size(),
				    dofs->n_dofs(),
				    dofs->get_tria().n_active_cells()));
};

template <int dim>
void DataOut_DoFData<dim>::add_data_vector (const Vector<double> &vec,
					    const string         &name)
{
  unsigned int n_components = dofs->get_fe().n_components ();

  vector<string> names;
				   // if only one component or vector
				   // is cell vector: we only need one
				   // name
  if ((n_components == 1) ||
      (vec.size() == dofs->get_tria().n_active_cells()))
    {
      names.resize (1, name);
    }
  else
				     // otherwise append _i to the
				     // given name
    {
      names.resize (n_components);
      for (unsigned int i=0; i<n_components; ++i)
	{
	  ostrstream namebuf;
	  namebuf << name << '_' << i << ends;
  	  names[i] = namebuf.str();
  	};
    };

  add_data_vector (vec, names);
}

template <int dim>
void DataOut_DoFData<dim>::clear_data_vectors ()
{
  dof_data.erase (dof_data.begin(), dof_data.end());
  cell_data.erase (cell_data.begin(), cell_data.end());

				   // delete patches
  vector<DataOutBase::Patch<dim> > dummy;
  patches.swap (dummy);
}

template <int dim>
void DataOut_DoFData<dim>::clear_input_data_references ()
{
  for (unsigned int i=0; i<dof_data.size(); ++i)
    dof_data[i].data = 0;

  for (unsigned int i=0; i<cell_data.size(); ++i)
    cell_data[i].data = 0;

  if (dofs != 0)
    {
      dofs->unsubscribe ();
      dofs = 0;
    };
};

template <int dim>
void DataOut_DoFData<dim>::clear ()
{
  dof_data.erase (dof_data.begin(), dof_data.end());
  cell_data.erase (cell_data.begin(), cell_data.end());

  if (dofs != 0)
    {
      dofs->unsubscribe ();
      dofs = 0;
    };

				   // delete patches
  vector<DataOutBase::Patch<dim> > dummy;
  patches.swap (dummy);
}

template <int dim>
vector<string> DataOut_DoFData<dim>::get_dataset_names () const
{
  vector<string> names;
				   // collect the names of dof
				   // and cell data
  for (typename vector<DataEntry>::const_iterator d=dof_data.begin();
       d!=dof_data.end(); ++d)
    for (unsigned int i=0; i<d->names.size(); ++i)
      names.push_back (d->names[i]);
  for (typename vector<DataEntry>::const_iterator d=cell_data.begin();
       d!=cell_data.end(); ++d)
    {
      Assert (d->names.size() == 1, ExcInternalError());
      names.push_back (d->names[0]);
    };

  return names;
};

template <int dim>
const vector<typename DataOutBase::Patch<dim> > &
DataOut_DoFData<dim>::get_patches () const
{
  return patches;
};

template <int dim>
void DataOut<dim>::build_some_patches (Data data)
{
  QTrapez<1>     q_trapez;
  QIterated<dim> patch_points (q_trapez, data.n_subdivisions);

  FEValues<dim> fe_patch_values(dofs->get_fe(),
				patch_points,
				update_values);

  const unsigned int n_q_points = patch_points.n_quadrature_points;

  unsigned int cell_number = 0;
  typename vector<DataOutBase::Patch<dim> >::iterator patch = patches.begin();
  DoFHandler<dim>::cell_iterator cell=first_cell();

				   // get first cell in this thread
  for (unsigned int i=0; (i<data.this_thread)&&(cell != dofs->end()); ++i)
    {
      ++patch;
      ++cell_number;
      cell=next_cell(cell);
    }

  				   // now loop over all cells and
				   // actually create the patches
  for (;cell != dofs->end();)
    {
      Assert (patch != patches.end(), ExcInternalError());

      for (unsigned int vertex=0; vertex<GeometryInfo<dim>::vertices_per_cell; ++vertex)
	patch->vertices[vertex] = cell->vertex(vertex);

      if (data.n_datasets > 0)
	{
	  fe_patch_values.reinit (cell);

					   // first fill dof_data
	  for (unsigned int dataset=0; dataset<dof_data.size(); ++dataset)
	    {
	      if (data.n_components == 1)
		{
		  fe_patch_values.get_function_values (*dof_data[dataset].data,
						       data.patch_values);
		  for (unsigned int q=0; q<n_q_points; ++q)
		    patch->data(dataset,q) = data.patch_values[q];
		}
	      else
						 // system of components
		{
		  fe_patch_values.get_function_values (*dof_data[dataset].data,
						       data.patch_values_system);
		  for (unsigned int component=0; component<data.n_components;
		       ++component)
		    for (unsigned int q=0; q<n_q_points; ++q)
		      patch->data(dataset*data.n_components+component,q) =
			data.patch_values_system[q](component);
		};
	    };

					   // then do the cell data
	  for (unsigned int dataset=0; dataset<cell_data.size(); ++dataset)
	    {
	      const double value = (*cell_data[dataset].data)(cell_number);
	      for (unsigned int q=0; q<n_q_points; ++q)
		patch->data(dataset+dof_data.size()*data.n_components,q) =
		  value;
	    };
	};
      				       // next cell (patch) in this thread
      for (unsigned int i=0;
	   (i<data.n_threads)&&(cell != dofs->end()); ++i)
	{
	  ++patch;
	  ++cell_number;
	  cell=next_cell(cell);
	}
    };
}

template <int dim>
void DataOut<dim>::build_patches (const unsigned int n_subdivisions,
				  const unsigned int n_threads_)
{
  Assert (dofs != 0, typename DataOut_DoFData<dim>::ExcNoDoFHandlerSelected());

#ifdef DEAL_II_USE_MT
  const unsigned int n_threads = n_threads_;
#else
				   // access this variable to avoid
				   // compiler warning about unused
				   // var:
  (void)n_threads_;
  const unsigned int n_threads = 1;
#endif

				   // before we start the loop:
				   // create a quadrature rule that
				   // actually has the points on this
				   // patch
  QTrapez<1>     q_trapez;
  QIterated<dim> patch_points (q_trapez, n_subdivisions);

  const unsigned int n_q_points     = patch_points.n_quadrature_points;
  const unsigned int n_components   = dofs->get_fe().n_components();
  const unsigned int n_datasets     = dof_data.size() * n_components +
				      cell_data.size();

				   // clear the patches array
  if (true)
    {
      vector<DataOutBase::Patch<dim> > dummy;
      patches.swap (dummy);
    };

				   // first count the cells we want to
				   // create patches of and make sure
				   // there is enough memory for that
  unsigned int n_patches = 0;
  for (DoFHandler<dim>::cell_iterator cell=first_cell();
       cell != dofs->end();
       cell = next_cell(cell))
    ++n_patches;

  vector<Data> thread_data(n_threads);

				   // init data for the threads
  for (unsigned int i=0;i<n_threads;++i)
    {
      thread_data[i].n_threads      = n_threads;
      thread_data[i].this_thread    = i;
      thread_data[i].n_components   = n_components;
      thread_data[i].n_datasets     = n_datasets;
      thread_data[i].n_subdivisions = n_subdivisions;
      thread_data[i].patch_values.resize (n_q_points);
      thread_data[i].patch_values_system.resize (n_q_points);

      for (unsigned int k=0; k<n_q_points; ++k)
	thread_data[i].patch_values_system[k].reinit(n_components);
    }

				   // create the patches with
				   // default values
  DataOutBase::Patch<dim>  default_patch;
  default_patch.n_subdivisions = n_subdivisions;
  default_patch.data.reinit (n_datasets, n_q_points);
  patches.insert (patches.end(), n_patches, default_patch);

#ifdef DEAL_II_USE_MT

  Threads::ThreadManager thread_manager;
  for (unsigned int l=0;l<n_threads;++l)
    Threads::spawn (thread_manager,
		    Threads::encapsulate (&DataOut<dim>::build_some_patches)
		    .collect_args (this, thread_data[l]));
  thread_manager.wait();

				   // just one thread
#else
  build_some_patches(thread_data[0]);
#endif
};

template <int dim>
typename DoFHandler<dim>::cell_iterator
DataOut<dim>::first_cell ()
{
  return dofs->begin_active ();
};

template <int dim>
typename DoFHandler<dim>::cell_iterator
DataOut<dim>::next_cell (const typename DoFHandler<dim>::cell_iterator &cell)
{
				   // convert the iterator to an
				   // active_iterator and advance
				   // this to the next active cell
  typename DoFHandler<dim>::active_cell_iterator active_cell = cell;
  ++active_cell;
  return active_cell;
};

// explicit instantiations
template class DataOut_DoFData<deal_II_dimension>;
template class DataOut<deal_II_dimension>;

<|endoftext|>


<commit_before>/*
 * SyslogAppender.hh
 *
 * Copyright 2001, LifeLine Networks BV (www.lifeline.nl). All rights reserved.
 * Copyright 2001, Walter Stroebel. All rights reserved.
 *
 * See the COPYING file for the terms of usage and distribution.
 */

#ifndef _LOG4CPP_REMOTESYSLOGAPPENDER_HH
#define _LOG4CPP_REMOTESYSLOGAPPENDER_HH

#include <log4cpp/Portability.hh>
#include <string>
#include <stdarg.h>
#include <log4cpp/LayoutAppender.hh>
#include <log4cpp/Priority.hh>
#ifdef WIN32
#include <winsock2.h>
#else
#include <netinet/in.h>
#endif

#ifdef LOG4CPP_HAVE_SYSLOG
#include <syslog.h>
#else
/// from syslog.h
typedef enum {
    LOG_EMERG   = 0,       ///< system is unusable
    LOG_ALERT   = 1,       ///< action must be taken immediately
    LOG_CRIT    = 2,       ///< critical conditions
    LOG_ERR     = 3,       ///< error conditions
    LOG_WARNING = 4,       ///< warning conditions
    LOG_NOTICE  = 5,       ///< normal but significant condition
    LOG_INFO    = 6,       ///< informational
    LOG_DEBUG   = 7,       ///< debug-level messages
} SyslogLevel;

typedef enum {
    LOG_KERN     = (0<<3),  ///< kernel messages
    LOG_USER     = (1<<3),  ///< random user-level messages
    LOG_MAIL     = (2<<3),  ///< mail system
    LOG_DAEMON   = (3<<3),  ///< system daemons
    LOG_AUTH     = (4<<3),  ///< security/authorization messages
    LOG_SYSLOG   = (5<<3),  ///< messages generated internally by syslogd
    LOG_LPR      = (6<<3),  ///< line printer subsystem
    LOG_NEWS     = (7<<3),  ///< network news subsystem
    LOG_UUCP     = (8<<3),  ///< UUCP subsystem
    LOG_CRON     = (9<<3),  ///< clock daemon
    LOG_AUTHPRIV = (10<<3), ///< security/authorization messages (private)
    LOG_FTP      = (11<<3), ///< ftp daemon

    /* other codes through 15 reserved for system use */
    LOG_LOCAL0   = (16<<3), ///< reserved for local use
    LOG_LOCAL1   = (17<<3), ///< reserved for local use
    LOG_LOCAL2   = (18<<3), ///< reserved for local use
    LOG_LOCAL3   = (19<<3), ///< reserved for local use
    LOG_LOCAL4   = (20<<3), ///< reserved for local use
    LOG_LOCAL5   = (21<<3), ///< reserved for local use
    LOG_LOCAL6   = (22<<3), ///< reserved for local use
    LOG_LOCAL7   = (23<<3), ///< reserved for local use
} SyslogFacility;
#endif

namespace log4cpp {

    /**
     * RemoteSyslogAppender sends LoggingEvents to a remote syslog system.
     *
     * Also see: draft-ietf-syslog-syslog-12.txt
     **/
    class LOG4CPP_EXPORT RemoteSyslogAppender : public LayoutAppender {
        public:

        /**
         * Translates a log4cpp priority to a syslog priority
         * @param priority The log4cpp priority.
         * @returns the syslog priority.
         **/
        static int toSyslogPriority(Priority::Value priority);

        /**
         * Instantiate a RemoteSyslogAppender with given name and name and
         * facility for syslog.
         * @param name The name of the Appender
         * @param syslogName The ident parameter in the openlog(3) call.
         * @param relayer The IP address or hostname of a standard syslog host.
         * @param facility The syslog facility to log to. Defaults to LOG_USER.
         * Value '-1' implies to use the default.
         * @param portNumber An alternative port number. Defaults to the
         * standard syslog port number (514).
         * Value '-1' implies to use the default.
         **/
        RemoteSyslogAppender(const std::string& name,
                             const std::string& syslogName,
                             const std::string& relayer,
                             int facility = LOG_USER,
                             int portNumber = 514);
        virtual ~RemoteSyslogAppender();

        /**
         * Closes and reopens the socket.
         **/
        virtual bool reopen();

        /**
         * Closes the socket
         **/
        virtual void close();

        protected:

        /**
         * Just creates the socket.
         **/
        virtual void open();

        /**
         * Sends a LoggingEvent to the remote syslog.
         * @param event the LoggingEvent to log.
         **/
        virtual void _append(const LoggingEvent& event);

        const std::string _syslogName;
        const std::string _relayer;
        int _facility;
        int _portNumber;
        int _socket;
        in_addr_t _ipAddr;
        private:
        int _cludge;
    };
}

#endif // _LOG4CPP_REMOTESYSLOGAPPENDER_HH
<commit_msg>use correct type SOCKET for win32<commit_after>/*
 * SyslogAppender.hh
 *
 * Copyright 2001, LifeLine Networks BV (www.lifeline.nl). All rights reserved.
 * Copyright 2001, Walter Stroebel. All rights reserved.
 *
 * See the COPYING file for the terms of usage and distribution.
 */

#ifndef _LOG4CPP_REMOTESYSLOGAPPENDER_HH
#define _LOG4CPP_REMOTESYSLOGAPPENDER_HH

#include <log4cpp/Portability.hh>
#include <string>
#include <stdarg.h>
#include <log4cpp/LayoutAppender.hh>
#include <log4cpp/Priority.hh>
#ifdef WIN32
#include <winsock2.h>
#else
#include <netinet/in.h>
#endif

#ifdef LOG4CPP_HAVE_SYSLOG
#include <syslog.h>
#else
/// from syslog.h
typedef enum {
    LOG_EMERG   = 0,       ///< system is unusable
    LOG_ALERT   = 1,       ///< action must be taken immediately
    LOG_CRIT    = 2,       ///< critical conditions
    LOG_ERR     = 3,       ///< error conditions
    LOG_WARNING = 4,       ///< warning conditions
    LOG_NOTICE  = 5,       ///< normal but significant condition
    LOG_INFO    = 6,       ///< informational
    LOG_DEBUG   = 7,       ///< debug-level messages
} SyslogLevel;

typedef enum {
    LOG_KERN     = (0<<3),  ///< kernel messages
    LOG_USER     = (1<<3),  ///< random user-level messages
    LOG_MAIL     = (2<<3),  ///< mail system
    LOG_DAEMON   = (3<<3),  ///< system daemons
    LOG_AUTH     = (4<<3),  ///< security/authorization messages
    LOG_SYSLOG   = (5<<3),  ///< messages generated internally by syslogd
    LOG_LPR      = (6<<3),  ///< line printer subsystem
    LOG_NEWS     = (7<<3),  ///< network news subsystem
    LOG_UUCP     = (8<<3),  ///< UUCP subsystem
    LOG_CRON     = (9<<3),  ///< clock daemon
    LOG_AUTHPRIV = (10<<3), ///< security/authorization messages (private)
    LOG_FTP      = (11<<3), ///< ftp daemon

    /* other codes through 15 reserved for system use */
    LOG_LOCAL0   = (16<<3), ///< reserved for local use
    LOG_LOCAL1   = (17<<3), ///< reserved for local use
    LOG_LOCAL2   = (18<<3), ///< reserved for local use
    LOG_LOCAL3   = (19<<3), ///< reserved for local use
    LOG_LOCAL4   = (20<<3), ///< reserved for local use
    LOG_LOCAL5   = (21<<3), ///< reserved for local use
    LOG_LOCAL6   = (22<<3), ///< reserved for local use
    LOG_LOCAL7   = (23<<3), ///< reserved for local use
} SyslogFacility;
#endif

namespace log4cpp {

    /**
     * RemoteSyslogAppender sends LoggingEvents to a remote syslog system.
     *
     * Also see: draft-ietf-syslog-syslog-12.txt
     **/
    class LOG4CPP_EXPORT RemoteSyslogAppender : public LayoutAppender {
        public:

        /**
         * Translates a log4cpp priority to a syslog priority
         * @param priority The log4cpp priority.
         * @returns the syslog priority.
         **/
        static int toSyslogPriority(Priority::Value priority);

        /**
         * Instantiate a RemoteSyslogAppender with given name and name and
         * facility for syslog.
         * @param name The name of the Appender
         * @param syslogName The ident parameter in the openlog(3) call.
         * @param relayer The IP address or hostname of a standard syslog host.
         * @param facility The syslog facility to log to. Defaults to LOG_USER.
         * Value '-1' implies to use the default.
         * @param portNumber An alternative port number. Defaults to the
         * standard syslog port number (514).
         * Value '-1' implies to use the default.
         **/
        RemoteSyslogAppender(const std::string& name,
                             const std::string& syslogName,
                             const std::string& relayer,
                             int facility = LOG_USER,
                             int portNumber = 514);
        virtual ~RemoteSyslogAppender();

        /**
         * Closes and reopens the socket.
         **/
        virtual bool reopen();

        /**
         * Closes the socket
         **/
        virtual void close();

        protected:

        /**
         * Just creates the socket.
         **/
        virtual void open();

        /**
         * Sends a LoggingEvent to the remote syslog.
         * @param event the LoggingEvent to log.
         **/
        virtual void _append(const LoggingEvent& event);

        const std::string _syslogName;
        const std::string _relayer;
        int _facility;
        int _portNumber;
#ifdef	WIN32
		SOCKET	_socket;
#else
		int		_socket;
#endif
        in_addr_t _ipAddr;
        private:
        int _cludge;
    };
}

#endif // _LOG4CPP_REMOTESYSLOGAPPENDER_HH
<|endoftext|>


<commit_before>/*****************************************************************************
 *
 * This file is part of Mapnik (c++ mapping toolkit)
 *
 * Copyright (C) 2011 Artem Pavlenko
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 *****************************************************************************/

#ifndef MAPNIK_FONT_ENGINE_FREETYPE_HPP
#define MAPNIK_FONT_ENGINE_FREETYPE_HPP

// mapnik
#include <mapnik/debug.hpp>
#include <mapnik/color.hpp>
#include <mapnik/utils.hpp>
#include <mapnik/ctrans.hpp>
#include <mapnik/geometry.hpp>
#include <mapnik/font_set.hpp>
#include <mapnik/char_info.hpp>
#include <mapnik/pixel_position.hpp>
#include <mapnik/image_compositing.hpp>

// freetype2
extern "C"
{
#include <ft2build.h>
#include FT_FREETYPE_H
#include FT_GLYPH_H
#include FT_STROKER_H
}

// boost
#include <boost/shared_ptr.hpp>
#include <boost/make_shared.hpp>
#include <boost/utility.hpp>
#include <boost/ptr_container/ptr_vector.hpp>
#include <boost/foreach.hpp>
#ifdef MAPNIK_THREADSAFE
#include <boost/thread/mutex.hpp>
#endif

// stl
#include <string>
#include <vector>
#include <map>
#include <iostream>
#include <algorithm>

// uci
#include <unicode/unistr.h>

namespace mapnik
{
class font_face;
class text_path;
class string_info;

typedef boost::shared_ptr<font_face> face_ptr;

class MAPNIK_DECL font_glyph : private boost::noncopyable
{
public:
    font_glyph(face_ptr face, unsigned index)
        : face_(face), index_(index) {}

    face_ptr get_face() const
    {
        return face_;
    }

    unsigned get_index() const
    {
        return index_;
    }
private:
    face_ptr face_;
    unsigned index_;
};

typedef boost::shared_ptr<font_glyph> glyph_ptr;

class font_face : boost::noncopyable
{
public:
    font_face(FT_Face face)
        : face_(face) {}

    std::string  family_name() const
    {
        return std::string(face_->family_name);
    }

    std::string  style_name() const
    {
        return std::string(face_->style_name);
    }

    FT_GlyphSlot glyph() const
    {
        return face_->glyph;
    }

    FT_Face get_face() const
    {
        return face_;
    }

    unsigned get_char(unsigned c) const
    {
        return FT_Get_Char_Index(face_, c);
    }

    bool set_pixel_sizes(unsigned size)
    {
        if (! FT_Set_Pixel_Sizes( face_, 0, size ))
            return true;
        return false;
    }

    bool set_character_sizes(double size)
    {
        if ( !FT_Set_Char_Size(face_,0,(FT_F26Dot6)(size * (1<<6)),0,0))
            return true;
        return false;
    }

    ~font_face()
    {
        MAPNIK_LOG_DEBUG(font_engine_freetype) << "font_face: Clean up face \"" << family_name() << " " << style_name() << "\"";

        FT_Done_Face(face_);
    }

private:
    FT_Face face_;
};

class MAPNIK_DECL font_face_set : private boost::noncopyable
{
public:
    font_face_set(void)
        : faces_(),
        dimension_cache_() {}

    void add(face_ptr face)
    {
        faces_.push_back(face);
        dimension_cache_.clear(); //Make sure we don't use old cached data
    }

    unsigned size() const
    {
        return faces_.size();
    }

    glyph_ptr get_glyph(unsigned c) const
    {
        BOOST_FOREACH ( face_ptr const& face, faces_)
        {
            FT_UInt g = face->get_char(c);
            if (g) return boost::make_shared<font_glyph>(face, g);
        }

        // Final fallback to empty square if nothing better in any font
        return boost::make_shared<font_glyph>(*faces_.begin(), 0);
    }

    char_info character_dimensions(const unsigned c);

    void get_string_info(string_info & info, UnicodeString const& ustr, char_properties *format);

    void set_pixel_sizes(unsigned size)
    {
        BOOST_FOREACH ( face_ptr const& face, faces_)
        {
            face->set_pixel_sizes(size);
        }
    }

    void set_character_sizes(double size)
    {
        BOOST_FOREACH ( face_ptr const& face, faces_)
        {
            face->set_character_sizes(size);
        }
    }
private:
    std::vector<face_ptr> faces_;
    std::map<unsigned, char_info> dimension_cache_;
};

// FT_Stroker wrapper
class stroker : boost::noncopyable
{
public:
    explicit stroker(FT_Stroker s)
        : s_(s) {}

    void init(double radius)
    {
        FT_Stroker_Set(s_, (FT_Fixed) (radius * (1<<6)),
                       FT_STROKER_LINECAP_ROUND,
                       FT_STROKER_LINEJOIN_ROUND,
                       0);
    }

    FT_Stroker const& get() const
    {
        return s_;
    }

    ~stroker()
    {
        MAPNIK_LOG_DEBUG(font_engine_freetype) << "stroker: Destroy stroker=" << s_;

        FT_Stroker_Done(s_);
    }
private:
    FT_Stroker s_;
};

typedef boost::shared_ptr<font_face_set> face_set_ptr;
typedef boost::shared_ptr<stroker> stroker_ptr;

class MAPNIK_DECL freetype_engine
{
public:
    static bool is_font_file(std::string const& file_name);

    /*! \brief register a font file
     *  @param file_name path to a font file.
     *  @return bool - true if at least one face was successfully registered in the file.
     */
    static bool register_font(std::string const& file_name);

    /*! \brief register a font file
     *  @param file_name - path to a directory containing fonts or subdirectories.
     *  @param recurse - default false, whether to search for fonts in sub directories.
     *  @return bool - true if at least one face was successfully registered.
     */
    static bool register_fonts(std::string const& dir, bool recurse = false);
    static std::vector<std::string> face_names();
    static std::map<std::string,std::pair<int,std::string> > const& get_mapping();
    face_ptr create_face(std::string const& family_name);
    stroker_ptr create_stroker();
    virtual ~freetype_engine();
    freetype_engine();
private:
    FT_Library library_;
#ifdef MAPNIK_THREADSAFE
    static boost::mutex mutex_;
#endif
    static std::map<std::string,std::pair<int,std::string> > name2file_;
};

template <typename T>
class MAPNIK_DECL face_manager : private boost::noncopyable
{
    typedef T font_engine_type;
    typedef std::map<std::string,face_ptr> face_ptr_cache_type;

public:
    face_manager(T & engine)
        : engine_(engine),
        stroker_(engine_.create_stroker()),
        face_ptr_cache_()  {}

    face_ptr get_face(std::string const& name)
    {
        face_ptr_cache_type::iterator itr;
        itr = face_ptr_cache_.find(name);
        if (itr != face_ptr_cache_.end())
        {
            return itr->second;
        }
        else
        {
            face_ptr face = engine_.create_face(name);
            if (face)
            {
                face_ptr_cache_.insert(make_pair(name,face));
            }
            return face;
        }
    }

    face_set_ptr get_face_set(std::string const& name)
    {
        face_set_ptr face_set = boost::make_shared<font_face_set>();
        if (face_ptr face = get_face(name))
        {
            face_set->add(face);
        }
        return face_set;
    }

    face_set_ptr get_face_set(font_set const& fset)
    {
        std::vector<std::string> const& names = fset.get_face_names();
        face_set_ptr face_set = boost::make_shared<font_face_set>();
        for (std::vector<std::string>::const_iterator name = names.begin(); name != names.end(); ++name)
        {
            face_ptr face = get_face(*name);
            if (face)
            {
                face_set->add(face);
            }
#ifdef MAPNIK_LOG
            else
            {
                MAPNIK_LOG_DEBUG(font_engine_freetype)
                        << "Failed to find face '" << *name
                        << "' in font set '" << fset.get_name() << "'\n";
            }
#endif
        }
        return face_set;
    }

    face_set_ptr get_face_set(std::string const& name, boost::optional<font_set> fset)
    {
        if (fset && fset->size() > 0)
        {
            return get_face_set(*fset);
        }
        else
        {
            return get_face_set(name);
        }
    }

    stroker_ptr get_stroker()
    {
        return stroker_;
    }

private:
    font_engine_type & engine_;
    stroker_ptr stroker_;
    face_ptr_cache_type face_ptr_cache_;
};

template <typename T>
struct text_renderer : private boost::noncopyable
{
    struct glyph_t : boost::noncopyable
    {
        FT_Glyph image;
        char_properties *properties;
        glyph_t(FT_Glyph image_, char_properties *properties_)
            : image(image_), properties(properties_) {}
        ~glyph_t () { FT_Done_Glyph(image);}
    };

    typedef boost::ptr_vector<glyph_t> glyphs_t;
    typedef T pixmap_type;

    text_renderer (pixmap_type & pixmap,
                   face_manager<freetype_engine> &font_manager_,
                   stroker & s,
                   composite_mode_e comp_op = src_over,
                   double scale_factor=1.0);
    box2d<double> prepare_glyphs(text_path const& path);
    void render(pixel_position pos);
    void render_id(int feature_id, pixel_position pos, double min_radius=1.0);

private:

    void render_bitmap(FT_Bitmap *bitmap, unsigned rgba, int x, int y, double opacity)
    {
        int x_max=x+bitmap->width;
        int y_max=y+bitmap->rows;
        int i,p,j,q;

        for (i=x,p=0;i<x_max;++i,++p)
        {
            for (j=y,q=0;j<y_max;++j,++q)
            {
                int gray=bitmap->buffer[q*bitmap->width+p];
                if (gray)
                {
                    pixmap_.blendPixel2(i, j, rgba, gray, opacity);
                }
            }
        }
    }

    void render_bitmap_id(FT_Bitmap *bitmap,int feature_id,int x,int y)
    {
        int x_max=x+bitmap->width;
        int y_max=y+bitmap->rows;
        int i,p,j,q;

        for (i=x,p=0;i<x_max;++i,++p)
        {
            for (j=y,q=0;j<y_max;++j,++q)
            {
                int gray=bitmap->buffer[q*bitmap->width+p];
                if (gray)
                {
                    pixmap_.setPixel(i,j,feature_id);
                    //pixmap_.blendPixel2(i,j,rgba,gray,opacity_);
                }
            }
        }
    }

    pixmap_type & pixmap_;
    face_manager<freetype_engine> &font_manager_;
    stroker & stroker_;
    glyphs_t glyphs_;
    composite_mode_e comp_op_;
    double scale_factor_;
};

typedef face_manager<freetype_engine> face_manager_freetype;

}

#endif // MAPNIK_FONT_ENGINE_FREETYPE_HPP
<commit_msg>remove uneeded debugging prints<commit_after>/*****************************************************************************
 *
 * This file is part of Mapnik (c++ mapping toolkit)
 *
 * Copyright (C) 2011 Artem Pavlenko
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 *****************************************************************************/

#ifndef MAPNIK_FONT_ENGINE_FREETYPE_HPP
#define MAPNIK_FONT_ENGINE_FREETYPE_HPP

// mapnik
#include <mapnik/color.hpp>
#include <mapnik/utils.hpp>
#include <mapnik/ctrans.hpp>
#include <mapnik/geometry.hpp>
#include <mapnik/font_set.hpp>
#include <mapnik/char_info.hpp>
#include <mapnik/pixel_position.hpp>
#include <mapnik/image_compositing.hpp>

// freetype2
extern "C"
{
#include <ft2build.h>
#include FT_FREETYPE_H
#include FT_GLYPH_H
#include FT_STROKER_H
}

// boost
#include <boost/shared_ptr.hpp>
#include <boost/make_shared.hpp>
#include <boost/utility.hpp>
#include <boost/ptr_container/ptr_vector.hpp>
#include <boost/foreach.hpp>
#ifdef MAPNIK_THREADSAFE
#include <boost/thread/mutex.hpp>
#endif

// stl
#include <string>
#include <vector>
#include <map>
#include <algorithm>

// uci
#include <unicode/unistr.h>

namespace mapnik
{
class font_face;
class text_path;
class string_info;

typedef boost::shared_ptr<font_face> face_ptr;

class MAPNIK_DECL font_glyph : private boost::noncopyable
{
public:
    font_glyph(face_ptr face, unsigned index)
        : face_(face), index_(index) {}

    face_ptr get_face() const
    {
        return face_;
    }

    unsigned get_index() const
    {
        return index_;
    }
private:
    face_ptr face_;
    unsigned index_;
};

typedef boost::shared_ptr<font_glyph> glyph_ptr;

class font_face : boost::noncopyable
{
public:
    font_face(FT_Face face)
        : face_(face) {}

    std::string  family_name() const
    {
        return std::string(face_->family_name);
    }

    std::string  style_name() const
    {
        return std::string(face_->style_name);
    }

    FT_GlyphSlot glyph() const
    {
        return face_->glyph;
    }

    FT_Face get_face() const
    {
        return face_;
    }

    unsigned get_char(unsigned c) const
    {
        return FT_Get_Char_Index(face_, c);
    }

    bool set_pixel_sizes(unsigned size)
    {
        if (! FT_Set_Pixel_Sizes( face_, 0, size ))
            return true;
        return false;
    }

    bool set_character_sizes(double size)
    {
        if ( !FT_Set_Char_Size(face_,0,(FT_F26Dot6)(size * (1<<6)),0,0))
            return true;
        return false;
    }

    ~font_face()
    {
        FT_Done_Face(face_);
    }

private:
    FT_Face face_;
};

class MAPNIK_DECL font_face_set : private boost::noncopyable
{
public:
    font_face_set(void)
        : faces_(),
        dimension_cache_() {}

    void add(face_ptr face)
    {
        faces_.push_back(face);
        dimension_cache_.clear(); //Make sure we don't use old cached data
    }

    unsigned size() const
    {
        return faces_.size();
    }

    glyph_ptr get_glyph(unsigned c) const
    {
        BOOST_FOREACH ( face_ptr const& face, faces_)
        {
            FT_UInt g = face->get_char(c);
            if (g) return boost::make_shared<font_glyph>(face, g);
        }

        // Final fallback to empty square if nothing better in any font
        return boost::make_shared<font_glyph>(*faces_.begin(), 0);
    }

    char_info character_dimensions(const unsigned c);

    void get_string_info(string_info & info, UnicodeString const& ustr, char_properties *format);

    void set_pixel_sizes(unsigned size)
    {
        BOOST_FOREACH ( face_ptr const& face, faces_)
        {
            face->set_pixel_sizes(size);
        }
    }

    void set_character_sizes(double size)
    {
        BOOST_FOREACH ( face_ptr const& face, faces_)
        {
            face->set_character_sizes(size);
        }
    }
private:
    std::vector<face_ptr> faces_;
    std::map<unsigned, char_info> dimension_cache_;
};

// FT_Stroker wrapper
class stroker : boost::noncopyable
{
public:
    explicit stroker(FT_Stroker s)
        : s_(s) {}

    void init(double radius)
    {
        FT_Stroker_Set(s_, (FT_Fixed) (radius * (1<<6)),
                       FT_STROKER_LINECAP_ROUND,
                       FT_STROKER_LINEJOIN_ROUND,
                       0);
    }

    FT_Stroker const& get() const
    {
        return s_;
    }

    ~stroker()
    {
        FT_Stroker_Done(s_);
    }
private:
    FT_Stroker s_;
};

typedef boost::shared_ptr<font_face_set> face_set_ptr;
typedef boost::shared_ptr<stroker> stroker_ptr;

class MAPNIK_DECL freetype_engine
{
public:
    static bool is_font_file(std::string const& file_name);

    /*! \brief register a font file
     *  @param file_name path to a font file.
     *  @return bool - true if at least one face was successfully registered in the file.
     */
    static bool register_font(std::string const& file_name);

    /*! \brief register a font file
     *  @param file_name - path to a directory containing fonts or subdirectories.
     *  @param recurse - default false, whether to search for fonts in sub directories.
     *  @return bool - true if at least one face was successfully registered.
     */
    static bool register_fonts(std::string const& dir, bool recurse = false);
    static std::vector<std::string> face_names();
    static std::map<std::string,std::pair<int,std::string> > const& get_mapping();
    face_ptr create_face(std::string const& family_name);
    stroker_ptr create_stroker();
    virtual ~freetype_engine();
    freetype_engine();
private:
    FT_Library library_;
#ifdef MAPNIK_THREADSAFE
    static boost::mutex mutex_;
#endif
    static std::map<std::string,std::pair<int,std::string> > name2file_;
};

template <typename T>
class MAPNIK_DECL face_manager : private boost::noncopyable
{
    typedef T font_engine_type;
    typedef std::map<std::string,face_ptr> face_ptr_cache_type;

public:
    face_manager(T & engine)
        : engine_(engine),
        stroker_(engine_.create_stroker()),
        face_ptr_cache_()  {}

    face_ptr get_face(std::string const& name)
    {
        face_ptr_cache_type::iterator itr;
        itr = face_ptr_cache_.find(name);
        if (itr != face_ptr_cache_.end())
        {
            return itr->second;
        }
        else
        {
            face_ptr face = engine_.create_face(name);
            if (face)
            {
                face_ptr_cache_.insert(make_pair(name,face));
            }
            return face;
        }
    }

    face_set_ptr get_face_set(std::string const& name)
    {
        face_set_ptr face_set = boost::make_shared<font_face_set>();
        if (face_ptr face = get_face(name))
        {
            face_set->add(face);
        }
        return face_set;
    }

    face_set_ptr get_face_set(font_set const& fset)
    {
        std::vector<std::string> const& names = fset.get_face_names();
        face_set_ptr face_set = boost::make_shared<font_face_set>();
        for (std::vector<std::string>::const_iterator name = names.begin(); name != names.end(); ++name)
        {
            face_ptr face = get_face(*name);
            if (face)
            {
                face_set->add(face);
            }
#ifdef MAPNIK_LOG
            else
            {
                MAPNIK_LOG_DEBUG(font_engine_freetype)
                        << "Failed to find face '" << *name
                        << "' in font set '" << fset.get_name() << "'\n";
            }
#endif
        }
        return face_set;
    }

    face_set_ptr get_face_set(std::string const& name, boost::optional<font_set> fset)
    {
        if (fset && fset->size() > 0)
        {
            return get_face_set(*fset);
        }
        else
        {
            return get_face_set(name);
        }
    }

    stroker_ptr get_stroker()
    {
        return stroker_;
    }

private:
    font_engine_type & engine_;
    stroker_ptr stroker_;
    face_ptr_cache_type face_ptr_cache_;
};

template <typename T>
struct text_renderer : private boost::noncopyable
{
    struct glyph_t : boost::noncopyable
    {
        FT_Glyph image;
        char_properties *properties;
        glyph_t(FT_Glyph image_, char_properties *properties_)
            : image(image_), properties(properties_) {}
        ~glyph_t () { FT_Done_Glyph(image);}
    };

    typedef boost::ptr_vector<glyph_t> glyphs_t;
    typedef T pixmap_type;

    text_renderer (pixmap_type & pixmap,
                   face_manager<freetype_engine> &font_manager_,
                   stroker & s,
                   composite_mode_e comp_op = src_over,
                   double scale_factor=1.0);
    box2d<double> prepare_glyphs(text_path const& path);
    void render(pixel_position pos);
    void render_id(int feature_id, pixel_position pos, double min_radius=1.0);

private:

    void render_bitmap(FT_Bitmap *bitmap, unsigned rgba, int x, int y, double opacity)
    {
        int x_max=x+bitmap->width;
        int y_max=y+bitmap->rows;
        int i,p,j,q;

        for (i=x,p=0;i<x_max;++i,++p)
        {
            for (j=y,q=0;j<y_max;++j,++q)
            {
                int gray=bitmap->buffer[q*bitmap->width+p];
                if (gray)
                {
                    pixmap_.blendPixel2(i, j, rgba, gray, opacity);
                }
            }
        }
    }

    void render_bitmap_id(FT_Bitmap *bitmap,int feature_id,int x,int y)
    {
        int x_max=x+bitmap->width;
        int y_max=y+bitmap->rows;
        int i,p,j,q;

        for (i=x,p=0;i<x_max;++i,++p)
        {
            for (j=y,q=0;j<y_max;++j,++q)
            {
                int gray=bitmap->buffer[q*bitmap->width+p];
                if (gray)
                {
                    pixmap_.setPixel(i,j,feature_id);
                    //pixmap_.blendPixel2(i,j,rgba,gray,opacity_);
                }
            }
        }
    }

    pixmap_type & pixmap_;
    face_manager<freetype_engine> &font_manager_;
    stroker & stroker_;
    glyphs_t glyphs_;
    composite_mode_e comp_op_;
    double scale_factor_;
};

typedef face_manager<freetype_engine> face_manager_freetype;

}

#endif // MAPNIK_FONT_ENGINE_FREETYPE_HPP
<|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
//
//  Make   a log file for the CPU and Memory usage
//
//  Principles:
//  Snapshots of the system information are writen to the text log files.
//  Text files were chosen in order to get the ouptu also in case code
//  is crashing.
//  Following information is stored in the log file:
//  TTimeStamp stamp;
//  CpuInfo_t  cpuInfo;
//  MemInfo_t  memInfo;
//  ProcInfo_t procInfo;
//
//  Root TSystem is used to retrieve this information:
//  gSystem->GetCpuInfo(&cpuInfo, 10);
//  gSystem->GetMemInfo(&memInfo);
//  gSystem->GetProcInfo(&procInfo);
//  for details see:
//  http://root.cern.ch/root/html/TUnixSystem.html
//  http://root.cern.ch/root/html/ProcInfo_t.html
//  http://root.cern.ch/root/html/MemInfo_t.html
//  http://root.cern.ch/root/html/CpuInfo_t.html
//  -------------------------------------------------------------------
//  class CpuInfo_t
//   Float_t	fIdle	cpu idle percentage
//   Float_t	fLoad15m	cpu load average over 15 m
//   Float_t	fLoad1m	cpu load average over 1 m
//   Float_t	fLoad5m	cpu load average over 5 m
//   Float_t	fSys	cpu sys load in percentage
//   Float_t	fTotal	cpu user+sys load in percentage
//   Float_t	fUser	cpu user load in percentage

//  -------------------------------------------------------------------
//  class ProcInfo_t:
//  Float_t	fCpuSys	system time used by this process in seconds
//  Float_t	fCpuUser	user time used by this process in seconds
//  Long_t	fMemResident	resident memory used by this process in KB
//  Long_t	fMemVirtual	virtual memory used by this process in KB
//  -------------------------------------------------------------------

//  The information from the AliSysInfo can be used as measurement
//  of the code quality. Be aware of the limitation induced by
//  using only system info described in the  AliSysInfo::Test() function
//
//  The example usage of the AliSysInfo is shown in the
//  AliSysInfo::Test() example.
//
//
//
//
//  The typical usage in the AliRoot code:
//  Make a set of stamps in the code in the place of interest
//  e.g.
//
//  AliSysInfo::AddStamp("Start");
//
//  loader->UnloadRecPoints();
//    AliSysInfo::AddStamp(Form("LRec%s_%d",fgkDetectorName[iDet],eventNr), iDet,1,eventNr);
//

// The log file can be transformed to the tree - to make a visualization
// See $ALICE_ROOT/macros/PlotSysInfo.C as an example

#include <Riostream.h>
//#include "AliLog.h"
#include "TStopwatch.h"
#include "TSystem.h"
#include "TTree.h"
#include "TFile.h"

#include "TTimeStamp.h"
#include "AliSysInfo.h"
#include "TBufferFile.h"

//#include "TMemStatManager.h"  //USE IFDEF

using std::endl;
using std::cout;
using std::ios_base;
using std::setprecision;
ClassImp(AliSysInfo)

AliSysInfo* AliSysInfo::fInstance=0;
Bool_t AliSysInfo::fgVerbose = kFALSE;

AliSysInfo::AliSysInfo():
    TObject(),
    fSysWatch(0),
    fTimer(0),
    fMemStat(0),
    fCallBackFunc(0),
    fNCallBack(0)
{
  fTimer = new TStopwatch;
  fSysWatch  = new fstream("syswatch.log", ios_base::out|ios_base::trunc);

  //hname/C:sname/C:sec/D:mI.fMemUsed/F:mI.fSwapUsed/F:pI.fMemResident/F:pI.fMemVirtual/F:cI.fUser/F:cI.fSys/F:cI.fCpuUser/F:pI.fCpuSys/F

  (*fSysWatch) <<"hname"<<"/C:"               // hname - hostname
               <<"sname"<<"/C:"              // stamp name
               <<"id0"<<"/I:"                // 0 id
               <<"id1"<<"/I:"                // 1 id
               <<"id2"<<"/I:"                // 1 id
               <<"id3"<<"/I:"                // 1 id
               <<"first"<<"/D:"              // first stamp
    //
	       <<"stampSec"<<"/D:"         // time  - time stamp in seconds
	       <<"mi.fMemUsed"<<"/D:"       // system info
	       <<"mi.fSwapUsed"<<"/D:"      //
	       <<"cI.fUser"<<"/D:"         //
	       <<"cI.fSys"<<"/D:"         //
	       <<"cI.fLoad1m"<<"/D:"         //
	       <<"cI.fLoad5m"<<"/D:"         //
	       <<"cI.fLoad15m"<<"/D:"         //
    //
	       <<"pI.fMemResident"<<"/D:"  // process info
	       <<"pI.fMemVirtual"<<"/D:"   //
	       <<"pI.fCpuUser"<<"/D:"      //
	       <<"pI.fCpuSys"<<"/D:"       //
    //
    	       <<"stampOldSec"<<"/D:"         // time  - time stamp in seconds
	       <<"miOld.fMemUsed"<<"/D:"       // system info - previous
	       <<"miOld.fSwapUsed"<<"/D:"      //
	       <<"cIOld.fUser"<<"/D:"         //
	       <<"cIOld.fSys"<<"/D:"         //
    //
	       <<"pIOld.fMemResident"<<"/D:"  // process info -previous
	       <<"pIOld.fMemVirtual"<<"/D:"   //
	       <<"pIOld.fCpuUser"<<"/D:"      //
	       <<"pIOld.fCpuSys"<<"/D:"       //
    //
	       <<"fileBytesRead"<<"/D:"       // file IO information
	       <<"fileBytesWritten"<<"/D:"    //
	       <<"fileCounter"<<"/D:"         //
	       <<"fileReadCalls"<<"/D"        //
	       << endl;

}

AliSysInfo * AliSysInfo::Instance(){
  //
  //
  //
  if (!fInstance){
    fInstance = new AliSysInfo;
  }
  return fInstance;
}

void AliSysInfo::AddStamp(const char *sname, Int_t id0, Int_t id1, Int_t id2, Int_t id3){
  //
  //
  if (!fgVerbose) return;
  //
  //
  TTimeStamp stamp;
  CpuInfo_t  cpuInfo;
  MemInfo_t  memInfo;
  ProcInfo_t procInfo;
  gSystem->GetCpuInfo(&cpuInfo, 10);
  gSystem->GetMemInfo(&memInfo);
  gSystem->GetProcInfo(&procInfo);
  //  procInfo.fMemVirtual/=1024;  //size in MBy
  //procInfo.fMemResident/=1024;  //size in MBy

  const char * hname = gSystem->HostName();

  static Int_t entry=0;
  static Double_t  first=stamp.GetSec()+stamp.GetNanoSec()/1000000000.;
  //
  static TTimeStamp stampOld;
  static CpuInfo_t  cpuInfoOld;
  static MemInfo_t  memInfoOld;
  static ProcInfo_t procInfoOld;
  Double_t fileBytesRead    = TFile::GetFileBytesRead();
  Double_t fileBytesWritten = TFile::GetFileBytesWritten();
  Double_t fileCounter      = TFile::GetFileCounter();
  Double_t fileReadCalls    = TFile::GetFileReadCalls();

  (*(Instance()->fSysWatch))
    << hname   <<"\t"               // hname - hostname
    << sname    <<"\t"              // stamp name
    << id0      <<"\t"
    << id1      <<"\t"
    << id2      <<"\t"
    << id3      <<"\t"
    <<setprecision(15)<< first    <<"\t"              // first stamp
    //
    <<setprecision(15)<< stamp.GetSec()+stamp.GetNanoSec()/1000000000.<<"\t"         // time  - time stamp in seconds
    << memInfo.fMemUsed<<"\t"       // system info
    << memInfo.fSwapUsed<<"\t"      //
    << cpuInfo.fUser <<"\t"         //
    << cpuInfo.fSys  <<"\t"         //
    << cpuInfo.fLoad1m  <<"\t"         //
    << cpuInfo.fLoad5m  <<"\t"         //
    << cpuInfo.fLoad15m  <<"\t"         //
    //
    <<setprecision(15)<< procInfo.fMemResident/1024.<<"\t"  // process info
    <<setprecision(15)<< procInfo.fMemVirtual/1024.<<"\t"   //
    << procInfo.fCpuUser<<"\t"      //
    << procInfo.fCpuSys<<"\t"       //
    //
    <<setprecision(15)<< stampOld.GetSec()+stampOld.GetNanoSec()/1000000000.<<"\t"         // time  - time stamp in seconds
    << memInfoOld.fMemUsed<<"\t"       // system info - previous
    << memInfoOld.fSwapUsed<<"\t"      //
    << cpuInfoOld.fUser <<"\t"         //
    << cpuInfoOld.fSys  <<"\t"         //
    //
    <<setprecision(15)<< procInfoOld.fMemResident/1024.<<"\t"  // process info -previous
    <<setprecision(15)<< procInfoOld.fMemVirtual/1024.<<"\t"   //
    << procInfoOld.fCpuUser<<"\t"      //
    << procInfoOld.fCpuSys<<"\t"       //
    //
    <<fileBytesRead<<"\t"           // file IO information
    <<fileBytesWritten<<"\t"        //
    <<fileCounter<<"\t"             //
    <<fileReadCalls<<"\t"            //
    << endl;

  stampOld   = stamp;
  cpuInfoOld = cpuInfo;
  memInfoOld = memInfo;
  procInfoOld= procInfo;

  //  if (fInstance->fMemStat) fInstance->fMemStat->AddStamps(sname);
  for (Int_t icallback=0; icallback<Instance()->fNCallBack; icallback++){
    Instance()->fCallBackFunc[icallback](sname);
  }
  entry++;
}

TTree * AliSysInfo::MakeTree(const char *lname){
  // char * lname = "syswatch.log"
  TTree * tree = new TTree;
  tree->ReadFile(lname);
  tree->SetAlias("deltaT","stampSec-stampOldSec");
  tree->SetAlias("T","stampSec-first");
  tree->SetAlias("deltaVM","(pI.fMemVirtual-pIOld.fMemVirtual)");
  tree->SetAlias("VM","pI.fMemVirtual");
  return tree;
}

Bool_t AliSysInfo::Contain(const char * str1, const char * str2){
  //
  //
  //
  TString str(str1);
  return str.Contains(str2);
}

void AliSysInfo::OpenMemStat(){
  //
  //
  //
  //USE IFDEF if MEMSTAT ENABLED
  //  Instance()->fMemStat = TMemStatManager::GetInstance();
  //   Instance()->fMemStat->SetAutoStamp(10000000, 10000000,1000000);
  //   Instance()->fMemStat->Enable();
}

void AliSysInfo::CloseMemStat(){
  //
  //
  //
  //USE IFDEF if MEMSTAT ENABLED
  //if (Instance()->fMemStat  == TMemStatManager::GetInstance()) Instance()->fMemStat->Close();
  //Instance()->fMemStat=0;
}

void AliSysInfo::AddCallBack(StampCallback_t callback){
  //
  // add cal back function
  //
  AliSysInfo *info =  Instance();
  if (!info->fCallBackFunc)
    info->fCallBackFunc = new StampCallback_t[100];
  info->fCallBackFunc[info->fNCallBack]=callback;
  info->fNCallBack++;
}

TTree*  AliSysInfo::Test(){
  //
  // Test example for AliSysInfo:
  // 1. Make huge memory leak
  // 2. Slow down execution
  /*
    To use the test:
    TTree * tree = AliSysInfo::Test();
    // Make alias what we set as input
    tree->SetAlias("deltaVMIn","(id0*100000+id1*10000+id2*1000)/1000000.")
    tree->SetAlias("deltaVM","(pI.fMemVirtual-pIOld.fMemVirtual)");
    tree->SetAlias("deltaTIn","(id1+id0*10)");
    tree->SetAlias("deltaT","stampSec-stampOldSec");
    //
    tree->SetMarkerStyle(23); tree->SetMarkerSize(0.5);
    // Memory usage
    tree->Draw("deltaVM:deltaVMIn","Entry$>0");
    // or alternative
    tree->Draw("deltaVM:deltaVMIn","Entry$>0","prof");
    //
    // draw time usage
    tree->Draw("deltaT:deltaTIn","Entry$>0");
  */
  //
  // The delta of VM as obtained from the AliSysInfo starts to be proportional
  // to  the input allocation after 0.12 MBy (and it is system dependent)
  // Bellow these limit the deltaVM can be used only in mean.
  // (compare first and  profile histogram)
  for (Int_t id0=0; id0<5; id0++)
    for (Int_t id1=1; id1<10; id1++)
      for (Int_t id2=0; id2<20; id2++){
	new Char_t[id2*1000+id1*10000+id0*100000];  // emulate memory leak
	gSystem->Sleep(id1+id0*10);         // emulate CPU usage
	AliSysInfo::AddStamp("Leak",id0,id1,id2);
      }
  TTree * tree = AliSysInfo::MakeTree("syswatch.log");
  return tree;
}

Double_t AliSysInfo::EstimateObjectSize(TObject* object){
  //
  // Estimate size of object as represented in the memory size in bytes
  // Warnings:
  //  1. Only data memebrs which are persistent are counted
  //  2. Local copy of the object is temporary created in memory
  //  3. Do not use it in standard programs, time and memory consument procedure
  //
  if (!object) return 0;
  TBufferFile * file = new TBufferFile(TBuffer::kWrite);
  file->WriteObject(object);
  Double_t size=file->Length();
  delete file;
  return size;
}
<commit_msg>Set default verbosity to ON, to prevent failing the tasks which require the sysinfo.log<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
//
//  Make   a log file for the CPU and Memory usage
//
//  Principles:
//  Snapshots of the system information are writen to the text log files.
//  Text files were chosen in order to get the ouptu also in case code
//  is crashing.
//  Following information is stored in the log file:
//  TTimeStamp stamp;
//  CpuInfo_t  cpuInfo;
//  MemInfo_t  memInfo;
//  ProcInfo_t procInfo;
//
//  Root TSystem is used to retrieve this information:
//  gSystem->GetCpuInfo(&cpuInfo, 10);
//  gSystem->GetMemInfo(&memInfo);
//  gSystem->GetProcInfo(&procInfo);
//  for details see:
//  http://root.cern.ch/root/html/TUnixSystem.html
//  http://root.cern.ch/root/html/ProcInfo_t.html
//  http://root.cern.ch/root/html/MemInfo_t.html
//  http://root.cern.ch/root/html/CpuInfo_t.html
//  -------------------------------------------------------------------
//  class CpuInfo_t
//   Float_t	fIdle	cpu idle percentage
//   Float_t	fLoad15m	cpu load average over 15 m
//   Float_t	fLoad1m	cpu load average over 1 m
//   Float_t	fLoad5m	cpu load average over 5 m
//   Float_t	fSys	cpu sys load in percentage
//   Float_t	fTotal	cpu user+sys load in percentage
//   Float_t	fUser	cpu user load in percentage

//  -------------------------------------------------------------------
//  class ProcInfo_t:
//  Float_t	fCpuSys	system time used by this process in seconds
//  Float_t	fCpuUser	user time used by this process in seconds
//  Long_t	fMemResident	resident memory used by this process in KB
//  Long_t	fMemVirtual	virtual memory used by this process in KB
//  -------------------------------------------------------------------

//  The information from the AliSysInfo can be used as measurement
//  of the code quality. Be aware of the limitation induced by
//  using only system info described in the  AliSysInfo::Test() function
//
//  The example usage of the AliSysInfo is shown in the
//  AliSysInfo::Test() example.
//
//
//
//
//  The typical usage in the AliRoot code:
//  Make a set of stamps in the code in the place of interest
//  e.g.
//
//  AliSysInfo::AddStamp("Start");
//
//  loader->UnloadRecPoints();
//    AliSysInfo::AddStamp(Form("LRec%s_%d",fgkDetectorName[iDet],eventNr), iDet,1,eventNr);
//

// The log file can be transformed to the tree - to make a visualization
// See $ALICE_ROOT/macros/PlotSysInfo.C as an example

#include <Riostream.h>
//#include "AliLog.h"
#include "TStopwatch.h"
#include "TSystem.h"
#include "TTree.h"
#include "TFile.h"

#include "TTimeStamp.h"
#include "AliSysInfo.h"
#include "TBufferFile.h"

//#include "TMemStatManager.h"  //USE IFDEF

using std::endl;
using std::cout;
using std::ios_base;
using std::setprecision;
ClassImp(AliSysInfo)

AliSysInfo* AliSysInfo::fInstance=0;
Bool_t AliSysInfo::fgVerbose = kTRUE;

AliSysInfo::AliSysInfo():
    TObject(),
    fSysWatch(0),
    fTimer(0),
    fMemStat(0),
    fCallBackFunc(0),
    fNCallBack(0)
{
  fTimer = new TStopwatch;
  fSysWatch  = new fstream("syswatch.log", ios_base::out|ios_base::trunc);

  //hname/C:sname/C:sec/D:mI.fMemUsed/F:mI.fSwapUsed/F:pI.fMemResident/F:pI.fMemVirtual/F:cI.fUser/F:cI.fSys/F:cI.fCpuUser/F:pI.fCpuSys/F

  (*fSysWatch) <<"hname"<<"/C:"               // hname - hostname
               <<"sname"<<"/C:"              // stamp name
               <<"id0"<<"/I:"                // 0 id
               <<"id1"<<"/I:"                // 1 id
               <<"id2"<<"/I:"                // 1 id
               <<"id3"<<"/I:"                // 1 id
               <<"first"<<"/D:"              // first stamp
    //
	       <<"stampSec"<<"/D:"         // time  - time stamp in seconds
	       <<"mi.fMemUsed"<<"/D:"       // system info
	       <<"mi.fSwapUsed"<<"/D:"      //
	       <<"cI.fUser"<<"/D:"         //
	       <<"cI.fSys"<<"/D:"         //
	       <<"cI.fLoad1m"<<"/D:"         //
	       <<"cI.fLoad5m"<<"/D:"         //
	       <<"cI.fLoad15m"<<"/D:"         //
    //
	       <<"pI.fMemResident"<<"/D:"  // process info
	       <<"pI.fMemVirtual"<<"/D:"   //
	       <<"pI.fCpuUser"<<"/D:"      //
	       <<"pI.fCpuSys"<<"/D:"       //
    //
    	       <<"stampOldSec"<<"/D:"         // time  - time stamp in seconds
	       <<"miOld.fMemUsed"<<"/D:"       // system info - previous
	       <<"miOld.fSwapUsed"<<"/D:"      //
	       <<"cIOld.fUser"<<"/D:"         //
	       <<"cIOld.fSys"<<"/D:"         //
    //
	       <<"pIOld.fMemResident"<<"/D:"  // process info -previous
	       <<"pIOld.fMemVirtual"<<"/D:"   //
	       <<"pIOld.fCpuUser"<<"/D:"      //
	       <<"pIOld.fCpuSys"<<"/D:"       //
    //
	       <<"fileBytesRead"<<"/D:"       // file IO information
	       <<"fileBytesWritten"<<"/D:"    //
	       <<"fileCounter"<<"/D:"         //
	       <<"fileReadCalls"<<"/D"        //
	       << endl;

}

AliSysInfo * AliSysInfo::Instance(){
  //
  //
  //
  if (!fInstance){
    fInstance = new AliSysInfo;
  }
  return fInstance;
}

void AliSysInfo::AddStamp(const char *sname, Int_t id0, Int_t id1, Int_t id2, Int_t id3){
  //
  //
  if (!fgVerbose) return;
  //
  //
  TTimeStamp stamp;
  CpuInfo_t  cpuInfo;
  MemInfo_t  memInfo;
  ProcInfo_t procInfo;
  gSystem->GetCpuInfo(&cpuInfo, 10);
  gSystem->GetMemInfo(&memInfo);
  gSystem->GetProcInfo(&procInfo);
  //  procInfo.fMemVirtual/=1024;  //size in MBy
  //procInfo.fMemResident/=1024;  //size in MBy

  const char * hname = gSystem->HostName();

  static Int_t entry=0;
  static Double_t  first=stamp.GetSec()+stamp.GetNanoSec()/1000000000.;
  //
  static TTimeStamp stampOld;
  static CpuInfo_t  cpuInfoOld;
  static MemInfo_t  memInfoOld;
  static ProcInfo_t procInfoOld;
  Double_t fileBytesRead    = TFile::GetFileBytesRead();
  Double_t fileBytesWritten = TFile::GetFileBytesWritten();
  Double_t fileCounter      = TFile::GetFileCounter();
  Double_t fileReadCalls    = TFile::GetFileReadCalls();

  (*(Instance()->fSysWatch))
    << hname   <<"\t"               // hname - hostname
    << sname    <<"\t"              // stamp name
    << id0      <<"\t"
    << id1      <<"\t"
    << id2      <<"\t"
    << id3      <<"\t"
    <<setprecision(15)<< first    <<"\t"              // first stamp
    //
    <<setprecision(15)<< stamp.GetSec()+stamp.GetNanoSec()/1000000000.<<"\t"         // time  - time stamp in seconds
    << memInfo.fMemUsed<<"\t"       // system info
    << memInfo.fSwapUsed<<"\t"      //
    << cpuInfo.fUser <<"\t"         //
    << cpuInfo.fSys  <<"\t"         //
    << cpuInfo.fLoad1m  <<"\t"         //
    << cpuInfo.fLoad5m  <<"\t"         //
    << cpuInfo.fLoad15m  <<"\t"         //
    //
    <<setprecision(15)<< procInfo.fMemResident/1024.<<"\t"  // process info
    <<setprecision(15)<< procInfo.fMemVirtual/1024.<<"\t"   //
    << procInfo.fCpuUser<<"\t"      //
    << procInfo.fCpuSys<<"\t"       //
    //
    <<setprecision(15)<< stampOld.GetSec()+stampOld.GetNanoSec()/1000000000.<<"\t"         // time  - time stamp in seconds
    << memInfoOld.fMemUsed<<"\t"       // system info - previous
    << memInfoOld.fSwapUsed<<"\t"      //
    << cpuInfoOld.fUser <<"\t"         //
    << cpuInfoOld.fSys  <<"\t"         //
    //
    <<setprecision(15)<< procInfoOld.fMemResident/1024.<<"\t"  // process info -previous
    <<setprecision(15)<< procInfoOld.fMemVirtual/1024.<<"\t"   //
    << procInfoOld.fCpuUser<<"\t"      //
    << procInfoOld.fCpuSys<<"\t"       //
    //
    <<fileBytesRead<<"\t"           // file IO information
    <<fileBytesWritten<<"\t"        //
    <<fileCounter<<"\t"             //
    <<fileReadCalls<<"\t"            //
    << endl;

  stampOld   = stamp;
  cpuInfoOld = cpuInfo;
  memInfoOld = memInfo;
  procInfoOld= procInfo;

  //  if (fInstance->fMemStat) fInstance->fMemStat->AddStamps(sname);
  for (Int_t icallback=0; icallback<Instance()->fNCallBack; icallback++){
    Instance()->fCallBackFunc[icallback](sname);
  }
  entry++;
}

TTree * AliSysInfo::MakeTree(const char *lname){
  // char * lname = "syswatch.log"
  TTree * tree = new TTree;
  tree->ReadFile(lname);
  tree->SetAlias("deltaT","stampSec-stampOldSec");
  tree->SetAlias("T","stampSec-first");
  tree->SetAlias("deltaVM","(pI.fMemVirtual-pIOld.fMemVirtual)");
  tree->SetAlias("VM","pI.fMemVirtual");
  return tree;
}

Bool_t AliSysInfo::Contain(const char * str1, const char * str2){
  //
  //
  //
  TString str(str1);
  return str.Contains(str2);
}

void AliSysInfo::OpenMemStat(){
  //
  //
  //
  //USE IFDEF if MEMSTAT ENABLED
  //  Instance()->fMemStat = TMemStatManager::GetInstance();
  //   Instance()->fMemStat->SetAutoStamp(10000000, 10000000,1000000);
  //   Instance()->fMemStat->Enable();
}

void AliSysInfo::CloseMemStat(){
  //
  //
  //
  //USE IFDEF if MEMSTAT ENABLED
  //if (Instance()->fMemStat  == TMemStatManager::GetInstance()) Instance()->fMemStat->Close();
  //Instance()->fMemStat=0;
}

void AliSysInfo::AddCallBack(StampCallback_t callback){
  //
  // add cal back function
  //
  AliSysInfo *info =  Instance();
  if (!info->fCallBackFunc)
    info->fCallBackFunc = new StampCallback_t[100];
  info->fCallBackFunc[info->fNCallBack]=callback;
  info->fNCallBack++;
}

TTree*  AliSysInfo::Test(){
  //
  // Test example for AliSysInfo:
  // 1. Make huge memory leak
  // 2. Slow down execution
  /*
    To use the test:
    TTree * tree = AliSysInfo::Test();
    // Make alias what we set as input
    tree->SetAlias("deltaVMIn","(id0*100000+id1*10000+id2*1000)/1000000.")
    tree->SetAlias("deltaVM","(pI.fMemVirtual-pIOld.fMemVirtual)");
    tree->SetAlias("deltaTIn","(id1+id0*10)");
    tree->SetAlias("deltaT","stampSec-stampOldSec");
    //
    tree->SetMarkerStyle(23); tree->SetMarkerSize(0.5);
    // Memory usage
    tree->Draw("deltaVM:deltaVMIn","Entry$>0");
    // or alternative
    tree->Draw("deltaVM:deltaVMIn","Entry$>0","prof");
    //
    // draw time usage
    tree->Draw("deltaT:deltaTIn","Entry$>0");
  */
  //
  // The delta of VM as obtained from the AliSysInfo starts to be proportional
  // to  the input allocation after 0.12 MBy (and it is system dependent)
  // Bellow these limit the deltaVM can be used only in mean.
  // (compare first and  profile histogram)
  for (Int_t id0=0; id0<5; id0++)
    for (Int_t id1=1; id1<10; id1++)
      for (Int_t id2=0; id2<20; id2++){
	new Char_t[id2*1000+id1*10000+id0*100000];  // emulate memory leak
	gSystem->Sleep(id1+id0*10);         // emulate CPU usage
	AliSysInfo::AddStamp("Leak",id0,id1,id2);
      }
  TTree * tree = AliSysInfo::MakeTree("syswatch.log");
  return tree;
}

Double_t AliSysInfo::EstimateObjectSize(TObject* object){
  //
  // Estimate size of object as represented in the memory size in bytes
  // Warnings:
  //  1. Only data memebrs which are persistent are counted
  //  2. Local copy of the object is temporary created in memory
  //  3. Do not use it in standard programs, time and memory consument procedure
  //
  if (!object) return 0;
  TBufferFile * file = new TBufferFile(TBuffer::kWrite);
  file->WriteObject(object);
  Double_t size=file->Length();
  delete file;
  return size;
}
<|endoftext|>


<commit_before>//
// Copyright (c) 2013-2014 Christoph Malek
// See LICENSE for more information.
//

#ifndef RJ_GAME_EDITOR_MOUSE_HPP
#define RJ_GAME_EDITOR_MOUSE_HPP

#include "editor_entity.hpp"
#include <rectojump/shared/input.hpp>
#include <rectojump/global/config_settings.hpp>

namespace rj
{
	class editor_mouse
	{
		rndr& m_render;

		editor_entity m_mouse_shape{{0.f, 0.f}};
		bool m_active{true};

	public:
		editor_mouse(rndr& r) :
			m_render{r}
		{

		}

		void update(dur duration)
		{
			auto new_pos(get_mousepos());
			m_mouse_shape.render_object().setPosition(new_pos);
		}

		void render()
		{
			if(m_active)
				m_render(m_mouse_shape.render_object());
		}

		void clear() noexcept
		{m_mouse_shape.render_object().setTexture(nullptr); m_active = false;}

		void set_texture(const sf::Texture* tx) noexcept
		{m_mouse_shape.render_object().setTexture(tx); m_active = true;}

		const sf::Texture* get_texture() noexcept
		{return m_mouse_shape.render_object().getTexture();}
	};
}

#endif // RJ_GAME_EDITOR_MOUSE_HPP
<commit_msg>editor/mouse: added a round_to<commit_after>//
// Copyright (c) 2013-2014 Christoph Malek
// See LICENSE for more information.
//

#ifndef RJ_GAME_EDITOR_MOUSE_HPP
#define RJ_GAME_EDITOR_MOUSE_HPP

#include "editor_entity.hpp"
#include <rectojump/shared/input.hpp>
#include <rectojump/global/config_settings.hpp>

namespace rj
{
	class editor_mouse
	{
		rndr& m_render;

		editor_entity m_mouse_shape{{0.f, 0.f}};
		bool m_active{true};

	public:
		editor_mouse(rndr& r) :
			m_render{r}
		{

		}

		void update(dur duration)
		{
			auto mousepos(get_mousepos());
			vec2f new_pos{round_to(mousepos.x, 48.f), round_to(mousepos.y, 48.f)};
			m_mouse_shape.render_object().setPosition(new_pos);
		}

		void render()
		{
			if(m_active)
				m_render(m_mouse_shape.render_object());
		}

		void clear() noexcept
		{m_mouse_shape.render_object().setTexture(nullptr); m_active = false;}

		void set_texture(const sf::Texture* tx) noexcept
		{m_mouse_shape.render_object().setTexture(tx); m_active = true;}

		const sf::Texture* get_texture() noexcept
		{return m_mouse_shape.render_object().getTexture();}
	};
}

#endif // RJ_GAME_EDITOR_MOUSE_HPP
<|endoftext|>


<commit_before>/*
 * Copyright 2015 Real Logic Ltd.
 *
 * 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 <cstdint>
#include <cstdio>
#include <signal.h>
#include <util/CommandOptionParser.h>
#include <thread>
#include <Aeron.h>
#include <array>
#include <concurrent/BusySpinIdleStrategy.h>
#include "FragmentAssembler.h"
#include "Configuration.h"

extern "C"
{
#include <hdr_histogram.h>
}

using namespace std::chrono;
using namespace aeron::util;
using namespace aeron;

std::atomic<bool> running (true);

void sigIntHandler (int param)
{
    running = false;
}

static const char optHelp         = 'h';
static const char optPrefix       = 'p';
static const char optPingChannel  = 'c';
static const char optPongChannel  = 'C';
static const char optPingStreamId = 's';
static const char optPongStreamId = 'S';
static const char optFrags        = 'f';
static const char optMessages     = 'm';
static const char optLength       = 'L';

struct Settings
{
    std::string dirPrefix = "";
    std::string pingChannel = samples::configuration::DEFAULT_PING_CHANNEL;
    std::string pongChannel = samples::configuration::DEFAULT_PONG_CHANNEL;
    std::int32_t pingStreamId = samples::configuration::DEFAULT_PING_STREAM_ID;
    std::int32_t pongStreamId = samples::configuration::DEFAULT_PONG_STREAM_ID;
    long numberOfMessages = samples::configuration::DEFAULT_NUMBER_OF_MESSAGES;
    int messageLength = samples::configuration::DEFAULT_MESSAGE_LENGTH;
    int fragmentCountLimit = samples::configuration::DEFAULT_FRAGMENT_COUNT_LIMIT;
};

Settings parseCmdLine(CommandOptionParser& cp, int argc, char** argv)
{
    cp.parse(argc, argv);
    if (cp.getOption(optHelp).isPresent())
    {
        cp.displayOptionsHelp(std::cout);
        exit(0);
    }

    Settings s;

    s.dirPrefix = cp.getOption(optPrefix).getParam(0, s.dirPrefix);
    s.pingChannel = cp.getOption(optPingChannel).getParam(0, s.pingChannel);
    s.pongChannel = cp.getOption(optPongChannel).getParam(0, s.pongChannel);
    s.pingStreamId = cp.getOption(optPingStreamId).getParamAsInt(0, 1, INT32_MAX, s.pingStreamId);
    s.pongStreamId = cp.getOption(optPongStreamId).getParamAsInt(0, 1, INT32_MAX, s.pongStreamId);
    s.numberOfMessages = cp.getOption(optMessages).getParamAsLong(0, 0, INT64_MAX, s.numberOfMessages);
    s.messageLength = cp.getOption(optLength).getParamAsInt(0, sizeof(std::int64_t), INT32_MAX, s.messageLength);
    s.fragmentCountLimit = cp.getOption(optFrags).getParamAsInt(0, 1, INT32_MAX, s.fragmentCountLimit);
    return s;
}

void sendPingAndReceivePong(
    const fragment_handler_t& fragmentHandler,
    std::shared_ptr<Publication> publication,
    std::shared_ptr<Subscription> subscription,
    Settings& settings)
{
    AERON_DECL_ALIGNED(std::uint8_t buffer[settings.messageLength], 16);
    concurrent::AtomicBuffer srcBuffer(buffer, settings.messageLength);
    BusySpinIdleStrategy idleStrategy;

    for (int i = 0; i < settings.numberOfMessages; i++)
    {
        do
        {
            // timestamps in the message are relative to this app, so just send the timepoint directly.
            steady_clock::time_point start = steady_clock::now();

            srcBuffer.putBytes(0, (std::uint8_t*)&start, sizeof(steady_clock::time_point));
        }
        while (publication->offer(srcBuffer, 0, settings.messageLength) < 0L);

        while (subscription->poll(fragmentHandler, settings.fragmentCountLimit) <= 0)
        {
            idleStrategy.idle(0);
        }
    }
}

int main(int argc, char **argv)
{
    CommandOptionParser cp;
    cp.addOption(CommandOption (optHelp,         0, 0, "                Displays help information."));
    cp.addOption(CommandOption (optPrefix,       1, 1, "dir             Prefix directory for aeron driver."));
    cp.addOption(CommandOption (optPingChannel,  1, 1, "channel         Ping Channel."));
    cp.addOption(CommandOption (optPongChannel,  1, 1, "channel         Pong Channel."));
    cp.addOption(CommandOption (optPingStreamId, 1, 1, "streamId        Ping Stream ID."));
    cp.addOption(CommandOption (optPongStreamId, 1, 1, "streamId        Pong Stream ID."));
    cp.addOption(CommandOption (optMessages,     1, 1, "number          Number of Messages."));
    cp.addOption(CommandOption (optLength,       1, 1, "length          Length of Messages."));
    cp.addOption(CommandOption (optFrags,        1, 1, "limit           Fragment Count Limit."));

    signal (SIGINT, sigIntHandler);

    try
    {
        Settings settings = parseCmdLine(cp, argc, argv);

        std::cout << "Subscribing Pong at " << settings.pongChannel << " on Stream ID " << settings.pongStreamId << std::endl;
        std::cout << "Publishing Ping at " << settings.pingChannel << " on Stream ID " << settings.pingStreamId << std::endl;

        aeron::Context context;
        std::atomic<int> countDown(1);

        if (settings.dirPrefix != "")
        {
            context.aeronDir(settings.dirPrefix);
        }

        context.newSubscriptionHandler(
            [](const std::string& channel, std::int32_t streamId, std::int64_t correlationId)
            {
                std::cout << "Subscription: " << channel << " " << correlationId << ":" << streamId << std::endl;
            });

        context.newPublicationHandler(
            [](const std::string& channel, std::int32_t streamId, std::int32_t sessionId, std::int64_t correlationId)
            {
                std::cout << "Publication: " << channel << " " << correlationId << ":" << streamId << ":" << sessionId << std::endl;
            });

        context.availableImageHandler([&](
            Image &image,
            const std::string &channel,
            std::int32_t streamId,
            std::int32_t sessionId,
            std::int64_t joiningPosition,
            const std::string &sourceIdentity)
        {
            std::cout << "Available image on " << channel << " streamId=" << streamId << " sessionId=" << sessionId;
            std::cout << " at position=" << joiningPosition << " from " << sourceIdentity << std::endl;

            if (channel == settings.pongChannel && streamId == settings.pongStreamId)
            {
                countDown--;
            }
        });

        context.unavailableImageHandler(
            [](Image &image, const std::string &channel, std::int32_t streamId, std::int32_t sessionId,
                std::int64_t position)
            {
                std::cout << "Unavailable image on " << channel << "streamId=" << streamId << " sessionId=" << sessionId;
                std::cout << " at position=" << position << std::endl;
            });

        Aeron aeron(context);

        std::int64_t subscriptionId = aeron.addSubscription(settings.pongChannel, settings.pongStreamId);
        std::int64_t publicationId = aeron.addPublication(settings.pingChannel, settings.pingStreamId);

        std::shared_ptr<Subscription> pongSubscription = aeron.findSubscription(subscriptionId);
        while (!pongSubscription)
        {
            std::this_thread::yield();
            pongSubscription = aeron.findSubscription(subscriptionId);
        }

        std::shared_ptr<Publication> pingPublication = aeron.findPublication(publicationId);
        while (!pingPublication)
        {
            std::this_thread::yield();
            pingPublication = aeron.findPublication(publicationId);
        }

        while (countDown > 0)
        {
            std::this_thread::yield();
        }

        hdr_histogram* histogram;
        hdr_init(1, 10 * 1000 * 1000 * 1000, 3, &histogram);

        do
        {
            hdr_reset(histogram);

            FragmentAssembler fragmentAssembler(
                [&](AtomicBuffer& buffer, index_t offset, index_t length, Header& header)
                {
                    steady_clock::time_point end = steady_clock::now();
                    steady_clock::time_point start;

                    buffer.getBytes(offset, (std::uint8_t*)&start, sizeof(steady_clock::time_point));
                    std::int64_t nanoRtt = duration<std::int64_t, std::nano>(end - start).count();

                    hdr_record_value(histogram, nanoRtt);
                });

            ::setlocale(LC_NUMERIC, "");
            printf("Pinging %'ld messages of length %d bytes\n", settings.numberOfMessages, settings.messageLength);

            sendPingAndReceivePong(fragmentAssembler.handler(), pingPublication, pongSubscription, settings);

            hdr_percentiles_print(histogram, stdout, 5, 1000.0, CLASSIC);
            fflush(stdout);
        }
        while (running && continuationBarrier("Execute again?"));

    }
    catch (CommandOptionException& e)
    {
        std::cerr << "ERROR: " << e.what() << std::endl << std::endl;
        cp.displayOptionsHelp(std::cerr);
        return -1;
    }
    catch (SourcedException& e)
    {
        std::cerr << "FAILED: " << e.what() << " : " << e.where() << std::endl;
        return -1;
    }
    catch (std::exception& e)
    {
        std::cerr << "FAILED: " << e.what() << " : " << std::endl;
        return -1;
    }

    return 0;
}
<commit_msg>[c++]: Fix warning on literal for overflow.<commit_after>/*
 * Copyright 2015 Real Logic Ltd.
 *
 * 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 <cstdint>
#include <cstdio>
#include <signal.h>
#include <util/CommandOptionParser.h>
#include <thread>
#include <Aeron.h>
#include <array>
#include <concurrent/BusySpinIdleStrategy.h>
#include "FragmentAssembler.h"
#include "Configuration.h"

extern "C"
{
#include <hdr_histogram.h>
}

using namespace std::chrono;
using namespace aeron::util;
using namespace aeron;

std::atomic<bool> running (true);

void sigIntHandler (int param)
{
    running = false;
}

static const char optHelp         = 'h';
static const char optPrefix       = 'p';
static const char optPingChannel  = 'c';
static const char optPongChannel  = 'C';
static const char optPingStreamId = 's';
static const char optPongStreamId = 'S';
static const char optFrags        = 'f';
static const char optMessages     = 'm';
static const char optLength       = 'L';

struct Settings
{
    std::string dirPrefix = "";
    std::string pingChannel = samples::configuration::DEFAULT_PING_CHANNEL;
    std::string pongChannel = samples::configuration::DEFAULT_PONG_CHANNEL;
    std::int32_t pingStreamId = samples::configuration::DEFAULT_PING_STREAM_ID;
    std::int32_t pongStreamId = samples::configuration::DEFAULT_PONG_STREAM_ID;
    long numberOfMessages = samples::configuration::DEFAULT_NUMBER_OF_MESSAGES;
    int messageLength = samples::configuration::DEFAULT_MESSAGE_LENGTH;
    int fragmentCountLimit = samples::configuration::DEFAULT_FRAGMENT_COUNT_LIMIT;
};

Settings parseCmdLine(CommandOptionParser& cp, int argc, char** argv)
{
    cp.parse(argc, argv);
    if (cp.getOption(optHelp).isPresent())
    {
        cp.displayOptionsHelp(std::cout);
        exit(0);
    }

    Settings s;

    s.dirPrefix = cp.getOption(optPrefix).getParam(0, s.dirPrefix);
    s.pingChannel = cp.getOption(optPingChannel).getParam(0, s.pingChannel);
    s.pongChannel = cp.getOption(optPongChannel).getParam(0, s.pongChannel);
    s.pingStreamId = cp.getOption(optPingStreamId).getParamAsInt(0, 1, INT32_MAX, s.pingStreamId);
    s.pongStreamId = cp.getOption(optPongStreamId).getParamAsInt(0, 1, INT32_MAX, s.pongStreamId);
    s.numberOfMessages = cp.getOption(optMessages).getParamAsLong(0, 0, INT64_MAX, s.numberOfMessages);
    s.messageLength = cp.getOption(optLength).getParamAsInt(0, sizeof(std::int64_t), INT32_MAX, s.messageLength);
    s.fragmentCountLimit = cp.getOption(optFrags).getParamAsInt(0, 1, INT32_MAX, s.fragmentCountLimit);
    return s;
}

void sendPingAndReceivePong(
    const fragment_handler_t& fragmentHandler,
    std::shared_ptr<Publication> publication,
    std::shared_ptr<Subscription> subscription,
    Settings& settings)
{
    AERON_DECL_ALIGNED(std::uint8_t buffer[settings.messageLength], 16);
    concurrent::AtomicBuffer srcBuffer(buffer, settings.messageLength);
    BusySpinIdleStrategy idleStrategy;

    for (int i = 0; i < settings.numberOfMessages; i++)
    {
        do
        {
            // timestamps in the message are relative to this app, so just send the timepoint directly.
            steady_clock::time_point start = steady_clock::now();

            srcBuffer.putBytes(0, (std::uint8_t*)&start, sizeof(steady_clock::time_point));
        }
        while (publication->offer(srcBuffer, 0, settings.messageLength) < 0L);

        while (subscription->poll(fragmentHandler, settings.fragmentCountLimit) <= 0)
        {
            idleStrategy.idle(0);
        }
    }
}

int main(int argc, char **argv)
{
    CommandOptionParser cp;
    cp.addOption(CommandOption (optHelp,         0, 0, "                Displays help information."));
    cp.addOption(CommandOption (optPrefix,       1, 1, "dir             Prefix directory for aeron driver."));
    cp.addOption(CommandOption (optPingChannel,  1, 1, "channel         Ping Channel."));
    cp.addOption(CommandOption (optPongChannel,  1, 1, "channel         Pong Channel."));
    cp.addOption(CommandOption (optPingStreamId, 1, 1, "streamId        Ping Stream ID."));
    cp.addOption(CommandOption (optPongStreamId, 1, 1, "streamId        Pong Stream ID."));
    cp.addOption(CommandOption (optMessages,     1, 1, "number          Number of Messages."));
    cp.addOption(CommandOption (optLength,       1, 1, "length          Length of Messages."));
    cp.addOption(CommandOption (optFrags,        1, 1, "limit           Fragment Count Limit."));

    signal (SIGINT, sigIntHandler);

    try
    {
        Settings settings = parseCmdLine(cp, argc, argv);

        std::cout << "Subscribing Pong at " << settings.pongChannel << " on Stream ID " << settings.pongStreamId << std::endl;
        std::cout << "Publishing Ping at " << settings.pingChannel << " on Stream ID " << settings.pingStreamId << std::endl;

        aeron::Context context;
        std::atomic<int> countDown(1);

        if (settings.dirPrefix != "")
        {
            context.aeronDir(settings.dirPrefix);
        }

        context.newSubscriptionHandler(
            [](const std::string& channel, std::int32_t streamId, std::int64_t correlationId)
            {
                std::cout << "Subscription: " << channel << " " << correlationId << ":" << streamId << std::endl;
            });

        context.newPublicationHandler(
            [](const std::string& channel, std::int32_t streamId, std::int32_t sessionId, std::int64_t correlationId)
            {
                std::cout << "Publication: " << channel << " " << correlationId << ":" << streamId << ":" << sessionId << std::endl;
            });

        context.availableImageHandler([&](
            Image &image,
            const std::string &channel,
            std::int32_t streamId,
            std::int32_t sessionId,
            std::int64_t joiningPosition,
            const std::string &sourceIdentity)
        {
            std::cout << "Available image on " << channel << " streamId=" << streamId << " sessionId=" << sessionId;
            std::cout << " at position=" << joiningPosition << " from " << sourceIdentity << std::endl;

            if (channel == settings.pongChannel && streamId == settings.pongStreamId)
            {
                countDown--;
            }
        });

        context.unavailableImageHandler(
            [](Image &image, const std::string &channel, std::int32_t streamId, std::int32_t sessionId,
                std::int64_t position)
            {
                std::cout << "Unavailable image on " << channel << "streamId=" << streamId << " sessionId=" << sessionId;
                std::cout << " at position=" << position << std::endl;
            });

        Aeron aeron(context);

        std::int64_t subscriptionId = aeron.addSubscription(settings.pongChannel, settings.pongStreamId);
        std::int64_t publicationId = aeron.addPublication(settings.pingChannel, settings.pingStreamId);

        std::shared_ptr<Subscription> pongSubscription = aeron.findSubscription(subscriptionId);
        while (!pongSubscription)
        {
            std::this_thread::yield();
            pongSubscription = aeron.findSubscription(subscriptionId);
        }

        std::shared_ptr<Publication> pingPublication = aeron.findPublication(publicationId);
        while (!pingPublication)
        {
            std::this_thread::yield();
            pingPublication = aeron.findPublication(publicationId);
        }

        while (countDown > 0)
        {
            std::this_thread::yield();
        }

        hdr_histogram* histogram;
        hdr_init(1, 10 * 1000 * 1000 * 1000L, 3, &histogram);

        do
        {
            hdr_reset(histogram);

            FragmentAssembler fragmentAssembler(
                [&](AtomicBuffer& buffer, index_t offset, index_t length, Header& header)
                {
                    steady_clock::time_point end = steady_clock::now();
                    steady_clock::time_point start;

                    buffer.getBytes(offset, (std::uint8_t*)&start, sizeof(steady_clock::time_point));
                    std::int64_t nanoRtt = duration<std::int64_t, std::nano>(end - start).count();

                    hdr_record_value(histogram, nanoRtt);
                });

            ::setlocale(LC_NUMERIC, "");
            printf("Pinging %'ld messages of length %d bytes\n", settings.numberOfMessages, settings.messageLength);

            sendPingAndReceivePong(fragmentAssembler.handler(), pingPublication, pongSubscription, settings);

            hdr_percentiles_print(histogram, stdout, 5, 1000.0, CLASSIC);
            fflush(stdout);
        }
        while (running && continuationBarrier("Execute again?"));

    }
    catch (CommandOptionException& e)
    {
        std::cerr << "ERROR: " << e.what() << std::endl << std::endl;
        cp.displayOptionsHelp(std::cerr);
        return -1;
    }
    catch (SourcedException& e)
    {
        std::cerr << "FAILED: " << e.what() << " : " << e.where() << std::endl;
        return -1;
    }
    catch (std::exception& e)
    {
        std::cerr << "FAILED: " << e.what() << " : " << std::endl;
        return -1;
    }

    return 0;
}
<|endoftext|>