<commit_before>#include "rpcconsole.h"
#include "ui_rpcconsole.h"

#include "clientmodel.h"
#include "bitcoinrpc.h"
#include "guiutil.h"

#include <QTime>
#include <QTimer>
#include <QThread>
#include <QTextEdit>
#include <QKeyEvent>
#include <QUrl>
#include <QScrollBar>

#include <openssl/crypto.h>

// TODO: make it possible to filter out categories (esp debug messages when implemented)
// TODO: receive errors and debug messages through ClientModel

const int CONSOLE_SCROLLBACK = 50;
const int CONSOLE_HISTORY = 50;

const QSize ICON_SIZE(24, 24);

const struct {
    const char *url;
    const char *source;
} ICON_MAPPING[] = {
    {"cmd-request", ":/icons/tx_input"},
    {"cmd-reply", ":/icons/tx_output"},
    {"cmd-error", ":/icons/tx_output"},
    {"misc", ":/icons/tx_inout"},
    {NULL, NULL}
};

/* Object for executing console RPC commands in a separate thread.
*/
class RPCExecutor: public QObject
{
    Q_OBJECT
public slots:
    void start();
    void request(const QString &command);
signals:
    void reply(int category, const QString &command);
};

#include "rpcconsole.moc"

void RPCExecutor::start()
{
   // Nothing to do
}

/**
 * Split shell command line into a list of arguments. Aims to emulate \c bash and friends.
 *
 * - Arguments are delimited with whitespace
 * - Extra whitespace at the beginning and end and between arguments will be ignored
 * - Text can be "double" or 'single' quoted
 * - The backslash \c \ is used as escape character
 *   - Outside quotes, any character can be escaped
 *   - Within double quotes, only escape \c " and backslashes before a \c " or another backslash
 *   - Within single quotes, no escaping is possible and no special interpretation takes place
 *
 * @param[out]   args        Parsed arguments will be appended to this list
 * @param[in]    strCommand  Command line to split
 */
bool parseCommandLine(std::vector<std::string> &args, const std::string &strCommand)
{
    enum CmdParseState
    {
        STATE_EATING_SPACES,
        STATE_ARGUMENT,
        STATE_SINGLEQUOTED,
        STATE_DOUBLEQUOTED,
        STATE_ESCAPE_OUTER,
        STATE_ESCAPE_DOUBLEQUOTED
    } state = STATE_EATING_SPACES;
    std::string curarg;
    foreach(char ch, strCommand)
    {
        switch(state)
        {
        case STATE_ARGUMENT: // In or after argument
        case STATE_EATING_SPACES: // Handle runs of whitespace
            switch(ch)
            {
            case '"': state = STATE_DOUBLEQUOTED; break;
            case '\'': state = STATE_SINGLEQUOTED; break;
            case '\\': state = STATE_ESCAPE_OUTER; break;
            case ' ': case '\n': case '\t':
                if(state == STATE_ARGUMENT) // Space ends argument
                {
                    args.push_back(curarg);
                    curarg.clear();
                }
                state = STATE_EATING_SPACES;
                break;
            default: curarg += ch; state = STATE_ARGUMENT;
            }
            break;
        case STATE_SINGLEQUOTED: // Single-quoted string
            switch(ch)
            {
            case '\'': state = STATE_ARGUMENT; break;
            default: curarg += ch;
            }
            break;
        case STATE_DOUBLEQUOTED: // Double-quoted string
            switch(ch)
            {
            case '"': state = STATE_ARGUMENT; break;
            case '\\': state = STATE_ESCAPE_DOUBLEQUOTED; break;
            default: curarg += ch;
            }
            break;
        case STATE_ESCAPE_OUTER: // '\' outside quotes
            curarg += ch; state = STATE_ARGUMENT;
            break;
        case STATE_ESCAPE_DOUBLEQUOTED: // '\' in double-quoted text
            if(ch != '"' && ch != '\\') curarg += '\\'; // keep '\' for everything but the quote and '\' itself
            curarg += ch; state = STATE_DOUBLEQUOTED;
            break;
        }
    }
    switch(state) // final state
    {
    case STATE_EATING_SPACES:
        return true;
    case STATE_ARGUMENT:
        args.push_back(curarg);
        return true;
    default: // ERROR to end in one of the other states
        return false;
    }
}

void RPCExecutor::request(const QString &command)
{
    std::vector<std::string> args;
    if(!parseCommandLine(args, command.toStdString()))
    {
        emit reply(RPCConsole::CMD_ERROR, QString("Parse error: unbalanced ' or \""));
        return;
    }
    if(args.empty())
        return; // Nothing to do
    try
    {
        std::string strPrint;
        // Convert argument list to JSON objects in method-dependent way,
        // and pass it along with the method name to the dispatcher.
        json_spirit::Value result = tableRPC.execute(
            args[0],
            RPCConvertValues(args[0], std::vector<std::string>(args.begin() + 1, args.end())));

        // Format result reply
        if (result.type() == json_spirit::null_type)
            strPrint = "";
        else if (result.type() == json_spirit::str_type)
            strPrint = result.get_str();
        else
            strPrint = write_string(result, true);

        emit reply(RPCConsole::CMD_REPLY, QString::fromStdString(strPrint));
    }
    catch (json_spirit::Object& objError)
    {
        try // Nice formatting for standard-format error
        {
            int code = find_value(objError, "code").get_int();
            std::string message = find_value(objError, "message").get_str();
            emit reply(RPCConsole::CMD_ERROR, QString::fromStdString(message) + " (code " + QString::number(code) + ")");
        }
        catch(std::runtime_error &) // raised when converting to invalid type, i.e. missing code or message
        {   // Show raw JSON object
            emit reply(RPCConsole::CMD_ERROR, QString::fromStdString(write_string(json_spirit::Value(objError), false)));
        }
    }
    catch (std::exception& e)
    {
        emit reply(RPCConsole::CMD_ERROR, QString("Error: ") + QString::fromStdString(e.what()));
    }
}

RPCConsole::RPCConsole(QWidget *parent) :
    QDialog(parent),
    ui(new Ui::RPCConsole),
    historyPtr(0)
{
    ui->setupUi(this);

#ifndef Q_OS_MAC
    ui->openDebugLogfileButton->setIcon(QIcon(":/icons/export"));
    ui->showCLOptionsButton->setIcon(QIcon(":/icons/options"));
#endif

    // Install event filter for up and down arrow
    ui->lineEdit->installEventFilter(this);
    ui->messagesWidget->installEventFilter(this);

    connect(ui->clearButton, SIGNAL(clicked()), this, SLOT(clear()));

    // set OpenSSL version label
    ui->openSSLVersion->setText(SSLeay_version(SSLEAY_VERSION));

    startExecutor();

    clear();
}

RPCConsole::~RPCConsole()
{
    emit stopExecutor();
    delete ui;
}

bool RPCConsole::eventFilter(QObject* obj, QEvent *event)
{
    if(event->type() == QEvent::KeyPress) // Special key handling
    {
        QKeyEvent *keyevt = static_cast<QKeyEvent*>(event);
        int key = keyevt->key();
        Qt::KeyboardModifiers mod = keyevt->modifiers();
        switch(key)
        {
        case Qt::Key_Up: if(obj == ui->lineEdit) { browseHistory(-1); return true; } break;
        case Qt::Key_Down: if(obj == ui->lineEdit) { browseHistory(1); return true; } break;
        case Qt::Key_PageUp: /* pass paging keys to messages widget */
        case Qt::Key_PageDown:
            if(obj == ui->lineEdit)
            {
                QApplication::postEvent(ui->messagesWidget, new QKeyEvent(*keyevt));
                return true;
            }
            break;
        default:
            // Typing in messages widget brings focus to line edit, and redirects key there
            // Exclude most combinations and keys that emit no text, except paste shortcuts
            if(obj == ui->messagesWidget && (
                  (!mod && !keyevt->text().isEmpty() && key != Qt::Key_Tab) ||
                  ((mod & Qt::ControlModifier) && key == Qt::Key_V) ||
                  ((mod & Qt::ShiftModifier) && key == Qt::Key_Insert)))
            {
                ui->lineEdit->setFocus();
                QApplication::postEvent(ui->lineEdit, new QKeyEvent(*keyevt));
                return true;
            }
        }
    }
    return QDialog::eventFilter(obj, event);
}

void RPCConsole::setClientModel(ClientModel *model)
{
    this->clientModel = model;
    if(model)
    {
        // Subscribe to information, replies, messages, errors
        connect(model, SIGNAL(numConnectionsChanged(int)), this, SLOT(setNumConnections(int)));
        connect(model, SIGNAL(numBlocksChanged(int,int)), this, SLOT(setNumBlocks(int,int)));

        // Provide initial values
        ui->clientVersion->setText(model->formatFullVersion());
        ui->clientName->setText(model->clientName());
        ui->buildDate->setText(model->formatBuildDate());
        ui->startupTime->setText(model->formatClientStartupTime());

        setNumConnections(model->getNumConnections());
        ui->isTestNet->setChecked(model->isTestNet());

        setNumBlocks(model->getNumBlocks(), model->getNumBlocksOfPeers());
    }
}

static QString categoryClass(int category)
{
    switch(category)
    {
    case RPCConsole::CMD_REQUEST:  return "cmd-request"; break;
    case RPCConsole::CMD_REPLY:    return "cmd-reply"; break;
    case RPCConsole::CMD_ERROR:    return "cmd-error"; break;
    default:                       return "misc";
    }
}

void RPCConsole::clear()
{
    ui->messagesWidget->clear();
    ui->lineEdit->clear();
    ui->lineEdit->setFocus();

    // Add smoothly scaled icon images.
    // (when using width/height on an img, Qt uses nearest instead of linear interpolation)
    for(int i=0; ICON_MAPPING[i].url; ++i)
    {
        ui->messagesWidget->document()->addResource(
                    QTextDocument::ImageResource,
                    QUrl(ICON_MAPPING[i].url),
                    QImage(ICON_MAPPING[i].source).scaled(ICON_SIZE, Qt::IgnoreAspectRatio, Qt::SmoothTransformation));
    }

    // Set default style sheet
    ui->messagesWidget->document()->setDefaultStyleSheet(
                "table { }"
                "td.time { color: #808080; padding-top: 3px; } "
                "td.message { font-family: Monospace; font-size: 12px; } "
                "td.cmd-request { color: #006060; } "
                "td.cmd-error { color: red; } "
                "b { color: #006060; } "
                );

    message(CMD_REPLY, (tr("Welcome to the CAIx RPC console.") + "
" +
                        tr("Use up and down arrows to navigate history, and Ctrl-L to clear screen.") + "
" +
                        tr("Type help for an overview of available commands.")), true);
}

void RPCConsole::message(int category, const QString &message, bool html)
{
    QTime time = QTime::currentTime();
    QString timeString = time.toString();
    QString out;
    out += "

" + timeString + "	";
    out += "	";
    out += "";
    if(html)
        out += message;
    else
        out += GUIUtil::HtmlEscape(message, true);
    out += "

";
    ui->messagesWidget->append(out);
}

void RPCConsole::setNumConnections(int count)
{
    ui->numberOfConnections->setText(QString::number(count));
}

