<commit_before>// Copyright (c) 2009-2017 The Regents of the University of Michigan
// This file is part of the HOOMD-blue project, released under the BSD 3-Clause License.

// Maintainer: joaander All developers are free to add the calls needed to export their modules

#include "HOOMDMath.h"
#include "ExecutionConfiguration.h"
#include "ClockSource.h"
#include "Profiler.h"
#include "ParticleData.h"
#include "SystemDefinition.h"
#include "BondedGroupData.h"
#include "Initializers.h"
#include "GetarInitializer.h"
#include "GSDReader.h"
#include "Compute.h"
#include "ComputeThermo.h"
#include "CellList.h"
#include "CellListStencil.h"
#include "ForceCompute.h"
#include "ForceConstraint.h"
#include "ConstForceCompute.h"
#include "Analyzer.h"
#include "IMDInterface.h"
#include "DCDDumpWriter.h"
#include "GetarDumpWriter.h"
#include "GSDDumpWriter.h"
#include "Logger.h"
#include "LogPlainTXT.h"
#include "LogMatrix.h"
#include "LogHDF5.h"
#include "CallbackAnalyzer.h"
#include "Updater.h"
#include "Integrator.h"
#include "SFCPackUpdater.h"
#include "BoxResizeUpdater.h"
#include "System.h"
#include "Variant.h"
#include "Messenger.h"
#include "SnapshotSystemData.h"

// include GPU classes
#ifdef ENABLE_CUDA
#include <cuda.h>
#include "CellListGPU.h"
#include "ComputeThermoGPU.h"
#include "SFCPackUpdaterGPU.h"

#include <cuda_profiler_api.h>
#endif

// include MPI classes
#ifdef ENABLE_MPI
#include "Communicator.h"
#include "DomainDecomposition.h"
#include "LoadBalancer.h"

#ifdef ENABLE_CUDA
#include "CommunicatorGPU.h"
#include "LoadBalancerGPU.h"
#endif // ENABLE_CUDA
#endif // ENABLE_MPI

#include "SignalHandler.h"

#include "HOOMDVersion.h"
#include "hoomd/extern/num_util.h"

#include <hoomd/extern/pybind/include/pybind11/pybind11.h>
#include <hoomd/extern/pybind/include/pybind11/stl_bind.h>

#include <iostream>
#include <sstream>
#include <fstream>
using namespace std;

#ifdef ENABLE_TBB
#include "tbb/task_scheduler_init.h"
#endif

/*! \file hoomd_module.cc
    \brief Brings all of the export_* functions together to export the hoomd python module
*/

/* numpy is terrible (see /opt/local/Library/Frameworks/Python.framework/Versions/2.7/
lib/python2.7/site-packages/numpy/core/generate_numpy_array.py)
The following #defines help get around this
*/

#if (PYBIND11_VERSION_MAJOR) != 2 || (PYBIND11_VERSION_MINOR) != 2
#error HOOMD-blue requires pybind11 2.2.x
#endif

#if PY_VERSION_HEX >= 0x03000000
#define MY_PY_VER_3x
#else
#define MY_PY_VER_2x
#endif

#ifdef MY_PY_VER_3x
void *my_import_array()
    {
    import_array();
    return NULL;
    }
#endif
#ifdef MY_PY_VER_2x
void my_import_array()
    {
    import_array();
    }
#endif

//! Method for getting the current version of HOOMD
/*! \returns Current HOOMD version identification string
*/
string get_hoomd_version()
    {
    ostringstream ver;
    // always outputting main version number: #402
    ver << "HOOMD-blue " << HOOMD_VERSION << endl;

    return ver.str();
    }

//! Layer for omp_get_num_procs()
int get_num_procs()
    {
    return 1;
    }

//! Get the hoomd version as a tuple
pybind11::object get_hoomd_version_tuple()
    {
    return pybind11::make_tuple(HOOMD_VERSION_MAJOR, HOOMD_VERSION_MINOR, HOOMD_VERSION_PATCH);
    }

//! Get the CUDA version as a tuple
pybind11::object get_cuda_version_tuple()
    {
    #ifdef ENABLE_CUDA
    int major = CUDA_VERSION / 1000;
    int minor = CUDA_VERSION / 10 % 100;
    return pybind11::make_tuple(major, minor);
    #else
    return pybind11::make_tuple(0,0);
    #endif
    }

//! Get the compiler version
string get_compiler_version()
    {
    #if defined(__GNUC__) && !(defined(__clang__) || defined(__INTEL_COMPILER))
    ostringstream o;
    o << "gcc " << __GNUC__ << "." << __GNUC_MINOR__ << "." <<  __GNUC_PATCHLEVEL__;
    return o.str();

    #elif defined(__clang__)
    ostringstream o;
    o << "clang " << __clang_major__ << "." << __clang_minor__ << "." <<  __clang_patchlevel__;
    return o.str();

    #elif defined(__INTEL_COMPILER)
    ostringstream o;
    o << "icc " << __INTEL_COMPILER;
    return o.str();

    #else
    return string("unknown");

    #endif
    }

//! Determine availability of MPI support
bool is_MPI_available()
   {
   return
#ifdef ENABLE_MPI
       true;
#else
       false;
#endif
    }

void mpi_barrier_world()
    {
    #ifdef ENABLE_MPI
    MPI_Barrier(MPI_COMM_WORLD);
    #endif
    }

//! Determine availability of TBB support
bool is_TBB_available()
   {
   return
#ifdef ENABLE_TBB
       true;
#else
       false;
#endif
    }

//! Start the CUDA profiler
void cuda_profile_start()
    {
    #ifdef ENABLE_CUDA
    cudaDeviceSynchronize();
    cudaProfilerStart();
    #endif
    }

//! Stop the CUDA profiler
void cuda_profile_stop()
    {
    #ifdef ENABLE_CUDA
    cudaDeviceSynchronize();
    cudaProfilerStop();
    #endif
    }

// values used in measuring hoomd launch timing
unsigned int hoomd_launch_time, hoomd_start_time, hoomd_mpi_init_time;
bool hoomd_launch_timing=false;

#ifdef ENABLE_MPI
//! Environment variables needed for setting up MPI
char env_enable_mpi_cuda[] = "MV2_USE_CUDA=1";

//! Initialize the MPI environment
void initialize_mpi()
    {
    #ifdef ENABLE_MPI_CUDA
    // if we are using an MPI-CUDA implementation, enable this feature
    // before the MPI_Init
    putenv(env_enable_mpi_cuda);
    #endif

    // benchmark hoomd launch times
    if (getenv("HOOMD_LAUNCH_TIME"))
        {
        // get the time that mpirun was called
        hoomd_launch_time = atoi(getenv("HOOMD_LAUNCH_TIME"));

        // compute the number of seconds to get here
        timeval t;
        gettimeofday(&t, NULL);
        hoomd_start_time = t.tv_sec - hoomd_launch_time;
        hoomd_launch_timing = true;
        }

    // initalize MPI
    MPI_Init(0, (char ***) NULL);

    if (hoomd_launch_timing)
        {
        // compute the number of seconds to get past mpi_init
        timeval t;
        gettimeofday(&t, NULL);
        hoomd_mpi_init_time = t.tv_sec - hoomd_launch_time;
        }
    }

//! Get the processor name associated to this rank
string get_mpi_proc_name()
    {
    char proc_name[MPI_MAX_PROCESSOR_NAME];
    int name_len;
    MPI_Get_processor_name(proc_name, &name_len);
    return string(proc_name);
    }

//! Finalize MPI environment
void finalize_mpi()
    {
    MPI_Finalize();
    }
#endif

//! Abort MPI runs
void abort_mpi(std::shared_ptr<ExecutionConfiguration> exec_conf)
    {
    #ifdef ENABLE_MPI
    if(exec_conf->getNRanksGlobal() > 1)
        {
        MPI_Abort(exec_conf->getMPICommunicator(), MPI_ERR_OTHER);
        }
    #endif
    }

//! broadcast string from root rank to all other ranks
std::string mpi_bcast_str(const std::string& s, std::shared_ptr<ExecutionConfiguration> exec_conf)
    {
    #ifdef ENABLE_MPI
    std::string result = s;
    bcast(result, 0, exec_conf->getMPICommunicator());
    return result;
    #else
    return s;
    #endif
    }

//! Create the python module
/*! each class setup their own python exports in a function export_ClassName
    create the hoomd python module and define the exports here.
*/
PYBIND11_MODULE(_hoomd, m)
    {
    #ifdef ENABLE_MPI
    // initialize MPI early
    initialize_mpi();

    // register clean-up function
    Py_AtExit(finalize_mpi);
    m.def("get_mpi_proc_name", get_mpi_proc_name);
    #endif

    // setup needed for numpy
    my_import_array();

    m.def("abort_mpi", abort_mpi);
    m.def("mpi_barrier_world", mpi_barrier_world);
    m.def("mpi_bcast_str", mpi_bcast_str);

    m.def("hoomd_compile_flags", &hoomd_compile_flags);
    m.def("output_version_info", &output_version_info);
    m.def("get_hoomd_version", &get_hoomd_version);

    m.def("get_num_procs", &get_num_procs);
    m.attr("__version__") = get_hoomd_version_tuple();
    m.attr("__git_sha1__") = pybind11::str(HOOMD_GIT_SHA1);
    m.attr("__git_refspec__") = pybind11::str(HOOMD_GIT_REFSPEC);
    m.attr("__cuda_version__") = get_cuda_version_tuple();
    m.attr("__compiler_version__") = pybind11::str(get_compiler_version());
    m.attr("__hoomd_source_dir__") = pybind11::str(HOOMD_SOURCE_DIR);

    m.def("is_MPI_available", &is_MPI_available);
    m.def("is_TBB_available", &is_TBB_available);

    m.def("cuda_profile_start", &cuda_profile_start);
    m.def("cuda_profile_stop", &cuda_profile_stop);

    pybind11::bind_vector< std::vector<Scalar> >(m,"std_vector_scalar");
    pybind11::bind_vector< std::vector<string> >(m,"std_vector_string");
    pybind11::bind_vector< std::vector<unsigned int> >(m,"std_vector_uint");
    pybind11::bind_vector< std::vector<int> >(m,"std_vector_int");
    pybind11::bind_vector< std::vector<Scalar3> >(m,"std_vector_scalar3");
    pybind11::bind_vector< std::vector<Scalar4> >(m,"std_vector_scalar4");

    InstallSIGINTHandler();

    // utils
    export_hoomd_math_functions(m);
    export_ClockSource(m);
    export_Profiler(m);

    // data structures
    export_BoxDim(m);
    export_ParticleData(m);
    export_SnapshotParticleData(m);
    export_ExecutionConfiguration(m);
    export_SystemDefinition(m);
    export_SnapshotSystemData(m);
    export_BondedGroupData<BondData,Bond>(m,"BondData","BondDataSnapshot");
    export_BondedGroupData<AngleData,Angle>(m,"AngleData","AngleDataSnapshot");
    export_BondedGroupData<DihedralData,Dihedral>(m,"DihedralData","DihedralDataSnapshot");
    export_BondedGroupData<ImproperData,Dihedral>(m,"ImproperData","ImproperDataSnapshot",false);
    export_BondedGroupData<ConstraintData,Constraint>(m,"ConstraintData","ConstraintDataSnapshot");
    export_BondedGroupData<PairData,Bond>(m,"PairData","PairDataSnapshot",false);

    // initializers
    export_GSDReader(m);
    getardump::export_GetarInitializer(m);

    // computes
    export_Compute(m);
    export_ComputeThermo(m);
    export_CellList(m);
    export_CellListStencil(m);
    export_ForceCompute(m);
    export_ForceConstraint(m);
    export_ConstForceCompute(m);

#ifdef ENABLE_CUDA
    export_CellListGPU(m);
    export_ComputeThermoGPU(m);
#endif

    // analyzers
    export_Analyzer(m);
    export_IMDInterface(m);
    export_DCDDumpWriter(m);
    getardump::export_GetarDumpWriter(m);
    export_GSDDumpWriter(m);
    export_Logger(m);
    export_LogPlainTXT(m);
    export_LogMatrix(m);
    export_LogHDF5(m);
    export_CallbackAnalyzer(m);
    export_ParticleGroup(m);

    // updaters
    export_Updater(m);
    export_Integrator(m);
    export_BoxResizeUpdater(m);
    export_SFCPackUpdater(m);
#ifdef ENABLE_CUDA
    export_SFCPackUpdaterGPU(m);
#endif

#ifdef ENABLE_MPI
    export_Communicator(m);
    export_DomainDecomposition(m);
    export_LoadBalancer(m);
#ifdef ENABLE_CUDA
    export_CommunicatorGPU(m);
    export_LoadBalancerGPU(m);
#endif // ENABLE_CUDA
#endif // ENABLE_MPI

    // system
    export_System(m);

    // variant
    export_Variant(m);

    // messenger
    export_Messenger(m);
    }
