<commit_before>#pragma once
#ifndef TARIGO_MSGPACK_VALUES_HPP
#define TARIGO_MSGPACK_VALUES_HPP

#include <string>
#include <memory>

#include <msgpack/value_base.hpp>

namespace tarigo {
namespace msgpack {

// -----------------------------------------------------------------------------
// Nil.
// -----------------------------------------------------------------------------
class value_nil final : public value_base<type::NIL, nil_struct> {
public:
    explicit value_nil() : value_base({}) {}
    enum format format() const override { return format::NIL; }
};

// -----------------------------------------------------------------------------
// Boolean.
// -----------------------------------------------------------------------------
class value_boolean final : public value_base<type::BOOLEAN, bool> {
public:
    explicit value_boolean(bool value) : value_base(value) {}
    enum format format() const override {
        return value_ ? format::TRUE : format::FALSE;
    }
};

// -----------------------------------------------------------------------------
// String.
// -----------------------------------------------------------------------------
class value_string final : public value_base<type::RAW_STRING, std::string> {
public:
    explicit value_string(const std::string &value) : value_base(value) {}
    explicit value_string(std::string &&value) : value_base(std::move(value)) {}

    enum format format() const override {
        const size_t len = value_.size();
        if (len <= 0x1f) return format::FIXSTR;
        if (len <= 0xff) return format::STR8;
        if (len <= 0xffff) return format::STR16;
        return format::STR32;
    }

    const std::string &string_value() const override { return value_; }
};

// -----------------------------------------------------------------------------
// Generic numeric value.
// -----------------------------------------------------------------------------

template <type MsgPackType, typename NativeType>
class value_number: public value_base<MsgPackType, NativeType> {
protected:
    explicit value_number(const NativeType &value)
            : value_base<MsgPackType, NativeType>(value) {}
    explicit value_number(NativeType &&value)
            : value_base<MsgPackType, NativeType>(std::move(value)) {}

    //FIXME:
    bool equals(const value * other) const override {
        switch( other->type() )
        {
            case type::INTEGER:
            case type::FLOAT:
            {
                return double_value() == other->double_value();
            } break;
            default:
            {
                return value_base<MsgPackType,NativeType>::equals(other);
            } break;
        }
    }

    //FIXME:
    bool less(const value * other) const override {
        switch( other->type() )
        {
            case type::INTEGER:
            case type::FLOAT:
            {
                return double_value() < other->double_value();
            } break;
            default:
            {
                return value_base<MsgPackType,NativeType>::equals(other);
            } break;
        }
    }

    float float_value() const override {
        return static_cast<float>(value_base<MsgPackType,NativeType>::value_);
    }

    double double_value() const override {
        return static_cast<double>(value_base<MsgPackType,NativeType>::value_);
    }

    int8_t int8_value() const override {
        return static_cast<int8_t>(value_base<MsgPackType,NativeType>::value_);
    }

    int16_t int16_value() const override {
        return static_cast<int16_t>(value_base<MsgPackType,NativeType>::value_);
    }
    int32_t int32_value() const override {
        return static_cast<int32_t>(value_base<MsgPackType,NativeType>::value_);
    }

    int64_t int64_value() const override {
        return static_cast<int64_t>(value_base<MsgPackType,NativeType>::value_);
    }

    uint8_t uint8_value() const override {
        return static_cast<uint8_t>(value_base<MsgPackType,NativeType>::value_);
    }

    uint16_t uint16_value() const override {
        return static_cast<uint16_t>(value_base<MsgPackType,NativeType>::value_);
    }

    uint32_t uint32_value() const override {
        return static_cast<uint32_t>(value_base<MsgPackType,NativeType>::value_);
    }

    uint64_t uint64_value() const override {
        return static_cast<uint64_t>(value_base<MsgPackType,NativeType>::value_);
    }
};

template <typename T,
        class = typename std::enable_if<std::is_integral<T>::value>::type>
format integer_format(T i) {
    if (i >= 0 && i <= 127) return format::POSITIVE_FIXINT;

    if (std::is_signed<T>::value) {
        if (i >= -32 && i <= -1) return format::NEGATIVE_FIXINT;
    }

    if (std::is_same<T, int8_t>::value) return format::INT8;
    if (std::is_same<T, int16_t>::value) return format::INT16;
    if (std::is_same<T, int32_t>::value) return format::INT32;
    if (std::is_same<T, int64_t>::value) return format::INT64;

    if (std::is_same<T, uint8_t>::value) return format::UINT8;
    if (std::is_same<T, uint16_t>::value) return format::UINT16;
    if (std::is_same<T, uint32_t>::value) return format::UINT32;
    if (std::is_same<T, uint64_t>::value) return format::UINT64;

    return format::UNDEFINED;
}

// -----------------------------------------------------------------------------
// Integers.
// -----------------------------------------------------------------------------

class value_int8 final : public value_number<type::INTEGER, int8_t> {
public:
    explicit value_int8(int8_t value) : value_number(value) {}

    enum format format() const override {
        return integer_format<int8_t >(value_);
    }
};

class value_int16 final : public value_number<type::INTEGER, int16_t> {
public:
    explicit value_int16(uint16_t value) : value_number(value) {}

    enum format format() const override {
        return integer_format<int16_t >(value_);
    }
};

class value_int32 final : public value_number<type::INTEGER, int32_t> {
public:
    explicit value_int32(int32_t value) : value_number(value) {}

    enum format format() const override {
        return integer_format<int32_t>(value_);
    }
};

class value_int64 final : public value_number<type::INTEGER, int64_t> {
public:
    explicit value_int64(int64_t value) : value_number(value) {}

    enum format format() const override {
        return integer_format<int64_t>(value_);
    }
};

class value_uint8 final : public value_number<type::INTEGER, uint8_t> {
public:
    explicit value_uint8(uint8_t value) : value_number(value) {}

    enum format format() const override {
        return integer_format<uint8_t>(value_);
    }
};

class value_uint16 final : public value_number<type::INTEGER, uint16_t> {
public:
    explicit value_uint16(uint16_t value) : value_number(value) {}

    enum format format() const override {
        return integer_format<uint16_t>(value_);
    }
};

class value_uint32 final : public value_number<type::INTEGER, uint32_t> {
public:
    explicit value_uint32(uint32_t value) : value_number(value) {}

    enum format format() const override {
        return integer_format<uint32_t>(value_);
    }
};

class value_uint64 final : public value_number<type::INTEGER, uint64_t> {
public:
    explicit value_uint64(uint64_t value) : value_number(value) {}

    enum format format() const override {
        return integer_format<uint64_t>(value_);
    }
};

// -----------------------------------------------------------------------------
// Floats.
// -----------------------------------------------------------------------------
class value_float final : public value_number<type::FLOAT, float> {
public:
    explicit value_float(float value) : value_number(value) {}
    enum format format() const override { return format::FLOAT32; }
};

class value_double final : public value_number<type::FLOAT, double> {
public:
    explicit value_double(double value) : value_number(value) {}
    enum format format() const override { return format::FLOAT64; }
};

// -----------------------------------------------------------------------------
// Binary.
// -----------------------------------------------------------------------------
class value_binary final : public value_base<type::RAW_BINARY,package::binary> {
    const package::binary &binary_items() const override { return value_; }
public:
    explicit value_binary(const package::binary &value) : value_base(value) {}
    explicit value_binary(package::binary &&value) : value_base(move(value)) {}

    enum format format() const override {
        const size_t len = value_.size();
        if(len <= 0xff) return format::BIN8;
        if (len <= 0xffff) return format::BIN16;
        return format::BIN32;
    }
};

// -----------------------------------------------------------------------------
// Array.
// -----------------------------------------------------------------------------
class value_array final : public value_base<type::ARRAY, package::array> {
public:
    explicit value_array(const package::array &values) : value_base(values) {}
    explicit value_array(package::array &&values) : value_base(move(values)) {}

public:
    enum format format() const override {
        const size_t len = value_.size();
        if (len <= 15) return format::FIXARRAY;
        if (len <= 0xffff) return format::ARRAY16;
        return format ::ARRAY32;
    }

    const package &operator[](size_t i) const override {
        if (i >= value_.size()) return static_nil();
        else return value_[i];
    }

    const package::array &array_items() const override { return value_; }
};

// -----------------------------------------------------------------------------
// Map.
// -----------------------------------------------------------------------------
class value_map final : public value_base<type::MAP, package::map> {
public:
    explicit value_map(const package::map &value) : value_base(value) {}
    explicit value_map(package::map &&value)   : value_base(move(value)) {}

public:
    enum format format() const override {
        const size_t len = value_.size();
        if(len <= 15) return format::FIXMAP;
        if(len <= 0xffff) return format::MAP16;
        return format::MAP32;
    }

    const package::map &map_items() const override { return value_; }

    const package & operator[](std::string const& key) const override {
        auto iter = value_.find(key);
        return (iter == value_.end()) ? static_nil() : iter->second;
    }
};

} // namespace msgpack
} // namespace tarigo

#endif // TARIGO_MSGPACK_VALUES_HPP<commit_msg>Add newline.<commit_after>#pragma once
#ifndef TARIGO_MSGPACK_VALUES_HPP
#define TARIGO_MSGPACK_VALUES_HPP

#include <string>
#include <memory>

#include <msgpack/value_base.hpp>

namespace tarigo {
namespace msgpack {

// -----------------------------------------------------------------------------
// Nil.
// -----------------------------------------------------------------------------
class value_nil final : public value_base<type::NIL, nil_struct> {
public:
    explicit value_nil() : value_base({}) {}
    enum format format() const override { return format::NIL; }
};

// -----------------------------------------------------------------------------
// Boolean.
// -----------------------------------------------------------------------------
class value_boolean final : public value_base<type::BOOLEAN, bool> {
public:
    explicit value_boolean(bool value) : value_base(value) {}
    enum format format() const override {
        return value_ ? format::TRUE : format::FALSE;
    }
};

// -----------------------------------------------------------------------------
// String.
// -----------------------------------------------------------------------------
class value_string final : public value_base<type::RAW_STRING, std::string> {
public:
    explicit value_string(const std::string &value) : value_base(value) {}
    explicit value_string(std::string &&value) : value_base(std::move(value)) {}

    enum format format() const override {
        const size_t len = value_.size();
        if (len <= 0x1f) return format::FIXSTR;
        if (len <= 0xff) return format::STR8;
        if (len <= 0xffff) return format::STR16;
        return format::STR32;
    }

    const std::string &string_value() const override { return value_; }
};

// -----------------------------------------------------------------------------
// Generic numeric value.
// -----------------------------------------------------------------------------

template <type MsgPackType, typename NativeType>
class value_number: public value_base<MsgPackType, NativeType> {
protected:
    explicit value_number(const NativeType &value)
            : value_base<MsgPackType, NativeType>(value) {}
    explicit value_number(NativeType &&value)
            : value_base<MsgPackType, NativeType>(std::move(value)) {}

    //FIXME:
    bool equals(const value * other) const override {
        switch( other->type() )
        {
            case type::INTEGER:
            case type::FLOAT:
            {
                return double_value() == other->double_value();
            } break;
            default:
            {
                return value_base<MsgPackType,NativeType>::equals(other);
            } break;
        }
    }

    //FIXME:
    bool less(const value * other) const override {
        switch( other->type() )
        {
            case type::INTEGER:
            case type::FLOAT:
            {
                return double_value() < other->double_value();
            } break;
            default:
            {
                return value_base<MsgPackType,NativeType>::equals(other);
            } break;
        }
    }

    float float_value() const override {
        return static_cast<float>(value_base<MsgPackType,NativeType>::value_);
    }

    double double_value() const override {
        return static_cast<double>(value_base<MsgPackType,NativeType>::value_);
    }

    int8_t int8_value() const override {
        return static_cast<int8_t>(value_base<MsgPackType,NativeType>::value_);
    }

    int16_t int16_value() const override {
        return static_cast<int16_t>(value_base<MsgPackType,NativeType>::value_);
    }
    int32_t int32_value() const override {
        return static_cast<int32_t>(value_base<MsgPackType,NativeType>::value_);
    }

    int64_t int64_value() const override {
        return static_cast<int64_t>(value_base<MsgPackType,NativeType>::value_);
    }

    uint8_t uint8_value() const override {
        return static_cast<uint8_t>(value_base<MsgPackType,NativeType>::value_);
    }

    uint16_t uint16_value() const override {
        return static_cast<uint16_t>(value_base<MsgPackType,NativeType>::value_);
    }

    uint32_t uint32_value() const override {
        return static_cast<uint32_t>(value_base<MsgPackType,NativeType>::value_);
    }

