<commit_before>/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** Commercial Usage
**
** Licensees holding valid Qt Commercial licenses may use this file in
** accordance with the Qt Commercial License Agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Nokia.
**
** 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.
**
** If you are unsure which license is appropriate for your use, please
** contact the sales department at http://qt.nokia.com/contact.
**
**************************************************************************/

#include "qmljscheck.h"
#include "qmljsbind.h"
#include "qmljsinterpreter.h"
#include "qmljsevaluate.h"
#include "parser/qmljsast_p.h"

#include <QtCore/QDebug>

using namespace QmlJS;
using namespace QmlJS::AST;
using namespace QmlJS::Interpreter;

Check::Check(Document::Ptr doc, const Snapshot &snapshot)
    : _doc(doc)
    , _snapshot(snapshot)
    , _context(&_engine)
    , _link(&_context, doc, snapshot)
    , _extraScope(0)
    , _allowAnyProperty(false)
{
}

Check::~Check()
{
}

QList<DiagnosticMessage> Check::operator()()
{
    _messages.clear();
    Node::accept(_doc->ast(), this);
    return _messages;
}

bool Check::visit(UiProgram *ast)
{
    // build the initial scope chain
    if (ast->members && ast->members->member)
        _link.scopeChainAt(_doc, ast->members->member);

    return true;
}

bool Check::visit(UiObjectDefinition *ast)
{
    visitQmlObject(ast, ast->qualifiedTypeNameId, ast->initializer);
    return false;
}

bool Check::visit(UiObjectBinding *ast)
{
    checkScopeObjectMember(ast->qualifiedId);

    visitQmlObject(ast, ast->qualifiedTypeNameId, ast->initializer);
    return false;
}

void Check::visitQmlObject(Node *ast, UiQualifiedId *typeId,
                           UiObjectInitializer *initializer)
{
    // If the 'typeId' starts with a lower-case letter, it doesn't define
    // a new object instance. For instance: anchors { ... }
    if (typeId->name->asString().at(0).isLower() && ! typeId->next) {
        checkScopeObjectMember(typeId);
        // ### don't give up!
        return;
    }

    if (! _context.lookupType(_doc.data(), typeId)) {
        warning(typeId->identifierToken, QLatin1String("unknown type"));
        // ### don't give up!
        return;
    }

    const ObjectValue *oldScopeObject = _context.qmlScopeObject();
    const ObjectValue *oldExtraScope = _extraScope;
    const bool oldAllowAnyProperty = _allowAnyProperty;
    const ObjectValue *scopeObject = _doc->bind()->findQmlObject(ast);
    _context.setQmlScopeObject(scopeObject);

#ifndef NO_DECLARATIVE_BACKEND
    // check if the object has a Qt.ListElement ancestor
    const ObjectValue *prototype = scopeObject->prototype(&_context);
    while (prototype) {
        if (const QmlObjectValue *qmlMetaObject = dynamic_cast<const QmlObjectValue *>(prototype)) {
            // ### Also check for Qt package. Involves changes in QmlObjectValue.
            if (qmlMetaObject->qmlTypeName() == QLatin1String("ListElement")) {
                _allowAnyProperty = true;
                break;
            }
        }
        prototype = prototype->prototype(&_context);
    }

    // check if the object has a Qt.PropertyChanges ancestor
    prototype = scopeObject->prototype(&_context);
    while (prototype) {
        if (const QmlObjectValue *qmlMetaObject = dynamic_cast<const QmlObjectValue *>(prototype)) {
            // ### Also check for Qt package. Involves changes in QmlObjectValue.
            if (qmlMetaObject->qmlTypeName() == QLatin1String("PropertyChanges"))
                break;
        }
        prototype = prototype->prototype(&_context);
    }
    // find the target script binding
    if (prototype && initializer) {
        for (UiObjectMemberList *m = initializer->members; m; m = m->next) {
            if (UiScriptBinding *scriptBinding = cast<UiScriptBinding *>(m->member)) {
                if (scriptBinding->qualifiedId
                        && scriptBinding->qualifiedId->name->asString() == QLatin1String("target")
                        && ! scriptBinding->qualifiedId->next) {
                    if (ExpressionStatement *expStmt = cast<ExpressionStatement *>(scriptBinding->statement)) {
                        Evaluate evaluator(&_context);
                        const Value *targetValue = evaluator(expStmt->expression);

                        if (const ObjectValue *target = value_cast<const ObjectValue *>(targetValue)) {
                            _extraScope = target;
                        } else {
                            _allowAnyProperty = true;
                        }
                    }
                }
            }
        }
    }
#endif

    Node::accept(initializer, this);

    _context.setQmlScopeObject(oldScopeObject);
    _extraScope = oldExtraScope;
    _allowAnyProperty = oldAllowAnyProperty;
}

bool Check::visit(UiScriptBinding *ast)
{
    checkScopeObjectMember(ast->qualifiedId);

    return true;
}

bool Check::visit(UiArrayBinding *ast)
{
    checkScopeObjectMember(ast->qualifiedId);

    return true;
}

void Check::checkScopeObjectMember(const UiQualifiedId *id)
{
    if (_allowAnyProperty)
        return;

    const ObjectValue *scopeObject = _context.qmlScopeObject();

    if (! id)
        return; // ### error?

    QString propertyName = id->name->asString();

    if (propertyName == QLatin1String("id") && ! id->next)
        return;

    // attached properties
    bool isAttachedProperty = false;
    if (! propertyName.isEmpty() && propertyName[0].isUpper()) {
        isAttachedProperty = true;
        scopeObject = _context.typeEnvironment(_doc.data());
    }

    if (! scopeObject)
        return;

    // global lookup for first part of id
    const Value *value = scopeObject->lookupMember(propertyName, &_context);
    if (_extraScope && !value)
        value = _extraScope->lookupMember(propertyName, &_context);
    if (!value) {
        error(id->identifierToken,
              QString("'%1' is not a valid property name").arg(propertyName));
        return;
    }

    // can't look up members for attached properties
    if (isAttachedProperty)
        return;

    // member lookup
    const UiQualifiedId *idPart = id;
    while (idPart->next) {
        const ObjectValue *objectValue = value_cast<const ObjectValue *>(value);
        if (! objectValue) {
            error(idPart->identifierToken,
                  QString("'%1' does not have members").arg(propertyName));
            return;
        }

        idPart = idPart->next;
        propertyName = idPart->name->asString();

        value = objectValue->lookupMember(propertyName, &_context);
        if (! value) {
            error(idPart->identifierToken,
                  QString("'%1' is not a member of '%2'").arg(propertyName, objectValue->className()));
            return;
        }
    }
}

void Check::error(const AST::SourceLocation &loc, const QString &message)
{
    _messages.append(DiagnosticMessage(DiagnosticMessage::Error, loc, message));
}

void Check::warning(const AST::SourceLocation &loc, const QString &message)
{
    _messages.append(DiagnosticMessage(DiagnosticMessage::Warning, loc, message));
}
<commit_msg>Suppress 'unknown property' warning after finding an unknown type. And made the warnings/errors translatable.<commit_after>/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** Commercial Usage
**
** Licensees holding valid Qt Commercial licenses may use this file in
** accordance with the Qt Commercial License Agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Nokia.
**
** 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.
**
** If you are unsure which license is appropriate for your use, please
** contact the sales department at http://qt.nokia.com/contact.
**
**************************************************************************/

#include "qmljscheck.h"
#include "qmljsbind.h"
#include "qmljsinterpreter.h"
#include "qmljsevaluate.h"
#include "parser/qmljsast_p.h"

#include <QtGui/QApplication>
#include <QtCore/QDebug>

namespace QmlJS {
namespace Messages {
static const char *invalidPropertyName =  QT_TRANSLATE_NOOP("QmlJS::Check", "'%1' is not a valid property name");
static const char *unknownType = QT_TRANSLATE_NOOP("QmlJS::Check", "unknown type");
} // namespace Messages

static inline QString tr(const char *msg)
{ return qApp->translate("QmlJS::Check", msg); }

} // namespace QmlJS

using namespace QmlJS;
using namespace QmlJS::AST;
using namespace QmlJS::Interpreter;

Check::Check(Document::Ptr doc, const Snapshot &snapshot)
    : _doc(doc)
    , _snapshot(snapshot)
    , _context(&_engine)
    , _link(&_context, doc, snapshot)
    , _extraScope(0)
    , _allowAnyProperty(false)
{
}

Check::~Check()
{
}

QList<DiagnosticMessage> Check::operator()()
{
    _messages.clear();
    Node::accept(_doc->ast(), this);
    return _messages;
}

bool Check::visit(UiProgram *ast)
{
    // build the initial scope chain
    if (ast->members && ast->members->member)
        _link.scopeChainAt(_doc, ast->members->member);

    return true;
}

bool Check::visit(UiObjectDefinition *ast)
{
    visitQmlObject(ast, ast->qualifiedTypeNameId, ast->initializer);
    return false;
}

bool Check::visit(UiObjectBinding *ast)
{
    checkScopeObjectMember(ast->qualifiedId);

    visitQmlObject(ast, ast->qualifiedTypeNameId, ast->initializer);
    return false;
}

