<commit_before>AliAnalysisTaskElectronEfficiencyV2* AddTask_rbailhac_ElectronEfficiencyV2_PbPb(Bool_t getFromAlien = kFALSE,
										TString cFileName ="Config_rbailhac_ElectronEfficiencyV2_PbPb.C",
										UInt_t trigger = AliVEvent::kINT7,
										Int_t rejpileup = 1,
										const Int_t CenMin =  0,
										const Int_t CenMax = 10,
										const Float_t PtMin =  0.2,
										const Float_t PtMax = 10.0,
										const Float_t EtaMin = -0.8,
										const Float_t EtaMax = +0.8,
										const Bool_t UsePtVec = kTRUE,
										const Bool_t DoULSLS = kTRUE,
										const TString generators = "pizero_0;eta_1;etaprime_2;rho_3;omega_4;phi_5;jpsi_6;Pythia CC_0;Pythia BB_0;Pythia B_0;",
										const std::string resolutionFilename ="",
										const std::string cocktailFilename   ="",
										const std::string centralityFilename ="",
										const TString outname = "LMEE.root")
{

  //get the current analysis manager
  AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
  if (!mgr) {
    Error("AddTask_rbailhac_test", "No analysis manager found.");
    return 0;
  }

  //Base Directory for GRID / LEGO Train
  TString configBasePath= "$ALICE_PHYSICS/PWGDQ/dielectron/macrosLMEE/";
  if(getFromAlien && (!gSystem->Exec(Form("alien_cp alien:///alice/cern.ch/user/r/rbailhac/PWGDQ/dielectron/macrosLMEE/%s .",cFileName.Data()))) ){
    configBasePath=Form("%s/",gSystem->pwd());
  }

  TString configFilePath(configBasePath+cFileName);

  std::cout << "Configpath:  " << configFilePath << std::endl;

  if (!gROOT->GetListOfGlobalFunctions()->FindObject("Config_rbailhac_ElectronEfficiencyV2_PbPb")) {
    printf("Load macro now\n");
    gROOT->LoadMacro(configFilePath.Data());
  }

  // trigger
  TString triggername = "NULL";
  if(trigger == (UInt_t)AliVEvent::kINT7)             triggername = "kINT7";
  else if(trigger == (UInt_t)AliVEvent::kCentral)     triggername = "kCentral";
  else if(trigger == (UInt_t)AliVEvent::kSemiCentral) triggername = "kSemiCentral";
  else if(trigger == (UInt_t)(AliVEvent::kINT7 | AliVEvent::kCentral | AliVEvent::kSemiCentral)) triggername = "kCombinedCentralityTriggers";
  else if(trigger == (UInt_t)(AliVEvent::kINT7 | AliVEvent::kCentral))                           triggername = "kCombinedCentral";
  else if(trigger == (UInt_t)(AliVEvent::kINT7 | AliVEvent::kSemiCentral))                       triggername = "kCombinedSemiCentral";

  // generators
  TString suffixgen = "";
  if(generators.Contains("Pythia CC") && (generators.Contains("Pythia BB") || generators.Contains("Pythia B"))) suffixgen = "_CC_BB";
  else if(generators.Contains("Pythia CC")) suffixgen = "_CC";
  else if(generators.Contains("Pythia BB") || generators.Contains("Pythia B")) suffixgen = "_BB";
  else if(generators.Contains("pizero_0")) suffixgen = "_LF";
  else suffixgen = "";

  // generator index
  TString suffixgenID = "";
  std::vector<UInt_t> genID;
  const Int_t ngenID = (Int_t)gROOT->ProcessLine("GetGenID()");
  if(ngenID > 0) {
    for (unsigned int i = 0; i < ngenID+1; ++i){
      UInt_t valuegenID = (UInt_t)(gROOT->ProcessLine(Form("GetGenID(%d)",i)));
      genID.push_back(valuegenID);
      suffixgenID += valuegenID;
    }
  }

  //create task and add it to the manager (MB)
  TString appendix;
  appendix += TString::Format("Cen%d_%d_%s_%s_%s_Pileup%d",CenMin,CenMax,triggername.Data(),suffixgen.Data(),suffixgenID.Data(),rejpileup);
  printf("appendix %s\n", appendix.Data());

  //##########################################################
  //############################################################
  // Creating an instance of the task
  AliAnalysisTaskElectronEfficiencyV2* task = new AliAnalysisTaskElectronEfficiencyV2(Form("TaskElectronEfficiencyV2_%s",appendix.Data()));
  gROOT->GetListOfSpecials()->Add(task);//this is only for ProcessLine(AddMCSignal);

  // #########################################################
  // #########################################################
  // Set TOF correction
  // if(tofcor){
  //  SetEtaCorrectionTOFRMS(task, AliDielectronVarManager::kP, AliDielectronVarManager::kEta);
  //  SetEtaCorrectionTOFMean(task, AliDielectronVarManager::kP, AliDielectronVarManager::kEta);
  //}

  // #########################################################
  // #########################################################
  // Event selection. Is the same for all the different cutsettings
  task->SetEnablePhysicsSelection(kTRUE);//always ON in Run2 analyses for both data and MC.
  task->SetTriggerMask(trigger);
  task->SetEventFilter((reinterpret_cast<AliDielectronEventCuts*>(gROOT->ProcessLine(Form("GetEventCuts(%f,%f,%d,\"%s\")",(Float_t)CenMin,(Float_t)CenMax,rejpileup,"V0M")))));

  // #########################################################
  // #########################################################
  // Set minimum and maximum values of generated tracks. Only used to save computing power.
  // Do not set here your analysis pt-cuts
  task->SetMinPtGen(0.1);
  task->SetMaxPtGen(1e+10);
  task->SetMinEtaGen(-1.5);
  task->SetMaxEtaGen(+1.5);

  // #########################################################
  // #########################################################
  // Set minimum and maximum values for pairing
  task->SetKinematicCuts(PtMin, PtMax, EtaMin, EtaMax);

  // #########################################################
  // #########################################################
  // Set Binning single variables
  if (UsePtVec == true) {
    const Int_t Npt = 68;
    Double_t pte[Npt] = {0.00,0.10,0.11,0.12,0.13,0.14,0.15,0.155,0.16,0.165,0.17,0.175,0.18,0.185,0.19,0.195,0.20,0.205,0.21,0.215,0.22,0.225,0.23,0.235,0.24,0.245,0.25,0.255,0.26,0.265,0.27,0.275,0.28,0.285,0.29,0.295,0.30,0.32,0.34,0.36,0.38,0.40,0.43,0.46,0.49,0.52,0.55,0.60,0.65,0.70,0.75,0.80,0.90,1.00,1.10,1.20,1.40,1.60,1.80,2.00,2.40,2.80,3.20,3.70,4.50,6.00,8.00,12.0};
    std::vector<double> v_pte(pte,std::end(pte));
    task->SetPtBins(v_pte);
  }
  else task->SetPtBinsLinear   (0,  10, 100);
  task->SetEtaBinsLinear (-1.,1.,20); // 40 before
  task->SetPhiBinsLinear  (0, TMath::TwoPi(), 36); // 90 before
  task->SetThetaBinsLinear(0, TMath::TwoPi(), 60);

  // pair variables
  const Int_t Nmee = 150;
  Double_t mee[Nmee] = {};
  for(Int_t i=0  ;i<110 ;i++) mee[i] = 0.01 * (i-  0) +  0.0;//from 0 to 1.09 GeV/c2, every 0.01 GeV/c2
  for(Int_t i=110;i<Nmee;i++) mee[i] = 0.1  * (i-110) +  1.1;//from 1.1 to 5 GeV/c2, evety 0.1 GeV/c2
  std::vector<double> v_mee(mee,std::end(mee));

  const Int_t NpTee = 130;
  Double_t pTee[NpTee] = {};
  for(Int_t i=0  ;i<20   ;i++) pTee[i] = 0.005 * (i-  0) +  0.0;//from 0 to 0.095 GeV/c, every 0.005 GeV/c
  for(Int_t i=20 ;i<119  ;i++) pTee[i] = 0.1  * (i- 20) +  0.1;//from 0.1 to 9.9 GeV/c, evety 0.1 GeV/c
  for(Int_t i=119;i<NpTee;i++) pTee[i] = 1.0  * (i-119) + 10.0;//from 10 to 20 GeV/c, evety 1.0 GeV/c
  std::vector<double> v_pTee(pTee,std::end(pTee));
  task->SetMassBins(v_mee);
  task->SetPairPtBins(v_pTee);
  //task->SetPhiVBinsLinear(0, TMath::Pi(), 100);
  //task->SetFillPhiV(kTRUE);

  // #########################################################
  // #########################################################
  //task->SetSmearGenerated(kFALSE); // cross check smearing the MC at single level and filling resolution maps
 // Resolution File, If resoFilename = "" no correction is applied
  task->SetResolutionFile(resolutionFilename);
  task->SetResolutionFileFromAlien("/alice/cern.ch/user/r/rbailhac/supportFiles/" + resolutionFilename);
  task->SetResolutionDeltaPtBinsLinear   (-10., 2., (Int_t)gROOT->ProcessLine("GetNbinsDeltaMom()"));
  task->SetResolutionRelPtBinsLinear   (0., 2.,  (Int_t)gROOT->ProcessLine("GetNbinsRelMom()"));
  task->SetResolutionEtaBinsLinear  (-0.4, 0.4, (Int_t)gROOT->ProcessLine("GetNbinsDeltaEta()"));
  task->SetResolutionPhiBinsLinear  (-0.4, 0.4, (Int_t)gROOT->ProcessLine("GetNbinsDeltaPhi()"));
  task->SetResolutionThetaBinsLinear(-0.4, 0.4, (Int_t)gROOT->ProcessLine("GetNbinsDeltaTheta()"));

  //###########################################################
  //############################################################
  // Set MCSignal and Cutsetting to fill the support histograms
  task->SetSupportHistoMCSignalAndCutsetting(0,0);//fill support histograms for first MCsignal and first cutsetting

  // #########################################################
  // #########################################################
  // Set centrality correction. If resoFilename = "" no correction is applied
  task->SetCentralityFile(centralityFilename);

  // #########################################################
  // #########################################################
  // Pairing related config
  task->SetDoPairing(kTRUE);
  task->SetULSandLS(DoULSLS);

  //#####################################################
  //######################################################
  // Generators
  cout<<"Efficiency based on MC generators: " << generators <<endl;
  TString generatorsPair=generators;
  task->SetGeneratorMCSignalName(generatorsPair);
  task->SetGeneratorULSSignalName(generators);

  //#################################################
  //#################################################
  // generator ID to select pile-up or not
  if(ngenID > 0) {
    task->SetGeneratorMCSignalIndex(genID);
    task->SetGeneratorULSSignalIndex(genID);
    task->SetCheckGenID(kTRUE);
  }

  //###############################################
  //##############################################
  task->SetCocktailWeighting(cocktailFilename);
  task->SetCocktailWeightingFromAlien("/alice/cern.ch/user/r/rbailhac/supportFiles/" + cocktailFilename);

  // #########################################################
  // #########################################################
  // Add MCSignals. Can be set to see differences of:
  // e.g. secondaries and primaries. or primaries from charm and resonances
  gROOT->ProcessLine(Form("AddSingleLegMCSignal(%s)",task->GetName()));//not task itself, task name
  gROOT->ProcessLine(Form("AddPairMCSignal(%s)"     ,task->GetName()));//not task itself, task name

  // #########################################################
  // #########################################################
  // Adding cutsettings
 // Cuts
  // Number of cuts
  const Int_t nDie = (Int_t)gROOT->ProcessLine("GetN()");
  //add dielectron analysis with different cuts to the task
  for (Int_t i=0; i<nDie; ++i){ //nDie defined in config file
    AliAnalysisFilter *filter = reinterpret_cast<AliAnalysisFilter*>(gROOT->ProcessLine(Form("Config_rbailhac_ElectronEfficiencyV2_PbPb(%d)",i)));
    task->AddTrackCuts(filter);
  }

  //########################################
  //########################################
  TString outlistname = Form("efficiency_%s",appendix.Data());
  const TString fileName = outname;
  mgr->AddTask(task);
  mgr->ConnectInput(task, 0, mgr->GetCommonInputContainer());
  mgr->ConnectOutput(task, 1, mgr->CreateContainer(outlistname, TList::Class(), AliAnalysisManager::kOutputContainer, Form("%s",fileName.Data())));

  return task;
}
<commit_msg>Add PID MC post calibration<commit_after>AliAnalysisTaskElectronEfficiencyV2* AddTask_rbailhac_ElectronEfficiencyV2_PbPb(Bool_t getFromAlien = kFALSE,
										TString cFileName ="Config_rbailhac_ElectronEfficiencyV2_PbPb.C",
										UInt_t trigger = AliVEvent::kINT7,
										Int_t rejpileup = 1,
										const Int_t CenMin =  0,
										const Int_t CenMax = 10,
										const Float_t PtMin =  0.2,
										const Float_t PtMax = 10.0,
										const Float_t EtaMin = -0.8,
										const Float_t EtaMax = +0.8,
										const Bool_t UsePtVec = kTRUE,
										const Bool_t DoULSLS = kTRUE,
										const TString generators = "pizero_0;eta_1;etaprime_2;rho_3;omega_4;phi_5;jpsi_6;Pythia CC_0;Pythia BB_0;Pythia B_0;",
										const std::string resolutionFilename ="",
										const std::string cocktailFilename   ="",
										const std::string centralityFilename ="",
										TString calibFileName = "",
										const TString outname = "LMEE.root")
{

  //get the current analysis manager
  AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
  if (!mgr) {
    Error("AddTask_rbailhac_test", "No analysis manager found.");
    return 0;
  }

  //Base Directory for GRID / LEGO Train
  TString configBasePath= "$ALICE_PHYSICS/PWGDQ/dielectron/macrosLMEE/";
  if(getFromAlien && (!gSystem->Exec(Form("alien_cp alien:///alice/cern.ch/user/r/rbailhac/PWGDQ/dielectron/macrosLMEE/%s .",cFileName.Data()))) ){
    configBasePath=Form("%s/",gSystem->pwd());
  }

  TString configFilePath(configBasePath+cFileName);

  std::cout << "Configpath:  " << configFilePath << std::endl;

  if (!gROOT->GetListOfGlobalFunctions()->FindObject("Config_rbailhac_ElectronEfficiencyV2_PbPb")) {
    printf("Load macro now\n");
    gROOT->LoadMacro(configFilePath.Data());
  }

  // trigger
  TString triggername = "NULL";
  if(trigger == (UInt_t)AliVEvent::kINT7)             triggername = "kINT7";
  else if(trigger == (UInt_t)AliVEvent::kCentral)     triggername = "kCentral";
  else if(trigger == (UInt_t)AliVEvent::kSemiCentral) triggername = "kSemiCentral";
  else if(trigger == (UInt_t)(AliVEvent::kINT7 | AliVEvent::kCentral | AliVEvent::kSemiCentral)) triggername = "kCombinedCentralityTriggers";
  else if(trigger == (UInt_t)(AliVEvent::kINT7 | AliVEvent::kCentral))                           triggername = "kCombinedCentral";
  else if(trigger == (UInt_t)(AliVEvent::kINT7 | AliVEvent::kSemiCentral))                       triggername = "kCombinedSemiCentral";

  // generators
  TString suffixgen = "";
  if(generators.Contains("Pythia CC") && (generators.Contains("Pythia BB") || generators.Contains("Pythia B"))) suffixgen = "_CC_BB";
  else if(generators.Contains("Pythia CC")) suffixgen = "_CC";
  else if(generators.Contains("Pythia BB") || generators.Contains("Pythia B")) suffixgen = "_BB";
  else if(generators.Contains("pizero_0")) suffixgen = "_LF";
  else suffixgen = "";

  // generator index
  TString suffixgenID = "";
  std::vector<UInt_t> genID;
  const Int_t ngenID = (Int_t)gROOT->ProcessLine("GetGenID()");
  if(ngenID > 0) {
    for (unsigned int i = 0; i < ngenID+1; ++i){
      UInt_t valuegenID = (UInt_t)(gROOT->ProcessLine(Form("GetGenID(%d)",i)));
      genID.push_back(valuegenID);
      suffixgenID += valuegenID;
    }
  }

  //create task and add it to the manager (MB)
  TString appendix;
  appendix += TString::Format("Cen%d_%d_%s_%s_%s_Pileup%d",CenMin,CenMax,triggername.Data(),suffixgen.Data(),suffixgenID.Data(),rejpileup);
  printf("appendix %s\n", appendix.Data());

  //##########################################################
  //############################################################
  // Creating an instance of the task
  AliAnalysisTaskElectronEfficiencyV2* task = new AliAnalysisTaskElectronEfficiencyV2(Form("TaskElectronEfficiencyV2_%s",appendix.Data()));
  gROOT->GetListOfSpecials()->Add(task);//this is only for ProcessLine(AddMCSignal);

  // #########################################################
  // #########################################################
  // Set TOF correction
  // if(tofcor){
  //  SetEtaCorrectionTOFRMS(task, AliDielectronVarManager::kP, AliDielectronVarManager::kEta);
  //  SetEtaCorrectionTOFMean(task, AliDielectronVarManager::kP, AliDielectronVarManager::kEta);
  //}

  // #########################################################
  // #########################################################
  // Event selection. Is the same for all the different cutsettings
  task->SetEnablePhysicsSelection(kTRUE);//always ON in Run2 analyses for both data and MC.
  task->SetTriggerMask(trigger);
  task->SetEventFilter((reinterpret_cast<AliDielectronEventCuts*>(gROOT->ProcessLine(Form("GetEventCuts(%f,%f,%d,\"%s\")",(Float_t)CenMin,(Float_t)CenMax,rejpileup,"V0M")))));

  // #########################################################
  // #########################################################
  // Set minimum and maximum values of generated tracks. Only used to save computing power.
  // Do not set here your analysis pt-cuts
  task->SetMinPtGen(0.1);
  task->SetMaxPtGen(1e+10);
  task->SetMinEtaGen(-1.5);
  task->SetMaxEtaGen(+1.5);

  // #########################################################
  // #########################################################
  // Set minimum and maximum values for pairing
  task->SetKinematicCuts(PtMin, PtMax, EtaMin, EtaMax);

  // #########################################################
  // #########################################################
  // Set Binning single variables
  if (UsePtVec == true) {
    const Int_t Npt = 68;
    Double_t pte[Npt] = {0.00,0.10,0.11,0.12,0.13,0.14,0.15,0.155,0.16,0.165,0.17,0.175,0.18,0.185,0.19,0.195,0.20,0.205,0.21,0.215,0.22,0.225,0.23,0.235,0.24,0.245,0.25,0.255,0.26,0.265,0.27,0.275,0.28,0.285,0.29,0.295,0.30,0.32,0.34,0.36,0.38,0.40,0.43,0.46,0.49,0.52,0.55,0.60,0.65,0.70,0.75,0.80,0.90,1.00,1.10,1.20,1.40,1.60,1.80,2.00,2.40,2.80,3.20,3.70,4.50,6.00,8.00,12.0};
    std::vector<double> v_pte(pte,std::end(pte));
    task->SetPtBins(v_pte);
  }
  else task->SetPtBinsLinear   (0,  10, 100);
  task->SetEtaBinsLinear (-1.,1.,20); // 40 before
  task->SetPhiBinsLinear  (0, TMath::TwoPi(), 36); // 90 before
  task->SetThetaBinsLinear(0, TMath::TwoPi(), 60);

  // pair variables
  const Int_t Nmee = 150;
  Double_t mee[Nmee] = {};
  for(Int_t i=0  ;i<110 ;i++) mee[i] = 0.01 * (i-  0) +  0.0;//from 0 to 1.09 GeV/c2, every 0.01 GeV/c2
  for(Int_t i=110;i<Nmee;i++) mee[i] = 0.1  * (i-110) +  1.1;//from 1.1 to 5 GeV/c2, evety 0.1 GeV/c2
  std::vector<double> v_mee(mee,std::end(mee));

  const Int_t NpTee = 130;
  Double_t pTee[NpTee] = {};
  for(Int_t i=0  ;i<20   ;i++) pTee[i] = 0.005 * (i-  0) +  0.0;//from 0 to 0.095 GeV/c, every 0.005 GeV/c
  for(Int_t i=20 ;i<119  ;i++) pTee[i] = 0.1  * (i- 20) +  0.1;//from 0.1 to 9.9 GeV/c, evety 0.1 GeV/c
  for(Int_t i=119;i<NpTee;i++) pTee[i] = 1.0  * (i-119) + 10.0;//from 10 to 20 GeV/c, evety 1.0 GeV/c
  std::vector<double> v_pTee(pTee,std::end(pTee));
  task->SetMassBins(v_mee);
  task->SetPairPtBins(v_pTee);
  //task->SetPhiVBinsLinear(0, TMath::Pi(), 100);
  //task->SetFillPhiV(kTRUE);

  // #########################################################
  // #########################################################
  //task->SetSmearGenerated(kFALSE); // cross check smearing the MC at single level and filling resolution maps
 // Resolution File, If resoFilename = "" no correction is applied
  task->SetResolutionFile(resolutionFilename);
  task->SetResolutionFileFromAlien("/alice/cern.ch/user/r/rbailhac/supportFiles/" + resolutionFilename);
  task->SetResolutionDeltaPtBinsLinear   (-10., 2., (Int_t)gROOT->ProcessLine("GetNbinsDeltaMom()"));
  task->SetResolutionRelPtBinsLinear   (0., 2.,  (Int_t)gROOT->ProcessLine("GetNbinsRelMom()"));
  task->SetResolutionEtaBinsLinear  (-0.4, 0.4, (Int_t)gROOT->ProcessLine("GetNbinsDeltaEta()"));
  task->SetResolutionPhiBinsLinear  (-0.4, 0.4, (Int_t)gROOT->ProcessLine("GetNbinsDeltaPhi()"));
  task->SetResolutionThetaBinsLinear(-0.4, 0.4, (Int_t)gROOT->ProcessLine("GetNbinsDeltaTheta()"));

  //###########################################################
  //############################################################
  // Set MCSignal and Cutsetting to fill the support histograms
  task->SetSupportHistoMCSignalAndCutsetting(0,0);//fill support histograms for first MCsignal and first cutsetting

  // #########################################################
  // #########################################################
  // Set centrality correction. If resoFilename = "" no correction is applied
  task->SetCentralityFile(centralityFilename);

  // #########################################################
  // #########################################################
  // Pairing related config
  task->SetDoPairing(kTRUE);
  task->SetULSandLS(DoULSLS);

  //#####################################################
  //######################################################
  // Generators
  cout<<"Efficiency based on MC generators: " << generators <<endl;
  TString generatorsPair=generators;
  task->SetGeneratorMCSignalName(generatorsPair);
  task->SetGeneratorULSSignalName(generators);

  //#################################################
  //#################################################
  // generator ID to select pile-up or not
  if(ngenID > 0) {
    task->SetGeneratorMCSignalIndex(genID);
    task->SetGeneratorULSSignalIndex(genID);
    task->SetCheckGenID(kTRUE);
  }

  //###############################################
  //##############################################
  task->SetCocktailWeighting(cocktailFilename);
  task->SetCocktailWeightingFromAlien("/alice/cern.ch/user/r/rbailhac/supportFiles/" + cocktailFilename);

  // #########################################################
  // #########################################################
  // Add MCSignals. Can be set to see differences of:
  // e.g. secondaries and primaries. or primaries from charm and resonances
  gROOT->ProcessLine(Form("AddSingleLegMCSignal(%s)",task->GetName()));//not task itself, task name
  gROOT->ProcessLine(Form("AddPairMCSignal(%s)"     ,task->GetName()));//not task itself, task name

  // #########################################################
  // #########################################################
  // PID postcalibration
  TH3D *hs_mean_ITS_El  = 0x0;
  TH3D *hs_width_ITS_El = 0x0;
  TH3D *hs_mean_TOF_El  = 0x0;
  TH3D *hs_width_TOF_El = 0x0;

  // PID post-calibration
  TFile *rootfile = 0x0;
  if(calibFileName.Contains("MC")){
    printf("reading : %s for PID calibration\n",calibFileName.Data());
    rootfile = TFile::Open(calibFileName,"READ");
    hs_mean_ITS_El  = (TH3D*)rootfile->Get("h3mean_ITS");
    hs_width_ITS_El = (TH3D*)rootfile->Get("h3width_ITS");
    hs_mean_TOF_El  = (TH3D*)rootfile->Get("h3mean_TOF");
    hs_width_TOF_El = (TH3D*)rootfile->Get("h3width_TOF");

    if(hs_mean_ITS_El) {
      cout<<"Adding mean ITS PID correction" <<endl;
      task->SetCentroidCorrFunction(AliAnalysisTaskElectronEfficiencyV2::kITS, hs_mean_ITS_El, AliDielectronVarManager::kNSDDSSDclsEvent, AliDielectronVarManager::kPIn, AliDielectronVarManager::kEta);
    }
    if(hs_mean_TOF_El) {
      cout<<"Adding mean TOF PID correction" <<endl;
      task->SetCentroidCorrFunction(AliAnalysisTaskElectronEfficiencyV2::kTOF, hs_mean_TOF_El, AliDielectronVarManager::kNSDDSSDclsEvent, AliDielectronVarManager::kPIn, AliDielectronVarManager::kEta);
    }
    if(hs_width_ITS_El) {
      cout<<"Adding width ITS PID correction" <<endl;
      task->SetWidthCorrFunction(AliAnalysisTaskElectronEfficiencyV2::kITS, hs_width_ITS_El, AliDielectronVarManager::kNSDDSSDclsEvent, AliDielectronVarManager::kPIn, AliDielectronVarManager::kEta);
    }
    if(hs_width_TOF_El) {
      cout<<"Adding width TOF PID correction" <<endl;
      task->SetWidthCorrFunction(AliAnalysisTaskElectronEfficiencyV2::kTOF, hs_width_TOF_El, AliDielectronVarManager::kNSDDSSDclsEvent, AliDielectronVarManager::kPIn, AliDielectronVarManager::kEta);
    }

  }

  // #########################################################
  // #########################################################
  // Adding cutsettings
 // Cuts
  // Number of cuts
  const Int_t nDie = (Int_t)gROOT->ProcessLine("GetN()");
  //add dielectron analysis with different cuts to the task
  for (Int_t i=0; i<nDie; ++i){ //nDie defined in config file
    AliAnalysisFilter *filter = reinterpret_cast<AliAnalysisFilter*>(gROOT->ProcessLine(Form("Config_rbailhac_ElectronEfficiencyV2_PbPb(%d)",i)));
    task->AddTrackCuts(filter);
  }

  //########################################
  //########################################
  TString outlistname = Form("efficiency_%s",appendix.Data());
  const TString fileName = outname;
  mgr->AddTask(task);
  mgr->ConnectInput(task, 0, mgr->GetCommonInputContainer());
  mgr->ConnectOutput(task, 1, mgr->CreateContainer(outlistname, TList::Class(), AliAnalysisManager::kOutputContainer, Form("%s",fileName.Data())));

  return task;
}
<|endoftext|>


