text:
/**************************************************************
 *
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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.
 *
 **************************************************************/

 // MARKER(update_precomp.py): autogen include statement, do not remove
//This file is about the conversion of the UOF v2.0 and ODF document format
#ifndef FILTER_SOURCE_XSLTFILTER_CONTAINERHELPER_HXX
#define FILTER_SOURCE_XSLTFILTER_CONTAINERHELPER_HXX

#include <map>
#include <boost/shared_ptr.hpp>
#include <boost/bind.hpp>

namespace XSLT{

template< typename KeyType, typename ObjType, typename CompType = ::std::less< KeyType > >
class RefMap : public ::std::map< KeyType, ::boost::shared_ptr< ObjType >, CompType >
{
public:
	typedef ::std::map< KeyType, ::boost::shared_ptr< ObjType >, CompType > container_type;
	typedef typename container_type::key_type		key_type;
	typedef typename container_type::mapped_type	mapped_type;
	typedef typename container_type::value_type		value_type;
	typedef typename container_type::key_compare	key_compare;

	inline bool has( key_type nKey ) const
	{
		const mapped_type* pxRef = getRef(nKey);
		return pxRef && pxRef->get();
	}

	inline mapped_type get( key_type nKey ) const
	{
		if(const mapped_type* pxRef = getRef(nKey) ) return *pxRef;
		return mapped_type();
	}

	template<typename FunctorType >
	inline void forEach( const FunctorType& rFunctor) const
	{
		::std::for_each(this->begin(), this->end(), ForEachFunctor< FunctorType >(rFunctor));
	}

	template< typename FuncType >
	inline void forEachMem(FuncType pFunc)
	{
		forEach( ::boost::bind(pFunc, _1 ));
	}

	template<typename FuncType, typename ParamType>
	inline void forEachMem(FuncType pFunc, ParamType aParam) const
	{
		forEach( ::boost::bind(pFunc, _1, aParam));
	}

	template<typename FuncType, typename ParamType1, typename ParamType2>
	inline void forEachMem(FuncType pFunc, ParamType1 aParam1, ParamType2 aParam2) const
	{
		forEach( ::boost::bind(pFunc, _1, aParam1, aParam2 ));
	}

	template<typename FuncType, typename ParamType1, typename ParamType2, typename ParamType3>
	inline void forEachMem(FuncType pFunc, ParamType1 aParam1, ParamType2 aParam2, ParamType3 aParam3 ) const
	{
		forEach( ::boost::bind(pFunc, _1, aParam1, aParam2, aParam3 ));
	}

	template<typename FuncType>
	inline void forEachWithKey(const FuncType& rFunctor) const
	{
		::std::for_each( this->begin(), this->end(), ForEachFunctorWithKey< FuncType >(rFunctor));
	}

	template<typename FuncType>
	inline void forEachMemWithKey(FuncType pFunc) const
	{
		forEachWithKey( ::boost::bind(pFunc, _2, _1));
	}

	template<typename FuncType, typename ParamType>
	inline void forEachMemWithKey(FuncType pFunc, ParamType aParam1) const
	{
		forEachWithKey( ::boost::bind(pFunc, _2, _1, aParam1) );
	}

	template<typename FuncType, typename ParamType1, typename ParamType2>
	inline void forEachMemWithKey(FuncType pFunc, ParamType1 aParam1, ParamType2 aParam2) const
	{
		forEachWithKey( ::boost::bind(pFunc, _2, _1, aParam1, aParam2) );
	}

	template<typename FuncType, typename ParamType1, typename ParamType2, typename ParamType3>
	inline void forEachMemWithKey(FuncType pFunc, ParamType1 aParam1, ParamType2 aParam2, ParamType3 aParam3) const
	{
		forEachWithKey( ::boost::bind(pFunc, _2, _1, aParam1, aParam2, aParam3) );
	}
private:
	template<typename FunctorType>
	struct ForEachFunctor
	{
		FunctorType m_aFunctor;
		inline explicit ForEachFunctor( const FunctorType& rFunctor): m_aFunctor(rFunctor){}
		inline void operator()(const value_type& rValue)
		{
			if(rValue.second.get())
				m_aFunctor(*rValue.second);
		}
	};

	template<typename FunctorType>
	struct ForEachFunctorWithKey
	{
		FunctorType m_aFunctor;
		inline explicit ForEachFunctorWithKey( const FunctorType& rFunctor) : m_aFunctor(rFunctor){}
		inline void operator()(const value_type& rValue)
		{
			if(rValue.second.get())
				m_aFunctor(rValue.first, *rValue.second);
		}
	};

	inline const mapped_type* getRef( key_type nKey ) const
	{
		typename container_type::const_iterator aIt = find(nKey);
		return (aIt == this->end())? 0 : &aIt->second;
	}
};

}

#endif

ext: hxx

max_stars_repo_name: Grosskopf/openoffice

max_issues_repo_name: Grosskopf/openoffice

max_forks_repo_name: Grosskopf/openoffice


text:
/*
// Copyright (c) 2018 Intel Corporation
//
// 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.
*/
#pragma once

#include <math.h>

#include <boost/algorithm/string/predicate.hpp>
#include <boost/algorithm/string/split.hpp>
#include <boost/container/flat_map.hpp>
#include <boost/range/algorithm/replace_copy_if.hpp>
#include <dbus_singleton.hpp>
#include <utils/json_utils.hpp>
#include <variant>

namespace redfish
{

constexpr const char* dbusSensorPrefix = "/xyz/openbmc_project/sensors/";

using GetSubTreeType = std::vector<
    std::pair<std::string,
              std::vector<std::pair<std::string, std::vector<std::string>>>>>;

using SensorVariant = std::variant<int64_t, double>;

using ManagedObjectsVectorType = std::vector<std::pair<
    sdbusplus::message::object_path,
    boost::container::flat_map<
        std::string, boost::container::flat_map<std::string, SensorVariant>>>>;

/**
 * SensorsAsyncResp
 * Gathers data needed for response processing after async calls are done
 */
class SensorsAsyncResp
{
  public:
    SensorsAsyncResp(crow::Response& response, const std::string& chassisId,
                     const std::initializer_list<const char*> types,
                     const std::string& subNode) :
        res(response),
        chassisId(chassisId), types(types), chassisSubNode(subNode)
    {
        res.jsonValue["@odata.id"] =
            "/redfish/v1/Chassis/" + chassisId + "/" + subNode;
    }

    ~SensorsAsyncResp()
    {
        if (res.result() == boost::beast::http::status::internal_server_error)
        {
            // Reset the json object to clear out any data that made it in
            // before the error happened todo(ed) handle error condition with
            // proper code
            res.jsonValue = nlohmann::json::object();
        }
        res.end();
    }

