<commit_before>#ifndef INC_MUSPELHEIM_HPP
#define INC_MUSPELHEIM_HPP

#include <functional>
#include <random>
#include <vector>

#include <boost/gil/extension/io/png_dynamic_io.hpp>
#include <boost/gil/image.hpp>
#include <boost/gil/typedefs.hpp>

// Make sure that multiplying points by floating-point values works correctly.
namespace boost { namespace gil {

  template <typename T, typename U>
  point2<T> operator *(const point2<T> &p, U t) {
    return point2<T>(p.x*t, p.y*t);
  }
  template <typename T, typename U>
  point2<U> operator *(T t, const point2<U> &p) {
    return point2<U>(t*p.x, t*p.y);
  }

} }

namespace muspelheim {

template<typename Pixel, typename T = double>
class flame_function {
public:
  using point_type = boost::gil::point2<T>;
  using pixel_type = Pixel;
  using function_type = std::function<
    point_type(const point_type &, const affine_transform<T> &)
  >;
  using value_type = std::pair<function_type, T>;

  flame_function(const function_type &f,
                 const affine_transform<T> &transform,
                 const Pixel &color,
                 const affine_transform<T> &post = {1, 0, 0, 0, 1, 0})
    : flame_function({{f, 1}}, transform, color, post) {}

  flame_function(const std::initializer_list<value_type> &f,
                 const affine_transform<T> &transform,
                 const Pixel &color,
                 const affine_transform<T> &post = {1, 0, 0, 0, 1, 0})
    : f_(f), transform_(transform), color_(color), post_(post) {}

  inline point_type operator ()(const point_type &p) const {
    point_type value = {0, 0};
    const auto &transformed = transform_(p);
    for(const auto &i : f_)
      value += i.second * i.first(transformed, transform_);
    return post_(value);
  }

  inline pixel_type color() const {
    return color_;
  }
private:
  std::vector<value_type> f_;
  affine_transform<T> transform_;
  Pixel color_;
  affine_transform<T> post_;
};

template<typename Pixel, typename T = double>
using flame_function_set = std::vector<flame_function<Pixel, T>>;

template<typename ChannelValue, typename Layout>
boost::gil::pixel<ChannelValue, Layout>
blend(const boost::gil::pixel<ChannelValue, Layout> &a,
      const boost::gil::pixel<ChannelValue, Layout> &b, double ratio) {
  boost::gil::pixel<ChannelValue, Layout> p;
  constexpr size_t channels = boost::mpl::size<
    typename Layout::color_space_t
  >::value;

  for(int i = 0; i < channels; i++)
    p[i] = a[i] * ratio + b[i] * (1 - ratio);
  return p;
}

template<typename View, typename Pixel, typename T>
void chaos_game(const View &dst, const flame_function_set<Pixel, T> &funcs,
                size_t num_iterations = 10000000) {
  using namespace boost::gil;
  using biunit_pt = point2<T>;
  using image_pt = point2<ptrdiff_t>;
  using color_image_t = image<Pixel, false>;

  std::default_random_engine engine(std::random_device{}());
  std::uniform_int_distribution<size_t> random_func(0, funcs.size() - 1);
  std::uniform_real_distribution<T> random_biunit(-1, 1);

  gray32_image_t alpha_img(dst.dimensions(), gray32_pixel_t(0), 0);
  auto alpha = view(alpha_img);

  color_image_t color_img(dst.dimensions(), Pixel(0), 0);
  auto color = view(color_img);

  biunit_pt point(random_biunit(engine), random_biunit(engine));

  for(size_t i = 0; i < 20; i++)
    point = funcs[random_func(engine)](point);

  for(size_t i = 0; i < num_iterations; i++) {
    auto &f = funcs[random_func(engine)];
    point = f(point);
    image_pt pt(
      static_cast<ptrdiff_t>((point.x + 1) / 2 * alpha.width()),
      static_cast<ptrdiff_t>((point.y + 1) / 2 * alpha.height())
    );
    if(pt.x < 0 || pt.x >= alpha.width() ||
       pt.y < 0 || pt.y >= alpha.height())
      continue;

    if(!alpha(pt)[0])
      color(pt) = f.color();
    else
      color(pt) = blend(color(pt), f.color(), 0.9);

    alpha(pt)[0]++;
  }

  bits32 max_alpha = 0;
  for(const auto &a : alpha) {
    if(a[0] > max_alpha)
      max_alpha = a[0];
  }

  auto logmax = std::log(static_cast<T>(max_alpha));
  for(size_t x = 0; x < dst.width(); x++) {
    for(size_t y = 0; y < dst.height(); y++) {
      auto a = std::log(static_cast<T>(alpha(x, y)[0])) / logmax;
      auto &c = color(x, y);
      dst(x, y) = typename View::value_type(c[0] * a, c[1] * a, c[2] * a);
    }
  }
}

} // namespace muspelheim

#endif
<commit_msg>Simplify the final rendering step to use 1D iteration<commit_after>#ifndef INC_MUSPELHEIM_HPP
#define INC_MUSPELHEIM_HPP

#include <functional>
#include <random>
#include <vector>

#include <boost/gil/extension/io/png_dynamic_io.hpp>
#include <boost/gil/image.hpp>
#include <boost/gil/typedefs.hpp>

// Make sure that multiplying points by floating-point values works correctly.
namespace boost { namespace gil {

  template <typename T, typename U>
  point2<T> operator *(const point2<T> &p, U t) {
    return point2<T>(p.x*t, p.y*t);
  }
  template <typename T, typename U>
  point2<U> operator *(T t, const point2<U> &p) {
    return point2<U>(t*p.x, t*p.y);
  }

} }

namespace muspelheim {

template<typename Pixel, typename T = double>
class flame_function {
public:
  using point_type = boost::gil::point2<T>;
  using pixel_type = Pixel;
  using function_type = std::function<
    point_type(const point_type &, const affine_transform<T> &)
  >;
  using value_type = std::pair<function_type, T>;

  flame_function(const function_type &f,
                 const affine_transform<T> &transform,
                 const Pixel &color,
                 const affine_transform<T> &post = {1, 0, 0, 0, 1, 0})
    : flame_function({{f, 1}}, transform, color, post) {}

  flame_function(const std::initializer_list<value_type> &f,
                 const affine_transform<T> &transform,
                 const Pixel &color,
                 const affine_transform<T> &post = {1, 0, 0, 0, 1, 0})
    : f_(f), transform_(transform), color_(color), post_(post) {}

  inline point_type operator ()(const point_type &p) const {
    point_type value = {0, 0};
    const auto &transformed = transform_(p);
    for(const auto &i : f_)
      value += i.second * i.first(transformed, transform_);
    return post_(value);
  }

  inline pixel_type color() const {
    return color_;
  }
private:
  std::vector<value_type> f_;
  affine_transform<T> transform_;
  Pixel color_;
  affine_transform<T> post_;
};

template<typename Pixel, typename T = double>
using flame_function_set = std::vector<flame_function<Pixel, T>>;

template<typename ChannelValue, typename Layout>
boost::gil::pixel<ChannelValue, Layout>
blend(const boost::gil::pixel<ChannelValue, Layout> &a,
      const boost::gil::pixel<ChannelValue, Layout> &b, double ratio) {
  boost::gil::pixel<ChannelValue, Layout> p;
  constexpr size_t channels = boost::mpl::size<
    typename Layout::color_space_t
  >::value;

  for(int i = 0; i < channels; i++)
    p[i] = a[i] * ratio + b[i] * (1 - ratio);
  return p;
}

template<typename View, typename Pixel, typename T>
void chaos_game(const View &dst, const flame_function_set<Pixel, T> &funcs,
                size_t num_iterations = 10000000) {
  using namespace boost::gil;
  using biunit_pt = point2<T>;
  using image_pt = point2<ptrdiff_t>;
  using color_image_t = image<Pixel, false>;

  std::default_random_engine engine(std::random_device{}());
  std::uniform_int_distribution<size_t> random_func(0, funcs.size() - 1);
  std::uniform_real_distribution<T> random_biunit(-1, 1);

  gray32_image_t alpha_img(dst.dimensions(), gray32_pixel_t(0), 0);
  auto alpha = view(alpha_img);

  color_image_t color_img(dst.dimensions(), Pixel(0), 0);
  auto color = view(color_img);

  biunit_pt point(random_biunit(engine), random_biunit(engine));

  for(size_t i = 0; i < 20; i++)
    point = funcs[random_func(engine)](point);

  for(size_t i = 0; i < num_iterations; i++) {
    auto &f = funcs[random_func(engine)];
    point = f(point);
    image_pt pt(
      static_cast<ptrdiff_t>((point.x + 1) / 2 * alpha.width()),
      static_cast<ptrdiff_t>((point.y + 1) / 2 * alpha.height())
    );
    if(pt.x < 0 || pt.x >= alpha.width() ||
       pt.y < 0 || pt.y >= alpha.height())
      continue;

    if(!alpha(pt)[0])
      color(pt) = f.color();
    else
      color(pt) = blend(color(pt), f.color(), 0.9);

    alpha(pt)[0]++;
  }

  bits32 max_alpha = 0;
  for(const auto &a : alpha) {
    if(a[0] > max_alpha)
      max_alpha = a[0];
  }

  auto logmax = std::log(static_cast<T>(max_alpha));
  for(size_t i = 0; i != dst.size(); i++) {
    auto a = std::log(static_cast<T>(alpha[i][0])) / logmax;
    auto &c = color[i];
    dst[i] = typename View::value_type(c[0] * a, c[1] * a, c[2] * a);
  }
}

} // namespace muspelheim

#endif
<|endoftext|>


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

#include "base/bind.h"
#include "base/bind_helpers.h"
#include "media/audio/test_audio_input_controller_factory.h"
#include "media/audio/audio_io.h"

