<commit_before>#include <qif>
#include "pybind11_aux.h"

namespace py = pybind11;
using namespace py::literals;
using namespace qif;

void init_channel_module(py::module);
void init_probab_module(py::module);
void init_metric_module(py::module);
void init_measure_module(py::module);
void init_mechanism_module(py::module);
void init_refinement_module(py::module);
void init_utility_module(py::module);
void init_lp_module(py::module);

py::handle def_c, double_c, uint_c, rat_c, point_c;

PYBIND11_MODULE(qif, m) {

	m.doc() = R"pbdoc(
		Quantitative Information Flow library.

		.. autosummary::
			:toctree: _autosummary
			:template: template.rst

			channel
			probab
			metric
			measure
			mechanism
			refinement
			utility
			lp

		|
	)pbdoc";

	// import np, user-friendly error message if not available
	py::module np;
	try {
		np = py::module::import("numpy");
	} catch(py::error_already_set) {
		throw std::runtime_error("numpy is required by qif");
	}

	// use np.random.randint to get a seed. Use int32_t instead of uint, cause numpy uses int32 for some reason on windows!
	uint seed = np.attr("random").attr("randint")(std::numeric_limits<int32_t>::max()).cast<uint>();
	arma::arma_rng::set_seed(seed);

	// Init mp++'s pybind11 integration
	mppp_pybind11::init();

	// Types
    py::class_<point>(m, "point")
		.def(py::init<double,double>())
		.def_readwrite("x", &point::x)
		.def_readwrite("y", &point::y)
		.def_static("from_polar", &point::from_polar)
		.def_static("from_cell", &point::from_cell)
        .def(py::self + py::self)
        .def("__repr__", &point::to_string);

	m.attr("double") = np.attr("float64");
	m.attr("uint")   = np.attr("uint64");
	m.attr("rat")    = py::module::import("fractions").attr("Fraction");

	// global class references
	double_c = m.attr("double");
	uint_c   = m.attr("uint");
	rat_c    = m.attr("rat");
	point_c  = m.attr("point");
	def_c    = double_c;

	m.def("set_default_type", [](py::object t) { def_c = t; });

	// initialize modules
	init_channel_module   (m.def_submodule("channel",   ""));
	init_probab_module    (m.def_submodule("probab",    ""));
	init_metric_module    (m.def_submodule("metric",    ""));
	init_measure_module   (m.def_submodule("measure",   ""));
	init_mechanism_module (m.def_submodule("mechanism", ""));
	init_refinement_module(m.def_submodule("refinement",""));
	init_utility_module   (m.def_submodule("utility",   ""));
	init_lp_module        (m.def_submodule("lp",        ""));

	// numpy formatter, so that rats are nicely displayed
	std::function<py::object(py::object)> fmt = [](py::object x) { return py::str(x); };
	np.attr("set_printoptions")("formatter"_a = py::dict("object"_a = fmt));

#ifdef QIF_VERSION
    m.attr("__version__") = QIF_VERSION;
#else
    m.attr("__version__") = "dev";
#endif

}
<commit_msg>python_lib: fix warning<commit_after>#include <qif>
#include "pybind11_aux.h"

namespace py = pybind11;
using namespace py::literals;
using namespace qif;

void init_channel_module(py::module);
void init_probab_module(py::module);
void init_metric_module(py::module);
void init_measure_module(py::module);
void init_mechanism_module(py::module);
void init_refinement_module(py::module);
void init_utility_module(py::module);
void init_lp_module(py::module);

py::handle def_c, double_c, uint_c, rat_c, point_c;

PYBIND11_MODULE(qif, m) {

	m.doc() = R"pbdoc(
		Quantitative Information Flow library.

		.. autosummary::
			:toctree: _autosummary
			:template: template.rst

			channel
			probab
			metric
			measure
			mechanism
			refinement
			utility
			lp

		|
	)pbdoc";

	// import np, user-friendly error message if not available
	py::module np;
	try {
		np = py::module::import("numpy");
	} catch(py::error_already_set&) {
		throw std::runtime_error("numpy is required by qif");
	}

	// use np.random.randint to get a seed. Use int32_t instead of uint, cause numpy uses int32 for some reason on windows!
	uint seed = np.attr("random").attr("randint")(std::numeric_limits<int32_t>::max()).cast<uint>();
	arma::arma_rng::set_seed(seed);

	// Init mp++'s pybind11 integration
	mppp_pybind11::init();

	// Types
    py::class_<point>(m, "point")
		.def(py::init<double,double>())
		.def_readwrite("x", &point::x)
		.def_readwrite("y", &point::y)
		.def_static("from_polar", &point::from_polar)
		.def_static("from_cell", &point::from_cell)
        .def(py::self + py::self)
        .def("__repr__", &point::to_string);

	m.attr("double") = np.attr("float64");
	m.attr("uint")   = np.attr("uint64");
	m.attr("rat")    = py::module::import("fractions").attr("Fraction");

	// global class references
	double_c = m.attr("double");
	uint_c   = m.attr("uint");
	rat_c    = m.attr("rat");
	point_c  = m.attr("point");
	def_c    = double_c;

	m.def("set_default_type", [](py::object t) { def_c = t; });

	// initialize modules
	init_channel_module   (m.def_submodule("channel",   ""));
	init_probab_module    (m.def_submodule("probab",    ""));
	init_metric_module    (m.def_submodule("metric",    ""));
	init_measure_module   (m.def_submodule("measure",   ""));
	init_mechanism_module (m.def_submodule("mechanism", ""));
	init_refinement_module(m.def_submodule("refinement",""));
	init_utility_module   (m.def_submodule("utility",   ""));
	init_lp_module        (m.def_submodule("lp",        ""));

	// numpy formatter, so that rats are nicely displayed
	std::function<py::object(py::object)> fmt = [](py::object x) { return py::str(x); };
	np.attr("set_printoptions")("formatter"_a = py::dict("object"_a = fmt));

#ifdef QIF_VERSION
    m.attr("__version__") = QIF_VERSION;
#else
    m.attr("__version__") = "dev";
#endif

}
<|endoftext|>


<commit_before>#pragma once
/*
**  Copyright (C) 2013 Aldebaran Robotics
**  See COPYING for the license
*/

#ifndef _QITYPE_ANYFUNCTION_HPP_
#define _QITYPE_ANYFUNCTION_HPP_

#include <qitype/api.hpp>
#include <boost/function.hpp>
#include <vector>

namespace qi {
  class AnyValue;
  class AutoAnyReference;

  template <typename T = AnyValue>
  class QITYPE_API VarArguments {
  public:
    VarArguments() {};
    VarArguments(const T& t) { _args.push_back(t); }
    VarArguments& operator()(const T& t) { _args.push_back(t);  return *this; }

    typedef std::vector<T> VectorType;

    VectorType &args()             { return _args; }
    const VectorType &args() const { return _args; }

  private:
    VectorType _args;
  };

  template <>
  class QITYPE_API VarArguments<AnyValue> {
  public:
    VarArguments() {};
    VarArguments(const AutoAnyReference& t);
    VarArguments& operator()(const AutoAnyReference& t);

    typedef std::vector<AnyValue> VectorType;

    VectorType &args()             { return _args; }
    const VectorType &args() const { return _args; }

  private:
    VectorType _args;
  };

  typedef VarArguments<> AnyVarArguments;
}

#include <qitype/typeinterface.hpp>

#ifdef _MSC_VER
#  pragma warning( push )
#  pragma warning( disable: 4251 )
#endif

namespace qi {

  inline VarArguments<AnyValue>::VarArguments(const AutoAnyReference& t) {
    _args.push_back(qi::AnyValue(t));
  }

  inline VarArguments<AnyValue>& VarArguments<AnyValue>::operator()(const AutoAnyReference& t) {
    _args.push_back(qi::AnyValue(t));
    return *this;
  }

  /// Signature information for both callable types FunctionTypeInterface and MethodType
  class QITYPE_API CallableTypeInterface
  {
  public:
    CallableTypeInterface();
    TypeInterface* resultType();
    const std::vector<TypeInterface*>& argumentsType();
    qi::Signature parametersSignature() const;
    qi::Signature returnSignature() const;
  protected:
    TypeInterface*              _resultType;
    // C4251
    std::vector<TypeInterface*> _argumentsType;
  };

  class QITYPE_API FunctionTypeInterface: public TypeInterface, public CallableTypeInterface
  {
  public:
    /** Call the function func with argument args that must be of the correct type.
    * @return the return value of type resultType(). This value is allocated and must be destroyed.
    */
    virtual void* call(void* storage, void** args, unsigned int argc) = 0;
  };

  template<typename T> FunctionTypeInterface* makeFunctionTypeInterface();

  struct ArgumentTransformation
  {
  public:
    // Drop first argument
    bool dropFirst;
    // Prepend boundValue to argument list
    bool prependValue;

    // So if both dropFirst and prependValue are set, first argument is
    // replaced with boundValue.
    ArgumentTransformation(bool dropFirst = false, bool prependValue=false, void* value = 0)
    : dropFirst(dropFirst)
    , prependValue(prependValue)
    , boundValue(value)
    {}

    void* boundValue;
  };

  template <typename T = AnyValue>
  class QITYPE_API KeywordArguments {
  public:
    KeywordArguments& operator()(const std::string& name, const T& t) { values[name] = t; return *this; }

    std::map<std::string, T> values;
  };

  /// A function with AnyArguments as its sole argument will behave as if AnyFunction::fromDynamicFunction was called.
  // This is going to be deprecated in profit of VarArgument and AnyVarArgument
  class QITYPE_API AnyArguments
  {
  public:
    AnyArguments() {};
    AnyArguments(const AnyValueVector& args)
    : _args(args) {}
    operator const AnyValueVector&() const { return _args;}
    AnyValueVector &args()             { return _args; }
    const AnyValueVector &args() const { return _args; }

