<commit_before>/**
 * Copyright 2014-2016 Steven T Sell (ssell@vertexfragment.com)
 *
 * 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 "stdafx.h"
#include "Widgets/SceneTreeItem.hpp"
#include "Widgets/SceneTree.hpp"

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

namespace Ocular
{
    namespace Editor
    {
        //----------------------------------------------------------------------------------
        // CONSTRUCTORS
        //----------------------------------------------------------------------------------

        SceneTreeItem::SceneTreeItem(SceneTree* parent, Core::SceneObject* object)
            : QTreeWidgetItem(parent),
              m_Object(object)
        {
            buildItem();
        }

        SceneTreeItem::SceneTreeItem(SceneTreeItem* parent, Core::SceneObject* object)
            : QTreeWidgetItem(parent),
              m_Object(object)
        {
            buildItem();
        }

        SceneTreeItem::~SceneTreeItem()
        {
            m_Object = nullptr;
        }

        //----------------------------------------------------------------------------------
        // PUBLIC METHODS
        //----------------------------------------------------------------------------------

        void SceneTreeItem::update(bool const recursive)
        {
            if(m_Object)
            {
                if(text(0).compare(m_Object->getName().c_str()) != 0)
                {
                    setText(0, QString(m_Object->getName().c_str()));
                }
            }
        }

        Core::SceneObject* SceneTreeItem::getObject() const
        {
            return m_Object;
        }

        Core::UUID const& SceneTreeItem::getUUID() const
        {
            return m_ObjectUUID;
        }

        //----------------------------------------------------------------------------------
        // PROTECTED METHODS
        //----------------------------------------------------------------------------------

        void SceneTreeItem::buildItem()
        {
            if(m_Object)
            {
                m_ObjectUUID = m_Object->getUUID();

                setText(0, QString(m_Object->getName().c_str()));
                setText(1, QString(m_ObjectUUID.toString().c_str()));
            }
            else
            {
                setText(0, QString("NULL"));
                setText(1, QString("0"));
            }
        }

        //----------------------------------------------------------------------------------
        // PRIVATE METHODS
        //----------------------------------------------------------------------------------
    }
}<commit_msg>Fix to issue #127<commit_after>/**
 * Copyright 2014-2016 Steven T Sell (ssell@vertexfragment.com)
 *
 * 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 "stdafx.h"
#include "Widgets/SceneTreeItem.hpp"
#include "Widgets/SceneTree.hpp"

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

namespace Ocular
{
    namespace Editor
    {
        //----------------------------------------------------------------------------------
        // CONSTRUCTORS
        //----------------------------------------------------------------------------------

        SceneTreeItem::SceneTreeItem(SceneTree* parent, Core::SceneObject* object)
            : QTreeWidgetItem(parent),
              m_Object(object)
        {
            buildItem();
        }

        SceneTreeItem::SceneTreeItem(SceneTreeItem* parent, Core::SceneObject* object)
            : QTreeWidgetItem(parent),
              m_Object(object)
        {
            buildItem();
        }

        SceneTreeItem::~SceneTreeItem()
        {
            m_Object = nullptr;
        }

        //----------------------------------------------------------------------------------
        // PUBLIC METHODS
        //----------------------------------------------------------------------------------

        void SceneTreeItem::update(bool const recursive)
        {
            if(m_Object)
            {
                if(text(0).compare(m_Object->getName().c_str()) != 0)
                {
                    setText(0, QString(m_Object->getName().c_str()));
                }
            }

            if(recursive)
            {
                for(int32_t i = 0; i < childCount(); i++)
                {
                    SceneTreeItem* childItem = dynamic_cast<SceneTreeItem*>(child(i));

                    if(childItem)
                    {
                        childItem->update(true);
                    }
                }
            }
        }

        Core::SceneObject* SceneTreeItem::getObject() const
        {
            return m_Object;
        }

        Core::UUID const& SceneTreeItem::getUUID() const
        {
            return m_ObjectUUID;
        }

        //----------------------------------------------------------------------------------
        // PROTECTED METHODS
        //----------------------------------------------------------------------------------

        void SceneTreeItem::buildItem()
        {
            if(m_Object)
            {
                m_ObjectUUID = m_Object->getUUID();

                setText(0, QString(m_Object->getName().c_str()));
                setText(1, QString(m_ObjectUUID.toString().c_str()));
            }
            else
            {
                setText(0, QString("NULL"));
                setText(1, QString("0"));
            }
        }

        //----------------------------------------------------------------------------------
        // PRIVATE METHODS
        //----------------------------------------------------------------------------------
    }
}<|endoftext|>


<commit_before>class AliAnalysisDataContainer;
class AliFlowTrackCuts;
class AliFlowTrackSimpleCuts;
class AliFlowEventCuts;
class AliFlowEventSimpleCuts;

void AddTaskPIDFlowSPMCKine(Int_t uptoWhichHarmonics = 5,
			    Float_t etamin=-0.8,
			    Float_t etamax=0.8,
			    Float_t gEtaGap=0.0,
			    TString fileNameBase="AnalysisResults",
			    TString uniqueStr="Pion_00",
			    TString gQVector ="Qa",
			    Int_t charge=0,
			    Double_t bmin = -1,
			    Int_t bmax = 50,
			    Bool_t isPID = kTRUE,
			    Bool_t isVZERO = kFALSE, // use vzero sp method
			    Bool_t useAfterBurner=kFALSE,
			    AliPID::EParticleType particleType=AliPID::kPion) {
  //macro to run over the kine tree for higher harmonics (pid with pdg)
  TF1 *gV2Param = 0x0;
  Bool_t doQA=kTRUE;

  // AFTERBURNER
  Double_t v1=0.0;
  Double_t v2=0.0;
  Double_t v3=0.0;
  Double_t v4=0.0;
  Int_t numberOfTrackClones=0; //non-flow

  //Define the range for eta subevents (for SP method) with TPC
  Double_t minA = etamin;//
  Double_t maxA = -0.5*gEtaGap;//
  Double_t minB = +0.5*gEtaGap;//
  Double_t maxB = etamax;//

  //---------Data selection---------- ESD only!!!
  //kMC, kGlobal, kESD_TPConly, kESD_SPDtracklet
  AliFlowTrackCuts::trackParameterType rptype = AliFlowTrackCuts::kMC;
  AliFlowTrackCuts::trackParameterType poitype = AliFlowTrackCuts::kMC;

  //---------Parameter mixing--------
  //kPure - no mixing, kTrackWithMCkine, kTrackWithMCPID, kTrackWithMCpt
  AliFlowTrackCuts::trackParameterMix rpmix = AliFlowTrackCuts::kPure;
  AliFlowTrackCuts::trackParameterMix poimix = AliFlowTrackCuts::kPure;

  const char* rptypestr = AliFlowTrackCuts::GetParamTypeName(rptype);  //ESD
  const char* poitypestr = AliFlowTrackCuts::GetParamTypeName(poitype); //ESD

  //general parameters
  const int nharmonics = uptoWhichHarmonics-1;
  TString outputSlotName[nharmonics];
  TString suffixName;

  //========================================//
  //Define event cuts
  AliFlowEventCuts* cutsEvent = new AliFlowEventCuts("eventcuts");
  if(bmin > = 0) cutsEvent->SetImpactParameterRange(bmin,bmax);
  cutsEvent->SetPrimaryVertexZrange(-10.,10.);
  cutsEvent->SetQA(doQA);

  //========================================//
  //Definition of reference particles
  AliFlowTrackCuts *cutsRP = new AliFlowTrackCuts("RP");
  cutsRP->SetParamType(rptype);
  cutsRP->SetParamMix(rpmix);
  cutsRP->SetPtRange(0.2,10.);
  cutsRP->SetEtaRange(etamin,etamax);
  cutsRP->SetMCisPrimary(kTRUE);
  cutsRP->SetRequireCharge(kTRUE);
  cutsRP->SetQA(doQA);

  //========================================//
  //Definition of POIs
  AliFlowTrackCuts* SP_POI = new AliFlowTrackCuts("POI");
  SP_POI->SetParamType(poitype);
  SP_POI->SetParamMix(poimix);
  SP_POI->SetMCisPrimary(kTRUE);
  SP_POI->SetPtRange(0.2,10.);
  SP_POI->SetIgnoreSignInMCPID(kTRUE);
  if(isPID){
    if(particleType==AliPID::kPion) SP_POI->SetMCPID(211);
    if(particleType==AliPID::kKaon) SP_POI->SetMCPID(321);
    if(particleType==AliPID::kProton) SP_POI->SetMCPID(2212);
  }
  if(charge != 0) SP_POI->SetCharge(charge);

  //=====================================================================
  //Define the sub events for the POIs
  if(!isVZERO && gQVector=="Qa") {
    SP_POI->SetEtaRange( +0.5*gEtaGap, etamax );
    printf(" > NOTE: Using half TPC (Qb) as POI selection u < \n");
    suffixName = "Qa";
  }
  if(!isVZERO && gQVector=="Qb") {
    SP_POI->SetEtaRange( etamin,-0.5*gEtaGap );
    printf(" > NOTE: Using half TPC (Qa) as POI selection u < \n");
    suffixName = "Qb";
  }
  if(isVZERO) {
    SP_POI->SetEtaRange( etamin,etamax );
    printf(" > NOTE: Using full TPC as POI selection u < \n");
    suffixName = "vzero";
  }
  SP_POI->SetQA(doQA);
  //=====================================================================

  suffixName += "_flow_";
  if(bmin >= 0) {
    suffixName += Form("%.2f_", bmin);
    suffixName += Form("%.2f_", bmax);
  }
  suffixName += Form("%.f_", gEtaGap*10);

  if(isPID)
    suffixName+=uniqueStr;
  else
    suffixName+="AllCharged";

  if (charge<0) suffixName+="-";
  if (charge>0) suffixName+="+";

  //for v2,v3,v4 and v5
  for(int harmonic = 2; harmonic < uptoWhichHarmonics + 1; harmonic++){
    outputSlotName[harmonic-2] = "";
    outputSlotName[harmonic-2]+=uniqueStr;
    outputSlotName[harmonic-2]+=Form("_v%i_",harmonic);
    if(bmin >= 0) {
      outputSlotName[harmonic-2]+=Form("%.2f-",bmin);
      outputSlotName[harmonic-2]+=Form("%.2f_",bmax);
    }
    if(isPID)
      outputSlotName[harmonic-2]+=AliPID::ParticleName(particleType);
    else
      outputSlotName[harmonic-2]+="AllCharged";
    if (charge<0) outputSlotName[harmonic-2]+="-";
    if (charge>0) outputSlotName[harmonic-2]+="+";
  }

  TString fileName(fileNameBase);
  fileName.Append(".root");

  //========================FLOWPACKAGE TASKS=========================//
  AliAnalysisDataContainer *cinput1;
  AliAnalysisDataContainer *coutputFE;
  AliAnalysisDataContainer* coutputFEQA;
  AliAnalysisTaskFlowEvent *taskFE;

  AliAnalysisDataContainer *flowEvent[nharmonics];
  AliAnalysisTaskFilterFE *tskFilter[nharmonics];

  AliAnalysisDataContainer *coutputSP[nharmonics];
  AliAnalysisTaskScalarProduct *taskSP[nharmonics];

  TString outputQA;
  TString myNameSP[nharmonics];
  TString slot[nharmonics];

  //======================================================================
  //Get the pointer to the existing analysis manager
  AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
  if (!mgr) {
    Error("AddTaskFlowEvent", "No analysis manager to connect to.");
    return NULL;
  }

  //Check the analysis type using the event handlers connected to the
  //analysis manager. The availability of MC handler can also be checked here.
  //=====================================================================
  if (!mgr->GetInputEventHandler()) {
    ::Error("AddTaskFlowEvent", "This task requires an input event handler");
    return NULL;
  }

  taskFE = new AliAnalysisTaskFlowEvent(Form("TaskFlowEvent_%s",suffixName.Data()),"",doQA);

  //Use after burner: rotate phi for each particle
  if(useAfterBurner) {
    if(gV2Param)
      taskFE->SetPtDifferentialV2(gV2Param);
    else
      taskFE->SetFlow(v1,v2,v3,v4);
    taskFE->SetNonFlowNumberOfTrackClones(numberOfTrackClones);
    taskFE->SetAfterburnerOn();
  }

  if(!isVZERO) taskFE->SetSubeventEtaRange(minA, maxA, minB, maxB);
  if(isVZERO)  taskFE->SetSubeventEtaRange(-5,-1.5,+1.5,5);
  mgr->AddTask(taskFE);

  // Pass cuts for RPs and POIs to the task:
  taskFE->SetCutsEvent(cutsEvent);
  taskFE->SetCutsRP(cutsRP);
  taskFE->SetCutsPOI(SP_POI);
  if (cutsRP->GetParamType()==AliFlowTrackCuts::kVZERO) {
    taskFE->SetHistWeightvsPhiMin(0.);
    taskFE->SetHistWeightvsPhiMax(200.);
  }

  AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
  cinput1 = mgr->GetCommonInputContainer();

  coutputFE = mgr->CreateContainer(Form("FlowEvent_%s",suffixName.Data()),AliFlowEventSimple::Class(),AliAnalysisManager::kExchangeContainer);

  mgr->ConnectInput(taskFE,0,cinput1);
  mgr->ConnectOutput(taskFE,1,coutputFE);
  //==========================================================
  TString Species = "";
  if(isPID)
    Species += AliPID::ParticleName(particleType);
  else
    Species += "Allcharged";

  for(int harm = 2; harm < uptoWhichHarmonics + 1; harm++){
    myNameSP[harm-2] = "SP_";
    myNameSP[harm-2] += gQVector;
    myNameSP[harm-2] += Form("_v%i_%s_%.f",harm,outputSlotName[harm-2].Data(),gEtaGap*10);

    flowEvent[harm-2] = mgr->CreateContainer( Form("Filter_%s", myNameSP[harm-2].Data()),AliFlowEventSimple::Class(),AliAnalysisManager::kExchangeContainer );

    tskFilter[harm-2] = new AliAnalysisTaskFilterFE( Form("TaskFilter_%s",myNameSP[harm-2].Data()),cutsRP, NULL);//SP_POI
    if(!isVZERO)
      tskFilter[harm-2]->SetSubeventEtaRange(minA, maxA, minB, maxB);
    if(isVZERO) tskFilter[harm-2]->SetSubeventEtaRange(-5,-1.5,+1.5,5);
    mgr->AddTask(tskFilter[harm-2]);
    mgr->ConnectInput( tskFilter[harm-2],0,coutputFE);
    mgr->ConnectOutput(tskFilter[harm-2],1,flowEvent[harm-2]);

    taskSP[harm-2] = new AliAnalysisTaskScalarProduct(Form("TaskScalarProduct_%s",outputSlotName[harm-2].Data()),kFALSE);
    taskSP[harm-2]->SetHarmonic(harm);
    taskSP[harm-2]->SetRelDiffMsub(1.0);
    taskSP[harm-2]->SetTotalQvector(gQVector);
    taskSP[harm-2]->SetApplyCorrectionForNUA(kTRUE);

    TString outputSP = fileName;
    outputSP += ":outputSPanalysis";
    outputSP+= rptypestr;
    slot[harm-2] = "SP_";
    slot[harm-2] += outputSlotName[harm-2];
    slot[harm-2] += "_";
    slot[harm-2] += gQVector;
    coutputSP[harm-2] = mgr->CreateContainer(Form("%s_%.f",slot[harm-2].Data(),gEtaGap*10),TList::Class(),AliAnalysisManager::kOutputContainer,outputSP);
    mgr->AddTask(taskSP[harm-2]);
    mgr->ConnectInput(taskSP[harm-2],0,flowEvent[harm-2]);
    mgr->ConnectInput(taskSP[harm-2],0,coutputFE);
    mgr->ConnectOutput(taskSP[harm-2],1,coutputSP[harm-2]);
  }

  if (taskFE->GetQAOn()) {
    outputQA = fileName;
    outputQA += ":QA";
    coutputFEQA = mgr->CreateContainer(Form("QA_%s",suffixName.Data()), TList::Class(),AliAnalysisManager::kOutputContainer,outputQA);
    mgr->ConnectOutput(taskFE,2,coutputFEQA);
  }
}

<commit_msg> minor tweak to addtask macro from naghmeh<commit_after>class AliAnalysisDataContainer;
class AliFlowTrackCuts;
class AliFlowTrackSimpleCuts;
class AliFlowEventCuts;
class AliFlowEventSimpleCuts;

void AddTaskPIDFlowSPMCKine(Int_t uptoWhichHarmonics = 5,
			    Float_t etamin=-0.8,
			    Float_t etamax=0.8,
			    Float_t gEtaGap=0.0,
			    TString fileNameBase="AnalysisResults",
			    TString uniqueStr="Pion_00",
			    TString gQVector ="Qa",
			    Int_t charge=0,
			    Double_t bmin = 0.0,
			    Double_t bmax = 12.0,
			    Bool_t isPID = kTRUE,
			    Bool_t isVZERO = kFALSE, // use vzero sp method
			    Bool_t useAfterBurner=kFALSE,
			    AliPID::EParticleType particleType=AliPID::kPion) {
  //macro to run over the kine tree for higher harmonics (pid with pdg)
  TF1 *gV2Param = 0x0;
  Bool_t doQA=kTRUE;

  // AFTERBURNER
  Double_t v1=0.0;
  Double_t v2=0.0;
  Double_t v3=0.0;
  Double_t v4=0.0;
  Int_t numberOfTrackClones=0; //non-flow

  //Define the range for eta subevents (for SP method) with TPC
  Double_t minA = etamin;//
  Double_t maxA = -0.5*gEtaGap;//
  Double_t minB = +0.5*gEtaGap;//
  Double_t maxB = etamax;//

  //---------Data selection---------- ESD only!!!
  //kMC, kGlobal, kESD_TPConly, kESD_SPDtracklet
  AliFlowTrackCuts::trackParameterType rptype = AliFlowTrackCuts::kMC;
  AliFlowTrackCuts::trackParameterType poitype = AliFlowTrackCuts::kMC;

  //---------Parameter mixing--------
  //kPure - no mixing, kTrackWithMCkine, kTrackWithMCPID, kTrackWithMCpt
  AliFlowTrackCuts::trackParameterMix rpmix = AliFlowTrackCuts::kPure;
  AliFlowTrackCuts::trackParameterMix poimix = AliFlowTrackCuts::kPure;

  const char* rptypestr = AliFlowTrackCuts::GetParamTypeName(rptype);  //ESD
  const char* poitypestr = AliFlowTrackCuts::GetParamTypeName(poitype); //ESD

  //general parameters
  const int nharmonics = uptoWhichHarmonics-1;
  TString outputSlotName[nharmonics];
  TString suffixName;

  //========================================//
  //Define event cuts
  AliFlowEventCuts* cutsEvent = new AliFlowEventCuts("eventcuts");
  if(bmin > = 0) cutsEvent->SetImpactParameterRange(bmin,bmax);
  cutsEvent->SetPrimaryVertexZrange(-10.,10.);
  cutsEvent->SetQA(doQA);

  //========================================//
  //Definition of reference particles
  AliFlowTrackCuts *cutsRP = new AliFlowTrackCuts("RP");
  cutsRP->SetParamType(rptype);
  cutsRP->SetParamMix(rpmix);
  cutsRP->SetPtRange(0.2,10.);
  cutsRP->SetEtaRange(etamin,etamax);
  cutsRP->SetMCisPrimary(kTRUE);
  cutsRP->SetRequireCharge(kTRUE);
  cutsRP->SetQA(doQA);

  //========================================//
  //Definition of POIs
  AliFlowTrackCuts* SP_POI = new AliFlowTrackCuts("POI");
  SP_POI->SetParamType(poitype);
  SP_POI->SetParamMix(poimix);
  SP_POI->SetMCisPrimary(kTRUE);
  SP_POI->SetPtRange(0.2,10.);
  SP_POI->SetIgnoreSignInMCPID(kTRUE);
  if(isPID){
    if(particleType==AliPID::kPion) SP_POI->SetMCPID(211);
    if(particleType==AliPID::kKaon) SP_POI->SetMCPID(321);
    if(particleType==AliPID::kProton) SP_POI->SetMCPID(2212);
  }
  if(charge != 0) SP_POI->SetCharge(charge);

  //=====================================================================
  //Define the sub events for the POIs
  if(!isVZERO && gQVector=="Qa") {
    SP_POI->SetEtaRange( +0.5*gEtaGap, etamax );
    printf(" > NOTE: Using half TPC (Qb) as POI selection u < \n");
    suffixName = "Qa";
  }
  if(!isVZERO && gQVector=="Qb") {
    SP_POI->SetEtaRange( etamin,-0.5*gEtaGap );
    printf(" > NOTE: Using half TPC (Qa) as POI selection u < \n");
    suffixName = "Qb";
  }
  if(isVZERO) {
    SP_POI->SetEtaRange( etamin,etamax );
    printf(" > NOTE: Using full TPC as POI selection u < \n");
    suffixName = "vzero";
  }
  SP_POI->SetQA(doQA);
  //=====================================================================

  suffixName += "_flow_";
  if(bmin >= 0) {
    suffixName += Form("%.2f_", bmin);
    suffixName += Form("%.2f_", bmax);
  }
  suffixName += Form("%.f_", gEtaGap*10);

  if(isPID)
    suffixName+=uniqueStr;
  else
    suffixName+="AllCharged";

  if (charge<0) suffixName+="-";
  if (charge>0) suffixName+="+";

  //for v2,v3,v4 and v5
  for(int harmonic = 2; harmonic < uptoWhichHarmonics + 1; harmonic++){
    outputSlotName[harmonic-2] = "";
    outputSlotName[harmonic-2]+=uniqueStr;
    outputSlotName[harmonic-2]+=Form("_v%i_",harmonic);
    if(bmin >= 0) {
      outputSlotName[harmonic-2]+=Form("%.2f-",bmin);
      outputSlotName[harmonic-2]+=Form("%.2f_",bmax);
    }
    if(isPID)
      outputSlotName[harmonic-2]+=AliPID::ParticleName(particleType);
    else
      outputSlotName[harmonic-2]+="AllCharged";
    if (charge<0) outputSlotName[harmonic-2]+="-";
    if (charge>0) outputSlotName[harmonic-2]+="+";
  }

  TString fileName(fileNameBase);
  fileName.Append(".root");

  //========================FLOWPACKAGE TASKS=========================//
  AliAnalysisDataContainer *cinput1;
  AliAnalysisDataContainer *coutputFE;
  AliAnalysisDataContainer* coutputFEQA;
  AliAnalysisTaskFlowEvent *taskFE;

  AliAnalysisDataContainer *flowEvent[nharmonics];
  AliAnalysisTaskFilterFE *tskFilter[nharmonics];

  AliAnalysisDataContainer *coutputSP[nharmonics];
  AliAnalysisTaskScalarProduct *taskSP[nharmonics];

  TString outputQA;
  TString myNameSP[nharmonics];
  TString slot[nharmonics];

  //======================================================================
  //Get the pointer to the existing analysis manager
  AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
  if (!mgr) {
    Error("AddTaskFlowEvent", "No analysis manager to connect to.");
    return NULL;
  }

  //Check the analysis type using the event handlers connected to the
  //analysis manager. The availability of MC handler can also be checked here.
  //=====================================================================
  if (!mgr->GetInputEventHandler()) {
    ::Error("AddTaskFlowEvent", "This task requires an input event handler");
    return NULL;
  }

  taskFE = new AliAnalysisTaskFlowEvent(Form("TaskFlowEvent_%s",suffixName.Data()),"",doQA);

  //Use after burner: rotate phi for each particle
  if(useAfterBurner) {
    if(gV2Param)
      taskFE->SetPtDifferentialV2(gV2Param);
    else
      taskFE->SetFlow(v1,v2,v3,v4);
    taskFE->SetNonFlowNumberOfTrackClones(numberOfTrackClones);
    taskFE->SetAfterburnerOn();
  }

  if(!isVZERO) taskFE->SetSubeventEtaRange(minA, maxA, minB, maxB);
  if(isVZERO)  taskFE->SetSubeventEtaRange(-5,-1.5,+1.5,5);
  mgr->AddTask(taskFE);

  // Pass cuts for RPs and POIs to the task:
  taskFE->SetCutsEvent(cutsEvent);
  taskFE->SetCutsRP(cutsRP);
  taskFE->SetCutsPOI(SP_POI);
  if (cutsRP->GetParamType()==AliFlowTrackCuts::kVZERO) {
    taskFE->SetHistWeightvsPhiMin(0.);
    taskFE->SetHistWeightvsPhiMax(200.);
  }

  AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
  cinput1 = mgr->GetCommonInputContainer();

  coutputFE = mgr->CreateContainer(Form("FlowEvent_%s",suffixName.Data()),AliFlowEventSimple::Class(),AliAnalysisManager::kExchangeContainer);

  mgr->ConnectInput(taskFE,0,cinput1);
  mgr->ConnectOutput(taskFE,1,coutputFE);
  //==========================================================
  TString Species = "";
  if(isPID)
    Species += AliPID::ParticleName(particleType);
  else
    Species += "Allcharged";

  for(int harm = 2; harm < uptoWhichHarmonics + 1; harm++){
    myNameSP[harm-2] = "SP_";
    myNameSP[harm-2] += gQVector;
    myNameSP[harm-2] += Form("_v%i_%s_%.f",harm,outputSlotName[harm-2].Data(),gEtaGap*10);

    flowEvent[harm-2] = mgr->CreateContainer( Form("Filter_%s", myNameSP[harm-2].Data()),AliFlowEventSimple::Class(),AliAnalysisManager::kExchangeContainer );

    tskFilter[harm-2] = new AliAnalysisTaskFilterFE( Form("TaskFilter_%s",myNameSP[harm-2].Data()),cutsRP, NULL);//SP_POI
    if(!isVZERO)
      tskFilter[harm-2]->SetSubeventEtaRange(minA, maxA, minB, maxB);
    if(isVZERO) tskFilter[harm-2]->SetSubeventEtaRange(-5,-1.5,+1.5,5);
    mgr->AddTask(tskFilter[harm-2]);
    mgr->ConnectInput( tskFilter[harm-2],0,coutputFE);
    mgr->ConnectOutput(tskFilter[harm-2],1,flowEvent[harm-2]);

    taskSP[harm-2] = new AliAnalysisTaskScalarProduct(Form("TaskScalarProduct_%s",outputSlotName[harm-2].Data()),kFALSE);
    taskSP[harm-2]->SetHarmonic(harm);
    taskSP[harm-2]->SetRelDiffMsub(1.0);
    taskSP[harm-2]->SetTotalQvector(gQVector);
    taskSP[harm-2]->SetApplyCorrectionForNUA(kTRUE);

    TString outputSP = fileName;
    outputSP += ":outputSPanalysis";
    outputSP+= rptypestr;
    slot[harm-2] = "SP_";
    slot[harm-2] += outputSlotName[harm-2];
    slot[harm-2] += "_";
    slot[harm-2] += gQVector;
    coutputSP[harm-2] = mgr->CreateContainer(Form("%s_%.f",slot[harm-2].Data(),gEtaGap*10),TList::Class(),AliAnalysisManager::kOutputContainer,outputSP);
    mgr->AddTask(taskSP[harm-2]);
    mgr->ConnectInput(taskSP[harm-2],0,flowEvent[harm-2]);
    mgr->ConnectInput(taskSP[harm-2],0,coutputFE);
    mgr->ConnectOutput(taskSP[harm-2],1,coutputSP[harm-2]);
  }

  if (taskFE->GetQAOn()) {
    outputQA = fileName;
    outputQA += ":QA";
    coutputFEQA = mgr->CreateContainer(Form("QA_%s",suffixName.Data()), TList::Class(),AliAnalysisManager::kOutputContainer,outputQA);
    mgr->ConnectOutput(taskFE,2,coutputFEQA);
  }
}

<|endoftext|>


<commit_before>/// \file runEMCALTimeCalibTask.C
/// \brief macro to run Time Calibration Task
///
/// Run in two steps.
/// 1. First iteration over statistics gives calibration constants.
/// Remember to apply energy cuts. We want to take into account only GOOD cells.
/// 2. Run method ProduceCalibConsts(inputFile,outputFile) to obtain reference
/// file with constants.
/// 3. Second iteration with applied conatants give results.
///
/// \author Marie Germain <marie.germain@subatech.in2p3.fr>, SUBATECH
/// \author Adam Matyja <adam.tomasz.matyja@ifj.edu.pl>, INP PAN Cracow
/// \date Jun 3, 2015

void runEMCALTimeCalibTask(Int_t type=0)
{
  //type = 0: local
  //type = 1: grid

  Bool_t isPhysicsSelection=kFALSE;// <<-----FIXME <<-----uncomment it in real data
  Bool_t isCentralitySelection=kFALSE;

  TStopwatch timer;
  timer.Start();
  printf("*** the task is: AliAnalysisTaskEMCALTimeCalib ***\n");
  // Grid connection
  printf("*** Connect to AliEn ***\n");
  TGrid::Connect("alien://");
  //printf("*** Connected to AliEn? in  ***\n");
  cout<< "Connected to AliEn" <<endl;
  timer.Print();

  //libraries
  gSystem->Load("libTree.so");
  gSystem->Load("libGeom.so");
  //gSystem->Load("libVMC.so");
  gSystem->Load("libSTEERBase.so");
  gSystem->Load("libESD.so");
  //gSystem->Load("libAOD.so");

  // load analysis framework
  gSystem->Load("libANALYSIS");
  gSystem->Load("libANALYSISalice");
  gSystem->Load("libANALYSISalice.so");

  gSystem->Load("libEMCALUtils.so");
  gSystem->Load("libPWGPPEMCAL.so");

  gSystem->AddIncludePath("-I$ALICE_ROOT");
  gSystem->AddIncludePath("-I$ALICE_PHYSICS");
  gSystem->AddIncludePath("-I./");

  // 	// test with lib from PWGGA train

  //ANALYSIS PART
  const char *collectionfile = "wn.xml";
  TChain* chain = NULL;
  if(type==0){//local files
    gROOT->LoadMacro("$ALICE_PHYSICS/PWG/EMCAL/macros/CreateESDChain.C");
    chain = CreateESDChain("files.txt", 1);
  }
  else if(type==1){//grid files
    chain = CreateChainFromCollection(collectionfile, "esdTree");
  }

  // for includes use either global setting in $HOME/.rootrc
  // ACLiC.IncludePaths: -I$(ALICE_ROOT)/include
  // or in each macro
  gSystem->AddIncludePath("-I$ALICE_ROOT/include");
  gSystem->AddIncludePath("-I$ALICE_PHYSICS/include");

  // Create the analysis manager
  AliAnalysisManager *mgr = new AliAnalysisManager("MyEmcalAnalysis");
  AliESDInputHandler* esdH = new AliESDInputHandler();
  mgr->SetInputEventHandler(esdH);

  if(isPhysicsSelection){
    gROOT->LoadMacro("$ALICE_PHYSICS/PWGPP/PilotTrain/AddTaskPhysicsSelection.C");
    AliPhysicsSelectionTask* physselTask = AddTaskPhysicsSelection();
    // physselTask->AddCollisionTriggerClass("+CINT1WU-B-NOPF-ALL");
  }
  if(isCentralitySelection){
    gROOT->LoadMacro("$ALICE_PHYSICS/OADB/macros/AddTaskCentrality.C");
    AliCentralitySelectionTask* centralityTask = AddTaskCentrality(); // Create task
  }

  //AliCalorimeterUtils *cu = new AliCalorimeterUtils();
  //   cu->SwitchOnBadChannelsRemoval();

  // Create task
  //UInt_t kTriggerInt = AliVEvent::kAnyINT;
  //UInt_t kTriggerEMC   = AliVEvent::kEMC8 || AliVEvent::kEMC7 || AliVEvent::kEMCEJE || AliVEvent::kEMCEGA;

  AliAnalysisTaskEMCALTimeCalib *taskmbemcal = new AliAnalysisTaskEMCALTimeCalib("TimeCalibTask");
  //  AliEMCALRecoUtils *reco = taskmbemcal->GetEMCALRecoUtils();
  //  taskmbemcal->PrintInfo();
  //  reco->SwitchOnRejectExoticCluster();

  taskmbemcal->SelectCollisionCandidates(AliVEvent::kEMC1|AliVEvent::kEMC7|AliVEvent::kEMC8|AliVEvent::kEMCEJE|AliVEvent::kEMCEGA);
  taskmbemcal->SetGeometryName("EMCAL_COMPLETE12SMV1_DCAL_8SM");

  //taskmbemcal->SelectCollisionCandidates(AliVEvent::kAnyINT);
  //taskmbemcal->SetDebugLevel(10);

  // Add task(s)
  // taskmbemcal->PrintInfo();
  if(isPhysicsSelection) mgr->AddTask(physselTask);
  mgr->AddTask(taskmbemcal);

  TString outputFileName;
  if(type==0)outputFileName="timeOutput.root";
  else if(type==1)outputFileName="timeResults.root";

  // Create containers for input/output
  AliAnalysisDataContainer *cinput = mgr->GetCommonInputContainer();
  AliAnalysisDataContainer *coutputList = mgr->CreateContainer("chistolist", TList::Class(),
     AliAnalysisManager::kOutputContainer, outputFileName.Data());

  // Connect input/output
  mgr->ConnectInput(taskmbemcal, 0, cinput);

  // No need to connect to a common AOD output container if the task does not
  // fill AOD info.
  //  mgr->ConnectOutput(task, 0, coutput0);
  mgr->ConnectOutput(taskmbemcal, 1, coutputList);

  // Enable debug printouts
  if(type==0) mgr->SetDebugLevel(12);

  if (!mgr->InitAnalysis()) return;
  mgr->PrintStatus();
  mgr->StartAnalysis("local", chain);

  timer.Stop();
  timer.Print();

}

//______________________________________________________________________________
TChain *CreateChainFromCollection(const char* xmlfile, const char *treeName="esdTree")
{
// Create a chain from an alien collection.
   TAlienCollection * myCollection  = TAlienCollection::Open(xmlfile);

   if (!myCollection) {
      ::Error("CreateChainSingle", "Cannot create an AliEn collection from %s", xmlfile) ;
      return NULL ;
  }

  TChain* chain = new TChain(treeName);
  myCollection->Reset() ;
  while ( myCollection->Next() ) chain->Add(myCollection->GetTURL("")) ;
  chain->ls();
  return chain;
}

// End of macro
<commit_msg>update comments, adapt for e, Adam Matyja<commit_after>/// \file runEMCALTimeCalibTask.C
/// \brief macro to run Time Calibration Task
///
/// Run in two steps.
/// 1. First iteration over statistics gives calibration constants.
/// Remember to apply energy cuts. We want to take into account only GOOD cells.
/// 2. Run method ProduceCalibConsts(inputFile,outputFile) to obtain reference
/// file with constants.
/// 3. Second iteration with applied consatants plus extra timing cut gives corrected calibration constants.
///
/// \param type: Int_t, local or grid processing
/// \param isESD: Bool_t, flag to process ESD or AOD
/// \param isPhysicsSelection: Bool_t, flag to use Physics Selection
/// \param isCentralitySelection: Bool_t, flag to use Centrality Selection
/// \author Marie Germain <marie.germain@subatech.in2p3.fr>, SUBATECH
/// \author Adam Matyja <adam.tomasz.matyja@ifj.edu.pl>, INP PAN Cracow
/// \date Jun 3, 2015

void runEMCALTimeCalibTask(Int_t type=0, Bool_t isESD=kTRUE, Bool_t isPhysicsSelection=kFALSE, Bool_t isCentralitySelection=kFALSE)
{
  //type = 0: local
  //type = 1: grid

  TStopwatch timer;
  timer.Start();
  printf("*** the task is: AliAnalysisTaskEMCALTimeCalib ***\n");
  // Grid connection
  printf("*** Connect to AliEn ***\n");
  TGrid::Connect("alien://");
  //printf("*** Connected to AliEn? in  ***\n");
  cout<< "Connected to AliEn" <<endl;
  timer.Print();

  //libraries
  gSystem->Load("libTree.so");
  gSystem->Load("libGeom.so");
  //gSystem->Load("libVMC.so");
  gSystem->Load("libSTEERBase.so");
  gSystem->Load("libESD.so");
  gSystem->Load("libAOD.so");

  // load analysis framework
  gSystem->Load("libANALYSIS");
  gSystem->Load("libANALYSISalice");
  gSystem->Load("libANALYSISalice.so");

  gSystem->Load("libEMCALUtils.so");
  gSystem->Load("libPWGPPEMCAL.so");

  gSystem->AddIncludePath("-I$ALICE_ROOT");
  gSystem->AddIncludePath("-I$ALICE_PHYSICS");
  gSystem->AddIncludePath("-I./");

  // 	// test with lib from PWGGA train

  //ANALYSIS PART
  //  const char *collectionfile = "wn_1run.xml";
  //  const char *collectionfile = "wn.xml";
  const char *collectionfile;
  if(isESD==kTRUE) collectionfile = "esd_156889.xml";
  else collectionfile= "aod_156889.xml";
  //const char *collectionfile = "esd_156889.xml";
  TChain* chain = NULL;
  if(type==0){//local files
    if(isESD==kTRUE) {
      gROOT->LoadMacro("$ALICE_PHYSICS/PWG/EMCAL/macros/CreateESDChain.C");
      chain = CreateESDChain("files.txt", 1);
    } else {
      gROOT->LoadMacro("$ALICE_PHYSICS/PWG/EMCAL/macros/CreateAODChain.C");
      chain = CreateAODChain("filesAOD.txt", 1);
    }
  }
  else if(type==1){//grid files
    if(isESD==kTRUE) chain = CreateChainFromCollection(collectionfile, "esdTree");
    else chain = CreateChainFromCollection(collectionfile, "aodTree");
  }

  // for includes use either global setting in $HOME/.rootrc
  // ACLiC.IncludePaths: -I$(ALICE_ROOT)/include
  // or in each macro
  gSystem->AddIncludePath("-I$ALICE_ROOT/include");
  gSystem->AddIncludePath("-I$ALICE_PHYSICS/include");

  // Create the analysis manager
  AliAnalysisManager *mgr = new AliAnalysisManager("MyEmcalAnalysis");
  AliInputEventHandler *inputHandler=NULL;

  //  AliESDInputHandler* esdH = new AliESDInputHandler();
  //  mgr->SetInputEventHandler(esdH);

  if(isESD==kTRUE) inputHandler = new AliESDInputHandler();
  else inputHandler = new AliAODInputHandler();

  mgr->SetInputEventHandler(inputHandler);

  AliPhysicsSelectionTask* physselTask=NULL;
  if(isPhysicsSelection){
    gROOT->LoadMacro("$ALICE_PHYSICS/PWGPP/PilotTrain/AddTaskPhysicsSelection.C");
    //    AliPhysicsSelectionTask* physselTask = AddTaskPhysicsSelection();
    physselTask = AddTaskPhysicsSelection();
    // physselTask->AddCollisionTriggerClass("+CINT1WU-B-NOPF-ALL");
  }
  AliCentralitySelectionTask* centralityTask=NULL;
  if(isCentralitySelection){
    gROOT->LoadMacro("$ALICE_PHYSICS/OADB/macros/AddTaskCentrality.C");
    //    AliCentralitySelectionTask* centralityTask = AddTaskCentrality(); // Create task
    centralityTask = AddTaskCentrality(); // Create task
  }

  //AliCalorimeterUtils *cu = new AliCalorimeterUtils();
  //   cu->SwitchOnBadChannelsRemoval();

  // Create task
  //UInt_t kTriggerInt = AliVEvent::kAnyINT;
  //UInt_t kTriggerEMC   = AliVEvent::kEMC8 || AliVEvent::kEMC7 || AliVEvent::kEMCEJE || AliVEvent::kEMCEGA;

  AliAnalysisTaskEMCALTimeCalib *taskmbemcal = new AliAnalysisTaskEMCALTimeCalib("TimeCalibTask");
  //  AliEMCALRecoUtils *reco = taskmbemcal->GetEMCALRecoUtils();
  //  taskmbemcal->PrintInfo();
  //  reco->SwitchOnRejectExoticCluster();

  taskmbemcal->SelectCollisionCandidates(AliVEvent::kEMC1|AliVEvent::kEMC7|AliVEvent::kEMC8|AliVEvent::kEMCEJE|AliVEvent::kEMCEGA);
  taskmbemcal->SetGeometryName("EMCAL_COMPLETE12SMV1_DCAL_8SM");

  //taskmbemcal->SelectCollisionCandidates(AliVEvent::kAnyINT);
  //taskmbemcal->SetDebugLevel(10);

  // Add task(s)
  // taskmbemcal->PrintInfo();
  if(isPhysicsSelection) mgr->AddTask(physselTask);
  if(isCentralitySelection) mgr->AddTask(centralityTask);
  mgr->AddTask(taskmbemcal);

  TString outputFileName;
  if(type==0)outputFileName="timeOutput.root";
  else if(type==1)outputFileName="timeResults.root";

  // Create containers for input/output
  AliAnalysisDataContainer *cinput = mgr->GetCommonInputContainer();
  AliAnalysisDataContainer *coutputList = mgr->CreateContainer("chistolist", TList::Class(),
     AliAnalysisManager::kOutputContainer, outputFileName.Data());

  // Connect input/output
  mgr->ConnectInput(taskmbemcal, 0, cinput);

  // No need to connect to a common AOD output container if the task does not
  // fill AOD info.
  //  mgr->ConnectOutput(task, 0, coutput0);
  mgr->ConnectOutput(taskmbemcal, 1, coutputList);

  // Enable debug printouts
  if(type==0) mgr->SetDebugLevel(12);

  if (!mgr->InitAnalysis()) return;
  mgr->PrintStatus();
  mgr->StartAnalysis("local", chain);

  timer.Stop();
  timer.Print();

}

//______________________________________________________________________________
TChain *CreateChainFromCollection(const char* xmlfile, const char *treeName="esdTree")
{
// Create a chain from an alien collection.
   TAlienCollection * myCollection  = TAlienCollection::Open(xmlfile);

   if (!myCollection) {
      ::Error("CreateChainSingle", "Cannot create an AliEn collection from %s", xmlfile) ;
      return NULL ;
  }

  TChain* chain = new TChain(treeName);
  myCollection->Reset() ;
  while ( myCollection->Next() ) chain->Add(myCollection->GetTURL("")) ;
  chain->ls();
  return chain;
}

// End of macro
<|endoftext|>


<commit_before><commit_msg>Temporarily remove collision on spinner (fix this later)<commit_after><|endoftext|>


<commit_before>#include "Anemometer.h"
#include <Arduino.h>

namespace SkyeTracker
{
	Anemometer::Anemometer(int sensorPin)
	{
		_sensorPin = sensorPin;
	}

	Anemometer::~Anemometer()
	{
	}

	// wind speed in meters per second
	float Anemometer::WindSpeed()
	{
		double reading = analogRead(_sensorPin); //Get a value between 0 and 1023 from the analog pin connected to the anemometer
		if (reading < 1 || reading > ADC_Resolution)
		{
			return 0;
		}
		double sensorVoltage = -0.000000000000016 * pow(reading, 4) + 0.000000000118171 * pow(reading, 3) - 0.000000301211691 * pow(reading, 2) + 0.001109019271794 * reading + 0.034143524634089;
		// Convert voltage value to wind speed using range of max and min voltages and wind speed for the anemometer
		if (sensorVoltage <= AnemometerVoltageMin) {
			return 0; // Check if voltage is below minimum value. If so, set wind speed to zero.
		}
		else {
			return (sensorVoltage - AnemometerVoltageMin)*AnemometerWindSpeedMax / (AnemometerVoltageMax - AnemometerVoltageMin); // For voltages above minimum value, use the linear relationship to calculate wind speed.
		}
	}
}
<commit_msg>improve documentation for anemometer sensorVoltage calculation<commit_after>#include "Anemometer.h"
#include <Arduino.h>

namespace SkyeTracker
{
	Anemometer::Anemometer(int sensorPin)
	{
		_sensorPin = sensorPin;
	}

	Anemometer::~Anemometer()
	{
	}

	// Wind speed in meters per second
	float Anemometer::WindSpeed()
	{
		// Get a value between 0 and 1023 from the analog pin connected to the anemometer
		double reading = analogRead(_sensorPin);
		if (reading < 1 || reading > ADC_Resolution)
		{
			return 0;
		}
		// The constants used in this calculation are taken from
		// https://github.com/G6EJD/ESP32-ADC-Accuracy-Improvement-function
		// and improves the default ADC reading accuracy to within 1%.
		double sensorVoltage = -0.000000000000016 * pow(reading, 4) +
		    0.000000000118171 * pow(reading, 3) - 0.000000301211691 * pow(reading, 2) +
			0.001109019271794 * reading + 0.034143524634089;

		// Convert voltage value to wind speed using range of max and min voltages and wind speed for the anemometer
		if (sensorVoltage <= AnemometerVoltageMin)
		{
			// Check if voltage is below minimum value. If so, set wind speed to zero.
			return 0;
		}
		else
		{
			// For voltages above minimum value, use the linear relationship to calculate wind speed.
			return (sensorVoltage - AnemometerVoltageMin) * AnemometerWindSpeedMax / (AnemometerVoltageMax - AnemometerVoltageMin);
		}
	}
}
<|endoftext|>


<commit_before>#pragma once

#include "trajectory.hpp"

#include <list>
#include <map>

#include "geometry/named_quantities.hpp"
#include "glog/logging.h"

using principia::geometry::Instant;

namespace principia {
namespace physics {

template<typename Frame>
Trajectory<Frame>::Trajectory(Body const& body)
    : body_(body),
      parent_(nullptr) {}

template<typename Frame>
std::map<Instant, Position<Frame>>
Trajectory<Frame>::Positions() const {
  return ApplyToDegreesOfFreedom<Position<Frame>>(
      [](DegreesOfFreedom<Frame> const& s) { return s.position; });
}

template<typename Frame>
std::map<Instant, Velocity<Frame>> Trajectory<Frame>::Velocities() const {
  return ApplyToDegreesOfFreedom<Velocity<Frame>>(
      [](DegreesOfFreedom<Frame> const& s) { return s.velocity; });
}

template<typename Frame>
std::list<Instant> Trajectory<Frame>::Times() const {
  std::list<Instant> result;

  // Our own data points in increasing time order.
  for (const auto it : timeline_) {
    Instant const& time = it.first;
    result.push_back(time);
  }

  // The data points of our ancestors in decreasing time order.
  Trajectory const* ancestor = this;
  while (ancestor->parent_ != nullptr) {
    Timeline::iterator it = *ancestor->fork_;
    do {
      Instant const& time = it->first;
      result.push_front(time);
    } while (it-- !=  // Postdecrement to process begin.
             ancestor->parent_->timeline_.begin());
    ancestor = ancestor->parent_;
  }

  return result;
}

template<typename Frame>
Position<Frame> const& Trajectory<Frame>::last_position() const {
  if (timeline_.empty()) {
    CHECK(fork_ != nullptr) << "Empty trajectory";
    return (*fork_)->second.position;
  } else {
    return timeline_.rbegin()->second.position;
  }
}

template<typename Frame>
Velocity<Frame> const& Trajectory<Frame>::last_velocity() const {
  if (timeline_.empty()) {
    CHECK(fork_ != nullptr) << "Empty trajectory";
    return (*fork_)->second.velocity;
  } else {
    return timeline_.rbegin()->second.velocity;
  }
}

template<typename Frame>
Instant const& Trajectory<Frame>::last_time() const {
  if (timeline_.empty()) {
    CHECK(fork_ != nullptr) << "Empty trajectory";
    return (*fork_)->first;
  } else {
    return timeline_.rbegin()->first;
  }
}

template<typename Frame>
void Trajectory<Frame>::Append(
    Instant const& time,
    DegreesOfFreedom<Frame> const& degrees_of_freedom) {
  auto inserted = timeline_.emplace(time, degrees_of_freedom);
  CHECK(timeline_.end() == ++inserted.first) << "Append out of order";
  CHECK(inserted.second) << "Append at existing time";
}

template<typename Frame>
void Trajectory<Frame>::ForgetAfter(Instant const& time) {
  // Check that |time| is the time of one of our Timeline or the time of fork.
  auto const it = timeline_.find(time);
  if (it == timeline_.end()) {
    CHECK(fork_ != nullptr)
        << "ForgetAfter a nonexistent time for a root trajectory";
    CHECK_EQ((*fork_)->first, time)
        << "ForgetAfter a nonexistent time for a nonroot trajectory";
  }

  // Each of these blocks gets an iterator denoting the first entry with
  // time > |time|.  It then removes that entry and all the entries that follow
  // it.  This preserve any entry with time == |time|.
  {
    const auto it = timeline_.upper_bound(time);
    timeline_.erase(it, timeline_.end());
  }
  {
    const auto it = children_.upper_bound(time);
    children_.erase(it, children_.end());
  }
}

template<typename Frame>
void Trajectory<Frame>::ForgetBefore(Instant const& time) {
  // Check that this is a root.
  CHECK(is_root()) << "ForgetBefore on a nonroot trajectory";
  // Check that |time| is the time of one of our Timeline or the time of fork.
  CHECK(timeline_.find(time) != timeline_.end())
      << "ForgetBefore a nonexistent time";
  {
    auto it = timeline_.upper_bound(time);
    timeline_.erase(timeline_.begin(), it);
  }
  {
    auto it = children_.upper_bound(time);
    children_.erase(children_.begin(), it);
  }
}

template<typename Frame>
Trajectory<Frame>* Trajectory<Frame>::Fork(Instant const& time) {
  auto fork_it = timeline_.find(time);
  CHECK(fork_it != timeline_.end()) << "Fork at nonexistent time";
  std::unique_ptr<Trajectory<Frame>> child(
      new Trajectory(body_, this /*parent*/, fork_it));
  child->timeline_.insert(++fork_it, timeline_.end());
  auto const child_it = children_.emplace(time, std::move(child));
  return child_it->second.get();
}

