<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: pyuno_util.cxx,v $
 *
 *  $Revision: 1.6 $
 *
 *  last change: $Author: hr $ $Date: 2006-06-20 05:04:45 $
 *
 *  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
 *
 ************************************************************************/

#include "pyuno_impl.hxx"

#include <time.h>
#include <osl/thread.h>

#include <typelib/typedescription.hxx>

#include <rtl/strbuf.hxx>
#include <rtl/ustrbuf.hxx>
#include <osl/time.h>

#include <com/sun/star/beans/XMaterialHolder.hpp>

using rtl::OUStringToOString;
using rtl::OUString;
using rtl::OString;
using rtl::OStringBuffer;
using rtl::OUStringBuffer;

using com::sun::star::uno::TypeDescription;
using com::sun::star::uno::Sequence;
using com::sun::star::uno::Reference;
using com::sun::star::uno::XInterface;
using com::sun::star::uno::Any;
using com::sun::star::uno::Type;
using com::sun::star::uno::UNO_QUERY;
using com::sun::star::uno::TypeClass;
using com::sun::star::uno::RuntimeException;
using com::sun::star::uno::XComponentContext;
using com::sun::star::lang::XSingleServiceFactory;
using com::sun::star::script::XTypeConverter;
using com::sun::star::beans::XMaterialHolder;

#define USTR_ASCII(x) OUString( RTL_CONSTASCII_USTRINGPARAM( x ) )
namespace pyuno
{
PyRef ustring2PyUnicode( const OUString & str )
{
    PyRef ret;
#if Py_UNICODE_SIZE == 2
    ret = PyRef( PyUnicode_FromUnicode( str.getStr(), str.getLength() ), SAL_NO_ACQUIRE );
#else
    OString sUtf8(OUStringToOString(str, RTL_TEXTENCODING_UTF8));
    ret = PyRef( PyUnicode_DecodeUTF8( sUtf8.getStr(), sUtf8.getLength(), NULL) , SAL_NO_ACQUIRE );
#endif
    return ret;
}

PyRef ustring2PyString( const OUString &str )
{
    OString o = OUStringToOString( str, osl_getThreadTextEncoding() );
    return PyRef( PyString_FromString( o.getStr() ), SAL_NO_ACQUIRE );
}

OUString pyString2ustring( PyObject *pystr )
{
    OUString ret;
    if( PyUnicode_Check( pystr ) )
    {
#if Py_UNICODE_SIZE == 2
    ret = OUString( (sal_Unicode * ) PyUnicode_AS_UNICODE( pystr ) );
#else
    PyObject* pUtf8 = PyUnicode_AsUTF8String(pystr);
    ret = OUString(PyString_AsString(pUtf8), PyString_Size(pUtf8), RTL_TEXTENCODING_UTF8);
    Py_DECREF(pUtf8);
#endif
    }
    else
    {
        char *name = PyString_AsString(pystr );
        ret = OUString( name, strlen(name), osl_getThreadTextEncoding() );
    }
    return ret;
}

PyRef getObjectFromUnoModule( const Runtime &runtime, const char * func )
    throw ( RuntimeException )
{
    PyRef object(PyDict_GetItemString( runtime.getImpl()->cargo->getUnoModule().get(), (char*)func ) );
    if( !object.is() )
    {
        OUStringBuffer buf;
        buf.appendAscii( "couldn't find core function " );
        buf.appendAscii( func );
        throw RuntimeException(buf.makeStringAndClear(),Reference< XInterface >());
    }
    return object;
}

//------------------------------------------------------------------------------------
// Logging
//------------------------------------------------------------------------------------

bool isLog( RuntimeCargo * cargo, sal_Int32 loglevel )
{
    return cargo && cargo->logFile && loglevel <= cargo->logLevel;
}

void log( RuntimeCargo * cargo, sal_Int32 level, const rtl::OUString &logString )
{
    log( cargo, level, OUStringToOString( logString, osl_getThreadTextEncoding() ).getStr() );
}

void log( RuntimeCargo * cargo, sal_Int32 level, const char *str )
{
    if( isLog( cargo, level ) )
    {
        static const char *strLevel[] = { "NONE", "CALL", "ARGS" };

        TimeValue systemTime;
        TimeValue localTime;
        oslDateTime localDateTime;

        osl_getSystemTime( &systemTime );
        osl_getLocalTimeFromSystemTime( &systemTime, &localTime );
        osl_getDateTimeFromTimeValue( &localTime, &localDateTime );

        fprintf( cargo->logFile,
                 "%4i-%02i-%02i %02i:%02i:%02i,%03i [%s,tid %i]: %s\n",
                 localDateTime.Year,
                 localDateTime.Month,
                 localDateTime.Day,
                 localDateTime.Hours,
                 localDateTime.Minutes,
                 localDateTime.Seconds,
                 localDateTime.NanoSeconds/1000000,
                 strLevel[level],
                 (sal_Int32) osl_getThreadIdentifier( 0),
                 str );
    }
}

namespace {

void appendPointer(rtl::OUStringBuffer & buffer, void * pointer) {
    buffer.append(
        sal::static_int_cast< sal_Int64 >(
            reinterpret_cast< sal_IntPtr >(pointer)),
        16);
}

}

void logException( RuntimeCargo *cargo, const char *intro,
                   void * ptr, const rtl::OUString &aFunctionName,
                   const void * data, const com::sun::star::uno::Type & type )
{
    if( isLog( cargo, LogLevel::CALL ) )
    {
        rtl::OUStringBuffer buf( 128 );
        buf.appendAscii( intro );
        appendPointer(buf, ptr);
        buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("].") );
        buf.append( aFunctionName );
        buf.appendAscii( RTL_CONSTASCII_STRINGPARAM( " = " ) );
        buf.append(
            val2str( data, type.getTypeLibType(), VAL2STR_MODE_SHALLOW ) );
        log( cargo,LogLevel::CALL, buf.makeStringAndClear() );
    }

}

void logReply(
    RuntimeCargo *cargo,
    const char *intro,
    void * ptr,
    const rtl::OUString & aFunctionName,
    const Any &returnValue,
    const Sequence< Any > & aParams )
{
    rtl::OUStringBuffer buf( 128 );
    buf.appendAscii( intro );
    appendPointer(buf, ptr);
    buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("].") );
    buf.append( aFunctionName );
    buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("()=") );
    if( isLog( cargo, LogLevel::ARGS ) )
    {
        buf.append(
            val2str( returnValue.getValue(), returnValue.getValueTypeRef(), VAL2STR_MODE_SHALLOW) );
        for( int i = 0; i < aParams.getLength() ; i ++ )
        {
            buf.appendAscii( RTL_CONSTASCII_STRINGPARAM(", " ) );
            buf.append(
                val2str( aParams[i].getValue(), aParams[i].getValueTypeRef(), VAL2STR_MODE_SHALLOW) );
        }
    }
    log( cargo,LogLevel::CALL, buf.makeStringAndClear() );

}

void logCall( RuntimeCargo *cargo, const char *intro,
              void * ptr, const rtl::OUString & aFunctionName,
              const Sequence< Any > & aParams )
{
    rtl::OUStringBuffer buf( 128 );
    buf.appendAscii( intro );
    appendPointer(buf, ptr);
    buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("].") );
    buf.append( aFunctionName );
    buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("(") );
    if( isLog( cargo, LogLevel::ARGS ) )
    {
        for( int i = 0; i < aParams.getLength() ; i ++ )
        {
            if( i > 0 )
                buf.appendAscii( RTL_CONSTASCII_STRINGPARAM(", " ) );
            buf.append(
                val2str( aParams[i].getValue(), aParams[i].getValueTypeRef(), VAL2STR_MODE_SHALLOW) );
        }
    }
    buf.appendAscii( RTL_CONSTASCII_STRINGPARAM(")") );
    log( cargo,LogLevel::CALL, buf.makeStringAndClear() );
}

}
<commit_msg>INTEGRATION: CWS warningfixes02 (1.6.2); FILE MERGED 2006/06/30 12:16:38 sb 1.6.2.1: #i66577# Made the code compile (warning-free) on a unxlngi6.pro GCC 4.1.1 Linux box.<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: pyuno_util.cxx,v $
 *
 *  $Revision: 1.7 $
 *
 *  last change: $Author: kz $ $Date: 2006-07-19 16:42:39 $
 *
 *  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
 *
 ************************************************************************/

#include "pyuno_impl.hxx"

#include <time.h>
#include <osl/thread.h>

#include <typelib/typedescription.hxx>

#include <rtl/strbuf.hxx>
#include <rtl/ustrbuf.hxx>
#include <osl/time.h>

#include <com/sun/star/beans/XMaterialHolder.hpp>

using rtl::OUStringToOString;
using rtl::OUString;
using rtl::OString;
using rtl::OStringBuffer;
using rtl::OUStringBuffer;

using com::sun::star::uno::TypeDescription;
using com::sun::star::uno::Sequence;
using com::sun::star::uno::Reference;
using com::sun::star::uno::XInterface;
using com::sun::star::uno::Any;
using com::sun::star::uno::Type;
using com::sun::star::uno::UNO_QUERY;
using com::sun::star::uno::TypeClass;
using com::sun::star::uno::RuntimeException;
using com::sun::star::uno::XComponentContext;
using com::sun::star::lang::XSingleServiceFactory;
using com::sun::star::script::XTypeConverter;
using com::sun::star::beans::XMaterialHolder;

#define USTR_ASCII(x) OUString( RTL_CONSTASCII_USTRINGPARAM( x ) )
namespace pyuno
{
PyRef ustring2PyUnicode( const OUString & str )
{
    PyRef ret;
#if Py_UNICODE_SIZE == 2
    ret = PyRef( PyUnicode_FromUnicode( str.getStr(), str.getLength() ), SAL_NO_ACQUIRE );
#else
    OString sUtf8(OUStringToOString(str, RTL_TEXTENCODING_UTF8));
    ret = PyRef( PyUnicode_DecodeUTF8( sUtf8.getStr(), sUtf8.getLength(), NULL) , SAL_NO_ACQUIRE );
#endif
    return ret;
}

PyRef ustring2PyString( const OUString &str )
{
    OString o = OUStringToOString( str, osl_getThreadTextEncoding() );
    return PyRef( PyString_FromString( o.getStr() ), SAL_NO_ACQUIRE );
}

OUString pyString2ustring( PyObject *pystr )
{
    OUString ret;
    if( PyUnicode_Check( pystr ) )
    {
#if Py_UNICODE_SIZE == 2
    ret = OUString( (sal_Unicode * ) PyUnicode_AS_UNICODE( pystr ) );
#else
    PyObject* pUtf8 = PyUnicode_AsUTF8String(pystr);
    ret = OUString(PyString_AsString(pUtf8), PyString_Size(pUtf8), RTL_TEXTENCODING_UTF8);
    Py_DECREF(pUtf8);
#endif
    }
    else
    {
        char *name = PyString_AsString(pystr );
        ret = OUString( name, strlen(name), osl_getThreadTextEncoding() );
    }
    return ret;
}

PyRef getObjectFromUnoModule( const Runtime &runtime, const char * func )
    throw ( RuntimeException )
{
    PyRef object(PyDict_GetItemString( runtime.getImpl()->cargo->getUnoModule().get(), (char*)func ) );
    if( !object.is() )
    {
        OUStringBuffer buf;
        buf.appendAscii( "couldn't find core function " );
        buf.appendAscii( func );
        throw RuntimeException(buf.makeStringAndClear(),Reference< XInterface >());
    }
    return object;
}

//------------------------------------------------------------------------------------
// Logging
//------------------------------------------------------------------------------------

bool isLog( RuntimeCargo * cargo, sal_Int32 loglevel )
{
    return cargo && cargo->logFile && loglevel <= cargo->logLevel;
}

void log( RuntimeCargo * cargo, sal_Int32 level, const rtl::OUString &logString )
{
    log( cargo, level, OUStringToOString( logString, osl_getThreadTextEncoding() ).getStr() );
}

void log( RuntimeCargo * cargo, sal_Int32 level, const char *str )
{
    if( isLog( cargo, level ) )
    {
        static const char *strLevel[] = { "NONE", "CALL", "ARGS" };

        TimeValue systemTime;
        TimeValue localTime;
        oslDateTime localDateTime;

        osl_getSystemTime( &systemTime );
        osl_getLocalTimeFromSystemTime( &systemTime, &localTime );
        osl_getDateTimeFromTimeValue( &localTime, &localDateTime );

        fprintf( cargo->logFile,
                 "%4i-%02i-%02i %02i:%02i:%02i,%03lu [%s,tid %ld]: %s\n",
                 localDateTime.Year,
                 localDateTime.Month,
                 localDateTime.Day,
                 localDateTime.Hours,
                 localDateTime.Minutes,
                 localDateTime.Seconds,
                 sal::static_int_cast< unsigned long >(
                     localDateTime.NanoSeconds/1000000),
                 strLevel[level],
                 sal::static_int_cast< long >(
                     (sal_Int32) osl_getThreadIdentifier( 0)),
                 str );
    }
}

namespace {

void appendPointer(rtl::OUStringBuffer & buffer, void * pointer) {
    buffer.append(
        sal::static_int_cast< sal_Int64 >(
            reinterpret_cast< sal_IntPtr >(pointer)),
        16);
}

}

void logException( RuntimeCargo *cargo, const char *intro,
                   void * ptr, const rtl::OUString &aFunctionName,
                   const void * data, const com::sun::star::uno::Type & type )
{
    if( isLog( cargo, LogLevel::CALL ) )
    {
        rtl::OUStringBuffer buf( 128 );
        buf.appendAscii( intro );
        appendPointer(buf, ptr);
        buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("].") );
        buf.append( aFunctionName );
        buf.appendAscii( RTL_CONSTASCII_STRINGPARAM( " = " ) );
        buf.append(
            val2str( data, type.getTypeLibType(), VAL2STR_MODE_SHALLOW ) );
        log( cargo,LogLevel::CALL, buf.makeStringAndClear() );
    }

}

