<commit_before>// ---------------------------------------------------------------------
// $Id: tria.cc 32807 2014-04-22 15:01:57Z heister $
//
// Copyright (C) 2015 - 2017 by the deal.II authors
//
// This file is part of the deal.II library.
//
// The deal.II library is free software; you can use it, 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.
// The full text of the license can be found in the file LICENSE at
// the top level of the deal.II distribution.
//
// ---------------------------------------------------------------------

#include <deal.II/base/utilities.h>
#include <deal.II/base/mpi.h>
#include <deal.II/grid/tria.h>
#include <deal.II/grid/tria_accessor.h>
#include <deal.II/grid/tria_iterator.h>
#include <deal.II/grid/grid_tools.h>
#include <deal.II/grid/filtered_iterator.h>
#include <deal.II/lac/sparsity_tools.h>
#include <deal.II/distributed/shared_tria.h>
#include <deal.II/distributed/tria.h>

DEAL_II_NAMESPACE_OPEN

#ifdef DEAL_II_WITH_MPI
namespace parallel
{
  namespace shared
  {

    template <int dim, int spacedim>
    Triangulation<dim,spacedim>::Triangulation (MPI_Comm mpi_communicator,
                                                const typename dealii::Triangulation<dim,spacedim>::MeshSmoothing smooth_grid,
                                                const bool allow_artificial_cells,
                                                const Settings settings):
      dealii::parallel::Triangulation<dim,spacedim>(mpi_communicator,smooth_grid,false),
      settings (settings),
      allow_artificial_cells(allow_artificial_cells)
    {
      const auto partition_settings
        = (partition_zoltan | partition_metis |
           partition_zorder | partition_custom_signal) & settings;
      Assert(partition_settings == partition_auto ||
             partition_settings == partition_metis ||
             partition_settings == partition_zoltan ||
             partition_settings == partition_zorder ||
             partition_settings == partition_custom_signal,
             ExcMessage ("Settings must contain exactly one type of the active cell partitioning scheme."))

      if (settings & construct_multigrid_hierarchy)
        Assert(allow_artificial_cells,
               ExcMessage ("construct_multigrid_hierarchy requires allow_artificial_cells to be set to true."))
      }

    template <int dim, int spacedim>
    void Triangulation<dim,spacedim>::partition()
    {
#ifdef DEBUG
      // Check that all meshes are the same (or at least have the same
      // total number of active cells):
      const unsigned int max_active_cells
        = Utilities::MPI::max(this->n_active_cells(), this->get_communicator());
      Assert(max_active_cells == this->n_active_cells(),
             ExcMessage("A parallel::shared::Triangulation needs to be refined in the same"
                        "way on all processors, but the participating processors don't "
                        "agree on the number of active cells."))
#endif

      auto partition_settings
        = (partition_zoltan | partition_metis |
           partition_zorder | partition_custom_signal) & settings;
      if (partition_settings == partition_auto)
#ifdef DEAL_II_TRILINOS_WITH_ZOLTAN
        partition_settings = partition_zoltan;
#elif defined DEAL_II_WITH_METIS
        partition_settings = partition_metis;
#else
        partition_settings = partition_zorder;
#endif

      if (partition_settings == partition_zoltan)
        {
#ifndef DEAL_II_TRILINOS_WITH_ZOLTAN
          AssertThrow (false,
                       ExcMessage("Choosing 'partition_zoltan' requires the library "
                                  "to be compiled with support for Zoltan! "
                                  "Instead, you might use 'partition_auto' to select "
                                  "a partitioning algorithm that is supported "
                                  "by your current configuration."));
#else
          GridTools::partition_triangulation (this->n_subdomains, *this,
                                              SparsityTools::Partitioner::zoltan);
#endif
        }
      else if (partition_settings == partition_metis)
        {
#ifndef DEAL_II_WITH_METIS
          AssertThrow (false,
                       ExcMessage("Choosing 'partition_metis' requires the library "
                                  "to be compiled with support for METIS! "
                                  "Instead, you might use 'partition_auto' to select "
                                  "a partitioning algorithm that is supported "
                                  "by your current configuration."));
#else
          GridTools::partition_triangulation (this->n_subdomains, *this,
                                              SparsityTools::Partitioner::metis);
#endif
        }
      else if (partition_settings == partition_zorder)
        {
          GridTools::partition_triangulation_zorder (this->n_subdomains, *this);
        }
      else if (partition_settings == partition_custom_signal)
        {
          // User partitions mesh manually
        }
      else
        {
          AssertThrow(false, ExcInternalError())
        }

      // do not partition multigrid levels if user is
      // defining a custom partition
      if ((settings & construct_multigrid_hierarchy) && !(settings & partition_custom_signal))
        dealii::GridTools::partition_multigrid_levels(*this);

      true_subdomain_ids_of_cells.resize(this->n_active_cells());

      // loop over all cells and mark artificial:
      typename parallel::shared::Triangulation<dim,spacedim>::active_cell_iterator
      cell = this->begin_active(),
      endc = this->end();

      if (allow_artificial_cells)
        {
          // get active halo layer of (ghost) cells
          // parallel::shared::Triangulation<dim>::
          std::function<bool (const typename parallel::shared::Triangulation<dim,spacedim>::active_cell_iterator &)> predicate
            = IteratorFilters::SubdomainEqualTo(this->my_subdomain);

          const std::vector<typename parallel::shared::Triangulation<dim,spacedim>::active_cell_iterator>
          active_halo_layer_vector = dealii::GridTools::compute_active_cell_halo_layer (*this, predicate);
          std::set<typename parallel::shared::Triangulation<dim,spacedim>::active_cell_iterator>
          active_halo_layer(active_halo_layer_vector.begin(), active_halo_layer_vector.end());

          for (unsigned int index=0; cell != endc; cell++, index++)
            {
              // store original/true subdomain ids:
              true_subdomain_ids_of_cells[index] = cell->subdomain_id();

              if (cell->is_locally_owned() == false &&
                  active_halo_layer.find(cell) == active_halo_layer.end())
                cell->set_subdomain_id(numbers::artificial_subdomain_id);
            }

          // loop over all cells in multigrid hierarchy and mark artificial:
          if (settings & construct_multigrid_hierarchy)
            {
              true_level_subdomain_ids_of_cells.resize(this->n_levels());

              std::function<bool (const typename parallel::shared::Triangulation<dim,spacedim>::cell_iterator &)> predicate
                = IteratorFilters::LocallyOwnedLevelCell();
              for (unsigned int lvl=0; lvl<this->n_levels(); ++lvl)
                {
                  true_level_subdomain_ids_of_cells[lvl].resize(this->n_cells(lvl));

                  const std::vector<typename parallel::shared::Triangulation<dim,spacedim>::cell_iterator>
                  level_halo_layer_vector = dealii::GridTools::compute_cell_halo_layer_on_level (*this, predicate, lvl);
                  std::set<typename parallel::shared::Triangulation<dim,spacedim>::cell_iterator>
                  level_halo_layer(level_halo_layer_vector.begin(), level_halo_layer_vector.end());

                  typename parallel::shared::Triangulation<dim,spacedim>::cell_iterator
                  cell = this->begin(lvl),
                  endc = this->end(lvl);
                  for (unsigned int index=0; cell != endc; cell++, index++)
                    {
                      // Store true level subdomain IDs before setting artificial
                      true_level_subdomain_ids_of_cells[lvl][index] = cell->level_subdomain_id();

                      // for active cells, we must have knowledge of level subdomain ids of
                      // all neighbors to our subdomain, not just neighbors on the same level.
                      // if the cells subdomain id was not set to artitficial above, we will
                      // also keep its level subdomain id since it is either owned by this processor
                      // or in the ghost layer of the active mesh.
                      if (!cell->has_children() && cell->subdomain_id() != numbers::artificial_subdomain_id)
                        continue;

                      // we must have knowledge of our parent in the hierarchy
                      if (cell->has_children())
                        {
                          bool keep_cell = false;
                          for (unsigned int c=0; c<GeometryInfo<dim>::max_children_per_cell; ++c)
                            if (cell->child(c)->level_subdomain_id() == this->my_subdomain)
                              {
                                keep_cell = true;
                                break;
                              }
                          if (keep_cell)
                            continue;
                        }

                      // we must have knowledge of our neighbors on the same level
                      if (!cell->is_locally_owned_on_level() &&
                          level_halo_layer.find(cell) != level_halo_layer.end())
                        continue;

                      // mark all other cells to artificial
                      cell->set_level_subdomain_id(numbers::artificial_subdomain_id);
                    }
                }
            }
        }
      else
        {
          // just store true subdomain ids
          for (unsigned int index=0; cell != endc; cell++, index++)
            true_subdomain_ids_of_cells[index] = cell->subdomain_id();
        }

#ifdef DEBUG
      {
        // Assert that each cell is owned by a processor
        unsigned int n_my_cells = 0;
        typename parallel::shared::Triangulation<dim,spacedim>::active_cell_iterator
        cell = this->begin_active(),
        endc = this->end();
        for (; cell!=endc; ++cell)
          if (cell->is_locally_owned())
            n_my_cells += 1;

        const unsigned int total_cells
          = Utilities::MPI::sum(n_my_cells, this->get_communicator());
        Assert(total_cells == this->n_active_cells(),
               ExcMessage("Not all cells are assigned to a processor."))
      }

      // If running with multigrid, assert that each level
      // cell is owned by a processor
      if (settings & construct_multigrid_hierarchy)
        {
          unsigned int n_my_cells = 0;
          typename parallel::shared::Triangulation<dim,spacedim>::cell_iterator
          cell = this->begin(),
          endc = this->end();
          for (; cell!=endc; ++cell)
            if (cell->is_locally_owned_on_level())
              n_my_cells += 1;

          const unsigned int total_cells
            = Utilities::MPI::sum(n_my_cells, this->get_communicator());
          Assert(total_cells == this->n_cells(),
                 ExcMessage("Not all cells are assigned to a processor."))
        }
#endif
    }

    template <int dim, int spacedim>
    bool
    Triangulation<dim,spacedim>::with_artificial_cells() const
    {
      return allow_artificial_cells;
    }

    template <int dim, int spacedim>
    const std::vector<types::subdomain_id> &
    Triangulation<dim,spacedim>::get_true_subdomain_ids_of_cells() const
    {
      return true_subdomain_ids_of_cells;
    }

    template <int dim, int spacedim>
    const std::vector<types::subdomain_id> &
    Triangulation<dim,spacedim>::get_true_level_subdomain_ids_of_cells(const unsigned int level) const
    {
      return true_level_subdomain_ids_of_cells[level];
    }

    template <int dim, int spacedim>
    void
    Triangulation<dim,spacedim>::execute_coarsening_and_refinement ()
    {
      dealii::Triangulation<dim,spacedim>::execute_coarsening_and_refinement ();
      partition();
      this->update_number_cache ();
    }

    template <int dim, int spacedim>
    void
    Triangulation<dim,spacedim>::create_triangulation (const std::vector< Point< spacedim > > &vertices,
                                                       const std::vector< CellData< dim > > &cells,
                                                       const SubCellData &subcelldata)
    {
      try
        {
          dealii::Triangulation<dim,spacedim>::
          create_triangulation (vertices, cells, subcelldata);
        }
      catch (const typename dealii::Triangulation<dim,spacedim>::DistortedCellList &)
        {
          // the underlying triangulation should not be checking for distorted
          // cells
          Assert (false, ExcInternalError());
        }
      partition();
      this->update_number_cache ();
    }