template<typename Frame>
bool Trajectory<Frame>::is_root() const {
  return parent_ == nullptr;
}

template<typename Frame>
Trajectory<Frame> const* Trajectory<Frame>::root() const {
  Trajectory const* ancestor = this;
  while (ancestor->parent_ != nullptr) {
    ancestor = ancestor->parent_;
  }
  return ancestor;
}

template<typename Frame>
Trajectory<Frame>* Trajectory<Frame>::root() {
  Trajectory* ancestor = this;
  while (ancestor->parent_ != nullptr) {
    ancestor = ancestor->parent_;
  }
  return ancestor;
}

template<typename Frame>
Instant const* Trajectory<Frame>::fork_time() const {
  if (parent_ == nullptr) {
    return nullptr;
  } else {
    return &((*fork_)->first);
  }
}

template<typename Frame>
Body const& Trajectory<Frame>::body() const {
  return body_;
}

template<typename Frame>
void Trajectory<Frame>::set_intrinsic_acceleration(
    IntrinsicAcceleration&& acceleration) {
  CHECK(body_.is_massless()) << "Trajectory is for a massive body";
  CHECK(intrinsic_acceleration_ == nullptr)
      << "Trajectory already has an intrinsic acceleration";
  intrinsic_acceleration_.reset(new IntrinsicAcceleration(acceleration));
}