namespace media {

TestAudioInputController::TestAudioInputController(
    TestAudioInputControllerFactory* factory,
    AudioManager* audio_manager,
    EventHandler* event_handler,
    SyncWriter* sync_writer)
    : AudioInputController(event_handler, sync_writer),
      factory_(factory),
      event_handler_(event_handler) {
  message_loop_ = audio_manager->GetMessageLoop();
}

TestAudioInputController::~TestAudioInputController() {
  // Inform the factory so that it allows creating new instances in future.
  factory_->OnTestAudioInputControllerDestroyed(this);
}

void TestAudioInputController::Close(const base::Closure& closed_task) {
  message_loop_->PostTaskAndReply(FROM_HERE,
                                  base::Bind(&base::DoNothing),
                                  closed_task);
}

TestAudioInputControllerFactory::TestAudioInputControllerFactory()
    : controller_(NULL) {
}

AudioInputController* TestAudioInputControllerFactory::Create(
    AudioManager* audio_manager,
    AudioInputController::EventHandler* event_handler,
    AudioParameters params) {
  DCHECK(!controller_);  // Only one test instance managed at a time.
  controller_ = new TestAudioInputController(this, audio_manager,
      event_handler, NULL);
  return controller_;
}

void TestAudioInputControllerFactory::OnTestAudioInputControllerDestroyed(
    TestAudioInputController* controller) {
  DCHECK_EQ(controller_, controller);
  controller_ = NULL;
}

}  // namespace media
<commit_msg>Revert 129623, this was creating ~92 (test-only) heapcheck leak reports.<commit_after>// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "media/audio/test_audio_input_controller_factory.h"
#include "media/audio/audio_io.h"

namespace media {

TestAudioInputController::TestAudioInputController(
    TestAudioInputControllerFactory* factory,
    AudioManager* audio_manager,
    EventHandler* event_handler,
    SyncWriter* sync_writer)
    : AudioInputController(event_handler, sync_writer),
      factory_(factory),
      event_handler_(event_handler) {
  message_loop_ = audio_manager->GetMessageLoop();
}

TestAudioInputController::~TestAudioInputController() {
  // Inform the factory so that it allows creating new instances in future.
  factory_->OnTestAudioInputControllerDestroyed(this);
}

void TestAudioInputController::Close(const base::Closure& closed_task) {
  message_loop_->PostTask(FROM_HERE, closed_task);
}

TestAudioInputControllerFactory::TestAudioInputControllerFactory()
    : controller_(NULL) {
}

AudioInputController* TestAudioInputControllerFactory::Create(
    AudioManager* audio_manager,
    AudioInputController::EventHandler* event_handler,
    AudioParameters params) {
  DCHECK(!controller_);  // Only one test instance managed at a time.
  controller_ = new TestAudioInputController(this, audio_manager,
      event_handler, NULL);
  return controller_;
}

void TestAudioInputControllerFactory::OnTestAudioInputControllerDestroyed(
    TestAudioInputController* controller) {
  DCHECK_EQ(controller_, controller);
  controller_ = NULL;
}

}  // namespace media
<|endoftext|>


<commit_before>/*=========================================================================
 *
 *  Copyright The University of North Carolina at Chapel Hill
 *  All rights reserved.
 *
 *  Licensed under the MADAI Software License. You may obtain a copy of
 *  this license at
 *
 *         https://madai-public.cs.unc.edu/software/license/
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 *
 *=========================================================================*/

#include "SimpleMetropolisHastingsSampler.h"

#include <cassert>
#include <cmath> // std::sin, cos, log, sqrt
#include <algorithm> // std::count

namespace madai {

SimpleMetropolisHastingsSampler
::SimpleMetropolisHastingsSampler( const Model * model ) :
  Sampler( model ),
  m_StepSize( 1.0e-2 ),
  m_NumberOfParameters( model->GetNumberOfParameters() ),
  m_NumberOfOutputs( model->GetNumberOfScalarOutputs() ),
  m_LastStepParameters( model->GetNumberOfParameters() ),
  m_LastStepOutputs( model->GetNumberOfScalarOutputs() ),
  m_LastStepLogLikelihood (-1e30)
{
  assert(model != NULL);
  for ( unsigned int i = 0; i < m_NumberOfParameters; i++ ) {
    double range[2];
    m_Model->GetRange( i, range );
    m_LastStepParameters[i] = 0.5 * (range[0] + range[1]);
    //FIXME should we have a random starting point?
  }
  Model * m = const_cast< Model * >(m_Model);
  m->GetScalarOutputsAndLogLikelihood(
    m_LastStepParameters,
    m_LastStepOutputs,
    m_LastStepLogLikelihood); // initial starting point.
}

SimpleMetropolisHastingsSampler
::~SimpleMetropolisHastingsSampler()
{
}

void SimpleMetropolisHastingsSampler
::SetStepSize( double stepSize )
{
  m_StepSize = stepSize;
}

static inline double uniform_rand()
 {
  // fixme better algorithm, seed.
  const static double R = 1.0 / static_cast<double>(RAND_MAX);
  return R * static_cast<double>(rand());
}

static inline void random_multinormal(double *d, size_t n,
                                      double * sqmodulus = NULL)
{
  //Box-Muller
  static const double TWO_PI = 6.28318530718;
  double sum_of_squares = 0.0;
  for (size_t i = 0; i < n ; /* intentionally left blank */ ) {
    double r = std::sqrt(-2.0 * std::log(uniform_rand()));
    double theta = TWO_PI * uniform_rand();
    double x = r * std::cos(theta);
    sum_of_squares += (x * x);
    d[i++] = x;
    if (i < n) {
      double y = r * std::sin(theta);
      sum_of_squares += (y * y);
      d[i++] = y;
    }
  }
  if (sqmodulus != NULL)
    *sqmodulus = sum_of_squares;
}
static inline void random_inside_hypersphere(
    double scale, double *d, size_t n)
{
  double sqmodulus = 0.0;
  random_multinormal(d, n, &sqmodulus);
  scale *= (uniform_rand() / std::sqrt(sqmodulus));
  for (size_t i = 0; i < n ; ++i )
    d[i] *= scale;
}

void
SimpleMetropolisHastingsSampler
::NextSample( Trace *trace )
{
  // xc is x_candidate
  Model * m = const_cast< Model * >(m_Model);

  std::vector< double > xc( m_NumberOfParameters, 0.0 );
  std::vector< double > yc( m_NumberOfOutputs, 0.0 );

  unsigned int output_index = this->GetOutputScalarToOptimizeIndex();
  unsigned int numberOfActiveParameters = this->GetNumberOfActiveParameters();
  std::vector< double > randomStep( numberOfActiveParameters, 0.0 );

  assert( std::count(this->m_ActiveParameterIndices.begin(),
    this->m_ActiveParameterIndices.end(), true) == numberOfActiveParameters);

  for ( unsigned int giveup = 1048576; giveup != 0; --giveup ) {
    random_inside_hypersphere(
      m_StepSize, &(randomStep[0]), numberOfActiveParameters);
    unsigned int k = 0;
    for(unsigned int i = 0; i < m_NumberOfParameters; i++) {
      if (this->m_ActiveParameterIndices[i]) {
        xc[i] = m_LastStepParameters[i] + randomStep[k];
        k++;
      } else {
        xc[i] = m_LastStepParameters[i];
				// Not sure how to respect this->m_CurrentParameters[i] ???
				// for (i < m_NumberOfParameters)
				//   if (!this->m_ActiveParameterIndices[i] &&
				//        (this->m_CurrentParameters[i] != m_LastStepParameters[i])) {
				//     do something;
				//   }
      }
    }

    if (m_OptimizeOnLikelihood) {
      double ll;
      m->GetScalarOutputsAndLogLikelihood(xc,yc,ll);
      double delta_logLikelihood = ll - m_LastStepLogLikelihood;
      if ((delta_logLikelihood > 0) ||
          (exp(delta_logLikelihood) > uniform_rand()))
        {
          m_LastStepLogLikelihood = ll;
          m_LastStepParameters = xc;
          m_LastStepOutputs = yc;
          trace->add(xc, yc, ll);
          return;
          //FIXME do somthing
        }
    } else {
      double ll;
      m->GetScalarOutputsAndLogLikelihood(xc,yc,ll);
      //m_Model->GetScalarOutputs(xc,yx);
      double f_of_x = m_LastStepOutputs[output_index];
      double f_of_xc = yc[output_index];
      if ((f_of_xc > f_of_x) || (f_of_xc > (f_of_x * uniform_rand())))
        {
          m_LastStepLogLikelihood = ll;
          m_LastStepParameters = xc;
          m_LastStepOutputs = yc;
          trace->add(xc, yc, ll);
          return;
          //FIXME do somthing ???
        }
    }
  }
}

} // end namespace madai
<commit_msg>Minor formatting changes<commit_after>/*=========================================================================
 *
 *  Copyright The University of North Carolina at Chapel Hill
 *  All rights reserved.
 *
 *  Licensed under the MADAI Software License. You may obtain a copy of
 *  this license at
 *
 *         https://madai-public.cs.unc.edu/software/license/
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 *
 *=========================================================================*/

#include "SimpleMetropolisHastingsSampler.h"

#include <cassert>
#include <cmath> // std::sin, cos, log, sqrt
#include <algorithm> // std::count