    crow::Response& res;
    std::string chassisId{};
    const std::vector<const char*> types;
    std::string chassisSubNode{};
};

/**
 * @brief Checks whether the specified sensor is one of the requested types.
 * @param objectPath DBus object path of the sensor.
 * @param SensorsAsyncResp Pointer to object holding response data and requested
 * sensor types.
 * @return true if sensor type is requested, false otherwise.
 */
inline bool
    isRequestedSensorType(const std::string& objectPath,
                          std::shared_ptr<SensorsAsyncResp> SensorsAsyncResp)
{
    for (const char* type : SensorsAsyncResp->types)
    {
        if (boost::starts_with(objectPath, type))
        {
            return true;
        }
    }
    return false;
}

/**
 * @brief Get objects with connection necessary for sensors
 * @param SensorsAsyncResp Pointer to object holding response data
 * @param sensorNames Sensors retrieved from chassis
 * @param callback Callback for processing gathered connections
 */
template <typename Callback>
void getObjectsWithConnection(
    std::shared_ptr<SensorsAsyncResp> SensorsAsyncResp,
    const boost::container::flat_set<std::string>& sensorNames,
    Callback&& callback)
{
    BMCWEB_LOG_DEBUG << "getObjectsWithConnection enter";
    const std::string path = "/xyz/openbmc_project/sensors";
    const std::array<std::string, 1> interfaces = {
        "xyz.openbmc_project.Sensor.Value"};

    // Response handler for parsing objects subtree
    auto respHandler = [callback{std::move(callback)}, SensorsAsyncResp,
                        sensorNames](const boost::system::error_code ec,
                                     const GetSubTreeType& subtree) {
        BMCWEB_LOG_DEBUG << "getObjectsWithConnection resp_handler enter";
        if (ec)
        {
            messages::internalError(SensorsAsyncResp->res);
            BMCWEB_LOG_ERROR
                << "getObjectsWithConnection resp_handler: Dbus error " << ec;
            return;
        }

        BMCWEB_LOG_DEBUG << "Found " << subtree.size() << " subtrees";

        // Make unique list of connections only for requested sensor types and
        // found in the chassis
        boost::container::flat_set<std::string> connections;
        std::set<std::pair<std::string, std::string>> objectsWithConnection;
        // Intrinsic to avoid malloc.  Most systems will have < 8 sensor
        // producers
        connections.reserve(8);

        BMCWEB_LOG_DEBUG << "sensorNames list count: " << sensorNames.size();
        for (const std::string& tsensor : sensorNames)
        {
            BMCWEB_LOG_DEBUG << "Sensor to find: " << tsensor;
        }

        for (const std::pair<
                 std::string,
                 std::vector<std::pair<std::string, std::vector<std::string>>>>&
                 object : subtree)
        {
            if (isRequestedSensorType(object.first, SensorsAsyncResp))
            {
                auto lastPos = object.first.rfind('/');
                if (lastPos != std::string::npos)
                {
                    std::string sensorName = object.first.substr(lastPos + 1);

                    if (sensorNames.find(sensorName) != sensorNames.end())
                    {
                        // For each Connection name
                        for (const std::pair<std::string,
                                             std::vector<std::string>>&
                                 objData : object.second)
                        {
                            BMCWEB_LOG_DEBUG << "Adding connection: "
                                             << objData.first;
                            connections.insert(objData.first);
                            objectsWithConnection.insert(
                                std::make_pair(object.first, objData.first));
                        }
                    }
                }
            }
        }
        BMCWEB_LOG_DEBUG << "Found " << connections.size() << " connections";
        callback(std::move(connections), std::move(objectsWithConnection));
        BMCWEB_LOG_DEBUG << "getObjectsWithConnection resp_handler exit";
    };
    // Make call to ObjectMapper to find all sensors objects
    crow::connections::systemBus->async_method_call(
        std::move(respHandler), "xyz.openbmc_project.ObjectMapper",
        "/xyz/openbmc_project/object_mapper",
        "xyz.openbmc_project.ObjectMapper", "GetSubTree", path, 2, interfaces);
    BMCWEB_LOG_DEBUG << "getObjectsWithConnection exit";
}

/**
 * @brief Create connections necessary for sensors
 * @param SensorsAsyncResp Pointer to object holding response data
 * @param sensorNames Sensors retrieved from chassis
 * @param callback Callback for processing gathered connections
 */
template <typename Callback>
void getConnections(std::shared_ptr<SensorsAsyncResp> SensorsAsyncResp,
                    const boost::container::flat_set<std::string>& sensorNames,
                    Callback&& callback)
{
    auto objectsWithConnectionCb =
        [callback](const boost::container::flat_set<std::string>& connections,
                   const std::set<std::pair<std::string, std::string>>&
                       objectsWithConnection) {
            callback(std::move(connections));
        };
    getObjectsWithConnection(SensorsAsyncResp, sensorNames,
                             std::move(objectsWithConnectionCb));
}

/**
 * @brief Gets all DBus sensor names.
 *
 * Finds the sensor names asynchronously.  Invokes callback when information has
 * been obtained.
 *
 * The callback must have the following signature:
 *   @code
 *   callback(boost::container::flat_set<std::string>& sensorNames)
 *   @endcode
 *
 * @param SensorsAsyncResp Pointer to object holding response data.
 * @param callback Callback to invoke when sensor names obtained.
 */
template <typename Callback>
void getAllSensors(std::shared_ptr<SensorsAsyncResp> SensorsAsyncResp,
                   Callback&& callback)
{
    BMCWEB_LOG_DEBUG << "getAllSensors enter";
    const std::array<std::string, 1> interfaces = {
        "xyz.openbmc_project.Sensor.Value"};

    // Response handler for GetSubTreePaths DBus method
    auto respHandler = [callback{std::move(callback)}, SensorsAsyncResp](
                           const boost::system::error_code ec,
                           const std::vector<std::string>& sensorList) {
        BMCWEB_LOG_DEBUG << "getAllSensors respHandler enter";
        if (ec)
        {
            messages::internalError(SensorsAsyncResp->res);
            BMCWEB_LOG_ERROR << "getAllSensors respHandler: DBus error " << ec;
            return;
        }
        boost::container::flat_set<std::string> sensorNames;
        for (const std::string& sensor : sensorList)
        {
            std::size_t lastPos = sensor.rfind("/");
            if (lastPos == std::string::npos)
            {
                BMCWEB_LOG_ERROR << "Failed to find '/' in " << sensor;
                continue;
            }
            std::string sensorName = sensor.substr(lastPos + 1);
            sensorNames.emplace(sensorName);
            BMCWEB_LOG_DEBUG << "Added sensor name " << sensorName;
        }
        callback(sensorNames);
        BMCWEB_LOG_DEBUG << "getAllSensors respHandler exit";
    };

    // Query mapper for all DBus sensor object paths
    crow::connections::systemBus->async_method_call(
        std::move(respHandler), "xyz.openbmc_project.ObjectMapper",
        "/xyz/openbmc_project/object_mapper",
        "xyz.openbmc_project.ObjectMapper", "GetSubTreePaths",
        "/xyz/openbmc_project/sensors", int32_t(0), interfaces);
    BMCWEB_LOG_DEBUG << "getAllSensors exit";
}

/**
 * @brief Retrieves requested chassis sensors and redundancy data from DBus .
 * @param SensorsAsyncResp   Pointer to object holding response data
 * @param callback  Callback for next step in gathered sensor processing
 */
template <typename Callback>
void getChassis(std::shared_ptr<SensorsAsyncResp> SensorsAsyncResp,
                Callback&& callback)
{
    BMCWEB_LOG_DEBUG << "getChassis enter";
    // Process response from EntityManager and extract chassis data
    auto respHandler = [callback{std::move(callback)},
                        SensorsAsyncResp](const boost::system::error_code ec,
                                          ManagedObjectsVectorType& resp) {
        BMCWEB_LOG_DEBUG << "getChassis respHandler enter";
        if (ec)
        {
            BMCWEB_LOG_ERROR << "getChassis respHandler DBUS error: " << ec;
            messages::internalError(SensorsAsyncResp->res);
            return;
        }
        boost::container::flat_set<std::string> sensorNames;

        //   SensorsAsyncResp->chassisId
        bool foundChassis = false;
        std::vector<std::string> split;
        // Reserve space for
        // /xyz/openbmc_project/inventory/<name>/<subname> + 3 subnames
        split.reserve(8);

        for (const auto& objDictEntry : resp)
        {
            const std::string& objectPath =
                static_cast<const std::string&>(objDictEntry.first);
            boost::algorithm::split(split, objectPath, boost::is_any_of("/"));
            if (split.size() < 2)
            {
                BMCWEB_LOG_ERROR << "Got path that isn't long enough "
                                 << objectPath;
                split.clear();
                continue;
            }
            const std::string& sensorName = split.end()[-1];
            const std::string& chassisName = split.end()[-2];

            if (chassisName != SensorsAsyncResp->chassisId)
            {
                split.clear();
                continue;
            }
            BMCWEB_LOG_DEBUG << "New sensor: " << sensorName;
            foundChassis = true;
            sensorNames.emplace(sensorName);
            split.clear();
        };
        BMCWEB_LOG_DEBUG << "Found " << sensorNames.size() << " Sensor names";

        if (!foundChassis)
        {
            BMCWEB_LOG_INFO << "Unable to find chassis named "
                            << SensorsAsyncResp->chassisId;
            messages::resourceNotFound(SensorsAsyncResp->res, "Chassis",
                                       SensorsAsyncResp->chassisId);
        }
        else
        {
            callback(sensorNames);
        }
        BMCWEB_LOG_DEBUG << "getChassis respHandler exit";
    };

    // Make call to EntityManager to find all chassis objects
    crow::connections::systemBus->async_method_call(
        respHandler, "xyz.openbmc_project.EntityManager", "/",
        "org.freedesktop.DBus.ObjectManager", "GetManagedObjects");
    BMCWEB_LOG_DEBUG << "getChassis exit";
}

/**
 * @brief Finds all DBus object paths that implement ObjectManager.
 *
 * Creates a mapping from the associated connection name to the object path.
 *
 * Finds the object paths asynchronously.  Invokes callback when information has
 * been obtained.
 *
 * The callback must have the following signature:
 *   @code
 *   callback(const boost::container::flat_map<std::string,
 *            std::string>& objectMgrPaths)
 *   @endcode
 *
 * @param SensorsAsyncResp Pointer to object holding response data.
 * @param callback Callback to invoke when object paths obtained.
 */
template <typename Callback>
void getObjectManagerPaths(std::shared_ptr<SensorsAsyncResp> SensorsAsyncResp,
                           Callback&& callback)
{
    BMCWEB_LOG_DEBUG << "getObjectManagerPaths enter";
    const std::array<std::string, 1> interfaces = {
        "org.freedesktop.DBus.ObjectManager"};

    // Response handler for GetSubTree DBus method
    auto respHandler = [callback{std::move(callback)},
                        SensorsAsyncResp](const boost::system::error_code ec,
                                          const GetSubTreeType& subtree) {
        BMCWEB_LOG_DEBUG << "getObjectManagerPaths respHandler enter";
        if (ec)
        {
            messages::internalError(SensorsAsyncResp->res);
            BMCWEB_LOG_ERROR << "getObjectManagerPaths respHandler: DBus error "
                             << ec;
            return;
        }

        // Loop over returned object paths
        boost::container::flat_map<std::string, std::string> objectMgrPaths;
        for (const std::pair<
                 std::string,
                 std::vector<std::pair<std::string, std::vector<std::string>>>>&
                 object : subtree)
        {
            // Loop over connections for current object path
            const std::string& objectPath = object.first;
            for (const std::pair<std::string, std::vector<std::string>>&
                     objData : object.second)
            {
                // Add mapping from connection to object path
                const std::string& connection = objData.first;
                objectMgrPaths[connection] = objectPath;
                BMCWEB_LOG_DEBUG << "Added mapping " << connection << " -> "
                                 << objectPath;
            }
        }
        callback(std::move(objectMgrPaths));
        BMCWEB_LOG_DEBUG << "getObjectManagerPaths respHandler exit";
    };

    // Query mapper for all DBus object paths that implement ObjectManager
    crow::connections::systemBus->async_method_call(
        std::move(respHandler), "xyz.openbmc_project.ObjectMapper",
        "/xyz/openbmc_project/object_mapper",
        "xyz.openbmc_project.ObjectMapper", "GetSubTree", "/", int32_t(0),
        interfaces);
    BMCWEB_LOG_DEBUG << "getObjectManagerPaths exit";
}

/**
 * @brief Builds a json sensor representation of a sensor.
 * @param sensorName  The name of the sensor to be built
 * @param sensorType  The type (temperature, fan_tach, etc) of the sensor to
 * build
 * @param interfacesDict  A dictionary of the interfaces and properties of said
 * interfaces to be built from
 * @param sensor_json  The json object to fill
 */
void objectInterfacesToJson(
    const std::string& sensorName, const std::string& sensorType,
    const boost::container::flat_map<
        std::string, boost::container::flat_map<std::string, SensorVariant>>&
        interfacesDict,
    nlohmann::json& sensor_json)
{
    // We need a value interface before we can do anything with it
    auto valueIt = interfacesDict.find("xyz.openbmc_project.Sensor.Value");
    if (valueIt == interfacesDict.end())
    {
        BMCWEB_LOG_ERROR << "Sensor doesn't have a value interface";
        return;
    }

    // Assume values exist as is (10^0 == 1) if no scale exists
    int64_t scaleMultiplier = 0;

    auto scaleIt = valueIt->second.find("Scale");
    // If a scale exists, pull value as int64, and use the scaling.
    if (scaleIt != valueIt->second.end())
    {
        const int64_t* int64Value = std::get_if<int64_t>(&scaleIt->second);
        if (int64Value != nullptr)
        {
            scaleMultiplier = *int64Value;
        }
    }

    sensor_json["MemberId"] = sensorName;
    sensor_json["Name"] = sensorName;
    sensor_json["Status"]["State"] = "Enabled";
    sensor_json["Status"]["Health"] = "OK";

    // Parameter to set to override the type we get from dbus, and force it to
    // int, regardless of what is available.  This is used for schemas like fan,
    // that require integers, not floats.
    bool forceToInt = false;

    const char* unit = "Reading";
    if (sensorType == "temperature")
    {
        unit = "ReadingCelsius";
        sensor_json["@odata.type"] = "#Thermal.v1_3_0.Temperature";
        // TODO(ed) Documentation says that path should be type fan_tach,
        // implementation seems to implement fan
    }
    else if (sensorType == "fan" || sensorType == "fan_tach")
    {
        unit = "Reading";
        sensor_json["ReadingUnits"] = "RPM";
        sensor_json["@odata.type"] = "#Thermal.v1_3_0.Fan";
        forceToInt = true;
    }
    else if (sensorType == "fan_pwm")
    {
        unit = "Reading";
        sensor_json["ReadingUnits"] = "Percent";
        sensor_json["@odata.type"] = "#Thermal.v1_3_0.Fan";
        forceToInt = true;
    }
    else if (sensorType == "voltage")
    {
        unit = "ReadingVolts";
        sensor_json["@odata.type"] = "#Power.v1_0_0.Voltage";
    }
    else if (sensorType == "power")
    {
        unit = "LastPowerOutputWatts";
    }
    else
    {
        BMCWEB_LOG_ERROR << "Redfish cannot map object type for " << sensorName;
        return;
    }
    // Map of dbus interface name, dbus property name and redfish property_name
    std::vector<std::tuple<const char*, const char*, const char*>> properties;
    properties.reserve(7);

    properties.emplace_back("xyz.openbmc_project.Sensor.Value", "Value", unit);

    // If sensor type doesn't map to Redfish PowerSupply, add threshold props
    if ((sensorType != "current") && (sensorType != "power"))
    {
        properties.emplace_back("xyz.openbmc_project.Sensor.Threshold.Warning",
                                "WarningHigh", "UpperThresholdNonCritical");
        properties.emplace_back("xyz.openbmc_project.Sensor.Threshold.Warning",
                                "WarningLow", "LowerThresholdNonCritical");
        properties.emplace_back("xyz.openbmc_project.Sensor.Threshold.Critical",
                                "CriticalHigh", "UpperThresholdCritical");
        properties.emplace_back("xyz.openbmc_project.Sensor.Threshold.Critical",
                                "CriticalLow", "LowerThresholdCritical");
    }

    // TODO Need to get UpperThresholdFatal and LowerThresholdFatal

    if (sensorType == "temperature")
    {
        properties.emplace_back("xyz.openbmc_project.Sensor.Value", "MinValue",
                                "MinReadingRangeTemp");
        properties.emplace_back("xyz.openbmc_project.Sensor.Value", "MaxValue",
                                "MaxReadingRangeTemp");
    }
    else if ((sensorType != "current") && (sensorType != "power"))
    {
        // Sensor type doesn't map to Redfish PowerSupply; add min/max props
        properties.emplace_back("xyz.openbmc_project.Sensor.Value", "MinValue",
                                "MinReadingRange");
        properties.emplace_back("xyz.openbmc_project.Sensor.Value", "MaxValue",
                                "MaxReadingRange");
    }

    for (const std::tuple<const char*, const char*, const char*>& p :
         properties)
    {
        auto interfaceProperties = interfacesDict.find(std::get<0>(p));
        if (interfaceProperties != interfacesDict.end())
        {
            auto valueIt = interfaceProperties->second.find(std::get<1>(p));
            if (valueIt != interfaceProperties->second.end())
            {
                const SensorVariant& valueVariant = valueIt->second;
                nlohmann::json& valueIt = sensor_json[std::get<2>(p)];
                // Attempt to pull the int64 directly
                const int64_t* int64Value = std::get_if<int64_t>(&valueVariant);

                const double* doubleValue = std::get_if<double>(&valueVariant);
                double temp = 0.0;
                if (int64Value != nullptr)
                {
                    temp = *int64Value;
                }
                else if (doubleValue != nullptr)
                {
                    temp = *doubleValue;
                }
                else
                {
                    BMCWEB_LOG_ERROR
                        << "Got value interface that wasn't int or double";
                    continue;
                }
                temp = temp * std::pow(10, scaleMultiplier);
                if (forceToInt)
                {
                    valueIt = static_cast<int64_t>(temp);
                }
                else
                {
                    valueIt = temp;
                }
            }
        }
    }
    BMCWEB_LOG_DEBUG << "Added sensor " << sensorName;
}

static void
    populateFanRedundancy(std::shared_ptr<SensorsAsyncResp> sensorsAsyncResp)
{
    crow::connections::systemBus->async_method_call(
        [sensorsAsyncResp](const boost::system::error_code ec,
                           const GetSubTreeType& resp) {
            if (ec)
            {
                return; // don't have to have this interface
            }
            for (const std::pair<std::string,
                                 std::vector<std::pair<
                                     std::string, std::vector<std::string>>>>&
                     pathPair : resp)
            {
                const std::string& path = pathPair.first;
                const std::vector<
                    std::pair<std::string, std::vector<std::string>>>& objDict =
                    pathPair.second;
                if (objDict.empty())
                {
                    continue; // this should be impossible
                }

                const std::string& owner = objDict.begin()->first;
                crow::connections::systemBus->async_method_call(
                    [path, owner,
                     sensorsAsyncResp](const boost::system::error_code ec,
                                       std::variant<std::vector<std::string>>
                                           variantEndpoints) {
                        if (ec)
                        {
                            return; // if they don't have an association we
                                    // can't tell what chassis is
                        }
                        // verify part of the right chassis
                        auto endpoints = std::get_if<std::vector<std::string>>(
                            &variantEndpoints);

                        if (endpoints == nullptr)
                        {
                            BMCWEB_LOG_ERROR << "Invalid association interface";
                            messages::internalError(sensorsAsyncResp->res);
                            return;
                        }

                        auto found = std::find_if(
                            endpoints->begin(), endpoints->end(),
                            [sensorsAsyncResp](const std::string& entry) {
                                return entry.find(
                                           sensorsAsyncResp->chassisId) !=
                                       std::string::npos;
                            });

                        if (found == endpoints->end())
                        {
                            return;
                        }
                        crow::connections::systemBus->async_method_call(
                            [path, sensorsAsyncResp](
                                const boost::system::error_code ec,
                                const boost::container::flat_map<
                                    std::string,
                                    std::variant<uint8_t,
                                                 std::vector<std::string>,
                                                 std::string>>& ret) {
                                if (ec)
                                {
                                    return; // don't have to have this
                                            // interface
                                }
                                auto findFailures = ret.find("AllowedFailures");
                                auto findCollection = ret.find("Collection");
                                auto findStatus = ret.find("Status");

                                if (findFailures == ret.end() ||
                                    findCollection == ret.end() ||
                                    findStatus == ret.end())
                                {
                                    BMCWEB_LOG_ERROR
                                        << "Invalid redundancy interface";
                                    messages::internalError(
                                        sensorsAsyncResp->res);
                                    return;
                                }

                                auto allowedFailures = std::get_if<uint8_t>(
                                    &(findFailures->second));
                                auto collection =
                                    std::get_if<std::vector<std::string>>(
                                        &(findCollection->second));
                                auto status = std::get_if<std::string>(
                                    &(findStatus->second));

                                if (allowedFailures == nullptr ||
                                    collection == nullptr || status == nullptr)
                                {

                                    BMCWEB_LOG_ERROR
                                        << "Invalid redundancy interface "
                                           "types";
                                    messages::internalError(
                                        sensorsAsyncResp->res);
                                    return;
                                }
                                size_t lastSlash = path.rfind("/");
                                if (lastSlash == std::string::npos)
                                {
                                    // this should be impossible
                                    messages::internalError(
                                        sensorsAsyncResp->res);
                                    return;
                                }
                                std::string name = path.substr(lastSlash + 1);
                                std::replace(name.begin(), name.end(), '_',
                                             ' ');

                                std::string health;

                                if (boost::ends_with(*status, "Full"))
                                {
                                    health = "OK";
                                }
                                else if (boost::ends_with(*status, "Degraded"))
                                {
                                    health = "Warning";
                                }
                                else
                                {
                                    health = "Critical";
                                }
                                std::vector<nlohmann::json> redfishCollection;
                                const auto& fanRedfish =
                                    sensorsAsyncResp->res.jsonValue["Fans"];
                                for (const std::string& item : *collection)
                                {
                                    lastSlash = item.rfind("/");
                                    // make a copy as collection is const
                                    std::string itemName =
                                        item.substr(lastSlash + 1);
                                    /*
                                    todo(ed): merge patch that fixes the names
                                    std::replace(itemName.begin(),
                                                 itemName.end(), '_', ' ');*/
                                    auto schemaItem = std::find_if(
                                        fanRedfish.begin(), fanRedfish.end(),
                                        [itemName](const nlohmann::json& fan) {
                                            return fan["MemberId"] == itemName;
                                        });
                                    if (schemaItem != fanRedfish.end())
                                    {
                                        redfishCollection.push_back(
                                            {{"@odata.id",
                                              (*schemaItem)["@odata.id"]}});
                                    }
                                    else
                                    {
                                        BMCWEB_LOG_ERROR
                                            << "failed to find fan in schema";
                                        messages::internalError(
                                            sensorsAsyncResp->res);
                                        return;
                                    }
                                }

                                auto& resp = sensorsAsyncResp->res
                                                 .jsonValue["Redundancy"];
                                resp.push_back(
                                    {{"@odata.id",
                                      "/refish/v1/Chassis/" +
                                          sensorsAsyncResp->chassisId + "/" +
                                          sensorsAsyncResp->chassisSubNode +
                                          "#/Redundancy/" +
                                          std::to_string(resp.size())},
                                     {"@odata.type",
                                      "#Redundancy.v1_3_2.Redundancy"},
                                     {"MinNumNeeded",
                                      collection->size() - *allowedFailures},
                                     {"MemberId", name},
                                     {"Mode", "N+m"},
                                     {"Name", name},
                                     {"RedundancySet", redfishCollection},
                                     {"Status",
                                      {{"Health", health},
                                       {"State", "Enabled"}}}});
                            },
                            owner, path, "org.freedesktop.DBus.Properties",
                            "GetAll",
                            "xyz.openbmc_project.Control.FanRedundancy");
                    },
                    "xyz.openbmc_project.ObjectMapper", path + "/inventory",
                    "org.freedesktop.DBus.Properties", "Get",
                    "xyz.openbmc_project.Association", "endpoints");
            }
        },
        "xyz.openbmc_project.ObjectMapper",
        "/xyz/openbmc_project/object_mapper",
        "xyz.openbmc_project.ObjectMapper", "GetSubTree",
        "/xyz/openbmc_project/control", 2,
        std::array<const char*, 1>{
            "xyz.openbmc_project.Control.FanRedundancy"});
}

/**
 * @brief Gets the values of the specified sensors.
 *
 * Stores the results as JSON in the SensorsAsyncResp.
 *
 * Gets the sensor values asynchronously.  Stores the results later when the
 * information has been obtained.
 *
 * The sensorNames set contains all sensors for the current chassis.
 * SensorsAsyncResp contains the requested sensor types.  Only sensors of a
 * requested type are included in the JSON output.
 *
 * To minimize the number of DBus calls, the DBus method
 * org.freedesktop.DBus.ObjectManager.GetManagedObjects() is used to get the
 * values of all sensors provided by a connection (service).
 *
 * The connections set contains all the connections that provide sensor values.
 *
 * The objectMgrPaths map contains mappings from a connection name to the
 * corresponding DBus object path that implements ObjectManager.
 *
 * @param SensorsAsyncResp Pointer to object holding response data.
 * @param sensorNames All sensors within the current chassis.
 * @param connections Connections that provide sensor values.
 * @param objectMgrPaths Mappings from connection name to DBus object path that
 * implements ObjectManager.
 */
void getSensorData(
    std::shared_ptr<SensorsAsyncResp> SensorsAsyncResp,
    const boost::container::flat_set<std::string>& sensorNames,
    const boost::container::flat_set<std::string>& connections,
    const boost::container::flat_map<std::string, std::string>& objectMgrPaths)
{
    BMCWEB_LOG_DEBUG << "getSensorData enter";
    // Get managed objects from all services exposing sensors
    for (const std::string& connection : connections)
    {
        // Response handler to process managed objects
        auto getManagedObjectsCb = [&, SensorsAsyncResp, sensorNames](
                                       const boost::system::error_code ec,
                                       ManagedObjectsVectorType& resp) {
            BMCWEB_LOG_DEBUG << "getManagedObjectsCb enter";
            if (ec)
            {
                BMCWEB_LOG_ERROR << "getManagedObjectsCb DBUS error: " << ec;
                messages::internalError(SensorsAsyncResp->res);
                return;
            }
            // Go through all objects and update response with sensor data
            for (const auto& objDictEntry : resp)
            {
                const std::string& objPath =
                    static_cast<const std::string&>(objDictEntry.first);
                BMCWEB_LOG_DEBUG << "getManagedObjectsCb parsing object "
                                 << objPath;

                // Skip sensor if it is not one of the requested types
                if (!isRequestedSensorType(objPath, SensorsAsyncResp))
                {
                    continue;
                }

                std::vector<std::string> split;
                // Reserve space for
                // /xyz/openbmc_project/sensors/<name>/<subname>
                split.reserve(6);
                boost::algorithm::split(split, objPath, boost::is_any_of("/"));
                if (split.size() < 6)
                {
                    BMCWEB_LOG_ERROR << "Got path that isn't long enough "
                                     << objPath;
                    continue;
                }
                // These indexes aren't intuitive, as boost::split puts an empty
                // string at the beginning
                const std::string& sensorType = split[4];
                const std::string& sensorName = split[5];
                BMCWEB_LOG_DEBUG << "sensorName " << sensorName
                                 << " sensorType " << sensorType;
                if (sensorNames.find(sensorName) == sensorNames.end())
                {
                    BMCWEB_LOG_ERROR << sensorName << " not in sensor list ";
                    continue;
                }

                const char* fieldName = nullptr;
                if (sensorType == "temperature")
                {
                    fieldName = "Temperatures";
                }
                else if (sensorType == "fan" || sensorType == "fan_tach" ||
                         sensorType == "fan_pwm")
                {
                    fieldName = "Fans";
                }
                else if (sensorType == "voltage")
                {
                    fieldName = "Voltages";
                }
                else if (sensorType == "current")
                {
                    fieldName = "PowerSupplies";
                }
                else if (sensorType == "power")
                {
                    fieldName = "PowerSupplies";
                }
                else
                {
                    BMCWEB_LOG_ERROR << "Unsure how to handle sensorType "
                                     << sensorType;
                    continue;
                }

                nlohmann::json& tempArray =
                    SensorsAsyncResp->res.jsonValue[fieldName];

                tempArray.push_back(
                    {{"@odata.id",
                      "/redfish/v1/Chassis/" + SensorsAsyncResp->chassisId +
                          "/" + SensorsAsyncResp->chassisSubNode + "#/" +
                          fieldName + "/" + std::to_string(tempArray.size())}});
                nlohmann::json& sensorJson = tempArray.back();

                objectInterfacesToJson(sensorName, sensorType,
                                       objDictEntry.second, sensorJson);
            }
            if (SensorsAsyncResp.use_count() == 1 &&
                SensorsAsyncResp->chassisSubNode == "Thermal")
            {
                populateFanRedundancy(SensorsAsyncResp);
            }
            BMCWEB_LOG_DEBUG << "getManagedObjectsCb exit";
        };

        // Find DBus object path that implements ObjectManager for the current
        // connection.  If no mapping found, default to "/".
        auto iter = objectMgrPaths.find(connection);
        const std::string& objectMgrPath =
            (iter != objectMgrPaths.end()) ? iter->second : "/";
        BMCWEB_LOG_DEBUG << "ObjectManager path for " << connection << " is "
                         << objectMgrPath;

        crow::connections::systemBus->async_method_call(
            getManagedObjectsCb, connection, objectMgrPath,
            "org.freedesktop.DBus.ObjectManager", "GetManagedObjects");
    };
    BMCWEB_LOG_DEBUG << "getSensorData exit";
}

/**
 * @brief Entry point for retrieving sensors data related to requested
 *        chassis.
 * @param SensorsAsyncResp   Pointer to object holding response data
 */
void getChassisData(std::shared_ptr<SensorsAsyncResp> SensorsAsyncResp)
{
    BMCWEB_LOG_DEBUG << "getChassisData enter";
    auto getChassisCb = [&, SensorsAsyncResp](
                            boost::container::flat_set<std::string>&
                                sensorNames) {
        BMCWEB_LOG_DEBUG << "getChassisCb enter";
        auto getConnectionCb =
            [&, SensorsAsyncResp, sensorNames](
                const boost::container::flat_set<std::string>& connections) {
                BMCWEB_LOG_DEBUG << "getConnectionCb enter";
                auto getObjectManagerPathsCb =
                    [SensorsAsyncResp, sensorNames,
                     connections](const boost::container::flat_map<
                                  std::string, std::string>& objectMgrPaths) {
                        BMCWEB_LOG_DEBUG << "getObjectManagerPathsCb enter";
                        // Get sensor data and store results in JSON response
                        getSensorData(SensorsAsyncResp, sensorNames,
                                      connections, objectMgrPaths);
                        BMCWEB_LOG_DEBUG << "getObjectManagerPathsCb exit";
                    };

                // Get mapping from connection names to the DBus object paths
                // that implement the ObjectManager interface
                getObjectManagerPaths(SensorsAsyncResp,
                                      std::move(getObjectManagerPathsCb));
                BMCWEB_LOG_DEBUG << "getConnectionCb exit";
            };

        // Get set of connections that provide sensor values
        getConnections(SensorsAsyncResp, sensorNames,
                       std::move(getConnectionCb));
        BMCWEB_LOG_DEBUG << "getChassisCb exit";
    };

#ifdef BMCWEB_ENABLE_REDFISH_ONE_CHASSIS
    // Get all sensor names
    getAllSensors(SensorsAsyncResp, std::move(getChassisCb));
#else
    // Get sensor names in chassis
    getChassis(SensorsAsyncResp, std::move(getChassisCb));
#endif
    BMCWEB_LOG_DEBUG << "getChassisData exit";
};

/**
 * @brief Entry point for overriding sensor values of given sensor
 *
 * @param res   response object
 * @param req   request object
 * @param params   parameter passed for CRUD
 * @param typeList   TypeList of sensors for the resource queried
 * @param chassisSubNode   Chassis Node for which the query has to happen
 */
void setSensorOverride(crow::Response& res, const crow::Request& req,
                       const std::vector<std::string>& params,
                       const std::initializer_list<const char*> typeList,
                       const std::string& chassisSubNode)
{

    // TODO: Need to figure out dynamic way to restrict patch (Set Sensor
    // override) based on another d-bus announcement to be more generic.
    if (params.size() != 1)
    {
        messages::internalError(res);
        res.end();
        return;
    }

    std::unordered_map<std::string, std::vector<nlohmann::json>> allCollections;
    std::optional<std::vector<nlohmann::json>> temperatureCollections;
    std::optional<std::vector<nlohmann::json>> fanCollections;
    std::vector<nlohmann::json> voltageCollections;
    BMCWEB_LOG_INFO << "setSensorOverride for subNode" << chassisSubNode
                    << "\n";

    if (chassisSubNode == "Thermal")
    {
        if (!json_util::readJson(req, res, "Temperatures",
                                 temperatureCollections, "Fans",
                                 fanCollections))
        {
            return;
        }
        if (!temperatureCollections && !fanCollections)
        {
            messages::resourceNotFound(res, "Thermal",
                                       "Temperatures / Voltages");
            res.end();
            return;
        }
        if (temperatureCollections)
        {
            allCollections.emplace("Temperatures",
                                   *std::move(temperatureCollections));
        }
        if (fanCollections)
        {
            allCollections.emplace("Fans", *std::move(fanCollections));
        }
    }
    else if (chassisSubNode == "Power")
    {
        if (!json_util::readJson(req, res, "Voltages", voltageCollections))
        {
            return;
        }
        allCollections.emplace("Voltages", std::move(voltageCollections));
    }
    else
    {
        res.result(boost::beast::http::status::not_found);
        res.end();
        return;
    }

    const char* propertyValueName;
    std::unordered_map<std::string, std::pair<double, std::string>> overrideMap;
    std::string memberId;
    double value;
    for (auto& collectionItems : allCollections)
    {
        if (collectionItems.first == "Temperatures")
        {
            propertyValueName = "ReadingCelsius";
        }
        else if (collectionItems.first == "Fans")
        {
            propertyValueName = "Reading";
        }
        else
        {
            propertyValueName = "ReadingVolts";
        }
        for (auto& item : collectionItems.second)
        {
            if (!json_util::readJson(item, res, "MemberId", memberId,
                                     propertyValueName, value))
            {
                return;
            }
            overrideMap.emplace(memberId,
                                std::make_pair(value, collectionItems.first));
        }
    }
    const std::string& chassisName = params[0];
    auto sensorAsyncResp = std::make_shared<SensorsAsyncResp>(
        res, chassisName, typeList, chassisSubNode);
    // first check for valid chassis id & sensor in requested chassis.
    auto getChassisSensorListCb = [sensorAsyncResp, overrideMap](
                                      const boost::container::flat_set<
                                          std::string>& sensorLists) {
        boost::container::flat_set<std::string> sensorNames;
        for (const auto& item : overrideMap)
        {
            const auto& sensor = item.first;
            if (sensorLists.find(item.first) == sensorLists.end())
            {
                BMCWEB_LOG_INFO << "Unable to find memberId " << item.first;
                messages::resourceNotFound(sensorAsyncResp->res,
                                           item.second.second, item.first);
                return;
            }
            sensorNames.emplace(sensor);
        }
        // Get the connection to which the memberId belongs
        auto getObjectsWithConnectionCb =
            [sensorAsyncResp, overrideMap](
                const boost::container::flat_set<std::string>& connections,
                const std::set<std::pair<std::string, std::string>>&
                    objectsWithConnection) {
                if (objectsWithConnection.size() != overrideMap.size())
                {
                    BMCWEB_LOG_INFO
                        << "Unable to find all objects with proper connection "
                        << objectsWithConnection.size() << " requested "
                        << overrideMap.size() << "\n";
                    messages::resourceNotFound(
                        sensorAsyncResp->res,
                        sensorAsyncResp->chassisSubNode == "Thermal"
                            ? "Temperatures"
                            : "Voltages",
                        "Count");
                    return;
                }
                for (const auto& item : objectsWithConnection)
                {

                    auto lastPos = item.first.rfind('/');
                    if (lastPos == std::string::npos)
                    {
                        messages::internalError(sensorAsyncResp->res);
                        return;
                    }
                    std::string sensorName = item.first.substr(lastPos + 1);

                    const auto& iterator = overrideMap.find(sensorName);
                    if (iterator == overrideMap.end())
                    {
                        BMCWEB_LOG_INFO << "Unable to find sensor object"
                                        << item.first << "\n";
                        messages::internalError(sensorAsyncResp->res);
                        return;
                    }
                    crow::connections::systemBus->async_method_call(
                        [sensorAsyncResp](const boost::system::error_code ec) {
                            if (ec)
                            {
                                BMCWEB_LOG_DEBUG
                                    << "setOverrideValueStatus DBUS error: "
                                    << ec;
                                messages::internalError(sensorAsyncResp->res);
                                return;
                            }
                        },
                        item.second, item.first,
                        "org.freedesktop.DBus.Properties", "Set",
                        "xyz.openbmc_project.Sensor.Value", "Value",
                        sdbusplus::message::variant<double>(
                            iterator->second.first));
                }
            };
        // Get object with connection for the given sensor name
        getObjectsWithConnection(sensorAsyncResp, sensorNames,
                                 std::move(getObjectsWithConnectionCb));
    };
    // get full sensor list for the given chassisId and cross verify the sensor.
    getChassis(sensorAsyncResp, std::move(getChassisSensorListCb));
}

} // namespace redfish

