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

#include <opengm/learning/loss/generalized-hammingloss.hxx>
#include <opengm/graphicalmodel/graphicalmodel.hxx>
#include <opengm/graphicalmodel/graphicalmodel_factor.hxx>

//*************************************
typedef double ValueType;
typedef size_t IndexType;
typedef size_t LabelType;
typedef opengm::meta::TypeListGenerator<opengm::ExplicitFunction<ValueType,IndexType,LabelType> >::type FunctionListType;
typedef opengm::GraphicalModel<ValueType,opengm::Adder, FunctionListType, opengm::DiscreteSpace<IndexType,LabelType> > GM;

//*************************************

int main() {

   std::vector<double> label_loss_multipliers;
   label_loss_multipliers.push_back(2.0);
   label_loss_multipliers.push_back(1.0);
   label_loss_multipliers.push_back(0.5);

   std::vector<double> node_loss_multipliers;
   node_loss_multipliers.push_back(5.0);
   node_loss_multipliers.push_back(6.0);
   node_loss_multipliers.push_back(7.0);
   node_loss_multipliers.push_back(8.0);

   // create loss
   opengm::learning::GeneralizedHammingLoss loss(node_loss_multipliers.begin(),
                                                 node_loss_multipliers.end(),
                                                 label_loss_multipliers.begin(),
                                                 label_loss_multipliers.end());

   // evaluate for a test point
   std::vector<size_t> labels;
   labels.push_back(0);
   labels.push_back(1);
   labels.push_back(2);
   labels.push_back(2);

   std::vector<size_t> ground_truth;
   ground_truth.push_back(1);
   ground_truth.push_back(1);
   ground_truth.push_back(1);
   ground_truth.push_back(1);

   OPENGM_ASSERT_OP(loss.loss(labels.begin(), labels.end(), ground_truth.begin(), ground_truth.end()), ==, 17.5);

   // add loss to a model and evaluate for a given labeling
   GM gm;
   size_t numberOfLabels = 3;
   gm.addVariable(numberOfLabels);
   gm.addVariable(numberOfLabels);
   gm.addVariable(numberOfLabels);
   gm.addVariable(numberOfLabels);

   // add a unary to node 2 (if indexed from 1)
   opengm::ExplicitFunction<typename GM::ValueType,typename GM::IndexType, typename GM::LabelType> f(&numberOfLabels, &(numberOfLabels)+1, 2.0);
   size_t variableIndex = 1;
   gm.addFactor(gm.addFunction(f), &variableIndex, &variableIndex+1);
   OPENGM_ASSERT_OP(gm.evaluate(labels.begin()), ==, 2.0);

   // loss augmented model:
   loss.addLoss(gm, ground_truth.begin());
   OPENGM_ASSERT_OP(gm.evaluate(labels.begin()), ==, 19.5);
}
<commit_msg>make it compileable<commit_after>#include <vector>
#include <iostream>

#include <opengm/learning/loss/generalized-hammingloss.hxx>
#include <opengm/graphicalmodel/graphicalmodel.hxx>
#include <opengm/graphicalmodel/graphicalmodel_factor.hxx>

//*************************************
typedef double ValueType;
typedef size_t IndexType;
typedef size_t LabelType;
typedef opengm::meta::TypeListGenerator<opengm::ExplicitFunction<ValueType,IndexType,LabelType> >::type FunctionListType;
typedef opengm::GraphicalModel<ValueType,opengm::Adder, FunctionListType, opengm::DiscreteSpace<IndexType,LabelType> > GM;

//*************************************

int main() {

   std::vector<double> label_loss_multipliers;
   label_loss_multipliers.push_back(2.0);
   label_loss_multipliers.push_back(1.0);
   label_loss_multipliers.push_back(0.5);

   std::vector<double> node_loss_multipliers;
   node_loss_multipliers.push_back(5.0);
   node_loss_multipliers.push_back(6.0);
   node_loss_multipliers.push_back(7.0);
   node_loss_multipliers.push_back(8.0);

   // create loss
   opengm::learning::GeneralizedHammingLoss loss(node_loss_multipliers.begin(),
                                                 node_loss_multipliers.end(),
                                                 label_loss_multipliers.begin(),
                                                 label_loss_multipliers.end());

   // evaluate for a test point
   std::vector<size_t> labels;
   labels.push_back(0);
   labels.push_back(1);
   labels.push_back(2);
   labels.push_back(2);

   std::vector<size_t> ground_truth;
   ground_truth.push_back(1);
   ground_truth.push_back(1);
   ground_truth.push_back(1);
   ground_truth.push_back(1);

   OPENGM_ASSERT_OP(loss.loss(labels.begin(), labels.end(), ground_truth.begin(), ground_truth.end()), ==, 17.5);

   // add loss to a model and evaluate for a given labeling
   GM gm;
   size_t numberOfLabels = 3;
   gm.addVariable(numberOfLabels);
   gm.addVariable(numberOfLabels);
   gm.addVariable(numberOfLabels);
   gm.addVariable(numberOfLabels);

   // add a unary to node 2 (if indexed from 1)
   opengm::ExplicitFunction<GM::ValueType,GM::IndexType,GM::LabelType> f(&numberOfLabels, &(numberOfLabels)+1, 2.0);
   size_t variableIndex = 1;
   gm.addFactor(gm.addFunction(f), &variableIndex, &variableIndex+1);
   OPENGM_ASSERT_OP(gm.evaluate(labels.begin()), ==, 2.0);

   // loss augmented model:
   loss.addLoss(gm, ground_truth.begin());
   OPENGM_ASSERT_OP(gm.evaluate(labels.begin()), ==, 19.5);
}
<|endoftext|>


<commit_before>#include "Common.h"
#include "Logging.h"

#include <stdarg.h>
#include <time.h>

VINYL_NS_BEGIN;

namespace Log
{
	FormatVar::FormatVar(int i)
	{
		m_type = FVT_Integer;
		m_data = (void*)i;
	}

	FormatVar::FormatVar(const char* str)
	{
		m_type = FVT_String;
		m_data = (void*)str;
	}

	FormatVar::FormatVar(char c)
	{
		m_type = FVT_Char;
		m_data = (void*)c;
	}

	FormatVar::~FormatVar()
	{
		if (m_cache != nullptr) {
			free(m_cache);
		}
	}

	const char* FormatVar::GetString()
	{
		if (m_type == FVT_Integer) {
			if (m_cache == nullptr) {
				m_cache = (char*)malloc(14);
			}
			int num = (int)m_data;
			snprintf(m_cache, 14, "%d", num);
			return m_cache;

		} else if (m_type == FVT_String) {
			return (const char*)m_data;

		} else if (m_type == FVT_Char) {
			if (m_cache == nullptr) {
				m_cache = (char*)malloc(2);
				m_cache[1] = '\0';
			}
			m_cache[0] = (char)(int)m_data;
			return m_cache;
		}

		return "";
	}

	s::String Format(const char* format, va_list vl)
	{
		s::StackArray<FormatVar> vars;
		vars.sa_bOnlyPop = true;

		int numHighest = 0;

		int bufferLen = 128;
		s::String ret;

		int len = strlen(format);
		for (int i = 0; i < len; i++) {
			char c = format[i];
			if (c == '%') {
				char cn = format[++i];
				char str[5];
				int strc = 0;
				while (cn >= '0' && cn <= '9' && strc < 4 && i < len) {
					str[strc] = cn;
					strc++;
					cn = format[++i];
				}
				i--;
				str[strc] = '\0';
				int num = atoi(str);
				if (num == 0) {
					continue;
				}
				if (num > numHighest) {
					for (int j = numHighest; j < num; j++) {
						FormatVar &newvar = va_arg(vl, FormatVar);
						vars.Push(&newvar);
					}
					numHighest = num;
				}
				FormatVar &var = vars[num - 1];
				ret += var.GetString();
				continue;
			}

			ret += c;
		}

		return ret;
	}

	LogLevel Level = LogLevel_Info;

	static s::Mutex _mutex;

	static void LogLine(const char* keyword, const s::String &str, int16_t color_windows, const char* color_linux)
	{
		_mutex.Lock();

#define LOG_FORMAT_BEGIN "%7s | %02d:%02d:%02d | "

		time_t t = time(nullptr);
		tm tms;
#if WINDOWS
		localtime_s(&tms, &t);
#else
		localtime_r(&t, &tms);
#endif

		s::String lineBegin = s::strPrintF(LOG_FORMAT_BEGIN, keyword, tms.tm_hour, tms.tm_min, tms.tm_sec);

#if WINDOWS
		HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
		SetConsoleTextAttribute(hConsole, color_windows);
		printf("%s%s\n", (const char*)lineBegin, (const char*)str);
		SetConsoleTextAttribute(hConsole, 7);
#else
		printf("\x1B[%sm%s%s\x1B[0m\n", color_linux, (const char*)lineBegin, (const char*)str);
#endif

		_mutex.Unlock();
	}

	void Trace(const char* format, ...)
	{
		if (Level > LogLevel_Trace) {
			return;
		}

		va_list vl;
		va_start(vl, format);
		s::String str = Format(format, vl);
		va_end(vl);

		LogLine("TRACE", str, 8, "02");
	}

	void Debug(const char* format, ...)
	{
		if (Level > LogLevel_Debug) {
			return;
		}

		va_list vl;
		va_start(vl, format);
		s::String str = Format(format, vl);
		va_end(vl);

		LogLine("DEBUG", str, 7, "38");
	}

	void Info(const char* format, ...)
	{
		if (Level > LogLevel_Info) {
			return;
		}

		va_list vl;
		va_start(vl, format);
		s::String str = Format(format, vl);
		va_end(vl);

		LogLine("INFO", str, 15, "37");
	}

	void Warning(const char* format, ...)
	{
		if (Level > LogLevel_Warning) {
			return;
		}

		va_list vl;
		va_start(vl, format);
		s::String str = Format(format, vl);
		va_end(vl);

		LogLine("WARNING", str, 13, "35");
	}

	void Error(const char* format, ...)
	{
		if (Level > LogLevel_Error) {
			return;
		}

		va_list vl;
		va_start(vl, format);
		s::String str = Format(format, vl);
		va_end(vl);

		LogLine("ERROR", str, 14, "33");
	}

	void Fatal(const char* format, ...)
	{
		if (Level > LogLevel_Fatal) {
			return;
		}

		va_list vl;
		va_start(vl, format);
		s::String str = Format(format, vl);
		va_end(vl);

		LogLine("FATAL", str, 12, "31");
	}
}

VINYL_NS_END;
<commit_msg>Fix linux build<commit_after>#include "Common.h"
#include "Logging.h"

#include <stdarg.h>
#include <time.h>

VINYL_NS_BEGIN;

namespace Log
{
	FormatVar::FormatVar(int i)
	{
		m_type = FVT_Integer;
		m_data = (void*)i;
	}

	FormatVar::FormatVar(const char* str)
	{
		m_type = FVT_String;
		m_data = (void*)str;
	}

	FormatVar::FormatVar(char c)
	{
		m_type = FVT_Char;
		m_data = (void*)c;
	}

	FormatVar::~FormatVar()
	{
		if (m_cache != nullptr) {
			free(m_cache);
		}
	}