void RPCConsole::setNumBlocks(int count, int countOfPeers)
{
    ui->numberOfBlocks->setText(QString::number(count));
    ui->totalBlocks->setText(QString::number(countOfPeers));
    if(clientModel)
    {
        // If there is no current number available display N/A instead of 0, which can't ever be true
        ui->totalBlocks->setText(clientModel->getNumBlocksOfPeers() == 0 ? tr("N/A") : QString::number(clientModel->getNumBlocksOfPeers()));
        ui->lastBlockTime->setText(clientModel->getLastBlockDate().toString());
    }
}

void RPCConsole::on_lineEdit_returnPressed()
{
    QString cmd = ui->lineEdit->text();
    ui->lineEdit->clear();

    if(!cmd.isEmpty())
    {
        message(CMD_REQUEST, cmd);
        emit cmdRequest(cmd);
        // Truncate history from current position
        history.erase(history.begin() + historyPtr, history.end());
        // Append command to history
        history.append(cmd);
        // Enforce maximum history size
        while(history.size() > CONSOLE_HISTORY)
            history.removeFirst();
        // Set pointer to end of history
        historyPtr = history.size();
        // Scroll console view to end
        scrollToEnd();
    }
}

void RPCConsole::browseHistory(int offset)
{
    historyPtr += offset;
    if(historyPtr < 0)
        historyPtr = 0;
    if(historyPtr > history.size())
        historyPtr = history.size();
    QString cmd;
    if(historyPtr < history.size())
        cmd = history.at(historyPtr);
    ui->lineEdit->setText(cmd);
}

void RPCConsole::startExecutor()
{
    QThread* thread = new QThread;
    RPCExecutor *executor = new RPCExecutor();
    executor->moveToThread(thread);

    // Notify executor when thread started (in executor thread)
    connect(thread, SIGNAL(started()), executor, SLOT(start()));
    // Replies from executor object must go to this object
    connect(executor, SIGNAL(reply(int,QString)), this, SLOT(message(int,QString)));
    // Requests from this object must go to executor
    connect(this, SIGNAL(cmdRequest(QString)), executor, SLOT(request(QString)));
    // On stopExecutor signal
    // - queue executor for deletion (in execution thread)
    // - quit the Qt event loop in the execution thread
    connect(this, SIGNAL(stopExecutor()), executor, SLOT(deleteLater()));
    connect(this, SIGNAL(stopExecutor()), thread, SLOT(quit()));
    // Queue the thread for deletion (in this thread) when it is finished
    connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater()));

    // Default implementation of QThread::run() simply spins up an event loop in the thread,
    // which is what we want.
    thread->start();
}

void RPCConsole::on_tabWidget_currentChanged(int index)
{
    if(ui->tabWidget->widget(index) == ui->tab_console)
    {
        ui->lineEdit->setFocus();
    }
}

void RPCConsole::on_openDebugLogfileButton_clicked()
{
    GUIUtil::openDebugLogfile();
}

void RPCConsole::scrollToEnd()
{
    QScrollBar *scrollbar = ui->messagesWidget->verticalScrollBar();
    scrollbar->setValue(scrollbar->maximum());
}

void RPCConsole::on_showCLOptionsButton_clicked()
{
    GUIUtil::HelpMessageBox help;
    help.exec();
}
<commit_msg>Improve rpc console history behavior<commit_after>#include "rpcconsole.h"
#include "ui_rpcconsole.h"

#include "clientmodel.h"
#include "bitcoinrpc.h"
#include "guiutil.h"

#include <QTime>
#include <QTimer>
#include <QThread>
#include <QTextEdit>
#include <QKeyEvent>
#include <QUrl>
#include <QScrollBar>

#include <openssl/crypto.h>

// TODO: make it possible to filter out categories (esp debug messages when implemented)
// TODO: receive errors and debug messages through ClientModel

const int CONSOLE_SCROLLBACK = 50;
const int CONSOLE_HISTORY = 50;

const QSize ICON_SIZE(24, 24);

const struct {
    const char *url;
    const char *source;
} ICON_MAPPING[] = {
    {"cmd-request", ":/icons/tx_input"},
    {"cmd-reply", ":/icons/tx_output"},
    {"cmd-error", ":/icons/tx_output"},
    {"misc", ":/icons/tx_inout"},
    {NULL, NULL}
};

/* Object for executing console RPC commands in a separate thread.
*/
class RPCExecutor: public QObject
{
    Q_OBJECT
public slots:
    void start();
    void request(const QString &command);
signals:
    void reply(int category, const QString &command);
};

#include "rpcconsole.moc"

void RPCExecutor::start()
{
   // Nothing to do
}

/**
 * Split shell command line into a list of arguments. Aims to emulate \c bash and friends.
 *
 * - Arguments are delimited with whitespace
 * - Extra whitespace at the beginning and end and between arguments will be ignored
 * - Text can be "double" or 'single' quoted
 * - The backslash \c \ is used as escape character
 *   - Outside quotes, any character can be escaped
 *   - Within double quotes, only escape \c " and backslashes before a \c " or another backslash
 *   - Within single quotes, no escaping is possible and no special interpretation takes place
 *
 * @param[out]   args        Parsed arguments will be appended to this list
 * @param[in]    strCommand  Command line to split
 */
bool parseCommandLine(std::vector<std::string> &args, const std::string &strCommand)
{
    enum CmdParseState
    {
        STATE_EATING_SPACES,
        STATE_ARGUMENT,
        STATE_SINGLEQUOTED,
        STATE_DOUBLEQUOTED,
        STATE_ESCAPE_OUTER,
        STATE_ESCAPE_DOUBLEQUOTED
    } state = STATE_EATING_SPACES;
    std::string curarg;
    foreach(char ch, strCommand)
    {
        switch(state)
        {
        case STATE_ARGUMENT: // In or after argument
        case STATE_EATING_SPACES: // Handle runs of whitespace
            switch(ch)
            {
            case '"': state = STATE_DOUBLEQUOTED; break;
            case '\'': state = STATE_SINGLEQUOTED; break;
            case '\\': state = STATE_ESCAPE_OUTER; break;
            case ' ': case '\n': case '\t':
                if(state == STATE_ARGUMENT) // Space ends argument
                {
                    args.push_back(curarg);
                    curarg.clear();
                }
                state = STATE_EATING_SPACES;
                break;
            default: curarg += ch; state = STATE_ARGUMENT;
            }
            break;
        case STATE_SINGLEQUOTED: // Single-quoted string
            switch(ch)
            {
            case '\'': state = STATE_ARGUMENT; break;
            default: curarg += ch;
            }
            break;
        case STATE_DOUBLEQUOTED: // Double-quoted string
            switch(ch)
            {
            case '"': state = STATE_ARGUMENT; break;
            case '\\': state = STATE_ESCAPE_DOUBLEQUOTED; break;
            default: curarg += ch;
            }
            break;
        case STATE_ESCAPE_OUTER: // '\' outside quotes
            curarg += ch; state = STATE_ARGUMENT;
            break;
        case STATE_ESCAPE_DOUBLEQUOTED: // '\' in double-quoted text
            if(ch != '"' && ch != '\\') curarg += '\\'; // keep '\' for everything but the quote and '\' itself
            curarg += ch; state = STATE_DOUBLEQUOTED;
            break;
        }
    }
    switch(state) // final state
    {
    case STATE_EATING_SPACES:
        return true;
    case STATE_ARGUMENT:
        args.push_back(curarg);
        return true;
    default: // ERROR to end in one of the other states
        return false;
    }
}

void RPCExecutor::request(const QString &command)
{
    std::vector<std::string> args;
    if(!parseCommandLine(args, command.toStdString()))
    {
        emit reply(RPCConsole::CMD_ERROR, QString("Parse error: unbalanced ' or \""));
        return;
    }
    if(args.empty())
        return; // Nothing to do
    try
    {
        std::string strPrint;
        // Convert argument list to JSON objects in method-dependent way,
        // and pass it along with the method name to the dispatcher.
        json_spirit::Value result = tableRPC.execute(
            args[0],
            RPCConvertValues(args[0], std::vector<std::string>(args.begin() + 1, args.end())));

        // Format result reply
        if (result.type() == json_spirit::null_type)
            strPrint = "";
        else if (result.type() == json_spirit::str_type)
            strPrint = result.get_str();
        else
            strPrint = write_string(result, true);

        emit reply(RPCConsole::CMD_REPLY, QString::fromStdString(strPrint));
    }
    catch (json_spirit::Object& objError)
    {
        try // Nice formatting for standard-format error
        {
            int code = find_value(objError, "code").get_int();
            std::string message = find_value(objError, "message").get_str();
            emit reply(RPCConsole::CMD_ERROR, QString::fromStdString(message) + " (code " + QString::number(code) + ")");
        }
        catch(std::runtime_error &) // raised when converting to invalid type, i.e. missing code or message
        {   // Show raw JSON object
            emit reply(RPCConsole::CMD_ERROR, QString::fromStdString(write_string(json_spirit::Value(objError), false)));
        }
    }
    catch (std::exception& e)
    {
        emit reply(RPCConsole::CMD_ERROR, QString("Error: ") + QString::fromStdString(e.what()));
    }
}

RPCConsole::RPCConsole(QWidget *parent) :
    QDialog(parent),
    ui(new Ui::RPCConsole),
    historyPtr(0)
{
    ui->setupUi(this);

#ifndef Q_OS_MAC
    ui->openDebugLogfileButton->setIcon(QIcon(":/icons/export"));
    ui->showCLOptionsButton->setIcon(QIcon(":/icons/options"));
#endif

    // Install event filter for up and down arrow
    ui->lineEdit->installEventFilter(this);
    ui->messagesWidget->installEventFilter(this);

    connect(ui->clearButton, SIGNAL(clicked()), this, SLOT(clear()));

    // set OpenSSL version label
    ui->openSSLVersion->setText(SSLeay_version(SSLEAY_VERSION));

    startExecutor();

    clear();
}

RPCConsole::~RPCConsole()
{
    emit stopExecutor();
    delete ui;
}

bool RPCConsole::eventFilter(QObject* obj, QEvent *event)
{
    if(event->type() == QEvent::KeyPress) // Special key handling
    {
        QKeyEvent *keyevt = static_cast<QKeyEvent*>(event);
        int key = keyevt->key();
        Qt::KeyboardModifiers mod = keyevt->modifiers();
        switch(key)
        {
        case Qt::Key_Up: if(obj == ui->lineEdit) { browseHistory(-1); return true; } break;
        case Qt::Key_Down: if(obj == ui->lineEdit) { browseHistory(1); return true; } break;
        case Qt::Key_PageUp: /* pass paging keys to messages widget */
        case Qt::Key_PageDown:
            if(obj == ui->lineEdit)
            {
                QApplication::postEvent(ui->messagesWidget, new QKeyEvent(*keyevt));
                return true;
            }
            break;
        default:
            // Typing in messages widget brings focus to line edit, and redirects key there
            // Exclude most combinations and keys that emit no text, except paste shortcuts
            if(obj == ui->messagesWidget && (
                  (!mod && !keyevt->text().isEmpty() && key != Qt::Key_Tab) ||
                  ((mod & Qt::ControlModifier) && key == Qt::Key_V) ||
                  ((mod & Qt::ShiftModifier) && key == Qt::Key_Insert)))
            {
                ui->lineEdit->setFocus();
                QApplication::postEvent(ui->lineEdit, new QKeyEvent(*keyevt));
                return true;
            }
        }
    }
    return QDialog::eventFilter(obj, event);
}