ext: hpp

max_stars_repo_name: steven-RD/bmcweb

max_issues_repo_name: steven-RD/bmcweb

max_forks_repo_name: steven-RD/bmcweb


text:
//
// Copyright © 2017 Arm Ltd. All rights reserved.
// SPDX-License-Identifier: MIT
//

#pragma once

#include <armnn/Tensor.hpp>

#include <boost/multi_array.hpp>

#include <cstddef>

template <std::size_t n>
boost::array<unsigned int, n> GetTensorShapeAsArray(const armnn::TensorInfo& tensorInfo)
{
    BOOST_ASSERT_MSG(n == tensorInfo.GetNumDimensions(),
        "Attempting to construct a shape array of mismatching size");

    boost::array<unsigned int, n> shape;
    for (unsigned int i = 0; i < n; i++)
    {
        shape[i] = tensorInfo.GetShape()[i];
    }
    return shape;
}

template <typename T, std::size_t n>
struct LayerTestResult
{
    LayerTestResult(const armnn::TensorInfo& outputInfo)
    {
        auto shape( GetTensorShapeAsArray<n>(outputInfo) );
        output.resize(shape);
        outputExpected.resize(shape);
        supported = true;
        compareBoolean = false;
    }

    boost::multi_array<T, n> output;
    boost::multi_array<T, n> outputExpected;
    bool supported;
    bool compareBoolean;
};