<commit_before>/****************************************************************/
/* MOOSE - Multiphysics Object Oriented Simulation Environment  */
/*                                                              */
/*          All contents are licensed under LGPL V2.1           */
/*             See LICENSE for full restrictions                */
/****************************************************************/

#include "InterfaceOrientationMaterial.h"
#include "MooseMesh.h"

template<>
InputParameters validParams<InterfaceOrientationMaterial>()
{
  InputParameters params = validParams<Material>();
  params.addParam<Real>("anisotropy_strength", 0.04, "Strength of the anisotropy (typically < 0.05)");
  params.addParam<unsigned int>("mode_number", 6, "Mode number for anisotropy");
  params.addParam<Real>("reference_angle", 90, "Reference angle for defining anistropy in degrees");
  params.addParam<Real>("eps_bar", 0.01, "Average value of the interface parameter epsilon");
  params.addRequiredCoupledVar("op", "Order parameter defining the solid phase");
  return params;
}

InterfaceOrientationMaterial::InterfaceOrientationMaterial(const InputParameters & parameters) :
    Material(parameters),
    _delta(getParam<Real>("anisotropy_strength")),
    _j(getParam<unsigned int>("mode_number")),
    _theta0(getParam<Real>("reference_angle")),
    _eps_bar(getParam<Real>("eps_bar")),
    _eps(declareProperty<Real>("eps")),
    _deps(declareProperty<Real>("deps")),
    _depsdgrad_op(declareProperty<RealGradient>("depsdgrad_op")),
    _ddepsdgrad_op(declareProperty<RealGradient>("ddepsdgrad_op")),
    _op(coupledValue("op")),
    _grad_op(coupledGradient("op"))
{
  // this currently only works in 2D simulations
  if (_mesh.dimension() != 2)
    mooseError("InterfaceOrientationMaterial requires a two-dimensional mesh.");
}