void logReply(
    RuntimeCargo *cargo,
    const char *intro,
    void * ptr,
    const rtl::OUString & aFunctionName,
    const Any &returnValue,
    const Sequence< Any > & aParams )
{
    rtl::OUStringBuffer buf( 128 );
    buf.appendAscii( intro );
    appendPointer(buf, ptr);
    buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("].") );
    buf.append( aFunctionName );
    buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("()=") );
    if( isLog( cargo, LogLevel::ARGS ) )
    {
        buf.append(
            val2str( returnValue.getValue(), returnValue.getValueTypeRef(), VAL2STR_MODE_SHALLOW) );
        for( int i = 0; i < aParams.getLength() ; i ++ )
        {
            buf.appendAscii( RTL_CONSTASCII_STRINGPARAM(", " ) );
            buf.append(
                val2str( aParams[i].getValue(), aParams[i].getValueTypeRef(), VAL2STR_MODE_SHALLOW) );
        }
    }
    log( cargo,LogLevel::CALL, buf.makeStringAndClear() );

}

void logCall( RuntimeCargo *cargo, const char *intro,
              void * ptr, const rtl::OUString & aFunctionName,
              const Sequence< Any > & aParams )
{
    rtl::OUStringBuffer buf( 128 );
    buf.appendAscii( intro );
    appendPointer(buf, ptr);
    buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("].") );
    buf.append( aFunctionName );
    buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("(") );
    if( isLog( cargo, LogLevel::ARGS ) )
    {
        for( int i = 0; i < aParams.getLength() ; i ++ )
        {
            if( i > 0 )
                buf.appendAscii( RTL_CONSTASCII_STRINGPARAM(", " ) );
            buf.append(
                val2str( aParams[i].getValue(), aParams[i].getValueTypeRef(), VAL2STR_MODE_SHALLOW) );
        }
    }
    buf.appendAscii( RTL_CONSTASCII_STRINGPARAM(")") );
    log( cargo,LogLevel::CALL, buf.makeStringAndClear() );
}

}
<|endoftext|>


<commit_before><commit_msg>Write the kmail account type correctly for KDE 4 KMail.  <commit_after><|endoftext|>


<commit_before>/*

Copyright (c) 2007, Arvid Norberg
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:

    * Redistributions of source code must retain the above copyright
      notice, this list of conditions and the following disclaimer.
    * Redistributions in binary form must reproduce the above copyright
      notice, this list of conditions and the following disclaimer in
      the documentation and/or other materials provided with the distribution.
    * Neither the name of the author nor the names of its
      contributors may be used to endorse or promote products derived
      from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.

*/

#include <asio/ip/host_name.hpp>
#include <asio/ip/multicast.hpp>
#include <boost/bind.hpp>

#include "libtorrent/socket.hpp"
#include "libtorrent/enum_net.hpp"
#include "libtorrent/broadcast_socket.hpp"
#include "libtorrent/assert.hpp"

namespace libtorrent
{
	bool is_local(address const& a)
	{
		if (a.is_v6()) return a.to_v6().is_link_local();
		address_v4 a4 = a.to_v4();
		unsigned long ip = a4.to_ulong();
		return ((ip & 0xff000000) == 0x0a000000
			|| (ip & 0xfff00000) == 0xac100000
			|| (ip & 0xffff0000) == 0xc0a80000);
	}

	bool is_loopback(address const& addr)
	{
		if (addr.is_v4())
		  return addr.to_v4() == address_v4::loopback();
		else
			return addr.to_v6() == address_v6::loopback();
	}

	bool is_multicast(address const& addr)
	{
		if (addr.is_v4())
			return addr.to_v4().is_multicast();
		else
			return addr.to_v6().is_multicast();
	}

	bool is_any(address const& addr)
	{
		if (addr.is_v4())
			return addr.to_v4() == address_v4::any();
		else
			return addr.to_v6() == address_v6::any();
	}

	address guess_local_address(asio::io_service& ios)
	{
		// make a best guess of the interface we're using and its IP
		asio::error_code ec;
		std::vector<address> const& interfaces = enum_net_interfaces(ios, ec);
		address ret = address_v4::any();
		for (std::vector<address>::const_iterator i = interfaces.begin()
			, end(interfaces.end()); i != end; ++i)
		{
			address const& a = *i;
			if (is_loopback(a)
				|| is_multicast(a)
				|| is_any(a)) continue;

			// prefer a v4 address, but return a v6 if
			// there are no v4
			if (a.is_v4()) return a;

			if (ret != address_v4::any())
				ret = a;
		}
		return ret;
	}

	broadcast_socket::broadcast_socket(asio::io_service& ios
		, udp::endpoint const& multicast_endpoint
		, receive_handler_t const& handler
		, bool loopback)
		: m_multicast_endpoint(multicast_endpoint)
		, m_on_receive(handler)
	{
		TORRENT_ASSERT(is_multicast(m_multicast_endpoint.address()));

		using namespace asio::ip::multicast;

		asio::error_code ec;
		std::vector<address> interfaces = enum_net_interfaces(ios, ec);

		for (std::vector<address>::const_iterator i = interfaces.begin()
			, end(interfaces.end()); i != end; ++i)
		{
			// only broadcast to IPv4 addresses that are not local
			if (!is_local(*i)) continue;
			// only multicast on compatible networks
			if (i->is_v4() != multicast_endpoint.address().is_v4()) continue;
			// ignore any loopback interface
			if (is_loopback(*i)) continue;

			boost::shared_ptr<datagram_socket> s(new datagram_socket(ios));
			if (i->is_v4())
			{
				s->open(udp::v4(), ec);
				if (ec) continue;
				s->set_option(datagram_socket::reuse_address(true), ec);
				if (ec) continue;
				s->bind(udp::endpoint(address_v4::any(), multicast_endpoint.port()), ec);
				if (ec) continue;
				s->set_option(join_group(multicast_endpoint.address()), ec);
				if (ec) continue;
				s->set_option(outbound_interface(i->to_v4()), ec);
				if (ec) continue;
			}
			else
			{
				s->open(udp::v6(), ec);
				if (ec) continue;
				s->set_option(datagram_socket::reuse_address(true), ec);
				if (ec) continue;
				s->bind(udp::endpoint(address_v6::any(), multicast_endpoint.port()), ec);
				if (ec) continue;
				s->set_option(join_group(multicast_endpoint.address()), ec);
				if (ec) continue;
//				s->set_option(outbound_interface(i->to_v6()), ec);
//				if (ec) continue;
			}
			s->set_option(hops(255), ec);
			if (ec) continue;
			s->set_option(enable_loopback(loopback), ec);
			if (ec) continue;
			m_sockets.push_back(socket_entry(s));
			socket_entry& se = m_sockets.back();
			s->async_receive_from(asio::buffer(se.buffer, sizeof(se.buffer))
				, se.remote, bind(&broadcast_socket::on_receive, this, &se, _1, _2));
#ifndef NDEBUG
//			std::cerr << "broadcast socket [ if: " << i->to_v4().to_string()
//				<< " group: " << multicast_endpoint.address() << " ]" << std::endl;
#endif
		}
		open_unicast_socket(ios, address_v4::any());
		open_unicast_socket(ios, address_v6::any());
	}

	void broadcast_socket::open_unicast_socket(io_service& ios, address const& addr)
	{
		asio::error_code ec;
		boost::shared_ptr<datagram_socket> s(new datagram_socket(ios));
		s->open(addr.is_v4() ? udp::v4() : udp::v6(), ec);
		if (ec) return;
		s->bind(udp::endpoint(addr, 0), ec);
		if (ec) return;
		m_unicast_sockets.push_back(socket_entry(s));
		socket_entry& se = m_unicast_sockets.back();
		s->async_receive_from(asio::buffer(se.buffer, sizeof(se.buffer))
			, se.remote, bind(&broadcast_socket::on_receive, this, &se, _1, _2));
	}

	void broadcast_socket::send(char const* buffer, int size, asio::error_code& ec)
	{
		for (std::list<socket_entry>::iterator i = m_unicast_sockets.begin()
			, end(m_unicast_sockets.end()); i != end; ++i)
		{
			if (!i->socket) continue;
			asio::error_code e;
			i->socket->send_to(asio::buffer(buffer, size), m_multicast_endpoint, 0, e);
#ifndef NDEBUG
//			std::cerr << " sending on " << i->socket->local_endpoint().address().to_string() << " to: " << m_multicast_endpoint << std::endl;
#endif
			if (e)
			{
				i->socket->close(e);
				i->socket.reset();
			}
		}

		for (std::list<socket_entry>::iterator i = m_sockets.begin()
			, end(m_sockets.end()); i != end; ++i)
		{
			if (!i->socket) continue;
			asio::error_code e;
			i->socket->send_to(asio::buffer(buffer, size), m_multicast_endpoint, 0, e);
#ifndef NDEBUG
//			std::cerr << " sending on " << i->socket->local_endpoint().address().to_string() << " to: " << m_multicast_endpoint << std::endl;
#endif
			if (e)
			{
				i->socket->close(e);
				i->socket.reset();
			}
		}
	}

	void broadcast_socket::on_receive(socket_entry* s, asio::error_code const& ec
		, std::size_t bytes_transferred)
	{
		if (ec || bytes_transferred == 0 || !m_on_receive) return;
		m_on_receive(s->remote, s->buffer, bytes_transferred);
		if (!s->socket) return;
		s->socket->async_receive_from(asio::buffer(s->buffer, sizeof(s->buffer))
			, s->remote, bind(&broadcast_socket::on_receive, this, s, _1, _2));
	}

	void broadcast_socket::close()
	{
		std::for_each(m_sockets.begin(), m_sockets.end(), bind(&socket_entry::close, _1));
		std::for_each(m_unicast_sockets.begin(), m_unicast_sockets.end(), bind(&socket_entry::close, _1));

		m_on_receive.clear();
	}
}