    template <int dim, int spacedim>
    void
    Triangulation<dim, spacedim>::
    copy_triangulation (const dealii::Triangulation<dim, spacedim> &other_tria)
    {
      Assert ((dynamic_cast<const dealii::parallel::distributed::Triangulation<dim,spacedim> *>(&other_tria) == nullptr),
              ExcMessage("Cannot use this function on parallel::distributed::Triangulation."));

      dealii::parallel::Triangulation<dim,spacedim>::copy_triangulation (other_tria);
      partition();
      this->update_number_cache ();
    }

    template <int dim, int spacedim>
    void
    Triangulation<dim,spacedim>::
    update_number_cache ()
    {
      parallel::Triangulation<dim,spacedim>::update_number_cache();

      if (settings & construct_multigrid_hierarchy)
        parallel::Triangulation<dim,spacedim>::fill_level_ghost_owners();
    }
  }
}

#else

namespace parallel
{
  namespace shared
  {
    template <int dim, int spacedim>
    bool
    Triangulation<dim,spacedim>::with_artificial_cells() const
    {
      Assert (false, ExcNotImplemented());
      return true;
    }

    template <int dim, int spacedim>
    const std::vector<unsigned int> &
    Triangulation<dim,spacedim>::get_true_subdomain_ids_of_cells() const
    {
      Assert (false, ExcNotImplemented());
      return true_subdomain_ids_of_cells;
    }

    template <int dim, int spacedim>
    const std::vector<unsigned int> &
    Triangulation<dim,spacedim>::get_true_level_subdomain_ids_of_cells(const unsigned int) const
    {
      Assert (false, ExcNotImplemented());
      return true_level_subdomain_ids_of_cells;
    }
  }
}

#endif

/*-------------- Explicit Instantiations -------------------------------*/
#include "shared_tria.inst"

DEAL_II_NAMESPACE_CLOSE
<commit_msg>Remove an old svn tag.<commit_after>// ---------------------------------------------------------------------
//
// Copyright (C) 2015 - 2017 by the deal.II authors
//
// This file is part of the deal.II library.
//
// The deal.II library is free software; you can use it, 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.
// The full text of the license can be found in the file LICENSE at
// the top level of the deal.II distribution.
//
// ---------------------------------------------------------------------

#include <deal.II/base/utilities.h>
#include <deal.II/base/mpi.h>
#include <deal.II/grid/tria.h>
#include <deal.II/grid/tria_accessor.h>
#include <deal.II/grid/tria_iterator.h>
#include <deal.II/grid/grid_tools.h>
#include <deal.II/grid/filtered_iterator.h>
#include <deal.II/lac/sparsity_tools.h>
#include <deal.II/distributed/shared_tria.h>
#include <deal.II/distributed/tria.h>

DEAL_II_NAMESPACE_OPEN

#ifdef DEAL_II_WITH_MPI
namespace parallel
{
  namespace shared
  {

    template <int dim, int spacedim>
    Triangulation<dim,spacedim>::Triangulation (MPI_Comm mpi_communicator,
                                                const typename dealii::Triangulation<dim,spacedim>::MeshSmoothing smooth_grid,
                                                const bool allow_artificial_cells,
                                                const Settings settings):
      dealii::parallel::Triangulation<dim,spacedim>(mpi_communicator,smooth_grid,false),
      settings (settings),
      allow_artificial_cells(allow_artificial_cells)
    {
      const auto partition_settings
        = (partition_zoltan | partition_metis |
           partition_zorder | partition_custom_signal) & settings;
      Assert(partition_settings == partition_auto ||
             partition_settings == partition_metis ||
             partition_settings == partition_zoltan ||
             partition_settings == partition_zorder ||
             partition_settings == partition_custom_signal,
             ExcMessage ("Settings must contain exactly one type of the active cell partitioning scheme."))

      if (settings & construct_multigrid_hierarchy)
        Assert(allow_artificial_cells,
               ExcMessage ("construct_multigrid_hierarchy requires allow_artificial_cells to be set to true."))
      }

    template <int dim, int spacedim>
    void Triangulation<dim,spacedim>::partition()
    {
#ifdef DEBUG
      // Check that all meshes are the same (or at least have the same
      // total number of active cells):
      const unsigned int max_active_cells
        = Utilities::MPI::max(this->n_active_cells(), this->get_communicator());
      Assert(max_active_cells == this->n_active_cells(),
             ExcMessage("A parallel::shared::Triangulation needs to be refined in the same"
                        "way on all processors, but the participating processors don't "
                        "agree on the number of active cells."))
#endif

      auto partition_settings
        = (partition_zoltan | partition_metis |
           partition_zorder | partition_custom_signal) & settings;
      if (partition_settings == partition_auto)
#ifdef DEAL_II_TRILINOS_WITH_ZOLTAN
        partition_settings = partition_zoltan;
#elif defined DEAL_II_WITH_METIS
        partition_settings = partition_metis;
#else
        partition_settings = partition_zorder;
#endif

      if (partition_settings == partition_zoltan)
        {
#ifndef DEAL_II_TRILINOS_WITH_ZOLTAN
          AssertThrow (false,
                       ExcMessage("Choosing 'partition_zoltan' requires the library "
                                  "to be compiled with support for Zoltan! "
                                  "Instead, you might use 'partition_auto' to select "
                                  "a partitioning algorithm that is supported "
                                  "by your current configuration."));
#else
          GridTools::partition_triangulation (this->n_subdomains, *this,
                                              SparsityTools::Partitioner::zoltan);
#endif
        }
      else if (partition_settings == partition_metis)
        {
#ifndef DEAL_II_WITH_METIS
          AssertThrow (false,
                       ExcMessage("Choosing 'partition_metis' requires the library "
                                  "to be compiled with support for METIS! "
                                  "Instead, you might use 'partition_auto' to select "
                                  "a partitioning algorithm that is supported "
                                  "by your current configuration."));
#else
          GridTools::partition_triangulation (this->n_subdomains, *this,
                                              SparsityTools::Partitioner::metis);
#endif
        }
      else if (partition_settings == partition_zorder)
        {
          GridTools::partition_triangulation_zorder (this->n_subdomains, *this);
        }
      else if (partition_settings == partition_custom_signal)
        {
          // User partitions mesh manually
        }
      else
        {
          AssertThrow(false, ExcInternalError())
        }

      // do not partition multigrid levels if user is
      // defining a custom partition
      if ((settings & construct_multigrid_hierarchy) && !(settings & partition_custom_signal))
        dealii::GridTools::partition_multigrid_levels(*this);

      true_subdomain_ids_of_cells.resize(this->n_active_cells());

      // loop over all cells and mark artificial:
      typename parallel::shared::Triangulation<dim,spacedim>::active_cell_iterator
      cell = this->begin_active(),
      endc = this->end();

      if (allow_artificial_cells)
        {
          // get active halo layer of (ghost) cells
          // parallel::shared::Triangulation<dim>::
          std::function<bool (const typename parallel::shared::Triangulation<dim,spacedim>::active_cell_iterator &)> predicate
            = IteratorFilters::SubdomainEqualTo(this->my_subdomain);

          const std::vector<typename parallel::shared::Triangulation<dim,spacedim>::active_cell_iterator>
          active_halo_layer_vector = dealii::GridTools::compute_active_cell_halo_layer (*this, predicate);
          std::set<typename parallel::shared::Triangulation<dim,spacedim>::active_cell_iterator>
          active_halo_layer(active_halo_layer_vector.begin(), active_halo_layer_vector.end());

          for (unsigned int index=0; cell != endc; cell++, index++)
            {
              // store original/true subdomain ids:
              true_subdomain_ids_of_cells[index] = cell->subdomain_id();

              if (cell->is_locally_owned() == false &&
                  active_halo_layer.find(cell) == active_halo_layer.end())
                cell->set_subdomain_id(numbers::artificial_subdomain_id);
            }

          // loop over all cells in multigrid hierarchy and mark artificial:
          if (settings & construct_multigrid_hierarchy)
            {
              true_level_subdomain_ids_of_cells.resize(this->n_levels());

              std::function<bool (const typename parallel::shared::Triangulation<dim,spacedim>::cell_iterator &)> predicate
                = IteratorFilters::LocallyOwnedLevelCell();
              for (unsigned int lvl=0; lvl<this->n_levels(); ++lvl)
                {
                  true_level_subdomain_ids_of_cells[lvl].resize(this->n_cells(lvl));

                  const std::vector<typename parallel::shared::Triangulation<dim,spacedim>::cell_iterator>
                  level_halo_layer_vector = dealii::GridTools::compute_cell_halo_layer_on_level (*this, predicate, lvl);
                  std::set<typename parallel::shared::Triangulation<dim,spacedim>::cell_iterator>
                  level_halo_layer(level_halo_layer_vector.begin(), level_halo_layer_vector.end());

                  typename parallel::shared::Triangulation<dim,spacedim>::cell_iterator
                  cell = this->begin(lvl),
                  endc = this->end(lvl);
                  for (unsigned int index=0; cell != endc; cell++, index++)
                    {
                      // Store true level subdomain IDs before setting artificial
                      true_level_subdomain_ids_of_cells[lvl][index] = cell->level_subdomain_id();

                      // for active cells, we must have knowledge of level subdomain ids of
                      // all neighbors to our subdomain, not just neighbors on the same level.
                      // if the cells subdomain id was not set to artitficial above, we will
                      // also keep its level subdomain id since it is either owned by this processor
                      // or in the ghost layer of the active mesh.
                      if (!cell->has_children() && cell->subdomain_id() != numbers::artificial_subdomain_id)
                        continue;

                      // we must have knowledge of our parent in the hierarchy
                      if (cell->has_children())
                        {
                          bool keep_cell = false;
                          for (unsigned int c=0; c<GeometryInfo<dim>::max_children_per_cell; ++c)
                            if (cell->child(c)->level_subdomain_id() == this->my_subdomain)
                              {
                                keep_cell = true;
                                break;
                              }
                          if (keep_cell)
                            continue;
                        }

                      // we must have knowledge of our neighbors on the same level
                      if (!cell->is_locally_owned_on_level() &&
                          level_halo_layer.find(cell) != level_halo_layer.end())
                        continue;

                      // mark all other cells to artificial
                      cell->set_level_subdomain_id(numbers::artificial_subdomain_id);
                    }
                }
            }
        }
      else
        {
          // just store true subdomain ids
          for (unsigned int index=0; cell != endc; cell++, index++)
            true_subdomain_ids_of_cells[index] = cell->subdomain_id();
        }

#ifdef DEBUG
      {
        // Assert that each cell is owned by a processor
        unsigned int n_my_cells = 0;
        typename parallel::shared::Triangulation<dim,spacedim>::active_cell_iterator
        cell = this->begin_active(),
        endc = this->end();
        for (; cell!=endc; ++cell)
          if (cell->is_locally_owned())
            n_my_cells += 1;

        const unsigned int total_cells
          = Utilities::MPI::sum(n_my_cells, this->get_communicator());
        Assert(total_cells == this->n_active_cells(),
               ExcMessage("Not all cells are assigned to a processor."))
      }

      // If running with multigrid, assert that each level
      // cell is owned by a processor
      if (settings & construct_multigrid_hierarchy)
        {
          unsigned int n_my_cells = 0;
          typename parallel::shared::Triangulation<dim,spacedim>::cell_iterator
          cell = this->begin(),
          endc = this->end();
          for (; cell!=endc; ++cell)
            if (cell->is_locally_owned_on_level())
              n_my_cells += 1;

          const unsigned int total_cells
            = Utilities::MPI::sum(n_my_cells, this->get_communicator());
          Assert(total_cells == this->n_cells(),
                 ExcMessage("Not all cells are assigned to a processor."))
        }
#endif
    }

    template <int dim, int spacedim>
    bool
    Triangulation<dim,spacedim>::with_artificial_cells() const
    {
      return allow_artificial_cells;
    }

