<commit_before>#include "wrap_joint.hpp"

#include <boost/python.hpp>
#include <Box2D/Dynamics/b2Body.h>
#include <Box2D/Dynamics/Joints/b2DistanceJoint.h>
#include <Box2D/Dynamics/Joints/b2FrictionJoint.h>
#include <Box2D/Dynamics/Joints/b2GearJoint.h>
#include <Box2D/Dynamics/Joints/b2Joint.h>
#include <Box2D/Dynamics/Joints/b2LineJoint.h>
#include <Box2D/Dynamics/Joints/b2MouseJoint.h>
#include <Box2D/Dynamics/Joints/b2PrismaticJoint.h>
#include <Box2D/Dynamics/Joints/b2PulleyJoint.h>
#include <Box2D/Dynamics/Joints/b2RevoluteJoint.h>
#include <Box2D/Dynamics/Joints/b2WeldJoint.h>

using namespace boost::python;

namespace pysics {
    void wrap_joint_type()
    {
        enum_<b2JointType>("JointType")
            .value("UNKNOWN_JOINT", e_unknownJoint)
            .value("REVOLUTE_JOINT", e_revoluteJoint)
            .value("PRISMATIC_JOINT", e_prismaticJoint)
            .value("DISTANCE_JOINT", e_distanceJoint)
            .value("PULLEY_JOINT", e_pulleyJoint)
            .value("MOUSE_JOINT", e_mouseJoint)
            .value("GEAR_JOINT", e_gearJoint)
            .value("LINE_JOINT", e_lineJoint)
            .value("WELD_JOINT", e_weldJoint)
            .value("FRICTION_JOINT", e_frictionJoint)
            .export_values()
        ;
    }

    void wrap_joint()
    {
        class_<b2Joint, boost::noncopyable>("Joint", no_init)
            .add_property("type", &b2Joint::GetType)
            .add_property("body_a", make_function(&b2Joint::GetBodyA, return_internal_reference<>()))
            .add_property("body_b", make_function(&b2Joint::GetBodyB, return_internal_reference<>()))
            .add_property("next", make_function(&b2Joint::GetNext, return_internal_reference<>()))
            .add_property("user_data", &b2Joint::GetUserData, &b2Joint::SetUserData)
            .add_property("active", &b2Joint::IsActive)

            .def("get_type", &b2Joint::GetType)
            .def("get_body_a", &b2Joint::GetBodyA, return_internal_reference<>())
            .def("get_body_b", &b2Joint::GetBodyB, return_internal_reference<>())
            .def("get_anchor_a", pure_virtual(&b2Joint::GetAnchorA))
            .def("get_anchor_b", pure_virtual(&b2Joint::GetAnchorB))
            .def("get_reaction_force", pure_virtual(&b2Joint::GetReactionForce))
            .def("get_reaction_torque", pure_virtual(&b2Joint::GetReactionTorque))
            .def("get_next", &b2Joint::GetNext, return_internal_reference<>())
            .def("get_user_data", &b2Joint::GetUserData)
            .def("set_user_data", &b2Joint::SetUserData)
            .def("is_active", &b2Joint::IsActive)
        ;
    }

    void wrap_revolute_joint()
    {
        class_<b2RevoluteJoint, bases<b2Joint> >("RevoluteJoint", no_init)
            .add_property("anchor_a", &b2RevoluteJoint::GetAnchorA)
            .add_property("anchor_b", &b2RevoluteJoint::GetAnchorB)
            .add_property("reaction_force", &b2RevoluteJoint::GetReactionForce)
            .add_property("reaction_torque", &b2RevoluteJoint::GetReactionTorque)
            .add_property("joint_angle", &b2RevoluteJoint::GetJointAngle)
            .add_property("joint_speed", &b2RevoluteJoint::GetJointSpeed)
            .add_property("limit_enabled", &b2RevoluteJoint::IsLimitEnabled, &b2RevoluteJoint::EnableLimit)
            .add_property("lower_limit", &b2RevoluteJoint::GetLowerLimit)
            .add_property("upper_limit", &b2RevoluteJoint::GetUpperLimit)
            .add_property("motor_enabled", &b2RevoluteJoint::IsMotorEnabled, &b2RevoluteJoint::EnableMotor)
            .add_property("motor_speed", &b2RevoluteJoint::GetMotorSpeed, &b2RevoluteJoint::SetMotorSpeed)
            .add_property("motor_torque", &b2RevoluteJoint::GetMotorTorque)

            .def("get_joint_angle", &b2RevoluteJoint::GetJointAngle)
            .def("get_joint_speed", &b2RevoluteJoint::GetJointSpeed)
            .def("is_limit_enabled", &b2RevoluteJoint::IsLimitEnabled)
            .def("set_limit_enabled", &b2RevoluteJoint::EnableLimit)
            .def("get_lower_limit", &b2RevoluteJoint::GetLowerLimit)
            .def("get_upper_limit", &b2RevoluteJoint::GetUpperLimit)
            .def("set_limits", &b2RevoluteJoint::SetLimits)
            .def("is_motor_enabled", &b2RevoluteJoint::IsMotorEnabled)
            .def("set_motor_enabled", &b2RevoluteJoint::EnableMotor)
            .def("get_motor_speed", &b2RevoluteJoint::GetMotorSpeed)
            .def("set_motor_speed", &b2RevoluteJoint::SetMotorSpeed)
            .def("set_max_motor_torque", &b2RevoluteJoint::SetMaxMotorTorque)
            .def("get_motor_torque", &b2RevoluteJoint::GetMotorTorque)
        ;
    }

    void wrap_prismatic_joint()
    {
        class_<b2PrismaticJoint, bases<b2Joint> >("PrismaticJoint", no_init)
            .add_property("anchor_a", &b2PrismaticJoint::GetAnchorA)
            .add_property("anchor_b", &b2PrismaticJoint::GetAnchorB)
            .add_property("reaction_force", &b2PrismaticJoint::GetReactionForce)
            .add_property("reaction_torque", &b2PrismaticJoint::GetReactionTorque)
            .add_property("joint_translation", &b2PrismaticJoint::GetJointTranslation)
            .add_property("joint_speed", &b2PrismaticJoint::GetJointSpeed)
            .add_property("limit_enabled", &b2PrismaticJoint::IsLimitEnabled, &b2PrismaticJoint::EnableLimit)
            .add_property("lower_limit", &b2PrismaticJoint::GetLowerLimit)
            .add_property("upper_limit", &b2PrismaticJoint::GetUpperLimit)
            .add_property("motor_enabled", &b2PrismaticJoint::IsMotorEnabled, &b2PrismaticJoint::EnableMotor)
            .add_property("motor_speed", &b2PrismaticJoint::GetMotorSpeed, &b2PrismaticJoint::SetMotorSpeed)
            .add_property("motor_force", &b2PrismaticJoint::GetMotorForce)

            .def("get_anchor_a", &b2PrismaticJoint::GetAnchorA)
            .def("get_anchor_b", &b2PrismaticJoint::GetAnchorB)
            .def("get_reaction_force", &b2PrismaticJoint::GetReactionForce)
            .def("get_reaction_torque", &b2PrismaticJoint::GetReactionTorque)
            .def("get_joint_translation", &b2PrismaticJoint::GetJointTranslation)
            .def("get_joint_speed", &b2PrismaticJoint::GetJointSpeed)
            .def("is_limit_enabled", &b2PrismaticJoint::IsLimitEnabled)
            .def("set_limit_enabled", &b2PrismaticJoint::EnableLimit)
            .def("get_lower_limit", &b2PrismaticJoint::GetLowerLimit)
            .def("get_upper_limit", &b2PrismaticJoint::GetUpperLimit)
            .def("set_limits", &b2PrismaticJoint::SetLimits)
            .def("is_motor_enabled", &b2PrismaticJoint::IsMotorEnabled)
            .def("set_motor_enabled", &b2PrismaticJoint::EnableMotor)
            .def("get_motor_speed", &b2PrismaticJoint::GetMotorSpeed)
            .def("set_motor_speed", &b2PrismaticJoint::SetMotorSpeed)
            .def("set_max_motor_force", &b2PrismaticJoint::SetMaxMotorForce)
            .def("get_motor_force", &b2PrismaticJoint::GetMotorForce)
        ;
    }

    void wrap_distance_joint()
    {
        class_<b2DistanceJoint, bases<b2Joint> >("DistanceJoint", no_init)
            .add_property("anchor_a", &b2DistanceJoint::GetAnchorA)
            .add_property("anchor_b", &b2DistanceJoint::GetAnchorB)
            .add_property("reaction_force", &b2DistanceJoint::GetReactionForce)
            .add_property("reaction_torque", &b2DistanceJoint::GetReactionTorque)
            .add_property("length", &b2DistanceJoint::GetLength, &b2DistanceJoint::SetLength)
            .add_property("frequency", &b2DistanceJoint::GetFrequency, &b2DistanceJoint::SetFrequency)
            .add_property("damping_ratio", &b2DistanceJoint::GetDampingRatio, &b2DistanceJoint::SetDampingRatio)

            .def("get_anchor_a", &b2DistanceJoint::GetAnchorA)
            .def("get_anchor_b", &b2DistanceJoint::GetAnchorB)
            .def("get_reaction_force", &b2DistanceJoint::GetReactionForce)
            .def("get_reaction_torque", &b2DistanceJoint::GetReactionTorque)
            .def("get_length", &b2DistanceJoint::GetLength)
            .def("set_length", &b2DistanceJoint::SetLength)
            .def("get_frequency", &b2DistanceJoint::GetFrequency)
            .def("set_frequency", &b2DistanceJoint::SetFrequency)
            .def("get_damping_ratio", &b2DistanceJoint::GetDampingRatio)
            .def("set_damping_ratio", &b2DistanceJoint::SetDampingRatio)
        ;
    }

    void wrap_pulley_joint()
    {
    }

    void wrap_mouse_joint()
    {
    }

    void wrap_gear_joint()
    {
    }

    void wrap_line_joint()
    {
    }

    void wrap_weld_joint()
    {
    }

    void wrap_friction_joint()
    {
    }
}
<commit_msg>fixed a couple of issues with joint properties<commit_after>#include "wrap_joint.hpp"

#include <boost/python.hpp>
#include <Box2D/Dynamics/b2Body.h>
#include <Box2D/Dynamics/Joints/b2DistanceJoint.h>
#include <Box2D/Dynamics/Joints/b2FrictionJoint.h>
#include <Box2D/Dynamics/Joints/b2GearJoint.h>
#include <Box2D/Dynamics/Joints/b2Joint.h>
#include <Box2D/Dynamics/Joints/b2LineJoint.h>
#include <Box2D/Dynamics/Joints/b2MouseJoint.h>
#include <Box2D/Dynamics/Joints/b2PrismaticJoint.h>
#include <Box2D/Dynamics/Joints/b2PulleyJoint.h>
#include <Box2D/Dynamics/Joints/b2RevoluteJoint.h>
#include <Box2D/Dynamics/Joints/b2WeldJoint.h>

using namespace boost::python;

namespace pysics {
    void wrap_joint_type()
    {
        enum_<b2JointType>("JointType")
            .value("UNKNOWN_JOINT", e_unknownJoint)
            .value("REVOLUTE_JOINT", e_revoluteJoint)
            .value("PRISMATIC_JOINT", e_prismaticJoint)
            .value("DISTANCE_JOINT", e_distanceJoint)
            .value("PULLEY_JOINT", e_pulleyJoint)
            .value("MOUSE_JOINT", e_mouseJoint)
            .value("GEAR_JOINT", e_gearJoint)
            .value("LINE_JOINT", e_lineJoint)
            .value("WELD_JOINT", e_weldJoint)
            .value("FRICTION_JOINT", e_frictionJoint)
            .export_values()
        ;
    }