namespace madai {

SimpleMetropolisHastingsSampler
::SimpleMetropolisHastingsSampler( const Model * model ) :
  Sampler( model ),
  m_StepSize( 1.0e-2 ),
  m_NumberOfParameters( model->GetNumberOfParameters() ),
  m_NumberOfOutputs( model->GetNumberOfScalarOutputs() ),
  m_LastStepParameters( model->GetNumberOfParameters() ),
  m_LastStepOutputs( model->GetNumberOfScalarOutputs() ),
  m_LastStepLogLikelihood (-1e30)
{
  assert(model != NULL);
  for ( unsigned int i = 0; i < m_NumberOfParameters; i++ ) {
    double range[2];
    m_Model->GetRange( i, range );
    m_LastStepParameters[i] = 0.5 * (range[0] + range[1]);
    //FIXME should we have a random starting point?
  }
  Model * m = const_cast< Model * >(m_Model);
  m->GetScalarOutputsAndLogLikelihood(
    m_LastStepParameters,
    m_LastStepOutputs,
    m_LastStepLogLikelihood); // initial starting point.
}

SimpleMetropolisHastingsSampler
::~SimpleMetropolisHastingsSampler()
{
}

void SimpleMetropolisHastingsSampler
::SetStepSize( double stepSize )
{
  m_StepSize = stepSize;
}

static inline double uniform_rand()
 {
  // fixme better algorithm, seed.
  const static double R = 1.0 / static_cast<double>(RAND_MAX);
  return R * static_cast<double>(rand());
}

static inline void random_multinormal(double *d, size_t n,
                                      double * sqmodulus = NULL)
{
  //Box-Muller
  static const double TWO_PI = 6.28318530718;
  double sum_of_squares = 0.0;
  for (size_t i = 0; i < n ; /* intentionally left blank */ ) {
    double r = std::sqrt(-2.0 * std::log(uniform_rand()));
    double theta = TWO_PI * uniform_rand();
    double x = r * std::cos(theta);
    sum_of_squares += (x * x);
    d[i++] = x;
    if (i < n) {
      double y = r * std::sin(theta);
      sum_of_squares += (y * y);
      d[i++] = y;
    }
  }
  if (sqmodulus != NULL)
    *sqmodulus = sum_of_squares;
}

static inline void random_inside_hypersphere( double scale, double *d, size_t n )
{
  double sqmodulus = 0.0;
  random_multinormal(d, n, &sqmodulus);
  scale *= (uniform_rand() / std::sqrt(sqmodulus));
  for (size_t i = 0; i < n ; ++i )
    d[i] *= scale;
}

void
SimpleMetropolisHastingsSampler
::NextSample( Trace *trace )
{
  // xc is x_candidate
  Model * m = const_cast< Model * >(m_Model);

  std::vector< double > xc( m_NumberOfParameters, 0.0 );
  std::vector< double > yc( m_NumberOfOutputs, 0.0 );

  unsigned int output_index = this->GetOutputScalarToOptimizeIndex();
  unsigned int numberOfActiveParameters = this->GetNumberOfActiveParameters();
  std::vector< double > randomStep( numberOfActiveParameters, 0.0 );

  assert( std::count( this->m_ActiveParameterIndices.begin(),
                      this->m_ActiveParameterIndices.end(), true ) == numberOfActiveParameters);

  for ( unsigned int giveup = 1048576; giveup != 0; --giveup ) {
    random_inside_hypersphere( m_StepSize,
                               &(randomStep[0]),
                               numberOfActiveParameters );

    unsigned int k = 0;
    for ( unsigned int i = 0; i < m_NumberOfParameters; i++ ) {
      if ( m_ActiveParameterIndices[i] ) {
        xc[i] = m_LastStepParameters[i] + randomStep[k];
        k++;
      } else {
        xc[i] = m_LastStepParameters[i];
        // Not sure how to respect this->m_CurrentParameters[i] ???
        // for (i < m_NumberOfParameters)
        //   if (!this->m_ActiveParameterIndices[i] &&
        //        (this->m_CurrentParameters[i] != m_LastStepParameters[i])) {
        //     do something;
        //   }
      }
    }

    if ( m_OptimizeOnLikelihood ) {
      double ll;
      m->GetScalarOutputsAndLogLikelihood(xc,yc,ll);
      double delta_logLikelihood = ll - m_LastStepLogLikelihood;

      if ((delta_logLikelihood > 0) ||
          (exp(delta_logLikelihood) > uniform_rand())) {
        m_LastStepLogLikelihood = ll;
        m_LastStepParameters = xc;
        m_LastStepOutputs = yc;
        trace->add(xc, yc, ll);
        return;
      }
    } else {
      double ll;
      m->GetScalarOutputsAndLogLikelihood(xc,yc,ll);

      double f_of_x = m_LastStepOutputs[output_index];
      double f_of_xc = yc[output_index];

      if ((f_of_xc > f_of_x) || (f_of_xc > (f_of_x * uniform_rand()))) {
        m_LastStepLogLikelihood = ll;
        m_LastStepParameters = xc;
        m_LastStepOutputs = yc;
        trace->add(xc, yc, ll);
        return;
      }
    }
  }
}

} // end namespace madai
<|endoftext|>


<commit_before>/*
** Copyright 2009-2012 Merethis
**
** This file is part of Centreon Broker.
**
** Centreon Broker is free software: you can redistribute it and/or
** modify it under the terms of the GNU General Public License version 2
** as published by the Free Software Foundation.
**
** Centreon Broker is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
** General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with Centreon Broker. If not, see
** <http://www.gnu.org/licenses/>.
*/

#include <QCoreApplication>
#include <QTimer>
#include <stddef.h>
#include <string.h>
#include "com/centreon/broker/config/applier/endpoint.hh"
#include "com/centreon/broker/config/applier/init.hh"
#include "com/centreon/broker/config/applier/logger.hh"
#include "com/centreon/broker/config/applier/modules.hh"
#include "com/centreon/broker/config/parser.hh"
#include "com/centreon/broker/config/state.hh"
#include "com/centreon/broker/exceptions/msg.hh"
#include "com/centreon/broker/logging/file.hh"
#include "com/centreon/broker/logging/logging.hh"
#include "com/centreon/broker/logging/manager.hh"
#include "com/centreon/broker/neb/callbacks.hh"
#include "com/centreon/broker/neb/internal.hh"
#include "com/centreon/broker/neb/monitoring_logger.hh"
#include "com/centreon/engine/common.hh"
#include "com/centreon/engine/globals.hh"
#include "com/centreon/engine/nebcallbacks.hh"

using namespace com::centreon;
using namespace com::centreon::broker;

// Specify the event broker API version.
NEB_API_VERSION(CURRENT_NEB_API_VERSION)

// Centreon Engine/Nagios function.
extern "C" {
  extern timed_event* event_list_high;
  extern timed_event* event_list_high_tail;
}

/**************************************
*                                     *
*           Static Objects            *
*                                     *
**************************************/

// Qt initialization flag.
static bool        gl_initialized_qt(false);
static int         gl_qt_argc;
static char const* gl_qt_argv[2] = {
  "CentreonBrokerModule",
  NULL
};

/**************************************
*                                     *
*          Static Functions           *
*                                     *
**************************************/

/**
 *  Process Qt events.
 *
 *  @param[in] arg Unused.
 */
static void process_qcore(void* arg) {
  (void)arg;
  QCoreApplication* app(QCoreApplication::instance());
  QTimer::singleShot(0, app, SLOT(quit()));
  app->exec();
  return ;
}

/**************************************
*                                     *
*         Exported Functions          *
*                                     *
**************************************/

extern "C" {
  /**
   *  @brief Module exit point.
   *
   *  This function is called when the module gets unloaded by Nagios.
   *  It will deregister all previously registered callbacks and perform
   *  some shutdown stuff.
   *
   *  @param[in] flags  Informational flags.
   *  @param[in] reason Unload reason.
   *
   *  @return 0 on success, any other value on failure.
   */
  int nebmodule_deinit(int flags, int reason) {
    (void)flags;
    (void)reason;

    try {
      // Unregister callbacks.
      neb::unregister_callbacks();

      // Unload singletons.
      broker::config::applier::deinit();

      // Deregister Qt application object.
      if (gl_initialized_qt) {
        timed_event* te(NULL);
        for (timed_event* current = event_list_high;
             current != event_list_high_tail;
             current = current->next)
          if (current->event_data == (void*)process_qcore) {
            te = current;
            break ;
          }
        if (te)
          remove_event(te, &event_list_high, &event_list_high_tail);
        delete QCoreApplication::instance();
      }
    }
    // Avoid exception propagation in C code.
    catch (...) {}

    return (0);
  }

  /**
   *  @brief Module entry point.
   *
   *  This function is called when the module gets loaded by Nagios. It
   *  will register callbacks to catch events and perform some
   *  initialization stuff like config file parsing, thread creation,
   *  ...
   *
   *  @param[in] flags  Informational flags.
   *  @param[in] args   The argument string of the module (shall contain the
   *                    configuration file name).
   *  @param[in] handle The module handle.
   *
   *  @return 0 on success, any other value on failure.
   */
  int nebmodule_init(int flags, char const* args, void* handle) {
    // Initialization.
    broker::config::applier::init();

    // Save module handle and flags for future use.
    neb::gl_mod_flags = flags;
    neb::gl_mod_handle = handle;

    // Set module informations.
    neb_set_module_info(
      neb::gl_mod_handle,
      NEBMODULE_MODINFO_TITLE,
      "Centreon Broker's cbmod");
    neb_set_module_info(
      neb::gl_mod_handle,
      NEBMODULE_MODINFO_AUTHOR,
      "Merethis");
    neb_set_module_info(
      neb::gl_mod_handle,
      NEBMODULE_MODINFO_COPYRIGHT,
      "Copyright 2009-2012 Merethis");
    neb_set_module_info(
      neb::gl_mod_handle,
      NEBMODULE_MODINFO_VERSION,
      CENTREON_BROKER_VERSION);
    neb_set_module_info(
      neb::gl_mod_handle,
      NEBMODULE_MODINFO_LICENSE,
      "GPL version 2");
    neb_set_module_info(
      neb::gl_mod_handle,
      NEBMODULE_MODINFO_DESC,
      "cbmod is part of CentreonBroker and is designed to " \
      "convert internal Nagios events to a proper data "    \
      "stream that can then be parsed by CentreonBroker's " \
      "cbd.");

    // Initialize Qt if not already done by parent process.
    if (!QCoreApplication::instance()) {
      gl_initialized_qt = true;
      new QCoreApplication(gl_qt_argc, (char**)gl_qt_argv);
    }

    // Disable timestamp printing in logs (cause starvation when forking).
    logging::file::with_timestamp(false);

    // Default logging object.
    neb::monitoring_logger monlog;

    try {
      // Default logging object.
      {
        // Debug ?
        bool debug;
        char const* dbg_flag("-d ");
        if (args && !strncmp(args, dbg_flag, strlen(dbg_flag))) {
          debug = true;
          args += strlen(dbg_flag);
        }
        else
          debug = false;

        // Add log.
        logging::manager::instance().log_on(
                                       monlog,
                                       (debug
                                        ? logging::config_type
                                        | logging::debug_type
                                        | logging::error_type
                                        | logging::info_type
                                        : logging::config_type
                                        | logging::error_type
                                        | logging::info_type),
                                       (debug ?
                                        logging::low
                                        : logging::high));
      }

      // Set configuration file.
      if (args) {
        char const* config_file("config_file=");
        size_t config_file_size(strlen(config_file));
        if (!strncmp(args, config_file, config_file_size))
          args += config_file_size;
        neb::gl_configuration_file = args;
      }
      else
        throw (exceptions::msg()
                 << "main: no configuration file provided");

      // Try configuration parsing.
      broker::config::parser p;
      broker::config::state s;
      p.parse(neb::gl_configuration_file, s);

      // Apply loggers.
      broker::config::applier::logger::instance().apply(s.loggers());

      // Remove monitoring log.
      logging::manager::instance().log_on(monlog, 0);
    }
    catch (std::exception const& e) {
      logging::error(logging::high) << e.what();
      logging::manager::instance().log_on(monlog, 0);
      return (-1);
    }
    catch (...) {
      logging::error(logging::high)
        << "main: configuration file parsing failed";
      logging::manager::instance().log_on(monlog, 0);
      return (-1);
    }

    // Remove old monitoring object.
    logging::manager::instance().log_on(monlog, 0);

    // Register process callback.
    if (neb_register_callback(
          NEBCALLBACK_PROCESS_DATA,
          neb::gl_mod_handle,
          0,
          &neb::callback_process) != OK)
      return (-1);

    // Process Qt events if necessary.
    if (gl_initialized_qt)
      schedule_new_event(
        99,
        1,
        time(NULL) + 1,
        1,
        1,
        NULL,
        1,
        (void*)process_qcore,
        NULL,
        0);

    return (0);
  }
}
<commit_msg>Discard SIGCHLD if NEB module load Qt (performance improvement).<commit_after>/*
** Copyright 2009-2012 Merethis
**
** This file is part of Centreon Broker.
**
** Centreon Broker is free software: you can redistribute it and/or
** modify it under the terms of the GNU General Public License version 2
** as published by the Free Software Foundation.
**
** Centreon Broker is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
** General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with Centreon Broker. If not, see
** <http://www.gnu.org/licenses/>.
*/