    template <int dim, int spacedim>
    const std::vector<types::subdomain_id> &
    Triangulation<dim,spacedim>::get_true_subdomain_ids_of_cells() const
    {
      return true_subdomain_ids_of_cells;
    }

    template <int dim, int spacedim>
    const std::vector<types::subdomain_id> &
    Triangulation<dim,spacedim>::get_true_level_subdomain_ids_of_cells(const unsigned int level) const
    {
      return true_level_subdomain_ids_of_cells[level];
    }

    template <int dim, int spacedim>
    void
    Triangulation<dim,spacedim>::execute_coarsening_and_refinement ()
    {
      dealii::Triangulation<dim,spacedim>::execute_coarsening_and_refinement ();
      partition();
      this->update_number_cache ();
    }

    template <int dim, int spacedim>
    void
    Triangulation<dim,spacedim>::create_triangulation (const std::vector< Point< spacedim > > &vertices,
                                                       const std::vector< CellData< dim > > &cells,
                                                       const SubCellData &subcelldata)
    {
      try
        {
          dealii::Triangulation<dim,spacedim>::
          create_triangulation (vertices, cells, subcelldata);
        }
      catch (const typename dealii::Triangulation<dim,spacedim>::DistortedCellList &)
        {
          // the underlying triangulation should not be checking for distorted
          // cells
          Assert (false, ExcInternalError());
        }
      partition();
      this->update_number_cache ();
    }

    template <int dim, int spacedim>
    void
    Triangulation<dim, spacedim>::
    copy_triangulation (const dealii::Triangulation<dim, spacedim> &other_tria)
    {
      Assert ((dynamic_cast<const dealii::parallel::distributed::Triangulation<dim,spacedim> *>(&other_tria) == nullptr),
              ExcMessage("Cannot use this function on parallel::distributed::Triangulation."));

      dealii::parallel::Triangulation<dim,spacedim>::copy_triangulation (other_tria);
      partition();
      this->update_number_cache ();
    }

    template <int dim, int spacedim>
    void
    Triangulation<dim,spacedim>::
    update_number_cache ()
    {
      parallel::Triangulation<dim,spacedim>::update_number_cache();

      if (settings & construct_multigrid_hierarchy)
        parallel::Triangulation<dim,spacedim>::fill_level_ghost_owners();
    }
  }
}

#else

namespace parallel
{
  namespace shared
  {
    template <int dim, int spacedim>
    bool
    Triangulation<dim,spacedim>::with_artificial_cells() const
    {
      Assert (false, ExcNotImplemented());
      return true;
    }

    template <int dim, int spacedim>
    const std::vector<unsigned int> &
    Triangulation<dim,spacedim>::get_true_subdomain_ids_of_cells() const
    {
      Assert (false, ExcNotImplemented());
      return true_subdomain_ids_of_cells;
    }

    template <int dim, int spacedim>
    const std::vector<unsigned int> &
    Triangulation<dim,spacedim>::get_true_level_subdomain_ids_of_cells(const unsigned int) const
    {
      Assert (false, ExcNotImplemented());
      return true_level_subdomain_ids_of_cells;
    }
  }
}

#endif

/*-------------- Explicit Instantiations -------------------------------*/
#include "shared_tria.inst"

DEAL_II_NAMESPACE_CLOSE
<|endoftext|>


<commit_before>// @(#)root/tree:$Id$
// Author: Rene Brun   14/04/97

/*************************************************************************
 * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers.               *
 * All rights reserved.                                                  *
 *                                                                       *
 * For the licensing terms see $ROOTSYS/LICENSE.                         *
 * For the list of contributors see $ROOTSYS/README/CREDITS.             *
 *************************************************************************/

////////////////////////////////////////////////////////////////////////////////
///
/// TCut
///
///  A specialized string object used for TTree selections.
///  A TCut object has a name and a title. It does not add any data
///  members compared to a TNamed. It only add a set of operators to
///  facilitate logical string concatenation. For example, assume
///
///     cut1 = "x<1"  and cut2 = "y>2"
///
/// then
///
///     cut1 && cut2 will be the string "(x<1)&&(y>2)"
///
///  Operators =, +=, +, *, !, &&, || overloaded.
///
/// Examples of use:
///
///     Root > TCut c1 = "x<1"
///     Root > TCut c2 = "y<0"
///     Root > TCut c3 = c1&&c2
///     Root > ntuple.Draw("x", c1)
///     Root > ntuple.Draw("x", c1||"x>0")
///     Root > ntuple.Draw("x", c1&&c2)
///     Root > ntuple.Draw("x", "(x+y)"*(c1&&c2))

#include "TCut.h"

ClassImp(TCut)

////////////////////////////////////////////////////////////////////////////////
/// Constructor.

TCut::TCut() : TNamed()
{
}

////////////////////////////////////////////////////////////////////////////////
/// Constructor.

TCut::TCut(const char *title) : TNamed("CUT",title)
{
}

////////////////////////////////////////////////////////////////////////////////
/// Constructor.

TCut::TCut(const char *name, const char *title) : TNamed(name,title)
{
}

////////////////////////////////////////////////////////////////////////////////
/// Copy Constructor.

TCut::TCut(const TCut &cut) : TNamed(cut)
{
}

////////////////////////////////////////////////////////////////////////////////
/// Typical destructor.

TCut::~TCut()
{
}

////////////////////////////////////////////////////////////////////////////////
/// Comparison.

Bool_t TCut::operator==(const char *rhs) const
{
   return fTitle == rhs;
}

////////////////////////////////////////////////////////////////////////////////
/// Comparison.

Bool_t TCut::operator==(const TCut &rhs) const
{
   return fTitle == rhs.fTitle;
}

////////////////////////////////////////////////////////////////////////////////
/// Comparison.

Bool_t TCut::operator!=(const char *rhs) const
{
   return fTitle != rhs;
}

////////////////////////////////////////////////////////////////////////////////
/// Comparison.

Bool_t TCut::operator!=(const TCut &rhs) const
{
   return fTitle != rhs.fTitle;
}

////////////////////////////////////////////////////////////////////////////////
/// Assignment.

TCut& TCut::operator=(const char *rhs)
{
   fTitle = rhs;
   return *this;
}

////////////////////////////////////////////////////////////////////////////////
/// Assignment.

TCut& TCut::operator=(const TCut& rhs)
{
   if (this != &rhs) TNamed::operator=(rhs);
   return *this;
}

////////////////////////////////////////////////////////////////////////////////
/// Addition.

TCut& TCut::operator+=(const char *rhs)
{
   if (!rhs || !rhs[0]) return *this;
   if (fTitle.Length() == 0)
      fTitle = rhs;
   else
      fTitle = "(" + fTitle + ")&&(" + TString(rhs) + ")";
   return *this;
}

////////////////////////////////////////////////////////////////////////////////
/// Addition.

TCut& TCut::operator+=(const TCut& rhs)
{
   if (rhs.fTitle.Length() == 0) return *this;
   if (fTitle.Length() == 0)
      fTitle = rhs;
   else
      fTitle = "(" + fTitle + ")&&(" + rhs.fTitle + ")";
   return *this;
}

////////////////////////////////////////////////////////////////////////////////
/// Multiplication.

TCut& TCut::operator*=(const char *rhs)
{
if (!rhs || !rhs[0]) return *this;
   if (fTitle.Length() == 0)
      fTitle = rhs;
   else
      fTitle = "(" + fTitle + ")*(" + TString(rhs) + ")";
   return *this;
}

////////////////////////////////////////////////////////////////////////////////
/// Multiplication.

TCut& TCut::operator*=(const TCut& rhs)
{
   if (rhs.fTitle.Length() == 0) return *this;
   if (fTitle.Length() == 0)
      fTitle = rhs;
   else
      fTitle = "(" + fTitle + ")*(" + rhs.fTitle + ")";
   return *this;
}

////////////////////////////////////////////////////////////////////////////////
/// Addition.

TCut operator+(const TCut& lhs, const char *rhs)
{
   return TCut(lhs) += rhs;
}

////////////////////////////////////////////////////////////////////////////////
/// Addition.

TCut operator+(const char *lhs, const TCut& rhs)
{
   return TCut(lhs) += rhs;
}

////////////////////////////////////////////////////////////////////////////////
/// Addition.

TCut operator+(const TCut& lhs, const TCut& rhs)
{
   return TCut(lhs) += rhs;
}

////////////////////////////////////////////////////////////////////////////////
/// Multiplication.

TCut operator*(const TCut& lhs, const char *rhs)
{
   return TCut(lhs) *= rhs;
}

////////////////////////////////////////////////////////////////////////////////
/// Multiplication.

TCut operator*(const char *lhs, const TCut& rhs)
{
   return TCut(lhs) *= rhs;
}

////////////////////////////////////////////////////////////////////////////////
/// Multiplication.

TCut operator*(const TCut& lhs, const TCut& rhs)
{
   return TCut(lhs) *= rhs;
}

////////////////////////////////////////////////////////////////////////////////
/// Logical and.

TCut operator&&(const TCut& lhs, const char *rhs)
{
   return TCut(lhs) += rhs;
}

////////////////////////////////////////////////////////////////////////////////
/// Logical and.

TCut operator&&(const char *lhs, const TCut& rhs)
{
   return TCut(lhs) += rhs;
}

////////////////////////////////////////////////////////////////////////////////
/// Logical and.

TCut operator&&(const TCut& lhs, const TCut& rhs)
{
   return TCut(lhs) += rhs;
}

////////////////////////////////////////////////////////////////////////////////
/// Logical or.

TCut operator||(const TCut& lhs, const char *rhs)
{
   if (lhs.fTitle.Length() == 0 && (!rhs || !rhs[0])) return TCut();
   if (lhs.fTitle.Length() == 0) return TCut(rhs);
   if (!rhs || !rhs[0]) return TCut(lhs);
   TString s = "(" + lhs.fTitle + ")||(" + TString(rhs) + ")";
   return TCut(s.Data());
}

////////////////////////////////////////////////////////////////////////////////
/// Logical or.

TCut operator||(const char *lhs, const TCut& rhs)
{
   if ((!lhs || !lhs[0]) && rhs.fTitle.Length() == 0) return TCut();
   if (!lhs || !lhs[0]) return TCut(rhs);
   if (rhs.fTitle.Length() == 0) return TCut(lhs);
   TString s = "(" + TString(lhs) + ")||(" + rhs.fTitle + ")";
   return TCut(s.Data());
}

////////////////////////////////////////////////////////////////////////////////
/// Logical or.

TCut operator||(const TCut& lhs, const TCut& rhs)
{
   if (lhs.fTitle.Length() == 0 && rhs.fTitle.Length() == 0) return TCut();
   if (lhs.fTitle.Length() == 0) return TCut(rhs);
   if (rhs.fTitle.Length() == 0) return TCut(lhs);
   TString s = "(" + lhs.fTitle + ")||(" + rhs.fTitle + ")";
   return TCut(s.Data());
}

////////////////////////////////////////////////////////////////////////////////
/// Logical negation.

TCut operator!(const TCut &rhs)
{
   if (rhs.fTitle.Length() == 0) return TCut();
   TString s = "!(" + rhs.fTitle + ")";
   return TCut(s.Data());
}

<commit_msg>Doxygen (\class was missing)<commit_after>// @(#)root/tree:$Id$
// Author: Rene Brun   14/04/97

/*************************************************************************
 * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers.               *
 * All rights reserved.                                                  *
 *                                                                       *
 * For the licensing terms see $ROOTSYS/LICENSE.                         *
 * For the list of contributors see $ROOTSYS/README/CREDITS.             *
 *************************************************************************/