void Check::visitQmlObject(Node *ast, UiQualifiedId *typeId,
                           UiObjectInitializer *initializer)
{
    // If the 'typeId' starts with a lower-case letter, it doesn't define
    // a new object instance. For instance: anchors { ... }
    if (typeId->name->asString().at(0).isLower() && ! typeId->next) {
        checkScopeObjectMember(typeId);
        // ### don't give up!
        return;
    }

    const bool oldAllowAnyProperty = _allowAnyProperty;

    if (! _context.lookupType(_doc.data(), typeId)) {
        warning(typeId->identifierToken, tr(Messages::unknownType));
        _allowAnyProperty = true; // suppress subsequent "unknown property" errors
    }

    const ObjectValue *oldScopeObject = _context.qmlScopeObject();
    const ObjectValue *oldExtraScope = _extraScope;
    const ObjectValue *scopeObject = _doc->bind()->findQmlObject(ast);
    _context.setQmlScopeObject(scopeObject);

#ifndef NO_DECLARATIVE_BACKEND
    // check if the object has a Qt.ListElement ancestor
    const ObjectValue *prototype = scopeObject->prototype(&_context);
    while (prototype) {
        if (const QmlObjectValue *qmlMetaObject = dynamic_cast<const QmlObjectValue *>(prototype)) {
            // ### Also check for Qt package. Involves changes in QmlObjectValue.
            if (qmlMetaObject->qmlTypeName() == QLatin1String("ListElement")) {
                _allowAnyProperty = true;
                break;
            }
        }
        prototype = prototype->prototype(&_context);
    }

    // check if the object has a Qt.PropertyChanges ancestor
    prototype = scopeObject->prototype(&_context);
    while (prototype) {
        if (const QmlObjectValue *qmlMetaObject = dynamic_cast<const QmlObjectValue *>(prototype)) {
            // ### Also check for Qt package. Involves changes in QmlObjectValue.
            if (qmlMetaObject->qmlTypeName() == QLatin1String("PropertyChanges"))
                break;
        }
        prototype = prototype->prototype(&_context);
    }
    // find the target script binding
    if (prototype && initializer) {
        for (UiObjectMemberList *m = initializer->members; m; m = m->next) {
            if (UiScriptBinding *scriptBinding = cast<UiScriptBinding *>(m->member)) {
                if (scriptBinding->qualifiedId
                        && scriptBinding->qualifiedId->name->asString() == QLatin1String("target")
                        && ! scriptBinding->qualifiedId->next) {
                    if (ExpressionStatement *expStmt = cast<ExpressionStatement *>(scriptBinding->statement)) {
                        Evaluate evaluator(&_context);
                        const Value *targetValue = evaluator(expStmt->expression);

                        if (const ObjectValue *target = value_cast<const ObjectValue *>(targetValue)) {
                            _extraScope = target;
                        } else {
                            _allowAnyProperty = true;
                        }
                    }
                }
            }
        }
    }
#endif

    Node::accept(initializer, this);

    _context.setQmlScopeObject(oldScopeObject);
    _extraScope = oldExtraScope;
    _allowAnyProperty = oldAllowAnyProperty;
}

bool Check::visit(UiScriptBinding *ast)
{
    checkScopeObjectMember(ast->qualifiedId);

    return true;
}

bool Check::visit(UiArrayBinding *ast)
{
    checkScopeObjectMember(ast->qualifiedId);

    return true;
}

void Check::checkScopeObjectMember(const UiQualifiedId *id)
{
    if (_allowAnyProperty)
        return;

    const ObjectValue *scopeObject = _context.qmlScopeObject();

    if (! id)
        return; // ### error?

    QString propertyName = id->name->asString();

    if (propertyName == QLatin1String("id") && ! id->next)
        return;

    // attached properties
    bool isAttachedProperty = false;
    if (! propertyName.isEmpty() && propertyName[0].isUpper()) {
        isAttachedProperty = true;
        scopeObject = _context.typeEnvironment(_doc.data());
    }

    if (! scopeObject)
        return;

    // global lookup for first part of id
    const Value *value = scopeObject->lookupMember(propertyName, &_context);
    if (_extraScope && !value)
        value = _extraScope->lookupMember(propertyName, &_context);
    if (!value) {
        error(id->identifierToken,
              tr(Messages::invalidPropertyName).arg(propertyName));
    }

    // can't look up members for attached properties
    if (isAttachedProperty)
        return;

    // member lookup
    const UiQualifiedId *idPart = id;
    while (idPart->next) {
        const ObjectValue *objectValue = value_cast<const ObjectValue *>(value);
        if (! objectValue) {
            error(idPart->identifierToken,
                  QString("'%1' does not have members").arg(propertyName));
            return;
        }

        idPart = idPart->next;
        propertyName = idPart->name->asString();

        value = objectValue->lookupMember(propertyName, &_context);
        if (! value) {
            error(idPart->identifierToken,
                  QString("'%1' is not a member of '%2'").arg(propertyName, objectValue->className()));
            return;
        }
    }
}

void Check::error(const AST::SourceLocation &loc, const QString &message)
{
    _messages.append(DiagnosticMessage(DiagnosticMessage::Error, loc, message));
}

void Check::warning(const AST::SourceLocation &loc, const QString &message)
{
    _messages.append(DiagnosticMessage(DiagnosticMessage::Warning, loc, message));
}
<|endoftext|>


<commit_before>#include <gtkmm.h>

#include <string>
#include <fstream>
#include <iostream>

#include "libjsapi.h"

#include "application.h"
#include "window.h"
#include "builder.h"

std::string LoadScript(int argc, char** argv) {
    std::string script;

    for (int i = 1; i < argc; i++) {
        std::fstream file;
        file.open(argv[i], std::ios::in);
        while (!!file) {
            char buffer[4096];
            file.read(buffer, sizeof(buffer));
            script.append(buffer, file.gcount());
            script += ";\n";
        }
    }

    return std::move(script);
}

int main(int argc, char** argv) {

    try {
        std::string script = LoadScript(argc, argv);

        rs::jsapi::Runtime rt(512 * 1024 * 1024);

        auto app = new Application(rt, "com.ripcordsoftware.examples.gtk", 1, argv);
        rs::jsapi::Global::DefineProperty(rt, "app", *app);

        auto builder = new Builder(rt);
        rs::jsapi::Global::DefineProperty(rt, "builder", *builder);

        rs::jsapi::Global::DefineFunction(rt, "trace",
            [](JSContext *cx, unsigned argc, JS::Value *vp){
                auto args = JS::CallArgsFromVp(argc, vp);

                for (int i = 0; i < args.length(); i++) {
                    rs::jsapi::Value value(cx, args[i]);
                    std::cout << value.ToString();
                }

                if (args.length() > 0) {
                    std::cout << std::endl;
                }

                return true;
            });

        rt.Evaluate(script.c_str());
    } catch (const rs::jsapi::ScriptException& ex) {
        std::cerr <<
            "ERROR: line " << ex.lineno << std::endl <<
            ex.what() << std::endl <<
            ex.linebuf << std::endl;

    }

    return 0;
}<commit_msg>Correct main script loading logic<commit_after>#include <gtkmm.h>

#include <string>
#include <fstream>
#include <iostream>

#include "libjsapi.h"

#include "application.h"
#include "window.h"
#include "builder.h"

std::string LoadScript(int argc, char** argv) {
    std::string script;

    for (int i = 1; i < argc; i++) {
        std::fstream file;
        file.open(argv[i], std::ios::in);
        while (!!file) {
            char buffer[4096];
            file.read(buffer, sizeof(buffer));
            script.append(buffer, file.gcount());
        }

        script += ";\n";
    }

    return std::move(script);
}

int main(int argc, char** argv) {

    try {
        std::string script = LoadScript(argc, argv);

        rs::jsapi::Runtime rt(1024 * 1024 * 1024);

        auto app = new Application(rt, "com.ripcordsoftware.examples.gtk", 1, argv);
        rs::jsapi::Global::DefineProperty(rt, "app", *app);

        auto builder = new Builder(rt);
        rs::jsapi::Global::DefineProperty(rt, "builder", *builder);

        rs::jsapi::Global::DefineFunction(rt, "trace",
            [](JSContext *cx, unsigned argc, JS::Value *vp){
                auto args = JS::CallArgsFromVp(argc, vp);

                for (int i = 0; i < args.length(); i++) {
                    rs::jsapi::Value value(cx, args[i]);
                    std::cout << value.ToString();
                }

                if (args.length() > 0) {
                    std::cout << std::endl;
                }

                return true;
            });

        rt.Evaluate(script.c_str());
    } catch (const rs::jsapi::ScriptException& ex) {
        std::cerr <<
            "ERROR: line " << ex.lineno << std::endl <<
            ex.what() << std::endl <<
            ex.linebuf << std::endl;

    }

    return 0;
}<|endoftext|>


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

#include "caffe2/core/net_dag.h"

#include <iostream>
#include <set>
#include <stack>
#include <unordered_map>
#include <unordered_set>

#include "caffe2/core/operator.h"
#include "caffe2/core/static_tracepoint.h"
#include "caffe2/core/timer.h"
#include "caffe2/proto/caffe2.pb.h"
#include "caffe2/utils/proto_utils.h"

CAFFE2_DEFINE_bool(
    caffe2_disable_chaining,
    false,
    "Disable chaining logic (some latent multi-device issues).");

CAFFE2_DEFINE_bool(
    caffe2_dag_net_collect_stats,
    false,
    "Collect time stats in DAG net");