#include <csignal>
#include <cstring>
#include <QCoreApplication>
#include <QTimer>
#include "com/centreon/broker/config/applier/endpoint.hh"
#include "com/centreon/broker/config/applier/init.hh"
#include "com/centreon/broker/config/applier/logger.hh"
#include "com/centreon/broker/config/applier/modules.hh"
#include "com/centreon/broker/config/parser.hh"
#include "com/centreon/broker/config/state.hh"
#include "com/centreon/broker/exceptions/msg.hh"
#include "com/centreon/broker/logging/file.hh"
#include "com/centreon/broker/logging/logging.hh"
#include "com/centreon/broker/logging/manager.hh"
#include "com/centreon/broker/neb/callbacks.hh"
#include "com/centreon/broker/neb/internal.hh"
#include "com/centreon/broker/neb/monitoring_logger.hh"
#include "com/centreon/engine/common.hh"
#include "com/centreon/engine/globals.hh"
#include "com/centreon/engine/nebcallbacks.hh"

using namespace com::centreon;
using namespace com::centreon::broker;

// Specify the event broker API version.
NEB_API_VERSION(CURRENT_NEB_API_VERSION)

// Centreon Engine/Nagios function.
extern "C" {
  extern timed_event* event_list_high;
  extern timed_event* event_list_high_tail;
}

/**************************************
*                                     *
*           Static Objects            *
*                                     *
**************************************/

// Qt initialization flag.
static bool        gl_initialized_qt(false);
static int         gl_qt_argc;
static char const* gl_qt_argv[2] = {
  "CentreonBrokerModule",
  NULL
};

/**************************************
*                                     *
*          Static Functions           *
*                                     *
**************************************/

/**
 *  Process Qt events.
 *
 *  @param[in] arg Unused.
 */
static void process_qcore(void* arg) {
  (void)arg;
  QCoreApplication* app(QCoreApplication::instance());
  QTimer::singleShot(0, app, SLOT(quit()));
  app->exec();
  return ;
}

/**************************************
*                                     *
*         Exported Functions          *
*                                     *
**************************************/

extern "C" {
  /**
   *  @brief Module exit point.
   *
   *  This function is called when the module gets unloaded by Nagios.
   *  It will deregister all previously registered callbacks and perform
   *  some shutdown stuff.
   *
   *  @param[in] flags  Informational flags.
   *  @param[in] reason Unload reason.
   *
   *  @return 0 on success, any other value on failure.
   */
  int nebmodule_deinit(int flags, int reason) {
    (void)flags;
    (void)reason;

    try {
      // Unregister callbacks.
      neb::unregister_callbacks();

      // Unload singletons.
      broker::config::applier::deinit();

      // Deregister Qt application object.
      if (gl_initialized_qt) {
        timed_event* te(NULL);
        for (timed_event* current = event_list_high;
             current != event_list_high_tail;
             current = current->next)
          if (current->event_data == (void*)process_qcore) {
            te = current;
            break ;
          }
        if (te)
          remove_event(te, &event_list_high, &event_list_high_tail);
        delete QCoreApplication::instance();
      }
    }
    // Avoid exception propagation in C code.
    catch (...) {}

    return (0);
  }

  /**
   *  @brief Module entry point.
   *
   *  This function is called when the module gets loaded by Nagios. It
   *  will register callbacks to catch events and perform some
   *  initialization stuff like config file parsing, thread creation,
   *  ...
   *
   *  @param[in] flags  Informational flags.
   *  @param[in] args   The argument string of the module (shall contain the
   *                    configuration file name).
   *  @param[in] handle The module handle.
   *
   *  @return 0 on success, any other value on failure.
   */
  int nebmodule_init(int flags, char const* args, void* handle) {
    // Initialization.
    broker::config::applier::init();

    // Save module handle and flags for future use.
    neb::gl_mod_flags = flags;
    neb::gl_mod_handle = handle;

    // Set module informations.
    neb_set_module_info(
      neb::gl_mod_handle,
      NEBMODULE_MODINFO_TITLE,
      "Centreon Broker's cbmod");
    neb_set_module_info(
      neb::gl_mod_handle,
      NEBMODULE_MODINFO_AUTHOR,
      "Merethis");
    neb_set_module_info(
      neb::gl_mod_handle,
      NEBMODULE_MODINFO_COPYRIGHT,
      "Copyright 2009-2012 Merethis");
    neb_set_module_info(
      neb::gl_mod_handle,
      NEBMODULE_MODINFO_VERSION,
      CENTREON_BROKER_VERSION);
    neb_set_module_info(
      neb::gl_mod_handle,
      NEBMODULE_MODINFO_LICENSE,
      "GPL version 2");
    neb_set_module_info(
      neb::gl_mod_handle,
      NEBMODULE_MODINFO_DESC,
      "cbmod is part of CentreonBroker and is designed to " \
      "convert internal Nagios events to a proper data "    \
      "stream that can then be parsed by CentreonBroker's " \
      "cbd.");

    // Initialize Qt if not already done by parent process.
    if (!QCoreApplication::instance()) {
      gl_initialized_qt = true;
      new QCoreApplication(gl_qt_argc, (char**)gl_qt_argv);
      signal(SIGCHLD, SIG_DFL);
    }

    // Disable timestamp printing in logs (cause starvation when forking).
    logging::file::with_timestamp(false);

    // Default logging object.
    neb::monitoring_logger monlog;

    try {
      // Default logging object.
      {
        // Debug ?
        bool debug;
        char const* dbg_flag("-d ");
        if (args && !strncmp(args, dbg_flag, strlen(dbg_flag))) {
          debug = true;
          args += strlen(dbg_flag);
        }
        else
          debug = false;

        // Add log.
        logging::manager::instance().log_on(
                                       monlog,
                                       (debug
                                        ? logging::config_type
                                        | logging::debug_type
                                        | logging::error_type
                                        | logging::info_type
                                        : logging::config_type
                                        | logging::error_type
                                        | logging::info_type),
                                       (debug ?
                                        logging::low
                                        : logging::high));
      }

      // Set configuration file.
      if (args) {
        char const* config_file("config_file=");
        size_t config_file_size(strlen(config_file));
        if (!strncmp(args, config_file, config_file_size))
          args += config_file_size;
        neb::gl_configuration_file = args;
      }
      else
        throw (exceptions::msg()
                 << "main: no configuration file provided");

      // Try configuration parsing.
      broker::config::parser p;
      broker::config::state s;
      p.parse(neb::gl_configuration_file, s);

      // Apply loggers.
      broker::config::applier::logger::instance().apply(s.loggers());

      // Remove monitoring log.
      logging::manager::instance().log_on(monlog, 0);
    }
    catch (std::exception const& e) {
      logging::error(logging::high) << e.what();
      logging::manager::instance().log_on(monlog, 0);
      return (-1);
    }
    catch (...) {
      logging::error(logging::high)
        << "main: configuration file parsing failed";
      logging::manager::instance().log_on(monlog, 0);
      return (-1);
    }

    // Remove old monitoring object.
    logging::manager::instance().log_on(monlog, 0);

    // Register process callback.
    if (neb_register_callback(
          NEBCALLBACK_PROCESS_DATA,
          neb::gl_mod_handle,
          0,
          &neb::callback_process) != OK)
      return (-1);

    // Process Qt events if necessary.
    if (gl_initialized_qt)
      schedule_new_event(
        99,
        1,
        time(NULL) + 1,
        1,
        1,
        NULL,
        1,
        (void*)process_qcore,
        NULL,
        0);

    return (0);
  }
}
<|endoftext|>


<commit_before>/******************************************************************************
*       SOFA, Simulation Open-Framework Architecture, version 1.0 RC 1        *
*                (c) 2006-2011 MGH, INRIA, USTL, UJF, CNRS                    *
*                                                                             *
* This library is free software; you can redistribute it and/or modify it     *
* under the terms of the GNU Lesser General Public License as published by    *
* the Free Software Foundation; either version 2.1 of the License, or (at     *
* your option) any later version.                                             *
*                                                                             *
* This library is distributed in the hope that it will be useful, but WITHOUT *
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or       *
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License *
* for more details.                                                           *
*                                                                             *
* You should have received a copy of the GNU Lesser General Public License    *
* along with this library; if not, write to the Free Software Foundation,     *
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA.          *
*******************************************************************************
*                               SOFA :: Modules                               *
*                                                                             *
* Authors: The SOFA Team and external contributors (see Authors.txt)          *
*                                                                             *
* Contact information: contact@sofa-framework.org                             *
******************************************************************************/
#define SOFA_COMPONENT_CONSTRAINTSET_UNILATERALINTERACTIONCONSTRAINT_CPP
#include <sofa/component/constraintset/UnilateralInteractionConstraint.inl>
#include <sofa/defaulttype/Vec3Types.h>
#include <sofa/component/container/MechanicalObject.h>
#include <sofa/core/ObjectFactory.h>