<commit_msg>Check if MPI has already been initialized before calling MPI_Init.<commit_after>// Copyright (c) 2009-2017 The Regents of the University of Michigan
// This file is part of the HOOMD-blue project, released under the BSD 3-Clause License.

// Maintainer: joaander All developers are free to add the calls needed to export their modules

#include "HOOMDMath.h"
#include "ExecutionConfiguration.h"
#include "ClockSource.h"
#include "Profiler.h"
#include "ParticleData.h"
#include "SystemDefinition.h"
#include "BondedGroupData.h"
#include "Initializers.h"
#include "GetarInitializer.h"
#include "GSDReader.h"
#include "Compute.h"
#include "ComputeThermo.h"
#include "CellList.h"
#include "CellListStencil.h"
#include "ForceCompute.h"
#include "ForceConstraint.h"
#include "ConstForceCompute.h"
#include "Analyzer.h"
#include "IMDInterface.h"
#include "DCDDumpWriter.h"
#include "GetarDumpWriter.h"
#include "GSDDumpWriter.h"
#include "Logger.h"
#include "LogPlainTXT.h"
#include "LogMatrix.h"
#include "LogHDF5.h"
#include "CallbackAnalyzer.h"
#include "Updater.h"
#include "Integrator.h"
#include "SFCPackUpdater.h"
#include "BoxResizeUpdater.h"
#include "System.h"
#include "Variant.h"
#include "Messenger.h"
#include "SnapshotSystemData.h"

// include GPU classes
#ifdef ENABLE_CUDA
#include <cuda.h>
#include "CellListGPU.h"
#include "ComputeThermoGPU.h"
#include "SFCPackUpdaterGPU.h"

#include <cuda_profiler_api.h>
#endif

// include MPI classes
#ifdef ENABLE_MPI
#include "Communicator.h"
#include "DomainDecomposition.h"
#include "LoadBalancer.h"

#ifdef ENABLE_CUDA
#include "CommunicatorGPU.h"
#include "LoadBalancerGPU.h"
#endif // ENABLE_CUDA
#endif // ENABLE_MPI

#include "SignalHandler.h"

#include "HOOMDVersion.h"
#include "hoomd/extern/num_util.h"

#include <hoomd/extern/pybind/include/pybind11/pybind11.h>
#include <hoomd/extern/pybind/include/pybind11/stl_bind.h>

#include <iostream>
#include <sstream>
#include <fstream>
using namespace std;

#ifdef ENABLE_TBB
#include "tbb/task_scheduler_init.h"
#endif

/*! \file hoomd_module.cc
    \brief Brings all of the export_* functions together to export the hoomd python module
*/

/* numpy is terrible (see /opt/local/Library/Frameworks/Python.framework/Versions/2.7/
lib/python2.7/site-packages/numpy/core/generate_numpy_array.py)
The following #defines help get around this
*/

#if (PYBIND11_VERSION_MAJOR) != 2 || (PYBIND11_VERSION_MINOR) != 2
#error HOOMD-blue requires pybind11 2.2.x
#endif

#if PY_VERSION_HEX >= 0x03000000
#define MY_PY_VER_3x
#else
#define MY_PY_VER_2x
#endif

#ifdef MY_PY_VER_3x
void *my_import_array()
    {
    import_array();
    return NULL;
    }
#endif
#ifdef MY_PY_VER_2x
void my_import_array()
    {
    import_array();
    }
#endif

//! Method for getting the current version of HOOMD
/*! \returns Current HOOMD version identification string
*/
string get_hoomd_version()
    {
    ostringstream ver;
    // always outputting main version number: #402
    ver << "HOOMD-blue " << HOOMD_VERSION << endl;

    return ver.str();
    }

//! Layer for omp_get_num_procs()
int get_num_procs()
    {
    return 1;
    }

//! Get the hoomd version as a tuple
pybind11::object get_hoomd_version_tuple()
    {
    return pybind11::make_tuple(HOOMD_VERSION_MAJOR, HOOMD_VERSION_MINOR, HOOMD_VERSION_PATCH);
    }

//! Get the CUDA version as a tuple
pybind11::object get_cuda_version_tuple()
    {
    #ifdef ENABLE_CUDA
    int major = CUDA_VERSION / 1000;
    int minor = CUDA_VERSION / 10 % 100;
    return pybind11::make_tuple(major, minor);
    #else
    return pybind11::make_tuple(0,0);
    #endif
    }

//! Get the compiler version
string get_compiler_version()
    {
    #if defined(__GNUC__) && !(defined(__clang__) || defined(__INTEL_COMPILER))
    ostringstream o;
    o << "gcc " << __GNUC__ << "." << __GNUC_MINOR__ << "." <<  __GNUC_PATCHLEVEL__;
    return o.str();

    #elif defined(__clang__)
    ostringstream o;
    o << "clang " << __clang_major__ << "." << __clang_minor__ << "." <<  __clang_patchlevel__;
    return o.str();

    #elif defined(__INTEL_COMPILER)
    ostringstream o;
    o << "icc " << __INTEL_COMPILER;
    return o.str();

    #else
    return string("unknown");

    #endif
    }

//! Determine availability of MPI support
bool is_MPI_available()
   {
   return
#ifdef ENABLE_MPI
       true;
#else
       false;
#endif
    }

void mpi_barrier_world()
    {
    #ifdef ENABLE_MPI
    MPI_Barrier(MPI_COMM_WORLD);
    #endif
    }

//! Determine availability of TBB support
bool is_TBB_available()
   {
   return
#ifdef ENABLE_TBB
       true;
#else
       false;
#endif
    }

//! Start the CUDA profiler
void cuda_profile_start()
    {
    #ifdef ENABLE_CUDA
    cudaDeviceSynchronize();
    cudaProfilerStart();
    #endif
    }

//! Stop the CUDA profiler
void cuda_profile_stop()
    {
    #ifdef ENABLE_CUDA
    cudaDeviceSynchronize();
    cudaProfilerStop();
    #endif
    }

// values used in measuring hoomd launch timing
unsigned int hoomd_launch_time, hoomd_start_time, hoomd_mpi_init_time;
bool hoomd_launch_timing=false;

#ifdef ENABLE_MPI
//! Environment variables needed for setting up MPI
char env_enable_mpi_cuda[] = "MV2_USE_CUDA=1";

//! Initialize the MPI environment
void initialize_mpi()
    {
    #ifdef ENABLE_MPI_CUDA
    // if we are using an MPI-CUDA implementation, enable this feature
    // before the MPI_Init
    putenv(env_enable_mpi_cuda);
    #endif

    // benchmark hoomd launch times
    if (getenv("HOOMD_LAUNCH_TIME"))
        {
        // get the time that mpirun was called
        hoomd_launch_time = atoi(getenv("HOOMD_LAUNCH_TIME"));

        // compute the number of seconds to get here
        timeval t;
        gettimeofday(&t, NULL);
        hoomd_start_time = t.tv_sec - hoomd_launch_time;
        hoomd_launch_timing = true;
        }

    // initialize MPI if it has not been initialized by another program
    int is_initialized = 0;
    MPI_Initialized(&is_initialized);
    if (!is_initialized)
        {
        MPI_Init(0, (char ***) NULL);
        }

    if (hoomd_launch_timing)
        {
        // compute the number of seconds to get past mpi_init
        timeval t;
        gettimeofday(&t, NULL);
        hoomd_mpi_init_time = t.tv_sec - hoomd_launch_time;
        }
    }

//! Get the processor name associated to this rank
string get_mpi_proc_name()
    {
    char proc_name[MPI_MAX_PROCESSOR_NAME];
    int name_len;
    MPI_Get_processor_name(proc_name, &name_len);
    return string(proc_name);
    }

//! Finalize MPI environment
void finalize_mpi()
    {
    MPI_Finalize();
    }
#endif

//! Abort MPI runs
void abort_mpi(std::shared_ptr<ExecutionConfiguration> exec_conf)
    {
    #ifdef ENABLE_MPI
    if(exec_conf->getNRanksGlobal() > 1)
        {
        MPI_Abort(exec_conf->getMPICommunicator(), MPI_ERR_OTHER);
        }
    #endif
    }

//! broadcast string from root rank to all other ranks
std::string mpi_bcast_str(const std::string& s, std::shared_ptr<ExecutionConfiguration> exec_conf)
    {
    #ifdef ENABLE_MPI
    std::string result = s;
    bcast(result, 0, exec_conf->getMPICommunicator());
    return result;
    #else
    return s;
    #endif
    }

