<commit_before>//------------------------------------------------------------------------------
// CLING - the C++ LLVM-based InterpreterG :)
// author:  Javier López-Gómez <jalopezg@inf.uc3m.es>
//
// This file is dual-licensed: you can choose to license it under the University
// of Illinois Open Source License or the GNU Lesser General Public License. See
// LICENSE.TXT for details.
//------------------------------------------------------------------------------

#include "DefinitionShadower.h"

#include "cling/Interpreter/Interpreter.h"
#include "cling/Interpreter/InterpreterCallbacks.h"
#include "cling/Utils/AST.h"

#include "clang/AST/Decl.h"
#include "clang/AST/DeclContextInternals.h"
#include "clang/AST/Stmt.h"
#include "clang/Sema/Lookup.h"
#include "clang/Sema/Sema.h"

using namespace clang;

namespace cling {
  /// \brief Returns whether the given source location is a Cling input line. If
  /// it came from the prompt, the file is a virtual file with overriden contents.
  static bool typedInClingPrompt(FullSourceLoc L) {
    if (L.isInvalid())
      return false;
    const SourceManager &SM = L.getManager();
    const FileID FID = SM.getFileID(L);
    return SM.isFileOverridden(SM.getFileEntryForID(FID))
           && (SM.getFileID(SM.getIncludeLoc(FID)) == SM.getMainFileID());
  }

  /// \brief Returns whether the given {Function,Tag,Var}Decl/TemplateDecl is a definition.
  static bool isDefinition(const Decl *D) {
    if (auto FD = dyn_cast<FunctionDecl>(D))
      return FD->isThisDeclarationADefinition();
    if (auto TD = dyn_cast<TagDecl>(D))
      return TD->isThisDeclarationADefinition();
    if (auto VD = dyn_cast<VarDecl>(D))
      return VD->isThisDeclarationADefinition();
    if (auto TD = dyn_cast<TemplateDecl>(D))
      return isDefinition(TD->getTemplatedDecl());
    return true;
  }

  DefinitionShadower::DefinitionShadower(Sema& S, Interpreter& I)
          : ASTTransformer(&S), m_Context(S.getASTContext()), m_Interp(I),
            m_TU(S.getASTContext().getTranslationUnitDecl())
  {}

  bool DefinitionShadower::isClingShadowNamespace(const DeclContext *DC) {
    auto NS = dyn_cast<NamespaceDecl>(DC);
    return NS && NS->getName().startswith("__cling_N5");
  }

  void DefinitionShadower::hideDecl(clang::NamedDecl *D) const {
    assert(isClingShadowNamespace(D->getDeclContext())
             && "D not in a __cling_N5xxx namespace?");

    // FIXME: this hides a decl from SemaLookup (there is no unloading). For
    // (large) L-values, this might be a memory leak. Should this be fixed?
    if (Scope* S = m_Sema->getScopeForContext(m_TU)) {
      S->RemoveDecl(D);
      if (utils::Analyze::isOnScopeChains(D, *m_Sema))
        m_Sema->IdResolver.RemoveDecl(D);
    }
    clang::StoredDeclsList &SDL = (*m_TU->getLookupPtr())[D->getDeclName()];
    if (SDL.getAsVector() || SDL.getAsDecl() == D)
      SDL.remove(D);

    if (InterpreterCallbacks *IC = m_Interp.getCallbacks())
      IC->DefinitionShadowed(D);
  }

  void DefinitionShadower::invalidatePreviousDefinitions(NamedDecl *D) const {
    LookupResult Previous(*m_Sema, D->getDeclName(), D->getLocation(),
                   Sema::LookupOrdinaryName, Sema::ForRedeclaration);
    m_Sema->LookupQualifiedName(Previous, m_TU);

    for (auto Prev : Previous) {
      if (Prev == D)
        continue;
      if (!isClingShadowNamespace(Prev->getDeclContext()))
        continue;
      if (isDefinition(Prev) && !isDefinition(D))
        continue;
      // If the found declaration is a function overload, do not invalidate it.
      // For templated functions, Sema::IsOverload() does the right thing as per
      // C++ [temp.over.link]p4.
      if (isa<FunctionDecl>(Prev) && isa<FunctionDecl>(D)
          && m_Sema->IsOverload(cast<FunctionDecl>(D),
                                cast<FunctionDecl>(Prev), /*IsForUsingDecl=*/false))
        continue;
      if (isa<FunctionTemplateDecl>(Prev) && isa<FunctionTemplateDecl>(D)
          && m_Sema->IsOverload(cast<FunctionTemplateDecl>(D)->getTemplatedDecl(),
                                cast<FunctionTemplateDecl>(Prev)->getTemplatedDecl(),
                                /*IsForUsingDecl=*/false))
        continue;

      hideDecl(Prev);

      // For unscoped enumerations, also invalidate all enumerators.
      if (EnumDecl *ED = dyn_cast<EnumDecl>(Prev)) {
        if (!ED->isTransparentContext())
          continue;
        for (auto &J : ED->decls())
          if (NamedDecl *ND = dyn_cast<NamedDecl>(J))
            hideDecl(ND);
      }
    }

    // Ignore any forward declaration issued after a definition. Fixes "error
    // : reference to 'xxx' is ambiguous" in `class C {}; class C; C foo;`.
    if (!Previous.empty() && !isDefinition(D))
      D->setInvalidDecl();
  }

  void DefinitionShadower::invalidatePreviousDefinitions(FunctionDecl *D) const {
    const CompilationOptions &CO = getTransaction()->getCompilationOpts();
    if (utils::Analyze::IsWrapper(D)) {
      if (!CO.DeclarationExtraction)
        return;

      // DeclExtractor shall move local declarations to the TU. Invalidate all
      // previous definitions (that may clash) before it runs.
      auto CS = dyn_cast<CompoundStmt>(D->getBody());
      for (auto &I : CS->body()) {
        auto DS = dyn_cast<DeclStmt>(I);
        if (!DS)
          continue;
        for (auto &J : DS->decls())
          if (auto ND = dyn_cast<NamedDecl>(J))
            invalidatePreviousDefinitions(ND);
      }
    } else
      invalidatePreviousDefinitions(cast<NamedDecl>(D));
  }

  void DefinitionShadower::invalidatePreviousDefinitions(Decl *D) const {
    if (auto FD = dyn_cast<FunctionDecl>(D))
      invalidatePreviousDefinitions(FD);
    else if (auto ND = dyn_cast<NamedDecl>(D))
      invalidatePreviousDefinitions(ND);
  }