    void wrap_joint()
    {
        class_<b2Joint, boost::noncopyable>("Joint", no_init)
            .add_property("type", &b2Joint::GetType)
            .add_property("body_a", make_function(&b2Joint::GetBodyA, return_internal_reference<>()))
            .add_property("body_b", make_function(&b2Joint::GetBodyB, return_internal_reference<>()))
            .add_property("next", make_function(&b2Joint::GetNext, return_internal_reference<>()))
            .add_property("user_data", &b2Joint::GetUserData, &b2Joint::SetUserData)
            .add_property("active", &b2Joint::IsActive)

            .def("get_type", &b2Joint::GetType)
            .def("get_body_a", &b2Joint::GetBodyA, return_internal_reference<>())
            .def("get_body_b", &b2Joint::GetBodyB, return_internal_reference<>())
            .def("get_anchor_a", pure_virtual(&b2Joint::GetAnchorA))
            .def("get_anchor_b", pure_virtual(&b2Joint::GetAnchorB))
            .def("get_reaction_force", pure_virtual(&b2Joint::GetReactionForce))
            .def("get_reaction_torque", pure_virtual(&b2Joint::GetReactionTorque))
            .def("get_next", &b2Joint::GetNext, return_internal_reference<>())
            .def("get_user_data", &b2Joint::GetUserData)
            .def("set_user_data", &b2Joint::SetUserData)
            .def("is_active", &b2Joint::IsActive)
        ;
    }

    void wrap_revolute_joint()
    {
        class_<b2RevoluteJoint, bases<b2Joint> >("RevoluteJoint", no_init)
            .add_property("anchor_a", &b2RevoluteJoint::GetAnchorA)
            .add_property("anchor_b", &b2RevoluteJoint::GetAnchorB)
            .add_property("joint_angle", &b2RevoluteJoint::GetJointAngle)
            .add_property("joint_speed", &b2RevoluteJoint::GetJointSpeed)
            .add_property("limit_enabled", &b2RevoluteJoint::IsLimitEnabled, &b2RevoluteJoint::EnableLimit)
            .add_property("lower_limit", &b2RevoluteJoint::GetLowerLimit)
            .add_property("upper_limit", &b2RevoluteJoint::GetUpperLimit)
            .add_property("motor_enabled", &b2RevoluteJoint::IsMotorEnabled, &b2RevoluteJoint::EnableMotor)
            .add_property("motor_speed", &b2RevoluteJoint::GetMotorSpeed, &b2RevoluteJoint::SetMotorSpeed)
            .add_property("motor_torque", &b2RevoluteJoint::GetMotorTorque)

            .def("get_anchor_a", &b2RevoluteJoint::GetAnchorA)
            .def("get_anchor_b", &b2RevoluteJoint::GetAnchorB)
            .def("get_reaction_force", &b2RevoluteJoint::GetReactionForce)
            .def("get_reaction_torque", &b2RevoluteJoint::GetReactionTorque)
            .def("get_joint_angle", &b2RevoluteJoint::GetJointAngle)
            .def("get_joint_speed", &b2RevoluteJoint::GetJointSpeed)
            .def("is_limit_enabled", &b2RevoluteJoint::IsLimitEnabled)
            .def("set_limit_enabled", &b2RevoluteJoint::EnableLimit)
            .def("get_lower_limit", &b2RevoluteJoint::GetLowerLimit)
            .def("get_upper_limit", &b2RevoluteJoint::GetUpperLimit)
            .def("set_limits", &b2RevoluteJoint::SetLimits)
            .def("is_motor_enabled", &b2RevoluteJoint::IsMotorEnabled)
            .def("set_motor_enabled", &b2RevoluteJoint::EnableMotor)
            .def("get_motor_speed", &b2RevoluteJoint::GetMotorSpeed)
            .def("set_motor_speed", &b2RevoluteJoint::SetMotorSpeed)
            .def("set_max_motor_torque", &b2RevoluteJoint::SetMaxMotorTorque)
            .def("get_motor_torque", &b2RevoluteJoint::GetMotorTorque)
        ;
    }

    void wrap_prismatic_joint()
    {
        class_<b2PrismaticJoint, bases<b2Joint> >("PrismaticJoint", no_init)
            .add_property("anchor_a", &b2PrismaticJoint::GetAnchorA)
            .add_property("anchor_b", &b2PrismaticJoint::GetAnchorB)
            .add_property("joint_translation", &b2PrismaticJoint::GetJointTranslation)
            .add_property("joint_speed", &b2PrismaticJoint::GetJointSpeed)
            .add_property("limit_enabled", &b2PrismaticJoint::IsLimitEnabled, &b2PrismaticJoint::EnableLimit)
            .add_property("lower_limit", &b2PrismaticJoint::GetLowerLimit)
            .add_property("upper_limit", &b2PrismaticJoint::GetUpperLimit)
            .add_property("motor_enabled", &b2PrismaticJoint::IsMotorEnabled, &b2PrismaticJoint::EnableMotor)
            .add_property("motor_speed", &b2PrismaticJoint::GetMotorSpeed, &b2PrismaticJoint::SetMotorSpeed)
            .add_property("motor_force", &b2PrismaticJoint::GetMotorForce)

            .def("get_anchor_a", &b2PrismaticJoint::GetAnchorA)
            .def("get_anchor_b", &b2PrismaticJoint::GetAnchorB)
            .def("get_reaction_force", &b2PrismaticJoint::GetReactionForce)
            .def("get_reaction_torque", &b2PrismaticJoint::GetReactionTorque)
            .def("get_joint_translation", &b2PrismaticJoint::GetJointTranslation)
            .def("get_joint_speed", &b2PrismaticJoint::GetJointSpeed)
            .def("is_limit_enabled", &b2PrismaticJoint::IsLimitEnabled)
            .def("set_limit_enabled", &b2PrismaticJoint::EnableLimit)
            .def("get_lower_limit", &b2PrismaticJoint::GetLowerLimit)
            .def("get_upper_limit", &b2PrismaticJoint::GetUpperLimit)
            .def("set_limits", &b2PrismaticJoint::SetLimits)
            .def("is_motor_enabled", &b2PrismaticJoint::IsMotorEnabled)
            .def("set_motor_enabled", &b2PrismaticJoint::EnableMotor)
            .def("get_motor_speed", &b2PrismaticJoint::GetMotorSpeed)
            .def("set_motor_speed", &b2PrismaticJoint::SetMotorSpeed)
            .def("set_max_motor_force", &b2PrismaticJoint::SetMaxMotorForce)
            .def("get_motor_force", &b2PrismaticJoint::GetMotorForce)
        ;
    }

    void wrap_distance_joint()
    {
        class_<b2DistanceJoint, bases<b2Joint> >("DistanceJoint", no_init)
            .add_property("anchor_a", &b2DistanceJoint::GetAnchorA)
            .add_property("anchor_b", &b2DistanceJoint::GetAnchorB)
            .add_property("length", &b2DistanceJoint::GetLength, &b2DistanceJoint::SetLength)
            .add_property("frequency", &b2DistanceJoint::GetFrequency, &b2DistanceJoint::SetFrequency)
            .add_property("damping_ratio", &b2DistanceJoint::GetDampingRatio, &b2DistanceJoint::SetDampingRatio)

            .def("get_anchor_a", &b2DistanceJoint::GetAnchorA)
            .def("get_anchor_b", &b2DistanceJoint::GetAnchorB)
            .def("get_reaction_force", &b2DistanceJoint::GetReactionForce)
            .def("get_reaction_torque", &b2DistanceJoint::GetReactionTorque)
            .def("get_length", &b2DistanceJoint::GetLength)
            .def("set_length", &b2DistanceJoint::SetLength)
            .def("get_frequency", &b2DistanceJoint::GetFrequency)
            .def("set_frequency", &b2DistanceJoint::SetFrequency)
            .def("get_damping_ratio", &b2DistanceJoint::GetDampingRatio)
            .def("set_damping_ratio", &b2DistanceJoint::SetDampingRatio)
        ;
    }

    void wrap_pulley_joint()
    {
    }

    void wrap_mouse_joint()
    {
    }

    void wrap_gear_joint()
    {
    }

    void wrap_line_joint()
    {
    }

    void wrap_weld_joint()
    {
    }

    void wrap_friction_joint()
    {
    }
}
<|endoftext|>


<commit_before>/*
 * #%L
 * %%
 * Copyright (C) 2011 - 2017 BMW Car IT GmbH
 * %%
 * 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.
 * #L%
 */

#include "libjoynrclustercontroller/mqtt/MosquittoConnection.h"

#include "joynr/ClusterControllerSettings.h"
#include "joynr/MessagingSettings.h"
#include "joynr/exceptions/JoynrException.h"