////////////////////////////////////////////////////////////////////////////////
/// \class TCut
///
///  A specialized string object used for TTree selections.
///  A TCut object has a name and a title. It does not add any data
///  members compared to a TNamed. It only add a set of operators to
///  facilitate logical string concatenation. For example, assume
///
///     cut1 = "x<1"  and cut2 = "y>2"
///
/// then
///
///     cut1 && cut2 will be the string "(x<1)&&(y>2)"
///
///  Operators =, +=, +, *, !, &&, || overloaded.
///
/// Examples of use:
///
///     Root > TCut c1 = "x<1"
///     Root > TCut c2 = "y<0"
///     Root > TCut c3 = c1&&c2
///     Root > ntuple.Draw("x", c1)
///     Root > ntuple.Draw("x", c1||"x>0")
///     Root > ntuple.Draw("x", c1&&c2)
///     Root > ntuple.Draw("x", "(x+y)"*(c1&&c2))

#include "TCut.h"

ClassImp(TCut)

////////////////////////////////////////////////////////////////////////////////
/// Constructor.

TCut::TCut() : TNamed()
{
}

////////////////////////////////////////////////////////////////////////////////
/// Constructor.

TCut::TCut(const char *title) : TNamed("CUT",title)
{
}

////////////////////////////////////////////////////////////////////////////////
/// Constructor.

TCut::TCut(const char *name, const char *title) : TNamed(name,title)
{
}

////////////////////////////////////////////////////////////////////////////////
/// Copy Constructor.

TCut::TCut(const TCut &cut) : TNamed(cut)
{
}

////////////////////////////////////////////////////////////////////////////////
/// Typical destructor.

TCut::~TCut()
{
}

////////////////////////////////////////////////////////////////////////////////
/// Comparison.

Bool_t TCut::operator==(const char *rhs) const
{
   return fTitle == rhs;
}

////////////////////////////////////////////////////////////////////////////////
/// Comparison.

Bool_t TCut::operator==(const TCut &rhs) const
{
   return fTitle == rhs.fTitle;
}

////////////////////////////////////////////////////////////////////////////////
/// Comparison.

Bool_t TCut::operator!=(const char *rhs) const
{
   return fTitle != rhs;
}

////////////////////////////////////////////////////////////////////////////////
/// Comparison.

Bool_t TCut::operator!=(const TCut &rhs) const
{
   return fTitle != rhs.fTitle;
}

////////////////////////////////////////////////////////////////////////////////
/// Assignment.

TCut& TCut::operator=(const char *rhs)
{
   fTitle = rhs;
   return *this;
}

////////////////////////////////////////////////////////////////////////////////
/// Assignment.

TCut& TCut::operator=(const TCut& rhs)
{
   if (this != &rhs) TNamed::operator=(rhs);
   return *this;
}

////////////////////////////////////////////////////////////////////////////////
/// Addition.

TCut& TCut::operator+=(const char *rhs)
{
   if (!rhs || !rhs[0]) return *this;
   if (fTitle.Length() == 0)
      fTitle = rhs;
   else
      fTitle = "(" + fTitle + ")&&(" + TString(rhs) + ")";
   return *this;
}

////////////////////////////////////////////////////////////////////////////////
/// Addition.

TCut& TCut::operator+=(const TCut& rhs)
{
   if (rhs.fTitle.Length() == 0) return *this;
   if (fTitle.Length() == 0)
      fTitle = rhs;
   else
      fTitle = "(" + fTitle + ")&&(" + rhs.fTitle + ")";
   return *this;
}

////////////////////////////////////////////////////////////////////////////////
/// Multiplication.

TCut& TCut::operator*=(const char *rhs)
{
if (!rhs || !rhs[0]) return *this;
   if (fTitle.Length() == 0)
      fTitle = rhs;
   else
      fTitle = "(" + fTitle + ")*(" + TString(rhs) + ")";
   return *this;
}

////////////////////////////////////////////////////////////////////////////////
/// Multiplication.

TCut& TCut::operator*=(const TCut& rhs)
{
   if (rhs.fTitle.Length() == 0) return *this;
   if (fTitle.Length() == 0)
      fTitle = rhs;
   else
      fTitle = "(" + fTitle + ")*(" + rhs.fTitle + ")";
   return *this;
}

////////////////////////////////////////////////////////////////////////////////
/// Addition.

TCut operator+(const TCut& lhs, const char *rhs)
{
   return TCut(lhs) += rhs;
}

////////////////////////////////////////////////////////////////////////////////
/// Addition.

TCut operator+(const char *lhs, const TCut& rhs)
{
   return TCut(lhs) += rhs;
}

////////////////////////////////////////////////////////////////////////////////
/// Addition.

TCut operator+(const TCut& lhs, const TCut& rhs)
{
   return TCut(lhs) += rhs;
}

////////////////////////////////////////////////////////////////////////////////
/// Multiplication.

TCut operator*(const TCut& lhs, const char *rhs)
{
   return TCut(lhs) *= rhs;
}

////////////////////////////////////////////////////////////////////////////////
/// Multiplication.

TCut operator*(const char *lhs, const TCut& rhs)
{
   return TCut(lhs) *= rhs;
}

////////////////////////////////////////////////////////////////////////////////
/// Multiplication.

TCut operator*(const TCut& lhs, const TCut& rhs)
{
   return TCut(lhs) *= rhs;
}

////////////////////////////////////////////////////////////////////////////////
/// Logical and.

TCut operator&&(const TCut& lhs, const char *rhs)
{
   return TCut(lhs) += rhs;
}

////////////////////////////////////////////////////////////////////////////////
/// Logical and.

TCut operator&&(const char *lhs, const TCut& rhs)
{
   return TCut(lhs) += rhs;
}

////////////////////////////////////////////////////////////////////////////////
/// Logical and.

TCut operator&&(const TCut& lhs, const TCut& rhs)
{
   return TCut(lhs) += rhs;
}

////////////////////////////////////////////////////////////////////////////////
/// Logical or.

TCut operator||(const TCut& lhs, const char *rhs)
{
   if (lhs.fTitle.Length() == 0 && (!rhs || !rhs[0])) return TCut();
   if (lhs.fTitle.Length() == 0) return TCut(rhs);
   if (!rhs || !rhs[0]) return TCut(lhs);
   TString s = "(" + lhs.fTitle + ")||(" + TString(rhs) + ")";
   return TCut(s.Data());
}

////////////////////////////////////////////////////////////////////////////////
/// Logical or.

TCut operator||(const char *lhs, const TCut& rhs)
{
   if ((!lhs || !lhs[0]) && rhs.fTitle.Length() == 0) return TCut();
   if (!lhs || !lhs[0]) return TCut(rhs);
   if (rhs.fTitle.Length() == 0) return TCut(lhs);
   TString s = "(" + TString(lhs) + ")||(" + rhs.fTitle + ")";
   return TCut(s.Data());
}

////////////////////////////////////////////////////////////////////////////////
/// Logical or.

TCut operator||(const TCut& lhs, const TCut& rhs)
{
   if (lhs.fTitle.Length() == 0 && rhs.fTitle.Length() == 0) return TCut();
   if (lhs.fTitle.Length() == 0) return TCut(rhs);
   if (rhs.fTitle.Length() == 0) return TCut(lhs);
   TString s = "(" + lhs.fTitle + ")||(" + rhs.fTitle + ")";
   return TCut(s.Data());
}

////////////////////////////////////////////////////////////////////////////////
/// Logical negation.

TCut operator!(const TCut &rhs)
{
   if (rhs.fTitle.Length() == 0) return TCut();
   TString s = "!(" + rhs.fTitle + ")";
   return TCut(s.Data());
}

<|endoftext|>


<commit_before>/*
 For more information, please see: http://software.sci.utah.edu

 The MIT License

 Copyright (c) 2012 Scientific Computing and Imaging Institute,
 University of Utah.

 Permission is hereby granted, free of charge, to any person obtaining a
 copy of this software and associated documentation files (the "Software"),
 to deal in the Software without restriction, including without limitation
 the rights to use, copy, modify, merge, publish, distribute, sublicense,
 and/or sell copies of the Software, and to permit persons to whom the
 Software is furnished to do so, subject to the following conditions:

 The above copyright notice and this permission notice shall be included
 in all copies or substantial portions of the Software.

 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
 THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 DEALINGS IN THE SOFTWARE.
 */

/**
 \brief A Lua class proxy for IO's dataset class.
 */

#include <vector>

#include "Controller/Controller.h"
#include "3rdParty/LUA/lua.hpp"
#include "IO/IOManager.h"
#include "IO/FileBackedDataset.h"
#include "IO/uvfDataset.h"

#include "../LuaScripting.h"
#include "../LuaClassRegistration.h"

#include "LuaTuvokTypes.h"

#include "LuaDatasetProxy.h"

using namespace std;

