<commit_before>/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (qt-info@nokia.com)
**
**
** GNU Lesser General Public License Usage
**
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this file.
** Please review the following information to ensure the GNU Lesser General
** Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** Other Usage
**
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**************************************************************************/

#include "qmlprojectrunconfiguration.h"
#include "qmlproject.h"
#include "qmlprojectmanagerconstants.h"
#include "qmlprojectrunconfigurationwidget.h"
#include <coreplugin/mimedatabase.h>
#include <coreplugin/editormanager/editormanager.h>
#include <coreplugin/editormanager/ieditor.h>
#include <coreplugin/icore.h>
#include <projectexplorer/target.h>
#include <utils/qtcassert.h>
#include <utils/qtcprocess.h>
#include <qtsupport/qtprofileinformation.h>
#include <qtsupport/qtoutputformatter.h>
#include <qtsupport/qtsupportconstants.h>

#ifdef Q_OS_WIN
#include <utils/winutils.h>
#endif

using Core::EditorManager;
using Core::ICore;
using Core::IEditor;

using namespace QmlProjectManager::Internal;

namespace QmlProjectManager {

const char * const M_CURRENT_FILE = "CurrentFile";

QmlProjectRunConfiguration::QmlProjectRunConfiguration(ProjectExplorer::Target *parent) :
    ProjectExplorer::RunConfiguration(parent, Core::Id(Constants::QML_RC_ID)),
    m_scriptFile(M_CURRENT_FILE),
    m_isEnabled(false)
{
    ctor();
}

QmlProjectRunConfiguration::QmlProjectRunConfiguration(ProjectExplorer::Target *parent,
                                                       QmlProjectRunConfiguration *source) :
    ProjectExplorer::RunConfiguration(parent, source),
    m_scriptFile(source->m_scriptFile),
    m_qmlViewerArgs(source->m_qmlViewerArgs),
    m_isEnabled(source->m_isEnabled),
    m_userEnvironmentChanges(source->m_userEnvironmentChanges)
{
    ctor();
}

bool QmlProjectRunConfiguration::isEnabled() const
{
    return m_isEnabled;
}

QString QmlProjectRunConfiguration::disabledReason() const
{
    if (!m_isEnabled)
        return tr("No qmlviewer or qmlobserver found.");
    return QString();
}

void QmlProjectRunConfiguration::ctor()
{
    // reset default settings in constructor
    debuggerAspect()->setUseCppDebugger(false);
    debuggerAspect()->setUseQmlDebugger(true);

    EditorManager *em = Core::EditorManager::instance();
    connect(em, SIGNAL(currentEditorChanged(Core::IEditor*)),
            this, SLOT(changeCurrentFile(Core::IEditor*)));

    connect(target(), SIGNAL(profileChanged()),
            this, SLOT(updateEnabled()));

    setDisplayName(tr("QML Viewer", "QMLRunConfiguration display name."));
}

QmlProjectRunConfiguration::~QmlProjectRunConfiguration()
{
}

QString QmlProjectRunConfiguration::viewerPath() const
{
    QtSupport::BaseQtVersion *version = qtVersion();
    if (!version)
        return QString();
    else
        return version->qmlviewerCommand();
}

QString QmlProjectRunConfiguration::observerPath() const
{
    QtSupport::BaseQtVersion *version = qtVersion();
    if (!version) {
        return QString();
    } else {
        if (!version->needsQmlDebuggingLibrary())
            return version->qmlviewerCommand();
        return version->qmlObserverTool();
    }
}

QString QmlProjectRunConfiguration::viewerArguments() const
{
    // arguments in .user file
    QString args = m_qmlViewerArgs;

    // arguments from .qmlproject file
    QmlProject *project = qobject_cast<QmlProject *>(target()->project());
    if (!project)
        return args;
    foreach (const QString &importPath, project->importPaths()) {
        Utils::QtcProcess::addArg(&args, "-I");
        Utils::QtcProcess::addArg(&args, importPath);
    }

    QString s = mainScript();
    if (!s.isEmpty()) {
        s = canonicalCapsPath(s);
        Utils::QtcProcess::addArg(&args, s);
    }
    return args;
}

QString QmlProjectRunConfiguration::workingDirectory() const
{
    QFileInfo projectFile(target()->project()->document()->fileName());
    return canonicalCapsPath(projectFile.absolutePath());
}

/* QtDeclarative checks explicitly that the capitalization for any URL / path
   is exactly like the capitalization on disk.*/
QString QmlProjectRunConfiguration::canonicalCapsPath(const QString &fileName)
{
    QString canonicalPath = QFileInfo(fileName).canonicalFilePath();

#if defined(Q_OS_WIN)
    canonicalPath = Utils::normalizePathName(canonicalPath);
#endif

    return canonicalPath;
}

QtSupport::BaseQtVersion *QmlProjectRunConfiguration::qtVersion() const
{
    return QtSupport::QtProfileInformation::qtVersion(target()->profile());
}

QWidget *QmlProjectRunConfiguration::createConfigurationWidget()
{
    QTC_ASSERT(m_configurationWidget.isNull(), return m_configurationWidget.data());
    m_configurationWidget = new QmlProjectRunConfigurationWidget(this);
    return m_configurationWidget.data();
}

Utils::OutputFormatter *QmlProjectRunConfiguration::createOutputFormatter() const
{
    return new QtSupport::QtOutputFormatter(target()->project());
}

QmlProjectRunConfiguration::MainScriptSource QmlProjectRunConfiguration::mainScriptSource() const
{
    QmlProject *project = qobject_cast<QmlProject *>(target()->project());
    if (!project)
        return FileInEditor;
    if (!project->mainFile().isEmpty())
        return FileInProjectFile;
    if (!m_mainScriptFilename.isEmpty())
        return FileInSettings;
    return FileInEditor;
}

/**
  Returns absolute path to main script file.
  */
QString QmlProjectRunConfiguration::mainScript() const
{
    QmlProject *project = qobject_cast<QmlProject *>(target()->project());
    if (!project)
        return m_currentFileFilename;
    if (!project->mainFile().isEmpty()) {
        const QString pathInProject = project->mainFile();
        if (QFileInfo(pathInProject).isAbsolute())
            return pathInProject;
        else
            return project->projectDir().absoluteFilePath(pathInProject);
    }

    if (!m_mainScriptFilename.isEmpty())
        return m_mainScriptFilename;

    return m_currentFileFilename;
}

void QmlProjectRunConfiguration::setScriptSource(MainScriptSource source,
                                                 const QString &settingsPath)
{
    if (source == FileInEditor) {
        m_scriptFile = M_CURRENT_FILE;
        m_mainScriptFilename.clear();
    } else if (source == FileInProjectFile) {
        m_scriptFile.clear();
        m_mainScriptFilename.clear();
    } else { // FileInSettings
        m_scriptFile = settingsPath;
        m_mainScriptFilename
                = target()->project()->projectDirectory() + QLatin1Char('/') + m_scriptFile;
    }
    updateEnabled();
    if (m_configurationWidget)
        m_configurationWidget.data()->updateFileComboBox();
}

Utils::Environment QmlProjectRunConfiguration::environment() const
{
    Utils::Environment env = baseEnvironment();
    env.modify(userEnvironmentChanges());
    return env;
}

ProjectExplorer::Abi QmlProjectRunConfiguration::abi() const
{
    ProjectExplorer::Abi hostAbi = ProjectExplorer::Abi::hostAbi();
    return ProjectExplorer::Abi(hostAbi.architecture(), hostAbi.os(), hostAbi.osFlavor(),
                                ProjectExplorer::Abi::RuntimeQmlFormat, hostAbi.wordWidth());
}

QVariantMap QmlProjectRunConfiguration::toMap() const
{
    QVariantMap map(ProjectExplorer::RunConfiguration::toMap());

    map.insert(QLatin1String(Constants::QML_VIEWER_ARGUMENTS_KEY), m_qmlViewerArgs);
    map.insert(QLatin1String(Constants::QML_MAINSCRIPT_KEY),  m_scriptFile);
    map.insert(QLatin1String(Constants::USER_ENVIRONMENT_CHANGES_KEY),
               Utils::EnvironmentItem::toStringList(m_userEnvironmentChanges));
    return map;
}

bool QmlProjectRunConfiguration::fromMap(const QVariantMap &map)
{
    m_qmlViewerArgs = map.value(QLatin1String(Constants::QML_VIEWER_ARGUMENTS_KEY)).toString();
    m_scriptFile = map.value(QLatin1String(Constants::QML_MAINSCRIPT_KEY), M_CURRENT_FILE).toString();
    m_userEnvironmentChanges = Utils::EnvironmentItem::fromStringList(
                map.value(QLatin1String(Constants::USER_ENVIRONMENT_CHANGES_KEY)).toStringList());

    if (m_scriptFile == M_CURRENT_FILE)
        setScriptSource(FileInEditor);
    else if (m_scriptFile.isEmpty())
        setScriptSource(FileInProjectFile);
    else
        setScriptSource(FileInSettings, m_scriptFile);

    return RunConfiguration::fromMap(map);
}

void QmlProjectRunConfiguration::changeCurrentFile(Core::IEditor *editor)
{
    if (editor)
        m_currentFileFilename = editor->document()->fileName();
    updateEnabled();
}

void QmlProjectRunConfiguration::updateEnabled()
{
    bool qmlFileFound = false;
    if (mainScriptSource() == FileInEditor) {
        Core::IEditor *editor = Core::EditorManager::currentEditor();
        Core::MimeDatabase *db = ICore::mimeDatabase();
        if (editor) {
            m_currentFileFilename = editor->document()->fileName();
            if (db->findByFile(mainScript()).type() == QLatin1String("application/x-qml"))
                qmlFileFound = true;
        }
        if (!editor
                || db->findByFile(mainScript()).type() == QLatin1String("application/x-qmlproject")) {
            // find a qml file with lowercase filename. This is slow, but only done
            // in initialization/other border cases.
            foreach (const QString &filename, target()->project()->files(ProjectExplorer::Project::AllFiles)) {
                const QFileInfo fi(filename);

                if (!filename.isEmpty() && fi.baseName()[0].isLower()
                        && db->findByFile(fi).type() == QLatin1String("application/x-qml"))
                {
                    m_currentFileFilename = filename;
                    qmlFileFound = true;
                    break;
                }

            }
        }
    } else { // use default one
        qmlFileFound = !mainScript().isEmpty();
    }

    bool newValue = (QFileInfo(viewerPath()).exists()
                     || QFileInfo(observerPath()).exists()) && qmlFileFound;

    // Always emit change signal to force reevaluation of run/debug buttons
    m_isEnabled = newValue;
    emit enabledChanged();
}

bool QmlProjectRunConfiguration::isValidVersion(QtSupport::BaseQtVersion *version)
{
    if (version
            && (version->type() == QtSupport::Constants::DESKTOPQT
                || version->type() == QtSupport::Constants::SIMULATORQT)
            && !version->qmlviewerCommand().isEmpty()) {
        return true;
    }
    return false;
}

Utils::Environment QmlProjectRunConfiguration::baseEnvironment() const
{
    Utils::Environment env;
    if (qtVersion())
        env = qtVersion()->qmlToolsEnvironment();
    return env;
}

void QmlProjectRunConfiguration::setUserEnvironmentChanges(const QList<Utils::EnvironmentItem> &diff)
{
    if (m_userEnvironmentChanges != diff) {
        m_userEnvironmentChanges = diff;
        if (m_configurationWidget)
            m_configurationWidget.data()->userEnvironmentChangesChanged();
    }
}

QList<Utils::EnvironmentItem> QmlProjectRunConfiguration::userEnvironmentChanges() const
{
    return m_userEnvironmentChanges;
}

} // namespace QmlProjectManager
<commit_msg>QmlProject: static_cast not qobject_cast<commit_after>/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (qt-info@nokia.com)
**
**
** GNU Lesser General Public License Usage
**
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this file.
** Please review the following information to ensure the GNU Lesser General
** Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** Other Usage
**
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**************************************************************************/

#include "qmlprojectrunconfiguration.h"
#include "qmlproject.h"
#include "qmlprojectmanagerconstants.h"
#include "qmlprojectrunconfigurationwidget.h"
#include <coreplugin/mimedatabase.h>
#include <coreplugin/editormanager/editormanager.h>
#include <coreplugin/editormanager/ieditor.h>
#include <coreplugin/icore.h>
#include <projectexplorer/target.h>
#include <utils/qtcassert.h>
#include <utils/qtcprocess.h>
#include <qtsupport/qtprofileinformation.h>
#include <qtsupport/qtoutputformatter.h>
#include <qtsupport/qtsupportconstants.h>