//! Create the python module
/*! each class setup their own python exports in a function export_ClassName
    create the hoomd python module and define the exports here.
*/
PYBIND11_MODULE(_hoomd, m)
    {
    #ifdef ENABLE_MPI
    // initialize MPI early
    initialize_mpi();

    // register clean-up function
    Py_AtExit(finalize_mpi);
    m.def("get_mpi_proc_name", get_mpi_proc_name);
    #endif

    // setup needed for numpy
    my_import_array();

    m.def("abort_mpi", abort_mpi);
    m.def("mpi_barrier_world", mpi_barrier_world);
    m.def("mpi_bcast_str", mpi_bcast_str);

    m.def("hoomd_compile_flags", &hoomd_compile_flags);
    m.def("output_version_info", &output_version_info);
    m.def("get_hoomd_version", &get_hoomd_version);

    m.def("get_num_procs", &get_num_procs);
    m.attr("__version__") = get_hoomd_version_tuple();
    m.attr("__git_sha1__") = pybind11::str(HOOMD_GIT_SHA1);
    m.attr("__git_refspec__") = pybind11::str(HOOMD_GIT_REFSPEC);
    m.attr("__cuda_version__") = get_cuda_version_tuple();
    m.attr("__compiler_version__") = pybind11::str(get_compiler_version());
    m.attr("__hoomd_source_dir__") = pybind11::str(HOOMD_SOURCE_DIR);

    m.def("is_MPI_available", &is_MPI_available);
    m.def("is_TBB_available", &is_TBB_available);

    m.def("cuda_profile_start", &cuda_profile_start);
    m.def("cuda_profile_stop", &cuda_profile_stop);

    pybind11::bind_vector< std::vector<Scalar> >(m,"std_vector_scalar");
    pybind11::bind_vector< std::vector<string> >(m,"std_vector_string");
    pybind11::bind_vector< std::vector<unsigned int> >(m,"std_vector_uint");
    pybind11::bind_vector< std::vector<int> >(m,"std_vector_int");
    pybind11::bind_vector< std::vector<Scalar3> >(m,"std_vector_scalar3");
    pybind11::bind_vector< std::vector<Scalar4> >(m,"std_vector_scalar4");

    InstallSIGINTHandler();

    // utils
    export_hoomd_math_functions(m);
    export_ClockSource(m);
    export_Profiler(m);

    // data structures
    export_BoxDim(m);
    export_ParticleData(m);
    export_SnapshotParticleData(m);
    export_ExecutionConfiguration(m);
    export_SystemDefinition(m);
    export_SnapshotSystemData(m);
    export_BondedGroupData<BondData,Bond>(m,"BondData","BondDataSnapshot");
    export_BondedGroupData<AngleData,Angle>(m,"AngleData","AngleDataSnapshot");
    export_BondedGroupData<DihedralData,Dihedral>(m,"DihedralData","DihedralDataSnapshot");
    export_BondedGroupData<ImproperData,Dihedral>(m,"ImproperData","ImproperDataSnapshot",false);
    export_BondedGroupData<ConstraintData,Constraint>(m,"ConstraintData","ConstraintDataSnapshot");
    export_BondedGroupData<PairData,Bond>(m,"PairData","PairDataSnapshot",false);

    // initializers
    export_GSDReader(m);
    getardump::export_GetarInitializer(m);

    // computes
    export_Compute(m);
    export_ComputeThermo(m);
    export_CellList(m);
    export_CellListStencil(m);
    export_ForceCompute(m);
    export_ForceConstraint(m);
    export_ConstForceCompute(m);

#ifdef ENABLE_CUDA
    export_CellListGPU(m);
    export_ComputeThermoGPU(m);
#endif

    // analyzers
    export_Analyzer(m);
    export_IMDInterface(m);
    export_DCDDumpWriter(m);
    getardump::export_GetarDumpWriter(m);
    export_GSDDumpWriter(m);
    export_Logger(m);
    export_LogPlainTXT(m);
    export_LogMatrix(m);
    export_LogHDF5(m);
    export_CallbackAnalyzer(m);
    export_ParticleGroup(m);

    // updaters
    export_Updater(m);
    export_Integrator(m);
    export_BoxResizeUpdater(m);
    export_SFCPackUpdater(m);
#ifdef ENABLE_CUDA
    export_SFCPackUpdaterGPU(m);
#endif

#ifdef ENABLE_MPI
    export_Communicator(m);
    export_DomainDecomposition(m);
    export_LoadBalancer(m);
#ifdef ENABLE_CUDA
    export_CommunicatorGPU(m);
    export_LoadBalancerGPU(m);
#endif // ENABLE_CUDA
#endif // ENABLE_MPI

    // system
    export_System(m);

    // variant
    export_Variant(m);

    // messenger
    export_Messenger(m);
    }
<|endoftext|>


<commit_before>// =================================================================== //
// Copyright (C) 2016-2017 Kimura Ryo                                  //
//                                                                     //
// This Source Code Form is subject to the terms of the Mozilla Public //
// License, v. 2.0. If a copy of the MPL was not distributed with this //
// file, You can obtain one at http://mozilla.org/MPL/2.0/.            //
// =================================================================== //

#include <libbsdf/Brdf/SpecularCoordinatesRandomSampleSet.h>

using namespace lb;

void SpecularCoordinatesRandomSampleSet::setupBrdf(SpecularCoordinatesBrdf* brdf,
                                                   float                    weight0,
                                                   float                    weight1,
                                                   float                    weight2,
                                                   float                    weight3)
{
    for (int inThIndex = 0; inThIndex < brdf->getNumInTheta();   ++inThIndex) {
    for (int inPhIndex = 0; inPhIndex < brdf->getNumInPhi();     ++inPhIndex) {
    for (int spThIndex = 0; spThIndex < brdf->getNumSpecTheta(); ++spThIndex) {
        RandomSampleSet::AngleList angles;
        SampleMap::iterator it;
        float w3;
        Spectrum sp;
        #pragma omp parallel for private(angles, it, w3, sp)
        for (int spPhIndex = 0; spPhIndex < brdf->getNumSpecPhi(); ++spPhIndex) {
            angles.resize(4);
            angles.at(0) = brdf->getInTheta(inThIndex);
            angles.at(1) = brdf->getInPhi(inPhIndex);
            angles.at(2) = brdf->getSpecTheta(spThIndex);
            angles.at(3) = brdf->getSpecPhi(spPhIndex);

            it = sampleMap_.find(angles);
            if (it != sampleMap_.end()) {
                brdf->setSpectrum(inThIndex, inPhIndex, spThIndex, spPhIndex,
                                  it->second);
            }
            else {
                // Modify a weight coefficient.
                w3 = weight3 * hermiteInterpolation3(1.0f, 1.0f / weight3, brdf->getSpecTheta(spThIndex) / PI_2_F);
                sp = estimateSpectrum<SpecularCoordinateSystem>(angles, weight0, weight1, weight2, w3);
                brdf->setSpectrum(inThIndex, inPhIndex, spThIndex, spPhIndex, sp);
            }
        }
    }}}

    brdf->getSampleSet()->updateAngleAttributes();
}
<commit_msg>Adjusted the parameter for estimation of sample points<commit_after>// =================================================================== //
// Copyright (C) 2016-2018 Kimura Ryo                                  //
//                                                                     //
// This Source Code Form is subject to the terms of the Mozilla Public //
// License, v. 2.0. If a copy of the MPL was not distributed with this //
// file, You can obtain one at http://mozilla.org/MPL/2.0/.            //
// =================================================================== //

#include <libbsdf/Brdf/SpecularCoordinatesRandomSampleSet.h>

using namespace lb;

void SpecularCoordinatesRandomSampleSet::setupBrdf(SpecularCoordinatesBrdf* brdf,
                                                   float                    weight0,
                                                   float                    weight1,
                                                   float                    weight2,
                                                   float                    weight3)
{
    for (int inThIndex = 0; inThIndex < brdf->getNumInTheta();   ++inThIndex) {
    for (int inPhIndex = 0; inPhIndex < brdf->getNumInPhi();     ++inPhIndex) {
    for (int spThIndex = 0; spThIndex < brdf->getNumSpecTheta(); ++spThIndex) {
        float angleInput3 = brdf->getInTheta(inThIndex) / SpecularCoordinateSystem::MAX_ANGLE0
                          + brdf->getSpecTheta(spThIndex) / SpecularCoordinateSystem::MAX_ANGLE2;
        angleInput3 /= 2.0;

        RandomSampleSet::AngleList angles;
        SampleMap::iterator it;
        float w3;
        Spectrum sp;
        #pragma omp parallel for private(angles, it, w3, sp)
        for (int spPhIndex = 0; spPhIndex < brdf->getNumSpecPhi(); ++spPhIndex) {
            angles.resize(4);
            angles.at(0) = brdf->getInTheta(inThIndex);
            angles.at(1) = brdf->getInPhi(inPhIndex);
            angles.at(2) = brdf->getSpecTheta(spThIndex);
            angles.at(3) = brdf->getSpecPhi(spPhIndex);

            it = sampleMap_.find(angles);
            if (it != sampleMap_.end()) {
                brdf->setSpectrum(inThIndex, inPhIndex, spThIndex, spPhIndex,
                                  it->second);
            }
            else {
                // Modify a weight coefficient for specular azimuthal angles.
                w3 = hermiteInterpolation3(weight3, 10.0f * weight3, angleInput3);

                sp = estimateSpectrum<SpecularCoordinateSystem>(angles, weight0, weight1, weight2, w3);
                brdf->setSpectrum(inThIndex, inPhIndex, spThIndex, spPhIndex, sp);
            }
        }
    }}}

    brdf->getSampleSet()->updateAngleAttributes();
}
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: EntryInputStream.hxx,v $
 *
 *  $Revision: 1.9 $
 *
 *  last change: $Author: rt $ $Date: 2005-09-08 16:12:12 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    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., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/
#ifndef _ENTRY_INPUT_STREAM_HXX
#define _ENTRY_INPUT_STREAM_HXX

#ifndef _CPPUHELPER_IMPLBASE2_HXX_
#include <cppuhelper/implbase2.hxx> // helper for implementations
#endif
#ifndef _COM_SUN_STAR_IO_XINPUTSTREAM_HPP_
#include <com/sun/star/io/XInputStream.hpp>
#endif
#ifndef _COM_SUN_STAR_IO_XSEEKABLE_HPP_
#include <com/sun/star/io/XSeekable.hpp>
#endif
#ifndef _INFLATER_HXX_
#include <Inflater.hxx>
#endif
#ifndef _COM_SUN_STAR_PACKAGES_ZIP_ZIPENTRY_HPP_
#include <com/sun/star/packages/zip/ZipEntry.hpp>
#endif
#ifndef _VOS_REF_H_
#include <vos/ref.hxx>
#endif
#ifndef _ENCRYPTION_DATA_HXX
#include <EncryptionData.hxx>
#endif
class EntryInputStream : public cppu::WeakImplHelper2< com::sun::star::io::XInputStream,
                                                       com::sun::star::io::XSeekable >
{
protected:
    com::sun::star::uno::Reference< com::sun::star::io::XInputStream > xStream;
    com::sun::star::uno::Reference< com::sun::star::io::XSeekable > xSeek;
    sal_Int64 nEnd, nCurrent, nUncompressedSize;
    sal_Bool bRawStream, bHaveInMemory, bEncrypted;
    com::sun::star::uno::Sequence < sal_Int8 > aBuffer;
    const vos::ORef < EncryptionData > xEncryptionData;
    const com::sun::star::packages::zip::ZipEntry aEntry;
    Inflater aInflater;
    void readIntoMemory()
        throw(::com::sun::star::io::NotConnectedException, ::com::sun::star::io::BufferSizeExceededException, ::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException);
public:
             EntryInputStream( com::sun::star::uno::Reference < com::sun::star::io::XInputStream > xInput,
                                const com::sun::star::packages::zip::ZipEntry &rNewEntry,
                               const vos::ORef < EncryptionData > &xEncryptData,
                               sal_Bool bGetRawStream = sal_False);
    virtual ~EntryInputStream();

    // XInputStream
    virtual sal_Int32 SAL_CALL readBytes( ::com::sun::star::uno::Sequence< sal_Int8 >& aData, sal_Int32 nBytesToRead )
        throw(::com::sun::star::io::NotConnectedException, ::com::sun::star::io::BufferSizeExceededException, ::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException);
    virtual sal_Int32 SAL_CALL readSomeBytes( ::com::sun::star::uno::Sequence< sal_Int8 >& aData, sal_Int32 nMaxBytesToRead )
        throw(::com::sun::star::io::NotConnectedException, ::com::sun::star::io::BufferSizeExceededException, ::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException);
    virtual void SAL_CALL skipBytes( sal_Int32 nBytesToSkip )
        throw(::com::sun::star::io::NotConnectedException, ::com::sun::star::io::BufferSizeExceededException, ::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException);
    virtual sal_Int32 SAL_CALL available(  )
        throw(::com::sun::star::io::NotConnectedException, ::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException);
    virtual void SAL_CALL closeInput(  )
        throw(::com::sun::star::io::NotConnectedException, ::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException);
    // XSeekable
    virtual void SAL_CALL seek( sal_Int64 location )
        throw(::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException);
    virtual sal_Int64 SAL_CALL getPosition(  )
        throw(::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException);
    virtual sal_Int64 SAL_CALL getLength(  )
        throw(::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException);
    /*
private:
    void fill( void );
    */
};