namespace sofa
{

namespace component
{

namespace constraintset
{

using namespace sofa::defaulttype;
using namespace sofa::helper;

SOFA_DECL_CLASS(UnilateralInteractionConstraint)

int UnilateralInteractionConstraintClass = core::RegisterObject("TODO-UnilateralInteractionConstraint")
#ifndef SOFA_FLOAT
        .add< UnilateralInteractionConstraint<Vec3dTypes> >()
#endif
#ifndef SOFA_DOUBLE
        .add< UnilateralInteractionConstraint<Vec3fTypes> >()
#endif
        ;

#ifndef SOFA_FLOAT
template class SOFA_CONSTRAINT_API UnilateralInteractionConstraint<Vec3dTypes>;
#endif
#ifndef SOFA_DOUBLE
template class SOFA_CONSTRAINT_API UnilateralInteractionConstraint<Vec3fTypes>;
#endif

void UnilateralConstraintResolutionWithFriction::init(int line, double** w, double* force)
{
    _W[0]=w[line  ][line  ];
    _W[1]=w[line  ][line+1];
    _W[2]=w[line  ][line+2];
    _W[3]=w[line+1][line+1];
    _W[4]=w[line+1][line+2];
    _W[5]=w[line+2][line+2];

//	return;

    ////////////////// christian : the following does not work ! /////////
    if(_prev)
    {
        force[line] = _prev->popForce();
        force[line+1] = _prev->popForce();
        force[line+2] = _prev->popForce();
    }

}

void UnilateralConstraintResolutionWithFriction::resolution(int line, double** /*w*/, double* d, double* force, double * /*dfree*/)
{
    double f[2];
    double normFt;

    f[0] = force[line]; f[1] = force[line+1];
    force[line] -= d[line] / _W[0];

    if(force[line] < 0)
    {
        force[line]=0; force[line+1]=0; force[line+2]=0;
        return;
    }

    d[line+1] += _W[1] * (force[line]-f[0]);
    d[line+2] += _W[2] * (force[line]-f[0]);
    force[line+1] -= 2*d[line+1] / (_W[3] +_W[5]) ;
    force[line+2] -= 2*d[line+2] / (_W[3] +_W[5]) ;

    normFt = sqrt(force[line+1]*force[line+1] + force[line+2]*force[line+2]);

    if(normFt > _mu*force[line])
    {
        force[line+1] *= _mu*force[line]/normFt;
        force[line+2] *= _mu*force[line]/normFt;
    }
}

void UnilateralConstraintResolutionWithFriction::store(int line, double* force, bool /*convergence*/)
{
    if(_prev)
    {
        _prev->pushForce(force[line]);
        _prev->pushForce(force[line+1]);
        _prev->pushForce(force[line+2]);
    }

    if(_active)
    {
        *_active = (force[line] != 0);
        _active = NULL; // Won't be used in the haptic thread
    }
}

} // namespace constraintset

} // namespace component

} // namespace sofa

<commit_msg>r9821/sofa : Little optimization in UnilateralConstraintResolutionWithFriction.<commit_after>/******************************************************************************
*       SOFA, Simulation Open-Framework Architecture, version 1.0 RC 1        *
*                (c) 2006-2011 MGH, INRIA, USTL, UJF, CNRS                    *
*                                                                             *
* This library is free software; you can redistribute it and/or modify it     *
* under the terms of the GNU Lesser General Public License as published by    *
* the Free Software Foundation; either version 2.1 of the License, or (at     *
* your option) any later version.                                             *
*                                                                             *
* This library is distributed in the hope that it will be useful, but WITHOUT *
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or       *
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License *
* for more details.                                                           *
*                                                                             *
* You should have received a copy of the GNU Lesser General Public License    *
* along with this library; if not, write to the Free Software Foundation,     *
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA.          *
*******************************************************************************
*                               SOFA :: Modules                               *
*                                                                             *
* Authors: The SOFA Team and external contributors (see Authors.txt)          *
*                                                                             *
* Contact information: contact@sofa-framework.org                             *
******************************************************************************/
#define SOFA_COMPONENT_CONSTRAINTSET_UNILATERALINTERACTIONCONSTRAINT_CPP
#include <sofa/component/constraintset/UnilateralInteractionConstraint.inl>
#include <sofa/defaulttype/Vec3Types.h>
#include <sofa/component/container/MechanicalObject.h>
#include <sofa/core/ObjectFactory.h>

namespace sofa
{

namespace component
{

namespace constraintset
{

using namespace sofa::defaulttype;
using namespace sofa::helper;

SOFA_DECL_CLASS(UnilateralInteractionConstraint)

int UnilateralInteractionConstraintClass = core::RegisterObject("TODO-UnilateralInteractionConstraint")
#ifndef SOFA_FLOAT
        .add< UnilateralInteractionConstraint<Vec3dTypes> >()
#endif
#ifndef SOFA_DOUBLE
        .add< UnilateralInteractionConstraint<Vec3fTypes> >()
#endif
        ;

#ifndef SOFA_FLOAT
template class SOFA_CONSTRAINT_API UnilateralInteractionConstraint<Vec3dTypes>;
#endif
#ifndef SOFA_DOUBLE
template class SOFA_CONSTRAINT_API UnilateralInteractionConstraint<Vec3fTypes>;
#endif

void UnilateralConstraintResolutionWithFriction::init(int line, double** w, double* force)
{
    _W[0]=w[line  ][line  ];
    _W[1]=w[line  ][line+1];
    _W[2]=w[line  ][line+2];
    _W[3]=w[line+1][line+1];
    _W[4]=w[line+1][line+2];
    _W[5]=w[line+2][line+2];

//	return;

    ////////////////// christian : the following does not work ! /////////
    if(_prev)
    {
        force[line] = _prev->popForce();
        force[line+1] = _prev->popForce();
        force[line+2] = _prev->popForce();
    }

}

void UnilateralConstraintResolutionWithFriction::resolution(int line, double** /*w*/, double* d, double* force, double * /*dfree*/)
{
    double f[2];
    double normFt;

    f[0] = force[line]; f[1] = force[line+1];
    force[line] -= d[line] / _W[0];

    if(force[line] < 0)
    {
        force[line]=0; force[line+1]=0; force[line+2]=0;
        return;
    }

    d[line+1] += _W[1] * (force[line]-f[0]);
    d[line+2] += _W[2] * (force[line]-f[0]);
    force[line+1] -= 2*d[line+1] / (_W[3] +_W[5]) ;
    force[line+2] -= 2*d[line+2] / (_W[3] +_W[5]) ;

    normFt = sqrt(force[line+1]*force[line+1] + force[line+2]*force[line+2]);

	double fN = _mu*force[line];
    if(normFt > fN)
    {
		double factor = fN / normFt;
        force[line+1] *= factor;
        force[line+2] *= factor;
    }
}

void UnilateralConstraintResolutionWithFriction::store(int line, double* force, bool /*convergence*/)
{
    if(_prev)
    {
        _prev->pushForce(force[line]);
        _prev->pushForce(force[line+1]);
        _prev->pushForce(force[line+2]);
    }

    if(_active)
    {
        *_active = (force[line] != 0);
        _active = NULL; // Won't be used in the haptic thread
    }
}

} // namespace constraintset

} // namespace component

} // namespace sofa

<|endoftext|>


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

// This file contains implementations for the JNI FeSupport interface.

#include "service/fe-support.h"

#include <boost/scoped_ptr.hpp>

#include "codegen/llvm-codegen.h"
#include "common/init.h"
#include "common/logging.h"
#include "common/status.h"
#include "exec/catalog-op-executor.h"
#include "exprs/expr.h"
#include "exprs/expr-context.h"
#include "runtime/exec-env.h"
#include "runtime/runtime-state.h"
#include "runtime/hdfs-fs-cache.h"
#include "runtime/lib-cache.h"
#include "runtime/client-cache.h"
#include "util/cpu-info.h"
#include "util/disk-info.h"
#include "util/dynamic-util.h"
#include "util/jni-util.h"
#include "util/mem-info.h"
#include "util/symbols-util.h"
#include "rpc/thrift-util.h"
#include "rpc/thrift-server.h"
#include "util/debug-util.h"
#include "gen-cpp/Data_types.h"
#include "gen-cpp/Frontend_types.h"

using namespace impala;
using namespace std;
using namespace boost;
using namespace apache::thrift::server;

// Called from the FE when it explicitly loads libfesupport.so for tests.
// This creates the minimal state necessary to service the other JNI calls.
// This is not called when we first start up the BE.
extern "C"
JNIEXPORT void JNICALL
Java_com_cloudera_impala_service_FeSupport_NativeFeTestInit(
    JNIEnv* env, jclass caller_class) {
  DCHECK(ExecEnv::GetInstance() == NULL) << "This should only be called once from the FE";
  char* name = const_cast<char*>("FeSupport");
  InitCommonRuntime(1, &name, false, TestInfo::FE_TEST);
  LlvmCodeGen::InitializeLlvm(true);
  ExecEnv* exec_env = new ExecEnv(); // This also caches it from the process.
  exec_env->InitForFeTests();
}

