<commit_before>/*
 * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met: redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer;
 * redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution;
 * neither the name of the copyright holders nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include <algorithm>

#include "mem/ruby/common/NetDest.hh"

NetDest::NetDest()
{
  resize();
}

void
NetDest::add(MachineID newElement)
{
    m_bits[vecIndex(newElement)].add(bitIndex(newElement.num));
}

void
NetDest::addNetDest(const NetDest& netDest)
{
    assert(m_bits.size() == netDest.getSize());
    for (int i = 0; i < m_bits.size(); i++) {
        m_bits[i].addSet(netDest.m_bits[i]);
    }
}

void
NetDest::addRandom()
{
    int i = random()%m_bits.size();
    m_bits[i].addRandom();
}

void
NetDest::setNetDest(MachineType machine, const Set& set)
{
    // assure that there is only one set of destinations for this machine
    assert(MachineType_base_level((MachineType)(machine + 1)) -
           MachineType_base_level(machine) == 1);
    m_bits[MachineType_base_level(machine)] = set;
}

void
NetDest::remove(MachineID oldElement)
{
    m_bits[vecIndex(oldElement)].remove(bitIndex(oldElement.num));
}

void
NetDest::removeNetDest(const NetDest& netDest)
{
    assert(m_bits.size() == netDest.getSize());
    for (int i = 0; i < m_bits.size(); i++) {
        m_bits[i].removeSet(netDest.m_bits[i]);
    }
}

void
NetDest::clear()
{
    for (int i = 0; i < m_bits.size(); i++) {
        m_bits[i].clear();
    }
}

void
NetDest::broadcast()
{
    for (MachineType machine = MachineType_FIRST;
         machine < MachineType_NUM; ++machine) {
        broadcast(machine);
    }
}

void
NetDest::broadcast(MachineType machineType)
{
    for (int i = 0; i < MachineType_base_count(machineType); i++) {
        MachineID mach = {machineType, i};
        add(mach);
    }
}

//For Princeton Network
std::vector<NodeID>
NetDest::getAllDest()
{
    std::vector<NodeID> dest;
    dest.clear();
    for (int i = 0; i < m_bits.size(); i++) {
        for (int j = 0; j < m_bits[i].getSize(); j++) {
            if (m_bits[i].isElement(j)) {
                int id = MachineType_base_number((MachineType)i) + j;
                dest.push_back((NodeID)id);
            }
        }
    }
    return dest;
}

int
NetDest::count() const
{
    int counter = 0;
    for (int i = 0; i < m_bits.size(); i++) {
        counter += m_bits[i].count();
    }
    return counter;
}

NodeID
NetDest::elementAt(MachineID index)
{
    return m_bits[vecIndex(index)].elementAt(bitIndex(index.num));
}

MachineID
NetDest::smallestElement() const
{
    assert(count() > 0);
    for (int i = 0; i < m_bits.size(); i++) {
        for (int j = 0; j < m_bits[i].getSize(); j++) {
            if (m_bits[i].isElement(j)) {
                MachineID mach = {MachineType_from_base_level(i), j};
                return mach;
            }
        }
    }
    panic("No smallest element of an empty set.");
}

MachineID
NetDest::smallestElement(MachineType machine) const
{
    int size = m_bits[MachineType_base_level(machine)].getSize();
    for (int j = 0; j < size; j++) {
        if (m_bits[MachineType_base_level(machine)].isElement(j)) {
            MachineID mach = {machine, j};
            return mach;
        }
    }

    panic("No smallest element of given MachineType.");
}

// Returns true iff all bits are set
bool
NetDest::isBroadcast() const
{
    for (int i = 0; i < m_bits.size(); i++) {
        if (!m_bits[i].isBroadcast()) {
            return false;
        }
    }
    return true;
}

// Returns true iff no bits are set
bool
NetDest::isEmpty() const
{
    for (int i = 0; i < m_bits.size(); i++) {
        if (!m_bits[i].isEmpty()) {
            return false;
        }
    }
    return true;
}

// returns the logical OR of "this" set and orNetDest
NetDest
NetDest::OR(const NetDest& orNetDest) const
{
    assert(m_bits.size() == orNetDest.getSize());
    NetDest result;
    for (int i = 0; i < m_bits.size(); i++) {
        result.m_bits[i] = m_bits[i].OR(orNetDest.m_bits[i]);
    }
    return result;
}

// returns the logical AND of "this" set and andNetDest
NetDest
NetDest::AND(const NetDest& andNetDest) const
{
    assert(m_bits.size() == andNetDest.getSize());
    NetDest result;
    for (int i = 0; i < m_bits.size(); i++) {
        result.m_bits[i] = m_bits[i].AND(andNetDest.m_bits[i]);
    }
    return result;
}

// Returns true if the intersection of the two sets is non-empty
bool
NetDest::intersectionIsNotEmpty(const NetDest& other_netDest) const
{
    assert(m_bits.size() == other_netDest.getSize());
    for (int i = 0; i < m_bits.size(); i++) {
        if (!m_bits[i].intersectionIsEmpty(other_netDest.m_bits[i])) {
            return true;
        }
    }
    return false;
}

bool
NetDest::isSuperset(const NetDest& test) const
{
    assert(m_bits.size() == test.getSize());

    for (int i = 0; i < m_bits.size(); i++) {
        if (!m_bits[i].isSuperset(test.m_bits[i])) {
            return false;
        }
    }
    return true;
}

bool
NetDest::isElement(MachineID element) const
{
    return ((m_bits[vecIndex(element)])).isElement(bitIndex(element.num));
}

void
NetDest::resize()
{
    m_bits.resize(MachineType_base_level(MachineType_NUM));
    assert(m_bits.size() == MachineType_NUM);

    for (int i = 0; i < m_bits.size(); i++) {
        m_bits[i].setSize(MachineType_base_count((MachineType)i));
    }
}

void
NetDest::print(std::ostream& out) const
{
    out << "[NetDest (" << m_bits.size() << ") ";

    for (int i = 0; i < m_bits.size(); i++) {
        for (int j = 0; j < m_bits[i].getSize(); j++) {
            out << (bool) m_bits[i].isElement(j) << " ";
        }
        out << " - ";
    }
    out << "]";
}

<commit_msg>Ruby NetDest: add assert for bad element in netdest<commit_after>/*
 * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met: redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer;
 * redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution;
 * neither the name of the copyright holders nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include <algorithm>

#include "mem/ruby/common/NetDest.hh"

NetDest::NetDest()
{
  resize();
}

void
NetDest::add(MachineID newElement)
{
    assert(bitIndex(newElement.num) < m_bits[vecIndex(newElement)].getSize());
    m_bits[vecIndex(newElement)].add(bitIndex(newElement.num));
}

void
NetDest::addNetDest(const NetDest& netDest)
{
    assert(m_bits.size() == netDest.getSize());
    for (int i = 0; i < m_bits.size(); i++) {
        m_bits[i].addSet(netDest.m_bits[i]);
    }
}

void
NetDest::addRandom()
{
    int i = random()%m_bits.size();
    m_bits[i].addRandom();
}

void
NetDest::setNetDest(MachineType machine, const Set& set)
{
    // assure that there is only one set of destinations for this machine
    assert(MachineType_base_level((MachineType)(machine + 1)) -
           MachineType_base_level(machine) == 1);
    m_bits[MachineType_base_level(machine)] = set;
}

void
NetDest::remove(MachineID oldElement)
{
    m_bits[vecIndex(oldElement)].remove(bitIndex(oldElement.num));
}

void
NetDest::removeNetDest(const NetDest& netDest)
{
    assert(m_bits.size() == netDest.getSize());
    for (int i = 0; i < m_bits.size(); i++) {
        m_bits[i].removeSet(netDest.m_bits[i]);
    }
}

void
NetDest::clear()
{
    for (int i = 0; i < m_bits.size(); i++) {
        m_bits[i].clear();
    }
}

void
NetDest::broadcast()
{
    for (MachineType machine = MachineType_FIRST;
         machine < MachineType_NUM; ++machine) {
        broadcast(machine);
    }
}

void
NetDest::broadcast(MachineType machineType)
{
    for (int i = 0; i < MachineType_base_count(machineType); i++) {
        MachineID mach = {machineType, i};
        add(mach);
    }
}

//For Princeton Network
std::vector<NodeID>
NetDest::getAllDest()
{
    std::vector<NodeID> dest;
    dest.clear();
    for (int i = 0; i < m_bits.size(); i++) {
        for (int j = 0; j < m_bits[i].getSize(); j++) {
            if (m_bits[i].isElement(j)) {
                int id = MachineType_base_number((MachineType)i) + j;
                dest.push_back((NodeID)id);
            }
        }
    }
    return dest;
}

int
NetDest::count() const
{
    int counter = 0;
    for (int i = 0; i < m_bits.size(); i++) {
        counter += m_bits[i].count();
    }
    return counter;
}

NodeID
NetDest::elementAt(MachineID index)
{
    return m_bits[vecIndex(index)].elementAt(bitIndex(index.num));
}

MachineID
NetDest::smallestElement() const
{
    assert(count() > 0);
    for (int i = 0; i < m_bits.size(); i++) {
        for (int j = 0; j < m_bits[i].getSize(); j++) {
            if (m_bits[i].isElement(j)) {
                MachineID mach = {MachineType_from_base_level(i), j};
                return mach;
            }
        }
    }
    panic("No smallest element of an empty set.");
}

MachineID
NetDest::smallestElement(MachineType machine) const
{
    int size = m_bits[MachineType_base_level(machine)].getSize();
    for (int j = 0; j < size; j++) {
        if (m_bits[MachineType_base_level(machine)].isElement(j)) {
            MachineID mach = {machine, j};
            return mach;
        }
    }

    panic("No smallest element of given MachineType.");
}

// Returns true iff all bits are set
bool
NetDest::isBroadcast() const
{
    for (int i = 0; i < m_bits.size(); i++) {
        if (!m_bits[i].isBroadcast()) {
            return false;
        }
    }
    return true;
}

// Returns true iff no bits are set
bool
NetDest::isEmpty() const
{
    for (int i = 0; i < m_bits.size(); i++) {
        if (!m_bits[i].isEmpty()) {
            return false;
        }
    }
    return true;
}

// returns the logical OR of "this" set and orNetDest
NetDest
NetDest::OR(const NetDest& orNetDest) const
{
    assert(m_bits.size() == orNetDest.getSize());
    NetDest result;
    for (int i = 0; i < m_bits.size(); i++) {
        result.m_bits[i] = m_bits[i].OR(orNetDest.m_bits[i]);
    }
    return result;
}

// returns the logical AND of "this" set and andNetDest
NetDest
NetDest::AND(const NetDest& andNetDest) const
{
    assert(m_bits.size() == andNetDest.getSize());
    NetDest result;
    for (int i = 0; i < m_bits.size(); i++) {
        result.m_bits[i] = m_bits[i].AND(andNetDest.m_bits[i]);
    }
    return result;
}

// Returns true if the intersection of the two sets is non-empty
bool
NetDest::intersectionIsNotEmpty(const NetDest& other_netDest) const
{
    assert(m_bits.size() == other_netDest.getSize());
    for (int i = 0; i < m_bits.size(); i++) {
        if (!m_bits[i].intersectionIsEmpty(other_netDest.m_bits[i])) {
            return true;
        }
    }
    return false;
}

bool
NetDest::isSuperset(const NetDest& test) const
{
    assert(m_bits.size() == test.getSize());

    for (int i = 0; i < m_bits.size(); i++) {
        if (!m_bits[i].isSuperset(test.m_bits[i])) {
            return false;
        }
    }
    return true;
}

bool
NetDest::isElement(MachineID element) const
{
    return ((m_bits[vecIndex(element)])).isElement(bitIndex(element.num));
}

void
NetDest::resize()
{
    m_bits.resize(MachineType_base_level(MachineType_NUM));
    assert(m_bits.size() == MachineType_NUM);

    for (int i = 0; i < m_bits.size(); i++) {
        m_bits[i].setSize(MachineType_base_count((MachineType)i));
    }
}

void
NetDest::print(std::ostream& out) const
{
    out << "[NetDest (" << m_bits.size() << ") ";

    for (int i = 0; i < m_bits.size(); i++) {
        for (int j = 0; j < m_bits[i].getSize(); j++) {
            out << (bool) m_bits[i].isElement(j) << " ";
        }
        out << " - ";
    }
    out << "]";
}

<|endoftext|>


<commit_before>/**
 * @file mvu.hpp
 * @author Ryan Curtin
 *
 * An implementation of Maximum Variance Unfolding.  This file defines an MVU
 * class as well as a class representing the objective function (a semidefinite
 * program) which MVU seeks to minimize.  Minimization is performed by the
 * Augmented Lagrangian optimizer (which in turn uses the L-BFGS optimizer).
 */