void RPCConsole::setClientModel(ClientModel *model)
{
    this->clientModel = model;
    if(model)
    {
        // Subscribe to information, replies, messages, errors
        connect(model, SIGNAL(numConnectionsChanged(int)), this, SLOT(setNumConnections(int)));
        connect(model, SIGNAL(numBlocksChanged(int,int)), this, SLOT(setNumBlocks(int,int)));

        // Provide initial values
        ui->clientVersion->setText(model->formatFullVersion());
        ui->clientName->setText(model->clientName());
        ui->buildDate->setText(model->formatBuildDate());
        ui->startupTime->setText(model->formatClientStartupTime());

        setNumConnections(model->getNumConnections());
        ui->isTestNet->setChecked(model->isTestNet());

        setNumBlocks(model->getNumBlocks(), model->getNumBlocksOfPeers());
    }
}

static QString categoryClass(int category)
{
    switch(category)
    {
    case RPCConsole::CMD_REQUEST:  return "cmd-request"; break;
    case RPCConsole::CMD_REPLY:    return "cmd-reply"; break;
    case RPCConsole::CMD_ERROR:    return "cmd-error"; break;
    default:                       return "misc";
    }
}

void RPCConsole::clear()
{
    ui->messagesWidget->clear();
    ui->lineEdit->clear();
    ui->lineEdit->setFocus();

    // Add smoothly scaled icon images.
    // (when using width/height on an img, Qt uses nearest instead of linear interpolation)
    for(int i=0; ICON_MAPPING[i].url; ++i)
    {
        ui->messagesWidget->document()->addResource(
                    QTextDocument::ImageResource,
                    QUrl(ICON_MAPPING[i].url),
                    QImage(ICON_MAPPING[i].source).scaled(ICON_SIZE, Qt::IgnoreAspectRatio, Qt::SmoothTransformation));
    }

    // Set default style sheet
    ui->messagesWidget->document()->setDefaultStyleSheet(
                "table { }"
                "td.time { color: #808080; padding-top: 3px; } "
                "td.message { font-family: Monospace; font-size: 12px; } "
                "td.cmd-request { color: #006060; } "
                "td.cmd-error { color: red; } "
                "b { color: #006060; } "
                );

    message(CMD_REPLY, (tr("Welcome to the CAIx RPC console.") + "
" +
                        tr("Use up and down arrows to navigate history, and Ctrl-L to clear screen.") + "
" +
                        tr("Type help for an overview of available commands.")), true);
}

void RPCConsole::message(int category, const QString &message, bool html)
{
    QTime time = QTime::currentTime();
    QString timeString = time.toString();
    QString out;
    out += "

" + timeString + "	";
    out += "	";
    out += "";
    if(html)
        out += message;
    else
        out += GUIUtil::HtmlEscape(message, true);
    out += "

";
    ui->messagesWidget->append(out);
}

void RPCConsole::setNumConnections(int count)
{
    ui->numberOfConnections->setText(QString::number(count));
}

void RPCConsole::setNumBlocks(int count, int countOfPeers)
{
    ui->numberOfBlocks->setText(QString::number(count));
    ui->totalBlocks->setText(QString::number(countOfPeers));
    if(clientModel)
    {
        // If there is no current number available display N/A instead of 0, which can't ever be true
        ui->totalBlocks->setText(clientModel->getNumBlocksOfPeers() == 0 ? tr("N/A") : QString::number(clientModel->getNumBlocksOfPeers()));
        ui->lastBlockTime->setText(clientModel->getLastBlockDate().toString());
    }
}

void RPCConsole::on_lineEdit_returnPressed()
{
    QString cmd = ui->lineEdit->text();
    ui->lineEdit->clear();

    if(!cmd.isEmpty())
    {
        message(CMD_REQUEST, cmd);
        emit cmdRequest(cmd);
        // Remove command, if already in history
        history.removeOne(cmd);
        // Append command to history
        history.append(cmd);
        // Enforce maximum history size
        while(history.size() > CONSOLE_HISTORY)
            history.removeFirst();
        // Set pointer to end of history
        historyPtr = history.size();
        // Scroll console view to end
        scrollToEnd();
    }
}

void RPCConsole::browseHistory(int offset)
{
    historyPtr += offset;
    if(historyPtr < 0)
        historyPtr = 0;
    if(historyPtr > history.size())
        historyPtr = history.size();
    QString cmd;
    if(historyPtr < history.size())
        cmd = history.at(historyPtr);
    ui->lineEdit->setText(cmd);
}

void RPCConsole::startExecutor()
{
    QThread* thread = new QThread;
    RPCExecutor *executor = new RPCExecutor();
    executor->moveToThread(thread);

    // Notify executor when thread started (in executor thread)
    connect(thread, SIGNAL(started()), executor, SLOT(start()));
    // Replies from executor object must go to this object
    connect(executor, SIGNAL(reply(int,QString)), this, SLOT(message(int,QString)));
    // Requests from this object must go to executor
    connect(this, SIGNAL(cmdRequest(QString)), executor, SLOT(request(QString)));
    // On stopExecutor signal
    // - queue executor for deletion (in execution thread)
    // - quit the Qt event loop in the execution thread
    connect(this, SIGNAL(stopExecutor()), executor, SLOT(deleteLater()));
    connect(this, SIGNAL(stopExecutor()), thread, SLOT(quit()));
    // Queue the thread for deletion (in this thread) when it is finished
    connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater()));

    // Default implementation of QThread::run() simply spins up an event loop in the thread,
    // which is what we want.
    thread->start();
}

void RPCConsole::on_tabWidget_currentChanged(int index)
{
    if(ui->tabWidget->widget(index) == ui->tab_console)
    {
        ui->lineEdit->setFocus();
    }
}

void RPCConsole::on_openDebugLogfileButton_clicked()
{
    GUIUtil::openDebugLogfile();
}

void RPCConsole::scrollToEnd()
{
    QScrollBar *scrollbar = ui->messagesWidget->verticalScrollBar();
    scrollbar->setValue(scrollbar->maximum());
}

void RPCConsole::on_showCLOptionsButton_clicked()
{
    GUIUtil::HelpMessageBox help;
    help.exec();
}
<|endoftext|>


<commit_before>/*
TidyEngine
Copyright (C) 2016 Jakob Sinclair

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

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

You should have received a copy of the GNU Lesser General Public License
along with this program.  If not, see <http://www.gnu.org/licenses/>.
Contact the author at: jakob.sinclair99@gmail.com
*/

#include "audio.hpp"
#include <cstdio>
#include <al.h>

AudioSystem::AudioSystem(bool create)
{
	if (create == true)
		CreateSystem();
}

AudioSystem::~AudioSystem()
{
	DestroySystem();
}

void AudioSystem::CreateSystem()
{
	m_Device = alcOpenDevice(nullptr);
	m_Context = alcCreateContext(m_Device, nullptr);
	alcMakeContextCurrent(m_Context);

	int error = alcGetError(m_Device);
	if (error != ALC_NO_ERROR) {
		std::printf("OpenAL error: %d\n", error);
		alcDestroyContext(m_Context);
		alcCloseDevice(m_Device);
		m_Context = nullptr;
		m_Device = nullptr;
	}
}

void AudioSystem::DestroySystem()
{
	if (m_Context != nullptr)
		alcDestroyContext(m_Context);
	if (m_Device != nullptr)
		alcCloseDevice(m_Device);

	m_Context = nullptr;
	m_Device = nullptr;
}

const ALCdevice *AudioSystem::GetDevice() const
{
	return m_Device;
}<commit_msg>libTidyEngine: fixed AS destroy<commit_after>/*
TidyEngine
Copyright (C) 2016 Jakob Sinclair

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

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

You should have received a copy of the GNU Lesser General Public License
along with this program.  If not, see <http://www.gnu.org/licenses/>.
Contact the author at: jakob.sinclair99@gmail.com
*/

#include "audio.hpp"
#include <cstdio>
#include <al.h>

AudioSystem::AudioSystem(bool create)
{
	if (create == true)
		CreateSystem();
}

AudioSystem::~AudioSystem()
{
	DestroySystem();
}

void AudioSystem::CreateSystem()
{
	m_Device = alcOpenDevice(nullptr);
	m_Context = alcCreateContext(m_Device, nullptr);
	alcMakeContextCurrent(m_Context);

	int error = alcGetError(m_Device);
	if (error != ALC_NO_ERROR) {
		std::printf("OpenAL error: %d\n", error);
		alcDestroyContext(m_Context);
		alcCloseDevice(m_Device);
		m_Context = nullptr;
		m_Device = nullptr;
	}
}

void AudioSystem::DestroySystem()
{
	alcMakeContextCurrent(nullptr);
	if (m_Context != nullptr)
		alcDestroyContext(m_Context);
	if (m_Device != nullptr)
		alcCloseDevice(m_Device);

	m_Context = nullptr;
	m_Device = nullptr;
}

const ALCdevice *AudioSystem::GetDevice() const
{
	return m_Device;
}<|endoftext|>


<commit_before>/*
 * Copyright 2011 Troels Blum <troels@blum.dk>
 *
 * This file is part of cphVB <http://code.google.com/p/cphvb/>.
 *
 * cphVB is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * cphVB is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with cphVB. If not, see <http://www.gnu.org/licenses/>.
 */

#include <iostream>
#include <sstream>
#include <cassert>
#include <stdexcept>
#include <cphvb.h>
#include "InstructionBatch.hpp"
#include "GenerateSourceCode.hpp"

int InstructionBatch::kernel = 0;

InstructionBatch::InstructionBatch(cphvb_instruction* inst, const std::vector<BaseArray*>& operandBase)
    : arraynum(0)
    , scalarnum(0)
    , variablenum(0)
{
    if (inst->operand[0]->ndim > 3)
        throw std::runtime_error("More than 3 dimensions not supported.");
    shape = std::vector<cphvb_index>(inst->operand[0]->shape, inst->operand[0]->shape + inst->operand[0]->ndim);
    add(inst, operandBase);
}

bool InstructionBatch::shapeMatch(cphvb_intp ndim,const cphvb_index dims[])
{
    int size = shape.size();
    if (ndim == size)
    {
        for (int i = 0; i < ndim; ++i)
        {
            if (dims[i] != shape[i])
                return false;
        }
        return true;
    }
    return false;
}

bool InstructionBatch::sameView(const cphvb_array* a, const cphvb_array* b)
{
    //assumes the the views shape are the same and they have the same base
    if (a == b)
        return true;
    if (a->start != b->start)
        return false;
    for (size_t i = 0; i < shape.size(); ++i)
    {
        if (a->stride[i] != b->stride[i])
            return false;
    }
    return true;
}