    uint64_t uint64_value() const override {
        return static_cast<uint64_t>(value_base<MsgPackType,NativeType>::value_);
    }
};

template <typename T,
        class = typename std::enable_if<std::is_integral<T>::value>::type>
format integer_format(T i) {
    if (i >= 0 && i <= 127) return format::POSITIVE_FIXINT;

    if (std::is_signed<T>::value) {
        if (i >= -32 && i <= -1) return format::NEGATIVE_FIXINT;
    }

    if (std::is_same<T, int8_t>::value) return format::INT8;
    if (std::is_same<T, int16_t>::value) return format::INT16;
    if (std::is_same<T, int32_t>::value) return format::INT32;
    if (std::is_same<T, int64_t>::value) return format::INT64;

    if (std::is_same<T, uint8_t>::value) return format::UINT8;
    if (std::is_same<T, uint16_t>::value) return format::UINT16;
    if (std::is_same<T, uint32_t>::value) return format::UINT32;
    if (std::is_same<T, uint64_t>::value) return format::UINT64;

    return format::UNDEFINED;
}

// -----------------------------------------------------------------------------
// Integers.
// -----------------------------------------------------------------------------

class value_int8 final : public value_number<type::INTEGER, int8_t> {
public:
    explicit value_int8(int8_t value) : value_number(value) {}

    enum format format() const override {
        return integer_format<int8_t >(value_);
    }
};

class value_int16 final : public value_number<type::INTEGER, int16_t> {
public:
    explicit value_int16(uint16_t value) : value_number(value) {}

    enum format format() const override {
        return integer_format<int16_t >(value_);
    }
};

class value_int32 final : public value_number<type::INTEGER, int32_t> {
public:
    explicit value_int32(int32_t value) : value_number(value) {}

    enum format format() const override {
        return integer_format<int32_t>(value_);
    }
};

class value_int64 final : public value_number<type::INTEGER, int64_t> {
public:
    explicit value_int64(int64_t value) : value_number(value) {}

    enum format format() const override {
        return integer_format<int64_t>(value_);
    }
};

class value_uint8 final : public value_number<type::INTEGER, uint8_t> {
public:
    explicit value_uint8(uint8_t value) : value_number(value) {}

    enum format format() const override {
        return integer_format<uint8_t>(value_);
    }
};

class value_uint16 final : public value_number<type::INTEGER, uint16_t> {
public:
    explicit value_uint16(uint16_t value) : value_number(value) {}

    enum format format() const override {
        return integer_format<uint16_t>(value_);
    }
};

class value_uint32 final : public value_number<type::INTEGER, uint32_t> {
public:
    explicit value_uint32(uint32_t value) : value_number(value) {}

    enum format format() const override {
        return integer_format<uint32_t>(value_);
    }
};

class value_uint64 final : public value_number<type::INTEGER, uint64_t> {
public:
    explicit value_uint64(uint64_t value) : value_number(value) {}

    enum format format() const override {
        return integer_format<uint64_t>(value_);
    }
};

// -----------------------------------------------------------------------------
// Floats.
// -----------------------------------------------------------------------------
class value_float final : public value_number<type::FLOAT, float> {
public:
    explicit value_float(float value) : value_number(value) {}
    enum format format() const override { return format::FLOAT32; }
};

class value_double final : public value_number<type::FLOAT, double> {
public:
    explicit value_double(double value) : value_number(value) {}
    enum format format() const override { return format::FLOAT64; }
};

// -----------------------------------------------------------------------------
// Binary.
// -----------------------------------------------------------------------------
class value_binary final : public value_base<type::RAW_BINARY,package::binary> {
    const package::binary &binary_items() const override { return value_; }
public:
    explicit value_binary(const package::binary &value) : value_base(value) {}
    explicit value_binary(package::binary &&value) : value_base(move(value)) {}

    enum format format() const override {
        const size_t len = value_.size();
        if(len <= 0xff) return format::BIN8;
        if (len <= 0xffff) return format::BIN16;
        return format::BIN32;
    }
};

// -----------------------------------------------------------------------------
// Array.
// -----------------------------------------------------------------------------
class value_array final : public value_base<type::ARRAY, package::array> {
public:
    explicit value_array(const package::array &values) : value_base(values) {}
    explicit value_array(package::array &&values) : value_base(move(values)) {}

public:
    enum format format() const override {
        const size_t len = value_.size();
        if (len <= 15) return format::FIXARRAY;
        if (len <= 0xffff) return format::ARRAY16;
        return format ::ARRAY32;
    }

    const package &operator[](size_t i) const override {
        if (i >= value_.size()) return static_nil();
        else return value_[i];
    }

    const package::array &array_items() const override { return value_; }
};

// -----------------------------------------------------------------------------
// Map.
// -----------------------------------------------------------------------------
class value_map final : public value_base<type::MAP, package::map> {
public:
    explicit value_map(const package::map &value) : value_base(value) {}
    explicit value_map(package::map &&value)   : value_base(move(value)) {}

public:
    enum format format() const override {
        const size_t len = value_.size();
        if(len <= 15) return format::FIXMAP;
        if(len <= 0xffff) return format::MAP16;
        return format::MAP32;
    }

    const package::map &map_items() const override { return value_; }

    const package & operator[](std::string const& key) const override {
        auto iter = value_.find(key);
        return (iter == value_.end()) ? static_nil() : iter->second;
    }
};

} // namespace msgpack
} // namespace tarigo

#endif // TARIGO_MSGPACK_VALUES_HPP
<|endoftext|>


<commit_before>/***************************************************************
 *
 * Copyright (C) 1990-2007, Condor Team, Computer Sciences Department,
 * University of Wisconsin-Madison, WI.
 *
 * 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.
 *
 ***************************************************************/

/*
   This file contains special stubs that are needed to make certain
   things work within a user job that can't use their normal
   functionality.
*/

#include "condor_common.h"
#include "std_univ_io.h"
#include "condor_sys.h"
#include "condor_debug.h"
#include "exit.h"
#include "shared_utils.h"
#include "get_port_range.h"
#include "condor_netdb.h"
#include "simplelist.h"
#include "condor_sockaddr.h"

extern	StdUnivSock* syscall_sock;

condor_sockaddr
get_local_ipaddr() {
	return syscall_sock->my_addr();
}

extern "C" {

extern	int		DebugFlags;
int		_condor_DebugFD = 0;

extern int SetSyscalls(int);
extern int SYSCALL(int, ...);

/*
	In the 6.3 series, REMOTE_syscall had been removed. Well, it turns out
	that 6.4 was supposed to be backwards compatible with 6.2. :( This means
	that some 6.2 starters are going to look for the symbol REMOTE_syscall in a
	6.3+(including 6.4) standard universe executable in order to determine if
	it had been linked with condor correctly. This function must do nothing
	except exist for a while until we get rid of it for good and in a
	non-backwards compatible way.
*/
void REMOTE_syscall(void) {} ;

/*
  _condor_dprintf_va is the real meat of dprintf().  We have different
  concerns inside the user job.  All we need to care about in here is
  making sure we have the right syscall mode.  Otherwise, we don't
  need to do anything complex with priv states, locking, etc.
*/
void
_condor_dprintf_va( int flags, const char* fmt, va_list args )
{
	int scm;
	int no_fd = FALSE;

		/* See if this is one of the messages we are logging */
	if( !(flags&DebugFlags) ) {
		return;
	}

		/* If dprintf() isn't initialized, don't seg fault */
	if( ! _condor_DebugFD ) {
		_condor_DebugFD = 2; /* stderr */
		no_fd = TRUE;
	}

		/*
		  When talking to the debug fd, you are talking to an fd that
		  is not visible to the user.  It is not entered in the
		  virtual file table, and, hence, you should be in unmapped
		  mode.
		*/
	scm = SetSyscalls( SYS_LOCAL | SYS_UNMAPPED );

		/* Actually print the message */
	_condor_vfprintf_va( _condor_DebugFD, fmt, args );

		/* Restore our syscall mode */
	(void) SetSyscalls( scm );

	if( no_fd ) {
		_condor_DebugFD = 0;
	}
}

int get_port_range(int is_outgoing, int *low_port, int *high_port)
{
	char *low = NULL, *high = NULL;

	// is_outgoing is ignored here.  all connections are assumed to be outgoing
	// since cedar should not be opening any listen sockets in the userjob.

	if ( (low = getenv("_condor_LOWPORT")) == NULL ) {
        dprintf(D_NETWORK, "_condor_LOWPORT undefined\n");
		return FALSE;
    }
	if ( (high = getenv("_condor_HIGHPORT")) == NULL ) {
        dprintf(D_ALWAYS, "_condor_LOWPORT is defined but _condor_HIGHPORT undefined!\n");
		return FALSE;
	}

	*low_port = atoi(low);
	*high_port = atoi(high);

	if(*low_port < 1024 || *high_port < 1024 || *low_port > *high_port) {
		dprintf(D_ALWAYS, "get_port_range - invalid LOWPORT(%d) \
		                   and/or HIGHPORT(%d)\n",
		                   *low_port, *high_port);
		return FALSE;
	}

	return TRUE;
}

int
_condor_bind_all_interfaces( void )
{
	char *tmp = NULL;
	int bind_all = FALSE;

	if( (tmp = getenv("_condor_BIND_ALL_INTERFACES")) == NULL ) {
        dprintf(D_NETWORK, "_condor_BIND_ALL_INTERFACES undefined\n");
		return TRUE;
    }

	switch( tmp[0] ) {
	case 'T':
	case 't':
	case 'Y':
	case 'y':
		bind_all = TRUE;
		break;
	default:
		bind_all = FALSE;
		break;
	}

	return bind_all;
}

struct hostent *
condor_gethostbyname( const char *name )
{
	return gethostbyname( name );
}

struct hostent *
condor_gethostbyaddr( const char *addr, SOCKET_LENGTH_TYPE len, int type )

{
	return gethostbyaddr( addr, len, type );
}

int
condor_gethostname( char *name, size_t namelen )
{
	return gethostname( name, namelen );
}

#if !defined(WIN32)
/*
  Can't open something because we are out of fd's.  Try to let
  somebody know what happened.  In the user job, we don't want to
  close a bunch of fds, since we'll loose our debug socket, which is
  always open.  In fact, we shouldn't have to close anything to be
  able to dprintf().  So, just dprintf(), flush the fd for good
  measure, and call Suicide() (so we don't leave the job queue).
*/
void
_condor_fd_panic( int line, const char* file )
{
	dprintf( D_ALWAYS,
			 "**** PANIC -- OUT OF FILE DESCRIPTORS at line %d in %s\n",
			 line, file );
	Suicide();
}
#endif /* ! LOOSE32 */

#if HAVE_EXT_GCB
int
GCB_local_bind(int fd, struct sockaddr *my_addr, socklen_t addrlen)
{
	return bind(fd, my_addr, addrlen);
}
#endif /* HAVE_EXT_GCB */

/* For MyString */
int vprintf_length(const char *format, va_list args) { return 0; }

} /* extern "C" */

/*
  We need our own definition of my_ip_addr(), which is used by
  Sock::bind() to support Condor on machines with multiple network
  interfaces.  This version, instead of looking in a config file for
  magic parameters, looks at the existing syscall_sock and grabs the
  IP address off of there.
*/
unsigned int
my_ip_addr()
{
	return syscall_sock->get_ip_int();
}

/*
  We need our own definition of my_ip_string(), which is used by the
  utilities in internet.c (which in turn are used by CEDAR).  This
  version, instead of looking in a config file for magic parameters,
  looks at the existing syscall_sock and grabs the IP address off of
  there.
*/
char*
my_ip_string()
{
	struct in_addr addr;
	memset( &addr, 0, sizeof(struct in_addr) );
	addr.s_addr = syscall_sock->get_ip_int();
	return inet_ntoa( addr );
}

std::vector<condor_sockaddr> resolve_hostname(const char* hostname) {
	std::vector<condor_sockaddr> ret;
	addrinfo* addrs = 0;
	int result;

	result = getaddrinfo(hostname, NULL, NULL, &addrs);
	if (result != 0 || !addrs) {
		return ret;
	}

	addrinfo* iter = addrs;
	while (iter) {
		ret.push_back(condor_sockaddr(iter->ai_addr));
		iter = iter->ai_next;
	}
	freeaddrinfo(addrs);

		// in order to completely eliminate duplicates, sort() should be
		// called before unique().

		// however, we do not need strict uniqueness here.
		// also, most of duplication comes from protocol variety.
		// e.g. same address with different socket type such as
		// SOCK_STREAM, SOCK_DGRAM
	std::vector<condor_sockaddr>::iterator it;
	it = std::unique(ret.begin(), ret.end());
	ret.resize(it - ret.begin());
	return ret;
}