	const char* FormatVar::GetString()
	{
		if (m_type == FVT_Integer) {
			if (m_cache == nullptr) {
				m_cache = (char*)malloc(14);
			}
#ifdef _LP64
			int num = (int)(long int)m_data;
#else
			int num = (int)m_data;
#endif
			snprintf(m_cache, 14, "%d", num);
			return m_cache;

		} else if (m_type == FVT_String) {
			return (const char*)m_data;

		} else if (m_type == FVT_Char) {
			if (m_cache == nullptr) {
				m_cache = (char*)malloc(2);
				m_cache[1] = '\0';
			}
#ifdef _LP64
			m_cache[0] = (char)(long int)m_data;
#else
			m_cache[0] = (char)(int)m_data;
#endif
			return m_cache;
		}

		return "";
	}

	s::String Format(const char* format, va_list vl)
	{
		s::StackArray<FormatVar> vars;
		vars.sa_bOnlyPop = true;

		int numHighest = 0;

		int bufferLen = 128;
		s::String ret;

		int len = strlen(format);
		for (int i = 0; i < len; i++) {
			char c = format[i];
			if (c == '%') {
				char cn = format[++i];
				char str[5];
				int strc = 0;
				while (cn >= '0' && cn <= '9' && strc < 4 && i < len) {
					str[strc] = cn;
					strc++;
					cn = format[++i];
				}
				i--;
				str[strc] = '\0';
				int num = atoi(str);
				if (num == 0) {
					continue;
				}
				if (num > numHighest) {
					for (int j = numHighest; j < num; j++) {
						FormatVar &newvar = va_arg(vl, FormatVar);
						vars.Push(&newvar);
					}
					numHighest = num;
				}
				FormatVar &var = vars[num - 1];
				ret += var.GetString();
				continue;
			}

			ret += c;
		}

		return ret;
	}

	LogLevel Level = LogLevel_Info;

	static s::Mutex _mutex;

	static void LogLine(const char* keyword, const s::String &str, int16_t color_windows, const char* color_linux)
	{
		_mutex.Lock();

#define LOG_FORMAT_BEGIN "%7s | %02d:%02d:%02d | "

		time_t t = time(nullptr);
		tm tms;
#if WINDOWS
		localtime_s(&tms, &t);
#else
		localtime_r(&t, &tms);
#endif

		s::String lineBegin = s::strPrintF(LOG_FORMAT_BEGIN, keyword, tms.tm_hour, tms.tm_min, tms.tm_sec);

#if WINDOWS
		HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
		SetConsoleTextAttribute(hConsole, color_windows);
		printf("%s%s\n", (const char*)lineBegin, (const char*)str);
		SetConsoleTextAttribute(hConsole, 7);
#else
		printf("\x1B[%sm%s%s\x1B[0m\n", color_linux, (const char*)lineBegin, (const char*)str);
#endif

		_mutex.Unlock();
	}

	void Trace(const char* format, ...)
	{
		if (Level > LogLevel_Trace) {
			return;
		}

		va_list vl;
		va_start(vl, format);
		s::String str = Format(format, vl);
		va_end(vl);

		LogLine("TRACE", str, 8, "02");
	}

	void Debug(const char* format, ...)
	{
		if (Level > LogLevel_Debug) {
			return;
		}

		va_list vl;
		va_start(vl, format);
		s::String str = Format(format, vl);
		va_end(vl);

		LogLine("DEBUG", str, 7, "38");
	}

	void Info(const char* format, ...)
	{
		if (Level > LogLevel_Info) {
			return;
		}

		va_list vl;
		va_start(vl, format);
		s::String str = Format(format, vl);
		va_end(vl);

		LogLine("INFO", str, 15, "37");
	}

	void Warning(const char* format, ...)
	{
		if (Level > LogLevel_Warning) {
			return;
		}

		va_list vl;
		va_start(vl, format);
		s::String str = Format(format, vl);
		va_end(vl);

		LogLine("WARNING", str, 13, "35");
	}

	void Error(const char* format, ...)
	{
		if (Level > LogLevel_Error) {
			return;
		}

		va_list vl;
		va_start(vl, format);
		s::String str = Format(format, vl);
		va_end(vl);

		LogLine("ERROR", str, 14, "33");
	}

	void Fatal(const char* format, ...)
	{
		if (Level > LogLevel_Fatal) {
			return;
		}

		va_list vl;
		va_start(vl, format);
		s::String str = Format(format, vl);
		va_end(vl);

		LogLine("FATAL", str, 12, "31");
	}
}

VINYL_NS_END;
<|endoftext|>


<commit_before>#include "Manager.h"

#include "BeginRequestRecord.h"
#include "EnumHelpers.h"
#include "ParametersRecord.h"
#include "RecordHeader.h"
#include "StandardInputRecord.h"

#include "fastcgi.h"

#include <QDebug>
#include <QFile>
#include <QHostAddress>
#include <QLocalSocket>
#include <QSignalMapper>

#include <errno.h>
#include <sys/file.h>
#include <sys/socket.h>
#include <sys/un.h>

namespace FastCgiQt
{
	Manager::Manager(ResponderGenerator responderGenerator, QObject* parent)
		:
			QObject(parent),
			m_responderGenerator(responderGenerator),
			m_socket(new QLocalSocket(this)),
			m_socketMapper(new QSignalMapper(this))
	{
		connect(
			m_socketMapper,
			SIGNAL(mapped(int)),
			this,
			SLOT(processSocketData(int))
		);

		// Initialise socket address structure
		sockaddr_un sa;
		socklen_t len = sizeof(sa);
		memset(&sa, 0, len);

		// The recommended way of telling if we're running as fastcgi or not.
		int error = ::getpeername(FCGI_LISTENSOCK_FILENO, reinterpret_cast<sockaddr*>(&sa), &len);
		if(error == -1 && errno != ENOTCONN)
		{
			qDebug() << tr("CGI not supported.");
			return;
		}

		// Listen on the socket
		qDebug() << "Accepting socket";
		lockSocket(FCGI_LISTENSOCK_FILENO);
		int newSocket = ::accept(FCGI_LISTENSOCK_FILENO, reinterpret_cast<sockaddr*>(&sa), &len);
		releaseSocket(FCGI_LISTENSOCK_FILENO);
		::close(FCGI_LISTENSOCK_FILENO);

		// We're connected, setup a QAbstractSocket
		qDebug() << "New socket:" << newSocket;
		m_socket->setSocketDescriptor(newSocket, QLocalSocket::ConnectedState, QIODevice::ReadWrite);
		// Map readyReady to processSocketData(newSocket)
		connect(
			m_socket,
			SIGNAL(readyRead()),
			m_socketMapper,
			SLOT(map())
		);
		m_socketMapper->setMapping(m_socket, newSocket);
	}

	void Manager::lockSocket(int socket)
	{
		::flock(socket, LOCK_EX);
	}

	void Manager::releaseSocket(int socket)
	{
		::flock(socket, LOCK_UN);
	}

	void Manager::processSocketData(int socket)
	{
		bool success;
		do
		{
			if(!m_socketHeaders.contains(socket))
			{
				success = processNewRecord(socket);
			}
			else
			{
				success = processRecordData(socket);
			}
		}
		while(success && m_socket->bytesAvailable() > 0);
	}

	bool Manager::processRecordData(int socket)
	{
		qDebug() << "Payload on socket" << socket;
		const RecordHeader header(m_socketHeaders.value(socket));
		if(m_socket->bytesAvailable() < header.payloadLength())
		{
			return false;
		}

		QByteArray data = m_socket->read(header.payloadLength());
		qint64 bytesRead = data.length();

		if(bytesRead != header.payloadLength())
		{
			qFatal("Couldn't read payload - tried to read %d bytes, got %d", header.payloadLength(), bytesRead);
		}
		switch(header.type())
		{
			case RecordHeader::BeginRequestRecord:
				beginRequest(header, data);
				break;
			case RecordHeader::ParametersRecord:
				loadParameters(header, data);
				break;
			case RecordHeader::StandardInputRecord:
				readStandardInput(header, data);
				break;
			default:
				qDebug() << "Got query string data" << m_requests[header.requestId()].getData();
				qFatal("Don't know how to deal with payload for type %s", ENUM_DEBUG_STRING(RecordHeader,RecordType,header.type()));
		}
		m_socketHeaders.remove(socket);
		return true;
	}

	void Manager::loadParameters(const RecordHeader& header, const QByteArray& data)
	{
		Q_ASSERT(header.type() == RecordHeader::ParametersRecord);
		Q_ASSERT(m_requests.value(header.requestId()).isValid());
		ParametersRecord record(header, data);
		m_requests[header.requestId()].addServerData(record.parameters());
	}

	void Manager::readStandardInput(const RecordHeader& header, const QByteArray& data)
	{
		Q_ASSERT(header.type() == RecordHeader::StandardInputRecord);
		Q_ASSERT(m_requests.value(header.requestId()).isValid());
		StandardInputRecord record(header, data);
		m_requests[header.requestId()].appendContent(record.streamData());
		if(m_requests[header.requestId()].haveContent())
		{
			respond(header.requestId());
		}
		qDebug() << "Read standard input - done?" << m_requests.value(header.requestId()).haveContent();
	}

	void Manager::beginRequest(const RecordHeader& header, const QByteArray& data)
	{
		Q_ASSERT(header.type() == RecordHeader::BeginRequestRecord);
		Q_ASSERT(!m_requests.value(header.requestId()).isValid());
		BeginRequestRecord record(header, *reinterpret_cast<const FCGI_BeginRequestBody*>(data.constData()));
		qDebug() << "Got new begin request with id" << record.requestId() << "role" << record.role() << "flags" << record.flags();
		Q_ASSERT(record.role() == BeginRequestRecord::ResponderRole);

		if(m_requests.size() -1 < record.requestId())
		{
			m_requests.resize((record.requestId() + 1) + 2);
			m_requests[record.requestId()] = Request(record.requestId());
		}
	}

	void Manager::respond(quint16 requestId)
	{
		Responder* responder = (*m_responderGenerator)(
			m_requests.at(requestId),
			m_socket,
			this
		);
		responder->respond();
		qDebug() << "responded";
		///@todo send end request
		delete responder;
	}

	bool Manager::processNewRecord(int socket)
	{
		qDebug() << "New record on socket" << socket;
		if(m_socket->bytesAvailable() < FCGI_HEADER_LEN)
		{
			return false;
		}

		FCGI_Header fcgiHeader;
		qint64 bytesRead = m_socket->read(reinterpret_cast<char*>(&fcgiHeader), FCGI_HEADER_LEN);
		if(bytesRead != FCGI_HEADER_LEN)
		{
			qFatal("Couldn't read FCGI header - tried to read %d bytes, got %d", FCGI_HEADER_LEN, bytesRead);
		}
		RecordHeader header(fcgiHeader);
		qDebug() << "Got header with record type" << header.type() << "id" << header.requestId() << "payload size" << header.payloadLength() << "content size" << header.contentLength();
		m_socketHeaders.insert(socket, header);
		if(m_socket->bytesAvailable() >= header.payloadLength())
		{
			processRecordData(socket);
		}
		return true;
	}
}
<commit_msg>send EndRequestRecords<commit_after>#include "Manager.h"