void InstructionBatch::add(cphvb_instruction* inst, const std::vector<BaseArray*>& operandBase)
{
    assert(!operandBase[0]->isScalar());

    // Check that the shape matches
    if (!shapeMatch(inst->operand[0]->ndim, inst->operand[0]->shape))
        throw BatchException(0);

    // If any operand's base is already used as output, it has to be alligned.
    for (size_t op = 0; op < operandBase.size(); ++op)
    {
        if (!cphvb_scalar(inst->operand[op]))
        {
            OutputMap::iterator oit = output.find(operandBase[op]);
            if (oit != output.end())
            {
                if (sameView(oit->second, inst->operand[op]))
                {
                    inst->operand[op] = oit->second;
                }
                else
                {
                    throw BatchException(0);
                }
            }
        }
    }

    // If the output operans is allready used as input it has to be alligned
    std::pair<InputMap::iterator, InputMap::iterator> irange = input.equal_range(operandBase[0]);
    for (InputMap::iterator iit = irange.first ; iit != irange.second; ++iit)
    {
        if (sameView(iit->second, inst->operand[0]))
        {
            inst->operand[0] = iit->second;
        }
        else
        {
            throw BatchException(0);
        }
    }

    // OK so we can accept the instruction
    instructions.push_back(inst);
    // Register output
    output[operandBase[0]] = inst->operand[0];
    // Are some of the input parameters allready know? Otherwise register them
    for (size_t op = 1; op < operandBase.size(); ++op)
    {
        OutputMap::iterator oit = output.find(operandBase[op]);
        irange = input.equal_range(operandBase[op]);
        if (irange.first == irange.second && oit == output.end())
        {  //first time we encounter this basearray
            input.insert(std::make_pair(operandBase[op], inst->operand[op]));
        }
        else if (oit != output.end() && sameView(oit->second, inst->operand[op]))
        {  //it is allready part of the output
            inst->operand[op] = oit->second;
        }
        for (InputMap::iterator iit = irange.first ; iit != irange.second; ++iit)
        {
            if (sameView(iit->second, inst->operand[op])) //it is allready part of the input
            {
                inst->operand[op] = iit->second;
            } else { //it is a new view on a known base array
                input.insert(std::make_pair(operandBase[op], inst->operand[op]));
            }
        }
    }

    // Register Kernel parameters
    for (size_t op = 0; op < operandBase.size(); ++op)
    {
        cphvb_array* base = cphvb_base_array(inst->operand[op]);
        if (parameters.find(base) == parameters.end())
        {
            std::stringstream ss;
            ss << "p" << arraynum++;
            parameters[base] = std::make_pair(operandBase[op],ss.str());
        }
    }
}

Kernel InstructionBatch::generateKernel(ResourceManager* resourceManager)
{
    std::stringstream ss;
    ss << "kernel" << kernel++;
    std::string code = generateCode(ss.str());
    std::vector<OCLtype> signature;
    for (ParameterMap::iterator pit = parameters.begin(); pit != parameters.end(); ++pit)
    {
        signature.push_back(pit->second.first->parameterType());
    }
    return Kernel(resourceManager, shape.size(), signature, code, ss.str());
}

cl::Event InstructionBatch::run(ResourceManager* resourceManager)
{
    if (output.begin() == output.end())
        return resourceManager->completeEvent();
    Kernel kernel = generateKernel(resourceManager);
    Kernel::Parameters kernelParameters;
    for (ParameterMap::iterator pit = parameters.begin(); pit != parameters.end(); ++pit)
    {
        if (output.find(pit->second.first) == output.end())
            kernelParameters.push_back(std::make_pair(pit->second.first, false));
        else
            kernelParameters.push_back(std::make_pair(pit->second.first, true));
    }
    cl::Event event = kernel.call(kernelParameters, shape);
    return event;
}

std::string InstructionBatch::generateCode(const std::string& kernelName)
{
#ifdef DEBUG
    std::cout << "[VE-GPU] generateCode(" << kernelName << ")" << std::endl;
#endif
    std::stringstream source;
    source << "__kernel void " << kernelName << "( ";

    // Add Array kernel parameters
    ParameterMap::iterator pit = parameters.begin();
    pit->second.first->printKernelParameterType(true, source);
    source << " " << pit->second.second;
#ifdef DEBUG
    source << " /* " << pit->first << " */";
#endif
    for (++pit; pit != parameters.end(); ++pit)
    {
        source << "\n                     , ";
        pit->second.first->printKernelParameterType(true, source);
        source << " " << pit->second.second;
#ifdef DEBUG
        source << " /* " << pit->first << " */";
#endif
    }

    source << ")\n{\n";

    generateGIDSource(shape.size(), source);

    // Load input parameters
    for (InputMap::iterator iit = input.begin(); iit != input.end(); ++iit)
    {
        if (!iit->first->isScalar())
        {
            std::stringstream ss;
            ss << "v" << variablenum++;
            kernelVariables[iit->second] = ss.str();
            source << "\t" << oclTypeStr(iit->first->type()) << " " << ss.str() << " = " <<
                parameters[cphvb_base_array(iit->second)].second << "[";
            generateOffsetSource(iit->second, source);
            source << "];\n";
        }
    }

    // Generate code for instructions
    for (std::vector<cphvb_instruction*>::iterator iit = instructions.begin(); iit != instructions.end(); ++iit)
    {
        std::vector<std::string> operands;
        // Has the output operand been assigned a variable name?
        VariableMap::iterator kvit = kernelVariables.find((*iit)->operand[0]);
        if (kvit == kernelVariables.end())
        {
            std::stringstream ss;
            ss << "v" << variablenum++;
            kernelVariables[(*iit)->operand[0]] = ss.str();
            operands.push_back(ss.str());
            source << "\t" << oclTypeStr(oclType((*iit)->operand[0]->type)) << " " << ss.str() << ";\n";
        }
        else
        {
            operands.push_back(kvit->second);
        }
        // find variable names for input operands
        for (int op = 1; op < cphvb_operands((*iit)->opcode); ++op)
        {
            if (cphvb_scalar((*iit)->operand[op]))
                operands.push_back(parameters[cphvb_base_array((*iit)->operand[op])].second);
            else
                operands.push_back(kernelVariables[(*iit)->operand[op]]);
        }

        // generate source code for the instruction
        generateInstructionSource((*iit)->opcode, operands, source);
    }

    // Save output parameters
    for (OutputMap::iterator oit = output.begin(); oit != output.end(); ++oit)
    {
        source << "\t" << parameters[cphvb_base_array(oit->second)].second << "[";
        generateOffsetSource(oit->second, source);
        source << "] = " <<  kernelVariables[oit->second] << ";\n";
    }

    source << "}\n";
    return source.str();
}

bool InstructionBatch::read(BaseArray* array)
{
    if (input.find(array) == input.end())
        return false;
    return true;
}

bool InstructionBatch::write(BaseArray* array)
{
    if (output.find(array) == output.end())
        return false;
    return true;
}

bool InstructionBatch::access(BaseArray* array)
{
    return (read(array) || write(array));
}

bool InstructionBatch::discard(BaseArray* array)
{
    OutputMap::iterator oit = output.find(array);
    bool r =  read(array);
    if (oit != output.end())
    {
        output.erase(oit);
        if (!r)
            parameters.erase(array->getSpec());
    }
    return !r;
}
<commit_msg>BugFix Register input before output in InstructionBatch<commit_after>/*
 * Copyright 2011 Troels Blum <troels@blum.dk>
 *
 * This file is part of cphVB <http://code.google.com/p/cphvb/>.
 *
 * cphVB is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * cphVB is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with cphVB. If not, see <http://www.gnu.org/licenses/>.
 */

#include <iostream>
#include <sstream>
#include <cassert>
#include <stdexcept>
#include <cphvb.h>
#include "InstructionBatch.hpp"
#include "GenerateSourceCode.hpp"

int InstructionBatch::kernel = 0;

InstructionBatch::InstructionBatch(cphvb_instruction* inst, const std::vector<BaseArray*>& operandBase)
    : arraynum(0)
    , scalarnum(0)
    , variablenum(0)
{
    if (inst->operand[0]->ndim > 3)
        throw std::runtime_error("More than 3 dimensions not supported.");
    shape = std::vector<cphvb_index>(inst->operand[0]->shape, inst->operand[0]->shape + inst->operand[0]->ndim);
    add(inst, operandBase);
}

bool InstructionBatch::shapeMatch(cphvb_intp ndim,const cphvb_index dims[])
{
    int size = shape.size();
    if (ndim == size)
    {
        for (int i = 0; i < ndim; ++i)
        {
            if (dims[i] != shape[i])
                return false;
        }
        return true;
    }
    return false;
}

bool InstructionBatch::sameView(const cphvb_array* a, const cphvb_array* b)
{
    //assumes the the views shape are the same and they have the same base
    if (a == b)
        return true;
    if (a->start != b->start)
        return false;
    for (size_t i = 0; i < shape.size(); ++i)
    {
        if (a->stride[i] != b->stride[i])
            return false;
    }
    return true;
}

void InstructionBatch::add(cphvb_instruction* inst, const std::vector<BaseArray*>& operandBase)
{
    assert(!operandBase[0]->isScalar());

    // Check that the shape matches
    if (!shapeMatch(inst->operand[0]->ndim, inst->operand[0]->shape))
        throw BatchException(0);

    // If any operand's base is already used as output, it has to be alligned.
    for (size_t op = 0; op < operandBase.size(); ++op)
    {
        if (!cphvb_scalar(inst->operand[op]))
        {
            OutputMap::iterator oit = output.find(operandBase[op]);
            if (oit != output.end())
            {
                if (sameView(oit->second, inst->operand[op]))
                {
                    inst->operand[op] = oit->second;
                }
                else
                {
                    throw BatchException(0);
                }
            }
        }
    }

    // If the output operans is allready used as input it has to be alligned
    std::pair<InputMap::iterator, InputMap::iterator> irange = input.equal_range(operandBase[0]);
    for (InputMap::iterator iit = irange.first ; iit != irange.second; ++iit)
    {
        if (sameView(iit->second, inst->operand[0]))
        {
            inst->operand[0] = iit->second;
        }
        else
        {
            throw BatchException(0);
        }
    }

    // OK so we can accept the instruction
    instructions.push_back(inst);
    // Are some of the input parameters allready know? Otherwise register them
    for (size_t op = 1; op < operandBase.size(); ++op)
    {
        OutputMap::iterator oit = output.find(operandBase[op]);
        irange = input.equal_range(operandBase[op]);
        if (irange.first == irange.second && oit == output.end())
        {  //first time we encounter this basearray
            input.insert(std::make_pair(operandBase[op], inst->operand[op]));
        }
        else if (oit != output.end() && sameView(oit->second, inst->operand[op]))
        {  //it is allready part of the output
            inst->operand[op] = oit->second;
        }
        for (InputMap::iterator iit = irange.first ; iit != irange.second; ++iit)
        {
            if (sameView(iit->second, inst->operand[op])) //it is allready part of the input
            {
                inst->operand[op] = iit->second;
            } else { //it is a new view on a known base array
                input.insert(std::make_pair(operandBase[op], inst->operand[op]));
            }
        }
    }

    // Register output
    output[operandBase[0]] = inst->operand[0];

    // Register Kernel parameters
    for (size_t op = 0; op < operandBase.size(); ++op)
    {
        cphvb_array* base = cphvb_base_array(inst->operand[op]);
        if (parameters.find(base) == parameters.end())
        {
            std::stringstream ss;
            ss << "p" << arraynum++;
            parameters[base] = std::make_pair(operandBase[op],ss.str());
        }
    }
}

Kernel InstructionBatch::generateKernel(ResourceManager* resourceManager)
{
    std::stringstream ss;
    ss << "kernel" << kernel++;
    std::string code = generateCode(ss.str());
    std::vector<OCLtype> signature;
    for (ParameterMap::iterator pit = parameters.begin(); pit != parameters.end(); ++pit)
    {
        signature.push_back(pit->second.first->parameterType());
    }
    return Kernel(resourceManager, shape.size(), signature, code, ss.str());
}