<commit_msg>broadcast socket updates (better upnp support)<commit_after>/*

Copyright (c) 2007, Arvid Norberg
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:

    * Redistributions of source code must retain the above copyright
      notice, this list of conditions and the following disclaimer.
    * Redistributions in binary form must reproduce the above copyright
      notice, this list of conditions and the following disclaimer in
      the documentation and/or other materials provided with the distribution.
    * Neither the name of the author nor the names of its
      contributors may be used to endorse or promote products derived
      from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.

*/

#include <asio/ip/host_name.hpp>
#include <asio/ip/multicast.hpp>
#include <boost/bind.hpp>

#include "libtorrent/socket.hpp"
#include "libtorrent/enum_net.hpp"
#include "libtorrent/broadcast_socket.hpp"
#include "libtorrent/assert.hpp"

namespace libtorrent
{
	bool is_local(address const& a)
	{
		if (a.is_v6()) return a.to_v6().is_link_local();
		address_v4 a4 = a.to_v4();
		unsigned long ip = a4.to_ulong();
		return ((ip & 0xff000000) == 0x0a000000
			|| (ip & 0xfff00000) == 0xac100000
			|| (ip & 0xffff0000) == 0xc0a80000);
	}

	bool is_loopback(address const& addr)
	{
		if (addr.is_v4())
		  return addr.to_v4() == address_v4::loopback();
		else
			return addr.to_v6() == address_v6::loopback();
	}

	bool is_multicast(address const& addr)
	{
		if (addr.is_v4())
			return addr.to_v4().is_multicast();
		else
			return addr.to_v6().is_multicast();
	}

	bool is_any(address const& addr)
	{
		if (addr.is_v4())
			return addr.to_v4() == address_v4::any();
		else
			return addr.to_v6() == address_v6::any();
	}

	address guess_local_address(asio::io_service& ios)
	{
		// make a best guess of the interface we're using and its IP
		asio::error_code ec;
		std::vector<address> const& interfaces = enum_net_interfaces(ios, ec);
		address ret = address_v4::any();
		for (std::vector<address>::const_iterator i = interfaces.begin()
			, end(interfaces.end()); i != end; ++i)
		{
			address const& a = *i;
			if (is_loopback(a)
				|| is_multicast(a)
				|| is_any(a)) continue;

			// prefer a v4 address, but return a v6 if
			// there are no v4
			if (a.is_v4()) return a;

			if (ret != address_v4::any())
				ret = a;
		}
		return ret;
	}

	broadcast_socket::broadcast_socket(asio::io_service& ios
		, udp::endpoint const& multicast_endpoint
		, receive_handler_t const& handler
		, bool loopback)
		: m_multicast_endpoint(multicast_endpoint)
		, m_on_receive(handler)
	{
		TORRENT_ASSERT(is_multicast(m_multicast_endpoint.address()));

		using namespace asio::ip::multicast;

		asio::error_code ec;
		std::vector<address> interfaces = enum_net_interfaces(ios, ec);

		if (multicast_endpoint.address().is_v4())
			open_multicast_socket(ios, address_v4::any(), loopback);
		else
			open_multicast_socket(ios, address_v6::any(), loopback);

		for (std::vector<address>::const_iterator i = interfaces.begin()
			, end(interfaces.end()); i != end; ++i)
		{
			// only broadcast to IPv4 addresses that are not local
			if (!is_local(*i)) continue;
			// only multicast on compatible networks
			if (i->is_v4() != multicast_endpoint.address().is_v4()) continue;
			// ignore any loopback interface
			if (is_loopback(*i)) continue;

#ifndef NDEBUG
//			std::cerr << "broadcast socket [ if: " << i->to_v4().to_string()
//				<< " group: " << multicast_endpoint.address() << " ]" << std::endl;
#endif
			open_unicast_socket(ios, *i);
		}
	}

	void broadcast_socket::open_multicast_socket(io_service& ios
		, address const& addr, bool loopback)
	{
		using namespace asio::ip::multicast;

		asio::error_code ec;
		boost::shared_ptr<datagram_socket> s(new datagram_socket(ios));
		if (addr.is_v4())
			s->open(udp::v4(), ec);
		else
			s->open(udp::v6(), ec);
		if (ec) return;
		s->set_option(datagram_socket::reuse_address(true), ec);
		if (ec) return;
		s->bind(udp::endpoint(addr, m_multicast_endpoint.port()), ec);
		if (ec) return;
		s->set_option(join_group(m_multicast_endpoint.address()), ec);
		if (ec) return;
		s->set_option(hops(255), ec);
		if (ec) return;
		s->set_option(enable_loopback(loopback), ec);
		if (ec) return;
		m_sockets.push_back(socket_entry(s));
		socket_entry& se = m_sockets.back();
		s->async_receive_from(asio::buffer(se.buffer, sizeof(se.buffer))
			, se.remote, bind(&broadcast_socket::on_receive, this, &se, _1, _2));
	}

	void broadcast_socket::open_unicast_socket(io_service& ios, address const& addr)
	{
		using namespace asio::ip::multicast;
		asio::error_code ec;
		boost::shared_ptr<datagram_socket> s(new datagram_socket(ios));
		s->open(addr.is_v4() ? udp::v4() : udp::v6(), ec);
		if (ec) return;
		s->bind(udp::endpoint(addr, 0), ec);
		if (ec) return;
		if (addr.is_v4())
			s->set_option(outbound_interface(addr.to_v4()), ec);
		if (ec) return;
		m_unicast_sockets.push_back(socket_entry(s));
		socket_entry& se = m_unicast_sockets.back();
		s->async_receive_from(asio::buffer(se.buffer, sizeof(se.buffer))
			, se.remote, bind(&broadcast_socket::on_receive, this, &se, _1, _2));
	}

	void broadcast_socket::send(char const* buffer, int size, asio::error_code& ec)
	{
		for (std::list<socket_entry>::iterator i = m_unicast_sockets.begin()
			, end(m_unicast_sockets.end()); i != end; ++i)
		{
			if (!i->socket) continue;
			asio::error_code e;
			i->socket->send_to(asio::buffer(buffer, size), m_multicast_endpoint, 0, e);
#ifndef NDEBUG
//			std::cerr << " sending on " << i->socket->local_endpoint().address().to_string() << " to: " << m_multicast_endpoint << std::endl;
#endif
			if (e)
			{
				i->socket->close(e);
				i->socket.reset();
			}
		}
	}

	void broadcast_socket::on_receive(socket_entry* s, asio::error_code const& ec
		, std::size_t bytes_transferred)
	{
		if (ec || bytes_transferred == 0 || !m_on_receive) return;
		m_on_receive(s->remote, s->buffer, bytes_transferred);
		if (!s->socket) return;
		s->socket->async_receive_from(asio::buffer(s->buffer, sizeof(s->buffer))
			, s->remote, bind(&broadcast_socket::on_receive, this, s, _1, _2));
	}

	void broadcast_socket::close()
	{
		std::for_each(m_sockets.begin(), m_sockets.end(), bind(&socket_entry::close, _1));
		std::for_each(m_unicast_sockets.begin(), m_unicast_sockets.end(), bind(&socket_entry::close, _1));

		m_on_receive.clear();
	}
}

<|endoftext|>


<commit_before>#include <cstdlib>
#include <cstdio>
#include <cstring>
#include <string>

#include <mist/json.h>
#include <mist/dtsc.h>
#include <mist/procs.h>
#include <mist/timing.h>

namespace Info {
  int getInfo(int argc, char* argv[]) {
    if (argc < 2){
      fprintf( stderr, "Usage: %s <filename>\n", argv[0] );
      return 1;
    }
    DTSC::File F(argv[1]);
    JSON::Value fileSpecs = F.getMeta();
    if( !fileSpecs ) {
      char ** cmd = (char**)malloc(3*sizeof(char*));
      cmd[0] = (char*)"ffprobe";
      cmd[1] = argv[1];
      cmd[2] = NULL;
      int outFD = -1;
      Util::Procs::StartPiped("FFProbe", cmd, 0, 0, &outFD);
      while( Util::Procs::isActive("FFProbe")){ Util::sleep(100); }
      FILE * outFile = fdopen( outFD, "r" );
      char * fileBuf = 0;
      size_t fileBufLen = 0;
      while ( !(feof(outFile) || ferror(outFile)) && (getline(&fileBuf, &fileBufLen, outFile) != -1)){
        std::string line = fileBuf;
        if (line.find("Input") != std::string::npos){
          std::string tmp = line.substr(line.find(", ") + 2);
          fileSpecs["format"] = tmp.substr(0, tmp.find(","));
        }
        if (line.find("Duration") != std::string::npos){
          std::string tmp = line.substr(line.find(": ", line.find("Duration")) + 2);
          tmp = tmp.substr(0, tmp.find(","));
          int length = (((atoi(tmp.substr(0,2).c_str()) * 60) + atoi(tmp.substr(3,2).c_str())) * 60) + atoi(tmp.substr(6,2).c_str());
          fileSpecs["length"] = length;
          length *= 100;
          length += atoi(tmp.substr(9,2).c_str());
          fileSpecs["lastms"] = length * 10;
        }
        if (line.find("bitrate") != std::string::npos ){
          std::string tmp = line.substr(line.find(": ", line.find("bitrate")) + 2);
          fileSpecs["bps"] = atoi(tmp.substr(0, tmp.find(" ")).c_str()) * 128;
        }
        if (line.find("Stream") != std::string::npos ){
          std::string tmp = line.substr(line.find(" ", line.find("Stream")) + 1);
          int strmIdx = fileSpecs["streams"].size();
          int curPos = 0;
          curPos = tmp.find(": ", curPos) + 2;
          fileSpecs["streams"][strmIdx]["type"] = tmp.substr(curPos, tmp.find(":", curPos) - curPos);
          curPos = tmp.find(":", curPos) + 2;
          fileSpecs["streams"][strmIdx]["codec"] = tmp.substr(curPos, tmp.find_first_of(", ", curPos) - curPos);
          curPos = tmp.find(",", curPos) + 2;
          if (fileSpecs["streams"][strmIdx]["type"] == "Video"){
            fileSpecs["streams"][strmIdx]["encoding"] = tmp.substr(curPos, tmp.find(",", curPos) - curPos);
            curPos = tmp.find(",", curPos) + 2;
            fileSpecs["streams"][strmIdx]["width"] = atoi(tmp.substr(curPos, tmp.find("x", curPos) - curPos).c_str());
            curPos = tmp.find("x", curPos) + 1;
            fileSpecs["streams"][strmIdx]["height"] = atoi(tmp.substr(curPos, tmp.find(",", curPos) - curPos).c_str());
            curPos = tmp.find(",", curPos) + 2;
            fileSpecs["streams"][strmIdx]["bps"] = atoi(tmp.substr(curPos, tmp.find(" ", curPos) - curPos).c_str()) * 128;
            curPos = tmp.find(",", curPos) + 2;
            fileSpecs["streams"][strmIdx]["fpks"] = (int)(atof(tmp.substr(curPos, tmp.find(" ", curPos) - curPos).c_str()) * 1000);
            fileSpecs["streams"][strmIdx].removeMember( "type" );
            fileSpecs["video"] = fileSpecs["streams"][strmIdx];
          }else if (fileSpecs["streams"][strmIdx]["type"] == "Audio"){
            fileSpecs["streams"][strmIdx]["samplerate"] = atoi(tmp.substr(curPos, tmp.find(" ", curPos) - curPos).c_str());
            curPos = tmp.find(",", curPos) + 2;
            if (tmp.substr(curPos, tmp.find(",", curPos) - curPos) == "stereo"){
              fileSpecs["streams"][strmIdx]["channels"] = 2;
            }else if (tmp.substr(curPos, tmp.find(",", curPos) - curPos) == "mono"){
              fileSpecs["streams"][strmIdx]["channels"] = 1;
            }else{
              fileSpecs["streams"][strmIdx]["channels"] = tmp.substr(curPos, tmp.find(",", curPos) - curPos);
            }
            curPos = tmp.find(",", curPos) + 2;
            fileSpecs["streams"][strmIdx]["samplewidth"] = tmp.substr(curPos, tmp.find(",", curPos) - curPos);
            curPos = tmp.find(",", curPos) + 2;
            fileSpecs["streams"][strmIdx]["bps"] = atoi(tmp.substr(curPos, tmp.find(" ", curPos) - curPos).c_str()) * 128;
            fileSpecs["streams"][strmIdx].removeMember( "type" );
            fileSpecs["audio"] = fileSpecs["streams"][strmIdx];
          }
        }
      }
      fclose( outFile );
      fileSpecs.removeMember( "streams" );
    } else {
      fileSpecs["format"] = "dtsc";
    }
    if (fileSpecs.isMember("video")){
      fileSpecs["video"].removeMember("init");
    }
    if (fileSpecs.isMember("audio")){
      fileSpecs["audio"].removeMember("init");
    }
    fileSpecs.removeMember("keybpos");
    fileSpecs.removeMember("keytime");
    printf( "%s", fileSpecs.toString().c_str() );
    return 0;
  }
}

