<commit_before>#include <QHBoxLayout>
/** \file
 *
 * \brief Declaration of \a QBrowseButton
 *
 * This file provides the declaration of the \a QBrowseButton class.
 *
 * \author Peter 'png' Hille <peter@das-system-networks.de>
 *
 * \version 1.0
 */
#include <QDebug>

#include "nullptr.h"
#include "QBrowseButton.h"

/** \brief Create new QBrowseButton instance
 *
 * Initializes a new QBrowseButton widget that can be used to browse for a
 * file.
 *
 * \param parent Parent QWidget that owns the newly created QBrowseButton
 */
QBrowseButton::QBrowseButton(QWidget *parent) :
    QFrame(parent), m_mode(QFileDialog::AnyFile), m_caption(tr("Browse for file")),
    m_selectedItem("")
{
    setupUi();
}

/** \brief Create new QBrowseButton for directories
 *
 * Initializes a QBrowseButton widget that can be used to browse for a
 * directory.
 *
 * \param dir Directory where the browser shall start
 * \param parent Parent QWidget that owns the newly created QBrowseButton
 */
QBrowseButton::QBrowseButton(QDir dir, QWidget *parent) :
    QFrame(parent), m_mode(QFileDialog::DirectoryOnly), m_caption(tr("Browse for directory")),
    m_selectedItem(dir.absolutePath())
{
    setupUi();
    setSelectedItem(m_selectedItem);
}

/** \brief Initialize sub-widgets
 *
 * Initializes the sub-widgets that belong to the QBrowseButton instance.
 *
 * \internal This helper method is called from the class constructors to reduce code
 * redundancy for initializing all the child widgets of our button.
 */
void QBrowseButton::setupUi() {
    QHBoxLayout* hbox = nullptr;
    try {
        hbox = new QHBoxLayout(this);
    }

    catch (std::bad_alloc& ex) {
        qCritical() << "Caught exception when trying to allocate new QVBoxLayout in" << Q_FUNC_INFO << ":" << ex.what();
        throw;
    }

    try {
        ui_leSelectedItem = new QLineEdit(m_selectedItem, this);
        ui_leSelectedItem->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Minimum);
        hbox->addWidget(ui_leSelectedItem);
    }

    catch (std::bad_alloc& ex) {
        qCritical() << "Caught exception when trying to allocate new QLineEdit in" << Q_FUNC_INFO << ":" << ex.what();
        throw;
    }

    try {
        ui_btnBrowse = new QPushButton(tr("..."), this);

        if (m_mode == QFileDialog::AnyFile)
            ui_btnBrowse->setIcon(QIcon::fromTheme("folder-open"));
        else
            ui_btnBrowse->setIcon(QIcon::fromTheme("folder-open"));

        ui_btnBrowse->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);

        connect(ui_btnBrowse, SIGNAL(clicked()), this, SLOT(btnBrowse_clicked()));

        hbox->addWidget(ui_btnBrowse);
    }

    catch (std::bad_alloc& ex) {
        qCritical() << "Caught exception when trying to allocate new QPushButton in" << Q_FUNC_INFO << ":" << ex.what();
        throw;
    }

    QFrame::setFrameStyle(QFrame::StyledPanel | QFrame::Raised);
    QFrame::setLineWidth(1);
    QFrame::setLayout(hbox);
}

/** \brief Set open mode
 *
 * This can be used to specify wether the dialog that gets opened when the user clicks the 'browse'
 * button shall be a file or directory selection dialog by using either \a QFileDialog::AnyFile or
 * \a QFileDialog::DirectoryOnly as value for the \a mode parameter.
 *
 * \note Other values for \a mode are ignored and generate a \a qWarning message!
 *
 * \param mode New selection mode for this button
 */
void QBrowseButton::setMode(QFileDialog::FileMode mode) {
    if (!(mode == QFileDialog::AnyFile || QFileDialog::DirectoryOnly)) {
        qWarning() << "Unsupported open mode" << mode << "in" << Q_FUNC_INFO;
        return;
    }

    m_mode = mode;
}

/** \brief Set selection dialog caption
 *
 * Sets the caption for the selection dialog that is shown when the user clicks the 'browse' button.
 *
 * \param title New selection dialog caption
 */
void QBrowseButton::setCaption(QString title) {
    m_caption = title;
}

/** \brief Set selected item
 *
 * Sets the 'selected item' box of this button to a new value.
 *
 * \param path New path that shall be shown in the 'selected item' box
 */
void QBrowseButton::setSelectedItem(QString path) {
    m_selectedItem = path;
    ui_leSelectedItem->setText(path);
}

/** \brief Set icon for 'browse' button
 *
 * Sets the icon for the 'browse' button to a new QIcon.
 *
 * \param icon New icon for 'browse' button
 */
void QBrowseButton::setIcon(QIcon icon) {
    ui_btnBrowse->setIcon(icon);
}

/** \brief Set 'browse' button caption
 *
 * Sets the caption of the 'browse' button to a new value.
 *
 * \param text New caption for 'browse' button
 */
void QBrowseButton::setButtonText(QString text) {
    ui_btnBrowse->setText(text);
}

/** \brief Slot for \a clicked signal of 'browse' button
 *
 * \internal This slot is connected to the \a clicked() signal of \a ui_btnBrowse and shows
 * a file or directory selection dialog depending on the settings that have been
 * specified for this \a QBrowseButton instance.
 */
void QBrowseButton::btnBrowse_clicked() {
    QString selection;
    switch (m_mode) {
    default:
    case QFileDialog::AnyFile:
        selection = QFileDialog::getOpenFileName(this, m_caption, m_selectedItem, "*");
        break;

    case QFileDialog::DirectoryOnly:
        selection = QFileDialog::getExistingDirectory(this, m_caption, m_selectedItem);
        break;
    }

    if (selection.isNull())
        return;

    m_selectedItem = selection;

    emit newSelection(selection);
}
<commit_msg>fix typo in Doxygen comments.<commit_after>/** \file
 *
 * \brief Implementation of \a QBrowseButton
 *
 * This file provides the implementation of the \a QBrowseButton class.
 *
 * \author Peter 'png' Hille <peter@das-system-networks.de>
 *
 * \version 1.0
 */
#include <QHBoxLayout>
#include <QDebug>

#include "nullptr.h"
#include "QBrowseButton.h"

/** \brief Create new QBrowseButton instance
 *
 * Initializes a new QBrowseButton widget that can be used to browse for a
 * file.
 *
 * \param parent Parent QWidget that owns the newly created QBrowseButton
 */
QBrowseButton::QBrowseButton(QWidget *parent) :
    QFrame(parent), m_mode(QFileDialog::AnyFile), m_caption(tr("Browse for file")),
    m_selectedItem("")
{
    setupUi();
}

/** \brief Create new QBrowseButton for directories
 *
 * Initializes a QBrowseButton widget that can be used to browse for a
 * directory.
 *
 * \param dir Directory where the browser shall start
 * \param parent Parent QWidget that owns the newly created QBrowseButton
 */
QBrowseButton::QBrowseButton(QDir dir, QWidget *parent) :
    QFrame(parent), m_mode(QFileDialog::DirectoryOnly), m_caption(tr("Browse for directory")),
    m_selectedItem(dir.absolutePath())
{
    setupUi();
    setSelectedItem(m_selectedItem);
}

/** \brief Initialize sub-widgets
 *
 * Initializes the sub-widgets that belong to the QBrowseButton instance.
 *
 * \internal This helper method is called from the class constructors to reduce code
 * redundancy for initializing all the child widgets of our button.
 */
void QBrowseButton::setupUi() {
    QHBoxLayout* hbox = nullptr;
    try {
        hbox = new QHBoxLayout(this);
    }

    catch (std::bad_alloc& ex) {
        qCritical() << "Caught exception when trying to allocate new QVBoxLayout in" << Q_FUNC_INFO << ":" << ex.what();
        throw;
    }

    try {
        ui_leSelectedItem = new QLineEdit(m_selectedItem, this);
        ui_leSelectedItem->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Minimum);
        hbox->addWidget(ui_leSelectedItem);
    }

    catch (std::bad_alloc& ex) {
        qCritical() << "Caught exception when trying to allocate new QLineEdit in" << Q_FUNC_INFO << ":" << ex.what();
        throw;
    }

    try {
        ui_btnBrowse = new QPushButton(tr("..."), this);

        if (m_mode == QFileDialog::AnyFile)
            ui_btnBrowse->setIcon(QIcon::fromTheme("folder-open"));
        else
            ui_btnBrowse->setIcon(QIcon::fromTheme("folder-open"));

        ui_btnBrowse->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);

        connect(ui_btnBrowse, SIGNAL(clicked()), this, SLOT(btnBrowse_clicked()));

        hbox->addWidget(ui_btnBrowse);
    }

    catch (std::bad_alloc& ex) {
        qCritical() << "Caught exception when trying to allocate new QPushButton in" << Q_FUNC_INFO << ":" << ex.what();
        throw;
    }

    QFrame::setFrameStyle(QFrame::StyledPanel | QFrame::Raised);
    QFrame::setLineWidth(1);
    QFrame::setLayout(hbox);
}

/** \brief Set open mode
 *
 * This can be used to specify wether the dialog that gets opened when the user clicks the 'browse'
 * button shall be a file or directory selection dialog by using either \a QFileDialog::AnyFile or
 * \a QFileDialog::DirectoryOnly as value for the \a mode parameter.
 *
 * \note Other values for \a mode are ignored and generate a \a qWarning message!
 *
 * \param mode New selection mode for this button
 */
void QBrowseButton::setMode(QFileDialog::FileMode mode) {
    if (!(mode == QFileDialog::AnyFile || QFileDialog::DirectoryOnly)) {
        qWarning() << "Unsupported open mode" << mode << "in" << Q_FUNC_INFO;
        return;
    }

    m_mode = mode;
}

/** \brief Set selection dialog caption
 *
 * Sets the caption for the selection dialog that is shown when the user clicks the 'browse' button.
 *
 * \param title New selection dialog caption
 */
void QBrowseButton::setCaption(QString title) {
    m_caption = title;
}

/** \brief Set selected item
 *
 * Sets the 'selected item' box of this button to a new value.
 *
 * \param path New path that shall be shown in the 'selected item' box
 */
void QBrowseButton::setSelectedItem(QString path) {
    m_selectedItem = path;
    ui_leSelectedItem->setText(path);
}

/** \brief Set icon for 'browse' button
 *
 * Sets the icon for the 'browse' button to a new QIcon.
 *
 * \param icon New icon for 'browse' button
 */
void QBrowseButton::setIcon(QIcon icon) {
    ui_btnBrowse->setIcon(icon);
}

/** \brief Set 'browse' button caption
 *
 * Sets the caption of the 'browse' button to a new value.
 *
 * \param text New caption for 'browse' button
 */
void QBrowseButton::setButtonText(QString text) {
    ui_btnBrowse->setText(text);
}

/** \brief Slot for \a clicked signal of 'browse' button
 *
 * \internal This slot is connected to the \a clicked() signal of \a ui_btnBrowse and shows
 * a file or directory selection dialog depending on the settings that have been
 * specified for this \a QBrowseButton instance.
 */
void QBrowseButton::btnBrowse_clicked() {
    QString selection;
    switch (m_mode) {
    default:
    case QFileDialog::AnyFile:
        selection = QFileDialog::getOpenFileName(this, m_caption, m_selectedItem, "*");
        break;

    case QFileDialog::DirectoryOnly:
        selection = QFileDialog::getExistingDirectory(this, m_caption, m_selectedItem);
        break;
    }

    if (selection.isNull())
        return;

    m_selectedItem = selection;

    emit newSelection(selection);
}
<|endoftext|>


<commit_before>#include <windows.h>
#include <iostream>

struct DebugBuffer
{
	DWORD   processId;
	char    debugText[4096-sizeof(DWORD)];
};

class IDebugEventHandler
{
public:
	virtual void OnDebugEvent (const DebugBuffer* debugBuffer) = 0;
};

class DebugMonitor
{
public:
	DebugMonitor (IDebugEventHandler* eventHandler) :
		eventHandler (eventHandler),
		mutexHandle (NULL),
		bufferReadyEventHandle (NULL),
		dataReadyEventHandle (NULL),
		fileMappingHandle (NULL),
		mapViewOfFileHandle (NULL),
		threadHandle (NULL),
		running (false)
	{
	}