cl::Event InstructionBatch::run(ResourceManager* resourceManager)
{
    if (output.begin() == output.end())
        return resourceManager->completeEvent();
    Kernel kernel = generateKernel(resourceManager);
    Kernel::Parameters kernelParameters;
    for (ParameterMap::iterator pit = parameters.begin(); pit != parameters.end(); ++pit)
    {
        if (output.find(pit->second.first) == output.end())
            kernelParameters.push_back(std::make_pair(pit->second.first, false));
        else
            kernelParameters.push_back(std::make_pair(pit->second.first, true));
    }
    cl::Event event = kernel.call(kernelParameters, shape);
    return event;
}

std::string InstructionBatch::generateCode(const std::string& kernelName)
{
#ifdef DEBUG
    std::cout << "[VE-GPU] generateCode(" << kernelName << ")" << std::endl;
#endif
    std::stringstream source;
    source << "__kernel void " << kernelName << "( ";

    // Add Array kernel parameters
    ParameterMap::iterator pit = parameters.begin();
    pit->second.first->printKernelParameterType(true, source);
    source << " " << pit->second.second;
#ifdef DEBUG
    source << " /* " << pit->first << " */";
#endif
    for (++pit; pit != parameters.end(); ++pit)
    {
        source << "\n                     , ";
        pit->second.first->printKernelParameterType(true, source);
        source << " " << pit->second.second;
#ifdef DEBUG
        source << " /* " << pit->first << " */";
#endif
    }

    source << ")\n{\n";

    generateGIDSource(shape.size(), source);

    // Load input parameters
    for (InputMap::iterator iit = input.begin(); iit != input.end(); ++iit)
    {
        if (!iit->first->isScalar())
        {
            std::stringstream ss;
            ss << "v" << variablenum++;
            kernelVariables[iit->second] = ss.str();
            source << "\t" << oclTypeStr(iit->first->type()) << " " << ss.str() << " = " <<
                parameters[cphvb_base_array(iit->second)].second << "[";
            generateOffsetSource(iit->second, source);
            source << "];\n";
        }
    }

    // Generate code for instructions
    for (std::vector<cphvb_instruction*>::iterator iit = instructions.begin(); iit != instructions.end(); ++iit)
    {
        std::vector<std::string> operands;
        // Has the output operand been assigned a variable name?
        VariableMap::iterator kvit = kernelVariables.find((*iit)->operand[0]);
        if (kvit == kernelVariables.end())
        {
            std::stringstream ss;
            ss << "v" << variablenum++;
            kernelVariables[(*iit)->operand[0]] = ss.str();
            operands.push_back(ss.str());
            source << "\t" << oclTypeStr(oclType((*iit)->operand[0]->type)) << " " << ss.str() << ";\n";
        }
        else
        {
            operands.push_back(kvit->second);
        }
        // find variable names for input operands
        for (int op = 1; op < cphvb_operands((*iit)->opcode); ++op)
        {
            if (cphvb_scalar((*iit)->operand[op]))
                operands.push_back(parameters[cphvb_base_array((*iit)->operand[op])].second);
            else
                operands.push_back(kernelVariables[(*iit)->operand[op]]);
        }

        // generate source code for the instruction
        generateInstructionSource((*iit)->opcode, operands, source);
    }

    // Save output parameters
    for (OutputMap::iterator oit = output.begin(); oit != output.end(); ++oit)
    {
        source << "\t" << parameters[cphvb_base_array(oit->second)].second << "[";
        generateOffsetSource(oit->second, source);
        source << "] = " <<  kernelVariables[oit->second] << ";\n";
    }

    source << "}\n";
    return source.str();
}

bool InstructionBatch::read(BaseArray* array)
{
    if (input.find(array) == input.end())
        return false;
    return true;
}

bool InstructionBatch::write(BaseArray* array)
{
    if (output.find(array) == output.end())
        return false;
    return true;
}

bool InstructionBatch::access(BaseArray* array)
{
    return (read(array) || write(array));
}

bool InstructionBatch::discard(BaseArray* array)
{
    OutputMap::iterator oit = output.find(array);
    bool r =  read(array);
    if (oit != output.end())
    {
        output.erase(oit);
        if (!r)
            parameters.erase(array->getSpec());
    }
    return !r;
}
<|endoftext|>


<commit_before>#include <algorithm>
#include <cmath>
#include <numeric>

#include "FPSCounter.h"

FPSCounter::FPSCounter()
{
	this->frameTimes.fill(0.0);
}

int FPSCounter::getFrameCount() const
{
	return static_cast<int>(this->frameTimes.size());
}

double FPSCounter::getFrameTime(int index) const
{
	return this->frameTimes.at(index);
}

double FPSCounter::getAverageFrameTime() const
{
	const double sum = std::accumulate(this->frameTimes.begin(), this->frameTimes.end(), 0.0);
	return sum / static_cast<double>(this->frameTimes.size());
}

double FPSCounter::getFPS() const
{
	const double fps = 1.0 / this->getAverageFrameTime();
	return std::isfinite(fps) ? fps : 0.0;
}

void FPSCounter::updateFrameTime(double dt)
{
	// Rotate the array right by one index (this puts the last value at the front).
	std::rotate(this->frameTimes.rbegin(),
		this->frameTimes.rbegin() + 1, this->frameTimes.rend());

	this->frameTimes.front() = dt;
}
<commit_msg>Reduced number of frame times used for average FPS.<commit_after>#include <algorithm>
#include <cassert>
#include <cmath>
#include <numeric>

#include "FPSCounter.h"

FPSCounter::FPSCounter()
{
	this->frameTimes.fill(0.0);
}

int FPSCounter::getFrameCount() const
{
	return static_cast<int>(this->frameTimes.size());
}

double FPSCounter::getFrameTime(int index) const
{
	return this->frameTimes.at(index);
}

double FPSCounter::getAverageFrameTime() const
{
	// Only need a few frame times to get a decent approximation.
	const size_t count = 20;
	assert(count <= this->frameTimes.size());

	const double sum = std::accumulate(this->frameTimes.begin(), this->frameTimes.begin() + count, 0.0);
	return sum / static_cast<double>(count);
}

double FPSCounter::getFPS() const
{
	const double fps = 1.0 / this->getAverageFrameTime();
	return std::isfinite(fps) ? fps : 0.0;
}

void FPSCounter::updateFrameTime(double dt)
{
	// Rotate the array right by one index (this puts the last value at the front).
	std::rotate(this->frameTimes.rbegin(),
		this->frameTimes.rbegin() + 1, this->frameTimes.rend());

	this->frameTimes.front() = dt;
}
<|endoftext|>


<commit_before>/*
This file is part of Bohrium and copyright (c) 2012 the Bohrium
team <http://www.bh107.org>.

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

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

You should have received a copy of the
GNU Lesser General Public License along with Bohrium.

If not, see <http://www.gnu.org/licenses/>.
*/

#include <vector>
#include <iostream>
#include <fstream>
#include <string>
#include <map>
#include <boost/functional/hash.hpp>
#include <iomanip>
#include <dlfcn.h>
#include <jitk/codegen_util.hpp>

#include "engine_openmp.hpp"

using namespace std;
namespace fs = boost::filesystem;

namespace bohrium {

static boost::hash<string> hasher;

EngineOpenMP::EngineOpenMP(const ConfigParser &config, jitk::Statistics &stat) :
                                           tmp_dir(fs::temp_directory_path() / fs::unique_path("bohrium_%%%%")),
                                           source_dir(tmp_dir / "src"),
                                           object_dir(tmp_dir / "obj"),
                                           compiler(config.defaultGet<string>("compiler_cmd", "/usr/bin/cc"),
                                                    config.defaultGet<string>("compiler_inc", ""),
                                                    config.defaultGet<string>("compiler_lib", "-lm"),
                                                    config.defaultGet<string>("compiler_flg", ""),
                                                    config.defaultGet<string>("compiler_ext", "")),
                                           verbose(config.defaultGet<bool>("verbose", false)),
                                           stat(stat)
{
    // Let's make sure that the directories exist
    fs::create_directories(source_dir);
    fs::create_directories(object_dir);
}

EngineOpenMP::~EngineOpenMP() {
    for(void *handle: _lib_handles) {
        dlerror(); // Reset errors
        if (dlclose(handle)) {
            cerr << dlerror() << endl;
        }
    }
}

// Returns the filename of the given 'hash'
static string hash_filename(size_t hash, string extension=".so") {
    stringstream ss;
    ss << setfill ('0') << setw(sizeof(size_t)*2) << hex << hash << extension;
    return ss.str();
}

KernelFunction EngineOpenMP::getFunction(const string &source) {
    size_t hash = hasher(source);
    ++stat.kernel_cache_lookups;

    // Do we have the function compiled and ready already?
    if (_functions.find(hash) != _functions.end()) {
        return _functions.at(hash);
    }
    ++stat.kernel_cache_misses;

    // The object file path
    fs::path objfile = object_dir / hash_filename(hash);

    // Write the source file and compile it (reading from disk)
    // NB: this is a nice debug option, but will hurt performance
    if (verbose) {
        fs::path srcfile = source_dir;
        {
            srcfile /= hash_filename(hash, ".c");
            ofstream ofs(srcfile.string());
            ofs << source;
            ofs.flush();
            ofs.close();
        }
        cout << "Write source " << srcfile << endl;
        compiler.compile(objfile.string(), srcfile.string());
    } else {
        // Pipe the source directly into the compiler thus no source file is written
        compiler.compile(objfile.string(), source.c_str(), source.size());
    }

    // Load the shared library
    void *lib_handle = dlopen(objfile.string().c_str(), RTLD_NOW);
    if (lib_handle == NULL) {
        cerr << "Cannot load library: " << dlerror() << endl;
        throw runtime_error("VE-OPENMP: Cannot load library");
    }
    _lib_handles.push_back(lib_handle);

    // Load the launcher function
    // The (clumsy) cast conforms with the ISO C standard and will
    // avoid any compiler warnings.
    dlerror(); // Reset errors
    *(void **) (&_functions[hash]) = dlsym(lib_handle, "launcher");
    const char* dlsym_error = dlerror();
    if (dlsym_error) {
        cerr << "Cannot load function launcher(): " << dlsym_error << endl;
        throw runtime_error("VE-OPENMP: Cannot load function launcher()");
    }

    return _functions.at(hash);
}

void EngineOpenMP::execute(const std::string &source, const jitk::Kernel &kernel,
                           const std::vector<const jitk::LoopB*> &threaded_blocks,
                           const std::vector<const bh_view*> &offset_strides,
                           const std::vector<const bh_instruction*> &constants) {

    // Make sure all arrays are allocated
    for (bh_base *base: kernel.getNonTemps()) {
        bh_data_malloc(base);
    }

    // Compile the kernel
    auto tbuild = chrono::steady_clock::now();
    KernelFunction func = getFunction(source);
    assert(func != NULL);
    stat.time_compile += chrono::steady_clock::now() - tbuild;

    // Create a 'data_list' of data pointers
    vector<void*> data_list;
    data_list.reserve(kernel.getNonTemps().size());
    for(bh_base *base: kernel.getNonTemps()) {
        assert(base->data != NULL);
        data_list.push_back(base->data);
    }

    // And the offset-and-strides
    vector<uint64_t> offset_and_strides;
    offset_and_strides.reserve(offset_strides.size());
    for (const bh_view *view: offset_strides) {
        const uint64_t t = (uint64_t) view->start;
        offset_and_strides.push_back(t);
        for (int i=0; i<view->ndim; ++i) {
            const uint64_t s = (uint64_t) view->stride[i];
            offset_and_strides.push_back(s);
        }
    }

    // And the constants
    vector<bh_constant_value> constant_arg;
    constant_arg.reserve(constants.size());
    for (const bh_instruction* instr: constants) {
        constant_arg.push_back(instr->constant.value);
    }

    auto texec = chrono::steady_clock::now();
    // Call the launcher function, which will execute the kernel
    func(&data_list[0], &offset_and_strides[0], &constant_arg[0]);
    stat.time_exec += chrono::steady_clock::now() - texec;

}

void EngineOpenMP::set_constructor_flag(std::vector<bh_instruction*> &instr_list) {
    const std::set<bh_base*> empty;
    jitk::util_set_constructor_flag(instr_list, empty);
}

} // bohrium
<commit_msg>Disable dlclose calls on EngineOpenMP destruction<commit_after>/*
This file is part of Bohrium and copyright (c) 2012 the Bohrium
team <http://www.bh107.org>.

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

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

You should have received a copy of the
GNU Lesser General Public License along with Bohrium.

If not, see <http://www.gnu.org/licenses/>.
*/