#ifdef Q_OS_WIN
#include <utils/winutils.h>
#endif

using Core::EditorManager;
using Core::ICore;
using Core::IEditor;

using namespace QmlProjectManager::Internal;

namespace QmlProjectManager {

const char * const M_CURRENT_FILE = "CurrentFile";

QmlProjectRunConfiguration::QmlProjectRunConfiguration(ProjectExplorer::Target *parent) :
    ProjectExplorer::RunConfiguration(parent, Core::Id(Constants::QML_RC_ID)),
    m_scriptFile(M_CURRENT_FILE),
    m_isEnabled(false)
{
    ctor();
}

QmlProjectRunConfiguration::QmlProjectRunConfiguration(ProjectExplorer::Target *parent,
                                                       QmlProjectRunConfiguration *source) :
    ProjectExplorer::RunConfiguration(parent, source),
    m_scriptFile(source->m_scriptFile),
    m_qmlViewerArgs(source->m_qmlViewerArgs),
    m_isEnabled(source->m_isEnabled),
    m_userEnvironmentChanges(source->m_userEnvironmentChanges)
{
    ctor();
}

bool QmlProjectRunConfiguration::isEnabled() const
{
    return m_isEnabled;
}

QString QmlProjectRunConfiguration::disabledReason() const
{
    if (!m_isEnabled)
        return tr("No qmlviewer or qmlobserver found.");
    return QString();
}

void QmlProjectRunConfiguration::ctor()
{
    // reset default settings in constructor
    debuggerAspect()->setUseCppDebugger(false);
    debuggerAspect()->setUseQmlDebugger(true);

    EditorManager *em = Core::EditorManager::instance();
    connect(em, SIGNAL(currentEditorChanged(Core::IEditor*)),
            this, SLOT(changeCurrentFile(Core::IEditor*)));

    connect(target(), SIGNAL(profileChanged()),
            this, SLOT(updateEnabled()));

    setDisplayName(tr("QML Viewer", "QMLRunConfiguration display name."));
}

QmlProjectRunConfiguration::~QmlProjectRunConfiguration()
{
}

QString QmlProjectRunConfiguration::viewerPath() const
{
    QtSupport::BaseQtVersion *version = qtVersion();
    if (!version)
        return QString();
    else
        return version->qmlviewerCommand();
}

QString QmlProjectRunConfiguration::observerPath() const
{
    QtSupport::BaseQtVersion *version = qtVersion();
    if (!version) {
        return QString();
    } else {
        if (!version->needsQmlDebuggingLibrary())
            return version->qmlviewerCommand();
        return version->qmlObserverTool();
    }
}

QString QmlProjectRunConfiguration::viewerArguments() const
{
    // arguments in .user file
    QString args = m_qmlViewerArgs;

    // arguments from .qmlproject file
    QmlProject *project = static_cast<QmlProject *>(target()->project());
    foreach (const QString &importPath, project->importPaths()) {
        Utils::QtcProcess::addArg(&args, "-I");
        Utils::QtcProcess::addArg(&args, importPath);
    }

    QString s = mainScript();
    if (!s.isEmpty()) {
        s = canonicalCapsPath(s);
        Utils::QtcProcess::addArg(&args, s);
    }
    return args;
}

QString QmlProjectRunConfiguration::workingDirectory() const
{
    QFileInfo projectFile(target()->project()->document()->fileName());
    return canonicalCapsPath(projectFile.absolutePath());
}

/* QtDeclarative checks explicitly that the capitalization for any URL / path
   is exactly like the capitalization on disk.*/
QString QmlProjectRunConfiguration::canonicalCapsPath(const QString &fileName)
{
    QString canonicalPath = QFileInfo(fileName).canonicalFilePath();

#if defined(Q_OS_WIN)
    canonicalPath = Utils::normalizePathName(canonicalPath);
#endif

    return canonicalPath;
}

QtSupport::BaseQtVersion *QmlProjectRunConfiguration::qtVersion() const
{
    return QtSupport::QtProfileInformation::qtVersion(target()->profile());
}

QWidget *QmlProjectRunConfiguration::createConfigurationWidget()
{
    QTC_ASSERT(m_configurationWidget.isNull(), return m_configurationWidget.data());
    m_configurationWidget = new QmlProjectRunConfigurationWidget(this);
    return m_configurationWidget.data();
}

Utils::OutputFormatter *QmlProjectRunConfiguration::createOutputFormatter() const
{
    return new QtSupport::QtOutputFormatter(target()->project());
}

QmlProjectRunConfiguration::MainScriptSource QmlProjectRunConfiguration::mainScriptSource() const
{
    QmlProject *project = static_cast<QmlProject *>(target()->project());
    if (!project->mainFile().isEmpty())
        return FileInProjectFile;
    if (!m_mainScriptFilename.isEmpty())
        return FileInSettings;
    return FileInEditor;
}

/**
  Returns absolute path to main script file.
  */
QString QmlProjectRunConfiguration::mainScript() const
{
    QmlProject *project = qobject_cast<QmlProject *>(target()->project());
    if (!project)
        return m_currentFileFilename;
    if (!project->mainFile().isEmpty()) {
        const QString pathInProject = project->mainFile();
        if (QFileInfo(pathInProject).isAbsolute())
            return pathInProject;
        else
            return project->projectDir().absoluteFilePath(pathInProject);
    }

    if (!m_mainScriptFilename.isEmpty())
        return m_mainScriptFilename;

    return m_currentFileFilename;
}

void QmlProjectRunConfiguration::setScriptSource(MainScriptSource source,
                                                 const QString &settingsPath)
{
    if (source == FileInEditor) {
        m_scriptFile = M_CURRENT_FILE;
        m_mainScriptFilename.clear();
    } else if (source == FileInProjectFile) {
        m_scriptFile.clear();
        m_mainScriptFilename.clear();
    } else { // FileInSettings
        m_scriptFile = settingsPath;
        m_mainScriptFilename
                = target()->project()->projectDirectory() + QLatin1Char('/') + m_scriptFile;
    }
    updateEnabled();
    if (m_configurationWidget)
        m_configurationWidget.data()->updateFileComboBox();
}

Utils::Environment QmlProjectRunConfiguration::environment() const
{
    Utils::Environment env = baseEnvironment();
    env.modify(userEnvironmentChanges());
    return env;
}

ProjectExplorer::Abi QmlProjectRunConfiguration::abi() const
{
    ProjectExplorer::Abi hostAbi = ProjectExplorer::Abi::hostAbi();
    return ProjectExplorer::Abi(hostAbi.architecture(), hostAbi.os(), hostAbi.osFlavor(),
                                ProjectExplorer::Abi::RuntimeQmlFormat, hostAbi.wordWidth());
}

QVariantMap QmlProjectRunConfiguration::toMap() const
{
    QVariantMap map(ProjectExplorer::RunConfiguration::toMap());

    map.insert(QLatin1String(Constants::QML_VIEWER_ARGUMENTS_KEY), m_qmlViewerArgs);
    map.insert(QLatin1String(Constants::QML_MAINSCRIPT_KEY),  m_scriptFile);
    map.insert(QLatin1String(Constants::USER_ENVIRONMENT_CHANGES_KEY),
               Utils::EnvironmentItem::toStringList(m_userEnvironmentChanges));
    return map;
}

bool QmlProjectRunConfiguration::fromMap(const QVariantMap &map)
{
    m_qmlViewerArgs = map.value(QLatin1String(Constants::QML_VIEWER_ARGUMENTS_KEY)).toString();
    m_scriptFile = map.value(QLatin1String(Constants::QML_MAINSCRIPT_KEY), M_CURRENT_FILE).toString();
    m_userEnvironmentChanges = Utils::EnvironmentItem::fromStringList(
                map.value(QLatin1String(Constants::USER_ENVIRONMENT_CHANGES_KEY)).toStringList());

    if (m_scriptFile == M_CURRENT_FILE)
        setScriptSource(FileInEditor);
    else if (m_scriptFile.isEmpty())
        setScriptSource(FileInProjectFile);
    else
        setScriptSource(FileInSettings, m_scriptFile);

    return RunConfiguration::fromMap(map);
}

void QmlProjectRunConfiguration::changeCurrentFile(Core::IEditor *editor)
{
    if (editor)
        m_currentFileFilename = editor->document()->fileName();
    updateEnabled();
}

void QmlProjectRunConfiguration::updateEnabled()
{
    bool qmlFileFound = false;
    if (mainScriptSource() == FileInEditor) {
        Core::IEditor *editor = Core::EditorManager::currentEditor();
        Core::MimeDatabase *db = ICore::mimeDatabase();
        if (editor) {
            m_currentFileFilename = editor->document()->fileName();
            if (db->findByFile(mainScript()).type() == QLatin1String("application/x-qml"))
                qmlFileFound = true;
        }
        if (!editor
                || db->findByFile(mainScript()).type() == QLatin1String("application/x-qmlproject")) {
            // find a qml file with lowercase filename. This is slow, but only done
            // in initialization/other border cases.
            foreach (const QString &filename, target()->project()->files(ProjectExplorer::Project::AllFiles)) {
                const QFileInfo fi(filename);

                if (!filename.isEmpty() && fi.baseName()[0].isLower()
                        && db->findByFile(fi).type() == QLatin1String("application/x-qml"))
                {
                    m_currentFileFilename = filename;
                    qmlFileFound = true;
                    break;
                }

            }
        }
    } else { // use default one
        qmlFileFound = !mainScript().isEmpty();
    }

    bool newValue = (QFileInfo(viewerPath()).exists()
                     || QFileInfo(observerPath()).exists()) && qmlFileFound;

    // Always emit change signal to force reevaluation of run/debug buttons
    m_isEnabled = newValue;
    emit enabledChanged();
}

bool QmlProjectRunConfiguration::isValidVersion(QtSupport::BaseQtVersion *version)
{
    if (version
            && (version->type() == QtSupport::Constants::DESKTOPQT
                || version->type() == QtSupport::Constants::SIMULATORQT)
            && !version->qmlviewerCommand().isEmpty()) {
        return true;
    }
    return false;
}

Utils::Environment QmlProjectRunConfiguration::baseEnvironment() const
{
    Utils::Environment env;
    if (qtVersion())
        env = qtVersion()->qmlToolsEnvironment();
    return env;
}

void QmlProjectRunConfiguration::setUserEnvironmentChanges(const QList<Utils::EnvironmentItem> &diff)
{
    if (m_userEnvironmentChanges != diff) {
        m_userEnvironmentChanges = diff;
        if (m_configurationWidget)
            m_configurationWidget.data()->userEnvironmentChangesChanged();
    }
}

QList<Utils::EnvironmentItem> QmlProjectRunConfiguration::userEnvironmentChanges() const
{
    return m_userEnvironmentChanges;
}

} // namespace QmlProjectManager
<|endoftext|>


<commit_before>/*
 * Copyright (C) 2015 Cloudius Systems, Ltd.
 */

#pragma once

#include "core/reactor.hh"
#include "core/iostream.hh"
#include "core/distributed.hh"
#include "core/print.hh"
#include "core/sstring.hh"
#include "net/api.hh"
#include "util/serialization.hh"
#include "gms/inet_address.hh"
#include "rpc/rpc.hh"
#include <unordered_map>
#include "db/config.hh"
#include "frozen_mutation.hh"
#include "db/serializer.hh"

namespace net {

/* All verb handler identifiers */
enum class messaging_verb : int32_t {
    MUTATION,
    MUTATION_DONE,
    BINARY, // Deprecated
    READ_REPAIR,
    READ,
    REQUEST_RESPONSE, // client-initiated reads and writes
    STREAM_INITIATE, // Deprecated
    STREAM_INITIATE_DONE, // Deprecated
    STREAM_REPLY, // Deprecated
    STREAM_REQUEST, // Deprecated
    RANGE_SLICE,
    BOOTSTRAP_TOKEN, // Deprecated
    TREE_REQUEST, // Deprecated
    TREE_RESPONSE, // Deprecated
    JOIN, // Deprecated
    GOSSIP_DIGEST_SYN,
    GOSSIP_DIGEST_ACK,
    GOSSIP_DIGEST_ACK2,
    DEFINITIONS_ANNOUNCE, // Deprecated
    DEFINITIONS_UPDATE,
    TRUNCATE,
    SCHEMA_CHECK,
    INDEX_SCAN, // Deprecated
    REPLICATION_FINISHED,
    INTERNAL_RESPONSE, // responses to internal calls
    COUNTER_MUTATION,
    STREAMING_REPAIR_REQUEST, // Deprecated
    STREAMING_REPAIR_RESPONSE, // Deprecated
    SNAPSHOT, // Similar to nt snapshot
    MIGRATION_REQUEST,
    GOSSIP_SHUTDOWN,
    _TRACE,
    ECHO,
    REPAIR_MESSAGE,
    PAXOS_PREPARE,
    PAXOS_PROPOSE,
    PAXOS_COMMIT,
    PAGED_RANGE,
    UNUSED_1,
    UNUSED_2,
    UNUSED_3,
};

} // namespace net