  private:
    AnyValueVector _args;
  };

  typedef boost::function<AnyReference(const AnyReferenceVector&)> DynamicFunction;

  /** Represents a generic callable function.
   * This class has value semantic.
   *
   */
  class QITYPE_API AnyFunction
  {
  public:
    AnyFunction();
    ~AnyFunction();
    AnyFunction(const AnyFunction& b);
    AnyFunction(FunctionTypeInterface* type, void* value);
    AnyFunction& operator = (const AnyFunction& b);
    AnyReference call(const AnyReferenceVector& args);
    AnyReference call(AnyReference arg1, const AnyReferenceVector& args);
    AnyReference operator()(const AnyReferenceVector& args);

    /// Change signature, drop the first argument passed to call.
    const AnyFunction& dropFirstArgument() const;
    /// Replace first argument by \p value which must be storage for correct type.
    const AnyFunction& replaceFirstArgument(void* value) const;
    /// Prepend extra argument \p value to argument list
    const AnyFunction& prependArgument(void* value) const;

    /// Return expected argument types, taking transform into account
    std::vector<TypeInterface*> argumentsType() const;
    TypeInterface*              resultType() const;
    //dropfirst is useful when you want the parameters signature of a method.
    Signature          parametersSignature(bool dropFirst=false) const;
    Signature          returnSignature() const;

    void swap(AnyFunction& b);

    operator bool() const;
    FunctionTypeInterface* functionType() const;

    /*** @return an AnyFunction wrapping func.
    * func can be:
    * - a boost::bind object
    * - a boost::function
    * - a function pointer
    * - a member function pointer
    *
    */
    template<typename F>
    static AnyFunction from(F func);
    /// @return a AnyFunction binding \p instance to member function \p func
    template<typename F, typename C>
    static AnyFunction from(F func, C instance);

    /// @return a AnyFunction that takes arguments as a list of unconverted AnyReference.
    static AnyFunction fromDynamicFunction(DynamicFunction f);

  private:
    FunctionTypeInterface*  type;
    void* value; //type-dependant storage
    mutable ArgumentTransformation transform;
  };

  /** Store function parameters as a list of AnyReference.
   * Storage can be on the stack or allocated
   * Memory management is the responsibility of the user.
   * If GenericFunctionParameters is obtained throug copy(), convert() or
   * fromBuffer(), it must be cleared by destroy()
   */
  class QITYPE_API GenericFunctionParameters: public AnyReferenceVector
  {
  public:
    GenericFunctionParameters();
    GenericFunctionParameters(const AnyReferenceVector&);
    /// Copy arguments. destroy() must be called on the result
    GenericFunctionParameters copy(bool notFirst=false) const;
    /// Convert the arguments to given signature. destroy() must be called on the result.
    GenericFunctionParameters convert(const Signature& sig) const;
    qi::Signature signature(bool dyn) const;
    void destroy(bool notFirst = false);
  };

  /// @return the type used by dynamic functions
  QITYPE_API FunctionTypeInterface* dynamicFunctionTypeInterface();
}

#include <qitype/details/anyfunction.hxx>
#include <qitype/details/anyfunctionfactory.hxx>

#ifdef _MSC_VER
#  pragma warning( pop )
#endif

#endif  // _QITYPE_ANYFUNCTION_HPP_
<commit_msg>VarArguments: do not export template classes<commit_after>#pragma once
/*
**  Copyright (C) 2013 Aldebaran Robotics
**  See COPYING for the license
*/

#ifndef _QITYPE_ANYFUNCTION_HPP_
#define _QITYPE_ANYFUNCTION_HPP_

#include <qitype/api.hpp>
#include <boost/function.hpp>
#include <vector>

namespace qi {
  class AnyValue;
  class AutoAnyReference;

  template <typename T = AnyValue>
  class VarArguments {
  public:
    VarArguments() {};
    VarArguments(const T& t) { _args.push_back(t); }
    VarArguments& operator()(const T& t) { _args.push_back(t);  return *this; }

    typedef std::vector<T> VectorType;

    VectorType &args()             { return _args; }
    const VectorType &args() const { return _args; }

  private:
    VectorType _args;
  };

  template <>
  class VarArguments<AnyValue> {
  public:
    VarArguments() {};
    VarArguments(const AutoAnyReference& t);
    VarArguments& operator()(const AutoAnyReference& t);

    typedef std::vector<AnyValue> VectorType;

    VectorType &args()             { return _args; }
    const VectorType &args() const { return _args; }

  private:
    VectorType _args;
  };

  typedef VarArguments<> AnyVarArguments;
}

#include <qitype/typeinterface.hpp>

#ifdef _MSC_VER
#  pragma warning( push )
#  pragma warning( disable: 4251 )
#endif

namespace qi {

  inline VarArguments<AnyValue>::VarArguments(const AutoAnyReference& t) {
    _args.push_back(qi::AnyValue(t));
  }

  inline VarArguments<AnyValue>& VarArguments<AnyValue>::operator()(const AutoAnyReference& t) {
    _args.push_back(qi::AnyValue(t));
    return *this;
  }

  /// Signature information for both callable types FunctionTypeInterface and MethodType
  class QITYPE_API CallableTypeInterface
  {
  public:
    CallableTypeInterface();
    TypeInterface* resultType();
    const std::vector<TypeInterface*>& argumentsType();
    qi::Signature parametersSignature() const;
    qi::Signature returnSignature() const;
  protected:
    TypeInterface*              _resultType;
    // C4251
    std::vector<TypeInterface*> _argumentsType;
  };

  class QITYPE_API FunctionTypeInterface: public TypeInterface, public CallableTypeInterface
  {
  public:
    /** Call the function func with argument args that must be of the correct type.
    * @return the return value of type resultType(). This value is allocated and must be destroyed.
    */
    virtual void* call(void* storage, void** args, unsigned int argc) = 0;
  };

  template<typename T> FunctionTypeInterface* makeFunctionTypeInterface();

  struct ArgumentTransformation
  {
  public:
    // Drop first argument
    bool dropFirst;
    // Prepend boundValue to argument list
    bool prependValue;

    // So if both dropFirst and prependValue are set, first argument is
    // replaced with boundValue.
    ArgumentTransformation(bool dropFirst = false, bool prependValue=false, void* value = 0)
    : dropFirst(dropFirst)
    , prependValue(prependValue)
    , boundValue(value)
    {}

    void* boundValue;
  };

  template <typename T = AnyValue>
  class QITYPE_API KeywordArguments {
  public:
    KeywordArguments& operator()(const std::string& name, const T& t) { values[name] = t; return *this; }

    std::map<std::string, T> values;
  };

  /// A function with AnyArguments as its sole argument will behave as if AnyFunction::fromDynamicFunction was called.
  // This is going to be deprecated in profit of VarArgument and AnyVarArgument
  class QITYPE_API AnyArguments
  {
  public:
    AnyArguments() {};
    AnyArguments(const AnyValueVector& args)
    : _args(args) {}
    operator const AnyValueVector&() const { return _args;}
    AnyValueVector &args()             { return _args; }
    const AnyValueVector &args() const { return _args; }

  private:
    AnyValueVector _args;
  };

  typedef boost::function<AnyReference(const AnyReferenceVector&)> DynamicFunction;

  /** Represents a generic callable function.
   * This class has value semantic.
   *
   */
  class QITYPE_API AnyFunction
  {
  public:
    AnyFunction();
    ~AnyFunction();
    AnyFunction(const AnyFunction& b);
    AnyFunction(FunctionTypeInterface* type, void* value);
    AnyFunction& operator = (const AnyFunction& b);
    AnyReference call(const AnyReferenceVector& args);
    AnyReference call(AnyReference arg1, const AnyReferenceVector& args);
    AnyReference operator()(const AnyReferenceVector& args);

    /// Change signature, drop the first argument passed to call.
    const AnyFunction& dropFirstArgument() const;
    /// Replace first argument by \p value which must be storage for correct type.
    const AnyFunction& replaceFirstArgument(void* value) const;
    /// Prepend extra argument \p value to argument list
    const AnyFunction& prependArgument(void* value) const;

    /// Return expected argument types, taking transform into account
    std::vector<TypeInterface*> argumentsType() const;
    TypeInterface*              resultType() const;
    //dropfirst is useful when you want the parameters signature of a method.
    Signature          parametersSignature(bool dropFirst=false) const;
    Signature          returnSignature() const;

    void swap(AnyFunction& b);

    operator bool() const;
    FunctionTypeInterface* functionType() const;

    /*** @return an AnyFunction wrapping func.
    * func can be:
    * - a boost::bind object
    * - a boost::function
    * - a function pointer
    * - a member function pointer
    *
    */
    template<typename F>
    static AnyFunction from(F func);
    /// @return a AnyFunction binding \p instance to member function \p func
    template<typename F, typename C>
    static AnyFunction from(F func, C instance);

    /// @return a AnyFunction that takes arguments as a list of unconverted AnyReference.
    static AnyFunction fromDynamicFunction(DynamicFunction f);

  private:
    FunctionTypeInterface*  type;
    void* value; //type-dependant storage
    mutable ArgumentTransformation transform;
  };

  /** Store function parameters as a list of AnyReference.
   * Storage can be on the stack or allocated
   * Memory management is the responsibility of the user.
   * If GenericFunctionParameters is obtained throug copy(), convert() or
   * fromBuffer(), it must be cleared by destroy()
   */
  class QITYPE_API GenericFunctionParameters: public AnyReferenceVector
  {
  public:
    GenericFunctionParameters();
    GenericFunctionParameters(const AnyReferenceVector&);
    /// Copy arguments. destroy() must be called on the result
    GenericFunctionParameters copy(bool notFirst=false) const;
    /// Convert the arguments to given signature. destroy() must be called on the result.
    GenericFunctionParameters convert(const Signature& sig) const;
    qi::Signature signature(bool dyn) const;
    void destroy(bool notFirst = false);
  };