max_stars_repo_name: tom-gall/armnn

max_issues_repo_name: tom-gall/armnn

max_forks_repo_name: tom-gall/armnn


text:
#include <Access/AllowedClientHosts.h>
#include <Common/Exception.h>
#include <common/SimpleCache.h>
#include <Functions/likePatternToRegexp.h>
#include <Poco/Net/SocketAddress.h>
#include <Poco/RegularExpression.h>
#include <common/logger_useful.h>
#include <ext/scope_guard.h>
#include <boost/algorithm/string/replace.hpp>
#include <ifaddrs.h>

namespace DB
{
namespace ErrorCodes
{
    extern const int DNS_ERROR;
}

namespace
{
    using IPAddress = Poco::Net::IPAddress;
    using IPSubnet = AllowedClientHosts::IPSubnet;

    /// Converts an address to IPv6.
    /// The loopback address "127.0.0.1" (or any "127.x.y.z") is converted to "::1".
    IPAddress toIPv6(const IPAddress & ip)
    {
        IPAddress v6;
        if (ip.family() == IPAddress::IPv6)
            v6 = ip;
        else
            v6 = IPAddress("::ffff:" + ip.toString());

        // ::ffff:127.XX.XX.XX -> ::1
        if ((v6 & IPAddress(104, IPAddress::IPv6)) == IPAddress("::ffff:127.0.0.0"))
            v6 = IPAddress{"::1"};

        return v6;
    }