namespace tuvok
{

namespace Registrar {
void addIOInterface(LuaClassRegistration<Dataset>& reg, Dataset*,
                    LuaScripting*) {
  reg.function(&Dataset::GetLODLevelCount, "LODs", "help?", false);
}
void dataset(std::shared_ptr<LuaScripting>& ss) {
  LuaDatasetProxy* proxy = new LuaDatasetProxy;
  ss->registerClass<Dataset>(
    proxy, &LuaDatasetProxy::CreateDS, "tuvok.dataset", "creates a new dataset",
    LuaClassRegCallback<Dataset>::Type(addIOInterface)
  );
  delete proxy;
}
}

LuaDatasetProxy::LuaDatasetProxy()
    : mReg(NULL)
    , mDS(NULL)
    , mDatasetType(Unknown) { }

LuaDatasetProxy::~LuaDatasetProxy()
{
  delete mReg; mReg = NULL;
  mDS = NULL;
}

Dataset* LuaDatasetProxy::CreateDS(const std::string& uvf, unsigned bricksize) {
  return Controller::Const().IOMan().CreateDataset(uvf,
    uint64_t(bricksize), false
  );
}

void LuaDatasetProxy::bind(Dataset* ds, shared_ptr<LuaScripting> ss)
{
  if (mReg == NULL)
    throw LuaError("Unable to bind dataset, no class registration available.");

  mReg->clearProxyFunctions();

  mDS = ds;
  if (ds != NULL)
  {
    // Register dataset functions using ds.
    string id;

    id = mReg->functionProxy(ds, &Dataset::GetDomainSize,
                             "getDomainSize", "", false);
    id = mReg->functionProxy(ds, &Dataset::GetRange,
                             "getRange", "", false);
    id = mReg->functionProxy(ds, &Dataset::GetLODLevelCount,
                             "getLODLevelCount", "", false);
    id = mReg->functionProxy(ds, &Dataset::GetNumberOfTimesteps,
                             "getNumberOfTimesteps", "", false);
    id = mReg->functionProxy(ds, &Dataset::GetMeshes,
                             "getMeshes", "", false);
    id = mReg->functionProxy(ds, &Dataset::GetBitWidth,
                             "getBitWidth", "", false);
    id = mReg->functionProxy(ds, &Dataset::Get1DHistogram,
                             "get1DHistogram", "", false);
    id = mReg->functionProxy(ds, &Dataset::Get2DHistogram,
                             "get2DHistogram", "", false);
    id = mReg->functionProxy(ds, &Dataset::SaveRescaleFactors,
                             "saveRescaleFactors", "", false);
    id = mReg->functionProxy(ds, &Dataset::GetRescaleFactors,
                             "getRescaleFactors", "", false);
    // We do NOT want the return values from GetMeshes stuck in the provenance
    // system (Okay, so the provenance system doesn't store return values, just
    // function parameters. But it's best to be safe).
    ss->setProvenanceExempt(id);

    // Attempt to cast the dataset to a file backed dataset.
    FileBackedDataset* fileDataset = dynamic_cast<FileBackedDataset*>(ds);
    if (fileDataset != NULL)
    {
      MESSAGE("Binding extra FileBackedDS functions.");
      id = mReg->functionProxy(fileDataset, &FileBackedDataset::Filename,
                               "fullpath", "Full path to the dataset.", false);
      id = mReg->functionProxy(ds, &FileBackedDataset::Name,
                               "name", "Dataset descriptive name.", false);
    }

    try {
      UVFDataset& uvfDataset = dynamic_cast<UVFDataset&>(*ds);
      MESSAGE("Binding extra UVF functions.");
      mDatasetType = UVF;
      mReg->functionProxy(&uvfDataset, &UVFDataset::RemoveMesh, "removeMesh",
                          "", true);
      mReg->functionProxy(&uvfDataset, &UVFDataset::AppendMesh,
                          "appendMesh", "", false);
      id = mReg->functionProxy(&uvfDataset,
        &UVFDataset::GeometryTransformToFile, "geomTransformToFile", "",
        false
      );
      ss->setProvenanceExempt(id);
    } catch(const std::bad_cast&) {
      WARNING("Not a uvf; not binding advanced functions.");
    }

    /// @todo Expose 1D/2D histogram? Currently, it is being transfered
    ///       via shared_ptr. If lua wants to interpret this, the histogram
    ///       will need to be placed in terms that lua can understand.
    ///       Two approaches:
    ///       1) Add Grid1D to the LuaStrictStack.
    ///       2) Create a Histogram1D and Histogram2D proxy.
    ///
    ///       The second solution would be more efficient, since there wouldn't
    ///       be any time spent converting datatypes to and from Lua (and with
    ///       histograms, that time wouldn't be negligible).
  }

}

void LuaDatasetProxy::defineLuaInterface(
    LuaClassRegistration<LuaDatasetProxy>& reg,
    LuaDatasetProxy* me,
    LuaScripting*)
{
  me->mReg = new LuaClassRegistration<LuaDatasetProxy>(reg);

  string id;

  // Register our functions
  id = reg.function(&LuaDatasetProxy::getDatasetType, "getDSType", "", false);
  id = reg.function(&LuaDatasetProxy::proxyGetMetadata, "getMetadata", "",
                    false);
}

std::vector<std::pair<std::string, std::string>>
LuaDatasetProxy::proxyGetMetadata()
{
  return mDS->GetMetadata();
}

} /* namespace tuvok */
<commit_msg>Bind minmax computation strategies into Lua.<commit_after>/*
 For more information, please see: http://software.sci.utah.edu

 The MIT License

 Copyright (c) 2012 Scientific Computing and Imaging Institute,
 University of Utah.

 Permission is hereby granted, free of charge, to any person obtaining a
 copy of this software and associated documentation files (the "Software"),
 to deal in the Software without restriction, including without limitation
 the rights to use, copy, modify, merge, publish, distribute, sublicense,
 and/or sell copies of the Software, and to permit persons to whom the
 Software is furnished to do so, subject to the following conditions:

 The above copyright notice and this permission notice shall be included
 in all copies or substantial portions of the Software.

 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
 THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 DEALINGS IN THE SOFTWARE.
 */

/**
 \brief A Lua class proxy for IO's dataset class.
 */

#include <vector>

#include "3rdParty/LUA/lua.hpp"
#include "Controller/Controller.h"
#include "IO/DynamicBrickingDS.h"
#include "IO/FileBackedDataset.h"
#include "IO/IOManager.h"
#include "IO/uvfDataset.h"
#include "../LuaClassRegistration.h"
#include "../LuaScripting.h"
#include "LuaDatasetProxy.h"
#include "LuaTuvokTypes.h"

using namespace std;

namespace tuvok
{

namespace Registrar {
void addIOInterface(LuaClassRegistration<Dataset>& reg, Dataset*,
                    LuaScripting*) {
  reg.function(&Dataset::GetLODLevelCount, "LODs", "help?", false);
}
void dataset(std::shared_ptr<LuaScripting>& ss) {
  LuaDatasetProxy* proxy = new LuaDatasetProxy;
  ss->registerClass<Dataset>(
    proxy, &LuaDatasetProxy::CreateDS, "tuvok.dataset", "creates a new dataset",
    LuaClassRegCallback<Dataset>::Type(addIOInterface)
  );
  delete proxy;
}
}

LuaDatasetProxy::LuaDatasetProxy()
    : mReg(NULL)
    , mDS(NULL)
    , mDatasetType(Unknown) { }

LuaDatasetProxy::~LuaDatasetProxy()
{
  delete mReg; mReg = NULL;
  mDS = NULL;
}

Dataset* LuaDatasetProxy::CreateDS(const std::string& uvf, unsigned bricksize) {
  return Controller::Const().IOMan().CreateDataset(uvf,
    uint64_t(bricksize), false
  );
}

void LuaDatasetProxy::bind(Dataset* ds, shared_ptr<LuaScripting> ss)
{
  if (mReg == NULL)
    throw LuaError("Unable to bind dataset, no class registration available.");

  mReg->clearProxyFunctions();

  mDS = ds;
  if (ds != NULL)
  {
    // Register dataset functions using ds.
    string id;

    id = mReg->functionProxy(ds, &Dataset::GetDomainSize,
                             "getDomainSize", "", false);
    id = mReg->functionProxy(ds, &Dataset::GetRange,
                             "getRange", "", false);
    id = mReg->functionProxy(ds, &Dataset::GetLODLevelCount,
                             "getLODLevelCount", "", false);
    id = mReg->functionProxy(ds, &Dataset::GetNumberOfTimesteps,
                             "getNumberOfTimesteps", "", false);
    id = mReg->functionProxy(ds, &Dataset::GetMeshes,
                             "getMeshes", "", false);
    id = mReg->functionProxy(ds, &Dataset::GetBitWidth,
                             "getBitWidth", "", false);
    id = mReg->functionProxy(ds, &Dataset::Get1DHistogram,
                             "get1DHistogram", "", false);
    id = mReg->functionProxy(ds, &Dataset::Get2DHistogram,
                             "get2DHistogram", "", false);
    id = mReg->functionProxy(ds, &Dataset::SaveRescaleFactors,
                             "saveRescaleFactors", "", false);
    id = mReg->functionProxy(ds, &Dataset::GetRescaleFactors,
                             "getRescaleFactors", "", false);
    // We do NOT want the return values from GetMeshes stuck in the provenance
    // system (Okay, so the provenance system doesn't store return values, just
    // function parameters. But it's best to be safe).
    ss->setProvenanceExempt(id);

    // Attempt to cast the dataset to a file backed dataset.
    FileBackedDataset* fileDataset = dynamic_cast<FileBackedDataset*>(ds);
    if (fileDataset != NULL)
    {
      MESSAGE("Binding extra FileBackedDS functions.");
      id = mReg->functionProxy(fileDataset, &FileBackedDataset::Filename,
                               "fullpath", "Full path to the dataset.", false);
      id = mReg->functionProxy(ds, &FileBackedDataset::Name,
                               "name", "Dataset descriptive name.", false);
    }

    try {
      UVFDataset& uvfDataset = dynamic_cast<UVFDataset&>(*ds);
      MESSAGE("Binding extra UVF functions.");
      mDatasetType = UVF;
      mReg->functionProxy(&uvfDataset, &UVFDataset::RemoveMesh, "removeMesh",
                          "", true);
      mReg->functionProxy(&uvfDataset, &UVFDataset::AppendMesh,
                          "appendMesh", "", false);
      id = mReg->functionProxy(&uvfDataset,
        &UVFDataset::GeometryTransformToFile, "geomTransformToFile", "",
        false
      );
      ss->setProvenanceExempt(id);
    } catch(const std::bad_cast&) {
      WARNING("Not a uvf; not binding advanced functions.");
    }

    /// @todo Expose 1D/2D histogram? Currently, it is being transfered
    ///       via shared_ptr. If lua wants to interpret this, the histogram
    ///       will need to be placed in terms that lua can understand.
    ///       Two approaches:
    ///       1) Add Grid1D to the LuaStrictStack.
    ///       2) Create a Histogram1D and Histogram2D proxy.
    ///
    ///       The second solution would be more efficient, since there wouldn't
    ///       be any time spent converting datatypes to and from Lua (and with
    ///       histograms, that time wouldn't be negligible).
  }

}

void LuaDatasetProxy::defineLuaInterface(
    LuaClassRegistration<LuaDatasetProxy>& reg,
    LuaDatasetProxy* me,
    LuaScripting* ss)
{
  me->mReg = new LuaClassRegistration<LuaDatasetProxy>(reg);

  string id;

  // Register our functions
  id = reg.function(&LuaDatasetProxy::getDatasetType, "getDSType", "", false);
  id = reg.function(&LuaDatasetProxy::proxyGetMetadata, "getMetadata", "",
                    false);

  lua_State* L = ss->getLuaState();
  lua_pushinteger(L, DynamicBrickingDS::MM_SOURCE);
  lua_setglobal(L, "MM_SOURCE");
  lua_pushinteger(L, DynamicBrickingDS::MM_PRECOMPUTE);
  lua_setglobal(L, "MM_PRECOMPUTE");
  lua_pushinteger(L, DynamicBrickingDS::MM_DYNAMIC);
  lua_setglobal(L, "MM_DYNAMIC");
}

std::vector<std::pair<std::string, std::string>>
LuaDatasetProxy::proxyGetMetadata()
{
  return mDS->GetMetadata();
}

} /* namespace tuvok */
<|endoftext|>


<commit_before>#include "clustering/reactor/reactor.hpp"

#include "clustering/immediate_consistency/branch/broadcaster.hpp"
#include "clustering/immediate_consistency/branch/replier.hpp"
#include "clustering/immediate_consistency/query/master.hpp"
#include "clustering/immediate_consistency/branch/multistore.hpp"
#include "concurrency/cross_thread_signal.hpp"
#include "concurrency/cross_thread_watchable.hpp"

template<class key_t, class value_t>
std::map<key_t, value_t> collapse_optionals_in_map(const std::map<key_t, boost::optional<value_t> > &map) {
    std::map<key_t, value_t> res;
    for (typename std::map<key_t, boost::optional<value_t> >::const_iterator it = map.begin(); it != map.end(); it++) {
        if (it->second) {
            res.insert(std::make_pair(it->first, it->second.get()));
        }
    }
    return res;
}

template<class protocol_t>
reactor_t<protocol_t>::reactor_t(
        io_backender_t *_io_backender,
        mailbox_manager_t *mm,
        typename master_t<protocol_t>::ack_checker_t *ack_checker_,
        clone_ptr_t<watchable_t<std::map<peer_id_t, boost::optional<directory_echo_wrapper_t<cow_ptr_t<reactor_business_card_t<protocol_t> > > > > > > rd,
        branch_history_manager_t<protocol_t> *bhm,
        clone_ptr_t<watchable_t<blueprint_t<protocol_t> > > b,
        multistore_ptr_t<protocol_t> *_underlying_svs,
        perfmon_collection_t *_parent_perfmon_collection,
        typename protocol_t::context_t *_ctx) THROWS_NOTHING :
    io_backender(_io_backender),
    mailbox_manager(mm),
    ack_checker(ack_checker_),
    directory_echo_writer(mailbox_manager, cow_ptr_t<reactor_business_card_t<protocol_t> >()),
    directory_echo_mirror(mailbox_manager, rd->subview(&collapse_optionals_in_map<peer_id_t, directory_echo_wrapper_t<cow_ptr_t<reactor_business_card_t<protocol_t> > > >)),
    branch_history_manager(bhm),
    blueprint_watchable(b),
    underlying_svs(_underlying_svs),
    blueprint_subscription(boost::bind(&reactor_t<protocol_t>::on_blueprint_changed, this)),
    parent_perfmon_collection(_parent_perfmon_collection),
    regions_perfmon_collection(),
    regions_perfmon_membership(parent_perfmon_collection, &regions_perfmon_collection, "regions"),
    ctx(_ctx)
{
    {
        typename watchable_t<blueprint_t<protocol_t> >::freeze_t freeze(blueprint_watchable);
        blueprint_watchable->get().guarantee_valid();
        try_spawn_roles();
        blueprint_subscription.reset(blueprint_watchable, &freeze);
    }
}