#include <vector>
#include <iostream>
#include <fstream>
#include <string>
#include <map>
#include <boost/functional/hash.hpp>
#include <iomanip>
#include <dlfcn.h>
#include <jitk/codegen_util.hpp>

#include "engine_openmp.hpp"

using namespace std;
namespace fs = boost::filesystem;

namespace bohrium {

static boost::hash<string> hasher;

EngineOpenMP::EngineOpenMP(const ConfigParser &config, jitk::Statistics &stat) :
                                           tmp_dir(fs::temp_directory_path() / fs::unique_path("bohrium_%%%%")),
                                           source_dir(tmp_dir / "src"),
                                           object_dir(tmp_dir / "obj"),
                                           compiler(config.defaultGet<string>("compiler_cmd", "/usr/bin/cc"),
                                                    config.defaultGet<string>("compiler_inc", ""),
                                                    config.defaultGet<string>("compiler_lib", "-lm"),
                                                    config.defaultGet<string>("compiler_flg", ""),
                                                    config.defaultGet<string>("compiler_ext", "")),
                                           verbose(config.defaultGet<bool>("verbose", false)),
                                           stat(stat)
{
    // Let's make sure that the directories exist
    fs::create_directories(source_dir);
    fs::create_directories(object_dir);
}

EngineOpenMP::~EngineOpenMP() {
    // If this cleanup is enabled, the application segfaults
    // on destruction of the EngineOpenMP class.
    //
    // The reason for that is that OpenMP currently has no
    // means in the definition of the standard to do a proper
    // cleanup and hence internally does something funny.
    // See https://stackoverflow.com/questions/5200418/destroying-threads-in-openmp-c
    // for details.
    //
    // TODO A more sensible way to get around this issue
    //      would be to also dlopen the openmp library
    //      itself and therefore increase our reference count
    //      to it. This enables the kernel so files to be unlinked
    //      and cleaned up, but prevents the problematic code on
    //      openmp cleanup to be triggered at bohrium runtime.

    // for(void *handle: _lib_handles) {
    //     dlerror(); // Reset errors
    //     if (dlclose(handle)) {
    //         cerr << dlerror() << endl;
    //     }
    // }
}

// Returns the filename of the given 'hash'
static string hash_filename(size_t hash, string extension=".so") {
    stringstream ss;
    ss << setfill ('0') << setw(sizeof(size_t)*2) << hex << hash << extension;
    return ss.str();
}

KernelFunction EngineOpenMP::getFunction(const string &source) {
    size_t hash = hasher(source);
    ++stat.kernel_cache_lookups;

    // Do we have the function compiled and ready already?
    if (_functions.find(hash) != _functions.end()) {
        return _functions.at(hash);
    }
    ++stat.kernel_cache_misses;

    // The object file path
    fs::path objfile = object_dir / hash_filename(hash);

    // Write the source file and compile it (reading from disk)
    // NB: this is a nice debug option, but will hurt performance
    if (verbose) {
        fs::path srcfile = source_dir;
        {
            srcfile /= hash_filename(hash, ".c");
            ofstream ofs(srcfile.string());
            ofs << source;
            ofs.flush();
            ofs.close();
        }
        cout << "Write source " << srcfile << endl;
        compiler.compile(objfile.string(), srcfile.string());
    } else {
        // Pipe the source directly into the compiler thus no source file is written
        compiler.compile(objfile.string(), source.c_str(), source.size());
    }

    // Load the shared library
    void *lib_handle = dlopen(objfile.string().c_str(), RTLD_NOW);
    if (lib_handle == NULL) {
        cerr << "Cannot load library: " << dlerror() << endl;
        throw runtime_error("VE-OPENMP: Cannot load library");
    }
    _lib_handles.push_back(lib_handle);

    // Load the launcher function
    // The (clumsy) cast conforms with the ISO C standard and will
    // avoid any compiler warnings.
    dlerror(); // Reset errors
    *(void **) (&_functions[hash]) = dlsym(lib_handle, "launcher");
    const char* dlsym_error = dlerror();
    if (dlsym_error) {
        cerr << "Cannot load function launcher(): " << dlsym_error << endl;
        throw runtime_error("VE-OPENMP: Cannot load function launcher()");
    }

    return _functions.at(hash);
}

void EngineOpenMP::execute(const std::string &source, const jitk::Kernel &kernel,
                           const std::vector<const jitk::LoopB*> &threaded_blocks,
                           const std::vector<const bh_view*> &offset_strides,
                           const std::vector<const bh_instruction*> &constants) {

    // Make sure all arrays are allocated
    for (bh_base *base: kernel.getNonTemps()) {
        bh_data_malloc(base);
    }

    // Compile the kernel
    auto tbuild = chrono::steady_clock::now();
    KernelFunction func = getFunction(source);
    assert(func != NULL);
    stat.time_compile += chrono::steady_clock::now() - tbuild;

    // Create a 'data_list' of data pointers
    vector<void*> data_list;
    data_list.reserve(kernel.getNonTemps().size());
    for(bh_base *base: kernel.getNonTemps()) {
        assert(base->data != NULL);
        data_list.push_back(base->data);
    }

    // And the offset-and-strides
    vector<uint64_t> offset_and_strides;
    offset_and_strides.reserve(offset_strides.size());
    for (const bh_view *view: offset_strides) {
        const uint64_t t = (uint64_t) view->start;
        offset_and_strides.push_back(t);
        for (int i=0; i<view->ndim; ++i) {
            const uint64_t s = (uint64_t) view->stride[i];
            offset_and_strides.push_back(s);
        }
    }

    // And the constants
    vector<bh_constant_value> constant_arg;
    constant_arg.reserve(constants.size());
    for (const bh_instruction* instr: constants) {
        constant_arg.push_back(instr->constant.value);
    }

    auto texec = chrono::steady_clock::now();
    // Call the launcher function, which will execute the kernel
    func(&data_list[0], &offset_and_strides[0], &constant_arg[0]);
    stat.time_exec += chrono::steady_clock::now() - texec;

}

void EngineOpenMP::set_constructor_flag(std::vector<bh_instruction*> &instr_list) {
    const std::set<bh_base*> empty;
    jitk::util_set_constructor_flag(instr_list, empty);
}

} // bohrium
<|endoftext|>


<commit_before>// $Id$
//
// Task to propagate tracks to EMCAL surface.
//
// Author: C.Loizides

#include <TClonesArray.h>
#include "AliAnalysisManager.h"
#include "AliEMCALRecoUtils.h"
#include "AliESDEvent.h"
#include "AliEmcalTrackPropagatorTask.h"

ClassImp(AliEmcalTrackPropagatorTask)

//________________________________________________________________________
AliEmcalTrackPropagatorTask::AliEmcalTrackPropagatorTask() :
  AliAnalysisTaskSE("AliEmcalTrackPropagatorTask"),
  fRecoUtils(0),
  fTracksName(),
  fDist(430),
  fMinPtCut(0.35),
  fEsdEv(0),
  fTracks(0)
{
  // Constructor.
}

//________________________________________________________________________
AliEmcalTrackPropagatorTask::AliEmcalTrackPropagatorTask(const char *name) :
  AliAnalysisTaskSE("AliEmcalTrackPropagatorTask"),
  fRecoUtils(0),
  fTracksName("TpcSpdVertexConstrainedTracks"),
  fDist(430),
  fMinPtCut(0.35),
  fEsdEv(0),
  fTracks(0)
{
  // Constructor.

  if (!name)
    return;

  SetName(name);

  fBranchNames = "ESD:AliESDHeader.,Tracks";
}

//________________________________________________________________________
AliEmcalTrackPropagatorTask::~AliEmcalTrackPropagatorTask()
{
  // Destructor.

  delete fRecoUtils;
}

//________________________________________________________________________
void AliEmcalTrackPropagatorTask::UserCreateOutputObjects()
{
  // Create histograms.

  if (!fRecoUtils) {
    fRecoUtils = new AliEMCALRecoUtils;
    fRecoUtils->SetStep(25);
    AliInfo("No reco utils given, creating default utils");
  }
}

//________________________________________________________________________
void AliEmcalTrackPropagatorTask::UserExec(Option_t *)
{
  // Main loop, called for each event.

  fEsdEv = dynamic_cast<AliESDEvent*>(InputEvent());
  if (!fEsdEv) {
    AliError("Task works only on ESD events, returning");
    return;
  }

  AliAnalysisManager *am = AliAnalysisManager::GetAnalysisManager();
  if (!am) {
    AliError("Manager zero, returning");
    return;
  }

  // get tracks from event if not yet there
  if (fTracksName == "Tracks")
    am->LoadBranch("Tracks");
  fTracks = dynamic_cast<TClonesArray*>((InputEvent()->FindListObject(fTracksName)));
  if (!fTracks) {
    AliError(Form("Could not get tracks %s, returning", fTracksName.Data()));
    return;
  }

  // Loop over all tracks
  const Int_t ntr = fTracks->GetEntries();
  for (Int_t i=0; i<ntr; ++i) {
    AliESDtrack *eTrack = static_cast<AliESDtrack*>(fTracks->At(i));
    if (!eTrack)
      continue;
    eTrack->ResetStatus(AliVTrack::kEMCALmatch);
    if(eTrack->Pt()<fMinPtCut)
      continue;
    Double_t phi = eTrack->Phi()*TMath::RadToDeg();
    if (TMath::Abs(eTrack->Eta())>0.8 || phi <= 20 || phi >= 240)
      continue;
    AliExternalTrackParam *trackParam =  const_cast<AliExternalTrackParam*>(eTrack->GetInnerParam());
    if(!trackParam)
      continue;

    // Extrapolate the track to EMCal surface
    AliExternalTrackParam emcalParam(*trackParam);
    Float_t etaout=-999, phiout=-999, ptout=-999;
    Bool_t ret = fRecoUtils->ExtrapolateTrackToEMCalSurface(&emcalParam,
                                                            fDist,
                                                            fRecoUtils->GetMass(),
                                                            fRecoUtils->GetStepSurface(),
                                                            etaout,
                                                            phiout,
							    ptout);
    if (!ret)
      continue;
    if (TMath::Abs(etaout)>0.75 || (phiout<70*TMath::DegToRad()) || (phiout>190*TMath::DegToRad()))
      continue;
    eTrack->SetOuterParam(&emcalParam,AliExternalTrackParam::kMultSec);
    eTrack->SetTrackPhiEtaPtOnEMCal(phiout, etaout, ptout);
    eTrack->SetStatus(AliVTrack::kEMCALmatch);
  }
}
<commit_msg>Adapted to have track propagation exactly done as in the filter.<commit_after>// $Id$
//
// Task to propagate tracks to EMCAL surface.
//
// Author: C.Loizides