#ifndef __MLPACK_METHODS_MVU_MVU_HPP
#define __MLPACK_METHODS_VU_MVU_HPP

#include <mlpack/core.hpp>

namespace mlpack {
namespace mvu {

/**
 * The MVU class is meant to provide a good abstraction for users.  The dataset
 * needs to be provided, as well as several parameters.
 *
 * - dataset
 * - new dimensionality
 */
class MVU
{
 public:
  MVU(const arma::mat& data_in);

  void Unfold(const size_t newDim,
              const size_t numNeighbors,
              arma::mat& output_coordinates);

 private:
  const arma::mat& data;
};

}; // namespace mvu
}; // namespace mlpack

#endif
<commit_msg>Formatted /mvu<commit_after>/**
 * @file mvu.hpp
 * @author Ryan Curtin
 *
 * An implementation of Maximum Variance Unfolding.  This file defines an MVU
 * class as well as a class representing the objective function (a semidefinite
 * program) which MVU seeks to minimize.  Minimization is performed by the
 * Augmented Lagrangian optimizer (which in turn uses the L-BFGS optimizer).
 */
#ifndef __MLPACK_METHODS_MVU_MVU_HPP
#define __MLPACK_METHODS_VU_MVU_HPP

#include <mlpack/core.hpp>

namespace mlpack {
namespace mvu {

/**
 * The MVU class is meant to provide a good abstraction for users.  The dataset
 * needs to be provided, as well as several parameters.
 *
 * - dataset
 * - new dimensionality
 */
class MVU
{
 public:
  MVU(const arma::mat& dataIn);

  void Unfold(const size_t newDim,
              const size_t numNeighbors,
              arma::mat& outputCoordinates);

 private:
  const arma::mat& data;
};

}; // namespace mvu
}; // namespace mlpack

#endif
<|endoftext|>


<commit_before>#ifndef MODBUS_CLIENT_HPP
#define MODBUS_CLIENT_HPP

#include <boost/asio.hpp>
#include <stdexcept>

class ModbusClient {
public:
    inline                              ModbusClient(const modbus::tcp::UnitId& unitId, OutputFormatter& out);

    inline void                         setTransactionId(const modbus::tcp::TransactionId& transactionId);
    inline void                         connect(const boost::asio::ip::tcp::endpoint& ep);
    inline void                         readCoils(const modbus::tcp::Address& startAddress, const modbus::tcp::NumBits& numCoils);
    inline void                         readDiscreteInputs(const modbus::tcp::Address& startAddress, const modbus::tcp::NumBits& numInputs);
    inline void                         readInputRegisters(const modbus::tcp::Address& startAddress, const modbus::tcp::NumRegs& numRegs);

private:
    OutputFormatter                    &m_outFormatter;
    boost::asio::io_service             m_io;
    boost::asio::ip::tcp::socket        m_socket;
    modbus::tcp::UnitId                 m_unitId;
    modbus::tcp::TransactionId          m_transactionId;
    std::vector<uint8_t>                m_tx_buffer;
    std::vector<uint8_t>                m_rx_buffer;

    void                                recvResponse();
};

ModbusClient::ModbusClient(const modbus::tcp::UnitId& unitId, OutputFormatter& out) :
    m_outFormatter(out),
    m_io(),
    m_socket(m_io),
    m_unitId(unitId),
    m_transactionId(1),
    m_tx_buffer(),
    m_rx_buffer()
{}

void ModbusClient::setTransactionId(const modbus::tcp::TransactionId& transactionId) {
    m_transactionId = transactionId;
}

void ModbusClient::connect(const boost::asio::ip::tcp::endpoint& ep) {
    m_socket.connect(ep);
}

void ModbusClient::readCoils(const modbus::tcp::Address& startAddress, const modbus::tcp::NumBits& numCoils) {
    modbus::tcp::Encoder encoder(m_unitId, m_transactionId);

    encoder.encodeReadCoilsReq(startAddress, numCoils, m_tx_buffer);
    m_outFormatter.displayOutgoing(m_tx_buffer);
    boost::asio::write(m_socket, boost::asio::buffer(m_tx_buffer));

    recvResponse();

    modbus::tcp::decoder_views::Header rsp_header_view(m_rx_buffer);

    if (rsp_header_view.isError())
        m_outFormatter.displayErrorResponse(m_rx_buffer, m_tx_buffer);
    else
        m_outFormatter.displayReadCoils(m_tx_buffer, m_rx_buffer);
}

void ModbusClient::readDiscreteInputs(const modbus::tcp::Address& startAddress, const modbus::tcp::NumBits& numInputs) {
    modbus::tcp::Encoder encoder(m_unitId, m_transactionId);

    encoder.encodeReadDiscreteInputsReq(startAddress, numInputs, m_tx_buffer);
    m_outFormatter.displayOutgoing(m_tx_buffer);
    boost::asio::write(m_socket, boost::asio::buffer(m_tx_buffer));

    recvResponse();

    modbus::tcp::decoder_views::Header rsp_header_view(m_rx_buffer);

    if (rsp_header_view.isError())
        m_outFormatter.displayErrorResponse(m_rx_buffer, m_tx_buffer);
    else
        m_outFormatter.displayReadDiscreteInputs(m_tx_buffer, m_rx_buffer);
}

void ModbusClient::readInputRegisters(const modbus::tcp::Address& startAddress, const modbus::tcp::NumRegs& numRegs) {
    modbus::tcp::Encoder encoder(m_unitId, m_transactionId);

    encoder.encodeReadInputRegistersReq(startAddress, numRegs, m_tx_buffer);
    m_outFormatter.displayOutgoing(m_tx_buffer);
    boost::asio::write(m_socket, boost::asio::buffer(m_tx_buffer));

    recvResponse();

    modbus::tcp::decoder_views::Header rsp_header_view(m_rx_buffer);

    if (rsp_header_view.isError())
        m_outFormatter.displayErrorResponse(m_rx_buffer, m_tx_buffer);
    else
        m_outFormatter.displayReadInputRegisters(m_tx_buffer, m_rx_buffer);
}

void ModbusClient::recvResponse() {
    m_rx_buffer.resize(sizeof(modbus::tcp::Header));
    boost::asio::read(m_socket, boost::asio::buffer(m_rx_buffer));

    modbus::tcp::decoder_views::Header rsp_header_view(m_rx_buffer);
    uint16_t payload_size = rsp_header_view.getLength() - 2;
    m_rx_buffer.resize(sizeof(modbus::tcp::Header) + payload_size);
    uint8_t *payload = m_rx_buffer.data() + sizeof(modbus::tcp::Header);

    boost::asio::read(m_socket, boost::asio::buffer(payload, payload_size));
}

#endif
<commit_msg>Fix bug in call to displayErrorResponse() method<commit_after>#ifndef MODBUS_CLIENT_HPP
#define MODBUS_CLIENT_HPP

#include <boost/asio.hpp>
#include <stdexcept>

class ModbusClient {
public:
    inline                              ModbusClient(const modbus::tcp::UnitId& unitId, OutputFormatter& out);

    inline void                         setTransactionId(const modbus::tcp::TransactionId& transactionId);
    inline void                         connect(const boost::asio::ip::tcp::endpoint& ep);
    inline void                         readCoils(const modbus::tcp::Address& startAddress, const modbus::tcp::NumBits& numCoils);
    inline void                         readDiscreteInputs(const modbus::tcp::Address& startAddress, const modbus::tcp::NumBits& numInputs);
    inline void                         readInputRegisters(const modbus::tcp::Address& startAddress, const modbus::tcp::NumRegs& numRegs);

private:
    OutputFormatter                    &m_outFormatter;
    boost::asio::io_service             m_io;
    boost::asio::ip::tcp::socket        m_socket;
    modbus::tcp::UnitId                 m_unitId;
    modbus::tcp::TransactionId          m_transactionId;
    std::vector<uint8_t>                m_tx_buffer;
    std::vector<uint8_t>                m_rx_buffer;

    void                                recvResponse();
};

ModbusClient::ModbusClient(const modbus::tcp::UnitId& unitId, OutputFormatter& out) :
    m_outFormatter(out),
    m_io(),
    m_socket(m_io),
    m_unitId(unitId),
    m_transactionId(1),
    m_tx_buffer(),
    m_rx_buffer()
{}

void ModbusClient::setTransactionId(const modbus::tcp::TransactionId& transactionId) {
    m_transactionId = transactionId;
}

void ModbusClient::connect(const boost::asio::ip::tcp::endpoint& ep) {
    m_socket.connect(ep);
}

void ModbusClient::readCoils(const modbus::tcp::Address& startAddress, const modbus::tcp::NumBits& numCoils) {
    modbus::tcp::Encoder encoder(m_unitId, m_transactionId);

    encoder.encodeReadCoilsReq(startAddress, numCoils, m_tx_buffer);
    m_outFormatter.displayOutgoing(m_tx_buffer);
    boost::asio::write(m_socket, boost::asio::buffer(m_tx_buffer));

    recvResponse();

    modbus::tcp::decoder_views::Header rsp_header_view(m_rx_buffer);

    if (rsp_header_view.isError())
        m_outFormatter.displayErrorResponse(m_tx_buffer, m_rx_buffer);
    else
        m_outFormatter.displayReadCoils(m_tx_buffer, m_rx_buffer);
}

void ModbusClient::readDiscreteInputs(const modbus::tcp::Address& startAddress, const modbus::tcp::NumBits& numInputs) {
    modbus::tcp::Encoder encoder(m_unitId, m_transactionId);

    encoder.encodeReadDiscreteInputsReq(startAddress, numInputs, m_tx_buffer);
    m_outFormatter.displayOutgoing(m_tx_buffer);
    boost::asio::write(m_socket, boost::asio::buffer(m_tx_buffer));

    recvResponse();

    modbus::tcp::decoder_views::Header rsp_header_view(m_rx_buffer);

    if (rsp_header_view.isError())
        m_outFormatter.displayErrorResponse(m_tx_buffer, m_rx_buffer);
    else
        m_outFormatter.displayReadDiscreteInputs(m_tx_buffer, m_rx_buffer);
}

void ModbusClient::readInputRegisters(const modbus::tcp::Address& startAddress, const modbus::tcp::NumRegs& numRegs) {
    modbus::tcp::Encoder encoder(m_unitId, m_transactionId);

    encoder.encodeReadInputRegistersReq(startAddress, numRegs, m_tx_buffer);
    m_outFormatter.displayOutgoing(m_tx_buffer);
    boost::asio::write(m_socket, boost::asio::buffer(m_tx_buffer));

    recvResponse();

    modbus::tcp::decoder_views::Header rsp_header_view(m_rx_buffer);

    if (rsp_header_view.isError())
        m_outFormatter.displayErrorResponse(m_tx_buffer, m_rx_buffer);
    else
        m_outFormatter.displayReadInputRegisters(m_tx_buffer, m_rx_buffer);
}

void ModbusClient::recvResponse() {
    m_rx_buffer.resize(sizeof(modbus::tcp::Header));
    boost::asio::read(m_socket, boost::asio::buffer(m_rx_buffer));

    modbus::tcp::decoder_views::Header rsp_header_view(m_rx_buffer);
    uint16_t payload_size = rsp_header_view.getLength() - 2;
    m_rx_buffer.resize(sizeof(modbus::tcp::Header) + payload_size);
    uint8_t *payload = m_rx_buffer.data() + sizeof(modbus::tcp::Header);

    boost::asio::read(m_socket, boost::asio::buffer(payload, payload_size));
}

#endif
<|endoftext|>


<commit_before>// Copyright 2014 MongoDB Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#pragma once

#include <array>
#include <functional>
#include <iostream>
#include <memory>
#include <mutex>
#include <stack>
#include <thread>
#include <type_traits>
#include <unordered_map>
#include <vector>

#include <mongocxx/config/private/prelude.hh>

namespace mongocxx {
MONGOCXX_INLINE_NAMESPACE_BEGIN
namespace test_util {

template <typename T>
class mock;

template <typename R, typename... Args>
class mock<R (*)(Args...)> {
   public:
    using underlying_ptr = R (*)(Args...);
    using callback = std::function<R(Args...)>;
    using conditional = std::function<bool(Args...)>;

    class rule {
        friend class mock;

       public:
        rule(callback callback) : _callback(std::move(callback)) {
            times(1);
        }