	~DebugMonitor ()
	{
	}

	bool Start ()
	{
		mutexHandle = OpenMutex (SYNCHRONIZE, FALSE, L"DBWinMutex");
		if (mutexHandle == NULL) {
			int error = GetLastError ();
			return false;
		}

		bufferReadyEventHandle = OpenEvent (SYNCHRONIZE, FALSE, L"DBWIN_BUFFER_READY");
		if (bufferReadyEventHandle == NULL) {
			bufferReadyEventHandle = CreateEvent (NULL, FALSE, TRUE, L"DBWIN_BUFFER_READY");
			if (bufferReadyEventHandle == NULL) {
				return false;
			}
		}

		dataReadyEventHandle = OpenEvent (SYNCHRONIZE, FALSE, L"DBWIN_DATA_READY");
		if (dataReadyEventHandle == NULL) {
			dataReadyEventHandle = CreateEvent (NULL, FALSE, FALSE, L"DBWIN_DATA_READY");
			if (dataReadyEventHandle == NULL) {
				return false;
			}
		}

		fileMappingHandle = OpenFileMapping (FILE_MAP_READ, FALSE, L"DBWIN_BUFFER");
		if (fileMappingHandle == NULL) {
			fileMappingHandle = CreateFileMapping (INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, sizeof (DebugBuffer), L"DBWIN_BUFFER");
			if (fileMappingHandle == NULL) {
				return false;
			}
		}

		mapViewOfFileHandle = MapViewOfFile (fileMappingHandle, SECTION_MAP_READ, 0, 0, 0);
		if (mapViewOfFileHandle == NULL) {
			return false;
		}

		threadHandle = CreateThread (NULL, 0, DebugMonitorThread, this, 0, NULL);
		if (threadHandle == NULL) {
			return false;
		}

		running = true;
		return true;
	}

	void Stop ()
	{
		running = false;

		if (threadHandle != NULL) {
			WaitForSingleObject (threadHandle, INFINITE);
		}

		if (mutexHandle != NULL) {
			CloseHandle (mutexHandle);
			mutexHandle = NULL;
		}

		if (fileMappingHandle != NULL) {
			UnmapViewOfFile (fileMappingHandle);
			CloseHandle (fileMappingHandle);
			fileMappingHandle = NULL;
		}

		if (bufferReadyEventHandle != NULL) {
			CloseHandle (bufferReadyEventHandle);
			bufferReadyEventHandle = NULL;
		}

		if (dataReadyEventHandle != NULL) {
			CloseHandle (dataReadyEventHandle);
			dataReadyEventHandle = NULL;
		}
	}

private:
	static DWORD WINAPI DebugMonitorThread (void *userData)
	{
		DebugMonitor* debugMonitor = (DebugMonitor*) userData;
		if (debugMonitor != NULL) {
			debugMonitor->ProcessEvents ();
		}
		return 0;
	}

	DWORD ProcessEvents ()
	{
		while (running) {
			DWORD result = WaitForSingleObject (dataReadyEventHandle, 100);
			if (result == WAIT_OBJECT_0) {
				DebugBuffer* debugBuffer = (DebugBuffer*) mapViewOfFileHandle;
				if (eventHandler != NULL) {
					eventHandler->OnDebugEvent (debugBuffer);
				}
				SetEvent (bufferReadyEventHandle);
			}
		}
		return 0;
	}

	IDebugEventHandler* eventHandler;

	HANDLE mutexHandle;
	HANDLE bufferReadyEventHandle;
	HANDLE dataReadyEventHandle;
	HANDLE fileMappingHandle;
	HANDLE mapViewOfFileHandle;
	HANDLE threadHandle;

	bool running;
};

class DebugFileWriter : public IDebugEventHandler
{
public:
	DebugFileWriter (const std::wstring& logFileName, DWORD processIdentifier)
	{
		fileHandle = CreateFile (logFileName.c_str (), GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
		processId = processIdentifier;
	}

	~DebugFileWriter ()
	{
		CloseHandle (fileHandle);
	}

	virtual void OnDebugEvent (const DebugBuffer* debugBuffer) override
	{
		if (processId == debugBuffer->processId) {
			DWORD bytesWritten = 0;
			WriteFile (fileHandle, debugBuffer->debugText, (DWORD) strlen (debugBuffer->debugText), &bytesWritten, NULL);
		}
	}

private:
	HANDLE	fileHandle;
	DWORD	processId;
};

int wmain (int argc, wchar_t* argv[])
{
	if (argc < 3) {
		std::cout << "Usage: DebugMonitor.exe [DebugLogFileName] [ApplicationName] <ApplicationArguments>" << std::endl;
		return 1;
	}

	std::wstring debugLogfileName = argv[1];
	std::wstring commandArguments = argv[2];
	for (int i = 3; i < argc; i++) {
		commandArguments += L" \"";
		commandArguments += argv[i];
		commandArguments += L"\"";
	}

	wchar_t commandArgumentsString[4096];
	wcscpy_s (commandArgumentsString, 4096, commandArguments.c_str ());

	STARTUPINFO startupInfo;
	ZeroMemory (&startupInfo, sizeof (STARTUPINFO));

	PROCESS_INFORMATION processInfo;
	ZeroMemory (&processInfo, sizeof (PROCESS_INFORMATION));

	BOOL processCreated = CreateProcess (NULL, commandArgumentsString, NULL, NULL, TRUE, 0, NULL, NULL, &startupInfo, &processInfo);
	if (!processCreated) {
		std::cout << "Error: Failed to start application" << std::endl;
		return 1;
	}

	if (processCreated) {
		DebugFileWriter debugFileWriter (debugLogfileName, processInfo.dwProcessId);
		DebugMonitor debugMonitor (&debugFileWriter);

		debugMonitor.Start ();
		WaitForSingleObject (processInfo.hProcess, INFINITE);
		debugMonitor.Stop ();

		CloseHandle (processInfo.hProcess);
		CloseHandle (processInfo.hThread);
	}

	DWORD exitCode = 0;
	GetExitCodeProcess (processInfo.hProcess, &exitCode);
	return exitCode;
}
<commit_msg>Correct help string.<commit_after>#include <windows.h>
#include <iostream>

struct DebugBuffer
{
	DWORD   processId;
	char    debugText[4096-sizeof(DWORD)];
};

class IDebugEventHandler
{
public:
	virtual void OnDebugEvent (const DebugBuffer* debugBuffer) = 0;
};

class DebugMonitor
{
public:
	DebugMonitor (IDebugEventHandler* eventHandler) :
		eventHandler (eventHandler),
		mutexHandle (NULL),
		bufferReadyEventHandle (NULL),
		dataReadyEventHandle (NULL),
		fileMappingHandle (NULL),
		mapViewOfFileHandle (NULL),
		threadHandle (NULL),
		running (false)
	{
	}

	~DebugMonitor ()
	{
	}

	bool Start ()
	{
		mutexHandle = OpenMutex (SYNCHRONIZE, FALSE, L"DBWinMutex");
		if (mutexHandle == NULL) {
			int error = GetLastError ();
			return false;
		}

		bufferReadyEventHandle = OpenEvent (SYNCHRONIZE, FALSE, L"DBWIN_BUFFER_READY");
		if (bufferReadyEventHandle == NULL) {
			bufferReadyEventHandle = CreateEvent (NULL, FALSE, TRUE, L"DBWIN_BUFFER_READY");
			if (bufferReadyEventHandle == NULL) {
				return false;
			}
		}

		dataReadyEventHandle = OpenEvent (SYNCHRONIZE, FALSE, L"DBWIN_DATA_READY");
		if (dataReadyEventHandle == NULL) {
			dataReadyEventHandle = CreateEvent (NULL, FALSE, FALSE, L"DBWIN_DATA_READY");
			if (dataReadyEventHandle == NULL) {
				return false;
			}
		}

		fileMappingHandle = OpenFileMapping (FILE_MAP_READ, FALSE, L"DBWIN_BUFFER");
		if (fileMappingHandle == NULL) {
			fileMappingHandle = CreateFileMapping (INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, sizeof (DebugBuffer), L"DBWIN_BUFFER");
			if (fileMappingHandle == NULL) {
				return false;
			}
		}

		mapViewOfFileHandle = MapViewOfFile (fileMappingHandle, SECTION_MAP_READ, 0, 0, 0);
		if (mapViewOfFileHandle == NULL) {
			return false;
		}

		threadHandle = CreateThread (NULL, 0, DebugMonitorThread, this, 0, NULL);
		if (threadHandle == NULL) {
			return false;
		}

		running = true;
		return true;
	}

	void Stop ()
	{
		running = false;

		if (threadHandle != NULL) {
			WaitForSingleObject (threadHandle, INFINITE);
		}

		if (mutexHandle != NULL) {
			CloseHandle (mutexHandle);
			mutexHandle = NULL;
		}

		if (fileMappingHandle != NULL) {
			UnmapViewOfFile (fileMappingHandle);
			CloseHandle (fileMappingHandle);
			fileMappingHandle = NULL;
		}

		if (bufferReadyEventHandle != NULL) {
			CloseHandle (bufferReadyEventHandle);
			bufferReadyEventHandle = NULL;
		}

		if (dataReadyEventHandle != NULL) {
			CloseHandle (dataReadyEventHandle);
			dataReadyEventHandle = NULL;
		}
	}

private:
	static DWORD WINAPI DebugMonitorThread (void *userData)
	{
		DebugMonitor* debugMonitor = (DebugMonitor*) userData;
		if (debugMonitor != NULL) {
			debugMonitor->ProcessEvents ();
		}
		return 0;
	}

	DWORD ProcessEvents ()
	{
		while (running) {
			DWORD result = WaitForSingleObject (dataReadyEventHandle, 100);
			if (result == WAIT_OBJECT_0) {
				DebugBuffer* debugBuffer = (DebugBuffer*) mapViewOfFileHandle;
				if (eventHandler != NULL) {
					eventHandler->OnDebugEvent (debugBuffer);
				}
				SetEvent (bufferReadyEventHandle);
			}
		}
		return 0;
	}

	IDebugEventHandler* eventHandler;

	HANDLE mutexHandle;
	HANDLE bufferReadyEventHandle;
	HANDLE dataReadyEventHandle;
	HANDLE fileMappingHandle;
	HANDLE mapViewOfFileHandle;
	HANDLE threadHandle;