void
InterfaceOrientationMaterial::computeQpProperties()
{
  Real cutoff = 0.99999;

  // cosine of the gradient orientation angle
  Real n;
  if (_grad_op[_qp].norm() == 0)
    n = 0;
  else
    n = _grad_op[_qp](0) / _grad_op[_qp].norm();

  if (n > cutoff)
    n = cutoff;

  if (n < -cutoff)
    n = -cutoff;

  const Real angle = std::acos(n);

  // Compute derivative of angle wrt n
  const Real dangledn = - 1.0 / std::sqrt(1.0 - n * n);

  // Compute derivative of n with respect to grad_op
  RealGradient dndgrad_op;
  if (_grad_op[_qp].norm_sq() == 0)
    dndgrad_op = 0;
  else
  {
    dndgrad_op(0) = _grad_op[_qp](1) * _grad_op[_qp](1);
    dndgrad_op(1) = - _grad_op[_qp](0) * _grad_op[_qp](1);
    dndgrad_op /= (_grad_op[_qp].norm_sq() * _grad_op[_qp].norm());
  }

  // Calculate interfacial parameter epsilon and its derivatives
  _eps[_qp]= _eps_bar * (_delta * std::cos(_j * (angle - _theta0 * libMesh::pi/180.0)) + 1.0);
  _deps[_qp]= - _eps_bar * _delta * _delta * std::sin(_j * (angle - _theta0 * libMesh::pi/180.0));
  Real d2eps = - _eps_bar * _delta * _delta * _delta * std::cos(_j * (angle - _theta0 * libMesh::pi/180.0));

  // Compute derivatives of epsilon and its derivative wrt grad_op
  _depsdgrad_op[_qp] = _deps[_qp] * dangledn * dndgrad_op;
  _ddepsdgrad_op[_qp] = d2eps * dangledn * dndgrad_op;
}
<commit_msg>Fix angle sign and derivative (#6893)<commit_after>/****************************************************************/
/* MOOSE - Multiphysics Object Oriented Simulation Environment  */
/*                                                              */
/*          All contents are licensed under LGPL V2.1           */
/*             See LICENSE for full restrictions                */
/****************************************************************/

#include "InterfaceOrientationMaterial.h"
#include "MooseMesh.h"
#include "MathUtils.h"

template<>
InputParameters validParams<InterfaceOrientationMaterial>()
{
  InputParameters params = validParams<Material>();
  params.addParam<Real>("anisotropy_strength", 0.04, "Strength of the anisotropy (typically < 0.05)");
  params.addParam<unsigned int>("mode_number", 6, "Mode number for anisotropy");
  params.addParam<Real>("reference_angle", 90, "Reference angle for defining anistropy in degrees");
  params.addParam<Real>("eps_bar", 0.01, "Average value of the interface parameter epsilon");
  params.addRequiredCoupledVar("op", "Order parameter defining the solid phase");
  return params;
}

InterfaceOrientationMaterial::InterfaceOrientationMaterial(const InputParameters & parameters) :
    Material(parameters),
    _delta(getParam<Real>("anisotropy_strength")),
    _j(getParam<unsigned int>("mode_number")),
    _theta0(getParam<Real>("reference_angle")),
    _eps_bar(getParam<Real>("eps_bar")),
    _eps(declareProperty<Real>("eps")),
    _deps(declareProperty<Real>("deps")),
    _depsdgrad_op(declareProperty<RealGradient>("depsdgrad_op")),
    _ddepsdgrad_op(declareProperty<RealGradient>("ddepsdgrad_op")),
    _op(coupledValue("op")),
    _grad_op(coupledGradient("op"))
{
  // this currently only works in 2D simulations
  if (_mesh.dimension() != 2)
    mooseError("InterfaceOrientationMaterial requires a two-dimensional mesh.");
}

void
InterfaceOrientationMaterial::computeQpProperties()
{
  Real cutoff = 0.99999;

  // cosine of the gradient orientation angle
  Real n;
  if (_grad_op[_qp].norm_sq() == 0)
    n = 0;
  else
    n = _grad_op[_qp](0) / _grad_op[_qp].norm();

  if (n > cutoff)
    n = cutoff;

  if (n < -cutoff)
    n = -cutoff;

  const Real angle = std::acos(n) * MathUtils::sign(_grad_op[_qp](1));

  // Compute derivative of angle wrt n
  const Real dangledn = - MathUtils::sign(_grad_op[_qp](1)) / std::sqrt(1.0 - n * n);

  // Compute derivative of n with respect to grad_op
  RealGradient dndgrad_op;
  if (_grad_op[_qp].norm_sq() == 0)
    dndgrad_op = 0;
  else
  {
    dndgrad_op(0) = _grad_op[_qp](1) * _grad_op[_qp](1);
    dndgrad_op(1) = - _grad_op[_qp](0) * _grad_op[_qp](1);
    dndgrad_op /= (_grad_op[_qp].norm_sq() * _grad_op[_qp].norm());
  }

  // Calculate interfacial parameter epsilon and its derivatives
  _eps[_qp]= _eps_bar * (_delta * std::cos(_j * (angle - _theta0 * libMesh::pi/180.0)) + 1.0);
  _deps[_qp]= - _eps_bar * _delta * _j * std::sin(_j * (angle - _theta0 * libMesh::pi/180.0));
  Real d2eps = - _eps_bar * _delta * _j * _j * std::cos(_j * (angle - _theta0 * libMesh::pi/180.0));

  // Compute derivatives of epsilon and its derivative wrt grad_op
  _depsdgrad_op[_qp] = _deps[_qp] * dangledn * dndgrad_op;
  _ddepsdgrad_op[_qp] = d2eps * dangledn * dndgrad_op;
}
<|endoftext|>


<commit_before>#include <cmath>
#include <fstream>
#include <iostream>
#include <sstream>

#include "io.hh"
#include "conf.hh"
#include "LM.hh"

using namespace std;
using namespace fsalm;

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

    conf::Config config;
    config("usage: strscore [OPTION...] ARPAFILE INPUT OUTPUT\n")
    ('h', "help", "", "", "display help");
    config.default_parse(argc, argv);
    if (config.arguments.size() != 3) config.print_help(stderr, 1);

    string arpafname = config.arguments[0];
    string infname = config.arguments[1];
    string outfname = config.arguments[2];

    LM lm;
    lm.read_arpa(io::Stream(arpafname, "r").file, true);
    lm.trim();

    ifstream infile(infname);
    if (!infile) {
        cerr << "Something went wrong opening the input file." << endl;
        exit(0);
    }

    ofstream outfile(outfname);
    if (!outfile) {
        cerr << "Something went wrong opening the output file." << endl;
        exit(0);
    }

    int count;
    string line, lstr;
    while (getline(infile, line)) {
        stringstream ss(line);
        ss >> count;
        ss >> lstr;

        float total_prob = 0.0;
        int node_id = lm.empty_node_id();
        for (int i=0; i<lstr.length(); i++) {
            int sym = lm.symbol_map().index(lstr.substr(i, 1));
            float curr_prob = 0.0;
            node_id = lm.walk(node_id, sym, &curr_prob);
            total_prob += curr_prob;
        }

        total_prob *= log(10.0); // Convert from log10 (ARPA default) to ln
        outfile << total_prob << "\t" << lstr << endl;
    }

    infile.close();
    outfile.close();

    exit(1);
}

<commit_msg>Normalize the scores.<commit_after>#include <cmath>
#include <fstream>
#include <iostream>
#include <sstream>
#include <vector>
#include <utility>

#include "defs.hh"
#include "io.hh"
#include "conf.hh"
#include "LM.hh"

using namespace std;
using namespace fsalm;

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

    conf::Config config;
    config("usage: strscore [OPTION...] ARPAFILE INPUT OUTPUT\n")
    ('h', "help", "", "", "display help");
    config.default_parse(argc, argv);
    if (config.arguments.size() != 3) config.print_help(stderr, 1);

    string arpafname = config.arguments[0];
    string infname = config.arguments[1];
    string outfname = config.arguments[2];

    LM lm;
    lm.read_arpa(io::Stream(arpafname, "r").file, true);
    lm.trim();

    ifstream infile(infname);
    if (!infile) {
        cerr << "Something went wrong opening the input file." << endl;
        exit(0);
    }

    ofstream outfile(outfname);
    if (!outfile) {
        cerr << "Something went wrong opening the output file." << endl;
        exit(0);
    }

    int count;
    string line, lstr;
    vector<pair<string, float> > scores;
    float normalizer = SMALL_LP;
    while (getline(infile, line)) {
        stringstream ss(line);
        ss >> count;
        ss >> lstr;

        float total_prob = 0.0;
        int node_id = lm.empty_node_id();
        for (int i=0; i<lstr.length(); i++) {
            int sym = lm.symbol_map().index(lstr.substr(i, 1));
            float curr_prob = 0.0;
            node_id = lm.walk(node_id, sym, &curr_prob);
            total_prob += curr_prob;
        }

        total_prob *= log(10.0); // Convert from log10 (ARPA default) to ln
        normalizer = add_log_domain_probs(normalizer, total_prob);
        scores.push_back(make_pair(lstr, total_prob));
    }

    for (auto it=scores.begin(); it != scores.end(); ++it)
        outfile << it->second-normalizer << "\t" << it->first << endl;

    infile.close();
    outfile.close();

    exit(1);
}

<|endoftext|>


<commit_before>/*=========================================================================

  Program:   Visualization Library
  Module:    PolyMap.cc
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

This file is part of the Visualization Library. No part of this file or its
contents may be copied, reproduced or altered in any way without the express
written consent of the authors.

Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen 1993, 1994

=========================================================================*/
//
// Methods for polygon mapper
//
#include "PolyMap.hh"

vlPolyMapper::vlPolyMapper()
{
  this->Input = 0;
  this->Verts = 0;
  this->Lines = 0;
  this->Polys = 0;
  this->Strips = 0;
  this->VertsVisibility = 1;
  this->LinesVisibility = 1;
  this->PolysVisibility = 1;
  this->StripsVisibility = 1;
}