namespace joynr
{

INIT_LOGGER(MosquittoConnection);

MosquittoConnection::MosquittoConnection(const MessagingSettings& messagingSettings,
                                         const ClusterControllerSettings& ccSettings,
                                         const std::string& clientId)
        : mosquittopp(clientId.c_str()),
          messagingSettings(messagingSettings),
          host(messagingSettings.getBrokerUrl().getBrokerChannelsBaseUrl().getHost()),
          port(messagingSettings.getBrokerUrl().getBrokerChannelsBaseUrl().getPort()),
          channelId(),
          subscribeChannelMid(),
          topic(),
          additionalTopics(),
          additionalTopicsMutex(),
          isConnected(false),
          isRunning(false),
          isChannelIdRegistered(false),
          subscribedToChannelTopic(false),
          onMessageReceived(),
          thread()
{
    JOYNR_LOG_DEBUG(logger, "Try to connect to tcp://{}:{}", host, port);

    mosqpp::lib_init();

    if (ccSettings.isMqttTlsEnabled()) {
        int rc = tls_set(ccSettings.getMqttCertificateAuthorityPemFilename().c_str(),
                         NULL,
                         ccSettings.getMqttCertificatePemFilename().c_str(),
                         ccSettings.getMqttPrivateKeyPemFilename().c_str());

        if (rc != MOSQ_ERR_SUCCESS) {
            JOYNR_LOG_ERROR(
                    logger, "Could not initialize TLS connection - {}", mosqpp::strerror(rc));
        }
    } else {
        JOYNR_LOG_DEBUG(logger, "MQTT connection not encrypted");
    };

    connect(host.c_str(), port, messagingSettings.getMqttKeepAliveTime().count());
}

MosquittoConnection::~MosquittoConnection()
{
    stop();
}

void MosquittoConnection::on_disconnect(int rc)
{
    if (rc == 0) {
        JOYNR_LOG_DEBUG(logger, "Disconnected from tcp://{}:{}", host, port);
    } else {
        JOYNR_LOG_ERROR(logger,
                        "Unexpectedly disconnected from tcp://{}:{}, error: {}",
                        host,
                        port,
                        mosqpp::strerror(rc));
    }
}

void MosquittoConnection::on_log(int level, const char* str)
{
    if (level == MOSQ_LOG_ERR) {
        JOYNR_LOG_ERROR(logger, "Mosquitto Log: {}", str);
    } else if (level == MOSQ_LOG_WARNING) {
        JOYNR_LOG_WARN(logger, "Mosquitto Log: {}", str);
    } else if (level == MOSQ_LOG_INFO) {
        JOYNR_LOG_INFO(logger, "Mosquitto Log: {}", str);
    } else {
        // MOSQ_LOG_NOTICE || MOSQ_LOG_DEBUG || any other log level
        JOYNR_LOG_DEBUG(logger, "Mosquitto Log: {}", str);
    }
}

void MosquittoConnection::on_error()
{
    JOYNR_LOG_WARN(logger, "Mosquitto Error");
}

std::uint16_t MosquittoConnection::getMqttQos() const
{
    return mqttQos;
}

std::string MosquittoConnection::getMqttPrio() const
{
    static const std::string value("low");
    return value;
}

bool MosquittoConnection::isMqttRetain() const
{
    return mqttRetain;
}

void MosquittoConnection::start()
{
    isRunning = true;
    thread = std::thread(&MosquittoConnection::runLoop, this);
}

void MosquittoConnection::stop()
{
    isRunning = false;
    if (thread.joinable()) {
        thread.join();
    }
}

void MosquittoConnection::runLoop()
{
    const int mqttConnectionTimeoutMs = messagingSettings.getMqttConnectionTimeout().count();

    while (isRunning) {
        int rc = loop(mqttConnectionTimeoutMs);

        if (rc != MOSQ_ERR_SUCCESS) {
            if (rc == MOSQ_ERR_CONN_LOST) {
                JOYNR_LOG_DEBUG(logger,
                                "error: connection to broker lost ({}), trying to reconnect...",
                                mosqpp::strerror(rc));
            } else if (rc == MOSQ_ERR_NO_CONN) {
                JOYNR_LOG_DEBUG(logger,
                                "error: not connected to a broker ({}), trying to reconnect...",
                                mosqpp::strerror(rc));
            } else {
                // MOSQ_ERR_INVAL || MOSQ_ERR_NOMEM || MOSQ_ERR_PROTOCOL || MOSQ_ERR_ERRNO
                JOYNR_LOG_ERROR(logger,
                                "connection to broker lost, unexpected error: {} ({}), trying to "
                                "reconnect...",
                                std::to_string(rc),
                                mosqpp::strerror(rc));
            }
            std::this_thread::sleep_for(messagingSettings.getMqttReconnectSleepTime());
            reconnect();
        }
    }

    JOYNR_LOG_TRACE(logger, "Try to disconnect Mosquitto Connection");
    int rc = disconnect();
    if (rc == MOSQ_ERR_SUCCESS) {
        JOYNR_LOG_DEBUG(logger, "Mosquitto Connection disconnected");
    } else {
        JOYNR_LOG_ERROR(logger,
                        "Mosquitto disconnect failed: error: {} ({})",
                        std::to_string(rc),
                        mosqpp::strerror(rc));
    }

    mosqpp::lib_cleanup();
}

void MosquittoConnection::on_connect(int rc)
{
    if (rc > 0) {
        if (rc == 1) {
            JOYNR_LOG_ERROR(logger,
                            "Mosquitto Connection Error {} ({})",
                            rc,
                            "connection refused (unacceptable protocol version)");
        } else if (rc == 2) {
            JOYNR_LOG_ERROR(logger,
                            "Mosquitto Connection Error {} ({})",
                            rc,
                            "connection refused (identifier rejected)");
        } else if (rc == 3) {
            JOYNR_LOG_DEBUG(logger,
                            "Mosquitto Connection Error {} ({})",
                            rc,
                            "connection refused (broker unavailable)");
        } else {
            JOYNR_LOG_ERROR(logger,
                            "Mosquitto Connection Error {} ({})",
                            rc,
                            "unknown error code (reserved for future use)");
        }
    } else {
        JOYNR_LOG_DEBUG(logger, "Mosquitto Connection established");
        isConnected = true;
        restoreSubscriptions();
    }
}

void MosquittoConnection::restoreSubscriptions()
{
    while (!isChannelIdRegistered && isRunning) {
        std::this_thread::sleep_for(std::chrono::milliseconds(25));
    }
    try {
        subscribeToTopicInternal(topic, true);
        std::lock_guard<std::recursive_mutex> lock(additionalTopicsMutex);
        for (const std::string& additionalTopic : additionalTopics) {
            subscribeToTopicInternal(additionalTopic);
        }
    } catch (const exceptions::JoynrRuntimeException& error) {
        JOYNR_LOG_ERROR(logger, "Error subscribing to Mqtt topic, error: ", error.getMessage());
    }
}

void MosquittoConnection::subscribeToTopicInternal(const std::string& topic,
                                                   const bool isChannelTopic)
{
    int* mid = nullptr;
    if (isChannelTopic) {
        mid = &subscribeChannelMid;
    }
    int rc = subscribe(mid, topic.c_str(), getMqttQos());
    switch (rc) {
    case (MOSQ_ERR_SUCCESS):
        JOYNR_LOG_DEBUG(logger, "Subscribed to {}", topic);
        break;
    case (MOSQ_ERR_NO_CONN):
        JOYNR_LOG_DEBUG(logger,
                        "Subscription to {} failed: error: {} (not connected to a broker). "
                        "Subscription will be restored on connect.",
                        topic,
                        std::to_string(rc));
        break;
    default:
        // MOSQ_ERR_INVAL, MOSQ_ERR_NOMEM
        std::string errorMsg = "Subscription to " + topic + " failed: error: " +
                               std::to_string(rc) + " (" + mosqpp::strerror(rc) + ")";
        throw exceptions::JoynrRuntimeException(errorMsg);
    }
}

void MosquittoConnection::subscribeToTopic(const std::string& topic)
{
    while (!isChannelIdRegistered && isRunning) {
        std::this_thread::sleep_for(std::chrono::milliseconds(25));
    }
    {
        std::lock_guard<std::recursive_mutex> lock(additionalTopicsMutex);
        if (additionalTopics.find(topic) != additionalTopics.end()) {
            JOYNR_LOG_DEBUG(logger, "already subscribed to topic {}", topic);
            return;
        }
        subscribeToTopicInternal(topic);
        additionalTopics.insert(topic);
    }
}

void MosquittoConnection::unsubscribeFromTopic(const std::string& topic)
{
    if (isChannelIdRegistered) {
        std::lock_guard<std::recursive_mutex> lock(additionalTopicsMutex);
        if (additionalTopics.find(topic) == additionalTopics.end()) {
            JOYNR_LOG_DEBUG(logger, "Unsubscribe called for non existing topic {}", topic);
            return;
        }
        additionalTopics.erase(topic);
        if (isConnected && isRunning) {
            int rc = unsubscribe(nullptr, topic.c_str());
            if (rc == MOSQ_ERR_SUCCESS) {
                JOYNR_LOG_DEBUG(logger, "Unsubscribed from {}", topic);
            } else {
                // MOSQ_ERR_INVAL || MOSQ_ERR_NOMEM || MOSQ_ERR_NO_CONN
                JOYNR_LOG_ERROR(logger,
                                "Unsubscribe from {} failed: error: {} ({})",
                                topic,
                                std::to_string(rc),
                                mosqpp::strerror(rc));
            }
        }
    }
}

void MosquittoConnection::publishMessage(
        const std::string& topic,
        const int qosLevel,
        const std::function<void(const exceptions::JoynrRuntimeException&)>& onFailure,
        uint32_t payloadlen = 0,
        const void* payload = nullptr)
{
    JOYNR_LOG_DEBUG(logger, "Publish to {}", topic);

    int mid;
    int rc = publish(&mid, topic.c_str(), payloadlen, payload, qosLevel, isMqttRetain());
    if (!(rc == MOSQ_ERR_SUCCESS)) {
        if (rc == MOSQ_ERR_INVAL || rc == MOSQ_ERR_PAYLOAD_SIZE) {
            onFailure(exceptions::JoynrMessageNotSentException(
                    "message could not be sent: mid (mqtt message id): " + std::to_string(mid) +
                    ", error: " + std::to_string(rc) + " (" + mosqpp::strerror(rc) + ")"));
        }
        // MOSQ_ERR_NOMEM || MOSQ_ERR_NO_CONN || MOSQ_ERR_PROTOCOL ||| unexpected errors
        onFailure(exceptions::JoynrDelayMessageException(
                "error sending message: mid (mqtt message id): " + std::to_string(mid) +
                ", error: " + std::to_string(rc) + " (" + mosqpp::strerror(rc) + ")"));
    }
    JOYNR_LOG_TRACE(logger, "published message with mqtt message id {}", std::to_string(mid));
}

void MosquittoConnection::registerChannelId(const std::string& channelId)
{
    this->channelId = channelId;
    topic = channelId + "/" + getMqttPrio() + "/" + "#";
    isChannelIdRegistered = true;
}

void MosquittoConnection::registerReceiveCallback(
        std::function<void(smrf::ByteVector&&)> onMessageReceived)
{
    this->onMessageReceived = onMessageReceived;
}

bool MosquittoConnection::isSubscribedToChannelTopic() const
{
    return subscribedToChannelTopic;
}

void MosquittoConnection::on_subscribe(int mid, int qos_count, const int* granted_qos)
{
    JOYNR_LOG_DEBUG(logger, "Subscribed (mid: {} with granted QOS {}", mid, granted_qos[0]);

    for (int i = 1; i < qos_count; i++) {
        JOYNR_LOG_DEBUG(logger, "QOS: {} granted {}", i, granted_qos[i]);
    }

    if (mid == subscribeChannelMid) {
        subscribedToChannelTopic = true;
    }
}

void MosquittoConnection::on_message(const mosquitto_message* message)
{
    std::uint8_t* data = static_cast<std::uint8_t*>(message->payload);
    smrf::ByteVector rawMessage(data, data + message->payloadlen);

    if (onMessageReceived) {
        onMessageReceived(std::move(rawMessage));
    } else {
        JOYNR_LOG_ERROR(
                logger, "Discarding received message, since onMessageReceived callback is empty.");
    }
}

void MosquittoConnection::on_publish(int mid)
{
    JOYNR_LOG_TRACE(logger, "published message with mid {}", std::to_string(mid));
}

} // namespace joynr
<commit_msg>[C++] Early exit if MosquittoConnection::onMessageReceived is not set.<commit_after>/*
 * #%L
 * %%
 * Copyright (C) 2011 - 2017 BMW Car IT GmbH
 * %%
 * 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.
 * #L%
 */

#include "libjoynrclustercontroller/mqtt/MosquittoConnection.h"

#include "joynr/ClusterControllerSettings.h"
#include "joynr/MessagingSettings.h"
#include "joynr/exceptions/JoynrException.h"