namespace caffe2 {

DAGNetBase::DAGNetBase(
    const std::shared_ptr<const NetDef>& net_def,
    Workspace* ws)
    : NetBase(net_def, ws), caught_exception_yet_(false), iter_(0) {
  // Blob creator allows us to track which operator created which blob.
  VLOG(1) << "Constructing DAGNet " << net_def->name();

  operator_nodes_ = dag_utils::prepareOperatorNodes(net_def, ws);

  execution_chains_ =
      (FLAGS_caffe2_disable_chaining
           ? dag_utils::singleChains(operator_nodes_)
           : dag_utils::computeChains(operator_nodes_));

  operators_.reserve(operator_nodes_.size());
  for (const auto& node : operator_nodes_) {
    operators_.push_back(node.operator_.get());
  }

  LOG(INFO) << "Number of parallel execution chains "
            << execution_chains_.size()
            << " Number of operators = " << net_def->op_size();
  // TODO: do we want to make sure that there are no loops in the
  // dependency graph?

  // Figure out the initial frontier - this is the one we will feed into the job
  // queue to start a run.
  for (int idx = 0; idx < operator_nodes_.size(); ++idx) {
    if (operator_nodes_[idx].parents_.size() == 0) {
      initial_frontier_.push_back(idx);
    }
  }
  // Finally, start the workers.
  int num_workers = net_def->has_num_workers() ? net_def->num_workers() : 1;
  CAFFE_ENFORCE(num_workers > 0, "Must have a positive number of workers.");
  if (num_workers == 1) {
    LOG(WARNING) << "Number of workers is 1: this means that all operators "
                 << "will be executed sequentially. Did you forget to set "
                 << "num_workers in the NetDef?";
  }
  num_workers_ = num_workers;

  for (int idx = 0; idx < operator_nodes_.size(); ++idx) {
    if (operator_nodes_[idx].is_chain_start_) {
      task_timers_[idx] = caffe2::make_unique<Timer>();
    }
  }
  stats_.reserve(DeviceType::COMPILE_TIME_MAX_DEVICE_TYPES);
  for (auto device_idx = 0;
       device_idx < DeviceType::COMPILE_TIME_MAX_DEVICE_TYPES;
       ++device_idx) {
    stats_.emplace_back(
        "dag_net/stats/" + net_def->name() + "/" +
        caffe2::DeviceTypeName(device_idx));
  }
}

DAGNetBase::~DAGNetBase() {
  if (job_queue_) {
    job_queue_->NoMoreJobs();
    VLOG(1) << "Joining workers.";
    for (auto& worker : workers_) {
      worker.join();
    }
  }
}

bool DAGNetBase::DoRunAsync() {
  StartAllObservers();

  // Lock run_in_progress_ to prevent concurrent Run()s.
  std::unique_lock<std::mutex> run_lock(run_in_progress_);
  VLOG(1) << "Running parallel net.";
  // First, set up job queue.
  remaining_ops_ = operator_nodes_.size();
  success_ = true;
  iter_++;
  if (!job_queue_) {
    job_queue_ = caffe2::make_unique<SimpleQueue<int>>();
  }
  // Figure out number of workers to start.
  auto num_workers_to_start = num_workers_ - workers_.size();

  // Ensure the number of workers matches the defined in case
  // any of the previously started threads terminated.
  for (auto i = 0; i < num_workers_to_start; i++) {
    VLOG(1) << "Start worker #" << workers_.size();
    workers_.push_back(std::thread(&DAGNetBase::WorkerFunction, this));
  }
  // Initialize the runtime parent count.
  for (auto& node : operator_nodes_) {
    node.runtime_parent_count_ = node.parents_.size();
  }
  // Kickstart the job queue.
  for (auto& value : initial_frontier_) {
    if (FLAGS_caffe2_dag_net_collect_stats) {
      task_timers_[value]->Start();
    }
    job_queue_->Push(value);
  }
  // Wait for failure or completed execution.
  {
    std::unique_lock<std::mutex> mutex_lock(remaining_ops_mutex_);
    for (;;) {
      if (remaining_ops_ == 0 || !success_) {
        break;
      }
      cv_.wait(mutex_lock);
    }
  }
  // Wait for all workers to terminate after failure.
  // If there is a failure, it is unlikely that the net is executed
  // again without modifications. Therefore it's easier to let the
  // workers terminate here, versus adding a drain state to make the
  // sure the job queue is cleared.
  if (!success_) {
    for (auto& worker : workers_) {
      worker.join();
    }
    workers_.clear();
    job_queue_.reset(nullptr);
#ifdef CAFFE2_USE_EXCEPTION_PTR
    if (caught_exception_) {
      // Reset flag here in case Net gets run again
      caught_exception_yet_ = false;
      std::rethrow_exception(caught_exception_);
    }
#endif // CAFFE2_USE_EXCEPTION_PTR
    return success_;
  }
  VLOG(2) << "All ops finished running.";
  for (const auto& op : operator_nodes_) {
    CAFFE_ENFORCE(
        op.runtime_parent_count_ == 0,
        "Operator ",
        op.operator_->debug_def().name(),
        "(",
        op.operator_->debug_def().type(),
        ") has some runtime parents left.");
  }

  StopAllObservers();
  // If the above while loop finished, we know that the current run finished.
  return success_;
}

void DAGNetBase::HandleException(
    int operator_idx,
    const std::string& exception_str) {
  const std::string& operator_name =
      operator_nodes_[operator_idx].operator_->debug_def().name();
  const std::string& operator_type =
      operator_nodes_[operator_idx].operator_->debug_def().type();
  const char* prefix = "Exception from operator '";
#ifdef CAFFE2_USE_EXCEPTION_PTR
  if (!caught_exception_yet_.exchange(true)) {
    caught_exception_ = std::current_exception();
  } else {
    prefix = "Secondary exception from operator '";
  }
#endif // CAFFE2_USE_EXCEPTION_PTR
  LOG(ERROR) << prefix << operator_name << "' (type '" << operator_type
             << "'): " << exception_str << "\n";
#ifndef CAFFE2_USE_EXCEPTION_PTR
  throw; // Can't capture for dispatch to other thread, re-throw here
#endif // CAFFE2_USE_EXCEPTION_PTR
}

void DAGNetBase::WorkerFunction() {
  // WorkerFunctions() is an infinite loop until there are no more jobs to run.
  while (true) {
    int idx = 0;

    // Return if there are no more operators to run (e.g. the
    // DAGNetBase is destructing, or there was an error on another
    // worker and we're cleaning up).
    if (!job_queue_->Pop(&idx)) {
      return;
    }
    if (FLAGS_caffe2_dag_net_collect_stats) {
      auto device_option =
          operator_nodes_[idx].operator_->event().GetDeviceOption();
      CAFFE_EVENT(
          stats_[device_option.device_type()],
          task_pool_wait_time_us,
          task_timers_[idx]->MicroSeconds());
    }

    VLOG(1) << "Running operator #" << idx << " "
            << operator_nodes_[idx].operator_->debug_def().name() << "("
            << operator_nodes_[idx].operator_->debug_def().type() << ").";
    CAFFE_ENFORCE(
        execution_chains_.find(idx) != execution_chains_.end(),
        "Can't find chain ",
        idx,
        ".");
    const auto& chain = execution_chains_[idx];
    bool this_success = false;
    try {
      this_success = RunAt(idx, execution_chains_[idx]);

      if (!this_success) {
        // If an exception was thrown, the operator def will get printed
        // by Operator::Run[Async], but if no exception occurs we print it here.
        LOG(ERROR) << "Operator chain failed: "
                   << ProtoDebugString(
                          operator_nodes_[idx].operator_->debug_def());
      }
    } catch (std::exception& e) {
      std::string exception_str = GetExceptionString(e);
      HandleException(idx, exception_str);
    } catch (...) {
      std::string exception_str = "Unknown exception";
      HandleException(idx, exception_str);
    }

    // Do book-keeping
    std::vector<int> chains_to_queue;
    for (const auto idx : chain) {
      for (const auto child : operator_nodes_[idx].children_) {
        const int count = --operator_nodes_[child].runtime_parent_count_;
        CAFFE_ENFORCE(
            count >= 0,
            "Found runtime parent count smaller than zero for ",
            "operator node ",
            operator_nodes_[child].operator_->debug_def().name(),
            "(",
            operator_nodes_[child].operator_->debug_def().type(),
            ").");

        if (count != 0) {
          continue;
        }

        if (operator_nodes_[child].is_chain_start_) {
          VLOG(2) << "Pushing chain #" << child << " to queue.";
          chains_to_queue.push_back(child);
        }
      }
    }

    // Notify the caller of Run
    {
      std::unique_lock<std::mutex> mutex_lock(remaining_ops_mutex_);
      remaining_ops_ -= chain.size();
      CAFFE_ENFORCE(remaining_ops_ >= 0);
      success_ &= this_success;
      if (remaining_ops_ == 0 || !success_) {
        cv_.notify_one();
      }

      // Terminate thread if this or any other operator chain failed.
      if (!success_) {
        job_queue_->NoMoreJobs();
        return;
      }

      // Queue follow up operator chains.
      // Can't do this inline because it can race with another thread
      // calling NoMoreJobs(). So the lock needs to be held on push.
      for (const auto idx : chains_to_queue) {
        if (FLAGS_caffe2_dag_net_collect_stats) {
          task_timers_[idx]->Start();
        }
        job_queue_->Push(idx);
      }
    }

    VLOG(2) << "Finished executing operator #" << idx;
  }
}

vector<float> DAGNetBase::TEST_Benchmark(
    const int warmup_runs,
    const int main_runs,
    const bool run_individual) {
  std::cout << "Starting benchmark." << std::endl;
  std::cout << "Running warmup runs." << std::endl;
  CAFFE_ENFORCE(
      warmup_runs >= 0,
      "Number of warm up runs should be non negative, provided ",
      warmup_runs,
      ".");
  for (int i = 0; i < warmup_runs; ++i) {
    CAFFE_ENFORCE(Run(), "Warmup run ", i, " has failed.");
  }

  std::cout << "Main runs." << std::endl;
  CAFFE_ENFORCE(
      main_runs >= 0,
      "Number of main runs should be non negative, provided ",
      main_runs,
      ".");
  Timer timer;
  for (int i = 0; i < main_runs; ++i) {
    CAFFE_ENFORCE(Run(), "Main run ", i, " has failed.");
  }
  auto millis = timer.MilliSeconds();
  std::cout << "Main run finished. Milliseconds per iter: "
            << millis / main_runs
            << ". Iters per second: " << 1000.0 * main_runs / millis << std::endl;

  if (run_individual) {
    std::cout << "DAGNet does not do per-op benchmark. To do so, "
                 "switch to a simple net type." << std::endl;
  }
  return vector<float>{millis / main_runs};
}

bool DAGNet::RunAt(int chain_id, const std::vector<int>& chain) {
  for (const auto i : chain) {
#ifdef CAFFE2_ENABLE_SDT
    const auto& op_name =
        operator_nodes_[i].operator_->debug_def().name().c_str();
    const auto& op_type =
        operator_nodes_[i].operator_->debug_def().type().c_str();
    auto* op_ptr = operator_nodes_[i].operator_.get();
    const auto& net_name = name_.c_str();
    CAFFE_SDT(operator_start, net_name, op_name, op_type, op_ptr);
#endif
    const auto success = operator_nodes_[i].operator_->Run();
#ifdef CAFFE2_ENABLE_SDT
    CAFFE_SDT(operator_done, net_name, op_name, op_type, op_ptr);
#endif
    if (!success) {
      return false;
    }
  }
  if (FLAGS_caffe2_dag_net_collect_stats) {
    auto device_option =
        operator_nodes_[chain_id].operator_->event().GetDeviceOption();
    CAFFE_EVENT(
        stats_[device_option.device_type()],
        task_time_to_succeeded_ms,
        task_timers_[chain_id]->MilliSeconds());
  }
  return true;
}

REGISTER_NET(dag, DAGNet);

} // namespace caffe2
<commit_msg>Make error messages in net_dag more clear<commit_after>/**
 * Copyright (c) 2016-present, Facebook, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "caffe2/core/net_dag.h"

#include <iostream>
#include <set>
#include <stack>
#include <unordered_map>
#include <unordered_set>

#include "caffe2/core/operator.h"
#include "caffe2/core/static_tracepoint.h"
#include "caffe2/core/timer.h"
#include "caffe2/proto/caffe2.pb.h"
#include "caffe2/utils/proto_utils.h"

CAFFE2_DEFINE_bool(
    caffe2_disable_chaining,
    false,
    "Disable chaining logic (some latent multi-device issues).");

CAFFE2_DEFINE_bool(
    caffe2_dag_net_collect_stats,
    false,
    "Collect time stats in DAG net");

namespace caffe2 {

DAGNetBase::DAGNetBase(
    const std::shared_ptr<const NetDef>& net_def,
    Workspace* ws)
    : NetBase(net_def, ws), caught_exception_yet_(false), iter_(0) {
  // Blob creator allows us to track which operator created which blob.
  VLOG(1) << "Constructing DAGNet " << net_def->name();

  operator_nodes_ = dag_utils::prepareOperatorNodes(net_def, ws);

  execution_chains_ =
      (FLAGS_caffe2_disable_chaining
           ? dag_utils::singleChains(operator_nodes_)
           : dag_utils::computeChains(operator_nodes_));

  operators_.reserve(operator_nodes_.size());
  for (const auto& node : operator_nodes_) {
    operators_.push_back(node.operator_.get());
  }

  LOG(INFO) << "Number of parallel execution chains "
            << execution_chains_.size()
            << " Number of operators = " << net_def->op_size();
  // TODO: do we want to make sure that there are no loops in the
  // dependency graph?

  // Figure out the initial frontier - this is the one we will feed into the job
  // queue to start a run.
  for (int idx = 0; idx < operator_nodes_.size(); ++idx) {
    if (operator_nodes_[idx].parents_.size() == 0) {
      initial_frontier_.push_back(idx);
    }
  }
  // Finally, start the workers.
  int num_workers = net_def->has_num_workers() ? net_def->num_workers() : 1;
  CAFFE_ENFORCE(num_workers > 0, "Must have a positive number of workers.");
  if (num_workers == 1) {
    LOG(WARNING) << "Number of workers is 1: this means that all operators "
                 << "will be executed sequentially. Did you forget to set "
                 << "num_workers in the NetDef?";
  }
  num_workers_ = num_workers;

  for (int idx = 0; idx < operator_nodes_.size(); ++idx) {
    if (operator_nodes_[idx].is_chain_start_) {
      task_timers_[idx] = caffe2::make_unique<Timer>();
    }
  }
  stats_.reserve(DeviceType::COMPILE_TIME_MAX_DEVICE_TYPES);
  for (auto device_idx = 0;
       device_idx < DeviceType::COMPILE_TIME_MAX_DEVICE_TYPES;
       ++device_idx) {
    stats_.emplace_back(
        "dag_net/stats/" + net_def->name() + "/" +
        caffe2::DeviceTypeName(device_idx));
  }
}

DAGNetBase::~DAGNetBase() {
  if (job_queue_) {
    job_queue_->NoMoreJobs();
    VLOG(1) << "Joining workers.";
    for (auto& worker : workers_) {
      worker.join();
    }
  }
}

bool DAGNetBase::DoRunAsync() {
  StartAllObservers();

  // Lock run_in_progress_ to prevent concurrent Run()s.
  std::unique_lock<std::mutex> run_lock(run_in_progress_);
  VLOG(1) << "Running parallel net.";
  // First, set up job queue.
  remaining_ops_ = operator_nodes_.size();
  success_ = true;
  iter_++;
  if (!job_queue_) {
    job_queue_ = caffe2::make_unique<SimpleQueue<int>>();
  }
  // Figure out number of workers to start.
  auto num_workers_to_start = num_workers_ - workers_.size();

  // Ensure the number of workers matches the defined in case
  // any of the previously started threads terminated.
  for (auto i = 0; i < num_workers_to_start; i++) {
    VLOG(1) << "Start worker #" << workers_.size();
    workers_.push_back(std::thread(&DAGNetBase::WorkerFunction, this));
  }
  // Initialize the runtime parent count.
  for (auto& node : operator_nodes_) {
    node.runtime_parent_count_ = node.parents_.size();
  }
  // Kickstart the job queue.
  for (auto& value : initial_frontier_) {
    if (FLAGS_caffe2_dag_net_collect_stats) {
      task_timers_[value]->Start();
    }
    job_queue_->Push(value);
  }
  // Wait for failure or completed execution.
  {
    std::unique_lock<std::mutex> mutex_lock(remaining_ops_mutex_);
    for (;;) {
      if (remaining_ops_ == 0 || !success_) {
        break;
      }
      cv_.wait(mutex_lock);
    }
  }
  // Wait for all workers to terminate after failure.
  // If there is a failure, it is unlikely that the net is executed
  // again without modifications. Therefore it's easier to let the
  // workers terminate here, versus adding a drain state to make the
  // sure the job queue is cleared.
  if (!success_) {
    for (auto& worker : workers_) {
      worker.join();
    }
    workers_.clear();
    job_queue_.reset(nullptr);
#ifdef CAFFE2_USE_EXCEPTION_PTR
    if (caught_exception_) {
      // Reset flag here in case Net gets run again
      caught_exception_yet_ = false;
      std::rethrow_exception(caught_exception_);
    }
#endif // CAFFE2_USE_EXCEPTION_PTR
    return success_;
  }
  VLOG(2) << "All ops finished running.";
  for (const auto& op : operator_nodes_) {
    CAFFE_ENFORCE(
        op.runtime_parent_count_ == 0,
        "Operator ",
        op.operator_->debug_def().name(),
        "(",
        op.operator_->debug_def().type(),
        ") has some runtime parents left.");
  }

  StopAllObservers();
  // If the above while loop finished, we know that the current run finished.
  return success_;
}

void DAGNetBase::HandleException(
    int operator_idx,
    const std::string& exception_str) {
  const std::string& operator_name =
      operator_nodes_[operator_idx].operator_->debug_def().name();
  const std::string& operator_type =
      operator_nodes_[operator_idx].operator_->debug_def().type();
  const char* prefix = "Exception from operator chain starting at '";
#ifdef CAFFE2_USE_EXCEPTION_PTR
  if (!caught_exception_yet_.exchange(true)) {
    caught_exception_ = std::current_exception();
  } else {
    prefix = "Secondary exception from operator chain starting at '";
  }
#endif // CAFFE2_USE_EXCEPTION_PTR
  LOG(ERROR) << prefix << operator_name << "' (type '" << operator_type
             << "'): " << exception_str << "\n";
#ifndef CAFFE2_USE_EXCEPTION_PTR
  throw; // Can't capture for dispatch to other thread, re-throw here
#endif // CAFFE2_USE_EXCEPTION_PTR
}

void DAGNetBase::WorkerFunction() {
  // WorkerFunctions() is an infinite loop until there are no more jobs to run.
  while (true) {
    int idx = 0;

    // Return if there are no more operators to run (e.g. the
    // DAGNetBase is destructing, or there was an error on another
    // worker and we're cleaning up).
    if (!job_queue_->Pop(&idx)) {
      return;
    }
    if (FLAGS_caffe2_dag_net_collect_stats) {
      auto device_option =
          operator_nodes_[idx].operator_->event().GetDeviceOption();
      CAFFE_EVENT(
          stats_[device_option.device_type()],
          task_pool_wait_time_us,
          task_timers_[idx]->MicroSeconds());
    }

    VLOG(1) << "Running chain starting at operator #" << idx << " "
            << operator_nodes_[idx].operator_->debug_def().name() << "("
            << operator_nodes_[idx].operator_->debug_def().type() << ").";
    CAFFE_ENFORCE(
        execution_chains_.find(idx) != execution_chains_.end(),
        "Can't find chain ",
        idx,
        ".");
    const auto& chain = execution_chains_[idx];
    bool this_success = false;
    try {
      this_success = RunAt(idx, execution_chains_[idx]);

      if (!this_success) {
        // If an exception was thrown, the operator def will get printed
        // by Operator::Run[Async], but if no exception occurs we print it here.
        LOG(ERROR) << "Operator chain failed starting at: "
                   << ProtoDebugString(
                          operator_nodes_[idx].operator_->debug_def());
      }
    } catch (std::exception& e) {
      std::string exception_str = GetExceptionString(e);
      HandleException(idx, exception_str);
    } catch (...) {
      std::string exception_str = "Unknown exception";
      HandleException(idx, exception_str);
    }

    // Do book-keeping
    std::vector<int> chains_to_queue;
    for (const auto idx : chain) {
      for (const auto child : operator_nodes_[idx].children_) {
        const int count = --operator_nodes_[child].runtime_parent_count_;
        CAFFE_ENFORCE(
            count >= 0,
            "Found runtime parent count smaller than zero for ",
            "operator node ",
            operator_nodes_[child].operator_->debug_def().name(),
            "(",
            operator_nodes_[child].operator_->debug_def().type(),
            ").");

        if (count != 0) {
          continue;
        }

        if (operator_nodes_[child].is_chain_start_) {
          VLOG(2) << "Pushing chain #" << child << " to queue.";
          chains_to_queue.push_back(child);
        }
      }
    }

    // Notify the caller of Run
    {
      std::unique_lock<std::mutex> mutex_lock(remaining_ops_mutex_);
      remaining_ops_ -= chain.size();
      CAFFE_ENFORCE(remaining_ops_ >= 0);
      success_ &= this_success;
      if (remaining_ops_ == 0 || !success_) {
        cv_.notify_one();
      }

      // Terminate thread if this or any other operator chain failed.
      if (!success_) {
        job_queue_->NoMoreJobs();
        return;
      }

      // Queue follow up operator chains.
      // Can't do this inline because it can race with another thread
      // calling NoMoreJobs(). So the lock needs to be held on push.
      for (const auto idx : chains_to_queue) {
        if (FLAGS_caffe2_dag_net_collect_stats) {
          task_timers_[idx]->Start();
        }
        job_queue_->Push(idx);
      }
    }

    VLOG(2) << "Finished executing operator #" << idx;
  }
}

vector<float> DAGNetBase::TEST_Benchmark(
    const int warmup_runs,
    const int main_runs,
    const bool run_individual) {
  std::cout << "Starting benchmark." << std::endl;
  std::cout << "Running warmup runs." << std::endl;
  CAFFE_ENFORCE(
      warmup_runs >= 0,
      "Number of warm up runs should be non negative, provided ",
      warmup_runs,
      ".");
  for (int i = 0; i < warmup_runs; ++i) {
    CAFFE_ENFORCE(Run(), "Warmup run ", i, " has failed.");
  }

  std::cout << "Main runs." << std::endl;
  CAFFE_ENFORCE(
      main_runs >= 0,
      "Number of main runs should be non negative, provided ",
      main_runs,
      ".");
  Timer timer;
  for (int i = 0; i < main_runs; ++i) {
    CAFFE_ENFORCE(Run(), "Main run ", i, " has failed.");
  }
  auto millis = timer.MilliSeconds();
  std::cout << "Main run finished. Milliseconds per iter: "
            << millis / main_runs
            << ". Iters per second: " << 1000.0 * main_runs / millis << std::endl;

  if (run_individual) {
    std::cout << "DAGNet does not do per-op benchmark. To do so, "
                 "switch to a simple net type." << std::endl;
  }
  return vector<float>{millis / main_runs};
}

bool DAGNet::RunAt(int chain_id, const std::vector<int>& chain) {
  for (const auto i : chain) {
#ifdef CAFFE2_ENABLE_SDT
    const auto& op_name =
        operator_nodes_[i].operator_->debug_def().name().c_str();
    const auto& op_type =
        operator_nodes_[i].operator_->debug_def().type().c_str();
    auto* op_ptr = operator_nodes_[i].operator_.get();
    const auto& net_name = name_.c_str();
    CAFFE_SDT(operator_start, net_name, op_name, op_type, op_ptr);
#endif
    const auto success = operator_nodes_[i].operator_->Run();
#ifdef CAFFE2_ENABLE_SDT
    CAFFE_SDT(operator_done, net_name, op_name, op_type, op_ptr);
#endif
    if (!success) {
      return false;
    }
  }
  if (FLAGS_caffe2_dag_net_collect_stats) {
    auto device_option =
        operator_nodes_[chain_id].operator_->event().GetDeviceOption();
    CAFFE_EVENT(
        stats_[device_option.device_type()],
        task_time_to_succeeded_ms,
        task_timers_[chain_id]->MilliSeconds());
  }
  return true;
}

REGISTER_NET(dag, DAGNet);

} // namespace caffe2
<|endoftext|>


<commit_before>/**
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <string>

#include <gmock/gmock.h>

#include <stout/gtest.hpp>
#include <stout/none.hpp>
#include <stout/os.hpp>
#include <stout/protobuf.hpp>
#include <stout/result.hpp>

#include "common/type_utils.hpp"

#include "messages/messages.hpp"

#include "tests/utils.hpp"

using namespace mesos;
using namespace mesos::internal;
using namespace mesos::internal::tests;

class ProtobufIOTest : public TemporaryDirectoryTest {};

// TODO(bmahler): Move this file into stout.
TEST_F(ProtobufIOTest, Basic)
{
  const std::string file = ".protobuf_io_test_basic";

  Try<int> result = os::open(
      file,
      O_CREAT | O_WRONLY | O_SYNC | O_CLOEXEC,
      S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);

  ASSERT_SOME(result);

  int fdw = result.get();

  result = os::open(
      file,
      O_CREAT | O_RDONLY | O_CLOEXEC,
      S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);

  ASSERT_SOME(result);

  int fdr = result.get();

  const size_t writes = 10;
  for (size_t i = 0; i < writes; i++) {
    FrameworkID frameworkId;
    frameworkId.set_value(stringify(i));
    Try<Nothing> result = ::protobuf::write(fdw, frameworkId);
    ASSERT_SOME(result);
  }

  Result<FrameworkID> read = None();
  size_t reads = 0;
  while (true) {
    read = ::protobuf::read<FrameworkID>(fdr);
    if (!read.isSome()) {
      break;
    }

    EXPECT_EQ(read.get().value(), stringify(reads++));
  }

  // Ensure we've hit the end of the file without reading a partial
  // protobuf.
  ASSERT_TRUE(read.isNone());
  ASSERT_EQ(writes, reads);

  os::close(fdw);
  os::close(fdr);
}

TEST_F(ProtobufIOTest, Append)
{
  const std::string file = ".protobuf_io_test_append";

  const size_t writes = 10;
  for (size_t i = 0; i < writes; i++) {
    FrameworkID frameworkId;
    frameworkId.set_value(stringify(i));

    Try<Nothing> result = ::protobuf::append(file, frameworkId);
    ASSERT_SOME(result);
  }

  Try<int> fd = os::open(
      file,
      O_CREAT | O_RDONLY | O_CLOEXEC,
      S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);

  ASSERT_SOME(fd);

  Result<FrameworkID> read = None();
  size_t reads = 0;
  while (true) {
    read = ::protobuf::read<FrameworkID>(fd.get());
    if (!read.isSome()) {
      break;
    }

    EXPECT_EQ(read.get().value(), stringify(reads++));
  }

  // Ensure we've hit the end of the file without reading a partial
  // protobuf.
  ASSERT_TRUE(read.isNone());
  ASSERT_EQ(writes, reads);

  os::close(fd.get());
}
<commit_msg>Added a protobuf unit test for RepeatedPtrField.<commit_after>/**
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <string>

#include <gmock/gmock.h>

#include <stout/gtest.hpp>
#include <stout/none.hpp>
#include <stout/os.hpp>
#include <stout/protobuf.hpp>
#include <stout/result.hpp>

#include "common/type_utils.hpp"

#include "messages/messages.hpp"

#include "tests/utils.hpp"

using namespace mesos;
using namespace mesos::internal;
using namespace mesos::internal::tests;

using std::string;

using google::protobuf::RepeatedPtrField;

class ProtobufIOTest : public TemporaryDirectoryTest {};

// TODO(bmahler): Move this file into stout.
TEST_F(ProtobufIOTest, Basic)
{
  const string file = ".protobuf_io_test_basic";

  Try<int> result = os::open(
      file,
      O_CREAT | O_WRONLY | O_SYNC | O_CLOEXEC,
      S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);

  ASSERT_SOME(result);

  int fdw = result.get();

  result = os::open(
      file,
      O_CREAT | O_RDONLY | O_CLOEXEC,
      S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);

  ASSERT_SOME(result);

  int fdr = result.get();

  const size_t writes = 10;
  for (size_t i = 0; i < writes; i++) {
    FrameworkID frameworkId;
    frameworkId.set_value(stringify(i));
    Try<Nothing> result = ::protobuf::write(fdw, frameworkId);
    ASSERT_SOME(result);
  }

  Result<FrameworkID> read = None();
  size_t reads = 0;
  while (true) {
    read = ::protobuf::read<FrameworkID>(fdr);
    if (!read.isSome()) {
      break;
    }

    EXPECT_EQ(read.get().value(), stringify(reads++));
  }

  // Ensure we've hit the end of the file without reading a partial
  // protobuf.
  ASSERT_TRUE(read.isNone());
  ASSERT_EQ(writes, reads);

  os::close(fdw);
  os::close(fdr);
}

TEST_F(ProtobufIOTest, Append)
{
  const string file = ".protobuf_io_test_append";

  const size_t writes = 10;
  for (size_t i = 0; i < writes; i++) {
    FrameworkID frameworkId;
    frameworkId.set_value(stringify(i));

    Try<Nothing> result = ::protobuf::append(file, frameworkId);
    ASSERT_SOME(result);
  }

  Try<int> fd = os::open(
      file,
      O_CREAT | O_RDONLY | O_CLOEXEC,
      S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);

  ASSERT_SOME(fd);

  Result<FrameworkID> read = None();
  size_t reads = 0;
  while (true) {
    read = ::protobuf::read<FrameworkID>(fd.get());
    if (!read.isSome()) {
      break;
    }

    EXPECT_EQ(read.get().value(), stringify(reads++));
  }

  // Ensure we've hit the end of the file without reading a partial
  // protobuf.
  ASSERT_TRUE(read.isNone());
  ASSERT_EQ(writes, reads);

  os::close(fd.get());
}

TEST_F(ProtobufIOTest, RepeatedPtrField)
{
  const string file = ".protobuf_io_test_repeated_ptr_field";

  RepeatedPtrField<FrameworkID> expected;

  const size_t size = 10;
  for (size_t i = 0; i < size; i++) {
    FrameworkID frameworkId;
    frameworkId.set_value(stringify(i));
    expected.Add()->CopyFrom(frameworkId);
  }

  Try<Nothing> write = ::protobuf::write(file, expected);
  ASSERT_SOME(write);

  Result<RepeatedPtrField<FrameworkID>> read =
    ::protobuf::read<RepeatedPtrField<FrameworkID>>(file);
  ASSERT_SOME(read);

  RepeatedPtrField<FrameworkID> actual = read.get();

  ASSERT_EQ(expected.size(), actual.size());
  for (size_t i = 0; i < size; i++) {
    EXPECT_EQ(expected.Get(i), actual.Get(i));
  }
}
<|endoftext|>


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

int
itkMultiLabelSTAPLEImageFilterTest(int, char *[])
{

  // Define the dimension of the images
  constexpr unsigned int Dimension = 3;
  constexpr unsigned int imageSizePerDimension = 2;
  constexpr unsigned int imageSize = 8; // std::pow(imageSizePerDimension, Dimension);

  // Declare the types of the images
  using ImageType = itk::Image<unsigned int, Dimension>;

  // Input data arrays for test images
  const unsigned int dataImageA[imageSize] = { 0, 1, 3, 3, 4, 6, 6, 0 };
  const unsigned int dataImageB[imageSize] = { 1, 1, 2, 4, 4, 5, 7, 1 };
  const unsigned int dataImageC[imageSize] = { 0, 2, 2, 3, 5, 5, 6, 8 };

  // Correct combinations of input images
  const unsigned int combinationABC[imageSize] = { 0, 1, 2, 3, 4, 5, 6, 9 };
  const unsigned int combinationAB[imageSize] = { 8, 1, 8, 8, 4, 8, 8, 8 };
  const unsigned int combinationABundecided255[imageSize] = { 255, 1, 255, 255, 4, 255, 255, 255 };

  // Declare the type of the index to access images
  using IndexType = itk::Index<Dimension>;

  // Declare the type of the size
  using SizeType = itk::Size<Dimension>;

  // Declare the type of the Region
  using RegionType = itk::ImageRegion<Dimension>;

  // Declare Iterator type appropriate for image
  using IteratorType = itk::ImageRegionIterator<ImageType>;

  // Declare the type for the ADD filter
  using FilterType = itk::MultiLabelSTAPLEImageFilter<ImageType>;
  using FilterTypePointer = FilterType::Pointer;

  // Declare the pointers to images
  using ImageTypePointer = ImageType::Pointer;

  // Create two images
  ImageTypePointer inputImageA = ImageType::New();
  ImageTypePointer inputImageB = ImageType::New();
  ImageTypePointer inputImageC = ImageType::New();

  RegionType region;
  {
    // Define their size, and start index
    SizeType size;
    size[0] = imageSizePerDimension;
    size[1] = imageSizePerDimension;
    size[2] = imageSizePerDimension;

    IndexType start;
    start[0] = 0;
    start[1] = 0;
    start[2] = 0;

    region.SetIndex(start);
    region.SetSize(size);
  }

  // Initialize Image A
  inputImageA->SetRegions(region);
  inputImageA->Allocate();

  IteratorType it = IteratorType(inputImageA, inputImageA->GetBufferedRegion());

  for (unsigned int i = 0; i < imageSize; ++i, ++it)
  {
    it.Set(dataImageA[i]);
  }

  // Initialize Image B
  inputImageB->SetRegions(region);
  inputImageB->Allocate();

  it = IteratorType(inputImageB, inputImageB->GetBufferedRegion());
  for (unsigned int i = 0; i < imageSize; ++i, ++it)
  {
    it.Set(dataImageB[i]);
  }

  // Initialize Image C
  inputImageC->SetRegions(region);
  inputImageC->Allocate();

  it = IteratorType(inputImageC, inputImageC->GetBufferedRegion());
  for (unsigned int i = 0; i < imageSize; ++i, ++it)
  {
    it.Set(dataImageC[i]);
  }

  // Create an LabelVoting Filter
  FilterTypePointer filter = FilterType::New();

  ITK_EXERCISE_BASIC_OBJECT_METHODS(filter, MultiLabelSTAPLEImageFilter, ImageToImageFilter);

  // Get the Smart Pointer to the Filter Output
  ImageTypePointer outputImage = filter->GetOutput();

  // = test first two input images with undecided label set to 255 = //

  // Connect the first two input images
  filter->SetInput(0, inputImageA);
  filter->SetInput(1, inputImageB);

  ITK_TEST_EXPECT_TRUE(!filter->GetHasMaximumNumberOfIterations());

  unsigned int maximumNumberOfIterations = 100;
  filter->SetMaximumNumberOfIterations(maximumNumberOfIterations);
  ITK_TEST_SET_GET_VALUE(maximumNumberOfIterations, filter->GetMaximumNumberOfIterations());

  ITK_TEST_EXPECT_TRUE(filter->GetHasMaximumNumberOfIterations());

  ITK_TEST_EXPECT_TRUE(!filter->GetHasLabelForUndecidedPixels());

  filter->UnsetMaximumNumberOfIterations();

  typename FilterType::WeightsType terminationUpdateThreshold = 1e-5;
  filter->SetTerminationUpdateThreshold(terminationUpdateThreshold);
  ITK_TEST_SET_GET_VALUE(terminationUpdateThreshold, filter->GetTerminationUpdateThreshold());

  // Set label for undecided pixels
  typename FilterType::OutputPixelType labelForUndecidedPixels = 255;
  filter->SetLabelForUndecidedPixels(labelForUndecidedPixels);
  ITK_TEST_SET_GET_VALUE(labelForUndecidedPixels, filter->GetLabelForUndecidedPixels());

  ITK_TEST_EXPECT_TRUE(filter->GetHasLabelForUndecidedPixels());

  ITK_TEST_EXPECT_TRUE(!filter->GetHasPriorProbabilities());

  typename FilterType::PriorProbabilitiesType::ValueType priorProbabilitiesVal(0.0);
  typename FilterType::PriorProbabilitiesType            priorProbabilities(1);
  priorProbabilities.Fill(priorProbabilitiesVal);
  filter->SetPriorProbabilities(priorProbabilities);
  ITK_TEST_SET_GET_VALUE(priorProbabilities, filter->GetPriorProbabilities());

  ITK_TEST_EXPECT_TRUE(filter->GetHasPriorProbabilities());

  ITK_TRY_EXPECT_EXCEPTION(filter->Update());

  filter->UnsetPriorProbabilities();

  // Execute the filter
  ITK_TRY_EXPECT_NO_EXCEPTION(filter->Update());

  std::cout << "ElapsedNumberOfIterations: " << filter->GetElapsedNumberOfIterations() << std::endl;

  // compare to correct results
  it = IteratorType(outputImage, outputImage->GetBufferedRegion());
  for (unsigned int i = 0; i < imageSize; ++i, ++it)
  {
    if (combinationABundecided255[i] != it.Get())
    {
      std::cout << "Incorrect result using images A,B and undecided=" << labelForUndecidedPixels << ": "
                << "i = " << i << ", correct = " << combinationABundecided255[i] << ", got = " << it.Get() << std::endl;
      return EXIT_FAILURE;
    }
  }

  // =========== test first two input images ============ //

  // unset undecided pixel label; reinstate automatic selection
  filter->UnsetLabelForUndecidedPixels();

  // Execute the filter
  ITK_TRY_EXPECT_NO_EXCEPTION(filter->Update());

  // compare to correct results
  it = IteratorType(outputImage, outputImage->GetBufferedRegion());
  for (unsigned int i = 0; i < 8; ++i, ++it)
  {
    if (combinationAB[i] != it.Get())
    {
      std::cout << "Incorrect result using images A,B: i = " << i << ", correct = " << combinationAB[i]
                << ", got = " << it.Get() << std::endl;
      return EXIT_FAILURE;
    }
  }

  // =========== test all three input images ============ //

  // connect third input image
  filter->SetInput(2, inputImageC);

  // Execute the filter
  ITK_TRY_EXPECT_NO_EXCEPTION(filter->Update());

  // compare to correct results
  it = IteratorType(outputImage, outputImage->GetBufferedRegion());
  for (unsigned int i = 0; i < 8; ++i, ++it)
  {
    if (combinationABC[i] != it.Get())
    {
      std::cout << "Incorrect result using images A,B,C: i = " << i << ", correct = " << combinationABC[i]
                << ", got = " << it.Get() << std::endl;
      return EXIT_FAILURE;
    }
  }

  std::cout << "Prior probabilities: " << filter->GetPriorProbabilities() << std::endl;
  std::cout << "Confusion matrix 0 " << std::endl << filter->GetConfusionMatrix(0) << std::endl;
  std::cout << "Confusion matrix 1 " << std::endl << filter->GetConfusionMatrix(1) << std::endl;
  std::cout << "Confusion matrix 2 " << std::endl << filter->GetConfusionMatrix(2) << std::endl;

  std::cout << "Test finished." << std::endl;
  return EXIT_SUCCESS;
}
<commit_msg>DOC: Conform to ITK SW Guidelines in comments<commit_after>/*=========================================================================
 *
 *  Copyright NumFOCUS
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *         https://www.apache.org/licenses/LICENSE-2.0.txt
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 *
 *=========================================================================*/