#include "BeginRequestRecord.h"
#include "EndRequestRecord.h"
#include "EnumHelpers.h"
#include "ParametersRecord.h"
#include "RecordHeader.h"
#include "StandardInputRecord.h"

#include "fastcgi.h"

#include <QDebug>
#include <QFile>
#include <QHostAddress>
#include <QLocalSocket>
#include <QSignalMapper>

#include <errno.h>
#include <sys/file.h>
#include <sys/socket.h>
#include <sys/un.h>

namespace FastCgiQt
{
	Manager::Manager(ResponderGenerator responderGenerator, QObject* parent)
		:
			QObject(parent),
			m_responderGenerator(responderGenerator),
			m_socket(new QLocalSocket(this)),
			m_socketMapper(new QSignalMapper(this))
	{
		connect(
			m_socketMapper,
			SIGNAL(mapped(int)),
			this,
			SLOT(processSocketData(int))
		);

		// Initialise socket address structure
		sockaddr_un sa;
		socklen_t len = sizeof(sa);
		memset(&sa, 0, len);

		// The recommended way of telling if we're running as fastcgi or not.
		int error = ::getpeername(FCGI_LISTENSOCK_FILENO, reinterpret_cast<sockaddr*>(&sa), &len);
		if(error == -1 && errno != ENOTCONN)
		{
			qDebug() << tr("CGI not supported.");
			return;
		}

		// Listen on the socket
		qDebug() << "Accepting socket";
		lockSocket(FCGI_LISTENSOCK_FILENO);
		int newSocket = ::accept(FCGI_LISTENSOCK_FILENO, reinterpret_cast<sockaddr*>(&sa), &len);
		releaseSocket(FCGI_LISTENSOCK_FILENO);
		::close(FCGI_LISTENSOCK_FILENO);

		// We're connected, setup a QAbstractSocket
		qDebug() << "New socket:" << newSocket;
		m_socket->setSocketDescriptor(newSocket, QLocalSocket::ConnectedState, QIODevice::ReadWrite);
		// Map readyReady to processSocketData(newSocket)
		connect(
			m_socket,
			SIGNAL(readyRead()),
			m_socketMapper,
			SLOT(map())
		);
		m_socketMapper->setMapping(m_socket, newSocket);
	}

	void Manager::lockSocket(int socket)
	{
		::flock(socket, LOCK_EX);
	}

	void Manager::releaseSocket(int socket)
	{
		::flock(socket, LOCK_UN);
	}

	void Manager::processSocketData(int socket)
	{
		bool success;
		do
		{
			if(!m_socketHeaders.contains(socket))
			{
				success = processNewRecord(socket);
			}
			else
			{
				success = processRecordData(socket);
			}
		}
		while(success && m_socket->bytesAvailable() > 0);
	}

	bool Manager::processRecordData(int socket)
	{
		qDebug() << "Payload on socket" << socket;
		const RecordHeader header(m_socketHeaders.value(socket));
		if(m_socket->bytesAvailable() < header.payloadLength())
		{
			return false;
		}

		QByteArray data = m_socket->read(header.payloadLength());
		qint64 bytesRead = data.length();

		if(bytesRead != header.payloadLength())
		{
			qFatal("Couldn't read payload - tried to read %d bytes, got %d", header.payloadLength(), bytesRead);
		}
		switch(header.type())
		{
			case RecordHeader::BeginRequestRecord:
				beginRequest(header, data);
				break;
			case RecordHeader::ParametersRecord:
				loadParameters(header, data);
				break;
			case RecordHeader::StandardInputRecord:
				readStandardInput(header, data);
				break;
			default:
				qDebug() << "Got query string data" << m_requests[header.requestId()].getData();
				qFatal("Don't know how to deal with payload for type %s", ENUM_DEBUG_STRING(RecordHeader,RecordType,header.type()));
		}
		m_socketHeaders.remove(socket);
		return true;
	}

	void Manager::loadParameters(const RecordHeader& header, const QByteArray& data)
	{
		Q_ASSERT(header.type() == RecordHeader::ParametersRecord);
		Q_ASSERT(m_requests.value(header.requestId()).isValid());
		ParametersRecord record(header, data);
		m_requests[header.requestId()].addServerData(record.parameters());
	}

	void Manager::readStandardInput(const RecordHeader& header, const QByteArray& data)
	{
		Q_ASSERT(header.type() == RecordHeader::StandardInputRecord);
		Q_ASSERT(m_requests.value(header.requestId()).isValid());
		StandardInputRecord record(header, data);
		m_requests[header.requestId()].appendContent(record.streamData());
		if(m_requests[header.requestId()].haveContent())
		{
			respond(header.requestId());
		}
	}

	void Manager::beginRequest(const RecordHeader& header, const QByteArray& data)
	{
		Q_ASSERT(header.type() == RecordHeader::BeginRequestRecord);
		Q_ASSERT(!m_requests.value(header.requestId()).isValid());
		BeginRequestRecord record(header, *reinterpret_cast<const FCGI_BeginRequestBody*>(data.constData()));
		qDebug() << "Got new begin request with id" << record.requestId() << "role" << record.role() << "flags" << record.flags();
		Q_ASSERT(record.role() == BeginRequestRecord::ResponderRole);

		if(m_requests.size() -1 < record.requestId())
		{
			m_requests.resize((record.requestId() + 1) + 2);
			m_requests[record.requestId()] = Request(record.requestId());
		}
	}

	void Manager::respond(quint16 requestId)
	{
		Responder* responder = (*m_responderGenerator)(
			m_requests.at(requestId),
			m_socket,
			this
		);
		responder->respond();
		m_socket->write(EndRequestRecord::create(requestId));
		qDebug() << "responded";
		delete responder;
	}

	bool Manager::processNewRecord(int socket)
	{
		qDebug() << "New record on socket" << socket;
		if(m_socket->bytesAvailable() < FCGI_HEADER_LEN)
		{
			return false;
		}

		FCGI_Header fcgiHeader;
		qint64 bytesRead = m_socket->read(reinterpret_cast<char*>(&fcgiHeader), FCGI_HEADER_LEN);
		if(bytesRead != FCGI_HEADER_LEN)
		{
			qFatal("Couldn't read FCGI header - tried to read %d bytes, got %d", FCGI_HEADER_LEN, bytesRead);
		}
		RecordHeader header(fcgiHeader);
		qDebug() << "Got header with record type" << header.type() << "id" << header.requestId() << "payload size" << header.payloadLength() << "content size" << header.contentLength();
		m_socketHeaders.insert(socket, header);
		if(m_socket->bytesAvailable() >= header.payloadLength())
		{
			processRecordData(socket);
		}
		return true;
	}
}
<|endoftext|>


<commit_before>// $Id$

// The libMesh Finite Element Library.
// Copyright (C) 2002-2007  Benjamin S. Kirk, John W. Peterson

// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.

// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.

// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

// System Includes
#include <algorithm>
#include <iostream>

// Local Includes
#include "libmesh_common.h"
#include "parallel.h"
#include "parallel_sort.h"
#include "parallel_bin_sorter.h"
#ifdef HAVE_LIBHILBERT
#  include "hilbert.h"
#endif