#endif
<commit_msg>INTEGRATION: CWS changefileheader (1.9.98); FILE MERGED 2008/04/01 15:22:24 thb 1.9.98.3: #i85898# Stripping all external header guards 2008/04/01 12:32:13 thb 1.9.98.2: #i85898# Stripping all external header guards 2008/03/31 16:19:09 rt 1.9.98.1: #i87441# Change license header to LPGL v3.<commit_after>/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2008 by Sun Microsystems, Inc.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * $RCSfile: EntryInputStream.hxx,v $
 * $Revision: 1.10 $
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org 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 version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/
#ifndef _ENTRY_INPUT_STREAM_HXX
#define _ENTRY_INPUT_STREAM_HXX

#include <cppuhelper/implbase2.hxx> // helper for implementations
#include <com/sun/star/io/XInputStream.hpp>
#include <com/sun/star/io/XSeekable.hpp>
#include <Inflater.hxx>
#include <com/sun/star/packages/zip/ZipEntry.hpp>
#ifndef _VOS_REF_H_
#include <vos/ref.hxx>
#endif
#ifndef _ENCRYPTION_DATA_HXX
#include <EncryptionData.hxx>
#endif
class EntryInputStream : public cppu::WeakImplHelper2< com::sun::star::io::XInputStream,
                                                       com::sun::star::io::XSeekable >
{
protected:
    com::sun::star::uno::Reference< com::sun::star::io::XInputStream > xStream;
    com::sun::star::uno::Reference< com::sun::star::io::XSeekable > xSeek;
    sal_Int64 nEnd, nCurrent, nUncompressedSize;
    sal_Bool bRawStream, bHaveInMemory, bEncrypted;
    com::sun::star::uno::Sequence < sal_Int8 > aBuffer;
    const vos::ORef < EncryptionData > xEncryptionData;
    const com::sun::star::packages::zip::ZipEntry aEntry;
    Inflater aInflater;
    void readIntoMemory()
        throw(::com::sun::star::io::NotConnectedException, ::com::sun::star::io::BufferSizeExceededException, ::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException);
public:
             EntryInputStream( com::sun::star::uno::Reference < com::sun::star::io::XInputStream > xInput,
                                const com::sun::star::packages::zip::ZipEntry &rNewEntry,
                               const vos::ORef < EncryptionData > &xEncryptData,
                               sal_Bool bGetRawStream = sal_False);
    virtual ~EntryInputStream();

    // XInputStream
    virtual sal_Int32 SAL_CALL readBytes( ::com::sun::star::uno::Sequence< sal_Int8 >& aData, sal_Int32 nBytesToRead )
        throw(::com::sun::star::io::NotConnectedException, ::com::sun::star::io::BufferSizeExceededException, ::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException);
    virtual sal_Int32 SAL_CALL readSomeBytes( ::com::sun::star::uno::Sequence< sal_Int8 >& aData, sal_Int32 nMaxBytesToRead )
        throw(::com::sun::star::io::NotConnectedException, ::com::sun::star::io::BufferSizeExceededException, ::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException);
    virtual void SAL_CALL skipBytes( sal_Int32 nBytesToSkip )
        throw(::com::sun::star::io::NotConnectedException, ::com::sun::star::io::BufferSizeExceededException, ::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException);
    virtual sal_Int32 SAL_CALL available(  )
        throw(::com::sun::star::io::NotConnectedException, ::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException);
    virtual void SAL_CALL closeInput(  )
        throw(::com::sun::star::io::NotConnectedException, ::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException);
    // XSeekable
    virtual void SAL_CALL seek( sal_Int64 location )
        throw(::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException);
    virtual sal_Int64 SAL_CALL getPosition(  )
        throw(::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException);
    virtual sal_Int64 SAL_CALL getLength(  )
        throw(::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException);
    /*
private:
    void fill( void );
    */
};

#endif
<|endoftext|>


<commit_before>/***************************************************************************
 *   Copyright (c) 2015 Stefan Tröger <stefantroeger@gmx.net>              *
 *                                                                         *
 *   This file is part of the FreeCAD CAx development system.              *
 *                                                                         *
 *   This library is free software; you can redistribute it and/or         *
 *   modify it under the terms of the GNU Library General Public           *
 *   License as published by the Free Software Foundation; either          *
 *   version 2 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 Library General Public License for more details.                  *
 *                                                                         *
 *   You should have received a copy of the GNU Library General Public     *
 *   License along with this library; see the file COPYING.LIB. If not,    *
 *   write to the Free Software Foundation, Inc., 59 Temple Place,         *
 *   Suite 330, Boston, MA  02111-1307, USA                                *
 *                                                                         *
 ***************************************************************************/

#include "PreCompiled.h"
#include "ViewProviderFemPostPipeline.h"
#include "ViewProviderFemPostFunction.h"
#include <Mod/Fem/App/FemPostPipeline.h>
#include <Base/Console.h>
#include <Gui/Application.h>

using namespace FemGui;

PROPERTY_SOURCE(FemGui::ViewProviderFemPostPipeline, FemGui::ViewProviderFemPostObject)

ViewProviderFemPostPipeline::ViewProviderFemPostPipeline()
{
    sPixmap = "fem-data";
}

ViewProviderFemPostPipeline::~ViewProviderFemPostPipeline()
{
}

std::vector< App::DocumentObject* > ViewProviderFemPostPipeline::claimChildren(void) const {

    Fem::FemPostPipeline* pipeline = static_cast<Fem::FemPostPipeline*>(getObject());
    std::vector<App::DocumentObject*> children;

    if(pipeline->Functions.getValue())
        children.push_back(pipeline->Functions.getValue());

    children.insert(children.end(), pipeline->Filter.getValues().begin(), pipeline->Filter.getValues().end());
    return children;
}

std::vector< App::DocumentObject* > ViewProviderFemPostPipeline::claimChildren3D(void) const {

    return claimChildren();
}

void ViewProviderFemPostPipeline::updateData(const App::Property* prop) {
    FemGui::ViewProviderFemPostObject::onChanged(prop);

    if(strcmp(prop->getName(), "Function") == 0) {
        updateFunctionSize();
    }

}

void ViewProviderFemPostPipeline::updateFunctionSize() {

    //we need to get the bounding box and set the function  provider size
    Fem::FemPostPipeline* obj = static_cast<Fem::FemPostPipeline*>(getObject());

    if(!obj->Functions.getValue() || !obj->Functions.getValue()->isDerivedFrom(Fem::FemPostFunctionProvider::getClassTypeId()))
        return;

    //get the functtion provider
    FemGui::ViewProviderFemPostFunctionProvider* vp = static_cast<FemGui::ViewProviderFemPostFunctionProvider*>(
                                                    Gui::Application::Instance->getViewProvider(obj->Functions.getValue()));

    if(obj->Data.getValue() && obj->Data.getValue()->IsA("vtkDataSet")) {
        vtkBoundingBox box = obj->getBoundingBox();

        vp->SizeX.setValue(box.GetLength(0)*1.2);
        vp->SizeY.setValue(box.GetLength(1)*1.2);
        vp->SizeZ.setValue(box.GetLength(2)*1.2);
    }
}
<commit_msg>FEM: typo, @luzpaz, I can't hardly belive there are still typos, but there are :-)<commit_after>/***************************************************************************
 *   Copyright (c) 2015 Stefan Tröger <stefantroeger@gmx.net>              *
 *                                                                         *
 *   This file is part of the FreeCAD CAx development system.              *
 *                                                                         *
 *   This library is free software; you can redistribute it and/or         *
 *   modify it under the terms of the GNU Library General Public           *
 *   License as published by the Free Software Foundation; either          *
 *   version 2 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 Library General Public License for more details.                  *
 *                                                                         *
 *   You should have received a copy of the GNU Library General Public     *
 *   License along with this library; see the file COPYING.LIB. If not,    *
 *   write to the Free Software Foundation, Inc., 59 Temple Place,         *
 *   Suite 330, Boston, MA  02111-1307, USA                                *
 *                                                                         *
 ***************************************************************************/

#include "PreCompiled.h"
#include "ViewProviderFemPostPipeline.h"
#include "ViewProviderFemPostFunction.h"
#include <Mod/Fem/App/FemPostPipeline.h>
#include <Base/Console.h>
#include <Gui/Application.h>

using namespace FemGui;

PROPERTY_SOURCE(FemGui::ViewProviderFemPostPipeline, FemGui::ViewProviderFemPostObject)

ViewProviderFemPostPipeline::ViewProviderFemPostPipeline()
{
    sPixmap = "fem-data";
}

ViewProviderFemPostPipeline::~ViewProviderFemPostPipeline()
{
}

std::vector< App::DocumentObject* > ViewProviderFemPostPipeline::claimChildren(void) const {

    Fem::FemPostPipeline* pipeline = static_cast<Fem::FemPostPipeline*>(getObject());
    std::vector<App::DocumentObject*> children;

    if(pipeline->Functions.getValue())
        children.push_back(pipeline->Functions.getValue());

    children.insert(children.end(), pipeline->Filter.getValues().begin(), pipeline->Filter.getValues().end());
    return children;
}

std::vector< App::DocumentObject* > ViewProviderFemPostPipeline::claimChildren3D(void) const {

    return claimChildren();
}

void ViewProviderFemPostPipeline::updateData(const App::Property* prop) {
    FemGui::ViewProviderFemPostObject::onChanged(prop);

    if(strcmp(prop->getName(), "Function") == 0) {
        updateFunctionSize();
    }

}

void ViewProviderFemPostPipeline::updateFunctionSize() {

    //we need to get the bounding box and set the function provider size
    Fem::FemPostPipeline* obj = static_cast<Fem::FemPostPipeline*>(getObject());

    if(!obj->Functions.getValue() || !obj->Functions.getValue()->isDerivedFrom(Fem::FemPostFunctionProvider::getClassTypeId()))
        return;

    //get the function provider
    FemGui::ViewProviderFemPostFunctionProvider* vp = static_cast<FemGui::ViewProviderFemPostFunctionProvider*>(
                                                    Gui::Application::Instance->getViewProvider(obj->Functions.getValue()));

    if(obj->Data.getValue() && obj->Data.getValue()->IsA("vtkDataSet")) {
        vtkBoundingBox box = obj->getBoundingBox();

        vp->SizeX.setValue(box.GetLength(0)*1.2);
        vp->SizeY.setValue(box.GetLength(1)*1.2);
        vp->SizeZ.setValue(box.GetLength(2)*1.2);
    }
}
<|endoftext|>


<commit_before>#include "BasicBlock.h"

#include <iostream>

#include "preprocessor/llvm_includes_start.h"
#include <llvm/IR/CFG.h>
#include <llvm/IR/Function.h>
#include <llvm/IR/Instructions.h>
#include <llvm/IR/IRBuilder.h>
#include <llvm/Support/raw_os_ostream.h>
#include "preprocessor/llvm_includes_end.h"