// Evaluates a batch of const exprs and returns the results in a serialized
// TResultRow, where each TColumnValue in the TResultRow stores the result of
// a predicate evaluation. It requires JniUtil::Init() to have been
// called.
extern "C"
JNIEXPORT jbyteArray JNICALL
Java_com_cloudera_impala_service_FeSupport_NativeEvalConstExprs(
    JNIEnv* env, jclass caller_class, jbyteArray thrift_expr_batch,
    jbyteArray thrift_query_ctx_bytes) {
  jbyteArray result_bytes = NULL;
  TQueryCtx query_ctx;
  TExprBatch expr_batch;
  JniLocalFrame jni_frame;
  TResultRow expr_results;
  ObjectPool obj_pool;

  DeserializeThriftMsg(env, thrift_expr_batch, &expr_batch);
  DeserializeThriftMsg(env, thrift_query_ctx_bytes, &query_ctx);
  query_ctx.request.query_options.disable_codegen = true;
  RuntimeState state(query_ctx);

  THROW_IF_ERROR_RET(jni_frame.push(env), env, JniUtil::internal_exc_class(),
                     result_bytes);
  // Exprs can allocate memory so we need to set up the mem trackers before
  // preparing/running the exprs.
  state.InitMemTrackers(TUniqueId(), NULL, -1);

  vector<TExpr>& texprs = expr_batch.exprs;
  // Prepare the exprs
  vector<ExprContext*> expr_ctxs;
  for (vector<TExpr>::iterator it = texprs.begin(); it != texprs.end(); it++) {
    ExprContext* ctx;
    THROW_IF_ERROR_RET(Expr::CreateExprTree(&obj_pool, *it, &ctx), env,
                       JniUtil::internal_exc_class(), result_bytes);
    THROW_IF_ERROR_RET(ctx->Prepare(&state, RowDescriptor()), env,
                       JniUtil::internal_exc_class(), result_bytes);
    expr_ctxs.push_back(ctx);
  }

  if (state.codegen_created()) {
    // Finalize the module so any UDF functions are jit'd
    LlvmCodeGen* codegen = NULL;
    state.GetCodegen(&codegen, /* initialize */ false);
    DCHECK_NOTNULL(codegen);
    codegen->EnableOptimizations(false);
    codegen->FinalizeModule();
  }

  vector<TColumnValue> results;
  // Open and evaluate the exprs
  for (int i = 0; i < expr_ctxs.size(); ++i) {
    TColumnValue val;
    THROW_IF_ERROR_RET(expr_ctxs[i]->Open(&state), env,
                       JniUtil::internal_exc_class(), result_bytes);
    expr_ctxs[i]->GetValue(NULL, false, &val);
    expr_ctxs[i]->Close(&state);
    results.push_back(val);
  }
  expr_results.__set_colVals(results);
  THROW_IF_ERROR_RET(SerializeThriftMsg(env, &expr_results, &result_bytes), env,
                     JniUtil::internal_exc_class(), result_bytes);
  return result_bytes;
}

// Does the symbol resolution, filling in the result in *result.
static void ResolveSymbolLookup(const TSymbolLookupParams params,
    const vector<ColumnType>& arg_types, TSymbolLookupResult* result) {
  LibCache::LibType type;
  if (params.fn_binary_type == TFunctionBinaryType::NATIVE ||
      params.fn_binary_type == TFunctionBinaryType::BUILTIN) {
    // We use TYPE_SO for builtins, since LibCache does not resolve symbols for IR
    // builtins. This is ok since builtins have the same symbol whether we run the IR or
    // native versions.
    type = LibCache::TYPE_SO;
  } else if (params.fn_binary_type == TFunctionBinaryType::IR) {
    type = LibCache::TYPE_IR;
  } else if (params.fn_binary_type == TFunctionBinaryType::HIVE) {
    type = LibCache::TYPE_JAR;
  } else {
    DCHECK(false) << params.fn_binary_type;
  }

  // Builtin functions are loaded directly from the running process
  if (params.fn_binary_type != TFunctionBinaryType::BUILTIN) {
    // Refresh the library if necessary since we're creating a new function
    LibCache::instance()->SetNeedsRefresh(params.location);
    string dummy_local_path;
    Status status = LibCache::instance()->GetLocalLibPath(
        params.location, type, &dummy_local_path);
    if (!status.ok()) {
      result->__set_result_code(TSymbolLookupResultCode::BINARY_NOT_FOUND);
      result->__set_error_msg(status.GetErrorMsg());
      return;
    }
  }

  if (SymbolsUtil::IsMangled(params.symbol)) {
    DCHECK(params.fn_binary_type != TFunctionBinaryType::HIVE);
    Status status =
        LibCache::instance()->CheckSymbolExists(params.location, type, params.symbol);
    if (status.ok()) {
      // The FE specified symbol exists, just use that.
      result->__set_result_code(TSymbolLookupResultCode::SYMBOL_FOUND);
      result->__set_symbol(params.symbol);
      // TODO: we can demangle the user symbol here and validate it against
      // params.arg_types. This would prevent someone from typing the wrong symbol
      // by accident. This requires more string parsing of the symbol.
      return;
    } else {
      // The input was already mangled and we couldn't find it, return the error.
      result->__set_result_code(TSymbolLookupResultCode::SYMBOL_NOT_FOUND);
      stringstream ss;
      ss << "Could not find symbol '" << params.symbol << "' in: " << params.location;
      result->__set_error_msg(ss.str());
      return;
    }
  }

  string symbol = params.symbol;
  ColumnType ret_type(INVALID_TYPE);
  if (params.__isset.ret_arg_type) ret_type = ColumnType(params.ret_arg_type);

  if (params.fn_binary_type != TFunctionBinaryType::HIVE) {
    // Mangle the user input
    if (params.symbol_type == TSymbolType::UDF_EVALUATE) {
      symbol = SymbolsUtil::MangleUserFunction(params.symbol,
          arg_types, params.has_var_args, params.__isset.ret_arg_type ? &ret_type : NULL);
    } else {
      DCHECK(params.symbol_type == TSymbolType::UDF_PREPARE ||
             params.symbol_type == TSymbolType::UDF_CLOSE);
      symbol = SymbolsUtil::ManglePrepareOrCloseFunction(params.symbol);
    }
  }

  // Look up the symbol
  Status status = LibCache::instance()->CheckSymbolExists(params.location, type, symbol);
  if (!status.ok()) {
    result->__set_result_code(TSymbolLookupResultCode::SYMBOL_NOT_FOUND);
    stringstream ss;
    ss << "Could not find function " << params.symbol << "(";

    if (params.symbol_type == TSymbolType::UDF_EVALUATE) {
      for (int i = 0; i < arg_types.size(); ++i) {
        ss << arg_types[i].DebugString();
        if (i != arg_types.size() - 1) ss << ", ";
      }
    } else {
      ss << "impala_udf::FunctionContext*, "
         << "impala_udf::FunctionContext::FunctionStateScope";
    }

    ss << ")";
    if (params.__isset.ret_arg_type) ss << " returns " << ret_type.DebugString();
    ss << " in: " << params.location;
    if (params.__isset.ret_arg_type) {
      ss << "\nCheck that function name, arguments, and return type are correct.";
    } else {
      ss << "\nCheck that symbol and argument types are correct.";
    }
    result->__set_error_msg(ss.str());
    return;
  }

  // We were able to resolve the symbol.
  result->__set_result_code(TSymbolLookupResultCode::SYMBOL_FOUND);
  result->__set_symbol(symbol);
}

extern "C"
JNIEXPORT jbyteArray JNICALL
Java_com_cloudera_impala_service_FeSupport_NativeCacheJar(
    JNIEnv* env, jclass caller_class, jbyteArray thrift_struct) {
  TCacheJarParams params;
  DeserializeThriftMsg(env, thrift_struct, &params);

  TCacheJarResult result;
  string local_path;
  Status status = LibCache::instance()->GetLocalLibPath(params.hdfs_location,
      LibCache::TYPE_JAR, &local_path);
  status.ToThrift(&result.status);
  if (status.ok()) result.__set_local_path(local_path);

  jbyteArray result_bytes = NULL;
  THROW_IF_ERROR_RET(SerializeThriftMsg(env, &result, &result_bytes), env,
                     JniUtil::internal_exc_class(), result_bytes);
  return result_bytes;
}

extern "C"
JNIEXPORT jbyteArray JNICALL
Java_com_cloudera_impala_service_FeSupport_NativeLookupSymbol(
    JNIEnv* env, jclass caller_class, jbyteArray thrift_struct) {
  TSymbolLookupParams lookup;
  DeserializeThriftMsg(env, thrift_struct, &lookup);

  vector<ColumnType> arg_types;
  for (int i = 0; i < lookup.arg_types.size(); ++i) {
    arg_types.push_back(ColumnType(lookup.arg_types[i]));
  }

  TSymbolLookupResult result;
  ResolveSymbolLookup(lookup, arg_types, &result);

  jbyteArray result_bytes = NULL;
  THROW_IF_ERROR_RET(SerializeThriftMsg(env, &result, &result_bytes), env,
                     JniUtil::internal_exc_class(), result_bytes);
  return result_bytes;
}

// Calls in to the catalog server to request prioritizing the loading of metadata for
// specific catalog objects.
extern "C"
JNIEXPORT jbyteArray JNICALL
Java_com_cloudera_impala_service_FeSupport_NativePrioritizeLoad(
    JNIEnv* env, jclass caller_class, jbyteArray thrift_struct) {
  TPrioritizeLoadRequest request;
  DeserializeThriftMsg(env, thrift_struct, &request);

  CatalogOpExecutor catalog_op_executor(ExecEnv::GetInstance(), NULL);
  TPrioritizeLoadResponse result;
  Status status = catalog_op_executor.PrioritizeLoad(request, &result);
  if (!status.ok()) {
    LOG(ERROR) << status.GetErrorMsg();
    // Create a new Status, copy in this error, then update the result.
    Status catalog_service_status(result.status);
    catalog_service_status.AddError(status);
    status.ToThrift(&result.status);
  }

  jbyteArray result_bytes = NULL;
  THROW_IF_ERROR_RET(SerializeThriftMsg(env, &result, &result_bytes), env,
                     JniUtil::internal_exc_class(), result_bytes);
  return result_bytes;
}