int main(int argc, char* argv[]) {
  return Info::getInfo(argc, argv);
}
<commit_msg>Updated MistInfo to support dtsc2<commit_after>#include <cstdlib>
#include <cstdio>
#include <cstring>
#include <string>

#include <mist/json.h>
#include <mist/dtsc.h>
#include <mist/procs.h>
#include <mist/timing.h>

namespace Info {
  int getInfo(int argc, char* argv[]) {
    if (argc < 2){
      fprintf( stderr, "Usage: %s <filename>\n", argv[0] );
      return 1;
    }
    DTSC::File F(argv[1]);
    JSON::Value fileSpecs = F.getMeta();
    if( !fileSpecs ) {
      char ** cmd = (char**)malloc(3*sizeof(char*));
      cmd[0] = (char*)"ffprobe";
      cmd[1] = argv[1];
      cmd[2] = NULL;
      int outFD = -1;
      Util::Procs::StartPiped("FFProbe", cmd, 0, 0, &outFD);
      while( Util::Procs::isActive("FFProbe")){ Util::sleep(100); }
      FILE * outFile = fdopen( outFD, "r" );
      char * fileBuf = 0;
      size_t fileBufLen = 0;
      while ( !(feof(outFile) || ferror(outFile)) && (getline(&fileBuf, &fileBufLen, outFile) != -1)){
        std::string line = fileBuf;
        if (line.find("Input") != std::string::npos){
          std::string tmp = line.substr(line.find(", ") + 2);
          fileSpecs["format"] = tmp.substr(0, tmp.find(","));
        }
        if (line.find("Duration") != std::string::npos){
          std::string tmp = line.substr(line.find(": ", line.find("Duration")) + 2);
          tmp = tmp.substr(0, tmp.find(","));
          int length = (((atoi(tmp.substr(0,2).c_str()) * 60) + atoi(tmp.substr(3,2).c_str())) * 60) + atoi(tmp.substr(6,2).c_str());
          fileSpecs["length"] = length;
          length *= 100;
          length += atoi(tmp.substr(9,2).c_str());
          fileSpecs["lastms"] = length * 10;
        }
        if (line.find("bitrate") != std::string::npos ){
          std::string tmp = line.substr(line.find(": ", line.find("bitrate")) + 2);
          fileSpecs["bps"] = atoi(tmp.substr(0, tmp.find(" ")).c_str()) * 128;
        }
        if (line.find("Stream") != std::string::npos ){
          std::string tmp = line.substr(line.find(" ", line.find("Stream")) + 1);
          int strmIdx = fileSpecs["streams"].size();
          int curPos = 0;
          curPos = tmp.find(": ", curPos) + 2;
          fileSpecs["streams"][strmIdx]["type"] = tmp.substr(curPos, tmp.find(":", curPos) - curPos);
          curPos = tmp.find(":", curPos) + 2;
          fileSpecs["streams"][strmIdx]["codec"] = tmp.substr(curPos, tmp.find_first_of(", ", curPos) - curPos);
          curPos = tmp.find(",", curPos) + 2;
          if (fileSpecs["streams"][strmIdx]["type"] == "Video"){
            fileSpecs["streams"][strmIdx]["encoding"] = tmp.substr(curPos, tmp.find(",", curPos) - curPos);
            curPos = tmp.find(",", curPos) + 2;
            fileSpecs["streams"][strmIdx]["width"] = atoi(tmp.substr(curPos, tmp.find("x", curPos) - curPos).c_str());
            curPos = tmp.find("x", curPos) + 1;
            fileSpecs["streams"][strmIdx]["height"] = atoi(tmp.substr(curPos, tmp.find(",", curPos) - curPos).c_str());
            curPos = tmp.find(",", curPos) + 2;
            fileSpecs["streams"][strmIdx]["bps"] = atoi(tmp.substr(curPos, tmp.find(" ", curPos) - curPos).c_str()) * 128;
            curPos = tmp.find(",", curPos) + 2;
            fileSpecs["streams"][strmIdx]["fpks"] = (int)(atof(tmp.substr(curPos, tmp.find(" ", curPos) - curPos).c_str()) * 1000);
            fileSpecs["streams"][strmIdx].removeMember( "type" );
            fileSpecs["video"] = fileSpecs["streams"][strmIdx];
          }else if (fileSpecs["streams"][strmIdx]["type"] == "Audio"){
            fileSpecs["streams"][strmIdx]["samplerate"] = atoi(tmp.substr(curPos, tmp.find(" ", curPos) - curPos).c_str());
            curPos = tmp.find(",", curPos) + 2;
            if (tmp.substr(curPos, tmp.find(",", curPos) - curPos) == "stereo"){
              fileSpecs["streams"][strmIdx]["channels"] = 2;
            }else if (tmp.substr(curPos, tmp.find(",", curPos) - curPos) == "mono"){
              fileSpecs["streams"][strmIdx]["channels"] = 1;
            }else{
              fileSpecs["streams"][strmIdx]["channels"] = tmp.substr(curPos, tmp.find(",", curPos) - curPos);
            }
            curPos = tmp.find(",", curPos) + 2;
            fileSpecs["streams"][strmIdx]["samplewidth"] = tmp.substr(curPos, tmp.find(",", curPos) - curPos);
            curPos = tmp.find(",", curPos) + 2;
            fileSpecs["streams"][strmIdx]["bps"] = atoi(tmp.substr(curPos, tmp.find(" ", curPos) - curPos).c_str()) * 128;
            fileSpecs["streams"][strmIdx].removeMember( "type" );
            fileSpecs["audio"] = fileSpecs["streams"][strmIdx];
          }
        }
      }
      fclose( outFile );
      fileSpecs.removeMember( "streams" );
    } else {
      fileSpecs["format"] = "dtsc";
      JSON::Value tracks = fileSpecs["tracks"];
      for(JSON::ObjIter trackIt = tracks.ObjBegin(); trackIt != tracks.ObjEnd(); trackIt++){
        if (fileSpecs["tracks"][trackIt->first].isMember("init")){
          fileSpecs["tracks"][trackIt->first].removeMember("init");
        }
        if (fileSpecs["tracks"][trackIt->first].isMember("frags")){
          fileSpecs["tracks"][trackIt->first].removeMember("frags");
        }
        if (fileSpecs["tracks"][trackIt->first].isMember("keys")){
          fileSpecs["tracks"][trackIt->first].removeMember("keys");
        }
      }
    }
    if (fileSpecs.isMember("video")){
      fileSpecs["video"].removeMember("init");
    }
    if (fileSpecs.isMember("audio")){
      fileSpecs["audio"].removeMember("init");
    }
    printf( "%s", fileSpecs.toString().c_str() );
    return 0;
  }
}

int main(int argc, char* argv[]) {
  return Info::getInfo(argc, argv);
}
<|endoftext|>


<commit_before>#include "openmit/model/ffm.h"
#include "openmit/tools/dstruct/sarray.h"