namespace Parallel {

// The Constructor sorts the local data using
// std::sort().  Therefore, the construction of
// a Parallel::Sort object takes O(nlogn) time,
// where n is the length of _data.
template <typename KeyType>
Sort<KeyType>::Sort(std::vector<KeyType>& d,
		    const unsigned int n_procs,
		    const unsigned int proc_id) :
  _n_procs(n_procs),
  _proc_id(proc_id),
  _bin_is_sorted(false),
  _data(d)
{
  std::sort(_data.begin(), _data.end());

  // Allocate storage
  _local_bin_sizes.resize(_n_procs);
}

template <typename KeyType>
void Sort<KeyType>::sort()
{
  this->binsort();
  this->communicate_bins();
  this->sort_local_bin();

  // Set sorted flag to true
  _bin_is_sorted = true;
}

template <typename KeyType>
void Sort<KeyType>::binsort()
{
  // Find the global min and max from all the
  // processors.
  std::vector<KeyType> global_min_max(2);

  // Insert the local min and max for this processor
  global_min_max[0] = -_data.front();
  global_min_max[1] =  _data.back();

  // Communicate to determine the global
  // min and max for all processors.
  Parallel::max(global_min_max);

  // Multiply the min by -1 to obtain the true min
  global_min_max[0] *= -1;

  // Bin-Sort based on the global min and max
  Parallel::BinSorter<KeyType> bs(_data);
  bs.binsort(_n_procs, global_min_max[1], global_min_max[0]);

  // Now save the local bin sizes in a vector so
  // we don't have to keep around the BinSorter.
  for (unsigned int i=0; i<_n_procs; ++i)
    _local_bin_sizes[i] = bs.sizeof_bin(i);
}

#if defined(HAVE_LIBHILBERT) && defined(HAVE_MPI)
// Full specialization for HilbertIndices, there is a fair amount of
// code duplication here that could potentially be consolidated with the
// above method
template <>
void Sort<Hilbert::HilbertIndices>::binsort()
{
  // Find the global min and max from all the
  // processors.  Do this using MPI_Allreduce.
  Hilbert::HilbertIndices
    local_min,  local_max,
    global_min, global_max;

  if (_data.empty())
    {
      local_min.rack0 = local_min.rack1 = local_min.rack2 = static_cast<Hilbert::inttype>(-1);
      local_max.rack0 = local_max.rack1 = local_max.rack2 = 0;
    }
  else
    {
      local_min = _data.front();
      local_max = _data.back();
    }

  MPI_Op hilbert_max, hilbert_min;
  MPI_Datatype hilbert_type;

  MPI_Type_contiguous (3, MPI_UNSIGNED, &hilbert_type);
  MPI_Type_commit     (&hilbert_type);
  MPI_Op_create       ((MPI_User_function*)__hilbert_max_op, true, &hilbert_max);
  MPI_Op_create       ((MPI_User_function*)__hilbert_min_op, true, &hilbert_min);

  // Communicate to determine the global
  // min and max for all processors.
  MPI_Allreduce(&local_min,
		&global_min,
		1,
		hilbert_type,
		hilbert_min,
		libMesh::COMM_WORLD);

  MPI_Allreduce(&local_max,
		&global_max,
		1,
		hilbert_type,
		hilbert_max,
		libMesh::COMM_WORLD);

  MPI_Type_free (&hilbert_type);
  MPI_Op_free   (&hilbert_max);
  MPI_Op_free   (&hilbert_min);

  // Bin-Sort based on the global min and max
  Parallel::BinSorter<Hilbert::HilbertIndices> bs(_data);
  bs.binsort(_n_procs, global_max, global_min);

  // Now save the local bin sizes in a vector so
  // we don't have to keep around the BinSorter.
  for (unsigned int i=0; i<_n_procs; ++i)
    _local_bin_sizes[i] = bs.sizeof_bin(i);
}

#endif // #ifdef HAVE_LIBHILBERT

template <typename KeyType>
void Sort<KeyType>::communicate_bins()
{
#ifdef HAVE_MPI
  // Create storage for the global bin sizes.  This
  // is the number of keys which will be held in
  // each bin over all processors.
  std::vector<unsigned int> global_bin_sizes = _local_bin_sizes;

  // Sum to find the total number of entries in each bin.
  Parallel::sum(global_bin_sizes);

  // Create a vector to temporarily hold the results of MPI_Gatherv
  // calls.  The vector dest  may be saved away to _my_bin depending on which
  // processor is being MPI_Gatherv'd.
  std::vector<KeyType> dest;

  unsigned int local_offset = 0;

  for (unsigned int i=0; i<_n_procs; ++i)
    {
      // Vector to receive the total bin size for each
      // processor.  Processor i's bin size will be
      // held in proc_bin_size[i]
      std::vector<unsigned int> proc_bin_size;

      // Find the number of contributions coming from each
      // processor for this bin.  Note: allgather combines
      // the MPI_Gather and MPI_Bcast operations into one.
      Parallel::allgather(_local_bin_sizes[i], proc_bin_size);

      // Compute the offsets into my_bin for each processor's
      // portion of the bin.  These are basically partial sums
      // of the proc_bin_size vector.
      std::vector<unsigned int> displacements(_n_procs);
      for (unsigned int j=1; j<_n_procs; ++j)
	displacements[j] = proc_bin_size[j-1] + displacements[j-1];

      // Resize the destination buffer
      dest.resize (global_bin_sizes[i]);

      MPI_Gatherv((_data.size() > local_offset) ?
		    &_data[local_offset] :
		    NULL,                        // Points to the beginning of the bin to be sent
		  _local_bin_sizes[i],           // How much data is in the bin being sent.
		  Parallel::datatype<KeyType>(), // The data type we are sorting
		  (dest.empty()) ?
		    NULL :
		    &dest[0],                    // Enough storage to hold all bin contributions
		  (int*) &proc_bin_size[0],      // How much is to be received from each processor
	          (int*) &displacements[0],      // Offsets into the receive buffer
		  Parallel::datatype<KeyType>(), // The data type we are sorting
		  i,                             // The root process (we do this once for each proc)
		  libMesh::COMM_WORLD);

      // Copy the destination buffer if it
      // corresponds to the bin for this processor
      if (i == _proc_id)
	_my_bin = dest;

      // Increment the local offset counter
      local_offset += _local_bin_sizes[i];
    }
#endif // HAVE_MPI
}

#if defined(HAVE_LIBHILBERT) && defined(HAVE_MPI)
// Full specialization for HilbertIndices, there is a fair amount of
// code duplication here that could potentially be consolidated with the
// above method
template <>
void Sort<Hilbert::HilbertIndices>::communicate_bins()
{
  // Create storage for the global bin sizes.  This
  // is the number of keys which will be held in
  // each bin over all processors.
  std::vector<unsigned int> global_bin_sizes(_n_procs);

  assert (_local_bin_sizes.size() == global_bin_sizes.size());

  // Sum to find the total number of entries in each bin.
  // This is stored in global_bin_sizes.  Note, we
  // explicitly know that we are communicating MPI_UNSIGNED's here.
  MPI_Allreduce(&_local_bin_sizes[0],
		&global_bin_sizes[0],
		_n_procs,
		MPI_UNSIGNED,
		MPI_SUM,
		libMesh::COMM_WORLD);

  MPI_Datatype hilbert_type;

  MPI_Type_contiguous (3, MPI_UNSIGNED, &hilbert_type);
  MPI_Type_commit     (&hilbert_type);

  // Create a vector to temporarily hold the results of MPI_Gatherv
  // calls.  The vector dest  may be saved away to _my_bin depending on which
  // processor is being MPI_Gatherv'd.
  std::vector<Hilbert::HilbertIndices> sendbuf, dest;

  unsigned int local_offset = 0;

  for (unsigned int i=0; i<_n_procs; ++i)
    {
      // Vector to receive the total bin size for each
      // processor.  Processor i's bin size will be
      // held in proc_bin_size[i]
      std::vector<unsigned int> proc_bin_size(_n_procs);

      // Find the number of contributions coming from each
      // processor for this bin.  Note: Allgather combines
      // the MPI_Gather and MPI_Bcast operations into one.
      // Note: Here again we know that we are communicating
      // MPI_UNSIGNED's so there is no need to check the MPI_traits.
      MPI_Allgather(&_local_bin_sizes[i], // Source: # of entries on this proc in bin i
		    1,                    // Number of items to gather
		    MPI_UNSIGNED,
		    &proc_bin_size[0],    // Destination: Total # of entries in bin i
		    1,
		    MPI_UNSIGNED,
		    libMesh::COMM_WORLD);

      // Compute the offsets into my_bin for each processor's
      // portion of the bin.  These are basically partial sums
      // of the proc_bin_size vector.
      std::vector<unsigned int> displacements(_n_procs);
      for (unsigned int j=1; j<_n_procs; ++j)
	displacements[j] = proc_bin_size[j-1] + displacements[j-1];

      // Resize the destination buffer
      dest.resize (global_bin_sizes[i]);

      MPI_Gatherv((_data.size() > local_offset) ?
		    &_data[local_offset] :
		    NULL,                   // Points to the beginning of the bin to be sent
		  _local_bin_sizes[i],      // How much data is in the bin being sent.
		  hilbert_type,             // The data type we are sorting
		  (dest.empty()) ?
		    NULL :
		    &dest[0],               // Enough storage to hold all bin contributions
		  (int*) &proc_bin_size[0], // How much is to be received from each processor
		  (int*) &displacements[0], // Offsets into the receive buffer
		  hilbert_type,             // The data type we are sorting
		  i,                        // The root process (we do this once for each proc)
		  libMesh::COMM_WORLD);

      // Copy the destination buffer if it
      // corresponds to the bin for this processor
      if (i == _proc_id)
	_my_bin = dest;

      // Increment the local offset counter
      local_offset += _local_bin_sizes[i];
    }

  MPI_Type_free (&hilbert_type);
}

#endif // #if defined(HAVE_LIBHILBERT) && defined(HAVE_MPI)

template <typename KeyType>
void Sort<KeyType>::sort_local_bin()
{
  std::sort(_my_bin.begin(), _my_bin.end());
}

template <typename KeyType>
const std::vector<KeyType>& Sort<KeyType>::bin()
{
  if (!_bin_is_sorted)
    {
      std::cout << "Warning! Bin is not yet sorted!" << std::endl;
    }

  return _my_bin;
}

}

// Explicitly instantiate for int, double
template class Parallel::Sort<int>;
template class Parallel::Sort<double>;
#if defined(HAVE_LIBHILBERT) && defined(HAVE_MPI)
template class Parallel::Sort<Hilbert::HilbertIndices>;
#endif
<commit_msg>handle the degenerate case where for some reason we try to sort a single item in parallel<commit_after>// $Id$

// The libMesh Finite Element Library.
// Copyright (C) 2002-2007  Benjamin S. Kirk, John W. Peterson

// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.

// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.

// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

// System Includes
#include <algorithm>
#include <iostream>

// Local Includes
#include "libmesh_common.h"
#include "parallel.h"
#include "parallel_sort.h"
#include "parallel_bin_sorter.h"
#ifdef HAVE_LIBHILBERT
#  include "hilbert.h"
#endif

