<commit_before>/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** No Commercial Usage
**
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** GNU Lesser General Public License Usage
**
** Alternatively, 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.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**************************************************************************/

#include "qtsingleapplication.h"

#include <extensionsystem/pluginmanager.h>
#include <extensionsystem/pluginspec.h>
#include <extensionsystem/iplugin.h>

#include <QtCore/QDir>
#include <QtCore/QUrl>
#include <QtCore/QTextStream>
#include <QtCore/QFileInfo>
#include <QtCore/QDebug>
#include <QtCore/QTimer>
#include <QtCore/QLibraryInfo>
#include <QtCore/QTranslator>
#include <QtCore/QSettings>
#include <QtCore/QVariant>
#include <QtCore/QThreadPool>

#include <QtNetwork/QNetworkProxyFactory>

#include <QtGui/QMessageBox>
#include <QtGui/QApplication>
#include <QtGui/QMainWindow>

#ifdef ENABLE_QT_BREAKPAD
#include <qtsystemexceptionhandler.h>
#endif

enum { OptionIndent = 4, DescriptionIndent = 24 };

static const char *appNameC = "Qt Creator";
static const char *corePluginNameC = "Core";
static const char *fixedOptionsC =
" [OPTION]... [FILE]...\n"
"Options:\n"
"    -help               Display this help\n"
"    -version            Display program version\n"
"    -client             Attempt to connect to already running instance\n";

static const char *HELP_OPTION1 = "-h";
static const char *HELP_OPTION2 = "-help";
static const char *HELP_OPTION3 = "/h";
static const char *HELP_OPTION4 = "--help";
static const char *VERSION_OPTION = "-version";
static const char *CLIENT_OPTION = "-client";

typedef QList<ExtensionSystem::PluginSpec *> PluginSpecSet;

// Helpers for displaying messages. Note that there is no console on Windows.
#ifdef Q_OS_WIN
// Format as
 HTML