namespace mit {

/////////////////////////////////////////////////////////////
// ffm model complemention for parameter server framework
/////////////////////////////////////////////////////////////

PSFFM::~PSFFM() {}

PSFFM* PSFFM::Get(const mit::KWArgs& kwargs) {
  return new PSFFM(kwargs);
}
/*
// single thread
void PSFFM::Pull(ps::KVPairs<mit_float>& response, mit::entry_map_type* weight) {
  size_t keys_size = response.keys.size();
  CHECK(keys_size > 0);
  CHECK_EQ(keys_size, response.extras.size());   // store field id
  response.lens.resize(keys_size);

  // intercept
  CHECK_EQ(response.keys[0], 0);
  if (weight->find(0) == weight->end()) {
    weight->insert(std::make_pair(0, mit::Entry::Create(
      model_param_, entry_meta_.get(), random_.get(), 0)));
  }
  response.vals.push_back((*weight)[0]->Get());
  response.lens[0] = 1;

  // feature
  for (auto i = 1u; i < keys_size; ++i) {
    ps::Key key = response.keys[i];
    if (weight->find(key) == weight->end()) {
      auto fid = response.extras[i];
      CHECK(fid > 0) << "fid = 0";
      auto* entry = mit::Entry::Create(model_param_, entry_meta_.get(), random_.get(), fid);
      weight->insert(std::make_pair(key, entry));
    }
    auto* entry = (*weight)[key];
    ps::SArray<mit_float> entry_data(entry->Data(), entry->Size());
    response.vals.append(entry_data);
    response.lens[i] = entry->Size();
  }
}
*/

void PSFFM::Pull(ps::KVPairs<mit_float>& response, mit::entry_map_type* weight) {
  size_t keys_size = response.keys.size();
  CHECK(keys_size > 0);
  CHECK_EQ(keys_size, response.extras.size());   // store field id
  response.lens.resize(keys_size);

  // intercept
  CHECK_EQ(response.keys[0], 0);
  if (weight->find(0) == weight->end()) {
    weight->insert(std::make_pair(0, mit::Entry::Create(
      model_param_, entry_meta_.get(), random_.get(), 0)));
  }
  response.vals.push_back((*weight)[0]->Get());
  response.lens[0] = 1;

  // feature (multi-thread)
  auto nthread = cli_param_.num_thread; CHECK(nthread > 0);
  std::vector<mit::SArray<mit_float>* > vals_thread(nthread);
  for (auto i = 0u; i < nthread; ++i) {
    vals_thread[i] = new mit::SArray<mit_float>();
  }
  int chunksize = (keys_size - 1) / nthread;
  if ((keys_size - 1) % nthread != 0) chunksize += 1;
  #pragma omp parallel for num_threads(nthread) schedule(static, chunksize)
  for (auto i = 1u; i < keys_size; ++i) {
    ps::Key key = response.keys[i];
    mit::Entry* entry = nullptr;
    if (weight->find(key) == weight->end()) {
      auto fid = response.extras[i]; CHECK(fid > 0);
      entry = mit::Entry::Create(model_param_, entry_meta_.get(), random_.get(), fid);
      CHECK_NOTNULL(entry);
      #pragma omp critical
      {
        std::lock_guard<std::mutex> lk(mu_);
        weight->insert(std::make_pair(key, entry));
      }
    } else {
      entry = (*weight)[key];
    }
    CHECK_NOTNULL(entry); CHECK(entry->Size() > 0);
    vals_thread[omp_get_thread_num()]->append(entry->Data(), entry->Size());
    response.lens[i] = entry->Size();
  }

  // merge multi-thread result
  for (auto i = 0u; i < nthread; ++i) {
    ps::SArray<mit_float> thread_data(vals_thread[i]->data(), vals_thread[i]->size());
    response.vals.append(thread_data);
    if (vals_thread[i]) { // free memory
      vals_thread[i]->clear();
      delete vals_thread[i]; vals_thread[i] = NULL;
    }
  }
  /*
  // feature (multi-thread)
  auto nthread = cli_param_.num_thread; CHECK(nthread > 0);
  std::vector<std::vector<mit_float>* > vals_thread(nthread);
  for (auto i = 0u; i < nthread; ++i) {
    vals_thread[i] = new std::vector<mit_float>();
  }
  int chunksize = (keys_size - 1) / nthread;
  if ((keys_size - 1) % nthread != 0) chunksize += 1;
  #pragma omp parallel for num_threads(nthread) schedule(static, chunksize)
  for (auto i = 1u; i < keys_size; ++i) {
    ps::Key key = response.keys[i];
    mit::Entry* entry = nullptr;
    if (weight->find(key) == weight->end()) {
      auto fid = response.extras[i]; CHECK(fid > 0);
      entry = mit::Entry::Create(model_param_, entry_meta_.get(), random_.get(), fid);
      CHECK_NOTNULL(entry);
      #pragma omp critical
      {
        std::lock_guard<std::mutex> lk(mu_);
        weight->insert(std::make_pair(key, entry));
      }
    } else {
      entry = (*weight)[key];
    }
    CHECK_NOTNULL(entry); CHECK(entry->Size() > 0);
    for (auto idx = 0u; idx < entry->Size(); ++idx) {
      vals_thread[omp_get_thread_num()]->push_back(entry->Get(idx));
    }
    response.lens[i] = entry->Size();
  }

  // merge multi-thread result
  for (auto i = 0u; i < nthread; ++i) {
    ps::SArray<mit_float> sarray(vals_thread[i]->data(), vals_thread[i]->size());
    response.vals.append(sarray);
    if (vals_thread[i]) { // free memory
      vals_thread[i]->clear();
      delete vals_thread[i]; vals_thread[i] = NULL;
    }
  }
  */
}

void PSFFM::Update(const ps::SArray<mit_uint>& keys,
                   const ps::SArray<mit_float>& vals,
                   const ps::SArray<int>& lens,
                   mit::entry_map_type* weight) {
  auto keys_size = keys.size();
  auto offset = 0u;
  for (auto i = 0u; i < keys_size; ++i) {
    auto key = keys[i];
    if (weight->find(key) == weight->end()) {
      LOG(FATAL) << key << " not in model structure";
    }
    // update_w (1-order linear item)
    auto w = (*weight)[key]->Get(0);
    auto g = vals[offset++];
    optimizer_->Update(key, 0, g, w, (*weight)[key]);
    (*weight)[key]->Set(0, w);
    // update_v (2-order cross item)
    if (lens[i] == 1) continue;
    for (int k = 1; k < lens[i]; ++k) {
      auto v = (*weight)[key]->Get(k);
      auto g = vals[offset++];
      optimizer_v_->Update(key, k, g, v, (*weight)[key]);
      (*weight)[key]->Set(k, v);
    }
  }
  CHECK_EQ(offset, vals.size()) << "offset not match vals.size for model update";
} // PSFFM::Update

void PSFFM::Gradient(const dmlc::Row<mit_uint>& row,
                     const std::vector<mit_float>& weights,
                     mit::key2offset_type& key2offset,
                     std::vector<mit_float>* grads,
                     const mit_float& loss_grad) {
  auto instweight = row.get_weight();
  // 0-order intercept
  if (! cli_param_.is_contain_intercept) {
    auto offset0 = key2offset[0].first;
    (*grads)[offset0] += loss_grad * 1 * instweight;
  }
  // 1-order linear item
  #pragma omp parallel for num_threads(cli_param_.num_thread)
  for (auto i = 0u; i < row.length; ++i) {
    mit_uint key = row.index[i];
    CHECK(key2offset.find(key) != key2offset.end()) << key << " not in key2offset";
    auto offset = key2offset[key].first;
    auto xi = row.get_value(i);
    (*grads)[offset] += loss_grad * xi * instweight;
  }
  // 2-order cross item
  #pragma omp parallel for num_threads(cli_param_.num_thread)
  for (auto i = 0u; i < row.length - 1; ++i) {
    auto fi = row.field[i];
    auto keyi = row.index[i];
    auto xi = row.get_value(i);
    // fi not in fields_map
    if (! entry_meta_->CombineInfo(fi)) continue;

    for (auto j = i + 1; j < row.length; ++j) {
      auto fj = row.field[j];
      if (fi == fj) continue; // not cross when same field
      if (! entry_meta_->CombineInfo(fj)) continue;
      auto keyj = row.index[j];
      auto xj = row.get_value(j);

      auto vifj_index = entry_meta_->FieldIndex(fi, fj);
      if (vifj_index == -1) continue;
      auto vifj_offset = key2offset[keyi].first + (1 + vifj_index * model_param_.embedding_size);

      auto vjfi_index = entry_meta_->FieldIndex(fj, fi);
      if (vjfi_index == -1) continue;
      auto vjfi_offset = key2offset[keyj].first + (1 + vjfi_index * model_param_.embedding_size);

      // vifj * vjfi * xi * xj
      // SSE Accelerated ?  const initialize for sse
      for (auto k = 0u; k < model_param_.embedding_size; ++k) {
        (*grads)[vifj_offset+k] += loss_grad * (weights[vjfi_offset+k] * xi * xj) * instweight;
        (*grads)[vjfi_offset+k] += loss_grad * (weights[vifj_offset+k] * xi * xj) * instweight;
      }
    }
  }
}

mit_float PSFFM::Predict(const dmlc::Row<mit_uint>& row,
                       const std::vector<mit_float>& weights,
                       mit::key2offset_type& key2offset,
                       bool norm) {
  auto wTx = Linear(row, weights, key2offset);
  wTx += Cross(row, weights, key2offset);
  if (norm) return mit::math::sigmoid(wTx);
  return wTx;
}

mit_float PSFFM::Linear(const dmlc::Row<mit_uint>& row,
                        const std::vector<mit_float>& weights,
                        mit::key2offset_type& key2offset) {
  mit_float wTx = 0.0f;
  // intercept
  if (! cli_param_.is_contain_intercept) {
    wTx += weights[key2offset[0].first];
  }
  #pragma omp parallel for reduction(+:wTx) num_threads(cli_param_.num_thread)
  for (auto i = 0u; i < row.length; ++i) {
    auto key = row.index[i];
    CHECK(key2offset.find(key) != key2offset.end()) << key << " not in key2offset";
    auto offseti = key2offset[key].first;
    wTx += weights[offseti] * row.get_value(i);
  }
  return wTx;
}

mit_float PSFFM::Cross(const dmlc::Row<mit_uint>& row, const std::vector<mit_float>& weights, mit::key2offset_type& key2offset) {
  const mit_float* pweights = weights.data();
  size_t weights_size = weights.size();
  mit_float cross = 0.0f;

  #pragma omp parallel for reduction(+:cross) num_threads(cli_param_.num_thread)
  for (auto i = 0u; i < row.length - 1; ++i) {
    auto fi = row.field[i];
    auto keyi = row.index[i];
    auto xi = row.get_value(i);
    // fi not in fields_map
    if (! entry_meta_->CombineInfo(fi)) continue;

    for (auto j = i + 1; j < row.length; ++j) {
      auto fj = row.field[j];
      if (fi == fj) continue; // not cross when same field
      if (! entry_meta_->CombineInfo(fj)) continue;
      auto keyj = row.index[j];
      auto xj = row.get_value(j);

      auto vifj_index = entry_meta_->FieldIndex(fi, fj);
      auto vjfi_index = entry_meta_->FieldIndex(fj, fi);
      if (vifj_index == -1 || vifj_index == -1) continue;

      auto vifj_offset = key2offset[keyi].first + (1 + vifj_index * model_param_.embedding_size);
      auto vjfi_offset = key2offset[keyj].first + (1 + vjfi_index * model_param_.embedding_size);

      CHECK(vifj_offset + model_param_.embedding_size < weights_size);
      CHECK(vjfi_offset + model_param_.embedding_size < weights_size);

      // sse acceleration
      auto inprod = InProdWithSSE(pweights + vifj_offset, pweights + vjfi_offset);
      cross += inprod * xi * xj;

      /*
      auto inprod = 0.0f;
      for (auto k = 0u; k < model_param_.embedding_size; ++k) {
        inprod += weights[vifj_offset+k] * weights[vjfi_offset+k];
      }
      cross += inprod * xi * xj;
      */
    }
  }
  return cross;
}

float PSFFM::InProdWithSSE(const float* p1, const float* p2) {
  float sum = 0.0f;
  __m128 inprod = _mm_setzero_ps();
  if (blocksize > 0) {
    for (auto offset = 0u; offset < blocksize; offset += 4) {
      __m128 v1 = _mm_loadu_ps(p1 + offset);
      __m128 v2 = _mm_loadu_ps(p2 + offset);
      inprod = _mm_add_ps(inprod, _mm_mul_ps(v1, v2));
    }
    inprod = _mm_hadd_ps(inprod, inprod);
    inprod = _mm_hadd_ps(inprod, inprod);
    float v;
    _mm_store_ss(&v, inprod);
    sum += v;
  }
  if (remainder > 0) {
    for (auto i = 0u; i < remainder; ++i) {
      sum += p1[blocksize + i] * p2[blocksize + i];
    }
  }
  return sum;
} // PSFFM::InProdWithSSE

/////////////////////////////////////////////////////////////
// ffm model complemention for mpi or local
/////////////////////////////////////////////////////////////

FFM::~FFM() {}

FFM* FFM::Get(const mit::KWArgs& kwargs) {
  return new FFM(kwargs);
}

void FFM::Gradient(const dmlc::Row<mit_uint>& row, const mit_float& pred, mit::SArray<mit_float>* grad) {
  // TODO
} // FFM::Gradient

mit_float FFM::Predict(const dmlc::Row<mit_uint>& row, const mit::SArray<mit_float>& weight, bool norm) {
  // TODO
  return 0.0f;
} // FFM::Predict

} // namespace mit
<commit_msg>update<commit_after>#include "openmit/model/ffm.h"
#include "openmit/tools/dstruct/sarray.h"