template<typename Frame>
void Trajectory<Frame>::clear_intrinsic_acceleration() {
  intrinsic_acceleration_.reset();
}

template<typename Frame>
bool Trajectory<Frame>::has_intrinsic_acceleration() const {
  return intrinsic_acceleration_ != nullptr;
}

template<typename Frame>
Vector<Acceleration, Frame> Trajectory<Frame>::evaluate_intrinsic_acceleration(
    Instant const& time) const {
  if (intrinsic_acceleration_ != nullptr &&
      (fork_ == nullptr || time > (*fork_)->first)) {
    return (*intrinsic_acceleration_)(time);
  } else {
    return Vector<Acceleration, Frame>({0 * SIUnit<Acceleration>(),
                                        0 * SIUnit<Acceleration>(),
                                        0 * SIUnit<Acceleration>()});
  }
}

template<typename Frame>
Trajectory<Frame>::Trajectory(Body const& body,
                              Trajectory* const parent,
                              typename Timeline::iterator const& fork)
    : body_(body),
#ifdef _MANAGED
      parent_(parent),
#else
      parent_(CHECK_NOTNULL(parent)),
#endif
      fork_(new Timeline::iterator(fork)) {}

template<typename Frame>
template<typename Value>
std::map<Instant, Value> Trajectory<Frame>::ApplyToDegreesOfFreedom(
    std::function<Value(DegreesOfFreedom<Frame> const&)> compute_value) const {
  std::map<Instant, Value> result;

  // Our own data points in increasing time order.
  for (const auto it : timeline_) {
    Instant const& time = it.first;
    DegreesOfFreedom<Frame> const& degrees_of_freedom = it.second;
    result.insert(result.end(),
                  std::make_pair(time, compute_value(degrees_of_freedom)));
  }

  // The data points of our ancestors in decreasing time order.
  Trajectory const* ancestor = this;
  while (ancestor->parent_ != nullptr) {
    Timeline::iterator it = *ancestor->fork_;
    do {
      Instant const& time = it->first;
      DegreesOfFreedom<Frame> const& degrees_of_freedom = it->second;
      result.insert(result.begin(),
                    std::make_pair(time, compute_value(degrees_of_freedom)));
    } while (it-- !=  // Postdecrement to process begin.
             ancestor->parent_->timeline_.begin());
    ancestor = ancestor->parent_;
  }

  return result;
}

}  // namespace physics
}  // namespace principia
<commit_msg>No managed code left<commit_after>#pragma once