        void times(int n) {
            until([n](Args...) mutable -> bool { return n-- > 0; });
        }

        void forever() {
            until([](Args...) { return true; });
        }

        void until(conditional conditional) {
            _conditional = std::move(conditional);
        }

       private:
        callback _callback;
        conditional _conditional;
    };

    class instance {
        friend class mock;

       public:
        instance(const instance&) = delete;
        instance& operator=(const instance&) = delete;

        ~instance() {
            _parent->destroy_active_instance();
        }

        // Interposing functions replace C-Driver functionality completely
        rule& interpose(const std::function<R(Args...)>& func) {
            _callbacks.emplace([func](Args... args) { return func(args...); });

            return _callbacks.top();
        }

        template <typename T, typename... U>
        typename std::enable_if<std::is_same<T, R>::value, rule&>::type interpose(T r, U... rs) {
            std::array<R, sizeof...(rs) + 1> vec = {r, rs...};
            std::size_t i = 0;

            _callbacks.emplace([vec, i](Args...) mutable -> R {
                if (i == vec.size()) {
                    i = 0;
                }
                return vec[i++];
            });
            _callbacks.top().times(vec.size());

            return _callbacks.top();
        }

        // Visiting functions get called in addition to the original C-Driver function
        rule& visit(std::function<void(Args...)> func) {
            _callbacks.emplace([=](Args... args) {
                func(args...);
                return _parent->_func(args...);
            });

            return _callbacks.top();
        }

        std::size_t depth() const {
            return _callbacks.size();
        }

        bool empty() const {
            return _callbacks.empty();
        }

       private:
        instance(mock* parent) : _parent(parent) {
        }

        mock* _parent;
        std::stack<rule> _callbacks;
    };

    friend class instance;

    mock(underlying_ptr func) : _func(std::move(func)) {
    }
    mock(mock&&) = delete;
    mock(const mock&) = delete;
    mock& operator=(const mock&) = delete;

    R operator()(Args... args) {
        auto instance = active_instance();
        if (instance) {
            while (!instance->_callbacks.empty()) {
                if (instance->_callbacks.top()._conditional(args...)) {
                    return instance->_callbacks.top()._callback(args...);
                }
                instance->_callbacks.pop();
            }
        }

        return _func(args...);
    }

    std::unique_ptr<instance> create_instance() {
        std::unique_ptr<instance> mock_instance(new instance(this));
        active_instance(mock_instance.get());
        return mock_instance;
    }

   private:
    instance* active_instance() {
        const auto id = std::this_thread::get_id();
        std::lock_guard<std::mutex> lock(_active_instances_lock);
        const auto iterator = _active_instances.find(id);
        if (iterator != _active_instances.end()) {
            return iterator->second;
        }
        return nullptr;
    }

    void active_instance(instance* instance) {
        const auto id = std::this_thread::get_id();
        std::lock_guard<std::mutex> lock(_active_instances_lock);

        auto& current = _active_instances[id];
        assert(!current);  // It is impossible to create two instances in a single thread
        current = instance;
    }

    void destroy_active_instance() {
        const auto id = std::this_thread::get_id();
        std::lock_guard<std::mutex> lock(_active_instances_lock);
        _active_instances.erase(id);
    }

    std::mutex _active_instances_lock;
    std::unordered_map<std::thread::id, instance*> _active_instances;
    const underlying_ptr _func;
};

}  // namespace test_util
MONGOCXX_INLINE_NAMESPACE_END
}  // namespace mongo

#include <mongocxx/config/private/postlude.hh>
<commit_msg>CXX-971 Fix incorrect comment in mock.hh<commit_after>// Copyright 2014 MongoDB Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#pragma once

#include <array>
#include <functional>
#include <iostream>
#include <memory>
#include <mutex>
#include <stack>
#include <thread>
#include <type_traits>
#include <unordered_map>
#include <vector>

#include <mongocxx/config/private/prelude.hh>

namespace mongocxx {
MONGOCXX_INLINE_NAMESPACE_BEGIN
namespace test_util {

template <typename T>
class mock;

template <typename R, typename... Args>
class mock<R (*)(Args...)> {
   public:
    using underlying_ptr = R (*)(Args...);
    using callback = std::function<R(Args...)>;
    using conditional = std::function<bool(Args...)>;

    class rule {
        friend class mock;

       public:
        rule(callback callback) : _callback(std::move(callback)) {
            times(1);
        }

        void times(int n) {
            until([n](Args...) mutable -> bool { return n-- > 0; });
        }

        void forever() {
            until([](Args...) { return true; });
        }

        void until(conditional conditional) {
            _conditional = std::move(conditional);
        }

       private:
        callback _callback;
        conditional _conditional;
    };

    class instance {
        friend class mock;

       public:
        instance(const instance&) = delete;
        instance& operator=(const instance&) = delete;

        ~instance() {
            _parent->destroy_active_instance();
        }

        // Interposing functions replace C-Driver functionality completely
        rule& interpose(const std::function<R(Args...)>& func) {
            _callbacks.emplace([func](Args... args) { return func(args...); });

            return _callbacks.top();
        }

        template <typename T, typename... U>
        typename std::enable_if<std::is_same<T, R>::value, rule&>::type interpose(T r, U... rs) {
            std::array<R, sizeof...(rs) + 1> vec = {r, rs...};
            std::size_t i = 0;

            _callbacks.emplace([vec, i](Args...) mutable -> R {
                if (i == vec.size()) {
                    i = 0;
                }
                return vec[i++];
            });
            _callbacks.top().times(vec.size());

            return _callbacks.top();
        }

        // Visiting functions get called in addition to the original C-Driver function
        rule& visit(std::function<void(Args...)> func) {
            _callbacks.emplace([=](Args... args) {
                func(args...);
                return _parent->_func(args...);
            });

            return _callbacks.top();
        }

        std::size_t depth() const {
            return _callbacks.size();
        }

        bool empty() const {
            return _callbacks.empty();
        }

       private:
        instance(mock* parent) : _parent(parent) {
        }

        mock* _parent;
        std::stack<rule> _callbacks;
    };

    friend class instance;

    mock(underlying_ptr func) : _func(std::move(func)) {
    }
    mock(mock&&) = delete;
    mock(const mock&) = delete;
    mock& operator=(const mock&) = delete;

    R operator()(Args... args) {
        auto instance = active_instance();
        if (instance) {
            while (!instance->_callbacks.empty()) {
                if (instance->_callbacks.top()._conditional(args...)) {
                    return instance->_callbacks.top()._callback(args...);
                }
                instance->_callbacks.pop();
            }
        }

        return _func(args...);
    }

    std::unique_ptr<instance> create_instance() {
        std::unique_ptr<instance> mock_instance(new instance(this));
        active_instance(mock_instance.get());
        return mock_instance;
    }

   private:
    instance* active_instance() {
        const auto id = std::this_thread::get_id();
        std::lock_guard<std::mutex> lock(_active_instances_lock);
        const auto iterator = _active_instances.find(id);
        if (iterator != _active_instances.end()) {
            return iterator->second;
        }
        return nullptr;
    }

    void active_instance(instance* instance) {
        const auto id = std::this_thread::get_id();
        std::lock_guard<std::mutex> lock(_active_instances_lock);

        auto& current = _active_instances[id];
        assert(!current);  // It is impossible to create two instances in a single thread
        current = instance;
    }

    void destroy_active_instance() {
        const auto id = std::this_thread::get_id();
        std::lock_guard<std::mutex> lock(_active_instances_lock);
        _active_instances.erase(id);
    }

    std::mutex _active_instances_lock;
    std::unordered_map<std::thread::id, instance*> _active_instances;
    const underlying_ptr _func;
};

}  // namespace test_util
MONGOCXX_INLINE_NAMESPACE_END
}  // namespace mongocxx

#include <mongocxx/config/private/postlude.hh>
<|endoftext|>


<commit_before>/* The MIT License:

Copyright (c) 2015 Ivan Gagis <igagis@gmail.com>

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE. */

// Home page: http://morda.googlecode.com

/**
 * @author Ivan Gagis <igagis@gmail.com>
 */

#pragma once

#include "Widget.hpp"
#include "List.hpp"

#include "containers/ScrollContainer.hpp"

namespace morda{

class TreeView :
		virtual public Widget,
		private ScrollContainer
{
	std::shared_ptr<List> list;
public:
	TreeView(const stob::Node* chain = nullptr);

	TreeView(const TreeView&) = delete;
	TreeView& operator=(const TreeView&) = delete;

	class ItemsProvider :
			public virtual ting::Shared,
			private List::ItemsProvider
	{
		friend class TreeView;

		TreeView* treeView = nullptr;
	protected:
		ItemsProvider(){}
	public:
		virtual ~ItemsProvider()noexcept{}

		virtual std::shared_ptr<Widget> getWidget(const std::vector<size_t>& path)const = 0;

		virtual void recycle(const std::vector<size_t>& path, std::shared_ptr<Widget> w)const{}

		virtual size_t count(const std::vector<size_t>& path)const noexcept = 0;

		void notifyDataSetChanged(){
			this->notifyDataSetChanged();
		}

		//TODO:
	};
private:

public:
	void setItemsProvider(std::shared_ptr<ItemsProvider> provider = nullptr);

};

}
<commit_msg>stuff<commit_after>/* The MIT License:

Copyright (c) 2015 Ivan Gagis <igagis@gmail.com>

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE. */

// Home page: http://morda.googlecode.com

/**
 * @author Ivan Gagis <igagis@gmail.com>
 */

#pragma once

#include "Widget.hpp"
#include "List.hpp"

#include "containers/ScrollContainer.hpp"

namespace morda{

class TreeView :
		virtual public Widget,
		private ScrollContainer
{
	std::shared_ptr<List> list;
public:
	TreeView(const stob::Node* chain = nullptr);

	TreeView(const TreeView&) = delete;
	TreeView& operator=(const TreeView&) = delete;

	class ItemsProvider :
			public virtual ting::Shared,
			private List::ItemsProvider
	{
		friend class TreeView;

	protected:
		ItemsProvider(){}
	public:
		virtual ~ItemsProvider()noexcept{}

		virtual std::shared_ptr<Widget> getWidget(const std::vector<size_t>& path)const = 0;

		virtual void recycle(const std::vector<size_t>& path, std::shared_ptr<Widget> w)const{}

		virtual size_t count(const std::vector<size_t>& path)const noexcept = 0;

		void notifyDataSetChanged(){
			this->List::ItemsProvider::notifyDataSetChanged();
		}

		//TODO:
	};
private:

public:
	void setItemsProvider(std::shared_ptr<ItemsProvider> provider = nullptr);

};

}
<|endoftext|>