  /// @return the type used by dynamic functions
  QITYPE_API FunctionTypeInterface* dynamicFunctionTypeInterface();
}

#include <qitype/details/anyfunction.hxx>
#include <qitype/details/anyfunctionfactory.hxx>

#ifdef _MSC_VER
#  pragma warning( pop )
#endif

#endif  // _QITYPE_ANYFUNCTION_HPP_
<|endoftext|>


<commit_before>
#pragma once

#include "quantities/si.hpp"

namespace principia {
namespace quantities {
namespace si {

template<typename D>
std::string Format() {
  auto const format_unit = [](std::string const& name,
                              int const exponent) -> std::string {
    switch (exponent) {
      case 0:
        return "";
        break;
      case 1:
        return " " + name;
      default:
        return " " + name + "^" + std::to_string(exponent);
    }
  };

  // This string has a leading space if it's not empty.
  auto const format =
      format_unit("m", D::Length) + format_unit("kg", D::Mass) +
      format_unit("s", D::Time) + format_unit("A", D::Current) +
      format_unit("K", D::Temperature) + format_unit("mol", D::Amount) +
      format_unit("cd", D::LuminousIntensity) + format_unit("rad", D::Angle);

  if (format.empty()) {
    return format;
  } else {
    return format.substr(1, format.size() - 1);
  }
}

template<typename D>
constexpr Quantity<D> Yotta(Quantity<D> base) {
  return 1e24 * base;
}
template<typename D>
constexpr Quantity<D> Zetta(Quantity<D> base) {
  return 1e21 * base;
}
template<typename D>
constexpr Quantity<D> Exa(Quantity<D> base) {
  return 1e18 * base;
}
template<typename D>
constexpr Quantity<D> Peta(Quantity<D> base) {
  return 1e15 * base;
}
template<typename D>
constexpr Quantity<D> Tera(Quantity<D> base) {
  return 1e12 * base;
}
template<typename D>
constexpr Quantity<D> Giga(Quantity<D> base) {
  return 1e9 * base;
}
template<typename D>
constexpr Quantity<D> Mega(Quantity<D> base) {
  return 1e6 * base;
}
template<typename D>
constexpr Quantity<D> Kilo(Quantity<D> base) {
  return 1e3 * base;
}
template<typename D>
constexpr Quantity<D> Hecto(Quantity<D> base) {
  return 1e2 * base;
}
template<typename D>
constexpr Quantity<D> Deca(Quantity<D> base) {
  return 1e1 * base;
}
template<typename D>
constexpr Quantity<D> Deci(Quantity<D> base) {
  return 1e-1 * base;
}
template<typename D>
constexpr Quantity<D> Centi(Quantity<D> base) {
  return 1e-2 * base;
}
template<typename D>
constexpr Quantity<D> Milli(Quantity<D> base) {
  return 1e-3 * base;
}
template<typename D>
constexpr Quantity<D> Micro(Quantity<D> base) {
  return 1e-6 * base;
}
template<typename D>
constexpr Quantity<D> Nano(Quantity<D> base) {
  return 1e-9 * base;
}
template<typename D>
constexpr Quantity<D> Pico(Quantity<D> base) {
  return 1e-12 * base;
}
template<typename D>
constexpr Quantity<D> Femto(Quantity<D> base) {
  return 1e-15 * base;
}
template<typename D>
constexpr Quantity<D> Atto(Quantity<D> base) {
  return 1e-18 * base;
}
template<typename D>
constexpr Quantity<D> Zepto(Quantity<D> base) {
  return 1e-21 * base;
}
template<typename D>
constexpr Quantity<D> Yocto(Quantity<D> base) {
  return 1e-24 * base;
}

}  // namespace si
}  // namespace quantities
}  // namespace principia
<commit_msg>Lint.<commit_after>
#pragma once

#include "quantities/si.hpp"

#include <string>

namespace principia {
namespace quantities {
namespace si {

template<typename D>
std::string Format() {
  auto const format_unit = [](std::string const& name,
                              int const exponent) -> std::string {
    switch (exponent) {
      case 0:
        return "";
        break;
      case 1:
        return " " + name;
      default:
        return " " + name + "^" + std::to_string(exponent);
    }
  };

  // This string has a leading space if it's not empty.
  auto const format =
      format_unit("m", D::Length) + format_unit("kg", D::Mass) +
      format_unit("s", D::Time) + format_unit("A", D::Current) +
      format_unit("K", D::Temperature) + format_unit("mol", D::Amount) +
      format_unit("cd", D::LuminousIntensity) + format_unit("rad", D::Angle);

  if (format.empty()) {
    return format;
  } else {
    return format.substr(1, format.size() - 1);
  }
}

template<typename D>
constexpr Quantity<D> Yotta(Quantity<D> base) {
  return 1e24 * base;
}
template<typename D>
constexpr Quantity<D> Zetta(Quantity<D> base) {
  return 1e21 * base;
}
template<typename D>
constexpr Quantity<D> Exa(Quantity<D> base) {
  return 1e18 * base;
}
template<typename D>
constexpr Quantity<D> Peta(Quantity<D> base) {
  return 1e15 * base;
}
template<typename D>
constexpr Quantity<D> Tera(Quantity<D> base) {
  return 1e12 * base;
}
template<typename D>
constexpr Quantity<D> Giga(Quantity<D> base) {
  return 1e9 * base;
}
template<typename D>
constexpr Quantity<D> Mega(Quantity<D> base) {
  return 1e6 * base;
}
template<typename D>
constexpr Quantity<D> Kilo(Quantity<D> base) {
  return 1e3 * base;
}
template<typename D>
constexpr Quantity<D> Hecto(Quantity<D> base) {
  return 1e2 * base;
}
template<typename D>
constexpr Quantity<D> Deca(Quantity<D> base) {
  return 1e1 * base;
}
template<typename D>
constexpr Quantity<D> Deci(Quantity<D> base) {
  return 1e-1 * base;
}
template<typename D>
constexpr Quantity<D> Centi(Quantity<D> base) {
  return 1e-2 * base;
}
template<typename D>
constexpr Quantity<D> Milli(Quantity<D> base) {
  return 1e-3 * base;
}
template<typename D>
constexpr Quantity<D> Micro(Quantity<D> base) {
  return 1e-6 * base;
}
template<typename D>
constexpr Quantity<D> Nano(Quantity<D> base) {
  return 1e-9 * base;
}
template<typename D>
constexpr Quantity<D> Pico(Quantity<D> base) {
  return 1e-12 * base;
}
template<typename D>
constexpr Quantity<D> Femto(Quantity<D> base) {
  return 1e-15 * base;
}
template<typename D>
constexpr Quantity<D> Atto(Quantity<D> base) {
  return 1e-18 * base;
}
template<typename D>
constexpr Quantity<D> Zepto(Quantity<D> base) {
  return 1e-21 * base;
}
template<typename D>
constexpr Quantity<D> Yocto(Quantity<D> base) {
  return 1e-24 * base;
}

}  // namespace si
}  // namespace quantities
}  // namespace principia
<|endoftext|>


<commit_before>//  Created by 乔磊 on 2015/8/7.
//  Copyright (c) 2015年 乔磊. All rights reserved.
//

#include <NSolver/linearVelocityPotential/linearVelocityPotential.h>

namespace velocityPotential
{
  using namespace dealii;

  template <int dim>
  void LinearVelocityPotential<dim>::transfer_solution (
    const FESystem<dim>     &fe_NS,
    const DoFHandler<dim>   &dof_handler_NS,
    LA::MPI::Vector         &NS_solution) const
  {
    // Set quadrature points on NS FE supporting points.
    // Then extract desired values on these quadrature points.
    // If the quadrature points and the supporting points are arranged in
    // the same order, then we can loop through all the quadrature points and
    // assign corresponding values the NS solution vector.

    const FE_Q<dim> &fe_potential = fe;
    const DoFHandler<dim> &dof_handler_potential =dof_handler;
    const LA::MPI::Vector &potential_solution = locally_relevant_solution;

    // Here we assume all Finite Element types are the same in the NS system.
    Quadrature<dim> quadrature_on_NS_support_points (fe_NS.base_element (0).get_unit_support_points());

    FEValues<dim> fe_values_potential (fe_potential, quadrature_on_NS_support_points,
                                       update_values | update_gradients |
                                       update_quadrature_points);

    const unsigned int n_q_points = quadrature_on_NS_support_points.size();

    const unsigned int   dofs_per_cell = fe_NS.dofs_per_cell;
    std::vector<types::global_dof_index> global_indices_of_local_dofs (dofs_per_cell);
    std::vector< Tensor<1,dim,double> > potential_grad_on_cell (n_q_points);

    // The two DoFHandlers are initialized from the same triangulation
    typename DoFHandler<dim>::active_cell_iterator
    cell_potential = dof_handler_potential.begin_active(),
    cell_NS = dof_handler_NS.begin_active(),
    endc_NS = dof_handler_NS.end();
    for (; cell_NS!=endc_NS; ++cell_NS, ++cell_potential)
      {
        Assert (cell_potential != dof_handler_potential.end(),
                ExcMessage ("Reached end of tria for potential equation before NS equation!"));
        if (cell_NS->is_locally_owned())
          {
            fe_values_potential.reinit (cell_potential);

            fe_values_potential.get_function_gradients (
              potential_solution,
              potential_grad_on_cell);

            cell_NS->get_dof_indices (global_indices_of_local_dofs);
            // Since the quadrature is extracted according to the target FE supporting
            // points, we just have to loop through all the quadrature points.
            // We assume that the quadrature points and supporting points are
            // arranged in the same order.
            for (unsigned int q_point=0; q_point<n_q_points; ++q_point)
              {
                double Mach_local = 0.0;
                for (unsigned d=0; d<dim; ++d)
                  {
                    const double velocity =
                      velocity_infty[d] + potential_grad_on_cell[q_point][d];

                    Mach_local += velocity * velocity;
                    const unsigned int system_index = fe_NS.component_to_system_index (d, q_point);
                    NS_solution[global_indices_of_local_dofs[system_index]] = velocity;
                  }

                const double gas_gamma (1.4);
                const double Mach_infty (velocity_infty.square());
                const double Mach_ratio =
                  (1.0 + 0.5* (gas_gamma-1.0) * Mach_infty) /
                  (1.0 + 0.5* (gas_gamma-1.0) * Mach_local);
                {
                  // Density component
                  const unsigned int system_index = fe_NS.component_to_system_index (dim, q_point);
                  NS_solution[global_indices_of_local_dofs[system_index]] =
                    std::pow (Mach_ratio, 1.0/ (gas_gamma - 1.0));
                }
                {
                  //Pressure component
                  const unsigned int system_index = fe_NS.component_to_system_index (dim+1, q_point);
                  NS_solution[global_indices_of_local_dofs[system_index]] =
                    std::pow (Mach_ratio, gas_gamma/ (gas_gamma - 1.0)) / gas_gamma;
                }
              }
          }
      }
  }

#include "linearVelocityPotential.inst"
}
<commit_msg>format code<commit_after>//  Created by 乔磊 on 2015/8/7.
//  Copyright (c) 2015年 乔磊. All rights reserved.
//