namespace Parallel {

// The Constructor sorts the local data using
// std::sort().  Therefore, the construction of
// a Parallel::Sort object takes O(nlogn) time,
// where n is the length of _data.
template <typename KeyType>
Sort<KeyType>::Sort(std::vector<KeyType>& d,
		    const unsigned int n_procs,
		    const unsigned int proc_id) :
  _n_procs(n_procs),
  _proc_id(proc_id),
  _bin_is_sorted(false),
  _data(d)
{
  std::sort(_data.begin(), _data.end());

  // Allocate storage
  _local_bin_sizes.resize(_n_procs);
}

template <typename KeyType>
void Sort<KeyType>::sort()
{
  // Find the global data size.  The sorting
  // algorithms assume they have a range to
  // work with, so catch the degenerate cases here
  unsigned int global_data_size = _data.size();

  Parallel::sum (global_data_size);

  if (global_data_size < 2)
    {
      // the entire global range is either empty
      // or contains only one element
      _my_bin = _data;

      Parallel::allgather (static_cast<unsigned int>(_my_bin.size()),
			   _local_bin_sizes);
    }
  else
    {
      this->binsort();
      this->communicate_bins();
      this->sort_local_bin();
    }

  // Set sorted flag to true
  _bin_is_sorted = true;
}

template <typename KeyType>
void Sort<KeyType>::binsort()
{
  // Find the global min and max from all the
  // processors.
  std::vector<KeyType> global_min_max(2);

  // Insert the local min and max for this processor
  global_min_max[0] = -_data.front();
  global_min_max[1] =  _data.back();

  // Communicate to determine the global
  // min and max for all processors.
  Parallel::max(global_min_max);

  // Multiply the min by -1 to obtain the true min
  global_min_max[0] *= -1;

  // Bin-Sort based on the global min and max
  Parallel::BinSorter<KeyType> bs(_data);
  bs.binsort(_n_procs, global_min_max[1], global_min_max[0]);

  // Now save the local bin sizes in a vector so
  // we don't have to keep around the BinSorter.
  for (unsigned int i=0; i<_n_procs; ++i)
    _local_bin_sizes[i] = bs.sizeof_bin(i);
}

#if defined(HAVE_LIBHILBERT) && defined(HAVE_MPI)
// Full specialization for HilbertIndices, there is a fair amount of
// code duplication here that could potentially be consolidated with the
// above method
template <>
void Sort<Hilbert::HilbertIndices>::binsort()
{
  // Find the global min and max from all the
  // processors.  Do this using MPI_Allreduce.
  Hilbert::HilbertIndices
    local_min,  local_max,
    global_min, global_max;

  if (_data.empty())
    {
      local_min.rack0 = local_min.rack1 = local_min.rack2 = static_cast<Hilbert::inttype>(-1);
      local_max.rack0 = local_max.rack1 = local_max.rack2 = 0;
    }
  else
    {
      local_min = _data.front();
      local_max = _data.back();
    }

  MPI_Op hilbert_max, hilbert_min;
  MPI_Datatype hilbert_type;

  MPI_Type_contiguous (3, MPI_UNSIGNED, &hilbert_type);
  MPI_Type_commit     (&hilbert_type);
  MPI_Op_create       ((MPI_User_function*)__hilbert_max_op, true, &hilbert_max);
  MPI_Op_create       ((MPI_User_function*)__hilbert_min_op, true, &hilbert_min);

  // Communicate to determine the global
  // min and max for all processors.
  MPI_Allreduce(&local_min,
		&global_min,
		1,
		hilbert_type,
		hilbert_min,
		libMesh::COMM_WORLD);

  MPI_Allreduce(&local_max,
		&global_max,
		1,
		hilbert_type,
		hilbert_max,
		libMesh::COMM_WORLD);

  MPI_Type_free (&hilbert_type);
  MPI_Op_free   (&hilbert_max);
  MPI_Op_free   (&hilbert_min);

  // Bin-Sort based on the global min and max
  Parallel::BinSorter<Hilbert::HilbertIndices> bs(_data);
  bs.binsort(_n_procs, global_max, global_min);

  // Now save the local bin sizes in a vector so
  // we don't have to keep around the BinSorter.
  for (unsigned int i=0; i<_n_procs; ++i)
    _local_bin_sizes[i] = bs.sizeof_bin(i);
}

#endif // #ifdef HAVE_LIBHILBERT

template <typename KeyType>
void Sort<KeyType>::communicate_bins()
{
#ifdef HAVE_MPI
  // Create storage for the global bin sizes.  This
  // is the number of keys which will be held in
  // each bin over all processors.
  std::vector<unsigned int> global_bin_sizes = _local_bin_sizes;

  // Sum to find the total number of entries in each bin.
  Parallel::sum(global_bin_sizes);

  // Create a vector to temporarily hold the results of MPI_Gatherv
  // calls.  The vector dest  may be saved away to _my_bin depending on which
  // processor is being MPI_Gatherv'd.
  std::vector<KeyType> dest;

  unsigned int local_offset = 0;

  for (unsigned int i=0; i<_n_procs; ++i)
    {
      // Vector to receive the total bin size for each
      // processor.  Processor i's bin size will be
      // held in proc_bin_size[i]
      std::vector<unsigned int> proc_bin_size;

      // Find the number of contributions coming from each
      // processor for this bin.  Note: allgather combines
      // the MPI_Gather and MPI_Bcast operations into one.
      Parallel::allgather(_local_bin_sizes[i], proc_bin_size);

      // Compute the offsets into my_bin for each processor's
      // portion of the bin.  These are basically partial sums
      // of the proc_bin_size vector.
      std::vector<unsigned int> displacements(_n_procs);
      for (unsigned int j=1; j<_n_procs; ++j)
	displacements[j] = proc_bin_size[j-1] + displacements[j-1];

      // Resize the destination buffer
      dest.resize (global_bin_sizes[i]);

      MPI_Gatherv((_data.size() > local_offset) ?
		    &_data[local_offset] :
		    NULL,                        // Points to the beginning of the bin to be sent
		  _local_bin_sizes[i],           // How much data is in the bin being sent.
		  Parallel::datatype<KeyType>(), // The data type we are sorting
		  (dest.empty()) ?
		    NULL :
		    &dest[0],                    // Enough storage to hold all bin contributions
		  (int*) &proc_bin_size[0],      // How much is to be received from each processor
	          (int*) &displacements[0],      // Offsets into the receive buffer
		  Parallel::datatype<KeyType>(), // The data type we are sorting
		  i,                             // The root process (we do this once for each proc)
		  libMesh::COMM_WORLD);

      // Copy the destination buffer if it
      // corresponds to the bin for this processor
      if (i == _proc_id)
	_my_bin = dest;

      // Increment the local offset counter
      local_offset += _local_bin_sizes[i];
    }
#endif // HAVE_MPI
}

#if defined(HAVE_LIBHILBERT) && defined(HAVE_MPI)
// Full specialization for HilbertIndices, there is a fair amount of
// code duplication here that could potentially be consolidated with the
// above method
template <>
void Sort<Hilbert::HilbertIndices>::communicate_bins()
{
  // Create storage for the global bin sizes.  This
  // is the number of keys which will be held in
  // each bin over all processors.
  std::vector<unsigned int> global_bin_sizes(_n_procs);

  assert (_local_bin_sizes.size() == global_bin_sizes.size());

  // Sum to find the total number of entries in each bin.
  // This is stored in global_bin_sizes.  Note, we
  // explicitly know that we are communicating MPI_UNSIGNED's here.
  MPI_Allreduce(&_local_bin_sizes[0],
		&global_bin_sizes[0],
		_n_procs,
		MPI_UNSIGNED,
		MPI_SUM,
		libMesh::COMM_WORLD);

  MPI_Datatype hilbert_type;

  MPI_Type_contiguous (3, MPI_UNSIGNED, &hilbert_type);
  MPI_Type_commit     (&hilbert_type);

  // Create a vector to temporarily hold the results of MPI_Gatherv
  // calls.  The vector dest  may be saved away to _my_bin depending on which
  // processor is being MPI_Gatherv'd.
  std::vector<Hilbert::HilbertIndices> sendbuf, dest;

  unsigned int local_offset = 0;

  for (unsigned int i=0; i<_n_procs; ++i)
    {
      // Vector to receive the total bin size for each
      // processor.  Processor i's bin size will be
      // held in proc_bin_size[i]
      std::vector<unsigned int> proc_bin_size(_n_procs);

      // Find the number of contributions coming from each
      // processor for this bin.  Note: Allgather combines
      // the MPI_Gather and MPI_Bcast operations into one.
      // Note: Here again we know that we are communicating
      // MPI_UNSIGNED's so there is no need to check the MPI_traits.
      MPI_Allgather(&_local_bin_sizes[i], // Source: # of entries on this proc in bin i
		    1,                    // Number of items to gather
		    MPI_UNSIGNED,
		    &proc_bin_size[0],    // Destination: Total # of entries in bin i
		    1,
		    MPI_UNSIGNED,
		    libMesh::COMM_WORLD);

      // Compute the offsets into my_bin for each processor's
      // portion of the bin.  These are basically partial sums
      // of the proc_bin_size vector.
      std::vector<unsigned int> displacements(_n_procs);
      for (unsigned int j=1; j<_n_procs; ++j)
	displacements[j] = proc_bin_size[j-1] + displacements[j-1];

      // Resize the destination buffer
      dest.resize (global_bin_sizes[i]);

      MPI_Gatherv((_data.size() > local_offset) ?
		    &_data[local_offset] :
		    NULL,                   // Points to the beginning of the bin to be sent
		  _local_bin_sizes[i],      // How much data is in the bin being sent.
		  hilbert_type,             // The data type we are sorting
		  (dest.empty()) ?
		    NULL :
		    &dest[0],               // Enough storage to hold all bin contributions
		  (int*) &proc_bin_size[0], // How much is to be received from each processor
		  (int*) &displacements[0], // Offsets into the receive buffer
		  hilbert_type,             // The data type we are sorting
		  i,                        // The root process (we do this once for each proc)
		  libMesh::COMM_WORLD);

      // Copy the destination buffer if it
      // corresponds to the bin for this processor
      if (i == _proc_id)
	_my_bin = dest;

      // Increment the local offset counter
      local_offset += _local_bin_sizes[i];
    }

  MPI_Type_free (&hilbert_type);
}

#endif // #if defined(HAVE_LIBHILBERT) && defined(HAVE_MPI)

template <typename KeyType>
void Sort<KeyType>::sort_local_bin()
{
  std::sort(_my_bin.begin(), _my_bin.end());
}

template <typename KeyType>
const std::vector<KeyType>& Sort<KeyType>::bin()
{
  if (!_bin_is_sorted)
    {
      std::cout << "Warning! Bin is not yet sorted!" << std::endl;
    }

  return _my_bin;
}

}

// Explicitly instantiate for int, double
template class Parallel::Sort<int>;
template class Parallel::Sort<double>;
#if defined(HAVE_LIBHILBERT) && defined(HAVE_MPI)
template class Parallel::Sort<Hilbert::HilbertIndices>;
#endif
<|endoftext|>


<commit_before>/*
 * Copyright (C) 2014 Open Source Robotics Foundation
 *
 * 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.
 *
*/

#ifdef _WIN32
  #include <Winsock2.h>
#else
  #include <arpa/inet.h>
  #include <netdb.h>
  #include <unistd.h>
#endif

#include <stdlib.h>
#include <cstring>
#include <iostream>
#include <string>
#include "ignition/transport/config.hh"
#include "ignition/transport/NetUtils.hh"

#ifdef HAVE_IFADDRS
# include <ifaddrs.h>
#endif

using namespace ignition;

//////////////////////////////////////////////////
bool transport::isPrivateIP(const char *_ip)
{
  bool b = !strncmp("192.168", _ip, 7) || !strncmp("10.", _ip, 3) ||
           !strncmp("169.254", _ip, 7);
  return b;
}

//////////////////////////////////////////////////
int transport::hostnameToIp(char *_hostname, std::string &_ip)
{
  struct hostent *he;
  struct in_addr **addr_list;
  int i;

  if ((he = gethostbyname(_hostname)) == nullptr)
  {
    // get the host info
    std::cerr << "Error in gethostbyname when using hostname = " << hostname;
    return 1;
  }

  addr_list = (struct in_addr **) he->h_addr_list;

  for (i = 0; addr_list[i] != nullptr; ++i)
  {
    // Return the first one;
    _ip = std::string(inet_ntoa(*addr_list[i]));
    return 0;
  }

  return 1;
}

//////////////////////////////////////////////////
std::string transport::determineHost()
{
  char *ip_env;
  // First, did the user set DZMQ_IP?
  ip_env = std::getenv("DZMQ_IP");

  if (ip_env)
  {
    if (strlen(ip_env) != 0)
      return ip_env;
    else
      std::cerr << "invalid DZMQ_IP (an empty string)" << std::endl;
  }

  // Second, try the hostname
  char host[1024];
  memset(host, 0, sizeof(host));
  if (gethostname(host, sizeof(host) - 1) != 0)
    std::cerr << "determineIP: gethostname failed" << std::endl;

  // We don't want localhost to be our ip
  else if (strlen(host) && strcmp("localhost", host))
  {
    std::string hostIP;
    strcat(host, ".local");
    if (hostnameToIp(host, hostIP) == 0)
    {
      return std::string(hostIP);
    }
  }

  // Third, fall back on interface search, which will yield an IP address
#ifdef HAVE_IFADDRS
  struct ifaddrs *ifa = nullptr, *ifp = NULL;
  int rc;
  if ((rc = getifaddrs(&ifp)) < 0)
  {
    std::cerr << "error in getifaddrs: " << strerror(rc) << std::endl;
    exit(-1);
  }
  char preferred_ip[200] = {0};
  for (ifa = ifp; ifa; ifa = ifa->ifa_next)
  {
    char ip_[200];
    socklen_t salen;
    if (!ifa->ifa_addr)
      continue;  // evidently this interface has no ip address
    if (ifa->ifa_addr->sa_family == AF_INET)
      salen = sizeof(struct sockaddr_in);
    else if (ifa->ifa_addr->sa_family == AF_INET6)
      salen = sizeof(struct sockaddr_in6);
    else
      continue;
    if (getnameinfo(ifa->ifa_addr, salen, ip_, sizeof(ip_), nullptr, 0,
                    NI_NUMERICHOST) < 0)
    {
      std::cout << "getnameinfo couldn't get the ip of interface " <<
                   ifa->ifa_name << std::endl;
      continue;
    }
    // prefer non-private IPs over private IPs
    if (!strcmp("127.0.0.1", ip_) || strchr(ip_, ':'))
      continue;  // ignore loopback unless we have no other choice
    if (ifa->ifa_addr->sa_family == AF_INET6 && !preferred_ip[0])
      strcpy(preferred_ip, ip_);
    else if (isPrivateIP(ip_) && !preferred_ip[0])
      strcpy(preferred_ip, ip_);
    else if (!isPrivateIP(ip_) &&
             (isPrivateIP(preferred_ip) || !preferred_ip[0]))
      strcpy(preferred_ip, ip_);
  }
  freeifaddrs(ifp);
  if (!preferred_ip[0])
  {
    std::cerr <<
      "Couldn't find a preferred IP via the getifaddrs() call; "
      "I'm assuming that your IP "
      "address is 127.0.0.1.  This should work for local processes, "
      "but will almost certainly not work if you have remote processes."
      "Report to the disc-zmq development team to seek a fix." << std::endl;
    return std::string("127.0.0.1");
  }
  return std::string(preferred_ip);
#else
  // @todo Fix IP determination in the case where getifaddrs() isn't
  // available.
  std::cerr <<
    "You don't have the getifaddrs() call; I'm assuming that your IP "
    "address is 127.0.0.1.  This should work for local processes, "
    "but will almost certainly not work if you have remote processes."
    "Report to the disc-zmq development team to seek a fix." << std::endl;
  return std::string("127.0.0.1");
#endif
}
<commit_msg>Fix variable name<commit_after>/*
 * Copyright (C) 2014 Open Source Robotics Foundation
 *
 * 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.
 *
*/