#include "Type.h"
#include "Utils.h"

namespace dev
{
namespace eth
{
namespace jit
{

BasicBlock::BasicBlock(instr_idx _firstInstrIdx, code_iterator _begin, code_iterator _end, llvm::Function* _mainFunc):
	m_firstInstrIdx{_firstInstrIdx},
	m_begin(_begin),
	m_end(_end),
	m_llvmBB(llvm::BasicBlock::Create(_mainFunc->getContext(), {"Instr.", std::to_string(_firstInstrIdx)}, _mainFunc))
{}

LocalStack::LocalStack(Stack& _globalStack):
	m_global(_globalStack)
{}

void LocalStack::push(llvm::Value* _value)
{
	assert(_value->getType() == Type::Word);
	m_local.push_back(_value);
	m_maxSize = std::max(m_maxSize, size());
}

llvm::Value* LocalStack::pop()
{
	auto item = get(0);
	assert(!m_local.empty() || !m_input.empty());

	if (m_local.size() > 0)
		m_local.pop_back();
	else
		++m_globalPops;

	m_minSize = std::min(m_minSize, size());
	return item;
}

/**
 *  Pushes a copy of _index-th element (tos is 0-th elem).
 */
void LocalStack::dup(size_t _index)
{
	auto val = get(_index);
	push(val);
}

/**
 *  Swaps tos with _index-th element (tos is 0-th elem).
 *  _index must be > 0.
 */
void LocalStack::swap(size_t _index)
{
	assert(_index > 0);
	auto val = get(_index);
	auto tos = get(0);
	set(_index, tos);
	set(0, val);
}

llvm::Value* LocalStack::get(size_t _index)
{
	if (_index < m_local.size())
		return *(m_local.rbegin() + _index); // count from back

	auto idx = _index - m_local.size() + m_globalPops;
	if (idx >= m_input.size())
		m_input.resize(idx + 1);
	auto& item = m_input[idx];

	if (!item)
		item = m_global.get(idx);

	return item;
}

void LocalStack::set(size_t _index, llvm::Value* _word)
{
	if (_index < m_local.size())
	{
		*(m_local.rbegin() + _index) = _word;
		return;
	}

	auto idx = _index - m_local.size() + m_globalPops;
	assert(idx < m_input.size());
	m_input[idx] = _word;
}

void LocalStack::finalize(llvm::IRBuilder<>& _builder, llvm::BasicBlock& _bb)
{
	auto blockTerminator = _bb.getTerminator();
	assert(blockTerminator);
	if (blockTerminator->getOpcode() != llvm::Instruction::Ret)
	{
		// Not needed in case of ret instruction. Ret invalidates the stack.
		_builder.SetInsertPoint(blockTerminator);

		// Update items fetched from global stack ignoring the poped ones
		assert(m_globalPops <= m_input.size()); // pop() always does get()
		for (auto i = m_globalPops; i < m_input.size(); ++i)
		{
			if (m_input[i])
				m_global.set(i, m_input[i]);
		}

		// Add new items
		auto pops = m_globalPops;			// Copy pops counter to keep original value
		for (auto& item: m_local)
		{
			if (pops) 						// Override poped global items
				m_global.set(--pops, item);	// using pops counter as the index
			else
				m_global.push(item);
		}

		// Pop not overriden items
		if (pops)
			m_global.pop(pops);
	}
}

}
}
}
<commit_msg>Update min local stack size correctly.<commit_after>#include "BasicBlock.h"

#include <iostream>

#include "preprocessor/llvm_includes_start.h"
#include <llvm/IR/CFG.h>
#include <llvm/IR/Function.h>
#include <llvm/IR/Instructions.h>
#include <llvm/IR/IRBuilder.h>
#include <llvm/Support/raw_os_ostream.h>
#include "preprocessor/llvm_includes_end.h"

#include "Type.h"
#include "Utils.h"

namespace dev
{
namespace eth
{
namespace jit
{

BasicBlock::BasicBlock(instr_idx _firstInstrIdx, code_iterator _begin, code_iterator _end, llvm::Function* _mainFunc):
	m_firstInstrIdx{_firstInstrIdx},
	m_begin(_begin),
	m_end(_end),
	m_llvmBB(llvm::BasicBlock::Create(_mainFunc->getContext(), {"Instr.", std::to_string(_firstInstrIdx)}, _mainFunc))
{}

LocalStack::LocalStack(Stack& _globalStack):
	m_global(_globalStack)
{}

void LocalStack::push(llvm::Value* _value)
{
	assert(_value->getType() == Type::Word);
	m_local.push_back(_value);
	m_maxSize = std::max(m_maxSize, size());
}

llvm::Value* LocalStack::pop()
{
	auto item = get(0);
	assert(!m_local.empty() || !m_input.empty());

	if (m_local.size() > 0)
		m_local.pop_back();
	else
		++m_globalPops;

	m_minSize = std::min(m_minSize, size());
	return item;
}

/**
 *  Pushes a copy of _index-th element (tos is 0-th elem).
 */
void LocalStack::dup(size_t _index)
{
	auto val = get(_index);
	push(val);
}

/**
 *  Swaps tos with _index-th element (tos is 0-th elem).
 *  _index must be > 0.
 */
void LocalStack::swap(size_t _index)
{
	assert(_index > 0);
	auto val = get(_index);
	auto tos = get(0);
	set(_index, tos);
	set(0, val);
}

llvm::Value* LocalStack::get(size_t _index)
{
	if (_index < m_local.size())
		return *(m_local.rbegin() + _index); // count from back

	auto idx = _index - m_local.size() + m_globalPops;
	if (idx >= m_input.size())
		m_input.resize(idx + 1);
	auto& item = m_input[idx];

	if (!item)
	{
		item = m_global.get(idx); 											// Reach an item from global stack
		m_minSize = std::min(m_minSize, -static_cast<ssize_t>(idx) - 1); 	// and remember required stack size
	}

	return item;
}

void LocalStack::set(size_t _index, llvm::Value* _word)
{
	if (_index < m_local.size())
	{
		*(m_local.rbegin() + _index) = _word;
		return;
	}

	auto idx = _index - m_local.size() + m_globalPops;
	assert(idx < m_input.size());
	m_input[idx] = _word;
}

void LocalStack::finalize(llvm::IRBuilder<>& _builder, llvm::BasicBlock& _bb)
{
	auto blockTerminator = _bb.getTerminator();
	assert(blockTerminator);
	if (blockTerminator->getOpcode() != llvm::Instruction::Ret)
	{
		// Not needed in case of ret instruction. Ret invalidates the stack.
		_builder.SetInsertPoint(blockTerminator);

		// Update items fetched from global stack ignoring the poped ones
		assert(m_globalPops <= m_input.size()); // pop() always does get()
		for (auto i = m_globalPops; i < m_input.size(); ++i)
		{
			if (m_input[i])
				m_global.set(i, m_input[i]);
		}

		// Add new items
		auto pops = m_globalPops;			// Copy pops counter to keep original value
		for (auto& item: m_local)
		{
			if (pops) 						// Override poped global items
				m_global.set(--pops, item);	// using pops counter as the index
			else
				m_global.push(item);
		}

		// Pop not overriden items
		if (pops)
			m_global.pop(pops);
	}
}

}
}
}
<|endoftext|>


<commit_before>/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
 *
 *  Libmemcached library
 *
 *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
 *  Copyright (C) 2006-2009 Brian Aker All rights reserved.
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions are
 *  met:
 *
 *      * Redistributions of source code must retain the above copyright
 *  notice, this list of conditions and the following disclaimer.
 *
 *      * Redistributions in binary form must reproduce the above
 *  copyright notice, this list of conditions and the following disclaimer
 *  in the documentation and/or other materials provided with the
 *  distribution.
 *
 *      * The names of its contributors may not be used to endorse or
 *  promote products derived from this software without specific prior
 *  written permission.
 *
 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 */

#include <libmemcached/common.h>

static inline void _server_init(org::libmemcached::Instance* self, memcached_st *root,
                                const memcached_string_t& hostname,
                                in_port_t port,
                                uint32_t weight, memcached_connection_t type)
{
  self->options.is_shutting_down= false;
  self->options.is_dead= false;
  self->cursor_active_= 0;
  self->port_= port;
  self->fd= INVALID_SOCKET;
  self->io_bytes_sent= 0;
  self->request_id= 0;
  self->server_failure_counter= 0;
  self->server_failure_counter_query_id= 0;
  self->weight= weight ? weight : 1; // 1 is the default weight value
  self->io_wait_count.read= 0;
  self->io_wait_count.write= 0;
  self->io_wait_count.timeouts= 0;
  self->io_wait_count._bytes_read= 0;
  self->major_version= UINT8_MAX;
  self->micro_version= UINT8_MAX;
  self->minor_version= UINT8_MAX;
  self->type= type;
  self->error_messages= NULL;
  self->read_ptr= self->read_buffer;
  self->read_buffer_length= 0;
  self->read_data_length= 0;
  self->write_buffer_offset= 0;
  self->address_info= NULL;
  self->address_info_next= NULL;

  self->state= MEMCACHED_SERVER_STATE_NEW;
  self->next_retry= 0;

  self->root= root;
  if (root)
  {
    self->version= ++root->server_info.version;
  }
  else
  {
    self->version= UINT_MAX;
  }
  self->limit_maxbytes= 0;
  memcpy(self->hostname, hostname.c_str, hostname.size);
  self->hostname[hostname.size]= 0;
}

static org::libmemcached::Instance* _server_create(org::libmemcached::Instance* self, const memcached_st *memc)
{
  if (self == NULL)
  {
   self= libmemcached_xmalloc(memc, org::libmemcached::Instance);

    if (self == NULL)
    {
      return NULL; /*  MEMCACHED_MEMORY_ALLOCATION_FAILURE */
    }

    self->options.is_allocated= true;
  }
  else
  {
    self->options.is_allocated= false;
  }

  self->options.is_initialized= true;

  return self;
}

org::libmemcached::Instance* __instance_create_with(memcached_st *memc,
                                                    org::libmemcached::Instance* self,
                                                    const memcached_string_t& hostname,
                                                    const in_port_t port,
                                                    uint32_t weight,
                                                    const memcached_connection_t type)
{
  if (memcached_is_valid_servername(hostname) == false)
  {
    memcached_set_error(*memc, MEMCACHED_INVALID_ARGUMENTS, MEMCACHED_AT, memcached_literal_param("Invalid hostname provided"));
    return NULL;
  }

  self= _server_create(self, memc);

  if (self == NULL)
  {
    return NULL;
  }

  _server_init(self, const_cast<memcached_st *>(memc), hostname, port, weight, type);

  if (memc and memcached_is_udp(memc))
  {
    self->write_buffer_offset= UDP_DATAGRAM_HEADER_LENGTH;
    memcached_io_init_udp_header(self, 0);
  }

  if (memc)
  {
    memcached_connect_try(self);
  }

  return self;
}

void __instance_free(org::libmemcached::Instance* self)
{
  memcached_quit_server(self, false);

  if (self->address_info)
  {
    freeaddrinfo(self->address_info);
    self->address_info= NULL;
    self->address_info_next= NULL;
  }
  assert(self->address_info_next == NULL);

  memcached_error_free(*self);

  if (memcached_is_allocated(self))
  {
    libmemcached_free(self->root, self);
  }
  else
  {
    self->options.is_initialized= false;
  }
}