namespace impala {

static JNINativeMethod native_methods[] = {
  {
    (char*)"NativeFeTestInit", (char*)"()V",
    (void*)::Java_com_cloudera_impala_service_FeSupport_NativeFeTestInit
  },
  {
    (char*)"NativeEvalConstExprs", (char*)"([B[B)[B",
    (void*)::Java_com_cloudera_impala_service_FeSupport_NativeEvalConstExprs
  },
  {
    (char*)"NativeCacheJar", (char*)"([B)[B",
    (void*)::Java_com_cloudera_impala_service_FeSupport_NativeCacheJar
  },
  {
    (char*)"NativeLookupSymbol", (char*)"([B)[B",
    (void*)::Java_com_cloudera_impala_service_FeSupport_NativeLookupSymbol
  },
  {
    (char*)"NativePrioritizeLoad", (char*)"([B)[B",
    (void*)::Java_com_cloudera_impala_service_FeSupport_NativePrioritizeLoad
  },
};

void InitFeSupport() {
  JNIEnv* env = getJNIEnv();
  jclass native_backend_cl = env->FindClass("com/cloudera/impala/service/FeSupport");
  env->RegisterNatives(native_backend_cl, native_methods,
      sizeof(native_methods) / sizeof(native_methods[0]));
  EXIT_IF_EXC(env);
}

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

// This file contains implementations for the JNI FeSupport interface.

#include "service/fe-support.h"

#include <boost/scoped_ptr.hpp>

#include "codegen/llvm-codegen.h"
#include "common/init.h"
#include "common/logging.h"
#include "common/status.h"
#include "exec/catalog-op-executor.h"
#include "exprs/expr.h"
#include "exprs/expr-context.h"
#include "runtime/exec-env.h"
#include "runtime/runtime-state.h"
#include "runtime/hdfs-fs-cache.h"
#include "runtime/lib-cache.h"
#include "runtime/client-cache.h"
#include "util/cpu-info.h"
#include "util/disk-info.h"
#include "util/dynamic-util.h"
#include "util/jni-util.h"
#include "util/mem-info.h"
#include "util/symbols-util.h"
#include "rpc/thrift-util.h"
#include "rpc/thrift-server.h"
#include "util/debug-util.h"
#include "gen-cpp/Data_types.h"
#include "gen-cpp/Frontend_types.h"

using namespace impala;
using namespace std;
using namespace boost;
using namespace apache::thrift::server;

// Called from the FE when it explicitly loads libfesupport.so for tests.
// This creates the minimal state necessary to service the other JNI calls.
// This is not called when we first start up the BE.
extern "C"
JNIEXPORT void JNICALL
Java_com_cloudera_impala_service_FeSupport_NativeFeTestInit(
    JNIEnv* env, jclass caller_class) {
  DCHECK(ExecEnv::GetInstance() == NULL) << "This should only be called once from the FE";
  char* name = const_cast<char*>("FeSupport");
  InitCommonRuntime(1, &name, false, TestInfo::FE_TEST);
  LlvmCodeGen::InitializeLlvm(true);
  ExecEnv* exec_env = new ExecEnv(); // This also caches it from the process.
  exec_env->InitForFeTests();
}

// Evaluates a batch of const exprs and returns the results in a serialized
// TResultRow, where each TColumnValue in the TResultRow stores the result of
// a predicate evaluation. It requires JniUtil::Init() to have been
// called.
extern "C"
JNIEXPORT jbyteArray JNICALL
Java_com_cloudera_impala_service_FeSupport_NativeEvalConstExprs(
    JNIEnv* env, jclass caller_class, jbyteArray thrift_expr_batch,
    jbyteArray thrift_query_ctx_bytes) {
  jbyteArray result_bytes = NULL;
  TQueryCtx query_ctx;
  TExprBatch expr_batch;
  JniLocalFrame jni_frame;
  TResultRow expr_results;
  ObjectPool obj_pool;

  DeserializeThriftMsg(env, thrift_expr_batch, &expr_batch);
  DeserializeThriftMsg(env, thrift_query_ctx_bytes, &query_ctx);
  query_ctx.request.query_options.disable_codegen = true;
  RuntimeState state(query_ctx);

  THROW_IF_ERROR_RET(jni_frame.push(env), env, JniUtil::internal_exc_class(),
                     result_bytes);
  // Exprs can allocate memory so we need to set up the mem trackers before
  // preparing/running the exprs.
  state.InitMemTrackers(TUniqueId(), NULL, -1);

  vector<TExpr>& texprs = expr_batch.exprs;
  // Prepare the exprs
  vector<ExprContext*> expr_ctxs;
  for (vector<TExpr>::iterator it = texprs.begin(); it != texprs.end(); it++) {
    ExprContext* ctx;
    THROW_IF_ERROR_RET(Expr::CreateExprTree(&obj_pool, *it, &ctx), env,
                       JniUtil::internal_exc_class(), result_bytes);
    THROW_IF_ERROR_RET(ctx->Prepare(&state, RowDescriptor()), env,
                       JniUtil::internal_exc_class(), result_bytes);
    expr_ctxs.push_back(ctx);
  }

  if (state.codegen_created()) {
    // Finalize the module so any UDF functions are jit'd
    LlvmCodeGen* codegen = NULL;
    state.GetCodegen(&codegen, /* initialize */ false);
    DCHECK_NOTNULL(codegen);
    codegen->EnableOptimizations(false);
    codegen->FinalizeModule();
  }

  vector<TColumnValue> results;
  // Open and evaluate the exprs
  for (int i = 0; i < expr_ctxs.size(); ++i) {
    TColumnValue val;
    THROW_IF_ERROR_RET(expr_ctxs[i]->Open(&state), env,
                       JniUtil::internal_exc_class(), result_bytes);
    expr_ctxs[i]->GetValue(NULL, false, &val);
    expr_ctxs[i]->Close(&state);
    results.push_back(val);
  }
  expr_results.__set_colVals(results);
  THROW_IF_ERROR_RET(SerializeThriftMsg(env, &expr_results, &result_bytes), env,
                     JniUtil::internal_exc_class(), result_bytes);
  return result_bytes;
}

// Does the symbol resolution, filling in the result in *result.
static void ResolveSymbolLookup(const TSymbolLookupParams params,
    const vector<ColumnType>& arg_types, TSymbolLookupResult* result) {
  LibCache::LibType type;
  if (params.fn_binary_type == TFunctionBinaryType::NATIVE ||
      params.fn_binary_type == TFunctionBinaryType::BUILTIN) {
    // We use TYPE_SO for builtins, since LibCache does not resolve symbols for IR
    // builtins. This is ok since builtins have the same symbol whether we run the IR or
    // native versions.
    type = LibCache::TYPE_SO;
  } else if (params.fn_binary_type == TFunctionBinaryType::IR) {
    type = LibCache::TYPE_IR;
  } else if (params.fn_binary_type == TFunctionBinaryType::HIVE) {
    type = LibCache::TYPE_JAR;
  } else {
    DCHECK(false) << params.fn_binary_type;
  }

  // Builtin functions are loaded directly from the running process
  if (params.fn_binary_type != TFunctionBinaryType::BUILTIN) {
    // Refresh the library if necessary since we're creating a new function
    LibCache::instance()->SetNeedsRefresh(params.location);
    string dummy_local_path;
    Status status = LibCache::instance()->GetLocalLibPath(
        params.location, type, &dummy_local_path);
    if (!status.ok()) {
      result->__set_result_code(TSymbolLookupResultCode::BINARY_NOT_FOUND);
      result->__set_error_msg(status.GetErrorMsg());
      return;
    }
  }

  if (params.fn_binary_type == TFunctionBinaryType::IR ||
      params.fn_binary_type == TFunctionBinaryType::HIVE ||
      SymbolsUtil::IsMangled(params.symbol)) {
    // Check if the FE specified symbol exists as-is.
    Status status =
        LibCache::instance()->CheckSymbolExists(params.location, type, params.symbol);
    if (status.ok()) {
      result->__set_result_code(TSymbolLookupResultCode::SYMBOL_FOUND);
      result->__set_symbol(params.symbol);
      // TODO: we can demangle the user symbol here and validate it against
      // params.arg_types. This would prevent someone from typing the wrong symbol
      // by accident. This requires more string parsing of the symbol.
      return;
    } else if (params.fn_binary_type != TFunctionBinaryType::IR) {
      // No use trying to mangle Hive or already mangled symbols, return the error.
      result->__set_result_code(TSymbolLookupResultCode::SYMBOL_NOT_FOUND);
      stringstream ss;
      ss << "Could not find symbol '" << params.symbol << "' in: " << params.location;
      result->__set_error_msg(ss.str());
      return;
    }
  }

  string symbol = params.symbol;
  ColumnType ret_type(INVALID_TYPE);
  if (params.__isset.ret_arg_type) ret_type = ColumnType(params.ret_arg_type);

  // Mangle the user input
  DCHECK_NE(params.fn_binary_type, TFunctionBinaryType::HIVE);
  if (params.symbol_type == TSymbolType::UDF_EVALUATE) {
    symbol = SymbolsUtil::MangleUserFunction(params.symbol,
        arg_types, params.has_var_args, params.__isset.ret_arg_type ? &ret_type : NULL);
  } else {
    DCHECK(params.symbol_type == TSymbolType::UDF_PREPARE ||
           params.symbol_type == TSymbolType::UDF_CLOSE);
    symbol = SymbolsUtil::ManglePrepareOrCloseFunction(params.symbol);
  }

  // Look up the mangled symbol
  Status status = LibCache::instance()->CheckSymbolExists(params.location, type, symbol);
  if (!status.ok()) {
    result->__set_result_code(TSymbolLookupResultCode::SYMBOL_NOT_FOUND);
    stringstream ss;
    ss << "Could not find function " << params.symbol << "(";

    if (params.symbol_type == TSymbolType::UDF_EVALUATE) {
      for (int i = 0; i < arg_types.size(); ++i) {
        ss << arg_types[i].DebugString();
        if (i != arg_types.size() - 1) ss << ", ";
      }
    } else {
      ss << "impala_udf::FunctionContext*, "
         << "impala_udf::FunctionContext::FunctionStateScope";
    }

    ss << ")";
    if (params.__isset.ret_arg_type) ss << " returns " << ret_type.DebugString();
    ss << " in: " << params.location;
    if (params.__isset.ret_arg_type) {
      ss << "\nCheck that function name, arguments, and return type are correct.";
    } else {
      ss << "\nCheck that symbol and argument types are correct.";
    }
    result->__set_error_msg(ss.str());
    return;
  }

  // We were able to resolve the symbol.
  result->__set_result_code(TSymbolLookupResultCode::SYMBOL_FOUND);
  result->__set_symbol(symbol);
}

extern "C"
JNIEXPORT jbyteArray JNICALL
Java_com_cloudera_impala_service_FeSupport_NativeCacheJar(
    JNIEnv* env, jclass caller_class, jbyteArray thrift_struct) {
  TCacheJarParams params;
  DeserializeThriftMsg(env, thrift_struct, &params);

  TCacheJarResult result;
  string local_path;
  Status status = LibCache::instance()->GetLocalLibPath(params.hdfs_location,
      LibCache::TYPE_JAR, &local_path);
  status.ToThrift(&result.status);
  if (status.ok()) result.__set_local_path(local_path);

  jbyteArray result_bytes = NULL;
  THROW_IF_ERROR_RET(SerializeThriftMsg(env, &result, &result_bytes), env,
                     JniUtil::internal_exc_class(), result_bytes);
  return result_bytes;
}

extern "C"
JNIEXPORT jbyteArray JNICALL
Java_com_cloudera_impala_service_FeSupport_NativeLookupSymbol(
    JNIEnv* env, jclass caller_class, jbyteArray thrift_struct) {
  TSymbolLookupParams lookup;
  DeserializeThriftMsg(env, thrift_struct, &lookup);

  vector<ColumnType> arg_types;
  for (int i = 0; i < lookup.arg_types.size(); ++i) {
    arg_types.push_back(ColumnType(lookup.arg_types[i]));
  }

  TSymbolLookupResult result;
  ResolveSymbolLookup(lookup, arg_types, &result);

  jbyteArray result_bytes = NULL;
  THROW_IF_ERROR_RET(SerializeThriftMsg(env, &result, &result_bytes), env,
                     JniUtil::internal_exc_class(), result_bytes);
  return result_bytes;
}

// Calls in to the catalog server to request prioritizing the loading of metadata for
// specific catalog objects.
extern "C"
JNIEXPORT jbyteArray JNICALL
Java_com_cloudera_impala_service_FeSupport_NativePrioritizeLoad(
    JNIEnv* env, jclass caller_class, jbyteArray thrift_struct) {
  TPrioritizeLoadRequest request;
  DeserializeThriftMsg(env, thrift_struct, &request);

  CatalogOpExecutor catalog_op_executor(ExecEnv::GetInstance(), NULL);
  TPrioritizeLoadResponse result;
  Status status = catalog_op_executor.PrioritizeLoad(request, &result);
  if (!status.ok()) {
    LOG(ERROR) << status.GetErrorMsg();
    // Create a new Status, copy in this error, then update the result.
    Status catalog_service_status(result.status);
    catalog_service_status.AddError(status);
    status.ToThrift(&result.status);
  }

  jbyteArray result_bytes = NULL;
  THROW_IF_ERROR_RET(SerializeThriftMsg(env, &result, &result_bytes), env,
                     JniUtil::internal_exc_class(), result_bytes);
  return result_bytes;
}

namespace impala {

static JNINativeMethod native_methods[] = {
  {
    (char*)"NativeFeTestInit", (char*)"()V",
    (void*)::Java_com_cloudera_impala_service_FeSupport_NativeFeTestInit
  },
  {
    (char*)"NativeEvalConstExprs", (char*)"([B[B)[B",
    (void*)::Java_com_cloudera_impala_service_FeSupport_NativeEvalConstExprs
  },
  {
    (char*)"NativeCacheJar", (char*)"([B)[B",
    (void*)::Java_com_cloudera_impala_service_FeSupport_NativeCacheJar
  },
  {
    (char*)"NativeLookupSymbol", (char*)"([B)[B",
    (void*)::Java_com_cloudera_impala_service_FeSupport_NativeLookupSymbol
  },
  {
    (char*)"NativePrioritizeLoad", (char*)"([B)[B",
    (void*)::Java_com_cloudera_impala_service_FeSupport_NativePrioritizeLoad
  },
};

void InitFeSupport() {
  JNIEnv* env = getJNIEnv();
  jclass native_backend_cl = env->FindClass("com/cloudera/impala/service/FeSupport");
  env->RegisterNatives(native_backend_cl, native_methods,
      sizeof(native_methods) / sizeof(native_methods[0]));
  EXIT_IF_EXC(env);
}

}
<|endoftext|>


<commit_before><commit_msg>BUG: Pass requires correct types on setp instructions..<commit_after><|endoftext|>


<commit_before>//=======================================================================
// Copyright (c) 2014 Baptiste Wicht
// Distributed under the terms of the MIT License.
// (See accompanying file LICENSE or copy at
//  http://opensource.org/licenses/MIT)
//=======================================================================

#ifndef ETL_GENERATORS_HPP
#define ETL_GENERATORS_HPP

#include <random>

namespace etl {

using random_engine = std::mt19937_64;

template<typename T>
struct scalar {
    const T value;