#ifdef _WIN32
  #include <Winsock2.h>
#else
  #include <arpa/inet.h>
  #include <netdb.h>
  #include <unistd.h>
#endif

#include <stdlib.h>
#include <cstring>
#include <iostream>
#include <string>
#include "ignition/transport/config.hh"
#include "ignition/transport/NetUtils.hh"

#ifdef HAVE_IFADDRS
# include <ifaddrs.h>
#endif

using namespace ignition;

//////////////////////////////////////////////////
bool transport::isPrivateIP(const char *_ip)
{
  bool b = !strncmp("192.168", _ip, 7) || !strncmp("10.", _ip, 3) ||
           !strncmp("169.254", _ip, 7);
  return b;
}

//////////////////////////////////////////////////
int transport::hostnameToIp(char *_hostname, std::string &_ip)
{
  struct hostent *he;
  struct in_addr **addr_list;
  int i;

  if ((he = gethostbyname(_hostname)) == nullptr)
  {
    // get the host info
    std::cerr << "Error in gethostbyname when using hostname = " << _hostname;
    return 1;
  }

  addr_list = (struct in_addr **) he->h_addr_list;

  for (i = 0; addr_list[i] != nullptr; ++i)
  {
    // Return the first one;
    _ip = std::string(inet_ntoa(*addr_list[i]));
    return 0;
  }

  return 1;
}

//////////////////////////////////////////////////
std::string transport::determineHost()
{
  char *ip_env;
  // First, did the user set DZMQ_IP?
  ip_env = std::getenv("DZMQ_IP");

  if (ip_env)
  {
    if (strlen(ip_env) != 0)
      return ip_env;
    else
      std::cerr << "invalid DZMQ_IP (an empty string)" << std::endl;
  }

  // Second, try the hostname
  char host[1024];
  memset(host, 0, sizeof(host));
  if (gethostname(host, sizeof(host) - 1) != 0)
    std::cerr << "determineIP: gethostname failed" << std::endl;

  // We don't want localhost to be our ip
  else if (strlen(host) && strcmp("localhost", host))
  {
    std::string hostIP;
    strcat(host, ".local");
    if (hostnameToIp(host, hostIP) == 0)
    {
      return std::string(hostIP);
    }
  }

  // Third, fall back on interface search, which will yield an IP address
#ifdef HAVE_IFADDRS
  struct ifaddrs *ifa = nullptr, *ifp = NULL;
  int rc;
  if ((rc = getifaddrs(&ifp)) < 0)
  {
    std::cerr << "error in getifaddrs: " << strerror(rc) << std::endl;
    exit(-1);
  }
  char preferred_ip[200] = {0};
  for (ifa = ifp; ifa; ifa = ifa->ifa_next)
  {
    char ip_[200];
    socklen_t salen;
    if (!ifa->ifa_addr)
      continue;  // evidently this interface has no ip address
    if (ifa->ifa_addr->sa_family == AF_INET)
      salen = sizeof(struct sockaddr_in);
    else if (ifa->ifa_addr->sa_family == AF_INET6)
      salen = sizeof(struct sockaddr_in6);
    else
      continue;
    if (getnameinfo(ifa->ifa_addr, salen, ip_, sizeof(ip_), nullptr, 0,
                    NI_NUMERICHOST) < 0)
    {
      std::cout << "getnameinfo couldn't get the ip of interface " <<
                   ifa->ifa_name << std::endl;
      continue;
    }
    // prefer non-private IPs over private IPs
    if (!strcmp("127.0.0.1", ip_) || strchr(ip_, ':'))
      continue;  // ignore loopback unless we have no other choice
    if (ifa->ifa_addr->sa_family == AF_INET6 && !preferred_ip[0])
      strcpy(preferred_ip, ip_);
    else if (isPrivateIP(ip_) && !preferred_ip[0])
      strcpy(preferred_ip, ip_);
    else if (!isPrivateIP(ip_) &&
             (isPrivateIP(preferred_ip) || !preferred_ip[0]))
      strcpy(preferred_ip, ip_);
  }
  freeifaddrs(ifp);
  if (!preferred_ip[0])
  {
    std::cerr <<
      "Couldn't find a preferred IP via the getifaddrs() call; "
      "I'm assuming that your IP "
      "address is 127.0.0.1.  This should work for local processes, "
      "but will almost certainly not work if you have remote processes."
      "Report to the disc-zmq development team to seek a fix." << std::endl;
    return std::string("127.0.0.1");
  }
  return std::string(preferred_ip);
#else
  // @todo Fix IP determination in the case where getifaddrs() isn't
  // available.
  std::cerr <<
    "You don't have the getifaddrs() call; I'm assuming that your IP "
    "address is 127.0.0.1.  This should work for local processes, "
    "but will almost certainly not work if you have remote processes."
    "Report to the disc-zmq development team to seek a fix." << std::endl;
  return std::string("127.0.0.1");
#endif
}
<|endoftext|>


<commit_before>/*****************************************************************************

  Licensed to Accellera Systems Initiative Inc. (Accellera) under one or
  more contributor license agreements.  See the NOTICE file distributed
  with this work for additional information regarding copyright ownership.
  Accellera licenses this file to you under the Apache License, Version 2.0
  (the "License"); you may not use this file except in compliance with the
  License.  You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

  Unless required by applicable law or agreed to in writing, software
  distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
  implied.  See the License for the specific language governing
  permissions and limitations under the License.

 *****************************************************************************/

#ifndef __SYSTEMC_EXT_TLM_CORE_1_REQ_RSP_PORTS_EVENT_FINDER_HH__
#define __SYSTEMC_EXT_TLM_CORE_1_REQ_RSP_PORTS_EVENT_FINDER_HH__

#include <sstream>

#include "../interfaces/tag.hh"

namespace tlm
{

template <class IF, class T>
class tlm_event_finder_t : public sc_core::sc_event_finder
{
  public:
    tlm_event_finder_t(const sc_core::sc_port_base &port_,
                       const sc_core::sc_event &(IF::*event_method_)(
                           tlm_tag<T> *) const) :
        sc_core::sc_event_finder(port_), m_event_method(event_method_)
    {}

    virtual ~tlm_event_finder_t() {}

    virtual const sc_core::sc_event &
        find_event(sc_core::sc_interface *if_p=nullptr) const;

  private:
    const sc_core::sc_event &(IF::*m_event_method)(tlm_tag<T> *) const;

  private:
    // disabled
    tlm_event_finder_t();
    tlm_event_finder_t(const tlm_event_finder_t<IF, T> &);
    tlm_event_finder_t<IF, T> &operator = (const tlm_event_finder_t<IF, T> &);
};

template <class IF, class T>
inline const sc_core::sc_event &
tlm_event_finder_t<IF, T>::find_event(sc_core::sc_interface *if_p) const
{
    const IF *iface = if_p ? dynamic_cast<const IF *>(if_p) :
        dynamic_cast<const IF *>(port()->_gem5Interface(0));
    if (iface == nullptr) {
        std::ostringstream out;
        out << "port is not bound: port '" << port()->name() <<
            "' (" << port()->kind() << ")";
        SC_REPORT_ERROR(sc_core::SC_ID_FIND_EVENT_, out.str().c_str());
        static sc_core::sc_event none;
        return none;
    }
    return (const_cast<IF *>(iface)->*m_event_method)(nullptr);
}

} // namespace tlm

#endif /* __SYSTEMC_EXT_TLM_CORE_1_REQ_RSP_PORTS_EVENT_FINDER_HH__ */
<commit_msg>systemc: Fix up some lingering Accellera specific code in TLM v1.<commit_after>/*****************************************************************************

  Licensed to Accellera Systems Initiative Inc. (Accellera) under one or
  more contributor license agreements.  See the NOTICE file distributed
  with this work for additional information regarding copyright ownership.
  Accellera licenses this file to you under the Apache License, Version 2.0
  (the "License"); you may not use this file except in compliance with the
  License.  You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

  Unless required by applicable law or agreed to in writing, software
  distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
  implied.  See the License for the specific language governing
  permissions and limitations under the License.

 *****************************************************************************/

#ifndef __SYSTEMC_EXT_TLM_CORE_1_REQ_RSP_PORTS_EVENT_FINDER_HH__
#define __SYSTEMC_EXT_TLM_CORE_1_REQ_RSP_PORTS_EVENT_FINDER_HH__

#include <sstream>

#include "../interfaces/tag.hh"

namespace tlm
{

template <class IF, class T>
class tlm_event_finder_t : public sc_core::sc_event_finder_t<IF>
{
  public:
    tlm_event_finder_t(const sc_core::sc_port_base &port_,
                       const sc_core::sc_event &(IF::*event_method_)(
                           tlm_tag<T> *) const) :
        sc_core::sc_event_finder_t<IF>(port_), m_event_method(event_method_)
    {}

    virtual ~tlm_event_finder_t() {}

    virtual const sc_core::sc_event &
        find_event(sc_core::sc_interface *if_p=nullptr) const;

  private:
    const sc_core::sc_event &(IF::*m_event_method)(tlm_tag<T> *) const;

  private:
    // disabled
    tlm_event_finder_t();
    tlm_event_finder_t(const tlm_event_finder_t<IF, T> &);
    tlm_event_finder_t<IF, T> &operator = (const tlm_event_finder_t<IF, T> &);
};

template <class IF, class T>
inline const sc_core::sc_event &
tlm_event_finder_t<IF, T>::find_event(sc_core::sc_interface *if_p) const
{
    const IF *iface = if_p ? dynamic_cast<const IF *>(if_p) :
        dynamic_cast<const IF *>(this->port()->_gem5Interface(0));
    if (iface == nullptr) {
        std::ostringstream out;
        out << "port is not bound: port '" << this->port()->name() <<
            "' (" << this->port()->kind() << ")";
        SC_REPORT_ERROR(sc_core::SC_ID_FIND_EVENT_, out.str().c_str());
        static sc_core::sc_event none;
        return none;
    }
    return (const_cast<IF *>(iface)->*m_event_method)(nullptr);
}

} // namespace tlm

#endif /* __SYSTEMC_EXT_TLM_CORE_1_REQ_RSP_PORTS_EVENT_FINDER_HH__ */
<|endoftext|>