<commit_before>/* Copyright (C) 2005-2011, Thorvald Natvig <thorvald@natvig.com>

   All rights reserved.

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

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

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

#include "mumble_pch.hpp"

#include "UserInformation.h"

#include "Audio.h"
#include "CELTCodec.h"
#include "Global.h"
#include "Net.h"
#include "ServerHandler.h"
#include "ViewCert.h"

static QString decode_utf8_qssl_string(const QString &input) {
	QString i = input;
	return QUrl::fromPercentEncoding(i.replace(QLatin1String("\\x"), QLatin1String("%")).toLatin1());
}

static QString decode_utf8_qssl_string(const QStringList &list) {
	if (list.count() > 0) {
		return decode_utf8_qssl_string(list.at(0));
	}
	return QString();
}

UserInformation::UserInformation(const MumbleProto::UserStats &msg, QWidget *p) : QDialog(p) {
	setupUi(this);

	uiSession = msg.session();

	qtTimer = new QTimer(this);
	connect(qtTimer, SIGNAL(timeout()), this, SLOT(tick()));
	qtTimer->start(6000);

	qgbConnection->setVisible(false);

	qlOpus->setText(tr("Not Reported"));

	update(msg);
	resize(sizeHint());

	qfCertificateFont = qlCertificate->font();
}

unsigned int UserInformation::session() const {
	return uiSession;
}

void UserInformation::tick() {
	if (bRequested)
		return;

	bRequested = true;

	g.sh->requestUserStats(uiSession, true);
}

void UserInformation::on_qpbCertificate_clicked() {
	ViewCert *vc = new ViewCert(qlCerts, this);
	vc->setWindowModality(Qt::WindowModal);
	vc->setAttribute(Qt::WA_DeleteOnClose, true);
	vc->show();
}

QString UserInformation::secsToString(unsigned int secs) {
	QStringList qsl;

	int weeks = secs / (60 * 60 * 24 * 7);
	secs = secs % (60 * 60 * 24 * 7);
	int days = secs / (60 * 60 * 24);
	secs = secs % (60 * 60 * 24);
	int hours = secs / (60 * 60);
	secs = secs % (60 * 60);
	int minutes = secs / 60;
	int seconds = secs % 60;

	if (weeks)
		qsl << tr("%1w").arg(weeks);
	if (days)
		qsl << tr("%1d").arg(days);
	if (hours)
		qsl << tr("%1h").arg(hours);
	if (minutes || hours)
		qsl << tr("%1m").arg(minutes);
	qsl << tr("%1s").arg(seconds);

	return qsl.join(QLatin1String(" "));
}

void UserInformation::update(const MumbleProto::UserStats &msg) {
	bRequested = false;

	bool showcon = false;

	ClientUser *cu = ClientUser::get(uiSession);
	if (cu)
		setWindowTitle(cu->qsName);

	if (msg.certificates_size() > 0) {
		showcon = true;
		qlCerts.clear();
		for (int i=0;i<msg.certificates_size(); ++i) {
			const std::string &s = msg.certificates(i);
			QList<QSslCertificate> certs = QSslCertificate::fromData(QByteArray(s.data(), static_cast<int>(s.length())), QSsl::Der);
			qlCerts <<certs;
		}
		if (! qlCerts.isEmpty()) {
			qpbCertificate->setEnabled(true);

			const QSslCertificate &cert = qlCerts.last();

#if QT_VERSION >= 0x050000
			const QMultiMap<QSsl::AlternativeNameEntryType, QString> &alts = cert.subjectAlternativeNames();
#else
			const QMultiMap<QSsl::AlternateNameEntryType, QString> &alts = cert.alternateSubjectNames();
#endif
			if (alts.contains(QSsl::EmailEntry))
				qlCertificate->setText(QStringList(alts.values(QSsl::EmailEntry)).join(tr(", ")));
			else
				qlCertificate->setText(decode_utf8_qssl_string(cert.subjectInfo(QSslCertificate::CommonName)));

			if (msg.strong_certificate()) {
				QFont f = qfCertificateFont;
				f.setBold(true);
				qlCertificate->setFont(f);
			} else {
				qlCertificate->setFont(qfCertificateFont);
			}
		} else {
			qpbCertificate->setEnabled(false);
			qlCertificate->setText(QString());
		}
	}
	if (msg.has_address()) {
		showcon = true;
		HostAddress ha(msg.address());
		qlAddress->setText(ha.toString());
	}
	if (msg.has_version()) {
		showcon = true;

		const MumbleProto::Version &mpv = msg.version();

		qlVersion->setText(tr("%1 (%2)").arg(MumbleVersion::toString(mpv.version())).arg(u8(mpv.release())));
		qlOS->setText(tr("%1 (%2)").arg(u8(mpv.os())).arg(u8(mpv.os_version())));
	}
	if (msg.celt_versions_size() > 0) {
		QStringList qsl;
		for (int i=0;i<msg.celt_versions_size(); ++i) {
			int v = msg.celt_versions(i);
			CELTCodec *cc = g.qmCodecs.value(v);
			if (cc)
				qsl << cc->version();
			else
				qsl << QString::number(v, 16);
		}
		qlCELT->setText(qsl.join(tr(", ")));
	}
	if (msg.has_opus()) {
		qlOpus->setText(msg.opus() ? tr("Supported") : tr("Not Supported"));
	}
	if (showcon)
		qgbConnection->setVisible(true);

	qlTCPCount->setText(QString::number(msg.tcp_packets()));
	qlUDPCount->setText(QString::number(msg.udp_packets()));

	qlTCPAvg->setText(QString::number(msg.tcp_ping_avg(), 'f', 2));
	qlUDPAvg->setText(QString::number(msg.udp_ping_avg(), 'f', 2));

	qlTCPVar->setText(QString::number(msg.tcp_ping_var() > 0.0f ? sqrtf(msg.tcp_ping_var()) : 0.0f, 'f', 2));
	qlUDPVar->setText(QString::number(msg.udp_ping_var() > 0.0f ? sqrtf(msg.udp_ping_var()) : 0.0f, 'f', 2));

	if (msg.has_from_client() && msg.has_from_server()) {
		qgbUDP->setVisible(true);
		const MumbleProto::UserStats_Stats &from = msg.from_client();
		qlFromGood->setText(QString::number(from.good()));
		qlFromLate->setText(QString::number(from.late()));
		qlFromLost->setText(QString::number(from.lost()));
		qlFromResync->setText(QString::number(from.resync()));

		const MumbleProto::UserStats_Stats &to = msg.from_server();
		qlToGood->setText(QString::number(to.good()));
		qlToLate->setText(QString::number(to.late()));
		qlToLost->setText(QString::number(to.lost()));
		qlToResync->setText(QString::number(to.resync()));

		quint32 allFromPackets = from.good() + from.late() + from.lost();
		qlFromLatePercent->setText(QString::number(allFromPackets > 0 ? from.late() * 100.0 / allFromPackets : 0., 'f', 2));
		qlFromLostPercent->setText(QString::number(allFromPackets > 0 ? from.lost() * 100.0 / allFromPackets : 0., 'f', 2));

		quint32 allToPackets = to.good() + to.late() + to.lost();
		qlToLatePercent->setText(QString::number(allToPackets > 0 ? to.late() * 100.0 / allToPackets : 0., 'f', 2));
		qlToLostPercent->setText(QString::number(allToPackets > 0 ? to.lost() * 100.0 / allToPackets : 0., 'f', 2));
	} else {
		qgbUDP->setVisible(false);
	}

	if (msg.has_onlinesecs()) {
		if (msg.has_idlesecs())
			qlTime->setText(tr("%1 online (%2 idle)").arg(secsToString(msg.onlinesecs()), secsToString(msg.idlesecs())));
		else
			qlTime->setText(tr("%1 online").arg(secsToString(msg.onlinesecs())));
	}
	if (msg.has_bandwidth()) {
		qlBandwidth->setVisible(true);
		qliBandwidth->setVisible(true);
		qlBandwidth->setText(tr("%1 kbit/s").arg(msg.bandwidth() / 125.0, 0, 'f', 1));
	} else {
		qlBandwidth->setVisible(false);
		qliBandwidth->setVisible(false);
		qlBandwidth->setText(QString());
	}
}
<commit_msg>UserInformation: only implement decode_utf8_qssl_string()'s QStringList override for Qt 5 builds.<commit_after>/* Copyright (C) 2005-2011, Thorvald Natvig <thorvald@natvig.com>

   All rights reserved.

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

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

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

#include "mumble_pch.hpp"

#include "UserInformation.h"

#include "Audio.h"
#include "CELTCodec.h"
#include "Global.h"
#include "Net.h"
#include "ServerHandler.h"
#include "ViewCert.h"

static QString decode_utf8_qssl_string(const QString &input) {
	QString i = input;
	return QUrl::fromPercentEncoding(i.replace(QLatin1String("\\x"), QLatin1String("%")).toLatin1());
}

#if QT_VERSION >= 0x050000
static QString decode_utf8_qssl_string(const QStringList &list) {
	if (list.count() > 0) {
		return decode_utf8_qssl_string(list.at(0));
	}
	return QString();
}
#endif

UserInformation::UserInformation(const MumbleProto::UserStats &msg, QWidget *p) : QDialog(p) {
	setupUi(this);

	uiSession = msg.session();

	qtTimer = new QTimer(this);
	connect(qtTimer, SIGNAL(timeout()), this, SLOT(tick()));
	qtTimer->start(6000);

	qgbConnection->setVisible(false);

	qlOpus->setText(tr("Not Reported"));

	update(msg);
	resize(sizeHint());

	qfCertificateFont = qlCertificate->font();
}

unsigned int UserInformation::session() const {
	return uiSession;
}

void UserInformation::tick() {
	if (bRequested)
		return;

	bRequested = true;

	g.sh->requestUserStats(uiSession, true);
}

void UserInformation::on_qpbCertificate_clicked() {
	ViewCert *vc = new ViewCert(qlCerts, this);
	vc->setWindowModality(Qt::WindowModal);
	vc->setAttribute(Qt::WA_DeleteOnClose, true);
	vc->show();
}

QString UserInformation::secsToString(unsigned int secs) {
	QStringList qsl;

	int weeks = secs / (60 * 60 * 24 * 7);
	secs = secs % (60 * 60 * 24 * 7);
	int days = secs / (60 * 60 * 24);
	secs = secs % (60 * 60 * 24);
	int hours = secs / (60 * 60);
	secs = secs % (60 * 60);
	int minutes = secs / 60;
	int seconds = secs % 60;

	if (weeks)
		qsl << tr("%1w").arg(weeks);
	if (days)
		qsl << tr("%1d").arg(days);
	if (hours)
		qsl << tr("%1h").arg(hours);
	if (minutes || hours)
		qsl << tr("%1m").arg(minutes);
	qsl << tr("%1s").arg(seconds);

	return qsl.join(QLatin1String(" "));
}

void UserInformation::update(const MumbleProto::UserStats &msg) {
	bRequested = false;

	bool showcon = false;

	ClientUser *cu = ClientUser::get(uiSession);
	if (cu)
		setWindowTitle(cu->qsName);

	if (msg.certificates_size() > 0) {
		showcon = true;
		qlCerts.clear();
		for (int i=0;i<msg.certificates_size(); ++i) {
			const std::string &s = msg.certificates(i);
			QList<QSslCertificate> certs = QSslCertificate::fromData(QByteArray(s.data(), static_cast<int>(s.length())), QSsl::Der);
			qlCerts <<certs;
		}
		if (! qlCerts.isEmpty()) {
			qpbCertificate->setEnabled(true);

			const QSslCertificate &cert = qlCerts.last();

#if QT_VERSION >= 0x050000
			const QMultiMap<QSsl::AlternativeNameEntryType, QString> &alts = cert.subjectAlternativeNames();
#else
			const QMultiMap<QSsl::AlternateNameEntryType, QString> &alts = cert.alternateSubjectNames();
#endif
			if (alts.contains(QSsl::EmailEntry))
				qlCertificate->setText(QStringList(alts.values(QSsl::EmailEntry)).join(tr(", ")));
			else
				qlCertificate->setText(decode_utf8_qssl_string(cert.subjectInfo(QSslCertificate::CommonName)));

			if (msg.strong_certificate()) {
				QFont f = qfCertificateFont;
				f.setBold(true);
				qlCertificate->setFont(f);
			} else {
				qlCertificate->setFont(qfCertificateFont);
			}
		} else {
			qpbCertificate->setEnabled(false);
			qlCertificate->setText(QString());
		}
	}
	if (msg.has_address()) {
		showcon = true;
		HostAddress ha(msg.address());
		qlAddress->setText(ha.toString());
	}
	if (msg.has_version()) {
		showcon = true;

		const MumbleProto::Version &mpv = msg.version();

		qlVersion->setText(tr("%1 (%2)").arg(MumbleVersion::toString(mpv.version())).arg(u8(mpv.release())));
		qlOS->setText(tr("%1 (%2)").arg(u8(mpv.os())).arg(u8(mpv.os_version())));
	}
	if (msg.celt_versions_size() > 0) {
		QStringList qsl;
		for (int i=0;i<msg.celt_versions_size(); ++i) {
			int v = msg.celt_versions(i);
			CELTCodec *cc = g.qmCodecs.value(v);
			if (cc)
				qsl << cc->version();
			else
				qsl << QString::number(v, 16);
		}
		qlCELT->setText(qsl.join(tr(", ")));
	}
	if (msg.has_opus()) {
		qlOpus->setText(msg.opus() ? tr("Supported") : tr("Not Supported"));
	}
	if (showcon)
		qgbConnection->setVisible(true);

	qlTCPCount->setText(QString::number(msg.tcp_packets()));
	qlUDPCount->setText(QString::number(msg.udp_packets()));

	qlTCPAvg->setText(QString::number(msg.tcp_ping_avg(), 'f', 2));
	qlUDPAvg->setText(QString::number(msg.udp_ping_avg(), 'f', 2));

	qlTCPVar->setText(QString::number(msg.tcp_ping_var() > 0.0f ? sqrtf(msg.tcp_ping_var()) : 0.0f, 'f', 2));
	qlUDPVar->setText(QString::number(msg.udp_ping_var() > 0.0f ? sqrtf(msg.udp_ping_var()) : 0.0f, 'f', 2));

	if (msg.has_from_client() && msg.has_from_server()) {
		qgbUDP->setVisible(true);
		const MumbleProto::UserStats_Stats &from = msg.from_client();
		qlFromGood->setText(QString::number(from.good()));
		qlFromLate->setText(QString::number(from.late()));
		qlFromLost->setText(QString::number(from.lost()));
		qlFromResync->setText(QString::number(from.resync()));

		const MumbleProto::UserStats_Stats &to = msg.from_server();
		qlToGood->setText(QString::number(to.good()));
		qlToLate->setText(QString::number(to.late()));
		qlToLost->setText(QString::number(to.lost()));
		qlToResync->setText(QString::number(to.resync()));

		quint32 allFromPackets = from.good() + from.late() + from.lost();
		qlFromLatePercent->setText(QString::number(allFromPackets > 0 ? from.late() * 100.0 / allFromPackets : 0., 'f', 2));
		qlFromLostPercent->setText(QString::number(allFromPackets > 0 ? from.lost() * 100.0 / allFromPackets : 0., 'f', 2));

		quint32 allToPackets = to.good() + to.late() + to.lost();
		qlToLatePercent->setText(QString::number(allToPackets > 0 ? to.late() * 100.0 / allToPackets : 0., 'f', 2));
		qlToLostPercent->setText(QString::number(allToPackets > 0 ? to.lost() * 100.0 / allToPackets : 0., 'f', 2));
	} else {
		qgbUDP->setVisible(false);
	}

	if (msg.has_onlinesecs()) {
		if (msg.has_idlesecs())
			qlTime->setText(tr("%1 online (%2 idle)").arg(secsToString(msg.onlinesecs()), secsToString(msg.idlesecs())));
		else
			qlTime->setText(tr("%1 online").arg(secsToString(msg.onlinesecs())));
	}
	if (msg.has_bandwidth()) {
		qlBandwidth->setVisible(true);
		qliBandwidth->setVisible(true);
		qlBandwidth->setText(tr("%1 kbit/s").arg(msg.bandwidth() / 125.0, 0, 'f', 1));
	} else {
		qlBandwidth->setVisible(false);
		qliBandwidth->setVisible(false);
		qlBandwidth->setText(QString());
	}
}
<|endoftext|>


<commit_before>// Copyright (C) 2011, James Webber.
// Distributed under a 3-clause BSD license.  See COPYING.
#ifndef CONFIG_C_STRING_HPP_i8ip7xsm
#define CONFIG_C_STRING_HPP_i8ip7xsm
#include "../util/asserts.hpp"

#include <cstring>

//! Something we can put in a map.
struct c_string {
  explicit c_string(const char *c) : str_(NERVE_CHECK_PTR(c)) {}
  bool operator<(const c_string &c) const { return std::strcmp(c.str_, this->str_) < 0; }
  const char *c_str() { return str_; }
  private:
  const char *str_;
};

#endif
<commit_msg>Remove oboslete file (it's in util already).<commit_after><|endoftext|>


<commit_before>#include <iostream>
#include <vector>

#include "../engines/physics/projectile.h"
#include "../classes/ship.h"
#include "netpacket.h"
#include "packetprotos.pb.h"

using namespace std;

void build_ship(Ship *ship) {
	vector<float> pos { 1,2,3 };
	ship->set_d(pos);
	vector<float> vel { 4,5,6 };
	ship->set_v(vel);
	vector<float> accel { 7,8,9 };
	ship->set_a(accel);

	vector<float> pitch { 10,11,12 };
	ship->set_p(pitch);
	vector<float> yaw { 13,14,15 };
	ship->set_y(yaw);
	vector<float> roll { 16,17,18 };
	ship->set_r(roll);

	ship->set_p_dot(6.6);
	ship->set_y_dot(8.8);
	ship->set_r_dot(7.7);
}

int get_packet_type_test() {

	// Build NetPacket
	NetPacket packet;
	protos::GeneralPacket gen_packet;
	Ship ship(1, 1, 2.0, 2.0);
	build_ship(&ship);

	// Build Ship Init Packet
	protos::ShipInitPacket ship_init_packet;
	protos::RenderedObj *ship_packet = ship_init_packet.mutable_ship();
	PacketUtils::fill_obj_packet(ship_packet, &ship);
	string *serialized_ship_init_packet = gen_packet.mutable_packet();
	ship_init_packet.SerializeToString(serialized_ship_init_packet);

	// Build General Packet
	gen_packet.set_packettype(PacketType::SHIP_INIT);
	string serialized_gen_packet;
	gen_packet.SerializeToString(&serialized_gen_packet);
	packet.packet_len = sizeof(int) + sizeof(serialized_gen_packet);
	packet.serialized_packet = serialized_gen_packet;

	// Read from NetPacket
	protos::GeneralPacket parsed_gen_packet;
	if (!parsed_gen_packet.ParseFromString(packet.serialized_packet))
		return 1;
	if (parsed_gen_packet.packettype() != PacketType::SHIP_INIT)
		return 1;

	cout << "get_packet_type test Passed!" << endl;
	return 0;
}

int get_packet_payload_test() {
	// Build NetPacket
	NetPacket packet;
	protos::GeneralPacket gen_packet;
	Ship ship(1, 1, 2.0, 2.0);
	build_ship(&ship);

	// Build Ship Init Packet
	protos::ShipInitPacket ship_init_packet;
	protos::RenderedObj *ship_packet = ship_init_packet.mutable_ship();
	PacketUtils::fill_obj_packet(ship_packet, &ship);
	string *serialized_ship_init_packet = gen_packet.mutable_packet();
	ship_init_packet.SerializeToString(serialized_ship_init_packet);

	// Build General Packet
	gen_packet.set_packettype(PacketType::SHIP_INIT);
	string serialized_gen_packet;
	gen_packet.SerializeToString(&serialized_gen_packet);
	packet.packet_len = sizeof(int) + sizeof(serialized_gen_packet);
	packet.serialized_packet = serialized_gen_packet;

	// Call get_packet_payload on packet
	protos::ShipInitPacket parsed_ship_init_packet;
	PacketUtils::get_packet_payload(packet, (void *) &parsed_ship_init_packet);

	// Read get_packet_payload output
	// (TODO): Do this test with other types of packets (not just objects)
	string serialized_new_ship_packet;
	parsed_ship_init_packet.ship().SerializeToString(&serialized_new_ship_packet);
	string serialized_ship_packet;
	ship_packet->SerializeToString(&serialized_ship_packet);
	if (serialized_ship_packet.compare(serialized_new_ship_packet) != 0)
		return 1;

	cout << "get_packet_payload test Passed!" << endl;
	return 0;
}

int make_packet_test() {

	// Build packet
	Ship ship(1, 1, 2.0, 2.0);
	build_ship(&ship);
	protos::RenderedObj ship_packet;
	PacketUtils::fill_obj_packet(&ship_packet, &ship);
	NetPacket packet;
	PacketUtils::make_packet(&packet, PacketType::SHIP_INIT, (void *) &ship, NULL);

	// Check packet length
	if (packet.packet_len != sizeof(int) + sizeof(packet.serialized_packet))
		return 1;

	// Check general packet contents
	protos::ShipInitPacket parsed_ship_init_packet;
	PacketUtils::get_packet_payload(packet, (void *) &parsed_ship_init_packet);

	// Read get_packet_payload output
	// (TODO): Do this test with other types of packets (not just ship_init packets)
	string serialized_new_ship_packet;
	parsed_ship_init_packet.ship().SerializeToString(&serialized_new_ship_packet);
	string serialized_ship_packet;
	ship_packet.SerializeToString(&serialized_ship_packet);
	if (serialized_ship_packet.compare(serialized_new_ship_packet) != 0)
		return 1;
	protos::RenderedObj ship_obj;
	ship_obj.ParseFromString(serialized_new_ship_packet);
	cout << "make_packet test Passed!" << endl;
	return 0;
}

int fill_obj_packet_test() {

	Ship ship(1, 1, 2.0, 2.0);
	build_ship(&ship);

	protos::RenderedObj ship_packet;
	PacketUtils::fill_obj_packet(&ship_packet, &ship);

	if (ship_packet.id() != (unsigned) ship.get_id())
		return 1;
	if (ship_packet.mass() != (unsigned) ship.get_mass())
		return 1;
	if (ship_packet.cur_tolerance() != ship.get_cur_tolerance())
		return 1;
	if (ship_packet.max_tolerance() != ship.get_max_tolerance())
		return 1;
	// TODO - ADD IS_DESTROYED TEST

	vector<float> pos_vec;
	pos_vec.push_back(ship_packet.pos().x());
	pos_vec.push_back(ship_packet.pos().y());
	pos_vec.push_back(ship_packet.pos().z());
	if (pos_vec != ship.get_d())
		return 1;

	vector<float> vel_vec;
	vel_vec.push_back(ship_packet.vel().x());
	vel_vec.push_back(ship_packet.vel().y());
	vel_vec.push_back(ship_packet.vel().z());
	if (vel_vec != ship.get_v())
		return 1;

	vector<float> accel_vec;
	accel_vec.push_back(ship_packet.accel().x());
	accel_vec.push_back(ship_packet.accel().y());
	accel_vec.push_back(ship_packet.accel().z());
	if (accel_vec != ship.get_a())
		return 1;

	vector<float> pitch_vec;
	pitch_vec.push_back(ship_packet.pitch().x());
	pitch_vec.push_back(ship_packet.pitch().y());
	pitch_vec.push_back(ship_packet.pitch().z());
	if (pitch_vec != ship.get_p())
		return 1;

	vector<float> yaw_vec;
	yaw_vec.push_back(ship_packet.yaw().x());
	yaw_vec.push_back(ship_packet.yaw().y());
	yaw_vec.push_back(ship_packet.yaw().z());
	if (yaw_vec != ship.get_y())
		return 1;

	vector<float> roll_vec;
	roll_vec.push_back(ship_packet.roll().x());
	roll_vec.push_back(ship_packet.roll().y());
	roll_vec.push_back(ship_packet.roll().z());
	if (roll_vec != ship.get_r())
		return 1;

	cout << "fill_obj_packet test Passed!" << endl;
	return 0;
}

int main() {
	int return_val;
	return_val = fill_obj_packet_test();
	return_val = get_packet_type_test();
	return_val = get_packet_payload_test();
	return_val = make_packet_test();
	if (return_val == 1)
		cout << "NET PACKET TEST FAILED!" << endl;
	else
		cout << "NET PACKET TEST PASSED!" << endl;
	return 0;
}
<commit_msg>Changing network packet testing interface<commit_after>#include <iostream>
#include <vector>

#include "../engines/physics/projectile.h"
#include "../classes/ship.h"
#include "netpacket.h"
#include "packetprotos.pb.h"

using namespace std;

void build_ship(Ship *ship) {
	vector<float> pos { 1,2,3 };
	ship->set_d(pos);
	vector<float> vel { 4,5,6 };
	ship->set_v(vel);
	vector<float> accel { 7,8,9 };
	ship->set_a(accel);

	vector<float> pitch { 10,11,12 };
	ship->set_p(pitch);
	vector<float> yaw { 13,14,15 };
	ship->set_y(yaw);
	vector<float> roll { 16,17,18 };
	ship->set_r(roll);

	ship->set_p_dot(6.6);
	ship->set_y_dot(8.8);
	ship->set_r_dot(7.7);
}

int get_packet_type_test() {

	// Build NetPacket
	NetPacket packet;
	protos::GeneralPacket gen_packet;
	Ship ship(1, 1, 2.0, 2.0);
	build_ship(&ship);

	// Build Ship Init Packet
	protos::ShipInitPacket ship_init_packet;
	protos::RenderedObj *ship_packet = ship_init_packet.mutable_ship();
	PacketUtils::fill_obj_packet(ship_packet, &ship);
	string *serialized_ship_init_packet = gen_packet.mutable_packet();
	ship_init_packet.SerializeToString(serialized_ship_init_packet);

	// Build General Packet
	gen_packet.set_packettype(PacketType::SHIP_INIT);
	string serialized_gen_packet;
	gen_packet.SerializeToString(&serialized_gen_packet);
	packet.packet_len = sizeof(int) + sizeof(serialized_gen_packet);
	packet.serialized_packet = serialized_gen_packet;

	// Read from NetPacket
	protos::GeneralPacket parsed_gen_packet;
	if (!parsed_gen_packet.ParseFromString(packet.serialized_packet))
		return 1;
	if (parsed_gen_packet.packettype() != PacketType::SHIP_INIT)
		return 1;

	cout << "get_packet_type test Passed!" << endl;
	return 0;
}

int get_packet_payload_test() {
	// Build NetPacket
	NetPacket packet;
	protos::GeneralPacket gen_packet;
	Ship ship(1, 1, 2.0, 2.0);
	build_ship(&ship);

	// Build Ship Init Packet
	protos::ShipInitPacket ship_init_packet;
	protos::RenderedObj *ship_packet = ship_init_packet.mutable_ship();
	PacketUtils::fill_obj_packet(ship_packet, &ship);
	string *serialized_ship_init_packet = gen_packet.mutable_packet();
	ship_init_packet.SerializeToString(serialized_ship_init_packet);

	// Build General Packet
	gen_packet.set_packettype(PacketType::SHIP_INIT);
	string serialized_gen_packet;
	gen_packet.SerializeToString(&serialized_gen_packet);
	packet.packet_len = sizeof(int) + sizeof(serialized_gen_packet);
	packet.serialized_packet = serialized_gen_packet;

	// Call get_packet_payload on packet
	protos::ShipInitPacket parsed_ship_init_packet;
	PacketUtils::get_packet_payload(packet, (void *) &parsed_ship_init_packet);

	// Read get_packet_payload output
	// (TODO): Do this test with other types of packets (not just objects)
	string serialized_new_ship_packet;
	parsed_ship_init_packet.ship().SerializeToString(&serialized_new_ship_packet);
	string serialized_ship_packet;
	ship_packet->SerializeToString(&serialized_ship_packet);
	if (serialized_ship_packet.compare(serialized_new_ship_packet) != 0)
		return 1;

	cout << "get_packet_payload test Passed!" << endl;
	return 0;
}

int make_packet_test() {

	// Build packet
	Ship ship(1, 1, 2.0, 2.0);
	build_ship(&ship);
	protos::RenderedObj ship_packet;
	PacketUtils::fill_obj_packet(&ship_packet, &ship);
	NetPacket packet;
	PacketUtils::make_packet(&packet, PacketType::SHIP_INIT, (void *) &ship, NULL);

	// Check packet length
	if (packet.packet_len != sizeof(int) + sizeof(packet.serialized_packet))
		return 1;

	// Check general packet contents
	protos::ShipInitPacket parsed_ship_init_packet;
	PacketUtils::get_packet_payload(packet, (void *) &parsed_ship_init_packet);

	// Read get_packet_payload output
	// (TODO): Do this test with other types of packets (not just ship_init packets)
	string serialized_new_ship_packet;
	parsed_ship_init_packet.ship().SerializeToString(&serialized_new_ship_packet);
	string serialized_ship_packet;
	ship_packet.SerializeToString(&serialized_ship_packet);
	if (serialized_ship_packet.compare(serialized_new_ship_packet) != 0)
		return 1;
	protos::RenderedObj ship_obj;
	ship_obj.ParseFromString(serialized_new_ship_packet);
	cout << "make_packet test Passed!" << endl;
	return 0;
}

int fill_obj_packet_test() {

	Ship ship(1, 1, 2.0, 2.0);
	build_ship(&ship);

	protos::RenderedObj ship_packet;
	PacketUtils::fill_obj_packet(&ship_packet, &ship);

	if (ship_packet.id() != (unsigned) ship.get_id())
		return 1;
	if (ship_packet.mass() != (unsigned) ship.get_mass())
		return 1;
	if (ship_packet.cur_tolerance() != ship.get_cur_tolerance())
		return 1;
	if (ship_packet.max_tolerance() != ship.get_max_tolerance())
		return 1;
	// TODO - ADD IS_DESTROYED TEST

	vector<float> pos_vec;
	pos_vec.push_back(ship_packet.pos().x());
	pos_vec.push_back(ship_packet.pos().y());
	pos_vec.push_back(ship_packet.pos().z());
	if (pos_vec != ship.get_d())
		return 1;

	vector<float> vel_vec;
	vel_vec.push_back(ship_packet.vel().x());
	vel_vec.push_back(ship_packet.vel().y());
	vel_vec.push_back(ship_packet.vel().z());
	if (vel_vec != ship.get_v())
		return 1;

	vector<float> accel_vec;
	accel_vec.push_back(ship_packet.accel().x());
	accel_vec.push_back(ship_packet.accel().y());
	accel_vec.push_back(ship_packet.accel().z());
	if (accel_vec != ship.get_a())
		return 1;

	vector<float> pitch_vec;
	pitch_vec.push_back(ship_packet.pitch().x());
	pitch_vec.push_back(ship_packet.pitch().y());
	pitch_vec.push_back(ship_packet.pitch().z());
	if (pitch_vec != ship.get_p())
		return 1;

	vector<float> yaw_vec;
	yaw_vec.push_back(ship_packet.yaw().x());
	yaw_vec.push_back(ship_packet.yaw().y());
	yaw_vec.push_back(ship_packet.yaw().z());
	if (yaw_vec != ship.get_y())
		return 1;

	vector<float> roll_vec;
	roll_vec.push_back(ship_packet.roll().x());
	roll_vec.push_back(ship_packet.roll().y());
	roll_vec.push_back(ship_packet.roll().z());
	if (roll_vec != ship.get_r())
		return 1;

	cout << "fill_obj_packet test Passed!" << endl;
	return 0;
}

int main() {
	int return_val = 0;
	return_val += fill_obj_packet_test();
	return_val += get_packet_type_test();
	return_val += get_packet_payload_test();
	return_val += make_packet_test();
	if (return_val == 4)
		cout << "NET PACKET TEST FAILED!" << endl;
	else
		cout << "NET PACKET TEST PASSED!" << endl;
	return 0;
}
<|endoftext|>


<commit_before>#include <stdio.h>
#include <string>
using std::string;

#include "nmranet/ConfigRepresentation.hxx"
#include "config.hxx"

#include "utils/StringPrintf.cxx"

//nmranet::ConfigDef def(0);

RENDER_CDI(nmranet, ConfigDef, "CDI", 1);

template <int N> void render_all_cdi() {
    printf("// skipping config %d\n", N);
    render_all_cdi<N-1>();
}

template <typename CdiType>
void render_cdi_helper(const CdiType &t, string ns, string name)
{
    string payload;
    t.config_renderer().render_cdi(&payload);
    printf("namespace %s {\n\nextern const char %s_DATA[];\n", ns.c_str(),
        name.c_str());
    printf("// This is a C++11 raw string.\n");
    printf("const char %s_DATA[] = R\"xmlpayload(%s)xmlpayload\";\n",
        name.c_str(), payload.c_str());
    printf("extern const size_t %s_SIZE;\n", name.c_str());
    printf("const size_t %s_SIZE = sizeof(%s_DATA);\n", name.c_str(),
        name.c_str());
    printf("\n}  // namespace %s\n\n", ns.c_str());
}

int main(int argc, char *argv[])
{
    printf(R"(
/* Generated code based off of config.hxx */

