13c827367444ee418f129b2c238299f49d3264554Jarkko Poyry/*-------------------------------------------------------------------------
23c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * drawElements Quality Program Execution Server
33c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * ---------------------------------------------
43c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
53c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * Copyright 2014 The Android Open Source Project
63c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
73c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * Licensed under the Apache License, Version 2.0 (the "License");
83c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * you may not use this file except in compliance with the License.
93c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * You may obtain a copy of the License at
103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *      http://www.apache.org/licenses/LICENSE-2.0
123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * Unless required by applicable law or agreed to in writing, software
143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * distributed under the License is distributed on an "AS IS" BASIS,
153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * See the License for the specific language governing permissions and
173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * limitations under the License.
183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *//*!
203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \file
213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \brief Test Execution Server.
223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *//*--------------------------------------------------------------------*/
233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "xsExecutionServer.hpp"
253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "deClock.h"
263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include <cstdio>
283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
293c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing std::vector;
303c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing std::string;
313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#if 1
333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#	define DBG_PRINT(X) printf X
343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#else
353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#	define DBG_PRINT(X)
363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#endif
373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
383c827367444ee418f129b2c238299f49d3264554Jarkko Poyrynamespace xs
393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
413c827367444ee418f129b2c238299f49d3264554Jarkko Poyryinline bool MessageBuilder::isComplete (void) const
423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (m_buffer.size() < MESSAGE_HEADER_SIZE)
443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return false;
453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
46745d7c616351405cfb6d2a7133d261eb4989d626Jarkko Pöyry		return m_buffer.size() == getMessageSize();
473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
493c827367444ee418f129b2c238299f49d3264554Jarkko Poyryconst deUint8* MessageBuilder::getMessageData (void) const
503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return m_buffer.size() > MESSAGE_HEADER_SIZE ? &m_buffer[MESSAGE_HEADER_SIZE] : DE_NULL;
523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
54745d7c616351405cfb6d2a7133d261eb4989d626Jarkko Pöyrysize_t MessageBuilder::getMessageDataSize (void) const
553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(isComplete());
57745d7c616351405cfb6d2a7133d261eb4989d626Jarkko Pöyry	return m_buffer.size() - MESSAGE_HEADER_SIZE;
583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
603c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid MessageBuilder::read (ByteBuffer& src)
613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Try to get header.
633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (m_buffer.size() < MESSAGE_HEADER_SIZE)
643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		while (m_buffer.size() < MESSAGE_HEADER_SIZE &&
663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			   src.getNumElements() > 0)
673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			m_buffer.push_back(src.popBack());
683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		DE_ASSERT(m_buffer.size() <= MESSAGE_HEADER_SIZE);
703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (m_buffer.size() == MESSAGE_HEADER_SIZE)
723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			// Got whole header, parse it.
743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			Message::parseHeader(&m_buffer[0], (int)m_buffer.size(), m_messageType, m_messageSize);
753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (m_buffer.size() >= MESSAGE_HEADER_SIZE)
793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// We have header.
81745d7c616351405cfb6d2a7133d261eb4989d626Jarkko Pöyry		size_t msgSize			= getMessageSize();
82745d7c616351405cfb6d2a7133d261eb4989d626Jarkko Pöyry		size_t numBytesLeft		= msgSize - m_buffer.size();
83745d7c616351405cfb6d2a7133d261eb4989d626Jarkko Pöyry		size_t numToRead		= (size_t)de::min(src.getNumElements(), (int)numBytesLeft);
843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (numToRead > 0)
863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			int curBufPos = (int)m_buffer.size();
883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			m_buffer.resize(curBufPos+numToRead);
89745d7c616351405cfb6d2a7133d261eb4989d626Jarkko Pöyry			src.popBack(&m_buffer[curBufPos], (int)numToRead);
903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
943c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid MessageBuilder::clear (void)
953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_buffer.clear();
973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_messageType	= MESSAGETYPE_NONE;
983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_messageSize	= 0;
993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
1003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1013c827367444ee418f129b2c238299f49d3264554Jarkko PoyryExecutionServer::ExecutionServer (xs::TestProcess* testProcess, deSocketFamily family, int port, RunMode runMode)
1023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	: TcpServer		(family, port)
1033fdee359c9eee4d6c1d823b23f7f64631b5945f8Jarkko Pöyry	, m_testDriver	(testProcess)
1043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_runMode		(runMode)
1053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
1073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1083c827367444ee418f129b2c238299f49d3264554Jarkko PoyryExecutionServer::~ExecutionServer (void)
1093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
1113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1123c827367444ee418f129b2c238299f49d3264554Jarkko PoyryTestDriver* ExecutionServer::acquireTestDriver (void)
1133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (!m_testDriverLock.tryLock())
1153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		throw Error("Failed to acquire test driver");
1163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return &m_testDriver;
1183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
1193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1203c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid ExecutionServer::releaseTestDriver (TestDriver* driver)
1213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(&m_testDriver == driver);
1233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_UNREF(driver);
1243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_testDriverLock.unlock();
1253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
1263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1273c827367444ee418f129b2c238299f49d3264554Jarkko PoyryConnectionHandler* ExecutionServer::createHandler (de::Socket* socket, const de::SocketAddress& clientAddress)
1283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	printf("ExecutionServer: New connection from %s:%d\n", clientAddress.getHost(), clientAddress.getPort());
1303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return new ExecutionRequestHandler(this, socket);
1313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
1323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1333c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid ExecutionServer::connectionDone (ConnectionHandler* handler)
1343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (m_runMode == RUNMODE_SINGLE_EXEC)
1363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_socket.close();
1373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	TcpServer::connectionDone(handler);
1393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
1403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1413c827367444ee418f129b2c238299f49d3264554Jarkko PoyryExecutionRequestHandler::ExecutionRequestHandler (ExecutionServer* server, de::Socket* socket)
1423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	: ConnectionHandler	(server, socket)
1433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_execServer		(server)
1443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_testDriver		(DE_NULL)
1453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_bufferIn		(RECV_BUFFER_SIZE)
1463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_bufferOut		(SEND_BUFFER_SIZE)
1473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_run				(false)
1483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_sendRecvTmpBuf	(SEND_RECV_TMP_BUFFER_SIZE)
1493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Set flags.
1513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_socket->setFlags(DE_SOCKET_NONBLOCKING|DE_SOCKET_KEEPALIVE|DE_SOCKET_CLOSE_ON_EXEC);
1523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Init protocol keepalives.
1543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	initKeepAlives();
1553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
1563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1573c827367444ee418f129b2c238299f49d3264554Jarkko PoyryExecutionRequestHandler::~ExecutionRequestHandler (void)
1583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (m_testDriver)
1603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_execServer->releaseTestDriver(m_testDriver);
1613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
1623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1633c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid ExecutionRequestHandler::handle (void)
1643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DBG_PRINT(("ExecutionRequestHandler::handle()\n"));
1663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	try
1683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
1693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// Process execution session.
1703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		processSession();
1713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
1723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	catch (const std::exception& e)
1733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
1743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		printf("ExecutionRequestHandler::run(): %s\n", e.what());
1753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
1763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DBG_PRINT(("ExecutionRequestHandler::handle(): Done!\n"));
1783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Release test driver.
1803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (m_testDriver)
1813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
1823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		try
1833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
1843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			m_testDriver->reset();
1853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
1863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		catch (...)
1873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
1883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
1893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_execServer->releaseTestDriver(m_testDriver);
1903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_testDriver = DE_NULL;
1913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
1923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Close connection.
1943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (m_socket->isConnected())
1953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_socket->shutdown();
1963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
1973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1983c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid ExecutionRequestHandler::acquireTestDriver (void)
1993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
2003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(!m_testDriver);
2013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Try to acquire test driver - may fail.
2033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_testDriver = m_execServer->acquireTestDriver();
2043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(m_testDriver);
2053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_testDriver->reset();
2063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
2083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2093c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid ExecutionRequestHandler::processSession (void)
2103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
2113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_run = true;
2123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	deUint64 lastIoTime = deGetMicroseconds();
2143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	while (m_run)
2163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
2173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		bool anyIO = false;
2183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// Read from socket to buffer.
2203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		anyIO = receive() || anyIO;
2213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// Send bytes in buffer.
2233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		anyIO = send() || anyIO;
2243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// Process incoming data.
2263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (m_bufferIn.getNumElements() > 0)
2273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
2283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			DE_ASSERT(!m_msgBuilder.isComplete());
2293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			m_msgBuilder.read(m_bufferIn);
2303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
2313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (m_msgBuilder.isComplete())
2333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
2343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			// Process message.
2353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			processMessage(m_msgBuilder.getMessageType(), m_msgBuilder.getMessageData(), m_msgBuilder.getMessageDataSize());
2363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			m_msgBuilder.clear();
2383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
2393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// Keepalives, anyone?
2413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		pollKeepAlives();
2423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// Poll test driver for IO.
2443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (m_testDriver)
2453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			anyIO = getTestDriver()->poll(m_bufferOut) || anyIO;
2463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// If no IO happens in a reasonable amount of time, go to sleep.
2483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
2493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			deUint64 curTime = deGetMicroseconds();
2503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (anyIO)
2513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				lastIoTime = curTime;
2523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			else if (curTime-lastIoTime > SERVER_IDLE_THRESHOLD*1000)
2533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				deSleep(SERVER_IDLE_SLEEP); // Too long since last IO, sleep for a while.
2543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			else
2553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				deYield(); // Just give other threads chance to run.
2563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
2573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
2583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
2593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
260745d7c616351405cfb6d2a7133d261eb4989d626Jarkko Pöyryvoid ExecutionRequestHandler::processMessage (MessageType type, const deUint8* data, size_t dataSize)
2613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
2623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	switch (type)
2633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
2643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case MESSAGETYPE_HELLO:
2653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
2663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			HelloMessage msg(data, dataSize);
2673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			DBG_PRINT(("HelloMessage: version = %d\n", msg.version));
2683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (msg.version != PROTOCOL_VERSION)
2693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				throw ProtocolError("Unsupported protocol version");
2703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			break;
2713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
2723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case MESSAGETYPE_TEST:
2743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
2753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			TestMessage msg(data, dataSize);
2763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			DBG_PRINT(("TestMessage: '%s'\n", msg.test.c_str()));
2773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			break;
2783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
2793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case MESSAGETYPE_KEEPALIVE:
2813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
2823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			KeepAliveMessage msg(data, dataSize);
2833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			DBG_PRINT(("KeepAliveMessage\n"));
2843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			keepAliveReceived();
2853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			break;
2863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
2873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case MESSAGETYPE_EXECUTE_BINARY:
2893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
2903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			ExecuteBinaryMessage msg(data, dataSize);
2913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			DBG_PRINT(("ExecuteBinaryMessage: '%s', '%s', '%s', '%s'\n", msg.name.c_str(), msg.params.c_str(), msg.workDir.c_str(), msg.caseList.substr(0, 10).c_str()));
2923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			getTestDriver()->startProcess(msg.name.c_str(), msg.params.c_str(), msg.workDir.c_str(), msg.caseList.c_str());
2933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			keepAliveReceived(); // \todo [2011-10-11 pyry] Remove this once Candy is fixed.
2943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			break;
2953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
2963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case MESSAGETYPE_STOP_EXECUTION:
2983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
2993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			StopExecutionMessage msg(data, dataSize);
3003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			DBG_PRINT(("StopExecutionMessage\n"));
3013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			getTestDriver()->stopProcess();
3023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			break;
3033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
3043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		default:
3063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			throw ProtocolError("Unsupported message");
3073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
3083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
3093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3103c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid ExecutionRequestHandler::initKeepAlives (void)
3113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
3123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	deUint64 curTime = deGetMicroseconds();
3133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_lastKeepAliveSent		= curTime;
3143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_lastKeepAliveReceived	= curTime;
3153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
3163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3173c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid ExecutionRequestHandler::keepAliveReceived (void)
3183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
3193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_lastKeepAliveReceived = deGetMicroseconds();
3203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
3213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3223c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid ExecutionRequestHandler::pollKeepAlives (void)
3233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
3243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	deUint64 curTime = deGetMicroseconds();
3253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Check that we've got keepalives in timely fashion.
3273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (curTime - m_lastKeepAliveReceived > KEEPALIVE_TIMEOUT*1000)
3283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		throw ProtocolError("Keepalive timeout occurred");
3293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Send some?
3313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (curTime - m_lastKeepAliveSent > KEEPALIVE_SEND_INTERVAL*1000 &&
3323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_bufferOut.getNumFree() >= MESSAGE_HEADER_SIZE)
3333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
3343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		vector<deUint8> buf;
3353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		KeepAliveMessage().write(buf);
3363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_bufferOut.pushFront(&buf[0], (int)buf.size());
3373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_lastKeepAliveSent = deGetMicroseconds();
3393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
3403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
3413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3423c827367444ee418f129b2c238299f49d3264554Jarkko Poyrybool ExecutionRequestHandler::receive (void)
3433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
344745d7c616351405cfb6d2a7133d261eb4989d626Jarkko Pöyry	size_t maxLen = de::min(m_sendRecvTmpBuf.size(), (size_t)m_bufferIn.getNumFree());
3453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (maxLen > 0)
3473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
348745d7c616351405cfb6d2a7133d261eb4989d626Jarkko Pöyry		size_t			numRecv;
3493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		deSocketResult	result	= m_socket->receive(&m_sendRecvTmpBuf[0], maxLen, &numRecv);
3503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (result == DE_SOCKETRESULT_SUCCESS)
3523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
3533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			DE_ASSERT(numRecv > 0);
354745d7c616351405cfb6d2a7133d261eb4989d626Jarkko Pöyry			m_bufferIn.pushFront(&m_sendRecvTmpBuf[0], (int)numRecv);
3553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return true;
3563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
3573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		else if (result == DE_SOCKETRESULT_CONNECTION_CLOSED)
3583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
3593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			m_run = false;
3603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return true;
3613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
3623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		else if (result == DE_SOCKETRESULT_WOULD_BLOCK)
3633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return false;
3643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		else if (result == DE_SOCKETRESULT_CONNECTION_TERMINATED)
3653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			throw ConnectionError("Connection terminated");
3663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		else
3673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			throw ConnectionError("receive() failed");
3683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
3693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
3703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return false;
3713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
3723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3733c827367444ee418f129b2c238299f49d3264554Jarkko Poyrybool ExecutionRequestHandler::send (void)
3743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
375745d7c616351405cfb6d2a7133d261eb4989d626Jarkko Pöyry	size_t maxLen = de::min(m_sendRecvTmpBuf.size(), (size_t)m_bufferOut.getNumElements());
3763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (maxLen > 0)
3783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
379745d7c616351405cfb6d2a7133d261eb4989d626Jarkko Pöyry		m_bufferOut.peekBack(&m_sendRecvTmpBuf[0], (int)maxLen);
3803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
381745d7c616351405cfb6d2a7133d261eb4989d626Jarkko Pöyry		size_t			numSent;
3823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		deSocketResult	result	= m_socket->send(&m_sendRecvTmpBuf[0], maxLen, &numSent);
3833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (result == DE_SOCKETRESULT_SUCCESS)
3853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
3863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			DE_ASSERT(numSent > 0);
387745d7c616351405cfb6d2a7133d261eb4989d626Jarkko Pöyry			m_bufferOut.popBack((int)numSent);
3883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return true;
3893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
3903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		else if (result == DE_SOCKETRESULT_CONNECTION_CLOSED)
3913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
3923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			m_run = false;
3933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return true;
3943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
3953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		else if (result == DE_SOCKETRESULT_WOULD_BLOCK)
3963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return false;
3973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		else if (result == DE_SOCKETRESULT_CONNECTION_TERMINATED)
3983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			throw ConnectionError("Connection terminated");
3993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		else
4003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			throw ConnectionError("send() failed");
4013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
4023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
4033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return false;
4043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
4053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} // xs
407