#include <TClonesArray.h>
#include "AliAnalysisManager.h"
#include "AliEMCALRecoUtils.h"
#include "AliESDEvent.h"
#include "AliEmcalTrackPropagatorTask.h"

ClassImp(AliEmcalTrackPropagatorTask)

//________________________________________________________________________
AliEmcalTrackPropagatorTask::AliEmcalTrackPropagatorTask() :
  AliAnalysisTaskSE("AliEmcalTrackPropagatorTask"),
  fRecoUtils(0),
  fTracksName(),
  fDist(430),
  fMinPtCut(0.35),
  fEsdEv(0),
  fTracks(0)
{
  // Constructor.
}

//________________________________________________________________________
AliEmcalTrackPropagatorTask::AliEmcalTrackPropagatorTask(const char *name) :
  AliAnalysisTaskSE("AliEmcalTrackPropagatorTask"),
  fRecoUtils(0),
  fTracksName("TpcSpdVertexConstrainedTracks"),
  fDist(430),
  fMinPtCut(0.35),
  fEsdEv(0),
  fTracks(0)
{
  // Constructor.

  if (!name)
    return;

  SetName(name);

  fBranchNames = "ESD:AliESDHeader.,Tracks";
}

//________________________________________________________________________
AliEmcalTrackPropagatorTask::~AliEmcalTrackPropagatorTask()
{
  // Destructor.

  delete fRecoUtils;
}

//________________________________________________________________________
void AliEmcalTrackPropagatorTask::UserCreateOutputObjects()
{
  // Create histograms.

  if (!fRecoUtils) {
    fRecoUtils = new AliEMCALRecoUtils;
    fRecoUtils->SetStep(20);
    AliInfo("No reco utils given, creating default utils");
  }
}

//________________________________________________________________________
void AliEmcalTrackPropagatorTask::UserExec(Option_t *)
{
  // Main loop, called for each event.

  fEsdEv = dynamic_cast<AliESDEvent*>(InputEvent());
  if (!fEsdEv) {
    AliError("Task works only on ESD events, returning");
    return;
  }

  AliAnalysisManager *am = AliAnalysisManager::GetAnalysisManager();
  if (!am) {
    AliError("Manager zero, returning");
    return;
  }

  // get tracks from event if not yet there
  if (fTracksName == "Tracks")
    am->LoadBranch("Tracks");
  fTracks = dynamic_cast<TClonesArray*>((InputEvent()->FindListObject(fTracksName)));
  if (!fTracks) {
    AliError(Form("Could not get tracks %s, returning", fTracksName.Data()));
    return;
  }

  // Loop over all tracks
  const Int_t ntr = fTracks->GetEntries();
  for (Int_t i=0; i<ntr; ++i) {
    AliESDtrack *eTrack = static_cast<AliESDtrack*>(fTracks->At(i));
    if (!eTrack)
      continue;
    eTrack->ResetStatus(AliVTrack::kEMCALmatch);
    if(eTrack->Pt()<fMinPtCut)
      continue;
    Double_t phi = eTrack->Phi()*TMath::RadToDeg();
    if (TMath::Abs(eTrack->Eta())>0.9 || phi <= 10 || phi >= 250)
      continue;
    AliExternalTrackParam *trackParam =  const_cast<AliExternalTrackParam*>(eTrack->GetInnerParam());
    if(!trackParam)
      continue;

    // Extrapolate the track to EMCal surface
    AliExternalTrackParam emcalParam(*trackParam);
    Float_t etaout=-999, phiout=-999, ptout=-999;
    Bool_t ret = fRecoUtils->ExtrapolateTrackToEMCalSurface(&emcalParam,
                                                            fDist,
                                                            eTrack->GetMass(),
                                                            fRecoUtils->GetStepSurface(),
                                                            etaout,
                                                            phiout,
							    ptout);
    if (!ret)
      continue;
    if (TMath::Abs(etaout)>0.75 || (phiout<70*TMath::DegToRad()) || (phiout>190*TMath::DegToRad()))
      continue;
    eTrack->SetOuterParam(&emcalParam,AliExternalTrackParam::kMultSec);
    eTrack->SetTrackPhiEtaPtOnEMCal(phiout, etaout, ptout);
    eTrack->SetStatus(AliVTrack::kEMCALmatch);
  }
}
<|endoftext|>


<commit_before>//
void runCaloElectron(bool submit = false, // true or false
					 const char *dataType="sim", // "sim/PbPb" or "real/pp" etc.
					 const char *pluginRunMode="test", // "test" or "full" or "terminate"
					 const char* fileName="/data/LHC10d15/1821/AliESDs.root")
{
	TStopwatch timer;
	timer.Start();

	gSystem->Load("libCore.so"); // jens
	gSystem->Load("libTree");
	gSystem->Load("libGeom");
	gSystem->Load("libVMC");
	gSystem->Load("libPhysics");
	gSystem->Load("libMinuit");

	gSystem->AddIncludePath("-I$ALICE_ROOT/include");
	gSystem->AddIncludePath("-I. -I$ALICE_ROOT/EMCAL -I$ALICE_ROOT/ANALYSIS");

	gSystem->Load("libSTEERBase");
	gSystem->Load("libESD");
	gSystem->Load("libAOD");

	gSystem->Load("libANALYSIS");
	gSystem->Load("libOADB"); // Jens
	gSystem->Load("libANALYSISalice");
	gSystem->Load("libCORRFW");

	gSystem->Load("libTENDER.so");

	gSystem->Load("libCDB"); // Jens
	gSystem->Load("libRAWDatabase");
	gSystem->Load("libProof");
	gSystem->Load("libSTEER");
	gSystem->Load("libTOFbase");
	gSystem->Load("libTRDbase");
	gSystem->Load("libVZERObase");
	gSystem->Load("libVZEROrec");
	gSystem->Load("libEMCALraw");
	gSystem->Load("libEMCALUtils");
	gSystem->Load("libEMCALbase");
	gSystem->Load("libEMCALrec");

	gSystem->Load("libTENDERSupplies.so");

	if (!submit) {
		cout << "local - no submitting" << endl;
	}
	else {
		cout << "submitting to grid" << endl;
	}

	gROOT->ProcessLine(".include $ALICE_ROOT/Tender/");
	gROOT->ProcessLine(".L AliAnalysisTaskCaloElectron.cxx+g");

	gInterpreter->GenerateDictionary("std::map<int, AliPhysicsSelection*>", "AliPhysicsSelection.h;map")  ;
	gInterpreter->GenerateDictionary("std::pair<int, AliPhysicsSelection*>", "AliPhysicsSelection.h;utility");

	char *kTreeName = "esdTree" ;
	TChain * chain   = new TChain(kTreeName,"myESDTree") ;

	if(submit){
		gSystem->Load("libNetx") ;
		gSystem->Load("libgapiUI");
		gSystem->Load("libRAliEn");
		TGrid::Connect("alien://") ;
	}

	// Make the analysis manager
	AliAnalysisManager *mgr = new AliAnalysisManager("CaloElectronManager");

	TString taskName = "EMCalElectron";
	TString dataStr(dataType);
	TString dataStrName(dataType);
	dataStrName.ReplaceAll("/",".");
	TString outputName = "Electron.ESD." + dataStrName + ".root";
	//TString outputDir = "totEt" + dataStr;
	TString outputDir = "emcal/electrons/LHC11a_pass2_without_SDD_EMC_v6";

	cout << " taskName " << taskName
	<< " outputName " << outputName
	<< " outputDir (alien) " << outputDir << endl;

	if (submit) {
		gROOT->LoadMacro("CreateAlienHandlerCaloElectron.C");
		AliAnalysisGrid *alienHandler = CreateAlienHandlerCaloElectron(outputDir, outputName, pluginRunMode);
		if (!alienHandler) return;
		mgr->SetGridHandler(alienHandler);
	}

	AliVEventHandler* esdH = new AliESDInputHandler;
	mgr->SetInputEventHandler(esdH);
	AliMCEventHandler* handler = new AliMCEventHandler;
	Bool_t isMC = kFALSE;
	Bool_t isPb = kFALSE;
	if ( dataStr.Contains("PbPb") ) { isPb = kTRUE;}
	if ( dataStr.Contains("sim") ) {
		cout << " MC " << endl;
		isMC = kTRUE;
		if (!submit)
		{
			if ( dataStr.Contains("PbPb") ) { // a la: simPbPb/LHC10e18a
				cout << " PbPb " << endl;
				TString fileLocation = "/home/dsilverm/data/E_T/" + dataStr + "/dir/AliESDs.root";
				cout << "fileLocation " << fileLocation.Data() << endl;
				chain->Add(fileLocation.Data()); // link to local test file
			}
			else if ( dataStr.Contains("pp") ){ // pp
				chain->Add("./118506.1821/AliESDs.root");//simulation p+p
				//chain->Add("/data/LHC10d15/1821/AliESDs.root");
				//chain->Add("/data/LHC10dpass2/10000126403050.70/AliESDs.root");//data
				//chain->Add("/home/dsilverm/data/E_T/sim/LHC10d1/117222/100/AliESDs.root"); // link to local test file
			}
			else {
				chain->Add(fileName);
			}
		}
		handler->SetReadTR(kFALSE);
		mgr->SetMCtruthEventHandler(handler);
	}
	else { // real data
		if (!submit)
		{
			chain->Add(fileName);
			//chain->Add("10000126403050.70/AliESDs.root");
			//chain->Add("/home/dsilverm/data/E_T/data/2010/LHC10b/000117222/ESDs/pass2/10000117222021.30/AliESDs.root"); // link to local test file
			cout << " not MC " << endl;
		}
	}

	//Tender Supplies
	if (!isMC)
	{
		cout << "Running the Tender..."<< endl;
		gROOT->LoadMacro("./CreateEMCALTender.C");
		AliAnalysisTaskSE *tender = CreateEMCALTender(kTRUE);
		//gROOT->LoadMacro("$ALICE_ROOT/ANALYSIS/TenderSupplies/AddTaskTender.C");
		//AliAnalysisTaskSE *tender = AddTaskTender(kTRUE);
		//mgr->AddTask(tender);
	}

	// Event selection
	gROOT->ProcessLine(".L $ALICE_ROOT/ANALYSIS/macros/AddTaskPhysicsSelection.C");

	AliPhysicsSelectionTask *physicsSelectionTask = AddTaskPhysicsSelection(isMC);//isMC is true when processing monte carlo
	if(isPb){
		gROOT->ProcessLine(".L $ALICE_ROOT/ANALYSIS/macros/AddTaskCentrality.C");
		gROOT->ProcessLine(".L AliCentralitySelectionTask.cxx++g");
		AliCentralitySelectionTask *centTask = AddTaskCentrality();
	}

	// Electron analysis
	AliAnalysisTaskCaloElectron *task1 = new AliAnalysisTaskCaloElectron(taskName,isMC);

	/*
	if ( dataStr.Contains("EMCAL") ) {
		cout << "EMCAL trigger" << endl;
		//task1->SetTriggerSelection(kTRUE,"CEMC1-B-NOPF-ALLNOTRD");
		physicsSelectionTask->SelectCollisionCandidates(AliVEvent::kEMC1);
	}
	else
		physicsSelectionTask->SelectCollisionCandidates(AliVEvent::kMB);
	*/

	mgr->AddTask(task1);

	AliAnalysisDataContainer *cinput1 = mgr->GetCommonInputContainer();
	AliAnalysisDataContainer *coutput1 = mgr->CreateContainer("out1", TList::Class(), AliAnalysisManager::kOutputContainer, outputName);

	//____________________________________________//
	mgr->ConnectInput(task1,0,cinput1);
	mgr->ConnectOutput(task1,1,coutput1);

	mgr->SetDebugLevel(0);

	if (!mgr->InitAnalysis()) return;
	mgr->PrintStatus();
	if(submit){
		mgr->StartAnalysis("grid");
	}
	else{
		mgr->StartAnalysis("local",chain);
	}

	timer.Stop();
	timer.Print();
}
<commit_msg>This should have been removed a long time ago<commit_after><|endoftext|>