template <class protocol_t>
reactor_t<protocol_t>::directory_entry_t::directory_entry_t(reactor_t<protocol_t> *_parent, typename protocol_t::region_t _region)
    : parent(_parent), region(_region), reactor_activity_id(nil_uuid())
{ }

template <class protocol_t>
directory_echo_version_t reactor_t<protocol_t>::directory_entry_t::set(typename reactor_business_card_t<protocol_t>::activity_t activity) {
    typename directory_echo_writer_t<cow_ptr_t<reactor_business_card_t<protocol_t> > >::our_value_change_t our_value_change(&parent->directory_echo_writer);
    {
        typename cow_ptr_t<reactor_business_card_t<protocol_t> >::change_t cow_ptr_change(&our_value_change.buffer);
        if (!reactor_activity_id.is_nil()) {
            cow_ptr_change.get()->activities.erase(reactor_activity_id);
        }
        reactor_activity_id = generate_uuid();
        cow_ptr_change.get()->activities.insert(std::make_pair(reactor_activity_id, typename reactor_business_card_t<protocol_t>::activity_entry_t(region, activity)));
    }
    return our_value_change.commit();
}

template <class protocol_t>
directory_echo_version_t reactor_t<protocol_t>::directory_entry_t::update_without_changing_id(typename reactor_business_card_t<protocol_t>::activity_t activity) {
    guarantee(!reactor_activity_id.is_nil(), "This method should only be called when an activity has already been set\n");
    typename directory_echo_writer_t<cow_ptr_t<reactor_business_card_t<protocol_t> > >::our_value_change_t our_value_change(&parent->directory_echo_writer);
    {
        typename cow_ptr_t<reactor_business_card_t<protocol_t> >::change_t cow_ptr_change(&our_value_change.buffer);
        cow_ptr_change.get()->activities[reactor_activity_id].activity = activity;
    }
    return our_value_change.commit();
}

template <class protocol_t>
reactor_t<protocol_t>::directory_entry_t::~directory_entry_t() {
    if (!reactor_activity_id.is_nil()) {
        typename directory_echo_writer_t<cow_ptr_t<reactor_business_card_t<protocol_t> > >::our_value_change_t our_value_change(&parent->directory_echo_writer);
        {
            typename cow_ptr_t<reactor_business_card_t<protocol_t> >::change_t cow_ptr_change(&our_value_change.buffer);
            cow_ptr_change.get()->activities.erase(reactor_activity_id);
        }
        our_value_change.commit();
    }
}

template<class protocol_t>
void reactor_t<protocol_t>::on_blueprint_changed() THROWS_NOTHING {
    blueprint_t<protocol_t> blueprint = blueprint_watchable->get();
    blueprint.guarantee_valid();

    typename std::map<peer_id_t, std::map<typename protocol_t::region_t, blueprint_role_t> >::const_iterator role_it = blueprint.peers_roles.find(get_me());
    guarantee(role_it != blueprint.peers_roles.end(), "reactor_t assumes that it is mentioned in the blueprint it's given.");

    std::map<typename protocol_t::region_t, blueprint_role_t> blueprint_roles = role_it->second;
    for (typename std::map<typename protocol_t::region_t, current_role_t *>::iterator it = current_roles.begin();
         it != current_roles.end(); ++it) {
        typename std::map<typename protocol_t::region_t, blueprint_role_t>::iterator it2 =
            blueprint_roles.find(it->first);
        if (it2 == blueprint_roles.end()) {
            /* The shard boundaries have changed, and the shard that the running
            coroutine was for no longer exists; interrupt it */
            it->second->abort_roles.pulse_if_not_already_pulsed();
        } else {
            if (it->second->role != it2->second) {
                /* Our role for the shard has changed; interrupt the running
                coroutine */
                it->second->abort_roles.pulse_if_not_already_pulsed();
            } else {
                /* Notify the running coroutine of the new blueprint */
                it->second->blueprint.set_value(blueprint);
            }
        }
    }
}

template<class protocol_t>
void reactor_t<protocol_t>::try_spawn_roles() THROWS_NOTHING {
    blueprint_t<protocol_t> blueprint = blueprint_watchable->get();

    typename std::map<peer_id_t, std::map<typename protocol_t::region_t, blueprint_role_t> >::const_iterator role_it = blueprint.peers_roles.find(get_me());
    guarantee(role_it != blueprint.peers_roles.end(), "reactor_t assumes that it is mentioned in the blueprint it's given.");

    std::map<typename protocol_t::region_t, blueprint_role_t> blueprint_roles = role_it->second;
    for (typename std::map<typename protocol_t::region_t, blueprint_role_t>::iterator it = blueprint_roles.begin();
         it != blueprint_roles.end(); ++it) {
        bool none_overlap = true;
        for (typename std::map<typename protocol_t::region_t, current_role_t *>::iterator it2 = current_roles.begin();
             it2 != current_roles.end(); ++it2) {
            if (region_overlaps(it->first, it2->first)) {
                none_overlap = false;
                break;
            }
        }

        if (none_overlap) {
            //This state will be cleaned up in run_role
            current_role_t *role = new current_role_t(it->second, blueprint);
            current_roles.insert(std::make_pair(it->first, role));
            coro_t::spawn_sometime(boost::bind(&reactor_t<protocol_t>::run_role, this, it->first,
                                               role, auto_drainer_t::lock_t(&drainer)));
        }
    }
}

template<class protocol_t>
void reactor_t<protocol_t>::run_cpu_sharded_role(
        int cpu_shard_number,
        current_role_t *role,
        const typename protocol_t::region_t& region,
        multistore_ptr_t<protocol_t> *svs_subview,
        signal_t *interruptor,
        cond_t *abort_roles) THROWS_NOTHING {
    store_view_t<protocol_t> *store_view = svs_subview->get_store(cpu_shard_number);
    typename protocol_t::region_t cpu_sharded_region = region_intersection(region, protocol_t::cpu_sharding_subspace(cpu_shard_number, svs_subview->num_stores()));

    switch (role->role) {
    case blueprint_role_primary:
        be_primary(cpu_sharded_region, store_view, role->blueprint.get_watchable(), interruptor);
        break;
    case blueprint_role_secondary:
        be_secondary(cpu_sharded_region, store_view, role->blueprint.get_watchable(), interruptor);
        break;
    case blueprint_role_nothing:
        be_nothing(cpu_sharded_region, store_view, role->blueprint.get_watchable(), interruptor);
        break;
    default:
        unreachable();
        break;
    }

    // When one role returns, make sure all others are aborted
    if (!abort_roles->is_pulsed()) {
        abort_roles->pulse();
    }
}

template<class protocol_t>
void reactor_t<protocol_t>::run_role(
        typename protocol_t::region_t region,
        current_role_t *role,
        auto_drainer_t::lock_t keepalive) THROWS_NOTHING {

    //A store_view_t derived object that acts as a store for the specified region
    multistore_ptr_t<protocol_t> svs_subview(underlying_svs, region);

    {
        //All of the be_{role} functions respond identically to blueprint changes
        //and interruptions... so we just unify those signals
        wait_any_t wait_any(&role->abort_roles, keepalive.get_drain_signal());

        // guarantee(CLUSTER_CPU_SHARDING_FACTOR == svs_subview.num_stores());

        pmap(svs_subview.num_stores(), boost::bind(&reactor_t<protocol_t>::run_cpu_sharded_role, this, _1, role, region, &svs_subview, &wait_any, &role->abort_roles));
    }

    //As promised, clean up the state from try_spawn_roles
    current_roles.erase(region);
    delete role;

    if (!keepalive.get_drain_signal()->is_pulsed()) {
        try_spawn_roles();
    }
}

template<class protocol_t>
boost::optional<boost::optional<broadcaster_business_card_t<protocol_t> > > reactor_t<protocol_t>::extract_broadcaster_from_reactor_business_card_primary(const boost::optional<boost::optional<typename reactor_business_card_t<protocol_t>::primary_t> > &bcard) {
    if (!bcard) {
        return boost::optional<boost::optional<broadcaster_business_card_t<protocol_t> > >();
    }
    if (!bcard.get()) {
        return boost::optional<boost::optional<broadcaster_business_card_t<protocol_t> > >(
            boost::optional<broadcaster_business_card_t<protocol_t> >());
    }
    return boost::optional<boost::optional<broadcaster_business_card_t<protocol_t> > >(
        boost::optional<broadcaster_business_card_t<protocol_t> >(bcard.get().get().broadcaster));
}

template <class protocol_t>
void reactor_t<protocol_t>::wait_for_directory_acks(directory_echo_version_t version_to_wait_on, signal_t *interruptor) THROWS_ONLY(interrupted_exc_t) {
    while (true) {
        /* This function waits for acks from all the peers mentioned in the
        blueprint. If the blueprint changes while we're waiting for acks, we
        restart from the top. This is important because otherwise we might
        deadlock. For example, if we were waiting for a machine to come back up
        and then it was declared dead, our interruptor might not be pulsed but
        the `ack_waiter_t` would never be pulsed so we would get stuck. */
        cond_t blueprint_changed;
        blueprint_t<protocol_t> bp;
        typename watchable_t<blueprint_t<protocol_t> >::subscription_t subscription(
            boost::bind(&cond_t::pulse_if_not_already_pulsed, &blueprint_changed));
        {
            typename watchable_t<blueprint_t<protocol_t> >::freeze_t freeze(blueprint_watchable);
            bp = blueprint_watchable->get();
            subscription.reset(blueprint_watchable, &freeze);
        }
        typename std::map<peer_id_t, std::map<typename protocol_t::region_t, blueprint_role_t> >::iterator it = bp.peers_roles.begin();
        for (it = bp.peers_roles.begin(); it != bp.peers_roles.end(); it++) {
            typename directory_echo_writer_t<cow_ptr_t<reactor_business_card_t<protocol_t> > >::ack_waiter_t ack_waiter(&directory_echo_writer, it->first, version_to_wait_on);
            wait_any_t waiter(&ack_waiter, &blueprint_changed);
            wait_interruptible(&waiter, interruptor);
            if (blueprint_changed.is_pulsed()) {
                break;
            }
        }
        if (!blueprint_changed.is_pulsed()) {
            break;
        }
    }
}

#include "mock/dummy_protocol.hpp"
#include "memcached/protocol.hpp"
#include "rdb_protocol/protocol.hpp"

template class reactor_t<mock::dummy_protocol_t>;
template class reactor_t<memcached_protocol_t>;
template class reactor_t<rdb_protocol_t>;
<commit_msg>Don't let a reactor start until its bcard has been insterted.<commit_after>#include "clustering/reactor/reactor.hpp"

#include "clustering/immediate_consistency/branch/broadcaster.hpp"
#include "clustering/immediate_consistency/branch/replier.hpp"
#include "clustering/immediate_consistency/query/master.hpp"
#include "clustering/immediate_consistency/branch/multistore.hpp"
#include "concurrency/cross_thread_signal.hpp"
#include "concurrency/cross_thread_watchable.hpp"