vlPolyMapper::~vlPolyMapper()
{
  if ( this->Input != 0 )
    {
    this->Input->UnRegister((void *)this);
    }
}

void vlPolyMapper::SetInput(vlPolyData *in)
{
  if (in != this->Input )
    {
    this->Input = in;
    this->Input->Register((void *)this);
    this->Modified();
    }
}
vlPolyData* vlPolyMapper::GetInput()
{
  return this->Input;
}
//
// Return bounding box of data
//
float *vlPolyMapper::GetBounds()
{
  static float bounds[] = {-1.0,1.0, -1.0,1.0, -1.0,1.0};

  if ( ! this->Input )
    return bounds;
  else
    {
    this->Input->Update();
    return this->Input->GetBounds();
    }
}

//
// Receives from Actor -> maps data to primitives
//
void vlPolyMapper::Render(vlRenderer *ren)
{
  vlPointData *pd;
  vlRGBArray *colors;
  vlScalars *scalars;
  int i;
  char forceBuild = 0;
//
// make sure that we've been properly initialized
//
  if ( ! this->Input )
    {
    vlErrorMacro(<< "No input!\n");
    return;
    }
  else
    this->Input->Update();

  if ( ! this->LookupTable ) this->LookupTable = new vlLookupTable;
  this->LookupTable->Build();

  if ( ! this->Polys )
    {
    forceBuild = 1;
    this->Verts = ren->GetPrimitive("points");
    this->Lines = ren->GetPrimitive("lines");
    this->Polys = ren->GetPrimitive("polygons");
    this->Strips = ren->GetPrimitive("triangle_strips");
    }
//
// Now send data down to primitives and draw it
//
  if ( forceBuild || this->Input->GetMTime() > this->BuildTime ||
  this->LookupTable->GetMTime() > this->BuildTime )
    {
//
// create colors
//
    if ( this->ScalarsVisible && (pd=this->Input->GetPointData()) &&
    (scalars=pd->GetScalars()) )
      {
      colors = new vlRGBArray;
      colors->Initialize (this->Input->NumberOfPoints());

      this->LookupTable->SetTableRange(this->ScalarRange);
      for (i=0; i<this->Input->NumberOfPoints(); i++)
        {
        colors->SetColor(i,this->LookupTable->MapValue(scalars->GetScalar(i)));
        }
      }
    else
      {
      colors = 0;
      }
//
//  Cause primitives to build themselves
//
    this->Verts->Build(this->Input,colors);
    this->Lines->Build(this->Input,colors);
    this->Polys->Build(this->Input,colors);
    this->Strips->Build(this->Input,colors);
    this->BuildTime.Modified();
    }

  if ( this->VertsVisibility ) this->Verts->Draw(ren);
  if ( this->LinesVisibility ) this->Lines->Draw(ren);
  if ( this->PolysVisibility ) this->Polys->Draw(ren);
  if ( this->StripsVisibility ) this->Strips->Draw(ren);

}

void vlPolyMapper::PrintSelf(ostream& os, vlIndent indent)
{
  if (this->ShouldIPrint(vlPolyMapper::GetClassName()))
    {
    vlMapper::PrintSelf(os,indent);

    if ( this->Input )
      {
      os << indent << "Input: (" << this->Input << ")\n";
      }
    else
      {
      os << indent << "Input: (none)\n";
      }

    os << indent << "Vertex Visibility: " << (this->VertsVisibility ? "On\n" : "Off\n");
    os << indent << "Line Visibility: " << (this->LinesVisibility ? "On\n" : "Off\n");
    os << indent << "Polygon Visibility: " << (this->PolysVisibility ? "On\n" : "Off\n");
    os << indent << "Triangle Strip Visibility: " << (this->StripsVisibility ? "On\n" : "Off\n");

   }
}
<commit_msg>Fixed some allocation problems<commit_after>/*=========================================================================

  Program:   Visualization Library
  Module:    PolyMap.cc
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

This file is part of the Visualization Library. No part of this file or its
contents may be copied, reproduced or altered in any way without the express
written consent of the authors.

Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen 1993, 1994

=========================================================================*/
//
// Methods for polygon mapper
//
#include "PolyMap.hh"

vlPolyMapper::vlPolyMapper()
{
  this->Input = 0;
  this->Verts = 0;
  this->Lines = 0;
  this->Polys = 0;
  this->Strips = 0;
  this->VertsVisibility = 1;
  this->LinesVisibility = 1;
  this->PolysVisibility = 1;
  this->StripsVisibility = 1;
}

vlPolyMapper::~vlPolyMapper()
{
  if ( this->Input != 0 )
    {
    this->Input->UnRegister((void *)this);
    }
}

void vlPolyMapper::SetInput(vlPolyData *in)
{
  if (in != this->Input )
    {
    this->Input = in;
    this->Input->Register((void *)this);
    this->Modified();
    }
}
vlPolyData* vlPolyMapper::GetInput()
{
  return this->Input;
}
//
// Return bounding box of data
//
float *vlPolyMapper::GetBounds()
{
  static float bounds[] = {-1.0,1.0, -1.0,1.0, -1.0,1.0};

  if ( ! this->Input )
    return bounds;
  else
    {
    this->Input->Update();
    return this->Input->GetBounds();
    }
}

//
// Receives from Actor -> maps data to primitives
//
void vlPolyMapper::Render(vlRenderer *ren)
{
  vlPointData *pd;
  vlRGBArray *colors;
  vlScalars *scalars;
  int i;
  char forceBuild = 0;
//
// make sure that we've been properly initialized
//
  if ( ! this->Input )
    {
    vlErrorMacro(<< "No input!\n");
    return;
    }
  else
    this->Input->Update();

  if ( ! this->LookupTable ) this->LookupTable = new vlLookupTable;
  this->LookupTable->Build();

//
// Now send data down to primitives and draw it
//
  if ( forceBuild || this->Input->GetMTime() > this->BuildTime ||
  this->LookupTable->GetMTime() > this->BuildTime )
    {
//
// create colors
//
    if ( this->ScalarsVisible && (pd=this->Input->GetPointData()) &&
    (scalars=pd->GetScalars()) )
      {
      colors = new vlRGBArray;
      colors->Initialize (this->Input->NumberOfPoints());

      this->LookupTable->SetTableRange(this->ScalarRange);
      for (i=0; i<this->Input->NumberOfPoints(); i++)
        {
        colors->SetColor(i,this->LookupTable->MapValue(scalars->GetScalar(i)));
        }
      }
    else
      {
      colors = 0;
      }

    if (this->VertsVisibility && this->Input->NumberOfVerts())
      {
      if (!this->Verts) this->Verts = ren->GetPrimitive("points");
      this->Verts->Build(this->Input,colors);
      }
    if ( this->LinesVisibility && this->Input->NumberOfLines())
      {
      if (!this->Lines) this->Lines = ren->GetPrimitive("lines");
      this->Lines->Build(this->Input,colors);
      }
    if ( this->PolysVisibility && this->Input->NumberOfPolys())
      {
      if (!this->Polys) this->Polys = ren->GetPrimitive("polygons");
      this->Polys->Build(this->Input,colors);
      }
    if ( this->StripsVisibility && this->Input->NumberOfStrips())
      {
      if (!this->Strips) this->Strips = ren->GetPrimitive("triangle_strips");
      this->Strips->Build(this->Input,colors);
      }

    this->BuildTime.Modified();
    }

  // draw the primitives
  if (this->VertsVisibility && this->Input->NumberOfVerts())
    {
    this->Verts->Draw(ren);
    }
  if ( this->LinesVisibility && this->Input->NumberOfLines())
    {
    this->Lines->Draw(ren);
    }
  if ( this->PolysVisibility && this->Input->NumberOfPolys())
    {
    this->Polys->Draw(ren);
    }
  if ( this->StripsVisibility && this->Input->NumberOfStrips())
    {
    this->Strips->Draw(ren);
    }

}

void vlPolyMapper::PrintSelf(ostream& os, vlIndent indent)
{
  if (this->ShouldIPrint(vlPolyMapper::GetClassName()))
    {
    vlMapper::PrintSelf(os,indent);

    if ( this->Input )
      {
      os << indent << "Input: (" << this->Input << ")\n";
      }
    else
      {
      os << indent << "Input: (none)\n";
      }

    os << indent << "Vertex Visibility: " << (this->VertsVisibility ? "On\n" : "Off\n");
    os << indent << "Line Visibility: " << (this->LinesVisibility ? "On\n" : "Off\n");
    os << indent << "Polygon Visibility: " << (this->PolysVisibility ? "On\n" : "Off\n");
    os << indent << "Triangle Strip Visibility: " << (this->StripsVisibility ? "On\n" : "Off\n");

   }
}
<|endoftext|>


<commit_before>#include "PWSfileV1V2.h"

#include <io.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <errno.h>

PWSfileV1V2::PWSfileV1V2(const CMyString &filename, RWmode mode, VERSION version)
  : PWSfile(filename,mode)
{
  m_curversion = version;
  m_IV = m_ipthing;
}

PWSfileV1V2::~PWSfileV1V2()
{
}

// Used to warn pre-2.0 users, and to identify the database as 2.x:
static const CMyString V2ItemName(" !!!Version 2 File Format!!! "
				  "Please upgrade to PasswordSafe 2.0"
				  " or later");
// Used to specify the exact version
static const CMyString VersionString("2.0");
static const CMyString AltVersionString("pre-2.0");

int PWSfileV1V2::WriteV2Header()
{
  CItemData header;
  // Fill out with V2-specific info
  // To make a dictionary attack a little harder, we make the length
  // of the first record (Name) variable, by appending variable length randomness
  // to the fixed string
  // OOPS - can't do this yet, since previous versions (pre-2.14) read the name
  // (in ReadV2Header)
  // and compare it directly to VersionString to check version - a small
  // mistake that would cause a pre-2.14 executable to barf reading a database
  // written by 2.14 and later.
  // #idef-ing this out, while correcting the code
  // in ReadV2Header. Perhaps this can be fixed a year from now?
#ifdef BREAK_PRE_2_14_COMPATIBILITY
  unsigned int rlen = RangeRand(62) + 2; // 64 is a trade-off...
  char *rbuf = new char[rlen];
  GetRandomData(rbuf, rlen-1);
  rbuf[rlen-1] = '\0'; // although zero may be there before - who cares?
  CMyString rname(V2ItemName);
  rname += rbuf;
  delete[] rbuf;
  header.SetName(rname, _T(""));
#else
  header.SetName(V2ItemName, _T(""));
#endif /* BREAK_PRE_2_14_COMPATIBILITY */
  header.SetPassword(VersionString);
  header.SetNotes(m_prefString);
  // need to fallback to V17, since the record
  // won't be readable otherwise!
  VERSION sv = m_curversion;
  m_curversion = V17;
  int status = WriteRecord(header);
  // restore after writing V17-format header
  m_curversion = sv;
  return status;
}

int PWSfileV1V2::ReadV2Header()
{
  CItemData header;
  // need to fallback to V17, since the header
  // is always written in this format
  VERSION sv = m_curversion;
  m_curversion = V17;
  int status = ReadRecord(header);
  // restore after reading V17-format header
  m_curversion = sv;
  if (status == SUCCESS) {
    const CMyString version = header.GetPassword();
    // Compare to AltVersionString due to silly mistake
    // "2.0" as well as "pre-2.0" are actually 2.0. sigh.
    status = (version == VersionString || version == AltVersionString)
      ? SUCCESS : WRONG_VERSION;
  }
  if (status == SUCCESS)
    m_prefString = header.GetNotes();
  return status;
}

int PWSfileV1V2::Open(const CMyString &passkey)
{
  int status = SUCCESS;

  ASSERT(m_curversion == V17 || m_curversion == V20);

  m_passkey = passkey;
  LPCTSTR passstr = LPCTSTR(m_passkey);

  if (m_rw == Write) {
#ifdef UNICODE
    m_fd = _wfopen((LPCTSTR)m_filename, _T("wb") );
#else
    m_fd = fopen((LPCTSTR)m_filename, _T("wb") );
#endif

    if (m_fd == NULL)
      return CANT_OPEN_FILE;

    // Following used to verify passkey against file's passkey
    unsigned char randstuff[StuffSize];
    unsigned char randhash[20];   // HashSize

    GetRandomData( randstuff, 8 );
    randstuff[8] = randstuff[9] = '\0';
    GenRandhash(m_passkey, randstuff, randhash);

    fwrite(randstuff, 1, 8, m_fd);
    fwrite(randhash, 1, 20, m_fd);

    GetRandomData(m_salt, SaltLength);

    fwrite(m_salt, 1, SaltLength, m_fd);

    GetRandomData( m_ipthing, 8);
    fwrite(m_ipthing, 1, 8, m_fd);
    m_fish = BlowFish::MakeBlowFish((const unsigned char *)passstr,
                                    m_passkey.GetLength(),
                                    m_salt, SaltLength);
    if (m_curversion == V20) {
      status = WriteV2Header();
    }
  } else { // open for read
#ifdef UNICODE
    m_fd = _wfopen((LPCTSTR) m_filename, _T("rb"));
#else
    m_fd = fopen((LPCTSTR) m_filename, _T("rb"));
#endif

    if (m_fd == NULL)
      return CANT_OPEN_FILE;
    status = CheckPassword(m_filename, m_passkey, m_fd);
    if (status != SUCCESS) {
      Close();
      return status;
    }
    fread(m_salt, 1, SaltLength, m_fd);
    fread(m_ipthing, 1, 8, m_fd);

    m_fish = BlowFish::MakeBlowFish((const unsigned char *)passstr,
                                    m_passkey.GetLength(),
                                    m_salt, SaltLength);
    if (m_curversion == V20)
      status = ReadV2Header();
  } // read mode
  return status;
}