#include <cstdint>
#include <unistd.h>

)");

    render_all_cdi<10>();
/*    render_all_cdi<9>();
    render_all_cdi<8>();
    render_all_cdi<7>();
    render_all_cdi<6>();
    render_all_cdi<5>();
    render_all_cdi<4>();
    render_all_cdi<3>();
    render_all_cdi<2>();
    render_all_cdi<1>();*/

    /*
      string cdi;
    def.config_renderer().render_cdi(&cdi);

    printf("%s", cdi.c_str());

    std::vector<unsigned> event_offsets;
    def.handle_events([&event_offsets](unsigned o)
        {
            event_offsets.push_back(o);
        });
    printf("<!-- events: ");
    for (unsigned o : event_offsets)
    {
        printf("%u,", o);
    }
    printf("-->\n");
    */
    return 0;
}
<commit_msg>Adds a feature to CompileCdiMain to force dumping the XML files into separate .xmlout files instead of generating the c++ output. This can be helpful in some cases where we ship the files manually.<commit_after>#include <stdio.h>
#include <string>
using std::string;

#include "nmranet/ConfigRepresentation.hxx"
#include "config.hxx"

#include "utils/StringPrintf.cxx"
#include "utils/FileUtils.hxx"

bool raw_render = false;

// nmranet::ConfigDef def(0);