namespace mit {

/////////////////////////////////////////////////////////////
// ffm model complemention for parameter server framework
/////////////////////////////////////////////////////////////

PSFFM::~PSFFM() {}

PSFFM* PSFFM::Get(const mit::KWArgs& kwargs) {
  return new PSFFM(kwargs);
}
/*
// single thread
void PSFFM::Pull(ps::KVPairs<mit_float>& response, mit::entry_map_type* weight) {
  size_t keys_size = response.keys.size();
  CHECK(keys_size > 0);
  CHECK_EQ(keys_size, response.extras.size());   // store field id
  response.lens.resize(keys_size);

  // intercept
  CHECK_EQ(response.keys[0], 0);
  if (weight->find(0) == weight->end()) {
    weight->insert(std::make_pair(0, mit::Entry::Create(
      model_param_, entry_meta_.get(), random_.get(), 0)));
  }
  response.vals.push_back((*weight)[0]->Get());
  response.lens[0] = 1;

  // feature
  for (auto i = 1u; i < keys_size; ++i) {
    ps::Key key = response.keys[i];
    if (weight->find(key) == weight->end()) {
      auto fid = response.extras[i];
      CHECK(fid > 0) << "fid = 0";
      auto* entry = mit::Entry::Create(model_param_, entry_meta_.get(), random_.get(), fid);
      weight->insert(std::make_pair(key, entry));
    }
    auto* entry = (*weight)[key];
    ps::SArray<mit_float> entry_data(entry->Data(), entry->Size());
    response.vals.append(entry_data);
    response.lens[i] = entry->Size();
  }
}
*/

void PSFFM::Pull(ps::KVPairs<mit_float>& response, mit::entry_map_type* weight) {
  size_t keys_size = response.keys.size();
  CHECK(keys_size > 0);
  CHECK_EQ(keys_size, response.extras.size());   // store field id
  response.lens.resize(keys_size);

  // intercept
  CHECK_EQ(response.keys[0], 0);
  if (weight->find(0) == weight->end()) {
    weight->insert(std::make_pair(0, mit::Entry::Create(
      model_param_, entry_meta_.get(), random_.get(), 0)));
  }
  response.vals.push_back((*weight)[0]->Get());
  response.lens[0] = 1;

  // feature (multi-thread)
  auto nthread = cli_param_.num_thread; CHECK(nthread > 0);
  std::vector<std::vector<mit_float>* > vals_thread(nthread);
  for (auto i = 0u; i < nthread; ++i) {
    vals_thread[i] = new std::vector<mit_float>();
  }
  int chunksize = (keys_size - 1) / nthread;
  if ((keys_size - 1) % nthread != 0) chunksize += 1;
  #pragma omp parallel for num_threads(nthread) schedule(static, chunksize)
  for (auto i = 1u; i < keys_size; ++i) {
    ps::Key key = response.keys[i];
    mit::Entry* entry = nullptr;
    if (weight->find(key) == weight->end()) {
      auto fid = response.extras[i]; CHECK(fid > 0);
      entry = mit::Entry::Create(model_param_, entry_meta_.get(), random_.get(), fid);
      CHECK_NOTNULL(entry);
      #pragma omp critical
      {
        std::lock_guard<std::mutex> lk(mu_);
        weight->insert(std::make_pair(key, entry));
      }
    } else {
      entry = (*weight)[key];
    }
    CHECK_NOTNULL(entry); CHECK(entry->Size() > 0);
    if (entry->Size() > 10) {
      vals_thread[omp_get_thread_num()]->insert(
        vals_thread[omp_get_thread_num()]->end(), entry->Data(), entry->Size());
    } else {
      for (auto idx = 0u; idx < entry->Size(); ++idx) {
        vals_thread[omp_get_thread_num()]->push_back(entry->Get(idx));
      }
    }
    response.lens[i] = entry->Size();
  }

  // merge multi-thread result
  for (auto i = 0u; i < nthread; ++i) {
    ps::SArray<mit_float> sarray(vals_thread[i]->data(), vals_thread[i]->size());
    response.vals.append(sarray);
    if (vals_thread[i]) { // free memory
      vals_thread[i]->clear();
      delete vals_thread[i]; vals_thread[i] = NULL;
    }
  }
}

void PSFFM::Update(const ps::SArray<mit_uint>& keys,
                   const ps::SArray<mit_float>& vals,
                   const ps::SArray<int>& lens,
                   mit::entry_map_type* weight) {
  auto keys_size = keys.size();
  auto offset = 0u;
  for (auto i = 0u; i < keys_size; ++i) {
    auto key = keys[i];
    if (weight->find(key) == weight->end()) {
      LOG(FATAL) << key << " not in model structure";
    }
    // update_w (1-order linear item)
    auto w = (*weight)[key]->Get(0);
    auto g = vals[offset++];
    optimizer_->Update(key, 0, g, w, (*weight)[key]);
    (*weight)[key]->Set(0, w);
    // update_v (2-order cross item)
    if (lens[i] == 1) continue;
    for (int k = 1; k < lens[i]; ++k) {
      auto v = (*weight)[key]->Get(k);
      auto g = vals[offset++];
      optimizer_v_->Update(key, k, g, v, (*weight)[key]);
      (*weight)[key]->Set(k, v);
    }
  }
  CHECK_EQ(offset, vals.size()) << "offset not match vals.size for model update";
} // PSFFM::Update

void PSFFM::Gradient(const dmlc::Row<mit_uint>& row,
                     const std::vector<mit_float>& weights,
                     mit::key2offset_type& key2offset,
                     std::vector<mit_float>* grads,
                     const mit_float& loss_grad) {
  auto instweight = row.get_weight();
  // 0-order intercept
  if (! cli_param_.is_contain_intercept) {
    auto offset0 = key2offset[0].first;
    (*grads)[offset0] += loss_grad * 1 * instweight;
  }
  // 1-order linear item
  #pragma omp parallel for num_threads(cli_param_.num_thread)
  for (auto i = 0u; i < row.length; ++i) {
    mit_uint key = row.index[i];
    CHECK(key2offset.find(key) != key2offset.end()) << key << " not in key2offset";
    auto offset = key2offset[key].first;
    auto xi = row.get_value(i);
    (*grads)[offset] += loss_grad * xi * instweight;
  }
  // 2-order cross item
  #pragma omp parallel for num_threads(cli_param_.num_thread)
  for (auto i = 0u; i < row.length - 1; ++i) {
    auto fi = row.field[i];
    auto keyi = row.index[i];
    auto xi = row.get_value(i);
    // fi not in fields_map
    if (! entry_meta_->CombineInfo(fi)) continue;

    for (auto j = i + 1; j < row.length; ++j) {
      auto fj = row.field[j];
      if (fi == fj) continue; // not cross when same field
      if (! entry_meta_->CombineInfo(fj)) continue;
      auto keyj = row.index[j];
      auto xj = row.get_value(j);

      auto vifj_index = entry_meta_->FieldIndex(fi, fj);
      if (vifj_index == -1) continue;
      auto vifj_offset = key2offset[keyi].first + (1 + vifj_index * model_param_.embedding_size);

      auto vjfi_index = entry_meta_->FieldIndex(fj, fi);
      if (vjfi_index == -1) continue;
      auto vjfi_offset = key2offset[keyj].first + (1 + vjfi_index * model_param_.embedding_size);

      // vifj * vjfi * xi * xj
      // SSE Accelerated ?  const initialize for sse
      for (auto k = 0u; k < model_param_.embedding_size; ++k) {
        (*grads)[vifj_offset+k] += loss_grad * (weights[vjfi_offset+k] * xi * xj) * instweight;
        (*grads)[vjfi_offset+k] += loss_grad * (weights[vifj_offset+k] * xi * xj) * instweight;
      }
    }
  }
}

mit_float PSFFM::Predict(const dmlc::Row<mit_uint>& row,
                       const std::vector<mit_float>& weights,
                       mit::key2offset_type& key2offset,
                       bool norm) {
  auto wTx = Linear(row, weights, key2offset);
  wTx += Cross(row, weights, key2offset);
  if (norm) return mit::math::sigmoid(wTx);
  return wTx;
}

mit_float PSFFM::Linear(const dmlc::Row<mit_uint>& row,
                        const std::vector<mit_float>& weights,
                        mit::key2offset_type& key2offset) {
  mit_float wTx = 0.0f;
  // intercept
  if (! cli_param_.is_contain_intercept) {
    wTx += weights[key2offset[0].first];
  }
  #pragma omp parallel for reduction(+:wTx) num_threads(cli_param_.num_thread)
  for (auto i = 0u; i < row.length; ++i) {
    auto key = row.index[i];
    CHECK(key2offset.find(key) != key2offset.end()) << key << " not in key2offset";
    auto offseti = key2offset[key].first;
    wTx += weights[offseti] * row.get_value(i);
  }
  return wTx;
}

mit_float PSFFM::Cross(const dmlc::Row<mit_uint>& row, const std::vector<mit_float>& weights, mit::key2offset_type& key2offset) {
  const mit_float* pweights = weights.data();
  size_t weights_size = weights.size();
  mit_float cross = 0.0f;

  #pragma omp parallel for reduction(+:cross) num_threads(cli_param_.num_thread)
  for (auto i = 0u; i < row.length - 1; ++i) {
    auto fi = row.field[i];
    auto keyi = row.index[i];
    auto xi = row.get_value(i);
    // fi not in fields_map
    if (! entry_meta_->CombineInfo(fi)) continue;

    for (auto j = i + 1; j < row.length; ++j) {
      auto fj = row.field[j];
      if (fi == fj) continue; // not cross when same field
      if (! entry_meta_->CombineInfo(fj)) continue;
      auto keyj = row.index[j];
      auto xj = row.get_value(j);

      auto vifj_index = entry_meta_->FieldIndex(fi, fj);
      auto vjfi_index = entry_meta_->FieldIndex(fj, fi);
      if (vifj_index == -1 || vifj_index == -1) continue;

      auto vifj_offset = key2offset[keyi].first + (1 + vifj_index * model_param_.embedding_size);
      auto vjfi_offset = key2offset[keyj].first + (1 + vjfi_index * model_param_.embedding_size);

      CHECK(vifj_offset + model_param_.embedding_size < weights_size);
      CHECK(vjfi_offset + model_param_.embedding_size < weights_size);

      // sse acceleration
      auto inprod = InProdWithSSE(pweights + vifj_offset, pweights + vjfi_offset);
      cross += inprod * xi * xj;

      /*
      auto inprod = 0.0f;
      for (auto k = 0u; k < model_param_.embedding_size; ++k) {
        inprod += weights[vifj_offset+k] * weights[vjfi_offset+k];
      }
      cross += inprod * xi * xj;
      */
    }
  }
  return cross;
}

float PSFFM::InProdWithSSE(const float* p1, const float* p2) {
  float sum = 0.0f;
  __m128 inprod = _mm_setzero_ps();
  if (blocksize > 0) {
    for (auto offset = 0u; offset < blocksize; offset += 4) {
      __m128 v1 = _mm_loadu_ps(p1 + offset);
      __m128 v2 = _mm_loadu_ps(p2 + offset);
      inprod = _mm_add_ps(inprod, _mm_mul_ps(v1, v2));
    }
    inprod = _mm_hadd_ps(inprod, inprod);
    inprod = _mm_hadd_ps(inprod, inprod);
    float v;
    _mm_store_ss(&v, inprod);
    sum += v;
  }
  if (remainder > 0) {
    for (auto i = 0u; i < remainder; ++i) {
      sum += p1[blocksize + i] * p2[blocksize + i];
    }
  }
  return sum;
} // PSFFM::InProdWithSSE

/////////////////////////////////////////////////////////////
// ffm model complemention for mpi or local
/////////////////////////////////////////////////////////////

FFM::~FFM() {}

FFM* FFM::Get(const mit::KWArgs& kwargs) {
  return new FFM(kwargs);
}

void FFM::Gradient(const dmlc::Row<mit_uint>& row, const mit_float& pred, mit::SArray<mit_float>* grad) {
  // TODO
} // FFM::Gradient

mit_float FFM::Predict(const dmlc::Row<mit_uint>& row, const mit::SArray<mit_float>& weight, bool norm) {
  // TODO
  return 0.0f;
} // FFM::Predict

} // namespace mit
<|endoftext|>