int PWSfileV1V2::Close()
{
  return PWSfile::Close();
}

int PWSfileV1V2::CheckPassword(const CMyString &filename,
                               const CMyString &passkey, FILE *a_fd)
{
  FILE *fd = a_fd;
  if (fd == NULL) {
#ifdef UNICODE
    fd = _wfopen((LPCTSTR) filename, _T("rb"));
#else
    fd = fopen((LPCTSTR) filename, _T("rb"));
#endif
  }
  if (fd == NULL)
    return CANT_OPEN_FILE;

  unsigned char randstuff[StuffSize];
  unsigned char randhash[20];   // HashSize

   fread(randstuff, 1, 8, fd);
   randstuff[8] = randstuff[9] = '\0'; // Gross fugbix
   fread(randhash, 1, 20, fd);

   if (a_fd == NULL) // if we opened the file, we close it...
     fclose(fd);

  unsigned char temphash[20]; // HashSize
  GenRandhash(passkey, randstuff, temphash);

  if (0 != ::memcmp((char*)randhash,
		    (char*)temphash,
		    20)) {// HashSize
    return WRONG_PASSWORD;
  } else {
    return SUCCESS;
  }
}

int PWSfileV1V2::WriteRecord(const CItemData &item)
{
  ASSERT(m_fd != NULL);
  ASSERT(m_curversion != UNKNOWN_VERSION);
  int status = SUCCESS;

  switch (m_curversion) {
  case V17: {
    // 1.x programs totally ignore the type byte, hence safe to write it
    // (no need for two WriteCBC functions)
    // Note that 2.0 format still requires that the header be in this format,
    // So that old programs reading new databases won't crash,
    // This introduces a small security issue, in that the header is known text,
    // making the password susceptible to a dictionary attack on the first block,
    // rather than the hash^n in the beginning of the file.
    // we can help minimize this here by writing a random byte in the "type"
    // byte of the first block.

    CMyString name = item.GetName();
    // If name field already exists - use it. This is for the 2.0 header, as well as for files
    // that were imported and re-exported.
    if (name.IsEmpty()) {
      // The name in 1.7 consists of title + SPLTCHR + username
      // DEFUSERNAME was used in previous versions, but 2.0 converts this upon import
      // so it is not an issue here.
      // Prepend 2.0 group field to name, if not empty
      // i.e. group "finances" name "broker" -> "finances.broker"
      CMyString group = item.GetGroup();
      CMyString title = item.GetTitle();
      if (!group.IsEmpty()) {
        group += _T(".");
        group += title;
        title = group;
      }
      name = title;
      name += SPLTCHR;
      name += item.GetUser();
    }
    unsigned char dummy_type;
    GetRandomData(&dummy_type, 1);
    WriteCBC(dummy_type, name);
    WriteCBC(CItemData::PASSWORD, item.GetPassword());
    WriteCBC(CItemData::NOTES, item.GetNotes());
  }
    break;
  case V20: {
    {
      uuid_array_t uuid_array;
      item.GetUUID(uuid_array);
      WriteCBC(CItemData::UUID, uuid_array, sizeof(uuid_array));
    }
    WriteCBC(CItemData::GROUP, item.GetGroup());
    WriteCBC(CItemData::TITLE, item.GetTitle());
    WriteCBC(CItemData::USER, item.GetUser());
    WriteCBC(CItemData::PASSWORD, item.GetPassword());
    WriteCBC(CItemData::NOTES, item.GetNotes());
    WriteCBC(CItemData::END, _T(""));
  }
    break;
  default:
    ASSERT(0);
    status = UNSUPPORTED_VERSION;
  }
  return status;
}

static void ExtractAutoTypeCmd(CMyString &notesStr, CMyString &autotypeStr)
{
  CString instr(notesStr);
  int left = instr.Find(_T("autotype:"));
  if (left == -1) {
    autotypeStr = _T("");
  } else {
    CString tmp(notesStr);
    tmp = tmp.Mid(left+9); // throw out everything left of "autotype:"
    instr = instr.Left(left);
    int right = tmp.FindOneOf(_T("\r\n"));
    if (right != -1) {
      instr += tmp.Right(right);
      tmp = tmp.Left(right);
    }
    autotypeStr = CMyString(tmp);
    notesStr = CMyString(instr);
  }
}

static void ExtractURL(CMyString &notesStr, CMyString &outurl)
{
  CString instr(notesStr);
  // Extract first instance of (http|https|ftp)://[^ \t\r\n]+
  int left = instr.Find(_T("http://"));
  if (left == -1)
    left = instr.Find(_T("https://"));
  if (left == -1)
    left = instr.Find(_T("ftp://"));
  if (left == -1) {
    outurl = _T("");
  } else {
    CString url(instr);
    instr = notesStr.Left(left);
    url = url.Mid(left); // throw out everything left of URL
    int right = url.FindOneOf(_T(" \t\r\n"));
    if (right != -1) {
      instr += url.Right(right);
      url = url.Left(right);
    }
    outurl = CMyString(url);
    notesStr = CMyString(instr);
  }
}

int PWSfileV1V2::ReadRecord(CItemData &item)
{
  ASSERT(m_fd != NULL);
  ASSERT(m_curversion != UNKNOWN_VERSION);

  CMyString tempdata;
  int numread = 0;
  unsigned char type;
  // We do a double cast because the LPCTSTR cast operator is overridden by the CString class
  // to access the pointer we need,
  // but we in fact need it as an unsigned char. Grrrr.

  switch (m_curversion) {
  case V17: {
    // type is meaningless, but why write two versions of ReadCBC?
    numread += ReadCBC(type, tempdata);
    item.SetName(tempdata, m_defusername);
    numread += ReadCBC(type, tempdata);
    item.SetPassword(tempdata);
    numread += ReadCBC(type, tempdata);
    item.SetNotes(tempdata);
    // No UUID, so we create one here
    item.CreateUUID();
    // No Group - currently leave empty
    return (numread > 0) ? SUCCESS : END_OF_FILE;
  }
  case V20: {
    int emergencyExit = 255; // to avoid endless loop.
    int fieldLen; // zero means end of file reached
    bool endFound = false; // set to true when record end detected - happy end
    do {
      fieldLen = ReadCBC(type, tempdata);
      if (fieldLen > 0) {
	numread += fieldLen;
	switch (type) {
	case CItemData::TITLE:
	  item.SetTitle(tempdata); break;
	case CItemData::USER:
	  item.SetUser(tempdata); break;
	case CItemData::PASSWORD:
	  item.SetPassword(tempdata); break;
	case CItemData::NOTES: {
      CMyString autotypeStr, URLStr;
      ExtractAutoTypeCmd(tempdata, autotypeStr);
      ExtractURL(tempdata, URLStr);
	  item.SetNotes(tempdata);
      if (!autotypeStr.IsEmpty())
        item.SetAutoType(autotypeStr);
      if (!URLStr.IsEmpty())
        item.SetURL(URLStr);
      break;
    }
	case CItemData::END:
	  endFound = true; break;
	case CItemData::UUID: {
	  LPCTSTR ptr = LPCTSTR(tempdata);
	  uuid_array_t uuid_array;
	  for (int i = 0; i < sizeof(uuid_array); i++)
	    uuid_array[i] = (unsigned char)ptr[i];
	  item.SetUUID(uuid_array); break;
	}
	case CItemData::GROUP:
	  item.SetGroup(tempdata); break;
	  // just silently ignore fields we don't support.
	  // this is forward compatability...
	case CItemData::CTIME:
	case CItemData::ATIME:
	case CItemData::LTIME:
	case CItemData::POLICY:
	default:
	  // XXX Set a flag here so user can be warned that
	  // XXX we read a file format we don't fully support
	  break;
	} // switch
      } // if (fieldLen > 0)
    } while (!endFound && fieldLen > 0 && --emergencyExit > 0);
    return (numread > 0) ? SUCCESS : END_OF_FILE;
  }
  default:
    ASSERT(0);
    return UNSUPPORTED_VERSION;
  }
}
<commit_msg>Remerge autottype & htp into Notes for v1v2 WriteRecord<commit_after>#include "PWSfileV1V2.h"

#include <io.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <errno.h>

PWSfileV1V2::PWSfileV1V2(const CMyString &filename, RWmode mode, VERSION version)
  : PWSfile(filename,mode)
{
  m_curversion = version;
  m_IV = m_ipthing;
}

PWSfileV1V2::~PWSfileV1V2()
{
}

// Used to warn pre-2.0 users, and to identify the database as 2.x:
static const CMyString V2ItemName(" !!!Version 2 File Format!!! "
				  "Please upgrade to PasswordSafe 2.0"
				  " or later");
// Used to specify the exact version
static const CMyString VersionString("2.0");
static const CMyString AltVersionString("pre-2.0");

int PWSfileV1V2::WriteV2Header()
{
  CItemData header;
  // Fill out with V2-specific info
  // To make a dictionary attack a little harder, we make the length
  // of the first record (Name) variable, by appending variable length randomness
  // to the fixed string
  // OOPS - can't do this yet, since previous versions (pre-2.14) read the name
  // (in ReadV2Header)
  // and compare it directly to VersionString to check version - a small
  // mistake that would cause a pre-2.14 executable to barf reading a database
  // written by 2.14 and later.
  // #idef-ing this out, while correcting the code
  // in ReadV2Header. Perhaps this can be fixed a year from now?
#ifdef BREAK_PRE_2_14_COMPATIBILITY
  unsigned int rlen = RangeRand(62) + 2; // 64 is a trade-off...
  char *rbuf = new char[rlen];
  GetRandomData(rbuf, rlen-1);
  rbuf[rlen-1] = '\0'; // although zero may be there before - who cares?
  CMyString rname(V2ItemName);
  rname += rbuf;
  delete[] rbuf;
  header.SetName(rname, _T(""));
#else
  header.SetName(V2ItemName, _T(""));
#endif /* BREAK_PRE_2_14_COMPATIBILITY */
  header.SetPassword(VersionString);
  header.SetNotes(m_prefString);
  // need to fallback to V17, since the record
  // won't be readable otherwise!
  VERSION sv = m_curversion;
  m_curversion = V17;
  int status = WriteRecord(header);
  // restore after writing V17-format header
  m_curversion = sv;
  return status;
}

int PWSfileV1V2::ReadV2Header()
{
  CItemData header;
  // need to fallback to V17, since the header
  // is always written in this format
  VERSION sv = m_curversion;
  m_curversion = V17;
  int status = ReadRecord(header);
  // restore after reading V17-format header
  m_curversion = sv;
  if (status == SUCCESS) {
    const CMyString version = header.GetPassword();
    // Compare to AltVersionString due to silly mistake
    // "2.0" as well as "pre-2.0" are actually 2.0. sigh.
    status = (version == VersionString || version == AltVersionString)
      ? SUCCESS : WRONG_VERSION;
  }
  if (status == SUCCESS)
    m_prefString = header.GetNotes();
  return status;
}

int PWSfileV1V2::Open(const CMyString &passkey)
{
  int status = SUCCESS;

  ASSERT(m_curversion == V17 || m_curversion == V20);

  m_passkey = passkey;
  LPCTSTR passstr = LPCTSTR(m_passkey);

  if (m_rw == Write) {
#ifdef UNICODE
    m_fd = _wfopen((LPCTSTR)m_filename, _T("wb") );
#else
    m_fd = fopen((LPCTSTR)m_filename, _T("wb") );
#endif

    if (m_fd == NULL)
      return CANT_OPEN_FILE;

    // Following used to verify passkey against file's passkey
    unsigned char randstuff[StuffSize];
    unsigned char randhash[20];   // HashSize

    GetRandomData( randstuff, 8 );
    randstuff[8] = randstuff[9] = '\0';
    GenRandhash(m_passkey, randstuff, randhash);

    fwrite(randstuff, 1, 8, m_fd);
    fwrite(randhash, 1, 20, m_fd);

    GetRandomData(m_salt, SaltLength);

    fwrite(m_salt, 1, SaltLength, m_fd);

    GetRandomData( m_ipthing, 8);
    fwrite(m_ipthing, 1, 8, m_fd);
    m_fish = BlowFish::MakeBlowFish((const unsigned char *)passstr,
                                    m_passkey.GetLength(),
                                    m_salt, SaltLength);
    if (m_curversion == V20) {
      status = WriteV2Header();
    }
  } else { // open for read
#ifdef UNICODE
    m_fd = _wfopen((LPCTSTR) m_filename, _T("rb"));
#else
    m_fd = fopen((LPCTSTR) m_filename, _T("rb"));
#endif

    if (m_fd == NULL)
      return CANT_OPEN_FILE;
    status = CheckPassword(m_filename, m_passkey, m_fd);
    if (status != SUCCESS) {
      Close();
      return status;
    }
    fread(m_salt, 1, SaltLength, m_fd);
    fread(m_ipthing, 1, 8, m_fd);

    m_fish = BlowFish::MakeBlowFish((const unsigned char *)passstr,
                                    m_passkey.GetLength(),
                                    m_salt, SaltLength);
    if (m_curversion == V20)
      status = ReadV2Header();
  } // read mode
  return status;
}