std::vector<condor_sockaddr> resolve_hostname(const MyString& hostname) {
	return resolve_hostname(hostname.Value());
}
<commit_msg>fixing compile error again<commit_after>/***************************************************************
 *
 * Copyright (C) 1990-2007, Condor Team, Computer Sciences Department,
 * University of Wisconsin-Madison, WI.
 *
 * 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.
 *
 ***************************************************************/

/*
   This file contains special stubs that are needed to make certain
   things work within a user job that can't use their normal
   functionality.
*/

#include "condor_common.h"
#include "std_univ_io.h"
#include "condor_sys.h"
#include "condor_debug.h"
#include "exit.h"
#include "shared_utils.h"
#include "get_port_range.h"
#include "condor_netdb.h"
#include "simplelist.h"
#include "condor_sockaddr.h"
#include <algorithm>

extern	StdUnivSock* syscall_sock;

condor_sockaddr
get_local_ipaddr() {
	return syscall_sock->my_addr();
}

extern "C" {

extern	int		DebugFlags;
int		_condor_DebugFD = 0;

extern int SetSyscalls(int);
extern int SYSCALL(int, ...);

/*
	In the 6.3 series, REMOTE_syscall had been removed. Well, it turns out
	that 6.4 was supposed to be backwards compatible with 6.2. :( This means
	that some 6.2 starters are going to look for the symbol REMOTE_syscall in a
	6.3+(including 6.4) standard universe executable in order to determine if
	it had been linked with condor correctly. This function must do nothing
	except exist for a while until we get rid of it for good and in a
	non-backwards compatible way.
*/
void REMOTE_syscall(void) {} ;

/*
  _condor_dprintf_va is the real meat of dprintf().  We have different
  concerns inside the user job.  All we need to care about in here is
  making sure we have the right syscall mode.  Otherwise, we don't
  need to do anything complex with priv states, locking, etc.
*/
void
_condor_dprintf_va( int flags, const char* fmt, va_list args )
{
	int scm;
	int no_fd = FALSE;

		/* See if this is one of the messages we are logging */
	if( !(flags&DebugFlags) ) {
		return;
	}

		/* If dprintf() isn't initialized, don't seg fault */
	if( ! _condor_DebugFD ) {
		_condor_DebugFD = 2; /* stderr */
		no_fd = TRUE;
	}

		/*
		  When talking to the debug fd, you are talking to an fd that
		  is not visible to the user.  It is not entered in the
		  virtual file table, and, hence, you should be in unmapped
		  mode.
		*/
	scm = SetSyscalls( SYS_LOCAL | SYS_UNMAPPED );

		/* Actually print the message */
	_condor_vfprintf_va( _condor_DebugFD, fmt, args );

		/* Restore our syscall mode */
	(void) SetSyscalls( scm );

	if( no_fd ) {
		_condor_DebugFD = 0;
	}
}

int get_port_range(int is_outgoing, int *low_port, int *high_port)
{
	char *low = NULL, *high = NULL;

	// is_outgoing is ignored here.  all connections are assumed to be outgoing
	// since cedar should not be opening any listen sockets in the userjob.

	if ( (low = getenv("_condor_LOWPORT")) == NULL ) {
        dprintf(D_NETWORK, "_condor_LOWPORT undefined\n");
		return FALSE;
    }
	if ( (high = getenv("_condor_HIGHPORT")) == NULL ) {
        dprintf(D_ALWAYS, "_condor_LOWPORT is defined but _condor_HIGHPORT undefined!\n");
		return FALSE;
	}

	*low_port = atoi(low);
	*high_port = atoi(high);

	if(*low_port < 1024 || *high_port < 1024 || *low_port > *high_port) {
		dprintf(D_ALWAYS, "get_port_range - invalid LOWPORT(%d) \
		                   and/or HIGHPORT(%d)\n",
		                   *low_port, *high_port);
		return FALSE;
	}

	return TRUE;
}

int
_condor_bind_all_interfaces( void )
{
	char *tmp = NULL;
	int bind_all = FALSE;

	if( (tmp = getenv("_condor_BIND_ALL_INTERFACES")) == NULL ) {
        dprintf(D_NETWORK, "_condor_BIND_ALL_INTERFACES undefined\n");
		return TRUE;
    }

	switch( tmp[0] ) {
	case 'T':
	case 't':
	case 'Y':
	case 'y':
		bind_all = TRUE;
		break;
	default:
		bind_all = FALSE;
		break;
	}

	return bind_all;
}

struct hostent *
condor_gethostbyname( const char *name )
{
	return gethostbyname( name );
}

struct hostent *
condor_gethostbyaddr( const char *addr, SOCKET_LENGTH_TYPE len, int type )

{
	return gethostbyaddr( addr, len, type );
}

int
condor_gethostname( char *name, size_t namelen )
{
	return gethostname( name, namelen );
}

#if !defined(WIN32)
/*
  Can't open something because we are out of fd's.  Try to let
  somebody know what happened.  In the user job, we don't want to
  close a bunch of fds, since we'll loose our debug socket, which is
  always open.  In fact, we shouldn't have to close anything to be
  able to dprintf().  So, just dprintf(), flush the fd for good
  measure, and call Suicide() (so we don't leave the job queue).
*/
void
_condor_fd_panic( int line, const char* file )
{
	dprintf( D_ALWAYS,
			 "**** PANIC -- OUT OF FILE DESCRIPTORS at line %d in %s\n",
			 line, file );
	Suicide();
}
#endif /* ! LOOSE32 */

#if HAVE_EXT_GCB
int
GCB_local_bind(int fd, struct sockaddr *my_addr, socklen_t addrlen)
{
	return bind(fd, my_addr, addrlen);
}
#endif /* HAVE_EXT_GCB */

/* For MyString */
int vprintf_length(const char *format, va_list args) { return 0; }

} /* extern "C" */

/*
  We need our own definition of my_ip_addr(), which is used by
  Sock::bind() to support Condor on machines with multiple network
  interfaces.  This version, instead of looking in a config file for
  magic parameters, looks at the existing syscall_sock and grabs the
  IP address off of there.
*/
unsigned int
my_ip_addr()
{
	return syscall_sock->get_ip_int();
}

/*
  We need our own definition of my_ip_string(), which is used by the
  utilities in internet.c (which in turn are used by CEDAR).  This
  version, instead of looking in a config file for magic parameters,
  looks at the existing syscall_sock and grabs the IP address off of
  there.
*/
char*
my_ip_string()
{
	struct in_addr addr;
	memset( &addr, 0, sizeof(struct in_addr) );
	addr.s_addr = syscall_sock->get_ip_int();
	return inet_ntoa( addr );
}

std::vector<condor_sockaddr> resolve_hostname(const char* hostname) {
	std::vector<condor_sockaddr> ret;
	addrinfo* addrs = 0;
	int result;

	result = getaddrinfo(hostname, NULL, NULL, &addrs);
	if (result != 0 || !addrs) {
		return ret;
	}

	addrinfo* iter = addrs;
	while (iter) {
		ret.push_back(condor_sockaddr(iter->ai_addr));
		iter = iter->ai_next;
	}
	freeaddrinfo(addrs);

		// in order to completely eliminate duplicates, sort() should be
		// called before unique().

		// however, we do not need strict uniqueness here.
		// also, most of duplication comes from protocol variety.
		// e.g. same address with different socket type such as
		// SOCK_STREAM, SOCK_DGRAM
	std::vector<condor_sockaddr>::iterator it;
	it = std::unique(ret.begin(), ret.end());
	ret.resize(it - ret.begin());
	return ret;
}

std::vector<condor_sockaddr> resolve_hostname(const MyString& hostname) {
	return resolve_hostname(hostname.Value());
}
<|endoftext|>


<commit_before>/*
 * DesktopUpdateChecker.cpp
 *
 * Copyright (C) 2009-11 by RStudio, Inc.
 *
 * This program is licensed to you under the terms of version 3 of the
 * GNU Affero General Public License. This program is distributed WITHOUT
 * ANY EXPRESS OR IMPLIED WARRANTY, INCLUDING THOSE OF NON-INFRINGEMENT,
 * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Please refer to the
 * AGPL (http://www.gnu.org/licenses/agpl-3.0.txt) for more details.
 *
 */

#include "DesktopUpdateChecker.hpp"

#include <QDesktopServices>
#include <QMessageBox>

#include <core/Log.hpp>
#include <core/Error.hpp>

#include <core/http/Util.hpp>

#include "DesktopOptions.hpp"
#include "DesktopURLDownloader.hpp"
#include "DesktopUpdateAvailableDialog.hpp"

#include "config.h"

using namespace core;