<commit_before>/*
 * #%L
 * %%
 * Copyright (C) 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 <gtest/gtest.h>

#include "joynr/BrokerUrl.h"
#include "joynr/ClusterControllerSettings.h"
#include "joynr/ImmutableMessage.h"
#include "joynr/Message.h"
#include "joynr/MessagingSettings.h"
#include "joynr/MutableMessage.h"
#include "joynr/Settings.h"
#include "joynr/exceptions/JoynrException.h"
#include "joynr/system/RoutingTypes/MqttAddress.h"

#include "libjoynrclustercontroller/mqtt/MqttSender.h"

#include "tests/mock/MockMosquittoConnection.h"

using namespace ::testing;

namespace joynr
{

class MqttSenderTest : public testing::Test
{
public:
    MqttSenderTest() : mqttAddress("brokerUri", "clientId"), mockMosquittoConnection(), mqttSender()
    {
    }

protected:
    void createMqttSender(std::string testSettingsFileNameMqtt)
    {
        Settings testSettings(testSettingsFileNameMqtt);
        MessagingSettings messagingSettings(testSettings);
        const ClusterControllerSettings ccSettings(testSettings);
        BrokerUrl brokerUrl("testBrokerUrl");
        std::chrono::seconds mqttKeepAliveTimeSeconds(1);
        std::chrono::seconds mqttReconnectDelayTimeSeconds(1);
        std::chrono::seconds mqttReconnectMaxDelayTimeSeconds(1);
        bool isMqttExponentialBackoffEnabled(false);
        const std::string clientId("testClientId");

        mockMosquittoConnection =
                std::make_shared<MockMosquittoConnection>(ccSettings,
                                                          brokerUrl,
                                                          mqttKeepAliveTimeSeconds,
                                                          mqttReconnectDelayTimeSeconds,
                                                          mqttReconnectMaxDelayTimeSeconds,
                                                          isMqttExponentialBackoffEnabled,
                                                          clientId);

        mqttSender = std::make_shared<MqttSender>(mockMosquittoConnection, messagingSettings);

        ON_CALL(*mockMosquittoConnection, isSubscribedToChannelTopic()).WillByDefault(Return(true));
        ON_CALL(*mockMosquittoConnection, getMqttQos()).WillByDefault(Return(0));
        ON_CALL(*mockMosquittoConnection, getMqttPrio()).WillByDefault(Return("low"));
    }

    ADD_LOGGER(MqttSenderTest)
    joynr::system::RoutingTypes::MqttAddress mqttAddress;

    std::shared_ptr<MockMosquittoConnection> mockMosquittoConnection;
    std::shared_ptr<MqttSender> mqttSender;
};

TEST_F(MqttSenderTest, messagePublishedToCorrectTopic)
{
    const std::string expectedTopic = mqttAddress.getTopic() + "/low";
    MutableMessage mutableMessage;

    createMqttSender("test-resources/MqttSenderTestWithMaxMessageSizeLimits2.settings");

    mutableMessage.setType(joynr::Message::VALUE_MESSAGE_TYPE_REQUEST());
    mutableMessage.setSender("testSender");
    mutableMessage.setRecipient("testRecipient");
    mutableMessage.setPayload("shortMessage");

    std::shared_ptr<joynr::ImmutableMessage> immutableMessage =
            mutableMessage.getImmutableMessage();

    EXPECT_CALL(*mockMosquittoConnection, publishMessage(
                    Eq(expectedTopic),
                    Eq(0),
                    _,
                    _,
                    _,
                    _));

    mqttSender->sendMessage(mqttAddress,
                            immutableMessage,
                            [] (const exceptions::JoynrRuntimeException& exception) {
                                FAIL() << "sendMessage failed: " << exception.getMessage();
                            });
}

TEST_F(MqttSenderTest, messagePublishedWithMsgTtlSecAlwaysRoundedUp)
{
    const TimePoint now = TimePoint::now();
    const std::uint32_t expectedRoundedMsgTtlSec = 61;
    auto onFailure = [] (const exceptions::JoynrRuntimeException& exception) {
        FAIL() << "sendMessage failed: " << exception.getMessage();
    };

    MutableMessage mutableMessage;

    createMqttSender("test-resources/MqttSenderTestWithMaxMessageSizeLimits2.settings");

    mutableMessage.setType(joynr::Message::VALUE_MESSAGE_TYPE_REQUEST());
    mutableMessage.setSender("testSender");
    mutableMessage.setRecipient("testRecipient");
    mutableMessage.setPayload("shortMessage");
    mutableMessage.setExpiryDate(now + std::chrono::milliseconds(60700)); // 60,7 sec will be rounded to 61 sec

    std::shared_ptr<joynr::ImmutableMessage> immutableMessage1 =
            mutableMessage.getImmutableMessage();

    EXPECT_CALL(*mockMosquittoConnection, publishMessage(
                    _,
                    _,
                    _,
                    Eq(expectedRoundedMsgTtlSec),
                    _,
                    _));

    mqttSender->sendMessage(mqttAddress, immutableMessage1, onFailure);

    auto relativeTtl1 = immutableMessage1->getExpiryDate().relativeFromNow().count();

    ASSERT_TRUE(relativeTtl1 % 1000 > 600 && relativeTtl1 % 1000 < 800);

    // Second message with different expiry date
    mutableMessage.setExpiryDate(now + std::chrono::milliseconds(60200)); // 60,2 sec will be rounded to 61 sec

    std::shared_ptr<joynr::ImmutableMessage> immutableMessage2 =
            mutableMessage.getImmutableMessage();

    EXPECT_CALL(*mockMosquittoConnection, publishMessage(
                    _,
                    _,
                    _,
                    Eq(expectedRoundedMsgTtlSec),
                    _,
                    _));

    mqttSender->sendMessage(mqttAddress, immutableMessage2, onFailure);

    auto relativeTtl2 = immutableMessage2->getExpiryDate().relativeFromNow().count();

    ASSERT_TRUE(relativeTtl2 % 1000 > 100 && relativeTtl2 % 1000 < 300);
}

TEST_F(MqttSenderTest, messagePublishedWithMsgTtlSecGreaterThanMaxIntervalAlwaysSetToMaxInterval)
{
    const TimePoint now = TimePoint::now();
    const std::uint32_t MESSAGE_EXPIRY_MAX_INTERVAL = std::numeric_limits<std::uint32_t>::max();
    const std::uint32_t expectedMaxMsgTtlSec = MESSAGE_EXPIRY_MAX_INTERVAL;

    auto onFailure = [] (const exceptions::JoynrRuntimeException& exception) {
        FAIL() << "sendMessage failed: " << exception.getMessage();
    };

    MutableMessage mutableMessage;

    createMqttSender("test-resources/MqttSenderTestWithMaxMessageSizeLimits2.settings");

    mutableMessage.setType(joynr::Message::VALUE_MESSAGE_TYPE_REQUEST());
    mutableMessage.setSender("testSender");
    mutableMessage.setRecipient("testRecipient");
    mutableMessage.setPayload("shortMessage");

    mutableMessage.setExpiryDate(now + std::chrono::seconds(MESSAGE_EXPIRY_MAX_INTERVAL) +
                                 std::chrono::seconds(6));

    std::shared_ptr<joynr::ImmutableMessage> immutableMessage1 =
            mutableMessage.getImmutableMessage();

    EXPECT_CALL(*mockMosquittoConnection, publishMessage(
                    _,
                    _,
                    _,
                    Eq(expectedMaxMsgTtlSec),
                    _,
                    _)).Times(2);

    mqttSender->sendMessage(mqttAddress, immutableMessage1, onFailure);

    mutableMessage.setExpiryDate(TimePoint::fromAbsoluteMs(-1000));

    std::shared_ptr<joynr::ImmutableMessage> immutableMessage2 =
            mutableMessage.getImmutableMessage();

    mqttSender->sendMessage(mqttAddress, immutableMessage2, onFailure);

}

TEST_F(MqttSenderTest, multicastMessagePublishedToCorrectTopic)
{
    const std::string expectedTopic = mqttAddress.getTopic();
    MutableMessage mutableMessage;

    createMqttSender("test-resources/MqttSenderTestWithMaxMessageSizeLimits2.settings");

    mutableMessage.setType(joynr::Message::VALUE_MESSAGE_TYPE_MULTICAST());
    mutableMessage.setSender("testSender");
    mutableMessage.setRecipient("testMulticastId");
    mutableMessage.setPayload("shortMessage");

    std::shared_ptr<joynr::ImmutableMessage> immutableMessage =
            mutableMessage.getImmutableMessage();

    EXPECT_CALL(*mockMosquittoConnection, publishMessage(
                    Eq(expectedTopic),
                    Eq(0),
                    _,
                    _,
                    _,
                    _));

    mqttSender->sendMessage(mqttAddress,
                            immutableMessage,
                            [] (const exceptions::JoynrRuntimeException& exception) {
                                FAIL() << "sendMessage failed: " << exception.getMessage();
                            });
}

TEST_F(MqttSenderTest, TestWithEnabledMessageSizeCheck)
{
    MutableMessage mutableMessage;
    bool gotExpectedExceptionType;
    bool gotCalled;

    createMqttSender("test-resources/MqttSenderTestWithMaxMessageSizeLimits1.settings");

    mutableMessage.setType(joynr::Message::VALUE_MESSAGE_TYPE_MULTICAST());
    mutableMessage.setSender("testSender");
    mutableMessage.setRecipient("testMulticastId");
    mutableMessage.setPayload("shortMessage");

    std::shared_ptr<joynr::ImmutableMessage> immutableMessage =
            mutableMessage.getImmutableMessage();

    gotCalled = false;
    mqttSender->sendMessage(mqttAddress,
                            immutableMessage,
                            [&gotCalled](
                                    const exceptions::JoynrRuntimeException& exception) {
        gotCalled = true;
        try {
            const joynr::exceptions::JoynrMessageNotSentException& messageNotSentException =
                    dynamic_cast<const joynr::exceptions::JoynrMessageNotSentException&>(exception);
            std::ignore = messageNotSentException;
        } catch (std::bad_cast& bc) {
            // fallthrough
        }
    });
    EXPECT_FALSE(gotCalled);

    std::string longMessagePayload(1000, 'x');
    mutableMessage.setPayload(longMessagePayload);
    immutableMessage = mutableMessage.getImmutableMessage();

    gotExpectedExceptionType = false;
    gotCalled = false;
    mqttSender->sendMessage(mqttAddress,
                            immutableMessage,
                            [&gotCalled, &gotExpectedExceptionType](
                                    const exceptions::JoynrRuntimeException& exception) {
        gotCalled = true;
        try {
            const joynr::exceptions::JoynrMessageNotSentException& messageNotSentException =
                    dynamic_cast<const joynr::exceptions::JoynrMessageNotSentException&>(exception);
            gotExpectedExceptionType = true;
            std::ignore = messageNotSentException;
        } catch (std::bad_cast& bc) {
            // fallthrough
        }
    });
    EXPECT_TRUE(gotCalled);
    EXPECT_TRUE(gotExpectedExceptionType);
}

TEST_F(MqttSenderTest, TestWithDisabledMessageSizeCheck)
{
    MutableMessage mutableMessage;

    createMqttSender("test-resources/MqttSenderTestWithMaxMessageSizeLimits2.settings");

    mutableMessage.setType(joynr::Message::VALUE_MESSAGE_TYPE_MULTICAST());
    mutableMessage.setSender("testSender");
    mutableMessage.setRecipient("testMulticastId");
    mutableMessage.setPayload("shortMessage");

    std::shared_ptr<joynr::ImmutableMessage> immutableMessage =
            mutableMessage.getImmutableMessage();

    bool gotCalled = false;
    mqttSender->sendMessage(
            mqttAddress,
            immutableMessage,
            [&gotCalled](const exceptions::JoynrRuntimeException&) { gotCalled = true; });
    EXPECT_FALSE(gotCalled);

    std::string longMessagePayload(1000, 'x');
    mutableMessage.setPayload(longMessagePayload);
    immutableMessage = mutableMessage.getImmutableMessage();

    gotCalled = false;
    mqttSender->sendMessage(
            mqttAddress,
            immutableMessage,
            [&gotCalled](const exceptions::JoynrRuntimeException&) { gotCalled = true; });
    EXPECT_FALSE(gotCalled);
}

} // namespace joynr
<commit_msg>[C++] Adjusted MqttSenderTest which now gets maximum packet size from Mock<commit_after>/*
 * #%L
 * %%
 * Copyright (C) 2020 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 <gtest/gtest.h>

#include "joynr/BrokerUrl.h"
#include "joynr/ClusterControllerSettings.h"
#include "joynr/ImmutableMessage.h"
#include "joynr/Message.h"
#include "joynr/MessagingSettings.h"
#include "joynr/MutableMessage.h"
#include "joynr/Settings.h"
#include "joynr/exceptions/JoynrException.h"
#include "joynr/system/RoutingTypes/MqttAddress.h"

#include "libjoynrclustercontroller/mqtt/MqttSender.h"

#include "tests/mock/MockMosquittoConnection.h"

using namespace ::testing;

namespace joynr
{

class MqttSenderTest : public testing::Test
{
public:
    MqttSenderTest() : mqttAddress("brokerUri", "clientId"), mockMosquittoConnection(), mqttSender()
    {
    }

protected:
    void createMqttSender(std::string testSettingsFileNameMqtt, std::uint32_t maximumPacketSize)
    {
        Settings testSettings(testSettingsFileNameMqtt);
        MessagingSettings messagingSettings(testSettings);
        const ClusterControllerSettings ccSettings(testSettings);
        BrokerUrl brokerUrl("testBrokerUrl");
        std::chrono::seconds mqttKeepAliveTimeSeconds(1);
        std::chrono::seconds mqttReconnectDelayTimeSeconds(1);
        std::chrono::seconds mqttReconnectMaxDelayTimeSeconds(1);
        bool isMqttExponentialBackoffEnabled(false);
        const std::string clientId("testClientId");

        mockMosquittoConnection =
                std::make_shared<MockMosquittoConnection>(ccSettings,
                                                          brokerUrl,
                                                          mqttKeepAliveTimeSeconds,
                                                          mqttReconnectDelayTimeSeconds,
                                                          mqttReconnectMaxDelayTimeSeconds,
                                                          isMqttExponentialBackoffEnabled,
                                                          clientId);

        mqttSender = std::make_shared<MqttSender>(mockMosquittoConnection, messagingSettings);

        ON_CALL(*mockMosquittoConnection, isSubscribedToChannelTopic()).WillByDefault(Return(true));
        ON_CALL(*mockMosquittoConnection, getMqttQos()).WillByDefault(Return(0));
        ON_CALL(*mockMosquittoConnection, getMqttPrio()).WillByDefault(Return("low"));
        ON_CALL(*mockMosquittoConnection, getMqttMaximumPacketSize()).WillByDefault(Return(maximumPacketSize));
    }

    ADD_LOGGER(MqttSenderTest)
    joynr::system::RoutingTypes::MqttAddress mqttAddress;

    std::shared_ptr<MockMosquittoConnection> mockMosquittoConnection;
    std::shared_ptr<MqttSender> mqttSender;
    const std::uint32_t noMqttMessagePacketSize = 0;
};

TEST_F(MqttSenderTest, messagePublishedToCorrectTopic)
{
    const std::string expectedTopic = mqttAddress.getTopic() + "/low";
    MutableMessage mutableMessage;

    createMqttSender("test-resources/MqttSenderTestWithMaxMessageSizeLimits2.settings", MqttSenderTest::noMqttMessagePacketSize);

    mutableMessage.setType(joynr::Message::VALUE_MESSAGE_TYPE_REQUEST());
    mutableMessage.setSender("testSender");
    mutableMessage.setRecipient("testRecipient");
    mutableMessage.setPayload("shortMessage");

    std::shared_ptr<joynr::ImmutableMessage> immutableMessage =
            mutableMessage.getImmutableMessage();

    EXPECT_CALL(*mockMosquittoConnection, publishMessage(
                    Eq(expectedTopic),
                    Eq(0),
                    _,
                    _,
                    _,
                    _));

    mqttSender->sendMessage(mqttAddress,
                            immutableMessage,
                            [] (const exceptions::JoynrRuntimeException& exception) {
                                FAIL() << "sendMessage failed: " << exception.getMessage();
                            });
}

TEST_F(MqttSenderTest, messagePublishedWithMsgTtlSecAlwaysRoundedUp)
{
    const TimePoint now = TimePoint::now();
    const std::uint32_t expectedRoundedMsgTtlSec = 61;
    auto onFailure = [] (const exceptions::JoynrRuntimeException& exception) {
        FAIL() << "sendMessage failed: " << exception.getMessage();
    };

    MutableMessage mutableMessage;

    createMqttSender("test-resources/MqttSenderTestWithMaxMessageSizeLimits2.settings", MqttSenderTest::noMqttMessagePacketSize);

    mutableMessage.setType(joynr::Message::VALUE_MESSAGE_TYPE_REQUEST());
    mutableMessage.setSender("testSender");
    mutableMessage.setRecipient("testRecipient");
    mutableMessage.setPayload("shortMessage");
    mutableMessage.setExpiryDate(now + std::chrono::milliseconds(60700)); // 60,7 sec will be rounded to 61 sec

    std::shared_ptr<joynr::ImmutableMessage> immutableMessage1 =
            mutableMessage.getImmutableMessage();

    EXPECT_CALL(*mockMosquittoConnection, publishMessage(
                    _,
                    _,
                    _,
                    Eq(expectedRoundedMsgTtlSec),
                    _,
                    _));

    mqttSender->sendMessage(mqttAddress, immutableMessage1, onFailure);

    auto relativeTtl1 = immutableMessage1->getExpiryDate().relativeFromNow().count();

    ASSERT_TRUE(relativeTtl1 % 1000 > 600 && relativeTtl1 % 1000 < 800);

    // Second message with different expiry date
    mutableMessage.setExpiryDate(now + std::chrono::milliseconds(60200)); // 60,2 sec will be rounded to 61 sec

    std::shared_ptr<joynr::ImmutableMessage> immutableMessage2 =
            mutableMessage.getImmutableMessage();

    EXPECT_CALL(*mockMosquittoConnection, publishMessage(
                    _,
                    _,
                    _,
                    Eq(expectedRoundedMsgTtlSec),
                    _,
                    _));

    mqttSender->sendMessage(mqttAddress, immutableMessage2, onFailure);

    auto relativeTtl2 = immutableMessage2->getExpiryDate().relativeFromNow().count();

    ASSERT_TRUE(relativeTtl2 % 1000 > 100 && relativeTtl2 % 1000 < 300);
}

TEST_F(MqttSenderTest, messagePublishedWithMsgTtlSecGreaterThanMaxIntervalAlwaysSetToMaxInterval)
{
    const TimePoint now = TimePoint::now();
    const std::uint32_t MESSAGE_EXPIRY_MAX_INTERVAL = std::numeric_limits<std::uint32_t>::max();
    const std::uint32_t expectedMaxMsgTtlSec = MESSAGE_EXPIRY_MAX_INTERVAL;

    auto onFailure = [] (const exceptions::JoynrRuntimeException& exception) {
        FAIL() << "sendMessage failed: " << exception.getMessage();
    };

    MutableMessage mutableMessage;

    createMqttSender("test-resources/MqttSenderTestWithMaxMessageSizeLimits2.settings", MqttSenderTest::noMqttMessagePacketSize);

    mutableMessage.setType(joynr::Message::VALUE_MESSAGE_TYPE_REQUEST());
    mutableMessage.setSender("testSender");
    mutableMessage.setRecipient("testRecipient");
    mutableMessage.setPayload("shortMessage");

    mutableMessage.setExpiryDate(now + std::chrono::seconds(MESSAGE_EXPIRY_MAX_INTERVAL) +
                                 std::chrono::seconds(6));

    std::shared_ptr<joynr::ImmutableMessage> immutableMessage1 =
            mutableMessage.getImmutableMessage();

    EXPECT_CALL(*mockMosquittoConnection, publishMessage(
                    _,
                    _,
                    _,
                    Eq(expectedMaxMsgTtlSec),
                    _,
                    _)).Times(2);

    mqttSender->sendMessage(mqttAddress, immutableMessage1, onFailure);

    mutableMessage.setExpiryDate(TimePoint::fromAbsoluteMs(-1000));

    std::shared_ptr<joynr::ImmutableMessage> immutableMessage2 =
            mutableMessage.getImmutableMessage();

    mqttSender->sendMessage(mqttAddress, immutableMessage2, onFailure);

}

TEST_F(MqttSenderTest, multicastMessagePublishedToCorrectTopic)
{
    const std::string expectedTopic = mqttAddress.getTopic();
    MutableMessage mutableMessage;

    createMqttSender("test-resources/MqttSenderTestWithMaxMessageSizeLimits2.settings", MqttSenderTest::noMqttMessagePacketSize);

    mutableMessage.setType(joynr::Message::VALUE_MESSAGE_TYPE_MULTICAST());
    mutableMessage.setSender("testSender");
    mutableMessage.setRecipient("testMulticastId");
    mutableMessage.setPayload("shortMessage");

    std::shared_ptr<joynr::ImmutableMessage> immutableMessage =
            mutableMessage.getImmutableMessage();

    EXPECT_CALL(*mockMosquittoConnection, publishMessage(
                    Eq(expectedTopic),
                    Eq(0),
                    _,
                    _,
                    _,
                    _));

    mqttSender->sendMessage(mqttAddress,
                            immutableMessage,
                            [] (const exceptions::JoynrRuntimeException& exception) {
                                FAIL() << "sendMessage failed: " << exception.getMessage();
                            });
}

TEST_F(MqttSenderTest, TestWithEnabledMessageSizeCheck)
{
    MutableMessage mutableMessage;
    bool gotExpectedExceptionType;
    bool gotCalled;

    createMqttSender("test-resources/MqttSenderTestWithMaxMessageSizeLimits1.settings", 900);

    mutableMessage.setType(joynr::Message::VALUE_MESSAGE_TYPE_MULTICAST());
    mutableMessage.setSender("testSender");
    mutableMessage.setRecipient("testMulticastId");
    mutableMessage.setPayload("shortMessage");

    std::shared_ptr<joynr::ImmutableMessage> immutableMessage =
            mutableMessage.getImmutableMessage();

    gotCalled = false;
    mqttSender->sendMessage(mqttAddress,
                            immutableMessage,
                            [&gotCalled](
                                    const exceptions::JoynrRuntimeException& exception) {
        gotCalled = true;
        try {
            const joynr::exceptions::JoynrMessageNotSentException& messageNotSentException =
                    dynamic_cast<const joynr::exceptions::JoynrMessageNotSentException&>(exception);
            std::ignore = messageNotSentException;
        } catch (std::bad_cast& bc) {
            // fallthrough
        }
    });
    EXPECT_FALSE(gotCalled);

    std::string longMessagePayload(1000, 'x');
    mutableMessage.setPayload(longMessagePayload);
    immutableMessage = mutableMessage.getImmutableMessage();

    gotExpectedExceptionType = false;
    gotCalled = false;
    mqttSender->sendMessage(mqttAddress,
                            immutableMessage,
                            [&gotCalled, &gotExpectedExceptionType](
                                    const exceptions::JoynrRuntimeException& exception) {
        gotCalled = true;
        try {
            const joynr::exceptions::JoynrMessageNotSentException& messageNotSentException =
                    dynamic_cast<const joynr::exceptions::JoynrMessageNotSentException&>(exception);
            gotExpectedExceptionType = true;
            std::ignore = messageNotSentException;
        } catch (std::bad_cast& bc) {
            // fallthrough
        }
    });
    EXPECT_TRUE(gotCalled);
    EXPECT_TRUE(gotExpectedExceptionType);
}

TEST_F(MqttSenderTest, TestWithDisabledMessageSizeCheck)
{
    MutableMessage mutableMessage;

    createMqttSender("test-resources/MqttSenderTestWithMaxMessageSizeLimits2.settings", 0);

    mutableMessage.setType(joynr::Message::VALUE_MESSAGE_TYPE_MULTICAST());
    mutableMessage.setSender("testSender");
    mutableMessage.setRecipient("testMulticastId");
    mutableMessage.setPayload("shortMessage");

    std::shared_ptr<joynr::ImmutableMessage> immutableMessage =
            mutableMessage.getImmutableMessage();

    bool gotCalled = false;
    mqttSender->sendMessage(
            mqttAddress,
            immutableMessage,
            [&gotCalled](const exceptions::JoynrRuntimeException&) { gotCalled = true; });
    EXPECT_FALSE(gotCalled);

    std::string longMessagePayload(1000, 'x');
    mutableMessage.setPayload(longMessagePayload);
    immutableMessage = mutableMessage.getImmutableMessage();

    gotCalled = false;
    mqttSender->sendMessage(
            mqttAddress,
            immutableMessage,
            [&gotCalled](const exceptions::JoynrRuntimeException&) { gotCalled = true; });
    EXPECT_FALSE(gotCalled);
}

} // namespace joynr
<|endoftext|>