    IPSubnet toIPv6(const IPSubnet & subnet)
    {
        return IPSubnet(toIPv6(subnet.getPrefix()), subnet.getMask());
    }

    /// Helper function for isAddressOfHost().
    bool isAddressOfHostImpl(const IPAddress & address, const String & host)
    {
        IPAddress addr_v6 = toIPv6(address);

        /// Resolve by hand, because Poco don't use AI_ALL flag but we need it.
        addrinfo * ai_begin = nullptr;
        SCOPE_EXIT(
        {
            if (ai_begin)
                freeaddrinfo(ai_begin);
        });

        addrinfo hints;
        memset(&hints, 0, sizeof(hints));
        hints.ai_family = AF_UNSPEC;
        hints.ai_flags |= AI_V4MAPPED | AI_ALL;

        int err = getaddrinfo(host.c_str(), nullptr, &hints, &ai_begin);
        if (err)
            throw Exception("Cannot getaddrinfo(" + host + "): " + gai_strerror(err), ErrorCodes::DNS_ERROR);

        for (const addrinfo * ai = ai_begin; ai; ai = ai->ai_next)
        {
            if (ai->ai_addrlen && ai->ai_addr)
            {
                if (ai->ai_family == AF_INET)
                {
                    const auto & sin = *reinterpret_cast<const sockaddr_in *>(ai->ai_addr);
                    if (addr_v6 == toIPv6(IPAddress(&sin.sin_addr, sizeof(sin.sin_addr))))
                    {
                        return true;
                    }
                }
                else if (ai->ai_family == AF_INET6)
                {
                    const auto & sin = *reinterpret_cast<const sockaddr_in6*>(ai->ai_addr);
                    if (addr_v6 == IPAddress(&sin.sin6_addr, sizeof(sin.sin6_addr), sin.sin6_scope_id))
                    {
                        return true;
                    }
                }
            }
        }

        return false;
    }

    auto & getIsAddressOfHostCache()
    {
        static SimpleCache<decltype(isAddressOfHostImpl), isAddressOfHostImpl> cache;
        return cache;
    }

    /// Whether a specified address is one of the addresses of a specified host.
    bool isAddressOfHost(const IPAddress & address, const String & host)
    {
        /// We need to cache DNS requests.
        return getIsAddressOfHostCache()(address, host);
    }

    /// Helper function for isAddressOfLocalhost().
    std::vector<IPAddress> getAddressesOfLocalhostImpl()
    {
        std::vector<IPAddress> addresses;

        ifaddrs * ifa_begin = nullptr;
        SCOPE_EXIT({
            if (ifa_begin)
                freeifaddrs(ifa_begin);
        });

        int err = getifaddrs(&ifa_begin);
        if (err)
            return {IPAddress{"::1"}};

        for (const ifaddrs * ifa = ifa_begin; ifa; ifa = ifa->ifa_next)
        {
            if (!ifa->ifa_addr)
                continue;
            if (ifa->ifa_addr->sa_family == AF_INET)
            {
                const auto & sin = *reinterpret_cast<const sockaddr_in *>(ifa->ifa_addr);
                addresses.push_back(toIPv6(IPAddress(&sin.sin_addr, sizeof(sin.sin_addr))));
            }
            else if (ifa->ifa_addr->sa_family == AF_INET6)
            {
                const auto & sin = *reinterpret_cast<const sockaddr_in6 *>(ifa->ifa_addr);
                addresses.push_back(IPAddress(&sin.sin6_addr, sizeof(sin.sin6_addr), sin.sin6_scope_id));
            }
        }
        return addresses;
    }

    /// Whether a specified address is one of the addresses of the localhost.
    bool isAddressOfLocalhost(const IPAddress & address)
    {
        /// We need to cache DNS requests.
        static const std::vector<IPAddress> local_addresses = getAddressesOfLocalhostImpl();
        return boost::range::find(local_addresses, toIPv6(address)) != local_addresses.end();
    }

    /// Helper function for getHostByAddress().
    String getHostByAddressImpl(const IPAddress & address)
    {
        Poco::Net::SocketAddress sock_addr(address, 0);

        /// Resolve by hand, because Poco library doesn't have such functionality.
        char host[1024];
        int err = getnameinfo(sock_addr.addr(), sock_addr.length(), host, sizeof(host), nullptr, 0, NI_NAMEREQD);
        if (err)
            throw Exception("Cannot getnameinfo(" + address.toString() + "): " + gai_strerror(err), ErrorCodes::DNS_ERROR);

        /// Check that PTR record is resolved back to client address
        if (!isAddressOfHost(address, host))
            throw Exception("Host " + String(host) + " isn't resolved back to " + address.toString(), ErrorCodes::DNS_ERROR);

        return host;
    }

    auto & getHostByAddressCache()
    {
        static SimpleCache<decltype(getHostByAddressImpl), &getHostByAddressImpl> cache;
        return cache;
    }

    /// Returns the host name by its address.
    String getHostByAddress(const IPAddress & address)
    {
        /// We need to cache DNS requests.
        return getHostByAddressCache()(address);
    }

    void parseLikePatternIfIPSubnet(const String & pattern, IPSubnet & subnet, IPAddress::Family address_family)
    {
        size_t slash = pattern.find('/');
        if (slash != String::npos)
        {
            /// IP subnet, e.g. "192.168.0.0/16" or "192.168.0.0/255.255.0.0".
            subnet = IPSubnet{pattern};
            return;
        }

        bool has_wildcard = (pattern.find_first_of("%_") != String::npos);
        if (has_wildcard)
        {
            /// IP subnet specified with one of the wildcard characters, e.g. "192.168.%.%".
            String wildcard_replaced_with_zero_bits = pattern;
            String wildcard_replaced_with_one_bits = pattern;
            if (address_family == IPAddress::IPv6)
            {
                boost::algorithm::replace_all(wildcard_replaced_with_zero_bits, "_", "0");
                boost::algorithm::replace_all(wildcard_replaced_with_zero_bits, "%", "0000");
                boost::algorithm::replace_all(wildcard_replaced_with_one_bits, "_", "f");
                boost::algorithm::replace_all(wildcard_replaced_with_one_bits, "%", "ffff");
            }
            else if (address_family == IPAddress::IPv4)
            {
                boost::algorithm::replace_all(wildcard_replaced_with_zero_bits, "%", "0");
                boost::algorithm::replace_all(wildcard_replaced_with_one_bits, "%", "255");
            }

            IPAddress prefix{wildcard_replaced_with_zero_bits};
            IPAddress mask = ~(prefix ^ IPAddress{wildcard_replaced_with_one_bits});
            subnet = IPSubnet{prefix, mask};
            return;
        }

        /// Exact IP address.
        subnet = IPSubnet{pattern};
    }

    /// Extracts a subnet, a host name or a host name regular expession from a like pattern.
    void parseLikePattern(
        const String & pattern, std::optional<IPSubnet> & subnet, std::optional<String> & name, std::optional<String> & name_regexp)
    {
        /// If `host` starts with digits and a dot then it's an IP pattern, otherwise it's a hostname pattern.
        size_t first_not_digit = pattern.find_first_not_of("0123456789");
        if ((first_not_digit != String::npos) && (first_not_digit != 0) && (pattern[first_not_digit] == '.'))
        {
            parseLikePatternIfIPSubnet(pattern, subnet.emplace(), IPAddress::IPv4);
            return;
        }

        size_t first_not_hex = pattern.find_first_not_of("0123456789ABCDEFabcdef");
        if (((first_not_hex == 4) && pattern[first_not_hex] == ':') || pattern.starts_with("::"))
        {
            parseLikePatternIfIPSubnet(pattern, subnet.emplace(), IPAddress::IPv6);
            return;
        }

        bool has_wildcard = (pattern.find_first_of("%_") != String::npos);
        if (has_wildcard)
        {
            name_regexp = likePatternToRegexp(pattern);
            return;
        }

        name = pattern;
    }
}

bool AllowedClientHosts::contains(const IPAddress & client_address) const
{
    if (any_host)
        return true;

    IPAddress client_v6 = toIPv6(client_address);

    std::optional<bool> is_client_local_value;
    auto is_client_local = [&]
    {
        if (is_client_local_value)
            return *is_client_local_value;
        is_client_local_value = isAddressOfLocalhost(client_v6);
        return *is_client_local_value;
    };

    if (local_host && is_client_local())
        return true;

    /// Check `addresses`.
    auto check_address = [&](const IPAddress & address_)
    {
        IPAddress address_v6 = toIPv6(address_);
        if (address_v6.isLoopback())
            return is_client_local();
        return address_v6 == client_v6;
    };

    for (const auto & address : addresses)
        if (check_address(address))
            return true;

    /// Check `subnets`.
    auto check_subnet = [&](const IPSubnet & subnet_)
    {
        IPSubnet subnet_v6 = toIPv6(subnet_);
        if (subnet_v6.isMaskAllBitsOne())
            return check_address(subnet_v6.getPrefix());
        return (client_v6 & subnet_v6.getMask()) == subnet_v6.getPrefix();
    };

    for (const auto & subnet : subnets)
        if (check_subnet(subnet))
            return true;

    /// Check `names`.
    auto check_name = [&](const String & name_)
    {
        if (boost::iequals(name_, "localhost"))
            return is_client_local();
        try
        {
            return isAddressOfHost(client_v6, name_);
        }
        catch (const Exception & e)
        {
            if (e.code() != ErrorCodes::DNS_ERROR)
                throw;
            /// Try to ignore DNS errors: if host cannot be resolved, skip it and try next.
            LOG_WARNING(
                &Logger::get("AddressPatterns"),
                "Failed to check if the allowed client hosts contain address {}. {}, code = {}",
                client_address.toString(), e.displayText(), e.code());
            return false;
        }
    };

    for (const String & name : names)
        if (check_name(name))
            return true;

    /// Check `name_regexps`.
    std::optional<String> resolved_host;
    auto check_name_regexp = [&](const String & name_regexp_)
    {
        try
        {
            if (boost::iequals(name_regexp_, "localhost"))
                return is_client_local();
            if (!resolved_host)
                resolved_host = getHostByAddress(client_v6);
            if (resolved_host->empty())
                return false;
            Poco::RegularExpression re(name_regexp_);
            Poco::RegularExpression::Match match;
            return re.match(*resolved_host, match) != 0;
        }
        catch (const Exception & e)
        {
            if (e.code() != ErrorCodes::DNS_ERROR)
                throw;
            /// Try to ignore DNS errors: if host cannot be resolved, skip it and try next.
            LOG_WARNING(
                &Logger::get("AddressPatterns"),
                "Failed to check if the allowed client hosts contain address {}. {}, code = {}",
                client_address.toString(), e.displayText(), e.code());
            return false;
        }
    };

    for (const String & name_regexp : name_regexps)
        if (check_name_regexp(name_regexp))
            return true;

    auto check_like_pattern = [&](const String & pattern)
    {
        std::optional<IPSubnet> subnet;
        std::optional<String> name;
        std::optional<String> name_regexp;
        parseLikePattern(pattern, subnet, name, name_regexp);
        if (subnet)
            return check_subnet(*subnet);
        else if (name)
            return check_name(*name);
        else if (name_regexp)
            return check_name_regexp(*name_regexp);
        else
            return false;
    };

    for (const String & like_pattern : like_patterns)
        if (check_like_pattern(like_pattern))
            return true;

    return false;
}

void AllowedClientHosts::dropDNSCaches()
{
    getIsAddressOfHostCache().drop();
    getHostByAddressCache().drop();
}

}