	bool running;
};

class DebugFileWriter : public IDebugEventHandler
{
public:
	DebugFileWriter (const std::wstring& logFileName, DWORD processIdentifier)
	{
		fileHandle = CreateFile (logFileName.c_str (), GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
		processId = processIdentifier;
	}

	~DebugFileWriter ()
	{
		CloseHandle (fileHandle);
	}

	virtual void OnDebugEvent (const DebugBuffer* debugBuffer) override
	{
		if (processId == debugBuffer->processId) {
			DWORD bytesWritten = 0;
			WriteFile (fileHandle, debugBuffer->debugText, (DWORD) strlen (debugBuffer->debugText), &bytesWritten, NULL);
		}
	}

private:
	HANDLE	fileHandle;
	DWORD	processId;
};

int wmain (int argc, wchar_t* argv[])
{
	if (argc < 3) {
		std::cout << "Usage: DebugToFile.exe [DebugLogFileName] [ApplicationName] <ApplicationArguments>" << std::endl;
		return 1;
	}

	std::wstring debugLogfileName = argv[1];
	std::wstring commandArguments = argv[2];
	for (int i = 3; i < argc; i++) {
		commandArguments += L" \"";
		commandArguments += argv[i];
		commandArguments += L"\"";
	}

	wchar_t commandArgumentsString[4096];
	wcscpy_s (commandArgumentsString, 4096, commandArguments.c_str ());

	STARTUPINFO startupInfo;
	ZeroMemory (&startupInfo, sizeof (STARTUPINFO));

	PROCESS_INFORMATION processInfo;
	ZeroMemory (&processInfo, sizeof (PROCESS_INFORMATION));

	BOOL processCreated = CreateProcess (NULL, commandArgumentsString, NULL, NULL, TRUE, 0, NULL, NULL, &startupInfo, &processInfo);
	if (!processCreated) {
		std::cout << "Error: Failed to start application" << std::endl;
		return 1;
	}

	if (processCreated) {
		DebugFileWriter debugFileWriter (debugLogfileName, processInfo.dwProcessId);
		DebugMonitor debugMonitor (&debugFileWriter);

		debugMonitor.Start ();
		WaitForSingleObject (processInfo.hProcess, INFINITE);
		debugMonitor.Stop ();

		CloseHandle (processInfo.hProcess);
		CloseHandle (processInfo.hThread);
	}

	DWORD exitCode = 0;
	GetExitCodeProcess (processInfo.hProcess, &exitCode);
	return exitCode;
}
<|endoftext|>


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

#include "statespace/SE2.hpp"
#include <assert.h>
#include <cmath>
#include <iostream>

namespace libcozmo {
namespace statespace {

SE2::~SE2() {
    for (int i = 0; i < m_state_map.size(); ++i) {
        delete(m_state_map[i]);
    }
    m_state_map.clear();
}

int SE2::get_or_create_state(const StateSpace::State& _state) {
    const State state = static_cast<const State&>(_state);
    const auto state_id = m_state_to_id_map.find(state);
    if (state_id != m_state_to_id_map.end()) {
        return state_id->second;
    }

    StateSpace::State* new_state = create_state();
    copy_state(state, new_state);
    m_state_to_id_map[state] = m_state_map.size() - 1;
    return m_state_map.size() - 1;
}

int SE2::get_or_create_state(
    const aikido::statespace::StateSpace::State& _state) {
    State discrete_state;
    continuous_state_to_discrete(_state, &discrete_state);
    return get_or_create_state(discrete_state);
}

void SE2::discrete_state_to_continuous(
    const StateSpace::State& _state,
    aikido::statespace::StateSpace::State* _continuous_state) const {
    const State state = static_cast<const State&>(_state);
    Eigen::Vector3d state_log;
    state_log.head<2>() =
        discrete_position_to_continuous(Eigen::Vector2i(state.x, state.y));
    state_log[2] =
        discrete_angle_to_continuous(state.theta);
    double angle = state_log(2);
    Eigen::Vector2d translation = state_log.head<2>();
    Eigen::Isometry2d transform(Eigen::Isometry2d::Identity());
    transform.linear() = Eigen::Rotation2Dd(angle).matrix();
    transform.translation() = translation;
    aikido::statespace::SE2::State* se2_continuous_state =
        static_cast<aikido::statespace::SE2::State*>(_continuous_state);
    se2_continuous_state->setIsometry(transform);
    _continuous_state = se2_continuous_state;
}

void SE2::continuous_state_to_discrete(
    const aikido::statespace::StateSpace::State& _state,
    StateSpace::State* _discrete_state) const {
    Eigen::Vector3d log_state;
    auto se2_state = static_cast<const aikido::statespace::SE2::State&>(_state);
    Eigen::Isometry2d transform = se2_state.getIsometry();
    log_state.head<2>() = transform.translation();
    Eigen::Rotation2Dd rotation = Eigen::Rotation2Dd::Identity();
    rotation.fromRotationMatrix(transform.rotation());
    log_state[2] = rotation.angle();
    const Eigen::Vector2i position =
        continuous_position_to_discrete(log_state.head<2>());
    const int theta = continuous_angle_to_discrete(log_state[2]);
    State* discrete_state = static_cast<State*>(_discrete_state);
    *discrete_state = State(position.x(), position.y(), theta);
}

bool SE2::get_state_id(const StateSpace::State& _state, int* _state_id) const {
    const State state = static_cast<const State&>(_state);
    const auto state_id_iter = m_state_to_id_map.find(state);
    if (state_id_iter != m_state_to_id_map.end()) {
        *_state_id = state_id_iter->second;
        return true;
    }
    return false;
}

StateSpace::State* SE2::get_state(const int& _state_id) const {
    if (_state_id >= size()) {
        return nullptr;
    }

    return m_state_map[_state_id];
}

bool SE2::is_valid_state(const StateSpace::State& _state) const {
    const State& state = static_cast<const State&>(_state);
    if (!(state.theta >= 0 && state.theta < m_num_theta_vals)) {
        return false;
    }
    return true;
}

int SE2::size() const {
    return m_state_map.size();
}

double SE2::get_distance(
    const StateSpace::State& _state_1,
    const StateSpace::State& _state_2) const {
    aikido::statespace::SE2::State continuous_state_1;
    discrete_state_to_continuous(_state_1, &continuous_state_1);
    aikido::statespace::SE2::State continuous_state_2;
    discrete_state_to_continuous(_state_2, &continuous_state_2);
    return m_distance_metric.distance(&continuous_state_1, &continuous_state_2);
}

double SE2::get_distance(
    const aikido::statespace::StateSpace::State& _state_1,
    const aikido::statespace::StateSpace::State& _state_2) const {
    return m_distance_metric.distance(&_state_1, &_state_2);
}

void SE2::copy_state(
    const StateSpace::State& _source, StateSpace::State* _destination) const {
    const State& source = static_cast<const State&>(_source);
    State* destination = static_cast<State*>(_destination);
    *destination = State(source.x, source.y, source.theta);
}

double SE2::get_resolution() const { return m_resolution; }

StateSpace::State* SE2::create_state() {
    m_state_map.push_back(new State());
    const auto state = m_state_map.back();
    return m_state_map.back();
}

double SE2::normalize_angle_rad(const double& theta_rad) const {
    double normalized_theta_rad = theta_rad;
    if (abs(theta_rad) > 2.0 * M_PI) {
        normalized_theta_rad = normalized_theta_rad -
            static_cast<int>(normalized_theta_rad / (2.0 * M_PI)) * 2.0 * M_PI;
    }
    if (theta_rad < 0) {
        normalized_theta_rad += 2.0 * M_PI;
    }
    return normalized_theta_rad;
}

double SE2::discrete_angle_to_continuous(const int& theta) const {
    return normalize_angle_rad(theta * (2 * M_PI /m_num_theta_vals));
}

int SE2::continuous_angle_to_discrete(const double& theta_rad) const {
    const double bin_size = 2.0 * M_PI / static_cast<double>(m_num_theta_vals);
    const int theta =
        normalize_angle_rad(theta_rad + bin_size / 2.0) / (2.0 * M_PI)
            * static_cast<double>(m_num_theta_vals);
    return static_cast<int>(theta);
}

Eigen::Vector2d SE2::discrete_position_to_continuous(
    const Eigen::Vector2i& position) const {
    const double x_mm = position.x() * m_resolution + (m_resolution / 2.0);
    const double y_mm = position.y() * m_resolution + (m_resolution / 2.0);
    return Eigen::Vector2d(x_mm, y_mm);
}

Eigen::Vector2i SE2::continuous_position_to_discrete(
    const Eigen::Vector2d& position) const {

    const int x = static_cast<int>(floor(position.x() / m_resolution));
    const int y = static_cast<int>(floor(position.y() / m_resolution));
    return Eigen::Vector2i(x, y);
}

}  // namespace statespace
}  // namespace libcozmo

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

#include "statespace/SE2.hpp"
#include <assert.h>
#include <cmath>
#include <iostream>

namespace libcozmo {
namespace statespace {

SE2::~SE2() {
    for (int i = 0; i < m_state_map.size(); ++i) {
        delete(m_state_map[i]);
    }
    m_state_map.clear();
}

int SE2::get_or_create_state(const StateSpace::State& _state) {
    const State state = static_cast<const State&>(_state);
    const auto state_id = m_state_to_id_map.find(state);
    if (state_id != m_state_to_id_map.end()) {
        return state_id->second;
    }

    StateSpace::State* new_state = create_state();
    copy_state(state, new_state);
    m_state_to_id_map[state] = m_state_map.size() - 1;
    return m_state_map.size() - 1;
}

int SE2::get_or_create_state(
    const aikido::statespace::StateSpace::State& _state) {
    State discrete_state;
    continuous_state_to_discrete(_state, &discrete_state);
    return get_or_create_state(discrete_state);
}

void SE2::discrete_state_to_continuous(
    const StateSpace::State& _state,
    aikido::statespace::StateSpace::State* _continuous_state) const {
    const State state = static_cast<const State&>(_state);
    Eigen::Vector3d state_log;
    state_log.head<2>() =
        discrete_position_to_continuous(Eigen::Vector2i(state.x, state.y));
    state_log[2] =
        discrete_angle_to_continuous(state.theta);
    double angle = state_log(2);
    Eigen::Vector2d translation = state_log.head<2>();
    Eigen::Isometry2d transform(Eigen::Isometry2d::Identity());
    transform.linear() = Eigen::Rotation2Dd(angle).matrix();
    transform.translation() = translation;
    aikido::statespace::SE2::State* se2_continuous_state =
        static_cast<aikido::statespace::SE2::State*>(_continuous_state);
    se2_continuous_state->setIsometry(transform);
    _continuous_state = se2_continuous_state;
}

void SE2::continuous_state_to_discrete(
    const aikido::statespace::StateSpace::State& _state,
    StateSpace::State* _discrete_state) const {
    Eigen::Vector3d log_state;
    auto se2_state = static_cast<const aikido::statespace::SE2::State&>(_state);
    Eigen::Isometry2d transform = se2_state.getIsometry();
    log_state.head<2>() = transform.translation();
    Eigen::Rotation2Dd rotation = Eigen::Rotation2Dd::Identity();
    rotation.fromRotationMatrix(transform.rotation());
    log_state[2] = rotation.angle();
    const Eigen::Vector2i position =
        continuous_position_to_discrete(log_state.head<2>());
    const int theta = continuous_angle_to_discrete(log_state[2]);
    State* discrete_state = static_cast<State*>(_discrete_state);
    *discrete_state = State(position.x(), position.y(), theta);
}

bool SE2::get_state_id(const StateSpace::State& _state, int* _state_id) const {
    const State state = static_cast<const State&>(_state);
    const auto state_id_iter = m_state_to_id_map.find(state);
    if (state_id_iter != m_state_to_id_map.end()) {
        *_state_id = state_id_iter->second;
        return true;
    }
    return false;
}

StateSpace::State* SE2::get_state(const int& _state_id) const {
    if (_state_id >= size()) {
        return nullptr;
    }

    return m_state_map[_state_id];
}

bool SE2::is_valid_state(const StateSpace::State& _state) const {
    const State& state = static_cast<const State&>(_state);
    if (!(state.theta >= 0 && state.theta < m_num_theta_vals)) {
        return false;
    }
    return true;
}

int SE2::size() const {
    return m_state_map.size();
}

double SE2::get_distance(
    const StateSpace::State& _state_1,
    const StateSpace::State& _state_2) const {
    aikido::statespace::SE2::State continuous_state_1;
    discrete_state_to_continuous(_state_1, &continuous_state_1);
    aikido::statespace::SE2::State continuous_state_2;
    discrete_state_to_continuous(_state_2, &continuous_state_2);
    return m_distance_metric.distance(&continuous_state_1, &continuous_state_2);
}

double SE2::get_distance(
    const aikido::statespace::StateSpace::State& _state_1,
    const aikido::statespace::StateSpace::State& _state_2) const {
    return m_distance_metric.distance(&_state_1, &_state_2);
}

void SE2::copy_state(
    const StateSpace::State& _source, StateSpace::State* _destination) const {
    const State& source = static_cast<const State&>(_source);
    State* destination = static_cast<State*>(_destination);
    *destination = State(source.x, source.y, source.theta);
}

double SE2::get_resolution() const { return m_resolution; }

StateSpace::State* SE2::create_state() {
    m_state_map.push_back(new State());
    const auto state = m_state_map.back();
    return m_state_map.back();
}

double SE2::normalize_angle_rad(const double& theta_rad) const {
    assert(m_bins % 2 == 0);
    double normalized_theta_rad = theta_rad;
    if (abs(theta_rad) > 2.0 * M_PI) {
        normalized_theta_rad = normalized_theta_rad -
            static_cast<int>(normalized_theta_rad / (2.0 * M_PI)) * 2.0 * M_PI;
    }
    if (theta_rad < 0) {
        normalized_theta_rad += 2.0 * M_PI;
    }
    return normalized_theta_rad;
}

double SE2::discrete_angle_to_continuous(const int& theta) const {
    return normalize_angle_rad(theta * (2 * M_PI /m_num_theta_vals));
}

int SE2::continuous_angle_to_discrete(const double& theta_rad) const {
    const double bin_size = 2.0 * M_PI / static_cast<double>(m_num_theta_vals);
    const int theta =
        normalize_angle_rad(theta_rad + bin_size / 2.0) / (2.0 * M_PI)
            * static_cast<double>(m_num_theta_vals);
    return static_cast<int>(theta);
}

Eigen::Vector2d SE2::discrete_position_to_continuous(
    const Eigen::Vector2i& position) const {
    const double x_mm = position.x() * m_resolution + (m_resolution / 2.0);
    const double y_mm = position.y() * m_resolution + (m_resolution / 2.0);
    return Eigen::Vector2d(x_mm, y_mm);
}

Eigen::Vector2i SE2::continuous_position_to_discrete(
    const Eigen::Vector2d& position) const {

    const int x = static_cast<int>(floor(position.x() / m_resolution));
    const int y = static_cast<int>(floor(position.y() / m_resolution));
    return Eigen::Vector2i(x, y);
}

}  // namespace statespace
}  // namespace libcozmo

<|endoftext|>


<commit_before>// @(#)alimdc:$Name$:$Id$
// Author: Fons Rademakers  26/11/99

/**************************************************************************
 * Copyright(c) 1998-2003, ALICE Experiment at CERN, All rights reserved. *
 *                                                                        *
 * Author: The ALICE Off-line Project.                                    *
 * Contributors are mentioned in the code where appropriate.              *
 *                                                                        *
 * Permission to use, copy, modify and distribute this software and its   *
 * documentation strictly for non-commercial purposes is hereby granted   *
 * without fee, provided that the above copyright notice appears in all   *
 * copies and that both the copyright notice and this permission notice   *
 * appear in the supporting documentation. The authors make no claims     *
 * about the suitability of this software for any purpose. It is          *
 * provided "as is" without express or implied warranty.                  *
 **************************************************************************/

//////////////////////////////////////////////////////////////////////////
//                                                                      //
// AliRawDB                                                             //
//                                                                      //
//////////////////////////////////////////////////////////////////////////

#include <errno.h>
#include <Riostream.h>

#include <TSystem.h>
#include <TKey.h>

#include "AliESD.h"
#include "AliRawEvent.h"
#include "AliRawEventHeaderBase.h"
#include "AliStats.h"

#include "AliRawDB.h"

ClassImp(AliRawDB)

const char *AliRawDB::fgkAliRootTag = "$Name$";

//______________________________________________________________________________
AliRawDB::AliRawDB(AliRawEvent *event,
		   AliESD *esd,
		   Int_t compress,
                   const char* fileName) :
  fRawDB(NULL),
  fTree(NULL),
  fEvent(event),
  fESDTree(NULL),
  fESD(esd),
  fCompress(compress),
  fMaxSize(-1),
  fFS1(""),
  fFS2(""),
  fDeleteFiles(kFALSE),
  fStop(kFALSE)
{
   // Create a new raw DB

   if (fileName) {
      if (!Create(fileName))
         MakeZombie();
   }
}

//______________________________________________________________________________
Bool_t AliRawDB::FSHasSpace(const char *fs) const
{
   // Check for at least fMaxSize bytes of free space on the file system.
   // If the space is not available return kFALSE, kTRUE otherwise.

   Long_t id, bsize, blocks, bfree;

   if (gSystem->GetFsInfo(fs, &id, &bsize, &blocks, &bfree) == 1) {
      Error("FSHasSpace", "could not stat file system %s", fs);
      return kFALSE;
   }

   // Leave 5 percent of diskspace free
   Double_t avail = Double_t(bfree) * 0.95;
   if (avail*bsize > fMaxSize)
      return kTRUE;

   Warning("FSHasSpace", "no space on file system %s", fs);
   return kFALSE;
}

//______________________________________________________________________________
const char *AliRawDB::GetFileName() const
{
   // Return filename based on hostname and date and time. This will make
   // each file unique. Also makes sure (via FSHasSpace()) that there is
   // enough space on the file system to store the file. Returns 0 in
   // case of error or interrupt signal.

   static TString fname;
   static Bool_t  fstoggle = kFALSE;

   TString fs = fstoggle ? fFS2 : fFS1;
   TDatime dt;

   TString hostname = gSystem->HostName();
   Int_t pos;
   if ((pos = hostname.Index(".")) != kNPOS)
      hostname.Remove(pos);

   if (!FSHasSpace(fs)) {
      while (1) {
         fstoggle = !fstoggle;
         fs = fstoggle ? fFS2 : fFS1;
         if (FSHasSpace(fs)) break;
         Info("GetFileName", "sleeping 30 seconds before retrying...");
         gSystem->Sleep(30000);   // sleep for 30 seconds
         if (fStop) return 0;
      }
   }

   fname = fs + "/" + hostname + "_";
   fname += dt.GetDate();
   fname += "_";
   fname += dt.GetTime();
   fname += ".root";

   fstoggle = !fstoggle;

   return fname;
}

//______________________________________________________________________________
void AliRawDB::SetFS(const char* fs1, const char* fs2)
{
// set the file system location

  fFS1 = fs1;
  if (fs1 && !fFS1.Contains(":")) {
    gSystem->ResetErrno();
    gSystem->MakeDirectory(fs1);
    if (gSystem->GetErrno() && gSystem->GetErrno() != EEXIST) {
      SysError("SetFS", "mkdir %s", fs1);
    }
  }

  fFS2 = fs2;
  if (fs2) {
    gSystem->ResetErrno();
    gSystem->MakeDirectory(fs2);
    if (gSystem->GetErrno() && gSystem->GetErrno() != EEXIST) {
      SysError("SetFS", "mkdir %s", fs2);
    }
  }
}

//______________________________________________________________________________
Bool_t AliRawDB::Create(const char* fileName)
{
   // Create a new raw DB.

   const Int_t kMaxRetry = 1;
   const Int_t kMaxSleep = 1;      // seconds
   const Int_t kMaxSleepLong = 10; // seconds
   Int_t retry = 0;

again:
   if (fStop) return kFALSE;

   const char *fname = fileName;
   if (!fname) fname = GetFileName();
   if (!fname) {
      Error("Create", "error getting raw DB file name");
      return kFALSE;
   }

   retry++;

   fRawDB = TFile::Open(fname, GetOpenOption(),
			Form("ALICE raw-data file (%s)", GetAliRootTag()), fCompress,
			GetNetopt());
   if (!fRawDB) {
      if (retry < kMaxRetry) {
         Warning("Create", "failure to open file, sleeping %d %s before retrying...",
                 kMaxSleep, kMaxSleep==1 ? "second" : "seconds");
         gSystem->Sleep(kMaxSleep*1000);
         goto again;
      }
      Error("Create", "failure to open file %s after %d tries", fname, kMaxRetry);
      return kFALSE;
   }
   if (retry > 1)
      Warning("Create", "succeeded to open file after %d retries", retry);

   if (fRawDB->IsZombie()) {
      if (fRawDB->GetErrno() == ENOSPC ||
          fRawDB->GetErrno() == 1018   ||   // SECOMERR
          fRawDB->GetErrno() == 1027) {     // SESYSERR
         fRawDB->ResetErrno();
         delete fRawDB;
         Warning("Create", "file is a zombie (no space), sleeping %d %s before retrying...",
                 kMaxSleepLong, kMaxSleepLong==1 ? "second" : "seconds");
         gSystem->Sleep(kMaxSleepLong*1000);   // sleep 10 seconds before retrying
         goto again;
      }
      Error("Create", "file %s is zombie", fname);
      fRawDB->ResetErrno();
      delete fRawDB;
      fRawDB = 0;
      if (retry < kMaxRetry) {
         Warning("Create", "file is a zombie, sleeping %d %s before retrying...",
                 kMaxSleep, kMaxSleep==1 ? "second" : "seconds");
         gSystem->Sleep(kMaxSleep*1000);
         goto again;
      }
      Error("Create", "failure to open file %s after %d tries", fname, kMaxRetry);
      return kFALSE;
   }

   // Create raw data TTree
   MakeTree();

   return kTRUE;
}

//______________________________________________________________________________
void AliRawDB::MakeTree()
{
   // Create ROOT Tree object container.

   fTree = new TTree("RAW", Form("ALICE raw-data tree (%s)", GetAliRootTag()));
   fTree->SetAutoSave(2000000000);  // autosave when 2 Gbyte written

   Int_t bufsize = 256000;
   // splitting 29.6 MB/s, no splitting 35.3 MB/s on P4 2GHz 15k SCSI
   //Int_t split   = 1;
   Int_t split   = 0;
   fTree->Branch("rawevent", "AliRawEvent", &fEvent, bufsize, split);

   // Create tree which will contain the HLT ESD information

   if (fESD) {
     fESDTree = new TTree("esdTree", Form("ALICE HLT ESD tree (%s)", GetAliRootTag()));
     fESDTree->SetAutoSave(2000000000);  // autosave when 2 Gbyte written
     split   = 0;
     fESDTree->Branch("ESD", "AliESD", &fESD, bufsize, split);
   }

}

//______________________________________________________________________________
Int_t AliRawDB::Close()
{
   // Close raw DB.
   if (!fRawDB) return 0;

   if (!fRawDB->IsOpen()) return 0;

   fRawDB->cd();

   // Write the tree.
   Bool_t error = kFALSE;
   if (fTree->Write() == 0)
     error = kTRUE;
   if (fESDTree)
     if (fESDTree->Write() == 0)
       error = kTRUE;

   // Close DB, this also deletes the fTree
   fRawDB->Close();

   Int_t filesize = fRawDB->GetEND();

   if (fDeleteFiles) {
      gSystem->Unlink(fRawDB->GetName());
      delete fRawDB;
      fRawDB = 0;
      if(!error)
	return filesize;
      else
	return -1;
   }

   // Write a text file with file GUID
   TString guidFileName = fRawDB->GetName();
   guidFileName += ".guid";
   ofstream fguid(guidFileName.Data());
   TString guid = fRawDB->GetUUID().AsString();
   fguid << fRawDB->GetName() << " \t" << guid.Data();
   fguid.close();

   delete fRawDB;
   fRawDB = 0;
   if(!error)
     return filesize;
   else
     return -1;
}

//______________________________________________________________________________
Int_t AliRawDB::Fill()
{
   // Fill the trees and return the number of written bytes

   Double_t bytes = fRawDB->GetBytesWritten();
   Bool_t error = kFALSE;
   if (fTree->Fill() == -1)
     error = kTRUE;
   if (fESDTree)
     if (fESDTree->Fill() == -1)
       error = kTRUE;
   if(!error)
     return Int_t(fRawDB->GetBytesWritten() - bytes);
   else
     return -1;
}

//______________________________________________________________________________
Int_t AliRawDB::GetTotalSize()
{
   // Return the total size of the trees
  Int_t total = 0;

  {
    Int_t skey = 0;
    TDirectory *dir = fTree->GetDirectory();
    if (dir) {
      TKey *key = dir->GetKey(fTree->GetName());
      if (key) skey = key->GetKeylen();
    }
    total += skey;
    if (fTree->GetZipBytes() > 0) total += fTree->GetTotBytes();
    TBuffer b(TBuffer::kWrite,10000);
    TTree::Class()->WriteBuffer(b,fTree);
    total += b.Length();
  }

  if(fESDTree)
    {
      Int_t skey = 0;
      TDirectory *dir = fESDTree->GetDirectory();
      if (dir) {
	TKey *key = dir->GetKey(fESDTree->GetName());
	if (key) skey = key->GetKeylen();
      }
      total += skey;
      if (fESDTree->GetZipBytes() > 0) total += fESDTree->GetTotBytes();
      TBuffer b(TBuffer::kWrite,10000);
      TTree::Class()->WriteBuffer(b,fESDTree);
      total += b.Length();
    }

  return total;
}

//______________________________________________________________________________
void AliRawDB::WriteStats(AliStats* stats)
{
   // Write stats to raw DB, local run DB and global MySQL DB.

   AliRawEventHeaderBase &header = *GetEvent()->GetHeader();

   // Write stats into RawDB
   TDirectory *ds = gDirectory;
   GetDB()->cd();
   stats->SetEvents(GetEvents());
   stats->SetLastId(header.GetP("Id")[0]);
   stats->SetFileSize(GetBytesWritten());
   stats->SetCompressionFactor(GetCompressionFactor());
   stats->SetEndTime();
   stats->Write("stats");
   ds->cd();
}

//______________________________________________________________________________
Bool_t AliRawDB::NextFile(const char* fileName)
{
   // Close te current file and open a new one.
   // Returns kFALSE in case opening failed.

   Close();

   if (!Create(fileName)) return kFALSE;
   return kTRUE;
}

//______________________________________________________________________________
Float_t AliRawDB::GetCompressionFactor() const
{
   // Return compression factor.

   if (fTree->GetZipBytes() == 0.)
      return 1.0;
   else
      return fTree->GetTotBytes()/fTree->GetZipBytes();
}

//______________________________________________________________________________
const char *AliRawDB::GetAliRootTag()
{
  // Return the aliroot tag (version)
  // used to generate the raw data file.
  // Stored in the raw-data file title.

  TString version = fgkAliRootTag;
  version.Remove(TString::kBoth,'$');
  version.ReplaceAll("Name","AliRoot version");

  return version.Data();
}
<commit_msg>Fixing the correct syntax for AliEn spooler<commit_after>// @(#)alimdc:$Name$:$Id$
// Author: Fons Rademakers  26/11/99

/**************************************************************************
 * Copyright(c) 1998-2003, ALICE Experiment at CERN, All rights reserved. *
 *                                                                        *
 * Author: The ALICE Off-line Project.                                    *
 * Contributors are mentioned in the code where appropriate.              *
 *                                                                        *
 * Permission to use, copy, modify and distribute this software and its   *
 * documentation strictly for non-commercial purposes is hereby granted   *
 * without fee, provided that the above copyright notice appears in all   *
 * copies and that both the copyright notice and this permission notice   *
 * appear in the supporting documentation. The authors make no claims     *
 * about the suitability of this software for any purpose. It is          *
 * provided "as is" without express or implied warranty.                  *
 **************************************************************************/

//////////////////////////////////////////////////////////////////////////
//                                                                      //
// AliRawDB                                                             //
//                                                                      //
//////////////////////////////////////////////////////////////////////////

#include <errno.h>
#include <Riostream.h>

#include <TSystem.h>
#include <TKey.h>

#include "AliESD.h"
#include "AliRawEvent.h"
#include "AliRawEventHeaderBase.h"
#include "AliStats.h"

#include "AliRawDB.h"

ClassImp(AliRawDB)

const char *AliRawDB::fgkAliRootTag = "$Name$";

//______________________________________________________________________________
AliRawDB::AliRawDB(AliRawEvent *event,
		   AliESD *esd,
		   Int_t compress,
                   const char* fileName) :
  fRawDB(NULL),
  fTree(NULL),
  fEvent(event),
  fESDTree(NULL),
  fESD(esd),
  fCompress(compress),
  fMaxSize(-1),
  fFS1(""),
  fFS2(""),
  fDeleteFiles(kFALSE),
  fStop(kFALSE)
{
   // Create a new raw DB

   if (fileName) {
      if (!Create(fileName))
         MakeZombie();
   }
}

//______________________________________________________________________________
Bool_t AliRawDB::FSHasSpace(const char *fs) const
{
   // Check for at least fMaxSize bytes of free space on the file system.
   // If the space is not available return kFALSE, kTRUE otherwise.

   Long_t id, bsize, blocks, bfree;

   if (gSystem->GetFsInfo(fs, &id, &bsize, &blocks, &bfree) == 1) {
      Error("FSHasSpace", "could not stat file system %s", fs);
      return kFALSE;
   }

   // Leave 5 percent of diskspace free
   Double_t avail = Double_t(bfree) * 0.95;
   if (avail*bsize > fMaxSize)
      return kTRUE;

   Warning("FSHasSpace", "no space on file system %s", fs);
   return kFALSE;
}

//______________________________________________________________________________
const char *AliRawDB::GetFileName() const
{
   // Return filename based on hostname and date and time. This will make
   // each file unique. Also makes sure (via FSHasSpace()) that there is
   // enough space on the file system to store the file. Returns 0 in
   // case of error or interrupt signal.

   static TString fname;
   static Bool_t  fstoggle = kFALSE;

   TString fs = fstoggle ? fFS2 : fFS1;
   TDatime dt;

   TString hostname = gSystem->HostName();
   Int_t pos;
   if ((pos = hostname.Index(".")) != kNPOS)
      hostname.Remove(pos);

   if (!FSHasSpace(fs)) {
      while (1) {
         fstoggle = !fstoggle;
         fs = fstoggle ? fFS2 : fFS1;
         if (FSHasSpace(fs)) break;
         Info("GetFileName", "sleeping 30 seconds before retrying...");
         gSystem->Sleep(30000);   // sleep for 30 seconds
         if (fStop) return 0;
      }
   }

   fname = fs + "/" + hostname + "_";
   fname += dt.GetDate();
   fname += "_";
   fname += dt.GetTime();
   fname += ".root";

   fstoggle = !fstoggle;

   return fname;
}

//______________________________________________________________________________
void AliRawDB::SetFS(const char* fs1, const char* fs2)
{
// set the file system location

  fFS1 = fs1;
  if (fs1 && !fFS1.Contains(":")) {
    gSystem->ResetErrno();
    gSystem->MakeDirectory(fs1);
    if (gSystem->GetErrno() && gSystem->GetErrno() != EEXIST) {
      SysError("SetFS", "mkdir %s", fs1);
    }
  }

  fFS2 = fs2;
  if (fs2) {
    gSystem->ResetErrno();
    gSystem->MakeDirectory(fs2);
    if (gSystem->GetErrno() && gSystem->GetErrno() != EEXIST) {
      SysError("SetFS", "mkdir %s", fs2);
    }
  }
}

//______________________________________________________________________________
Bool_t AliRawDB::Create(const char* fileName)
{
   // Create a new raw DB.

   const Int_t kMaxRetry = 1;
   const Int_t kMaxSleep = 1;      // seconds
   const Int_t kMaxSleepLong = 10; // seconds
   Int_t retry = 0;

again:
   if (fStop) return kFALSE;

   const char *fname = fileName;
   if (!fname) fname = GetFileName();
   if (!fname) {
      Error("Create", "error getting raw DB file name");
      return kFALSE;
   }

   retry++;

   fRawDB = TFile::Open(fname, GetOpenOption(),
			Form("ALICE raw-data file (%s)", GetAliRootTag()), fCompress,
			GetNetopt());
   if (!fRawDB) {
      if (retry < kMaxRetry) {
         Warning("Create", "failure to open file, sleeping %d %s before retrying...",
                 kMaxSleep, kMaxSleep==1 ? "second" : "seconds");
         gSystem->Sleep(kMaxSleep*1000);
         goto again;
      }
      Error("Create", "failure to open file %s after %d tries", fname, kMaxRetry);
      return kFALSE;
   }
   if (retry > 1)
      Warning("Create", "succeeded to open file after %d retries", retry);

   if (fRawDB->IsZombie()) {
      if (fRawDB->GetErrno() == ENOSPC ||
          fRawDB->GetErrno() == 1018   ||   // SECOMERR
          fRawDB->GetErrno() == 1027) {     // SESYSERR
         fRawDB->ResetErrno();
         delete fRawDB;
         Warning("Create", "file is a zombie (no space), sleeping %d %s before retrying...",
                 kMaxSleepLong, kMaxSleepLong==1 ? "second" : "seconds");
         gSystem->Sleep(kMaxSleepLong*1000);   // sleep 10 seconds before retrying
         goto again;
      }
      Error("Create", "file %s is zombie", fname);
      fRawDB->ResetErrno();
      delete fRawDB;
      fRawDB = 0;
      if (retry < kMaxRetry) {
         Warning("Create", "file is a zombie, sleeping %d %s before retrying...",
                 kMaxSleep, kMaxSleep==1 ? "second" : "seconds");
         gSystem->Sleep(kMaxSleep*1000);
         goto again;
      }
      Error("Create", "failure to open file %s after %d tries", fname, kMaxRetry);
      return kFALSE;
   }

   // Create raw data TTree
   MakeTree();

   return kTRUE;
}

//______________________________________________________________________________
void AliRawDB::MakeTree()
{
   // Create ROOT Tree object container.

   fTree = new TTree("RAW", Form("ALICE raw-data tree (%s)", GetAliRootTag()));
   fTree->SetAutoSave(2000000000);  // autosave when 2 Gbyte written

   Int_t bufsize = 256000;
   // splitting 29.6 MB/s, no splitting 35.3 MB/s on P4 2GHz 15k SCSI
   //Int_t split   = 1;
   Int_t split   = 0;
   fTree->Branch("rawevent", "AliRawEvent", &fEvent, bufsize, split);

   // Create tree which will contain the HLT ESD information

   if (fESD) {
     fESDTree = new TTree("esdTree", Form("ALICE HLT ESD tree (%s)", GetAliRootTag()));
     fESDTree->SetAutoSave(2000000000);  // autosave when 2 Gbyte written
     split   = 0;
     fESDTree->Branch("ESD", "AliESD", &fESD, bufsize, split);
   }

}

//______________________________________________________________________________
Int_t AliRawDB::Close()
{
   // Close raw DB.
   if (!fRawDB) return 0;

   if (!fRawDB->IsOpen()) return 0;

   fRawDB->cd();

   // Write the tree.
   Bool_t error = kFALSE;
   if (fTree->Write() == 0)
     error = kTRUE;
   if (fESDTree)
     if (fESDTree->Write() == 0)
       error = kTRUE;

   // Close DB, this also deletes the fTree
   fRawDB->Close();

   Int_t filesize = fRawDB->GetEND();

   if (fDeleteFiles) {
      gSystem->Unlink(fRawDB->GetName());
      delete fRawDB;
      fRawDB = 0;
      if(!error)
	return filesize;
      else
	return -1;
   }

   // Write a text file with file GUID
   TString guidFileName = fRawDB->GetName();
   guidFileName += ".guid";
   ofstream fguid(guidFileName.Data());
   TString guid = fRawDB->GetUUID().AsString();
   fguid << "guid: \t" << guid.Data();
   fguid.close();

   delete fRawDB;
   fRawDB = 0;
   if(!error)
     return filesize;
   else
     return -1;
}

//______________________________________________________________________________
Int_t AliRawDB::Fill()
{
   // Fill the trees and return the number of written bytes

   Double_t bytes = fRawDB->GetBytesWritten();
   Bool_t error = kFALSE;
   if (fTree->Fill() == -1)
     error = kTRUE;
   if (fESDTree)
     if (fESDTree->Fill() == -1)
       error = kTRUE;
   if(!error)
     return Int_t(fRawDB->GetBytesWritten() - bytes);
   else
     return -1;
}

//______________________________________________________________________________
Int_t AliRawDB::GetTotalSize()
{
   // Return the total size of the trees
  Int_t total = 0;

  {
    Int_t skey = 0;
    TDirectory *dir = fTree->GetDirectory();
    if (dir) {
      TKey *key = dir->GetKey(fTree->GetName());
      if (key) skey = key->GetKeylen();
    }
    total += skey;
    if (fTree->GetZipBytes() > 0) total += fTree->GetTotBytes();
    TBuffer b(TBuffer::kWrite,10000);
    TTree::Class()->WriteBuffer(b,fTree);
    total += b.Length();
  }

  if(fESDTree)
    {
      Int_t skey = 0;
      TDirectory *dir = fESDTree->GetDirectory();
      if (dir) {
	TKey *key = dir->GetKey(fESDTree->GetName());
	if (key) skey = key->GetKeylen();
      }
      total += skey;
      if (fESDTree->GetZipBytes() > 0) total += fESDTree->GetTotBytes();
      TBuffer b(TBuffer::kWrite,10000);
      TTree::Class()->WriteBuffer(b,fESDTree);
      total += b.Length();
    }

  return total;
}

//______________________________________________________________________________
void AliRawDB::WriteStats(AliStats* stats)
{
   // Write stats to raw DB, local run DB and global MySQL DB.

   AliRawEventHeaderBase &header = *GetEvent()->GetHeader();

   // Write stats into RawDB
   TDirectory *ds = gDirectory;
   GetDB()->cd();
   stats->SetEvents(GetEvents());
   stats->SetLastId(header.GetP("Id")[0]);
   stats->SetFileSize(GetBytesWritten());
   stats->SetCompressionFactor(GetCompressionFactor());
   stats->SetEndTime();
   stats->Write("stats");
   ds->cd();
}

//______________________________________________________________________________
Bool_t AliRawDB::NextFile(const char* fileName)
{
   // Close te current file and open a new one.
   // Returns kFALSE in case opening failed.

   Close();

   if (!Create(fileName)) return kFALSE;
   return kTRUE;
}

//______________________________________________________________________________
Float_t AliRawDB::GetCompressionFactor() const
{
   // Return compression factor.

   if (fTree->GetZipBytes() == 0.)
      return 1.0;
   else
      return fTree->GetTotBytes()/fTree->GetZipBytes();
}

//______________________________________________________________________________
const char *AliRawDB::GetAliRootTag()
{
  // Return the aliroot tag (version)
  // used to generate the raw data file.
  // Stored in the raw-data file title.

  TString version = fgkAliRootTag;
  version.Remove(TString::kBoth,'$');
  version.ReplaceAll("Name","AliRoot version");

  return version.Data();
}
<|endoftext|>


<commit_before><commit_msg>Refactorings<commit_after><|endoftext|>


<commit_before>// This file is part of the "x0" project
//   (c) 2009-2015 Christian Parpart <https://github.com/christianparpart>
//
// x0 is free software: you can redistribute it and/or modify it under
// the terms of the GNU Affero General Public License v3.0.
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.

#include "Config.h"
#include "XzeroDaemon.h"
#include "XzeroContext.h"

#include "modules/access.h"
#include "modules/accesslog.h"
#include "modules/auth.h"
#include "modules/compress.h"
#include "modules/core.h"
#include "modules/dirlisting.h"
#include "modules/empty_gif.h"
#include "modules/userdir.h"
#include "modules/webdav.h"
#include "modules/proxy/ProxyModule.h"

#include <xzero/http/HttpRequest.h>
#include <xzero/http/HttpResponse.h>
#include <xzero/http/HttpOutput.h>
#include <xzero/http/HttpFileHandler.h>
#include <xzero/http/http1/ConnectionFactory.h>
#include <xzero/io/LocalFileRepository.h>
#include <xzero/executor/NativeScheduler.h>
#include <xzero/net/SslConnector.h>
#include <xzero/net/InetConnector.h>
#include <xzero/net/Server.h>
#include <xzero/cli/CLI.h>
#include <xzero/cli/Flags.h>
#include <xzero/RuntimeError.h>
#include <xzero/MimeTypes.h>
#include <xzero/Application.h>
#include <xzero/StringUtil.h>
#include <xzero/logging.h>
#include <xzero-flow/FlowParser.h>
#include <xzero-flow/IRGenerator.h>
#include <xzero-flow/TargetCodeGenerator.h>
#include <xzero-flow/ir/IRProgram.h>
#include <xzero-flow/ir/PassManager.h>
#include <xzero-flow/transform/UnusedBlockPass.h>
#include <xzero-flow/transform/EmptyBlockElimination.h>
#include <xzero-flow/transform/InstructionElimination.h>
#include <xzero-flow/FlowCallVisitor.h>
#include <iostream>
#include <sstream>
#include <fstream>

using namespace xzero;
using namespace xzero::http;

// XXX variable defined by mimetypes2cc compiler
extern std::unordered_map<std::string, std::string> mimetypes2cc;

namespace x0d {

XzeroDaemon::XzeroDaemon()
    : generation_(1),
      startupTime_(),
      terminate_(false),
      mimetypes_(),
      vfs_(mimetypes_, "/", true, true, false),
      lastWorker_(0),
      schedulers_(),
      modules_(),
      server_(new Server()),
      unit_(nullptr),
      programIR_(nullptr),
      program_(nullptr),
      main_(nullptr),
      setupApi_(),
      mainApi_(),
      optimizationLevel_(1),
      http1_(),
      config_(new Config) {

  // defaulting worker/affinities to total host CPU count
  config_->workers = CoreModule::cpuCount();
  config_->workerAffinities.resize(config_->workers);
  for (int i = 0; i < config_->workers; ++i)
    config_->workerAffinities[i] = i;

  loadModule<CoreModule>();
  loadModule<AccessModule>();
  loadModule<AccesslogModule>();
  loadModule<AuthModule>();
  loadModule<CompressModule>();
  loadModule<DirlistingModule>();
  loadModule<EmptyGifModule>();
  loadModule<UserdirModule>();
  loadModule<WebdavModule>();
  loadModule<ProxyModule>();
}

XzeroDaemon::~XzeroDaemon() {
  terminate();
  threadedExecutor_.joinAll();
}

bool XzeroDaemon::import(
    const std::string& name,
    const std::string& path,
    std::vector<flow::vm::NativeCallback*>* builtins) {

  if (path.empty())
    logDebug("x0d", "Loading plugin \"$0\"", name);
  else
    logDebug("x0d", "Loading plugin \"$0\" from \"$1\"", name, path);

  // TODO actually load the plugin

  return true;
}

// for instant-mode
void XzeroDaemon::loadConfigEasy(const std::string& docroot, int port) {
  std::string flow =
      "handler setup {\n"
      "  listen port: #{port};\n"
      "}\n"
      "\n"
      "handler main {\n"
      "  docroot '#{docroot}';\n"
      "  staticfile;\n"
      "}\n";

  StringUtil::replaceAll(&flow, "#{port}", std::to_string(port));
  StringUtil::replaceAll(&flow, "#{docroot}", docroot);

  loadConfigStream(
      std::unique_ptr<std::istream>(new std::istringstream(flow)),
      "instant-mode.conf");
}

void XzeroDaemon::loadConfigFile(const std::string& configFileName) {
  std::unique_ptr<std::istream> input(new std::ifstream(configFileName));
  loadConfigStream(std::move(input), configFileName);
}

void XzeroDaemon::loadConfigStream(std::unique_ptr<std::istream>&& is,
                                   const std::string& filename) {
  flow::FlowParser parser(
      this,
      std::bind(&XzeroDaemon::import, this, std::placeholders::_1,
                                            std::placeholders::_2,
                                            std::placeholders::_3),
      [](const std::string& msg) {
        logError("x0d", "Configuration file error. $0", msg);
      });

  parser.openStream(std::move(is), filename);
  unit_ = parser.parse();

  flow::IRGenerator irgen;
  irgen.setExports({"setup", "main"});
  irgen.setErrorCallback([&](const std::string& msg) {
    logError("x0d", "$0", msg);
  });

  programIR_ = irgen.generate(unit_.get());

  {
    flow::PassManager pm;

    // mandatory passes
    pm.registerPass(std::make_unique<flow::UnusedBlockPass>());

    // optional passes
    if (optimizationLevel_ >= 1) {
      pm.registerPass(std::make_unique<flow::EmptyBlockElimination>());
      pm.registerPass(std::make_unique<flow::InstructionElimination>());
    }

    pm.run(programIR_.get());
  }

  verify(programIR_.get());

  program_ = flow::TargetCodeGenerator().generate(programIR_.get());
  program_->link(this);

  validateConfig();

  if (!program_->findHandler("setup")) {
    RAISE(RuntimeError, "No setup handler found.");
  }

  main_ = program_->findHandler("main");
}

bool XzeroDaemon::configure() {
  try {
    // free up some resources (not needed anymore)
    programIR_.reset();

    // run setup handler
    program_->findHandler("setup")->run();

    postConfig();

    return true;
  } catch (const RuntimeError& e) {
    if (e == Status::ConfigurationError) {
      logError("x0d", "Configuration failed. $0", e.what());
      return false;
    }

    throw;
  }
}

void XzeroDaemon::postConfig() {
  if (config_->listeners.empty()) {
    RAISE(ConfigurationError, "No listeners configured.");
  }

  // HTTP/1 connection factory
  http1_.reset(new http1::ConnectionFactory(
      config_->maxRequestUriLength,
      config_->maxRequestBodySize,
      config_->maxKeepAliveRequests,
      config_->maxKeepAlive,
      config_->tcpCork,
      config_->tcpNoDelay));

  http1_->setHandler(std::bind(&XzeroDaemon::handleRequest, this,
        std::placeholders::_1, std::placeholders::_2));

  // mimetypes
  mimetypes_.setDefaultMimeType(config_->mimetypesDefault);

  if (!config_->mimetypesPath.empty()) {
    mimetypes_.loadFromLocal(config_->mimetypesPath);
  }

  if (mimetypes_.empty()) {
    logDebug("x0d", "No mimetypes given. Defaulting to builtin database.");
    mimetypes_.load(mimetypes2cc);
  }

  // schedulers & threading
  schedulers_.emplace_back(newScheduler());

  for (int i = 1; i < config_->workers; ++i) {
    schedulers_.emplace_back(newScheduler());
    threadedExecutor_.execute(std::bind(&XzeroDaemon::runOneThread, this, i));
  }

  // listeners
  for (const ListenerConfig& l: config_->listeners) {
    if (l.ssl) {
      if (config_->sslContexts.empty()) {
        RAISE(ConfigurationError, "SSL listeners found but no SSL contexts configured.");
      }
      setupConnector<SslConnector>(
          l.bindAddress, l.port, l.backlog,
          l.multiAcceptCount, l.reuseAddr, l.reusePort,
          [this](SslConnector* connector) {
            for (const SslContext& cx: config_->sslContexts) {
              // TODO: include trustfile & priorities
              connector->addContext(cx.certfile, cx.keyfile);
            }
          }
      );
    } else {
      setupConnector<InetConnector>(
          l.bindAddress, l.port, l.backlog,
          l.multiAcceptCount, l.reuseAddr, l.reusePort,
          nullptr);
    }
  }
}

std::unique_ptr<Scheduler> XzeroDaemon::newScheduler() {
  return std::unique_ptr<Scheduler>(new NativeScheduler(
        std::unique_ptr<xzero::ExceptionHandler>(
              new CatchAndLogExceptionHandler("x0d")),
        nullptr /* preInvoke */,
        nullptr /* postInvoke */));
}

void XzeroDaemon::handleRequest(HttpRequest* request, HttpResponse* response) {
  XzeroContext* cx = new XzeroContext(main_, request, response);
  cx->run();
}

void XzeroDaemon::validateConfig() {
  validateContext("setup", setupApi_);
  validateContext("main", mainApi_);
}

void XzeroDaemon::validateContext(const std::string& entrypointHandlerName,
                                  const std::vector<std::string>& api) {
  auto entrypointFn = unit_->findHandler(entrypointHandlerName);
  if (!entrypointFn)
    RAISE(RuntimeError, "No handler with name %s found.",
                        entrypointHandlerName.c_str());

  flow::FlowCallVisitor callVisitor(entrypointFn);
  auto calls = callVisitor.calls();

  unsigned errorCount = 0;

  for (const auto& i: calls) {
    if (!i->callee()->isBuiltin()) {
      // skip script user-defined handlers
      continue;
    }

    if (std::find(api.begin(), api.end(), i->callee()->name()) == api.end()) {
      logError("x0d",
          "Illegal call to '$0' found within handler $1 (or its callees).",
          i->callee()->name(),
          entrypointHandlerName);
      logError("x0d", "$0", i->location().str());
      errorCount++;
    }
  }

  if (errorCount) {
    RAISE(RuntimeError, "Configuration validation failed.");
  }
}

void XzeroDaemon::run() {
  server_->start();
  runOneThread(0);
  logTrace("x0d", "Main loop quit. Shutting down.");
  server_->stop();
}

void XzeroDaemon::runOneThread(int index) {
  Scheduler* scheduler = schedulers_[index].get();

  if (index <= config_->workerAffinities.size())
    setThreadAffinity(config_->workerAffinities[index], index);

  while (!terminate_.load()) {
    scheduler->runLoop();
  }
}

void XzeroDaemon::setThreadAffinity(int cpu, int workerId) {
#ifdef HAVE_PTHREAD_SETAFFINITY_NP
  cpu_set_t set;

  CPU_ZERO(&set);
  CPU_SET(cpu, &set);

  logTrace("x0d", "setAffinity: cpu $0 on worker $1", cpu, workerId);

  pthread_t tid = pthread_self();

  int rv = pthread_setaffinity_np(tid, sizeof(set), &set);
  if (rv < 0) {
    logError("x0d",
             "setting scheduler affinity on CPU $0 failed for worker $1. $2",
             cpu, workerId, strerror(errno));
  }
#else
  logError("x0d",
           "setting scheduler affinity on CPU $0 failed for worker $1. $2",
           cpu, workerId, strerror(ENOTSUP));
#endif
}

void XzeroDaemon::terminate() {
  terminate_ = true;

  for (auto& scheduler: schedulers_) {
    scheduler->breakLoop();
  }
}

Scheduler* XzeroDaemon::selectClientScheduler() {
  // TODO: support least-load

  if (++lastWorker_ == schedulers_.size())
    lastWorker_ = 0;

  return schedulers_[lastWorker_].get();
}

template<typename T>
void XzeroDaemon::setupConnector(
    const xzero::IPAddress& bindAddress, int port, int backlog,
    int multiAcceptCount, bool reuseAddr, bool reusePort,
    std::function<void(T*)> connectorVisitor) {

  if (reusePort && !InetConnector::isReusePortSupported()) {
    logWarning("x0d", "You platform does not support SO_REUSEPORT. "
                      "Falling back to traditional connection scheduling.");
    reusePort = false;
  }

  if (reusePort) {
    for (auto& scheduler: schedulers_) {
      Scheduler* sched = scheduler.get();
      T* connector = doSetupConnector<T>(
          sched,
          [sched]() -> Scheduler* { return sched; },
          bindAddress, port, backlog,
          multiAcceptCount, reuseAddr, reusePort);
      if (connectorVisitor) {
        connectorVisitor(connector);
      }
    }
  } else {
    T* connector = doSetupConnector<T>(
        schedulers_[0].get(),
        std::bind(&XzeroDaemon::selectClientScheduler, this),
        bindAddress, port, backlog,
        multiAcceptCount, reuseAddr, reusePort);
    if (connectorVisitor) {
      connectorVisitor(connector);
    }
  }
}

template<typename T>
T* XzeroDaemon::doSetupConnector(
    xzero::Scheduler* listenerScheduler,
    xzero::InetConnector::SchedulerSelector clientSchedulerSelector,
    const xzero::IPAddress& ipaddr, int port,
    int backlog, int multiAccept, bool reuseAddr, bool reusePort) {

  auto inet = server_->addConnector<T>(
      "inet",
      listenerScheduler,
      listenerScheduler,
      clientSchedulerSelector,
      config_->maxReadIdle,
      config_->maxWriteIdle,
      config_->tcpFinTimeout,
      ipaddr,
      port,
      backlog,
      reuseAddr,
      reusePort
  );

  inet->setMultiAcceptCount(multiAccept);
  inet->addConnectionFactory(http1_);

  return inet;
}

} // namespace x0d
<commit_msg>alphabetical rearrangements<commit_after>// This file is part of the "x0" project
//   (c) 2009-2015 Christian Parpart <https://github.com/christianparpart>
//
// x0 is free software: you can redistribute it and/or modify it under
// the terms of the GNU Affero General Public License v3.0.
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.

#include "Config.h"
#include "XzeroDaemon.h"
#include "XzeroContext.h"

#include "modules/access.h"
#include "modules/accesslog.h"
#include "modules/auth.h"
#include "modules/compress.h"
#include "modules/core.h"
#include "modules/dirlisting.h"
#include "modules/empty_gif.h"
#include "modules/userdir.h"
#include "modules/webdav.h"
#include "modules/proxy/ProxyModule.h"

#include <xzero/http/HttpRequest.h>
#include <xzero/http/HttpResponse.h>
#include <xzero/http/HttpOutput.h>
#include <xzero/http/HttpFileHandler.h>
#include <xzero/http/http1/ConnectionFactory.h>
#include <xzero/io/LocalFileRepository.h>
#include <xzero/executor/NativeScheduler.h>
#include <xzero/net/SslConnector.h>
#include <xzero/net/InetConnector.h>
#include <xzero/net/Server.h>
#include <xzero/cli/CLI.h>
#include <xzero/cli/Flags.h>
#include <xzero/RuntimeError.h>
#include <xzero/MimeTypes.h>
#include <xzero/Application.h>
#include <xzero/StringUtil.h>
#include <xzero/logging.h>
#include <xzero-flow/FlowParser.h>
#include <xzero-flow/IRGenerator.h>
#include <xzero-flow/TargetCodeGenerator.h>
#include <xzero-flow/ir/IRProgram.h>
#include <xzero-flow/ir/PassManager.h>
#include <xzero-flow/transform/UnusedBlockPass.h>
#include <xzero-flow/transform/EmptyBlockElimination.h>
#include <xzero-flow/transform/InstructionElimination.h>
#include <xzero-flow/FlowCallVisitor.h>
#include <iostream>
#include <sstream>
#include <fstream>

using namespace xzero;
using namespace xzero::http;

// XXX variable defined by mimetypes2cc compiler
extern std::unordered_map<std::string, std::string> mimetypes2cc;

namespace x0d {

XzeroDaemon::XzeroDaemon()
    : generation_(1),
      startupTime_(),
      terminate_(false),
      mimetypes_(),
      vfs_(mimetypes_, "/", true, true, false),
      lastWorker_(0),
      schedulers_(),
      modules_(),
      server_(new Server()),
      unit_(nullptr),
      programIR_(nullptr),
      program_(nullptr),
      main_(nullptr),
      setupApi_(),
      mainApi_(),
      optimizationLevel_(1),
      http1_(),
      config_(new Config) {

  // defaulting worker/affinities to total host CPU count
  config_->workers = CoreModule::cpuCount();
  config_->workerAffinities.resize(config_->workers);
  for (int i = 0; i < config_->workers; ++i)
    config_->workerAffinities[i] = i;

  loadModule<AccessModule>();
  loadModule<AccesslogModule>();
  loadModule<AuthModule>();
  loadModule<CompressModule>();
  loadModule<CoreModule>();
  loadModule<DirlistingModule>();
  loadModule<EmptyGifModule>();
  loadModule<ProxyModule>();
  loadModule<UserdirModule>();
  loadModule<WebdavModule>();
}

XzeroDaemon::~XzeroDaemon() {
  terminate();
  threadedExecutor_.joinAll();
}

bool XzeroDaemon::import(
    const std::string& name,
    const std::string& path,
    std::vector<flow::vm::NativeCallback*>* builtins) {

  if (path.empty())
    logDebug("x0d", "Loading plugin \"$0\"", name);
  else
    logDebug("x0d", "Loading plugin \"$0\" from \"$1\"", name, path);

  // TODO actually load the plugin

  return true;
}

// for instant-mode
void XzeroDaemon::loadConfigEasy(const std::string& docroot, int port) {
  std::string flow =
      "handler setup {\n"
      "  listen port: #{port};\n"
      "}\n"
      "\n"
      "handler main {\n"
      "  docroot '#{docroot}';\n"
      "  staticfile;\n"
      "}\n";

  StringUtil::replaceAll(&flow, "#{port}", std::to_string(port));
  StringUtil::replaceAll(&flow, "#{docroot}", docroot);

  loadConfigStream(
      std::unique_ptr<std::istream>(new std::istringstream(flow)),
      "instant-mode.conf");
}

void XzeroDaemon::loadConfigFile(const std::string& configFileName) {
  std::unique_ptr<std::istream> input(new std::ifstream(configFileName));
  loadConfigStream(std::move(input), configFileName);
}

void XzeroDaemon::loadConfigStream(std::unique_ptr<std::istream>&& is,
                                   const std::string& filename) {
  flow::FlowParser parser(
      this,
      std::bind(&XzeroDaemon::import, this, std::placeholders::_1,
                                            std::placeholders::_2,
                                            std::placeholders::_3),
      [](const std::string& msg) {
        logError("x0d", "Configuration file error. $0", msg);
      });

  parser.openStream(std::move(is), filename);
  unit_ = parser.parse();

  flow::IRGenerator irgen;
  irgen.setExports({"setup", "main"});
  irgen.setErrorCallback([&](const std::string& msg) {
    logError("x0d", "$0", msg);
  });

  programIR_ = irgen.generate(unit_.get());

  {
    flow::PassManager pm;

    // mandatory passes
    pm.registerPass(std::make_unique<flow::UnusedBlockPass>());

    // optional passes
    if (optimizationLevel_ >= 1) {
      pm.registerPass(std::make_unique<flow::EmptyBlockElimination>());
      pm.registerPass(std::make_unique<flow::InstructionElimination>());
    }

    pm.run(programIR_.get());
  }

  verify(programIR_.get());

  program_ = flow::TargetCodeGenerator().generate(programIR_.get());
  program_->link(this);

  validateConfig();

  if (!program_->findHandler("setup")) {
    RAISE(RuntimeError, "No setup handler found.");
  }

  main_ = program_->findHandler("main");
}

bool XzeroDaemon::configure() {
  try {
    // free up some resources (not needed anymore)
    programIR_.reset();

    // run setup handler
    program_->findHandler("setup")->run();

    postConfig();

    return true;
  } catch (const RuntimeError& e) {
    if (e == Status::ConfigurationError) {
      logError("x0d", "Configuration failed. $0", e.what());
      return false;
    }

    throw;
  }
}

void XzeroDaemon::postConfig() {
  if (config_->listeners.empty()) {
    RAISE(ConfigurationError, "No listeners configured.");
  }

  // HTTP/1 connection factory
  http1_.reset(new http1::ConnectionFactory(
      config_->maxRequestUriLength,
      config_->maxRequestBodySize,
      config_->maxKeepAliveRequests,
      config_->maxKeepAlive,
      config_->tcpCork,
      config_->tcpNoDelay));

  http1_->setHandler(std::bind(&XzeroDaemon::handleRequest, this,
        std::placeholders::_1, std::placeholders::_2));

  // mimetypes
  mimetypes_.setDefaultMimeType(config_->mimetypesDefault);

  if (!config_->mimetypesPath.empty()) {
    mimetypes_.loadFromLocal(config_->mimetypesPath);
  }

  if (mimetypes_.empty()) {
    logDebug("x0d", "No mimetypes given. Defaulting to builtin database.");
    mimetypes_.load(mimetypes2cc);
  }

  // schedulers & threading
  schedulers_.emplace_back(newScheduler());

  for (int i = 1; i < config_->workers; ++i) {
    schedulers_.emplace_back(newScheduler());
    threadedExecutor_.execute(std::bind(&XzeroDaemon::runOneThread, this, i));
  }

  // listeners
  for (const ListenerConfig& l: config_->listeners) {
    if (l.ssl) {
      if (config_->sslContexts.empty()) {
        RAISE(ConfigurationError, "SSL listeners found but no SSL contexts configured.");
      }
      setupConnector<SslConnector>(
          l.bindAddress, l.port, l.backlog,
          l.multiAcceptCount, l.reuseAddr, l.reusePort,
          [this](SslConnector* connector) {
            for (const SslContext& cx: config_->sslContexts) {
              // TODO: include trustfile & priorities
              connector->addContext(cx.certfile, cx.keyfile);
            }
          }
      );
    } else {
      setupConnector<InetConnector>(
          l.bindAddress, l.port, l.backlog,
          l.multiAcceptCount, l.reuseAddr, l.reusePort,
          nullptr);
    }
  }
}

std::unique_ptr<Scheduler> XzeroDaemon::newScheduler() {
  return std::unique_ptr<Scheduler>(new NativeScheduler(
        std::unique_ptr<xzero::ExceptionHandler>(
              new CatchAndLogExceptionHandler("x0d")),
        nullptr /* preInvoke */,
        nullptr /* postInvoke */));
}

void XzeroDaemon::handleRequest(HttpRequest* request, HttpResponse* response) {
  XzeroContext* cx = new XzeroContext(main_, request, response);
  cx->run();
}

void XzeroDaemon::validateConfig() {
  validateContext("setup", setupApi_);
  validateContext("main", mainApi_);
}

void XzeroDaemon::validateContext(const std::string& entrypointHandlerName,
                                  const std::vector<std::string>& api) {
  auto entrypointFn = unit_->findHandler(entrypointHandlerName);
  if (!entrypointFn)
    RAISE(RuntimeError, "No handler with name %s found.",
                        entrypointHandlerName.c_str());

  flow::FlowCallVisitor callVisitor(entrypointFn);
  auto calls = callVisitor.calls();

  unsigned errorCount = 0;

  for (const auto& i: calls) {
    if (!i->callee()->isBuiltin()) {
      // skip script user-defined handlers
      continue;
    }

    if (std::find(api.begin(), api.end(), i->callee()->name()) == api.end()) {
      logError("x0d",
          "Illegal call to '$0' found within handler $1 (or its callees).",
          i->callee()->name(),
          entrypointHandlerName);
      logError("x0d", "$0", i->location().str());
      errorCount++;
    }
  }

  if (errorCount) {
    RAISE(RuntimeError, "Configuration validation failed.");
  }
}

void XzeroDaemon::run() {
  server_->start();
  runOneThread(0);
  logTrace("x0d", "Main loop quit. Shutting down.");
  server_->stop();
}

void XzeroDaemon::runOneThread(int index) {
  Scheduler* scheduler = schedulers_[index].get();

  if (index <= config_->workerAffinities.size())
    setThreadAffinity(config_->workerAffinities[index], index);

  while (!terminate_.load()) {
    scheduler->runLoop();
  }
}

void XzeroDaemon::setThreadAffinity(int cpu, int workerId) {
#ifdef HAVE_PTHREAD_SETAFFINITY_NP
  cpu_set_t set;

  CPU_ZERO(&set);
  CPU_SET(cpu, &set);

  logTrace("x0d", "setAffinity: cpu $0 on worker $1", cpu, workerId);

  pthread_t tid = pthread_self();

  int rv = pthread_setaffinity_np(tid, sizeof(set), &set);
  if (rv < 0) {
    logError("x0d",
             "setting scheduler affinity on CPU $0 failed for worker $1. $2",
             cpu, workerId, strerror(errno));
  }
#else
  logError("x0d",
           "setting scheduler affinity on CPU $0 failed for worker $1. $2",
           cpu, workerId, strerror(ENOTSUP));
#endif
}

void XzeroDaemon::terminate() {
  terminate_ = true;

  for (auto& scheduler: schedulers_) {
    scheduler->breakLoop();
  }
}

Scheduler* XzeroDaemon::selectClientScheduler() {
  // TODO: support least-load

  if (++lastWorker_ == schedulers_.size())
    lastWorker_ = 0;

  return schedulers_[lastWorker_].get();
}

template<typename T>
void XzeroDaemon::setupConnector(
    const xzero::IPAddress& bindAddress, int port, int backlog,
    int multiAcceptCount, bool reuseAddr, bool reusePort,
    std::function<void(T*)> connectorVisitor) {

  if (reusePort && !InetConnector::isReusePortSupported()) {
    logWarning("x0d", "You platform does not support SO_REUSEPORT. "
                      "Falling back to traditional connection scheduling.");
    reusePort = false;
  }

  if (reusePort) {
    for (auto& scheduler: schedulers_) {
      Scheduler* sched = scheduler.get();
      T* connector = doSetupConnector<T>(
          sched,
          [sched]() -> Scheduler* { return sched; },
          bindAddress, port, backlog,
          multiAcceptCount, reuseAddr, reusePort);
      if (connectorVisitor) {
        connectorVisitor(connector);
      }
    }
  } else {
    T* connector = doSetupConnector<T>(
        schedulers_[0].get(),
        std::bind(&XzeroDaemon::selectClientScheduler, this),
        bindAddress, port, backlog,
        multiAcceptCount, reuseAddr, reusePort);
    if (connectorVisitor) {
      connectorVisitor(connector);
    }
  }
}

template<typename T>
T* XzeroDaemon::doSetupConnector(
    xzero::Scheduler* listenerScheduler,
    xzero::InetConnector::SchedulerSelector clientSchedulerSelector,
    const xzero::IPAddress& ipaddr, int port,
    int backlog, int multiAccept, bool reuseAddr, bool reusePort) {

  auto inet = server_->addConnector<T>(
      "inet",
      listenerScheduler,
      listenerScheduler,
      clientSchedulerSelector,
      config_->maxReadIdle,
      config_->maxWriteIdle,
      config_->tcpFinTimeout,
      ipaddr,
      port,
      backlog,
      reuseAddr,
      reusePort
  );

  inet->setMultiAcceptCount(multiAccept);
  inet->addConnectionFactory(http1_);

  return inet;
}

} // namespace x0d
<|endoftext|>


<commit_before>#include "MainWindow.h"
#include "QuizzWidget.h"
#include "ToolsWidget.h"
#include "Database.h"
#include "administration/AdminQuizzWidget.h"
#include "ThemeSelectionWidget.h"

#include <QMenu>
#include <QMenuBar>
#include <QVBoxLayout>
#include <QPushButton>
#include <QDebug>
#include <QLabel>

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
{
    // Build menu
    QMenu *fileMenu(this->menuBar()->addMenu(tr("File")));
    fileMenu->addAction(QIcon(":/images/quit.png"), tr("Quit"), this, SLOT(close()));

    QMenu *adminMenu(this->menuBar()->addMenu(tr("Administration")));
    adminMenu->addAction(QIcon(":/images/admin_quizz.png"), tr("Quizz administration"), this, SLOT(launch_admin_quizz()));

    // Build main widget
    this->buildWidget();

    // Add main widget to the window
    this->setCentralWidget(_main_widget);

    // Set title
    this->setWindowTitle("MuSIK : Musical Software Instrument for Kids");
}

MainWindow::~MainWindow()
{
    #ifndef QT_NO_DEBUG
        qDebug() << "~MainWindow()";
    #endif
}

void MainWindow::buildWidget()
{
    #define MUSIK_BUTTON_STYLE "QPushButton { margin: 10px; font: bold 20px; font-family: trebuchet ms; color: #FFF;" \
                               "background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #00aaf2, stop: 1 #005676);" \
                               "border-style: outset; border-radius: 10px; padding: 15px; }" \
                               "QPushButton:hover { background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #00ccf2, stop: 1 #007876); }"

    // Create label for title
    QLabel *title_label = new QLabel("MuSIK : Musical Software Instrument for Kids");
    QLabel *description_label = new QLabel(tr("Welcome in MuSIK! You can try out some musical tools like VLC or Audacity,
"
                                           "you can test your knowledge with the musical quizz or play NotesExploder to
 "
                                           "see if you are able to survive among many notes"));
    title_label->setStyleSheet("QLabel { font: bold 20px; font-family: trebuchet ms; color: #57E; margin: 0 auto; }");
    description_label->setStyleSheet("QLabel { font: 14px; font-family: trebuchet ms; margin: 0 auto; }");

    // Create main window buttons
    QPushButton *tools_button = new QPushButton(QIcon(":/images/tools.png"), tr("Tools"));
    QPushButton *quizz_button = new QPushButton(QIcon(":/images/quizz.png"), tr("Quizz"));

    connect(tools_button, SIGNAL(clicked()), this, SLOT(launch_tools()));
    connect(quizz_button, SIGNAL(clicked()), this, SLOT(launch_quizz_selection()));

    tools_button->setStyleSheet(MUSIK_BUTTON_STYLE);
    quizz_button->setStyleSheet(MUSIK_BUTTON_STYLE);

    tools_button->setIconSize(QSize(25, 25));
    quizz_button->setIconSize(QSize(25, 25));

    // Add widgets
    _main_widget = new QWidget(this);

    QVBoxLayout *layout = new QVBoxLayout(_main_widget);
    layout->addWidget(title_label);
    layout->addWidget(description_label);
    layout->addWidget(tools_button);
    layout->addWidget(quizz_button);
}

void MainWindow::launch_tools()
{
    this->setCentralWidget(new ToolsWidget(this));
}

void MainWindow::launch_quizz_selection()
{
    this->setCentralWidget(new ThemeSelectionWidget(this));
}

void MainWindow::launch_quizz(QStringList themes)
{
    this->setCentralWidget(new QuizzWidget(this, themes));
}

void MainWindow::launch_admin_quizz()
{
    this->setCentralWidget(new AdminQuizzWidget(this));
}

void MainWindow::back()
{
    this->buildWidget();
    this->setCentralWidget(_main_widget);
}
<commit_msg>Update MainWindow.cpp<commit_after>#include "MainWindow.h"
#include "QuizzWidget.h"
#include "ToolsWidget.h"
#include "Database.h"
#include "administration/AdminQuizzWidget.h"
#include "ThemeSelectionWidget.h"

#include <QMenu>
#include <QMenuBar>
#include <QVBoxLayout>
#include <QPushButton>
#include <QDebug>
#include <QLabel>

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
{
    // Build menu
    QMenu *fileMenu(this->menuBar()->addMenu(tr("File")));
    fileMenu->addAction(QIcon(":/images/quit.png"), tr("Quit"), this, SLOT(close()));

    QMenu *adminMenu(this->menuBar()->addMenu(tr("Administration")));
    adminMenu->addAction(QIcon(":/images/admin_quizz.png"), tr("Quizz administration"), this, SLOT(launch_admin_quizz()));

    // Build main widget
    this->buildWidget();

    // Add main widget to the window
    this->setCentralWidget(_main_widget);

    // Set title
    this->setWindowTitle("MuSIK : Musical Software Instrument for Kids");

    // Set icon
    this->setWindowIcon(QIcon(":/images/icon.png"));
}

MainWindow::~MainWindow()
{
    #ifndef QT_NO_DEBUG
        qDebug() << "~MainWindow()";
    #endif
}

void MainWindow::buildWidget()
{
    #define MUSIK_BUTTON_STYLE "QPushButton { margin: 10px; font: bold 20px; font-family: trebuchet ms; color: #FFF;" \
                               "background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #00aaf2, stop: 1 #005676);" \
                               "border-style: outset; border-radius: 10px; padding: 15px; }" \
                               "QPushButton:hover { background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #00ccf2, stop: 1 #007876); }"

    // Create label for title
    QLabel *title_label = new QLabel("MuSIK : Musical Software Instrument for Kids");
    QLabel *description_label = new QLabel(tr("Welcome in MuSIK! You can try out some musical tools like VLC or Audacity,
"
                                           "you can test your knowledge with the musical quizz or play NotesExploder to
 "
                                           "see if you are able to survive among many notes"));
    title_label->setStyleSheet("QLabel { font: bold 20px; font-family: trebuchet ms; color: #57E; margin: 0 auto; }");
    description_label->setStyleSheet("QLabel { font: 14px; font-family: trebuchet ms; margin: 0 auto; }");

    // Create main window buttons
    QPushButton *tools_button = new QPushButton(QIcon(":/images/tools.png"), tr("Tools"));
    QPushButton *quizz_button = new QPushButton(QIcon(":/images/quizz.png"), tr("Quizz"));

    connect(tools_button, SIGNAL(clicked()), this, SLOT(launch_tools()));
    connect(quizz_button, SIGNAL(clicked()), this, SLOT(launch_quizz_selection()));

    tools_button->setStyleSheet(MUSIK_BUTTON_STYLE);
    quizz_button->setStyleSheet(MUSIK_BUTTON_STYLE);

    tools_button->setIconSize(QSize(25, 25));
    quizz_button->setIconSize(QSize(25, 25));

    // Add widgets
    _main_widget = new QWidget(this);

    QVBoxLayout *layout = new QVBoxLayout(_main_widget);
    layout->addWidget(title_label);
    layout->addWidget(description_label);
    layout->addWidget(tools_button);
    layout->addWidget(quizz_button);
}

void MainWindow::launch_tools()
{
    this->setCentralWidget(new ToolsWidget(this));
}

void MainWindow::launch_quizz_selection()
{
    this->setCentralWidget(new ThemeSelectionWidget(this));
}

void MainWindow::launch_quizz(QStringList themes)
{
    this->setCentralWidget(new QuizzWidget(this, themes));
}

void MainWindow::launch_admin_quizz()
{
    this->setCentralWidget(new AdminQuizzWidget(this));
}

void MainWindow::back()
{
    this->buildWidget();
    this->setCentralWidget(_main_widget);
}
<|endoftext|>