void memcached_instance_free(org::libmemcached::Instance* self)
{
  if (self)
  {
    __instance_free(self);
  }
}

memcached_return_t memcached_server_cursor(const memcached_st *ptr,
                                           const memcached_server_fn *callback,
                                           void *context,
                                           uint32_t number_of_callbacks)
{
  memcached_return_t rc;
  if (memcached_failed(rc= initialize_const_query(ptr)))
  {
    return rc;
  }

  size_t errors= 0;
  for (uint32_t x= 0; x < memcached_instance_list_count(ptr); x++)
  {
    org::libmemcached::Instance* instance= memcached_instance_by_position(ptr, x);

    for (uint32_t y= 0; y < number_of_callbacks; y++)
    {
      memcached_return_t ret= (*callback[y])(ptr, instance, context);

      if (memcached_failed(ret))
      {
        errors++;
        continue;
      }
    }
  }

  return errors ? MEMCACHED_SOME_ERRORS : MEMCACHED_SUCCESS;
}

memcached_return_t memcached_server_execute(memcached_st *ptr,
                                            memcached_server_execute_fn callback,
                                            void *context)
{
  if (callback == NULL)
  {
    return MEMCACHED_INVALID_ARGUMENTS;
  }

  bool some_errors= false;;
  for (uint32_t x= 0; x < memcached_instance_list_count(ptr); x++)
  {
    org::libmemcached::Instance* instance= memcached_instance_fetch(ptr, x);

    memcached_return_t rc= (*callback)(ptr, instance, context);
    if (rc == MEMCACHED_INVALID_ARGUMENTS)
    {
      return rc;
    }
    else if (memcached_fatal(rc))
    {
      some_errors= true;
    }
  }

  (void)some_errors;
  return MEMCACHED_SUCCESS;
}

memcached_server_instance_st memcached_server_by_key(memcached_st *ptr,
                                                     const char *key,
                                                     size_t key_length,
                                                     memcached_return_t *error)
{
  memcached_return_t unused;
  if (error == NULL)
  {
    error= &unused;
  }

  memcached_return_t rc;
  if (memcached_failed(rc= initialize_const_query(ptr)))
  {
    *error= rc;
    return NULL;
  }

  if (memcached_failed((memcached_key_test(*ptr, (const char **)&key, &key_length, 1))))
  {
    *error= memcached_last_error(ptr);
    return NULL;
  }

  uint32_t server_key= memcached_generate_hash(ptr, key, key_length);
  return memcached_instance_by_position(ptr, server_key);
}

/*
  If we do not have a valid object to clone from, we toss an error.
*/
static org::libmemcached::Instance* memcached_instance_clone(org::libmemcached::Instance* source)
{
  /* We just do a normal create if source is missing */
  if (source == NULL)
  {
    return NULL;
  }

  memcached_string_t hostname= { memcached_string_make_from_cstr(source->hostname) };
  return __instance_create_with(source->root,
                                NULL,
                                hostname,
                                source->port(), source->weight,
                                source->type);
}

void set_last_disconnected_host(org::libmemcached::Instance* self)
{
  assert(self->root);
  if (self->root)
  {
    if (memcached_server_get_last_disconnect(self->root) and
        memcached_server_get_last_disconnect(self->root)->version == self->version)
    {
      return;
    }

    // const_cast
    memcached_st *root= (memcached_st *)self->root;

    memcached_instance_free((org::libmemcached::Instance*)(root->last_disconnected_server));

    // We set is_parsing so that no lookup happens
    root->state.is_parsing= true;
    root->last_disconnected_server= memcached_instance_clone(self);
    root->state.is_parsing= false;

    ((org::libmemcached::Instance*)memcached_server_get_last_disconnect(root))->version= self->version;
  }
}

memcached_server_instance_st memcached_server_get_last_disconnect(const memcached_st *self)
{
  WATCHPOINT_ASSERT(self);
  if (self == NULL)
  {
    return 0;
  }

  return (memcached_server_instance_st)self->last_disconnected_server;
}

void memcached_instance_next_retry(memcached_server_instance_st self, const time_t absolute_time)
{
  WATCHPOINT_ASSERT(self);
  if (self)
  {
    ((org::libmemcached::Instance*)self)->next_retry= absolute_time;
  }
}
<commit_msg>Fix style issue<commit_after>/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
 *
 *  Libmemcached library
 *
 *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
 *  Copyright (C) 2006-2009 Brian Aker All rights reserved.
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions are
 *  met:
 *
 *      * Redistributions of source code must retain the above copyright
 *  notice, this list of conditions and the following disclaimer.
 *
 *      * Redistributions in binary form must reproduce the above
 *  copyright notice, this list of conditions and the following disclaimer
 *  in the documentation and/or other materials provided with the
 *  distribution.
 *
 *      * The names of its contributors may not be used to endorse or
 *  promote products derived from this software without specific prior
 *  written permission.
 *
 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 */

#include <libmemcached/common.h>

static inline void _server_init(org::libmemcached::Instance* self, memcached_st *root,
                                const memcached_string_t& hostname,
                                in_port_t port,
                                uint32_t weight, memcached_connection_t type)
{
  self->options.is_shutting_down= false;
  self->options.is_dead= false;
  self->cursor_active_= 0;
  self->port_= port;
  self->fd= INVALID_SOCKET;
  self->io_bytes_sent= 0;
  self->request_id= 0;
  self->server_failure_counter= 0;
  self->server_failure_counter_query_id= 0;
  self->weight= weight ? weight : 1; // 1 is the default weight value
  self->io_wait_count.read= 0;
  self->io_wait_count.write= 0;
  self->io_wait_count.timeouts= 0;
  self->io_wait_count._bytes_read= 0;
  self->major_version= UINT8_MAX;
  self->micro_version= UINT8_MAX;
  self->minor_version= UINT8_MAX;
  self->type= type;
  self->error_messages= NULL;
  self->read_ptr= self->read_buffer;
  self->read_buffer_length= 0;
  self->read_data_length= 0;
  self->write_buffer_offset= 0;
  self->address_info= NULL;
  self->address_info_next= NULL;

  self->state= MEMCACHED_SERVER_STATE_NEW;
  self->next_retry= 0;

  self->root= root;
  if (root)
  {
    self->version= ++root->server_info.version;
  }
  else
  {
    self->version= UINT_MAX;
  }
  self->limit_maxbytes= 0;
  memcpy(self->hostname, hostname.c_str, hostname.size);
  self->hostname[hostname.size]= 0;
}

static org::libmemcached::Instance* _server_create(org::libmemcached::Instance* self, const memcached_st *memc)
{
  if (self == NULL)
  {
   self= libmemcached_xmalloc(memc, org::libmemcached::Instance);

    if (self == NULL)
    {
      return NULL; /*  MEMCACHED_MEMORY_ALLOCATION_FAILURE */
    }

    self->options.is_allocated= true;
  }
  else
  {
    self->options.is_allocated= false;
  }

  self->options.is_initialized= true;

  return self;
}

org::libmemcached::Instance* __instance_create_with(memcached_st *memc,
                                                    org::libmemcached::Instance* self,
                                                    const memcached_string_t& hostname,
                                                    const in_port_t port,
                                                    uint32_t weight,
                                                    const memcached_connection_t type)
{
  if (memcached_is_valid_servername(hostname) == false)
  {
    memcached_set_error(*memc, MEMCACHED_INVALID_ARGUMENTS, MEMCACHED_AT, memcached_literal_param("Invalid hostname provided"));
    return NULL;
  }

  self= _server_create(self, memc);

  if (self == NULL)
  {
    return NULL;
  }

  _server_init(self, const_cast<memcached_st *>(memc), hostname, port, weight, type);

  if (memc and memcached_is_udp(memc))
  {
    self->write_buffer_offset= UDP_DATAGRAM_HEADER_LENGTH;
    memcached_io_init_udp_header(self, 0);
  }

  if (memc)
  {
    memcached_connect_try(self);
  }

  return self;
}

void __instance_free(org::libmemcached::Instance* self)
{
  memcached_quit_server(self, false);

  if (self->address_info)
  {
    freeaddrinfo(self->address_info);
    self->address_info= NULL;
    self->address_info_next= NULL;
  }
  assert(self->address_info_next == NULL);

  memcached_error_free(*self);

  if (memcached_is_allocated(self))
  {
    libmemcached_free(self->root, self);
  }
  else
  {
    self->options.is_initialized= false;
  }
}

void memcached_instance_free(org::libmemcached::Instance* self)
{
  if (self)
  {
    __instance_free(self);
  }
}

memcached_return_t memcached_server_cursor(const memcached_st* memc,
                                           const memcached_server_fn *callback,
                                           void *context,
                                           uint32_t number_of_callbacks)
{
  memcached_return_t rc;
  if (memcached_failed(rc= initialize_const_query(memc)))
  {
    return rc;
  }

  size_t errors= 0;
  for (uint32_t x= 0; x < memcached_instance_list_count(memc); x++)
  {
    org::libmemcached::Instance* instance= memcached_instance_by_position(memc, x);

    for (uint32_t y= 0; y < number_of_callbacks; y++)
    {
      memcached_return_t ret= (*callback[y])(memc, instance, context);

      if (memcached_failed(ret))
      {
        errors++;
        continue;
      }
    }
  }

  return errors ? MEMCACHED_SOME_ERRORS : MEMCACHED_SUCCESS;
}

memcached_return_t memcached_server_execute(memcached_st *memc,
                                            memcached_server_execute_fn callback,
                                            void *context)
{
  if (callback == NULL)
  {
    return MEMCACHED_INVALID_ARGUMENTS;
  }

  bool some_errors= false;;
  for (uint32_t x= 0; x < memcached_instance_list_count(memc); x++)
  {
    org::libmemcached::Instance* instance= memcached_instance_fetch(memc, x);

    memcached_return_t rc= (*callback)(memc, instance, context);
    if (rc == MEMCACHED_INVALID_ARGUMENTS)
    {
      return rc;
    }
    else if (memcached_fatal(rc))
    {
      some_errors= true;
    }
  }

  (void)some_errors;
  return MEMCACHED_SUCCESS;
}

memcached_server_instance_st memcached_server_by_key(memcached_st *memc,
                                                     const char *key,
                                                     size_t key_length,
                                                     memcached_return_t *error)
{
  memcached_return_t unused;
  if (error == NULL)
  {
    error= &unused;
  }

  memcached_return_t rc;
  if (memcached_failed(rc= initialize_const_query(memc)))
  {
    *error= rc;
    return NULL;
  }

  if (memcached_failed((memcached_key_test(*memc, (const char **)&key, &key_length, 1))))
  {
    *error= memcached_last_error(memc);
    return NULL;
  }

  uint32_t server_key= memcached_generate_hash(memc, key, key_length);
  return memcached_instance_by_position(memc, server_key);
}

/*
  If we do not have a valid object to clone from, we toss an error.
*/
static org::libmemcached::Instance* memcached_instance_clone(org::libmemcached::Instance* source)
{
  /* We just do a normal create if source is missing */
  if (source == NULL)
  {
    return NULL;
  }

  memcached_string_t hostname= { memcached_string_make_from_cstr(source->hostname) };
  return __instance_create_with(source->root,
                                NULL,
                                hostname,
                                source->port(), source->weight,
                                source->type);
}