namespace joynr
{

INIT_LOGGER(MosquittoConnection);

MosquittoConnection::MosquittoConnection(const MessagingSettings& messagingSettings,
                                         const ClusterControllerSettings& ccSettings,
                                         const std::string& clientId)
        : mosquittopp(clientId.c_str()),
          messagingSettings(messagingSettings),
          host(messagingSettings.getBrokerUrl().getBrokerChannelsBaseUrl().getHost()),
          port(messagingSettings.getBrokerUrl().getBrokerChannelsBaseUrl().getPort()),
          channelId(),
          subscribeChannelMid(),
          topic(),
          additionalTopics(),
          additionalTopicsMutex(),
          isConnected(false),
          isRunning(false),
          isChannelIdRegistered(false),
          subscribedToChannelTopic(false),
          onMessageReceived(),
          thread()
{
    JOYNR_LOG_DEBUG(logger, "Try to connect to tcp://{}:{}", host, port);

    mosqpp::lib_init();

    if (ccSettings.isMqttTlsEnabled()) {
        int rc = tls_set(ccSettings.getMqttCertificateAuthorityPemFilename().c_str(),
                         NULL,
                         ccSettings.getMqttCertificatePemFilename().c_str(),
                         ccSettings.getMqttPrivateKeyPemFilename().c_str());

        if (rc != MOSQ_ERR_SUCCESS) {
            JOYNR_LOG_ERROR(
                    logger, "Could not initialize TLS connection - {}", mosqpp::strerror(rc));
        }
    } else {
        JOYNR_LOG_DEBUG(logger, "MQTT connection not encrypted");
    };

    connect(host.c_str(), port, messagingSettings.getMqttKeepAliveTime().count());
}

MosquittoConnection::~MosquittoConnection()
{
    stop();
}

void MosquittoConnection::on_disconnect(int rc)
{
    if (rc == 0) {
        JOYNR_LOG_DEBUG(logger, "Disconnected from tcp://{}:{}", host, port);
    } else {
        JOYNR_LOG_ERROR(logger,
                        "Unexpectedly disconnected from tcp://{}:{}, error: {}",
                        host,
                        port,
                        mosqpp::strerror(rc));
    }
}

void MosquittoConnection::on_log(int level, const char* str)
{
    if (level == MOSQ_LOG_ERR) {
        JOYNR_LOG_ERROR(logger, "Mosquitto Log: {}", str);
    } else if (level == MOSQ_LOG_WARNING) {
        JOYNR_LOG_WARN(logger, "Mosquitto Log: {}", str);
    } else if (level == MOSQ_LOG_INFO) {
        JOYNR_LOG_INFO(logger, "Mosquitto Log: {}", str);
    } else {
        // MOSQ_LOG_NOTICE || MOSQ_LOG_DEBUG || any other log level
        JOYNR_LOG_DEBUG(logger, "Mosquitto Log: {}", str);
    }
}

void MosquittoConnection::on_error()
{
    JOYNR_LOG_WARN(logger, "Mosquitto Error");
}

std::uint16_t MosquittoConnection::getMqttQos() const
{
    return mqttQos;
}

std::string MosquittoConnection::getMqttPrio() const
{
    static const std::string value("low");
    return value;
}

bool MosquittoConnection::isMqttRetain() const
{
    return mqttRetain;
}

void MosquittoConnection::start()
{
    isRunning = true;
    thread = std::thread(&MosquittoConnection::runLoop, this);
}

void MosquittoConnection::stop()
{
    isRunning = false;
    if (thread.joinable()) {
        thread.join();
    }
}

void MosquittoConnection::runLoop()
{
    const int mqttConnectionTimeoutMs = messagingSettings.getMqttConnectionTimeout().count();

    while (isRunning) {
        int rc = loop(mqttConnectionTimeoutMs);

        if (rc != MOSQ_ERR_SUCCESS) {
            if (rc == MOSQ_ERR_CONN_LOST) {
                JOYNR_LOG_DEBUG(logger,
                                "error: connection to broker lost ({}), trying to reconnect...",
                                mosqpp::strerror(rc));
            } else if (rc == MOSQ_ERR_NO_CONN) {
                JOYNR_LOG_DEBUG(logger,
                                "error: not connected to a broker ({}), trying to reconnect...",
                                mosqpp::strerror(rc));
            } else {
                // MOSQ_ERR_INVAL || MOSQ_ERR_NOMEM || MOSQ_ERR_PROTOCOL || MOSQ_ERR_ERRNO
                JOYNR_LOG_ERROR(logger,
                                "connection to broker lost, unexpected error: {} ({}), trying to "
                                "reconnect...",
                                std::to_string(rc),
                                mosqpp::strerror(rc));
            }
            std::this_thread::sleep_for(messagingSettings.getMqttReconnectSleepTime());
            reconnect();
        }
    }

    JOYNR_LOG_TRACE(logger, "Try to disconnect Mosquitto Connection");
    int rc = disconnect();
    if (rc == MOSQ_ERR_SUCCESS) {
        JOYNR_LOG_DEBUG(logger, "Mosquitto Connection disconnected");
    } else {
        JOYNR_LOG_ERROR(logger,
                        "Mosquitto disconnect failed: error: {} ({})",
                        std::to_string(rc),
                        mosqpp::strerror(rc));
    }

    mosqpp::lib_cleanup();
}

void MosquittoConnection::on_connect(int rc)
{
    if (rc > 0) {
        if (rc == 1) {
            JOYNR_LOG_ERROR(logger,
                            "Mosquitto Connection Error {} ({})",
                            rc,
                            "connection refused (unacceptable protocol version)");
        } else if (rc == 2) {
            JOYNR_LOG_ERROR(logger,
                            "Mosquitto Connection Error {} ({})",
                            rc,
                            "connection refused (identifier rejected)");
        } else if (rc == 3) {
            JOYNR_LOG_DEBUG(logger,
                            "Mosquitto Connection Error {} ({})",
                            rc,
                            "connection refused (broker unavailable)");
        } else {
            JOYNR_LOG_ERROR(logger,
                            "Mosquitto Connection Error {} ({})",
                            rc,
                            "unknown error code (reserved for future use)");
        }
    } else {
        JOYNR_LOG_DEBUG(logger, "Mosquitto Connection established");
        isConnected = true;
        restoreSubscriptions();
    }
}

void MosquittoConnection::restoreSubscriptions()
{
    while (!isChannelIdRegistered && isRunning) {
        std::this_thread::sleep_for(std::chrono::milliseconds(25));
    }
    try {
        subscribeToTopicInternal(topic, true);
        std::lock_guard<std::recursive_mutex> lock(additionalTopicsMutex);
        for (const std::string& additionalTopic : additionalTopics) {
            subscribeToTopicInternal(additionalTopic);
        }
    } catch (const exceptions::JoynrRuntimeException& error) {
        JOYNR_LOG_ERROR(logger, "Error subscribing to Mqtt topic, error: ", error.getMessage());
    }
}

void MosquittoConnection::subscribeToTopicInternal(const std::string& topic,
                                                   const bool isChannelTopic)
{
    int* mid = nullptr;
    if (isChannelTopic) {
        mid = &subscribeChannelMid;
    }
    int rc = subscribe(mid, topic.c_str(), getMqttQos());
    switch (rc) {
    case (MOSQ_ERR_SUCCESS):
        JOYNR_LOG_DEBUG(logger, "Subscribed to {}", topic);
        break;
    case (MOSQ_ERR_NO_CONN):
        JOYNR_LOG_DEBUG(logger,
                        "Subscription to {} failed: error: {} (not connected to a broker). "
                        "Subscription will be restored on connect.",
                        topic,
                        std::to_string(rc));
        break;
    default:
        // MOSQ_ERR_INVAL, MOSQ_ERR_NOMEM
        std::string errorMsg = "Subscription to " + topic + " failed: error: " +
                               std::to_string(rc) + " (" + mosqpp::strerror(rc) + ")";
        throw exceptions::JoynrRuntimeException(errorMsg);
    }
}

void MosquittoConnection::subscribeToTopic(const std::string& topic)
{
    while (!isChannelIdRegistered && isRunning) {
        std::this_thread::sleep_for(std::chrono::milliseconds(25));
    }
    {
        std::lock_guard<std::recursive_mutex> lock(additionalTopicsMutex);
        if (additionalTopics.find(topic) != additionalTopics.end()) {
            JOYNR_LOG_DEBUG(logger, "already subscribed to topic {}", topic);
            return;
        }
        subscribeToTopicInternal(topic);
        additionalTopics.insert(topic);
    }
}

void MosquittoConnection::unsubscribeFromTopic(const std::string& topic)
{
    if (isChannelIdRegistered) {
        std::lock_guard<std::recursive_mutex> lock(additionalTopicsMutex);
        if (additionalTopics.find(topic) == additionalTopics.end()) {
            JOYNR_LOG_DEBUG(logger, "Unsubscribe called for non existing topic {}", topic);
            return;
        }
        additionalTopics.erase(topic);
        if (isConnected && isRunning) {
            int rc = unsubscribe(nullptr, topic.c_str());
            if (rc == MOSQ_ERR_SUCCESS) {
                JOYNR_LOG_DEBUG(logger, "Unsubscribed from {}", topic);
            } else {
                // MOSQ_ERR_INVAL || MOSQ_ERR_NOMEM || MOSQ_ERR_NO_CONN
                JOYNR_LOG_ERROR(logger,
                                "Unsubscribe from {} failed: error: {} ({})",
                                topic,
                                std::to_string(rc),
                                mosqpp::strerror(rc));
            }
        }
    }
}

void MosquittoConnection::publishMessage(
        const std::string& topic,
        const int qosLevel,
        const std::function<void(const exceptions::JoynrRuntimeException&)>& onFailure,
        uint32_t payloadlen = 0,
        const void* payload = nullptr)
{
    JOYNR_LOG_DEBUG(logger, "Publish to {}", topic);

    int mid;
    int rc = publish(&mid, topic.c_str(), payloadlen, payload, qosLevel, isMqttRetain());
    if (!(rc == MOSQ_ERR_SUCCESS)) {
        if (rc == MOSQ_ERR_INVAL || rc == MOSQ_ERR_PAYLOAD_SIZE) {
            onFailure(exceptions::JoynrMessageNotSentException(
                    "message could not be sent: mid (mqtt message id): " + std::to_string(mid) +
                    ", error: " + std::to_string(rc) + " (" + mosqpp::strerror(rc) + ")"));
        }
        // MOSQ_ERR_NOMEM || MOSQ_ERR_NO_CONN || MOSQ_ERR_PROTOCOL ||| unexpected errors
        onFailure(exceptions::JoynrDelayMessageException(
                "error sending message: mid (mqtt message id): " + std::to_string(mid) +
                ", error: " + std::to_string(rc) + " (" + mosqpp::strerror(rc) + ")"));
    }
    JOYNR_LOG_TRACE(logger, "published message with mqtt message id {}", std::to_string(mid));
}

void MosquittoConnection::registerChannelId(const std::string& channelId)
{
    this->channelId = channelId;
    topic = channelId + "/" + getMqttPrio() + "/" + "#";
    isChannelIdRegistered = true;
}

void MosquittoConnection::registerReceiveCallback(
        std::function<void(smrf::ByteVector&&)> onMessageReceived)
{
    this->onMessageReceived = onMessageReceived;
}

bool MosquittoConnection::isSubscribedToChannelTopic() const
{
    return subscribedToChannelTopic;
}

void MosquittoConnection::on_subscribe(int mid, int qos_count, const int* granted_qos)
{
    JOYNR_LOG_DEBUG(logger, "Subscribed (mid: {} with granted QOS {}", mid, granted_qos[0]);

    for (int i = 1; i < qos_count; i++) {
        JOYNR_LOG_DEBUG(logger, "QOS: {} granted {}", i, granted_qos[i]);
    }

    if (mid == subscribeChannelMid) {
        subscribedToChannelTopic = true;
    }
}

void MosquittoConnection::on_message(const mosquitto_message* message)
{
    if (!onMessageReceived) {
        JOYNR_LOG_ERROR(
                logger, "Discarding received message, since onMessageReceived callback is empty.");
        return;
    }

    std::uint8_t* data = static_cast<std::uint8_t*>(message->payload);
    smrf::ByteVector rawMessage(data, data + message->payloadlen);
    onMessageReceived(std::move(rawMessage));
}

void MosquittoConnection::on_publish(int mid)
{
    JOYNR_LOG_TRACE(logger, "published message with mid {}", std::to_string(mid));
}

} // namespace joynr
<|endoftext|>


<commit_before><commit_msg>do not display toolbar if there are no icons #876<commit_after><|endoftext|>