#include "trajectory.hpp"

#include <list>
#include <map>

#include "geometry/named_quantities.hpp"
#include "glog/logging.h"

using principia::geometry::Instant;

namespace principia {
namespace physics {

template<typename Frame>
Trajectory<Frame>::Trajectory(Body const& body)
    : body_(body),
      parent_(nullptr) {}

template<typename Frame>
std::map<Instant, Position<Frame>>
Trajectory<Frame>::Positions() const {
  return ApplyToDegreesOfFreedom<Position<Frame>>(
      [](DegreesOfFreedom<Frame> const& s) { return s.position; });
}

template<typename Frame>
std::map<Instant, Velocity<Frame>> Trajectory<Frame>::Velocities() const {
  return ApplyToDegreesOfFreedom<Velocity<Frame>>(
      [](DegreesOfFreedom<Frame> const& s) { return s.velocity; });
}

template<typename Frame>
std::list<Instant> Trajectory<Frame>::Times() const {
  std::list<Instant> result;

  // Our own data points in increasing time order.
  for (const auto it : timeline_) {
    Instant const& time = it.first;
    result.push_back(time);
  }

  // The data points of our ancestors in decreasing time order.
  Trajectory const* ancestor = this;
  while (ancestor->parent_ != nullptr) {
    Timeline::iterator it = *ancestor->fork_;
    do {
      Instant const& time = it->first;
      result.push_front(time);
    } while (it-- !=  // Postdecrement to process begin.
             ancestor->parent_->timeline_.begin());
    ancestor = ancestor->parent_;
  }

  return result;
}

template<typename Frame>
Position<Frame> const& Trajectory<Frame>::last_position() const {
  if (timeline_.empty()) {
    CHECK(fork_ != nullptr) << "Empty trajectory";
    return (*fork_)->second.position;
  } else {
    return timeline_.rbegin()->second.position;
  }
}

template<typename Frame>
Velocity<Frame> const& Trajectory<Frame>::last_velocity() const {
  if (timeline_.empty()) {
    CHECK(fork_ != nullptr) << "Empty trajectory";
    return (*fork_)->second.velocity;
  } else {
    return timeline_.rbegin()->second.velocity;
  }
}

template<typename Frame>
Instant const& Trajectory<Frame>::last_time() const {
  if (timeline_.empty()) {
    CHECK(fork_ != nullptr) << "Empty trajectory";
    return (*fork_)->first;
  } else {
    return timeline_.rbegin()->first;
  }
}

template<typename Frame>
void Trajectory<Frame>::Append(
    Instant const& time,
    DegreesOfFreedom<Frame> const& degrees_of_freedom) {
  auto inserted = timeline_.emplace(time, degrees_of_freedom);
  CHECK(timeline_.end() == ++inserted.first) << "Append out of order";
  CHECK(inserted.second) << "Append at existing time";
}

template<typename Frame>
void Trajectory<Frame>::ForgetAfter(Instant const& time) {
  // Check that |time| is the time of one of our Timeline or the time of fork.
  auto const it = timeline_.find(time);
  if (it == timeline_.end()) {
    CHECK(fork_ != nullptr)
        << "ForgetAfter a nonexistent time for a root trajectory";
    CHECK_EQ((*fork_)->first, time)
        << "ForgetAfter a nonexistent time for a nonroot trajectory";
  }

  // Each of these blocks gets an iterator denoting the first entry with
  // time > |time|.  It then removes that entry and all the entries that follow
  // it.  This preserve any entry with time == |time|.
  {
    const auto it = timeline_.upper_bound(time);
    timeline_.erase(it, timeline_.end());
  }
  {
    const auto it = children_.upper_bound(time);
    children_.erase(it, children_.end());
  }
}

template<typename Frame>
void Trajectory<Frame>::ForgetBefore(Instant const& time) {
  // Check that this is a root.
  CHECK(is_root()) << "ForgetBefore on a nonroot trajectory";
  // Check that |time| is the time of one of our Timeline or the time of fork.
  CHECK(timeline_.find(time) != timeline_.end())
      << "ForgetBefore a nonexistent time";
  {
    auto it = timeline_.upper_bound(time);
    timeline_.erase(timeline_.begin(), it);
  }
  {
    auto it = children_.upper_bound(time);
    children_.erase(children_.begin(), it);
  }
}

template<typename Frame>
Trajectory<Frame>* Trajectory<Frame>::Fork(Instant const& time) {
  auto fork_it = timeline_.find(time);
  CHECK(fork_it != timeline_.end()) << "Fork at nonexistent time";
  std::unique_ptr<Trajectory<Frame>> child(
      new Trajectory(body_, this /*parent*/, fork_it));
  child->timeline_.insert(++fork_it, timeline_.end());
  auto const child_it = children_.emplace(time, std::move(child));
  return child_it->second.get();
}

template<typename Frame>
bool Trajectory<Frame>::is_root() const {
  return parent_ == nullptr;
}

template<typename Frame>
Trajectory<Frame> const* Trajectory<Frame>::root() const {
  Trajectory const* ancestor = this;
  while (ancestor->parent_ != nullptr) {
    ancestor = ancestor->parent_;
  }
  return ancestor;
}

template<typename Frame>
Trajectory<Frame>* Trajectory<Frame>::root() {
  Trajectory* ancestor = this;
  while (ancestor->parent_ != nullptr) {
    ancestor = ancestor->parent_;
  }
  return ancestor;
}

template<typename Frame>
Instant const* Trajectory<Frame>::fork_time() const {
  if (parent_ == nullptr) {
    return nullptr;
  } else {
    return &((*fork_)->first);
  }
}

template<typename Frame>
Body const& Trajectory<Frame>::body() const {
  return body_;
}

template<typename Frame>
void Trajectory<Frame>::set_intrinsic_acceleration(
    IntrinsicAcceleration&& acceleration) {
  CHECK(body_.is_massless()) << "Trajectory is for a massive body";
  CHECK(intrinsic_acceleration_ == nullptr)
      << "Trajectory already has an intrinsic acceleration";
  intrinsic_acceleration_.reset(new IntrinsicAcceleration(acceleration));
}

template<typename Frame>
void Trajectory<Frame>::clear_intrinsic_acceleration() {
  intrinsic_acceleration_.reset();
}

template<typename Frame>
bool Trajectory<Frame>::has_intrinsic_acceleration() const {
  return intrinsic_acceleration_ != nullptr;
}

template<typename Frame>
Vector<Acceleration, Frame> Trajectory<Frame>::evaluate_intrinsic_acceleration(
    Instant const& time) const {
  if (intrinsic_acceleration_ != nullptr &&
      (fork_ == nullptr || time > (*fork_)->first)) {
    return (*intrinsic_acceleration_)(time);
  } else {
    return Vector<Acceleration, Frame>({0 * SIUnit<Acceleration>(),
                                        0 * SIUnit<Acceleration>(),
                                        0 * SIUnit<Acceleration>()});
  }
}

template<typename Frame>
Trajectory<Frame>::Trajectory(Body const& body,
                              Trajectory* const parent,
                              typename Timeline::iterator const& fork)
    : body_(body),
      parent_(CHECK_NOTNULL(parent)),
      fork_(new Timeline::iterator(fork)) {}

template<typename Frame>
template<typename Value>
std::map<Instant, Value> Trajectory<Frame>::ApplyToDegreesOfFreedom(
    std::function<Value(DegreesOfFreedom<Frame> const&)> compute_value) const {
  std::map<Instant, Value> result;

  // Our own data points in increasing time order.
  for (const auto it : timeline_) {
    Instant const& time = it.first;
    DegreesOfFreedom<Frame> const& degrees_of_freedom = it.second;
    result.insert(result.end(),
                  std::make_pair(time, compute_value(degrees_of_freedom)));
  }

  // The data points of our ancestors in decreasing time order.
  Trajectory const* ancestor = this;
  while (ancestor->parent_ != nullptr) {
    Timeline::iterator it = *ancestor->fork_;
    do {
      Instant const& time = it->first;
      DegreesOfFreedom<Frame> const& degrees_of_freedom = it->second;
      result.insert(result.begin(),
                    std::make_pair(time, compute_value(degrees_of_freedom)));
    } while (it-- !=  // Postdecrement to process begin.
             ancestor->parent_->timeline_.begin());
    ancestor = ancestor->parent_;
  }

  return result;
}

}  // namespace physics
}  // namespace principia
<|endoftext|>