RENDER_CDI(nmranet, ConfigDef, "CDI", 1);

template <int N> void render_all_cdi()
{
    printf("// skipping config %d\n", N);
    render_all_cdi<N - 1>();
}

template <typename CdiType>
void render_cdi_helper(const CdiType &t, string ns, string name)
{
    string payload;
    t.config_renderer().render_cdi(&payload);
    if (raw_render)
    {
        string filename = name + ".xmlout";
        printf("Writing %d bytes to %s\n", (int)payload.size(),
            filename.c_str());
        write_string_to_file(filename, payload);
    }
    else
    {
        printf("namespace %s {\n\nextern const char %s_DATA[];\n", ns.c_str(),
            name.c_str());
        printf("// This is a C++11 raw string.\n");
        printf("const char %s_DATA[] = R\"xmlpayload(%s)xmlpayload\";\n",
            name.c_str(), payload.c_str());
        printf("extern const size_t %s_SIZE;\n", name.c_str());
        printf("const size_t %s_SIZE = sizeof(%s_DATA);\n", name.c_str(),
            name.c_str());
        printf("\n}  // namespace %s\n\n", ns.c_str());
    }
}

int main(int argc, char *argv[])
{
    if (argc > 1 && string(argv[1]) == "-r")
    {
        raw_render = true;
    }
    else
    {
        printf(R"(
/* Generated code based off of config.hxx */

#include <cstdint>
#include <unistd.h>

)");
    }

    render_all_cdi<10>();
    /*    render_all_cdi<9>();
        render_all_cdi<8>();
        render_all_cdi<7>();
        render_all_cdi<6>();
        render_all_cdi<5>();
        render_all_cdi<4>();
        render_all_cdi<3>();
        render_all_cdi<2>();
        render_all_cdi<1>();*/

    /*
      string cdi;
    def.config_renderer().render_cdi(&cdi);

    printf("%s", cdi.c_str());

    std::vector<unsigned> event_offsets;
    def.handle_events([&event_offsets](unsigned o)
        {
            event_offsets.push_back(o);
        });
    printf("<!-- events: ");
    for (unsigned o : event_offsets)
    {
        printf("%u,", o);
    }
    printf("-->\n");
    */
    return 0;
}
<|endoftext|>


<commit_before>#include "opt/sched/bb_scheduler.h"

#include "design/resource_attr.h"
#include "iroha/i_design.h"
#include "iroha/resource_class.h"
#include "opt/bb_set.h"
#include "opt/delay_info.h"
#include "opt/sched/bb_data_path.h"
#include "opt/sched/data_path_set.h"
#include "opt/sched/path_node.h"
#include "opt/sched/resource_conflict_tracker.h"
#include "opt/sched/resource_tracker.h"