ext: cpp

max_stars_repo_name: andresokol/ClickHouse

max_issues_repo_name: andresokol/ClickHouse

max_forks_repo_name: andresokol/ClickHouse


text:
// Copyright (C) 2016-2018 Internet Systems Consortium, Inc. ("ISC")
//
// 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 <config.h>

#include <http/request.h>
#include <boost/algorithm/string.hpp>
#include <boost/lexical_cast.hpp>
#include <sstream>

namespace {

/// @brief New line (CRLF).
const std::string crlf = "\r\n";

}

namespace isc {
namespace http {

HttpRequest::HttpRequest()
    : HttpMessage(INBOUND), required_methods_(),
      method_(Method::HTTP_METHOD_UNKNOWN),
      context_(new HttpRequestContext()) {
}

HttpRequest::HttpRequest(const Method& method, const std::string& uri,
                         const HttpVersion& version)
    : HttpMessage(OUTBOUND), required_methods_(),
      method_(Method::HTTP_METHOD_UNKNOWN),
      context_(new HttpRequestContext()) {
    context()->method_ = methodToString(method);
    context()->uri_ = uri;
    context()->http_version_major_ = version.major_;
    context()->http_version_minor_ = version.minor_;
}

void
HttpRequest::requireHttpMethod(const HttpRequest::Method& method) {
    required_methods_.insert(method);
}

void
HttpRequest::create() {
    try {
        // The RequestParser doesn't validate the method name. Thus, this
        // may throw an exception. But, we're fine with lower case names,
        // e.g. get, post etc.
        method_ = methodFromString(context_->method_);

        // Check if the method is allowed for this request.
        if (!inRequiredSet(method_, required_methods_)) {
            isc_throw(BadValue, "use of HTTP " << methodToString(method_)
                      << " not allowed");
        }

        http_version_.major_ = context_->http_version_major_;
        http_version_.minor_ = context_->http_version_minor_;

        // Check if the HTTP version is allowed for this request.
        if (!inRequiredSet(http_version_, required_versions_)) {
            isc_throw(BadValue, "use of HTTP version "
                      << http_version_.major_ << "."
                      << http_version_.minor_
                      << " not allowed");
        }

        // Copy headers from the context.
        for (auto header = context_->headers_.begin();
             header != context_->headers_.end();
             ++header) {
            HttpHeaderPtr hdr(new HttpHeader(header->name_, header->value_));
            headers_[hdr->getLowerCaseName()] = hdr;
        }

        if (getDirection() == HttpMessage::OUTBOUND) {
            HttpHeaderPtr hdr(new HttpHeader("Content-Length",
                                             boost::lexical_cast<std::string>(context_->body_.length())));
            headers_["content-length"] = hdr;
        }

        // Iterate over required headers and check that they exist
        // in the HTTP request.
        for (auto req_header = required_headers_.begin();
             req_header != required_headers_.end();
             ++req_header) {
            auto header = headers_.find(req_header->first);
            if (header == headers_.end()) {
                isc_throw(BadValue, "required header " << req_header->first
                          << " not found in the HTTP request");
            } else if (!req_header->second->getValue().empty() &&
                       !header->second->isValueEqual(req_header->second->getValue())) {
                // If specific value is required for the header, check
                // that the value in the HTTP request matches it.
                isc_throw(BadValue, "required header's " << header->first
                          << " value is " << req_header->second->getValue()
                          << ", but " << header->second->getValue() << " was found");
            }
        }

    } catch (const std::exception& ex) {
        // Reset the state of the object if we failed at any point.
        reset();
        isc_throw(HttpRequestError, ex.what());
    }

    // All ok.
    created_ = true;
}

void
HttpRequest::finalize() {
    if (!created_) {
        create();
    }

    // Copy the body from the context. Derive classes may further
    // interpret the body contents, e.g. against the Content-Type.
    finalized_ = true;
}

void
HttpRequest::reset() {
    created_ = false;
    finalized_ = false;
    method_ = HttpRequest::Method::HTTP_METHOD_UNKNOWN;
    headers_.clear();
}

HttpRequest::Method
HttpRequest::getMethod() const {
    checkCreated();
    return (method_);
}

std::string
HttpRequest::getUri() const {
    checkCreated();
    return (context_->uri_);
}

std::string
HttpRequest::getBody() const {
    checkFinalized();
    return (context_->body_);
}

std::string
HttpRequest::toBriefString() const {
    checkFinalized();

    std::ostringstream s;
    s << methodToString(getMethod()) << " " << getUri() << " HTTP/" <<
        getHttpVersion().major_ << "." << getHttpVersion().minor_;
    return (s.str());
}

std::string
HttpRequest::toString() const {
    checkFinalized();

    std::ostringstream s;
    // HTTP method, URI and version number.
    s << toBriefString() << crlf;

    for (auto header_it = headers_.cbegin(); header_it != headers_.cend();
         ++header_it) {
        s << header_it->second->getName() << ": " << header_it->second->getValue()
          << crlf;
    }

    s << crlf;

    s << getBody();

    return (s.str());
}

bool
HttpRequest::isPersistent() const {
    HttpHeaderPtr conn;

    try {
        conn = getHeader("connection");

    } catch (...) {
        // If there is an exception, it means that the header was not found.
    }

    std::string conn_value;
    if (conn) {
        conn_value = conn->getLowerCaseValue();
    }

    HttpVersion ver = getHttpVersion();

    return (((ver == HttpVersion::HTTP_10()) && (conn_value == "keep-alive")) ||
            ((HttpVersion::HTTP_10() < ver) && (conn_value.empty() || (conn_value != "close"))));
}

HttpRequest::Method
HttpRequest::methodFromString(std::string method) const {
    boost::to_upper(method);
    if (method == "GET") {
        return (Method::HTTP_GET);
    } else if (method == "POST") {
        return (Method::HTTP_POST);
    } else if (method == "HEAD") {
        return (Method::HTTP_HEAD);
    } else if (method == "PUT") {
        return (Method::HTTP_PUT);
    } else if (method == "DELETE") {
        return (Method::HTTP_DELETE);
    } else if (method == "OPTIONS") {
        return (Method::HTTP_OPTIONS);
    } else if (method == "CONNECT") {
        return (Method::HTTP_CONNECT);
    } else {
        isc_throw(HttpRequestError, "unknown HTTP method " << method);
    }
}

std::string
HttpRequest::methodToString(const HttpRequest::Method& method) const {
    switch (method) {
    case Method::HTTP_GET:
        return ("GET");
    case Method::HTTP_POST:
        return ("POST");
    case Method::HTTP_HEAD:
        return ("HEAD");
    case Method::HTTP_PUT:
        return ("PUT");
    case Method::HTTP_DELETE:
        return ("DELETE");
    case Method::HTTP_OPTIONS:
        return ("OPTIONS");
    case Method::HTTP_CONNECT:
        return ("CONNECT");
    default:
        return ("unknown HTTP method");
    }
}

}
}

ext: cc

max_stars_repo_name: mcr/kea

max_issues_repo_name: jxiaobin/kea

max_forks_repo_name: jxiaobin/kea


text:
#ifndef SAXQUANTIZER_HPP
#define SAXQUANTIZER_HPP

#include "../CAPCA.h"
#include <deque>
#include <vector>
#include <cassert>
#include <boost/math/distributions/normal.hpp>

using std::deque;
using std::vector;
using namespace std;
namespace SaxQuantizer {

	inline void fill_cutpoints(const size_t& alphabet_size, vector<double> *cutpoints) {
		assert(alphabet_size > 0);
		static boost::math::normal dist(0.0, 1.0);
		//std::cout << "alphabet: " << alphabet_size << std::endl;
		cutpoints->reserve(alphabet_size);
		cutpoints->push_back(-DBL_MAX);
		//cout << "cdf: ";
		for (size_t i = 1; i < alphabet_size; ++i) {
			double cdf = ((double)i) / alphabet_size;
			//cout << quantile(dist, cdf) << " ";
			cutpoints->push_back(quantile(dist, cdf));
			//cout << cutpoints->begin();
		}
		//cout << endl;
	}

	/**
	 * Symbolic Aggregate Approximation with fractional sliding window, numerosity reduction, and scaling
	 */
	class SAX : virtual public APCA_QUAL {
	private:
		size_t m_window_size;
		size_t m_string_size;// the number of segments, N .
		size_t m_alphabet_size;

		double m_baseline_mean;
		double m_baseline_stdev;
		vector<double> m_cutpoints;

		bool m_trained;

		size_t segment_number;//200923

		/**
		 * SAX with fractional sliding window and automatic scaling.
		 * @param <it>: start iterator
		 * @param <end>: end iterator
		 * @param <syms> (out): quantized range
		 */
		template<class Iter>
		void saxify(Iter it, const Iter end, vector<int> *syms) {
			// perform PAA using a fractional sliding window
		   // double paa[m_string_size];
			double* paa = new double[m_string_size];
			double paa_window = ((double)m_window_size) / m_string_size;

			double p = 0; // p for progress
			double w = 1; // w for weight
			size_t available = 0;

			for (size_t i = 0; i < m_string_size && it != end; ++i, ++available) {
				// normalize around baseline

				double normalized = (*it - m_baseline_mean) / m_baseline_stdev;

				paa[i] = 0;
				double j = 0;

				while (j < paa_window && it != end) {

					paa[i] += w * normalized; // sum of (partial) elements inside the window
					j += w;
					p += w;

					// window full
					if (paa_window == p) {

						if (fabs(w - 1.0) <= 0.01) {   // if last element fully consumed,
							++it;                        // then just move next.
						}
						else {                       // o.w.,
							w = 1.0 - w;                 // set remaining portion.
						}
						p = 0;                         // reset progress

					  // window not full, but next must be split
					}
					else if (paa_window - p < 1.0) {

						w = paa_window - p;            // set needed portion
						++it;                          // move to next

					  // window not full, next can be fully consumed
					}
					else {
						++it;                          // move to next
					}
				}

				paa[i] /= j; // averaging
			}

			// map to symbols. 0-based.
			//cout << "available" << available << endl;
			for (size_t i = 0; i < available; ++i) {
				int cnt = -1;
				for (const auto & cp : m_cutpoints) {
					if (paa[i] >= cp) ++cnt;
				}
				syms->push_back(cnt);
			}
			delete[] paa;
		}