<commit_before>// Copyright 2016 Proyectos y Sistemas de Mantenimiento SL (eProsima).
//
// 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 <fastrtps/transport/UDPv4Transport.h>
#include <gtest/gtest.h>
#include <boost/thread.hpp>
#include <fastrtps/utils/IPFinder.h>
#include <memory>

using namespace std;
using namespace eprosima::fastrtps;
using namespace eprosima::fastrtps::rtps;
using namespace boost::interprocess;

const uint32_t ReceiveBufferCapacity = 65536;

class UDPv4Tests: public ::testing::Test
{
   public:
   UDPv4Tests()
   {
      HELPER_SetDescriptorDefaults();
   }

   void HELPER_SetDescriptorDefaults();

   UDPv4TransportDescriptor descriptor;
   unique_ptr<boost::thread> senderThread;
   unique_ptr<boost::thread> receiverThread;
};

TEST_F(UDPv4Tests, locators_with_kind_1_supported)
{
   // Given
   UDPv4Transport transportUnderTest(descriptor);

   Locator_t supportedLocator;
   supportedLocator.kind = LOCATOR_KIND_UDPv4;
   Locator_t unsupportedLocator;
   unsupportedLocator.kind = LOCATOR_KIND_UDPv6;

   // Then
   ASSERT_TRUE(transportUnderTest.IsLocatorSupported(supportedLocator));
   ASSERT_FALSE(transportUnderTest.IsLocatorSupported(unsupportedLocator));
}