namespace std {
template <>
class hash<net::messaging_verb> {
public:
    size_t operator()(const net::messaging_verb& x) const {
        return hash<int32_t>()(int32_t(x));
    }
};
} // namespace std

namespace net {

// NOTE: operator(input_stream<char>&, T&) takes a reference to uninitialized
//       T object and should use placement new in case T is non POD
struct serializer {
    // For integer type
    template<typename T>
    inline auto operator()(output_stream<char>& out, T&& v, std::enable_if_t<std::is_integral<std::remove_reference_t<T>>::value, void*> = nullptr) {
        auto v_ = net::hton(v);
        return out.write(reinterpret_cast<const char*>(&v_), sizeof(T));
    }
    template<typename T>
    inline auto operator()(input_stream<char>& in, T& v, std::enable_if_t<std::is_integral<T>::value, void*> = nullptr) {
        return in.read_exactly(sizeof(v)).then([&v] (temporary_buffer<char> buf) mutable {
            if (buf.size() != sizeof(v)) {
                throw rpc::closed_error();
            }
            v = net::ntoh(*reinterpret_cast<const net::packed<T>*>(buf.get()));
        });
    }

    // For vectors
    template<typename T>
    inline auto operator()(output_stream<char>& out, std::vector<T>& v) {
        return operator()(out, v.size()).then([&out, &v, this] {
            return do_for_each(v.begin(), v.end(), [&out, this] (T& e) {
                return operator()(out, e);
            });
        });
    }
    template<typename T>
    inline auto operator()(input_stream<char>& in, std::vector<T>& v) {
        using size_type = typename  std::vector<T>::size_type;
        return in.read_exactly(sizeof(size_type)).then([&v, &in, this] (temporary_buffer<char> buf) {
            if (buf.size() != sizeof(size_type)) {
                throw rpc::closed_error();
            }
            size_type c = net::ntoh(*reinterpret_cast<const net::packed<size_type>*>(buf.get()));
            new (&v) std::vector<T>;
            v.reserve(c);
            union U {
                U(){}
                ~U(){}
                T v;
            };
            return do_until([c] () mutable {return !c--;}, [&v, &in, u = U(), this] () mutable {
                return operator()(in, u.v).then([&u, &v] {
                    v.emplace_back(std::move(u.v));
                });
            });
        });
    }

    // For messaging_verb
    inline auto operator()(output_stream<char>& out, messaging_verb& v) {
        bytes b(bytes::initialized_later(), sizeof(v));
        auto _out = b.begin();
        serialize_int32(_out, int32_t(v));
        return out.write(reinterpret_cast<const char*>(b.c_str()), sizeof(v));
    }
    inline auto operator()(input_stream<char>& in, messaging_verb& v) {
        return in.read_exactly(sizeof(v)).then([&v] (temporary_buffer<char> buf) mutable {
            if (buf.size() != sizeof(v)) {
                throw rpc::closed_error();
            }
            bytes_view bv(reinterpret_cast<const int8_t*>(buf.get()), sizeof(v));
            v = messaging_verb(read_simple<int32_t>(bv));
        });
    }

    // For sstring
    inline auto operator()(output_stream<char>& out, sstring& v) {
        auto serialize_string_size = serialize_int16_size + v.size();
        auto sz = serialize_int16_size + serialize_string_size;
        bytes b(bytes::initialized_later(), sz);
        auto _out = b.begin();
        serialize_int16(_out, serialize_string_size);
        serialize_string(_out, v);
        return out.write(reinterpret_cast<const char*>(b.c_str()), sz);
    }
    inline auto operator()(input_stream<char>& in, sstring& v) {
        return in.read_exactly(serialize_int16_size).then([&in, &v] (temporary_buffer<char> buf) mutable {
            if (buf.size() != serialize_int16_size) {
                throw rpc::closed_error();
            }
            size_t serialize_string_size = net::ntoh(*reinterpret_cast<const net::packed<int16_t>*>(buf.get()));
            return in.read_exactly(serialize_string_size).then([serialize_string_size, &v]
                (temporary_buffer<char> buf) mutable {
                if (buf.size() != serialize_string_size) {
                    throw rpc::closed_error();
                }
                bytes_view bv(reinterpret_cast<const int8_t*>(buf.get()), serialize_string_size);
                new (&v) sstring(read_simple_short_string(bv));
                return make_ready_future<>();
            });
        });
    }

    // For frozen_mutation
    inline auto operator()(output_stream<char>& out, const frozen_mutation& v) {
        db::frozen_mutation_serializer s(v);
        uint32_t sz = s.size() + data_output::serialized_size(sz);
        bytes b(bytes::initialized_later(), sz);
        data_output o(b);
        o.write<uint32_t>(sz - data_output::serialized_size(sz));
        db::frozen_mutation_serializer::write(o, v);
        return out.write(reinterpret_cast<const char*>(b.c_str()), sz);
    }
    inline auto operator()(input_stream<char>& in, frozen_mutation& v) {
        static auto sz = data_output::serialized_size<uint32_t>();
        return in.read_exactly(sz).then([&v, &in] (temporary_buffer<char> buf) mutable {
            if (buf.size() != sz) {
                throw rpc::closed_error();
            }
            data_input i(bytes_view(reinterpret_cast<const int8_t*>(buf.get()), sz));
            size_t msz = i.read<int32_t>();
            return in.read_exactly(msz).then([&v, msz] (temporary_buffer<char> buf) {
                if (buf.size() != msz) {
                    throw rpc::closed_error();
                }
                data_input i(bytes_view(reinterpret_cast<const int8_t*>(buf.get()), msz));
                new (&v) frozen_mutation(db::frozen_mutation_serializer::read(i));
            });
        });
    }

    // For complex types which have serialize()/deserialize(),  e.g. gms::gossip_digest_syn, gms::gossip_digest_ack2
    template<typename T>
    inline auto operator()(output_stream<char>& out, T&& v, std::enable_if_t<!std::is_integral<std::remove_reference_t<T>>::value &&
                                                                             !std::is_enum<std::remove_reference_t<T>>::value, void*> = nullptr) {
        auto sz = serialize_int32_size + v.serialized_size();
        bytes b(bytes::initialized_later(), sz);
        auto _out = b.begin();
        serialize_int32(_out, int32_t(sz - serialize_int32_size));
        v.serialize(_out);
        return out.write(reinterpret_cast<const char*>(b.c_str()), sz);
    }
    template<typename T>
    inline auto operator()(input_stream<char>& in, T& v, std::enable_if_t<!std::is_integral<T>::value &&
                                                                          !std::is_enum<T>::value, void*> = nullptr) {
        return in.read_exactly(serialize_int32_size).then([&in, &v] (temporary_buffer<char> buf) mutable {
            if (buf.size() != serialize_int32_size) {
                throw rpc::closed_error();
            }
            size_t sz = net::ntoh(*reinterpret_cast<const net::packed<int32_t>*>(buf.get()));
            return in.read_exactly(sz).then([sz, &v] (temporary_buffer<char> buf) mutable {
                if (buf.size() != sz) {
                    throw rpc::closed_error();
                }
                bytes_view bv(reinterpret_cast<const int8_t*>(buf.get()), sz);
                new (&v) T(T::deserialize(bv));
                return make_ready_future<>();
            });
        });
    }
};

class messaging_service {
public:
    struct shard_id {
        gms::inet_address addr;
        uint32_t cpu_id;
        friend inline bool operator==(const shard_id& x, const shard_id& y) {
            return x.addr == y.addr && x.cpu_id == y.cpu_id ;
        }
        friend inline bool operator<(const shard_id& x, const shard_id& y) {
            if (x.addr < y.addr) {
                return true;
            } else if (y.addr < x.addr) {
                return false;
            } else {
                return x.cpu_id < y.cpu_id;
            }
        }
        friend inline std::ostream& operator<<(std::ostream& os, const shard_id& x) {
            return os << x.addr << ":" << x.cpu_id;
        }
        struct hash {
            size_t operator()(const shard_id& id) const {
                return std::hash<uint32_t>()(id.cpu_id) + std::hash<uint32_t>()(id.addr.raw_addr());
            }
        };
    };
    struct shard_info {
        shard_info(std::unique_ptr<rpc::protocol<serializer, messaging_verb>::client>&& client)
            : rpc_client(std::move(client)) {
        }
        std::unique_ptr<rpc::protocol<serializer, messaging_verb>::client> rpc_client;
    };

    void foreach_client(std::function<void(const messaging_service::shard_id& id,
                    const messaging_service::shard_info& info)> f) const {
        for (auto i = _clients.cbegin(); i != _clients.cend(); i++) {
            f(i->first, i->second);
        }
    }
private:
    static constexpr uint16_t _default_port = 7000;
    gms::inet_address _listen_address;
    uint16_t _port;
    rpc::protocol<serializer, messaging_verb> _rpc;
    rpc::protocol<serializer, messaging_verb>::server _server;
    std::unordered_map<shard_id, shard_info, shard_id::hash> _clients;
public:
    messaging_service(gms::inet_address ip = gms::inet_address("0.0.0.0"))
        : _listen_address(ip)
        , _port(_default_port)
        , _rpc(serializer{})
        , _server(_rpc, ipv4_addr{_listen_address.raw_addr(), _port}) {
    }
public:
    uint16_t port() {
        return _port;
    }
    auto listen_address() {
        return _listen_address;
    }
    future<> stop() {
        return make_ready_future<>();
    }

    static auto no_wait() {
        return rpc::no_wait;
    }
public:
    // Register a handler (a callback lambda) for verb
    template <typename Func>
    void register_handler(messaging_verb verb, Func&& func) {
        _rpc.register_handler(verb, std::move(func));
    }

    // Send a message for verb
    template <typename MsgIn, typename... MsgOut>
    auto send_message(messaging_verb verb, shard_id id, MsgOut&&... msg) {
        auto& rpc_client = get_rpc_client(id);
        auto rpc_handler = _rpc.make_client<MsgIn(MsgOut...)>(verb);
        return rpc_handler(rpc_client, std::forward<MsgOut>(msg)...).then_wrapped([this, id] (auto&& f) {
            try {
                if (f.failed()) {
                    f.get();
                    assert(false); // never reached
                }
                return std::move(f);
            } catch(...) {
                // FIXME: we need to distinguish between a transport error and
                // a server error.
                // remove_rpc_client(id);
                throw;
            }
        });
    }

    template <typename... MsgOut>
    auto send_message_oneway(messaging_verb verb, shard_id id, MsgOut&&... msg) {
        return send_message<rpc::no_wait_type>(std::move(verb), std::move(id), std::forward<MsgOut>(msg)...);
    }
private:
    // Return rpc::protocol::client for a shard which is a ip + cpuid pair.
    rpc::protocol<serializer, messaging_verb>::client& get_rpc_client(shard_id id) {
        auto it = _clients.find(id);
        if (it == _clients.end()) {
            auto remote_addr = ipv4_addr(id.addr.raw_addr(), _port);
            auto client = std::make_unique<rpc::protocol<serializer, messaging_verb>::client>(_rpc, remote_addr, ipv4_addr{_listen_address.raw_addr(), 0});
            it = _clients.emplace(id, shard_info(std::move(client))).first;
            return *it->second.rpc_client;
        } else {
            return *it->second.rpc_client;
        }
    }

    void remove_rpc_client(shard_id id) {
        _clients.erase(id);
    }
};

extern distributed<messaging_service> _the_messaging_service;

inline distributed<messaging_service>& get_messaging_service() {
    return _the_messaging_service;
}

inline messaging_service& get_local_messaging_service() {
    return _the_messaging_service.local();
}

future<> init_messaging_service(sstring listen_address, db::config::seed_provider_type seed_provider);
} // namespace net
<commit_msg>Adding dropped messages counter to messaging_service<commit_after>/*
 * Copyright (C) 2015 Cloudius Systems, Ltd.
 */

#pragma once

#include "core/reactor.hh"
#include "core/iostream.hh"
#include "core/distributed.hh"
#include "core/print.hh"
#include "core/sstring.hh"
#include "net/api.hh"
#include "util/serialization.hh"
#include "gms/inet_address.hh"
#include "rpc/rpc.hh"
#include <unordered_map>
#include "db/config.hh"
#include "frozen_mutation.hh"
#include "db/serializer.hh"