<commit_before>// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
#include "core/optimizer/initializer.h"
#include "core/optimizer/layer_norm_fusion.h"
#include "core/graph/graph_utils.h"
#include "float.h"
#include <deque>

using namespace ONNX_NAMESPACE;
using namespace onnxruntime::common;
namespace onnxruntime {

// LayerNorm supports limited data types.
static std::vector<std::string> supported_data_types{"tensor(float16)", "tensor(float)", "tensor(double)"};

static bool IsSupportedDataType(const Node& node) {
  for (const auto& input_arg : node.InputDefs()) {
    if (std::find(supported_data_types.begin(), supported_data_types.end(),
      *(input_arg->Type())) == supported_data_types.end()) {
      return false;
    }
  }
  return true;
}

/**
Layer Normalization will fuse LayerNormalization into one node :
+---------------------+
|                     |
|                     v
X --> ReduceMean --> Sub --> Pow --> ReduceMean --> Add --> Sqrt --> Div --> Mul --> Add
                      |                                               ^
                      |                                               |
                      +-----------------------------------------------+
It also handles cases of duplicated sub nodes exported from older version of PyTorch :
+---------------------+
|                     v
|          +-------> Sub ---------------------------------------------+
|          |                                                          |
|          |                                                          v
X --> ReduceMean --> Sub --> Pow --> ReduceMean --> Add --> Sqrt --> Div --> Mul --> Add
|                     ^
|                     |
+---------------------+
*/
Status LayerNormFusion::ApplyImpl(Graph& graph, bool& modified, int graph_level, const logging::Logger& logger) const {
  GraphViewer graph_viewer(graph);
  const auto& node_topology_list = graph_viewer.GetNodesInTopologicalOrder();
  std::vector<std::reference_wrapper<Node>> nodes_to_remove;
  for (auto node_index : node_topology_list) {
    nodes_to_remove.clear();
    auto* p_reduce_mean = graph.GetNode(node_index);
    if (p_reduce_mean == nullptr)
      continue;  // we removed the node as part of an earlier fusion

    Node& reduce_mean_node = *p_reduce_mean;
    ORT_RETURN_IF_ERROR(Recurse(reduce_mean_node, modified, graph_level, logger));

    if (!graph_utils::IsSupportedOptypeVersionAndDomain(reduce_mean_node, "ReduceMean", {1}) ||
        !graph_utils::IsSupportedProvider(reduce_mean_node, GetCompatibleExecutionProviders()) ||
        (reduce_mean_node.GetOutputEdgesCount() != 1 && reduce_mean_node.GetOutputEdgesCount() != 2) ||
        !IsSupportedDataType(reduce_mean_node)) {
      continue;
    }
    nodes_to_remove.push_back(reduce_mean_node);

    // Loop through the children of current "ReduceMean" node. See if they match ["Sub"] or ["Sub", "Sub"]
    int subCnt = 0;
    const Node* p_sub_node = nullptr;
    const Node* p_sub_node_dup = nullptr;
    for (auto iter = reduce_mean_node.OutputNodesBegin(); iter != reduce_mean_node.OutputNodesEnd(); ++iter) {
      if ((*iter).OpType().compare("Sub") == 0) {
        if (subCnt == 0) {
          p_sub_node = &(*iter);

        } else {
          p_sub_node_dup = &(*iter);
        }
        subCnt++;
      } else {
        // doesn't match layer norm pattern. break.
        subCnt = -1;
        break;
      }
    }

    if (subCnt != 1 && subCnt != 2) {
      continue;
    }

    Node& sub_node = *graph.GetNode(p_sub_node->Index());
    if (!graph_utils::IsSupportedOptypeVersionAndDomain(sub_node, "Sub", {7}) ||
        sub_node.GetExecutionProviderType() != reduce_mean_node.GetExecutionProviderType() ||
        !IsSupportedDataType(sub_node)) {
      continue;
    }
    nodes_to_remove.push_back(sub_node);

    // Find the "Div" node after "Sub".
    const Node* p_div = nullptr;
    p_div = graph_utils::FirstChildByType(sub_node, "Div");

    // Find the sub_dup node if exist
    if (p_sub_node_dup != nullptr) {
      Node& sub_node_dup = *graph.GetNode(p_sub_node_dup->Index());
      if (!graph_utils::IsSupportedOptypeVersionAndDomain(sub_node_dup, "Sub", {7}) ||
          sub_node_dup.GetExecutionProviderType() != reduce_mean_node.GetExecutionProviderType() ||
          sub_node_dup.GetOutputEdgesCount() != 1 ||
          !IsSupportedDataType(sub_node_dup)) {
        continue;
      }
      nodes_to_remove.push_back(sub_node_dup);
      // Find Div node after the duplicated sub node if it's not found after the first sub node.
      if (p_div == nullptr) {
        p_div = graph_utils::FirstChildByType(sub_node_dup, "Div");
      }
    }

    if (p_div == nullptr) {
      continue;
    }
    Node& div_node = *graph.GetNode(p_div->Index());
    if (!graph_utils::IsSupportedOptypeVersionAndDomain(div_node, "Div", {7}) ||
        div_node.GetExecutionProviderType() != reduce_mean_node.GetExecutionProviderType() ||
        div_node.GetOutputEdgesCount() != 1 ||
        !IsSupportedDataType(div_node)) {
      continue;
    }
    nodes_to_remove.push_back(div_node);

    // Traceback the div node to find sqrt --> div
    const Node* p_sqrt = graph_utils::FirstParentByType(div_node, "Sqrt");
    if (p_sqrt == nullptr) {
      continue;
    }
    Node& sqrt_node = *graph.GetNode(p_sqrt->Index());

    if (!graph_utils::IsSupportedOptypeVersionAndDomain(sqrt_node, "Sqrt", {6}) ||
        sqrt_node.GetExecutionProviderType() != reduce_mean_node.GetExecutionProviderType() ||
        sqrt_node.GetOutputEdgesCount() != 1 ||
        !IsSupportedDataType(sqrt_node) ||
        sqrt_node.GetInputEdgesCount() == 0) {
      continue;
    }
    nodes_to_remove.push_back(sqrt_node);

    // Traceback the sqrt node to find add --> sqrt
    Node& add2_node = *graph.GetNode(sqrt_node.InputNodesBegin()->Index());
    if (!graph_utils::IsSupportedOptypeVersionAndDomain(add2_node, "Add", {7}) ||
        add2_node.GetExecutionProviderType() != reduce_mean_node.GetExecutionProviderType() ||
        add2_node.GetOutputEdgesCount() != 1 ||
        !IsSupportedDataType(add2_node)) {
      continue;
    }
    nodes_to_remove.push_back(add2_node);

    // Traceback the add node to find reduceMean --> add
    const Node* p_reduce_mean2 = nullptr;

    p_reduce_mean2 = graph_utils::FirstParentByType(add2_node, "ReduceMean");
    if (p_reduce_mean2 == nullptr) {
      continue;
    }
    Node& reduce_mean2_node = *graph.GetNode(p_reduce_mean2->Index());
    if (!graph_utils::IsSupportedOptypeVersionAndDomain(reduce_mean2_node, "ReduceMean", {1}) ||
        reduce_mean2_node.GetExecutionProviderType() != reduce_mean_node.GetExecutionProviderType() ||
        reduce_mean2_node.GetOutputEdgesCount() != 1 ||
        !IsSupportedDataType(reduce_mean2_node) ||
        reduce_mean2_node.GetInputEdgesCount() == 0) {
      continue;
    }
    nodes_to_remove.push_back(reduce_mean2_node);

    // Traceback the reduceMean node to find pow --> reduceMean
    Node& pow_node = *graph.GetNode(reduce_mean2_node.InputNodesBegin()->Index());
    if (!graph_utils::IsSupportedOptypeVersionAndDomain(pow_node, "Pow", {7}) ||
        pow_node.GetExecutionProviderType() != reduce_mean_node.GetExecutionProviderType() ||
        pow_node.GetOutputEdgesCount() != 1 ||
        !IsSupportedDataType(pow_node)) {
      continue;
    }
    nodes_to_remove.push_back(pow_node);

    // Traceback the pow node to find sub --> pow
    const Node* p_sub2_node = graph_utils::FirstParentByType(pow_node, "Sub");
    if (p_sub2_node == nullptr) {
      continue;
    }
    Node& sub2_node = *graph.GetNode(p_sub2_node->Index());
    if (!graph_utils::IsSupportedOptypeVersionAndDomain(sub2_node, "Sub", {7}) ||
        sub2_node.GetExecutionProviderType() != reduce_mean_node.GetExecutionProviderType() ||
        !IsSupportedDataType(sub2_node)) {
      continue;
    }

    // Traceback the sub node to find reduceMean --> sub
    const Node* p_reduce_mean_check = graph_utils::FirstParentByType(sub2_node, "ReduceMean");
    // Check if the reduceMean node after traceback is the same node as the reduceMean node from the beginning.
    if (p_reduce_mean_check == nullptr || p_reduce_mean_check != &reduce_mean_node) {
      continue;
    }

    // div --> mul
    Node& mul_node = *graph.GetNode(div_node.OutputNodesBegin()->Index());
    if (!graph_utils::IsSupportedOptypeVersionAndDomain(mul_node, "Mul", {7}) ||
        mul_node.GetExecutionProviderType() != reduce_mean_node.GetExecutionProviderType() ||
        !IsSupportedDataType(mul_node)) {
      continue;
    }
    nodes_to_remove.push_back(mul_node);

    // mul --> add
    Node& last_add_node = *graph.GetNode(mul_node.OutputNodesBegin()->Index());
    if (!graph_utils::IsSupportedOptypeVersionAndDomain(last_add_node, "Add", {7}) ||
        last_add_node.GetExecutionProviderType() != reduce_mean_node.GetExecutionProviderType() ||
        !IsSupportedDataType(last_add_node)) {
      continue;
    }
    nodes_to_remove.push_back(last_add_node);

    // Get the inputs for the new LayerNormalization node.
    NodeArg* scale = nullptr;
    NodeArg* bias = nullptr;
    for (size_t i = 0; i < mul_node.MutableInputDefs().size(); i++) {
      if (graph_utils::NodeArgIsConstant(graph, *(mul_node.MutableInputDefs()[i])) ||
          graph_utils::IsGraphInput(graph, mul_node.MutableInputDefs()[i])) {
        // Scale must be 1d.
        if (mul_node.MutableInputDefs()[i]->Shape()->dim_size() == 1) {
          scale = mul_node.MutableInputDefs()[i];
        }
      }
    }

    for (size_t i = 0; i < last_add_node.MutableInputDefs().size(); i++) {
      if (graph_utils::NodeArgIsConstant(graph, *(last_add_node.MutableInputDefs()[i])) ||
          graph_utils::IsGraphInput(graph, last_add_node.MutableInputDefs()[i])) {
        // Bias must be 1d.
        if (last_add_node.MutableInputDefs()[i]->Shape()->dim_size() == 1) {
          bias = last_add_node.MutableInputDefs()[i];
        }
      }
    }
    if (scale == nullptr || bias == nullptr) {
      continue;
    }

    // Scale and bias must have the same dimension.
    if (scale->Shape()->dim(0).dim_value() != bias->Shape()->dim(0).dim_value()) {
      continue;
    }
    const std::vector<NodeArg*> layer_norm_input_defs{reduce_mean_node.MutableInputDefs()[0], scale, bias};
    Node& layer_norm_node = graph.AddNode(graph.GenerateNodeName("LayerNormalization"),
                                          "LayerNormalization",
                                          "fused LayerNorm subgraphs ",
                                          layer_norm_input_defs,
                                          {}, {}, kOnnxDomain);

    // Assign provider to this new node. Provider should be same as the provider for old node.
    layer_norm_node.SetExecutionProviderType(reduce_mean_node.GetExecutionProviderType());

    // move input edges to add (first in list) across to the layer_norm_node.
    // move output definitions and output edges from mul_node (last in list) to layer_norm_node.
    // remove all the other nodes.
    graph_utils::FinalizeNodeFusion(graph, nodes_to_remove, layer_norm_node);

    modified = true;
  }
  return Status::OK();
}
}  // namespace onnxruntime<commit_msg>make layernorm fusion to support opset 11 (#2545)<commit_after>// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
#include "core/optimizer/initializer.h"
#include "core/optimizer/layer_norm_fusion.h"
#include "core/graph/graph_utils.h"
#include "float.h"
#include <deque>