int PWSfileV1V2::Close()
{
  return PWSfile::Close();
}

int PWSfileV1V2::CheckPassword(const CMyString &filename,
                               const CMyString &passkey, FILE *a_fd)
{
  FILE *fd = a_fd;
  if (fd == NULL) {
#ifdef UNICODE
    fd = _wfopen((LPCTSTR) filename, _T("rb"));
#else
    fd = fopen((LPCTSTR) filename, _T("rb"));
#endif
  }
  if (fd == NULL)
    return CANT_OPEN_FILE;

  unsigned char randstuff[StuffSize];
  unsigned char randhash[20];   // HashSize

   fread(randstuff, 1, 8, fd);
   randstuff[8] = randstuff[9] = '\0'; // Gross fugbix
   fread(randhash, 1, 20, fd);

   if (a_fd == NULL) // if we opened the file, we close it...
     fclose(fd);

  unsigned char temphash[20]; // HashSize
  GenRandhash(passkey, randstuff, temphash);

  if (0 != ::memcmp((char*)randhash,
		    (char*)temphash,
		    20)) {// HashSize
    return WRONG_PASSWORD;
  } else {
    return SUCCESS;
  }
}

static CMyString ReMergeNotes(const CItemData &item)
{
  CMyString notes = item.GetNotes();
  const CMyString url(item.GetURL());
  if (!url.IsEmpty()) {
    notes += _T("\r\n"); notes += url;
  }
  const CMyString at(item.GetAutoType());
  if (!at.IsEmpty()) {
    notes += _T("\r\nautotype:");
    notes += at;
  }
  return notes;
}

int PWSfileV1V2::WriteRecord(const CItemData &item)
{
  ASSERT(m_fd != NULL);
  ASSERT(m_curversion != UNKNOWN_VERSION);
  int status = SUCCESS;

  switch (m_curversion) {
  case V17: {
    // 1.x programs totally ignore the type byte, hence safe to write it
    // (no need for two WriteCBC functions)
    // Note that 2.0 format still requires that the header be in this format,
    // So that old programs reading new databases won't crash,
    // This introduces a small security issue, in that the header is known text,
    // making the password susceptible to a dictionary attack on the first block,
    // rather than the hash^n in the beginning of the file.
    // we can help minimize this here by writing a random byte in the "type"
    // byte of the first block.

    CMyString name = item.GetName();
    // If name field already exists - use it. This is for the 2.0 header, as well as for files
    // that were imported and re-exported.
    if (name.IsEmpty()) {
      // The name in 1.7 consists of title + SPLTCHR + username
      // DEFUSERNAME was used in previous versions, but 2.0 converts this upon import
      // so it is not an issue here.
      // Prepend 2.0 group field to name, if not empty
      // i.e. group "finances" name "broker" -> "finances.broker"
      CMyString group = item.GetGroup();
      CMyString title = item.GetTitle();
      if (!group.IsEmpty()) {
        group += _T(".");
        group += title;
        title = group;
      }
      name = title;
      name += SPLTCHR;
      name += item.GetUser();
    }
    unsigned char dummy_type;
    GetRandomData(&dummy_type, 1);
    WriteCBC(dummy_type, name);
    WriteCBC(CItemData::PASSWORD, item.GetPassword());
    WriteCBC(CItemData::NOTES, ReMergeNotes(item));
  }
    break;
  case V20: {
    {
      uuid_array_t uuid_array;
      item.GetUUID(uuid_array);
      WriteCBC(CItemData::UUID, uuid_array, sizeof(uuid_array));
    }
    WriteCBC(CItemData::GROUP, item.GetGroup());
    WriteCBC(CItemData::TITLE, item.GetTitle());
    WriteCBC(CItemData::USER, item.GetUser());
    WriteCBC(CItemData::PASSWORD, item.GetPassword());
    WriteCBC(CItemData::NOTES, ReMergeNotes(item));
    WriteCBC(CItemData::END, _T(""));
  }
    break;
  default:
    ASSERT(0);
    status = UNSUPPORTED_VERSION;
  }
  return status;
}

static void ExtractAutoTypeCmd(CMyString &notesStr, CMyString &autotypeStr)
{
  CString instr(notesStr);
  int left = instr.Find(_T("autotype:"));
  if (left == -1) {
    autotypeStr = _T("");
  } else {
    CString tmp(notesStr);
    tmp = tmp.Mid(left+9); // throw out everything left of "autotype:"
    instr = instr.Left(left);
    int right = tmp.FindOneOf(_T("\r\n"));
    if (right != -1) {
      instr += tmp.Right(right);
      tmp = tmp.Left(right);
    }
    autotypeStr = CMyString(tmp);
    notesStr = CMyString(instr);
  }
}

static void ExtractURL(CMyString &notesStr, CMyString &outurl)
{
  CString instr(notesStr);
  // Extract first instance of (http|https|ftp)://[^ \t\r\n]+
  int left = instr.Find(_T("http://"));
  if (left == -1)
    left = instr.Find(_T("https://"));
  if (left == -1)
    left = instr.Find(_T("ftp://"));
  if (left == -1) {
    outurl = _T("");
  } else {
    CString url(instr);
    instr = notesStr.Left(left);
    url = url.Mid(left); // throw out everything left of URL
    int right = url.FindOneOf(_T(" \t\r\n"));
    if (right != -1) {
      instr += url.Right(right);
      url = url.Left(right);
    }
    outurl = CMyString(url);
    notesStr = CMyString(instr);
  }
}

int PWSfileV1V2::ReadRecord(CItemData &item)
{
  ASSERT(m_fd != NULL);
  ASSERT(m_curversion != UNKNOWN_VERSION);

  CMyString tempdata;
  int numread = 0;
  unsigned char type;
  // We do a double cast because the LPCTSTR cast operator is overridden by the CString class
  // to access the pointer we need,
  // but we in fact need it as an unsigned char. Grrrr.

  switch (m_curversion) {
  case V17: {
    // type is meaningless, but why write two versions of ReadCBC?
    numread += ReadCBC(type, tempdata);
    item.SetName(tempdata, m_defusername);
    numread += ReadCBC(type, tempdata);
    item.SetPassword(tempdata);
    numread += ReadCBC(type, tempdata);
    item.SetNotes(tempdata);
    // No UUID, so we create one here
    item.CreateUUID();
    // No Group - currently leave empty
    return (numread > 0) ? SUCCESS : END_OF_FILE;
  }
  case V20: {
    int emergencyExit = 255; // to avoid endless loop.
    int fieldLen; // zero means end of file reached
    bool endFound = false; // set to true when record end detected - happy end
    do {
      fieldLen = ReadCBC(type, tempdata);
      if (fieldLen > 0) {
	numread += fieldLen;
	switch (type) {
	case CItemData::TITLE:
	  item.SetTitle(tempdata); break;
	case CItemData::USER:
	  item.SetUser(tempdata); break;
	case CItemData::PASSWORD:
	  item.SetPassword(tempdata); break;
	case CItemData::NOTES: {
      CMyString autotypeStr, URLStr;
      ExtractAutoTypeCmd(tempdata, autotypeStr);
      ExtractURL(tempdata, URLStr);
	  item.SetNotes(tempdata);
      if (!autotypeStr.IsEmpty())
        item.SetAutoType(autotypeStr);
      if (!URLStr.IsEmpty())
        item.SetURL(URLStr);
      break;
    }
	case CItemData::END:
	  endFound = true; break;
	case CItemData::UUID: {
	  LPCTSTR ptr = LPCTSTR(tempdata);
	  uuid_array_t uuid_array;
	  for (int i = 0; i < sizeof(uuid_array); i++)
	    uuid_array[i] = (unsigned char)ptr[i];
	  item.SetUUID(uuid_array); break;
	}
	case CItemData::GROUP:
	  item.SetGroup(tempdata); break;
	  // just silently ignore fields we don't support.
	  // this is forward compatability...
	case CItemData::CTIME:
	case CItemData::ATIME:
	case CItemData::LTIME:
	case CItemData::POLICY:
	default:
	  // XXX Set a flag here so user can be warned that
	  // XXX we read a file format we don't fully support
	  break;
	} // switch
      } // if (fieldLen > 0)
    } while (!endFound && fieldLen > 0 && --emergencyExit > 0);
    return (numread > 0) ? SUCCESS : END_OF_FILE;
  }
  default:
    ASSERT(0);
    return UNSUPPORTED_VERSION;
  }
}
<|endoftext|>


<commit_before>/******************************************************************************
* Controls.cpp
*
* Contains the yaw_controller() and depth_controller functions
******************************************************************************/
#include "Mapper.h"

/******************************************************************************
* float yaw_controller()
*
* Takes in readings from the IMU and returns a value between -1 and 1 (-100% -
* +100%) that the port and starboard thrusters should run at
******************************************************************************/
/*
float yaw_controller(bno055, yaw_pid)
{
	// control output //
	if( bno055.yaw < 180 ) // AUV is pointed right
	{
		// u[2] is negative

		motor_percent = yaw_pid.kp*(yaw_pid.err)
			+ yaw_pid.kd*(bno055.r)+ yaw_pid.ki*yaw_pid.i_err; // yaw controller

	}
	else		// AUV is pointed left
	{
		// u[2] is positive
		motor_percent = yaw_pid.kp*(yaw_pid.err)
			+ yaw_pid.kd*(bno055.r)
			+ yaw_pid.ki*yaw_pid.i_err; // yaw controller
	}
	// saturate yaw controller //
	if( u[2] > YAW_SAT )
	{
		motor_percent=YAW_SAT;
	}
	else if( motor_percent < -YAW_SAT )
	{
		motor_percent = -YAW_SAT;
	}

	yaw_pid.i_err += yaw_pid.err*DT;
	// set current yaw to be the old yaw //
	yaw_pid.oldyaw = bno055.yaw;

	return motor_percent;
}
*/

/******************************************************************************
* float depth_controller(float range)
*
* Takes a range-from-bottom reading from the laser range-finder code and
* returns a value between -1 and 1 (-100% - +100%) that the vertical thruster
* should run at
******************************************************************************/
/*
float depth_controller(float range)
{
	float vert_percent;			// vertical thruster output in a percentage
	float depth_sum_error = 0;	// accumulated range error for integral control
    float range_current;
    float range_old;
    float

	// accumulated range error for integral control //
	depth_sum_error += range - depth_pid.setpoint;

	if( range > depth_pid.setpoint )
	{
		vert_percent = depth_pid.kp*(range-depth_pid.setpoint)
			+ depth_pid.ki*(depth_sum_error)
			+ depth_pid.kd*((range_current-range_old)/DT);
	}
	else
	{
		// shut off vertical thruster //
		vert_percent = 0;
	}

	// saturate depth controller //
	if( vert_percent > DEPTH_SAT )
	{
		vert_percent = DEPTH_SAT;
	}
	else if( vert_percent < -DEPTH_SAT )
	{
		vert_percent = -DEPTH_SAT;
	}

	// set current depth to be the old depth //
	depth_pid.old = depth_pid.current;

	return vert_percent;
}
*/
<commit_msg>Uncommented Yaw Controller<commit_after>/******************************************************************************
* Controls.cpp
*
* Contains the yaw_controller() and depth_controller functions
******************************************************************************/
#include "Mapper.h"

/******************************************************************************
* float yaw_controller()
*
* Takes in readings from the IMU and returns a value between -1 and 1 (-100% -
* +100%) that the port and starboard thrusters should run at
******************************************************************************/

float yaw_controller(bno055, yaw_pid)
{
	// control output //
	if( bno055.yaw < 180 ) // AUV is pointed right
	{
		// u[2] is negative

		motor_percent = yaw_pid.kp*(yaw_pid.err)
			+ yaw_pid.kd*(bno055.r)+ yaw_pid.ki*yaw_pid.i_err; // yaw controller

	}
	else		// AUV is pointed left
	{
		// u[2] is positive
	motor_percent = yaw_pid.kp*(yaw_pid.err) + yaw_pid.kd*(bno055.r)
			+ yaw_pid.ki*yaw_pid.i_err; // yaw controller
	}
	// saturate yaw controller //
	if( u[2] > YAW_SAT )
	{
		motor_percent=YAW_SAT;
	}
	else if( motor_percent < -YAW_SAT )
	{
		motor_percent = -YAW_SAT;
	}

	yaw_pid.i_err += yaw_pid.err*DT;
	// set current yaw to be the old yaw //
	yaw_pid.oldyaw = bno055.yaw;

	return motor_percent;
}