TEST_F(UDPv4Tests, opening_and_closing_output_channel)
{
   // Given
   UDPv4Transport transportUnderTest(descriptor);
   Locator_t genericOutputChannelLocator;
   genericOutputChannelLocator.kind = LOCATOR_KIND_UDPv4;
   genericOutputChannelLocator.port = 7400; // arbitrary

   // Then
   ASSERT_FALSE (transportUnderTest.IsOutputChannelOpen(genericOutputChannelLocator));
   ASSERT_TRUE  (transportUnderTest.OpenOutputChannel(genericOutputChannelLocator));
   ASSERT_TRUE  (transportUnderTest.IsOutputChannelOpen(genericOutputChannelLocator));
   ASSERT_TRUE  (transportUnderTest.CloseOutputChannel(genericOutputChannelLocator));
   ASSERT_FALSE (transportUnderTest.IsOutputChannelOpen(genericOutputChannelLocator));
   ASSERT_FALSE (transportUnderTest.CloseOutputChannel(genericOutputChannelLocator));
}

TEST_F(UDPv4Tests, opening_and_closing_input_channel)
{
   // Given
   UDPv4Transport transportUnderTest(descriptor);
   Locator_t multicastFilterLocator;
   multicastFilterLocator.kind = LOCATOR_KIND_UDPv4;
   multicastFilterLocator.port = 7410; // arbitrary
   multicastFilterLocator.set_IP4_address(239, 255, 0, 1);

   // Then
   ASSERT_FALSE (transportUnderTest.IsInputChannelOpen(multicastFilterLocator));
   ASSERT_TRUE  (transportUnderTest.OpenInputChannel(multicastFilterLocator));
   ASSERT_TRUE  (transportUnderTest.IsInputChannelOpen(multicastFilterLocator));
   ASSERT_TRUE  (transportUnderTest.CloseInputChannel(multicastFilterLocator));
   ASSERT_FALSE (transportUnderTest.IsInputChannelOpen(multicastFilterLocator));
   ASSERT_FALSE (transportUnderTest.CloseInputChannel(multicastFilterLocator));
}

TEST_F(UDPv4Tests, send_and_receive_between_ports)
{
   UDPv4Transport transportUnderTest(descriptor);

   Locator_t multicastLocator;
   multicastLocator.port = 7410;
   multicastLocator.kind = LOCATOR_KIND_UDPv4;
   multicastLocator.set_IP4_address(239, 255, 0, 1);

   Locator_t outputChannelLocator;
   outputChannelLocator.port = 7400;
   outputChannelLocator.kind = LOCATOR_KIND_UDPv4;
   ASSERT_TRUE(transportUnderTest.OpenOutputChannel(outputChannelLocator)); // Includes loopback
   ASSERT_TRUE(transportUnderTest.OpenInputChannel(multicastLocator));
   octet message[5] = { 'H','e','l','l','o' };

   auto sendThreadFunction = [&]()
   {
      EXPECT_TRUE(transportUnderTest.Send(message, 5, outputChannelLocator, multicastLocator));
   };

   auto receiveThreadFunction = [&]()
   {
      octet receiveBuffer[ReceiveBufferCapacity];
      uint32_t receiveBufferSize;

      Locator_t remoteLocatorToReceive;
      EXPECT_TRUE(transportUnderTest.Receive(receiveBuffer, ReceiveBufferCapacity, receiveBufferSize, multicastLocator, remoteLocatorToReceive));
      EXPECT_EQ(memcmp(message,receiveBuffer,5), 0);
   };

   receiverThread.reset(new boost::thread(receiveThreadFunction));
   senderThread.reset(new boost::thread(sendThreadFunction));
   senderThread->join();
   receiverThread->join();
}

TEST_F(UDPv4Tests, send_to_loopback)
{
   UDPv4Transport transportUnderTest(descriptor);

   Locator_t multicastLocator;
   multicastLocator.port = 7410;
   multicastLocator.kind = LOCATOR_KIND_UDPv4;
   multicastLocator.set_IP4_address(239, 255, 0, 1);

   Locator_t outputChannelLocator;
   outputChannelLocator.port = 7400;
   outputChannelLocator.kind = LOCATOR_KIND_UDPv4;
   outputChannelLocator.set_IP4_address(127,0,0,1); // Loopback
   ASSERT_TRUE(transportUnderTest.OpenOutputChannel(outputChannelLocator));
   ASSERT_TRUE(transportUnderTest.OpenInputChannel(multicastLocator));
   octet message[5] = { 'H','e','l','l','o' };

   auto sendThreadFunction = [&]()
   {
      Locator_t destinationLocator;
      destinationLocator.port = 7410;
      destinationLocator.kind = LOCATOR_KIND_UDPv4;
      EXPECT_TRUE(transportUnderTest.Send(message, 5, outputChannelLocator, multicastLocator));
   };

   auto receiveThreadFunction = [&]()
   {
      octet receiveBuffer[ReceiveBufferCapacity];
      uint32_t receiveBufferSize;

      Locator_t remoteLocatorToReceive;
      EXPECT_TRUE(transportUnderTest.Receive(receiveBuffer, ReceiveBufferCapacity, receiveBufferSize, multicastLocator, remoteLocatorToReceive));
      EXPECT_EQ(memcmp(message,receiveBuffer,5), 0);
   };

   receiverThread.reset(new boost::thread(receiveThreadFunction));
   senderThread.reset(new boost::thread(sendThreadFunction));
   senderThread->join();
   receiverThread->join();
}

TEST_F(UDPv4Tests, send_is_rejected_if_buffer_size_is_bigger_to_size_specified_in_descriptor)
{
   // Given
   UDPv4Transport transportUnderTest(descriptor);
   Locator_t genericOutputChannelLocator;
   genericOutputChannelLocator.kind = LOCATOR_KIND_UDPv4;
   genericOutputChannelLocator.port = 7400;
   transportUnderTest.OpenOutputChannel(genericOutputChannelLocator);

   Locator_t destinationLocator;
   destinationLocator.kind = LOCATOR_KIND_UDPv4;
   destinationLocator.port = 7410;

   // Then
   vector<octet> receiveBufferWrongSize(descriptor.sendBufferSize + 1);
   ASSERT_FALSE(transportUnderTest.Send(receiveBufferWrongSize.data(), (uint32_t)receiveBufferWrongSize.size(), genericOutputChannelLocator, destinationLocator));
}

TEST_F(UDPv4Tests, Receive_is_rejected_if_buffer_size_is_smaller_than_size_specified_in_descriptor)
{
   // Given
   UDPv4Transport transportUnderTest(descriptor);
   Locator_t genericInputChannelLocator;
   genericInputChannelLocator.kind = LOCATOR_KIND_UDPv4;
   genericInputChannelLocator.port = 7410;
   transportUnderTest.OpenInputChannel(genericInputChannelLocator);

   Locator_t originLocator;
   octet* emptyBuffer = nullptr;
   uint32_t size;
   // Then
   ASSERT_FALSE(transportUnderTest.Receive(emptyBuffer,0, size, genericInputChannelLocator, originLocator));
}

TEST_F(UDPv4Tests, opening_any_output_address_opens_port_for_all_IP_addresses)
{
   // Given
   UDPv4Transport transportUnderTest(descriptor);

   Locator_t specificOutputChannelLocator;
   specificOutputChannelLocator.kind = LOCATOR_KIND_UDPv4;
   specificOutputChannelLocator.port = 7410;
   specificOutputChannelLocator.set_IP4_address(222,222,222,222);

   Locator_t differentOutputChannelLocator;
   differentOutputChannelLocator.kind = LOCATOR_KIND_UDPv4;
   differentOutputChannelLocator.port = 7410;
   differentOutputChannelLocator.set_IP4_address(111,111,111,111);

   // When
   ASSERT_TRUE(transportUnderTest.OpenOutputChannel(specificOutputChannelLocator));

   // Then
   ASSERT_TRUE(transportUnderTest.IsOutputChannelOpen(differentOutputChannelLocator));
}

TEST_F(UDPv4Tests, RemoteToMainLocal_simply_strips_out_address_leaving_IP_ANY)
{
   // Given
   UDPv4Transport transportUnderTest(descriptor);

   Locator_t remoteLocator;
   remoteLocator.kind = LOCATOR_KIND_UDPv4;
   remoteLocator.port = 7410;
   remoteLocator.set_IP4_address(222,222,222,222);

   // When
   Locator_t mainLocalLocator = transportUnderTest.RemoteToMainLocal(remoteLocator);

   ASSERT_EQ(mainLocalLocator.port, remoteLocator.port);
   ASSERT_EQ(mainLocalLocator.kind, remoteLocator.kind);

   ASSERT_EQ(mainLocalLocator.to_IP4_string(), "0.0.0.0");
}

TEST_F(UDPv4Tests, in_granular_mode_locators_match_if_port_AND_address_matches)
{
   // Given
   descriptor.granularMode = true;
   UDPv4Transport transportUnderTest(descriptor);
   Locator_t locatorAlpha;
   locatorAlpha.port = 50000;
   locatorAlpha.set_IP4_address(239, 255, 0, 1);
   Locator_t locatorBeta = locatorAlpha;

   // Then
   ASSERT_TRUE(transportUnderTest.DoLocatorsMatch(locatorAlpha, locatorBeta));

   locatorBeta.set_IP4_address(100, 100, 100, 100);
   // Then
   ASSERT_FALSE(transportUnderTest.DoLocatorsMatch(locatorAlpha, locatorBeta));
}

TEST_F(UDPv4Tests, granular_send_to_wrong_interface)
{
   descriptor.granularMode = true;
   UDPv4Transport transportUnderTest(descriptor);

   Locator_t outputChannelLocator;
   outputChannelLocator.port = 7400;
   outputChannelLocator.kind = LOCATOR_KIND_UDPv4;
   outputChannelLocator.set_IP4_address(127,0,0,1); // Loopback
   ASSERT_TRUE(transportUnderTest.OpenOutputChannel(outputChannelLocator));

   //Sending through a different IP will NOT work in granular mode, except 0.0.0.0
   outputChannelLocator.set_IP4_address(111,111,111,111);
   vector<octet> message = { 'H','e','l','l','o' };
   ASSERT_FALSE(transportUnderTest.Send(message.data(), (uint32_t)message.size(), outputChannelLocator, Locator_t()));
}

void UDPv4Tests::HELPER_SetDescriptorDefaults()
{
   descriptor.sendBufferSize = 5;
   descriptor.receiveBufferSize = 5;
   descriptor.granularMode = false;
}