namespace net {

/* All verb handler identifiers */
enum class messaging_verb : int32_t {
    MUTATION,
    MUTATION_DONE,
    BINARY, // Deprecated
    READ_REPAIR,
    READ,
    REQUEST_RESPONSE, // client-initiated reads and writes
    STREAM_INITIATE, // Deprecated
    STREAM_INITIATE_DONE, // Deprecated
    STREAM_REPLY, // Deprecated
    STREAM_REQUEST, // Deprecated
    RANGE_SLICE,
    BOOTSTRAP_TOKEN, // Deprecated
    TREE_REQUEST, // Deprecated
    TREE_RESPONSE, // Deprecated
    JOIN, // Deprecated
    GOSSIP_DIGEST_SYN,
    GOSSIP_DIGEST_ACK,
    GOSSIP_DIGEST_ACK2,
    DEFINITIONS_ANNOUNCE, // Deprecated
    DEFINITIONS_UPDATE,
    TRUNCATE,
    SCHEMA_CHECK,
    INDEX_SCAN, // Deprecated
    REPLICATION_FINISHED,
    INTERNAL_RESPONSE, // responses to internal calls
    COUNTER_MUTATION,
    STREAMING_REPAIR_REQUEST, // Deprecated
    STREAMING_REPAIR_RESPONSE, // Deprecated
    SNAPSHOT, // Similar to nt snapshot
    MIGRATION_REQUEST,
    GOSSIP_SHUTDOWN,
    _TRACE,
    ECHO,
    REPAIR_MESSAGE,
    PAXOS_PREPARE,
    PAXOS_PROPOSE,
    PAXOS_COMMIT,
    PAGED_RANGE,
    UNUSED_1,
    UNUSED_2,
    UNUSED_3,
    LAST,
};

} // namespace net

namespace std {
template <>
class hash<net::messaging_verb> {
public:
    size_t operator()(const net::messaging_verb& x) const {
        return hash<int32_t>()(int32_t(x));
    }
};
} // namespace std

namespace net {

// NOTE: operator(input_stream<char>&, T&) takes a reference to uninitialized
//       T object and should use placement new in case T is non POD
struct serializer {
    // For integer type
    template<typename T>
    inline auto operator()(output_stream<char>& out, T&& v, std::enable_if_t<std::is_integral<std::remove_reference_t<T>>::value, void*> = nullptr) {
        auto v_ = net::hton(v);
        return out.write(reinterpret_cast<const char*>(&v_), sizeof(T));
    }
    template<typename T>
    inline auto operator()(input_stream<char>& in, T& v, std::enable_if_t<std::is_integral<T>::value, void*> = nullptr) {
        return in.read_exactly(sizeof(v)).then([&v] (temporary_buffer<char> buf) mutable {
            if (buf.size() != sizeof(v)) {
                throw rpc::closed_error();
            }
            v = net::ntoh(*reinterpret_cast<const net::packed<T>*>(buf.get()));
        });
    }

    // For vectors
    template<typename T>
    inline auto operator()(output_stream<char>& out, std::vector<T>& v) {
        return operator()(out, v.size()).then([&out, &v, this] {
            return do_for_each(v.begin(), v.end(), [&out, this] (T& e) {
                return operator()(out, e);
            });
        });
    }
    template<typename T>
    inline auto operator()(input_stream<char>& in, std::vector<T>& v) {
        using size_type = typename  std::vector<T>::size_type;
        return in.read_exactly(sizeof(size_type)).then([&v, &in, this] (temporary_buffer<char> buf) {
            if (buf.size() != sizeof(size_type)) {
                throw rpc::closed_error();
            }
            size_type c = net::ntoh(*reinterpret_cast<const net::packed<size_type>*>(buf.get()));
            new (&v) std::vector<T>;
            v.reserve(c);
            union U {
                U(){}
                ~U(){}
                T v;
            };
            return do_until([c] () mutable {return !c--;}, [&v, &in, u = U(), this] () mutable {
                return operator()(in, u.v).then([&u, &v] {
                    v.emplace_back(std::move(u.v));
                });
            });
        });
    }

    // For messaging_verb
    inline auto operator()(output_stream<char>& out, messaging_verb& v) {
        bytes b(bytes::initialized_later(), sizeof(v));
        auto _out = b.begin();
        serialize_int32(_out, int32_t(v));
        return out.write(reinterpret_cast<const char*>(b.c_str()), sizeof(v));
    }
    inline auto operator()(input_stream<char>& in, messaging_verb& v) {
        return in.read_exactly(sizeof(v)).then([&v] (temporary_buffer<char> buf) mutable {
            if (buf.size() != sizeof(v)) {
                throw rpc::closed_error();
            }
            bytes_view bv(reinterpret_cast<const int8_t*>(buf.get()), sizeof(v));
            v = messaging_verb(read_simple<int32_t>(bv));
        });
    }

    // For sstring
    inline auto operator()(output_stream<char>& out, sstring& v) {
        auto serialize_string_size = serialize_int16_size + v.size();
        auto sz = serialize_int16_size + serialize_string_size;
        bytes b(bytes::initialized_later(), sz);
        auto _out = b.begin();
        serialize_int16(_out, serialize_string_size);
        serialize_string(_out, v);
        return out.write(reinterpret_cast<const char*>(b.c_str()), sz);
    }
    inline auto operator()(input_stream<char>& in, sstring& v) {
        return in.read_exactly(serialize_int16_size).then([&in, &v] (temporary_buffer<char> buf) mutable {
            if (buf.size() != serialize_int16_size) {
                throw rpc::closed_error();
            }
            size_t serialize_string_size = net::ntoh(*reinterpret_cast<const net::packed<int16_t>*>(buf.get()));
            return in.read_exactly(serialize_string_size).then([serialize_string_size, &v]
                (temporary_buffer<char> buf) mutable {
                if (buf.size() != serialize_string_size) {
                    throw rpc::closed_error();
                }
                bytes_view bv(reinterpret_cast<const int8_t*>(buf.get()), serialize_string_size);
                new (&v) sstring(read_simple_short_string(bv));
                return make_ready_future<>();
            });
        });
    }

    // For frozen_mutation
    inline auto operator()(output_stream<char>& out, const frozen_mutation& v) {
        db::frozen_mutation_serializer s(v);
        uint32_t sz = s.size() + data_output::serialized_size(sz);
        bytes b(bytes::initialized_later(), sz);
        data_output o(b);
        o.write<uint32_t>(sz - data_output::serialized_size(sz));
        db::frozen_mutation_serializer::write(o, v);
        return out.write(reinterpret_cast<const char*>(b.c_str()), sz);
    }
    inline auto operator()(input_stream<char>& in, frozen_mutation& v) {
        static auto sz = data_output::serialized_size<uint32_t>();
        return in.read_exactly(sz).then([&v, &in] (temporary_buffer<char> buf) mutable {
            if (buf.size() != sz) {
                throw rpc::closed_error();
            }
            data_input i(bytes_view(reinterpret_cast<const int8_t*>(buf.get()), sz));
            size_t msz = i.read<int32_t>();
            return in.read_exactly(msz).then([&v, msz] (temporary_buffer<char> buf) {
                if (buf.size() != msz) {
                    throw rpc::closed_error();
                }
                data_input i(bytes_view(reinterpret_cast<const int8_t*>(buf.get()), msz));
                new (&v) frozen_mutation(db::frozen_mutation_serializer::read(i));
            });
        });
    }

    // For complex types which have serialize()/deserialize(),  e.g. gms::gossip_digest_syn, gms::gossip_digest_ack2
    template<typename T>
    inline auto operator()(output_stream<char>& out, T&& v, std::enable_if_t<!std::is_integral<std::remove_reference_t<T>>::value &&
                                                                             !std::is_enum<std::remove_reference_t<T>>::value, void*> = nullptr) {
        auto sz = serialize_int32_size + v.serialized_size();
        bytes b(bytes::initialized_later(), sz);
        auto _out = b.begin();
        serialize_int32(_out, int32_t(sz - serialize_int32_size));
        v.serialize(_out);
        return out.write(reinterpret_cast<const char*>(b.c_str()), sz);
    }
    template<typename T>
    inline auto operator()(input_stream<char>& in, T& v, std::enable_if_t<!std::is_integral<T>::value &&
                                                                          !std::is_enum<T>::value, void*> = nullptr) {
        return in.read_exactly(serialize_int32_size).then([&in, &v] (temporary_buffer<char> buf) mutable {
            if (buf.size() != serialize_int32_size) {
                throw rpc::closed_error();
            }
            size_t sz = net::ntoh(*reinterpret_cast<const net::packed<int32_t>*>(buf.get()));
            return in.read_exactly(sz).then([sz, &v] (temporary_buffer<char> buf) mutable {
                if (buf.size() != sz) {
                    throw rpc::closed_error();
                }
                bytes_view bv(reinterpret_cast<const int8_t*>(buf.get()), sz);
                new (&v) T(T::deserialize(bv));
                return make_ready_future<>();
            });
        });
    }
};

class messaging_service {
public:
    struct shard_id {
        gms::inet_address addr;
        uint32_t cpu_id;
        friend inline bool operator==(const shard_id& x, const shard_id& y) {
            return x.addr == y.addr && x.cpu_id == y.cpu_id ;
        }
        friend inline bool operator<(const shard_id& x, const shard_id& y) {
            if (x.addr < y.addr) {
                return true;
            } else if (y.addr < x.addr) {
                return false;
            } else {
                return x.cpu_id < y.cpu_id;
            }
        }
        friend inline std::ostream& operator<<(std::ostream& os, const shard_id& x) {
            return os << x.addr << ":" << x.cpu_id;
        }
        struct hash {
            size_t operator()(const shard_id& id) const {
                return std::hash<uint32_t>()(id.cpu_id) + std::hash<uint32_t>()(id.addr.raw_addr());
            }
        };
    };
    struct shard_info {
        shard_info(std::unique_ptr<rpc::protocol<serializer, messaging_verb>::client>&& client)
            : rpc_client(std::move(client)) {
        }
        std::unique_ptr<rpc::protocol<serializer, messaging_verb>::client> rpc_client;
    };

    void foreach_client(std::function<void(const messaging_service::shard_id& id,
                    const messaging_service::shard_info& info)> f) const {
        for (auto i = _clients.cbegin(); i != _clients.cend(); i++) {
            f(i->first, i->second);
        }
    }

    void increment_dropped_messages(messaging_verb verb) {
        _dropped_messages[static_cast<int32_t>(verb)]++;
    }

    uint64_t get_dropped_messages(messaging_verb verb) const {
        return _dropped_messages[static_cast<int32_t>(verb)];
    }

    const uint64_t* get_dropped_messages() const {
        return _dropped_messages;
    }

private:
    static constexpr uint16_t _default_port = 7000;
    gms::inet_address _listen_address;
    uint16_t _port;
    rpc::protocol<serializer, messaging_verb> _rpc;
    rpc::protocol<serializer, messaging_verb>::server _server;
    std::unordered_map<shard_id, shard_info, shard_id::hash> _clients;
    uint64_t _dropped_messages[static_cast<int32_t>(messaging_verb::LAST)] = {};
public:
    messaging_service(gms::inet_address ip = gms::inet_address("0.0.0.0"))
        : _listen_address(ip)
        , _port(_default_port)
        , _rpc(serializer{})
        , _server(_rpc, ipv4_addr{_listen_address.raw_addr(), _port}) {
    }
public:
    uint16_t port() {
        return _port;
    }
    auto listen_address() {
        return _listen_address;
    }
    future<> stop() {
        return make_ready_future<>();
    }

    static auto no_wait() {
        return rpc::no_wait;
    }
public:
    // Register a handler (a callback lambda) for verb
    template <typename Func>
    void register_handler(messaging_verb verb, Func&& func) {
        _rpc.register_handler(verb, std::move(func));
    }

    // Send a message for verb
    template <typename MsgIn, typename... MsgOut>
    auto send_message(messaging_verb verb, shard_id id, MsgOut&&... msg) {
        auto& rpc_client = get_rpc_client(id);
        auto rpc_handler = _rpc.make_client<MsgIn(MsgOut...)>(verb);
        return rpc_handler(rpc_client, std::forward<MsgOut>(msg)...).then_wrapped([this, id, verb] (auto&& f) {
            try {
                if (f.failed()) {
                    this->increment_dropped_messages(verb);
                    f.get();
                    assert(false); // never reached
                }
                return std::move(f);
            } catch(...) {
                // FIXME: we need to distinguish between a transport error and
                // a server error.
                // remove_rpc_client(id);
                throw;
            }
        });
    }