#include <NSolver/linearVelocityPotential/linearVelocityPotential.h>

namespace velocityPotential
{
  using namespace dealii;

  template <int dim>
  void LinearVelocityPotential<dim>::transfer_solution (
    const FESystem<dim>     &fe_NS,
    const DoFHandler<dim>   &dof_handler_NS,
    LA::MPI::Vector         &NS_solution) const
  {
    // Set quadrature points on NS FE supporting points.
    // Then extract desired values on these quadrature points.
    // If the quadrature points and the supporting points are arranged in
    // the same order, then we can loop through all the quadrature points and
    // assign corresponding values the NS solution vector.

    const FE_Q<dim> &fe_potential = fe;
    const DoFHandler<dim> &dof_handler_potential =dof_handler;
    const LA::MPI::Vector &potential_solution = locally_relevant_solution;

    // Here we assume all Finite Element types are the same in the NS system.
    Quadrature<dim> quadrature_on_NS_support_points (fe_NS.base_element (0).get_unit_support_points());

    FEValues<dim> fe_values_potential (fe_potential, quadrature_on_NS_support_points,
                                       update_values | update_gradients |
                                       update_quadrature_points);

    const unsigned int n_q_points = quadrature_on_NS_support_points.size();

    const unsigned int dofs_per_cell = fe_NS.dofs_per_cell;
    std::vector<types::global_dof_index> global_indices_of_local_dofs (dofs_per_cell);
    std::vector<Tensor<1,dim,double> > potential_grad_on_cell (n_q_points);

    // The two DoFHandlers are initialized from the same triangulation
    typename DoFHandler<dim>::active_cell_iterator
    cell_potential = dof_handler_potential.begin_active(),
    cell_NS = dof_handler_NS.begin_active(),
    endc_NS = dof_handler_NS.end();
    for (; cell_NS!=endc_NS; ++cell_NS, ++cell_potential)
      {
        Assert (cell_potential != dof_handler_potential.end(),
                ExcMessage ("Reached end of tria for potential equation before NS equation!"));
        if (cell_NS->is_locally_owned())
          {
            fe_values_potential.reinit (cell_potential);

            fe_values_potential.get_function_gradients (
              potential_solution,
              potential_grad_on_cell);

            cell_NS->get_dof_indices (global_indices_of_local_dofs);
            // Since the quadrature is extracted according to the target FE supporting
            // points, we just have to loop through all the quadrature points.
            // We assume that the quadrature points and supporting points are
            // arranged in the same order.
            for (unsigned int q_point=0; q_point<n_q_points; ++q_point)
              {
                double Mach_local = 0.0;
                for (unsigned d=0; d<dim; ++d)
                  {
                    const double velocity =
                      velocity_infty[d] + potential_grad_on_cell[q_point][d];

                    Mach_local += velocity * velocity;
                    const unsigned int system_index = fe_NS.component_to_system_index (d, q_point);
                    NS_solution[global_indices_of_local_dofs[system_index]] = velocity;
                  }

                const double gas_gamma (1.4);
                const double Mach_infty (velocity_infty.square());
                const double Mach_ratio =
                  (1.0 + 0.5* (gas_gamma-1.0) * Mach_infty) /
                  (1.0 + 0.5* (gas_gamma-1.0) * Mach_local);
                {
                  // Density component
                  const unsigned int system_index = fe_NS.component_to_system_index (dim, q_point);
                  NS_solution[global_indices_of_local_dofs[system_index]] =
                    std::pow (Mach_ratio, 1.0/ (gas_gamma - 1.0));
                }
                {
                  //Pressure component
                  const unsigned int system_index = fe_NS.component_to_system_index (dim+1, q_point);
                  NS_solution[global_indices_of_local_dofs[system_index]] =
                    std::pow (Mach_ratio, gas_gamma/ (gas_gamma - 1.0)) / gas_gamma;
                }
              }
          }
      }
  }

#include "linearVelocityPotential.inst"
}
<|endoftext|>


<commit_before>/* Copyright (c) 2017-2020 Hans-Kristian Arntzen
 *
 * 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.
 */

#include "fxaa.hpp"
#include "math.hpp"

namespace Granite
{
void setup_fxaa_postprocess(RenderGraph &graph, const std::string &input, const std::string &output, VkFormat output_format)
{
	graph.get_texture_resource(input).get_attachment_info().unorm_srgb_alias = true;

	auto &fxaa = graph.add_pass("fxaa", RenderGraph::get_default_post_graphics_queue());
	AttachmentInfo fxaa_output;
	fxaa_output.size_class = SizeClass::InputRelative;
	fxaa_output.size_relative_name = input;
	fxaa_output.format = output_format;

	fxaa.add_color_output(output, fxaa_output);
	auto &fxaa_input = fxaa.add_texture_input(input);
	fxaa.set_build_render_pass([&, input](Vulkan::CommandBuffer &cmd) {
		auto &input_image = graph.get_physical_texture_resource(fxaa_input);
		cmd.set_unorm_texture(0, 0, input_image);
		cmd.set_sampler(0, 0, Vulkan::StockSampler::LinearClamp);
		vec2 inv_size(1.0f / input_image.get_image().get_create_info().width,
		              1.0f / input_image.get_image().get_create_info().height);
		cmd.push_constants(&inv_size, 0, sizeof(inv_size));

		auto &output_image = graph.get_physical_texture_resource(fxaa.get_color_outputs()[0]->get_physical_index());
		bool srgb = Vulkan::format_is_srgb(output_image.get_format());

		Vulkan::CommandBufferUtil::draw_fullscreen_quad(cmd, "builtin://shaders/quad.vert",
		                                                "builtin://shaders/post/fxaa.frag",
		                                                {{"FXAA_TARGET_SRGB", srgb ? 1 : 0}});
	});
}
}<commit_msg>Add prerotate support to FXAA.<commit_after>/* Copyright (c) 2017-2020 Hans-Kristian Arntzen
 *
 * 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.
 */

#include "fxaa.hpp"
#include "math.hpp"

namespace Granite
{
void setup_fxaa_postprocess(RenderGraph &graph, const std::string &input, const std::string &output, VkFormat output_format)
{
	graph.get_texture_resource(input).get_attachment_info().unorm_srgb_alias = true;

	auto &fxaa = graph.add_pass("fxaa", RenderGraph::get_default_post_graphics_queue());
	AttachmentInfo fxaa_output;
	fxaa_output.supports_prerotate = true;
	fxaa_output.size_class = SizeClass::InputRelative;
	fxaa_output.size_relative_name = input;
	fxaa_output.format = output_format;

	fxaa.add_color_output(output, fxaa_output);
	auto &fxaa_input = fxaa.add_texture_input(input);
	fxaa.set_build_render_pass([&, input](Vulkan::CommandBuffer &cmd) {
		auto &input_image = graph.get_physical_texture_resource(fxaa_input);
		cmd.set_unorm_texture(0, 0, input_image);
		cmd.set_sampler(0, 0, Vulkan::StockSampler::LinearClamp);
		vec2 inv_size(1.0f / input_image.get_image().get_create_info().width,
		              1.0f / input_image.get_image().get_create_info().height);
		cmd.push_constants(&inv_size, 0, sizeof(inv_size));

		auto &output_image = graph.get_physical_texture_resource(fxaa.get_color_outputs()[0]->get_physical_index());
		bool srgb = Vulkan::format_is_srgb(output_image.get_format());

		Vulkan::CommandBufferUtil::draw_fullscreen_quad(cmd, "builtin://shaders/quad.vert",
		                                                "builtin://shaders/post/fxaa.frag",
		                                                {{"FXAA_TARGET_SRGB", srgb ? 1 : 0}});
	});
}
}<|endoftext|>


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

The MIT License

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

License for the specific language governing rights and limitations under
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.
*/

#include <Interface/Modules/Forward/BuildBEMatrixDialog.h>
#include <Core/Algorithms/Legacy/Forward/BuildBEMatrixAlgo.h>

using namespace SCIRun::Gui;
using namespace SCIRun::Dataflow::Networks;
using namespace SCIRun::Core::Algorithms;
using namespace SCIRun::Core::Algorithms::Forward;