namespace iroha {
namespace opt {
namespace sched {

BBScheduler::BBScheduler(BBDataPath *data_path, DelayInfo *delay_info,
			 ResourceConflictTracker *conflict_tracker)
  : data_path_(data_path), delay_info_(delay_info),
    conflict_tracker_(conflict_tracker),
    resource_tracker_(new BBResourceTracker()) {
}

BBScheduler::~BBScheduler() {
}

bool BBScheduler::IsSchedulable() {
  // TODO: We might split a basic block before/after special insns, because
  // this is too awkward.
  BB *bb = data_path_->GetBB();
  for (IState *st : bb->states_) {
    for (IInsn *insn : st->insns_) {
      if (ResourceAttr::IsMultiCycleInsn(insn)) {
	return false;
      }
      if (ResourceAttr::IsExtAccessInsn(insn) ||
	  ResourceAttr::IsExtWaitInsn(insn)) {
	return false;
      }
      auto rc = *(insn->GetResource()->GetClass());
      if (resource::IsExtCombinational(rc)) {
	return false;
      }
      // This is really awkward...
      if (insn->depending_insns_.size() > 0) {
	return false;
      }
    }
  }
  return true;
}

void BBScheduler::Schedule() {
  if (!IsSchedulable()) {
    return;
  }
  ClearSchedule();
  // Sort by accumlated latency from leafs.
  int num_states = data_path_->GetBB()->states_.size();
  auto &nodes = data_path_->GetNodes();
  for (auto &p : nodes) {
    PathNode *n = p.second;
    if (n->IsTransition()) {
      // Schedule transition insns in the original order.
      // (optional: schedule them earlier than other insns by using
      // negative sort key)
      int idx = n->GetInitialStIndex() - num_states;
      sorted_nodes_[idx].push_back(n);
    } else {
      sorted_nodes_[n->GetAccumlatedDelayFromLeaf()].push_back(n);
    }
  }
  // Iterate from leafs.
  bool has_unscheduled;
  do {
    has_unscheduled = false;
    for (auto &lt : sorted_nodes_) {
      auto &ev = lt.second;
      for (auto *n : ev) {
	if (!ScheduleNode(n)) {
	  has_unscheduled = true;
	}
      }
    }
  } while (has_unscheduled);
}

bool BBScheduler::ScheduleNode(PathNode *n) {
  if (n->GetFinalStIndex() > -1) {
    // already scheduled.
    return true;
  }
  // Minimum state index by src register position.
  int min_st_index = GetMinStIndex(n);
  if (min_st_index < 0) {
    return false;
  }
  // Ordering of memory access.
  if (!CheckPrecedingNodesOfSameResource(n)) {
    return false;
  }
  // Calculates local delay.
  if (n->GetInsn()->GetResource()->GetClass()->IsExclusive()) {
    ScheduleExclusive(n, min_st_index);
  } else {
    ScheduleNonExclusive(n, min_st_index);
  }

  return true;
}

int BBScheduler::GetMinStIndex(PathNode *n) {
  cout << n->GetInsn()->GetId() << "\n";
  // Checks if all preceding nodes (W->W, W->R, R->W) are scheduled.
  for (auto &s : n->source_edges_) {
    PathEdge *edge = s.second;
    PathNode *source_node = edge->GetSourceNode();
    // cout << " " << source_node->GetInsn()->GetId() << " " << edge->GetType() << "\n";
    if (source_node->GetFinalStIndex() < 0) {
      // Not yet scheduled. Fail and try later again.
      return -1;
    }
  }
  // Determines the location.
  int min_st_index = 0;
  for (auto &s : n->source_edges_) {
    PathEdge *edge = s.second;
    if (!edge->IsWtoR()) {
      continue;
    }
    PathNode *source_node = edge->GetSourceNode();
    if (min_st_index < source_node->GetFinalStIndex()) {
      min_st_index = source_node->GetFinalStIndex();
    }
    if (min_st_index == source_node->GetFinalStIndex()) {
      int tmp_local_delay =
	source_node->state_local_delay_ + n->GetNodeDelay();
      if (tmp_local_delay > delay_info_->GetMaxDelay()) {
	// Local margin is not sufficient. Go to the next state.
	++min_st_index;
      }
    }
  }
  int t = GetMinStByPrecedingNodeOfSameResource(n);
  if (t >= 0) {
    if (t > min_st_index) {
      min_st_index = t;
    }
  }
  int u = GetMinStByEdgeDependency(n);
  if (u >= 0) {
    if (u >= min_st_index) {
      min_st_index = u;
    }
  }
  return min_st_index;
}

int BBScheduler::GetLocalDelayBeforeNode(PathNode *n, int st_index) {
  int source_local_delay = 0;
  for (auto &s : n->source_edges_) {
    PathEdge *edge = s.second;
    if (!edge->IsWtoR()) {
      continue;
    }
    PathNode *source_node = edge->GetSourceNode();
    if (source_node->GetFinalStIndex() < st_index) {
      continue;
    }
    if (source_local_delay < source_node->state_local_delay_) {
      source_local_delay = source_node->state_local_delay_;
    }
  }
  return source_local_delay;
}

void BBScheduler::ClearSchedule() {
  auto &nodes = data_path_->GetNodes();
  for (auto &p : nodes) {
    PathNode *n = p.second;
    n->SetFinalStIndex(-1);
    n->state_local_delay_ = 0;
  }
}

void BBScheduler::ScheduleExclusive(PathNode *n, int min_st_index) {
  int loc = min_st_index;
  // Tries to find a state index where this node can use the resource.
  while (true) {
    if (resource_tracker_->CanUseResource(n, loc)) {
      resource_tracker_->AllocateResource(n, loc);
      break;
    }
    ++loc;
  }
  n->state_local_delay_ = n->GetNodeDelay();
  bool has_conflict = true;
  if (loc == min_st_index) {
    has_conflict = false;
    n->state_local_delay_ += GetLocalDelayBeforeNode(n, min_st_index);
  }
  conflict_tracker_->AddUsage(n, has_conflict);
  n->SetFinalStIndex(loc);
}

void BBScheduler::ScheduleNonExclusive(PathNode *n, int st_index) {
  // Just place the insn at st_index.
  n->SetFinalStIndex(st_index);
  int source_local_delay = GetLocalDelayBeforeNode(n, st_index);
  n->state_local_delay_ = source_local_delay + n->GetNodeDelay();
}

int BBScheduler::GetMinStByEdgeDependency(PathNode *n) {
  int min = -1;
  for (auto &s : n->source_edges_) {
    PathEdge *edge = s.second;
    // This takes care of W->W or R->W.
    if (edge->IsWtoR()) {
      continue;
    }
    PathNode *source_node = edge->GetSourceNode();
    if (source_node->GetFinalStIndex() > min) {
      min = source_node->GetFinalStIndex();
    }
  }
  if (min >= 0) {
    return min + 1;
  }
  return -1;
}

bool BBScheduler::CheckPrecedingNodesOfSameResource(PathNode *n) {
  IResource *res = n->GetInsn()->GetResource();
  if (!ResourceAttr::IsOrderedResource(res)) {
    // Skips normal resources (other than array access or so on).
    return true;
  }
  int idx = GetMinStByPrecedingNodeOfSameResource(n);
  if (idx < 0) {
    // Preceding node is not scheduled.
    return false;
  }
  return true;
}

int BBScheduler::GetMinStByPrecedingNodeOfSameResource(PathNode *n) {
  IResource *res = n->GetInsn()->GetResource();
  if (!ResourceAttr::IsOrderedResource(res)) {
    return -1;
  }
  auto &m = data_path_->GetResourceNodeMap(res);
  auto it = m.find(n->GetInitialStIndex());
  if (it == m.begin()) {
    return 0;
  }
  it--;
  PathNode *prev = it->second;
  int st_index = prev->GetFinalStIndex();
  if (st_index > -1) {
    return st_index + 1;
  }
  return -1;
}

}  // namespace sched
}  // namespace opt
}  // namespace iroha
<commit_msg>Enable instruction scheduler for depending insns.<commit_after>#include "opt/sched/bb_scheduler.h"

#include "design/resource_attr.h"
#include "iroha/i_design.h"
#include "iroha/resource_class.h"
#include "opt/bb_set.h"
#include "opt/delay_info.h"
#include "opt/sched/bb_data_path.h"
#include "opt/sched/data_path_set.h"
#include "opt/sched/path_node.h"
#include "opt/sched/resource_conflict_tracker.h"
#include "opt/sched/resource_tracker.h"

namespace iroha {
namespace opt {
namespace sched {

BBScheduler::BBScheduler(BBDataPath *data_path, DelayInfo *delay_info,
			 ResourceConflictTracker *conflict_tracker)
  : data_path_(data_path), delay_info_(delay_info),
    conflict_tracker_(conflict_tracker),
    resource_tracker_(new BBResourceTracker()) {
}

BBScheduler::~BBScheduler() {
}

bool BBScheduler::IsSchedulable() {
  BB *bb = data_path_->GetBB();
  for (IState *st : bb->states_) {
    for (IInsn *insn : st->insns_) {
      if (ResourceAttr::IsMultiCycleInsn(insn)) {
	return false;
      }
      if (ResourceAttr::IsExtAccessInsn(insn) ||
	  ResourceAttr::IsExtWaitInsn(insn)) {
	return false;
      }
      auto rc = *(insn->GetResource()->GetClass());
      if (resource::IsExtCombinational(rc)) {
	return false;
      }
    }
  }
  return true;
}

void BBScheduler::Schedule() {
  if (!IsSchedulable()) {
    return;
  }
  ClearSchedule();
  // Sort by accumlated latency from leafs.
  int num_states = data_path_->GetBB()->states_.size();
  auto &nodes = data_path_->GetNodes();
  for (auto &p : nodes) {
    PathNode *n = p.second;
    if (n->IsTransition()) {
      // Schedule transition insns in the original order.
      // (optional: schedule them earlier than other insns by using
      // negative sort key)
      int idx = n->GetInitialStIndex() - num_states;
      sorted_nodes_[idx].push_back(n);
    } else {
      sorted_nodes_[n->GetAccumlatedDelayFromLeaf()].push_back(n);
    }
  }
  // Iterate from leafs.
  bool has_unscheduled;
  do {
    has_unscheduled = false;
    for (auto &lt : sorted_nodes_) {
      auto &ev = lt.second;
      for (auto *n : ev) {
	if (!ScheduleNode(n)) {
	  has_unscheduled = true;
	}
      }
    }
  } while (has_unscheduled);
}

bool BBScheduler::ScheduleNode(PathNode *n) {
  if (n->GetFinalStIndex() > -1) {
    // already scheduled.
    return true;
  }
  // Minimum state index by src register position.
  int min_st_index = GetMinStIndex(n);
  if (min_st_index < 0) {
    return false;
  }
  // Ordering of memory access.
  if (!CheckPrecedingNodesOfSameResource(n)) {
    return false;
  }
  // Calculates local delay.
  if (n->GetInsn()->GetResource()->GetClass()->IsExclusive()) {
    ScheduleExclusive(n, min_st_index);
  } else {
    ScheduleNonExclusive(n, min_st_index);
  }

  return true;
}

int BBScheduler::GetMinStIndex(PathNode *n) {
  cout << n->GetInsn()->GetId() << "\n";
  // Checks if all preceding nodes (W->W, W->R, R->W) are scheduled.
  for (auto &s : n->source_edges_) {
    PathEdge *edge = s.second;
    PathNode *source_node = edge->GetSourceNode();
    // cout << " " << source_node->GetInsn()->GetId() << " " << edge->GetType() << "\n";
    if (source_node->GetFinalStIndex() < 0) {
      // Not yet scheduled. Fail and try later again.
      return -1;
    }
  }
  // Determines the location.
  int min_st_index = 0;
  for (auto &s : n->source_edges_) {
    PathEdge *edge = s.second;
    if (!edge->IsWtoR()) {
      continue;
    }
    PathNode *source_node = edge->GetSourceNode();
    if (min_st_index < source_node->GetFinalStIndex()) {
      min_st_index = source_node->GetFinalStIndex();
    }
    if (min_st_index == source_node->GetFinalStIndex()) {
      int tmp_local_delay =
	source_node->state_local_delay_ + n->GetNodeDelay();
      if (tmp_local_delay > delay_info_->GetMaxDelay()) {
	// Local margin is not sufficient. Go to the next state.
	++min_st_index;
      }
    }
  }
  int t = GetMinStByPrecedingNodeOfSameResource(n);
  if (t >= 0) {
    if (t > min_st_index) {
      min_st_index = t;
    }
  }
  int u = GetMinStByEdgeDependency(n);
  if (u >= 0) {
    if (u >= min_st_index) {
      min_st_index = u;
    }
  }
  return min_st_index;
}

int BBScheduler::GetLocalDelayBeforeNode(PathNode *n, int st_index) {
  int source_local_delay = 0;
  for (auto &s : n->source_edges_) {
    PathEdge *edge = s.second;
    if (!edge->IsWtoR()) {
      continue;
    }
    PathNode *source_node = edge->GetSourceNode();
    if (source_node->GetFinalStIndex() < st_index) {
      continue;
    }
    if (source_local_delay < source_node->state_local_delay_) {
      source_local_delay = source_node->state_local_delay_;
    }
  }
  return source_local_delay;
}

void BBScheduler::ClearSchedule() {
  auto &nodes = data_path_->GetNodes();
  for (auto &p : nodes) {
    PathNode *n = p.second;
    n->SetFinalStIndex(-1);
    n->state_local_delay_ = 0;
  }
}

void BBScheduler::ScheduleExclusive(PathNode *n, int min_st_index) {
  int loc = min_st_index;
  // Tries to find a state index where this node can use the resource.
  while (true) {
    if (resource_tracker_->CanUseResource(n, loc)) {
      resource_tracker_->AllocateResource(n, loc);
      break;
    }
    ++loc;
  }
  n->state_local_delay_ = n->GetNodeDelay();
  bool has_conflict = true;
  if (loc == min_st_index) {
    has_conflict = false;
    n->state_local_delay_ += GetLocalDelayBeforeNode(n, min_st_index);
  }
  conflict_tracker_->AddUsage(n, has_conflict);
  n->SetFinalStIndex(loc);
}

void BBScheduler::ScheduleNonExclusive(PathNode *n, int st_index) {
  // Just place the insn at st_index.
  n->SetFinalStIndex(st_index);
  int source_local_delay = GetLocalDelayBeforeNode(n, st_index);
  n->state_local_delay_ = source_local_delay + n->GetNodeDelay();
}

int BBScheduler::GetMinStByEdgeDependency(PathNode *n) {
  int min = -1;
  for (auto &s : n->source_edges_) {
    PathEdge *edge = s.second;
    // This takes care of W->W or R->W.
    if (edge->IsWtoR()) {
      continue;
    }
    PathNode *source_node = edge->GetSourceNode();
    if (source_node->GetFinalStIndex() > min) {
      min = source_node->GetFinalStIndex();
    }
  }
  if (min >= 0) {
    return min + 1;
  }
  return -1;
}

bool BBScheduler::CheckPrecedingNodesOfSameResource(PathNode *n) {
  IResource *res = n->GetInsn()->GetResource();
  if (!ResourceAttr::IsOrderedResource(res)) {
    // Skips normal resources (other than array access or so on).
    return true;
  }
  int idx = GetMinStByPrecedingNodeOfSameResource(n);
  if (idx < 0) {
    // Preceding node is not scheduled.
    return false;
  }
  return true;
}

int BBScheduler::GetMinStByPrecedingNodeOfSameResource(PathNode *n) {
  IResource *res = n->GetInsn()->GetResource();
  if (!ResourceAttr::IsOrderedResource(res)) {
    return -1;
  }
  auto &m = data_path_->GetResourceNodeMap(res);
  auto it = m.find(n->GetInitialStIndex());
  if (it == m.begin()) {
    return 0;
  }
  it--;
  PathNode *prev = it->second;
  int st_index = prev->GetFinalStIndex();
  if (st_index > -1) {
    return st_index + 1;
  }
  return -1;
}

}  // namespace sched
}  // namespace opt
}  // namespace iroha
<|endoftext|>