    template <typename... MsgOut>
    auto send_message_oneway(messaging_verb verb, shard_id id, MsgOut&&... msg) {
        return send_message<rpc::no_wait_type>(std::move(verb), std::move(id), std::forward<MsgOut>(msg)...);
    }
private:
    // Return rpc::protocol::client for a shard which is a ip + cpuid pair.
    rpc::protocol<serializer, messaging_verb>::client& get_rpc_client(shard_id id) {
        auto it = _clients.find(id);
        if (it == _clients.end()) {
            auto remote_addr = ipv4_addr(id.addr.raw_addr(), _port);
            auto client = std::make_unique<rpc::protocol<serializer, messaging_verb>::client>(_rpc, remote_addr, ipv4_addr{_listen_address.raw_addr(), 0});
            it = _clients.emplace(id, shard_info(std::move(client))).first;
            return *it->second.rpc_client;
        } else {
            return *it->second.rpc_client;
        }
    }

    void remove_rpc_client(shard_id id) {
        _clients.erase(id);
    }
};

extern distributed<messaging_service> _the_messaging_service;

inline distributed<messaging_service>& get_messaging_service() {
    return _the_messaging_service;
}

inline messaging_service& get_local_messaging_service() {
    return _the_messaging_service.local();
}

future<> init_messaging_service(sstring listen_address, db::config::seed_provider_type seed_provider);
} // namespace net
<|endoftext|>


<commit_before>#include "scene_editor_gizmo_collection.h"

#include "gizmos/scripting/scripting_gizmo.h"
#include "gizmos/translate_gizmo.h"
#include "gizmos/selected_bounds_gizmo.h"
#include "gizmos/selection_box_gizmo.h"
#include "halley/core/graphics/camera.h"
using namespace Halley;

SceneEditorGizmoCollection::SceneEditorGizmoCollection(UIFactory& factory, Resources& resources, ISceneEditorWindow& sceneEditorWindow)
	: factory(factory)
	, resources(resources)
	, sceneEditorWindow(sceneEditorWindow)
{
	// TODO: read this elsewhere
	snapRules.grid = GridSnapMode::Pixel;
	snapRules.line = LineSnapMode::IsometricAxisAligned;

	selectedBoundsGizmo = std::make_unique<SelectedBoundsGizmo>(snapRules, resources);
	selectionBoxGizmo = std::make_unique<SelectionBoxGizmo>(snapRules, resources);

	resetTools();
}

bool SceneEditorGizmoCollection::update(Time time, const Camera& camera, const ISceneEditor& sceneEditor, const SceneEditorInputState& inputState, SceneEditorOutputState& outputState)
{
	selectedBoundsGizmo->setCamera(camera);
	selectedBoundsGizmo->update(time, sceneEditor, inputState);
	selectionBoxGizmo->setCamera(camera);
	selectionBoxGizmo->update(time, sceneEditor, inputState);

	if (activeGizmo) {
		activeGizmo->setCamera(camera);
		activeGizmo->setOutputState(&outputState);
		activeGizmo->update(time, sceneEditor, inputState);
		activeGizmo->setOutputState(nullptr);

		return activeGizmo->isHighlighted();
	}
	return false;
}

void SceneEditorGizmoCollection::draw(Painter& painter)
{
	selectedBoundsGizmo->draw(painter);
	selectionBoxGizmo->draw(painter);

	if (activeGizmo) {
		activeGizmo->draw(painter);
	}
}

void SceneEditorGizmoCollection::setSelectedEntity(const std::optional<EntityRef>& entity, EntityData& data)
{
	selectedEntity = entity;
	entityData = &data;

	selectedBoundsGizmo->setSelectedEntity(entity, *entityData);

	if (activeGizmo) {
		activeGizmo->setSelectedEntity(entity, *entityData);
	}
}

void SceneEditorGizmoCollection::refreshEntity()
{
	selectedBoundsGizmo->refreshEntity();
	if (activeGizmo) {
		activeGizmo->refreshEntity();
	}
}

void SceneEditorGizmoCollection::onEntityModified(const UUID& uuid, const EntityData& oldData, const EntityData& newData)
{
	if (selectedEntity && selectedEntity->getInstanceUUID() == uuid) {
		if (newData.getComponents().size() != oldData.getComponents().size()) {
			refreshEntity();
		}
	}
}

std::shared_ptr<UIWidget> SceneEditorGizmoCollection::setTool(const String& tool, const String& componentName, const String& fieldName)
{
	const bool changedTool = currentTool != tool;

	currentTool = tool;
	activeGizmo.reset();

	const auto iter = gizmoFactories.find(tool);
	if (iter != gizmoFactories.end()) {
		if (iter->second) {
			activeGizmo = iter->second(snapRules, componentName, fieldName);
		}
	} else {
		activeGizmo.reset();
	}

	if (changedTool) {
		sceneEditorWindow.setSetting(EditorSettingType::Temp, "tools.curTool", ConfigNode(tool));
		sceneEditorWindow.setHighlightedComponents(activeGizmo ? activeGizmo->getHighlightedComponents() : std::vector<String>());
	}

	if (activeGizmo) {
		activeGizmo->setSelectedEntity(selectedEntity, *entityData);
		return activeGizmo->makeUI();
	}

	return {};
}

void SceneEditorGizmoCollection::deselect()
{
	if (activeGizmo) {
		activeGizmo->deselect();
	}
}

void SceneEditorGizmoCollection::generateList(UIList& list)
{
	const auto iconCol = factory.getColourScheme()->getColour("ui_text");
	list.clear();
	for (const auto& tool: tools) {
		list.addImage(tool.id, std::make_shared<UIImage>(tool.icon.clone().setColour(iconCol)), 1, {}, UISizerAlignFlags::Centre)->setToolTip(tool.toolTip);
	}
	uiList = &list;
}

ISceneEditorWindow& SceneEditorGizmoCollection::getSceneEditorWindow()
{
	return sceneEditorWindow;
}

bool SceneEditorGizmoCollection::onKeyPress(KeyboardKeyPress key, UIList& list)
{
	for (const auto& t: tools) {
		if (key == t.shortcut) {
			list.setSelectedOptionId(t.id);
			return true;
		}
	}

	return false;
}

void SceneEditorGizmoCollection::addTool(const Tool& tool, GizmoFactory gizmoFactory)
{
	tools.push_back(tool);
	gizmoFactories[tool.id] = std::move(gizmoFactory);
}

void SceneEditorGizmoCollection::resetTools()
{
	clear();

	addTool(Tool("drag", LocalisedString::fromHardcodedString("Hand [H]"), Sprite().setImage(resources, "ui/scene_editor_drag.png"), KeyCode::H),
		[this] (SnapRules snapRules, const String& componentName, const String& fieldName)
		{
			return std::unique_ptr<SceneEditorGizmo>{};
		}
	);
	addTool(Tool("translate", LocalisedString::fromHardcodedString("Move [V]"), Sprite().setImage(resources, "ui/scene_editor_move.png"), KeyCode::V),
		[this] (SnapRules snapRules, const String& componentName, const String& fieldName)
		{
			return std::make_unique<TranslateGizmo>(snapRules, factory, sceneEditorWindow);
		}
	);
	addTool(Tool("scripting", LocalisedString::fromHardcodedString("Scripting [S]"), Sprite().setImage(resources, "ui/scene_editor_scripting.png"), KeyCode::S),
		[this] (SnapRules snapRules, const String& componentName, const String& fieldName)
		{
			return std::make_unique<ScriptingGizmo>(snapRules, factory, sceneEditorWindow, sceneEditorWindow.getScriptNodeTypes());
		}
	);
}

void SceneEditorGizmoCollection::clear()
{
	tools.clear();
	gizmoFactories.clear();
	if (uiList) {
		uiList->clear();
		uiList = nullptr;
	}
}
<commit_msg>Fix crash when reloading DLL and one of the game-specific gizmos was selected<commit_after>#include "scene_editor_gizmo_collection.h"

#include "gizmos/scripting/scripting_gizmo.h"
#include "gizmos/translate_gizmo.h"
#include "gizmos/selected_bounds_gizmo.h"
#include "gizmos/selection_box_gizmo.h"
#include "halley/core/graphics/camera.h"
using namespace Halley;

SceneEditorGizmoCollection::SceneEditorGizmoCollection(UIFactory& factory, Resources& resources, ISceneEditorWindow& sceneEditorWindow)
	: factory(factory)
	, resources(resources)
	, sceneEditorWindow(sceneEditorWindow)
{
	// TODO: read this elsewhere
	snapRules.grid = GridSnapMode::Pixel;
	snapRules.line = LineSnapMode::IsometricAxisAligned;

	selectedBoundsGizmo = std::make_unique<SelectedBoundsGizmo>(snapRules, resources);
	selectionBoxGizmo = std::make_unique<SelectionBoxGizmo>(snapRules, resources);

	resetTools();
}

bool SceneEditorGizmoCollection::update(Time time, const Camera& camera, const ISceneEditor& sceneEditor, const SceneEditorInputState& inputState, SceneEditorOutputState& outputState)
{
	selectedBoundsGizmo->setCamera(camera);
	selectedBoundsGizmo->update(time, sceneEditor, inputState);
	selectionBoxGizmo->setCamera(camera);
	selectionBoxGizmo->update(time, sceneEditor, inputState);

	if (activeGizmo) {
		activeGizmo->setCamera(camera);
		activeGizmo->setOutputState(&outputState);
		activeGizmo->update(time, sceneEditor, inputState);
		activeGizmo->setOutputState(nullptr);

		return activeGizmo->isHighlighted();
	}
	return false;
}

void SceneEditorGizmoCollection::draw(Painter& painter)
{
	selectedBoundsGizmo->draw(painter);
	selectionBoxGizmo->draw(painter);

	if (activeGizmo) {
		activeGizmo->draw(painter);
	}
}

void SceneEditorGizmoCollection::setSelectedEntity(const std::optional<EntityRef>& entity, EntityData& data)
{
	selectedEntity = entity;
	entityData = &data;

	selectedBoundsGizmo->setSelectedEntity(entity, *entityData);

	if (activeGizmo) {
		activeGizmo->setSelectedEntity(entity, *entityData);
	}
}

void SceneEditorGizmoCollection::refreshEntity()
{
	selectedBoundsGizmo->refreshEntity();
	if (activeGizmo) {
		activeGizmo->refreshEntity();
	}
}

void SceneEditorGizmoCollection::onEntityModified(const UUID& uuid, const EntityData& oldData, const EntityData& newData)
{
	if (selectedEntity && selectedEntity->getInstanceUUID() == uuid) {
		if (newData.getComponents().size() != oldData.getComponents().size()) {
			refreshEntity();
		}
	}
}

std::shared_ptr<UIWidget> SceneEditorGizmoCollection::setTool(const String& tool, const String& componentName, const String& fieldName)
{
	const bool changedTool = currentTool != tool;

	currentTool = tool;
	activeGizmo.reset();

	const auto iter = gizmoFactories.find(tool);
	if (iter != gizmoFactories.end()) {
		if (iter->second) {
			activeGizmo = iter->second(snapRules, componentName, fieldName);
		}
	} else {
		activeGizmo.reset();
	}

	if (changedTool) {
		sceneEditorWindow.setSetting(EditorSettingType::Temp, "tools.curTool", ConfigNode(tool));
		sceneEditorWindow.setHighlightedComponents(activeGizmo ? activeGizmo->getHighlightedComponents() : std::vector<String>());
	}

	if (activeGizmo) {
		activeGizmo->setSelectedEntity(selectedEntity, *entityData);
		return activeGizmo->makeUI();
	}

	return {};
}

void SceneEditorGizmoCollection::deselect()
{
	if (activeGizmo) {
		activeGizmo->deselect();
	}
}

void SceneEditorGizmoCollection::generateList(UIList& list)
{
	const auto iconCol = factory.getColourScheme()->getColour("ui_text");
	list.clear();
	for (const auto& tool: tools) {
		list.addImage(tool.id, std::make_shared<UIImage>(tool.icon.clone().setColour(iconCol)), 1, {}, UISizerAlignFlags::Centre)->setToolTip(tool.toolTip);
	}
	uiList = &list;
}

ISceneEditorWindow& SceneEditorGizmoCollection::getSceneEditorWindow()
{
	return sceneEditorWindow;
}

bool SceneEditorGizmoCollection::onKeyPress(KeyboardKeyPress key, UIList& list)
{
	for (const auto& t: tools) {
		if (key == t.shortcut) {
			list.setSelectedOptionId(t.id);
			return true;
		}
	}

	return false;
}