namespace TableColumns
{
  const int MinColumn = 0;

  const int FieldName = 0;
  const int FieldType = 1;
  const int BoundaryCondition = 2;
  const int InsideConductivity = 3;
  const int OutsideConductivity = 4;

  const int MaxColumn = OutsideConductivity + 1;
}

BuildBEMatrixDialog::BuildBEMatrixDialog(const std::string& name, ModuleStateHandle state,
  QWidget* parent /* = 0 */)
  : ModuleDialogGeneric(state, parent)
{
  setupUi(this);
  setWindowTitle(QString::fromStdString(name));
  fixSize();
  WidgetStyleMixin::tableHeaderStyle(this->tableWidget);
  tableWidget->resizeColumnsToContents();

  connect(tableWidget, SIGNAL(cellChanged(int,int)), this, SLOT(pushTable(int,int)));
}

void BuildBEMatrixDialog::updateFromPortChange(int numPorts, const std::string&)
{
  //std::cout << "updateFromPortChange " << numPorts << std::endl;
  auto oldRowCount = tableWidget->rowCount();
  tableWidget->setRowCount(numPorts - 1);
  tableWidget->blockSignals(true);
  for (int i = oldRowCount; i < tableWidget->rowCount(); ++i)
  {
    using namespace TableColumns;
    tableWidget->setItem(i, FieldName, new QTableWidgetItem("field" + QString::number(i)));
    tableWidget->setItem(i, FieldType, new QTableWidgetItem("[populated on execute]"));
    tableWidget->setCellWidget(i, BoundaryCondition, makeComboBoxItem(i));
    tableWidget->setCellWidget(i, InsideConductivity, makeDoubleEntryItem(i, InsideConductivity));
    tableWidget->setCellWidget(i, OutsideConductivity, makeDoubleEntryItem(i, OutsideConductivity));

    // type is readonly
    auto type = tableWidget->item(i, FieldType);
    type->setFlags(type->flags() & ~Qt::ItemIsEditable);
    pushTableRow(i);
  }
  pull();
  tableWidget->resizeColumnsToContents();
  tableWidget->blockSignals(false);
}

QComboBox* BuildBEMatrixDialog::makeComboBoxItem(int i) const
{
  QStringList bcList;
  bcList << "Measurement (Neumann)" << "Source (Dirichlet)";
  QComboBox* bcBox = new QComboBox();
  bcBox->addItems(bcList);
  bcBox->setCurrentIndex(i == 0 ? 1 : 0);
  connect(bcBox, SIGNAL(currentIndexChanged(int)), this, SLOT(pushBoundaryConditions()));
  return bcBox;
}

QDoubleSpinBox* BuildBEMatrixDialog::makeDoubleEntryItem(int row, int col) const
{
  auto spin = new QDoubleSpinBox();
  spin->setValue((row + col + 1) % 6);
  const char* slot = col == TableColumns::InsideConductivity ? SLOT(pushInsides()) : SLOT(pushOutsides());
  connect(spin, SIGNAL(valueChanged(double)), this, slot);
  return spin;
}

void BuildBEMatrixDialog::pushTable(int row, int col)
{
  using namespace TableColumns;
  if (FieldName == col)
    pushNames();
  else if (BoundaryCondition == col)
    pushBoundaryConditions();
  else if (InsideConductivity == col)
    pushInsides();
  else if (OutsideConductivity == col)
    pushOutsides();
}

void BuildBEMatrixDialog::pushTableRow(int row)
{
  using namespace TableColumns;
  for (int col = MinColumn; col < MaxColumn; ++col)
    pushTable(row, col);
}

void BuildBEMatrixDialog::pushNames()
{
  using namespace TableColumns;
  if (!pulling_)
  {
    VariableList names;
    for (int i = 0; i < tableWidget->rowCount(); ++i)
    {
      auto item = tableWidget->item(i, FieldName);
      names.push_back(makeVariable("", item->text().toStdString()));
    }
    state_->setValue(Parameters::FieldNameList, names);
  }
}

void BuildBEMatrixDialog::pushBoundaryConditions()
{
  using namespace TableColumns;
  if (!pulling_)
  {
    VariableList names;
    for (int i = 0; i < tableWidget->rowCount(); ++i)
    {
      auto box = qobject_cast<QComboBox*>(tableWidget->cellWidget(i, BoundaryCondition));
      names.push_back(makeVariable("", box->currentText().toStdString()));
    }
    state_->setValue(Parameters::BoundaryConditionList, names);
  }
}

void BuildBEMatrixDialog::pushInsides()
{
  using namespace TableColumns;
  if (!pulling_)
  {
    VariableList names;
    for (int i = 0; i < tableWidget->rowCount(); ++i)
    {
      auto box = qobject_cast<QDoubleSpinBox*>(tableWidget->cellWidget(i, InsideConductivity));
      names.push_back(makeVariable("", box->value()));
    }
    state_->setValue(Parameters::InsideConductivityList, names);
  }
}

void BuildBEMatrixDialog::pushOutsides()
{
  using namespace TableColumns;
  if (!pulling_)
  {
    VariableList names;
    for (int i = 0; i < tableWidget->rowCount(); ++i)
    {
      auto box = qobject_cast<QDoubleSpinBox*>(tableWidget->cellWidget(i, OutsideConductivity));
      names.push_back(makeVariable("", box->value()));
    }
    state_->setValue(Parameters::OutsideConductivityList, names);
  }
}

void BuildBEMatrixDialog::pullSpecial()
{
  pullNames();
  pullFieldTypes();
  pullBoundaryConditions();
  pullInsides();
  pullOutsides();
}

void BuildBEMatrixDialog::pullNames()
{
  using namespace TableColumns;
  Pulling p(this);
  auto nameList = state_->getValue(Parameters::FieldNameList).toVector();
  const int rows = std::min(static_cast<int>(nameList.size()), tableWidget->rowCount());
  for (int row = 0; row < rows; ++row)
  {
    auto item = tableWidget->item(row, FieldName);
    item->setText(QString::fromStdString(nameList[row].toString()));
  }
}

void BuildBEMatrixDialog::pullFieldTypes()
{
  using namespace TableColumns;
  Pulling p(this);
  auto typeList = transient_value_cast<FieldTypeListType>(state_->getTransientValue(Parameters::FieldTypeList));
  const int rows = std::min(static_cast<int>(typeList.size()), tableWidget->rowCount());
  for (int row = 0; row < rows; ++row)
  {
    auto item = tableWidget->item(row, FieldType);
    item->setText(QString::fromStdString(typeList[row]));
  }
}

void BuildBEMatrixDialog::pullBoundaryConditions()
{
  using namespace TableColumns;
  Pulling p(this);
  auto bdyList = state_->getValue(Parameters::BoundaryConditionList).toVector();
  const int rows = std::min(static_cast<int>(bdyList.size()), tableWidget->rowCount());
  for (int row = 0; row < rows; ++row)
  {
    auto box = qobject_cast<QComboBox*>(tableWidget->cellWidget(row, BoundaryCondition));
    auto str = QString::fromStdString(bdyList[row].toString());
    box->setCurrentIndex(box->findText(str));
  }
}

void BuildBEMatrixDialog::pullInsides()
{
  using namespace TableColumns;
  Pulling p(this);
  auto condList = state_->getValue(Parameters::InsideConductivityList).toVector();
  const int rows = std::min(static_cast<int>(condList.size()), tableWidget->rowCount());
  for (int row = 0; row < rows; ++row)
  {
    auto box = qobject_cast<QDoubleSpinBox*>(tableWidget->cellWidget(row, InsideConductivity));
    box->setValue(condList[row].toDouble());
  }
}

void BuildBEMatrixDialog::pullOutsides()
{
  using namespace TableColumns;
  Pulling p(this);
  auto condList = state_->getValue(Parameters::OutsideConductivityList).toVector();
  const int rows = std::min(static_cast<int>(condList.size()), tableWidget->rowCount());
  for (int row = 0; row < rows; ++row)
  {
    auto box = qobject_cast<QDoubleSpinBox*>(tableWidget->cellWidget(row, OutsideConductivity));
    box->setValue(condList[row].toDouble());
  }
}
<commit_msg>fiddling with resolution of conductivity<commit_after>/*
For more information, please see: http://software.sci.utah.edu

The MIT License

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

License for the specific language governing rights and limitations under
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.
*/

#include <Interface/Modules/Forward/BuildBEMatrixDialog.h>
#include <Core/Algorithms/Legacy/Forward/BuildBEMatrixAlgo.h>

using namespace SCIRun::Gui;
using namespace SCIRun::Dataflow::Networks;
using namespace SCIRun::Core::Algorithms;
using namespace SCIRun::Core::Algorithms::Forward;

namespace TableColumns
{
  const int MinColumn = 0;

  const int FieldName = 0;
  const int FieldType = 1;
  const int BoundaryCondition = 2;
  const int InsideConductivity = 3;
  const int OutsideConductivity = 4;

  const int MaxColumn = OutsideConductivity + 1;
}

BuildBEMatrixDialog::BuildBEMatrixDialog(const std::string& name, ModuleStateHandle state,
  QWidget* parent /* = 0 */)
  : ModuleDialogGeneric(state, parent)
{
  setupUi(this);
  setWindowTitle(QString::fromStdString(name));
  fixSize();
  WidgetStyleMixin::tableHeaderStyle(this->tableWidget);
  tableWidget->resizeColumnsToContents();

  connect(tableWidget, SIGNAL(cellChanged(int,int)), this, SLOT(pushTable(int,int)));
}