/******************************************************************************
* float depth_controller(float range)
*
* Takes a range-from-bottom reading from the laser range-finder code and
* returns a value between -1 and 1 (-100% - +100%) that the vertical thruster
* should run at
******************************************************************************/
/*
float depth_controller(float range)
{
	float vert_percent;			// vertical thruster output in a percentage
	float depth_sum_error = 0;	// accumulated range error for integral control
    float range_current;
    float range_old;
    float

	// accumulated range error for integral control //
	depth_sum_error += range - depth_pid.setpoint;

	if( range > depth_pid.setpoint )
	{
		vert_percent = depth_pid.kp*(range-depth_pid.setpoint)
			+ depth_pid.ki*(depth_sum_error)
			+ depth_pid.kd*((range_current-range_old)/DT);
	}
	else
	{
		// shut off vertical thruster //
		vert_percent = 0;
	}

	// saturate depth controller //
	if( vert_percent > DEPTH_SAT )
	{
		vert_percent = DEPTH_SAT;
	}
	else if( vert_percent < -DEPTH_SAT )
	{
		vert_percent = -DEPTH_SAT;
	}

	// set current depth to be the old depth //
	depth_pid.old = depth_pid.current;

	return vert_percent;
}
*/
<|endoftext|>


<commit_before><commit_msg>remove unused variable "rep".<commit_after><|endoftext|>


<commit_before>#include "util.hh"

#include <string>
using namespace std;

internal_error::internal_error() : message("unknown internal error") {}

internal_error::internal_error(string msg) : message("internal error: " + msg) {}

string internal_error::get_message() {
	return message;
}

user_error::user_error() : message("unknown user error") {}

user_error::user_error(string msg) : message("user error: " + msg) {}

string user_error::get_message() {
	return message;
}

<commit_msg>bugfix<commit_after>#include "util.hh"
using namespace util;

#include <string>
using namespace std;

internal_error::internal_error() : message("unknown internal error") {}

internal_error::internal_error(string msg) : message("internal error: " + msg) {}

string internal_error::get_message() {
	return message;
}

user_error::user_error() : message("unknown user error") {}

user_error::user_error(string msg) : message("user error: " + msg) {}

string user_error::get_message() {
	return message;
}

<|endoftext|>


<commit_before>/*
 *
 * Copyright 2015, Google Inc.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *
 *     * Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above
 * copyright notice, this list of conditions and the following disclaimer
 * in the documentation and/or other materials provided with the
 * distribution.
 *     * Neither the name of Google Inc. nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 */

#include <cassert>
#include <functional>
#include <memory>
#include <string>
#include <thread>
#include <vector>
#include <sstream>

#include <grpc/grpc.h>
#include <grpc/support/histogram.h>
#include <grpc/support/log.h>
#include <gflags/gflags.h>
#include <grpc++/async_unary_call.h>
#include <grpc++/client_context.h>
#include <grpc++/status.h>
#include "test/core/util/grpc_profiler.h"
#include "test/cpp/util/create_test_channel.h"
#include "test/cpp/qps/qpstest.pb.h"

DEFINE_bool(enable_ssl, false, "Whether to use ssl/tls.");
DEFINE_int32(server_port, 0, "Server port.");
DEFINE_string(server_host, "127.0.0.1", "Server host.");
DEFINE_int32(client_threads, 4, "Number of client threads.");

// We have a configurable number of channels for sending RPCs.
// RPCs are sent round-robin on the available channels by the
// various threads. Interesting cases are 1 global channel or
// 1 per-thread channel, but we can support any number.
// The channels are assigned round-robin on an RPC by RPC basis
// rather than just at initialization time in order to also measure the
// impact of cache thrashing caused by channel changes. This is an issue
// if you are not in one of the above "interesting cases"
DEFINE_int32(client_channels, 4, "Number of client channels.");

DEFINE_int32(num_rpcs, 1000, "Number of RPCs per thread.");
DEFINE_int32(payload_size, 1, "Payload size in bytes");

// Alternatively, specify parameters for test as a workload so that multiple
// tests are initiated back-to-back. This is convenient for keeping a borg
// allocation consistent. This is a space-separated list of
// [threads channels num_rpcs payload_size ]*
DEFINE_string(workload, "", "Workload parameters");

using grpc::ChannelInterface;
using grpc::CreateTestChannel;
using grpc::testing::ServerStats;
using grpc::testing::SimpleRequest;
using grpc::testing::SimpleResponse;
using grpc::testing::StatsRequest;
using grpc::testing::TestService;

// In some distros, gflags is in the namespace google, and in some others,
// in gflags. This hack is enabling us to find both.
namespace google {}
namespace gflags {}
using namespace google;
using namespace gflags;

static double now() {
  gpr_timespec tv = gpr_now();
  return 1e9 * tv.tv_sec + tv.tv_nsec;
}

class ClientRpcContext {
 public:
  ClientRpcContext() {}
  virtual ~ClientRpcContext() {}
  virtual bool operator()() = 0;  // do next state, return false if steps done
  static void *tag(ClientRpcContext *c) { return reinterpret_cast<void *>(c); }
  static ClientRpcContext *detag(void *t) {
    return reinterpret_cast<ClientRpcContext *>(t);
  }
  virtual void report_stats(gpr_histogram *hist) = 0;
};
template <class RequestType, class ResponseType>
class ClientRpcContextUnaryImpl : public ClientRpcContext {
 public:
  ClientRpcContextUnaryImpl(
      const RequestType &req,
      std::function<
          std::unique_ptr<grpc::ClientAsyncResponseReader<ResponseType>>(
              grpc::ClientContext *, const RequestType &, void *)> start_req,
      std::function<void(grpc::Status, ResponseType *)> on_done)
      : context_(),
        req_(req),
        response_(),
        next_state_(&ClientRpcContextUnaryImpl::ReqSent),
        callback_(on_done),
        start_(now()),
        response_reader_(
            start_req(&context_, req_, ClientRpcContext::tag(this))) {}
  ~ClientRpcContextUnaryImpl() GRPC_OVERRIDE {}
  bool operator()() GRPC_OVERRIDE { return (this->*next_state_)(); }
  void report_stats(gpr_histogram *hist) GRPC_OVERRIDE {
    gpr_histogram_add(hist, now() - start_);
  }

 private:
  bool ReqSent() {
    next_state_ = &ClientRpcContextUnaryImpl::RespDone;
    response_reader_->Finish(&response_, &status_, ClientRpcContext::tag(this));
    return true;
  }
  bool RespDone() {
    next_state_ = &ClientRpcContextUnaryImpl::DoCallBack;
    return false;
  }
  bool DoCallBack() {
    callback_(status_, &response_);
    return false;
  }
  grpc::ClientContext context_;
  RequestType req_;
  ResponseType response_;
  bool (ClientRpcContextUnaryImpl::*next_state_)();
  std::function<void(grpc::Status, ResponseType *)> callback_;
  grpc::Status status_;
  double start_;
  std::unique_ptr<grpc::ClientAsyncResponseReader<ResponseType>>
      response_reader_;
};

static void RunTest(const int client_threads, const int client_channels,
                    const int num_rpcs, const int payload_size) {
  gpr_log(GPR_INFO,
          "QPS test with parameters\n"
          "enable_ssl = %d\n"
          "client_channels = %d\n"
          "client_threads = %d\n"
          "num_rpcs = %d\n"
          "payload_size = %d\n"
          "server_host:server_port = %s:%d\n\n",
          FLAGS_enable_ssl, client_channels, client_threads, num_rpcs,
          payload_size, FLAGS_server_host.c_str(), FLAGS_server_port);

  std::ostringstream oss;
  oss << FLAGS_server_host << ":" << FLAGS_server_port;

  class ClientChannelInfo {
   public:
    explicit ClientChannelInfo(const grpc::string &server)
        : channel_(CreateTestChannel(server, FLAGS_enable_ssl)),
          stub_(TestService::NewStub(channel_)) {}
    ChannelInterface *get_channel() { return channel_.get(); }
    TestService::Stub *get_stub() { return stub_.get(); }

   private:
    std::shared_ptr<ChannelInterface> channel_;
    std::unique_ptr<TestService::Stub> stub_;
  };

  std::vector<ClientChannelInfo> channels;
  for (int i = 0; i < client_channels; i++) {
    channels.push_back(ClientChannelInfo(oss.str()));
  }

  std::vector<std::thread> threads;  // Will add threads when ready to execute
  std::vector<::gpr_histogram *> thread_stats(client_threads);

  TestService::Stub *stub_stats = channels[0].get_stub();
  grpc::ClientContext context_stats_begin;
  StatsRequest stats_request;
  ServerStats server_stats_begin;
  stats_request.set_test_num(0);
  grpc::Status status_beg = stub_stats->CollectServerStats(
      &context_stats_begin, stats_request, &server_stats_begin);

  grpc_profiler_start("qps_client_async.prof");

  auto CheckDone = [=](grpc::Status s, SimpleResponse *response) {
    GPR_ASSERT(s.IsOk() && (response->payload().type() ==
                            grpc::testing::PayloadType::COMPRESSABLE) &&
               (response->payload().body().length() ==
                static_cast<size_t>(payload_size)));
  };

  for (int i = 0; i < client_threads; i++) {
    gpr_histogram *hist = gpr_histogram_create(0.01, 60e9);
    GPR_ASSERT(hist != NULL);
    thread_stats[i] = hist;

    threads.push_back(std::thread(
        [hist, client_threads, client_channels, num_rpcs, payload_size,
         &channels, &CheckDone](int channel_num) {
          using namespace std::placeholders;
          SimpleRequest request;
          request.set_response_type(grpc::testing::PayloadType::COMPRESSABLE);
          request.set_response_size(payload_size);

          grpc::CompletionQueue cli_cq;

          int rpcs_sent = 0;
          while (rpcs_sent < num_rpcs) {
            rpcs_sent++;
            TestService::Stub *stub = channels[channel_num].get_stub();
            grpc::ClientContext context;
            auto start_req = std::bind(&TestService::Stub::AsyncUnaryCall, stub,
                                       _1, _2, &cli_cq, _3);
            new ClientRpcContextUnaryImpl<SimpleRequest, SimpleResponse>(
                request, start_req, CheckDone);
            void *got_tag;
            bool ok;

            // Need to call 2 next for every 1 RPC (1 for req done, 1 for resp
            // done)
            cli_cq.Next(&got_tag, &ok);
            if (!ok) break;
            ClientRpcContext *ctx = ClientRpcContext::detag(got_tag);
            if ((*ctx)() == false) {
              // call the callback and then delete it
              (*ctx)();
              delete ctx;
            }
            cli_cq.Next(&got_tag, &ok);
            if (!ok) break;
            ctx = ClientRpcContext::detag(got_tag);
            if ((*ctx)() == false) {
              // call the callback and then delete it
              ctx->report_stats(hist);
              (*ctx)();
              delete ctx;
            }
            // Now do runtime round-robin assignment of the next
            // channel number
            channel_num += client_threads;
            channel_num %= client_channels;
          }
        },
        i % client_channels));
  }

  gpr_histogram *hist = gpr_histogram_create(0.01, 60e9);
  GPR_ASSERT(hist != NULL);
  for (auto &t : threads) {
    t.join();
  }

  grpc_profiler_stop();

  for (int i = 0; i < client_threads; i++) {
    gpr_histogram *h = thread_stats[i];
    gpr_log(GPR_INFO, "latency at thread %d (50/90/95/99/99.9): %f/%f/%f/%f/%f",
            i, gpr_histogram_percentile(h, 50), gpr_histogram_percentile(h, 90),
            gpr_histogram_percentile(h, 95), gpr_histogram_percentile(h, 99),
            gpr_histogram_percentile(h, 99.9));
    gpr_histogram_merge(hist, h);
    gpr_histogram_destroy(h);
  }

  gpr_log(
      GPR_INFO,
      "latency across %d threads with %d channels and %d payload "
      "(50/90/95/99/99.9): %f / %f / %f / %f / %f",
      client_threads, client_channels, payload_size,
      gpr_histogram_percentile(hist, 50), gpr_histogram_percentile(hist, 90),
      gpr_histogram_percentile(hist, 95), gpr_histogram_percentile(hist, 99),
      gpr_histogram_percentile(hist, 99.9));
  gpr_histogram_destroy(hist);

  grpc::ClientContext context_stats_end;
  ServerStats server_stats_end;
  grpc::Status status_end = stub_stats->CollectServerStats(
      &context_stats_end, stats_request, &server_stats_end);

  double elapsed = server_stats_end.time_now() - server_stats_begin.time_now();
  int total_rpcs = client_threads * num_rpcs;
  double utime = server_stats_end.time_user() - server_stats_begin.time_user();
  double stime =
      server_stats_end.time_system() - server_stats_begin.time_system();
  gpr_log(GPR_INFO,
          "Elapsed time: %.3f\n"
          "RPC Count: %d\n"
          "QPS: %.3f\n"
          "System time: %.3f\n"
          "User time: %.3f\n"
          "Resource usage: %.1f%%\n",
          elapsed, total_rpcs, total_rpcs / elapsed, stime, utime,
          (stime + utime) / elapsed * 100.0);
}