void SceneEditorGizmoCollection::addTool(const Tool& tool, GizmoFactory gizmoFactory)
{
	tools.push_back(tool);
	gizmoFactories[tool.id] = std::move(gizmoFactory);
}

void SceneEditorGizmoCollection::resetTools()
{
	clear();

	addTool(Tool("drag", LocalisedString::fromHardcodedString("Hand [H]"), Sprite().setImage(resources, "ui/scene_editor_drag.png"), KeyCode::H),
		[this] (SnapRules snapRules, const String& componentName, const String& fieldName)
		{
			return std::unique_ptr<SceneEditorGizmo>{};
		}
	);
	addTool(Tool("translate", LocalisedString::fromHardcodedString("Move [V]"), Sprite().setImage(resources, "ui/scene_editor_move.png"), KeyCode::V),
		[this] (SnapRules snapRules, const String& componentName, const String& fieldName)
		{
			return std::make_unique<TranslateGizmo>(snapRules, factory, sceneEditorWindow);
		}
	);
	addTool(Tool("scripting", LocalisedString::fromHardcodedString("Scripting [S]"), Sprite().setImage(resources, "ui/scene_editor_scripting.png"), KeyCode::S),
		[this] (SnapRules snapRules, const String& componentName, const String& fieldName)
		{
			return std::make_unique<ScriptingGizmo>(snapRules, factory, sceneEditorWindow, sceneEditorWindow.getScriptNodeTypes());
		}
	);
}

void SceneEditorGizmoCollection::clear()
{
	tools.clear();
	gizmoFactories.clear();
	if (uiList) {
		uiList->clear();
		uiList = nullptr;
	}
	activeGizmo.reset();
}
<|endoftext|>


<commit_before><commit_msg>Optimize debug line buffer resizing<commit_after><|endoftext|>


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

#include <math.h>
#include <votca/tools/histogramnew.h>
#include <votca/tools/tokenizer.h>
#include <votca/csg/csgapplication.h>

using namespace std;
using namespace votca::csg;
using namespace votca::tools;

class CsgDensityApp
    : public CsgApplication
{
    string ProgramName() { return "csg_density"; }
    void HelpText(ostream &out) {
        out << "Calculates the mass density distribution along a box axis or radial density profile from reference point";
    }

    // some program options are added here
    void Initialize();

    // we want to process a trajectory
    bool DoTrajectory() {return true;}
    bool DoMapping() {return true;}
    bool DoMappingDefault(void) { return false; }

    // write out results in EndEvaluate
    void EndEvaluate();
    void BeginEvaluate(Topology *top, Topology *top_atom);
    void EvalConfiguration(Topology *top, Topology *top_ref);

    bool EvaluateOptions() {
        CsgApplication::EvaluateOptions();
        CheckRequired("out", "no output topology specified");
        CheckRequired("trj", "no trajectory file specified");
        return true;
    };

protected:
    string _filter, _out;
    HistogramNew _dist;
    double _rmax;
    int _nbin;
    double _scale;
    int _frames;
    int _nblock;
    int _block_length;
    vec _ref;
    vec _axis;
    string _axisname;
    string _molname;
    double _area;
    void WriteDensity(const string &suffix="");
};

int main(int argc, char** argv)
{
    CsgDensityApp app;
    return app.Exec(argc, argv);
}

void CsgDensityApp::BeginEvaluate(Topology *top, Topology *top_atom) {

     matrix box = top->getBox();
     vec a = box.getCol(0);
     vec b = box.getCol(1);
     vec c = box.getCol(2);

    _dist.setPeriodic(true);
    _axis=vec(0,0,0);
    _area=0;
    if(_axisname=="x") {
      _axis.setX(1);
      _rmax = abs(a);
      _area= abs(b^c);
    }
    else if(_axisname=="y") {
      _axis.setY(1);
       _rmax = abs(b);
      _area= abs(a^c);
    }
    else if(_axisname=="z") {
      _axis.setZ(1);
      _rmax = abs(c);
      _area= abs(a^b);
    }
    else if(_axisname=="r") {
      _dist.setPeriodic(false);
      _rmax = min(min(abs(a/2), abs(b/2)), abs(c/2));
    } else {
      throw std::runtime_error("unknown axis type");
    }

    if(OptionsMap().count("rmax"))
      _rmax = OptionsMap()["rmax"].as<double>();

    if(OptionsMap().count("block-length")){
       _block_length=OptionsMap()["block-length"].as<int>();
    } else {
      _block_length=0;
    }

    if (_axisname=="r") {
      if(!OptionsMap().count("ref"))
         _ref = a/2+b/2+c/2;
       cout << "Using referece point: " << _ref << endl;
    }
    else if(OptionsMap().count("ref"))
        throw std::runtime_error("reference center can only be used in case of spherical density");

    _dist.Initialize(0, _rmax, _nbin);

    cout << "rmax: " << _rmax << endl;
    cout << "axis: " << _axisname << endl;
    cout << "Bins: " << _nbin << endl;
    _frames=0;
    _nblock=0;
}

void CsgDensityApp::EvalConfiguration(Topology *top, Topology *top_ref)
{
    // loop over all molecules
    bool did_something = false;
    for(MoleculeContainer::iterator imol=top->Molecules().begin(); imol!=top->Molecules().end(); ++imol) {
        Molecule *mol = *imol;
        if(!wildcmp(_molname.c_str(),mol->getName().c_str()))
            continue;
        int N = mol->BeadCount();
            for(int i=0; i<N; i++) {
                Bead *b = mol->getBead(i);
                if(!wildcmp(_filter.c_str(), b->getName().c_str()))
                    continue;
                double r;
                if (_axisname=="r") {
                    r = abs(top->BCShortestConnection(_ref, b->getPos()));
                } else {
                    r = b->getPos() *  _axis;
                }
                _dist.Process(r, b->getM());
                did_something = true;
            }
    }
    _frames++;
    if (!did_something) throw std::runtime_error("No molecule in selection");
    if(_block_length != 0) {
        if((_nframes % _block_length)==0) {
            _nblock++;
	    string suffix = string("_") + boost::lexical_cast<string>(_nblock);
	    WriteDensity(suffix);
	    _dist.Clear();
	}
    }
}

// output everything when processing frames is done
void CsgDensityApp::WriteDensity(const string &suffix)
{
  if (_axisname=="r") {
    _dist.data().y() = _scale/(_frames*_rmax/(double)_nbin *4*M_PI) * element_div( _dist.data().y(),
                   element_prod(_dist.data().x(), _dist.data().x()));
  } else {
    _dist.data().y() = _scale/((double)_frames * _area * _rmax/ (double)_nbin ) *_dist.data().y();
  }
  _dist.data().Save(_out + suffix);
}

void CsgDensityApp::EndEvaluate()
{
  if(_block_length == 0)
    WriteDensity();
}

// add our user program options
void CsgDensityApp::Initialize()
{
    CsgApplication::Initialize();
    // add program option to pick molecule
    AddProgramOptions("Specific options:")
             ("axis", boost::program_options::value<string>(&_axisname)->default_value("r"), "[x|y|z|r] density axis (r=spherical)")
             ("bins", boost::program_options::value<int>(&_nbin)->default_value(50), "bins")
             ("block-length", boost::program_options::value<int>(), "  write blocks of this length, the averages are cleared after every write")
             ("out", boost::program_options::value<string>(&_out), "Output file")
             ("rmax", boost::program_options::value<double>(), "rmax (default for [r] =min of all box vectors/2, else l )")
             ("scale", boost::program_options::value<double>(&_scale)->default_value(1.0), "scale factor for the density")
             ("molname", boost::program_options::value<string>(&_molname)->default_value("*"), "molname")
             ("filter", boost::program_options::value<string>(&_filter)->default_value("*"), "filter bead names")
             ("ref", boost::program_options::value<vec>(&_ref), "reference zero point");
}

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

#include <math.h>
#include <votca/tools/histogramnew.h>
#include <votca/tools/tokenizer.h>
#include <votca/csg/csgapplication.h>

using namespace std;
using namespace votca::csg;
using namespace votca::tools;

class CsgDensityApp
    : public CsgApplication
{
    string ProgramName() { return "csg_density"; }
    void HelpText(ostream &out) {
        out << "Calculates the mass density distribution along a box axis or radial density profile from reference point";
    }

    // some program options are added here
    void Initialize();

    // we want to process a trajectory
    bool DoTrajectory() {return true;}
    bool DoMapping() {return true;}
    bool DoMappingDefault(void) { return false; }

    // write out results in EndEvaluate
    void EndEvaluate();
    void BeginEvaluate(Topology *top, Topology *top_atom);
    void EvalConfiguration(Topology *top, Topology *top_ref);

    bool EvaluateOptions() {
        CsgApplication::EvaluateOptions();
        CheckRequired("out", "no output topology specified");
        CheckRequired("trj", "no trajectory file specified");
        return true;
    };

protected:
    string _filter, _out;
    HistogramNew _dist;
    double _rmax;
    int _nbin;
    double _scale;
    int _frames;
    int _nblock;
    int _block_length;
    vec _ref;
    vec _axis;
    string _axisname;
    string _molname;
    double _area;
    void WriteDensity(int nframes,const string &suffix="");
};

int main(int argc, char** argv)
{
    CsgDensityApp app;
    return app.Exec(argc, argv);
}

void CsgDensityApp::BeginEvaluate(Topology *top, Topology *top_atom) {

     matrix box = top->getBox();
     vec a = box.getCol(0);
     vec b = box.getCol(1);
     vec c = box.getCol(2);

    _dist.setPeriodic(true);
    _axis=vec(0,0,0);
    _area=0;
    if(_axisname=="x") {
      _axis.setX(1);
      _rmax = abs(a);
      _area= abs(b^c);
    }
    else if(_axisname=="y") {
      _axis.setY(1);
       _rmax = abs(b);
      _area= abs(a^c);
    }
    else if(_axisname=="z") {
      _axis.setZ(1);
      _rmax = abs(c);
      _area= abs(a^b);
    }
    else if(_axisname=="r") {
      _dist.setPeriodic(false);
      _rmax = min(min(abs(a/2), abs(b/2)), abs(c/2));
    } else {
      throw std::runtime_error("unknown axis type");
    }

    if(OptionsMap().count("rmax"))
      _rmax = OptionsMap()["rmax"].as<double>();

    if(OptionsMap().count("block-length")){
       _block_length=OptionsMap()["block-length"].as<int>();
    } else {
      _block_length=0;
    }

    if (_axisname=="r") {
      if(!OptionsMap().count("ref"))
         _ref = a/2+b/2+c/2;
       cout << "Using referece point: " << _ref << endl;
    }
    else if(OptionsMap().count("ref"))
        throw std::runtime_error("reference center can only be used in case of spherical density");

    _dist.Initialize(0, _rmax, _nbin);

    cout << "rmax: " << _rmax << endl;
    cout << "axis: " << _axisname << endl;
    cout << "Bins: " << _nbin << endl;
    _frames=0;
    _nblock=0;
}

void CsgDensityApp::EvalConfiguration(Topology *top, Topology *top_ref)
{
    // loop over all molecules
    bool did_something = false;
    for(MoleculeContainer::iterator imol=top->Molecules().begin(); imol!=top->Molecules().end(); ++imol) {
        Molecule *mol = *imol;
        if(!wildcmp(_molname.c_str(),mol->getName().c_str()))
            continue;
        int N = mol->BeadCount();
            for(int i=0; i<N; i++) {
                Bead *b = mol->getBead(i);
                if(!wildcmp(_filter.c_str(), b->getName().c_str()))
                    continue;
                double r;
                if (_axisname=="r") {
                    r = abs(top->BCShortestConnection(_ref, b->getPos()));
                } else {
                    r = b->getPos() *  _axis;
                }
                _dist.Process(r, b->getM());
                did_something = true;
            }
    }
    _frames++;
    if (!did_something) throw std::runtime_error("No molecule in selection");
    if(_block_length != 0) {
        if((_nframes % _block_length)==0) {
            _nblock++;
	    string suffix = string("_") + boost::lexical_cast<string>(_nblock);
	    WriteDensity(_block_length,suffix);
	    _dist.Clear();
	}
    }
}

// output everything when processing frames is done
void CsgDensityApp::WriteDensity(int nframes, const string &suffix)
{
  if (_axisname=="r") {
    _dist.data().y() = _scale/(nframes*_rmax/(double)_nbin *4*M_PI) * element_div( _dist.data().y(),
                   element_prod(_dist.data().x(), _dist.data().x()));
  } else {
    _dist.data().y() = _scale/((double)nframes * _area * _rmax/ (double)_nbin ) *_dist.data().y();
  }
  _dist.data().Save(_out + suffix);
}