	public:
		/**
		* Constructs a SAX quantizer of a given window size, string size and alphabet size.
		* @param <window_size>: sliding window size
		* @param <string_size>: output string size for each sliding window (can be greater than window_size)
		* @param <alphabet_size>: number of codewords
		*/
		SAX(size_t window_size, size_t string_size, size_t alphabet_size)
			: m_window_size(window_size), m_string_size(string_size), m_alphabet_size(alphabet_size),
			m_baseline_mean(0), m_baseline_stdev(1), m_trained(false) {

			assert(window_size > 0);
			assert(string_size > 0);
			assert(alphabet_size > 0);

			fill_cutpoints(alphabet_size, &m_cutpoints);
		}

		/**
		* Constructs a SAX quantizer of timeseries and alphabet size.
		* @param <window_size>: sliding window size
		* @param <string_size>: output string size for each sliding window (can be greater than window_size)
		* @param <alphabet_size>: number of codewords

		*/
		SAX(const size_t& alphabet_size): m_window_size(1), m_string_size(1), m_alphabet_size(alphabet_size),m_baseline_mean(0), m_baseline_stdev(1), m_trained(false) {

			assert(alphabet_size > 0);

			fill_cutpoints(alphabet_size, &m_cutpoints);
		}

		virtual ~SAX() {
			m_cutpoints.clear();
		}

		/**
		 * Trains the quantizer from a given sample. This sets the baseline mean and stdevs, which are used in
		 * normalizing the input.
		 *
		 * @param <samples>: list of training values
		 */
		template<typename Container>
		void train(const Container & samples) {
			double mean = 0;
			double stdev = DBL_MIN;

			assert(!samples.empty());

			if (samples.size() < 2) {
				mean = samples[0];
				stdev = DBL_MIN;

			}
			else {
				size_t n = 0;
				double M2 = 0;
				for (const auto & val : samples) {
					++n;
					double delta = val - mean;
					mean += delta / n;
					M2 += delta * (val - mean);
				}
				stdev = sqrt(M2 / (n - 1));
			}

			if (stdev == 0) stdev = DBL_MIN;

			m_baseline_mean = mean;
			m_baseline_stdev = stdev;

			m_trained = true;
		}

		template<typename Container>
		size_t quantize(const Container & seq, vector<int> *qseq, bool reduce = true) {
			if (!m_trained) train(seq);

			vector<int> buf1, buf2;
			auto *syms_buf = &buf1;
			auto *old_syms_buf = &buf2;

			size_t consumed = 0;
			for (consumed = 0; consumed < seq.size(); ++consumed) {

				if (reduce) { // run-length numerosity reduction
					syms_buf->clear();
					saxify(seq.begin() + consumed, seq.end(), syms_buf);

					// skip window if same as previous
					if (*syms_buf != *old_syms_buf) {
						qseq->insert(qseq->end(), syms_buf->begin(), syms_buf->end());
						std::swap(syms_buf, old_syms_buf);
					}

				}
				else { // no reduction
					saxify(seq.begin() + consumed, seq.end(), qseq);
				}

				// ignore excess elements, if sequence size isn't a multiple of window size
				//if (seq.size() - consumed <= m_window_size) break;
			}

			return consumed;
		}

		/**
		* Constructs a SAX quantizer of timeseries and alphabet size.
		* @param <window_size>: sliding window size
		* @param <string_size>: output string size for each sliding window (can be greater than window_size)
		* @param <alphabet_size>: number of codewords
		* @date : 2018/3/31 15:48
		* @author :
		*/
		template<typename Container>
		size_t getSAX(const Container& seq, vector<char>& qseq) {
			if (!m_trained) train(seq);
			double normalized = NULL;
			for (auto& it : seq) {
				//cout << it << endl;
				normalized = (it - m_baseline_mean) / m_baseline_stdev;
				int cnt = -1;
				//cout << "*******************************************" << endl;
				for (const auto & cp : m_cutpoints) {
					//cout << normalized << ", " << cp << ", " << (normalized > cp ? true:false) << endl;
					if (normalized >= cp) ++cnt;
				}
				qseq.push_back(static_cast<char>(cnt + 65));
			}

			return 0;
		}

		/**
		 * Returns the order of the quantizer (here, the window size)
		 */
		inline size_t order() const {
			return m_window_size;
		}

		inline double ratio() const {
			return ((double)m_window_size) / m_string_size;
		}

		template<typename T, typename Y, typename U>
		void get_SAX(const vector<T>& const original_time_series_vector, const Y& const segment_number, const U& const SAX_container) {

			vector<double> paa_vector;
			vector<int> SAX_quantizer_vector;

			APCA_QUAL::get_PAA(original_time_series_vector, segment_number, SAX_container);

			for (int i = 0; i < segment_number; i++) {
				paa_vector.emplace_back(SAX_container.v[i]);
			}

			quantize(paa_vector, &SAX_quantizer_vector, false);

			copy_n(SAX_quantizer_vector.begin(), SAX_quantizer_vector.size(), SAX_container.v);

		}

		/**
		* @Name: distance_cell
		* @Qualifier: cell(r,c)
		* @Date: 200923
		* @author:
		*/
		template<typename T>
		inline double get_distance_cell(const T& const vaule_1, const T& const vaule_2) {
			if (fabs(vaule_1 - vaule_2) <= 1) {
				return 0;
			}
			else {
				return m_cutpoints[max(vaule_1 + 1, vaule_2 + 1) - 1] - m_cutpoints[min(vaule_1 + 1, vaule_2 + 1)];
			}
		}

		template<typename T>
		double distance_LB_SAX(const T& const SAX_container1, const T& const SAX_container2) {

			const auto& const QProjection = SAX_container1;
			const auto& const italicC = SAX_container2;

			int i = 0, j = 0;
			double distance = 0;

			double sum = (italicC.r[0] + 1) * pow(get_distance_cell(QProjection.v[0], italicC.v[0]), 2);

			for (i = 1; i < italicC.segmentNum; i++) {
				sum += (italicC.r[i] - italicC.r[i - 1]) * pow( get_distance_cell( QProjection.v[i], italicC.v[i] ), 2 );
			}
			distance = sqrt(sum);
			return distance;
		}
	};
}

#endif


text:
#include "formant.h"
#include <Eigen/Dense>

using namespace Analysis::Formant;
using Analysis::FormantResult;

using namespace Eigen;

struct Analysis::Formant::KarmaState
{
    int numF;
    VectorXd y;
    MatrixXd F;
    MatrixXd Q;
    MatrixXd R;
    VectorXd m_up;
    VectorXd P_up;
};

constexpr int ncep = 15;
constexpr int numF = 3;

Karma::Karma()
    : state(new KarmaState)
{
    state->F.setIdentity(2 * numF, 2 * numF);

    state->Q.setZero(2 * numF, 2 * numF);
    state->Q.diagonal().head(numF).setConstant(320 * 320);
    state->Q.diagonal().tail(numF).setConstant(100 * 100);

    state->R.setZero(ncep, ncep);
    for (int i = 0; i < ncep; ++i) {
        state->R(i, i) = 1.0 / (double) (i + 1);
    }

    VectorXd x0(2 * numF);
    x0 << 500, 1500, 2500,
           80,  120,  160;

    state->m_up = x0;
    state->P_up = state->Q;
}

Karma::~Karma()
{
    delete state;
}

static VectorXd calcCepstrumCoefs(const double *lpc, int lpcOrder, int ncep);
static MatrixXd calcMatrixH(const VectorXd& m, int cepOrder, double Fs);
static VectorXd calcCepstrumMapping(const VectorXd& m, int cepOrder, double Fs);

FormantResult Karma::solve(const double *lpc, int lpcOrder, double sampleRate)
{
    auto& F  = state->F;
    auto  Ft = state->F.transpose();
    auto& Q  = state->Q;
    auto& R  = state->R;

    auto m_pred = F * state->m_up;
    auto P_pred = F * state->P_up * Ft + Q;

    auto H  = calcMatrixH(m_pred, ncep, sampleRate);
    auto Ht = H.transpose();

    auto S = H * P_pred * Ht + R;
    auto K = (P_pred * Ht) * S.colPivHouseholderQr().inverse();

    auto y_pred = calcCepstrumMapping(m_pred, ncep, sampleRate);
    auto y      = calcCepstrumCoefs(lpc, lpcOrder, ncep);

    state->m_up = m_pred + K * (y - y_pred);
    state->P_up = P_pred - K * H * P_pred;

    rpm::vector<FormantData> formants(numF);
    for (int i = 0; i < numF; ++i) {
        formants[i] = {
            .frequency = state->m_up(i),
            .bandwidth = state->m_up(numF + i),
        };
    }

    return { .formants = formants };
}

VectorXd calcCepstrumCoefs(const double *lpc, int lpcOrder, int ncep)
{
    VectorXd C(ncep);

    for (int n = 1; n <= ncep; ++n) {
        if (n == 1) {
            C(n - 1) = lpc[n - 1];
        }
        else if (n <= lpcOrder) {
            C(n - 1) = lpc[n - 1];
            for (int i = 1; i <= ncep - 1; ++i) {
                C(n - 1) += (double) i / (double) n * lpc[n - i - 1] * C(i - 1);
            }
        }
        else {
            C(n - 1) = 0.0;
            for (int i = ncep - lpcOrder; i <= ncep - 1; ++i) {
                C(n - 1) += (double) i / (double) n * lpc[n - i - 1] * C(i - 1);
            }
        }
    }

    return C;
}

MatrixXd calcMatrixH(const VectorXd &m, int cepOrder, double Fs)
{
    const int numF = m.size() / 2;
    auto freq = m.segment(0, numF);
    auto band = m.segment(numF, numF);

    MatrixXd H(cepOrder, 2 * numF);

    for (int i = 0; i < cepOrder; ++i) {
        for (int j = 0; j < numF; ++j) {
            const double bwTerm = exp((-M_PI * (i + 1) * band(j)) / Fs);

            H(i, j)        = -4.0 * M_PI / Fs * bwTerm * sin((2.0 * M_PI * (i + 1) * freq(j)) / Fs);
            H(i, numF + j) = -2.0 * M_PI / Fs * bwTerm * cos((2.0 * M_PI * (i + 1) * freq(j)) / Fs);
        }
    }

    return H;
}

VectorXd calcCepstrumMapping(const VectorXd& m, int cepOrder, double Fs)
{
    const int numF = m.size() / 2;
    auto freq = m.segment(0, numF);
    auto band = m.segment(numF, numF);

    VectorXd C_int(numF);
    VectorXd C(cepOrder);

    for (int i = 0; i < cepOrder; ++i) {
        for (int p = 0; p < numF; ++p) {
            const double bwTerm = (2.0 / (double) (i + 1)) * exp((-M_PI * (i + 1) * band(p)) / Fs);
            C_int(p) = bwTerm * cos((2.0 * M_PI * (i + 1) * freq(p)) / Fs);
        }
        C(i) = C_int.sum();
    }

    return C;
}