<commit_before>#include "qnetstring.h"

/**********************************************************************************************************************/
/* Public API                                                                                */
/**********************************************************************************************************************/

QNetString::QNetString(QObject *parent) :
    QObject(parent)
{
    // Connect to our internal signals
    connect(this, SIGNAL(tryParse()), this, SLOT(onTryParse()));
} // end QNetString

QByteArray QNetString::encode(QByteArray data)
{
    return QString("%1:%2,").arg(data.length()).arg(data.constData()).toUtf8();
} // end encode

/**********************************************************************************************************************/
/* Public Slots                                                                                */
/**********************************************************************************************************************/

void QNetString::addData(QByteArray data)
{
    this->buffer.append(data);
    emit tryParse();
} // end addData

/**********************************************************************************************************************/
/* Private Slots                                                                                */
/**********************************************************************************************************************/

void QNetString::onTryParse()
{
    int netstringLength = -1;

    while(true)
    {
        // If the buffer's empty or we don't have a colon, we can't parse.
        if(this->buffer.length() == 0 || !buffer.contains(':'))
        {
            // We don't have enough data to read
            return;
        } // end if

        int idx = buffer.indexOf(':');

        // Determine our length
        netstringLength = buffer.left(idx).toInt();

        if(buffer.length() < idx + netstringLength + 2)
        {
            return;
        } // end if

        if(buffer[netstringLength + idx + 1] != ',')
        {
            qCritical() << "Invalid netstring: " << QString(buffer);
        } // end if

        // Pull out our data
        QByteArray data = buffer.mid(idx + 1, netstringLength);

        //qDebug() << "Data: " << data;

        // Trim our buffer, and reset our lengh
        buffer = buffer.mid(idx + netstringLength + 2);

        //qDebug() << "Buffer: " << buffer;

        // Emit the data
        emit dataReady(data);
    } // end while
} // end onTryParse
<commit_msg>fixed a bug where we would not properly encode a netstring the moment we left the range of ASCII values. Now, we do it all with QByteArray, which should be faster, and much much much more robust. This solves an issue that prevented AES encrypted data from being sent.<commit_after>#include "qnetstring.h"

/**********************************************************************************************************************/
/* Public API                                                                                */
/**********************************************************************************************************************/

QNetString::QNetString(QObject *parent) :
    QObject(parent)
{
    // Connect to our internal signals
    connect(this, SIGNAL(tryParse()), this, SLOT(onTryParse()));
} // end QNetString

QByteArray QNetString::encode(QByteArray data)
{
	return QByteArray::number(data.length(), 10).append(':').append(data).append(',');
} // end encode

/**********************************************************************************************************************/
/* Public Slots                                                                                */
/**********************************************************************************************************************/

void QNetString::addData(QByteArray data)
{
    this->buffer.append(data);
    emit tryParse();
} // end addData

/**********************************************************************************************************************/
/* Private Slots                                                                                */
/**********************************************************************************************************************/

void QNetString::onTryParse()
{
    int netstringLength = -1;

    while(true)
    {
        // If the buffer's empty or we don't have a colon, we can't parse.
        if(this->buffer.length() == 0 || !buffer.contains(':'))
        {
            // We don't have enough data to read
            return;
        } // end if

        int idx = buffer.indexOf(':');

        // Determine our length
        netstringLength = buffer.left(idx).toInt();

        if(buffer.length() < idx + netstringLength + 2)
        {
            return;
        } // end if

        if(buffer[netstringLength + idx + 1] != ',')
        {
            qCritical() << "Invalid netstring: " << QString(buffer);
        } // end if

        // Pull out our data
        QByteArray data = buffer.mid(idx + 1, netstringLength);

        //qDebug() << "Data: " << data;

        // Trim our buffer, and reset our lengh
        buffer = buffer.mid(idx + netstringLength + 2);

        //qDebug() << "Buffer: " << buffer;

        // Emit the data
        emit dataReady(data);
    } // end while
} // end onTryParse
<|endoftext|>


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

// This is a test file for our protobuf specifications of bmv2 json.
// It reads an input bmv2 json string (usually the output of p4c) via stdin,
// it parses the string using protobuf, and then dumps the parsed protobuf
// objects using protobuf text format and json.
// The dumps are written to output files whose paths are provided as command
// line arguments.

// The implementation of our PDPI interface.

#include "p4_symbolic/ir/pdpi_driver.h"

#include <memory>

#include "p4_pdpi/util.h"

namespace p4_symbolic {
namespace ir {

// Parse into standard p4 protobuf and then into PDPI.
// If either of these steps fail, their failure status is returned.
pdpi::StatusOr<pdpi::ir::IrP4Info> ParsePdpi(std::string p4info_path) {
  // Verify link and compile versions are the same.
  GOOGLE_PROTOBUF_VERIFY_VERSION;

  // Parse the p4info file into the standard p4 protobuf.
  p4::config::v1::P4Info p4info;
  RETURN_IF_ERROR(pdpi::ReadProtoFromFile(p4info_path, &p4info));

  // Transform the p4 protobuf to a pdpi protobuf using a pdpi::P4InfoManager.
  pdpi::StatusOr<std::unique_ptr<pdpi::P4InfoManager>> status_or_info =
      pdpi::P4InfoManager::Create(p4info);
  RETURN_IF_ERROR(status_or_info.status());

  return pdpi::StatusOr<pdpi::ir::IrP4Info>(
      status_or_info.value()->GetIrP4Info());
}

}  // namespace ir
}  // namespace p4_symbolic
<commit_msg>remove google protobuf verify version from pdpi_driver<commit_after>// Copyright 2020 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// This is a test file for our protobuf specifications of bmv2 json.
// It reads an input bmv2 json string (usually the output of p4c) via stdin,
// it parses the string using protobuf, and then dumps the parsed protobuf
// objects using protobuf text format and json.
// The dumps are written to output files whose paths are provided as command
// line arguments.

// The implementation of our PDPI interface.

#include "p4_symbolic/ir/pdpi_driver.h"

#include <memory>

#include "p4_pdpi/util.h"

namespace p4_symbolic {
namespace ir {

// Parse into standard p4 protobuf and then into PDPI.
// If either of these steps fail, their failure status is returned.
pdpi::StatusOr<pdpi::ir::IrP4Info> ParsePdpi(std::string p4info_path) {
  // Parse the p4info file into the standard p4 protobuf.
  p4::config::v1::P4Info p4info;
  RETURN_IF_ERROR(pdpi::ReadProtoFromFile(p4info_path, &p4info));

  // Transform the p4 protobuf to a pdpi protobuf using a pdpi::P4InfoManager.
  pdpi::StatusOr<std::unique_ptr<pdpi::P4InfoManager>> status_or_info =
      pdpi::P4InfoManager::Create(p4info);
  RETURN_IF_ERROR(status_or_info.status());

  return pdpi::StatusOr<pdpi::ir::IrP4Info>(
      status_or_info.value()->GetIrP4Info());
}

}  // namespace ir
}  // namespace p4_symbolic
<|endoftext|>


<commit_before>// Copyright (c) 2014, German Neuroinformatics Node (G-Node)
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted under the terms of the BSD License. See
// LICENSE file in the root of the Project.

#include <boost/python.hpp>
#include <boost/optional.hpp>

#include <nix.hpp>
#include <accessors.hpp>
#include <transmorgify.hpp>

#include <PyEntity.hpp>
#include <PyValue.hpp>

using namespace nix;
using namespace boost::python;

namespace nixpy {

void PyValue::do_export() {

    class_<Value>("Value")
        .def_readwrite("reference", &Value::reference)
        .def_readwrite("filename", &Value::filename)
        .def_readwrite("encoder", &Value::encoder)
        .def_readwrite("checksum", &Value::checksum)
        ;

    to_python_converter<std::vector<Value>, vector_transmogrify<Value>>();
    vector_transmogrify<Value>::register_from_python();
    to_python_converter<boost::optional<Value>, option_transmogrify<Value>>();

}

}
<commit_msg>PyValue: constructors and setter and setter<commit_after>// Copyright (c) 2014, German Neuroinformatics Node (G-Node)
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted under the terms of the BSD License. See
// LICENSE file in the root of the Project.

#include <boost/python.hpp>
#include <boost/optional.hpp>

#include <nix.hpp>
#include <accessors.hpp>
#include <transmorgify.hpp>

#include <PyEntity.hpp>
#include <PyValue.hpp>

using namespace nix;
using namespace boost::python;

namespace nixpy {

std::shared_ptr<Value> create(PyObject* value) {

    std::shared_ptr<Value> created = std::make_shared<Value>(new Value());

    if (PyBool_Check(value)) {
        bool conv = extract<bool>(value);
        created->set(conv);
    } else if (PyInt_Check(value)) {
        int64_t conv = extract<int64_t>(value);
        created->set(conv);
    } else if (PyFloat_Check(value)) {
        double conv = extract<double>(value);
        created->set(conv);
    } else if (PyString_Check(value)) {
        std::string conv = extract<std::string>(value);
        created->set(conv);
    } else {
        throw std::runtime_error("Wrong type");
    }

    return created;
}

void set(Value& ref, PyObject* value) {

    if (PyBool_Check(value)) {
        bool conv = extract<bool>(value);
        ref.set(conv);
    } else if (PyInt_Check(value)) {
        int64_t conv = extract<int64_t>(value);
        ref.set(conv);
    } else if (PyFloat_Check(value)) {
        double conv = extract<double>(value);
        ref.set(conv);
    } else if (PyString_Check(value)) {
        std::string conv = extract<std::string>(value);
        ref.set(conv);
    } else {
        throw std::runtime_error("Wrong type");
    }

}

PyObject* get(const Value& ref) {

    DataType type = ref.type();
    switch(type) {
        case DataType::Bool:
            return incref(object(ref.get<bool>()).ptr());
        case DataType::Float:
        case DataType::Double:
            return incref(object(ref.get<double>()).ptr());
        case DataType::Char:
        case DataType::Int8:
        case DataType::Int16:
        case DataType::Int32:
        case DataType::Int64:
            return incref(object(ref.get<int64_t>()).ptr());
        case DataType::UInt8:
        case DataType::UInt16:
        case DataType::UInt32:
        case DataType::UInt64:
            return incref(object(ref.get<u_int64_t>()).ptr());
        case DataType::String:
            return incref(object(ref.get<std::string>()).ptr());
        case DataType::Date:
        case DataType::DateTime:
            // TODO support for date
        case DataType::Nothing:
        default:
            Py_RETURN_NONE;
    }
}

void PyValue::do_export() {

    class_<Value>("Value")
        .def("__init__", make_constructor(create))
        .def_readwrite("reference", &Value::reference)
        .def_readwrite("filename", &Value::filename)
        .def_readwrite("encoder", &Value::encoder)
        .def_readwrite("checksum", &Value::checksum)
        .def("set", set)
        .def("get", get)
        // Other
        .def("__str__", &toStr<Value>)
        .def("__repr__", &toStr<Value>)
        ;

    to_python_converter<std::vector<Value>, vector_transmogrify<Value>>();
    vector_transmogrify<Value>::register_from_python();
    to_python_converter<boost::optional<Value>, option_transmogrify<Value>>();

}

}
<|endoftext|>