<commit_before>#include "multiverso/net.h"

#include <limits>
#include <mutex>

#include "multiverso/message.h"
// #include "multiverso/net/zmq_net.h"
#include "multiverso/util/log.h"

// TODO(feiga) remove this
#define MULTIVERSO_USE_MPI

// TODO(feiga): move to seperated files
#ifdef MULTIVERSO_USE_MPI
#include <mpi.h>
#endif

#ifdef _MSC_VER
#undef max
#endif

namespace multiverso {

#ifdef MULTIVERSO_USE_MPI
class MPINetWrapper : public NetInterface {
public:
  MPINetWrapper() : more_(std::numeric_limits<int>::max()) {}

  void Init(int* argc, char** argv) override {
    // MPI_Init(argc, &argv);
    MPI_Initialized(&inited_);
    if (!inited_) {
      MPI_Init_thread(argc, &argv, MPI_THREAD_MULTIPLE, &thread_provided_);
    }
    MPI_Query_thread(&thread_provided_);
	if (thread_provided_ < MPI_THREAD_SERIALIZED)
	{
		Log::Fatal("At least MPI_THREAD_SERIALIZED supported is needed by multiverso\n");
	}
    MPI_Comm_rank(MPI_COMM_WORLD, &rank_);
    MPI_Comm_size(MPI_COMM_WORLD, &size_);
    Log::Debug("%s net util inited, rank = %d, size = %d\n",
      name().c_str(), rank(), size());
  }

  void Finalize() override { MPI_Finalize(); }

  int rank() const override { return rank_; }
  int size() const override { return size_; }
  std::string name() const override { return "MPI"; }

  size_t Send(const MessagePtr& msg) override {
    if (thread_provided_ == MPI_THREAD_SERIALIZED) {
      std::lock_guard<std::mutex> lock(mutex_);
      return SendMsg(msg);
    } else if (thread_provided_ == MPI_THREAD_MULTIPLE) {
      return SendMsg(msg);
    } else {
      CHECK(false);
      return 0;
    }
  }

  size_t Recv(MessagePtr* msg) override {
    if (thread_provided_ == MPI_THREAD_SERIALIZED) {
      MPI_Status status;
      int flag;
      // non-blocking probe whether message comes
      MPI_Iprobe(MPI_ANY_SOURCE, 0, MPI_COMM_WORLD, &flag, &status);
      if (flag) {
        // a message come
        // block receive with lock guard
        std::lock_guard<std::mutex> lock(mutex_);
        return RecvMsg(msg);
      } else {
        // no message comes
        return 0;
      }
    } else if (thread_provided_ == MPI_THREAD_MULTIPLE) {
      return RecvMsg(msg);
    } else {
      CHECK(false);
      return 0;
    }
  }

  size_t SendMsg(const MessagePtr& msg) {
    size_t size = Message::kHeaderSize;
    MPI_Send(msg->header(), Message::kHeaderSize, MPI_BYTE,
             msg->dst(), 0, MPI_COMM_WORLD);
    // Send multiple msg
    for (auto& blob : msg->data()) {
      CHECK_NOTNULL(blob.data());
      MPI_Send(blob.data(), static_cast<int>(blob.size()), MPI_BYTE, msg->dst(),
        0, MPI_COMM_WORLD);
      size += blob.size();
    }
    // Send an extra over tag indicating the finish of this Message
    MPI_Send(&more_, sizeof(int), MPI_BYTE, msg->dst(),
      0, MPI_COMM_WORLD);
    Log::Debug("MPI-Net: rank %d send msg size = %d\n", rank(), size+4);
    return size + sizeof(int);
  }

  size_t RecvMsg(MessagePtr* msg_ptr) {
    // Receiving a Message from multiple recv
    Log::Debug("MPI-Net: rank %d started recv msg\n", rank());
    MessagePtr& msg = *msg_ptr;
    MPI_Status status;
    MPI_Recv(msg->header(), Message::kHeaderSize,
             MPI_BYTE, MPI_ANY_SOURCE,
             0, MPI_COMM_WORLD, &status);
    size_t size = Message::kHeaderSize;
    while (true) {
      int count;
      MPI_Probe(msg->src(), 0, MPI_COMM_WORLD, &status);
      MPI_Get_count(&status, MPI_BYTE, &count);
      Blob blob(count);
      // We only receive from msg->src() until we recv the overtag msg
      MPI_Recv(blob.data(), count, MPI_BYTE, msg->src(),
               0, MPI_COMM_WORLD, &status);
      size += count;
      if (count == sizeof(int) && blob.As<int>() == more_) break;
      msg->Push(blob);
    }
    Log::Debug("MPI-Net: rank %d end recv from src %d, size = %d\n", rank(), msg->src(), size);
    return size;
  }

private:
  const int more_;
  std::mutex mutex_;
  int thread_provided_;
  int inited_;
  int rank_;
  int size_;
};

#endif

NetInterface* NetInterface::Get() {
#ifdef MULTIVERSO_USE_ZMQ
  Log::Fatal("Not implemented yet\n");
  static ZeroMQNetWrapper net_impl;
#else
#ifdef MULTIVERSO_USE_MPI
  static MPINetWrapper net_impl;
#endif
#endif
  return &net_impl; // net_util.get();
}

}
<commit_msg>adding suggestion for Multiverso init<commit_after>#include "multiverso/net.h"

#include <limits>
#include <mutex>

#include "multiverso/message.h"
// #include "multiverso/net/zmq_net.h"
#include "multiverso/util/log.h"

// TODO(feiga) remove this
#define MULTIVERSO_USE_MPI

// TODO(feiga): move to seperated files
#ifdef MULTIVERSO_USE_MPI
#include <mpi.h>
#endif

#ifdef _MSC_VER
#undef max
#endif

namespace multiverso {

#ifdef MULTIVERSO_USE_MPI
class MPINetWrapper : public NetInterface {
public:
  MPINetWrapper() : more_(std::numeric_limits<int>::max()) {}

  void Init(int* argc, char** argv) override {
    // MPI_Init(argc, &argv);
    MPI_Initialized(&inited_);
    if (!inited_) {
      MPI_Init_thread(argc, &argv, MPI_THREAD_MULTIPLE, &thread_provided_);
    }
    MPI_Query_thread(&thread_provided_);
	if (thread_provided_ < MPI_THREAD_SERIALIZED)
	{
		Log::Fatal("At least MPI_THREAD_SERIALIZED supported is needed by multiverso.\n");
	}
	else if (thread_provided_ == MPI_THREAD_SERIALIZED)
	{
		Log::Info("multiverso MPI-Net is initialized under MPI_THREAD_SERIALIZED mode.\n");
	}
	else if (thread_provided_ == MPI_THREAD_MULTIPLE)
	{
		Log::Debug("multiverso MPI-Net is initialized under MPI_THREAD_MULTIPLE mode.\n");
	}
    MPI_Comm_rank(MPI_COMM_WORLD, &rank_);
    MPI_Comm_size(MPI_COMM_WORLD, &size_);
    Log::Debug("%s net util inited, rank = %d, size = %d\n",
      name().c_str(), rank(), size());
  }

  void Finalize() override { MPI_Finalize(); }

  int rank() const override { return rank_; }
  int size() const override { return size_; }
  std::string name() const override { return "MPI"; }

  size_t Send(const MessagePtr& msg) override {
    if (thread_provided_ == MPI_THREAD_SERIALIZED) {
      std::lock_guard<std::mutex> lock(mutex_);
      return SendMsg(msg);
    } else if (thread_provided_ == MPI_THREAD_MULTIPLE) {
      return SendMsg(msg);
    } else {
      CHECK(false);
      return 0;
    }
  }

  size_t Recv(MessagePtr* msg) override {
    if (thread_provided_ == MPI_THREAD_SERIALIZED) {
      MPI_Status status;
      int flag;
      // non-blocking probe whether message comes
      MPI_Iprobe(MPI_ANY_SOURCE, 0, MPI_COMM_WORLD, &flag, &status);
      if (flag) {
        // a message come
        // block receive with lock guard
        std::lock_guard<std::mutex> lock(mutex_);
        return RecvMsg(msg);
      } else {
        // no message comes
        return 0;
      }
    } else if (thread_provided_ == MPI_THREAD_MULTIPLE) {
      return RecvMsg(msg);
    } else {
      CHECK(false);
      return 0;
    }
  }

  size_t SendMsg(const MessagePtr& msg) {
    size_t size = Message::kHeaderSize;
    MPI_Send(msg->header(), Message::kHeaderSize, MPI_BYTE,
             msg->dst(), 0, MPI_COMM_WORLD);
    // Send multiple msg
    for (auto& blob : msg->data()) {
      CHECK_NOTNULL(blob.data());
      MPI_Send(blob.data(), static_cast<int>(blob.size()), MPI_BYTE, msg->dst(),
        0, MPI_COMM_WORLD);
      size += blob.size();
    }
    // Send an extra over tag indicating the finish of this Message
    MPI_Send(&more_, sizeof(int), MPI_BYTE, msg->dst(),
      0, MPI_COMM_WORLD);
    Log::Debug("MPI-Net: rank %d send msg size = %d\n", rank(), size+4);
    return size + sizeof(int);
  }

  size_t RecvMsg(MessagePtr* msg_ptr) {
    // Receiving a Message from multiple recv
    Log::Debug("MPI-Net: rank %d started recv msg\n", rank());
    MessagePtr& msg = *msg_ptr;
    MPI_Status status;
    MPI_Recv(msg->header(), Message::kHeaderSize,
             MPI_BYTE, MPI_ANY_SOURCE,
             0, MPI_COMM_WORLD, &status);
    size_t size = Message::kHeaderSize;
    while (true) {
      int count;
      MPI_Probe(msg->src(), 0, MPI_COMM_WORLD, &status);
      MPI_Get_count(&status, MPI_BYTE, &count);
      Blob blob(count);
      // We only receive from msg->src() until we recv the overtag msg
      MPI_Recv(blob.data(), count, MPI_BYTE, msg->src(),
               0, MPI_COMM_WORLD, &status);
      size += count;
      if (count == sizeof(int) && blob.As<int>() == more_) break;
      msg->Push(blob);
    }
    Log::Debug("MPI-Net: rank %d end recv from src %d, size = %d\n", rank(), msg->src(), size);
    return size;
  }

private:
  const int more_;
  std::mutex mutex_;
  int thread_provided_;
  int inited_;
  int rank_;
  int size_;
};

#endif

NetInterface* NetInterface::Get() {
#ifdef MULTIVERSO_USE_ZMQ
  Log::Fatal("Not implemented yet\n");
  static ZeroMQNetWrapper net_impl;
#else
#ifdef MULTIVERSO_USE_MPI
  static MPINetWrapper net_impl;
#endif
#endif
  return &net_impl; // net_util.get();
}

}
<|endoftext|>