void CsgDensityApp::EndEvaluate()
{
  if(_block_length == 0)
    WriteDensity(_frames);
}

// add our user program options
void CsgDensityApp::Initialize()
{
    CsgApplication::Initialize();
    // add program option to pick molecule
    AddProgramOptions("Specific options:")
             ("axis", boost::program_options::value<string>(&_axisname)->default_value("r"), "[x|y|z|r] density axis (r=spherical)")
             ("bins", boost::program_options::value<int>(&_nbin)->default_value(50), "bins")
             ("block-length", boost::program_options::value<int>(), "  write blocks of this length, the averages are cleared after every write")
             ("out", boost::program_options::value<string>(&_out), "Output file")
             ("rmax", boost::program_options::value<double>(), "rmax (default for [r] =min of all box vectors/2, else l )")
             ("scale", boost::program_options::value<double>(&_scale)->default_value(1.0), "scale factor for the density")
             ("molname", boost::program_options::value<string>(&_molname)->default_value("*"), "molname")
             ("filter", boost::program_options::value<string>(&_filter)->default_value("*"), "filter bead names")
             ("ref", boost::program_options::value<vec>(&_ref), "reference zero point");
}

<|endoftext|>


<commit_before>class AliAnalysisGrid;

void RunAnalysisITS() {
  //
  // Macro to analyze ESDs from raw data reconstruction
  // A.Dainese, andrea.dainese@pd.infn.it
  //
  //gSystem->Setenv("alien_CLOSE_SE","ALICE::CNAF::SE");

  gSystem->SetIncludePath("-I. -I$ROOTSYS/include -I$ALICE_ROOT -I$ALICE_ROOT/include -I$ALICE_ROOT/ITS -I$ALICE_ROOT/TPC -I$ALICE_ROOT/CONTAINERS -I$ALICE_ROOT/STEER -I$ALICE_ROOT/TRD -I$ALICE_ROOT/macros -I$ALICE_ROOT/ANALYSIS -g");

  //
  TString analysisMode = "local"; // "local", "grid", or "proof" (not yet)

  Long64_t nentries=1000000000000000,firstentry=0;
  Bool_t useAlienPlugin=kFALSE;
  Bool_t uselibPWG1=kTRUE;
  TString pluginmode="full";
  TString loadMacroPath="./";
  Bool_t readHLT=kFALSE;
  //

  if(analysisMode=="grid") {
    // Connect to AliEn
    TGrid::Connect("alien://");
  } else if(analysisMode=="proof") {
    // Connect to the PROOF cluster
    printf("PROOF mode not yet functional..\n");
    return;
    TProof::Open("alicecaf");
    //TProof::Reset("alicecaf");
  }

  // Load analysis libraries
  gSystem->Load("libANALYSIS.so");
  gSystem->Load("libANALYSISalice.so");
  if(uselibPWG1) {gSystem->Load("libTENDER.so"); gSystem->Load("libPWG1.so");}

  // Create Alien plugin, if requested
  if(useAlienPlugin) {
    AliAnalysisGrid *alienHandler = CreateAlienHandler(pluginmode,uselibPWG1);
    if(!alienHandler) return;
  }

  TChain *chainESD = 0;
  if(!useAlienPlugin) {
    // Prepare input chain
    //    chainESD = CreateESDChain("/home/dainesea/alignData/RAWdata_CosmicsSum09/RecoSPD/chunk.",13,13);
    chainESD=new TChain("esdTree");
    //chainESD->Add("alien:///alice/cern.ch/user/s/sitta/output/000088361/ESDs/pass1/09000088361017.10/AliESDs.root");
    chainESD->Add("AliESDs.root");
  }

  // Create the analysis manager
  AliAnalysisManager *mgr  = new AliAnalysisManager("My Manager","My Manager");
  // Enable debug printouts
  mgr->SetDebugLevel(10);
  // Connect plug-in to the analysis manager
  if(useAlienPlugin) mgr->SetGridHandler(alienHandler);

  // Add ESD handler
  AliESDInputHandler *esdH = new AliESDInputHandler();
  if(readHLT) esdH->SetReadHLT();
  mgr->SetInputEventHandler(esdH);

  //-------------------------------------------------------------------

  //-------------------------------------------------------------------
  // Analysis tasks (wagons of the train)
  //
  TString taskName;

  if(!uselibPWG1) gROOT->LoadMacro("AliAlignmentDataFilterITS.cxx++g");
  taskName="AddTaskAlignmentDataFilterITS.C";
  taskName.Prepend(loadMacroPath.Data());
  gROOT->LoadMacro(taskName.Data());
  AliAlignmentDataFilterITS *itsTask = AddTaskAlignmentDataFilterITS();

  if(!uselibPWG1) gROOT->LoadMacro("AliTrackMatchingTPCITSCosmics.cxx++g");
  taskName="AddTaskTrackMatchingTPCITS.C";
  taskName.Prepend(loadMacroPath.Data());
  gROOT->LoadMacro(taskName.Data());
  AliTrackMatchingTPCITSCosmics *tpcitsTask = AddTaskTrackMatchingTPCITS();
  if(readHLT) tpcitsTask->SetReadHLTESD(kTRUE);
  /*
  Bool_t readMC=kTRUE;

  if(!uselibPWG1) gROOT->LoadMacro("AliAnalysisTaskVertexESD.cxx++g");
  taskName="AddTaskVertexESD.C";
  taskName.Prepend(loadMacroPath.Data());
  gROOT->LoadMacro(taskName.Data());
  AliAnalysisTaskVertexESD *vtxTask = AddTaskVertexESD(readMC);

  if(!uselibPWG1) gROOT->LoadMacro("AliAnalysisTaskITSTrackingCheck.cxx++g");
  taskName="AddTaskPerformanceITS.C";
  taskName.Prepend(loadMacroPath.Data());
  gROOT->LoadMacro(taskName.Data());
  AliAnalysisTaskITSTrackingCheck *itsTask = AddTaskPerformanceITS(readMC);

  if(readMC) {
    AliMCEventHandler  *mcH = new AliMCEventHandler();
    mgr->SetMCtruthEventHandler(mcH);
  }
  */
  //
  // Run the analysis
  //
  if(chainESD) printf("CHAIN HAS %d ENTRIES\n",(Int_t)chainESD->GetEntries());

  if(!mgr->InitAnalysis()) return;
  mgr->PrintStatus();
  if(analysisMode=="grid" && !useAlienPlugin) analysisMode="local";
  mgr->StartAnalysis(analysisMode.Data(),chainESD,nentries,firstentry);

  return;
}
//_____________________________________________________________________________
//
AliAnalysisGrid* CreateAlienHandler(TString pluginmode="test",
				    Bool_t uselibPWG1=kFALSE)
{
  // Check if user has a valid token, otherwise make one. This has limitations.
  // One can always follow the standard procedure of calling alien-token-init then
  //   source /tmp/gclient_env_$UID in the current shell.
   if (!AliAnalysisGrid::CreateToken()) return NULL;
   AliAnalysisAlien *plugin = new AliAnalysisAlien();
   // Set the run mode (can be "full", "test", "offline", "submit" or "terminate")
   plugin->SetRunMode(pluginmode.Data());
   plugin->SetUser("dainesea");
   plugin->SetNtestFiles(1);
   // Set versions of used packages
   plugin->SetAPIVersion("V2.4");
   plugin->SetROOTVersion("v5-24-00");
   plugin->SetAliROOTVersion("v4-18-07-AN");
   // Declare input data to be processed.
   // Method 1: Create automatically XML collections using alien 'find' command.
   // Define production directory LFN
   plugin->SetGridDataDir("/alice/data/2009/LHC09c");
   //plugin->SetGridDataDir("/alice/cern.ch/user/s/sitta/output/000088361/");
   // Set data search pattern
   //plugin->SetDataPattern("AliESDs.root");
   plugin->SetDataPattern("ESD.tag.root");
   Int_t n=0;
   n++; plugin->AddRunNumber("000080015");
   n++; plugin->AddRunNumber("000080261");
   plugin->SetNrunsPerMaster(n);
   // Method 2: Declare existing data files (raw collections, xml collections, root file)
   // If no path mentioned data is supposed to be in the work directory (see SetGridWorkingDir())
   // XML collections added via this method can be combined with the first method if
   // the content is compatible (using or not tags)
   // e.g.: find -z -x 80015 /alice/data/2009/LHC09c/000080015/ESDs/ ESD.tag.root > 80015.xml
   //plugin->AddDataFile("79876.xml");
   //plugin->AddDataFile("80015.xml");
   //plugin->AddDataFile("80261.xml");
   //   plugin->AddDataFile("/alice/data/2008/LHC08c/000057657/raw/Run57657.Merged.RAW.tag.root");
   // Define alien work directory where all files will be copied. Relative to alien $HOME.
   plugin->SetGridWorkingDir("analysisITS");
   // Declare alien output directory. Relative to working directory.
   plugin->SetGridOutputDir("output151009"); // In this case will be $HOME/work/output
   // Declare the analysis source files names separated by blancs. To be compiled runtime
   // using ACLiC on the worker nodes.
   if(!uselibPWG1) {
     plugin->SetAnalysisSource("AliAlignmentDataFilterITS.cxx");
     plugin->SetAnalysisSource("AliTrackMatchingTPCITSCosmics.cxx");
   }
   // Declare all libraries (other than the default ones for the framework. These will be
   // loaded by the generated analysis macro. Add all extra files (task .cxx/.h) here.
   //plugin->SetAdditionalLibs("AliAlignmentDataFilterITS.h AliAlignmentDataFilterITS.cxx libProof.so libRAWDatabase.so libRAWDatarec.so libCDB.so libSTEER.so libITSbase.so libITSrec.so");
   plugin->AddIncludePath("-I. -I$ROOTSYS/include -I$ALICE_ROOT -I$ALICE_ROOT/include -I$ALICE_ROOT/ITS -I$ALICE_ROOT/TPC -I$ALICE_ROOT/CONTAINERS -I$ALICE_ROOT/STEER -I$ALICE_ROOT/TRD -I$ALICE_ROOT/macros -I$ALICE_ROOT/ANALYSIS -g");
   if(!uselibPWG1) {
     plugin->SetAdditionalLibs("AliAlignmentDataFilterITS.h AliAlignmentDataFilterITS.cxx AliTrackMatchingTPCITSCosmics.h AliTrackMatchingTPCITSCosmics.cxx libProof.so libRAWDatabase.so libRAWDatarec.so libCDB.so libSTEER.so libITSbase.so libITSrec.so");
   } else {
     plugin->SetAdditionalLibs("libGui.so libProof.so libMinuit.so libRAWDatabase.so libRAWDatarec.so libCDB.so libSTEER.so libITSbase.so libITSrec.so libTPCbase.so libTPCrec.so libTRDbase.so libTRDrec.so libTENDER.so libPWG1.so");
   }
   // Declare the output file names separated by blancs.
   // (can be like: file.root or file.root@ALICE::Niham::File)
   plugin->SetDefaultOutputs(kTRUE);
   // Optionally define the files to be archived.
   //   plugin->SetOutputArchive("log_archive.zip:stdout,stderr@ALICE::NIHAM::File root_archive.zip:*.root@ALICE::NIHAM::File");
   plugin->SetOutputArchive("log_archive.zip:stdout,stderr");
   // Optionally set a name for the generated analysis macro (default MyAnalysis.C)
   plugin->SetAnalysisMacro("AnalysisITS.C");
   // Optionally set maximum number of input files/subjob (default 100, put 0 to ignore)
   plugin->SetSplitMaxInputFileNumber(1);
   // Optionally set number of failed jobs that will trigger killing waiting sub-jobs.
   //plugin->SetMaxInitFailed(5);
   // Optionally resubmit threshold.
   //plugin->SetMasterResubmitThreshold(90);
   // Optionally set time to live (default 30000 sec)
   //plugin->SetTTL(20000);
   // Optionally set input format (default xml-single)
   plugin->SetInputFormat("xml-single");
   // Optionally modify the name of the generated JDL (default analysis.jdl)
   plugin->SetJDLName("TaskAnalysisITS.jdl");
   // Optionally modify job price (default 1)
   //plugin->SetPrice(1);
   // Optionally modify split mode (default 'se')
   plugin->SetSplitMode("se");
   // Optionally set the preferred SE
   plugin->SetPreferedSE("ALICE::CNAF::SE");

   return plugin;
}
//-----------------------------------------------------------------------------
TChain *CreateESDChain(TString esdpath=".",Int_t ifirst=-1,Int_t ilast=-1) {

  TChain *chainESD = new TChain("esdTree");

  if(ifirst<0) {
    chainESD->Add("AliESDs.root");
  } else {
    for(Int_t i=ifirst; i<=ilast; i++) {
      TString esdfile=esdpath; esdfile+=i; esdfile.Append("/AliESDs.root");
      chainESD->Add(esdfile.Data());
    }
  }

  return chainESD;
}
<commit_msg>Add possbility to read also the RecPoints<commit_after>class AliAnalysisGrid;