void set_last_disconnected_host(org::libmemcached::Instance* self)
{
  assert(self->root);
  if (self->root)
  {
    if (memcached_server_get_last_disconnect(self->root) and
        memcached_server_get_last_disconnect(self->root)->version == self->version)
    {
      return;
    }

    // const_cast
    memcached_st *root= (memcached_st *)self->root;

    memcached_instance_free((org::libmemcached::Instance*)(root->last_disconnected_server));

    // We set is_parsing so that no lookup happens
    root->state.is_parsing= true;
    root->last_disconnected_server= memcached_instance_clone(self);
    root->state.is_parsing= false;

    ((org::libmemcached::Instance*)memcached_server_get_last_disconnect(root))->version= self->version;
  }
}

memcached_server_instance_st memcached_server_get_last_disconnect(const memcached_st *self)
{
  WATCHPOINT_ASSERT(self);
  if (self == NULL)
  {
    return 0;
  }

  return (memcached_server_instance_st)self->last_disconnected_server;
}

void memcached_instance_next_retry(memcached_server_instance_st self, const time_t absolute_time)
{
  WATCHPOINT_ASSERT(self);
  if (self)
  {
    ((org::libmemcached::Instance*)self)->next_retry= absolute_time;
  }
}
<|endoftext|>


<commit_before>/*
 This file is part of cpp-ethereum.

 cpp-ethereum is free software: you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
 the Free Software Foundation, either version 3 of the License, or
 (at your option) any later version.

 cpp-ethereum 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 cpp-ethereum.  If not, see <http://www.gnu.org/licenses/>.
 */
/** @file RLPXHandshake.cpp
 * @author Alex Leverington <nessence@gmail.com>
 * @date 2015
 */

#include "Host.h"
#include "Session.h"
#include "Peer.h"
#include "RLPxHandshake.h"
using namespace std;
using namespace dev;
using namespace dev::p2p;
using namespace CryptoPP;

void RLPXHandshake::writeAuth()
{
	clog(NetConnect) << "p2p.connect.egress sending auth to " << m_socket->remoteEndpoint();
	m_auth.resize(Signature::size + h256::size + Public::size + h256::size + 1);
	bytesRef sig(&m_auth[0], Signature::size);
	bytesRef hepubk(&m_auth[Signature::size], h256::size);
	bytesRef pubk(&m_auth[Signature::size + h256::size], Public::size);
	bytesRef nonce(&m_auth[Signature::size + h256::size + Public::size], h256::size);

	// E(remote-pubk, S(ecdhe-random, ecdh-shared-secret^nonce) || H(ecdhe-random-pubk) || pubk || nonce || 0x0)
	Secret staticShared;
	crypto::ecdh::agree(m_host->m_alias.sec(), m_remote, staticShared);
	sign(m_ecdhe.seckey(), staticShared ^ m_nonce).ref().copyTo(sig);
	sha3(m_ecdhe.pubkey().ref(), hepubk);
	m_host->m_alias.pub().ref().copyTo(pubk);
	m_nonce.ref().copyTo(nonce);
	m_auth[m_auth.size() - 1] = 0x0;
	encryptECIES(m_remote, &m_auth, m_authCipher);

	auto self(shared_from_this());
	ba::async_write(m_socket->ref(), ba::buffer(m_authCipher), [this, self](boost::system::error_code ec, std::size_t)
	{
		transition(ec);
	});
}

void RLPXHandshake::writeAck()
{
	clog(NetConnect) << "p2p.connect.ingress sending ack to " << m_socket->remoteEndpoint();
	m_ack.resize(Public::size + h256::size + 1);
	bytesRef epubk(&m_ack[0], Public::size);
	bytesRef nonce(&m_ack[Public::size], h256::size);
	m_ecdhe.pubkey().ref().copyTo(epubk);
	m_nonce.ref().copyTo(nonce);
	m_ack[m_ack.size() - 1] = 0x0;
	encryptECIES(m_remote, &m_ack, m_ackCipher);

	auto self(shared_from_this());
	ba::async_write(m_socket->ref(), ba::buffer(m_ackCipher), [this, self](boost::system::error_code ec, std::size_t)
	{
		transition(ec);
	});
}

void RLPXHandshake::readAuth()
{
	clog(NetConnect) << "p2p.connect.ingress recving auth from " << m_socket->remoteEndpoint();
	m_authCipher.resize(307);
	auto self(shared_from_this());
	ba::async_read(m_socket->ref(), ba::buffer(m_authCipher, 307), [this, self](boost::system::error_code ec, std::size_t)
	{
		if (ec)
			transition(ec);
		else if (decryptECIES(m_host->m_alias.sec(), bytesConstRef(&m_authCipher), m_auth))
		{
			bytesConstRef sig(&m_auth[0], Signature::size);
			bytesConstRef hepubk(&m_auth[Signature::size], h256::size);
			bytesConstRef pubk(&m_auth[Signature::size + h256::size], Public::size);
			bytesConstRef nonce(&m_auth[Signature::size + h256::size + Public::size], h256::size);
			pubk.copyTo(m_remote.ref());
			nonce.copyTo(m_remoteNonce.ref());

			Secret sharedSecret;
			crypto::ecdh::agree(m_host->m_alias.sec(), m_remote, sharedSecret);
			m_remoteEphemeral = recover(*(Signature*)sig.data(), sharedSecret ^ m_remoteNonce);

			if (sha3(m_remoteEphemeral) != *(h256*)hepubk.data())
			{
				clog(NetConnect) << "p2p.connect.ingress auth failed (invalid: hash mismatch) for" << m_socket->remoteEndpoint();
				m_nextState = Error;
			}

			transition();
		}
		else
		{
			clog(NetConnect) << "p2p.connect.ingress recving auth decrypt failed for" << m_socket->remoteEndpoint();
			m_nextState = Error;
			transition();
		}
	});
}

void RLPXHandshake::readAck()
{
	clog(NetConnect) << "p2p.connect.egress recving ack from " << m_socket->remoteEndpoint();
	m_ackCipher.resize(210);
	auto self(shared_from_this());
	ba::async_read(m_socket->ref(), ba::buffer(m_ackCipher, 210), [this, self](boost::system::error_code ec, std::size_t)
	{
		if (ec)
			transition(ec);
		else if (decryptECIES(m_host->m_alias.sec(), bytesConstRef(&m_ackCipher), m_ack))
		{
			bytesConstRef(&m_ack).cropped(0, Public::size).copyTo(m_remoteEphemeral.ref());
			bytesConstRef(&m_ack).cropped(Public::size, h256::size).copyTo(m_remoteNonce.ref());
			transition();
		}
		else
		{
			clog(NetConnect) << "p2p.connect.egress recving ack decrypt failed for " << m_socket->remoteEndpoint();
			m_nextState = Error;
			transition();
		}
	});
}

void RLPXHandshake::error()
{
	m_idleTimer.cancel();

	auto connected = m_socket->isConnected();
	if (connected && !m_socket->remoteEndpoint().address().is_unspecified())
		clog(NetConnect) << "Disconnecting " << m_socket->remoteEndpoint() << " (Handshake Failed)";
	else
		clog(NetConnect) << "Handshake Failed (Connection reset by peer)";

	m_socket->close();
	if (m_io != nullptr)
		delete m_io;
}

void RLPXHandshake::transition(boost::system::error_code _ech)
{
	if (_ech || m_nextState == Error || m_cancel)
	{
		clog(NetConnect) << "Handshake Failed (I/O Error:" << _ech.message() << ")";
		return error();
	}

	auto self(shared_from_this());
	if (m_nextState == New)
	{
		m_nextState = AckAuth;
		if (m_originated)
			writeAuth();
		else
			readAuth();
	}
	else if (m_nextState == AckAuth)
	{
		m_nextState = WriteHello;
		if (m_originated)
			readAck();
		else
			writeAck();
	}
	else if (m_nextState == WriteHello)
	{
		m_nextState = ReadHello;
		clog(NetConnect) << (m_originated ? "p2p.connect.egress" : "p2p.connect.ingress") << "sending capabilities handshake";

		/// This pointer will be freed if there is an error otherwise
		/// it will be passed to Host which will take ownership.
		m_io = new RLPXFrameIO(*this);

		// old packet format
		// 5 arguments, HelloPacket
		RLPStream s;
		s.append((unsigned)0).appendList(5)
		<< dev::p2p::c_protocolVersion
		<< m_host->m_clientVersion
		<< m_host->caps()
		<< m_host->listenPort()
		<< m_host->id();
		bytes packet;
		s.swapOut(packet);
		m_io->writeSingleFramePacket(&packet, m_handshakeOutBuffer);
		ba::async_write(m_socket->ref(), ba::buffer(m_handshakeOutBuffer), [this, self](boost::system::error_code ec, std::size_t)
		{
			transition(ec);
		});
	}
	else if (m_nextState == ReadHello)
	{
		// Authenticate and decrypt initial hello frame with initial RLPXFrameIO
		// and request m_host to start session.
		m_nextState = StartSession;

		// read frame header
		m_handshakeInBuffer.resize(h256::size);
		ba::async_read(m_socket->ref(), boost::asio::buffer(m_handshakeInBuffer, h256::size), [this, self](boost::system::error_code ec, std::size_t)
		{
			if (ec)
				transition(ec);
			else
			{
				/// authenticate and decrypt header
				if (!m_io->authAndDecryptHeader(bytesRef(m_handshakeInBuffer.data(), h256::size)))
				{
					m_nextState = Error;
					transition();
					return;
				}

				clog(NetNote) << (m_originated ? "p2p.connect.egress" : "p2p.connect.ingress") << "recvd hello header";

				/// check frame size
				bytes& header = m_handshakeInBuffer;
				uint32_t frameSize = (uint32_t)(header[2]) | (uint32_t)(header[1])<<8 | (uint32_t)(header[0])<<16;
				if (frameSize > 1024)
				{
					// all future frames: 16777216
					clog(NetWarn) << (m_originated ? "p2p.connect.egress" : "p2p.connect.ingress") << "hello frame is too large" << frameSize;
					m_nextState = Error;
					transition();
					return;
				}

				/// rlp of header has protocol-type, sequence-id[, total-packet-size]
				bytes headerRLP(header.size() - 3 - h128::size);
				bytesConstRef(&header).cropped(3).copyTo(&headerRLP);

				/// read padded frame and mac
				m_handshakeInBuffer.resize(frameSize + ((16 - (frameSize % 16)) % 16) + h128::size);
				ba::async_read(m_socket->ref(), boost::asio::buffer(m_handshakeInBuffer, m_handshakeInBuffer.size()), [this, self, headerRLP](boost::system::error_code ec, std::size_t)
				{
					if (ec)
						transition(ec);
					else
					{
						bytesRef frame(&m_handshakeInBuffer);
						if (!m_io->authAndDecryptFrame(frame))
						{
							clog(NetWarn) << (m_originated ? "p2p.connect.egress" : "p2p.connect.ingress") << "hello frame: decrypt failed";
							m_nextState = Error;
							transition();
							return;
						}

						PacketType packetType = (PacketType)(frame[0] == 0x80 ? 0x0 : frame[0]);
						if (packetType != 0)
						{
							clog(NetWarn) << (m_originated ? "p2p.connect.egress" : "p2p.connect.ingress") << "hello frame: invalid packet type";
							m_nextState = Error;
							transition();
							return;
						}

						clog(NetNote) << (m_originated ? "p2p.connect.egress" : "p2p.connect.ingress") << "hello frame: success. starting session.";
						RLP rlp(frame.cropped(1), RLP::ThrowOnFail | RLP::FailIfTooSmall);
						m_host->startPeerSession(m_remote, rlp, m_io, m_socket->remoteEndpoint());
					}
				});
			}
		});
	}

	m_idleTimer.expires_from_now(c_timeout);
	m_idleTimer.async_wait([this, self](boost::system::error_code const& _ec)
	{
		if (!_ec)
		{
			if (!m_socket->remoteEndpoint().address().is_unspecified())
				clog(NetWarn) << "Disconnecting " << m_socket->remoteEndpoint() << " (Handshake Timeout)";
			cancel();
		}
	});
}
<commit_msg>defer failure when H of pubk doesn't match (reverts back to release functionality where assert() is skipped)<commit_after>/*
 This file is part of cpp-ethereum.

 cpp-ethereum is free software: you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
 the Free Software Foundation, either version 3 of the License, or
 (at your option) any later version.

 cpp-ethereum 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 cpp-ethereum.  If not, see <http://www.gnu.org/licenses/>.
 */