void BuildBEMatrixDialog::updateFromPortChange(int numPorts, const std::string&)
{
  //std::cout << "updateFromPortChange " << numPorts << std::endl;
  auto oldRowCount = tableWidget->rowCount();
  tableWidget->setRowCount(numPorts - 1);
  tableWidget->blockSignals(true);
  for (int i = oldRowCount; i < tableWidget->rowCount(); ++i)
  {
    using namespace TableColumns;
    tableWidget->setItem(i, FieldName, new QTableWidgetItem("field" + QString::number(i)));
    tableWidget->setItem(i, FieldType, new QTableWidgetItem("[populated on execute]"));
    tableWidget->setCellWidget(i, BoundaryCondition, makeComboBoxItem(i));
    tableWidget->setCellWidget(i, InsideConductivity, makeDoubleEntryItem(i, InsideConductivity));
    tableWidget->setCellWidget(i, OutsideConductivity, makeDoubleEntryItem(i, OutsideConductivity));

    // type is readonly
    auto type = tableWidget->item(i, FieldType);
    type->setFlags(type->flags() & ~Qt::ItemIsEditable);
    pushTableRow(i);
  }
  pull();
  tableWidget->resizeColumnsToContents();
  tableWidget->blockSignals(false);
}

QComboBox* BuildBEMatrixDialog::makeComboBoxItem(int i) const
{
  QStringList bcList;
  bcList << "Measurement (Neumann)" << "Source (Dirichlet)";
  QComboBox* bcBox = new QComboBox();
  bcBox->addItems(bcList);
  bcBox->setCurrentIndex(i == 0 ? 1 : 0);
  connect(bcBox, SIGNAL(currentIndexChanged(int)), this, SLOT(pushBoundaryConditions()));
  return bcBox;
}

QDoubleSpinBox* BuildBEMatrixDialog::makeDoubleEntryItem(int row, int col) const
{
  auto spin = new QDoubleSpinBox();
  spin->setValue((row + col + 1) % 2);
  const char* slot = col == TableColumns::InsideConductivity ? SLOT(pushInsides()) : SLOT(pushOutsides());
  connect(spin, SIGNAL(valueChanged(double)), this, slot);
  return spin;
}

void BuildBEMatrixDialog::pushTable(int row, int col)
{
  using namespace TableColumns;
  if (FieldName == col)
    pushNames();
  else if (BoundaryCondition == col)
    pushBoundaryConditions();
  else if (InsideConductivity == col)
    pushInsides();
  else if (OutsideConductivity == col)
    pushOutsides();
}

void BuildBEMatrixDialog::pushTableRow(int row)
{
  using namespace TableColumns;
  for (int col = MinColumn; col < MaxColumn; ++col)
    pushTable(row, col);
}

void BuildBEMatrixDialog::pushNames()
{
  using namespace TableColumns;
  if (!pulling_)
  {
    VariableList names;
    for (int i = 0; i < tableWidget->rowCount(); ++i)
    {
      auto item = tableWidget->item(i, FieldName);
      names.push_back(makeVariable("", item->text().toStdString()));
    }
    state_->setValue(Parameters::FieldNameList, names);
  }
}

void BuildBEMatrixDialog::pushBoundaryConditions()
{
  using namespace TableColumns;
  if (!pulling_)
  {
    VariableList names;
    for (int i = 0; i < tableWidget->rowCount(); ++i)
    {
      auto box = qobject_cast<QComboBox*>(tableWidget->cellWidget(i, BoundaryCondition));
      names.push_back(makeVariable("", box->currentText().toStdString()));
    }
    state_->setValue(Parameters::BoundaryConditionList, names);
  }
}

void BuildBEMatrixDialog::pushInsides()
{
  using namespace TableColumns;
  if (!pulling_)
  {
    VariableList names;
    for (int i = 0; i < tableWidget->rowCount(); ++i)
    {
      auto box = qobject_cast<QDoubleSpinBox*>(tableWidget->cellWidget(i, InsideConductivity));
      names.push_back(makeVariable("", box->value()));
    }
    state_->setValue(Parameters::InsideConductivityList, names);
  }
}

void BuildBEMatrixDialog::pushOutsides()
{
  using namespace TableColumns;
  if (!pulling_)
  {
    VariableList names;
    for (int i = 0; i < tableWidget->rowCount(); ++i)
    {
      auto box = qobject_cast<QDoubleSpinBox*>(tableWidget->cellWidget(i, OutsideConductivity));
      names.push_back(makeVariable("", box->value()));
    }
    state_->setValue(Parameters::OutsideConductivityList, names);
  }
}

void BuildBEMatrixDialog::pullSpecial()
{
  pullNames();
  pullFieldTypes();
  pullBoundaryConditions();
  pullInsides();
  pullOutsides();
}

void BuildBEMatrixDialog::pullNames()
{
  using namespace TableColumns;
  Pulling p(this);
  auto nameList = state_->getValue(Parameters::FieldNameList).toVector();
  const int rows = std::min(static_cast<int>(nameList.size()), tableWidget->rowCount());
  for (int row = 0; row < rows; ++row)
  {
    auto item = tableWidget->item(row, FieldName);
    item->setText(QString::fromStdString(nameList[row].toString()));
  }
}

void BuildBEMatrixDialog::pullFieldTypes()
{
  using namespace TableColumns;
  Pulling p(this);
  auto typeList = transient_value_cast<FieldTypeListType>(state_->getTransientValue(Parameters::FieldTypeList));
  const int rows = std::min(static_cast<int>(typeList.size()), tableWidget->rowCount());
  for (int row = 0; row < rows; ++row)
  {
    auto item = tableWidget->item(row, FieldType);
    item->setText(QString::fromStdString(typeList[row]));
  }
}

void BuildBEMatrixDialog::pullBoundaryConditions()
{
  using namespace TableColumns;
  Pulling p(this);
  auto bdyList = state_->getValue(Parameters::BoundaryConditionList).toVector();
  const int rows = std::min(static_cast<int>(bdyList.size()), tableWidget->rowCount());
  for (int row = 0; row < rows; ++row)
  {
    auto box = qobject_cast<QComboBox*>(tableWidget->cellWidget(row, BoundaryCondition));
    auto str = QString::fromStdString(bdyList[row].toString());
    box->setCurrentIndex(box->findText(str));
  }
}

void BuildBEMatrixDialog::pullInsides()
{
  using namespace TableColumns;
  Pulling p(this);
  auto condList = state_->getValue(Parameters::InsideConductivityList).toVector();
  const int rows = std::min(static_cast<int>(condList.size()), tableWidget->rowCount());
  for (int row = 0; row < rows; ++row)
  {
    auto box = qobject_cast<QDoubleSpinBox*>(tableWidget->cellWidget(row, InsideConductivity));
    box->setValue(condList[row].toDouble());
  }
}

void BuildBEMatrixDialog::pullOutsides()
{
  using namespace TableColumns;
  Pulling p(this);
  auto condList = state_->getValue(Parameters::OutsideConductivityList).toVector();
  const int rows = std::min(static_cast<int>(condList.size()), tableWidget->rowCount());
  for (int row = 0; row < rows; ++row)
  {
    auto box = qobject_cast<QDoubleSpinBox*>(tableWidget->cellWidget(row, OutsideConductivity));
    box->setValue(condList[row].toDouble());
  }
}
<|endoftext|>


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

#include <grpc/support/port_platform.h>

#include "src/core/lib/security/authorization/evaluate_args.h"

#include "src/core/lib/slice/slice_utils.h"