void RunAnalysisITS() {
  //
  // Macro to analyze ESDs from raw data reconstruction
  // A.Dainese, andrea.dainese@pd.infn.it
  //
  //gSystem->Setenv("alien_CLOSE_SE","ALICE::CNAF::SE");

  gSystem->SetIncludePath("-I. -I$ROOTSYS/include -I$ALICE_ROOT -I$ALICE_ROOT/include -I$ALICE_ROOT/ITS -I$ALICE_ROOT/TPC -I$ALICE_ROOT/CONTAINERS -I$ALICE_ROOT/STEER -I$ALICE_ROOT/TRD -I$ALICE_ROOT/macros -I$ALICE_ROOT/ANALYSIS -g");

  //
  TString analysisMode = "local"; // "local", "grid", or "proof" (not yet)

  Long64_t nentries=1000000000000000,firstentry=0;
  Bool_t useAlienPlugin=kFALSE;
  Bool_t uselibPWG1=kTRUE;
  TString pluginmode="full";
  TString loadMacroPath="./";
  Bool_t readHLT=kFALSE;
  //

  if(analysisMode=="grid") {
    // Connect to AliEn
    TGrid::Connect("alien://");
  } else if(analysisMode=="proof") {
    // Connect to the PROOF cluster
    printf("PROOF mode not yet functional..\n");
    return;
    TProof::Open("alicecaf");
    //TProof::Reset("alicecaf");
  }

  // Load analysis libraries
  gSystem->Load("libANALYSIS.so");
  gSystem->Load("libANALYSISalice.so");
  if(uselibPWG1) {gSystem->Load("libTENDER.so");gSystem->Load("libPWG1.so");}

  // Create Alien plugin, if requested
  if(useAlienPlugin) {
    AliAnalysisGrid *alienHandler = CreateAlienHandler(pluginmode,uselibPWG1);
    if(!alienHandler) return;
  }

  TChain *chainESD = 0;
  if(!useAlienPlugin) {
    // Prepare input chain
    chainESD = CreateESDChain("/home/dainesea/alignEvents2/boxTRUNK280909_zero/event.",1,48);
    //chainESD=new TChain("esdTree");
    //chainESD->Add("alien:///alice/cern.ch/user/s/sitta/output/000088361/ESDs/pass1/09000088361017.10/AliESDs.root");
    //chainESD->Add("./AliESDs.root");
  }

  // Create the analysis manager
  AliAnalysisManager *mgr  = new AliAnalysisManager("My Manager","My Manager");
  // Enable debug printouts
  mgr->SetDebugLevel(10);
  // Connect plug-in to the analysis manager
  if(useAlienPlugin) mgr->SetGridHandler(alienHandler);

  //-------------------------------------------------------------------

  // Add ESD handler
  Bool_t readRP=kTRUE;
  AliESDInputHandler *esdH = 0;
  if(readRP) {
    esdH = new AliESDInputHandlerRP();
  } else {
    esdH = new AliESDInputHandler();
  }
  if(readHLT) esdH->SetReadHLT();
  mgr->SetInputEventHandler(esdH);

  //-------------------------------------------------------------------
  // Analysis tasks (wagons of the train)
  //
  TString taskName;
  /*
  if(!uselibPWG1) gROOT->LoadMacro("AliAlignmentDataFilterITS.cxx++g");
  taskName="AddTaskAlignmentDataFilterITS.C";
  taskName.Prepend(loadMacroPath.Data());
  gROOT->LoadMacro(taskName.Data());
  AliAlignmentDataFilterITS *itsTask = AddTaskAlignmentDataFilterITS();

  if(!uselibPWG1) gROOT->LoadMacro("AliTrackMatchingTPCITSCosmics.cxx++g");
  taskName="AddTaskTrackMatchingTPCITS.C";
  taskName.Prepend(loadMacroPath.Data());
  gROOT->LoadMacro(taskName.Data());
  AliTrackMatchingTPCITSCosmics *tpcitsTask = AddTaskTrackMatchingTPCITS();
  if(readHLT) tpcitsTask->SetReadHLTESD(kTRUE);
  */
  Bool_t readMC=kTRUE;
  if(!uselibPWG1) gROOT->LoadMacro("AliAnalysisTaskVertexESD.cxx++g");
  taskName="AddTaskVertexESD.C";
  taskName.Prepend(loadMacroPath.Data());
  gROOT->LoadMacro(taskName.Data());
  //AliAnalysisTaskVertexESD *vtxTask = AddTaskVertexESD(readMC);

  if(!uselibPWG1) gROOT->LoadMacro("AliAnalysisTaskITSTrackingCheck.cxx++g");
  taskName="AddTaskPerformanceITS.C";
  taskName.Prepend(loadMacroPath.Data());
  gROOT->LoadMacro(taskName.Data());
  AliAnalysisTaskITSTrackingCheck *itsTask = AddTaskPerformanceITS(readMC,readRP);

  if(readMC) {
    AliMCEventHandler  *mcH = new AliMCEventHandler();
    mgr->SetMCtruthEventHandler(mcH);
  }

  //
  // Run the analysis
  //
  if(chainESD) printf("CHAIN HAS %d ENTRIES\n",(Int_t)chainESD->GetEntries());

  if(!mgr->InitAnalysis()) return;
  mgr->PrintStatus();
  if(analysisMode=="grid" && !useAlienPlugin) analysisMode="local";
  mgr->StartAnalysis(analysisMode.Data(),chainESD,nentries,firstentry);

  return;
}
//_____________________________________________________________________________
//
AliAnalysisGrid* CreateAlienHandler(TString pluginmode="test",
				    Bool_t uselibPWG1=kFALSE)
{
  // Check if user has a valid token, otherwise make one. This has limitations.
  // One can always follow the standard procedure of calling alien-token-init then
  //   source /tmp/gclient_env_$UID in the current shell.
   if (!AliAnalysisGrid::CreateToken()) return NULL;
   AliAnalysisAlien *plugin = new AliAnalysisAlien();
   // Set the run mode (can be "full", "test", "offline", "submit" or "terminate")
   plugin->SetRunMode(pluginmode.Data());
   plugin->SetUser("dainesea");
   plugin->SetNtestFiles(1);
   // Set versions of used packages
   plugin->SetAPIVersion("V2.4");
   plugin->SetROOTVersion("v5-24-00");
   plugin->SetAliROOTVersion("v4-18-07-AN");
   // Declare input data to be processed.
   // Method 1: Create automatically XML collections using alien 'find' command.
   // Define production directory LFN
   plugin->SetGridDataDir("/alice/data/2009/LHC09c");
   //plugin->SetGridDataDir("/alice/cern.ch/user/s/sitta/output/000088361/");
   // Set data search pattern
   //plugin->SetDataPattern("AliESDs.root");
   plugin->SetDataPattern("ESD.tag.root");
   Int_t n=0;
   n++; plugin->AddRunNumber("000080015");
   n++; plugin->AddRunNumber("000080261");
   plugin->SetNrunsPerMaster(n);
   // Method 2: Declare existing data files (raw collections, xml collections, root file)
   // If no path mentioned data is supposed to be in the work directory (see SetGridWorkingDir())
   // XML collections added via this method can be combined with the first method if
   // the content is compatible (using or not tags)
   // e.g.: find -z -x 80015 /alice/data/2009/LHC09c/000080015/ESDs/ ESD.tag.root > 80015.xml
   //plugin->AddDataFile("79876.xml");
   //plugin->AddDataFile("80015.xml");
   //plugin->AddDataFile("80261.xml");
   //   plugin->AddDataFile("/alice/data/2008/LHC08c/000057657/raw/Run57657.Merged.RAW.tag.root");
   // Define alien work directory where all files will be copied. Relative to alien $HOME.
   plugin->SetGridWorkingDir("analysisITS");
   // Declare alien output directory. Relative to working directory.
   plugin->SetGridOutputDir("output151009"); // In this case will be $HOME/work/output
   // Declare the analysis source files names separated by blancs. To be compiled runtime
   // using ACLiC on the worker nodes.
   if(!uselibPWG1) {
     plugin->SetAnalysisSource("AliAlignmentDataFilterITS.cxx");
     plugin->SetAnalysisSource("AliTrackMatchingTPCITSCosmics.cxx");
   }
   // Declare all libraries (other than the default ones for the framework. These will be
   // loaded by the generated analysis macro. Add all extra files (task .cxx/.h) here.
   //plugin->SetAdditionalLibs("AliAlignmentDataFilterITS.h AliAlignmentDataFilterITS.cxx libProof.so libRAWDatabase.so libRAWDatarec.so libCDB.so libSTEER.so libITSbase.so libITSrec.so");
   plugin->AddIncludePath("-I. -I$ROOTSYS/include -I$ALICE_ROOT -I$ALICE_ROOT/include -I$ALICE_ROOT/ITS -I$ALICE_ROOT/TPC -I$ALICE_ROOT/CONTAINERS -I$ALICE_ROOT/STEER -I$ALICE_ROOT/TRD -I$ALICE_ROOT/macros -I$ALICE_ROOT/ANALYSIS -g");
   if(!uselibPWG1) {
     plugin->SetAdditionalLibs("AliAlignmentDataFilterITS.h AliAlignmentDataFilterITS.cxx AliTrackMatchingTPCITSCosmics.h AliTrackMatchingTPCITSCosmics.cxx libProof.so libRAWDatabase.so libRAWDatarec.so libCDB.so libSTEER.so libITSbase.so libITSrec.so");
   } else {
     plugin->SetAdditionalLibs("libGui.so libProof.so libMinuit.so libRAWDatabase.so libRAWDatarec.so libCDB.so libSTEER.so libITSbase.so libITSrec.so libTPCbase.so libTPCrec.so libTRDbase.so libTRDrec.so libTENDER.so libPWG1.so");
   }
   // Declare the output file names separated by blancs.
   // (can be like: file.root or file.root@ALICE::Niham::File)
   plugin->SetDefaultOutputs(kTRUE);
   // Optionally define the files to be archived.
   //   plugin->SetOutputArchive("log_archive.zip:stdout,stderr@ALICE::NIHAM::File root_archive.zip:*.root@ALICE::NIHAM::File");
   plugin->SetOutputArchive("log_archive.zip:stdout,stderr");
   // Optionally set a name for the generated analysis macro (default MyAnalysis.C)
   plugin->SetAnalysisMacro("AnalysisITS.C");
   // Optionally set maximum number of input files/subjob (default 100, put 0 to ignore)
   plugin->SetSplitMaxInputFileNumber(1);
   // Optionally set number of failed jobs that will trigger killing waiting sub-jobs.
   //plugin->SetMaxInitFailed(5);
   // Optionally resubmit threshold.
   //plugin->SetMasterResubmitThreshold(90);
   // Optionally set time to live (default 30000 sec)
   //plugin->SetTTL(20000);
   // Optionally set input format (default xml-single)
   plugin->SetInputFormat("xml-single");
   // Optionally modify the name of the generated JDL (default analysis.jdl)
   plugin->SetJDLName("TaskAnalysisITS.jdl");
   // Optionally modify job price (default 1)
   //plugin->SetPrice(1);
   // Optionally modify split mode (default 'se')
   plugin->SetSplitMode("se");
   // Optionally set the preferred SE
   plugin->SetPreferedSE("ALICE::CNAF::SE");

   return plugin;
}
//-----------------------------------------------------------------------------
TChain *CreateESDChain(TString esdpath=".",Int_t ifirst=-1,Int_t ilast=-1) {

  TChain *chainESD = new TChain("esdTree");

  if(ifirst<0) {
    chainESD->Add("AliESDs.root");
  } else {
    for(Int_t i=ifirst; i<=ilast; i++) {
      TString command=".! ln -s ";
      command+=esdpath.Data();
      command+=i;
      command+= "/AliESDs_def.root ";
      command+=esdpath.Data();
      command+=i;
      command+= "/AliESDs.root ";
      gROOT->ProcessLine(command.Data());
      command.ReplaceAll("AliESDs","AliESDfriends");
      gROOT->ProcessLine(command.Data());
      TString esdfile=esdpath; esdfile+=i; esdfile.Append("/AliESDs.root");
      chainESD->Add(esdfile.Data());
    }
  }

  return chainESD;
}
<|endoftext|>