template<class key_t, class value_t>
std::map<key_t, value_t> collapse_optionals_in_map(const std::map<key_t, boost::optional<value_t> > &map) {
    std::map<key_t, value_t> res;
    for (typename std::map<key_t, boost::optional<value_t> >::const_iterator it = map.begin(); it != map.end(); it++) {
        if (it->second) {
            res.insert(std::make_pair(it->first, it->second.get()));
        }
    }
    return res;
}

template<class protocol_t>
reactor_t<protocol_t>::reactor_t(
        io_backender_t *_io_backender,
        mailbox_manager_t *mm,
        typename master_t<protocol_t>::ack_checker_t *ack_checker_,
        clone_ptr_t<watchable_t<std::map<peer_id_t, boost::optional<directory_echo_wrapper_t<cow_ptr_t<reactor_business_card_t<protocol_t> > > > > > > rd,
        branch_history_manager_t<protocol_t> *bhm,
        clone_ptr_t<watchable_t<blueprint_t<protocol_t> > > b,
        multistore_ptr_t<protocol_t> *_underlying_svs,
        perfmon_collection_t *_parent_perfmon_collection,
        typename protocol_t::context_t *_ctx) THROWS_NOTHING :
    io_backender(_io_backender),
    mailbox_manager(mm),
    ack_checker(ack_checker_),
    directory_echo_writer(mailbox_manager, cow_ptr_t<reactor_business_card_t<protocol_t> >()),
    directory_echo_mirror(mailbox_manager, rd->subview(&collapse_optionals_in_map<peer_id_t, directory_echo_wrapper_t<cow_ptr_t<reactor_business_card_t<protocol_t> > > >)),
    branch_history_manager(bhm),
    blueprint_watchable(b),
    underlying_svs(_underlying_svs),
    blueprint_subscription(boost::bind(&reactor_t<protocol_t>::on_blueprint_changed, this)),
    parent_perfmon_collection(_parent_perfmon_collection),
    regions_perfmon_collection(),
    regions_perfmon_membership(parent_perfmon_collection, &regions_perfmon_collection, "regions"),
    ctx(_ctx)
{
    {
        typename watchable_t<blueprint_t<protocol_t> >::freeze_t freeze(blueprint_watchable);
        blueprint_watchable->get().guarantee_valid();
        try_spawn_roles();
        blueprint_subscription.reset(blueprint_watchable, &freeze);
    }
}

template <class protocol_t>
reactor_t<protocol_t>::directory_entry_t::directory_entry_t(reactor_t<protocol_t> *_parent, typename protocol_t::region_t _region)
    : parent(_parent), region(_region), reactor_activity_id(nil_uuid())
{ }

template <class protocol_t>
directory_echo_version_t reactor_t<protocol_t>::directory_entry_t::set(typename reactor_business_card_t<protocol_t>::activity_t activity) {
    typename directory_echo_writer_t<cow_ptr_t<reactor_business_card_t<protocol_t> > >::our_value_change_t our_value_change(&parent->directory_echo_writer);
    {
        typename cow_ptr_t<reactor_business_card_t<protocol_t> >::change_t cow_ptr_change(&our_value_change.buffer);
        if (!reactor_activity_id.is_nil()) {
            cow_ptr_change.get()->activities.erase(reactor_activity_id);
        }
        reactor_activity_id = generate_uuid();
        cow_ptr_change.get()->activities.insert(std::make_pair(reactor_activity_id, typename reactor_business_card_t<protocol_t>::activity_entry_t(region, activity)));
    }
    return our_value_change.commit();
}

template <class protocol_t>
directory_echo_version_t reactor_t<protocol_t>::directory_entry_t::update_without_changing_id(typename reactor_business_card_t<protocol_t>::activity_t activity) {
    guarantee(!reactor_activity_id.is_nil(), "This method should only be called when an activity has already been set\n");
    typename directory_echo_writer_t<cow_ptr_t<reactor_business_card_t<protocol_t> > >::our_value_change_t our_value_change(&parent->directory_echo_writer);
    {
        typename cow_ptr_t<reactor_business_card_t<protocol_t> >::change_t cow_ptr_change(&our_value_change.buffer);
        cow_ptr_change.get()->activities[reactor_activity_id].activity = activity;
    }
    return our_value_change.commit();
}

template <class protocol_t>
reactor_t<protocol_t>::directory_entry_t::~directory_entry_t() {
    if (!reactor_activity_id.is_nil()) {
        typename directory_echo_writer_t<cow_ptr_t<reactor_business_card_t<protocol_t> > >::our_value_change_t our_value_change(&parent->directory_echo_writer);
        {
            typename cow_ptr_t<reactor_business_card_t<protocol_t> >::change_t cow_ptr_change(&our_value_change.buffer);
            cow_ptr_change.get()->activities.erase(reactor_activity_id);
        }
        our_value_change.commit();
    }
}

template<class protocol_t>
void reactor_t<protocol_t>::on_blueprint_changed() THROWS_NOTHING {
    blueprint_t<protocol_t> blueprint = blueprint_watchable->get();
    blueprint.guarantee_valid();

    typename std::map<peer_id_t, std::map<typename protocol_t::region_t, blueprint_role_t> >::const_iterator role_it = blueprint.peers_roles.find(get_me());
    guarantee(role_it != blueprint.peers_roles.end(), "reactor_t assumes that it is mentioned in the blueprint it's given.");

    std::map<typename protocol_t::region_t, blueprint_role_t> blueprint_roles = role_it->second;
    for (typename std::map<typename protocol_t::region_t, current_role_t *>::iterator it = current_roles.begin();
         it != current_roles.end(); ++it) {
        typename std::map<typename protocol_t::region_t, blueprint_role_t>::iterator it2 =
            blueprint_roles.find(it->first);
        if (it2 == blueprint_roles.end()) {
            /* The shard boundaries have changed, and the shard that the running
            coroutine was for no longer exists; interrupt it */
            it->second->abort_roles.pulse_if_not_already_pulsed();
        } else {
            if (it->second->role != it2->second) {
                /* Our role for the shard has changed; interrupt the running
                coroutine */
                it->second->abort_roles.pulse_if_not_already_pulsed();
            } else {
                /* Notify the running coroutine of the new blueprint */
                it->second->blueprint.set_value(blueprint);
            }
        }
    }
}

template<class protocol_t>
void reactor_t<protocol_t>::try_spawn_roles() THROWS_NOTHING {
    blueprint_t<protocol_t> blueprint = blueprint_watchable->get();

    typename std::map<peer_id_t, std::map<typename protocol_t::region_t, blueprint_role_t> >::const_iterator role_it = blueprint.peers_roles.find(get_me());
    guarantee(role_it != blueprint.peers_roles.end(), "reactor_t assumes that it is mentioned in the blueprint it's given.");

    std::map<typename protocol_t::region_t, blueprint_role_t> blueprint_roles = role_it->second;
    for (typename std::map<typename protocol_t::region_t, blueprint_role_t>::iterator it = blueprint_roles.begin();
         it != blueprint_roles.end(); ++it) {
        bool none_overlap = true;
        for (typename std::map<typename protocol_t::region_t, current_role_t *>::iterator it2 = current_roles.begin();
             it2 != current_roles.end(); ++it2) {
            if (region_overlaps(it->first, it2->first)) {
                none_overlap = false;
                break;
            }
        }

        if (none_overlap) {
            //This state will be cleaned up in run_role
            current_role_t *role = new current_role_t(it->second, blueprint);
            current_roles.insert(std::make_pair(it->first, role));
            coro_t::spawn_sometime(boost::bind(&reactor_t<protocol_t>::run_role, this, it->first,
                                               role, auto_drainer_t::lock_t(&drainer)));
        }
    }
}

template<class protocol_t>
void reactor_t<protocol_t>::run_cpu_sharded_role(
        int cpu_shard_number,
        current_role_t *role,
        const typename protocol_t::region_t& region,
        multistore_ptr_t<protocol_t> *svs_subview,
        signal_t *interruptor,
        cond_t *abort_roles) THROWS_NOTHING {
    store_view_t<protocol_t> *store_view = svs_subview->get_store(cpu_shard_number);
    typename protocol_t::region_t cpu_sharded_region = region_intersection(region, protocol_t::cpu_sharding_subspace(cpu_shard_number, svs_subview->num_stores()));

    switch (role->role) {
    case blueprint_role_primary:
        be_primary(cpu_sharded_region, store_view, role->blueprint.get_watchable(), interruptor);
        break;
    case blueprint_role_secondary:
        be_secondary(cpu_sharded_region, store_view, role->blueprint.get_watchable(), interruptor);
        break;
    case blueprint_role_nothing:
        be_nothing(cpu_sharded_region, store_view, role->blueprint.get_watchable(), interruptor);
        break;
    default:
        unreachable();
        break;
    }

    // When one role returns, make sure all others are aborted
    if (!abort_roles->is_pulsed()) {
        abort_roles->pulse();
    }
}

template<class protocol_t>
bool we_see_our_bcard(const std::map<peer_id_t, cow_ptr_t<reactor_business_card_t<protocol_t> > > &bcards, peer_id_t me) {
    return std_contains(bcards, me);
}

template<class protocol_t>
void reactor_t<protocol_t>::run_role(
        typename protocol_t::region_t region,
        current_role_t *role,
        auto_drainer_t::lock_t keepalive) THROWS_NOTHING {

    //A store_view_t derived object that acts as a store for the specified region
    multistore_ptr_t<protocol_t> svs_subview(underlying_svs, region);

    {
        //All of the be_{role} functions respond identically to blueprint changes
        //and interruptions... so we just unify those signals
        wait_any_t wait_any(&role->abort_roles, keepalive.get_drain_signal());

        try {
            directory_echo_mirror.get_internal()->run_until_satisfied(boost::bind(&we_see_our_bcard<protocol_t>, _1, get_me()), &wait_any);
        } catch (const interrupted_exc_t &) {
            goto CLEANUP;
        }
        // guarantee(CLUSTER_CPU_SHARDING_FACTOR == svs_subview.num_stores());

        pmap(svs_subview.num_stores(), boost::bind(&reactor_t<protocol_t>::run_cpu_sharded_role, this, _1, role, region, &svs_subview, &wait_any, &role->abort_roles));
    }

CLEANUP:
    //As promised, clean up the state from try_spawn_roles
    current_roles.erase(region);
    delete role;

    if (!keepalive.get_drain_signal()->is_pulsed()) {
        try_spawn_roles();
    }
}

template<class protocol_t>
boost::optional<boost::optional<broadcaster_business_card_t<protocol_t> > > reactor_t<protocol_t>::extract_broadcaster_from_reactor_business_card_primary(const boost::optional<boost::optional<typename reactor_business_card_t<protocol_t>::primary_t> > &bcard) {
    if (!bcard) {
        return boost::optional<boost::optional<broadcaster_business_card_t<protocol_t> > >();
    }
    if (!bcard.get()) {
        return boost::optional<boost::optional<broadcaster_business_card_t<protocol_t> > >(
            boost::optional<broadcaster_business_card_t<protocol_t> >());
    }
    return boost::optional<boost::optional<broadcaster_business_card_t<protocol_t> > >(
        boost::optional<broadcaster_business_card_t<protocol_t> >(bcard.get().get().broadcaster));
}