namespace desktop {

QUrl UpdateChecker::checkForUpdatesURL()
{
   QUrl url("http://www.rstudio.org/links/check_for_update");
   url.addQueryItem("version", RSTUDIO_VERSION);
   return url;
}

void UpdateChecker::performCheck(bool manuallyInvoked)
{
   // build URL (specify key-value pair return)
   QUrl url = checkForUpdatesURL();
   url.addQueryItem("format", "kvp");

   // download manifest (URL downlader frees itself)
   URLDownloader* pURLDownloader = new URLDownloader(url,
                                                     10000,
                                                     manuallyInvoked,
                                                     pOwnerWindow_);
   connect(pURLDownloader, SIGNAL(downloadError(const QString&)),
           this, SLOT(manifestDownloadError(const QString&)));
   connect(pURLDownloader, SIGNAL(downloadComplete(const QByteArray&)),
           this, SLOT(manifestDownloadComplete(const QByteArray&)));
}

void UpdateChecker::manifestDownloadError(const QString &message)
{
   LOG_ERROR_MESSAGE("Error downloading manifest: " + message.toStdString());

   URLDownloader* pURLDownloader = qobject_cast<URLDownloader*>(sender());
   if (pURLDownloader && pURLDownloader->manuallyInvoked())
   {
      // WA_DeleteOnClose
      QMessageBox* pMsg = new QMessageBox(
            QMessageBox::Warning,
            "Error Checking for Updates",
            "An error occurred while checking for updates:\n\n"
            + message,
            QMessageBox::Ok,
            pOwnerWindow_,
            Qt::Sheet | Qt::Dialog | Qt::MSWindowsFixedSizeDialogHint);
      pMsg->setWindowModality(Qt::WindowModal);
      pMsg->setAttribute(Qt::WA_DeleteOnClose);
      pMsg->show();
   }
}

void UpdateChecker::manifestDownloadComplete(const QByteArray& data)
{
   // parse manifest
   std::string manifest(data.constData(), data.size());
   http::Fields fields;
   http::util::parseForm(manifest, &fields);

   // get the list of ignored updates
   QStringList ignoredVersions = options().ignoredUpdateVersions();

   // is there an update which we haven't already chosen to ignore?
   std::string stdUpdateVersion = http::util::fieldValue(fields, "update-version");
   QString updateVersion = QString::fromStdString(stdUpdateVersion);
   if ( (updateVersion.size() > 0) && !ignoredVersions.contains(updateVersion))
   {
      // get update info
      std::string updateURL = http::util::fieldValue(fields, "update-url");
      std::string updateMessage = http::util::fieldValue(fields, "update-message");
      int isUrgent = http::util::fieldValue<int>(fields, "update-urgent", 0);
      DesktopUpdateInfo updateInfo;
      updateInfo.currentVersion = RSTUDIO_VERSION;
      updateInfo.updatedVersion = updateVersion;
      updateInfo.updateURL = QString::fromStdString(updateURL);
      updateInfo.updateMessage = QString::fromStdString(updateMessage);
      updateInfo.isUrgent = isUrgent != 0;

      // invoke dialog
      DesktopUpdateAvailableDialog dialog(updateInfo, pOwnerWindow_);
      int result = dialog.exec();

      // record if we are permanently ignoring
      switch (result)
      {
      case DesktopUpdateAvailableDialog::Accepted:
         QDesktopServices::openUrl(QUrl(updateInfo.updateURL));
         break;
      case DesktopUpdateAvailableDialog::Rejected:
         break;
      case DesktopUpdateAvailableDialog::Ignored:
         ignoredVersions.append(updateVersion);
         options().setIgnoredUpdateVersions(ignoredVersions);
         break;
      }
   }
   else
   {
      URLDownloader* pURLDownloader = qobject_cast<URLDownloader*>(sender());
      if (pURLDownloader && pURLDownloader->manuallyInvoked())
      {
         // WA_DeleteOnClose
         QMessageBox* pMsg = new QMessageBox(
               QMessageBox::Warning,
               "No Update Available",
               "You're using the newest version of RStudio.",
               QMessageBox::Ok,
               pOwnerWindow_,
               Qt::Sheet | Qt::Dialog | Qt::MSWindowsFixedSizeDialogHint);
         pMsg->setWindowModality(Qt::WindowModal);
         pMsg->setAttribute(Qt::WA_DeleteOnClose);
         pMsg->show();
      }
   }
}

} // namespace desktop
<commit_msg>Don't ignore any versions when Check For Updates is manually invoked<commit_after>/*
 * DesktopUpdateChecker.cpp
 *
 * Copyright (C) 2009-11 by RStudio, Inc.
 *
 * This program is licensed to you under the terms of version 3 of the
 * GNU Affero General Public License. This program is distributed WITHOUT
 * ANY EXPRESS OR IMPLIED WARRANTY, INCLUDING THOSE OF NON-INFRINGEMENT,
 * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Please refer to the
 * AGPL (http://www.gnu.org/licenses/agpl-3.0.txt) for more details.
 *
 */

#include "DesktopUpdateChecker.hpp"

#include <QDesktopServices>
#include <QMessageBox>

#include <core/Log.hpp>
#include <core/Error.hpp>

#include <core/http/Util.hpp>

#include "DesktopOptions.hpp"
#include "DesktopURLDownloader.hpp"
#include "DesktopUpdateAvailableDialog.hpp"

#include "config.h"

using namespace core;

namespace desktop {

QUrl UpdateChecker::checkForUpdatesURL()
{
   QUrl url("http://www.rstudio.org/links/check_for_update");
   url.addQueryItem("version", RSTUDIO_VERSION);
   return url;
}

void UpdateChecker::performCheck(bool manuallyInvoked)
{
   // build URL (specify key-value pair return)
   QUrl url = checkForUpdatesURL();
   url.addQueryItem("format", "kvp");

   // download manifest (URL downlader frees itself)
   URLDownloader* pURLDownloader = new URLDownloader(url,
                                                     10000,
                                                     manuallyInvoked,
                                                     pOwnerWindow_);
   connect(pURLDownloader, SIGNAL(downloadError(const QString&)),
           this, SLOT(manifestDownloadError(const QString&)));
   connect(pURLDownloader, SIGNAL(downloadComplete(const QByteArray&)),
           this, SLOT(manifestDownloadComplete(const QByteArray&)));
}

void UpdateChecker::manifestDownloadError(const QString &message)
{
   LOG_ERROR_MESSAGE("Error downloading manifest: " + message.toStdString());

   URLDownloader* pURLDownloader = qobject_cast<URLDownloader*>(sender());
   if (pURLDownloader && pURLDownloader->manuallyInvoked())
   {
      // WA_DeleteOnClose
      QMessageBox* pMsg = new QMessageBox(
            QMessageBox::Warning,
            "Error Checking for Updates",
            "An error occurred while checking for updates:\n\n"
            + message,
            QMessageBox::Ok,
            pOwnerWindow_,
            Qt::Sheet | Qt::Dialog | Qt::MSWindowsFixedSizeDialogHint);
      pMsg->setWindowModality(Qt::WindowModal);
      pMsg->setAttribute(Qt::WA_DeleteOnClose);
      pMsg->show();
   }
}

void UpdateChecker::manifestDownloadComplete(const QByteArray& data)
{
   // parse manifest
   std::string manifest(data.constData(), data.size());
   http::Fields fields;
   http::util::parseForm(manifest, &fields);

   // get the list of ignored updates
   QStringList ignoredVersions = options().ignoredUpdateVersions();

   URLDownloader* pURLDownloader = qobject_cast<URLDownloader*>(sender());

   // is there an update which we haven't already chosen to ignore?
   std::string stdUpdateVersion = http::util::fieldValue(fields, "update-version");
   QString updateVersion = QString::fromStdString(stdUpdateVersion);
   if ( (updateVersion.size() > 0) &&
        (!ignoredVersions.contains(updateVersion) || pURLDownloader->manuallyInvoked()) )
   {
      // get update info
      std::string updateURL = http::util::fieldValue(fields, "update-url");
      std::string updateMessage = http::util::fieldValue(fields, "update-message");
      int isUrgent = http::util::fieldValue<int>(fields, "update-urgent", 0);
      DesktopUpdateInfo updateInfo;
      updateInfo.currentVersion = RSTUDIO_VERSION;
      updateInfo.updatedVersion = updateVersion;
      updateInfo.updateURL = QString::fromStdString(updateURL);
      updateInfo.updateMessage = QString::fromStdString(updateMessage);
      updateInfo.isUrgent = isUrgent != 0;

      // invoke dialog
      DesktopUpdateAvailableDialog dialog(updateInfo, pOwnerWindow_);
      int result = dialog.exec();

      // record if we are permanently ignoring
      switch (result)
      {
      case DesktopUpdateAvailableDialog::Accepted:
         QDesktopServices::openUrl(QUrl(updateInfo.updateURL));
         break;
      case DesktopUpdateAvailableDialog::Rejected:
         break;
      case DesktopUpdateAvailableDialog::Ignored:
         ignoredVersions.append(updateVersion);
         options().setIgnoredUpdateVersions(ignoredVersions);
         break;
      }
   }
   else
   {
      if (pURLDownloader && pURLDownloader->manuallyInvoked())
      {
         // WA_DeleteOnClose
         QMessageBox* pMsg = new QMessageBox(
               QMessageBox::Warning,
               "No Update Available",
               "You're using the newest version of RStudio.",
               QMessageBox::Ok,
               pOwnerWindow_,
               Qt::Sheet | Qt::Dialog | Qt::MSWindowsFixedSizeDialogHint);
         pMsg->setWindowModality(Qt::WindowModal);
         pMsg->setAttribute(Qt::WA_DeleteOnClose);
         pMsg->show();
      }
   }
}

} // namespace desktop
<|endoftext|>


<commit_before>#include "PaxosProposer.h"
#include "System/Events/EventLoop.h"
#include "Framework/Replication/ReplicationConfig.h"

PaxosProposer::~PaxosProposer()
{
    delete vote;
}

void PaxosProposer::Init(QuorumContext* context_)
{
    context = context_;

    prepareTimeout.SetCallable(MFUNC(PaxosProposer, OnPrepareTimeout));
    prepareTimeout.SetDelay(PAXOS_ROUND_TIMEOUT);
    proposeTimeout.SetCallable(MFUNC(PaxosProposer, OnProposeTimeout));
    proposeTimeout.SetDelay(PAXOS_ROUND_TIMEOUT);
    restartTimeout.SetCallable(MFUNC(PaxosProposer, OnRestartTimeout));
    restartTimeout.SetDelay(PAXOS_RESTART_TIMEOUT);

    vote = NULL;
    state.Init();
}

void PaxosProposer::RemoveTimers()
{
    if (prepareTimeout.IsActive())
        EventLoop::Remove(&prepareTimeout);

    if (proposeTimeout.IsActive())
        EventLoop::Remove(&proposeTimeout);

    if (restartTimeout.IsActive())
        EventLoop::Remove(&restartTimeout);
}

void PaxosProposer::SetUseTimeouts(bool useTimeouts_)
{
    useTimeouts = useTimeouts_;
}

void PaxosProposer::OnPrepareResponse(PaxosMessage& imsg)
{
    Log_Trace("msg.nodeID = %u", imsg.nodeID);

    if (!state.preparing || imsg.proposalID != state.proposalID)
        return;

    if (imsg.type == PAXOS_PREPARE_REJECTED)
        vote->RegisterRejected(imsg.nodeID);
    else
        vote->RegisterAccepted(imsg.nodeID);

    if (imsg.type == PAXOS_PREPARE_REJECTED)
    {
        Log_Debug("Prepare rejected");
        if (imsg.promisedProposalID > state.highestPromisedProposalID)
            state.highestPromisedProposalID = imsg.promisedProposalID;
    }
    else if (imsg.type == PAXOS_PREPARE_PREVIOUSLY_ACCEPTED &&
             imsg.acceptedProposalID >= state.highestReceivedProposalID)
    {
        /* the >= could be replaced by > which would result in less copys
         * however this would result in complications in multi paxos
         * in the multi paxos steady state this branch is inactive
         * it only runs after leader failure
         * so it's ok
         */
        state.highestReceivedProposalID = imsg.acceptedProposalID;
        state.proposedRunID = imsg.runID;
        ASSERT(imsg.value.GetLength() > 0);
        state.proposedValue.Write(imsg.value);
    }

    if (vote->IsRejected())
    {
        StopPreparing();
        EventLoop::Add(&restartTimeout);
    }
    else if (vote->IsAccepted())
        StartProposing();
}

void PaxosProposer::OnProposeResponse(PaxosMessage& imsg)
{
    PaxosMessage omsg;

    Log_Trace("msg.nodeID = %u", imsg.nodeID);

    if (!state.proposing || imsg.proposalID != state.proposalID)
        return;

    if (imsg.type == PAXOS_PROPOSE_REJECTED)
    {
        Log_Debug("Propose rejected");
        vote->RegisterRejected(imsg.nodeID);
    }
    else
        vote->RegisterAccepted(imsg.nodeID);

    if (vote->IsRejected())
    {
        StopProposing();
        EventLoop::Add(&restartTimeout);
    }
    else if (vote->IsAccepted())
    {
        // a majority have accepted our proposal, we have consensus
        StopProposing();
        omsg.LearnProposal(context->GetPaxosID(), MY_NODEID, state.proposalID);
        BroadcastMessage(omsg);
    }
}

void PaxosProposer::Propose(Buffer& value)
{
    Log_Trace();

    if (IsActive())
        ASSERT_FAIL();

    state.proposedRunID = REPLICATION_CONFIG->GetRunID();
    ASSERT(value.GetLength() > 0);
    state.proposedValue.Write(value);

    if (state.multi && state.numProposals == 0)
    {
        state.numProposals++;
        StartProposing();
    }
    else
        StartPreparing();
}

void PaxosProposer::Restart()
{
    Timer* timer;

    if (!state.preparing && !state.proposing)
        return;

    if (state.preparing)
        timer = &prepareTimeout;
    else
        timer = &proposeTimeout;

    EventLoop::Remove(timer);

    if (context->IsPaxosBlocked())
    {
        if (useTimeouts)
            EventLoop::Add(timer);
        return;
    }

    StartPreparing();
}

void PaxosProposer::Stop()
{
    state.proposedRunID = 0;
    state.proposedValue.Clear();
    state.preparing = false;
    state.proposing = false;
    state.multi = false;
    EventLoop::Remove(&prepareTimeout);
    EventLoop::Remove(&proposeTimeout);
    EventLoop::Remove(&restartTimeout);
}

bool PaxosProposer::IsActive()
{
    return (state.preparing || state.proposing || restartTimeout.IsActive());
}

uint64_t PaxosProposer::GetMemoryUsage()
{
    return sizeof(PaxosProposer) + state.proposedValue.GetSize();
}

void PaxosProposer::OnPrepareTimeout()
{
    Log_Debug("OnPrepareTimeout");
    Log_Trace();

    ASSERT(state.preparing);

    if (context->IsPaxosBlocked())
    {
        EventLoop::Add(&prepareTimeout);
        return;
    }

    if (useTimeouts || vote->IsRejected())
        StartPreparing();
    else
        EventLoop::Add(&prepareTimeout);
}

void PaxosProposer::OnProposeTimeout()
{
    Log_Debug("OnProposeTimeout");
    Log_Trace();

    ASSERT(state.proposing);

    if (context->IsPaxosBlocked())
    {
        EventLoop::Add(&proposeTimeout);
        return;
    }

    if (useTimeouts || vote->IsRejected())
        StartPreparing();
    else
        EventLoop::Add(&proposeTimeout);
}

void PaxosProposer::OnRestartTimeout()
{
    Log_Debug("OnRestartTimeout");
    Log_Trace();

    ASSERT(!state.preparing);
    ASSERT(!state.proposing);
    ASSERT(!prepareTimeout.IsActive());
    ASSERT(!proposeTimeout.IsActive());

    if (context->IsPaxosBlocked())
    {
        EventLoop::Add(&restartTimeout);
        return;
    }

    if (useTimeouts)
        StartPreparing();
    else
        EventLoop::Add(&restartTimeout);
}

void PaxosProposer::BroadcastMessage(PaxosMessage& omsg)
{
    Log_Trace();

    vote->Reset();
    context->GetTransport()->BroadcastMessage(omsg);
}

void PaxosProposer::StopPreparing()
{
    Log_Trace();

    state.preparing = false;
    EventLoop::Remove(&prepareTimeout);
}

void PaxosProposer::StopProposing()
{
    Log_Trace();

    state.proposing = false;
    EventLoop::Remove(&proposeTimeout);
}

void PaxosProposer::StartPreparing()
{
    PaxosMessage omsg;

    Log_Trace();

    StopProposing();

    NewVote();
    state.preparing = true;
    state.numProposals++;
    state.proposalID = REPLICATION_CONFIG->NextProposalID(MAX(state.proposalID, state.highestPromisedProposalID));
    state.highestReceivedProposalID = 0;

    omsg.PrepareRequest(context->GetPaxosID(), MY_NODEID, state.proposalID);
    BroadcastMessage(omsg);

    if (restartTimeout.IsActive())
        EventLoop::Remove(&restartTimeout);
    EventLoop::Reset(&prepareTimeout);
}

void PaxosProposer::StartProposing()
{
    PaxosMessage omsg;

    Log_Trace();

    StopPreparing();

    NewVote();
    state.proposing = true;

    ASSERT(state.proposedValue.GetLength() > 0);
    omsg.ProposeRequest(context->GetPaxosID(), MY_NODEID, state.proposalID,
     state.proposedRunID, state.proposedValue);
    BroadcastMessage(omsg);

    if (restartTimeout.IsActive())
        EventLoop::Remove(&restartTimeout);
    EventLoop::Reset(&proposeTimeout);
}

void PaxosProposer::NewVote()
{
    delete vote;
    vote = context->GetQuorum()->NewVote();
}
<commit_msg>Added debug logging to PaxosProposer.<commit_after>#include "PaxosProposer.h"
#include "System/Events/EventLoop.h"
#include "Framework/Replication/ReplicationConfig.h"

PaxosProposer::~PaxosProposer()
{
    delete vote;
}

void PaxosProposer::Init(QuorumContext* context_)
{
    context = context_;

    prepareTimeout.SetCallable(MFUNC(PaxosProposer, OnPrepareTimeout));
    prepareTimeout.SetDelay(PAXOS_ROUND_TIMEOUT);
    proposeTimeout.SetCallable(MFUNC(PaxosProposer, OnProposeTimeout));
    proposeTimeout.SetDelay(PAXOS_ROUND_TIMEOUT);
    restartTimeout.SetCallable(MFUNC(PaxosProposer, OnRestartTimeout));
    restartTimeout.SetDelay(PAXOS_RESTART_TIMEOUT);

    vote = NULL;
    state.Init();
}

void PaxosProposer::RemoveTimers()
{
    if (prepareTimeout.IsActive())
        EventLoop::Remove(&prepareTimeout);

    if (proposeTimeout.IsActive())
        EventLoop::Remove(&proposeTimeout);

    if (restartTimeout.IsActive())
        EventLoop::Remove(&restartTimeout);
}

void PaxosProposer::SetUseTimeouts(bool useTimeouts_)
{
    useTimeouts = useTimeouts_;
}

void PaxosProposer::OnPrepareResponse(PaxosMessage& imsg)
{
    Log_Trace("msg.nodeID = %u", imsg.nodeID);

    if (!state.preparing || imsg.proposalID != state.proposalID)
        return;

    if (imsg.type == PAXOS_PREPARE_REJECTED)
        vote->RegisterRejected(imsg.nodeID);
    else
        vote->RegisterAccepted(imsg.nodeID);

    if (imsg.type == PAXOS_PREPARE_REJECTED)
    {
        Log_Debug("Prepare rejected, quorumID: %U", context->GetQuorumID());
        if (imsg.promisedProposalID > state.highestPromisedProposalID)
            state.highestPromisedProposalID = imsg.promisedProposalID;
    }
    else if (imsg.type == PAXOS_PREPARE_PREVIOUSLY_ACCEPTED &&
             imsg.acceptedProposalID >= state.highestReceivedProposalID)
    {
        /* the >= could be replaced by > which would result in less copys
         * however this would result in complications in multi paxos
         * in the multi paxos steady state this branch is inactive
         * it only runs after leader failure
         * so it's ok
         */
        state.highestReceivedProposalID = imsg.acceptedProposalID;
        state.proposedRunID = imsg.runID;
        ASSERT(imsg.value.GetLength() > 0);
        state.proposedValue.Write(imsg.value);
    }

    if (vote->IsRejected())
    {
        StopPreparing();
        EventLoop::Add(&restartTimeout);
    }
    else if (vote->IsAccepted())
        StartProposing();
}

void PaxosProposer::OnProposeResponse(PaxosMessage& imsg)
{
    PaxosMessage omsg;

    Log_Trace("msg.nodeID = %u", imsg.nodeID);

    if (!state.proposing || imsg.proposalID != state.proposalID)
        return;

    if (imsg.type == PAXOS_PROPOSE_REJECTED)
    {
        Log_Debug("Propose rejected, quorumID: %U", context->GetQuorumID());
        vote->RegisterRejected(imsg.nodeID);
    }
    else
        vote->RegisterAccepted(imsg.nodeID);

    if (vote->IsRejected())
    {
        StopProposing();
        EventLoop::Add(&restartTimeout);
    }
    else if (vote->IsAccepted())
    {
        // a majority have accepted our proposal, we have consensus
        StopProposing();
        omsg.LearnProposal(context->GetPaxosID(), MY_NODEID, state.proposalID);
        BroadcastMessage(omsg);
    }
}

void PaxosProposer::Propose(Buffer& value)
{
    Log_Trace();

    if (IsActive())
        ASSERT_FAIL();

    state.proposedRunID = REPLICATION_CONFIG->GetRunID();
    ASSERT(value.GetLength() > 0);
    state.proposedValue.Write(value);

    if (state.multi && state.numProposals == 0)
    {
        state.numProposals++;
        StartProposing();
    }
    else
        StartPreparing();
}

void PaxosProposer::Restart()
{
    Timer* timer;

    if (!state.preparing && !state.proposing)
        return;

    if (state.preparing)
        timer = &prepareTimeout;
    else
        timer = &proposeTimeout;

    EventLoop::Remove(timer);

    if (context->IsPaxosBlocked())
    {
        if (useTimeouts)
            EventLoop::Add(timer);
        return;
    }

    StartPreparing();
}

void PaxosProposer::Stop()
{
    state.proposedRunID = 0;
    state.proposedValue.Clear();
    state.preparing = false;
    state.proposing = false;
    state.multi = false;
    EventLoop::Remove(&prepareTimeout);
    EventLoop::Remove(&proposeTimeout);
    EventLoop::Remove(&restartTimeout);
}

bool PaxosProposer::IsActive()
{
    return (state.preparing || state.proposing || restartTimeout.IsActive());
}

uint64_t PaxosProposer::GetMemoryUsage()
{
    return sizeof(PaxosProposer) + state.proposedValue.GetSize();
}

void PaxosProposer::OnPrepareTimeout()
{
    Log_Debug("OnPrepareTimeout, quorumID: %U", context->GetQuorumID());
    Log_Trace();

    ASSERT(state.preparing);

    if (context->IsPaxosBlocked())
    {
        EventLoop::Add(&prepareTimeout);
        return;
    }

    if (useTimeouts || vote->IsRejected())
        StartPreparing();
    else
        EventLoop::Add(&prepareTimeout);
}

void PaxosProposer::OnProposeTimeout()
{
    Log_Debug("OnProposeTimeout, quorumID: %U", context->GetQuorumID());
    Log_Trace();

    ASSERT(state.proposing);

    if (context->IsPaxosBlocked())
    {
        EventLoop::Add(&proposeTimeout);
        return;
    }

    if (useTimeouts || vote->IsRejected())
        StartPreparing();
    else
        EventLoop::Add(&proposeTimeout);
}

void PaxosProposer::OnRestartTimeout()
{
    Log_Debug("OnRestartTimeout, quorumID: %U", context->GetQuorumID());
    Log_Trace();

    ASSERT(!state.preparing);
    ASSERT(!state.proposing);
    ASSERT(!prepareTimeout.IsActive());
    ASSERT(!proposeTimeout.IsActive());

    if (context->IsPaxosBlocked())
    {
        EventLoop::Add(&restartTimeout);
        return;
    }

    if (useTimeouts)
        StartPreparing();
    else
        EventLoop::Add(&restartTimeout);
}

void PaxosProposer::BroadcastMessage(PaxosMessage& omsg)
{
    Log_Trace();

    vote->Reset();
    context->GetTransport()->BroadcastMessage(omsg);
}

void PaxosProposer::StopPreparing()
{
    Log_Trace();

    state.preparing = false;
    EventLoop::Remove(&prepareTimeout);
}

void PaxosProposer::StopProposing()
{
    Log_Trace();

    state.proposing = false;
    EventLoop::Remove(&proposeTimeout);
}

void PaxosProposer::StartPreparing()
{
    PaxosMessage omsg;

    Log_Trace();

    StopProposing();

    NewVote();
    state.preparing = true;
    state.numProposals++;
    state.proposalID = REPLICATION_CONFIG->NextProposalID(MAX(state.proposalID, state.highestPromisedProposalID));
    state.highestReceivedProposalID = 0;

    omsg.PrepareRequest(context->GetPaxosID(), MY_NODEID, state.proposalID);
    BroadcastMessage(omsg);

    if (restartTimeout.IsActive())
        EventLoop::Remove(&restartTimeout);
    EventLoop::Reset(&prepareTimeout);
}

void PaxosProposer::StartProposing()
{
    PaxosMessage omsg;

    Log_Trace();

    StopPreparing();

    NewVote();
    state.proposing = true;

    ASSERT(state.proposedValue.GetLength() > 0);
    omsg.ProposeRequest(context->GetPaxosID(), MY_NODEID, state.proposalID,
     state.proposedRunID, state.proposedValue);
    BroadcastMessage(omsg);

    if (restartTimeout.IsActive())
        EventLoop::Remove(&restartTimeout);
    EventLoop::Reset(&proposeTimeout);
}

void PaxosProposer::NewVote()
{
    delete vote;
    vote = context->GetQuorum()->NewVote();
}
<|endoftext|>


<commit_before>#include "vlc_video_source.h"
#include <cstdio>
#include <cstdlib>
#include <chrono>
#include <thread>

namespace gg
{

VideoSourceVLC::VideoSourceVLC(const std::string path)
    : _vlc_inst(nullptr)
    , _vlc_mp(nullptr)
    , _video_buffer(nullptr)
    , _data_length(0)
    , _cols(0)
    , _rows(0)
    , _sub(nullptr)
    , _path(path)
{
    this->init_vlc();
    this->run_vlc();
}

VideoSourceVLC::~VideoSourceVLC()
{
    stop_vlc();
    release_vlc();
}

bool VideoSourceVLC::get_frame_dimensions(int & width, int & height)
{
    ///\todo mutex

    if(this->_cols == 0 || this->_rows == 0)
        return false;

    width = this->_cols;
    height = this->_rows;
    return true;
}

bool VideoSourceVLC::get_frame(VideoFrame_BGRA & frame)
{
    throw VideoSourceError("VLC video source supports only I420 colour space");

    // TODO

    ///\todo mutex

    if (_cols == 0 || _rows == 0 || _video_buffer == nullptr)
        return false;

    // allocate and fill the image
    if (_cols * _rows * 4 == this->_data_length)
        frame = VideoFrame_BGRA(this->_video_buffer, this->_cols, this->_rows);
    else
        throw VideoSourceError("VLC video source does not support padded images");

    return true;
}

bool VideoSourceVLC::get_frame(VideoFrame_I420 & frame)
{
    if (_data_length > 0)
    {
        // TODO manage data?
        frame = VideoFrame_I420(_video_buffer, _data_length, _cols, _rows, false);
        return true;
    }
    else
        return false;

    // TODO #86
}

double VideoSourceVLC::get_frame_rate()
{
    //return libvlc_media_player_get_rate( m_mp );
    return libvlc_media_player_get_fps(_vlc_mp);
    //throw std::runtime_error("get_frame_rate to be implemented");
    //return 0.0;
}

void VideoSourceVLC::set_sub_frame(int x, int y, int width, int height)
{
    // TODO mutex?

    if (x >= _full.x and x + width <= _full.x + _full.width and
        y >= _full.y and y + height <= _full.y + _full.height)
    {
        stop_vlc();
        release_vlc();
        if (_sub == nullptr) _sub = new FrameBox;
        _sub->x = x;
        _sub->y = y;
        _sub->width = width;
        _sub->height = height;
        init_vlc();
        run_vlc();
    }
}

void VideoSourceVLC::get_full_frame()
{
    // TODO mutex?
    stop_vlc();
    release_vlc();
    init_vlc();
    run_vlc();
}

void VideoSourceVLC::init_vlc()
{
    // VLC pointers
    libvlc_media_t * vlc_media = nullptr;

    // VLC options
    char smem_options[512];

    sprintf(smem_options, "#");
    if (_sub != nullptr)
    {
        unsigned int croptop = _sub->y,
                     cropbottom = _full.height - (_sub->y + _sub->height),
                     cropleft = _sub->x,
                     cropright = _full.width - (_sub->x + _sub->width);
        sprintf(smem_options,
                "%stranscode{vcodec=I420,vfilter=croppadd{",
                smem_options);
        sprintf(smem_options,
                "%scroptop=%u,cropbottom=%u,cropleft=%u,cropright=%u}}:",
                smem_options,
                croptop, cropbottom, cropleft, cropright);
    }
    sprintf(smem_options,
            "%ssmem{video-data=%lld,video-prerender-callback=%lld,video-postrender-callback=%lld}",
            smem_options,
            (long long int)(intptr_t)(void*) this,
            (long long int)(intptr_t)(void*) &VideoSourceVLC::prepareRender,
            (long long int)(intptr_t)(void*) &VideoSourceVLC::handleStream );

    const char * const vlc_args[] = {
        "-I", "dummy", // Don't use any interface
        "--ignore-config", // Don't use VLC's config
        "--extraintf=logger", // Log anything
        // TODO - what about the options below?
        //"--verbose=2", // Be much more verbose then normal for debugging purpose
        //"--clock-jitter=0",
        //"--file-caching=150",
        "--no-audio",
        "--sout", smem_options // Stream to memory
    };

    // We launch VLC
    _vlc_inst = libvlc_new(sizeof(vlc_args) / sizeof(vlc_args[0]), vlc_args);
    if (_vlc_inst == nullptr)
        throw VideoSourceError("Could not create VLC engine");

    // If path contains a colon (:), it will be treated as a
    // URL. Else, it will be considered as a local path.
    if (_path.find(":") == std::string::npos)
        vlc_media = libvlc_media_new_path(_vlc_inst, _path.c_str());
    else
        vlc_media = libvlc_media_new_location(_vlc_inst, _path.c_str());
    if (vlc_media == nullptr)
        throw VideoSourceError(std::string("Could not open ").append(_path));

    libvlc_media_add_option(vlc_media, ":noaudio");
    libvlc_media_add_option(vlc_media, ":no-video-title-show");

    // Create a media player playing environement
    _vlc_mp = libvlc_media_player_new_from_media(vlc_media);
    if (_vlc_mp == nullptr)
        throw VideoSourceError("Could not create VLC media player");

    // No need to keep the media now
    libvlc_media_release( vlc_media );
}

void VideoSourceVLC::run_vlc()
{
    // play the media_player
    if (libvlc_media_player_play(_vlc_mp) != 0)
        throw VideoSourceError("Could not start VLC media player");

    // empirically determined value that allows for initialisation
    // to succeed before any API functions are called on this object
    std::this_thread::sleep_for(std::chrono::milliseconds(350));
    unsigned int width, height;
    if (libvlc_video_get_size(_vlc_mp, 0, &width, &height) != 0)
        throw VideoSourceError("Could not get video dimensions");

    _full.x = 0;
    _full.y = 0;
    _full.width = width;
    _full.height = height;
}

void VideoSourceVLC::stop_vlc()
{
    // stop playing
    libvlc_media_player_stop(_vlc_mp);
}

void VideoSourceVLC::release_vlc()
{
    // free media player
    libvlc_media_player_release(_vlc_mp);

    // free engine
    libvlc_release(_vlc_inst);

    // free buffer
    if (_video_buffer != nullptr)
        delete[] _video_buffer;
    _data_length = 0;
    _cols = 0;
    _rows = 0;

    // free sub-frame
    if (_sub != nullptr)
    {
        delete _sub;
        _sub = nullptr;
    }
}

void VideoSourceVLC::prepareRender(VideoSourceVLC * p_video_data,
                                   uint8_t ** pp_pixel_buffer,
                                   size_t size)
{
    ///\todo create mutex guard

    unsigned int width, height;
    if (libvlc_video_get_size(p_video_data->_vlc_mp, 0, &width, &height) != 0)
        return;
    p_video_data->_cols = width;
    p_video_data->_rows = height;

    if (size > p_video_data->_data_length)
        p_video_data->_video_buffer = reinterpret_cast<uint8_t *>(
                    realloc(p_video_data->_video_buffer, size * sizeof(uint8_t))
                    );
    p_video_data->_data_length = size;

    *pp_pixel_buffer = p_video_data->_video_buffer;
}

void VideoSourceVLC::handleStream(VideoSourceVLC * p_video_data,
                                  uint8_t * p_pixel_buffer,
                                  size_t cols,
                                  size_t rows,
                                  size_t colour_depth,
                                  size_t size)
{
    // TODO: explain how data should be handled (see #86)
    // TODO: Unlock the mutex
}

}
<commit_msg>Issue #83: selectively using malloc and realloc based on data length, and also getting width and height in handleStream rather than prepareRender<commit_after>#include "vlc_video_source.h"
#include <cstdio>
#include <cstdlib>
#include <chrono>
#include <thread>

namespace gg
{

VideoSourceVLC::VideoSourceVLC(const std::string path)
    : _vlc_inst(nullptr)
    , _vlc_mp(nullptr)
    , _video_buffer(nullptr)
    , _data_length(0)
    , _cols(0)
    , _rows(0)
    , _sub(nullptr)
    , _path(path)
{
    this->init_vlc();
    this->run_vlc();
}

VideoSourceVLC::~VideoSourceVLC()
{
    stop_vlc();
    release_vlc();
}

bool VideoSourceVLC::get_frame_dimensions(int & width, int & height)
{
    ///\todo mutex

    if(this->_cols == 0 || this->_rows == 0)
        return false;

    width = this->_cols;
    height = this->_rows;
    return true;
}

bool VideoSourceVLC::get_frame(VideoFrame_BGRA & frame)
{
    throw VideoSourceError("VLC video source supports only I420 colour space");

    // TODO

    ///\todo mutex

    if (_cols == 0 || _rows == 0 || _video_buffer == nullptr)
        return false;

    // allocate and fill the image
    if (_cols * _rows * 4 == this->_data_length)
        frame = VideoFrame_BGRA(this->_video_buffer, this->_cols, this->_rows);
    else
        throw VideoSourceError("VLC video source does not support padded images");

    return true;
}

bool VideoSourceVLC::get_frame(VideoFrame_I420 & frame)
{
    if (_data_length > 0)
    {
        // TODO manage data?
        frame = VideoFrame_I420(_video_buffer, _data_length, _cols, _rows, false);
        return true;
    }
    else
        return false;

    // TODO #86
}

double VideoSourceVLC::get_frame_rate()
{
    //return libvlc_media_player_get_rate( m_mp );
    return libvlc_media_player_get_fps(_vlc_mp);
    //throw std::runtime_error("get_frame_rate to be implemented");
    //return 0.0;
}

void VideoSourceVLC::set_sub_frame(int x, int y, int width, int height)
{
    // TODO mutex?

    if (x >= _full.x and x + width <= _full.x + _full.width and
        y >= _full.y and y + height <= _full.y + _full.height)
    {
        stop_vlc();
        release_vlc();
        if (_sub == nullptr) _sub = new FrameBox;
        _sub->x = x;
        _sub->y = y;
        _sub->width = width;
        _sub->height = height;
        init_vlc();
        run_vlc();
    }
}

void VideoSourceVLC::get_full_frame()
{
    // TODO mutex?
    stop_vlc();
    release_vlc();
    init_vlc();
    run_vlc();
}

void VideoSourceVLC::init_vlc()
{
    // VLC pointers
    libvlc_media_t * vlc_media = nullptr;

    // VLC options
    char smem_options[512];

    sprintf(smem_options, "#");
    if (_sub != nullptr)
    {
        unsigned int croptop = _sub->y,
                     cropbottom = _full.height - (_sub->y + _sub->height),
                     cropleft = _sub->x,
                     cropright = _full.width - (_sub->x + _sub->width);
        sprintf(smem_options,
                "%stranscode{vcodec=I420,vfilter=croppadd{",
                smem_options);
        sprintf(smem_options,
                "%scroptop=%u,cropbottom=%u,cropleft=%u,cropright=%u}}:",
                smem_options,
                croptop, cropbottom, cropleft, cropright);
    }
    sprintf(smem_options,
            "%ssmem{video-data=%lld,video-prerender-callback=%lld,video-postrender-callback=%lld}",
            smem_options,
            (long long int)(intptr_t)(void*) this,
            (long long int)(intptr_t)(void*) &VideoSourceVLC::prepareRender,
            (long long int)(intptr_t)(void*) &VideoSourceVLC::handleStream );

    const char * const vlc_args[] = {
        "-I", "dummy", // Don't use any interface
        "--ignore-config", // Don't use VLC's config
        "--extraintf=logger", // Log anything
        // TODO - what about the options below?
        //"--verbose=2", // Be much more verbose then normal for debugging purpose
        //"--clock-jitter=0",
        //"--file-caching=150",
        "--no-audio",
        "--sout", smem_options // Stream to memory
    };

    // We launch VLC
    _vlc_inst = libvlc_new(sizeof(vlc_args) / sizeof(vlc_args[0]), vlc_args);
    if (_vlc_inst == nullptr)
        throw VideoSourceError("Could not create VLC engine");

    // If path contains a colon (:), it will be treated as a
    // URL. Else, it will be considered as a local path.
    if (_path.find(":") == std::string::npos)
        vlc_media = libvlc_media_new_path(_vlc_inst, _path.c_str());
    else
        vlc_media = libvlc_media_new_location(_vlc_inst, _path.c_str());
    if (vlc_media == nullptr)
        throw VideoSourceError(std::string("Could not open ").append(_path));

    libvlc_media_add_option(vlc_media, ":noaudio");
    libvlc_media_add_option(vlc_media, ":no-video-title-show");

    // Create a media player playing environement
    _vlc_mp = libvlc_media_player_new_from_media(vlc_media);
    if (_vlc_mp == nullptr)
        throw VideoSourceError("Could not create VLC media player");

    // No need to keep the media now
    libvlc_media_release( vlc_media );
}

void VideoSourceVLC::run_vlc()
{
    // play the media_player
    if (libvlc_media_player_play(_vlc_mp) != 0)
        throw VideoSourceError("Could not start VLC media player");

    // empirically determined value that allows for initialisation
    // to succeed before any API functions are called on this object
    std::this_thread::sleep_for(std::chrono::milliseconds(350));
    unsigned int width, height;
    if (libvlc_video_get_size(_vlc_mp, 0, &width, &height) != 0)
        throw VideoSourceError("Could not get video dimensions");

    _full.x = 0;
    _full.y = 0;
    _full.width = width;
    _full.height = height;
}

void VideoSourceVLC::stop_vlc()
{
    // stop playing
    libvlc_media_player_stop(_vlc_mp);
}

void VideoSourceVLC::release_vlc()
{
    // free media player
    libvlc_media_player_release(_vlc_mp);

    // free engine
    libvlc_release(_vlc_inst);

    // free buffer
    if (_video_buffer != nullptr)
        delete[] _video_buffer;
    _data_length = 0;
    _cols = 0;
    _rows = 0;

    // free sub-frame
    if (_sub != nullptr)
    {
        delete _sub;
        _sub = nullptr;
    }
}

void VideoSourceVLC::prepareRender(VideoSourceVLC * p_video_data,
                                   uint8_t ** pp_pixel_buffer,
                                   size_t size)
{
    ///\todo create mutex guard
    if (size > p_video_data->_data_length)
    {
        if (p_video_data->_data_length == 0)
            p_video_data->_video_buffer = reinterpret_cast<uint8_t *>(
                        malloc(size * sizeof(uint8_t))
                        );
        else
            p_video_data->_video_buffer = reinterpret_cast<uint8_t *>(
                        realloc(p_video_data->_video_buffer, size * sizeof(uint8_t))
                        );
    }
    p_video_data->_data_length = size;

    *pp_pixel_buffer = p_video_data->_video_buffer;
}

void VideoSourceVLC::handleStream(VideoSourceVLC * p_video_data,
                                  uint8_t * p_pixel_buffer,
                                  size_t cols,
                                  size_t rows,
                                  size_t colour_depth,
                                  size_t size)
{
    // TODO: explain how data should be handled (see #86)
    p_video_data->_cols = cols;
    p_video_data->_rows = rows;
    // TODO: Unlock the mutex
}

}
<|endoftext|>


<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#include "nl_bond.h"

#include <cassert>
#include <glog/logging.h>
#include <linux/if_bridge.h>
#include <netlink/route/link.h>
#include <netlink/route/link/bonding.h>

#include "cnetlink.h"
#include "nl_output.h"
#include "sai.h"

namespace basebox {

nl_bond::nl_bond(cnetlink *nl) : swi(nullptr), nl(nl) {}

void nl_bond::clear() noexcept {
  lag_members.clear();
  ifi2lag.clear();
}

uint32_t nl_bond::get_lag_id(rtnl_link *bond) {
  assert(bond);

  auto it = ifi2lag.find(rtnl_link_get_ifindex(bond));
  if (it == ifi2lag.end()) {
    VLOG(1) << __FUNCTION__ << ": lag_id not found of lag " << OBJ_CAST(bond);
    return 0;
  }

  auto rv_lm = lag_members.find(it->second);
  if (rv_lm == lag_members.end()) {
    VLOG(1) << ": no members in lag " << OBJ_CAST(bond);
    return 0;
  }

  VLOG(3) << __FUNCTION__ << ": found id=" << rv_lm->first;
  return rv_lm->first;
}

std::set<uint32_t> nl_bond::get_members(rtnl_link *bond) {
  auto it = ifi2lag.find(rtnl_link_get_ifindex(bond));
  if (it == ifi2lag.end()) {
    LOG(WARNING) << __FUNCTION__ << ": lag does not exist for "
                 << OBJ_CAST(bond);
    return {};
  }

  auto mem_it = lag_members.find(it->second);
  if (mem_it == lag_members.end()) {
    LOG(WARNING) << __FUNCTION__ << ": lag does not exist for "
                 << OBJ_CAST(bond);
    return {};
  }

  return mem_it->second;
}

int nl_bond::update_lag(rtnl_link *old_link, rtnl_link *new_link) {
#ifdef HAVE_RTNL_LINK_BOND_GET_MODE
  VLOG(1) << __FUNCTION__ << ": updating bond interface ";
  int rv = 0;

  uint8_t o_mode, n_mode;
  uint32_t lag_id = nl->get_port_id(new_link);

  if (lag_id == 0) {
    rv = add_lag(new_link);
    if (rv < 0)
      return rv;

    lag_id = rv;
  }

  rv = rtnl_link_bond_get_mode(old_link, &o_mode);
  if (rv < 0) {
    VLOG(1) << __FUNCTION__ << ": failed to get mode for "
            << OBJ_CAST(new_link);
  }

  rv = rtnl_link_bond_get_mode(new_link, &n_mode);
  if (rv < 0) {
    VLOG(1) << __FUNCTION__ << ": failed to get mode for "
            << OBJ_CAST(new_link);
  }

  if (o_mode != n_mode) {
    VLOG(1) << __FUNCTION__ << ": bond mode updated "
            << static_cast<uint32_t>(n_mode);
    rv = swi->lag_set_mode(lag_id, n_mode);

    if (rv < 0) {
      VLOG(1) << __FUNCTION__ << ": failed to set active state for "
              << OBJ_CAST(new_link);
    }

    return 0;
  }

  add_l3_address(new_link);
#endif

  return 0;
}

int nl_bond::add_lag(rtnl_link *bond) {
  uint32_t lag_id = 0;
  int rv = 0;
#ifdef HAVE_RTNL_LINK_BOND_GET_MODE
  uint8_t mode;

  rtnl_link_bond_get_mode(bond, &mode);

  assert(bond);
  rv = swi->lag_create(&lag_id, rtnl_link_get_name(bond), mode);
  if (rv < 0) {
    LOG(ERROR) << __FUNCTION__ << ": failed to create lag for "
               << OBJ_CAST(bond);
    return rv;
  }

  rv = lag_id;

  auto rv_emp =
      ifi2lag.emplace(std::make_pair(rtnl_link_get_ifindex(bond), lag_id));

  if (!rv_emp.second) {
    VLOG(1) << __FUNCTION__
            << ": lag exists with lag_id=" << rv_emp.first->second
            << " for bond " << OBJ_CAST(bond);
    rv = rv_emp.first->second;

    if (lag_id != rv_emp.first->second)
      swi->lag_remove(lag_id);
  }

  add_l3_address(bond);
#endif

  return rv;
}

int nl_bond::remove_lag(rtnl_link *bond) {
#ifdef HAVE_RTNL_LINK_BOND_GET_MODE
  int rv = 0;
  auto it = ifi2lag.find(rtnl_link_get_ifindex(bond));

  if (it == ifi2lag.end()) {
    LOG(WARNING) << __FUNCTION__ << ": lag does not exist for "
                 << OBJ_CAST(bond);
    return -ENODEV;
  }

  rv = swi->lag_remove(it->second);
  if (rv < 0) {
    LOG(ERROR) << __FUNCTION__
               << ": failed to remove lag with lag_id=" << it->second
               << " for bond " << OBJ_CAST(bond);
    return rv;
  }

  ifi2lag.erase(it);
#endif

  return 0;
}

int nl_bond::add_lag_member(rtnl_link *bond, rtnl_link *link) {
  int rv = 0;
#ifdef HAVE_RTNL_LINK_BOND_GET_MODE
  uint32_t lag_id;
  uint8_t state = 0;

  auto it = ifi2lag.find(rtnl_link_get_ifindex(bond));
  if (it == ifi2lag.end()) {
    VLOG(1) << __FUNCTION__ << ": no lag_id found creating new for "
            << OBJ_CAST(bond);

    rv = add_lag(bond);
    if (rv < 0)
      return rv;

    lag_id = rv;
  } else {
    lag_id = it->second;
  }

  uint32_t port_id = nl->get_port_id(link);
  if (port_id == 0) {
    VLOG(1) << __FUNCTION__ << ": ignoring port " << OBJ_CAST(link);
    return -EINVAL;
  }

  auto mem_it = lag_members.find(it->second);
  if (mem_it == lag_members.end()) { // No ports in lag
    std::set<uint32_t> members;
    members.insert(port_id);
    auto lm_rv = lag_members.emplace(lag_id, members);
  } else {
    mem_it->second.insert(port_id);
  }

  rv = rtnl_link_bond_slave_get_state(link, &state);
  if (rv < 0) {
    VLOG(1) << __FUNCTION__ << ": failed to get slave state for "
            << OBJ_CAST(link);
  }

  rv = swi->lag_add_member(lag_id, port_id);
  if (rv < 0) {
    LOG(ERROR) << __FUNCTION__ << ": failed add member " << port_id;
    return -EINVAL;
  }

  rv = swi->lag_set_member_active(lag_id, port_id, state == 0);
  if (rv < 0) {
    LOG(ERROR) << __FUNCTION__ << ": failed set active member " << port_id;
    return -EINVAL;
  }

  if (rtnl_link_get_master(bond)) {
    // check bridge attachement
    auto br_link = nl->get_link(rtnl_link_get_ifindex(bond), AF_BRIDGE);
    if (br_link) {
      VLOG(2) << __FUNCTION__
              << ": bond was already bridge slave: " << OBJ_CAST(br_link);
      nl->link_created(br_link);

      auto new_state = rtnl_link_bridge_get_port_state(br_link);
      std::string state;

      switch (new_state) {
      case BR_STATE_FORWARDING:
        state = "forward";
        break;
      case BR_STATE_BLOCKING:
        state = "block";
        break;
      case BR_STATE_DISABLED:
        state = "disable";
        break;
      case BR_STATE_LISTENING:
        state = "listen";
        break;
      case BR_STATE_LEARNING:
        state = "learn";
        break;
      default:
        VLOG(1) << __FUNCTION__ << ": stp state change not supported";
        return rv;
      }

      swi->ofdpa_stg_state_port_set(port_id, state);
    }

    rv = nl->set_bridge_port_vlan_tpid(br_link);
    if (rv < 0)
      LOG(ERROR) << __FUNCTION__
                 << ": failed to set egress TPID entry for port "
                 << OBJ_CAST(link);
  }

  // XXX FIXME check for vlan interfaces
#endif

  return rv;
}

int nl_bond::remove_lag_member(rtnl_link *link) {
  assert(link);

  int master_id = rtnl_link_get_master(link);
  auto master = nl->get_link(master_id, AF_UNSPEC);

  return remove_lag_member(master, link);
}

int nl_bond::remove_lag_member(rtnl_link *bond, rtnl_link *link) {
  int rv = 0;
#ifdef HAVE_RTNL_LINK_BOND_GET_MODE
  auto it = ifi2lag.find(rtnl_link_get_ifindex(bond));
  if (it == ifi2lag.end()) {
    LOG(FATAL) << __FUNCTION__ << ": no lag_id found for " << OBJ_CAST(bond);
  }

  uint32_t port_id = nl->get_port_id(link);
  if (port_id == 0) {
    VLOG(1) << __FUNCTION__ << ": ignore invalid lag port " << OBJ_CAST(link);
    return -EINVAL;
  }

  auto lm_rv = lag_members.find(it->second);
  if (lm_rv == lag_members.end()) {
    VLOG(1) << __FUNCTION__ << ": ignore invalid attached port "
            << OBJ_CAST(link);
    return -EINVAL;
  }

  rv = swi->lag_remove_member(it->second, port_id);
  lag_members.erase(lm_rv);

  if (nl->is_bridge_interface(bond)) {
    swi->ofdpa_stg_state_port_set(port_id, "forward");

    auto br_link = nl->get_link(rtnl_link_get_ifindex(bond), AF_BRIDGE);
    rv = nl->unset_bridge_port_vlan_tpid(br_link);

    if (rv < 0)
      LOG(ERROR) << __FUNCTION__
                 << ": failed to set egress TPID entry for port "
                 << OBJ_CAST(link);
  }

  if (lm_rv->second.empty())
    remove_l3_address(bond);

  if (nl->is_bridge_interface(bond))
    swi->ofdpa_stg_state_port_set(port_id, "forward");
#endif

  return rv;
}

int nl_bond::update_lag_member(rtnl_link *old_slave, rtnl_link *new_slave) {
#ifdef HAVE_RTNL_LINK_BOND_GET_MODE
  assert(new_slave);

  int rv;
  uint8_t new_state;
  uint8_t old_state;

  int n_master_id = rtnl_link_get_master(new_slave);
  int o_master_id = rtnl_link_get_master(old_slave);
  auto new_master = nl->get_link(n_master_id, AF_UNSPEC);
  auto old_master = nl->get_link(o_master_id, AF_UNSPEC);
  auto port_id = nl->get_port_id(new_slave);

  if (old_master != new_master || new_master == 0) {
    return -EINVAL;
  }

  rv = rtnl_link_bond_slave_get_state(new_slave, &new_state);
  if (rv != 0) {
    VLOG(1) << __FUNCTION__ << ": failed to get state";
    return -EINVAL;
  }
  rtnl_link_bond_slave_get_state(old_slave, &old_state);
  if (rv != 0) {
    VLOG(1) << __FUNCTION__ << ": failed to get state";
    return -EINVAL;
  }

  rv = swi->lag_set_member_active(nl->get_port_id(new_master), port_id,
                                  new_state == 0);
#endif
  return 0;
}

int nl_bond::add_l3_address(rtnl_link *link) {
  int rv = 0;
#ifdef HAVE_RTNL_LINK_BOND_GET_MODE
  assert(link);

  std::deque<rtnl_addr *> addresses;
  nl->get_l3_addrs(link, &addresses);

  for (auto i : addresses) {
    LOG(INFO) << __FUNCTION__ << ": adding address=" << OBJ_CAST(i);

    rv = nl->add_l3_addr(i);
    if (rv < 0)
      LOG(ERROR) << __FUNCTION__ << ":failed to add l3 address " << OBJ_CAST(i)
                 << " to " << OBJ_CAST(link);
  }
  LOG(INFO) << __FUNCTION__ << ": added l3 addresses to bond "
            << OBJ_CAST(link);

#endif
  return rv;
}

int nl_bond::remove_l3_address(rtnl_link *link) {
  int rv = 0;
#ifdef HAVE_RTNL_LINK_BOND_GET_MODE
  assert(link);

  std::deque<rtnl_addr *> addresses;
  nl->get_l3_addrs(link, &addresses);

  for (auto i : addresses) {
    rv = nl->del_l3_addr(i);
    if (rv < 0)
      LOG(ERROR) << __FUNCTION__ << ":failed to remove l3 address from "
                 << OBJ_CAST(link);
  }

#endif
  return rv;
}

} // namespace basebox
<commit_msg>nl_bond: return lag id when bond has no members<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#include "nl_bond.h"

#include <cassert>
#include <glog/logging.h>
#include <linux/if_bridge.h>
#include <netlink/route/link.h>
#include <netlink/route/link/bonding.h>

#include "cnetlink.h"
#include "nl_output.h"
#include "sai.h"

namespace basebox {

nl_bond::nl_bond(cnetlink *nl) : swi(nullptr), nl(nl) {}

void nl_bond::clear() noexcept {
  lag_members.clear();
  ifi2lag.clear();
}

uint32_t nl_bond::get_lag_id(rtnl_link *bond) {
  assert(bond);

  auto it = ifi2lag.find(rtnl_link_get_ifindex(bond));
  if (it == ifi2lag.end()) {
    VLOG(1) << __FUNCTION__ << ": lag_id not found of lag " << OBJ_CAST(bond);
    return 0;
  }

  return it->second;
}

std::set<uint32_t> nl_bond::get_members(rtnl_link *bond) {
  auto it = ifi2lag.find(rtnl_link_get_ifindex(bond));
  if (it == ifi2lag.end()) {
    LOG(WARNING) << __FUNCTION__ << ": lag does not exist for "
                 << OBJ_CAST(bond);
    return {};
  }

  auto mem_it = lag_members.find(it->second);
  if (mem_it == lag_members.end()) {
    LOG(WARNING) << __FUNCTION__ << ": lag does not exist for "
                 << OBJ_CAST(bond);
    return {};
  }

  return mem_it->second;
}

int nl_bond::update_lag(rtnl_link *old_link, rtnl_link *new_link) {
#ifdef HAVE_RTNL_LINK_BOND_GET_MODE
  VLOG(1) << __FUNCTION__ << ": updating bond interface ";
  int rv = 0;

  uint8_t o_mode, n_mode;
  uint32_t lag_id = nl->get_port_id(new_link);

  if (lag_id == 0) {
    rv = add_lag(new_link);
    if (rv < 0)
      return rv;

    lag_id = rv;
  }

  rv = rtnl_link_bond_get_mode(old_link, &o_mode);
  if (rv < 0) {
    VLOG(1) << __FUNCTION__ << ": failed to get mode for "
            << OBJ_CAST(new_link);
  }

  rv = rtnl_link_bond_get_mode(new_link, &n_mode);
  if (rv < 0) {
    VLOG(1) << __FUNCTION__ << ": failed to get mode for "
            << OBJ_CAST(new_link);
  }

  if (o_mode != n_mode) {
    VLOG(1) << __FUNCTION__ << ": bond mode updated "
            << static_cast<uint32_t>(n_mode);
    rv = swi->lag_set_mode(lag_id, n_mode);

    if (rv < 0) {
      VLOG(1) << __FUNCTION__ << ": failed to set active state for "
              << OBJ_CAST(new_link);
    }

    return 0;
  }

  add_l3_address(new_link);
#endif

  return 0;
}

int nl_bond::add_lag(rtnl_link *bond) {
  uint32_t lag_id = 0;
  int rv = 0;
#ifdef HAVE_RTNL_LINK_BOND_GET_MODE
  uint8_t mode;

  rtnl_link_bond_get_mode(bond, &mode);

  assert(bond);
  rv = swi->lag_create(&lag_id, rtnl_link_get_name(bond), mode);
  if (rv < 0) {
    LOG(ERROR) << __FUNCTION__ << ": failed to create lag for "
               << OBJ_CAST(bond);
    return rv;
  }

  rv = lag_id;

  auto rv_emp =
      ifi2lag.emplace(std::make_pair(rtnl_link_get_ifindex(bond), lag_id));

  if (!rv_emp.second) {
    VLOG(1) << __FUNCTION__
            << ": lag exists with lag_id=" << rv_emp.first->second
            << " for bond " << OBJ_CAST(bond);
    rv = rv_emp.first->second;

    if (lag_id != rv_emp.first->second)
      swi->lag_remove(lag_id);
  }

  add_l3_address(bond);
#endif

  return rv;
}

int nl_bond::remove_lag(rtnl_link *bond) {
#ifdef HAVE_RTNL_LINK_BOND_GET_MODE
  int rv = 0;
  auto it = ifi2lag.find(rtnl_link_get_ifindex(bond));

  if (it == ifi2lag.end()) {
    LOG(WARNING) << __FUNCTION__ << ": lag does not exist for "
                 << OBJ_CAST(bond);
    return -ENODEV;
  }

  rv = swi->lag_remove(it->second);
  if (rv < 0) {
    LOG(ERROR) << __FUNCTION__
               << ": failed to remove lag with lag_id=" << it->second
               << " for bond " << OBJ_CAST(bond);
    return rv;
  }

  ifi2lag.erase(it);
#endif

  return 0;
}

int nl_bond::add_lag_member(rtnl_link *bond, rtnl_link *link) {
  int rv = 0;
#ifdef HAVE_RTNL_LINK_BOND_GET_MODE
  uint32_t lag_id;
  uint8_t state = 0;

  auto it = ifi2lag.find(rtnl_link_get_ifindex(bond));
  if (it == ifi2lag.end()) {
    VLOG(1) << __FUNCTION__ << ": no lag_id found creating new for "
            << OBJ_CAST(bond);

    rv = add_lag(bond);
    if (rv < 0)
      return rv;

    lag_id = rv;
  } else {
    lag_id = it->second;
  }

  uint32_t port_id = nl->get_port_id(link);
  if (port_id == 0) {
    VLOG(1) << __FUNCTION__ << ": ignoring port " << OBJ_CAST(link);
    return -EINVAL;
  }

  auto mem_it = lag_members.find(it->second);
  if (mem_it == lag_members.end()) { // No ports in lag
    std::set<uint32_t> members;
    members.insert(port_id);
    auto lm_rv = lag_members.emplace(lag_id, members);
  } else {
    mem_it->second.insert(port_id);
  }

  rv = rtnl_link_bond_slave_get_state(link, &state);
  if (rv < 0) {
    VLOG(1) << __FUNCTION__ << ": failed to get slave state for "
            << OBJ_CAST(link);
  }

  rv = swi->lag_add_member(lag_id, port_id);
  if (rv < 0) {
    LOG(ERROR) << __FUNCTION__ << ": failed add member " << port_id;
    return -EINVAL;
  }

  rv = swi->lag_set_member_active(lag_id, port_id, state == 0);
  if (rv < 0) {
    LOG(ERROR) << __FUNCTION__ << ": failed set active member " << port_id;
    return -EINVAL;
  }

  if (rtnl_link_get_master(bond)) {
    // check bridge attachement
    auto br_link = nl->get_link(rtnl_link_get_ifindex(bond), AF_BRIDGE);
    if (br_link) {
      VLOG(2) << __FUNCTION__
              << ": bond was already bridge slave: " << OBJ_CAST(br_link);
      nl->link_created(br_link);

      auto new_state = rtnl_link_bridge_get_port_state(br_link);
      std::string state;

      switch (new_state) {
      case BR_STATE_FORWARDING:
        state = "forward";
        break;
      case BR_STATE_BLOCKING:
        state = "block";
        break;
      case BR_STATE_DISABLED:
        state = "disable";
        break;
      case BR_STATE_LISTENING:
        state = "listen";
        break;
      case BR_STATE_LEARNING:
        state = "learn";
        break;
      default:
        VLOG(1) << __FUNCTION__ << ": stp state change not supported";
        return rv;
      }

      swi->ofdpa_stg_state_port_set(port_id, state);
    }

    rv = nl->set_bridge_port_vlan_tpid(br_link);
    if (rv < 0)
      LOG(ERROR) << __FUNCTION__
                 << ": failed to set egress TPID entry for port "
                 << OBJ_CAST(link);
  }

  // XXX FIXME check for vlan interfaces
#endif

  return rv;
}

int nl_bond::remove_lag_member(rtnl_link *link) {
  assert(link);

  int master_id = rtnl_link_get_master(link);
  auto master = nl->get_link(master_id, AF_UNSPEC);

  return remove_lag_member(master, link);
}

int nl_bond::remove_lag_member(rtnl_link *bond, rtnl_link *link) {
  int rv = 0;
#ifdef HAVE_RTNL_LINK_BOND_GET_MODE
  auto it = ifi2lag.find(rtnl_link_get_ifindex(bond));
  if (it == ifi2lag.end()) {
    LOG(FATAL) << __FUNCTION__ << ": no lag_id found for " << OBJ_CAST(bond);
  }

  uint32_t port_id = nl->get_port_id(link);
  if (port_id == 0) {
    VLOG(1) << __FUNCTION__ << ": ignore invalid lag port " << OBJ_CAST(link);
    return -EINVAL;
  }

  auto lm_rv = lag_members.find(it->second);
  if (lm_rv == lag_members.end()) {
    VLOG(1) << __FUNCTION__ << ": ignore invalid attached port "
            << OBJ_CAST(link);
    return -EINVAL;
  }

  rv = swi->lag_remove_member(it->second, port_id);
  lag_members.erase(lm_rv);

  if (nl->is_bridge_interface(bond)) {
    swi->ofdpa_stg_state_port_set(port_id, "forward");

    auto br_link = nl->get_link(rtnl_link_get_ifindex(bond), AF_BRIDGE);
    rv = nl->unset_bridge_port_vlan_tpid(br_link);

    if (rv < 0)
      LOG(ERROR) << __FUNCTION__
                 << ": failed to set egress TPID entry for port "
                 << OBJ_CAST(link);
  }

  if (lm_rv->second.empty())
    remove_l3_address(bond);

  if (nl->is_bridge_interface(bond))
    swi->ofdpa_stg_state_port_set(port_id, "forward");
#endif

  return rv;
}

int nl_bond::update_lag_member(rtnl_link *old_slave, rtnl_link *new_slave) {
#ifdef HAVE_RTNL_LINK_BOND_GET_MODE
  assert(new_slave);

  int rv;
  uint8_t new_state;
  uint8_t old_state;

  int n_master_id = rtnl_link_get_master(new_slave);
  int o_master_id = rtnl_link_get_master(old_slave);
  auto new_master = nl->get_link(n_master_id, AF_UNSPEC);
  auto old_master = nl->get_link(o_master_id, AF_UNSPEC);
  auto port_id = nl->get_port_id(new_slave);

  if (old_master != new_master || new_master == 0) {
    return -EINVAL;
  }

  rv = rtnl_link_bond_slave_get_state(new_slave, &new_state);
  if (rv != 0) {
    VLOG(1) << __FUNCTION__ << ": failed to get state";
    return -EINVAL;
  }
  rtnl_link_bond_slave_get_state(old_slave, &old_state);
  if (rv != 0) {
    VLOG(1) << __FUNCTION__ << ": failed to get state";
    return -EINVAL;
  }

  rv = swi->lag_set_member_active(nl->get_port_id(new_master), port_id,
                                  new_state == 0);
#endif
  return 0;
}

int nl_bond::add_l3_address(rtnl_link *link) {
  int rv = 0;
#ifdef HAVE_RTNL_LINK_BOND_GET_MODE
  assert(link);

  std::deque<rtnl_addr *> addresses;
  nl->get_l3_addrs(link, &addresses);

  for (auto i : addresses) {
    LOG(INFO) << __FUNCTION__ << ": adding address=" << OBJ_CAST(i);

    rv = nl->add_l3_addr(i);
    if (rv < 0)
      LOG(ERROR) << __FUNCTION__ << ":failed to add l3 address " << OBJ_CAST(i)
                 << " to " << OBJ_CAST(link);
  }
  LOG(INFO) << __FUNCTION__ << ": added l3 addresses to bond "
            << OBJ_CAST(link);

#endif
  return rv;
}

int nl_bond::remove_l3_address(rtnl_link *link) {
  int rv = 0;
#ifdef HAVE_RTNL_LINK_BOND_GET_MODE
  assert(link);

  std::deque<rtnl_addr *> addresses;
  nl->get_l3_addrs(link, &addresses);

  for (auto i : addresses) {
    rv = nl->del_l3_addr(i);
    if (rv < 0)
      LOG(ERROR) << __FUNCTION__ << ":failed to remove l3 address from "
                 << OBJ_CAST(link);
  }

#endif
  return rv;
}

} // namespace basebox
<|endoftext|>