int main(int argc, char **argv) {
  grpc_init();
  ParseCommandLineFlags(&argc, &argv, true);

  GPR_ASSERT(FLAGS_server_port);

  if (FLAGS_workload.length() == 0) {
    RunTest(FLAGS_client_threads, FLAGS_client_channels, FLAGS_num_rpcs,
            FLAGS_payload_size);
  } else {
    std::istringstream workload(FLAGS_workload);
    int client_threads, client_channels, num_rpcs, payload_size;
    workload >> client_threads;
    while (!workload.eof()) {
      workload >> client_channels >> num_rpcs >> payload_size;
      RunTest(client_threads, client_channels, num_rpcs, payload_size);
      workload >> client_threads;
    }
    gpr_log(GPR_INFO, "Done with specified workload.");
  }

  grpc_shutdown();
  return 0;
}
<commit_msg><:: -> < ::<commit_after>/*
 *
 * Copyright 2015, Google Inc.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *
 *     * Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above
 * copyright notice, this list of conditions and the following disclaimer
 * in the documentation and/or other materials provided with the
 * distribution.
 *     * Neither the name of Google Inc. nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 */

#include <cassert>
#include <functional>
#include <memory>
#include <string>
#include <thread>
#include <vector>
#include <sstream>

#include <grpc/grpc.h>
#include <grpc/support/histogram.h>
#include <grpc/support/log.h>
#include <gflags/gflags.h>
#include <grpc++/async_unary_call.h>
#include <grpc++/client_context.h>
#include <grpc++/status.h>
#include "test/core/util/grpc_profiler.h"
#include "test/cpp/util/create_test_channel.h"
#include "test/cpp/qps/qpstest.pb.h"

DEFINE_bool(enable_ssl, false, "Whether to use ssl/tls.");
DEFINE_int32(server_port, 0, "Server port.");
DEFINE_string(server_host, "127.0.0.1", "Server host.");
DEFINE_int32(client_threads, 4, "Number of client threads.");

// We have a configurable number of channels for sending RPCs.
// RPCs are sent round-robin on the available channels by the
// various threads. Interesting cases are 1 global channel or
// 1 per-thread channel, but we can support any number.
// The channels are assigned round-robin on an RPC by RPC basis
// rather than just at initialization time in order to also measure the
// impact of cache thrashing caused by channel changes. This is an issue
// if you are not in one of the above "interesting cases"
DEFINE_int32(client_channels, 4, "Number of client channels.");

DEFINE_int32(num_rpcs, 1000, "Number of RPCs per thread.");
DEFINE_int32(payload_size, 1, "Payload size in bytes");

// Alternatively, specify parameters for test as a workload so that multiple
// tests are initiated back-to-back. This is convenient for keeping a borg
// allocation consistent. This is a space-separated list of
// [threads channels num_rpcs payload_size ]*
DEFINE_string(workload, "", "Workload parameters");

using grpc::ChannelInterface;
using grpc::CreateTestChannel;
using grpc::testing::ServerStats;
using grpc::testing::SimpleRequest;
using grpc::testing::SimpleResponse;
using grpc::testing::StatsRequest;
using grpc::testing::TestService;

// In some distros, gflags is in the namespace google, and in some others,
// in gflags. This hack is enabling us to find both.
namespace google {}
namespace gflags {}
using namespace google;
using namespace gflags;

static double now() {
  gpr_timespec tv = gpr_now();
  return 1e9 * tv.tv_sec + tv.tv_nsec;
}

class ClientRpcContext {
 public:
  ClientRpcContext() {}
  virtual ~ClientRpcContext() {}
  virtual bool operator()() = 0;  // do next state, return false if steps done
  static void *tag(ClientRpcContext *c) { return reinterpret_cast<void *>(c); }
  static ClientRpcContext *detag(void *t) {
    return reinterpret_cast<ClientRpcContext *>(t);
  }
  virtual void report_stats(gpr_histogram *hist) = 0;
};
template <class RequestType, class ResponseType>
class ClientRpcContextUnaryImpl : public ClientRpcContext {
 public:
  ClientRpcContextUnaryImpl(
      const RequestType &req,
      std::function<
          std::unique_ptr<grpc::ClientAsyncResponseReader<ResponseType>>(
              grpc::ClientContext *, const RequestType &, void *)> start_req,
      std::function<void(grpc::Status, ResponseType *)> on_done)
      : context_(),
        req_(req),
        response_(),
        next_state_(&ClientRpcContextUnaryImpl::ReqSent),
        callback_(on_done),
        start_(now()),
        response_reader_(
            start_req(&context_, req_, ClientRpcContext::tag(this))) {}
  ~ClientRpcContextUnaryImpl() GRPC_OVERRIDE {}
  bool operator()() GRPC_OVERRIDE { return (this->*next_state_)(); }
  void report_stats(gpr_histogram *hist) GRPC_OVERRIDE {
    gpr_histogram_add(hist, now() - start_);
  }

 private:
  bool ReqSent() {
    next_state_ = &ClientRpcContextUnaryImpl::RespDone;
    response_reader_->Finish(&response_, &status_, ClientRpcContext::tag(this));
    return true;
  }
  bool RespDone() {
    next_state_ = &ClientRpcContextUnaryImpl::DoCallBack;
    return false;
  }
  bool DoCallBack() {
    callback_(status_, &response_);
    return false;
  }
  grpc::ClientContext context_;
  RequestType req_;
  ResponseType response_;
  bool (ClientRpcContextUnaryImpl::*next_state_)();
  std::function<void(grpc::Status, ResponseType *)> callback_;
  grpc::Status status_;
  double start_;
  std::unique_ptr<grpc::ClientAsyncResponseReader<ResponseType>>
      response_reader_;
};

static void RunTest(const int client_threads, const int client_channels,
                    const int num_rpcs, const int payload_size) {
  gpr_log(GPR_INFO,
          "QPS test with parameters\n"
          "enable_ssl = %d\n"
          "client_channels = %d\n"
          "client_threads = %d\n"
          "num_rpcs = %d\n"
          "payload_size = %d\n"
          "server_host:server_port = %s:%d\n\n",
          FLAGS_enable_ssl, client_channels, client_threads, num_rpcs,
          payload_size, FLAGS_server_host.c_str(), FLAGS_server_port);

  std::ostringstream oss;
  oss << FLAGS_server_host << ":" << FLAGS_server_port;

  class ClientChannelInfo {
   public:
    explicit ClientChannelInfo(const grpc::string &server)
        : channel_(CreateTestChannel(server, FLAGS_enable_ssl)),
          stub_(TestService::NewStub(channel_)) {}
    ChannelInterface *get_channel() { return channel_.get(); }
    TestService::Stub *get_stub() { return stub_.get(); }

   private:
    std::shared_ptr<ChannelInterface> channel_;
    std::unique_ptr<TestService::Stub> stub_;
  };

  std::vector<ClientChannelInfo> channels;
  for (int i = 0; i < client_channels; i++) {
    channels.push_back(ClientChannelInfo(oss.str()));
  }

  std::vector<std::thread> threads;  // Will add threads when ready to execute
  std::vector< ::gpr_histogram *> thread_stats(client_threads);

  TestService::Stub *stub_stats = channels[0].get_stub();
  grpc::ClientContext context_stats_begin;
  StatsRequest stats_request;
  ServerStats server_stats_begin;
  stats_request.set_test_num(0);
  grpc::Status status_beg = stub_stats->CollectServerStats(
      &context_stats_begin, stats_request, &server_stats_begin);

  grpc_profiler_start("qps_client_async.prof");

  auto CheckDone = [=](grpc::Status s, SimpleResponse *response) {
    GPR_ASSERT(s.IsOk() && (response->payload().type() ==
                            grpc::testing::PayloadType::COMPRESSABLE) &&
               (response->payload().body().length() ==
                static_cast<size_t>(payload_size)));
  };

  for (int i = 0; i < client_threads; i++) {
    gpr_histogram *hist = gpr_histogram_create(0.01, 60e9);
    GPR_ASSERT(hist != NULL);
    thread_stats[i] = hist;

    threads.push_back(std::thread(
        [hist, client_threads, client_channels, num_rpcs, payload_size,
         &channels, &CheckDone](int channel_num) {
          using namespace std::placeholders;
          SimpleRequest request;
          request.set_response_type(grpc::testing::PayloadType::COMPRESSABLE);
          request.set_response_size(payload_size);

          grpc::CompletionQueue cli_cq;

          int rpcs_sent = 0;
          while (rpcs_sent < num_rpcs) {
            rpcs_sent++;
            TestService::Stub *stub = channels[channel_num].get_stub();
            grpc::ClientContext context;
            auto start_req = std::bind(&TestService::Stub::AsyncUnaryCall, stub,
                                       _1, _2, &cli_cq, _3);
            new ClientRpcContextUnaryImpl<SimpleRequest, SimpleResponse>(
                request, start_req, CheckDone);
            void *got_tag;
            bool ok;

            // Need to call 2 next for every 1 RPC (1 for req done, 1 for resp
            // done)
            cli_cq.Next(&got_tag, &ok);
            if (!ok) break;
            ClientRpcContext *ctx = ClientRpcContext::detag(got_tag);
            if ((*ctx)() == false) {
              // call the callback and then delete it
              (*ctx)();
              delete ctx;
            }
            cli_cq.Next(&got_tag, &ok);
            if (!ok) break;
            ctx = ClientRpcContext::detag(got_tag);
            if ((*ctx)() == false) {
              // call the callback and then delete it
              ctx->report_stats(hist);
              (*ctx)();
              delete ctx;
            }
            // Now do runtime round-robin assignment of the next
            // channel number
            channel_num += client_threads;
            channel_num %= client_channels;
          }
        },
        i % client_channels));
  }

  gpr_histogram *hist = gpr_histogram_create(0.01, 60e9);
  GPR_ASSERT(hist != NULL);
  for (auto &t : threads) {
    t.join();
  }

  grpc_profiler_stop();

  for (int i = 0; i < client_threads; i++) {
    gpr_histogram *h = thread_stats[i];
    gpr_log(GPR_INFO, "latency at thread %d (50/90/95/99/99.9): %f/%f/%f/%f/%f",
            i, gpr_histogram_percentile(h, 50), gpr_histogram_percentile(h, 90),
            gpr_histogram_percentile(h, 95), gpr_histogram_percentile(h, 99),
            gpr_histogram_percentile(h, 99.9));
    gpr_histogram_merge(hist, h);
    gpr_histogram_destroy(h);
  }

  gpr_log(
      GPR_INFO,
      "latency across %d threads with %d channels and %d payload "
      "(50/90/95/99/99.9): %f / %f / %f / %f / %f",
      client_threads, client_channels, payload_size,
      gpr_histogram_percentile(hist, 50), gpr_histogram_percentile(hist, 90),
      gpr_histogram_percentile(hist, 95), gpr_histogram_percentile(hist, 99),
      gpr_histogram_percentile(hist, 99.9));
  gpr_histogram_destroy(hist);

  grpc::ClientContext context_stats_end;
  ServerStats server_stats_end;
  grpc::Status status_end = stub_stats->CollectServerStats(
      &context_stats_end, stats_request, &server_stats_end);

  double elapsed = server_stats_end.time_now() - server_stats_begin.time_now();
  int total_rpcs = client_threads * num_rpcs;
  double utime = server_stats_end.time_user() - server_stats_begin.time_user();
  double stime =
      server_stats_end.time_system() - server_stats_begin.time_system();
  gpr_log(GPR_INFO,
          "Elapsed time: %.3f\n"
          "RPC Count: %d\n"
          "QPS: %.3f\n"
          "System time: %.3f\n"
          "User time: %.3f\n"
          "Resource usage: %.1f%%\n",
          elapsed, total_rpcs, total_rpcs / elapsed, stime, utime,
          (stime + utime) / elapsed * 100.0);
}

int main(int argc, char **argv) {
  grpc_init();
  ParseCommandLineFlags(&argc, &argv, true);

  GPR_ASSERT(FLAGS_server_port);

  if (FLAGS_workload.length() == 0) {
    RunTest(FLAGS_client_threads, FLAGS_client_channels, FLAGS_num_rpcs,
            FLAGS_payload_size);
  } else {
    std::istringstream workload(FLAGS_workload);
    int client_threads, client_channels, num_rpcs, payload_size;
    workload >> client_threads;
    while (!workload.eof()) {
      workload >> client_channels >> num_rpcs >> payload_size;
      RunTest(client_threads, client_channels, num_rpcs, payload_size);
      workload >> client_threads;
    }
    gpr_log(GPR_INFO, "Done with specified workload.");
  }

  grpc_shutdown();
  return 0;
}
<|endoftext|>