  ASTTransformer::Result DefinitionShadower::Transform(Decl* D) {
    Transaction *T = getTransaction();
    const CompilationOptions &CO = T->getCompilationOpts();
    // Global declarations whose origin is the Cling prompt are subject to be
    // nested in a `__cling_N5' namespace.
    if (!CO.EnableShadowing
        || D->getLexicalDeclContext() != m_TU || D->isInvalidDecl()
        || isa<UsingDirectiveDecl>(D) || isa<UsingDecl>(D)
        // FIXME: NamespaceDecl requires additional processing (TBD)
        || isa<NamespaceDecl>(D)
        || (isa<FunctionDecl>(D) && cast<FunctionDecl>(D)->isTemplateInstantiation())
        || !typedInClingPrompt(FullSourceLoc{D->getLocation(),
                                             m_Context.getSourceManager()}))
      return Result(D, true);

    // Each transaction gets at most a `__cling_N5xxx' namespace. If `T' already
    // has one, reuse it.
    auto NS = T->getDefinitionShadowNS();
    if (!NS) {
      NS = NamespaceDecl::Create(m_Context, m_TU, /*inline=*/true,
                                 SourceLocation(), SourceLocation(),
                                 &m_Context.Idents.get("__cling_N5"
                                       + std::to_string(m_UniqueNameCounter++)),
                                 nullptr);
      //NS->setImplicit();
      m_TU->addDecl(NS);
      T->setDefinitionShadowNS(NS);
    }

    m_TU->removeDecl(D);
    if (isa<CXXRecordDecl>(D->getDeclContext()))
      D->setLexicalDeclContext(NS);
    else
      D->setDeclContext(NS);
    // An instantiated function template inherits the declaration context of the
    // templated decl. This is used for name mangling; fix it to avoid clashing.
    if (auto FTD = dyn_cast<FunctionTemplateDecl>(D))
      FTD->getTemplatedDecl()->setDeclContext(NS);
    NS->addDecl(D);

    // Invalidate previous definitions so that LookupResult::resolveKind() does not
    // mark resolution as ambiguous.
    invalidatePreviousDefinitions(D);
    return Result(D, true);
  }
} // end namespace cling
<commit_msg>DefinitionShadower: allow shadowing of non-user-defined declarations (#6571)<commit_after>//------------------------------------------------------------------------------
// CLING - the C++ LLVM-based InterpreterG :)
// author:  Javier López-Gómez <jalopezg@inf.uc3m.es>
//
// This file is dual-licensed: you can choose to license it under the University
// of Illinois Open Source License or the GNU Lesser General Public License. See
// LICENSE.TXT for details.
//------------------------------------------------------------------------------

#include "DefinitionShadower.h"

#include "cling/Interpreter/Interpreter.h"
#include "cling/Interpreter/InterpreterCallbacks.h"
#include "cling/Utils/AST.h"

#include "clang/AST/Decl.h"
#include "clang/AST/DeclContextInternals.h"
#include "clang/AST/Stmt.h"
#include "clang/Sema/Lookup.h"
#include "clang/Sema/Sema.h"

using namespace clang;

namespace cling {
  /// \brief Returns whether the given source location is a Cling input line. If
  /// it came from the prompt, the file is a virtual file with overriden contents.
  static bool typedInClingPrompt(FullSourceLoc L) {
    if (L.isInvalid())
      return false;
    const SourceManager &SM = L.getManager();
    const FileID FID = SM.getFileID(L);
    return SM.isFileOverridden(SM.getFileEntryForID(FID))
           && (SM.getFileID(SM.getIncludeLoc(FID)) == SM.getMainFileID());
  }

  /// \brief Returns whether the given {Function,Tag,Var}Decl/TemplateDecl is a definition.
  static bool isDefinition(const Decl *D) {
    if (auto FD = dyn_cast<FunctionDecl>(D))
      return FD->isThisDeclarationADefinition();
    if (auto TD = dyn_cast<TagDecl>(D))
      return TD->isThisDeclarationADefinition();
    if (auto VD = dyn_cast<VarDecl>(D))
      return VD->isThisDeclarationADefinition();
    if (auto TD = dyn_cast<TemplateDecl>(D))
      return isDefinition(TD->getTemplatedDecl());
    return true;
  }

  /// \brief Returns whether the given declaration is a template instantiation
  /// or specialization.
  static bool isInstantiationOrSpecialization(const Decl *D) {
    if (auto FD = dyn_cast<FunctionDecl>(D))
      return FD->isTemplateInstantiation() || FD->isFunctionTemplateSpecialization();
    if (auto CTSD = dyn_cast<ClassTemplateSpecializationDecl>(D))
      return CTSD->getSpecializationKind() != TSK_Undeclared;
    if (auto VTSD = dyn_cast<VarTemplateSpecializationDecl>(D))
      return VTSD->getSpecializationKind() != TSK_Undeclared;
    return false;
  }

  DefinitionShadower::DefinitionShadower(Sema& S, Interpreter& I)
          : ASTTransformer(&S), m_Context(S.getASTContext()), m_Interp(I),
            m_TU(S.getASTContext().getTranslationUnitDecl())
  {}

  bool DefinitionShadower::isClingShadowNamespace(const DeclContext *DC) {
    auto NS = dyn_cast<NamespaceDecl>(DC);
    return NS && NS->getName().startswith("__cling_N5");
  }

  void DefinitionShadower::hideDecl(clang::NamedDecl *D) const {
    // FIXME: this hides a decl from SemaLookup (there is no unloading). For
    // (large) L-values, this might be a memory leak. Should this be fixed?
    if (Scope* S = m_Sema->getScopeForContext(m_TU)) {
      S->RemoveDecl(D);
      if (utils::Analyze::isOnScopeChains(D, *m_Sema))
        m_Sema->IdResolver.RemoveDecl(D);
    }
    clang::StoredDeclsList &SDL = (*m_TU->getLookupPtr())[D->getDeclName()];
    if (SDL.getAsVector() || SDL.getAsDecl() == D)
      SDL.remove(D);

    if (InterpreterCallbacks *IC = m_Interp.getCallbacks())
      IC->DefinitionShadowed(D);
  }

  void DefinitionShadower::invalidatePreviousDefinitions(NamedDecl *D) const {
    LookupResult Previous(*m_Sema, D->getDeclName(), D->getLocation(),
                   Sema::LookupOrdinaryName, Sema::ForRedeclaration);
    m_Sema->LookupQualifiedName(Previous, m_TU);

    for (auto Prev : Previous) {
      if (Prev == D)
        continue;
      if (isDefinition(Prev) && !isDefinition(D))
        continue;
      // If the found declaration is a function overload, do not invalidate it.
      // For templated functions, Sema::IsOverload() does the right thing as per
      // C++ [temp.over.link]p4.
      if (isa<FunctionDecl>(Prev) && isa<FunctionDecl>(D)
          && m_Sema->IsOverload(cast<FunctionDecl>(D),
                                cast<FunctionDecl>(Prev), /*IsForUsingDecl=*/false))
        continue;
      if (isa<FunctionTemplateDecl>(Prev) && isa<FunctionTemplateDecl>(D)
          && m_Sema->IsOverload(cast<FunctionTemplateDecl>(D)->getTemplatedDecl(),
                                cast<FunctionTemplateDecl>(Prev)->getTemplatedDecl(),
                                /*IsForUsingDecl=*/false))
        continue;

      hideDecl(Prev);

      // For unscoped enumerations, also invalidate all enumerators.
      if (EnumDecl *ED = dyn_cast<EnumDecl>(Prev)) {
        if (!ED->isTransparentContext())
          continue;
        for (auto &J : ED->decls())
          if (NamedDecl *ND = dyn_cast<NamedDecl>(J))
            hideDecl(ND);
      }
    }

    // Ignore any forward declaration issued after a definition. Fixes "error
    // : reference to 'xxx' is ambiguous" in `class C {}; class C; C foo;`.
    if (!Previous.empty() && !isDefinition(D))
      D->setInvalidDecl();
  }

  void DefinitionShadower::invalidatePreviousDefinitions(FunctionDecl *D) const {
    const CompilationOptions &CO = getTransaction()->getCompilationOpts();
    if (utils::Analyze::IsWrapper(D)) {
      if (!CO.DeclarationExtraction)
        return;

      // DeclExtractor shall move local declarations to the TU. Invalidate all
      // previous definitions (that may clash) before it runs.
      auto CS = dyn_cast<CompoundStmt>(D->getBody());
      for (auto &I : CS->body()) {
        auto DS = dyn_cast<DeclStmt>(I);
        if (!DS)
          continue;
        for (auto &J : DS->decls())
          if (auto ND = dyn_cast<NamedDecl>(J))
            invalidatePreviousDefinitions(ND);
      }
    } else
      invalidatePreviousDefinitions(cast<NamedDecl>(D));
  }

  void DefinitionShadower::invalidatePreviousDefinitions(Decl *D) const {
    if (auto FD = dyn_cast<FunctionDecl>(D))
      invalidatePreviousDefinitions(FD);
    else if (auto ND = dyn_cast<NamedDecl>(D))
      invalidatePreviousDefinitions(ND);
  }

  ASTTransformer::Result DefinitionShadower::Transform(Decl* D) {
    Transaction *T = getTransaction();
    if (!T->getCompilationOpts().EnableShadowing)
      return Result(D, true);

    // For variable templates, Transform() is invoked with a VarDecl; get the
    // corresponding VarTemplateDecl.
    if (auto VD = dyn_cast<VarDecl>(D))
      if (auto VTD = VD->getDescribedVarTemplate())
        D = VTD;

    // Disable definition shadowing for some specific cases.
    if (D->getLexicalDeclContext() != m_TU || D->isInvalidDecl()
        || isa<UsingDirectiveDecl>(D) || isa<UsingDecl>(D) || isa<NamespaceDecl>(D)
        || isInstantiationOrSpecialization(D)
        || !typedInClingPrompt(FullSourceLoc{D->getLocation(),
                                             m_Context.getSourceManager()}))
      return Result(D, true);

    // Each transaction gets at most a `__cling_N5xxx' namespace. If `T' already
    // has one, reuse it.
    auto NS = T->getDefinitionShadowNS();
    if (!NS) {
      NS = NamespaceDecl::Create(m_Context, m_TU, /*inline=*/true,
                                 SourceLocation(), SourceLocation(),
                                 &m_Context.Idents.get("__cling_N5"
                                       + std::to_string(m_UniqueNameCounter++)),
                                 nullptr);
      //NS->setImplicit();
      m_TU->addDecl(NS);
      T->setDefinitionShadowNS(NS);
    }

    m_TU->removeDecl(D);
    if (isa<CXXRecordDecl>(D->getDeclContext()))
      D->setLexicalDeclContext(NS);
    else
      D->setDeclContext(NS);
    // An instantiated function template inherits the declaration context of the
    // templated decl. This is used for name mangling; fix it to avoid clashing.
    if (auto FTD = dyn_cast<FunctionTemplateDecl>(D))
      FTD->getTemplatedDecl()->setDeclContext(NS);
    NS->addDecl(D);

    // Invalidate previous definitions so that LookupResult::resolveKind() does not
    // mark resolution as ambiguous.
    invalidatePreviousDefinitions(D);
    return Result(D, true);
  }
} // end namespace cling
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2011-2014, Georgia Tech Research Corporation
 * All rights reserved.
 *
 * Author(s): Karen Liu <karenliu@cc.gatech.edu>
 *
 * Georgia Tech Graphics Lab and Humanoid Robotics Lab
 *
 * Directed by Prof. C. Karen Liu and Prof. Mike Stilman
 * <karenliu@cc.gatech.edu> <mstilman@cc.gatech.edu>
 *
 * This file is provided under the following "BSD-style" License:
 *   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.
 *   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 HOLDER OR
 *   CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
 *   USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
 *   AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 *   LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 *   ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 *   POSSIBILITY OF SUCH DAMAGE.
 */

#include "dart/utils/Paths.h"
#include "dart/math/Helpers.h"
#include "dart/dynamics/Skeleton.h"
#include "dart/dynamics/BodyNode.h"
#include "dart/dynamics/Joint.h"
#include "dart/simulation/World.h"
#include "dart/utils/SkelParser.h"
#include "dart/constraint/BallJointConstraint.h"
#include "dart/constraint/ConstraintSolver.h"

#include "apps/rigidLoop/MyWindow.h"

using namespace dart;
using namespace math;
using namespace dynamics;
using namespace simulation;
using namespace constraint;

int main(int argc, char* argv[])
{
  // load a skeleton file
  // create and initialize the world
  dart::simulation::World* myWorld
    = utils::SkelParser::readWorld(DART_DATA_PATH"/skel/chain.skel");
  assert(myWorld != NULL);

  // create and initialize the world
  Eigen::Vector3d gravity(0.0, -9.81, 0.0);
  myWorld->setGravity(gravity);
  myWorld->setTimeStep(1.0/2000);

  int dof =  myWorld->getSkeleton(0)->getNumDofs();

  Eigen::VectorXd initPose(dof);
  initPose.setZero();
  initPose[5] = 3.14159 * 0.1;
  initPose[20] = 3.14159 * 0.4;
  initPose[23] = 3.14159 * 0.4;
  initPose[26] = 3.14159 * 0.4;
  initPose[29] = 3.14159 * 0.4;
  myWorld->getSkeleton(0)->setPositions(initPose);
  myWorld->getSkeleton(0)->computeForwardKinematics(true, true, false);

  // create a ball joint constraint
  BodyNode *bd1 = myWorld->getSkeleton(0)->getBodyNode("link 6");
  BodyNode *bd2 = myWorld->getSkeleton(0)->getBodyNode("link 10");
  Eigen::Vector3d offset(0.0, 0.025, 0.0);
  Eigen::Vector3d jointPos = bd1->getTransform() * offset;
  BallJointConstraint *cl = new BallJointConstraint(bd1, bd2, jointPos);
  myWorld->getConstraintSolver()->addConstraint(cl);

  // create a window and link it to the world
  MyWindow window;
  window.setWorld(myWorld);

  glutInit(&argc, argv);
  window.initWindow(640, 480, "Closed Loop");
  glutMainLoop();

  return 0;
}
<commit_msg>Test rigidLoop with WeldJointConstraint instead of BallJointConstraint - It will be replaced BallJointConstraint back once BallJointConstraint is stabilized<commit_after>/*
 * Copyright (c) 2011-2014, Georgia Tech Research Corporation
 * All rights reserved.
 *
 * Author(s): Karen Liu <karenliu@cc.gatech.edu>
 *
 * Georgia Tech Graphics Lab and Humanoid Robotics Lab
 *
 * Directed by Prof. C. Karen Liu and Prof. Mike Stilman
 * <karenliu@cc.gatech.edu> <mstilman@cc.gatech.edu>
 *
 * This file is provided under the following "BSD-style" License:
 *   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.
 *   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 HOLDER OR
 *   CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
 *   USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
 *   AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 *   LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 *   ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 *   POSSIBILITY OF SUCH DAMAGE.
 */

#include "dart/utils/Paths.h"
#include "dart/math/Helpers.h"
#include "dart/dynamics/Skeleton.h"
#include "dart/dynamics/BodyNode.h"
#include "dart/dynamics/Joint.h"
#include "dart/simulation/World.h"
#include "dart/utils/SkelParser.h"
#include "dart/constraint/BallJointConstraint.h"
#include "dart/constraint/WeldJointConstraint.h"
#include "dart/constraint/ConstraintSolver.h"

#include "apps/rigidLoop/MyWindow.h"

using namespace dart;
using namespace math;
using namespace dynamics;
using namespace simulation;
using namespace constraint;

int main(int argc, char* argv[])
{
  // load a skeleton file
  // create and initialize the world
  dart::simulation::World* myWorld
    = utils::SkelParser::readWorld(DART_DATA_PATH"/skel/chain.skel");
  assert(myWorld != NULL);

  // create and initialize the world
  Eigen::Vector3d gravity(0.0, -9.81, 0.0);
  myWorld->setGravity(gravity);
  myWorld->setTimeStep(1.0/2000);

  int dof =  myWorld->getSkeleton(0)->getNumDofs();

  Eigen::VectorXd initPose(dof);
  initPose.setZero();
  initPose[5] = 3.14159 * 0.1;
  initPose[20] = 3.14159 * 0.4;
  initPose[23] = 3.14159 * 0.4;
  initPose[26] = 3.14159 * 0.4;
  initPose[29] = 3.14159 * 0.4;
  myWorld->getSkeleton(0)->setPositions(initPose);
  myWorld->getSkeleton(0)->computeForwardKinematics(true, true, false);

  // create a ball joint constraint
  BodyNode *bd1 = myWorld->getSkeleton(0)->getBodyNode("link 6");
  BodyNode *bd2 = myWorld->getSkeleton(0)->getBodyNode("link 10");
  //Eigen::Vector3d offset(0.0, 0.025, 0.0);
  //Eigen::Vector3d jointPos = bd1->getTransform() * offset;
  //BallJointConstraint *cl = new BallJointConstraint(bd1, bd2, jointPos);
  WeldJointConstraint *cl = new WeldJointConstraint(bd1, bd2);
  myWorld->getConstraintSolver()->addConstraint(cl);

  // create a window and link it to the world
  MyWindow window;
  window.setWorld(myWorld);

  glutInit(&argc, argv);
  window.initWindow(640, 480, "Closed Loop");
  glutMainLoop();

  return 0;
}
<|endoftext|>


<commit_before>//===--- ParentMap.cpp - Mappings from Stmts to their Parents ---*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
//  This file defines the ParentMap class.
//
//===----------------------------------------------------------------------===//

#include "clang/AST/ParentMap.h"
#include "clang/AST/Decl.h"
#include "clang/AST/Expr.h"
#include "llvm/ADT/DenseMap.h"

using namespace clang;

typedef llvm::DenseMap<Stmt*, Stmt*> MapTy;

static void BuildParentMap(MapTy& M, Stmt* S) {
  for (Stmt::child_iterator I=S->child_begin(), E=S->child_end(); I!=E; ++I)
    if (*I) {
      M[*I] = S;
      BuildParentMap(M, *I);
    }
}

ParentMap::ParentMap(Stmt* S) : Impl(0) {
  if (S) {
    MapTy *M = new MapTy();
    BuildParentMap(*M, S);
    Impl = M;
  }
}

ParentMap::~ParentMap() {
  delete (MapTy*) Impl;
}

Stmt* ParentMap::getParent(Stmt* S) const {
  MapTy* M = (MapTy*) Impl;
  MapTy::iterator I = M->find(S);
  return I == M->end() ? 0 : I->second;
}

bool ParentMap::isConsumedExpr(Expr* E) const {
  Stmt *P = getParent(E);
  Stmt *DirectChild = E;

  // Ignore parents that are parentheses or casts.
  while (P && (isa<ParenExpr>(E) || isa<CastExpr>(E))) {
    DirectChild = P;
    P = getParent(P);
  }

  if (!P)
    return false;

  switch (P->getStmtClass()) {
    default:
      return isa<Expr>(P);
    case Stmt::DeclStmtClass:
      return true;
    case Stmt::BinaryOperatorClass: {
      BinaryOperator *BE = cast<BinaryOperator>(P);
      return BE->getOpcode()==BinaryOperator::Comma && DirectChild==BE->getLHS();
    }
    case Stmt::ForStmtClass:
      return DirectChild == cast<ForStmt>(P)->getCond();
    case Stmt::WhileStmtClass:
      return DirectChild == cast<WhileStmt>(P)->getCond();
    case Stmt::DoStmtClass:
      return DirectChild == cast<DoStmt>(P)->getCond();
    case Stmt::IfStmtClass:
      return DirectChild == cast<IfStmt>(P)->getCond();
    case Stmt::IndirectGotoStmtClass:
      return DirectChild == cast<IndirectGotoStmt>(P)->getTarget();
    case Stmt::SwitchStmtClass:
      return DirectChild == cast<SwitchStmt>(P)->getCond();
    case Stmt::ReturnStmtClass:
      return true;
  }
}

<commit_msg>Fix bug in ParentMap::isConsumedExpr. A BinaryOperator always "consumes" the value of its subexpressions unless it is a comma (in which case it doesn't consume the left subexpression).<commit_after>//===--- ParentMap.cpp - Mappings from Stmts to their Parents ---*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
//  This file defines the ParentMap class.
//
//===----------------------------------------------------------------------===//

#include "clang/AST/ParentMap.h"
#include "clang/AST/Decl.h"
#include "clang/AST/Expr.h"
#include "llvm/ADT/DenseMap.h"

using namespace clang;

typedef llvm::DenseMap<Stmt*, Stmt*> MapTy;

static void BuildParentMap(MapTy& M, Stmt* S) {
  for (Stmt::child_iterator I=S->child_begin(), E=S->child_end(); I!=E; ++I)
    if (*I) {
      M[*I] = S;
      BuildParentMap(M, *I);
    }
}

ParentMap::ParentMap(Stmt* S) : Impl(0) {
  if (S) {
    MapTy *M = new MapTy();
    BuildParentMap(*M, S);
    Impl = M;
  }
}

ParentMap::~ParentMap() {
  delete (MapTy*) Impl;
}

Stmt* ParentMap::getParent(Stmt* S) const {
  MapTy* M = (MapTy*) Impl;
  MapTy::iterator I = M->find(S);
  return I == M->end() ? 0 : I->second;
}

bool ParentMap::isConsumedExpr(Expr* E) const {
  Stmt *P = getParent(E);
  Stmt *DirectChild = E;

  // Ignore parents that are parentheses or casts.
  while (P && (isa<ParenExpr>(E) || isa<CastExpr>(E))) {
    DirectChild = P;
    P = getParent(P);
  }

  if (!P)
    return false;

  switch (P->getStmtClass()) {
    default:
      return isa<Expr>(P);
    case Stmt::DeclStmtClass:
      return true;
    case Stmt::BinaryOperatorClass: {
      BinaryOperator *BE = cast<BinaryOperator>(P);
      // If it is a comma, only the left side is consumed.
      // If it isn't a comma, both sides are consumed.
      return BE->getOpcode()!=BinaryOperator::Comma || DirectChild==BE->getLHS();
    }
    case Stmt::ForStmtClass:
      return DirectChild == cast<ForStmt>(P)->getCond();
    case Stmt::WhileStmtClass:
      return DirectChild == cast<WhileStmt>(P)->getCond();
    case Stmt::DoStmtClass:
      return DirectChild == cast<DoStmt>(P)->getCond();
    case Stmt::IfStmtClass:
      return DirectChild == cast<IfStmt>(P)->getCond();
    case Stmt::IndirectGotoStmtClass:
      return DirectChild == cast<IndirectGotoStmt>(P)->getTarget();
    case Stmt::SwitchStmtClass:
      return DirectChild == cast<SwitchStmt>(P)->getCond();
    case Stmt::ReturnStmtClass:
      return true;
  }
}

<|endoftext|>


<commit_before>#pragma once

#ifndef RAZ_RAZ_HPP
#define RAZ_RAZ_HPP

#define GLEW_STATIC

#include "Math/Constants.hpp"
#include "Math/Matrix.hpp"
#include "Math/Quaternion.hpp"
#include "Math/Transform.hpp"
#include "Math/Vector.hpp"
#include "Render/Application.hpp"
#include "Render/Camera.hpp"
#include "Render/Cubemap.hpp"
#include "Render/Framebuffer.hpp"
#include "Render/GraphicObjects.hpp"
#include "Render/RenderSystem.hpp"
#include "Render/Light.hpp"
#include "Render/Material.hpp"
#include "Render/Mesh.hpp"
#include "Render/Scene.hpp"
#include "Render/Shader.hpp"
#include "Render/ShaderProgram.hpp"
#include "Render/Submesh.hpp"
#include "Render/Texture.hpp"
#include "Render/UniformBuffer.hpp"
#include "Utils/Bitset.hpp"
#include "Utils/FileUtils.hpp"
#include "Utils/Image.hpp"
#include "Utils/Input.hpp"
#include "Utils/Overlay.hpp"
#include "Utils/Shape.hpp"
#include "Utils/StrUtils.hpp"
#include "Utils/Window.hpp"

#endif // RAZ_RAZ_HPP
<commit_msg>[Update] Added ECS's headers to global include one; removed Scene<commit_after>#pragma once

#ifndef RAZ_RAZ_HPP
#define RAZ_RAZ_HPP

#define GLEW_STATIC

#include "Application.hpp"
#include "Entity.hpp"
#include "Component.hpp"
#include "World.hpp"
#include "Math/Constants.hpp"
#include "Math/Matrix.hpp"
#include "Math/Quaternion.hpp"
#include "Math/Transform.hpp"
#include "Math/Vector.hpp"
#include "Render/Application.hpp"
#include "Render/Camera.hpp"
#include "Render/Cubemap.hpp"
#include "Render/Framebuffer.hpp"
#include "Render/GraphicObjects.hpp"
#include "Render/RenderSystem.hpp"
#include "Render/Light.hpp"
#include "Render/Material.hpp"
#include "Render/Mesh.hpp"
#include "Render/Shader.hpp"
#include "Render/ShaderProgram.hpp"
#include "Render/Submesh.hpp"
#include "Render/Texture.hpp"
#include "Render/UniformBuffer.hpp"
#include "Utils/Bitset.hpp"
#include "Utils/FileUtils.hpp"
#include "Utils/Image.hpp"
#include "Utils/Input.hpp"
#include "Utils/Overlay.hpp"
#include "Utils/Shape.hpp"
#include "Utils/StrUtils.hpp"
#include "Utils/Window.hpp"

#endif // RAZ_RAZ_HPP
<|endoftext|>


<commit_before>// Copyright 2015 Cloudera 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 "exec/kudu-scanner.h"

#include <boost/foreach.hpp>
#include <kudu/client/row_result.h>
#include <thrift/protocol/TDebugProtocol.h>
#include <vector>

#include "exprs/expr.h"
#include "exprs/expr-context.h"
#include "exec/kudu-util.h"
#include "runtime/mem-pool.h"
#include "runtime/runtime-state.h"
#include "runtime/row-batch.h"
#include "runtime/string-value.h"
#include "runtime/tuple-row.h"
#include "gutil/gscoped_ptr.h"
#include "gutil/strings/substitute.h"
#include "util/jni-util.h"
#include "util/periodic-counter-updater.h"
#include "util/runtime-profile.h"

#include "common/names.h"

using kudu::client::KuduClient;
using kudu::client::KuduColumnSchema;
using kudu::client::KuduPredicate;
using kudu::client::KuduRowResult;
using kudu::client::KuduSchema;
using kudu::client::KuduTable;
using strings::Substitute;

DEFINE_bool(pick_only_leaders_for_tests, false,
            "Whether to pick only leader replicas, for tests purposes only.");

namespace impala {

namespace {

// Sets up the scan range predicate on the scanner, i.e. the partition start/stop keys
// of the partition the scanner is supposed to scan.
Status SetupScanRangePredicate(const TKuduKeyRange& key_range,
    kudu::client::KuduScanner* scanner) {
  if (key_range.partitionStartKey.empty() && key_range.partitionStopKey.empty()) {
    return Status::OK();
  }

  if (!key_range.partitionStartKey.empty()) {
    KUDU_RETURN_IF_ERROR(scanner->AddLowerBoundPartitionKeyRaw(
            key_range.partitionStartKey), "adding scan range lower bound");
  }
  if (!key_range.partitionStopKey.empty()) {
    KUDU_RETURN_IF_ERROR(scanner->AddExclusiveUpperBoundPartitionKeyRaw(
            key_range.partitionStopKey), "adding scan range upper bound");
  }

  return Status::OK();
}

} // anonymous namespace

KuduScanner::KuduScanner(KuduScanNode* scan_node, RuntimeState* state)
  : scan_node_(scan_node),
    state_(state) {}

Status KuduScanner::Open(const std::tr1::shared_ptr<KuduClient>& client,
    const std::tr1::shared_ptr<KuduTable>& table) {
  client_ = client;
  table_ = table;
  materialized_slots_ = scan_node_->materialized_slots();
  tuple_byte_size_ = scan_node_->tuple_desc()->byte_size();
  tuple_num_null_bytes_ = scan_node_->tuple_desc()->num_null_bytes();
  projected_columns_ = scan_node_->projected_columns();

  // Store columns that need relocation when materialized into the
  // destination row batch.
  for (int i = 0; i < materialized_slots_.size(); ++i) {
    if (materialized_slots_[i]->type().type == TYPE_STRING) {
      string_slots_.push_back(materialized_slots_[i]);
    }
  }

  return scan_node_->GetConjunctCtxs(&conjunct_ctxs_);
}

Status KuduScanner::KeepKuduScannerAlive() {
  if (!scanner_) return Status::OK();
  KUDU_RETURN_IF_ERROR(scanner_->KeepAlive(), "Unable to keep the "
      "Kudu scanner alive.");
  return Status::OK();
}

Status KuduScanner::GetNext(RowBatch* row_batch, bool* eos) {
  int tuple_buffer_size = row_batch->capacity() * tuple_byte_size_;
  void* tuple_buffer = row_batch->tuple_data_pool()->TryAllocate(tuple_buffer_size);
  if (tuple_buffer_size > 0 && tuple_buffer == NULL) return Status::MEM_LIMIT_EXCEEDED;
  Tuple* tuple = reinterpret_cast<Tuple*>(tuple_buffer);

  // Main scan loop:
  // Tries to fill 'row_batch' with rows from the last fetched block.
  // If there are no rows to decode tries to get the next block from kudu.
  // If there are no more blocks in the current range tries to get the next range.
  // If there aren't any more rows, blocks or ranges we're done.
  while(true) {
    RETURN_IF_CANCELLED(state_);

    // If the last fetched block has more rows, decode and if we filled up the batch
    // return.
    if (CurrentBlockHasMoreRows()) {
      bool batch_done = false;
      RETURN_IF_ERROR(DecodeRowsIntoRowBatch(row_batch, &tuple, &batch_done));
      if (batch_done) return Status::OK();
    }

    // If the current scanner has more blocks, fetch them.
    if (CurrentScannerHasMoreBlocks()) {
      RETURN_IF_ERROR(GetNextBlock());
      continue;
    }

    // No more blocks in the current scanner, close it.
    CloseCurrentScanner();

    // No more rows or blocks, we're done.
    *eos = true;
    return Status::OK();
  }

  return Status::OK();
}

void KuduScanner::Close() {
  if (scanner_) CloseCurrentScanner();
  Expr::Close(conjunct_ctxs_, state_);
}

Status KuduScanner::OpenNextScanner(const TKuduKeyRange& key_range)  {
  DCHECK(scanner_ == NULL);
  scanner_.reset(new kudu::client::KuduScanner(table_.get()));
  KUDU_RETURN_IF_ERROR(scanner_->SetProjectedColumns(projected_columns_),
      "Unable to set projected columns");

  RETURN_IF_ERROR(SetupScanRangePredicate(key_range, scanner_.get()));

  vector<KuduPredicate*> predicates;
  scan_node_->ClonePredicates(&predicates);
  BOOST_FOREACH(KuduPredicate* predicate, predicates) {
    KUDU_RETURN_IF_ERROR(scanner_->AddConjunctPredicate(predicate),
                         "Unable to add conjunct predicate.");
  }

  if (UNLIKELY(FLAGS_pick_only_leaders_for_tests)) {
    KUDU_RETURN_IF_ERROR(scanner_->SetSelection(kudu::client::KuduClient::LEADER_ONLY),
                         "Could not set replica selection.");
  }

  {
    SCOPED_TIMER(scan_node_->kudu_read_timer());
    KUDU_RETURN_IF_ERROR(scanner_->Open(), "Unable to open scanner");
  }
  return Status::OK();
}

void KuduScanner::CloseCurrentScanner() {
  DCHECK_NOTNULL(scanner_.get());
  scanner_->Close();
  scanner_.reset();
  ExprContext::FreeLocalAllocations(conjunct_ctxs_);
}

Status KuduScanner::HandleEmptyProjection(RowBatch* row_batch, bool* batch_done) {
  int rem_in_block = cur_rows_.size() - rows_scanned_current_block_;
  int rows_to_add = std::min(row_batch->capacity() - row_batch->num_rows(),
      rem_in_block);
  rows_scanned_current_block_ += rows_to_add;
  row_batch->CommitRows(rows_to_add);
  // If we've reached the capacity, or the LIMIT for the scan, return.
  if (row_batch->AtCapacity() || scan_node_->ReachedLimit()) {
    *batch_done = true;
  }
  return Status::OK();
}

Status KuduScanner::DecodeRowsIntoRowBatch(RowBatch* row_batch,
    Tuple** tuple_mem, bool* batch_done) {

  // Short-circuit the count(*) case.
  if (materialized_slots_.empty()) return HandleEmptyProjection(row_batch, batch_done);

  int idx = row_batch->AddRow();
  TupleRow* row = row_batch->GetRow(idx);
  row->SetTuple(0, *tuple_mem);

  // Now iterate through the Kudu rows.
  for (int krow_idx = rows_scanned_current_block_; krow_idx < cur_rows_.size();
       ++krow_idx) {
    const KuduRowResult& krow = cur_rows_[krow_idx];

    // Clear any NULL indicators set by a previous iteration.
    (*tuple_mem)->Init(tuple_num_null_bytes_);

    // Transform a Kudu row into an Impala row.
    RETURN_IF_ERROR(KuduRowToImpalaTuple(krow, row_batch, *tuple_mem));
    ++rows_scanned_current_block_;

    // Evaluate the conjuncts that haven't been pushed down.
    if (conjunct_ctxs_.empty() || ExecNode::EvalConjuncts(&conjunct_ctxs_[0],
        conjunct_ctxs_.size(), row)) {

      // Materialize those slots that require auxiliary memory
      RETURN_IF_ERROR(RelocateValuesFromKudu(*tuple_mem, row_batch->tuple_data_pool()));

      // If the conjuncts pass on the row commit it.
      row_batch->CommitLastRow();

      // Add another row.
      idx = row_batch->AddRow();

      // If we've reached the capacity, or the LIMIT for the scan, return.
      if (idx == RowBatch::INVALID_ROW_INDEX || row_batch->AtCapacity() ||
          scan_node_->ReachedLimit()) {
        *batch_done = true;
        break;
      }

      // Move to the next tuple in the tuple buffer.
      *tuple_mem = next_tuple(*tuple_mem);

      // Make 'row' point to the new row.
      row = row_batch->GetRow(idx);
      row->SetTuple(0, *tuple_mem);
    }
  }
  return Status::OK();
}

void KuduScanner::SetSlotToNull(Tuple* tuple, const SlotDescriptor& slot) {
  DCHECK(slot.is_nullable());
  tuple->SetNull(slot.null_indicator_offset());
}

bool KuduScanner::IsSlotNull(Tuple* tuple, const SlotDescriptor& slot) {
  return slot.is_nullable() && tuple->IsNull(slot.null_indicator_offset());
}

Status KuduScanner::RelocateValuesFromKudu(Tuple* tuple, MemPool* mem_pool) {
  for (int i = 0; i < string_slots_.size(); ++i) {
    const SlotDescriptor* slot = string_slots_[i];
    // NULL handling was done in KuduRowToImpalaTuple.
    if (IsSlotNull(tuple, *slot)) continue;

    // Extract the string value.
    void* slot_ptr = tuple->GetSlot(slot->tuple_offset());
    DCHECK(slot->type().type == TYPE_STRING);

    // The string value of the slot has a pointer to memory from the Kudu row.
    StringValue* val = reinterpret_cast<StringValue*>(slot_ptr);
    char* old_buf = val->ptr;
    // KUDU never returns values larger than 8MB
    DCHECK_LE(val->len, 8 * (1 << 20));
    val->ptr = reinterpret_cast<char*>(mem_pool->TryAllocate(val->len));
    if (UNLIKELY(val->ptr == NULL)) {
      if (UNLIKELY(val->len > 0)) return Status::MEM_LIMIT_EXCEEDED;
    } else {
      DCHECK(val->len > 0);
      memcpy(val->ptr, old_buf, val->len);
    }
  }
  return Status::OK();
}

Status KuduScanner::KuduRowToImpalaTuple(const KuduRowResult& row,
    RowBatch* row_batch, Tuple* tuple) {
  for (int i = 0; i < materialized_slots_.size(); ++i) {
    const SlotDescriptor* info = materialized_slots_[i];
    void* slot = tuple->GetSlot(info->tuple_offset());

    if (row.IsNull(i)) {
      SetSlotToNull(tuple, *info);
      continue;
    }

    switch (info->type().type) {
      case TYPE_STRING: {
        // For types with auxiliary memory (String, Binary,...) store the original memory
        // location in the tuple. Relocate the memory into the row batch's memory in a
        // later step.
        kudu::Slice slice;
        KUDU_RETURN_IF_ERROR(row.GetString(i, &slice),
            "Error getting column value from Kudu.");
        reinterpret_cast<StringValue*>(slot)->ptr =
            const_cast<char*>(reinterpret_cast<const char*>(slice.data()));
        reinterpret_cast<StringValue*>(slot)->len = static_cast<int>(slice.size());
        break;
      }
      case TYPE_TINYINT:
        KUDU_RETURN_IF_ERROR(row.GetInt8(i, reinterpret_cast<int8_t*>(slot)),
            "Error getting column value from Kudu.");
        break;
      case TYPE_SMALLINT:
        KUDU_RETURN_IF_ERROR(row.GetInt16(i, reinterpret_cast<int16_t*>(slot)),
            "Error getting column value from Kudu.");
        break;
      case TYPE_INT:
        KUDU_RETURN_IF_ERROR(row.GetInt32(i, reinterpret_cast<int32_t*>(slot)),
            "Error getting column value from Kudu.");
        break;
      case TYPE_BIGINT:
        KUDU_RETURN_IF_ERROR(row.GetInt64(i, reinterpret_cast<int64_t*>(slot)),
            "Error getting column value from Kudu.");
        break;
      case TYPE_FLOAT:
        KUDU_RETURN_IF_ERROR(row.GetFloat(i, reinterpret_cast<float*>(slot)),
            "Error getting column value from Kudu.");
        break;
      case TYPE_DOUBLE:
        KUDU_RETURN_IF_ERROR(row.GetDouble(i, reinterpret_cast<double*>(slot)),
            "Error getting column value from Kudu.");
        break;
      default:
        DCHECK(false) << "Impala type unsupported in Kudu: "
            << TypeToString(info->type().type);
        return Status(TErrorCode::IMPALA_KUDU_TYPE_MISSING,
            TypeToString(info->type().type));
    }
  }
  return Status::OK();
}

Status KuduScanner::GetNextBlock() {
  SCOPED_TIMER(scan_node_->kudu_read_timer());
  cur_rows_.clear();
  KUDU_RETURN_IF_ERROR(scanner_->NextBatch(&cur_rows_), "Unable to advance iterator");
  COUNTER_ADD(scan_node_->kudu_round_trips(), 1);
  rows_scanned_current_block_ = 0;
  COUNTER_ADD(scan_node_->rows_read_counter(), cur_rows_.size());
  return Status::OK();
}

}  // namespace impala
<commit_msg>Fix uninitialized class member in KuduScanner<commit_after>// Copyright 2015 Cloudera 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 "exec/kudu-scanner.h"

#include <boost/foreach.hpp>
#include <kudu/client/row_result.h>
#include <thrift/protocol/TDebugProtocol.h>
#include <vector>

#include "exprs/expr.h"
#include "exprs/expr-context.h"
#include "exec/kudu-util.h"
#include "runtime/mem-pool.h"
#include "runtime/runtime-state.h"
#include "runtime/row-batch.h"
#include "runtime/string-value.h"
#include "runtime/tuple-row.h"
#include "gutil/gscoped_ptr.h"
#include "gutil/strings/substitute.h"
#include "util/jni-util.h"
#include "util/periodic-counter-updater.h"
#include "util/runtime-profile.h"

#include "common/names.h"

using kudu::client::KuduClient;
using kudu::client::KuduColumnSchema;
using kudu::client::KuduPredicate;
using kudu::client::KuduRowResult;
using kudu::client::KuduSchema;
using kudu::client::KuduTable;
using strings::Substitute;

DEFINE_bool(pick_only_leaders_for_tests, false,
            "Whether to pick only leader replicas, for tests purposes only.");

namespace impala {

namespace {

// Sets up the scan range predicate on the scanner, i.e. the partition start/stop keys
// of the partition the scanner is supposed to scan.
Status SetupScanRangePredicate(const TKuduKeyRange& key_range,
    kudu::client::KuduScanner* scanner) {
  if (key_range.partitionStartKey.empty() && key_range.partitionStopKey.empty()) {
    return Status::OK();
  }

  if (!key_range.partitionStartKey.empty()) {
    KUDU_RETURN_IF_ERROR(scanner->AddLowerBoundPartitionKeyRaw(
            key_range.partitionStartKey), "adding scan range lower bound");
  }
  if (!key_range.partitionStopKey.empty()) {
    KUDU_RETURN_IF_ERROR(scanner->AddExclusiveUpperBoundPartitionKeyRaw(
            key_range.partitionStopKey), "adding scan range upper bound");
  }

  return Status::OK();
}

} // anonymous namespace

KuduScanner::KuduScanner(KuduScanNode* scan_node, RuntimeState* state)
  : scan_node_(scan_node),
    state_(state),
    rows_scanned_current_block_(0) {}

Status KuduScanner::Open(const std::tr1::shared_ptr<KuduClient>& client,
    const std::tr1::shared_ptr<KuduTable>& table) {
  client_ = client;
  table_ = table;
  materialized_slots_ = scan_node_->materialized_slots();
  tuple_byte_size_ = scan_node_->tuple_desc()->byte_size();
  tuple_num_null_bytes_ = scan_node_->tuple_desc()->num_null_bytes();
  projected_columns_ = scan_node_->projected_columns();

  // Store columns that need relocation when materialized into the
  // destination row batch.
  for (int i = 0; i < materialized_slots_.size(); ++i) {
    if (materialized_slots_[i]->type().type == TYPE_STRING) {
      string_slots_.push_back(materialized_slots_[i]);
    }
  }

  return scan_node_->GetConjunctCtxs(&conjunct_ctxs_);
}

Status KuduScanner::KeepKuduScannerAlive() {
  if (!scanner_) return Status::OK();
  KUDU_RETURN_IF_ERROR(scanner_->KeepAlive(), "Unable to keep the "
      "Kudu scanner alive.");
  return Status::OK();
}

Status KuduScanner::GetNext(RowBatch* row_batch, bool* eos) {
  int tuple_buffer_size = row_batch->capacity() * tuple_byte_size_;
  void* tuple_buffer = row_batch->tuple_data_pool()->TryAllocate(tuple_buffer_size);
  if (tuple_buffer_size > 0 && tuple_buffer == NULL) return Status::MEM_LIMIT_EXCEEDED;
  Tuple* tuple = reinterpret_cast<Tuple*>(tuple_buffer);

  // Main scan loop:
  // Tries to fill 'row_batch' with rows from the last fetched block.
  // If there are no rows to decode tries to get the next block from kudu.
  // If there are no more blocks in the current range tries to get the next range.
  // If there aren't any more rows, blocks or ranges we're done.
  while(true) {
    RETURN_IF_CANCELLED(state_);

    // If the last fetched block has more rows, decode and if we filled up the batch
    // return.
    if (CurrentBlockHasMoreRows()) {
      bool batch_done = false;
      RETURN_IF_ERROR(DecodeRowsIntoRowBatch(row_batch, &tuple, &batch_done));
      if (batch_done) return Status::OK();
    }

    // If the current scanner has more blocks, fetch them.
    if (CurrentScannerHasMoreBlocks()) {
      RETURN_IF_ERROR(GetNextBlock());
      continue;
    }

    // No more blocks in the current scanner, close it.
    CloseCurrentScanner();

    // No more rows or blocks, we're done.
    *eos = true;
    return Status::OK();
  }

  return Status::OK();
}

void KuduScanner::Close() {
  if (scanner_) CloseCurrentScanner();
  Expr::Close(conjunct_ctxs_, state_);
}

Status KuduScanner::OpenNextScanner(const TKuduKeyRange& key_range)  {
  DCHECK(scanner_ == NULL);
  scanner_.reset(new kudu::client::KuduScanner(table_.get()));
  KUDU_RETURN_IF_ERROR(scanner_->SetProjectedColumns(projected_columns_),
      "Unable to set projected columns");

  RETURN_IF_ERROR(SetupScanRangePredicate(key_range, scanner_.get()));

  vector<KuduPredicate*> predicates;
  scan_node_->ClonePredicates(&predicates);
  BOOST_FOREACH(KuduPredicate* predicate, predicates) {
    KUDU_RETURN_IF_ERROR(scanner_->AddConjunctPredicate(predicate),
                         "Unable to add conjunct predicate.");
  }

  if (UNLIKELY(FLAGS_pick_only_leaders_for_tests)) {
    KUDU_RETURN_IF_ERROR(scanner_->SetSelection(kudu::client::KuduClient::LEADER_ONLY),
                         "Could not set replica selection.");
  }

  {
    SCOPED_TIMER(scan_node_->kudu_read_timer());
    KUDU_RETURN_IF_ERROR(scanner_->Open(), "Unable to open scanner");
  }
  return Status::OK();
}

void KuduScanner::CloseCurrentScanner() {
  DCHECK_NOTNULL(scanner_.get());
  scanner_->Close();
  scanner_.reset();
  ExprContext::FreeLocalAllocations(conjunct_ctxs_);
}

Status KuduScanner::HandleEmptyProjection(RowBatch* row_batch, bool* batch_done) {
  int rem_in_block = cur_rows_.size() - rows_scanned_current_block_;
  int rows_to_add = std::min(row_batch->capacity() - row_batch->num_rows(),
      rem_in_block);
  rows_scanned_current_block_ += rows_to_add;
  row_batch->CommitRows(rows_to_add);
  // If we've reached the capacity, or the LIMIT for the scan, return.
  if (row_batch->AtCapacity() || scan_node_->ReachedLimit()) {
    *batch_done = true;
  }
  return Status::OK();
}

Status KuduScanner::DecodeRowsIntoRowBatch(RowBatch* row_batch,
    Tuple** tuple_mem, bool* batch_done) {

  // Short-circuit the count(*) case.
  if (materialized_slots_.empty()) return HandleEmptyProjection(row_batch, batch_done);

  int idx = row_batch->AddRow();
  TupleRow* row = row_batch->GetRow(idx);
  row->SetTuple(0, *tuple_mem);

  // Now iterate through the Kudu rows.
  for (int krow_idx = rows_scanned_current_block_; krow_idx < cur_rows_.size();
       ++krow_idx) {
    const KuduRowResult& krow = cur_rows_[krow_idx];

    // Clear any NULL indicators set by a previous iteration.
    (*tuple_mem)->Init(tuple_num_null_bytes_);

    // Transform a Kudu row into an Impala row.
    RETURN_IF_ERROR(KuduRowToImpalaTuple(krow, row_batch, *tuple_mem));
    ++rows_scanned_current_block_;

    // Evaluate the conjuncts that haven't been pushed down.
    if (conjunct_ctxs_.empty() || ExecNode::EvalConjuncts(&conjunct_ctxs_[0],
        conjunct_ctxs_.size(), row)) {

      // Materialize those slots that require auxiliary memory
      RETURN_IF_ERROR(RelocateValuesFromKudu(*tuple_mem, row_batch->tuple_data_pool()));

      // If the conjuncts pass on the row commit it.
      row_batch->CommitLastRow();

      // Add another row.
      idx = row_batch->AddRow();

      // If we've reached the capacity, or the LIMIT for the scan, return.
      if (idx == RowBatch::INVALID_ROW_INDEX || row_batch->AtCapacity() ||
          scan_node_->ReachedLimit()) {
        *batch_done = true;
        break;
      }

      // Move to the next tuple in the tuple buffer.
      *tuple_mem = next_tuple(*tuple_mem);

      // Make 'row' point to the new row.
      row = row_batch->GetRow(idx);
      row->SetTuple(0, *tuple_mem);
    }
  }
  return Status::OK();
}

void KuduScanner::SetSlotToNull(Tuple* tuple, const SlotDescriptor& slot) {
  DCHECK(slot.is_nullable());
  tuple->SetNull(slot.null_indicator_offset());
}

bool KuduScanner::IsSlotNull(Tuple* tuple, const SlotDescriptor& slot) {
  return slot.is_nullable() && tuple->IsNull(slot.null_indicator_offset());
}

Status KuduScanner::RelocateValuesFromKudu(Tuple* tuple, MemPool* mem_pool) {
  for (int i = 0; i < string_slots_.size(); ++i) {
    const SlotDescriptor* slot = string_slots_[i];
    // NULL handling was done in KuduRowToImpalaTuple.
    if (IsSlotNull(tuple, *slot)) continue;

    // Extract the string value.
    void* slot_ptr = tuple->GetSlot(slot->tuple_offset());
    DCHECK(slot->type().type == TYPE_STRING);

    // The string value of the slot has a pointer to memory from the Kudu row.
    StringValue* val = reinterpret_cast<StringValue*>(slot_ptr);
    char* old_buf = val->ptr;
    // KUDU never returns values larger than 8MB
    DCHECK_LE(val->len, 8 * (1 << 20));
    val->ptr = reinterpret_cast<char*>(mem_pool->TryAllocate(val->len));
    if (UNLIKELY(val->ptr == NULL)) {
      if (UNLIKELY(val->len > 0)) return Status::MEM_LIMIT_EXCEEDED;
    } else {
      DCHECK(val->len > 0);
      memcpy(val->ptr, old_buf, val->len);
    }
  }
  return Status::OK();
}

Status KuduScanner::KuduRowToImpalaTuple(const KuduRowResult& row,
    RowBatch* row_batch, Tuple* tuple) {
  for (int i = 0; i < materialized_slots_.size(); ++i) {
    const SlotDescriptor* info = materialized_slots_[i];
    void* slot = tuple->GetSlot(info->tuple_offset());

    if (row.IsNull(i)) {
      SetSlotToNull(tuple, *info);
      continue;
    }

    switch (info->type().type) {
      case TYPE_STRING: {
        // For types with auxiliary memory (String, Binary,...) store the original memory
        // location in the tuple. Relocate the memory into the row batch's memory in a
        // later step.
        kudu::Slice slice;
        KUDU_RETURN_IF_ERROR(row.GetString(i, &slice),
            "Error getting column value from Kudu.");
        reinterpret_cast<StringValue*>(slot)->ptr =
            const_cast<char*>(reinterpret_cast<const char*>(slice.data()));
        reinterpret_cast<StringValue*>(slot)->len = static_cast<int>(slice.size());
        break;
      }
      case TYPE_TINYINT:
        KUDU_RETURN_IF_ERROR(row.GetInt8(i, reinterpret_cast<int8_t*>(slot)),
            "Error getting column value from Kudu.");
        break;
      case TYPE_SMALLINT:
        KUDU_RETURN_IF_ERROR(row.GetInt16(i, reinterpret_cast<int16_t*>(slot)),
            "Error getting column value from Kudu.");
        break;
      case TYPE_INT:
        KUDU_RETURN_IF_ERROR(row.GetInt32(i, reinterpret_cast<int32_t*>(slot)),
            "Error getting column value from Kudu.");
        break;
      case TYPE_BIGINT:
        KUDU_RETURN_IF_ERROR(row.GetInt64(i, reinterpret_cast<int64_t*>(slot)),
            "Error getting column value from Kudu.");
        break;
      case TYPE_FLOAT:
        KUDU_RETURN_IF_ERROR(row.GetFloat(i, reinterpret_cast<float*>(slot)),
            "Error getting column value from Kudu.");
        break;
      case TYPE_DOUBLE:
        KUDU_RETURN_IF_ERROR(row.GetDouble(i, reinterpret_cast<double*>(slot)),
            "Error getting column value from Kudu.");
        break;
      default:
        DCHECK(false) << "Impala type unsupported in Kudu: "
            << TypeToString(info->type().type);
        return Status(TErrorCode::IMPALA_KUDU_TYPE_MISSING,
            TypeToString(info->type().type));
    }
  }
  return Status::OK();
}

Status KuduScanner::GetNextBlock() {
  SCOPED_TIMER(scan_node_->kudu_read_timer());
  cur_rows_.clear();
  KUDU_RETURN_IF_ERROR(scanner_->NextBatch(&cur_rows_), "Unable to advance iterator");
  COUNTER_ADD(scan_node_->kudu_round_trips(), 1);
  rows_scanned_current_block_ = 0;
  COUNTER_ADD(scan_node_->rows_read_counter(), cur_rows_.size());
  return Status::OK();
}

}  // namespace impala
<|endoftext|>


<commit_before>#include	<gtest/gtest.h>
#include	<april/aprillibrary.h>
#include	<april/logic/world.h>
#include	<april/logic/actuator.h>
#include	<april/logic/actor.h>
#include	<april/logic/actuatorfactory.h>

using namespace april;

TEST(Actuator, init) {

	initAprilLibrary();
	World * w = new World( "test-world", 1000 );
	DEC_REF( w, w );

	Actor * ag = new Actor( w );
	DEC_REF(ag,ag);
	Actuator * act = new Actuator( ag );
	DEC_REF(act,act);

	endAprilLibrary();
}

<commit_msg>Actuators test: created from DNA<commit_after>#include	<gtest/gtest.h>
#include	<april/aprillibrary.h>
#include	<april/logic/world.h>
#include	<april/logic/actor.h>
#include	<april/logic/actorfactory.h>
#include	<april/logic/actuator.h>
#include	<april/logic/actuatorfactory.h>

using namespace april;

TEST(Actuator, init) {

	initAprilLibrary();
	World * w = new World( "test-world", 1000 );
	DEC_REF( w, w );

	Actor * ag = new Actor( w );
	DEC_REF(ag,ag);
	Actuator * act = new Actuator( ag );
	DEC_REF(act,act);

	endAprilLibrary();
}

enum TestIds {
	TestIdKind = 1,
	TestIdActuator = 2
};

class ActuatorTstFact : public ActuatorFactory {
public:
	ActuatorTstFact( World * w ): ActuatorFactory( w ) {
		w->insertId( TestIdActuator, "actuators.test" );
		addMyself( TestIdActuator );
	}
	virtual Actuator * create ( Actor * a, ID id ) {
		Q_UNUSED( id );
		Actuator * ret = new Actuator( a );
		return ret;
	}
};

class ActorActuatorTstFact : public ActorFactory {
public:
	ActorActuatorTstFact( World * w ) : ActorFactory( w ) {
		w->insertId( TestIdKind, "kinds.test" );
		addMyself( TestIdKind );
		initDNA( TestIdKind );
		EXPECT_TRUE( defaultDNA().addActuator( TestIdActuator ) );
	}
	virtual Actor * create ( ID id ) {
		Q_UNUSED( id );
		Q_ASSERT( id == TestIdKind );
		Actor * ret = new Actor( world() );
		setDNA( ret );
		return ret;
	}
	virtual void copyDefaultDNA ( DNA & destination ) {
		destination = defaultDNA();
	}
};

TEST(Actuator, factory) {
	initAprilLibrary();

	World * w = new World( __FUNCTION__, 1000 );
	DEC_REF( w, w );

	ActuatorTstFact * actuator_fact = new ActuatorTstFact( w );
	DEC_REF( actuator_fact, actuator_fact );

	ActorActuatorTstFact * actor_fact = new ActorActuatorTstFact( w );
	DEC_REF( actor_fact, actor_fact );

	Actor * a = w->createActor( TestIdKind );
	DEC_REF( a, a );
	EXPECT_TRUE( a != NULL );
	EXPECT_TRUE( a->firstSensor() == NULL );
	EXPECT_TRUE( a->firstReflex() == NULL );
	EXPECT_TRUE( a->firstBrain() == NULL );
	EXPECT_TRUE( a->firstActuator() != NULL );
	EXPECT_EQ( a->kind(), TestIdKind );
	EXPECT_EQ( a->kindName(), "kinds.test" );

	Actuator * r = a->firstActuator();
	EXPECT_TRUE( r->next() == NULL );
	EXPECT_TRUE( r->prev() == NULL );
	EXPECT_TRUE( r->actor() == a );

	endAprilLibrary();
}
<|endoftext|>


<commit_before>/*! \file */ //Copyright 2011-2018 Tyler Gilbert; All Rights Reserved

#ifndef SYS_SYS_HPP_
#define SYS_SYS_HPP_

#if !defined __link
#include <sos/sos.h>
#endif

#include <sos/dev/sys.h>
#include <sos/link.h>
#include "File.hpp"

namespace sys {

/*! \brief Sys Class
 * \details This class allows access to system attributes and functions.
 */
class Sys : public File {
public:

#if defined __link
	Sys(link_transport_mdriver_t * driver);
#else
	Sys();
#endif

    /*! \details Returns a c style string pointer
     * to the API version.
     *
     * This version is 2.4.0
     *
     */
    static const char * version(){ return "2.4.0"; }

	enum {
		LAUNCH_OPTIONS_FLASH /*! Install in flash memory */ = APPFS_FLAG_IS_FLASH,
		LAUNCH_OPTIONS_STARTUP /*! Run at startup (must be in flash) */ = APPFS_FLAG_IS_STARTUP,
		LAUNCH_OPTIONS_ROOT /*! Run as root (if applicable) */ = APPFS_FLAG_IS_ROOT,
		LAUNCH_OPTIONS_REPLACE /*! Delete if application exists */ = APPFS_FLAG_IS_REPLACE,
		LAUNCH_OPTIONS_ORPHAN /*! Allow app to become an orphan */ = APPFS_FLAG_IS_ORPHAN,
		LAUNCH_OPTIONS_UNIQUE_NAMES /*! Create a unique name on install */ = APPFS_FLAG_IS_UNIQUE,
		LAUNCH_RAM_SIZE_DEFAULT = 0
	};

	/*! \details Launches a new application.
	 *
	 * @param path The path to the application
	 * @param exec_dest A pointer to a buffer where the execution path will be written (null if not needed)
	 * @param args The arguments to pass to the applications
	 * @param options For example:  LAUNCH_OPTIONS_FLASH | LAUNCH_OPTIONS_STARTUP
	 * @param ram_size The amount of RAM that will be used by the app
	 * @param update_progress A callback to show the progress if the app needs to be installed (copied to flash/RAM)
	 * @param envp Not used (set to zero)
	 * @return The process ID of the new app if successful
	 *
	 * This method must be called locally in an app. It can't be executed over the link protocol.
	 */
	static int launch(const char * path,
			char * exec_dest = 0,
			const char * args = 0,
			int options = 0, //run in RAM, discard on exit
			int ram_size = LAUNCH_RAM_SIZE_DEFAULT,
			int (*update_progress)(int, int) = 0,
			char *const envp[] = 0
	);

	/*! \details Frees the RAM associated with the app without deleting the code from flash
	 * (should not be called when the app is currently running).
	 *
	 * @param path The path to the app (use \a exec_dest from launch())
	 * @param driver Used with link protocol only
	 * @return Zero on success
	 *
	 * This method can causes problems if not used correctly. The RAM associated with
	 * the app will be free and available for other applications. Any applications
	 * that are using the RAM must quit before the RAM can be reclaimed using reclaim_ram().
	 *
	 * \sa reclaim_ram()
	 */
	static int free_ram(const char * path, link_transport_mdriver_t * driver = 0);

	/*! \details Reclaims RAM that was freed using free_ram().
	 *
	 * @param path The path to the app
	 * @param driver Used with link protocol only
	 * @return Zero on success
	 *
	 * \sa free_ram()
	 */
	static int reclaim_ram(const char * path, link_transport_mdriver_t * driver = 0);

	static void assign_zero_sum32(void * data, int size);
	static int verify_zero_sum32(void * data, int size);

#if !defined __link

	/*! \details Gets the version (system/board version).
	 *
	 * @param version The destination string for the version
	 * @return Zero on success
	 */
	static int get_version(var::String & version);
    static var::String get_version();

	/*! \details Gets the version (kernel version).
	 *
	 * @param version The destination string for the version
	 * @return Zero on success
	 */
	static int get_kernel_version(var::String & version);

	/*! \details Puts the kernel in powerdown mode.
	 *
	 * @param timeout_msec The number of milliseconds before the
	 * device will power on (reset).  If this isn't supported,
	 * the device will power off until reset by an external signal
	 */
	static void powerdown(int timeout_msec = 0);

	/*! \details Puts the kernel in hibernate mode.
	 *
	 * @param timeout_msec The number of milliseconds before the
	 * device will wake up from hibernation.  If this isn't supported,
	 * the device will stay in hibernation until woken up externally
	 */
	static int hibernate(int timeout_msec = 0);

	/*! \details Executes a kernel request.
	 *
	 * @param req The request number
	 * @param arg Argument pointer
	 * @return The result of the execution of the request. (-1 if request is not available)
	 *
	 * The kernel request must
	 * be defined and implemented by the board support package.
	 */
	static int request(int req, void * arg = 0);

	/*! \details Forces a reset of the device. */
	static void reset();

	/*! \details Loads the board configuration provided as
	 * part of the board support package.
	 *
	 * @param config A reference to the destination object
	 * @return Zero on success
	 *
	 * The object must be opened before calling this method.
	 *
	 * \sa open()
	 */
	int get_board_config(sos_board_config_t & config);
#endif

	/*! \details Opens /dev/sys.
	 *
	 * @return Zero on success
	 *
	 */
	int open(){
		return File::open("/dev/sys", RDWR);
	}

	using File::open;

	/*! \details Loads the current system info.
	 *
	 * @param attr A reference to where the data should be stored
	 * @return Zero on success
	 *
	 * The object must be opened before calling this method.
	 *
	 * \sa open()
	 *
	 */
	int get_info(sys_info_t & attr);
	int get_23_info(sys_23_info_t & attr);
	int get_26_info(sys_26_info_t & attr);

    //these are deprecated: use sys::Task instead
	int get_taskattr(sys_taskattr_t & attr, int task = -1);
	inline int get_taskattr(sys_taskattr_t * attr, int task = -1){
		return get_taskattr(*attr, task);
	}

	int current_task() const { return m_current_task; }
	void set_current_task(int v){ m_current_task = v; }

	/*! \details Loads the cloud kernel ID.
	 *
	 * @param id A reference to the destination data
	 * @return Less than zero if the operation failed
	 *
	 * The object must be opened before calling this method.
	 *
	 */
	int get_id(sys_id_t & id);

#if !defined __link
	/*! \details Redirects the standard output to the file specified.
	 *
	 * @param fd The file descriptor where the standard output should be directed.
	 *
	 * The file desriptor should be open and ready for writing. For example,
	 * to redirect the standard output to the UART:
	 *
	 * \code
	 * #include <sapi/sys.hpp>
	 * #include <sapi/hal.hpp>
	 *
	 * Uart uart(0);
	 * uart.init(); //initializes uart using default settings (if available)
	 * Sys::redirect_stdout( uart.fileno() );
	 * printf("This will be written to UART0\n");
	 * \endcode
	 *
	 *
	 */
	static void redirect_stdout(int fd){
		_impure_ptr->_stdout->_file = fd;
	}

	/*! \details Redirects the standard input from the specified file descriptor.
	 *
	 * @param fd The open and readable file descriptor to use for standard input
	 *
	 * See Sys::redirect_stdout() for an example.
	 *
	 */
	static void redirect_stdin(int fd){
		_impure_ptr->_stdin->_file = fd;
	}

	/*! \details Redirects the standard error from the specified file descriptor.
	 *
	 * @param fd The open and writable file descriptor to use for standard input
	 *
	 * See Sys::redirect_stdout() for an example.
	 *
	 */
	static void redirect_stderr(int fd){
		_impure_ptr->_stderr->_file = fd;
	}
#endif

private:
	int m_current_task;

};

}

#endif /* SYS_SYS_HPP_ */
<commit_msg>Fixed a documentation error<commit_after>/*! \file */ //Copyright 2011-2018 Tyler Gilbert; All Rights Reserved

#ifndef SYS_SYS_HPP_
#define SYS_SYS_HPP_

#if !defined __link
#include <sos/sos.h>
#endif

#include <sos/dev/sys.h>
#include <sos/link.h>
#include "File.hpp"

namespace sys {

/*! \brief Sys Class
 * \details This class allows access to system attributes and functions.
 */
class Sys : public File {
public:

#if defined __link
	Sys(link_transport_mdriver_t * driver);
#else
	Sys();
#endif

    /*! \details Returns a c style string pointer
     * to the API version.
     *
     * This version is 2.4.0
     *
     */
    static const char * version(){ return "2.4.0"; }

	enum {
		LAUNCH_OPTIONS_FLASH /*! Install in flash memory */ = APPFS_FLAG_IS_FLASH,
		LAUNCH_OPTIONS_STARTUP /*! Run at startup (must be in flash) */ = APPFS_FLAG_IS_STARTUP,
		LAUNCH_OPTIONS_ROOT /*! Run as root (if applicable) */ = APPFS_FLAG_IS_ROOT,
		LAUNCH_OPTIONS_REPLACE /*! Delete if application exists */ = APPFS_FLAG_IS_REPLACE,
		LAUNCH_OPTIONS_ORPHAN /*! Allow app to become an orphan */ = APPFS_FLAG_IS_ORPHAN,
		LAUNCH_OPTIONS_UNIQUE_NAMES /*! Create a unique name on install */ = APPFS_FLAG_IS_UNIQUE,
		LAUNCH_RAM_SIZE_DEFAULT = 0
	};

	/*! \details Launches a new application.
	 *
	 * @param path The path to the application
	 * @param exec_dest A pointer to a buffer where the execution path will be written (null if not needed)
	 * @param args The arguments to pass to the applications
	 * @param options For example:  LAUNCH_OPTIONS_FLASH | LAUNCH_OPTIONS_STARTUP
	 * @param ram_size The amount of RAM that will be used by the app
	 * @param update_progress A callback to show the progress if the app needs to be installed (copied to flash/RAM)
	 * @param envp Not used (set to zero)
	 * @return The process ID of the new app if successful
	 *
	 * This method must be called locally in an app. It can't be executed over the link protocol.
	 */
	static int launch(const char * path,
			char * exec_dest = 0,
			const char * args = 0,
			int options = 0, //run in RAM, discard on exit
			int ram_size = LAUNCH_RAM_SIZE_DEFAULT,
			int (*update_progress)(int, int) = 0,
			char *const envp[] = 0
	);

	/*! \details Frees the RAM associated with the app without deleting the code from flash
	 * (should not be called when the app is currently running).
	 *
	 * @param path The path to the app (use \a exec_dest from launch())
	 * @param driver Used with link protocol only
	 * @return Zero on success
	 *
	 * This method can causes problems if not used correctly. The RAM associated with
	 * the app will be free and available for other applications. Any applications
	 * that are using the RAM must quit before the RAM can be reclaimed using reclaim_ram().
	 *
	 * \sa reclaim_ram()
	 */
	static int free_ram(const char * path, link_transport_mdriver_t * driver = 0);

	/*! \details Reclaims RAM that was freed using free_ram().
	 *
	 * @param path The path to the app
	 * @param driver Used with link protocol only
	 * @return Zero on success
	 *
	 * \sa free_ram()
	 */
	static int reclaim_ram(const char * path, link_transport_mdriver_t * driver = 0);

	static void assign_zero_sum32(void * data, int size);
	static int verify_zero_sum32(void * data, int size);

#if !defined __link

	/*! \details Gets the version (system/board version).
	 *
	 * @param version The destination string for the version
	 * @return Zero on success
	 */
	static int get_version(var::String & version);
    static var::String get_version();

	/*! \details Gets the version (kernel version).
	 *
	 * @param version The destination string for the version
	 * @return Zero on success
	 */
	static int get_kernel_version(var::String & version);

	/*! \details Puts the kernel in powerdown mode.
	 *
	 * @param timeout_msec The number of milliseconds before the
	 * device will power on (reset).  If this isn't supported,
	 * the device will power off until reset by an external signal
	 */
	static void powerdown(int timeout_msec = 0);

	/*! \details Puts the kernel in hibernate mode.
	 *
	 * @param timeout_msec The number of milliseconds before the
	 * device will wake up from hibernation.  If this isn't supported,
	 * the device will stay in hibernation until woken up externally
	 */
	static int hibernate(int timeout_msec = 0);

	/*! \details Executes a kernel request.
	 *
	 * @param req The request number
	 * @param arg Argument pointer
	 * @return The result of the execution of the request. (-1 if request is not available)
	 *
	 * The kernel request must
	 * be defined and implemented by the board support package.
	 */
	static int request(int req, void * arg = 0);

	/*! \details Forces a reset of the device. */
	static void reset();

	/*! \details Loads the board configuration provided as
	 * part of the board support package.
	 *
	 * @param config A reference to the destination object
	 * @return Zero on success
	 *
	 * The object must be opened before calling this method.
	 *
	 * \sa open()
	 */
	int get_board_config(sos_board_config_t & config);
#endif

	/*! \details Opens /dev/sys.
	 *
     * @return Less than zero for an error
	 *
	 */
	int open(){
		return File::open("/dev/sys", RDWR);
	}

	using File::open;

	/*! \details Loads the current system info.
	 *
	 * @param attr A reference to where the data should be stored
	 * @return Zero on success
	 *
	 * The object must be opened before calling this method.
	 *
	 * \sa open()
	 *
	 */
	int get_info(sys_info_t & attr);
	int get_23_info(sys_23_info_t & attr);
	int get_26_info(sys_26_info_t & attr);

    //these are deprecated: use sys::Task instead
	int get_taskattr(sys_taskattr_t & attr, int task = -1);
	inline int get_taskattr(sys_taskattr_t * attr, int task = -1){
		return get_taskattr(*attr, task);
	}

	int current_task() const { return m_current_task; }
	void set_current_task(int v){ m_current_task = v; }

	/*! \details Loads the cloud kernel ID.
	 *
	 * @param id A reference to the destination data
	 * @return Less than zero if the operation failed
	 *
	 * The object must be opened before calling this method.
	 *
	 */
	int get_id(sys_id_t & id);

#if !defined __link
	/*! \details Redirects the standard output to the file specified.
	 *
	 * @param fd The file descriptor where the standard output should be directed.
	 *
	 * The file desriptor should be open and ready for writing. For example,
	 * to redirect the standard output to the UART:
	 *
	 * \code
	 * #include <sapi/sys.hpp>
	 * #include <sapi/hal.hpp>
	 *
	 * Uart uart(0);
	 * uart.init(); //initializes uart using default settings (if available)
	 * Sys::redirect_stdout( uart.fileno() );
	 * printf("This will be written to UART0\n");
	 * \endcode
	 *
	 *
	 */
	static void redirect_stdout(int fd){
		_impure_ptr->_stdout->_file = fd;
	}

	/*! \details Redirects the standard input from the specified file descriptor.
	 *
	 * @param fd The open and readable file descriptor to use for standard input
	 *
	 * See Sys::redirect_stdout() for an example.
	 *
	 */
	static void redirect_stdin(int fd){
		_impure_ptr->_stdin->_file = fd;
	}

	/*! \details Redirects the standard error from the specified file descriptor.
	 *
	 * @param fd The open and writable file descriptor to use for standard input
	 *
	 * See Sys::redirect_stdout() for an example.
	 *
	 */
	static void redirect_stderr(int fd){
		_impure_ptr->_stderr->_file = fd;
	}
#endif

private:
	int m_current_task;

};

}

#endif /* SYS_SYS_HPP_ */
<|endoftext|>