#include "itkMultiLabelSTAPLEImageFilter.h"
#include "itkTestingMacros.h"

int
itkMultiLabelSTAPLEImageFilterTest(int, char *[])
{

  // Define the dimension of the images
  constexpr unsigned int Dimension = 3;
  constexpr unsigned int imageSizePerDimension = 2;
  constexpr unsigned int imageSize = 8; // std::pow(imageSizePerDimension, Dimension);

  // Declare the types of the images
  using ImageType = itk::Image<unsigned int, Dimension>;

  // Input data arrays for test images
  const unsigned int dataImageA[imageSize] = { 0, 1, 3, 3, 4, 6, 6, 0 };
  const unsigned int dataImageB[imageSize] = { 1, 1, 2, 4, 4, 5, 7, 1 };
  const unsigned int dataImageC[imageSize] = { 0, 2, 2, 3, 5, 5, 6, 8 };

  // Correct combinations of input images
  const unsigned int combinationABC[imageSize] = { 0, 1, 2, 3, 4, 5, 6, 9 };
  const unsigned int combinationAB[imageSize] = { 8, 1, 8, 8, 4, 8, 8, 8 };
  const unsigned int combinationABundecided255[imageSize] = { 255, 1, 255, 255, 4, 255, 255, 255 };

  // Declare the type of the index to access images
  using IndexType = itk::Index<Dimension>;

  // Declare the type of the size
  using SizeType = itk::Size<Dimension>;

  // Declare the type of the Region
  using RegionType = itk::ImageRegion<Dimension>;

  // Declare Iterator type appropriate for image
  using IteratorType = itk::ImageRegionIterator<ImageType>;

  // Declare the type for the ADD filter
  using FilterType = itk::MultiLabelSTAPLEImageFilter<ImageType>;
  using FilterTypePointer = FilterType::Pointer;

  // Declare the pointers to images
  using ImageTypePointer = ImageType::Pointer;

  // Create two images
  ImageTypePointer inputImageA = ImageType::New();
  ImageTypePointer inputImageB = ImageType::New();
  ImageTypePointer inputImageC = ImageType::New();

  RegionType region;
  {
    // Define their size, and start index
    SizeType size;
    size[0] = imageSizePerDimension;
    size[1] = imageSizePerDimension;
    size[2] = imageSizePerDimension;

    IndexType start;
    start[0] = 0;
    start[1] = 0;
    start[2] = 0;

    region.SetIndex(start);
    region.SetSize(size);
  }

  // Initialize Image A
  inputImageA->SetRegions(region);
  inputImageA->Allocate();

  IteratorType it = IteratorType(inputImageA, inputImageA->GetBufferedRegion());

  for (unsigned int i = 0; i < imageSize; ++i, ++it)
  {
    it.Set(dataImageA[i]);
  }

  // Initialize Image B
  inputImageB->SetRegions(region);
  inputImageB->Allocate();

  it = IteratorType(inputImageB, inputImageB->GetBufferedRegion());
  for (unsigned int i = 0; i < imageSize; ++i, ++it)
  {
    it.Set(dataImageB[i]);
  }

  // Initialize Image C
  inputImageC->SetRegions(region);
  inputImageC->Allocate();

  it = IteratorType(inputImageC, inputImageC->GetBufferedRegion());
  for (unsigned int i = 0; i < imageSize; ++i, ++it)
  {
    it.Set(dataImageC[i]);
  }

  // Create an LabelVoting Filter
  FilterTypePointer filter = FilterType::New();

  ITK_EXERCISE_BASIC_OBJECT_METHODS(filter, MultiLabelSTAPLEImageFilter, ImageToImageFilter);

  // Get the Smart Pointer to the Filter Output
  ImageTypePointer outputImage = filter->GetOutput();

  // Test first two input images with undecided label set to 255

  // Connect the first two input images
  filter->SetInput(0, inputImageA);
  filter->SetInput(1, inputImageB);

  ITK_TEST_EXPECT_TRUE(!filter->GetHasMaximumNumberOfIterations());

  unsigned int maximumNumberOfIterations = 100;
  filter->SetMaximumNumberOfIterations(maximumNumberOfIterations);
  ITK_TEST_SET_GET_VALUE(maximumNumberOfIterations, filter->GetMaximumNumberOfIterations());

  ITK_TEST_EXPECT_TRUE(filter->GetHasMaximumNumberOfIterations());

  ITK_TEST_EXPECT_TRUE(!filter->GetHasLabelForUndecidedPixels());

  filter->UnsetMaximumNumberOfIterations();

  typename FilterType::WeightsType terminationUpdateThreshold = 1e-5;
  filter->SetTerminationUpdateThreshold(terminationUpdateThreshold);
  ITK_TEST_SET_GET_VALUE(terminationUpdateThreshold, filter->GetTerminationUpdateThreshold());

  // Set label for undecided pixels
  typename FilterType::OutputPixelType labelForUndecidedPixels = 255;
  filter->SetLabelForUndecidedPixels(labelForUndecidedPixels);
  ITK_TEST_SET_GET_VALUE(labelForUndecidedPixels, filter->GetLabelForUndecidedPixels());

  ITK_TEST_EXPECT_TRUE(filter->GetHasLabelForUndecidedPixels());

  ITK_TEST_EXPECT_TRUE(!filter->GetHasPriorProbabilities());

  typename FilterType::PriorProbabilitiesType::ValueType priorProbabilitiesVal(0.0);
  typename FilterType::PriorProbabilitiesType            priorProbabilities(1);
  priorProbabilities.Fill(priorProbabilitiesVal);
  filter->SetPriorProbabilities(priorProbabilities);
  ITK_TEST_SET_GET_VALUE(priorProbabilities, filter->GetPriorProbabilities());

  ITK_TEST_EXPECT_TRUE(filter->GetHasPriorProbabilities());

  ITK_TRY_EXPECT_EXCEPTION(filter->Update());

  filter->UnsetPriorProbabilities();

  // Execute the filter
  ITK_TRY_EXPECT_NO_EXCEPTION(filter->Update());

  std::cout << "ElapsedNumberOfIterations: " << filter->GetElapsedNumberOfIterations() << std::endl;

  // Compare to correct results
  it = IteratorType(outputImage, outputImage->GetBufferedRegion());
  for (unsigned int i = 0; i < imageSize; ++i, ++it)
  {
    if (combinationABundecided255[i] != it.Get())
    {
      std::cout << "Incorrect result using images A,B and undecided=" << labelForUndecidedPixels << ": "
                << "i = " << i << ", correct = " << combinationABundecided255[i] << ", got = " << it.Get() << std::endl;
      return EXIT_FAILURE;
    }
  }

  // Test first two input images

  // Unset undecided pixel label; reinstate automatic selection
  filter->UnsetLabelForUndecidedPixels();

  // Execute the filter
  ITK_TRY_EXPECT_NO_EXCEPTION(filter->Update());

  // Compare to correct results
  it = IteratorType(outputImage, outputImage->GetBufferedRegion());
  for (unsigned int i = 0; i < 8; ++i, ++it)
  {
    if (combinationAB[i] != it.Get())
    {
      std::cout << "Incorrect result using images A,B: i = " << i << ", correct = " << combinationAB[i]
                << ", got = " << it.Get() << std::endl;
      return EXIT_FAILURE;
    }
  }

  // Test all three input images

  // Connect third input image
  filter->SetInput(2, inputImageC);

  // Execute the filter
  ITK_TRY_EXPECT_NO_EXCEPTION(filter->Update());

  // Compare to correct results
  it = IteratorType(outputImage, outputImage->GetBufferedRegion());
  for (unsigned int i = 0; i < 8; ++i, ++it)
  {
    if (combinationABC[i] != it.Get())
    {
      std::cout << "Incorrect result using images A,B,C: i = " << i << ", correct = " << combinationABC[i]
                << ", got = " << it.Get() << std::endl;
      return EXIT_FAILURE;
    }
  }

  std::cout << "Prior probabilities: " << filter->GetPriorProbabilities() << std::endl;
  std::cout << "Confusion matrix 0 " << std::endl << filter->GetConfusionMatrix(0) << std::endl;
  std::cout << "Confusion matrix 1 " << std::endl << filter->GetConfusionMatrix(1) << std::endl;
  std::cout << "Confusion matrix 2 " << std::endl << filter->GetConfusionMatrix(2) << std::endl;

  std::cout << "Test finished." << std::endl;
  return EXIT_SUCCESS;
}
<|endoftext|>


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