using namespace ONNX_NAMESPACE;
using namespace onnxruntime::common;
namespace onnxruntime {

// LayerNorm supports limited data types.
static std::vector<std::string> supported_data_types{"tensor(float16)", "tensor(float)", "tensor(double)"};

static bool IsSupportedDataType(const Node& node) {
  for (const auto& input_arg : node.InputDefs()) {
    if (std::find(supported_data_types.begin(), supported_data_types.end(),
                  *(input_arg->Type())) == supported_data_types.end()) {
      return false;
    }
  }
  return true;
}

/**
Layer Normalization will fuse LayerNormalization into one node :
+---------------------+
|                     |
|                     v
X --> ReduceMean --> Sub --> Pow --> ReduceMean --> Add --> Sqrt --> Div --> Mul --> Add
                      |                                               ^
                      |                                               |
                      +-----------------------------------------------+
It also handles cases of duplicated sub nodes exported from older version of PyTorch :
+---------------------+
|                     v
|          +-------> Sub ---------------------------------------------+
|          |                                                          |
|          |                                                          v
X --> ReduceMean --> Sub --> Pow --> ReduceMean --> Add --> Sqrt --> Div --> Mul --> Add
|                     ^
|                     |
+---------------------+
*/
Status LayerNormFusion::ApplyImpl(Graph& graph, bool& modified, int graph_level, const logging::Logger& logger) const {
  GraphViewer graph_viewer(graph);
  const auto& node_topology_list = graph_viewer.GetNodesInTopologicalOrder();
  std::vector<std::reference_wrapper<Node>> nodes_to_remove;
  for (auto node_index : node_topology_list) {
    nodes_to_remove.clear();
    auto* p_reduce_mean = graph.GetNode(node_index);
    if (p_reduce_mean == nullptr)
      continue;  // we removed the node as part of an earlier fusion

    Node& reduce_mean_node = *p_reduce_mean;
    ORT_RETURN_IF_ERROR(Recurse(reduce_mean_node, modified, graph_level, logger));

    if (!graph_utils::IsSupportedOptypeVersionAndDomain(reduce_mean_node, "ReduceMean", {1, 11}) ||
        !graph_utils::IsSupportedProvider(reduce_mean_node, GetCompatibleExecutionProviders()) ||
        (reduce_mean_node.GetOutputEdgesCount() != 1 && reduce_mean_node.GetOutputEdgesCount() != 2) ||
        !IsSupportedDataType(reduce_mean_node)) {
      continue;
    }
    nodes_to_remove.push_back(reduce_mean_node);

    // Loop through the children of current "ReduceMean" node. See if they match ["Sub"] or ["Sub", "Sub"]
    int subCnt = 0;
    const Node* p_sub_node = nullptr;
    const Node* p_sub_node_dup = nullptr;
    for (auto iter = reduce_mean_node.OutputNodesBegin(); iter != reduce_mean_node.OutputNodesEnd(); ++iter) {
      if ((*iter).OpType().compare("Sub") == 0) {
        if (subCnt == 0) {
          p_sub_node = &(*iter);

        } else {
          p_sub_node_dup = &(*iter);
        }
        subCnt++;
      } else {
        // doesn't match layer norm pattern. break.
        subCnt = -1;
        break;
      }
    }

    if (subCnt != 1 && subCnt != 2) {
      continue;
    }

    Node& sub_node = *graph.GetNode(p_sub_node->Index());
    if (!graph_utils::IsSupportedOptypeVersionAndDomain(sub_node, "Sub", {7}) ||
        sub_node.GetExecutionProviderType() != reduce_mean_node.GetExecutionProviderType() ||
        !IsSupportedDataType(sub_node)) {
      continue;
    }
    nodes_to_remove.push_back(sub_node);

    // Find the "Div" node after "Sub".
    const Node* p_div = nullptr;
    p_div = graph_utils::FirstChildByType(sub_node, "Div");

    // Find the sub_dup node if exist
    if (p_sub_node_dup != nullptr) {
      Node& sub_node_dup = *graph.GetNode(p_sub_node_dup->Index());
      if (!graph_utils::IsSupportedOptypeVersionAndDomain(sub_node_dup, "Sub", {7}) ||
          sub_node_dup.GetExecutionProviderType() != reduce_mean_node.GetExecutionProviderType() ||
          sub_node_dup.GetOutputEdgesCount() != 1 ||
          !IsSupportedDataType(sub_node_dup)) {
        continue;
      }
      nodes_to_remove.push_back(sub_node_dup);
      // Find Div node after the duplicated sub node if it's not found after the first sub node.
      if (p_div == nullptr) {
        p_div = graph_utils::FirstChildByType(sub_node_dup, "Div");
      }
    }

    if (p_div == nullptr) {
      continue;
    }
    Node& div_node = *graph.GetNode(p_div->Index());
    if (!graph_utils::IsSupportedOptypeVersionAndDomain(div_node, "Div", {7}) ||
        div_node.GetExecutionProviderType() != reduce_mean_node.GetExecutionProviderType() ||
        div_node.GetOutputEdgesCount() != 1 ||
        !IsSupportedDataType(div_node)) {
      continue;
    }
    nodes_to_remove.push_back(div_node);

    // Traceback the div node to find sqrt --> div
    const Node* p_sqrt = graph_utils::FirstParentByType(div_node, "Sqrt");
    if (p_sqrt == nullptr) {
      continue;
    }
    Node& sqrt_node = *graph.GetNode(p_sqrt->Index());

    if (!graph_utils::IsSupportedOptypeVersionAndDomain(sqrt_node, "Sqrt", {6}) ||
        sqrt_node.GetExecutionProviderType() != reduce_mean_node.GetExecutionProviderType() ||
        sqrt_node.GetOutputEdgesCount() != 1 ||
        !IsSupportedDataType(sqrt_node) ||
        sqrt_node.GetInputEdgesCount() == 0) {
      continue;
    }
    nodes_to_remove.push_back(sqrt_node);

    // Traceback the sqrt node to find add --> sqrt
    Node& add2_node = *graph.GetNode(sqrt_node.InputNodesBegin()->Index());
    if (!graph_utils::IsSupportedOptypeVersionAndDomain(add2_node, "Add", {7}) ||
        add2_node.GetExecutionProviderType() != reduce_mean_node.GetExecutionProviderType() ||
        add2_node.GetOutputEdgesCount() != 1 ||
        !IsSupportedDataType(add2_node)) {
      continue;
    }
    nodes_to_remove.push_back(add2_node);

    // Traceback the add node to find reduceMean --> add
    const Node* p_reduce_mean2 = nullptr;

    p_reduce_mean2 = graph_utils::FirstParentByType(add2_node, "ReduceMean");
    if (p_reduce_mean2 == nullptr) {
      continue;
    }
    Node& reduce_mean2_node = *graph.GetNode(p_reduce_mean2->Index());
    if (!graph_utils::IsSupportedOptypeVersionAndDomain(reduce_mean2_node, "ReduceMean", {1, 11}) ||
        reduce_mean2_node.GetExecutionProviderType() != reduce_mean_node.GetExecutionProviderType() ||
        reduce_mean2_node.GetOutputEdgesCount() != 1 ||
        !IsSupportedDataType(reduce_mean2_node) ||
        reduce_mean2_node.GetInputEdgesCount() == 0) {
      continue;
    }
    nodes_to_remove.push_back(reduce_mean2_node);

    // Traceback the reduceMean node to find pow --> reduceMean
    Node& pow_node = *graph.GetNode(reduce_mean2_node.InputNodesBegin()->Index());
    if (!graph_utils::IsSupportedOptypeVersionAndDomain(pow_node, "Pow", {7}) ||
        pow_node.GetExecutionProviderType() != reduce_mean_node.GetExecutionProviderType() ||
        pow_node.GetOutputEdgesCount() != 1 ||
        !IsSupportedDataType(pow_node)) {
      continue;
    }
    nodes_to_remove.push_back(pow_node);

    // Traceback the pow node to find sub --> pow
    const Node* p_sub2_node = graph_utils::FirstParentByType(pow_node, "Sub");
    if (p_sub2_node == nullptr) {
      continue;
    }
    Node& sub2_node = *graph.GetNode(p_sub2_node->Index());
    if (!graph_utils::IsSupportedOptypeVersionAndDomain(sub2_node, "Sub", {7}) ||
        sub2_node.GetExecutionProviderType() != reduce_mean_node.GetExecutionProviderType() ||
        !IsSupportedDataType(sub2_node)) {
      continue;
    }

    // Traceback the sub node to find reduceMean --> sub
    const Node* p_reduce_mean_check = graph_utils::FirstParentByType(sub2_node, "ReduceMean");
    // Check if the reduceMean node after traceback is the same node as the reduceMean node from the beginning.
    if (p_reduce_mean_check == nullptr || p_reduce_mean_check != &reduce_mean_node) {
      continue;
    }

    // div --> mul
    Node& mul_node = *graph.GetNode(div_node.OutputNodesBegin()->Index());
    if (!graph_utils::IsSupportedOptypeVersionAndDomain(mul_node, "Mul", {7}) ||
        mul_node.GetExecutionProviderType() != reduce_mean_node.GetExecutionProviderType() ||
        !IsSupportedDataType(mul_node)) {
      continue;
    }
    nodes_to_remove.push_back(mul_node);

    // mul --> add
    Node& last_add_node = *graph.GetNode(mul_node.OutputNodesBegin()->Index());
    if (!graph_utils::IsSupportedOptypeVersionAndDomain(last_add_node, "Add", {7}) ||
        last_add_node.GetExecutionProviderType() != reduce_mean_node.GetExecutionProviderType() ||
        !IsSupportedDataType(last_add_node)) {
      continue;
    }
    nodes_to_remove.push_back(last_add_node);

    // Get the inputs for the new LayerNormalization node.
    NodeArg* scale = nullptr;
    NodeArg* bias = nullptr;
    for (size_t i = 0; i < mul_node.MutableInputDefs().size(); i++) {
      if (graph_utils::NodeArgIsConstant(graph, *(mul_node.MutableInputDefs()[i])) ||
          graph_utils::IsGraphInput(graph, mul_node.MutableInputDefs()[i])) {
        // Scale must be 1d.
        if (mul_node.MutableInputDefs()[i]->Shape()->dim_size() == 1) {
          scale = mul_node.MutableInputDefs()[i];
        }
      }
    }

    for (size_t i = 0; i < last_add_node.MutableInputDefs().size(); i++) {
      if (graph_utils::NodeArgIsConstant(graph, *(last_add_node.MutableInputDefs()[i])) ||
          graph_utils::IsGraphInput(graph, last_add_node.MutableInputDefs()[i])) {
        // Bias must be 1d.
        if (last_add_node.MutableInputDefs()[i]->Shape()->dim_size() == 1) {
          bias = last_add_node.MutableInputDefs()[i];
        }
      }
    }
    if (scale == nullptr || bias == nullptr) {
      continue;
    }

    // Scale and bias must have the same dimension.
    if (scale->Shape()->dim(0).dim_value() != bias->Shape()->dim(0).dim_value()) {
      continue;
    }
    const std::vector<NodeArg*> layer_norm_input_defs{reduce_mean_node.MutableInputDefs()[0], scale, bias};
    Node& layer_norm_node = graph.AddNode(graph.GenerateNodeName("LayerNormalization"),
                                          "LayerNormalization",
                                          "fused LayerNorm subgraphs ",
                                          layer_norm_input_defs,
                                          {}, {}, kOnnxDomain);

    // Assign provider to this new node. Provider should be same as the provider for old node.
    layer_norm_node.SetExecutionProviderType(reduce_mean_node.GetExecutionProviderType());

    // move input edges to add (first in list) across to the layer_norm_node.
    // move output definitions and output edges from mul_node (last in list) to layer_norm_node.
    // remove all the other nodes.
    graph_utils::FinalizeNodeFusion(graph, nodes_to_remove, layer_norm_node);

    modified = true;
  }
  return Status::OK();
}
}  // namespace onnxruntime
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  $RCSfile: num.hxx,v $
 *
 *  $Revision: 1.5 $
 *
 *  last change: $Author: hr $ $Date: 2004-05-10 16:29:06 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (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.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

#ifndef _NUM_HXX
#define _NUM_HXX

#ifndef _SFXTABDLG_HXX //autogen
#include <sfx2/tabdlg.hxx>
#endif
#ifndef _MENUBTN_HXX //autogen
#include <vcl/menubtn.hxx>
#endif
#ifndef _FIELD_HXX //autogen
#include <vcl/field.hxx>
#endif
#ifndef _FIXED_HXX //autogen
#include <vcl/fixed.hxx>
#endif
#ifndef _STDCTRL_HXX //autogen
#include <svtools/stdctrl.hxx>
#endif
#ifndef _BUTTON_HXX //autogen
#include <vcl/button.hxx>
#endif
#ifndef _LSTBOX_HXX //autogen
#include <vcl/lstbox.hxx>
#endif
#ifndef _EDIT_HXX //autogen
#include <vcl/edit.hxx>
#endif
#ifndef _SVX_STDDLG_HXX //autogen
#include <svx/stddlg.hxx>
#endif
#ifndef _NUMPREVW_HXX
#include <numprevw.hxx>
#endif
//CHINA001 #ifndef _SVX_NUMPAGES_HXX
//CHINA001 #include <svx/numpages.hxx>
//CHINA001 #endif
#include "numrule.hxx"
#include "bmpwin.hxx" // BmpWindow

class SwWrtShell;
class SwDocShell;
class SwUiNumRules;
class SwCharFmt;
class SvxBrushItem;
class SwOutlineTabDialog;

/*-----------------13.02.97 14.02-------------------

--------------------------------------------------*/

struct SwBmpItemInfo
{
    SvxBrushItem*   pBrushItem;
    USHORT          nItemId;
};

/*-----------------07.02.97 15.37-------------------

--------------------------------------------------*/
#define NUM_PAGETYPE_BULLET         0
#define NUM_PAGETYPE_SINGLENUM      1
#define NUM_PAGETYPE_NUM            2
#define NUM_PAGETYPE_BMP            3
#define PAGETYPE_USER_START         10

/*-----------------08.02.97 10.48-------------------
    struct aktuelle Numerierung, wird in einem PointerItem
    uebertragen und von allen Tabpages geshared
--------------------------------------------------*/

class SwNumValueSet;
class ValueSet;
class SwBmpNumValueSet;

/*-----------------03.12.97 10:18-------------------

--------------------------------------------------*/
class SwNumPositionTabPage : public SfxTabPage
{
    FixedLine       aLevelFL;
    MultiListBox    aLevelLB;

    FixedLine            aPositionFL;
    FixedText           aDistBorderFT;
    MetricField         aDistBorderMF;
    CheckBox            aRelativeCB;
    FixedText           aIndentFT;
    MetricField         aIndentMF;
    FixedText           aDistNumFT;
    MetricField         aDistNumMF;
    FixedText           aAlignFT;
    ListBox             aAlignLB;
    PushButton          aStandardPB;

    NumberingPreview    aPreviewWIN;

    SwNumRule*          pActNum;
    SwNumRule*          pSaveNum;
    SwWrtShell*         pWrtSh;

    SwOutlineTabDialog* pOutlineDlg;
    USHORT              nActNumLvl;

    BOOL                bModified           : 1;
    BOOL                bHasChild           : 1;
    BOOL                bPreset             : 1;
    BOOL                bInInintControl     : 1;  //Modify-Fehler umgehen, soll ab 391 behoben sein

//  void                SetMinDist();
    void                InitControls();

    DECL_LINK( LevelHdl, ListBox * );
    DECL_LINK( EditModifyHdl, Edit*);
    DECL_LINK( DistanceHdl, MetricField * );
    DECL_LINK( RelativeHdl, CheckBox * );
    DECL_LINK( StandardHdl, PushButton * );

    public:
        SwNumPositionTabPage(Window* pParent,
                               const SfxItemSet& rSet);
        ~SwNumPositionTabPage();

    virtual void        ActivatePage(const SfxItemSet& rSet);
    virtual int         DeactivatePage(SfxItemSet *pSet);
    virtual BOOL        FillItemSet( SfxItemSet& rSet );
    virtual void        Reset( const SfxItemSet& rSet );

    static SfxTabPage*  Create( Window* pParent,
                                const SfxItemSet& rAttrSet);

    void                SetOutlineTabDialog(SwOutlineTabDialog* pDlg){pOutlineDlg = pDlg;}
    void                SetWrtShell(SwWrtShell* pSh);
#if OSL_DEBUG_LEVEL > 1
    void                SetModified(BOOL bRepaint = TRUE);
#else
    void                SetModified(BOOL bRepaint = TRUE)
                            {bModified = TRUE;
                                if(bRepaint)
                                {
                                    aPreviewWIN.SetLevel(nActNumLvl);
                                    aPreviewWIN.Invalidate();
                                }
                            }
#endif
};

class SwSvxNumBulletTabDialog : public SfxTabDialog
{
    SwWrtShell&         rWrtSh;

    String              sRemoveText;
    int                 nRetOptionsDialog;

    protected:
        virtual short   Ok();
        virtual void    PageCreated(USHORT nPageId, SfxTabPage& rPage);
        DECL_LINK(RemoveNumberingHdl, PushButton*);
    public:
        SwSvxNumBulletTabDialog(Window* pParent,
                    const SfxItemSet* pSwItemSet,
                    SwWrtShell &);
        ~SwSvxNumBulletTabDialog();
};
#endif // _NUM_CXX

<commit_msg>INTEGRATION: CWS ooo19126 (1.5.726); FILE MERGED 2005/09/05 13:45:28 rt 1.5.726.1: #i54170# Change license header: remove SISSL<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: num.hxx,v $
 *
 *  $Revision: 1.6 $
 *
 *  last change: $Author: rt $ $Date: 2005-09-09 09:52:33 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

#ifndef _NUM_HXX
#define _NUM_HXX

#ifndef _SFXTABDLG_HXX //autogen
#include <sfx2/tabdlg.hxx>
#endif
#ifndef _MENUBTN_HXX //autogen
#include <vcl/menubtn.hxx>
#endif
#ifndef _FIELD_HXX //autogen
#include <vcl/field.hxx>
#endif
#ifndef _FIXED_HXX //autogen
#include <vcl/fixed.hxx>
#endif
#ifndef _STDCTRL_HXX //autogen
#include <svtools/stdctrl.hxx>
#endif
#ifndef _BUTTON_HXX //autogen
#include <vcl/button.hxx>
#endif
#ifndef _LSTBOX_HXX //autogen
#include <vcl/lstbox.hxx>
#endif
#ifndef _EDIT_HXX //autogen
#include <vcl/edit.hxx>
#endif
#ifndef _SVX_STDDLG_HXX //autogen
#include <svx/stddlg.hxx>
#endif
#ifndef _NUMPREVW_HXX
#include <numprevw.hxx>
#endif
//CHINA001 #ifndef _SVX_NUMPAGES_HXX
//CHINA001 #include <svx/numpages.hxx>
//CHINA001 #endif
#include "numrule.hxx"
#include "bmpwin.hxx" // BmpWindow

class SwWrtShell;
class SwDocShell;
class SwUiNumRules;
class SwCharFmt;
class SvxBrushItem;
class SwOutlineTabDialog;

/*-----------------13.02.97 14.02-------------------

--------------------------------------------------*/

struct SwBmpItemInfo
{
    SvxBrushItem*   pBrushItem;
    USHORT          nItemId;
};

/*-----------------07.02.97 15.37-------------------

--------------------------------------------------*/
#define NUM_PAGETYPE_BULLET         0
#define NUM_PAGETYPE_SINGLENUM      1
#define NUM_PAGETYPE_NUM            2
#define NUM_PAGETYPE_BMP            3
#define PAGETYPE_USER_START         10

/*-----------------08.02.97 10.48-------------------
    struct aktuelle Numerierung, wird in einem PointerItem
    uebertragen und von allen Tabpages geshared
--------------------------------------------------*/

class SwNumValueSet;
class ValueSet;
class SwBmpNumValueSet;

/*-----------------03.12.97 10:18-------------------

--------------------------------------------------*/
class SwNumPositionTabPage : public SfxTabPage
{
    FixedLine       aLevelFL;
    MultiListBox    aLevelLB;

    FixedLine            aPositionFL;
    FixedText           aDistBorderFT;
    MetricField         aDistBorderMF;
    CheckBox            aRelativeCB;
    FixedText           aIndentFT;
    MetricField         aIndentMF;
    FixedText           aDistNumFT;
    MetricField         aDistNumMF;
    FixedText           aAlignFT;
    ListBox             aAlignLB;
    PushButton          aStandardPB;

    NumberingPreview    aPreviewWIN;

    SwNumRule*          pActNum;
    SwNumRule*          pSaveNum;
    SwWrtShell*         pWrtSh;

    SwOutlineTabDialog* pOutlineDlg;
    USHORT              nActNumLvl;

    BOOL                bModified           : 1;
    BOOL                bHasChild           : 1;
    BOOL                bPreset             : 1;
    BOOL                bInInintControl     : 1;  //Modify-Fehler umgehen, soll ab 391 behoben sein

//  void                SetMinDist();
    void                InitControls();

    DECL_LINK( LevelHdl, ListBox * );
    DECL_LINK( EditModifyHdl, Edit*);
    DECL_LINK( DistanceHdl, MetricField * );
    DECL_LINK( RelativeHdl, CheckBox * );
    DECL_LINK( StandardHdl, PushButton * );

    public:
        SwNumPositionTabPage(Window* pParent,
                               const SfxItemSet& rSet);
        ~SwNumPositionTabPage();

    virtual void        ActivatePage(const SfxItemSet& rSet);
    virtual int         DeactivatePage(SfxItemSet *pSet);
    virtual BOOL        FillItemSet( SfxItemSet& rSet );
    virtual void        Reset( const SfxItemSet& rSet );

    static SfxTabPage*  Create( Window* pParent,
                                const SfxItemSet& rAttrSet);

    void                SetOutlineTabDialog(SwOutlineTabDialog* pDlg){pOutlineDlg = pDlg;}
    void                SetWrtShell(SwWrtShell* pSh);
#if OSL_DEBUG_LEVEL > 1
    void                SetModified(BOOL bRepaint = TRUE);
#else
    void                SetModified(BOOL bRepaint = TRUE)
                            {bModified = TRUE;
                                if(bRepaint)
                                {
                                    aPreviewWIN.SetLevel(nActNumLvl);
                                    aPreviewWIN.Invalidate();
                                }
                            }
#endif
};

class SwSvxNumBulletTabDialog : public SfxTabDialog
{
    SwWrtShell&         rWrtSh;

    String              sRemoveText;
    int                 nRetOptionsDialog;

    protected:
        virtual short   Ok();
        virtual void    PageCreated(USHORT nPageId, SfxTabPage& rPage);
        DECL_LINK(RemoveNumberingHdl, PushButton*);
    public:
        SwSvxNumBulletTabDialog(Window* pParent,
                    const SfxItemSet* pSwItemSet,
                    SwWrtShell &);
        ~SwSvxNumBulletTabDialog();
};
#endif // _NUM_CXX

<|endoftext|>


<commit_before>
#include "gps.hpp"
#include "nmea.hpp"
#include "backtrace.hpp"
#include <iostream>

gps::gps() : running(false), gps_port(io_service), queue_len(50)
{

}
gps::~gps()
{
	stop();
}

void gps::start()
{
	running = true;
	iothread = boost::thread(boost::bind(&gps::gps_comm, this));
}

void gps::stop()
{
	running = false;
	iothread.join();
}

bool gps::get_last_state(GPSState& state)
{
	boost::mutex::scoped_lock lock(state_queue_mutex);

	if(state_queue.empty())
	{
		std::cerr << "GPS queue empty!" << std::endl;
		return false;
	}

	struct timeval now;
	gettimeofday(&now, NULL);
	time_t secDelta = difftime(now.tv_sec, state_queue.back().laptoptime.tv_sec);
	suseconds_t usecDelta = now.tv_usec - state_queue.back().laptoptime.tv_usec;
	double delta = double(secDelta) + 1e-6*double(usecDelta);
	if(delta > .5)
	{
		std::cerr << "GPS Marker Out Of Date!" << std::endl;
		return false;
	}

	if( (state_queue.back().qual != GPS_QUALITY_NON_DIFF) && (state_queue.back().qual != GPS_QUALITY_WAAS))
	{
		std::cerr << "GPS state bad - " << int(state_queue.back().qual) << std::endl;
		return false;
	}

	state = state_queue.back();
	return true;
}

bool gps::get_speed(double& speed)
{
	GPSState state;
	if(get_last_state(state))
	{
		speed = state.speedoverground;
		return true;
	}
	return false;
}

bool gps::get_heading(double& heading)
{
	GPSState state;
	if(get_last_state(state))
	{
		heading = state.courseoverground;
		return true;
	}
	return false;
}

bool gps::open(const char* port, size_t baud)
{
	m_port = port;
	m_baud = baud;

	try
	{
		gps_port.open(port);
	}
	catch(...)
	{
		std::cerr << "Failed to open serial port" << std::endl;
		stacktrace();
		return false;
	}

	if(!gps_port.is_open())
	{
		return false;
	}

	try
	{
		gps_port.set_option(boost::asio::serial_port_base::baud_rate(baud));
		//gps_port.set_option(boost::asio::serial_port_base::flow_control(boost::asio::serial_port_base::flow_control::none));
		gps_port.set_option(boost::asio::serial_port_base::parity(boost::asio::serial_port_base::parity::none));
		gps_port.set_option(boost::asio::serial_port_base::stop_bits(boost::asio::serial_port_base::stop_bits::one));
	}
	catch(...)
	{
		return false;
	}

	m_connected = true;

	return true;
}

void gps::close()
{
	gps_port.close();
	m_connected = false;
}

void gps::handle_serial_read_timer(const boost::system::error_code& ec)
{
	if(ec)
	{
		return;
	}

	std::cerr << "Serial Timout" << std::endl;
{
	boost::mutex::scoped_lock lock(state_queue_mutex);
	state_queue.clear();
}

	gps_port.cancel();
	reconnect();
}

void gps::handle_serial_read(const boost::system::error_code& ec, size_t len, boost::asio::deadline_timer& timeout)
{
	if(ec || (len == 0))
	{
		return;
	}
	timeout.cancel();//data rec, kill the timer

	std::string line;
	try
	{
		std::istream is(&comm_buffer);
		std::getline(is, line);
	}
	catch(...)
	{
		std::cerr << "Error parsing GPS packet!" << std::endl;
		return;
	}

	try
	{
		GPSState state;
		//if(nmea::decodeGPGGA(line, state))
		if(nmea::decodeGPRMC(line, state))
		{
			gettimeofday(&state.laptoptime, NULL);
			boost::mutex::scoped_lock lock(state_queue_mutex);

			state_queue.push_back(state);
			if(state_queue.size() > queue_len)
			{
				state_queue.pop_front();
			}
		}
	}
	catch(...)
	{
		std::cerr << "Error parsing GPS packet!" << std::endl;
	}
}

void gps::gps_comm()
{
	while(running)
	{
		boost::asio::deadline_timer timeout(io_service);
		timeout.expires_from_now(boost::posix_time::milliseconds(2e3));
		try
		{
			boost::asio::async_read_until(gps_port, comm_buffer, '\n', boost::bind(&gps::handle_serial_read, this, boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred, boost::ref(timeout)));

			timeout.async_wait(boost::bind(&gps::handle_serial_read_timer, this, boost::asio::placeholders::error));

			io_service.run();
			io_service.reset();
		}
		catch(...)
		{
			reconnect();
		}
	}
}

void gps::reconnect()
{
	close();
	usleep(1e6);
	open(m_port.c_str(), m_baud);
}

bool gps::parse_message(const std::string& line, GPSState& state)
{
	if(nmea::decodeGPGGA(line, state))
	{
		return true;
	}
	if(nmea::decodeGPRMC(line, state))
	{
		return true;
	}
	if(nmea::decodeGPRMT(line))
	{
		return true;
	}
	if(nmea::decodeGPGSA(line))
	{
		return true;
	}
	if(nmea::decodeGPGSV(line))
	{
		return true;
	}
	return false;
}

<commit_msg>improve gps slightly<commit_after>
#include "gps.hpp"
#include "nmea.hpp"
#include "backtrace.hpp"
#include <iostream>

gps::gps() : running(false), gps_port(io_service), queue_len(50)
{

}
gps::~gps()
{
	stop();
}

void gps::start()
{
	running = true;
	iothread = boost::thread(boost::bind(&gps::gps_comm, this));
}

void gps::stop()
{
	running = false;
	iothread.join();
}

bool gps::get_last_state(GPSState& state)
{
	boost::mutex::scoped_lock lock(state_queue_mutex);

	if(state_queue.empty())
	{
		std::cerr << "GPS queue empty!" << std::endl;
		return false;
	}

	struct timeval now;
	gettimeofday(&now, NULL);
	time_t secDelta = difftime(now.tv_sec, state_queue.back().laptoptime.tv_sec);
	suseconds_t usecDelta = now.tv_usec - state_queue.back().laptoptime.tv_usec;
	double delta = double(secDelta) + 1e-6*double(usecDelta);
	if(delta > .5)
	{
		std::cerr << "GPS Marker Out Of Date!" << std::endl;
		//return false;//if we want it to be fatal HACK
	}

	if( (state_queue.back().qual != GPS_QUALITY_NON_DIFF) && (state_queue.back().qual != GPS_QUALITY_WAAS))
	{
		std::cerr << "GPS state bad - " << int(state_queue.back().qual) << std::endl;
		//return false;//if we want it to be fatal HACK
	}

	state = state_queue.back();
	return true;
}

bool gps::get_speed(double& speed)
{
	GPSState state;
	if(get_last_state(state))
	{
		speed = state.speedoverground;
		return true;
	}
	return false;
}

bool gps::get_heading(double& heading)
{
	GPSState state;
	if(get_last_state(state))
	{
		heading = state.courseoverground;
		return true;
	}
	return false;
}

bool gps::open(const char* port, size_t baud)
{
	m_port = port;
	m_baud = baud;

	try
	{
		gps_port.open(port);
	}
	catch(...)
	{
		std::cerr << "Failed to open serial port" << std::endl;
		stacktrace();
		return false;
	}

	if(!gps_port.is_open())
	{
		return false;
	}

	try
	{
		gps_port.set_option(boost::asio::serial_port_base::baud_rate(baud));
		//gps_port.set_option(boost::asio::serial_port_base::flow_control(boost::asio::serial_port_base::flow_control::none));
		gps_port.set_option(boost::asio::serial_port_base::parity(boost::asio::serial_port_base::parity::none));
		gps_port.set_option(boost::asio::serial_port_base::stop_bits(boost::asio::serial_port_base::stop_bits::one));
	}
	catch(...)
	{
		return false;
	}

	m_connected = true;

	return true;
}

void gps::close()
{
	gps_port.close();
	m_connected = false;
}

void gps::handle_serial_read_timer(const boost::system::error_code& ec)
{
	if(ec)
	{
		return;
	}

	std::cerr << "Serial Timout" << std::endl;
{
	boost::mutex::scoped_lock lock(state_queue_mutex);
	state_queue.clear();
}

	gps_port.cancel();
	reconnect();
}

void gps::handle_serial_read(const boost::system::error_code& ec, size_t len, boost::asio::deadline_timer& timeout)
{
	if(ec || (len == 0))
	{
		return;
	}
	timeout.cancel();//data rec, kill the timer

	std::string line;
	try
	{
		std::istream is(&comm_buffer);
		std::getline(is, line);
	}
	catch(...)
	{
		std::cerr << "Error parsing GPS packet!" << std::endl;
		return;
	}

	try
	{
		GPSState state;
		//if(nmea::decodeGPGGA(line, state))
		//if(nmea::decodeGPRMC(line, state))
		if(gps::parse_message(line, state))
		{
			gettimeofday(&state.laptoptime, NULL);
			boost::mutex::scoped_lock lock(state_queue_mutex);

			state_queue.push_back(state);
			if(state_queue.size() > queue_len)
			{
				state_queue.pop_front();
			}
		}
	}
	catch(...)
	{
		std::cerr << "Error parsing GPS packet!" << std::endl;
	}
}

void gps::gps_comm()
{
	while(running)
	{
		boost::asio::deadline_timer timeout(io_service);
		timeout.expires_from_now(boost::posix_time::milliseconds(2e3));
		try
		{
			boost::asio::async_read_until(gps_port, comm_buffer, '\n', boost::bind(&gps::handle_serial_read, this, boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred, boost::ref(timeout)));

			timeout.async_wait(boost::bind(&gps::handle_serial_read_timer, this, boost::asio::placeholders::error));

			io_service.run();
			io_service.reset();
		}
		catch(...)
		{
			reconnect();
		}
	}
}

void gps::reconnect()
{
	close();
	usleep(1e6);
	open(m_port.c_str(), m_baud);
}

bool gps::parse_message(const std::string& line, GPSState& state)
{
	if(nmea::decodeGPGGA(line, state))
	{
		return true;
	}
	if(nmea::decodeGPRMC(line, state))
	{
		return true;
	}
	if(nmea::decodeGPRMT(line))
	{
		return true;
	}
	if(nmea::decodeGPGSA(line))
	{
		return true;
	}
	if(nmea::decodeGPGSV(line))
	{
		return true;
	}
	return false;
}

<|endoftext|>


<commit_before><commit_msg>component labels use correct allocator - fixes #885<commit_after><|endoftext|>