<commit_before>#ifndef SAPLIST_HPP
#define SAPLIST_HPP 1

#include <functional>
#include <map>
#include <typeinfo>
#include <climits>
#include "CollisionManager.hpp"

class Collisionable {
protected: int x, y, w, h;
public: Collisionable(int x=0, int y=0, int w=0, int h=0) :
    x(x), y(y), w(w), h(h) {}
};

class SAPList : public CollisionManager<Collisionable> {

    class EndPoint;

    class AABB {
    public:
        /** min/max
         *  - first is x axis
         *  - second is y axis */
        EndPoint * min[2];
        EndPoint * max[2];

        size_t typeId; /* Need to use std::type_info::hash_code() */
        void * owner;
    };

    /**
     * TODO:
     * - Optimize merging isMin boolean into another member
     *   (as a flag)
     * - Using doubly-linked list could waste memory but is easier to implement
     *   than arrays.
     * - Implement pair manager
     */
    class EndPoint {
    public:
        AABB * owner;
        int value;
        bool isMin;

        EndPoint * prev;
        EndPoint * next;

        EndPoint (AABB* o,int v,bool m,EndPoint* p,EndPoint* n) :
            owner(o), value(v), isMin(m), prev(p), next(n) {}

        /** When and EndPoint is destroyed, it updates prev and next */
        ~EndPoint () {
            if (this->prev != NULL) {
                this->prev->next = this->next;
            }
            if (this->next != NULL)
                this->next->prev = this->prev;
        }
    };

    /**
     * Action manager stores actions to perform on collision or separation
     * of two objects depending on their type
     * It also stores default actions to execute if no specific action is
     * defined for two types.
     */
    class ActionManager {
    public:
        std::map < std::pair < size_t,size_t >,
                   std::pair < std::function < void (void *, void *) >,
                               std::function < void (void *, void *) > > >
        actions;

        std::function < void (void *, void *) >
        onCollision(size_t t1, size_t t2) {
            return this
                ->actions[std::pair<size_t, size_t>(t1,t2)].first;
        }

        std::function < void (void *, void *) >
        onSeparation(size_t t1, size_t t2) {
            return this
                ->actions[std::pair<size_t, size_t>(t1,t2)].second;
        }
    };

private:

    EndPoint * xAxis;
    EndPoint * yAxis;
    ActionManager actions;

    void swap(EndPoint * p1, EndPoint * p2) {
        p2->next->prev = p1;
        p1->next = p2->next;
        p1->prev->next = p2;
        p1->prev = p2;
        p2->next = p1;
    }

    /* check on one axis */
    inline bool partialCollisionCheck(const AABB & b1,
                                      const AABB & b2,
                                      int dim) {
        return (b1.max[dim] <= b2.max[dim] && b1.max[dim] >= b2.min[dim])
            || (b1.min[dim] >= b2.min[dim] && b1.max[dim] <= b2.max[dim]);
    }

    bool collisionCheck(const AABB & b1, const AABB & b2) {
        return partialCollisionCheck (b1, b2, 0)
            && partialCollisionCheck (b1, b2, 1);
    }

    void updateEndPoint(EndPoint * pt) {

         auto aux =
            [&pt, this]
            (std::function<EndPoint*(EndPoint*)>succ,
             std::function<bool(int,int)>loop_cond,
             std::function<bool(EndPoint*,EndPoint*)>mustAdd,
             std::function<bool(EndPoint*,EndPoint*)>mustRm) {

            EndPoint * tmp = succ(pt);

            while (loop_cond(tmp->value, pt->value)) {
                this->swap(tmp, pt);
                if (mustAdd(pt, tmp)) {
                    if (this->collisionCheck(*(pt->owner), *(tmp->owner))) {
                    this->actions.onCollision
                        (pt->owner->typeId, tmp->owner->typeId)
                        (pt->owner->owner, tmp->owner->owner);
                    }
                } else if (mustRm(pt, tmp)) {
                    this->actions.onSeparation
                        (pt->owner->typeId,tmp->owner->typeId)
                        (pt->owner->owner, tmp->owner->owner);
                }
            }
        };

        /** TODO: use aux to update on x and y axis */

    }

public:

    SAPList () {
        /* not sure about the true/false values */
        xAxis = new EndPoint(NULL, INT_MIN, true, NULL, NULL);
        xAxis->next = new EndPoint(NULL, INT_MAX, false, xAxis, NULL);
        yAxis = new EndPoint(NULL, INT_MIN, true, NULL, NULL);
        yAxis->next = new EndPoint(NULL, INT_MAX, false, yAxis, NULL);
    }

    ~SAPList () {

        while (xAxis->next != NULL) {
            delete xAxis->next;
        } delete xAxis;

        while (yAxis->next != NULL) {
            delete yAxis->next;
        } delete yAxis;
    }

    void addObject(const Collisionable &) {}
    void updateObject(const Collisionable &) {}
    void removeObject(const Collisionable &) {}
};

#endif
<commit_msg>Doc++, used public field in Collisionable objects, new functions: - AABB constructor - mk_AABB<commit_after>#ifndef SAPLIST_HPP
#define SAPLIST_HPP 1

#include <functional>
#include <map>
#include <typeinfo>
#include <climits>
#include "CollisionManager.hpp"

class Collisionable {
    /* FIXME: use getters instead of public fields */
public:
    int x, y, w, h;
    Collisionable(int x=0, int y=0, int w=0, int h=0) :
    x(x), y(y), w(w), h(h) {}
};

class SAPList : public CollisionManager<Collisionable> {

    class EndPoint;

    class AABB {
    public:
        /** min/max
         *  - first is x axis
         *  - second is y axis */
        EndPoint * min[2];
        EndPoint * max[2];

        size_t typeId; /* Need to use std::type_info::hash_code() */
        void * owner;

        AABB (int * minX, int minY, int maxX, int maxY, size_t t, void * o) :
            typeId(t), owner(o) {
            min[0] = minX;
            min[1] = minY;
            max[0] = maxX;
            max[1] = maxY;
        }

    };

    /**
     * TODO:
     * - Optimize merging isMin boolean into another member
     *   (as a flag)
     * - Using doubly-linked list could waste memory but is easier to implement
     *   than arrays.
     * - Implement pair manager
     */
    class EndPoint {
    public:
        AABB * owner;
        int value;
        bool isMin;

        EndPoint * prev;
        EndPoint * next;

        EndPoint (AABB* o,int v,bool m,EndPoint* p,EndPoint* n) :
            owner(o), value(v), isMin(m), prev(p), next(n) {}

        /** When and EndPoint is destroyed, it updates prev and next */
        ~EndPoint () {
            if (this->prev != NULL) {
                this->prev->next = this->next;
            }
            if (this->next != NULL)
                this->next->prev = this->prev;
        }
    };

    /**
     * Action manager stores actions to perform on collision or separation
     * of two objects depending on their type
     * It also stores default actions to execute if no specific action is
     * defined for two types.
     */
    class ActionManager {
    public:
        /**
         * action table stores 2 actions per types couple:
         * - first is onCollision
         * - second is onSeparation
         */
        std::map < std::pair < size_t,size_t >,
                   std::pair < std::function < void (void *, void *) >,
                               std::function < void (void *, void *) > > >
        actions;

        /**
         * @param t1 type id of first object
         * @param t2 type id of second object
         * @return function to call on t1/t2 collision
         */
        std::function < void (void *, void *) >
        onCollision(size_t t1, size_t t2) {
            return this
                ->actions[std::pair<size_t, size_t>(t1,t2)].first;
        }

        /**
         * @param t1 type id of first object
         * @param t2 type id of second object
         * @return function to call on t1/t2 separation
         */
        std::function < void (void *, void *) >
        onSeparation(size_t t1, size_t t2) {
            return this
                ->actions[std::pair<size_t, size_t>(t1,t2)].second;
        }
    };

private:

    EndPoint * xAxis;
    EndPoint * yAxis;
    ActionManager actions;

    /** Swap two EndPoint * */
    void swap(EndPoint * p1, EndPoint * p2) {
        p2->next->prev = p1;
        p1->next = p2->next;
        p1->prev->next = p2;
        p1->prev = p2;
        p2->next = p1;
    }

    /** A collision between two AABB on one axis */
    inline bool partialCollisionCheck(const AABB & b1,
                                      const AABB & b2,
                                      int dim) {
        return (b1.max[dim] <= b2.max[dim] && b1.max[dim] >= b2.min[dim])
            || (b1.min[dim] >= b2.min[dim] && b1.max[dim] <= b2.max[dim]);
    }

    /**
     * Check if two AABB collide using 2 axises
     * @see partialCollisionCheck
     */
    bool collisionCheck(const AABB & b1, const AABB & b2) {
        return partialCollisionCheck (b1, b2, 0)
            && partialCollisionCheck (b1, b2, 1);
    }

    /** Create the AABB corresponding to a collisionable object
     * @param c the object used to create the corresponding AABB
     * @return a pointer to freshly heap-allocated AABB
     */
    AABB * mk_AABB(const Collisionable & c) {
        EndPoint * miX, * miY, * maX, * maY;

        /* TODO: create EndPoints */

        return new AABB(miX, miY, maX, maY, typeid(c).hash_code, (void *) c);
    }

    /** Update EndPoint place and call the appropriate function in case
     * of collision/separation
     * @param pt the EndPoint to update
     */
    void updateEndPoint(EndPoint * pt) {

         auto aux =
            [&pt, this]
            (std::function<EndPoint*(EndPoint*)>succ,
             std::function<bool(int,int)>loop_cond,
             std::function<bool(EndPoint*,EndPoint*)>mustAdd,
             std::function<bool(EndPoint*,EndPoint*)>mustRm) {

            EndPoint * tmp = succ(pt);

            while (loop_cond(tmp->value, pt->value)) {
                this->swap(tmp, pt);
                if (mustAdd(pt, tmp)) {
                    if (this->collisionCheck(*(pt->owner), *(tmp->owner))) {
                    this->actions.onCollision
                        (pt->owner->typeId, tmp->owner->typeId)
                        (pt->owner->owner, tmp->owner->owner);
                    }
                } else if (mustRm(pt, tmp)) {
                    this->actions.onSeparation
                        (pt->owner->typeId,tmp->owner->typeId)
                        (pt->owner->owner, tmp->owner->owner);
                }
            }
        };

        /** TODO: use aux to update on x and y axis */

    }

public:

    SAPList () {
        /* not sure about the true/false values */
        xAxis = new EndPoint(NULL, INT_MIN, true, NULL, NULL);
        xAxis->next = new EndPoint(NULL, INT_MAX, false, xAxis, NULL);
        yAxis = new EndPoint(NULL, INT_MIN, true, NULL, NULL);
        yAxis->next = new EndPoint(NULL, INT_MAX, false, yAxis, NULL);
    }

    ~SAPList () {

        while (xAxis->next != NULL) {
            delete xAxis->next;
        } delete xAxis;

        while (yAxis->next != NULL) {
            delete yAxis->next;
        } delete yAxis;
    }

    void addObject(const Collisionable &) {}
    void updateObject(const Collisionable &) {}
    void removeObject(const Collisionable &) {}
};

#endif
<|endoftext|>