<commit_before>/**
 * @file
 */
#pragma once

#include "libbirch/SharedPtr.hpp"
#include "libbirch/WeakPtr.hpp"
#include "libbirch/Memo.hpp"

namespace libbirch {
/**
 * Shared or weak pointer to a Memo, according to context. This is used by
 * LazyPtr for its memo field. It records the context of the
 * pointer: whether it is part of a member variable or not, and keeps a
 * weak or shared pointer to the Memo according to that context.
 *
 * @ingroup libbirch
 */
class ContextPtr {
public:
  /**
   * Default constructor.
   */
  ContextPtr() :
      context(currentContext) {
    //
  }

  /**
   * Value constructor.
   */
  ContextPtr(Memo* memo) :
      memo(memo == currentContext ? nullptr : memo),
      context(currentContext) {
    //
  }

  /**
   * Copy constructor.
   */
  ContextPtr(const ContextPtr& o) :
      memo(nullptr),
      context(currentContext) {
    if (o.memo) {
      if (o.memo != context) {
        memo = o.memo;
      }
    } else {
      if (o.context != context) {
        memo = o.context;
      }
    }
  }

  /**
   * Move constructor.
   */
  ContextPtr(ContextPtr&& o) :
      memo(nullptr),
      context(currentContext) {
    if (o.memo) {
      if (o.memo != context) {
        memo = std::move(o.memo);
      }
    } else {
      if (o.context != context) {
        memo = std::move(o.context);
      }
    }
  }

  /**
   * Value assignment.
   */
  ContextPtr& operator=(Memo* memo) {
    this->memo = (memo == context.get()) ? nullptr : memo;
    return *this;
  }

  /**
   * Copy assignment.
   */
  ContextPtr& operator=(const ContextPtr& o) {
    if (o.memo) {
      if (o.memo != context) {
        memo = o.memo;
      } else {
        memo = nullptr;
      }
    } else {
      if (o.context != context) {
        memo = o.context;
      } else {
        memo = nullptr;
      }
    }
    return *this;
  }

  /**
   * Move assignment.
   */
  ContextPtr& operator=(ContextPtr&& o) {
    if (o.memo) {
      if (o.memo != context) {
        memo = std::move(o.memo);
      } else {
        memo = nullptr;
      }
    } else {
      if (o.context != context) {
        memo = std::move(o.context);
      } else {
        memo = nullptr;
      }
    }
    return *this;
  }

  /**
   * Get the raw pointer.
   */
  Memo* get() const {
    return memo.get() ? memo.get() : context.get();
  }

  /**
   * Get the context.
   */
  Memo* getContext() const {
    return context.get();
  }

  /**
   * Dereference.
   */
  Memo& operator*() const {
    return *get();
  }

  /**
   * Member access.
   */
  Memo* operator->() const {
    return get();
  }

  /**
   * Equal comparison.
   */
  bool operator==(const ContextPtr& o) const {
    return get() == o.get();
  }

  /**
   * Not equal comparison.
   */
  bool operator!=(const ContextPtr& o) const {
    return get() != o.get();
  }

  /**
   * Is the pointer not null?
   */
  operator bool() const {
    return get() != nullptr;
  }

private:
  /**
   * The memo, if it is difference to context, otherwise `nullptr`.
   */
  SharedPtr<LazyMemo> memo;

  /**
   * The owning context. This is the context in which the pointer itself was
   * created. For a member variable, it is the same as the context of the
   * containing object.
   */
  WeakPtr<LazyMemo> context;
};
}
<commit_msg>WeakPtr to InitPtr in ContextPtr for performance improvement.<commit_after>/**
 * @file
 */
#pragma once

#include "libbirch/SharedPtr.hpp"
#include "libbirch/InitPtr.hpp"
#include "libbirch/Memo.hpp"

namespace libbirch {
/**
 * Shared or weak pointer to a Memo, according to context. This is used by
 * LazyPtr for its memo field. It records the context of the
 * pointer: whether it is part of a member variable or not, and keeps a
 * weak or shared pointer to the Memo according to that context.
 *
 * @ingroup libbirch
 */
class ContextPtr {
public:
  /**
   * Default constructor.
   */
  ContextPtr() :
      context(currentContext) {
    //
  }

  /**
   * Value constructor.
   */
  ContextPtr(Memo* memo) :
      memo(memo == currentContext ? nullptr : memo),
      context(currentContext) {
    //
  }

  /**
   * Copy constructor.
   */
  ContextPtr(const ContextPtr& o) :
      memo(nullptr),
      context(currentContext) {
    if (o.memo) {
      if (o.memo != context) {
        memo = o.memo;
      }
    } else {
      if (o.context != context) {
        memo = o.context;
      }
    }
  }

  /**
   * Move constructor.
   */
  ContextPtr(ContextPtr&& o) :
      memo(nullptr),
      context(currentContext) {
    if (o.memo) {
      if (o.memo != context) {
        memo = std::move(o.memo);
      }
    } else {
      if (o.context != context) {
        memo = std::move(o.context);
      }
    }
  }

  /**
   * Value assignment.
   */
  ContextPtr& operator=(Memo* memo) {
    this->memo = (memo == context.get()) ? nullptr : memo;
    return *this;
  }

  /**
   * Copy assignment.
   */
  ContextPtr& operator=(const ContextPtr& o) {
    if (o.memo) {
      if (o.memo != context) {
        memo = o.memo;
      } else {
        memo = nullptr;
      }
    } else {
      if (o.context != context) {
        memo = o.context;
      } else {
        memo = nullptr;
      }
    }
    return *this;
  }

  /**
   * Move assignment.
   */
  ContextPtr& operator=(ContextPtr&& o) {
    if (o.memo) {
      if (o.memo != context) {
        memo = std::move(o.memo);
      } else {
        memo = nullptr;
      }
    } else {
      if (o.context != context) {
        memo = std::move(o.context);
      } else {
        memo = nullptr;
      }
    }
    return *this;
  }

  /**
   * Get the raw pointer.
   */
  Memo* get() const {
    return memo.get() ? memo.get() : context.get();
  }

  /**
   * Get the context.
   */
  Memo* getContext() const {
    return context.get();
  }

  /**
   * Dereference.
   */
  Memo& operator*() const {
    return *get();
  }

  /**
   * Member access.
   */
  Memo* operator->() const {
    return get();
  }

  /**
   * Equal comparison.
   */
  bool operator==(const ContextPtr& o) const {
    return get() == o.get();
  }

  /**
   * Not equal comparison.
   */
  bool operator!=(const ContextPtr& o) const {
    return get() != o.get();
  }

  /**
   * Is the pointer not null?
   */
  operator bool() const {
    return get() != nullptr;
  }

private:
  /**
   * The memo, if it is difference to context, otherwise `nullptr`.
   */
  SharedPtr<LazyMemo> memo;

  /**
   * The owning context. This is the context in which the pointer itself was
   * created. For a member variable, it is the same as the context of the
   * containing object. Because the containing object holds a WeakPtr to the
   * same object, use of an InitPtr is sufficient here.
   */
  InitPtr<LazyMemo> context;
};
}
<|endoftext|>


<commit_before>// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "base/logging.h"
#include "views/window/client_view.h"
#if defined(OS_LINUX)
#include "chrome/views/window/hit_test.h"
#endif
#include "views/window/window.h"
#include "views/window/window_delegate.h"

namespace views {

///////////////////////////////////////////////////////////////////////////////
// ClientView, public:

ClientView::ClientView(Window* window, View* contents_view)
    : window_(window),
      contents_view_(contents_view) {
}

int ClientView::NonClientHitTest(const gfx::Point& point) {
  return bounds().Contains(point) ? HTCLIENT : HTNOWHERE;
}

void ClientView::WindowClosing() {
  window_->GetDelegate()->WindowClosing();
}

///////////////////////////////////////////////////////////////////////////////
// ClientView, View overrides:

gfx::Size ClientView::GetPreferredSize() {
  // |contents_view_| is allowed to be NULL up until the point where this view
  // is attached to a Container.
  if (contents_view_)
    return contents_view_->GetPreferredSize();
  return gfx::Size();
}

void ClientView::Layout() {
  // |contents_view_| is allowed to be NULL up until the point where this view
  // is attached to a Container.
  if (contents_view_)
    contents_view_->SetBounds(0, 0, width(), height());
}

void ClientView::ViewHierarchyChanged(bool is_add, View* parent, View* child) {
  if (is_add && child == this) {
    DCHECK(GetWidget());
    DCHECK(contents_view_); // |contents_view_| must be valid now!
    AddChildView(contents_view_);
  }
}

void ClientView::DidChangeBounds(const gfx::Rect& previous,
                                 const gfx::Rect& current) {
  // Overridden to do nothing. The NonClientView manually calls Layout on the
  // ClientView when it is itself laid out, see comment in
  // NonClientView::Layout.
}

}  // namespace views
<commit_msg>fix checkdeps bustage<commit_after>// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "base/logging.h"
#include "views/window/client_view.h"
#if defined(OS_LINUX)
#include "views/window/hit_test.h"
#endif
#include "views/window/window.h"
#include "views/window/window_delegate.h"

namespace views {

///////////////////////////////////////////////////////////////////////////////
// ClientView, public:

ClientView::ClientView(Window* window, View* contents_view)
    : window_(window),
      contents_view_(contents_view) {
}

int ClientView::NonClientHitTest(const gfx::Point& point) {
  return bounds().Contains(point) ? HTCLIENT : HTNOWHERE;
}

void ClientView::WindowClosing() {
  window_->GetDelegate()->WindowClosing();
}

///////////////////////////////////////////////////////////////////////////////
// ClientView, View overrides:

gfx::Size ClientView::GetPreferredSize() {
  // |contents_view_| is allowed to be NULL up until the point where this view
  // is attached to a Container.
  if (contents_view_)
    return contents_view_->GetPreferredSize();
  return gfx::Size();
}

void ClientView::Layout() {
  // |contents_view_| is allowed to be NULL up until the point where this view
  // is attached to a Container.
  if (contents_view_)
    contents_view_->SetBounds(0, 0, width(), height());
}

void ClientView::ViewHierarchyChanged(bool is_add, View* parent, View* child) {
  if (is_add && child == this) {
    DCHECK(GetWidget());
    DCHECK(contents_view_); // |contents_view_| must be valid now!
    AddChildView(contents_view_);
  }
}

void ClientView::DidChangeBounds(const gfx::Rect& previous,
                                 const gfx::Rect& current) {
  // Overridden to do nothing. The NonClientView manually calls Layout on the
  // ClientView when it is itself laid out, see comment in
  // NonClientView::Layout.
}

}  // namespace views
<|endoftext|>