static inline void toHtml(QString &t)
{
    t.replace(QLatin1Char('&'), QLatin1String("&"));
    t.replace(QLatin1Char('<'), QLatin1String("<"));
    t.replace(QLatin1Char('>'), QLatin1String(">"));
    t.insert(0, QLatin1String("
"));
    t.append(QLatin1String("
"));
}

static void displayHelpText(QString t) // No console on Windows.
{
    toHtml(t);
    QMessageBox::information(0, QLatin1String(appNameC), t);
}

static void displayError(const QString &t) // No console on Windows.
{
    QMessageBox::critical(0, QLatin1String(appNameC), t);
}

#else

static void displayHelpText(const QString &t)
{
    qWarning("%s", qPrintable(t));
}

static void displayError(const QString &t)
{
    qCritical("%s", qPrintable(t));
}

#endif

static void printVersion(const ExtensionSystem::PluginSpec *coreplugin,
                         const ExtensionSystem::PluginManager &pm)
{
    QString version;
    QTextStream str(&version);
    str << '\n' << appNameC << ' ' << coreplugin->version()<< " based on Qt " << qVersion() << "\n\n";
    pm.formatPluginVersions(str);
    str << '\n' << coreplugin->copyright() << '\n';
    displayHelpText(version);
}

static void printHelp(const QString &a0, const ExtensionSystem::PluginManager &pm)
{
    QString help;
    QTextStream str(&help);
    str << "Usage: " << a0  << fixedOptionsC;
    ExtensionSystem::PluginManager::formatOptions(str, OptionIndent, DescriptionIndent);
    pm.formatPluginOptions(str,  OptionIndent, DescriptionIndent);
    displayHelpText(help);
}

static inline QString msgCoreLoadFailure(const QString &why)
{
    return QCoreApplication::translate("Application", "Failed to load core: %1").arg(why);
}

static inline QString msgSendArgumentFailed()
{
    return QCoreApplication::translate("Application", "Unable to send command line arguments to the already running instance. It appears to be not responding.");
}

static inline QStringList getPluginPaths()
{
    QStringList rc;
    // Figure out root:  Up one from 'bin'
    QDir rootDir = QApplication::applicationDirPath();
    rootDir.cdUp();
    const QString rootDirPath = rootDir.canonicalPath();
    // 1) "plugins" (Win/Linux)
    QString pluginPath = rootDirPath;
    pluginPath += QLatin1Char('/');
    pluginPath += QLatin1String(IDE_LIBRARY_BASENAME);
    pluginPath += QLatin1Char('/');
    pluginPath += QLatin1String("qtcreator");
    pluginPath += QLatin1Char('/');
    pluginPath += QLatin1String("plugins");
    rc.push_back(pluginPath);
    // 2) "PlugIns" (OS X)
    pluginPath = rootDirPath;
    pluginPath += QLatin1Char('/');
    pluginPath += QLatin1String("PlugIns");
    rc.push_back(pluginPath);
    return rc;
}

#ifdef Q_OS_MAC
#  define SHARE_PATH "/../Resources"
#else
#  define SHARE_PATH "/../share/qtcreator"
#endif

int main(int argc, char **argv)
{
#ifdef Q_OS_MAC
    // increase the number of file that can be opened in Qt Creator.
    struct rlimit rl;
    getrlimit(RLIMIT_NOFILE, &rl);

    rl.rlim_cur = qMin((rlim_t)OPEN_MAX, rl.rlim_max);
    setrlimit(RLIMIT_NOFILE, &rl);
#endif

    SharedTools::QtSingleApplication app((QLatin1String(appNameC)), argc, argv);

    const int threadCount = QThreadPool::globalInstance()->maxThreadCount();
    QThreadPool::globalInstance()->setMaxThreadCount(qMax(4, 2 * threadCount));

#ifdef ENABLE_QT_BREAKPAD
    QtSystemExceptionHandler systemExceptionHandler;
#endif

    QTranslator translator;
    QTranslator qtTranslator;
    QString locale = QLocale::system().name();

    // Must be done before any QSettings class is created
    QSettings::setPath(QSettings::IniFormat, QSettings::SystemScope,
            QCoreApplication::applicationDirPath()+QLatin1String(SHARE_PATH));
    // keep this in sync with the MainWindow ctor in coreplugin/mainwindow.cpp
    const QSettings settings(QSettings::IniFormat, QSettings::UserScope,
                                 QLatin1String("Nokia"), QLatin1String("QtCreator"));
    locale = settings.value("General/OverrideLanguage", locale).toString();

    const QString &creatorTrPath = QCoreApplication::applicationDirPath()
                        + QLatin1String(SHARE_PATH "/translations");
    if (translator.load(QLatin1String("qtcreator_") + locale, creatorTrPath)) {
        const QString &qtTrPath = QLibraryInfo::location(QLibraryInfo::TranslationsPath);
        const QString &qtTrFile = QLatin1String("qt_") + locale;
        // Binary installer puts Qt tr files into creatorTrPath
        if (qtTranslator.load(qtTrFile, qtTrPath) || qtTranslator.load(qtTrFile, creatorTrPath)) {
            app.installTranslator(&translator);
            app.installTranslator(&qtTranslator);
            app.setProperty("qtc_locale", locale);
        } else {
            translator.load(QString()); // unload()
        }
    }

    // Make sure we honor the system's proxy settings
#if defined(Q_OS_UNIX) && !defined(Q_OS_MAC)
    QUrl proxyUrl(QString::fromLatin1(qgetenv("http_proxy")));
    if (proxyUrl.isValid()) {
        QNetworkProxy proxy(QNetworkProxy::HttpCachingProxy, proxyUrl.host(),
                            proxyUrl.port(), proxyUrl.userName(), proxyUrl.password());
        QNetworkProxy::setApplicationProxy(proxy);
    }
#else
    QNetworkProxyFactory::setUseSystemConfiguration(true);
#endif
    // Load
    ExtensionSystem::PluginManager pluginManager;
    pluginManager.setFileExtension(QLatin1String("pluginspec"));

    const QStringList pluginPaths = getPluginPaths();
    pluginManager.setPluginPaths(pluginPaths);

    const QStringList arguments = app.arguments();
    QMap<QString, QString> foundAppOptions;
    if (arguments.size() > 1) {
        QMap<QString, bool> appOptions;
        appOptions.insert(QLatin1String(HELP_OPTION1), false);
        appOptions.insert(QLatin1String(HELP_OPTION2), false);
        appOptions.insert(QLatin1String(HELP_OPTION3), false);
        appOptions.insert(QLatin1String(HELP_OPTION4), false);
        appOptions.insert(QLatin1String(VERSION_OPTION), false);
        appOptions.insert(QLatin1String(CLIENT_OPTION), false);
        QString errorMessage;
        if (!pluginManager.parseOptions(arguments,
                                        appOptions,
                                        &foundAppOptions,
                                        &errorMessage)) {
            displayError(errorMessage);
            printHelp(QFileInfo(app.applicationFilePath()).baseName(), pluginManager);
            return -1;
        }
    }

    const PluginSpecSet plugins = pluginManager.plugins();
    ExtensionSystem::PluginSpec *coreplugin = 0;
    foreach (ExtensionSystem::PluginSpec *spec, plugins) {
        if (spec->name() == QLatin1String(corePluginNameC)) {
            coreplugin = spec;
            break;
        }
    }
    if (!coreplugin) {
        QString nativePaths = QDir::toNativeSeparators(pluginPaths.join(QLatin1String(",")));
        const QString reason = QCoreApplication::translate("Application", "Could not find 'Core.pluginspec' in %1").arg(nativePaths);
        displayError(msgCoreLoadFailure(reason));
        return 1;
    }
    if (coreplugin->hasError()) {
        displayError(msgCoreLoadFailure(coreplugin->errorString()));
        return 1;
    }
    if (foundAppOptions.contains(QLatin1String(VERSION_OPTION))) {
        printVersion(coreplugin, pluginManager);
        return 0;
    }
    if (foundAppOptions.contains(QLatin1String(HELP_OPTION1))
            || foundAppOptions.contains(QLatin1String(HELP_OPTION2))
            || foundAppOptions.contains(QLatin1String(HELP_OPTION3))
            || foundAppOptions.contains(QLatin1String(HELP_OPTION4))) {
        printHelp(QFileInfo(app.applicationFilePath()).baseName(), pluginManager);
        return 0;
    }

    const bool isFirstInstance = !app.isRunning();
    if (!isFirstInstance && foundAppOptions.contains(QLatin1String(CLIENT_OPTION))) {
        if (!app.sendMessage(pluginManager.serializedArguments())) {
            displayError(msgSendArgumentFailed());
            return -1;
        }
        return 0;
    }

    pluginManager.loadPlugins();
    if (coreplugin->hasError()) {
        displayError(msgCoreLoadFailure(coreplugin->errorString()));
        return 1;
    }
    {
        QStringList errors;
        foreach (ExtensionSystem::PluginSpec *p, pluginManager.plugins())
            // only show errors on startup if plugin is enabled.
            if (p->hasError() && p->isEnabled() && !p->isDisabledIndirectly())
                errors.append(p->name() + "\n" + p->errorString());
        if (!errors.isEmpty())
            QMessageBox::warning(0,
                QCoreApplication::translate("Application", "Qt Creator - Plugin loader messages"),
                errors.join(QString::fromLatin1("\n\n")));
    }

    if (isFirstInstance) {
        // Set up lock and remote arguments for the first instance only.
        // Silently fallback to unconnected instances for any subsequent
        // instances.
        app.initialize();
        QObject::connect(&app, SIGNAL(messageReceived(QString)),
                         &pluginManager, SLOT(remoteArguments(QString)));
    }
    QObject::connect(&app, SIGNAL(fileOpenRequest(QString)), coreplugin->plugin(), SLOT(fileOpenRequest(QString)));

    // shutdown plugin manager on the exit
    QObject::connect(&app, SIGNAL(aboutToQuit()), &pluginManager, SLOT(shutdown()));

    // Do this after the event loop has started
    QTimer::singleShot(100, &pluginManager, SLOT(startTests()));

    return app.exec();
}

<commit_msg>Fix the manual proxy hack for Linux so it works with HTTPS<commit_after>/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** No Commercial Usage
**
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** GNU Lesser General Public License Usage
**
** Alternatively, 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.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**************************************************************************/

#include "qtsingleapplication.h"

#include <extensionsystem/pluginmanager.h>
#include <extensionsystem/pluginspec.h>
#include <extensionsystem/iplugin.h>

#include <QtCore/QDir>
#include <QtCore/QUrl>
#include <QtCore/QTextStream>
#include <QtCore/QFileInfo>
#include <QtCore/QDebug>
#include <QtCore/QTimer>
#include <QtCore/QLibraryInfo>
#include <QtCore/QTranslator>
#include <QtCore/QSettings>
#include <QtCore/QVariant>
#include <QtCore/QThreadPool>

#include <QtNetwork/QNetworkProxyFactory>

#include <QtGui/QMessageBox>
#include <QtGui/QApplication>
#include <QtGui/QMainWindow>

#ifdef ENABLE_QT_BREAKPAD
#include <qtsystemexceptionhandler.h>
#endif

enum { OptionIndent = 4, DescriptionIndent = 24 };

static const char *appNameC = "Qt Creator";
static const char *corePluginNameC = "Core";
static const char *fixedOptionsC =
" [OPTION]... [FILE]...\n"
"Options:\n"
"    -help               Display this help\n"
"    -version            Display program version\n"
"    -client             Attempt to connect to already running instance\n";

static const char *HELP_OPTION1 = "-h";
static const char *HELP_OPTION2 = "-help";
static const char *HELP_OPTION3 = "/h";
static const char *HELP_OPTION4 = "--help";
static const char *VERSION_OPTION = "-version";
static const char *CLIENT_OPTION = "-client";

typedef QList<ExtensionSystem::PluginSpec *> PluginSpecSet;

// Helpers for displaying messages. Note that there is no console on Windows.
#ifdef Q_OS_WIN
// Format as
 HTML
static inline void toHtml(QString &t)
{
    t.replace(QLatin1Char('&'), QLatin1String("&"));
    t.replace(QLatin1Char('<'), QLatin1String("<"));
    t.replace(QLatin1Char('>'), QLatin1String(">"));
    t.insert(0, QLatin1String("
"));
    t.append(QLatin1String("
"));
}

static void displayHelpText(QString t) // No console on Windows.
{
    toHtml(t);
    QMessageBox::information(0, QLatin1String(appNameC), t);
}

static void displayError(const QString &t) // No console on Windows.
{
    QMessageBox::critical(0, QLatin1String(appNameC), t);
}

#else

static void displayHelpText(const QString &t)
{
    qWarning("%s", qPrintable(t));
}

static void displayError(const QString &t)
{
    qCritical("%s", qPrintable(t));
}

#endif

static void printVersion(const ExtensionSystem::PluginSpec *coreplugin,
                         const ExtensionSystem::PluginManager &pm)
{
    QString version;
    QTextStream str(&version);
    str << '\n' << appNameC << ' ' << coreplugin->version()<< " based on Qt " << qVersion() << "\n\n";
    pm.formatPluginVersions(str);
    str << '\n' << coreplugin->copyright() << '\n';
    displayHelpText(version);
}

static void printHelp(const QString &a0, const ExtensionSystem::PluginManager &pm)
{
    QString help;
    QTextStream str(&help);
    str << "Usage: " << a0  << fixedOptionsC;
    ExtensionSystem::PluginManager::formatOptions(str, OptionIndent, DescriptionIndent);
    pm.formatPluginOptions(str,  OptionIndent, DescriptionIndent);
    displayHelpText(help);
}

static inline QString msgCoreLoadFailure(const QString &why)
{
    return QCoreApplication::translate("Application", "Failed to load core: %1").arg(why);
}

static inline QString msgSendArgumentFailed()
{
    return QCoreApplication::translate("Application", "Unable to send command line arguments to the already running instance. It appears to be not responding.");
}

static inline QStringList getPluginPaths()
{
    QStringList rc;
    // Figure out root:  Up one from 'bin'
    QDir rootDir = QApplication::applicationDirPath();
    rootDir.cdUp();
    const QString rootDirPath = rootDir.canonicalPath();
    // 1) "plugins" (Win/Linux)
    QString pluginPath = rootDirPath;
    pluginPath += QLatin1Char('/');
    pluginPath += QLatin1String(IDE_LIBRARY_BASENAME);
    pluginPath += QLatin1Char('/');
    pluginPath += QLatin1String("qtcreator");
    pluginPath += QLatin1Char('/');
    pluginPath += QLatin1String("plugins");
    rc.push_back(pluginPath);
    // 2) "PlugIns" (OS X)
    pluginPath = rootDirPath;
    pluginPath += QLatin1Char('/');
    pluginPath += QLatin1String("PlugIns");
    rc.push_back(pluginPath);
    return rc;
}

#ifdef Q_OS_MAC
#  define SHARE_PATH "/../Resources"
#else
#  define SHARE_PATH "/../share/qtcreator"
#endif

int main(int argc, char **argv)
{
#ifdef Q_OS_MAC
    // increase the number of file that can be opened in Qt Creator.
    struct rlimit rl;
    getrlimit(RLIMIT_NOFILE, &rl);

    rl.rlim_cur = qMin((rlim_t)OPEN_MAX, rl.rlim_max);
    setrlimit(RLIMIT_NOFILE, &rl);
#endif

    SharedTools::QtSingleApplication app((QLatin1String(appNameC)), argc, argv);

    const int threadCount = QThreadPool::globalInstance()->maxThreadCount();
    QThreadPool::globalInstance()->setMaxThreadCount(qMax(4, 2 * threadCount));

#ifdef ENABLE_QT_BREAKPAD
    QtSystemExceptionHandler systemExceptionHandler;
#endif

    QTranslator translator;
    QTranslator qtTranslator;
    QString locale = QLocale::system().name();

    // Must be done before any QSettings class is created
    QSettings::setPath(QSettings::IniFormat, QSettings::SystemScope,
            QCoreApplication::applicationDirPath()+QLatin1String(SHARE_PATH));
    // keep this in sync with the MainWindow ctor in coreplugin/mainwindow.cpp
    const QSettings settings(QSettings::IniFormat, QSettings::UserScope,
                                 QLatin1String("Nokia"), QLatin1String("QtCreator"));
    locale = settings.value("General/OverrideLanguage", locale).toString();

    const QString &creatorTrPath = QCoreApplication::applicationDirPath()
                        + QLatin1String(SHARE_PATH "/translations");
    if (translator.load(QLatin1String("qtcreator_") + locale, creatorTrPath)) {
        const QString &qtTrPath = QLibraryInfo::location(QLibraryInfo::TranslationsPath);
        const QString &qtTrFile = QLatin1String("qt_") + locale;
        // Binary installer puts Qt tr files into creatorTrPath
        if (qtTranslator.load(qtTrFile, qtTrPath) || qtTranslator.load(qtTrFile, creatorTrPath)) {
            app.installTranslator(&translator);
            app.installTranslator(&qtTranslator);
            app.setProperty("qtc_locale", locale);
        } else {
            translator.load(QString()); // unload()
        }
    }

    // Make sure we honor the system's proxy settings
#if defined(Q_OS_UNIX) && !defined(Q_OS_MAC)
    QUrl proxyUrl(QString::fromLatin1(qgetenv("http_proxy")));
    if (proxyUrl.isValid()) {
        QNetworkProxy proxy(QNetworkProxy::HttpProxy, proxyUrl.host(),
                            proxyUrl.port(), proxyUrl.userName(), proxyUrl.password());
        QNetworkProxy::setApplicationProxy(proxy);
    }
#else
    QNetworkProxyFactory::setUseSystemConfiguration(true);
#endif
    // Load
    ExtensionSystem::PluginManager pluginManager;
    pluginManager.setFileExtension(QLatin1String("pluginspec"));

    const QStringList pluginPaths = getPluginPaths();
    pluginManager.setPluginPaths(pluginPaths);

    const QStringList arguments = app.arguments();
    QMap<QString, QString> foundAppOptions;
    if (arguments.size() > 1) {
        QMap<QString, bool> appOptions;
        appOptions.insert(QLatin1String(HELP_OPTION1), false);
        appOptions.insert(QLatin1String(HELP_OPTION2), false);
        appOptions.insert(QLatin1String(HELP_OPTION3), false);
        appOptions.insert(QLatin1String(HELP_OPTION4), false);
        appOptions.insert(QLatin1String(VERSION_OPTION), false);
        appOptions.insert(QLatin1String(CLIENT_OPTION), false);
        QString errorMessage;
        if (!pluginManager.parseOptions(arguments,
                                        appOptions,
                                        &foundAppOptions,
                                        &errorMessage)) {
            displayError(errorMessage);
            printHelp(QFileInfo(app.applicationFilePath()).baseName(), pluginManager);
            return -1;
        }
    }

    const PluginSpecSet plugins = pluginManager.plugins();
    ExtensionSystem::PluginSpec *coreplugin = 0;
    foreach (ExtensionSystem::PluginSpec *spec, plugins) {
        if (spec->name() == QLatin1String(corePluginNameC)) {
            coreplugin = spec;
            break;
        }
    }
    if (!coreplugin) {
        QString nativePaths = QDir::toNativeSeparators(pluginPaths.join(QLatin1String(",")));
        const QString reason = QCoreApplication::translate("Application", "Could not find 'Core.pluginspec' in %1").arg(nativePaths);
        displayError(msgCoreLoadFailure(reason));
        return 1;
    }
    if (coreplugin->hasError()) {
        displayError(msgCoreLoadFailure(coreplugin->errorString()));
        return 1;
    }
    if (foundAppOptions.contains(QLatin1String(VERSION_OPTION))) {
        printVersion(coreplugin, pluginManager);
        return 0;
    }
    if (foundAppOptions.contains(QLatin1String(HELP_OPTION1))
            || foundAppOptions.contains(QLatin1String(HELP_OPTION2))
            || foundAppOptions.contains(QLatin1String(HELP_OPTION3))
            || foundAppOptions.contains(QLatin1String(HELP_OPTION4))) {
        printHelp(QFileInfo(app.applicationFilePath()).baseName(), pluginManager);
        return 0;
    }

    const bool isFirstInstance = !app.isRunning();
    if (!isFirstInstance && foundAppOptions.contains(QLatin1String(CLIENT_OPTION))) {
        if (!app.sendMessage(pluginManager.serializedArguments())) {
            displayError(msgSendArgumentFailed());
            return -1;
        }
        return 0;
    }

    pluginManager.loadPlugins();
    if (coreplugin->hasError()) {
        displayError(msgCoreLoadFailure(coreplugin->errorString()));
        return 1;
    }
    {
        QStringList errors;
        foreach (ExtensionSystem::PluginSpec *p, pluginManager.plugins())
            // only show errors on startup if plugin is enabled.
            if (p->hasError() && p->isEnabled() && !p->isDisabledIndirectly())
                errors.append(p->name() + "\n" + p->errorString());
        if (!errors.isEmpty())
            QMessageBox::warning(0,
                QCoreApplication::translate("Application", "Qt Creator - Plugin loader messages"),
                errors.join(QString::fromLatin1("\n\n")));
    }

    if (isFirstInstance) {
        // Set up lock and remote arguments for the first instance only.
        // Silently fallback to unconnected instances for any subsequent
        // instances.
        app.initialize();
        QObject::connect(&app, SIGNAL(messageReceived(QString)),
                         &pluginManager, SLOT(remoteArguments(QString)));
    }
    QObject::connect(&app, SIGNAL(fileOpenRequest(QString)), coreplugin->plugin(), SLOT(fileOpenRequest(QString)));

    // shutdown plugin manager on the exit
    QObject::connect(&app, SIGNAL(aboutToQuit()), &pluginManager, SLOT(shutdown()));

    // Do this after the event loop has started
    QTimer::singleShot(100, &pluginManager, SLOT(startTests()));

    return app.exec();
}

<|endoftext|>


<commit_before>#ifndef STAN_MATH_OPENCL_KERNEL_GENERATOR_LOAD_HPP
#define STAN_MATH_OPENCL_KERNEL_GENERATOR_LOAD_HPP
#ifdef STAN_OPENCL

#include <stan/math/opencl/matrix_cl.hpp>
#include <stan/math/opencl/matrix_cl_view.hpp>
#include <stan/math/opencl/kernel_generator/type_str.hpp>
#include <stan/math/opencl/kernel_generator/name_generator.hpp>
#include <stan/math/opencl/kernel_generator/operation_cl.hpp>
#include <stan/math/opencl/kernel_generator/operation_cl_lhs.hpp>
#include <type_traits>
#include <string>
#include <utility>
#include <set>

namespace stan {
namespace math {

/**
 * Represents an access to a \c matrix_cl in kernel generator expressions
 * @tparam T \c matrix_cl
 */
template <typename T>
class load_
    : public operation_cl_lhs<load_<T>,
                              typename std::remove_reference_t<T>::type> {
 protected:
  T a_;

 public:
  using Scalar = typename std::remove_reference_t<T>::type;
  using base = operation_cl<load_<T>, Scalar>;
  using base::var_name;
  static_assert(std::is_base_of<matrix_cl<Scalar>,
                                typename std::remove_reference_t<T>>::value,
                "load_: argument a must be a matrix_cl<T>!");
  static_assert(
      std::is_arithmetic<Scalar>::value,
      "load_: T in \"matrix_cl<T> a\" argument must be an arithmetic type!");

  /**
   * Constructor
   * @param a \c matrix_cl
   */
  explicit load_(T&& a) : a_(std::forward<T>(a)) {}

  /**
   * Creates a deep copy of this expression.
   * @return copy of \c *this
   */
  inline load_<T&> deep_copy() const & { return load_<T&>(a_); }
  inline load_<T> deep_copy() && { return load_<T>(std::forward<T>(a_)); }

  /**
   * generates kernel code for this expression.
   * @param i row index variable name
   * @param j column index variable name
   * @return part of kernel with code for this expression
   */
  inline kernel_parts generate(const std::string& i,
                               const std::string& j) const {
    kernel_parts res{};
    std::string type = type_str<Scalar>();
    res.body = type + " " + var_name + " = 0;"
               " if (!((!contains_nonzero(" + var_name + "_view, LOWER) && "
               + j + " < " + i + ") || (!contains_nonzero(" + var_name +
               "_view, UPPER) && " + j + " > " + i + "))) {"
               + var_name + " = " + var_name + "_global[" + i + " + " +
               var_name + "_rows * " + j + "];}\n";
    res.args = "__global " + type + "* " + var_name + "_global, int " + var_name
               + "_rows, int " + var_name + "_view, ";
    return res;
  }

  /**
   * generates kernel code for this expression if it appears on the left hand
   * side of an assignment.
   * @param i row index variable name
   * @param j column index variable name
   * @return part of kernel with code for this expressions
   */
  inline kernel_parts generate_lhs(const std::string& i,
                                   const std::string& j) const {
    kernel_parts res;
    std::string type = type_str<Scalar>();
    res.args = "__global " + type + "* " + var_name + "_global, int " + var_name
               + "_rows, int " + var_name + "_view, ";
    res.body
        = var_name + "_global[" + i + " + " + var_name + "_rows * " + j + "]";
    return res;
  }

  /**
   * Sets kernel arguments for this expression.
   * @param[in,out] generated set of expressions that already set their kernel
   * arguments
   * @param kernel kernel to set arguments on
   * @param[in,out] arg_num consecutive number of the first argument to set.
   * This is incremented for each argument set by this function.
   */
  inline void set_args(std::set<const operation_cl_base*>& generated,
                       cl::Kernel& kernel, int& arg_num) const {
    if (generated.count(this) == 0) {
      generated.insert(this);
      kernel.setArg(arg_num++, a_.buffer());
      kernel.setArg(arg_num++, a_.rows());
      kernel.setArg(arg_num++, a_.view());
    }
  }

  /**
   * Adds read event to the matrix used in this expression.
   * @param e the event to add
   */
  inline void add_read_event(cl::Event& e) const { a_.add_read_event(e); }

  /**
   * Adds write event to the matrix used in this expression.
   * @param e the event to add
   */
  inline void add_write_event(cl::Event& e) const { a_.add_write_event(e); }

  /**
   * Number of rows of a matrix that would be the result of evaluating this
   * expression.
   * @return number of rows
   */
  inline int rows() const { return a_.rows(); }

  /**
   * Number of columns of a matrix that would be the result of evaluating this
   * expression.
   * @return number of columns
   */
  inline int cols() const { return a_.cols(); }

  /**
   * View of a matrix that would be the result of evaluating this expression.
   * @return view
   */
  inline matrix_cl_view view() const { return a_.view(); }

  /**
   * Sets view of the matrix depending on which part is written.
   * @param bottom_diagonal Index of the top sub- or super- diagonal written
   * with nonzero elements.
   * @param top_diagonal Index of the top sub- or super- diagonal written with
   * nonzero elements.
   * @param bottom_zero_diagonal Index of the top sub- or super- diagonal
   * written with zeros if it ie more extreme than \c bottom_diagonal. Otherwise
   * it should be set to equal value as \c bottom_diagonal.
   * @param top_zero_diagonal Index of the top sub- or super- diagonal written
   * with zeros if it ie more extreme than \c top_diagonal. Otherwise it should
   * be set to equal value as \c top_diagonal.
   */
  inline void set_view(int bottom_diagonal, int top_diagonal,
                       int bottom_zero_diagonal, int top_zero_diagonal) const {
    if (bottom_diagonal < 0) {
      a_.view(either(a_.view(), matrix_cl_view::Lower));
    } else if (bottom_zero_diagonal <= 1 - a_.rows()) {
      a_.view(both(a_.view(), matrix_cl_view::Upper));
    }
    if (top_diagonal > 0) {
      a_.view(either(a_.view(), matrix_cl_view::Upper));
    } else if (top_zero_diagonal >= a_.cols() - 1) {
      a_.view(both(a_.view(), matrix_cl_view::Lower));
    }
  }

  /**
   * Determine index of bottom diagonal written.
   * @return number of columns
   */
  inline int bottom_diagonal() const {
    return contains_nonzero(a_.view(), matrix_cl_view::Lower) ? -a_.rows() + 1
                                                              : 0;
  }

  /**
   * Determine index of top diagonal written.
   * @return number of columns
   */
  inline int top_diagonal() const {
    return contains_nonzero(a_.view(), matrix_cl_view::Upper) ? a_.cols() - 1
                                                              : 0;
  }

  /**
   * Evaluates the expression. \c load_ returns a const reference to stored
   * matrix_cl.
   * @return Result of the expression.
   */
  const T& eval() const { return a_; }

  /**
   * If needed resizes underlying matrix to desired number of rows and cols.
   * @param rows desired number of rows
   * @param cols desired number of columns
   */
  inline void check_assign_dimensions(int rows, int cols) const {
    if (a_.rows() != rows || a_.cols() != cols) {
      a_ = matrix_cl<Scalar>(rows, cols);
    }
  }
};

}  // namespace math
}  // namespace stan

#endif
#endif
<commit_msg>[Jenkins] auto-formatting by clang-format version 6.0.0 (tags/google/stable/2017-11-14)<commit_after>#ifndef STAN_MATH_OPENCL_KERNEL_GENERATOR_LOAD_HPP
#define STAN_MATH_OPENCL_KERNEL_GENERATOR_LOAD_HPP
#ifdef STAN_OPENCL

#include <stan/math/opencl/matrix_cl.hpp>
#include <stan/math/opencl/matrix_cl_view.hpp>
#include <stan/math/opencl/kernel_generator/type_str.hpp>
#include <stan/math/opencl/kernel_generator/name_generator.hpp>
#include <stan/math/opencl/kernel_generator/operation_cl.hpp>
#include <stan/math/opencl/kernel_generator/operation_cl_lhs.hpp>
#include <type_traits>
#include <string>
#include <utility>
#include <set>

namespace stan {
namespace math {

/**
 * Represents an access to a \c matrix_cl in kernel generator expressions
 * @tparam T \c matrix_cl
 */
template <typename T>
class load_
    : public operation_cl_lhs<load_<T>,
                              typename std::remove_reference_t<T>::type> {
 protected:
  T a_;

 public:
  using Scalar = typename std::remove_reference_t<T>::type;
  using base = operation_cl<load_<T>, Scalar>;
  using base::var_name;
  static_assert(std::is_base_of<matrix_cl<Scalar>,
                                typename std::remove_reference_t<T>>::value,
                "load_: argument a must be a matrix_cl<T>!");
  static_assert(
      std::is_arithmetic<Scalar>::value,
      "load_: T in \"matrix_cl<T> a\" argument must be an arithmetic type!");

  /**
   * Constructor
   * @param a \c matrix_cl
   */
  explicit load_(T&& a) : a_(std::forward<T>(a)) {}

  /**
   * Creates a deep copy of this expression.
   * @return copy of \c *this
   */
  inline load_<T&> deep_copy() const& { return load_<T&>(a_); }
  inline load_<T> deep_copy() && { return load_<T>(std::forward<T>(a_)); }

  /**
   * generates kernel code for this expression.
   * @param i row index variable name
   * @param j column index variable name
   * @return part of kernel with code for this expression
   */
  inline kernel_parts generate(const std::string& i,
                               const std::string& j) const {
    kernel_parts res{};
    std::string type = type_str<Scalar>();
    res.body = type + " " + var_name + " = 0;"
               " if (!((!contains_nonzero(" + var_name + "_view, LOWER) && "
               + j + " < " + i + ") || (!contains_nonzero(" + var_name +
               "_view, UPPER) && " + j + " > " + i + "))) {"
               + var_name + " = " + var_name + "_global[" + i + " + " +
               var_name + "_rows * " + j + "];}\n";
    res.args = "__global " + type + "* " + var_name + "_global, int " + var_name
               + "_rows, int " + var_name + "_view, ";
    return res;
  }

  /**
   * generates kernel code for this expression if it appears on the left hand
   * side of an assignment.
   * @param i row index variable name
   * @param j column index variable name
   * @return part of kernel with code for this expressions
   */
  inline kernel_parts generate_lhs(const std::string& i,
                                   const std::string& j) const {
    kernel_parts res;
    std::string type = type_str<Scalar>();
    res.args = "__global " + type + "* " + var_name + "_global, int " + var_name
               + "_rows, int " + var_name + "_view, ";
    res.body
        = var_name + "_global[" + i + " + " + var_name + "_rows * " + j + "]";
    return res;
  }

  /**
   * Sets kernel arguments for this expression.
   * @param[in,out] generated set of expressions that already set their kernel
   * arguments
   * @param kernel kernel to set arguments on
   * @param[in,out] arg_num consecutive number of the first argument to set.
   * This is incremented for each argument set by this function.
   */
  inline void set_args(std::set<const operation_cl_base*>& generated,
                       cl::Kernel& kernel, int& arg_num) const {
    if (generated.count(this) == 0) {
      generated.insert(this);
      kernel.setArg(arg_num++, a_.buffer());
      kernel.setArg(arg_num++, a_.rows());
      kernel.setArg(arg_num++, a_.view());
    }
  }

  /**
   * Adds read event to the matrix used in this expression.
   * @param e the event to add
   */
  inline void add_read_event(cl::Event& e) const { a_.add_read_event(e); }

  /**
   * Adds write event to the matrix used in this expression.
   * @param e the event to add
   */
  inline void add_write_event(cl::Event& e) const { a_.add_write_event(e); }

  /**
   * Number of rows of a matrix that would be the result of evaluating this
   * expression.
   * @return number of rows
   */
  inline int rows() const { return a_.rows(); }

  /**
   * Number of columns of a matrix that would be the result of evaluating this
   * expression.
   * @return number of columns
   */
  inline int cols() const { return a_.cols(); }

  /**
   * View of a matrix that would be the result of evaluating this expression.
   * @return view
   */
  inline matrix_cl_view view() const { return a_.view(); }

  /**
   * Sets view of the matrix depending on which part is written.
   * @param bottom_diagonal Index of the top sub- or super- diagonal written
   * with nonzero elements.
   * @param top_diagonal Index of the top sub- or super- diagonal written with
   * nonzero elements.
   * @param bottom_zero_diagonal Index of the top sub- or super- diagonal
   * written with zeros if it ie more extreme than \c bottom_diagonal. Otherwise
   * it should be set to equal value as \c bottom_diagonal.
   * @param top_zero_diagonal Index of the top sub- or super- diagonal written
   * with zeros if it ie more extreme than \c top_diagonal. Otherwise it should
   * be set to equal value as \c top_diagonal.
   */
  inline void set_view(int bottom_diagonal, int top_diagonal,
                       int bottom_zero_diagonal, int top_zero_diagonal) const {
    if (bottom_diagonal < 0) {
      a_.view(either(a_.view(), matrix_cl_view::Lower));
    } else if (bottom_zero_diagonal <= 1 - a_.rows()) {
      a_.view(both(a_.view(), matrix_cl_view::Upper));
    }
    if (top_diagonal > 0) {
      a_.view(either(a_.view(), matrix_cl_view::Upper));
    } else if (top_zero_diagonal >= a_.cols() - 1) {
      a_.view(both(a_.view(), matrix_cl_view::Lower));
    }
  }

  /**
   * Determine index of bottom diagonal written.
   * @return number of columns
   */
  inline int bottom_diagonal() const {
    return contains_nonzero(a_.view(), matrix_cl_view::Lower) ? -a_.rows() + 1
                                                              : 0;
  }

  /**
   * Determine index of top diagonal written.
   * @return number of columns
   */
  inline int top_diagonal() const {
    return contains_nonzero(a_.view(), matrix_cl_view::Upper) ? a_.cols() - 1
                                                              : 0;
  }

  /**
   * Evaluates the expression. \c load_ returns a const reference to stored
   * matrix_cl.
   * @return Result of the expression.
   */
  const T& eval() const { return a_; }

  /**
   * If needed resizes underlying matrix to desired number of rows and cols.
   * @param rows desired number of rows
   * @param cols desired number of columns
   */
  inline void check_assign_dimensions(int rows, int cols) const {
    if (a_.rows() != rows || a_.cols() != cols) {
      a_ = matrix_cl<Scalar>(rows, cols);
    }
  }
};

}  // namespace math
}  // namespace stan

#endif
#endif
<|endoftext|>


<commit_before>#ifndef STAN_MATH_PRIM_FUN_GENERALIZED_INVERSE_HPP
#define STAN_MATH_PRIM_FUN_GENERALIZED_INVERSE_HPP

#include <stan/math/prim/meta.hpp>
#include <stan/math/prim/err.hpp>
#include <stan/math/prim/fun/Eigen.hpp>
#include <stan/math/prim/fun/chol2inv.hpp>
#include <stan/math/prim/fun/add_diag.hpp>
#include <stan/math/prim/fun/rep_vector.hpp>
#include <stan/math/prim/fun/cholesky_decompose.hpp>
#include <stan/math/prim/fun/transpose.hpp>
#include <stan/math/prim/fun/tcrossprod.hpp>
#include <stan/math/prim/fun/crossprod.hpp>

namespace stan {
namespace math {

/**
 * Returns the Moore-Penrose generalized inverse of the specified matrix.
 *
 * @tparam T type of elements in the matrix
 * @tparam n number of rows, can be Eigen::Dynamic
 * @tparam m number of columns, can be Eigen::Dynamic
 *
 * @param m specified matrix
 * @return Generalized inverse of the matrix (an empty matrix if the specified matrix has
 * size zero).
 */
template <typename EigMat,
          require_eigen_vt<std::is_arithmetic, EigMat>* = nullptr>
inline Eigen::Matrix<value_type_t<EigMat>, EigMat::RowsAtCompileTime,
                     EigMat::ColsAtCompileTime>
generalized_inverse(const EigMat& M) {
  if (M.size() == 0) {
    return {};
  }

  constexpr int n = EigMat::RowsAtCompileTime;
  constexpr int m = EigMat::ColsAtCompileTime;

  if (n == m) {
      return M.inverse();
  }

  bool transp(false);
  constexpr int mn;

  if (n < m) {
    transp = true;
    mn = n;
    Eigen::Matrix<T, mn, mn> A = tcrossprod(G);
  } else {
     mn = m;
    Eigen::Matrix<T, mn, mn> A = = crossprod(G);
  }

   A = add_diag(A, rep_vector(1e-10, mn));

   Eigen::Matrix<T, mn, mn> L = cholesky_decompose(A);
   Eigen::Matrix<T, mn, mn> M = chol2inv(L);

   if (transp){
      return transpose(G) * tcrossprod(L * M);
   } else {
      return tcrossprod(L * M) * transpose(G);
   }
}

}  // namespace math
}  // namespace stan

#endif
<commit_msg>fixed docs on generalized_inverse<commit_after>#ifndef STAN_MATH_PRIM_FUN_GENERALIZED_INVERSE_HPP
#define STAN_MATH_PRIM_FUN_GENERALIZED_INVERSE_HPP

#include <stan/math/prim/meta.hpp>
#include <stan/math/prim/err.hpp>
#include <stan/math/prim/fun/Eigen.hpp>
#include <stan/math/prim/fun/chol2inv.hpp>
#include <stan/math/prim/fun/add_diag.hpp>
#include <stan/math/prim/fun/rep_vector.hpp>
#include <stan/math/prim/fun/cholesky_decompose.hpp>
#include <stan/math/prim/fun/transpose.hpp>
#include <stan/math/prim/fun/tcrossprod.hpp>
#include <stan/math/prim/fun/crossprod.hpp>

namespace stan {
namespace math {

/**
 * Returns the Moore-Penrose generalized inverse of the specified matrix.
 *
 * @tparam T type of elements in the matrix
 * @tparam n number of rows, can be Eigen::Dynamic
 * @tparam m number of columns, can be Eigen::Dynamic
 *
 * @param M specified matrix
 * @return Generalized inverse of the matrix (an empty matrix if the specified matrix has
 * size zero).
 */
template <typename EigMat, require_eigen_vt<std::is_arithmetic, EigMat>* = nullptr>
inline Eigen::Matrix<value_type_t<EigMat>, EigMat::RowsAtCompileTime,
                     EigMat::ColsAtCompileTime>
generalized_inverse(const EigMat& M) {
  if (M.size() == 0) {
    return {};
  }

  constexpr int n = EigMat::RowsAtCompileTime;
  constexpr int m = EigMat::ColsAtCompileTime;

  if (n == m) {
      return M.inverse();
  }

  bool transp(false);
  constexpr int mn;

  if (n < m) {
    transp = true;
    mn = n;
    Eigen::Matrix<T, mn, mn> A = tcrossprod(G);
  } else {
     mn = m;
    Eigen::Matrix<T, mn, mn> A = = crossprod(G);
  }

   A = add_diag(A, rep_vector(1e-10, mn));

   Eigen::Matrix<T, mn, mn> L = cholesky_decompose(A);
   Eigen::Matrix<T, mn, mn> M = chol2inv(L);

   if (transp){
      return transpose(G) * tcrossprod(L * M);
   } else {
      return tcrossprod(L * M) * transpose(G);
   }
}

}  // namespace math
}  // namespace stan

#endif
<|endoftext|>


<commit_before>#ifndef STAN_MATH_PRIM_FUN_TRACE_GEN_QUAD_FORM_HPP
#define STAN_MATH_PRIM_FUN_TRACE_GEN_QUAD_FORM_HPP

#include <stan/math/prim/meta.hpp>
#include <stan/math/prim/err.hpp>
#include <stan/math/prim/fun/Eigen.hpp>
#include <stan/math/prim/fun/trace.hpp>
#include <stan/math/prim/fun/multiply.hpp>
#include <stan/math/prim/fun/transpose.hpp>
#include <exception>

namespace stan {
namespace math {

/**
 * Return the trace of D times the quadratic form of B and A.
 * That is, `trace_gen_quad_form(D, A, B) = trace(D * B' * A * B).`
 *
 * @tparam EigMatD type of the first matrix or expression
 * @tparam EigMatA type of the second matrix or expression
 * @tparam EigMatB type of the third matrix or expression
 *
 * @param D multiplier
 * @param A outside term in quadratic form
 * @param B inner term in quadratic form
 * @return trace(D * B' * A * B)
 * @throw std::domain_error if A or D is not square
 * @throw std::domain_error if A cannot be multiplied by B or B cannot
 * be multiplied by D.
 */
template <typename TD, typename TA, typename TB,
          typename = require_all_eigen_t<TD, TA, TB>,
          typename = require_all_not_vt_var<TD, TA, TB>,
          typename = require_any_not_vt_arithmetic<TD, TA, TB>>
inline auto trace_gen_quad_form(const TD &D, const TA &A, const TB &B) {
  check_square("trace_gen_quad_form", "A", A);
  check_square("trace_gen_quad_form", "D", D);
  check_multiplicable("trace_gen_quad_form", "A", A, "B", B);
  check_multiplicable("trace_gen_quad_form", "B", B, "D", D);
  return multiply(B, D.transpose()).cwiseProduct(multiply(A, B)).sum();
}

/**
 * Return the trace of D times the quadratic form of B and A.
 * That is, `trace_gen_quad_form(D, A, B) = trace(D * B' * A * B).`
 * This is the overload for arithmetic types to allow Eigen's expression
 * templates to be used for efficiency.
 *
 * @tparam EigMatD type of the first matrix or expression
 * @tparam EigMatA type of the second matrix or expression
 * @tparam EigMatB type of the third matrix or expression
 *
 * @param D multiplier
 * @param A outside term in quadratic form
 * @param B inner term in quadratic form
 * @return trace(D * B' * A * B)
 * @throw std::domain_error if A or D is not square
 * @throw std::domain_error if A cannot be multiplied by B or B cannot
 * be multiplied by D.
 */
template <typename EigMatD, typename EigMatA, typename EigMatB,
          require_all_eigen_vt<std::is_arithmetic, EigMatD, EigMatA,
                               EigMatB>* = nullptr>
inline double trace_gen_quad_form(const EigMatD& D, const EigMatA& A,
                                  const EigMatB& B) {
  check_square("trace_gen_quad_form", "A", A);
  check_square("trace_gen_quad_form", "D", D);
  check_multiplicable("trace_gen_quad_form", "A", A, "B", B);
  check_multiplicable("trace_gen_quad_form", "B", B, "D", D);
  return (B * D.transpose()).cwiseProduct(A * B).sum();
}

}  // namespace math
}  // namespace stan

#endif
<commit_msg>[Jenkins] auto-formatting by clang-format version 6.0.0-1ubuntu2 (tags/RELEASE_600/final)<commit_after>#ifndef STAN_MATH_PRIM_FUN_TRACE_GEN_QUAD_FORM_HPP
#define STAN_MATH_PRIM_FUN_TRACE_GEN_QUAD_FORM_HPP

#include <stan/math/prim/meta.hpp>
#include <stan/math/prim/err.hpp>
#include <stan/math/prim/fun/Eigen.hpp>
#include <stan/math/prim/fun/trace.hpp>
#include <stan/math/prim/fun/multiply.hpp>
#include <stan/math/prim/fun/transpose.hpp>
#include <exception>

namespace stan {
namespace math {

/**
 * Return the trace of D times the quadratic form of B and A.
 * That is, `trace_gen_quad_form(D, A, B) = trace(D * B' * A * B).`
 *
 * @tparam EigMatD type of the first matrix or expression
 * @tparam EigMatA type of the second matrix or expression
 * @tparam EigMatB type of the third matrix or expression
 *
 * @param D multiplier
 * @param A outside term in quadratic form
 * @param B inner term in quadratic form
 * @return trace(D * B' * A * B)
 * @throw std::domain_error if A or D is not square
 * @throw std::domain_error if A cannot be multiplied by B or B cannot
 * be multiplied by D.
 */
template <typename TD, typename TA, typename TB,
          typename = require_all_eigen_t<TD, TA, TB>,
          typename = require_all_not_vt_var<TD, TA, TB>,
          typename = require_any_not_vt_arithmetic<TD, TA, TB>>
inline auto trace_gen_quad_form(const TD& D, const TA& A, const TB& B) {
  check_square("trace_gen_quad_form", "A", A);
  check_square("trace_gen_quad_form", "D", D);
  check_multiplicable("trace_gen_quad_form", "A", A, "B", B);
  check_multiplicable("trace_gen_quad_form", "B", B, "D", D);
  return multiply(B, D.transpose()).cwiseProduct(multiply(A, B)).sum();
}

/**
 * Return the trace of D times the quadratic form of B and A.
 * That is, `trace_gen_quad_form(D, A, B) = trace(D * B' * A * B).`
 * This is the overload for arithmetic types to allow Eigen's expression
 * templates to be used for efficiency.
 *
 * @tparam EigMatD type of the first matrix or expression
 * @tparam EigMatA type of the second matrix or expression
 * @tparam EigMatB type of the third matrix or expression
 *
 * @param D multiplier
 * @param A outside term in quadratic form
 * @param B inner term in quadratic form
 * @return trace(D * B' * A * B)
 * @throw std::domain_error if A or D is not square
 * @throw std::domain_error if A cannot be multiplied by B or B cannot
 * be multiplied by D.
 */
template <typename EigMatD, typename EigMatA, typename EigMatB,
          require_all_eigen_vt<std::is_arithmetic, EigMatD, EigMatA,
                               EigMatB>* = nullptr>
inline double trace_gen_quad_form(const EigMatD& D, const EigMatA& A,
                                  const EigMatB& B) {
  check_square("trace_gen_quad_form", "A", A);
  check_square("trace_gen_quad_form", "D", D);
  check_multiplicable("trace_gen_quad_form", "A", A, "B", B);
  check_multiplicable("trace_gen_quad_form", "B", B, "D", D);
  return (B * D.transpose()).cwiseProduct(A * B).sum();
}

}  // namespace math
}  // namespace stan

#endif
<|endoftext|>


<commit_before>//-----------------------------------
// Copyright Pierric Gimmig 2013-2017
//-----------------------------------

#include "BpfTrace.h"
#include "LinuxUtils.h"
#include "CoreApp.h"
#include "Capture.h"
#include "OrbitModule.h"
#include "OrbitProcess.h"
#include "Params.h"
#include "Utils.h"
#include <fstream>
#include <sstream>

#if __linux__
#include "BpfTraceVisitor.h"
#include "LinuxPerfEvent.h"
#include "LinuxPerfEventProcessor.h"
#include "LinuxPerfRingBuffer.h"
#include "LinuxPerfUtils.h"
#include "OrbitFunction.h"
#include "Pdb.h"
#include <linux/perf_event.h>
#include <map>
#include <vector>

using namespace LinuxPerfUtils;
#endif

//-----------------------------------------------------------------------------
BpfTrace::BpfTrace(Callback a_Callback)
{
    m_Callback = a_Callback ? a_Callback : [this](const std::string& a_Buffer)
    {
        if( GParams.m_BpftraceCallstacks )
            CommandCallbackWithCallstacks(a_Buffer);
        else
            CommandCallback(a_Buffer);
    };

    m_ScriptFileName = ws2s(Path::GetBasePath()) + "orbit.bt";
}

//-----------------------------------------------------------------------------
void BpfTrace::Start()
{
#if __linux__
    m_ExitRequested = false;
    m_TimerStacks.clear();
    if( !WriteBpfScript() )
        return;

    m_BpfCommand = std::string("bpftrace ") + m_ScriptFileName;
    if ( GParams.m_UseBpftrace || GParams.m_BpftraceCallstacks ) {
        m_Thread = std::make_shared<std::thread>
            ( &LinuxUtils::StreamCommandOutput
            , m_BpfCommand.c_str()
            , m_Callback
            , &m_ExitRequested );
    }
    else
    {
        m_Thread = std::make_shared<std::thread>
            ( BpfTrace::RunPerfEventOpen
            , &m_ExitRequested );
    }

    m_Thread->detach();
#endif
}

//-----------------------------------------------------------------------------
void BpfTrace::Stop()
{
    m_ExitRequested = true;
}

//-----------------------------------------------------------------------------
std::string BpfTrace::GetBpfScript()
{
    if (!m_Script.empty())
    {
        return m_Script;
    }

    std::stringstream ss;

    for (Function *func : Capture::GTargetProcess->GetFunctions())
    {
        if (func->IsSelected())
        {
            uint64_t virtual_address = (uint64_t)func->GetVirtualAddress();
            Capture::GSelectedFunctionsMap[func->m_Address] = func;

            if( GParams.m_BpftraceCallstacks )
            {
                ss << "   uprobe:" << func->m_Probe << R"({ printf("b )" << std::to_string(virtual_address) << R"( %u %lld\n%s\n\nd\n\n", tid, nsecs, ustack(perf)); })" << std::endl;
            }
            else
            {
                ss << "   uprobe:" << func->m_Probe << R"({ printf("b )" << std::to_string(virtual_address) << R"( %u %lld\n", tid, nsecs); })" << std::endl;
            }

            ss << "uretprobe:" << func->m_Probe << R"({ printf("e )" << std::to_string(virtual_address) << R"( %u %lld\n", tid, nsecs); })" << std::endl;
        }
    }

    return ss.str();
}

//-----------------------------------------------------------------------------
bool BpfTrace::WriteBpfScript()
{
    std::string script = GetBpfScript();
    if (script.empty())
        return false;

    std::ofstream outFile;
    outFile.open(m_ScriptFileName);
    if (outFile.fail())
        return false;

    outFile << script;
    outFile.close();
    return true;
}

//-----------------------------------------------------------------------------
uint64_t BpfTrace::ProcessString(const std::string& a_String)
{
    auto hash = StringHash(a_String);
    if (m_StringMap.find(hash) == m_StringMap.end())
    {
        m_StringMap[hash] = a_String;
    }

    return hash;
}

//-----------------------------------------------------------------------------
void BpfTrace::CommandCallback(const std::string& a_Line)
{
    auto tokens = Tokenize(a_Line);
    const std::string& mode             = tokens[0];
    const std::string& functionAddress  = tokens[1];
    const std::string& threadName       = tokens[2];
    const std::string& timestamp        = tokens[3];

    bool isBegin = mode == "b";
    bool isEnd   = !isBegin;

    if (isBegin)
    {
        Timer timer;
        timer.m_TID = atoi(threadName.c_str());
        uint64_t nanos = std::stoull(timestamp);
        timer.m_Start = nanos;
        timer.m_Depth = (uint8_t)m_TimerStacks[threadName].size();
        timer.m_FunctionAddress = std::stoull(functionAddress);
        m_TimerStacks[threadName].push_back(timer);
    }

    if (isEnd)
    {
        std::vector<Timer>& timers = m_TimerStacks[threadName];
        if (timers.size())
        {
            Timer& timer = timers.back();
            uint64_t nanos = std::stoull(timestamp);
            timer.m_End = nanos;
            GCoreApp->ProcessTimer(&timer, functionAddress);
            timers.pop_back();
        }
    }
}

//-----------------------------------------------------------------------------
void BpfTrace::CommandCallbackWithCallstacks(const std::string& a_Line)
{
    if (a_Line.empty() || a_Line == "\n")
        return;

    auto tokens = Tokenize(a_Line);

    const std::string& mode = tokens[0];
    bool isBegin = mode == "b";
    bool isEnd   = mode == "e";

    bool isStackLine = StartsWith(a_Line, "\t");
    bool isEndOfStack = a_Line == "d\n";

    if (!isBegin && !isEnd && !isStackLine && !isEndOfStack)
    {
        if (StartsWith(a_Line, "Lost"))
        {
            PRINT(a_Line.c_str());
            return;
        }

        if (StartsWith(a_Line, "Attaching"))
            return;

        // if the line does not start with one of the above,
        // we might have a broken line, e.g. due to a small buffer
        PRINT("read unexpected line:%s\nthe buffer might be to small.", a_Line.c_str());
        return;
    }

    if (isStackLine) {
        const std::string& addressStr = LTrim(tokens[0]);
        uint64_t address = std::stoull(addressStr, nullptr, 16);

        std::string function = tokens[1];

        std::string moduleRaw = tokens[2];
        std::string module = Replace(moduleRaw.substr(1), ")\n", "");

        // TODO: this is copy&paste from LinuxPerf.cpp
        std::wstring moduleName = ToLower(Path::GetFileName(s2ws(module)));
        std::shared_ptr<Module> moduleFromName = Capture::GTargetProcess->GetModuleFromName( ws2s(moduleName) );

        if( moduleFromName )
        {
            uint64_t new_address = moduleFromName->ValidateAddress(address);
            address = new_address;
        }

        m_CallStack.m_Data.push_back(address);
        if( Capture::GTargetProcess && !Capture::GTargetProcess->HasSymbol(address))
        {
            GCoreApp->AddSymbol(address, module, function);
        }

        return;
    }

    if (isEndOfStack)
    {
        if ( m_CallStack.m_Data.size() ) {
            m_CallStack.m_Depth = (uint32_t)m_CallStack.m_Data.size();
            m_CallStack.m_ThreadId = atoi(m_LastThreadName.c_str());
            std::vector<Timer>& timers = m_TimerStacks[m_LastThreadName];
            if (timers.size())
            {
                Timer& timer = timers.back();
                timer.m_CallstackHash = m_CallStack.Hash();
                GCoreApp->ProcessCallStack( m_CallStack );
            }
        }

        m_CallStack.Clear();
        m_LastThreadName = "";
        return;
    }

    const std::string& functionAddress  = tokens[1];
    const std::string& threadName       = tokens[2];
    const std::string& timestamp        = tokens[3];

    m_LastThreadName = threadName;

    if (isBegin)
    {
        Timer timer;
        timer.m_TID = atoi(threadName.c_str());
        uint64_t nanos = std::stoull(timestamp);
        timer.m_Start = nanos;
        timer.m_Depth = (uint8_t)m_TimerStacks[threadName].size();
        timer.m_FunctionAddress = std::stoull(functionAddress);
        m_TimerStacks[threadName].push_back(timer);
        return;
    }

    if (isEnd)
    {
        std::vector<Timer>& timers = m_TimerStacks[threadName];
        if (timers.size())
        {
            Timer& timer = timers.back();
            uint64_t nanos = std::stoull(timestamp);
            timer.m_End = nanos;
            GCoreApp->ProcessTimer(&timer, functionAddress);
            timers.pop_back();
        }
        return;
    }
}

//-----------------------------------------------------------------------------
void BpfTrace::RunPerfEventOpen(bool* a_ExitRequested)
{
    #if __linux__
    int ROUND_ROBIN_BATCH_SIZE = 5;
    std::vector<uint64_t> fds;
    std::map<Function*, LinuxPerfRingBuffer> uprobe_ring_buffers;
    std::map<Function*, LinuxPerfRingBuffer> uretprobe_ring_buffers;

    for (const auto& pair : Capture::GSelectedFunctionsMap)
    {
        // gather function information
        Function* function = pair.second;
        uint64_t offset = function->m_Address;
        uint64_t virtual_address = function->GetVirtualAddress();
        std::string module = ws2s(function->m_Pdb->GetFileName());

        // create uprobe for that function on that PID profiling all cpus
        uint64_t uprobe_fd = 0;
        if (GParams.m_BpftraceCallstacks)
            uprobe_fd = LinuxPerfUtils::uprobe_event_open(
                module.c_str(), offset, Capture::GTargetProcess->GetID(), -1,
                PERF_SAMPLE_STACK_USER | PERF_SAMPLE_REGS_USER
            );
        else
            uprobe_fd = LinuxPerfUtils::uprobe_event_open(
                module.c_str(), offset, Capture::GTargetProcess->GetID(), -1
            );

        uprobe_ring_buffers.emplace(function, uprobe_fd);
        fds.push_back(uprobe_fd);

        // create uretprobe for that function on that PID profiling all cpus
        uint64_t uretprobe_fd = LinuxPerfUtils::uretprobe_event_open(
            module.c_str(), offset, Capture::GTargetProcess->GetID(), -1
        );
        uretprobe_ring_buffers.emplace(function, uretprobe_fd);
        fds.push_back(uretprobe_fd);

        // start capturing
        LinuxPerfUtils::start_capturing(uprobe_fd);
        LinuxPerfUtils::start_capturing(uretprobe_fd);
    }

    LinuxPerfEventProcessor event_buffer(std::make_unique<BpfTraceVisitor>());

    bool new_events = false;

    while( !(*a_ExitRequested) )
    {
        // Lets sleep a bit, such that we are not constantly reading from the buffers
        // and thus wasting cpu time. 1000 microseconds are still small enought to
        // not have our buffers overflown and therefore loosing events.
        if (!new_events)
        {
            usleep(10000);
        }

        new_events = false;

        // read from all ring buffers, create events and store them in the event_queue
        // TODO: implement a better scheduling strategy.
        for (auto& pair : uprobe_ring_buffers)
        {
            auto& ring_buffer = pair.second;
            int i = 0;
            // read everything that is new
            while (ring_buffer.HasNewData() && i < ROUND_ROBIN_BATCH_SIZE)
            {
                perf_event_header header{};
                ring_buffer.ReadHeader(&header);

                // perf_event_header::type contains the type of record,
                // defined in enum perf_event_type in perf_event.h.
                switch (header.type)
                {
                case PERF_RECORD_SAMPLE:
                    {
                        if (GParams.m_BpftraceCallstacks)
                        {
                            auto record = ring_buffer.ConsumeRecord<LinuxUprobeEventWithStack>(header);
                            record.SetFunction(pair.first);
                            event_buffer.Push(std::make_unique<LinuxUprobeEventWithStack>(std::move(record)));
                        }
                        else
                        {
                            auto record = ring_buffer.ConsumeRecord<LinuxUprobeEvent>(header);
                            record.SetFunction(pair.first);
                            event_buffer.Push(std::make_unique<LinuxUprobeEvent>(std::move(record)));
                        }

                    }
                    break;
                 case PERF_RECORD_LOST:
                    {
                        auto lost = ring_buffer.ConsumeRecord<LinuxPerfLostEvent>(header);
                        PRINT("Lost %u Events\n", lost.Lost());
                    }
                    break;
                default:
                    PRINT("Unexpected Perf Sample Type: %u", header.type);
                    ring_buffer.SkipRecord(header);
                    break;
                }
            }
        }

        for (auto& pair : uretprobe_ring_buffers)
        {
            auto& ring_buffer = pair.second;
            int i = 0;
            // read everything that is new
            while (ring_buffer.HasNewData() && i < ROUND_ROBIN_BATCH_SIZE)
            {
                perf_event_header header{};
                ring_buffer.ReadHeader(&header);

                // perf_event_header::type contains the type of record,
                // defined in enum perf_event_type in perf_event.h.
                switch (header.type)
                {
                case PERF_RECORD_SAMPLE:
                    {
                        auto record = ring_buffer.ConsumeRecord<LinuxUretprobeEvent>(header);
                        record.SetFunction(pair.first);
                        event_buffer.Push(std::make_unique<LinuxUretprobeEvent>(std::move(record)));
                    }
                    break;
                 case PERF_RECORD_LOST:
                    {
                        auto lost = ring_buffer.ConsumeRecord<LinuxPerfLostEvent>(header);
                        PRINT("Lost %u Events\n", lost.Lost());
                    }
                    break;
                default:
                    PRINT("Unexpected Perf Sample Type: %u", header.type);
                    ring_buffer.SkipRecord(header);
                    break;
                }
            }
        }

        event_buffer.ProcessTillOffset();
    }

    for (auto fd : fds)
    {
        LinuxPerfUtils::stop_capturing(fd);
    }

    event_buffer.ProcessAll();
    #endif
}<commit_msg>fixed round robin<commit_after>//-----------------------------------
// Copyright Pierric Gimmig 2013-2017
//-----------------------------------

#include "BpfTrace.h"
#include "LinuxUtils.h"
#include "CoreApp.h"
#include "Capture.h"
#include "OrbitModule.h"
#include "OrbitProcess.h"
#include "Params.h"
#include "Utils.h"
#include <fstream>
#include <sstream>

#if __linux__
#include "BpfTraceVisitor.h"
#include "LinuxPerfEvent.h"
#include "LinuxPerfEventProcessor.h"
#include "LinuxPerfRingBuffer.h"
#include "LinuxPerfUtils.h"
#include "OrbitFunction.h"
#include "Pdb.h"
#include <linux/perf_event.h>
#include <map>
#include <vector>

using namespace LinuxPerfUtils;
#endif

//-----------------------------------------------------------------------------
BpfTrace::BpfTrace(Callback a_Callback)
{
    m_Callback = a_Callback ? a_Callback : [this](const std::string& a_Buffer)
    {
        if( GParams.m_BpftraceCallstacks )
            CommandCallbackWithCallstacks(a_Buffer);
        else
            CommandCallback(a_Buffer);
    };

    m_ScriptFileName = ws2s(Path::GetBasePath()) + "orbit.bt";
}

//-----------------------------------------------------------------------------
void BpfTrace::Start()
{
#if __linux__
    m_ExitRequested = false;
    m_TimerStacks.clear();
    if( !WriteBpfScript() )
        return;

    m_BpfCommand = std::string("bpftrace ") + m_ScriptFileName;
    if ( GParams.m_UseBpftrace || GParams.m_BpftraceCallstacks ) {
        m_Thread = std::make_shared<std::thread>
            ( &LinuxUtils::StreamCommandOutput
            , m_BpfCommand.c_str()
            , m_Callback
            , &m_ExitRequested );
    }
    else
    {
        m_Thread = std::make_shared<std::thread>
            ( BpfTrace::RunPerfEventOpen
            , &m_ExitRequested );
    }

    m_Thread->detach();
#endif
}

//-----------------------------------------------------------------------------
void BpfTrace::Stop()
{
    m_ExitRequested = true;
}

//-----------------------------------------------------------------------------
std::string BpfTrace::GetBpfScript()
{
    if (!m_Script.empty())
    {
        return m_Script;
    }

    std::stringstream ss;

    for (Function *func : Capture::GTargetProcess->GetFunctions())
    {
        if (func->IsSelected())
        {
            uint64_t virtual_address = (uint64_t)func->GetVirtualAddress();
            Capture::GSelectedFunctionsMap[func->m_Address] = func;

            if( GParams.m_BpftraceCallstacks )
            {
                ss << "   uprobe:" << func->m_Probe << R"({ printf("b )" << std::to_string(virtual_address) << R"( %u %lld\n%s\n\nd\n\n", tid, nsecs, ustack(perf)); })" << std::endl;
            }
            else
            {
                ss << "   uprobe:" << func->m_Probe << R"({ printf("b )" << std::to_string(virtual_address) << R"( %u %lld\n", tid, nsecs); })" << std::endl;
            }

            ss << "uretprobe:" << func->m_Probe << R"({ printf("e )" << std::to_string(virtual_address) << R"( %u %lld\n", tid, nsecs); })" << std::endl;
        }
    }

    return ss.str();
}

//-----------------------------------------------------------------------------
bool BpfTrace::WriteBpfScript()
{
    std::string script = GetBpfScript();
    if (script.empty())
        return false;

    std::ofstream outFile;
    outFile.open(m_ScriptFileName);
    if (outFile.fail())
        return false;

    outFile << script;
    outFile.close();
    return true;
}

//-----------------------------------------------------------------------------
uint64_t BpfTrace::ProcessString(const std::string& a_String)
{
    auto hash = StringHash(a_String);
    if (m_StringMap.find(hash) == m_StringMap.end())
    {
        m_StringMap[hash] = a_String;
    }

    return hash;
}

//-----------------------------------------------------------------------------
void BpfTrace::CommandCallback(const std::string& a_Line)
{
    auto tokens = Tokenize(a_Line);
    const std::string& mode             = tokens[0];
    const std::string& functionAddress  = tokens[1];
    const std::string& threadName       = tokens[2];
    const std::string& timestamp        = tokens[3];

    bool isBegin = mode == "b";
    bool isEnd   = !isBegin;

    if (isBegin)
    {
        Timer timer;
        timer.m_TID = atoi(threadName.c_str());
        uint64_t nanos = std::stoull(timestamp);
        timer.m_Start = nanos;
        timer.m_Depth = (uint8_t)m_TimerStacks[threadName].size();
        timer.m_FunctionAddress = std::stoull(functionAddress);
        m_TimerStacks[threadName].push_back(timer);
    }

    if (isEnd)
    {
        std::vector<Timer>& timers = m_TimerStacks[threadName];
        if (timers.size())
        {
            Timer& timer = timers.back();
            uint64_t nanos = std::stoull(timestamp);
            timer.m_End = nanos;
            GCoreApp->ProcessTimer(&timer, functionAddress);
            timers.pop_back();
        }
    }
}

//-----------------------------------------------------------------------------
void BpfTrace::CommandCallbackWithCallstacks(const std::string& a_Line)
{
    if (a_Line.empty() || a_Line == "\n")
        return;

    auto tokens = Tokenize(a_Line);

    const std::string& mode = tokens[0];
    bool isBegin = mode == "b";
    bool isEnd   = mode == "e";

    bool isStackLine = StartsWith(a_Line, "\t");
    bool isEndOfStack = a_Line == "d\n";

    if (!isBegin && !isEnd && !isStackLine && !isEndOfStack)
    {
        if (StartsWith(a_Line, "Lost"))
        {
            PRINT(a_Line.c_str());
            return;
        }

        if (StartsWith(a_Line, "Attaching"))
            return;

        // if the line does not start with one of the above,
        // we might have a broken line, e.g. due to a small buffer
        PRINT("read unexpected line:%s\nthe buffer might be to small.", a_Line.c_str());
        return;
    }

    if (isStackLine) {
        const std::string& addressStr = LTrim(tokens[0]);
        uint64_t address = std::stoull(addressStr, nullptr, 16);

        std::string function = tokens[1];

        std::string moduleRaw = tokens[2];
        std::string module = Replace(moduleRaw.substr(1), ")\n", "");

        // TODO: this is copy&paste from LinuxPerf.cpp
        std::wstring moduleName = ToLower(Path::GetFileName(s2ws(module)));
        std::shared_ptr<Module> moduleFromName = Capture::GTargetProcess->GetModuleFromName( ws2s(moduleName) );

        if( moduleFromName )
        {
            uint64_t new_address = moduleFromName->ValidateAddress(address);
            address = new_address;
        }

        m_CallStack.m_Data.push_back(address);
        if( Capture::GTargetProcess && !Capture::GTargetProcess->HasSymbol(address))
        {
            GCoreApp->AddSymbol(address, module, function);
        }

        return;
    }

    if (isEndOfStack)
    {
        if ( m_CallStack.m_Data.size() ) {
            m_CallStack.m_Depth = (uint32_t)m_CallStack.m_Data.size();
            m_CallStack.m_ThreadId = atoi(m_LastThreadName.c_str());
            std::vector<Timer>& timers = m_TimerStacks[m_LastThreadName];
            if (timers.size())
            {
                Timer& timer = timers.back();
                timer.m_CallstackHash = m_CallStack.Hash();
                GCoreApp->ProcessCallStack( m_CallStack );
            }
        }

        m_CallStack.Clear();
        m_LastThreadName = "";
        return;
    }

    const std::string& functionAddress  = tokens[1];
    const std::string& threadName       = tokens[2];
    const std::string& timestamp        = tokens[3];

    m_LastThreadName = threadName;

    if (isBegin)
    {
        Timer timer;
        timer.m_TID = atoi(threadName.c_str());
        uint64_t nanos = std::stoull(timestamp);
        timer.m_Start = nanos;
        timer.m_Depth = (uint8_t)m_TimerStacks[threadName].size();
        timer.m_FunctionAddress = std::stoull(functionAddress);
        m_TimerStacks[threadName].push_back(timer);
        return;
    }

    if (isEnd)
    {
        std::vector<Timer>& timers = m_TimerStacks[threadName];
        if (timers.size())
        {
            Timer& timer = timers.back();
            uint64_t nanos = std::stoull(timestamp);
            timer.m_End = nanos;
            GCoreApp->ProcessTimer(&timer, functionAddress);
            timers.pop_back();
        }
        return;
    }
}

//-----------------------------------------------------------------------------
void BpfTrace::RunPerfEventOpen(bool* a_ExitRequested)
{
    #if __linux__
    int ROUND_ROBIN_BATCH_SIZE = 5;
    std::vector<uint64_t> fds;
    std::map<Function*, LinuxPerfRingBuffer> uprobe_ring_buffers;
    std::map<Function*, LinuxPerfRingBuffer> uretprobe_ring_buffers;

    for (const auto& pair : Capture::GSelectedFunctionsMap)
    {
        // gather function information
        Function* function = pair.second;
        uint64_t offset = function->m_Address;
        uint64_t virtual_address = function->GetVirtualAddress();
        std::string module = ws2s(function->m_Pdb->GetFileName());

        // create uprobe for that function on that PID profiling all cpus
        uint64_t uprobe_fd = 0;
        if (GParams.m_BpftraceCallstacks)
            uprobe_fd = LinuxPerfUtils::uprobe_event_open(
                module.c_str(), offset, Capture::GTargetProcess->GetID(), -1,
                PERF_SAMPLE_STACK_USER | PERF_SAMPLE_REGS_USER
            );
        else
            uprobe_fd = LinuxPerfUtils::uprobe_event_open(
                module.c_str(), offset, Capture::GTargetProcess->GetID(), -1
            );

        uprobe_ring_buffers.emplace(function, uprobe_fd);
        fds.push_back(uprobe_fd);

        // create uretprobe for that function on that PID profiling all cpus
        uint64_t uretprobe_fd = LinuxPerfUtils::uretprobe_event_open(
            module.c_str(), offset, Capture::GTargetProcess->GetID(), -1
        );
        uretprobe_ring_buffers.emplace(function, uretprobe_fd);
        fds.push_back(uretprobe_fd);

        // start capturing
        LinuxPerfUtils::start_capturing(uprobe_fd);
        LinuxPerfUtils::start_capturing(uretprobe_fd);
    }

    LinuxPerfEventProcessor event_buffer(std::make_unique<BpfTraceVisitor>());

    bool new_events = false;

    while( !(*a_ExitRequested) )
    {
        // Lets sleep a bit, such that we are not constantly reading from the buffers
        // and thus wasting cpu time. 1000 microseconds are still small enought to
        // not have our buffers overflown and therefore loosing events.
        if (!new_events)
        {
            usleep(10000);
        }

        new_events = false;

        // read from all ring buffers, create events and store them in the event_queue
        // TODO: implement a better scheduling strategy.
        for (auto& pair : uprobe_ring_buffers)
        {
            auto& ring_buffer = pair.second;
            int i = 0;
            // read everything that is new
            while (ring_buffer.HasNewData() && i < ROUND_ROBIN_BATCH_SIZE)
            {
                i++;
                new_events = true;
                perf_event_header header{};
                ring_buffer.ReadHeader(&header);

                // perf_event_header::type contains the type of record,
                // defined in enum perf_event_type in perf_event.h.
                switch (header.type)
                {
                case PERF_RECORD_SAMPLE:
                    {
                        if (GParams.m_BpftraceCallstacks)
                        {
                            auto record = ring_buffer.ConsumeRecord<LinuxUprobeEventWithStack>(header);
                            record.SetFunction(pair.first);
                            event_buffer.Push(std::make_unique<LinuxUprobeEventWithStack>(std::move(record)));
                        }
                        else
                        {
                            auto record = ring_buffer.ConsumeRecord<LinuxUprobeEvent>(header);
                            record.SetFunction(pair.first);
                            event_buffer.Push(std::make_unique<LinuxUprobeEvent>(std::move(record)));
                        }

                    }
                    break;
                 case PERF_RECORD_LOST:
                    {
                        auto lost = ring_buffer.ConsumeRecord<LinuxPerfLostEvent>(header);
                        PRINT("Lost %u Events\n", lost.Lost());
                    }
                    break;
                default:
                    PRINT("Unexpected Perf Sample Type: %u", header.type);
                    ring_buffer.SkipRecord(header);
                    break;
                }
            }
        }

        for (auto& pair : uretprobe_ring_buffers)
        {
            auto& ring_buffer = pair.second;
            int i = 0;
            // read everything that is new
            while (ring_buffer.HasNewData() && i < ROUND_ROBIN_BATCH_SIZE)
            {
                i++;
                new_events = true;
                perf_event_header header{};
                ring_buffer.ReadHeader(&header);

                // perf_event_header::type contains the type of record,
                // defined in enum perf_event_type in perf_event.h.
                switch (header.type)
                {
                case PERF_RECORD_SAMPLE:
                    {
                        auto record = ring_buffer.ConsumeRecord<LinuxUretprobeEvent>(header);
                        record.SetFunction(pair.first);
                        event_buffer.Push(std::make_unique<LinuxUretprobeEvent>(std::move(record)));
                    }
                    break;
                 case PERF_RECORD_LOST:
                    {
                        auto lost = ring_buffer.ConsumeRecord<LinuxPerfLostEvent>(header);
                        PRINT("Lost %u Events\n", lost.Lost());
                    }
                    break;
                default:
                    PRINT("Unexpected Perf Sample Type: %u", header.type);
                    ring_buffer.SkipRecord(header);
                    break;
                }
            }
        }

        event_buffer.ProcessTillOffset();
    }

    for (auto fd : fds)
    {
        LinuxPerfUtils::stop_capturing(fd);
    }

    event_buffer.ProcessAll();
    #endif
}<|endoftext|>


<commit_before><commit_msg>GenerateTerms: Pass tree as a pointer<commit_after><|endoftext|>


<commit_before>/*
 * Copyright (c) 2014 ARM Limited
 * All rights reserved
 *
 * The license below extends only to copyright in the software and shall
 * not be construed as granting a license to any other intellectual
 * property including but not limited to intellectual property relating
 * to a hardware implementation of the functionality of the software
 * licensed hereunder.  You may use the software subject to the license
 * terms below provided that you ensure that this notice is replicated
 * unmodified and in its entirety in all distributions of the software,
 * modified or unmodified, in source code or in binary form.
 *
 * Copyright (c) 2002-2005 The Regents of The University of Michigan
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met: redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer;
 * redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution;
 * neither the name of the copyright holders nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * Authors: Nathan Binkert
 *          Dave Greene
 *          Andreas Sandberg
 */

#ifndef __BASE_MISC_HH__
#define __BASE_MISC_HH__

#include <iostream>

#include "base/compiler.hh"
#include "base/cprintf.hh"

#if defined(__SUNPRO_CC)
#define __FUNCTION__ "how to fix me?"
#endif

void __exit_epilogue(int code,
                     const char *func, const char *file, int line,
                     const char *format) M5_ATTR_NORETURN;

// General exit message, these functions will never return and will
// either abort() if code is < 0 or exit with the code if >= 0
template<typename ...Args> void
__exit_message(const char *prefix, int code,
               const char *func, const char *file, int line,
               const char *format, const Args &...args) M5_ATTR_NORETURN;
template<typename ...Args> void
__exit_message(const char *prefix, int code,
               const char *func, const char *file, int line,
               const std::string &format, const Args &...args) M5_ATTR_NORETURN;

template<typename ...Args> void
__exit_message(const char *prefix, int code,
               const char *func, const char *file, int line,
               const char *format, const Args &...args)
{
    std::cerr << prefix << ": ";
    ccprintf(std::cerr, format, args...);

    __exit_epilogue(code, func, file, line, format);
}

template<typename ...Args> void
__exit_message(const char *prefix, int code,
               const char *func, const char *file, int line,
               const std::string &format, const Args &...args)
{
    __exit_message(prefix, code, func, file, line, format.c_str(),
                   args...);
}

#define exit_message(prefix, code, ...)                                 \
    __exit_message(prefix, code, __FUNCTION__, __FILE__, __LINE__,      \
                   __VA_ARGS__)

//
// This implements a cprintf based panic() function.  panic() should
// be called when something happens that should never ever happen
// regardless of what the user does (i.e., an acutal m5 bug).  panic()
// calls abort which can dump core or enter the debugger.
//
//
#define panic(...) exit_message("panic", -1, __VA_ARGS__)

//
// This implements a cprintf based fatal() function.  fatal() should
// be called when the simulation cannot continue due to some condition
// that is the user's fault (bad configuration, invalid arguments,
// etc.) and not a simulator bug.  fatal() calls  abort() like
// panic() does.
//
#define fatal(...) exit_message("fatal", -1, __VA_ARGS__)

/**
 * Conditional panic macro that checks the supplied condition and only panics
 * if the condition is true and allows the programmer to specify diagnostic
 * printout.  Useful to replace if + panic, or if + print + assert, etc.
 *
 * @param cond Condition that is checked; if true -> panic
 * @param ...  Printf-based format string with arguments, extends printout.
 */
#define panic_if(cond, ...) \
    do { \
        if ((cond)) \
            exit_message("panic condition "#cond" occurred", -1, __VA_ARGS__); \
    } while (0)

/**
 * Conditional fatal macro that checks the supplied condition and only causes a
 * fatal error if the condition is true and allows the programmer to specify
 * diagnostic printout.  Useful to replace if + fatal, or if + print + assert,
 * etc.
 *
 * @param cond Condition that is checked; if true -> fatal
 * @param ...  Printf-based format string with arguments, extends printout.
 */
#define fatal_if(cond, ...) \
    do { \
        if ((cond)) \
            exit_message("fatal condition "#cond" occurred", 1, __VA_ARGS__); \
    } while (0)

void
__base_message_epilogue(std::ostream &stream, bool verbose,
                        const char *func, const char *file, int line,
                        const char *format);

template<typename ...Args> void
__base_message(std::ostream &stream, const char *prefix, bool verbose,
               const char *func, const char *file, int line,
               const char *format, const Args &...args)
{
    stream << prefix << ": ";
    ccprintf(stream, format, args...);

    __base_message_epilogue(stream, verbose, func, file, line, format);
}

template<typename ...Args> void
__base_message(std::ostream &stream, const char *prefix, bool verbose,
               const char *func, const char *file, int line,
               const std::string &format, const Args &...args)
{
    __base_message(stream, prefix, verbose, func, file, line, format.c_str(),
                   args...);
}

#define base_message(stream, prefix, verbose, ...)                      \
    __base_message(stream, prefix, verbose, __FUNCTION__, __FILE__, __LINE__, \
                   __VA_ARGS__)

// Only print the message the first time this expression is
// encountered.  i.e.  This doesn't check the string itself and
// prevent duplicate strings, this prevents the statement from
// happening more than once. So, even if the arguments change and that
// would have resulted in a different message thoes messages would be
// supressed.
#define base_message_once(...) do {                     \
        static bool once = false;                       \
        if (!once) {                                    \
            base_message(__VA_ARGS__);                  \
            once = true;                                \
        }                                               \
    } while (0)

#define cond_message(cond, ...) do {            \
        if (cond)                               \
            base_message(__VA_ARGS__);          \
    } while (0)

#define cond_message_once(cond, ...) do {               \
        static bool once = false;                       \
        if (!once && cond) {                            \
            base_message(__VA_ARGS__);                  \
            once = true;                                \
        }                                               \
    } while (0)

extern bool want_warn, warn_verbose;
extern bool want_info, info_verbose;
extern bool want_hack, hack_verbose;

#define warn(...) \
    cond_message(want_warn, std::cerr, "warn", warn_verbose, __VA_ARGS__)
#define inform(...) \
    cond_message(want_info, std::cout, "info", info_verbose, __VA_ARGS__)
#define hack(...) \
    cond_message(want_hack, std::cerr, "hack", hack_verbose, __VA_ARGS__)

#define warn_once(...) \
    cond_message_once(want_warn, std::cerr, "warn", warn_verbose, __VA_ARGS__)
#define inform_once(...) \
    cond_message_once(want_info, std::cout, "info", info_verbose, __VA_ARGS__)
#define hack_once(...) \
    cond_message_once(want_hack, std::cerr, "hack", hack_verbose, __VA_ARGS__)

/**
 * The chatty assert macro will function like a normal assert, but will allow the
 * specification of additional, helpful material to aid debugging why the
 * assertion actually failed.  Like the normal assertion, the chatty_assert
 * will not be active in fast builds.
 *
 * @param cond Condition that is checked; if false -> assert
 * @param ...  Printf-based format string with arguments, extends printout.
 */
#ifdef NDEBUG
#define chatty_assert(cond, ...)
#else //!NDEBUG
#define chatty_assert(cond, ...)                                                \
    do {                                                                        \
        if (!(cond)) {                                                          \
            base_message(std::cerr, "assert("#cond") failing", 1, __VA_ARGS__); \
            assert(cond);                                                       \
        }                                                                       \
    } while (0)
#endif // NDEBUG
#endif // __BASE_MISC_HH__
<commit_msg>base: misc: Add missing header file.<commit_after>/*
 * Copyright (c) 2014 ARM Limited
 * All rights reserved
 *
 * The license below extends only to copyright in the software and shall
 * not be construed as granting a license to any other intellectual
 * property including but not limited to intellectual property relating
 * to a hardware implementation of the functionality of the software
 * licensed hereunder.  You may use the software subject to the license
 * terms below provided that you ensure that this notice is replicated
 * unmodified and in its entirety in all distributions of the software,
 * modified or unmodified, in source code or in binary form.
 *
 * Copyright (c) 2002-2005 The Regents of The University of Michigan
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met: redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer;
 * redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution;
 * neither the name of the copyright holders nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * Authors: Nathan Binkert
 *          Dave Greene
 *          Andreas Sandberg
 */

#ifndef __BASE_MISC_HH__
#define __BASE_MISC_HH__

#include <cassert>
#include <iostream>

#include "base/compiler.hh"
#include "base/cprintf.hh"

#if defined(__SUNPRO_CC)
#define __FUNCTION__ "how to fix me?"
#endif

void __exit_epilogue(int code,
                     const char *func, const char *file, int line,
                     const char *format) M5_ATTR_NORETURN;

// General exit message, these functions will never return and will
// either abort() if code is < 0 or exit with the code if >= 0
template<typename ...Args> void
__exit_message(const char *prefix, int code,
               const char *func, const char *file, int line,
               const char *format, const Args &...args) M5_ATTR_NORETURN;
template<typename ...Args> void
__exit_message(const char *prefix, int code,
               const char *func, const char *file, int line,
               const std::string &format, const Args &...args) M5_ATTR_NORETURN;

template<typename ...Args> void
__exit_message(const char *prefix, int code,
               const char *func, const char *file, int line,
               const char *format, const Args &...args)
{
    std::cerr << prefix << ": ";
    ccprintf(std::cerr, format, args...);

    __exit_epilogue(code, func, file, line, format);
}

template<typename ...Args> void
__exit_message(const char *prefix, int code,
               const char *func, const char *file, int line,
               const std::string &format, const Args &...args)
{
    __exit_message(prefix, code, func, file, line, format.c_str(),
                   args...);
}

#define exit_message(prefix, code, ...)                                 \
    __exit_message(prefix, code, __FUNCTION__, __FILE__, __LINE__,      \
                   __VA_ARGS__)

//
// This implements a cprintf based panic() function.  panic() should
// be called when something happens that should never ever happen
// regardless of what the user does (i.e., an acutal m5 bug).  panic()
// calls abort which can dump core or enter the debugger.
//
//
#define panic(...) exit_message("panic", -1, __VA_ARGS__)

//
// This implements a cprintf based fatal() function.  fatal() should
// be called when the simulation cannot continue due to some condition
// that is the user's fault (bad configuration, invalid arguments,
// etc.) and not a simulator bug.  fatal() calls  abort() like
// panic() does.
//
#define fatal(...) exit_message("fatal", -1, __VA_ARGS__)

/**
 * Conditional panic macro that checks the supplied condition and only panics
 * if the condition is true and allows the programmer to specify diagnostic
 * printout.  Useful to replace if + panic, or if + print + assert, etc.
 *
 * @param cond Condition that is checked; if true -> panic
 * @param ...  Printf-based format string with arguments, extends printout.
 */
#define panic_if(cond, ...) \
    do { \
        if ((cond)) \
            exit_message("panic condition "#cond" occurred", -1, __VA_ARGS__); \
    } while (0)

/**
 * Conditional fatal macro that checks the supplied condition and only causes a
 * fatal error if the condition is true and allows the programmer to specify
 * diagnostic printout.  Useful to replace if + fatal, or if + print + assert,
 * etc.
 *
 * @param cond Condition that is checked; if true -> fatal
 * @param ...  Printf-based format string with arguments, extends printout.
 */
#define fatal_if(cond, ...) \
    do { \
        if ((cond)) \
            exit_message("fatal condition "#cond" occurred", 1, __VA_ARGS__); \
    } while (0)

void
__base_message_epilogue(std::ostream &stream, bool verbose,
                        const char *func, const char *file, int line,
                        const char *format);

template<typename ...Args> void
__base_message(std::ostream &stream, const char *prefix, bool verbose,
               const char *func, const char *file, int line,
               const char *format, const Args &...args)
{
    stream << prefix << ": ";
    ccprintf(stream, format, args...);

    __base_message_epilogue(stream, verbose, func, file, line, format);
}

template<typename ...Args> void
__base_message(std::ostream &stream, const char *prefix, bool verbose,
               const char *func, const char *file, int line,
               const std::string &format, const Args &...args)
{
    __base_message(stream, prefix, verbose, func, file, line, format.c_str(),
                   args...);
}

#define base_message(stream, prefix, verbose, ...)                      \
    __base_message(stream, prefix, verbose, __FUNCTION__, __FILE__, __LINE__, \
                   __VA_ARGS__)

// Only print the message the first time this expression is
// encountered.  i.e.  This doesn't check the string itself and
// prevent duplicate strings, this prevents the statement from
// happening more than once. So, even if the arguments change and that
// would have resulted in a different message thoes messages would be
// supressed.
#define base_message_once(...) do {                     \
        static bool once = false;                       \
        if (!once) {                                    \
            base_message(__VA_ARGS__);                  \
            once = true;                                \
        }                                               \
    } while (0)

#define cond_message(cond, ...) do {            \
        if (cond)                               \
            base_message(__VA_ARGS__);          \
    } while (0)

#define cond_message_once(cond, ...) do {               \
        static bool once = false;                       \
        if (!once && cond) {                            \
            base_message(__VA_ARGS__);                  \
            once = true;                                \
        }                                               \
    } while (0)

extern bool want_warn, warn_verbose;
extern bool want_info, info_verbose;
extern bool want_hack, hack_verbose;

#define warn(...) \
    cond_message(want_warn, std::cerr, "warn", warn_verbose, __VA_ARGS__)
#define inform(...) \
    cond_message(want_info, std::cout, "info", info_verbose, __VA_ARGS__)
#define hack(...) \
    cond_message(want_hack, std::cerr, "hack", hack_verbose, __VA_ARGS__)

#define warn_once(...) \
    cond_message_once(want_warn, std::cerr, "warn", warn_verbose, __VA_ARGS__)
#define inform_once(...) \
    cond_message_once(want_info, std::cout, "info", info_verbose, __VA_ARGS__)
#define hack_once(...) \
    cond_message_once(want_hack, std::cerr, "hack", hack_verbose, __VA_ARGS__)

/**
 * The chatty assert macro will function like a normal assert, but will allow the
 * specification of additional, helpful material to aid debugging why the
 * assertion actually failed.  Like the normal assertion, the chatty_assert
 * will not be active in fast builds.
 *
 * @param cond Condition that is checked; if false -> assert
 * @param ...  Printf-based format string with arguments, extends printout.
 */
#ifdef NDEBUG
#define chatty_assert(cond, ...)
#else //!NDEBUG
#define chatty_assert(cond, ...)                                                \
    do {                                                                        \
        if (!(cond)) {                                                          \
            base_message(std::cerr, "assert("#cond") failing", 1, __VA_ARGS__); \
            assert(cond);                                                       \
        }                                                                       \
    } while (0)
#endif // NDEBUG
#endif // __BASE_MISC_HH__
<|endoftext|>


<commit_before><commit_msg>windows fontgen removed<commit_after><|endoftext|>


<commit_before><commit_msg>Replace List with std::vector< GraphicFilter* ><commit_after><|endoftext|>


<commit_before><commit_msg>Chg: Vertical Formatting - Maximum size for rotated portions<commit_after><|endoftext|>


<commit_before><commit_msg>INTEGRATION: CWS pchfix02 (1.12.474); FILE MERGED 2006/09/01 17:52:54 kaib 1.12.474.1: #i68856# Added header markers and pch files<commit_after><|endoftext|>