int main(int argc, char **argv)
{
    testing::InitGoogleTest(&argc, argv);
    return RUN_ALL_TESTS();
}
<commit_msg>Refs #1725. Fixes #50<commit_after>// Copyright 2016 Proyectos y Sistemas de Mantenimiento SL (eProsima).
//
// 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 <fastrtps/transport/UDPv4Transport.h>
#include <gtest/gtest.h>
#include <boost/thread.hpp>
#include <fastrtps/utils/IPFinder.h>
#include <memory>

using namespace std;
using namespace eprosima::fastrtps;
using namespace eprosima::fastrtps::rtps;
using namespace boost::interprocess;

const uint32_t ReceiveBufferCapacity = 65536;

class UDPv4Tests: public ::testing::Test
{
   public:
   UDPv4Tests()
   {
      HELPER_SetDescriptorDefaults();
   }

   void HELPER_SetDescriptorDefaults();

   UDPv4TransportDescriptor descriptor;
   unique_ptr<boost::thread> senderThread;
   unique_ptr<boost::thread> receiverThread;
};

TEST_F(UDPv4Tests, locators_with_kind_1_supported)
{
   // Given
   UDPv4Transport transportUnderTest(descriptor);

   Locator_t supportedLocator;
   supportedLocator.kind = LOCATOR_KIND_UDPv4;
   Locator_t unsupportedLocator;
   unsupportedLocator.kind = LOCATOR_KIND_UDPv6;

   // Then
   ASSERT_TRUE(transportUnderTest.IsLocatorSupported(supportedLocator));
   ASSERT_FALSE(transportUnderTest.IsLocatorSupported(unsupportedLocator));
}

TEST_F(UDPv4Tests, opening_and_closing_output_channel)
{
   // Given
   UDPv4Transport transportUnderTest(descriptor);
   Locator_t genericOutputChannelLocator;
   genericOutputChannelLocator.kind = LOCATOR_KIND_UDPv4;
   genericOutputChannelLocator.port = 7400; // arbitrary

   // Then
   ASSERT_FALSE (transportUnderTest.IsOutputChannelOpen(genericOutputChannelLocator));
   ASSERT_TRUE  (transportUnderTest.OpenOutputChannel(genericOutputChannelLocator));
   ASSERT_TRUE  (transportUnderTest.IsOutputChannelOpen(genericOutputChannelLocator));
   ASSERT_TRUE  (transportUnderTest.CloseOutputChannel(genericOutputChannelLocator));
   ASSERT_FALSE (transportUnderTest.IsOutputChannelOpen(genericOutputChannelLocator));
   ASSERT_FALSE (transportUnderTest.CloseOutputChannel(genericOutputChannelLocator));
}

TEST_F(UDPv4Tests, opening_and_closing_input_channel)
{
   // Given
   UDPv4Transport transportUnderTest(descriptor);
   Locator_t multicastFilterLocator;
   multicastFilterLocator.kind = LOCATOR_KIND_UDPv4;
   multicastFilterLocator.port = 7410; // arbitrary
   multicastFilterLocator.set_IP4_address(239, 255, 0, 1);

   // Then
   ASSERT_FALSE (transportUnderTest.IsInputChannelOpen(multicastFilterLocator));
   ASSERT_TRUE  (transportUnderTest.OpenInputChannel(multicastFilterLocator));
   ASSERT_TRUE  (transportUnderTest.IsInputChannelOpen(multicastFilterLocator));
   ASSERT_TRUE  (transportUnderTest.CloseInputChannel(multicastFilterLocator));
   ASSERT_FALSE (transportUnderTest.IsInputChannelOpen(multicastFilterLocator));
   ASSERT_FALSE (transportUnderTest.CloseInputChannel(multicastFilterLocator));
}

#ifndef __APPLE__
TEST_F(UDPv4Tests, send_and_receive_between_ports)
{
   UDPv4Transport transportUnderTest(descriptor);

   Locator_t multicastLocator;
   multicastLocator.port = 7410;
   multicastLocator.kind = LOCATOR_KIND_UDPv4;
   multicastLocator.set_IP4_address(239, 255, 0, 1);

   Locator_t outputChannelLocator;
   outputChannelLocator.port = 7400;
   outputChannelLocator.kind = LOCATOR_KIND_UDPv4;
   ASSERT_TRUE(transportUnderTest.OpenOutputChannel(outputChannelLocator)); // Includes loopback
   ASSERT_TRUE(transportUnderTest.OpenInputChannel(multicastLocator));
   octet message[5] = { 'H','e','l','l','o' };

   auto sendThreadFunction = [&]()
   {
      EXPECT_TRUE(transportUnderTest.Send(message, 5, outputChannelLocator, multicastLocator));
   };

   auto receiveThreadFunction = [&]()
   {
      octet receiveBuffer[ReceiveBufferCapacity];
      uint32_t receiveBufferSize;

      Locator_t remoteLocatorToReceive;
      EXPECT_TRUE(transportUnderTest.Receive(receiveBuffer, ReceiveBufferCapacity, receiveBufferSize, multicastLocator, remoteLocatorToReceive));
      EXPECT_EQ(memcmp(message,receiveBuffer,5), 0);
   };

   receiverThread.reset(new boost::thread(receiveThreadFunction));
   senderThread.reset(new boost::thread(sendThreadFunction));
   senderThread->join();
   receiverThread->join();
}

TEST_F(UDPv4Tests, send_to_loopback)
{
   UDPv4Transport transportUnderTest(descriptor);

   Locator_t multicastLocator;
   multicastLocator.port = 7410;
   multicastLocator.kind = LOCATOR_KIND_UDPv4;
   multicastLocator.set_IP4_address(239, 255, 0, 1);

   Locator_t outputChannelLocator;
   outputChannelLocator.port = 7400;
   outputChannelLocator.kind = LOCATOR_KIND_UDPv4;
   outputChannelLocator.set_IP4_address(127,0,0,1); // Loopback
   ASSERT_TRUE(transportUnderTest.OpenOutputChannel(outputChannelLocator));
   ASSERT_TRUE(transportUnderTest.OpenInputChannel(multicastLocator));
   octet message[5] = { 'H','e','l','l','o' };

   auto sendThreadFunction = [&]()
   {
      Locator_t destinationLocator;
      destinationLocator.port = 7410;
      destinationLocator.kind = LOCATOR_KIND_UDPv4;
      EXPECT_TRUE(transportUnderTest.Send(message, 5, outputChannelLocator, multicastLocator));
   };

   auto receiveThreadFunction = [&]()
   {
      octet receiveBuffer[ReceiveBufferCapacity];
      uint32_t receiveBufferSize;

      Locator_t remoteLocatorToReceive;
      EXPECT_TRUE(transportUnderTest.Receive(receiveBuffer, ReceiveBufferCapacity, receiveBufferSize, multicastLocator, remoteLocatorToReceive));
      EXPECT_EQ(memcmp(message,receiveBuffer,5), 0);
   };

   receiverThread.reset(new boost::thread(receiveThreadFunction));
   senderThread.reset(new boost::thread(sendThreadFunction));
   senderThread->join();
   receiverThread->join();
}
#endif

TEST_F(UDPv4Tests, send_is_rejected_if_buffer_size_is_bigger_to_size_specified_in_descriptor)
{
   // Given
   UDPv4Transport transportUnderTest(descriptor);
   Locator_t genericOutputChannelLocator;
   genericOutputChannelLocator.kind = LOCATOR_KIND_UDPv4;
   genericOutputChannelLocator.port = 7400;
   transportUnderTest.OpenOutputChannel(genericOutputChannelLocator);

   Locator_t destinationLocator;
   destinationLocator.kind = LOCATOR_KIND_UDPv4;
   destinationLocator.port = 7410;

   // Then
   vector<octet> receiveBufferWrongSize(descriptor.sendBufferSize + 1);
   ASSERT_FALSE(transportUnderTest.Send(receiveBufferWrongSize.data(), (uint32_t)receiveBufferWrongSize.size(), genericOutputChannelLocator, destinationLocator));
}

TEST_F(UDPv4Tests, Receive_is_rejected_if_buffer_size_is_smaller_than_size_specified_in_descriptor)
{
   // Given
   UDPv4Transport transportUnderTest(descriptor);
   Locator_t genericInputChannelLocator;
   genericInputChannelLocator.kind = LOCATOR_KIND_UDPv4;
   genericInputChannelLocator.port = 7410;
   transportUnderTest.OpenInputChannel(genericInputChannelLocator);

   Locator_t originLocator;
   octet* emptyBuffer = nullptr;
   uint32_t size;
   // Then
   ASSERT_FALSE(transportUnderTest.Receive(emptyBuffer,0, size, genericInputChannelLocator, originLocator));
}

TEST_F(UDPv4Tests, opening_any_output_address_opens_port_for_all_IP_addresses)
{
   // Given
   UDPv4Transport transportUnderTest(descriptor);

   Locator_t specificOutputChannelLocator;
   specificOutputChannelLocator.kind = LOCATOR_KIND_UDPv4;
   specificOutputChannelLocator.port = 7410;
   specificOutputChannelLocator.set_IP4_address(222,222,222,222);

   Locator_t differentOutputChannelLocator;
   differentOutputChannelLocator.kind = LOCATOR_KIND_UDPv4;
   differentOutputChannelLocator.port = 7410;
   differentOutputChannelLocator.set_IP4_address(111,111,111,111);

   // When
   ASSERT_TRUE(transportUnderTest.OpenOutputChannel(specificOutputChannelLocator));

   // Then
   ASSERT_TRUE(transportUnderTest.IsOutputChannelOpen(differentOutputChannelLocator));
}

TEST_F(UDPv4Tests, RemoteToMainLocal_simply_strips_out_address_leaving_IP_ANY)
{
   // Given
   UDPv4Transport transportUnderTest(descriptor);

   Locator_t remoteLocator;
   remoteLocator.kind = LOCATOR_KIND_UDPv4;
   remoteLocator.port = 7410;
   remoteLocator.set_IP4_address(222,222,222,222);

   // When
   Locator_t mainLocalLocator = transportUnderTest.RemoteToMainLocal(remoteLocator);

   ASSERT_EQ(mainLocalLocator.port, remoteLocator.port);
   ASSERT_EQ(mainLocalLocator.kind, remoteLocator.kind);

   ASSERT_EQ(mainLocalLocator.to_IP4_string(), "0.0.0.0");
}

TEST_F(UDPv4Tests, in_granular_mode_locators_match_if_port_AND_address_matches)
{
   // Given
   descriptor.granularMode = true;
   UDPv4Transport transportUnderTest(descriptor);
   Locator_t locatorAlpha;
   locatorAlpha.port = 50000;
   locatorAlpha.set_IP4_address(239, 255, 0, 1);
   Locator_t locatorBeta = locatorAlpha;

   // Then
   ASSERT_TRUE(transportUnderTest.DoLocatorsMatch(locatorAlpha, locatorBeta));

   locatorBeta.set_IP4_address(100, 100, 100, 100);
   // Then
   ASSERT_FALSE(transportUnderTest.DoLocatorsMatch(locatorAlpha, locatorBeta));
}

TEST_F(UDPv4Tests, granular_send_to_wrong_interface)
{
   descriptor.granularMode = true;
   UDPv4Transport transportUnderTest(descriptor);

   Locator_t outputChannelLocator;
   outputChannelLocator.port = 7400;
   outputChannelLocator.kind = LOCATOR_KIND_UDPv4;
   outputChannelLocator.set_IP4_address(127,0,0,1); // Loopback
   ASSERT_TRUE(transportUnderTest.OpenOutputChannel(outputChannelLocator));

   //Sending through a different IP will NOT work in granular mode, except 0.0.0.0
   outputChannelLocator.set_IP4_address(111,111,111,111);
   vector<octet> message = { 'H','e','l','l','o' };
   ASSERT_FALSE(transportUnderTest.Send(message.data(), (uint32_t)message.size(), outputChannelLocator, Locator_t()));
}

void UDPv4Tests::HELPER_SetDescriptorDefaults()
{
   descriptor.sendBufferSize = 5;
   descriptor.receiveBufferSize = 5;
   descriptor.granularMode = false;
}

int main(int argc, char **argv)
{
    testing::InitGoogleTest(&argc, argv);
    return RUN_ALL_TESTS();
}
<|endoftext|>