max_stars_repo_name: alargepileofash/in-formant

max_issues_repo_name: alargepileofash/in-formant

max_forks_repo_name: alargepileofash/in-formant


text:
// Copyright (C) 2004-2012 The Trustees of Indiana University.

// Use, modification and distribution is subject to the Boost Software
// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)

//  Authors: Nicholas Edmonds
//           Douglas Gregor
//           Andrew Lumsdaine

// The placement of this #include probably looks very odd relative to
// the #ifndef/#define pair below. However, this placement is
// extremely important to allow the various property map headers to be
// included in any order.
#include <boost/property_map/property_map.hpp>

#ifndef BOOST_PARALLEL_LOCAL_PROPERTY_MAP_HPP
#define BOOST_PARALLEL_LOCAL_PROPERTY_MAP_HPP

#ifndef BOOST_GRAPH_USE_MPI
#error "Parallel BGL files should not be included unless <boost/graph/use_mpi.hpp> has been included"
#endif

#include <cassert>

namespace boost {
  /** Property map that accesses an underlying, local property map
   * using a subset of the global keys.
   */
  template<typename GlobalMap, typename StorageMap>
  class local_property_map
  {
    typedef typename property_traits<GlobalMap>::value_type owner_local_pair;

  public:
    typedef typename property_traits<StorageMap>::value_type value_type;
    typedef typename property_traits<GlobalMap>::key_type key_type;
    typedef typename property_traits<StorageMap>::reference  reference;
    typedef typename property_traits<StorageMap>::category   category;

    local_property_map() { }

    local_property_map(amplusplus::transport& trans,
                       const GlobalMap& global, const StorageMap& storage)
      : transport_(trans), global_(global), storage(storage) { }

    // Cast away the const'ness of the transport since the const graph it comes
    // from is in sequential BGL and I don't want to pull in that whole library
    // to modify it -- this is not safe, but it is expedient (NGE)
    local_property_map(const amplusplus::transport& trans,
                       const GlobalMap& global, const StorageMap& storage)
      : transport_(const_cast<amplusplus::transport&>(trans)), global_(global), storage(storage) { }

    reference operator[](const key_type& key)
    {
      owner_local_pair p = get(global_, key);
      assert(p.first == transport_.rank());
      return storage[p.second];
    }

    GlobalMap& global() const { return global_; }
    StorageMap& base() const { return storage; }

    amplusplus::transport& transport()       { return transport_; }
    amplusplus::transport& transport() const { return transport_; }

  private:
    amplusplus::transport& transport_;
    mutable GlobalMap global_;
    mutable StorageMap storage;
  };

  template<typename GlobalMap, typename StorageMap>
  inline
  typename local_property_map<GlobalMap, StorageMap>::reference
  get(const local_property_map<GlobalMap, StorageMap>& pm,
      typename local_property_map<GlobalMap, StorageMap>::key_type
        const & key)

  {
    typename property_traits<GlobalMap>::value_type p = get(pm.global(), key);
    return get(pm.base(), p.second);
  }

  template<typename GlobalMap, typename StorageMap>
  inline void
  put(const local_property_map<GlobalMap, StorageMap>& pm,
      typename local_property_map<GlobalMap, StorageMap>
                 ::key_type const & key,
      typename local_property_map<GlobalMap, StorageMap>
                 ::value_type const& v)
  {
    typename property_traits<GlobalMap>::value_type p = get(pm.global(), key);
    assert(p.first == pm.transport().rank());
    put(pm.base(), p.second, v);
  }

  template<typename GlobalMap, typename StorageMap>
  inline bool
  exchange(const local_property_map<GlobalMap, StorageMap>& pm,
	   typename local_property_map<GlobalMap, StorageMap>
	              ::key_type const & key,
	   typename local_property_map<GlobalMap, StorageMap>
	              ::value_type const& oldval,
	   typename local_property_map<GlobalMap, StorageMap>
                      ::value_type const& newval)
  {
    typename property_traits<GlobalMap>::value_type p = get(pm.global(), key);
    assert(p.first == pm.transport().rank());
    return exchange(pm.base(), p.second, oldval, newval);
  }

  template<typename GlobalMap, typename StorageMap>
  inline bool
  maybe_exchange(const local_property_map<GlobalMap, StorageMap>& pm,
		 typename local_property_map<GlobalMap, StorageMap>
	                    ::key_type const & key,
		 typename local_property_map<GlobalMap, StorageMap>
	                    ::value_type const& oldval,
		 typename local_property_map<GlobalMap, StorageMap>
                            ::value_type const& newval)
  {
    typename property_traits<GlobalMap>::value_type p = get(pm.global(), key);
    assert(p.first == pm.transport().rank());
    return maybe_exchange(pm.base(), p.second, oldval, newval);
  }
} // end namespace boost
#endif // BOOST_PARALLEL_LOCAL_PROPERTY_MAP_HPP

max_stars_repo_name: thejkane/AGM

max_issues_repo_name: thejkane/AGM

max_forks_repo_name: thejkane/AGM


text:
#include <gtest/gtest.h>
#include <gmock/gmock.h>
#define BOOST_FILESYSTEM_NO_DEPRECATED
#define BOOST_NO_CXX11_SCOPED_ENUMS
#include <boost/filesystem.hpp>
#include <fstream>

#include "fileman/cache_manager.h"

using namespace testing;
using namespace std;

TEST(CacheManager, CacheDir)
{
	auto tmp = fs::temp_directory_path();

	// disabled due to problems on windows machines
	// EXPECT_THROW(cache_manager m("/a"), fm_exception);
	// EXPECT_THROW(cache_manager m("/a/"), fm_exception);
	// EXPECT_THROW(cache_manager o(""), fm_exception);

	EXPECT_NO_THROW(cache_manager p(tmp.string()));
	EXPECT_NO_THROW(cache_manager q("/tmp/"));
	EXPECT_NO_THROW(cache_manager r((tmp / "recodex" / "subdir").string()));
	EXPECT_TRUE(fs::is_directory(tmp / "recodex" / "subdir"));
	fs::remove_all(tmp / "recodex");
}

TEST(CacheManager, GetExistingFile)
{
	auto tmp = fs::temp_directory_path();
	// std::string cache_path_name = "/tmp/recodex/";
	// fs::path cache_path(cache_path_name);
	fs::create_directory(tmp / "recodex");
	{
		ofstream file((tmp / "recodex" / "test.txt").string());
		file << "testing input" << endl;
	}
	cache_manager m((tmp / "recodex").string());
	// Copy file to existing directory
	m.get_file("test.txt", (tmp / "test.txt").string());
	EXPECT_TRUE(fs::is_regular_file((tmp / "test.txt").string()));

	// Copy the same file to same directory - should be overriden
	EXPECT_NO_THROW(m.get_file("test.txt", (tmp / "test.txt").string()));

	// Copy file to nonexisting directory
	EXPECT_THROW(m.get_file("test.txt", (tmp / "recodex" / "nonexist" / "test.txt").string()), fm_exception);

	// Clean used resources
	fs::remove(tmp / "test.txt");
	fs::remove_all(tmp / "recodex");
}

TEST(CacheManager, GetNonexistingFile)
{
	auto tmp = fs::temp_directory_path();
	cache_manager m(tmp.string());
	EXPECT_THROW(m.get_file("ab5cd.txt", "~"), fm_exception);
	EXPECT_THROW(m.get_file((tmp / "as4df.txt").string(), "~"), fm_exception);
	EXPECT_THROW(m.get_file("ab5cd.txt", "/a"), fm_exception);
}

TEST(CacheManager, PutExistingFile)
{
	auto tmp = fs::temp_directory_path();
	{
		ofstream file((tmp / "test.txt").string());
		file << "testing input" << endl;
	}
	cache_manager m((tmp / "recodex").string());
	EXPECT_NO_THROW(m.put_file((tmp / "test.txt").string(), "test.txt"));
	EXPECT_TRUE(fs::is_regular_file((tmp / "recodex" / "test.txt").string()));
	fs::remove((tmp / "test.txt").string());
	fs::remove_all((tmp / "recodex").string());
}

TEST(CacheManager, PutNonexistingFile)
{
	auto tmp = fs::temp_directory_path();
	cache_manager m((tmp / "recodex").string());
	EXPECT_THROW(m.put_file((tmp / "as4df.txt").string(), "as4df.txt"), fm_exception);
	fs::remove_all((tmp / "recodex").string());
}

max_stars_repo_name: rqu/worker

max_issues_repo_name: rqu/worker

max_forks_repo_name: rqu/worker


text:
/*
==============================================================================
Kratos
A General Purpose Software for Multi-Physics Finite Element Analysis
Version 1.0 (Released on march 05, 2007).

Copyright 2007
Pooyan Dadvand, Riccardo Rossi
pooyan@cimne.upc.edu
rrossi@cimne.upc.edu
CIMNE (International Center for Numerical Methods in Engineering),
Gran Capita' s/n, 08034 Barcelona, Spain

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 condition:

Distribution of this code for  any  commercial purpose  is permissible
ONLY BY DIRECT ARRANGEMENT WITH THE COPYRIGHT OWNER.

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.

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

//
//   Project Name:        Kratos
//   Last modified by:    $Author: rrossi $
//   Date:                $Date: 2007-10-24 08:20:31 $
//   Revision:            $Revision: 1.5 $
//
//

// System includes

// External includes
#include <boost/python.hpp>

// Project includes
#include "includes/define.h"
#include "processes/process.h"
#include "python/add_utilities_to_python.h"
#include "utilities/variable_utils.h"
#include "utilities/normal_calculation_utils.h"
#include "utilities/body_normal_calculation_utils.h"
#include "utilities/body_distance_calculation_utils.h"

namespace Kratos
{

namespace Python
{

  void  AddUtilitiesToPython()
  {
	using namespace boost::python;

	  class_<VariableUtils>("VariableUtils", init<>())
		.def("SaveVectorVar",&VariableUtils::SaveVectorVar)
		.def("SaveScalarVar",&VariableUtils::SaveScalarVar)
		.def("SelectNodeList",&VariableUtils::SelectNodeList)
		.def("CopyVectorVar",&VariableUtils::CopyVectorVar)
		.def("CopyScalarVar",&VariableUtils::CopyScalarVar)
		.def("SetToZero_VectorVar",&VariableUtils::SetToZero_VectorVar)
		.def("SetToZero_ScalarVar",&VariableUtils::SetToZero_ScalarVar)
		;

	  class_<NormalCalculationUtils>("NormalCalculationUtils", init<>())
		.def("CalculateOnSimplex",&NormalCalculationUtils::CalculateOnSimplex)
		;

	  class_<BodyNormalCalculationUtils>("BodyNormalCalculationUtils", init<>())
		.def("CalculateBodyNormals",&BodyNormalCalculationUtils::CalculateBodyNormals)
		;

	  class_<BodyDistanceCalculationUtils>("BodyDistanceCalculationUtils", init<>())
			  .def("CalculateDistances2D",&BodyDistanceCalculationUtils::CalculateDistances<2>)
			  .def("CalculateDistances3D",&BodyDistanceCalculationUtils::CalculateDistances<3>)
			  ;
  }

}  // namespace Python.

} // Namespace Kratos