/*
* LOCAL includes
*/
#include "robot_description.hpp"
#include "../helpers/filesystem_helpers.hpp"

namespace naoqi{

namespace tools{

std::string getRobotDescription( const robot::Robot& robot){
    std::string urdf_path;
    static std::string robot_desc;
    if(!robot_desc.empty())
      return robot_desc;

    if ( robot == robot::PEPPER)
    {
      urdf_path = helpers::filesystem::getURDF("pepper.urdf");
    }
    else if ( robot == robot::NAO )
    {
      urdf_path = helpers::filesystem::getURDF("nao.urdf");
    }
    else
    {
      std::cerr << " could not load urdf file from disk " << std::endl;
      return std::string();
    }

    std::ifstream stream( (urdf_path).c_str() );
    if (!stream)
    {
      std::cerr << "failed to load robot description in joint_state_publisher: " << urdf_path << std::endl;
      return std::string();
    }
    robot_desc = std::string( (std::istreambuf_iterator<char>(stream)), std::istreambuf_iterator<char>());
    return robot_desc;
}

} // tools

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

/*
* LOCAL includes
*/
#include "robot_description.hpp"
#include "../helpers/filesystem_helpers.hpp"

namespace naoqi{

namespace tools{

std::string getRobotDescription( const robot::Robot& robot){
    std::string urdf_path;
    static std::string robot_desc;
    if(!robot_desc.empty())
      return robot_desc;

    if ( robot == robot::PEPPER)
    {
      urdf_path = helpers::filesystem::getURDF("pepper.urdf");
    }
    else if ( robot == robot::NAO )
    {
      urdf_path = helpers::filesystem::getURDF("nao.urdf");
    }
    else if ( robot == robot::ROMEO )
    {
      urdf_path = helpers::filesystem::getURDF("romeo.urdf");
    }
    else
    {
      std::cerr << " could not load urdf file from disk " << std::endl;
      return std::string();
    }

    std::ifstream stream( (urdf_path).c_str() );
    if (!stream)
    {
      std::cerr << "failed to load robot description in joint_state_publisher: " << urdf_path << std::endl;
      return std::string();
    }
    robot_desc = std::string( (std::istreambuf_iterator<char>(stream)), std::istreambuf_iterator<char>());
    return robot_desc;
}

} // tools

} // naoqi
<|endoftext|>


<commit_before>#include "QGCMAVLinkUASFactory.h"
#include "UASManager.h"

QGCMAVLinkUASFactory::QGCMAVLinkUASFactory(QObject *parent) :
    QObject(parent)
{
}

UASInterface* QGCMAVLinkUASFactory::createUAS(MAVLinkProtocol* mavlink, LinkInterface* link, int sysid, mavlink_heartbeat_t* heartbeat, QObject* parent)
{
    QPointer<QObject> p;

    if (parent != NULL)
    {
        p = parent;
    }
    else
    {
        p = mavlink;
    }

    UASInterface* uas;

    switch (heartbeat->autopilot)
    {
    case MAV_AUTOPILOT_GENERIC:
    {
        UAS* mav = new UAS(mavlink, sysid);
        // Set the system type
        mav->setSystemType((int)heartbeat->type);
        // Connect this robot to the UAS object
        connect(mavlink, SIGNAL(messageReceived(LinkInterface*, mavlink_message_t)), mav, SLOT(receiveMessage(LinkInterface*, mavlink_message_t)));
#ifdef QGC_PROTOBUF_ENABLED
        connect(mavlink, SIGNAL(extendedMessageReceived(LinkInterface*, std::tr1::shared_ptr<google::protobuf::Message>)), mav, SLOT(receiveExtendedMessage(LinkInterface*, std::tr1::shared_ptr<google::protobuf::Message>)));
#endif
        uas = mav;
    }
    break;
    case MAV_AUTOPILOT_PIXHAWK:
    {
        PxQuadMAV* mav = new PxQuadMAV(mavlink, sysid);
        // Set the system type
        mav->setSystemType((int)heartbeat->type);
        // Connect this robot to the UAS object
        // it is IMPORTANT here to use the right object type,
        // else the slot of the parent object is called (and thus the special
        // packets never reach their goal)
        connect(mavlink, SIGNAL(messageReceived(LinkInterface*, mavlink_message_t)), mav, SLOT(receiveMessage(LinkInterface*, mavlink_message_t)));
#ifdef QGC_PROTOBUF_ENABLED
        connect(mavlink, SIGNAL(extendedMessageReceived(LinkInterface*, std::tr1::shared_ptr<google::protobuf::Message>)), mav, SLOT(receiveExtendedMessage(LinkInterface*, std::tr1::shared_ptr<google::protobuf::Message>)));
#endif
        uas = mav;
    }
    break;
    case MAV_AUTOPILOT_SLUGS:
    {
        SlugsMAV* mav = new SlugsMAV(mavlink, sysid);
        // Set the system type
        mav->setSystemType((int)heartbeat->type);
        // Connect this robot to the UAS object
        // it is IMPORTANT here to use the right object type,
        // else the slot of the parent object is called (and thus the special
        // packets never reach their goal)
        connect(mavlink, SIGNAL(messageReceived(LinkInterface*, mavlink_message_t)), mav, SLOT(receiveMessage(LinkInterface*, mavlink_message_t)));
        uas = mav;
    }
    break;
    case MAV_AUTOPILOT_ARDUPILOTMEGA:
    {
        ArduPilotMegaMAV* mav = new ArduPilotMegaMAV(mavlink, sysid);
        // Set the system type
        mav->setSystemType((int)heartbeat->type);
        // Connect this robot to the UAS object
        // it is IMPORTANT here to use the right object type,
        // else the slot of the parent object is called (and thus the special
        // packets never reach their goal)
        connect(mavlink, SIGNAL(messageReceived(LinkInterface*, mavlink_message_t)), mav, SLOT(receiveMessage(LinkInterface*, mavlink_message_t)));
        uas = mav;
    }
    break;
#ifdef QGC_USE_SENSESOAR_MESSAGES
	case MAV_AUTOPILOT_SENSESOAR:
		{
			senseSoarMAV* mav = new senseSoarMAV(mavlink,sysid);
			mav->setSystemType((int)heartbeat->type);
			connect(mavlink, SIGNAL(messageReceived(LinkInterface*, mavlink_message_t)), mav, SLOT(receiveMessage(LinkInterface*, mavlink_message_t)));
			uas = mav;
			break;
		}
#endif
    default:
    {
        UAS* mav = new UAS(mavlink, sysid);
        mav->setSystemType((int)heartbeat->type);
        // Connect this robot to the UAS object
        // it is IMPORTANT here to use the right object type,
        // else the slot of the parent object is called (and thus the special
        // packets never reach their goal)
        connect(mavlink, SIGNAL(messageReceived(LinkInterface*, mavlink_message_t)), mav, SLOT(receiveMessage(LinkInterface*, mavlink_message_t)));
        uas = mav;
    }
    break;
    }

    // Set the autopilot type
    uas->setAutopilotType((int)heartbeat->autopilot);

    // Make UAS aware that this link can be used to communicate with the actual robot
    uas->addLink(link);

    // Now add UAS to "official" list, which makes the whole application aware of it
    UASManager::instance()->addUAS(uas);

    return uas;
}
<commit_msg>Move UAS objects to their own worker threads<commit_after>#include "QGCMAVLinkUASFactory.h"
#include "UASManager.h"

QGCMAVLinkUASFactory::QGCMAVLinkUASFactory(QObject *parent) :
    QObject(parent)
{
}

UASInterface* QGCMAVLinkUASFactory::createUAS(MAVLinkProtocol* mavlink, LinkInterface* link, int sysid, mavlink_heartbeat_t* heartbeat, QObject* parent)
{
    QPointer<QObject> p;

    if (parent != NULL)
    {
        p = parent;
    }
    else
    {
        p = mavlink;
    }

    UASInterface* uas;

    QThread* worker = new QThread();

    switch (heartbeat->autopilot)
    {
    case MAV_AUTOPILOT_GENERIC:
    {
        UAS* mav = new UAS(mavlink, sysid);
        // Set the system type
        mav->setSystemType((int)heartbeat->type);

        mav->moveToThread(worker);

        // Connect this robot to the UAS object
        connect(mavlink, SIGNAL(messageReceived(LinkInterface*, mavlink_message_t)), mav, SLOT(receiveMessage(LinkInterface*, mavlink_message_t)));
#ifdef QGC_PROTOBUF_ENABLED
        connect(mavlink, SIGNAL(extendedMessageReceived(LinkInterface*, std::tr1::shared_ptr<google::protobuf::Message>)), mav, SLOT(receiveExtendedMessage(LinkInterface*, std::tr1::shared_ptr<google::protobuf::Message>)));
#endif
        uas = mav;
    }
    break;
    case MAV_AUTOPILOT_PIXHAWK:
    {
        PxQuadMAV* mav = new PxQuadMAV(mavlink, sysid);
        // Set the system type
        mav->setSystemType((int)heartbeat->type);

        mav->moveToThread(worker);

        // Connect this robot to the UAS object
        // it is IMPORTANT here to use the right object type,
        // else the slot of the parent object is called (and thus the special
        // packets never reach their goal)
        connect(mavlink, SIGNAL(messageReceived(LinkInterface*, mavlink_message_t)), mav, SLOT(receiveMessage(LinkInterface*, mavlink_message_t)));
#ifdef QGC_PROTOBUF_ENABLED
        connect(mavlink, SIGNAL(extendedMessageReceived(LinkInterface*, std::tr1::shared_ptr<google::protobuf::Message>)), mav, SLOT(receiveExtendedMessage(LinkInterface*, std::tr1::shared_ptr<google::protobuf::Message>)));
#endif
        uas = mav;
    }
    break;
    case MAV_AUTOPILOT_SLUGS:
    {
        SlugsMAV* mav = new SlugsMAV(mavlink, sysid);
        // Set the system type
        mav->setSystemType((int)heartbeat->type);

        mav->moveToThread(worker);

        // Connect this robot to the UAS object
        // it is IMPORTANT here to use the right object type,
        // else the slot of the parent object is called (and thus the special
        // packets never reach their goal)
        connect(mavlink, SIGNAL(messageReceived(LinkInterface*, mavlink_message_t)), mav, SLOT(receiveMessage(LinkInterface*, mavlink_message_t)));
        uas = mav;
    }
    break;
    case MAV_AUTOPILOT_ARDUPILOTMEGA:
    {
        ArduPilotMegaMAV* mav = new ArduPilotMegaMAV(mavlink, sysid);
        // Set the system type
        mav->setSystemType((int)heartbeat->type);

        mav->moveToThread(worker);

        // Connect this robot to the UAS object
        // it is IMPORTANT here to use the right object type,
        // else the slot of the parent object is called (and thus the special
        // packets never reach their goal)
        connect(mavlink, SIGNAL(messageReceived(LinkInterface*, mavlink_message_t)), mav, SLOT(receiveMessage(LinkInterface*, mavlink_message_t)));
        uas = mav;
    }
    break;
#ifdef QGC_USE_SENSESOAR_MESSAGES
	case MAV_AUTOPILOT_SENSESOAR:
		{
			senseSoarMAV* mav = new senseSoarMAV(mavlink,sysid);
			mav->setSystemType((int)heartbeat->type);

            mav->moveToThread(worker);

			connect(mavlink, SIGNAL(messageReceived(LinkInterface*, mavlink_message_t)), mav, SLOT(receiveMessage(LinkInterface*, mavlink_message_t)));
			uas = mav;
			break;
		}
#endif
    default:
    {
        UAS* mav = new UAS(mavlink, sysid);
        mav->setSystemType((int)heartbeat->type);

        mav->moveToThread(worker);

        // Connect this robot to the UAS object
        // it is IMPORTANT here to use the right object type,
        // else the slot of the parent object is called (and thus the special
        // packets never reach their goal)
        connect(mavlink, SIGNAL(messageReceived(LinkInterface*, mavlink_message_t)), mav, SLOT(receiveMessage(LinkInterface*, mavlink_message_t)));
        uas = mav;
    }
    break;
    }

    // Set the autopilot type
    uas->setAutopilotType((int)heartbeat->autopilot);

    // Make UAS aware that this link can be used to communicate with the actual robot
    uas->addLink(link);

    // Now add UAS to "official" list, which makes the whole application aware of it
    UASManager::instance()->addUAS(uas);

    worker->start(QThread::HighPriority);

    return uas;
}
<|endoftext|>