<commit_before>#include "lite/handle_syscalls.h"
#include "simulator.h"
#include "thread_manager.h"
#include "thread.h"
#include "syscall_model.h"
#include "performance_model.h"
#include "log.h"
#include "syscall_strings.h"
#include "local_storage.h"

#include <syscall.h>
#include <stdlib.h>

namespace lite
{

void handleSyscall(THREADID threadIndex, CONTEXT* ctx)
{
   // We shouldn't block on actual SYS_futex calls while inside the SyscallEntry function
   // Therefore, do all the work here, which is at INS_InsertCall(syscall, IPOINT_BEFORE)

   IntPtr syscall_number = PIN_GetContextReg (ctx, REG_GAX);
   LOG_PRINT("Syscall Number(%d)", syscall_number);
   //printf("Entering syscall %s(%ld)\n", syscall_string(syscall_number), syscall_number);

   SyscallMdl::syscall_args_t args;

#ifdef TARGET_IA32
   args.arg0 = PIN_GetContextReg (ctx, REG_GBX);
   args.arg1 = PIN_GetContextReg (ctx, REG_GCX);
   args.arg2 = PIN_GetContextReg (ctx, REG_GDX);
   args.arg3 = PIN_GetContextReg (ctx, REG_GSI);
   args.arg4 = PIN_GetContextReg (ctx, REG_GDI);
   args.arg5 = PIN_GetContextReg (ctx, REG_GBP);
#endif

#ifdef TARGET_INTEL64
   // FIXME: The LEVEL_BASE:: ugliness is required by the fact that REG_R8 etc
   // are also defined in /usr/include/sys/ucontext.h
   args.arg0 = PIN_GetContextReg (ctx, LEVEL_BASE::REG_GDI);
   args.arg1 = PIN_GetContextReg (ctx, LEVEL_BASE::REG_GSI);
   args.arg2 = PIN_GetContextReg (ctx, LEVEL_BASE::REG_GDX);
   args.arg3 = PIN_GetContextReg (ctx, LEVEL_BASE::REG_R10);
   args.arg4 = PIN_GetContextReg (ctx, LEVEL_BASE::REG_R8);
   args.arg5 = PIN_GetContextReg (ctx, LEVEL_BASE::REG_R9);
#endif

   if (syscall_number == SYS_clone)
   {
      #if defined(TARGET_IA32)
         localStore[threadIndex].pthread_create.tid_ptr = (void*)args.arg2;
      #elif defined(TARGET_INTEL64)
         localStore[threadIndex].pthread_create.tid_ptr = (void*)args.arg3;
      #endif
      localStore[threadIndex].pthread_create.clear_tid = args.arg0 & CLONE_CHILD_CLEARTID ? true : false;
   }

   Thread* thread = Sim()->getThreadManager()->getCurrentThread(threadIndex);
   LOG_ASSERT_ERROR(thread != NULL, "Thread(NULL)");
   thread->getSyscallMdl()->runEnter(syscall_number, args);
}

void syscallEnterRunModel(THREADID threadIndex, CONTEXT* ctx, SYSCALL_STANDARD syscall_standard, void* v)
{
   Thread* thread = Sim()->getThreadManager()->getCurrentThread(threadIndex);
   LOG_ASSERT_ERROR(thread != NULL, "Thread(NULL)");
   if (thread->getSyscallMdl()->isEmulated())
   {
      PIN_SetSyscallNumber(ctx, syscall_standard, SYS_getpid);
   }
}

void syscallExitRunModel(THREADID threadIndex, CONTEXT* ctx, SYSCALL_STANDARD syscall_standard, void* v)
{
   Thread* thread = Sim()->getThreadManager()->getCurrentThread(threadIndex);
   LOG_ASSERT_ERROR(thread != NULL, "Thread(NULL)");
   IntPtr old_return_val = PIN_GetSyscallReturn(ctx, syscall_standard);

   if (thread->getSyscallMdl()->isEmulated())
   {
      IntPtr syscall_return = thread->getSyscallMdl()->runExit(old_return_val);
      PIN_SetContextReg(ctx, REG_GAX, syscall_return);

      LOG_PRINT("Syscall returned (%p)", syscall_return);
   }
   else
   {
      thread->getSyscallMdl()->runExit(old_return_val);
   }
}

bool interceptSignal(THREADID threadIndex, INT32 signal, CONTEXT *ctx, BOOL hasHandler, const EXCEPTION_INFO *pExceptInfo, void* v)
{
   ADDRINT eip = PIN_GetContextReg(ctx, REG_INST_PTR);
   fprintf(stderr, "Application received fatal signal %u at eip %p\n", signal, (void*)eip);

   INT32 column, line;
   string fileName;
   PIN_GetSourceLocation(eip, &column, &line, &fileName);
   fprintf(stderr, "in %s:%u\n", fileName.c_str(), line);

   switch(PIN_GetDebugStatus())
   {
      case DEBUG_STATUS_CONNECTED:
         // A debugger is already connected, it should just break
         break;
      // TODO: This is supposed to work in a future Pin version. Right now, a fatal signal will kill Pin & the application
      case DEBUG_STATUS_UNCONNECTED:
         // The -appdebug_enable switch was used, but no debugger is currently connected
         // Instruct the user to do this now
         DEBUG_CONNECTION_INFO info;
         if (!PIN_GetDebugConnectionInfo(&info) || info._type != DEBUG_CONNECTION_TYPE_TCP_SERVER)
            break;
         fprintf(stderr, "\nStart GDB and enter this command:\n  target remote :%d\n\n", info._tcpServer._tcpPort);
         PIN_WaitForDebuggerToConnect(0);
         break;
      case DEBUG_STATUS_UNCONNECTABLE:
         // Application debugging is enabled, but it is too early to allow a debugger to connect
         fprintf(stderr, "\nApplication debugging is enabled, but it is too early to allow a debugger to connect.\n\n");
         exit(0);
      case DEBUG_STATUS_DISABLED:
         // No -appdebug* switch given to Pin, nothing we can do
         fprintf(stderr, "\nApplication debugging is currently disabled.\nTo enable it, start Sniper with the --appdebug or --appdebug-wait command line switch.\n\n");
         exit(0);
   }

   return true;
}

}
<commit_msg>[pin] Pin frontend does not support execv (simulator will die), add a warning to use --sift mode which might support it later<commit_after>#include "lite/handle_syscalls.h"
#include "simulator.h"
#include "thread_manager.h"
#include "thread.h"
#include "syscall_model.h"
#include "performance_model.h"
#include "log.h"
#include "syscall_strings.h"
#include "local_storage.h"

#include <syscall.h>
#include <stdlib.h>

namespace lite
{

void handleSyscall(THREADID threadIndex, CONTEXT* ctx)
{
   // We shouldn't block on actual SYS_futex calls while inside the SyscallEntry function
   // Therefore, do all the work here, which is at INS_InsertCall(syscall, IPOINT_BEFORE)

   IntPtr syscall_number = PIN_GetContextReg (ctx, REG_GAX);
   LOG_PRINT("Syscall Number(%d)", syscall_number);
   //printf("Entering syscall %s(%ld)\n", syscall_string(syscall_number), syscall_number);

   SyscallMdl::syscall_args_t args;

#ifdef TARGET_IA32
   args.arg0 = PIN_GetContextReg (ctx, REG_GBX);
   args.arg1 = PIN_GetContextReg (ctx, REG_GCX);
   args.arg2 = PIN_GetContextReg (ctx, REG_GDX);
   args.arg3 = PIN_GetContextReg (ctx, REG_GSI);
   args.arg4 = PIN_GetContextReg (ctx, REG_GDI);
   args.arg5 = PIN_GetContextReg (ctx, REG_GBP);
#endif

#ifdef TARGET_INTEL64
   // FIXME: The LEVEL_BASE:: ugliness is required by the fact that REG_R8 etc
   // are also defined in /usr/include/sys/ucontext.h
   args.arg0 = PIN_GetContextReg (ctx, LEVEL_BASE::REG_GDI);
   args.arg1 = PIN_GetContextReg (ctx, LEVEL_BASE::REG_GSI);
   args.arg2 = PIN_GetContextReg (ctx, LEVEL_BASE::REG_GDX);
   args.arg3 = PIN_GetContextReg (ctx, LEVEL_BASE::REG_R10);
   args.arg4 = PIN_GetContextReg (ctx, LEVEL_BASE::REG_R8);
   args.arg5 = PIN_GetContextReg (ctx, LEVEL_BASE::REG_R9);
#endif

   if (syscall_number == SYS_clone)
   {
      #if defined(TARGET_IA32)
         localStore[threadIndex].pthread_create.tid_ptr = (void*)args.arg2;
      #elif defined(TARGET_INTEL64)
         localStore[threadIndex].pthread_create.tid_ptr = (void*)args.arg3;
      #endif
      localStore[threadIndex].pthread_create.clear_tid = args.arg0 & CLONE_CHILD_CLEARTID ? true : false;
   }
   else if (syscall_number == SYS_execve)
   {
      LOG_PRINT_ERROR("execv system call not supported in Pin mode, use SIFT mode instead (--sift)");
   }

   Thread* thread = Sim()->getThreadManager()->getCurrentThread(threadIndex);
   LOG_ASSERT_ERROR(thread != NULL, "Thread(NULL)");
   thread->getSyscallMdl()->runEnter(syscall_number, args);
}

void syscallEnterRunModel(THREADID threadIndex, CONTEXT* ctx, SYSCALL_STANDARD syscall_standard, void* v)
{
   Thread* thread = Sim()->getThreadManager()->getCurrentThread(threadIndex);
   LOG_ASSERT_ERROR(thread != NULL, "Thread(NULL)");
   if (thread->getSyscallMdl()->isEmulated())
   {
      PIN_SetSyscallNumber(ctx, syscall_standard, SYS_getpid);
   }
}

void syscallExitRunModel(THREADID threadIndex, CONTEXT* ctx, SYSCALL_STANDARD syscall_standard, void* v)
{
   Thread* thread = Sim()->getThreadManager()->getCurrentThread(threadIndex);
   LOG_ASSERT_ERROR(thread != NULL, "Thread(NULL)");
   IntPtr old_return_val = PIN_GetSyscallReturn(ctx, syscall_standard);

   if (thread->getSyscallMdl()->isEmulated())
   {
      IntPtr syscall_return = thread->getSyscallMdl()->runExit(old_return_val);
      PIN_SetContextReg(ctx, REG_GAX, syscall_return);

      LOG_PRINT("Syscall returned (%p)", syscall_return);
   }
   else
   {
      thread->getSyscallMdl()->runExit(old_return_val);
   }
}

bool interceptSignal(THREADID threadIndex, INT32 signal, CONTEXT *ctx, BOOL hasHandler, const EXCEPTION_INFO *pExceptInfo, void* v)
{
   ADDRINT eip = PIN_GetContextReg(ctx, REG_INST_PTR);
   fprintf(stderr, "Application received fatal signal %u at eip %p\n", signal, (void*)eip);

   INT32 column, line;
   string fileName;
   PIN_GetSourceLocation(eip, &column, &line, &fileName);
   fprintf(stderr, "in %s:%u\n", fileName.c_str(), line);

   switch(PIN_GetDebugStatus())
   {
      case DEBUG_STATUS_CONNECTED:
         // A debugger is already connected, it should just break
         break;
      // TODO: This is supposed to work in a future Pin version. Right now, a fatal signal will kill Pin & the application
      case DEBUG_STATUS_UNCONNECTED:
         // The -appdebug_enable switch was used, but no debugger is currently connected
         // Instruct the user to do this now
         DEBUG_CONNECTION_INFO info;
         if (!PIN_GetDebugConnectionInfo(&info) || info._type != DEBUG_CONNECTION_TYPE_TCP_SERVER)
            break;
         fprintf(stderr, "\nStart GDB and enter this command:\n  target remote :%d\n\n", info._tcpServer._tcpPort);
         PIN_WaitForDebuggerToConnect(0);
         break;
      case DEBUG_STATUS_UNCONNECTABLE:
         // Application debugging is enabled, but it is too early to allow a debugger to connect
         fprintf(stderr, "\nApplication debugging is enabled, but it is too early to allow a debugger to connect.\n\n");
         exit(0);
      case DEBUG_STATUS_DISABLED:
         // No -appdebug* switch given to Pin, nothing we can do
         fprintf(stderr, "\nApplication debugging is currently disabled.\nTo enable it, start Sniper with the --appdebug or --appdebug-wait command line switch.\n\n");
         exit(0);
   }

   return true;
}

}
<|endoftext|>