/** @file RLPXHandshake.cpp
 * @author Alex Leverington <nessence@gmail.com>
 * @date 2015
 */

#include "Host.h"
#include "Session.h"
#include "Peer.h"
#include "RLPxHandshake.h"
using namespace std;
using namespace dev;
using namespace dev::p2p;
using namespace CryptoPP;

void RLPXHandshake::writeAuth()
{
	clog(NetConnect) << "p2p.connect.egress sending auth to " << m_socket->remoteEndpoint();
	m_auth.resize(Signature::size + h256::size + Public::size + h256::size + 1);
	bytesRef sig(&m_auth[0], Signature::size);
	bytesRef hepubk(&m_auth[Signature::size], h256::size);
	bytesRef pubk(&m_auth[Signature::size + h256::size], Public::size);
	bytesRef nonce(&m_auth[Signature::size + h256::size + Public::size], h256::size);

	// E(remote-pubk, S(ecdhe-random, ecdh-shared-secret^nonce) || H(ecdhe-random-pubk) || pubk || nonce || 0x0)
	Secret staticShared;
	crypto::ecdh::agree(m_host->m_alias.sec(), m_remote, staticShared);
	sign(m_ecdhe.seckey(), staticShared ^ m_nonce).ref().copyTo(sig);
	sha3(m_ecdhe.pubkey().ref(), hepubk);
	m_host->m_alias.pub().ref().copyTo(pubk);
	m_nonce.ref().copyTo(nonce);
	m_auth[m_auth.size() - 1] = 0x0;
	encryptECIES(m_remote, &m_auth, m_authCipher);

	auto self(shared_from_this());
	ba::async_write(m_socket->ref(), ba::buffer(m_authCipher), [this, self](boost::system::error_code ec, std::size_t)
	{
		transition(ec);
	});
}

void RLPXHandshake::writeAck()
{
	clog(NetConnect) << "p2p.connect.ingress sending ack to " << m_socket->remoteEndpoint();
	m_ack.resize(Public::size + h256::size + 1);
	bytesRef epubk(&m_ack[0], Public::size);
	bytesRef nonce(&m_ack[Public::size], h256::size);
	m_ecdhe.pubkey().ref().copyTo(epubk);
	m_nonce.ref().copyTo(nonce);
	m_ack[m_ack.size() - 1] = 0x0;
	encryptECIES(m_remote, &m_ack, m_ackCipher);

	auto self(shared_from_this());
	ba::async_write(m_socket->ref(), ba::buffer(m_ackCipher), [this, self](boost::system::error_code ec, std::size_t)
	{
		transition(ec);
	});
}

void RLPXHandshake::readAuth()
{
	clog(NetConnect) << "p2p.connect.ingress recving auth from " << m_socket->remoteEndpoint();
	m_authCipher.resize(307);
	auto self(shared_from_this());
	ba::async_read(m_socket->ref(), ba::buffer(m_authCipher, 307), [this, self](boost::system::error_code ec, std::size_t)
	{
		if (ec)
			transition(ec);
		else if (decryptECIES(m_host->m_alias.sec(), bytesConstRef(&m_authCipher), m_auth))
		{
			bytesConstRef sig(&m_auth[0], Signature::size);
			bytesConstRef hepubk(&m_auth[Signature::size], h256::size);
			bytesConstRef pubk(&m_auth[Signature::size + h256::size], Public::size);
			bytesConstRef nonce(&m_auth[Signature::size + h256::size + Public::size], h256::size);
			pubk.copyTo(m_remote.ref());
			nonce.copyTo(m_remoteNonce.ref());

			Secret sharedSecret;
			crypto::ecdh::agree(m_host->m_alias.sec(), m_remote, sharedSecret);
			m_remoteEphemeral = recover(*(Signature*)sig.data(), sharedSecret ^ m_remoteNonce);

			if (sha3(m_remoteEphemeral) != *(h256*)hepubk.data())
				clog(NetConnect) << "p2p.connect.ingress auth failed (invalid: hash mismatch) for" << m_socket->remoteEndpoint();

			transition();
		}
		else
		{
			clog(NetConnect) << "p2p.connect.ingress recving auth decrypt failed for" << m_socket->remoteEndpoint();
			m_nextState = Error;
			transition();
		}
	});
}

void RLPXHandshake::readAck()
{
	clog(NetConnect) << "p2p.connect.egress recving ack from " << m_socket->remoteEndpoint();
	m_ackCipher.resize(210);
	auto self(shared_from_this());
	ba::async_read(m_socket->ref(), ba::buffer(m_ackCipher, 210), [this, self](boost::system::error_code ec, std::size_t)
	{
		if (ec)
			transition(ec);
		else if (decryptECIES(m_host->m_alias.sec(), bytesConstRef(&m_ackCipher), m_ack))
		{
			bytesConstRef(&m_ack).cropped(0, Public::size).copyTo(m_remoteEphemeral.ref());
			bytesConstRef(&m_ack).cropped(Public::size, h256::size).copyTo(m_remoteNonce.ref());
			transition();
		}
		else
		{
			clog(NetConnect) << "p2p.connect.egress recving ack decrypt failed for " << m_socket->remoteEndpoint();
			m_nextState = Error;
			transition();
		}
	});
}

void RLPXHandshake::error()
{
	m_idleTimer.cancel();

	auto connected = m_socket->isConnected();
	if (connected && !m_socket->remoteEndpoint().address().is_unspecified())
		clog(NetConnect) << "Disconnecting " << m_socket->remoteEndpoint() << " (Handshake Failed)";
	else
		clog(NetConnect) << "Handshake Failed (Connection reset by peer)";

	m_socket->close();
	if (m_io != nullptr)
		delete m_io;
}

void RLPXHandshake::transition(boost::system::error_code _ech)
{
	if (_ech || m_nextState == Error || m_cancel)
	{
		clog(NetConnect) << "Handshake Failed (I/O Error:" << _ech.message() << ")";
		return error();
	}

	auto self(shared_from_this());
	if (m_nextState == New)
	{
		m_nextState = AckAuth;
		if (m_originated)
			writeAuth();
		else
			readAuth();
	}
	else if (m_nextState == AckAuth)
	{
		m_nextState = WriteHello;
		if (m_originated)
			readAck();
		else
			writeAck();
	}
	else if (m_nextState == WriteHello)
	{
		m_nextState = ReadHello;
		clog(NetConnect) << (m_originated ? "p2p.connect.egress" : "p2p.connect.ingress") << "sending capabilities handshake";

		/// This pointer will be freed if there is an error otherwise
		/// it will be passed to Host which will take ownership.
		m_io = new RLPXFrameIO(*this);

		// old packet format
		// 5 arguments, HelloPacket
		RLPStream s;
		s.append((unsigned)0).appendList(5)
		<< dev::p2p::c_protocolVersion
		<< m_host->m_clientVersion
		<< m_host->caps()
		<< m_host->listenPort()
		<< m_host->id();
		bytes packet;
		s.swapOut(packet);
		m_io->writeSingleFramePacket(&packet, m_handshakeOutBuffer);
		ba::async_write(m_socket->ref(), ba::buffer(m_handshakeOutBuffer), [this, self](boost::system::error_code ec, std::size_t)
		{
			transition(ec);
		});
	}
	else if (m_nextState == ReadHello)
	{
		// Authenticate and decrypt initial hello frame with initial RLPXFrameIO
		// and request m_host to start session.
		m_nextState = StartSession;

		// read frame header
		m_handshakeInBuffer.resize(h256::size);
		ba::async_read(m_socket->ref(), boost::asio::buffer(m_handshakeInBuffer, h256::size), [this, self](boost::system::error_code ec, std::size_t)
		{
			if (ec)
				transition(ec);
			else
			{
				/// authenticate and decrypt header
				if (!m_io->authAndDecryptHeader(bytesRef(m_handshakeInBuffer.data(), h256::size)))
				{
					m_nextState = Error;
					transition();
					return;
				}

				clog(NetNote) << (m_originated ? "p2p.connect.egress" : "p2p.connect.ingress") << "recvd hello header";

				/// check frame size
				bytes& header = m_handshakeInBuffer;
				uint32_t frameSize = (uint32_t)(header[2]) | (uint32_t)(header[1])<<8 | (uint32_t)(header[0])<<16;
				if (frameSize > 1024)
				{
					// all future frames: 16777216
					clog(NetWarn) << (m_originated ? "p2p.connect.egress" : "p2p.connect.ingress") << "hello frame is too large" << frameSize;
					m_nextState = Error;
					transition();
					return;
				}

				/// rlp of header has protocol-type, sequence-id[, total-packet-size]
				bytes headerRLP(header.size() - 3 - h128::size);
				bytesConstRef(&header).cropped(3).copyTo(&headerRLP);

				/// read padded frame and mac
				m_handshakeInBuffer.resize(frameSize + ((16 - (frameSize % 16)) % 16) + h128::size);
				ba::async_read(m_socket->ref(), boost::asio::buffer(m_handshakeInBuffer, m_handshakeInBuffer.size()), [this, self, headerRLP](boost::system::error_code ec, std::size_t)
				{
					if (ec)
						transition(ec);
					else
					{
						bytesRef frame(&m_handshakeInBuffer);
						if (!m_io->authAndDecryptFrame(frame))
						{
							clog(NetWarn) << (m_originated ? "p2p.connect.egress" : "p2p.connect.ingress") << "hello frame: decrypt failed";
							m_nextState = Error;
							transition();
							return;
						}

						PacketType packetType = (PacketType)(frame[0] == 0x80 ? 0x0 : frame[0]);
						if (packetType != 0)
						{
							clog(NetWarn) << (m_originated ? "p2p.connect.egress" : "p2p.connect.ingress") << "hello frame: invalid packet type";
							m_nextState = Error;
							transition();
							return;
						}

						clog(NetNote) << (m_originated ? "p2p.connect.egress" : "p2p.connect.ingress") << "hello frame: success. starting session.";
						RLP rlp(frame.cropped(1), RLP::ThrowOnFail | RLP::FailIfTooSmall);
						m_host->startPeerSession(m_remote, rlp, m_io, m_socket->remoteEndpoint());
					}
				});
			}
		});
	}

	m_idleTimer.expires_from_now(c_timeout);
	m_idleTimer.async_wait([this, self](boost::system::error_code const& _ec)
	{
		if (!_ec)
		{
			if (!m_socket->remoteEndpoint().address().is_unspecified())
				clog(NetWarn) << "Disconnecting " << m_socket->remoteEndpoint() << " (Handshake Timeout)";
			cancel();
		}
	});
}
<|endoftext|>