template <class protocol_t>
void reactor_t<protocol_t>::wait_for_directory_acks(directory_echo_version_t version_to_wait_on, signal_t *interruptor) THROWS_ONLY(interrupted_exc_t) {
    while (true) {
        /* This function waits for acks from all the peers mentioned in the
        blueprint. If the blueprint changes while we're waiting for acks, we
        restart from the top. This is important because otherwise we might
        deadlock. For example, if we were waiting for a machine to come back up
        and then it was declared dead, our interruptor might not be pulsed but
        the `ack_waiter_t` would never be pulsed so we would get stuck. */
        cond_t blueprint_changed;
        blueprint_t<protocol_t> bp;
        typename watchable_t<blueprint_t<protocol_t> >::subscription_t subscription(
            boost::bind(&cond_t::pulse_if_not_already_pulsed, &blueprint_changed));
        {
            typename watchable_t<blueprint_t<protocol_t> >::freeze_t freeze(blueprint_watchable);
            bp = blueprint_watchable->get();
            subscription.reset(blueprint_watchable, &freeze);
        }
        typename std::map<peer_id_t, std::map<typename protocol_t::region_t, blueprint_role_t> >::iterator it = bp.peers_roles.begin();
        for (it = bp.peers_roles.begin(); it != bp.peers_roles.end(); it++) {
            typename directory_echo_writer_t<cow_ptr_t<reactor_business_card_t<protocol_t> > >::ack_waiter_t ack_waiter(&directory_echo_writer, it->first, version_to_wait_on);
            wait_any_t waiter(&ack_waiter, &blueprint_changed);
            wait_interruptible(&waiter, interruptor);
            if (blueprint_changed.is_pulsed()) {
                break;
            }
        }
        if (!blueprint_changed.is_pulsed()) {
            break;
        }
    }
}

#include "mock/dummy_protocol.hpp"
#include "memcached/protocol.hpp"
#include "rdb_protocol/protocol.hpp"

template class reactor_t<mock::dummy_protocol_t>;
template class reactor_t<memcached_protocol_t>;
template class reactor_t<rdb_protocol_t>;
<|endoftext|>


<commit_before><commit_msg>coverity#738566 Uninitialized pointer field<commit_after><|endoftext|>


<commit_before>/*======================================================================

  This file is part of the elastix software.

  Copyright (c) University Medical Center Utrecht. All rights reserved.
  See src/CopyrightElastix.txt or http://elastix.isi.uu.nl/legal.php for
  details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE. See the above copyright notices for more information.

======================================================================*/

#ifndef __elxOptimizerBase_hxx
#define __elxOptimizerBase_hxx

#include "elxOptimizerBase.h"

#include "itkSingleValuedNonLinearOptimizer.h"

//#include <kwsys/MD5.h.in> // for MD5 hash
//#include KWSYS_HEADER(MD5.h)

namespace elastix
{
using namespace itk;

/**
 * ****************** Constructor ***********************************
 */

template <class TElastix>
OptimizerBase<TElastix>
::OptimizerBase()
{
  this->m_NewSamplesEveryIteration = false;

} // end Constructor

/**
 * ****************** SetCurrentPositionPublic ************************
 *
 * Add empty SetCurrentPositionPublic, so it is known everywhere.
 */

template <class TElastix>
void
OptimizerBase<TElastix>
::SetCurrentPositionPublic( const ParametersType & /** param */ )
{
  xl::xout["error"] << "ERROR: This function should be overridden or just "
    << "not used.\n";
  xl::xout["error"] << "  Are you using BSplineTransformWithDiffusion in "
    << "combination with another optimizer than the "
    << "StandardGradientDescentOptimizer? Don't!" << std::endl;

  /** Throw an exception if this function is not overridden. */
  itkExceptionMacro( << "ERROR: The SetCurrentPositionPublic method is not "
    << "implemented in your optimizer" );

} // end SetCurrentPositionPublic()

/**
 * ****************** BeforeEachResolutionBase **********************
 */

template <class TElastix>
void
OptimizerBase<TElastix>
::BeforeEachResolutionBase( void )
{
  /** Get the current resolution level. */
  unsigned int level
    = this->GetRegistration()->GetAsITKBaseType()->GetCurrentLevel();

  /** Check if after every iteration a new sample set should be created. */
  this->m_NewSamplesEveryIteration = false;
  this->GetConfiguration()->ReadParameter( this->m_NewSamplesEveryIteration,
    "NewSamplesEveryIteration", this->GetComponentLabel(), level, 0 );

} // end BeforeEachResolutionBase()

/**
 * ****************** AfterRegistrationBase **********************
 */

template <class TElastix>
void
OptimizerBase<TElastix>
::AfterRegistrationBase( void )
{
//   /** Get the final parameters. */
//   ParametersType finalTP = this->GetAsITKBaseType()->GetCurrentPosition();
//
//   /** Compute the MD5 Checksum. */
//   unsigned char * md5InputData = reinterpret_cast<unsigned char *>( finalTP );
//
//   kwsysMD5* md5 = kwsysMD5_New();
//   kwsysMD5_Initialize( md5 );
//   kwsysMD5_Append( md5, md5InputData, md5InputData->GetSize() );
//   unsigned char digest[16];
//   kwsysMD5_Finalize( md5, digest );
//   kwsysMD5_Delete( md5 );
//
// //   char md5out[33];
// //   kwsysMD5_DigestToHex(digest, md5out);
// //   md5out[32] = 0;
//
//   elxout << "\nRegistration result checksum: "
//     << digest
//     << std::endl;

} // end AfterRegistrationBase()

/**
 * ****************** SelectNewSamples ****************************
 */

template <class TElastix>
void
OptimizerBase<TElastix>
::SelectNewSamples( void )
{
  /** Force the metric to base its computation on a new subset of image samples.
   * Not every metric may have implemented this.
   */
  for ( unsigned int i = 0; i < this->GetElastix()->GetNumberOfMetrics(); ++i )
  {
    this->GetElastix()->GetElxMetricBase(i)->SelectNewSamples();
  }

} // end SelectNewSamples()

/**
 * ****************** GetNewSamplesEveryIteration ********************
 */

template <class TElastix>
bool
OptimizerBase<TElastix>
::GetNewSamplesEveryIteration( void ) const
{
  /** itkGetConstMacro Without the itkDebugMacro. */
  return this->m_NewSamplesEveryIteration;

} // end GetNewSamplesEveryIteration()

/**
 * ****************** SetSinusScales ********************
 */

template <class TElastix>
void
OptimizerBase<TElastix>
::SetSinusScales( double amplitude, double frequency,
  unsigned long numberOfParameters )
{
  typedef typename ITKBaseType::ScalesType ScalesType;

  const double nrofpar = static_cast<double>( numberOfParameters );
  ScalesType scales( numberOfParameters );

  for ( unsigned long i = 0; i < numberOfParameters; ++i )
  {
    const double x = static_cast<double>( i ) / nrofpar * 2.0
      * vnl_math::pi * frequency;
    scales[ i ] = vcl_pow( amplitude, vcl_sin( x ) );
  }
  this->GetAsITKBaseType()->SetScales( scales );

} // end SetSinusScales()

} // end namespace elastix

#endif // end #ifndef __elxOptimizerBase_hxx
<commit_msg>-ENH: implement computation of crc32 checksum on the final parameter vector, to facilitate testing (and comparison of registration results betweeen platforms). The crc checksum is written to the screen and log file.  <commit_after>/*======================================================================

  This file is part of the elastix software.

  Copyright (c) University Medical Center Utrecht. All rights reserved.
  See src/CopyrightElastix.txt or http://elastix.isi.uu.nl/legal.php for
  details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE. See the above copyright notices for more information.

======================================================================*/

#ifndef __elxOptimizerBase_hxx
#define __elxOptimizerBase_hxx

#include "elxOptimizerBase.h"

#include "itkSingleValuedNonLinearOptimizer.h"
#include "itk_zlib.h"

namespace elastix
{
using namespace itk;

/**
 * ****************** Constructor ***********************************
 */

template <class TElastix>
OptimizerBase<TElastix>
::OptimizerBase()
{
  this->m_NewSamplesEveryIteration = false;

} // end Constructor

/**
 * ****************** SetCurrentPositionPublic ************************
 *
 * Add empty SetCurrentPositionPublic, so it is known everywhere.
 */

template <class TElastix>
void
OptimizerBase<TElastix>
::SetCurrentPositionPublic( const ParametersType & /** param */ )
{
  xl::xout["error"] << "ERROR: This function should be overridden or just "
    << "not used.\n";
  xl::xout["error"] << "  Are you using BSplineTransformWithDiffusion in "
    << "combination with another optimizer than the "
    << "StandardGradientDescentOptimizer? Don't!" << std::endl;

  /** Throw an exception if this function is not overridden. */
  itkExceptionMacro( << "ERROR: The SetCurrentPositionPublic method is not "
    << "implemented in your optimizer" );

} // end SetCurrentPositionPublic()

/**
 * ****************** BeforeEachResolutionBase **********************
 */

template <class TElastix>
void
OptimizerBase<TElastix>
::BeforeEachResolutionBase( void )
{
  /** Get the current resolution level. */
  unsigned int level
    = this->GetRegistration()->GetAsITKBaseType()->GetCurrentLevel();

  /** Check if after every iteration a new sample set should be created. */
  this->m_NewSamplesEveryIteration = false;
  this->GetConfiguration()->ReadParameter( this->m_NewSamplesEveryIteration,
    "NewSamplesEveryIteration", this->GetComponentLabel(), level, 0 );

} // end BeforeEachResolutionBase()

/**
 * ****************** AfterRegistrationBase **********************
 */

template <class TElastix>
void
OptimizerBase<TElastix>
::AfterRegistrationBase( void )
{
  typedef typename ParametersType::ValueType ParametersValueType;

  /** Get the final parameters. */
  ParametersType finalTP = this->GetAsITKBaseType()->GetCurrentPosition();

  /** Compute the crc checksum using zlib crc32 function. */
  const unsigned char * crcInputData = reinterpret_cast<const unsigned char *>( finalTP.data_block() );
  uLong crc = crc32(0L, Z_NULL, 0);
  crc = crc32(crc, crcInputData, finalTP.Size()* sizeof(ParametersValueType) );

  elxout << "\nRegistration result checksum: "
    << crc
    << std::endl;

} // end AfterRegistrationBase()

/**
 * ****************** SelectNewSamples ****************************
 */

template <class TElastix>
void
OptimizerBase<TElastix>
::SelectNewSamples( void )
{
  /** Force the metric to base its computation on a new subset of image samples.
   * Not every metric may have implemented this.
   */
  for ( unsigned int i = 0; i < this->GetElastix()->GetNumberOfMetrics(); ++i )
  {
    this->GetElastix()->GetElxMetricBase(i)->SelectNewSamples();
  }

} // end SelectNewSamples()

/**
 * ****************** GetNewSamplesEveryIteration ********************
 */

template <class TElastix>
bool
OptimizerBase<TElastix>
::GetNewSamplesEveryIteration( void ) const
{
  /** itkGetConstMacro Without the itkDebugMacro. */
  return this->m_NewSamplesEveryIteration;

} // end GetNewSamplesEveryIteration()

/**
 * ****************** SetSinusScales ********************
 */

template <class TElastix>
void
OptimizerBase<TElastix>
::SetSinusScales( double amplitude, double frequency,
  unsigned long numberOfParameters )
{
  typedef typename ITKBaseType::ScalesType ScalesType;

  const double nrofpar = static_cast<double>( numberOfParameters );
  ScalesType scales( numberOfParameters );

  for ( unsigned long i = 0; i < numberOfParameters; ++i )
  {
    const double x = static_cast<double>( i ) / nrofpar * 2.0
      * vnl_math::pi * frequency;
    scales[ i ] = vcl_pow( amplitude, vcl_sin( x ) );
  }
  this->GetAsITKBaseType()->SetScales( scales );

} // end SetSinusScales()

} // end namespace elastix

#endif // end #ifndef __elxOptimizerBase_hxx
<|endoftext|>