    explicit constexpr scalar(T v) : value(v) {}

    constexpr const T operator[](std::size_t) const {
        return value;
    }

    constexpr const T operator()(std::size_t) const {
        return value;
    }

    constexpr const T operator()(std::size_t, std::size_t) const {
        return value;
    }
};

template<typename T = double>
struct normal_generator_op {
    using value_type = T;

    random_engine rand_engine;
    std::normal_distribution<value_type> normal_distribution;

    normal_generator_op() : rand_engine(std::time(nullptr)), normal_distribution(0.0, 1.0) {}

    value_type operator()(){
        return normal_distribution(rand_engine);
    }
};

template<typename T = double>
struct sequence_generator_op {
    using value_type = T;

    value_type current = 0;

    sequence_generator_op(value_type start = 0) : current(start) {}

    value_type operator()(){
        return current++;
    }
};

} //end of namespace etl

#endif
<commit_msg>Support for higher dimensions<commit_after>//=======================================================================
// Copyright (c) 2014 Baptiste Wicht
// Distributed under the terms of the MIT License.
// (See accompanying file LICENSE or copy at
//  http://opensource.org/licenses/MIT)
//=======================================================================

#ifndef ETL_GENERATORS_HPP
#define ETL_GENERATORS_HPP

#include <random>

#include "cpp_utils/tmp.hpp"

namespace etl {

using random_engine = std::mt19937_64;

template<typename T>
struct scalar {
    const T value;

    explicit constexpr scalar(T v) : value(v) {}

    constexpr const T operator[](std::size_t) const {
        return value;
    }

    template<typename... S>
    T operator()(S... /*args*/) const {
        static_assert(cpp::all_convertible_to<std::size_t, S...>::value, "Invalid size types");

        return value;
    }
};

template<typename T = double>
struct normal_generator_op {
    using value_type = T;

    random_engine rand_engine;
    std::normal_distribution<value_type> normal_distribution;

    normal_generator_op() : rand_engine(std::time(nullptr)), normal_distribution(0.0, 1.0) {}

    value_type operator()(){
        return normal_distribution(rand_engine);
    }
};

template<typename T = double>
struct sequence_generator_op {
    using value_type = T;

    value_type current = 0;

    sequence_generator_op(value_type start = 0) : current(start) {}

    value_type operator()(){
        return current++;
    }
};

} //end of namespace etl

#endif
<|endoftext|>


<commit_before>#ifndef GHULBUS_LIBRARY_INCLUDE_GUARD_BASE_PERFLOG_HPP
#define GHULBUS_LIBRARY_INCLUDE_GUARD_BASE_PERFLOG_HPP

/** @file
*
* @brief Minimalistic Performance Logger.
* @author Andreas Weis (der_ghulbus@ghulbus-inc.de)
*/

#include <gbBase/config.hpp>
#include <gbBase/Log.hpp>

#include <chrono>
#include <deque>
#include <string>
#include <string_view>

namespace GHULBUS_BASE_NAMESPACE
{
class PerfLog {
    struct LogEntry {
        std::chrono::steady_clock::time_point t;
        std::string label;

        LogEntry(std::chrono::steady_clock::time_point const& nt, std::string&& nl)
            :t(nt), label(std::move(nl))
        {}
    };
    using Log = std::deque<LogEntry>;
private:
    Log m_log;
public:
    inline PerfLog()
        :PerfLog("Epoch")
    {}

    inline explicit PerfLog(std::string_view initial_label)
    {
        tick(initial_label);
    }

    void tick(std::string_view label)
    {
        m_log.emplace_back(std::chrono::steady_clock::now(), std::string(label));
    }

    void tick(LogLevel log_level, std::string_view label)
    {
        auto const t0 = m_log.back().t;
        tick(label);
        GHULBUS_LOG_QUALIFIED(log_level, label << " - took " <<
            std::chrono::duration_cast<std::chrono::milliseconds>(m_log.back().t - t0).count() << " ms.");
    }

    Log const& getLog() const
    {
        return m_log;
    }
};
}
#endif
<commit_msg>additional documentation<commit_after>#ifndef GHULBUS_LIBRARY_INCLUDE_GUARD_BASE_PERFLOG_HPP
#define GHULBUS_LIBRARY_INCLUDE_GUARD_BASE_PERFLOG_HPP

/** @file
 *
 * @brief Minimalistic Performance Logger.
 * @author Andreas Weis (der_ghulbus@ghulbus-inc.de)
 */

#include <gbBase/config.hpp>
#include <gbBase/Log.hpp>

#include <chrono>
#include <deque>
#include <string>
#include <string_view>

namespace GHULBUS_BASE_NAMESPACE
{
/** A simple performance logger.
 * PerfLog records timestamped events with every tick().
 * These can either be retrieved later or passed on to the logger straight away.
 * Each event consists of a string label and a timestamp.
 */
class PerfLog {
    struct LogEntry {
        std::chrono::steady_clock::time_point t;
        std::string label;

        LogEntry(std::chrono::steady_clock::time_point const& nt, std::string&& nl)
            :t(nt), label(std::move(nl))
        {}
    };
    using Log = std::deque<LogEntry>;
private:
    Log m_log;
public:
    /** Constructor.
     * This will create the initial event labeled "Epoch".
     */
    inline PerfLog()
        :PerfLog("Epoch")
    {}

    /** Constructor.
     * This will create the initial event with the label passed as argument.
     */
    inline explicit PerfLog(std::string_view initial_label)
    {
        tick(initial_label);
    }

    /** Adds a new event to the log.
     * @param[in] label The label associated with the event.
     */
    void tick(std::string_view label)
    {
        m_log.emplace_back(std::chrono::steady_clock::now(), std::string(label));
    }

    /** Adds a new event to the log and log the time passed since the last tick to the logger.
     * @param[in] log_level The log level used for the triggered logging operation.
     * @param[in] label The label associated with the event.
     */
    void tick(LogLevel log_level, std::string_view label)
    {
        auto const t0 = m_log.back().t;
        tick(label);
        GHULBUS_LOG_QUALIFIED(log_level, label << " - took " <<
            std::chrono::duration_cast<std::chrono::milliseconds>(m_log.back().t - t0).count() << " ms.");
    }

    /** Retrieves the event log.
     */
    Log const& getLog() const
    {
        return m_log;
    }
};
}
#endif
<|endoftext|>