namespace grpc_core {

absl::string_view EvaluateArgs::GetPath() const {
  absl::string_view path;
  if (metadata_ != nullptr && metadata_->idx.named.path != nullptr) {
    grpc_linked_mdelem* elem = metadata_->idx.named.path;
    const grpc_slice& val = GRPC_MDVALUE(elem->md);
    path = StringViewFromSlice(val);
  }
  return path;
}

absl::string_view EvaluateArgs::GetHost() const {
  absl::string_view host;
  if (metadata_ != nullptr && metadata_->idx.named.host != nullptr) {
    grpc_linked_mdelem* elem = metadata_->idx.named.host;
    const grpc_slice& val = GRPC_MDVALUE(elem->md);
    host = StringViewFromSlice(val);
  }
  return host;
}

absl::string_view EvaluateArgs::GetMethod() const {
  absl::string_view method;
  if (metadata_ != nullptr && metadata_->idx.named.method != nullptr) {
    grpc_linked_mdelem* elem = metadata_->idx.named.method;
    const grpc_slice& val = GRPC_MDVALUE(elem->md);
    method = StringViewFromSlice(val);
  }
  return method;
}

std::multimap<absl::string_view, absl::string_view> EvaluateArgs::GetHeaders()
    const {
  std::multimap<absl::string_view, absl::string_view> headers;
  if (metadata_ == nullptr) {
    return headers;
  }
  for (grpc_linked_mdelem* elem = metadata_->list.head; elem != nullptr;
       elem = elem->next) {
    const grpc_slice& key = GRPC_MDKEY(elem->md);
    const grpc_slice& val = GRPC_MDVALUE(elem->md);
    headers.emplace(StringViewFromSlice(key), StringViewFromSlice(val));
  }
  return headers;
}

absl::string_view EvaluateArgs::GetSpiffeId() const {
  if (auth_context_ == nullptr) {
    return "";
  }
  grpc_auth_property_iterator it = grpc_auth_context_find_properties_by_name(
      auth_context_, GRPC_PEER_SPIFFE_ID_PROPERTY_NAME);
  const grpc_auth_property* prop = grpc_auth_property_iterator_next(&it);
  if (prop == nullptr || grpc_auth_property_iterator_next(&it) != nullptr)
    return "";
  return absl::string_view(
      reinterpret_cast<const char*>(prop->value, prop->value_length));
}

absl::string_view EvaluateArgs::GetCertServerName() const {
  if (auth_context_ == nullptr) {
    return "";
  }
  grpc_auth_property_iterator it = grpc_auth_context_find_properties_by_name(
      auth_context_, GRPC_X509_CN_PROPERTY_NAME);
  const grpc_auth_property* prop = grpc_auth_property_iterator_next(&it);
  if (prop == nullptr || grpc_auth_property_iterator_next(&it) != nullptr)
    return "";
  return absl::string_view(prop->value, prop->value_length);
}

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

#include <grpc/support/port_platform.h>

#include "src/core/lib/security/authorization/evaluate_args.h"

#include "src/core/lib/slice/slice_utils.h"

namespace grpc_core {

absl::string_view EvaluateArgs::GetPath() const {
  absl::string_view path;
  if (metadata_ != nullptr && metadata_->idx.named.path != nullptr) {
    grpc_linked_mdelem* elem = metadata_->idx.named.path;
    const grpc_slice& val = GRPC_MDVALUE(elem->md);
    path = StringViewFromSlice(val);
  }
  return path;
}

absl::string_view EvaluateArgs::GetHost() const {
  absl::string_view host;
  if (metadata_ != nullptr && metadata_->idx.named.host != nullptr) {
    grpc_linked_mdelem* elem = metadata_->idx.named.host;
    const grpc_slice& val = GRPC_MDVALUE(elem->md);
    host = StringViewFromSlice(val);
  }
  return host;
}

absl::string_view EvaluateArgs::GetMethod() const {
  absl::string_view method;
  if (metadata_ != nullptr && metadata_->idx.named.method != nullptr) {
    grpc_linked_mdelem* elem = metadata_->idx.named.method;
    const grpc_slice& val = GRPC_MDVALUE(elem->md);
    method = StringViewFromSlice(val);
  }
  return method;
}

std::multimap<absl::string_view, absl::string_view> EvaluateArgs::GetHeaders()
    const {
  std::multimap<absl::string_view, absl::string_view> headers;
  if (metadata_ == nullptr) {
    return headers;
  }
  for (grpc_linked_mdelem* elem = metadata_->list.head; elem != nullptr;
       elem = elem->next) {
    const grpc_slice& key = GRPC_MDKEY(elem->md);
    const grpc_slice& val = GRPC_MDVALUE(elem->md);
    headers.emplace(StringViewFromSlice(key), StringViewFromSlice(val));
  }
  return headers;
}

absl::string_view EvaluateArgs::GetSpiffeId() const {
  if (auth_context_ == nullptr) {
    return "";
  }
  grpc_auth_property_iterator it = grpc_auth_context_find_properties_by_name(
      auth_context_, GRPC_PEER_SPIFFE_ID_PROPERTY_NAME);
  const grpc_auth_property* prop = grpc_auth_property_iterator_next(&it);
  if (prop == nullptr || grpc_auth_property_iterator_next(&it) != nullptr) {
    return "";
  }
  return absl::string_view(prop->value, prop->value_length);
}

absl::string_view EvaluateArgs::GetCertServerName() const {
  if (auth_context_ == nullptr) {
    return "";
  }
  grpc_auth_property_iterator it = grpc_auth_context_find_properties_by_name(
      auth_context_, GRPC_X509_CN_PROPERTY_NAME);
  const grpc_auth_property* prop = grpc_auth_property_iterator_next(&it);
  if (prop == nullptr || grpc_auth_property_iterator_next(&it) != nullptr) {
    return "";
  }
  return absl::string_view(prop->value, prop->value_length);
}

}  // namespace grpc_core
<|endoftext|>


<commit_before>#include "dockerappmanager.h"

#include <sstream>

/**
 * @brief This package manager compliments the OSTreePackageManager by also including optional Docker Apps.
 *
 * A full description of the Docker App project can be found here:
 *  https://github.com/docker/app/
 *
 * Docker Apps are very analogous to docker-compose. In fact, this module
 * currently "renders" the docker-app file into a docker-compose file. Each
 * Docker App appears as a Target in the TUF targets list. Each OStree target
 * can then reference these docker apps in its custom data section. eg:
 *
 *   "targets": {
 *     httpd.dockerapp-1 : {
 *       "custom" : {"hardwareIds" : ["all"], "name" : "httpd.dockerapp", "version" : "1"},
 *       "hashes" : {"sha256" : "f0ad4e3ce6a5e9cb70c9d747e977fddfacd08419deec0714622029b12dde8338"},
 *       "length" : 889
 *     },
 *    "raspberrypi3-64-lmp-144" : {
 *      "custom" : {
 *         "docker_apps" : {
 *            "httpd" : {
 *               "filename" : "httpd.dockerapp-1"
 *            }
 *         },
 *         "hardwareIds" : ["raspberrypi3-64"],
 *         "name" : "raspberrypi3-64-lmp",
 *         "targetFormat" : "OSTREE",
 *         "version" : "144"
 *      },
 *      "hashes" : {"sha256" : "20ac4f7cd50cda6bfed0caa1f8231cc9a7e40bec60026c66df5f7e143af96942"},
 *      "length" : 0
 *     }
 *   }
 */

struct DockerApp {
  DockerApp(std::string app_name, const PackageConfig &config)
      : name(std::move(app_name)),
        app_root(config.docker_apps_root / name),
        app_params(config.docker_app_params),
        app_bin(config.docker_app_bin),
        compose_bin(config.docker_compose_bin) {}

  bool render(const std::string &app_content, bool persist) {
    auto bin = boost::filesystem::canonical(app_bin).string();
    Utils::writeFile(app_root / (name + ".dockerapp"), app_content);
    std::string cmd("cd " + app_root.string() + " && " + bin + " render " + name);
    if (!app_params.empty()) {
      cmd += " -f " + app_params.string();
    }
    std::string yaml;
    if (Utils::shell(cmd, &yaml, true) != 0) {
      LOG_ERROR << "Unable to run " << cmd << " output:\n" << yaml;
      return false;
    }
    if (persist) {
      Utils::writeFile(app_root / "docker-compose.yml", yaml);
    }
    return true;
  }

  bool start() {
    // Depending on the number and size of the containers in the docker-app,
    // this command can take a bit of time to complete. Rather than using,
    // Utils::shell which isn't interactive, we'll use std::system so that
    // stdout/stderr is streamed while docker sets things up.
    auto bin = boost::filesystem::canonical(compose_bin).string();
    std::string cmd("cd " + app_root.string() + " && " + bin + " up --remove-orphans -d");
    return std::system(cmd.c_str()) == 0;
  }

  void remove() {
    auto bin = boost::filesystem::canonical(compose_bin).string();
    std::string cmd("cd " + app_root.string() + " && " + bin + " down");
    if (std::system(cmd.c_str()) == 0) {
      boost::filesystem::remove_all(app_root);
    } else {
      LOG_ERROR << "docker-compose was unable to bring down: " << app_root;
    }
  }

  std::string name;
  boost::filesystem::path app_root;
  boost::filesystem::path app_params;
  boost::filesystem::path app_bin;
  boost::filesystem::path compose_bin;
};

bool DockerAppManager::iterate_apps(const Uptane::Target &target, const DockerAppCb &cb) const {
  auto apps = target.custom_data()["docker_apps"];
  bool res = true;
  Uptane::ImagesRepository repo;
  // checkMetaOffline pulls in data from INvStorage to properly initialize
  // the targets member of the instance so that we can use the LazyTargetList
  repo.checkMetaOffline(*storage_);

  if (!apps) {
    LOG_DEBUG << "Detected an update target from Director with no docker-apps data";
    for (const auto &t : Uptane::LazyTargetsList(repo, storage_, fake_fetcher_)) {
      if (t.MatchTarget(target)) {
        LOG_DEBUG << "Found the match " << t;
        apps = t.custom_data()["docker_apps"];
        break;
      }
    }
  }

  for (const auto &t : Uptane::LazyTargetsList(repo, storage_, fake_fetcher_)) {
    for (Json::ValueIterator i = apps.begin(); i != apps.end(); ++i) {
      if ((*i).isObject() && (*i).isMember("filename")) {
        for (const auto &app : config.docker_apps) {
          if (i.key().asString() == app && (*i)["filename"].asString() == t.filename()) {
            if (!cb(app, t)) {
              res = false;
            }
          }
        }
      } else {
        LOG_ERROR << "Invalid custom data for docker-app: " << i.key().asString() << " -> " << *i;
      }
    }
  }
  return res;
}

bool DockerAppManager::fetchTarget(const Uptane::Target &target, Uptane::Fetcher &fetcher, const KeyManager &keys,
                                   FetcherProgressCb progress_cb, const api::FlowControlToken *token) {
  if (!OstreeManager::fetchTarget(target, fetcher, keys, progress_cb, token)) {
    return false;
  }

  LOG_INFO << "Looking for DockerApps to fetch";
  auto cb = [this, &fetcher, &keys, progress_cb, token](const std::string &app, const Uptane::Target &app_target) {
    LOG_INFO << "Fetching " << app << " -> " << app_target;
    return PackageManagerInterface::fetchTarget(app_target, fetcher, keys, progress_cb, token);
  };
  return iterate_apps(target, cb);
}

data::InstallationResult DockerAppManager::install(const Uptane::Target &target) const {
  auto res = OstreeManager::install(target);
  handleRemovedApps();
  auto cb = [this](const std::string &app, const Uptane::Target &app_target) {
    LOG_INFO << "Installing " << app << " -> " << app_target;
    std::stringstream ss;
    ss << *storage_->openTargetFile(app_target);
    DockerApp dapp(app, config);
    return dapp.render(ss.str(), true) && dapp.start();
  };
  if (!iterate_apps(target, cb)) {
    return data::InstallationResult(data::ResultCode::Numeric::kInstallFailed, "Could not render docker app");
  }
  return res;
}

// Handle the case like:
//  1) sota.toml is configured with 2 docker apps: "app1, app2"
//  2) update is applied, so we are now running both app1 and app2
//  3) sota.toml is updated with 1 docker app: "app1"
// At this point we should stop app2 and remove it.
void DockerAppManager::handleRemovedApps() const {
  if (!boost::filesystem::is_directory(config.docker_apps_root)) {
    LOG_DEBUG << "config.docker_apps_root does not exist";
    return;
  }
  for (auto &entry : boost::make_iterator_range(boost::filesystem::directory_iterator(config.docker_apps_root), {})) {
    if (boost::filesystem::is_directory(entry)) {
      std::string name = entry.path().filename().native();
      if (std::find(config.docker_apps.begin(), config.docker_apps.end(), name) == config.docker_apps.end()) {
        LOG_WARNING << "Docker App(" << name
                    << ") installed, but is now removed from configuration. Removing from system";
        DockerApp(name, config).remove();
      }
    }
  }
}

TargetStatus DockerAppManager::verifyTarget(const Uptane::Target &target) const {
  TargetStatus status;
  if (target.IsOstree()) {
    status = OstreeManager::verifyTarget(target);
    if (status != TargetStatus::kGood) {
      return status;
    }
  }
  auto cb = [this](const std::string &app, const Uptane::Target &app_target) {
    LOG_INFO << "Verifying " << app << " -> " << app_target;
    std::stringstream ss;
    ss << *storage_->openTargetFile(app_target);
    DockerApp dapp(app, config);
    return dapp.render(ss.str(), false);
  };
  if (!iterate_apps(target, cb)) {
    return TargetStatus::kInvalid;
  }
  return TargetStatus::kGood;
}
<commit_msg>docker-app: Fix bad parameters file logic<commit_after>#include "dockerappmanager.h"

#include <sstream>

/**
 * @brief This package manager compliments the OSTreePackageManager by also including optional Docker Apps.
 *
 * A full description of the Docker App project can be found here:
 *  https://github.com/docker/app/
 *
 * Docker Apps are very analogous to docker-compose. In fact, this module
 * currently "renders" the docker-app file into a docker-compose file. Each
 * Docker App appears as a Target in the TUF targets list. Each OStree target
 * can then reference these docker apps in its custom data section. eg:
 *
 *   "targets": {
 *     httpd.dockerapp-1 : {
 *       "custom" : {"hardwareIds" : ["all"], "name" : "httpd.dockerapp", "version" : "1"},
 *       "hashes" : {"sha256" : "f0ad4e3ce6a5e9cb70c9d747e977fddfacd08419deec0714622029b12dde8338"},
 *       "length" : 889
 *     },
 *    "raspberrypi3-64-lmp-144" : {
 *      "custom" : {
 *         "docker_apps" : {
 *            "httpd" : {
 *               "filename" : "httpd.dockerapp-1"
 *            }
 *         },
 *         "hardwareIds" : ["raspberrypi3-64"],
 *         "name" : "raspberrypi3-64-lmp",
 *         "targetFormat" : "OSTREE",
 *         "version" : "144"
 *      },
 *      "hashes" : {"sha256" : "20ac4f7cd50cda6bfed0caa1f8231cc9a7e40bec60026c66df5f7e143af96942"},
 *      "length" : 0
 *     }
 *   }
 */

struct DockerApp {
  DockerApp(std::string app_name, const PackageConfig &config)
      : name(std::move(app_name)),
        app_root(config.docker_apps_root / name),
        app_params(config.docker_app_params),
        app_bin(config.docker_app_bin),
        compose_bin(config.docker_compose_bin) {}

  bool render(const std::string &app_content, bool persist) {
    auto bin = boost::filesystem::canonical(app_bin).string();
    Utils::writeFile(app_root / (name + ".dockerapp"), app_content);
    std::string cmd("cd " + app_root.string() + " && " + bin + " render " + name);
    if (!app_params.empty()) {
      cmd += " --parameters-file " + app_params.string();
    }
    std::string yaml;
    if (Utils::shell(cmd, &yaml, true) != 0) {
      LOG_ERROR << "Unable to run " << cmd << " output:\n" << yaml;
      return false;
    }
    if (persist) {
      Utils::writeFile(app_root / "docker-compose.yml", yaml);
    }
    return true;
  }

  bool start() {
    // Depending on the number and size of the containers in the docker-app,
    // this command can take a bit of time to complete. Rather than using,
    // Utils::shell which isn't interactive, we'll use std::system so that
    // stdout/stderr is streamed while docker sets things up.
    auto bin = boost::filesystem::canonical(compose_bin).string();
    std::string cmd("cd " + app_root.string() + " && " + bin + " up --remove-orphans -d");
    return std::system(cmd.c_str()) == 0;
  }

  void remove() {
    auto bin = boost::filesystem::canonical(compose_bin).string();
    std::string cmd("cd " + app_root.string() + " && " + bin + " down");
    if (std::system(cmd.c_str()) == 0) {
      boost::filesystem::remove_all(app_root);
    } else {
      LOG_ERROR << "docker-compose was unable to bring down: " << app_root;
    }
  }

  std::string name;
  boost::filesystem::path app_root;
  boost::filesystem::path app_params;
  boost::filesystem::path app_bin;
  boost::filesystem::path compose_bin;
};

bool DockerAppManager::iterate_apps(const Uptane::Target &target, const DockerAppCb &cb) const {
  auto apps = target.custom_data()["docker_apps"];
  bool res = true;
  Uptane::ImagesRepository repo;
  // checkMetaOffline pulls in data from INvStorage to properly initialize
  // the targets member of the instance so that we can use the LazyTargetList
  repo.checkMetaOffline(*storage_);

  if (!apps) {
    LOG_DEBUG << "Detected an update target from Director with no docker-apps data";
    for (const auto &t : Uptane::LazyTargetsList(repo, storage_, fake_fetcher_)) {
      if (t.MatchTarget(target)) {
        LOG_DEBUG << "Found the match " << t;
        apps = t.custom_data()["docker_apps"];
        break;
      }
    }
  }

  for (const auto &t : Uptane::LazyTargetsList(repo, storage_, fake_fetcher_)) {
    for (Json::ValueIterator i = apps.begin(); i != apps.end(); ++i) {
      if ((*i).isObject() && (*i).isMember("filename")) {
        for (const auto &app : config.docker_apps) {
          if (i.key().asString() == app && (*i)["filename"].asString() == t.filename()) {
            if (!cb(app, t)) {
              res = false;
            }
          }
        }
      } else {
        LOG_ERROR << "Invalid custom data for docker-app: " << i.key().asString() << " -> " << *i;
      }
    }
  }
  return res;
}

bool DockerAppManager::fetchTarget(const Uptane::Target &target, Uptane::Fetcher &fetcher, const KeyManager &keys,
                                   FetcherProgressCb progress_cb, const api::FlowControlToken *token) {
  if (!OstreeManager::fetchTarget(target, fetcher, keys, progress_cb, token)) {
    return false;
  }

  LOG_INFO << "Looking for DockerApps to fetch";
  auto cb = [this, &fetcher, &keys, progress_cb, token](const std::string &app, const Uptane::Target &app_target) {
    LOG_INFO << "Fetching " << app << " -> " << app_target;
    return PackageManagerInterface::fetchTarget(app_target, fetcher, keys, progress_cb, token);
  };
  return iterate_apps(target, cb);
}

data::InstallationResult DockerAppManager::install(const Uptane::Target &target) const {
  auto res = OstreeManager::install(target);
  handleRemovedApps();
  auto cb = [this](const std::string &app, const Uptane::Target &app_target) {
    LOG_INFO << "Installing " << app << " -> " << app_target;
    std::stringstream ss;
    ss << *storage_->openTargetFile(app_target);
    DockerApp dapp(app, config);
    return dapp.render(ss.str(), true) && dapp.start();
  };
  if (!iterate_apps(target, cb)) {
    return data::InstallationResult(data::ResultCode::Numeric::kInstallFailed, "Could not render docker app");
  }
  return res;
}

// Handle the case like:
//  1) sota.toml is configured with 2 docker apps: "app1, app2"
//  2) update is applied, so we are now running both app1 and app2
//  3) sota.toml is updated with 1 docker app: "app1"
// At this point we should stop app2 and remove it.
void DockerAppManager::handleRemovedApps() const {
  if (!boost::filesystem::is_directory(config.docker_apps_root)) {
    LOG_DEBUG << "config.docker_apps_root does not exist";
    return;
  }
  for (auto &entry : boost::make_iterator_range(boost::filesystem::directory_iterator(config.docker_apps_root), {})) {
    if (boost::filesystem::is_directory(entry)) {
      std::string name = entry.path().filename().native();
      if (std::find(config.docker_apps.begin(), config.docker_apps.end(), name) == config.docker_apps.end()) {
        LOG_WARNING << "Docker App(" << name
                    << ") installed, but is now removed from configuration. Removing from system";
        DockerApp(name, config).remove();
      }
    }
  }
}

TargetStatus DockerAppManager::verifyTarget(const Uptane::Target &target) const {
  TargetStatus status;
  if (target.IsOstree()) {
    status = OstreeManager::verifyTarget(target);
    if (status != TargetStatus::kGood) {
      return status;
    }
  }
  auto cb = [this](const std::string &app, const Uptane::Target &app_target) {
    LOG_INFO << "Verifying " << app << " -> " << app_target;
    std::stringstream ss;
    ss << *storage_->openTargetFile(app_target);
    DockerApp dapp(app, config);
    return dapp.render(ss.str(), false);
  };
  if (!iterate_apps(target, cb)) {
    return TargetStatus::kInvalid;
  }
  return TargetStatus::kGood;
}
<|endoftext|>