<commit_before>// $Id$
//
// Task to skim ESD files.
//
//

#include "AliEsdSkimTask.h"
#include <TClonesArray.h>
#include <TFile.h>
#include <TTree.h>
#include "AliAnalysisManager.h"
#include "AliESDEvent.h"
#include "AliESDtrackCuts.h"
#include "AliMultiplicity.h"

//_________________________________________________________________________________________________
AliEsdSkimTask::AliEsdSkimTask(const char *opt) :
  AliAnalysisTaskSE(opt), fEvent(0), fTree(0), fCuts(0),
  fDoZDC(1), fDoV0(1), fDoT0(1), fDoTPCv(1), fDoSPDv(1), fDoPriv(1),
  fDoEmCs(1), fDoPCs(1), fDoEmT(1), fDoPT(1), fDoTracks(1), fDoMult(1),
  fDoTof(1), fDoPileup(1), fDoClus(1), fEmcNames(""),
  fDoMiniTracks(0), fTracks("Tracks"), fPhosClusOnly(0)
{
  // Constructor.

  if (!opt)
    return;

  DefineOutput(1, TTree::Class());
}

//_________________________________________________________________________________________________
void AliEsdSkimTask::UserExec(Option_t */*opt*/)
{
  // Process event.

  AliESDEvent *esdin = dynamic_cast<AliESDEvent*>(InputEvent());
  if (!esdin)
    return;

  AliAnalysisManager *am = AliAnalysisManager::GetAnalysisManager();

  fEvent->Reset();

  TList* objsin  = esdin->GetList();
  TList* objsout = fEvent->GetList();

  AliESDHeader *header = dynamic_cast<AliESDHeader*>(objsin->FindObject("AliESDHeader"));
  if (header) {
    am->LoadBranch("AliESDHeader.");
    *header = *esdin->GetHeader();
  }
  AliESDRun *run = dynamic_cast<AliESDRun*>(objsin->FindObject("AliESDRun"));
  if (run) {
    am->LoadBranch("AliESDRun.");
    *run = *esdin->GetESDRun();
  }
  AliESDZDC *zdc = dynamic_cast<AliESDZDC*>(objsin->FindObject("AliESDZDC"));
  if (zdc) {
    am->LoadBranch("AliESDZDC.");
    *zdc = *esdin->GetESDZDC();
  }
  AliESDVZERO *v0 = dynamic_cast<AliESDVZERO*>(objsin->FindObject("AliESDVZERO"));
  if (v0) {
    am->LoadBranch("AliESDVZERO.");
    *v0 = *esdin->GetVZEROData();
  }
  AliESDTZERO *t0 = dynamic_cast<AliESDTZERO*>(objsin->FindObject("AliESDTZERO"));
  if (t0) {
    am->LoadBranch("AliESDTZERO.");
    *t0 = *esdin->GetESDTZERO();
  }
  AliESDVertex *tpcv = dynamic_cast<AliESDVertex*>(objsin->FindObject("TPCVertex"));
  if (tpcv) {
    am->LoadBranch("TPCVertex.");
    *tpcv = *esdin->GetPrimaryVertexTPC();
  }
  AliESDVertex *spdv = dynamic_cast<AliESDVertex*>(objsin->FindObject("SPDVertex"));
  if (spdv) {
    am->LoadBranch("SPDVertex.");
    *spdv = *esdin->GetPrimaryVertexSPD();
  }
  AliESDVertex *priv = dynamic_cast<AliESDVertex*>(objsin->FindObject("PrimaryVertex"));
  if (priv) {
    am->LoadBranch("PrimaryVertex.");
    *priv = *esdin->GetPrimaryVertexTracks();
  }
  AliESDCaloCells *ecells = dynamic_cast<AliESDCaloCells*>(objsin->FindObject("EMCALCells"));
  if (ecells) {
    am->LoadBranch("EMCALCells.");
    *ecells = *esdin->GetEMCALCells();
  }
  AliESDCaloCells *pcells = dynamic_cast<AliESDCaloCells*>(objsin->FindObject("PHOSCells"));
  if (pcells) {
    am->LoadBranch("PHOSCells.");
    *pcells = *esdin->GetPHOSCells();
  }
  AliESDCaloTrigger *etrig = dynamic_cast<AliESDCaloTrigger*>(objsin->FindObject("EMCALTrigger"));
  if (etrig) {
    am->LoadBranch("EMCALTrigger.");
    *etrig = *esdin->GetCaloTrigger("EMCAL");
  }
  AliESDCaloTrigger *ptrig = dynamic_cast<AliESDCaloTrigger*>(objsin->FindObject("PHOSTrigger"));
  if (ptrig) {
    am->LoadBranch("PHOSTrigger.");
    *ptrig = *esdin->GetCaloTrigger("PHOS");
  }

  AliMultiplicity *mult = dynamic_cast<AliMultiplicity*>(objsin->FindObject("AliMultiplicity"));
  if (mult) {
    am->LoadBranch("AliMultiplicity.");
    *mult = *esdin->GetMultiplicity();
  }

  AliTOFHeader *tofh = dynamic_cast<AliTOFHeader*>(objsin->FindObject("AliTOFHeader"));
  if (tofh) {
    am->LoadBranch("AliTOFHeader.");
    *tofh = *esdin->GetTOFHeader();
  }
  TClonesArray *spup = dynamic_cast<TClonesArray*>(objsin->FindObject("SPDPileupVertices"));
  if (spup) {
    am->LoadBranch("SPDPileupVertices");
    Int_t N = esdin->GetNumberOfPileupVerticesSPD();
    for (Int_t i=0; i<N; ++i) {
      const AliESDVertex *vtx = esdin->GetPileupVertexSPD(i);
      if (vtx)
        fEvent->AddPileupVertexSPD(vtx);
    }
  }
  TClonesArray *tpup = dynamic_cast<TClonesArray*>(objsin->FindObject("TrkPileupVertices"));
  if (tpup) {
    am->LoadBranch("TrkPileupVertices");
    Int_t N = esdin->GetNumberOfPileupVerticesTracks();
    for (Int_t i=0; i<N; ++i) {
      const AliESDVertex *vtx = esdin->GetPileupVertexTracks(i);
      if (vtx)
        fEvent->AddPileupVertexTracks(vtx);
    }
  }
  TClonesArray *clus = dynamic_cast<TClonesArray*>(objsin->FindObject("CaloClusters"));
  if (clus) {
    am->LoadBranch("");
    Int_t N = esdin->GetNumberOfCaloClusters();
    for (Int_t i=0; i<N; ++i) {
      AliESDCaloCluster *c = esdin->GetCaloCluster(i);
      if (fPhosClusOnly && c->IsEMCAL())
        continue;
      if (c)
        fEvent->AddCaloCluster(c);
    }
  }
  TObjArray *namearr = fEmcNames.Tokenize(";");
  if (namearr) {
    for (Int_t i=0; i<namearr->GetEntries(); ++i) {
      TString cname(namearr->At(i)->GetName());
      if (cname.Length()<=0)
        continue;
      TClonesArray *arrin  = dynamic_cast<TClonesArray*>(objsin->FindObject(cname));
      TClonesArray *arrout = dynamic_cast<TClonesArray*>(objsout->FindObject(cname));
      //AliFatal(Form("Can not find tracks with name %s", fTracks.Data()));
      arrout->Delete();
      const Int_t N = arrin->GetEntries();
      for (Int_t iC=0, nC=0; iC<N; ++iC) {
        AliESDCaloCluster *c = dynamic_cast<AliESDCaloCluster*>(arrin->At(iC));
        if (!c)
          continue;
        new ((*arrout)[nC++]) AliESDCaloCluster(*c);
      }
    }
    delete namearr;
  }
  if (fDoTracks) {
    am->LoadBranch("Tracks");
    TClonesArray *tracks = dynamic_cast<TClonesArray*>(objsin->FindObject(fTracks));
    if (!tracks) {
      AliFatal(Form("Can not find tracks with name %s", fTracks.Data()));
      return;
    }
    const Int_t Ntracks = tracks->GetEntries();
    Int_t nacc = 0;
    for (Int_t iTracks = 0; iTracks < Ntracks; ++iTracks) {
      AliESDtrack *track = dynamic_cast<AliESDtrack*>(tracks->At(iTracks));
      if (!track)
        continue;
      if (fCuts) {
        if (!fCuts->IsSelected(track))
          continue;
      }
      if (fDoMiniTracks) {
        track->MakeMiniESDtrack();
      }
      fEvent->AddTrack(track);
      ++nacc;
    }
    if (fCuts)
      AliInfo(Form("Selected %d out of %d \n", nacc, Ntracks));
  }
  fTree->Fill();
}

//_________________________________________________________________________________________________
void AliEsdSkimTask::UserCreateOutputObjects()
{
  // Create output objects.

  fTree = new TTree("esdTree", "Tree with skimmed ESD objects");
  fEvent = new AliESDEvent;
  fEvent->AddObject(new AliESDHeader());
  fEvent->AddObject(new AliESDRun());
  if (fDoZDC)
    fEvent->AddObject(new AliESDZDC());
  if (fDoV0)
    fEvent->AddObject(new AliESDVZERO());
  if (fDoT0)
    fEvent->AddObject(new AliESDTZERO());
  if (fDoTPCv) {
    AliESDVertex *tpcv = new AliESDVertex();
    tpcv->SetName("TPCVertex");
    fEvent->AddObject(tpcv);
  }
  if (fDoSPDv) {
    AliESDVertex *spdv = new AliESDVertex();
    spdv->SetName("SPDVertex");
    fEvent->AddObject(spdv);
  }
  if (fDoPriv) {
    AliESDVertex *priv = new AliESDVertex();
    priv->SetName("PrimaryVertex");
    fEvent->AddObject(priv);
  }
  if (fDoEmCs) {
    fEvent->AddObject(new AliESDCaloCells("EMCALCells","EMCALCells"));
  }
  if (fDoPCs) {
    fEvent->AddObject(new AliESDCaloCells("PHOSCells","PHOSCells"));
  }
  if (fDoEmT) {
    AliESDCaloTrigger *etrig = new AliESDCaloTrigger;
    etrig->SetName("EMCALTrigger");
    fEvent->AddObject(etrig);
  }
  if (fDoPT) {
    AliESDCaloTrigger *ptrig = new AliESDCaloTrigger;
    ptrig->SetName("PHOSTrigger");
    fEvent->AddObject(ptrig);
  }
  if (fDoMult) {
    fEvent->AddObject(new AliMultiplicity());
  }
  if (fDoPileup) {
    TClonesArray *arr1 = new TClonesArray("AliESDVertex",0);
    arr1->SetName("SPDPileupVertices");
    fEvent->AddObject(arr1);
    TClonesArray *arr2 = new TClonesArray("AliESDVertex",0);
    arr2->SetName("TPCPileupVertices");
    fEvent->AddObject(arr2);
  }
  if (fDoTof) {
    fEvent->AddObject(new AliTOFHeader());
  }
  if (fDoClus) {
    TClonesArray *arr = new TClonesArray("AliESDCaloCluster",0);
    arr->SetName("CaloClusters");
    fEvent->AddObject(arr);
  }
  TObjArray *namearr = fEmcNames.Tokenize(";");
  if (namearr) {
    for (Int_t i=0; i<namearr->GetEntries(); ++i) {
      TString cname(namearr->At(i)->GetName());
      if (cname.Length()<=0)
        continue;
      TClonesArray *arr = new TClonesArray("AliESDCaloCluster",0);
      arr->SetName(cname);
      fEvent->AddObject(arr);
    }
    delete namearr;
  }
  if (fDoTracks) {
    TClonesArray *arr = new TClonesArray("AliESDtrack",0);
    arr->SetName("Tracks");
    fEvent->AddObject(arr);
  }
  fEvent->GetStdContent();
  fEvent->WriteToTree(fTree);
  fTree->GetUserInfo()->Add(fEvent);
  TFile *file = OpenFile(1);
  fTree->SetDirectory(file);
  fTree->SetAutoFlush(-1024*1024*1024);
  fTree->SetAutoSave(-1024*1024*1024);
  PostData(1,fTree);
}
<commit_msg>make mini esd tracks<commit_after>// $Id$
//
// Task to skim ESD files.
//
//

#include "AliEsdSkimTask.h"
#include <TClonesArray.h>
#include <TFile.h>
#include <TTree.h>
#include "AliAnalysisManager.h"
#include "AliESDEvent.h"
#include "AliESDtrackCuts.h"
#include "AliMultiplicity.h"

//_________________________________________________________________________________________________
AliEsdSkimTask::AliEsdSkimTask(const char *opt) :
  AliAnalysisTaskSE(opt), fEvent(0), fTree(0), fCuts(0),
  fDoZDC(1), fDoV0(1), fDoT0(1), fDoTPCv(1), fDoSPDv(1), fDoPriv(1),
  fDoEmCs(1), fDoPCs(1), fDoEmT(1), fDoPT(1), fDoTracks(1), fDoMult(1),
  fDoTof(1), fDoPileup(1), fDoClus(1), fEmcNames(""),
  fDoMiniTracks(0), fTracks("Tracks"), fPhosClusOnly(0)
{
  // Constructor.

  if (!opt)
    return;

  DefineOutput(1, TTree::Class());
}

//_________________________________________________________________________________________________
void AliEsdSkimTask::UserExec(Option_t */*opt*/)
{
  // Process event.

  AliESDEvent *esdin = dynamic_cast<AliESDEvent*>(InputEvent());
  if (!esdin)
    return;

  AliAnalysisManager *am = AliAnalysisManager::GetAnalysisManager();

  fEvent->Reset();

  TList* objsin  = esdin->GetList();
  TList* objsout = fEvent->GetList();

  AliESDHeader *header = dynamic_cast<AliESDHeader*>(objsin->FindObject("AliESDHeader"));
  if (header) {
    am->LoadBranch("AliESDHeader.");
    *header = *esdin->GetHeader();
  }
  AliESDRun *run = dynamic_cast<AliESDRun*>(objsin->FindObject("AliESDRun"));
  if (run) {
    am->LoadBranch("AliESDRun.");
    *run = *esdin->GetESDRun();
  }
  AliESDZDC *zdc = dynamic_cast<AliESDZDC*>(objsin->FindObject("AliESDZDC"));
  if (zdc) {
    am->LoadBranch("AliESDZDC.");
    *zdc = *esdin->GetESDZDC();
  }
  AliESDVZERO *v0 = dynamic_cast<AliESDVZERO*>(objsin->FindObject("AliESDVZERO"));
  if (v0) {
    am->LoadBranch("AliESDVZERO.");
    *v0 = *esdin->GetVZEROData();
  }
  AliESDTZERO *t0 = dynamic_cast<AliESDTZERO*>(objsin->FindObject("AliESDTZERO"));
  if (t0) {
    am->LoadBranch("AliESDTZERO.");
    *t0 = *esdin->GetESDTZERO();
  }
  AliESDVertex *tpcv = dynamic_cast<AliESDVertex*>(objsin->FindObject("TPCVertex"));
  if (tpcv) {
    am->LoadBranch("TPCVertex.");
    *tpcv = *esdin->GetPrimaryVertexTPC();
  }
  AliESDVertex *spdv = dynamic_cast<AliESDVertex*>(objsin->FindObject("SPDVertex"));
  if (spdv) {
    am->LoadBranch("SPDVertex.");
    *spdv = *esdin->GetPrimaryVertexSPD();
  }
  AliESDVertex *priv = dynamic_cast<AliESDVertex*>(objsin->FindObject("PrimaryVertex"));
  if (priv) {
    am->LoadBranch("PrimaryVertex.");
    *priv = *esdin->GetPrimaryVertexTracks();
  }
  AliESDCaloCells *ecells = dynamic_cast<AliESDCaloCells*>(objsin->FindObject("EMCALCells"));
  if (ecells) {
    am->LoadBranch("EMCALCells.");
    *ecells = *esdin->GetEMCALCells();
  }
  AliESDCaloCells *pcells = dynamic_cast<AliESDCaloCells*>(objsin->FindObject("PHOSCells"));
  if (pcells) {
    am->LoadBranch("PHOSCells.");
    *pcells = *esdin->GetPHOSCells();
  }
  AliESDCaloTrigger *etrig = dynamic_cast<AliESDCaloTrigger*>(objsin->FindObject("EMCALTrigger"));
  if (etrig) {
    am->LoadBranch("EMCALTrigger.");
    *etrig = *esdin->GetCaloTrigger("EMCAL");
  }
  AliESDCaloTrigger *ptrig = dynamic_cast<AliESDCaloTrigger*>(objsin->FindObject("PHOSTrigger"));
  if (ptrig) {
    am->LoadBranch("PHOSTrigger.");
    *ptrig = *esdin->GetCaloTrigger("PHOS");
  }

  AliMultiplicity *mult = dynamic_cast<AliMultiplicity*>(objsin->FindObject("AliMultiplicity"));
  if (mult) {
    am->LoadBranch("AliMultiplicity.");
    *mult = *esdin->GetMultiplicity();
  }

  AliTOFHeader *tofh = dynamic_cast<AliTOFHeader*>(objsin->FindObject("AliTOFHeader"));
  if (tofh) {
    am->LoadBranch("AliTOFHeader.");
    *tofh = *esdin->GetTOFHeader();
  }
  TClonesArray *spup = dynamic_cast<TClonesArray*>(objsin->FindObject("SPDPileupVertices"));
  if (spup) {
    am->LoadBranch("SPDPileupVertices");
    Int_t N = esdin->GetNumberOfPileupVerticesSPD();
    for (Int_t i=0; i<N; ++i) {
      const AliESDVertex *vtx = esdin->GetPileupVertexSPD(i);
      if (vtx)
        fEvent->AddPileupVertexSPD(vtx);
    }
  }
  TClonesArray *tpup = dynamic_cast<TClonesArray*>(objsin->FindObject("TrkPileupVertices"));
  if (tpup) {
    am->LoadBranch("TrkPileupVertices");
    Int_t N = esdin->GetNumberOfPileupVerticesTracks();
    for (Int_t i=0; i<N; ++i) {
      const AliESDVertex *vtx = esdin->GetPileupVertexTracks(i);
      if (vtx)
        fEvent->AddPileupVertexTracks(vtx);
    }
  }
  TClonesArray *clus = dynamic_cast<TClonesArray*>(objsin->FindObject("CaloClusters"));
  if (clus) {
    am->LoadBranch("");
    Int_t N = esdin->GetNumberOfCaloClusters();
    for (Int_t i=0; i<N; ++i) {
      AliESDCaloCluster *c = esdin->GetCaloCluster(i);
      if (fPhosClusOnly && c->IsEMCAL())
        continue;
      if (c)
        fEvent->AddCaloCluster(c);
    }
  }
  TObjArray *namearr = fEmcNames.Tokenize(";");
  if (namearr) {
    for (Int_t i=0; i<namearr->GetEntries(); ++i) {
      TString cname(namearr->At(i)->GetName());
      if (cname.Length()<=0)
        continue;
      TClonesArray *arrin  = dynamic_cast<TClonesArray*>(objsin->FindObject(cname));
      TClonesArray *arrout = dynamic_cast<TClonesArray*>(objsout->FindObject(cname));
      //AliFatal(Form("Can not find tracks with name %s", fTracks.Data()));
      arrout->Delete();
      const Int_t N = arrin->GetEntries();
      for (Int_t iC=0, nC=0; iC<N; ++iC) {
        AliESDCaloCluster *c = dynamic_cast<AliESDCaloCluster*>(arrin->At(iC));
        if (!c)
          continue;
        new ((*arrout)[nC++]) AliESDCaloCluster(*c);
      }
    }
    delete namearr;
  }
  if (fDoTracks) {
    am->LoadBranch("Tracks");
    TClonesArray *tracks = dynamic_cast<TClonesArray*>(objsin->FindObject(fTracks));
    if (!tracks) {
      AliFatal(Form("Can not find tracks with name %s", fTracks.Data()));
      return;
    }
    const Int_t Ntracks = tracks->GetEntries();
    Int_t nacc = 0;
    for (Int_t iTracks = 0; iTracks < Ntracks; ++iTracks) {
      AliESDtrack *track = dynamic_cast<AliESDtrack*>(tracks->At(iTracks));
      if (!track)
        continue;
      if (fCuts) {
        if (!fCuts->IsSelected(track))
          continue;
      }
      if (fDoMiniTracks) {
        class AliEsdMiniTrack : public AliESDtrack
        {
          public:
            AliEsdMiniTrack(const AliESDtrack &t) : AliESDtrack(t) {}
            void MakeMiniESDtrack() {
              delete fCp;       fCp       = 0;
              delete fIp;       fIp       = 0;
              delete fTPCInner; fTPCInner = 0;
              delete fOp;       fOp       = 0;
              delete fHMPIDp;   fHMPIDp   = 0;
              for (Int_t i=0; i<3;i++) fKinkIndexes[i] = 0;
              for (Int_t i=0; i<3;i++) fV0Indexes[i] = 0;
              fTRDchi2   = 0;
              fTRDncls   = 0;
              fTRDncls0  = 0;
              fTRDsignal = 0;
              for (Int_t i=0;i<kTRDnPlanes;i++) {
                fTRDTimBin[i]  = 0;
              }
              for (Int_t i=0;i<AliPID::kSPECIES;i++) fTRDr[i] = 0;
              fTRDLabel      = 0;
              fTRDQuality    = -1;
              fTRDntracklets = 0;
              if(fTRDnSlices)
                delete[] fTRDslices;
              fTRDslices     = 0;
              fTRDnSlices    = 0;
              fTRDBudget     = -1;
              fHMPIDchi2     = 0;
              fHMPIDqn       = 0;
              fHMPIDcluIdx   = -1;
              fHMPIDsignal   = 0;
              for (Int_t i=0;i<AliPID::kSPECIES;i++) fHMPIDr[i] = 0;
              fHMPIDtrkTheta = 0;
              fHMPIDtrkPhi   = 0;
              fHMPIDtrkX     = 0;
              fHMPIDtrkY     = 0;
              fHMPIDmipX     = fCacheNCrossedRows;
              fHMPIDmipY     = fCacheChi2TPCConstrainedVsGlobal;
            }
        };

        AliEsdMiniTrack *newtrack = new AliEsdMiniTrack(*track);
        newtrack->MakeMiniESDtrack();
        if (track->GetEMCALcluster()==-123) {
          newtrack->SetEMCALcluster(track->GetEMCALcluster());
          newtrack->SetTRDQuality(track->GetTRDQuality());
          newtrack->SetTRDBudget(track->GetTRDBudget());
        }
        track = newtrack;
      }
      fEvent->AddTrack(track);
      ++nacc;
    }
    if (fCuts)
      AliInfo(Form("Selected %d out of %d \n", nacc, Ntracks));
  }
  fTree->Fill();
}

//_________________________________________________________________________________________________
void AliEsdSkimTask::UserCreateOutputObjects()
{
  // Create output objects.

  fTree = new TTree("esdTree", "Tree with skimmed ESD objects");
  fEvent = new AliESDEvent;
  fEvent->AddObject(new AliESDHeader());
  fEvent->AddObject(new AliESDRun());
  if (fDoZDC)
    fEvent->AddObject(new AliESDZDC());
  if (fDoV0)
    fEvent->AddObject(new AliESDVZERO());
  if (fDoT0)
    fEvent->AddObject(new AliESDTZERO());
  if (fDoTPCv) {
    AliESDVertex *tpcv = new AliESDVertex();
    tpcv->SetName("TPCVertex");
    fEvent->AddObject(tpcv);
  }
  if (fDoSPDv) {
    AliESDVertex *spdv = new AliESDVertex();
    spdv->SetName("SPDVertex");
    fEvent->AddObject(spdv);
  }
  if (fDoPriv) {
    AliESDVertex *priv = new AliESDVertex();
    priv->SetName("PrimaryVertex");
    fEvent->AddObject(priv);
  }
  if (fDoEmCs) {
    fEvent->AddObject(new AliESDCaloCells("EMCALCells","EMCALCells"));
  }
  if (fDoPCs) {
    fEvent->AddObject(new AliESDCaloCells("PHOSCells","PHOSCells"));
  }
  if (fDoEmT) {
    AliESDCaloTrigger *etrig = new AliESDCaloTrigger;
    etrig->SetName("EMCALTrigger");
    fEvent->AddObject(etrig);
  }
  if (fDoPT) {
    AliESDCaloTrigger *ptrig = new AliESDCaloTrigger;
    ptrig->SetName("PHOSTrigger");
    fEvent->AddObject(ptrig);
  }
  if (fDoMult) {
    fEvent->AddObject(new AliMultiplicity());
  }
  if (fDoPileup) {
    TClonesArray *arr1 = new TClonesArray("AliESDVertex",0);
    arr1->SetName("SPDPileupVertices");
    fEvent->AddObject(arr1);
    TClonesArray *arr2 = new TClonesArray("AliESDVertex",0);
    arr2->SetName("TPCPileupVertices");
    fEvent->AddObject(arr2);
  }
  if (fDoTof) {
    fEvent->AddObject(new AliTOFHeader());
  }
  if (fDoClus) {
    TClonesArray *arr = new TClonesArray("AliESDCaloCluster",0);
    arr->SetName("CaloClusters");
    fEvent->AddObject(arr);
  }
  TObjArray *namearr = fEmcNames.Tokenize(";");
  if (namearr) {
    for (Int_t i=0; i<namearr->GetEntries(); ++i) {
      TString cname(namearr->At(i)->GetName());
      if (cname.Length()<=0)
        continue;
      TClonesArray *arr = new TClonesArray("AliESDCaloCluster",0);
      arr->SetName(cname);
      fEvent->AddObject(arr);
    }
    delete namearr;
  }
  if (fDoTracks) {
    TClonesArray *arr = new TClonesArray("AliESDtrack",0);
    arr->SetName("Tracks");
    fEvent->AddObject(arr);
  }
  fEvent->GetStdContent();
  fEvent->WriteToTree(fTree);
  fTree->GetUserInfo()->Add(fEvent);
  TFile *file = OpenFile(1);
  fTree->SetDirectory(file);
  fTree->SetAutoFlush(-1024*1024*1024);
  fTree->SetAutoSave(-1024*1024*1024);
  PostData(1,fTree);
}
<|endoftext|>


<commit_before>#ifndef MRR_POSIX_LIB_SHARED_MEM_HXX_
#define MRR_POSIX_LIB_SHARED_MEM_HXX_

#include <sys/shm.h>
#include <sys/stat.h>

//m=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
// TODO:
//
// Break this into 3 partial specializations:
//
// Single Value:
//
// template<typename T>
// struct shared_memory<T,1>;
//
//
// String:
//
// template <unsigned N>
// struct shared_memory<char,N>;
//
//
// Array:
//
// template <typename T, unsigned N>
// struct shared_memory<T,N>;
//

//m=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

namespace mrr {
namespace posix {

//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

template <typename T, unsigned Size = 1>
struct shared_memory
{
  using value_type = T;
  using stripped_ptr_type = typename std::remove_pointer<value_type>::type;
  using flag_type = int;

  shared_memory(int flags)
    : segment_id_(shmget(IPC_PRIVATE, sizeof(T)*Size, flags)),
      shared_mem_(static_cast<value_type*>(shmat(segment_id_, NULL, 0)))
  {
  }

  shared_memory()
    : segment_id_(-1), shared_mem_(nullptr)
  {
  }

  shared_memory(shared_memory const& shm)
    : segment_id_(shm.segment_id_), shared_mem_(shm.shared_mem_)
  {
  }

  int segment_id() const
  {
    return segment_id_;
  }

  void attach(int segment_id)
  {
    segment_id_ = segment_id;
    shared_mem_ = static_cast<value_type*>(shmat(segment_id_, NULL, 0));
  }

  void clear()
  {
    shmdt(shared_mem_);
  }

  void release()
  {
    shmctl(segment_id_, IPC_RMID, NULL);
  }

  ~shared_memory()
  {
    release();
  }

  shared_memory& operator =(value_type const& val)
  {
    *shared_mem_ = val;
    return *this;
  }

  // For char[]
  shared_memory& operator =(value_type const * const& str)
  {
    sprintf(shared_mem_, str);
    return *this;
  }

  value_type* operator&()
  {
    return shared_mem_;
  }

  std::ostream& print(std::ostream& os) const
  {
    if(Size > 1 && std::is_same<value_type,char>::value)
      os << shared_mem_;
    else
      os << *shared_mem_;

    return os;
  }

  value_type& operator*()
  {
    return *shared_mem_;
  }

private:
  int segment_id_;
  value_type* shared_mem_;

}; // struct shared_memory

//m=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

} // namespace posix
} // namespace mrr

//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

template <typename T, unsigned Size>
std::ostream& operator <<(std::ostream& os, mrr::posix::shared_memory<T,Size> const& mem)
{
  return mem.print(os);
}

#endif // #ifndef MRR_POSIX_LIB_SHARED_MEM_HXX_
<commit_msg>Moved core functionality of shared memory to shared_memory_base<T,N><commit_after>#ifndef MRR_POSIX_LIB_SHARED_MEM_HXX_
#define MRR_POSIX_LIB_SHARED_MEM_HXX_

#include <sys/shm.h>
#include <sys/stat.h>

//m=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
// TODO:
//
// Break this into 3 partial specializations:
//
// Single Value:
//
// template<typename T>
// struct shared_memory<T,1>;
//
//
// String:
//
// template <unsigned N>
// struct shared_memory<char,N>;
//
//
// Array:
//
// template <typename T, unsigned N>
// struct shared_memory<T,N>;
//

//m=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

namespace mrr {
namespace posix {

//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

//m=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
template <typename T, unsigned Size>
struct shared_memory;

//m=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
template <typename T, unsigned Size>
struct shared_memory_base
{
  using value_type = T;
  using flag_type = int;

private:
  friend class shared_memory<T,Size>;

protected:
  shared_memory_base(int flags)
    : segment_id_(shmget(IPC_PRIVATE, sizeof(T)*Size, flags)),
      shared_mem_(static_cast<value_type*>(shmat(segment_id_, NULL, 0)))
  {
  }

  shared_memory_base()
    : segment_id_(-1), shared_mem_(nullptr)
  {
  }

public:
  int segment_id() const
  {
    return segment_id_;
  }

  void attach(int segment_id)
  {
    segment_id_ = segment_id;
    shared_mem_ = static_cast<value_type*>(shmat(segment_id_, NULL, 0));
  }

  void clear()
  {
    shmdt(shared_mem_);
  }

  void release()
  {
    shmctl(segment_id_, IPC_RMID, NULL);
  }

  ~shared_memory_base()
  {
    release();
  }

protected:
  int segment_id_;
  value_type* shared_mem_;

}; // struct shared_memory base

//m=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
template <typename T, unsigned Size = 1>
struct shared_memory : shared_memory_base<T,Size>
{
  using base_type = shared_memory_base<T,Size>;

  using value_type = typename base_type::value_type;
  using flag_type = typename base_type::flag_type;

  shared_memory(int flags)
    : base_type(flags)
  {
  }

  shared_memory()
    : base_type()
  {
  }

  shared_memory& operator =(value_type const& val)
  {
    *base_type::shared_mem_ = val;
    return *this;
  }

  // For char[]
  shared_memory& operator =(value_type const * const& str)
  {
    sprintf(base_type::shared_mem_, str);
    return *this;
  }

  value_type* operator&()
  {
    return base_type::shared_mem_;
  }

  std::ostream& print(std::ostream& os) const
  {
    if(Size > 1 && std::is_same<value_type,char>::value)
      os << base_type::shared_mem_;
    else
      os << *base_type::shared_mem_;

    return os;
  }

  value_type& operator*()
  {
    return *base_type::shared_mem_;
  }

}; // struct shared_memory

//m=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

} // namespace posix
} // namespace mrr

//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

template <typename T, unsigned Size>
std::ostream& operator <<(std::ostream& os, mrr::posix::shared_memory<T,Size> const& mem)
{
  return mem.print(os);
}

#endif // #ifndef MRR_POSIX_LIB_SHARED_MEM_HXX_
<|endoftext|>


<commit_before>/* Copyright (c) 2016 PaddlePaddle Authors. All Rights Reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License. */

#include "paddle/fluid/operators/lookup_table_op.h"

#include <memory>

#include "paddle/fluid/framework/no_need_buffer_vars_inference.h"
#include "paddle/fluid/framework/var_type_inference.h"

namespace paddle {
namespace operators {

class LookupTableOp : public framework::OperatorWithKernel {
 public:
  using framework::OperatorWithKernel::OperatorWithKernel;

  void InferShape(framework::InferShapeContext* ctx) const override {
    OP_INOUT_CHECK(ctx->HasInput("W"), "Input", "W", "LookupTable");
    OP_INOUT_CHECK(ctx->HasInput("Ids"), "Input", "Ids", "LookupTable");
    OP_INOUT_CHECK(ctx->HasOutput("Out"), "Output", "Out", "LookupTable");

    auto table_dims = ctx->GetInputDim("W");
    auto ids_dims = ctx->GetInputDim("Ids");
    int ids_rank = ids_dims.size();
    VLOG(5) << "ids rank is " << ids_rank << std::endl;
    PADDLE_ENFORCE_EQ(
        table_dims.size(), 2,
        platform::errors::InvalidArgument(
            "ShapeError: The dimensions of the 'lookup table' must be 2. "
            "But received lookup table's dimensions = %d, "
            "lookup table's shape = [%s].",
            table_dims.size(), table_dims));
    PADDLE_ENFORCE_EQ(
        ids_dims[ids_rank - 1], 1,
        platform::errors::InvalidArgument(
            "ShapeError: The last dimensions of the 'Ids' tensor must be 1. "
            "But received Ids's last dimensions = %d, Ids's shape = [%s].",
            ids_dims[ids_rank - 1], ids_dims));

    auto output_dims =
        framework::vectorize(framework::slice_ddim(ids_dims, 0, ids_rank - 1));
    output_dims.push_back(table_dims[1]);
    ctx->SetOutputDim("Out", framework::make_ddim(output_dims));

    if (ctx->GetOutputsVarType("Out")[0] ==
        framework::proto::VarType::LOD_TENSOR) {
      ctx->ShareLoD("Ids", /*->*/ "Out");
    }
  }

 protected:
  framework::OpKernelType GetExpectedKernelType(
      const framework::ExecutionContext& ctx) const override {
    auto data_type = OperatorWithKernel::IndicateVarDataType(ctx, "W");
    return framework::OpKernelType(data_type, ctx.device_context());
  }
};

class LookupTableOpMaker : public framework::OpProtoAndCheckerMaker {
 public:
  void Make() override {
    AddInput("W",
             "(Tensor) The input represents embedding tensors, "
             "which is a learnable parameter.");
    AddInput("Ids",
             "An input with type int64 "
             "contains the ids to be looked up in W. "
             "The last dimension size must be 1.");
    AddOutput("Out", "The lookup results, which have the same type as W.");
    AddAttr<bool>("is_sparse",
                  "(boolean, default false) "
                  "Sparse update.")
        .SetDefault(false);
    AddAttr<bool>("is_distributed",
                  "(boolean, default false) distributed lookup table.")
        .SetDefault(false);
    AddAttr<int64_t>("padding_idx",
                     "(int64, default -1) "
                     "If the value is -1, it makes no effect to lookup. "
                     "Otherwise the given value indicates padding the output "
                     "with zeros whenever lookup encounters it in Ids.")
        .SetDefault(kNoPadding);

    // for parameter training config
    AddAttr<bool>("remote_prefetch",
                  "pull sparse params from parameters, this can only be used "
                  "in distributed training")
        .SetDefault(false);

    AddAttr<std::string>("entry_config",
                         "embedding sparse feature entry config, "
                         " probability entry / counting "
                         " this can only be used in distributed training"
                         "entry")
        .SetDefault("");

    AddAttr<bool>("is_test",
                  "(bool, default false) Set to true for inference only, false "
                  "for training.")
        .SetDefault(false);

    AddAttr<std::string>("entry",
                         "(std::string, default "
                         ") for entry attribute.")
        .SetDefault("none");

    AddAttr<std::vector<std::string>>(
        "table_names",
        "(string vector, the split table names that will be fetched from "
        "parameter server)"
        "in the order of input variables for mapping")
        .SetDefault({});
    AddAttr<int>("trainer_id", "trainer id from 0 ~ worker_num.").SetDefault(0);
    AddAttr<bool>("grad_inplace",
                  "(boolean, default false) "
                  "If the grad op reuse the input's variable.")
        .SetDefault(false);
    AddAttr<std::vector<std::string>>(
        "epmap",
        "(string vector, default 127.0.0.1:6164)"
        "Server endpoints in the order of input variables for mapping")
        .SetDefault({});
    AddAttr<std::vector<int64_t>>("height_sections",
                                  "Height for each output SelectedRows.")
        .SetDefault(std::vector<int64_t>({}));
    AddComment(R"DOC(
Lookup Table Operator.

This operator is used to perform lookups on the parameter W,
then concatenated into a dense tensor.

The input Ids can carry the LoD (Level of Details) information,
or not. And the output only shares the LoD information with input Ids.

)DOC");
  }
};

DECLARE_NO_NEED_BUFFER_VARS_INFERER(LookupTableGradOpNoBufferVarsInferer, "W");

template <typename T>
class LookupTableGradOpMaker : public framework::SingleGradOpMaker<T> {
 public:
  using framework::SingleGradOpMaker<T>::SingleGradOpMaker;

 protected:
  void Apply(GradOpPtr<T> op) const override {
    op->SetType("lookup_table_grad");

    op->SetInput("W", this->Input("W"));
    op->SetInput("Ids", this->Input("Ids"));
    op->SetInput(framework::GradVarName("Out"), this->OutputGrad("Out"));

    op->SetOutput(framework::GradVarName("W"), this->InputGrad("W"));

    op->SetAttrMap(this->Attrs());
  }
};

class LookupTableOpGrad : public framework::OperatorWithKernel {
 public:
  using framework::OperatorWithKernel::OperatorWithKernel;

  void InferShape(framework::InferShapeContext* ctx) const override {
    auto table_dims = ctx->GetInputDim("W");
    ctx->SetOutputDim(framework::GradVarName("W"), table_dims);
  }

 protected:
  framework::OpKernelType GetExpectedKernelType(
      const framework::ExecutionContext& ctx) const override {
    auto data_type = OperatorWithKernel::IndicateVarDataType(
        ctx, framework::GradVarName("Out"));
    return framework::OpKernelType(data_type, ctx.device_context());
  }
};

class LookupTableOpGradVarTypeInference : public framework::VarTypeInference {
 public:
  void operator()(framework::InferVarTypeContext* ctx) const override {
    auto out_var_name = framework::GradVarName("W");
    auto attr = ctx->GetAttr("is_sparse");
    bool is_sparse = BOOST_GET(bool, attr);
    if (is_sparse) {
      VLOG(3) << "lookup_table_grad op " << framework::GradVarName("W")
              << " is set to SelectedRows";
      ctx->SetOutputType(out_var_name,
                         framework::proto::VarType::SELECTED_ROWS);
    } else {
      VLOG(3) << "lookup_table_grad op " << framework::GradVarName("W")
              << " is set to LoDTensor";
      ctx->SetOutputType(out_var_name, framework::proto::VarType::LOD_TENSOR);
    }
    ctx->SetOutputDataType(out_var_name, ctx->GetInputDataType("W"));
  }
};

}  // namespace operators
}  // namespace paddle

namespace ops = paddle::operators;
REGISTER_OPERATOR(lookup_table, ops::LookupTableOp, ops::LookupTableOpMaker,
                  ops::LookupTableGradOpMaker<paddle::framework::OpDesc>,
                  ops::LookupTableGradOpMaker<paddle::imperative::OpBase>);

REGISTER_OPERATOR(lookup_table_grad, ops::LookupTableOpGrad,
                  ops::LookupTableGradOpNoBufferVarsInferer,
                  ops::LookupTableOpGradVarTypeInference);

REGISTER_OP_CPU_KERNEL(lookup_table, ops::LookupTableKernel<float>,
                       ops::LookupTableKernel<double>,
                       ops::LookupTableKernel<int8_t>);
REGISTER_OP_CPU_KERNEL(lookup_table_grad, ops::LookupTableGradKernel<float>,
                       ops::LookupTableGradKernel<double>);
<commit_msg>for inference checkpoint (#30081)<commit_after>/* Copyright (c) 2016 PaddlePaddle Authors. All Rights Reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License. */

#include "paddle/fluid/operators/lookup_table_op.h"

#include <memory>

#include "paddle/fluid/framework/no_need_buffer_vars_inference.h"
#include "paddle/fluid/framework/op_version_registry.h"
#include "paddle/fluid/framework/var_type_inference.h"

namespace paddle {
namespace operators {

class LookupTableOp : public framework::OperatorWithKernel {
 public:
  using framework::OperatorWithKernel::OperatorWithKernel;

  void InferShape(framework::InferShapeContext* ctx) const override {
    OP_INOUT_CHECK(ctx->HasInput("W"), "Input", "W", "LookupTable");
    OP_INOUT_CHECK(ctx->HasInput("Ids"), "Input", "Ids", "LookupTable");
    OP_INOUT_CHECK(ctx->HasOutput("Out"), "Output", "Out", "LookupTable");

    auto table_dims = ctx->GetInputDim("W");
    auto ids_dims = ctx->GetInputDim("Ids");
    int ids_rank = ids_dims.size();
    VLOG(5) << "ids rank is " << ids_rank << std::endl;
    PADDLE_ENFORCE_EQ(
        table_dims.size(), 2,
        platform::errors::InvalidArgument(
            "ShapeError: The dimensions of the 'lookup table' must be 2. "
            "But received lookup table's dimensions = %d, "
            "lookup table's shape = [%s].",
            table_dims.size(), table_dims));
    PADDLE_ENFORCE_EQ(
        ids_dims[ids_rank - 1], 1,
        platform::errors::InvalidArgument(
            "ShapeError: The last dimensions of the 'Ids' tensor must be 1. "
            "But received Ids's last dimensions = %d, Ids's shape = [%s].",
            ids_dims[ids_rank - 1], ids_dims));

    auto output_dims =
        framework::vectorize(framework::slice_ddim(ids_dims, 0, ids_rank - 1));
    output_dims.push_back(table_dims[1]);
    ctx->SetOutputDim("Out", framework::make_ddim(output_dims));

    if (ctx->GetOutputsVarType("Out")[0] ==
        framework::proto::VarType::LOD_TENSOR) {
      ctx->ShareLoD("Ids", /*->*/ "Out");
    }
  }

 protected:
  framework::OpKernelType GetExpectedKernelType(
      const framework::ExecutionContext& ctx) const override {
    auto data_type = OperatorWithKernel::IndicateVarDataType(ctx, "W");
    return framework::OpKernelType(data_type, ctx.device_context());
  }
};

class LookupTableOpMaker : public framework::OpProtoAndCheckerMaker {
 public:
  void Make() override {
    AddInput("W",
             "(Tensor) The input represents embedding tensors, "
             "which is a learnable parameter.");
    AddInput("Ids",
             "An input with type int64 "
             "contains the ids to be looked up in W. "
             "The last dimension size must be 1.");
    AddOutput("Out", "The lookup results, which have the same type as W.");
    AddAttr<bool>("is_sparse",
                  "(boolean, default false) "
                  "Sparse update.")
        .SetDefault(false);
    AddAttr<bool>("is_distributed",
                  "(boolean, default false) distributed lookup table.")
        .SetDefault(false);
    AddAttr<int64_t>("padding_idx",
                     "(int64, default -1) "
                     "If the value is -1, it makes no effect to lookup. "
                     "Otherwise the given value indicates padding the output "
                     "with zeros whenever lookup encounters it in Ids.")
        .SetDefault(kNoPadding);

    // for parameter training config
    AddAttr<bool>("remote_prefetch",
                  "pull sparse params from parameters, this can only be used "
                  "in distributed training")
        .SetDefault(false);

    AddAttr<std::string>("entry_config",
                         "embedding sparse feature entry config, "
                         " probability entry / counting "
                         " this can only be used in distributed training"
                         "entry")
        .SetDefault("");

    AddAttr<bool>("is_test",
                  "(bool, default false) Set to true for inference only, false "
                  "for training.")
        .SetDefault(false);

    AddAttr<std::string>("entry",
                         "(std::string, default "
                         ") for entry attribute.")
        .SetDefault("none");

    AddAttr<std::vector<std::string>>(
        "table_names",
        "(string vector, the split table names that will be fetched from "
        "parameter server)"
        "in the order of input variables for mapping")
        .SetDefault({});
    AddAttr<int>("trainer_id", "trainer id from 0 ~ worker_num.").SetDefault(0);
    AddAttr<bool>("grad_inplace",
                  "(boolean, default false) "
                  "If the grad op reuse the input's variable.")
        .SetDefault(false);
    AddAttr<std::vector<std::string>>(
        "epmap",
        "(string vector, default 127.0.0.1:6164)"
        "Server endpoints in the order of input variables for mapping")
        .SetDefault({});
    AddAttr<std::vector<int64_t>>("height_sections",
                                  "Height for each output SelectedRows.")
        .SetDefault(std::vector<int64_t>({}));
    AddComment(R"DOC(
Lookup Table Operator.

This operator is used to perform lookups on the parameter W,
then concatenated into a dense tensor.

The input Ids can carry the LoD (Level of Details) information,
or not. And the output only shares the LoD information with input Ids.

)DOC");
  }
};

DECLARE_NO_NEED_BUFFER_VARS_INFERER(LookupTableGradOpNoBufferVarsInferer, "W");

template <typename T>
class LookupTableGradOpMaker : public framework::SingleGradOpMaker<T> {
 public:
  using framework::SingleGradOpMaker<T>::SingleGradOpMaker;

 protected:
  void Apply(GradOpPtr<T> op) const override {
    op->SetType("lookup_table_grad");

    op->SetInput("W", this->Input("W"));
    op->SetInput("Ids", this->Input("Ids"));
    op->SetInput(framework::GradVarName("Out"), this->OutputGrad("Out"));

    op->SetOutput(framework::GradVarName("W"), this->InputGrad("W"));

    op->SetAttrMap(this->Attrs());
  }
};

class LookupTableOpGrad : public framework::OperatorWithKernel {
 public:
  using framework::OperatorWithKernel::OperatorWithKernel;

  void InferShape(framework::InferShapeContext* ctx) const override {
    auto table_dims = ctx->GetInputDim("W");
    ctx->SetOutputDim(framework::GradVarName("W"), table_dims);
  }

 protected:
  framework::OpKernelType GetExpectedKernelType(
      const framework::ExecutionContext& ctx) const override {
    auto data_type = OperatorWithKernel::IndicateVarDataType(
        ctx, framework::GradVarName("Out"));
    return framework::OpKernelType(data_type, ctx.device_context());
  }
};

class LookupTableOpGradVarTypeInference : public framework::VarTypeInference {
 public:
  void operator()(framework::InferVarTypeContext* ctx) const override {
    auto out_var_name = framework::GradVarName("W");
    auto attr = ctx->GetAttr("is_sparse");
    bool is_sparse = BOOST_GET(bool, attr);
    if (is_sparse) {
      VLOG(3) << "lookup_table_grad op " << framework::GradVarName("W")
              << " is set to SelectedRows";
      ctx->SetOutputType(out_var_name,
                         framework::proto::VarType::SELECTED_ROWS);
    } else {
      VLOG(3) << "lookup_table_grad op " << framework::GradVarName("W")
              << " is set to LoDTensor";
      ctx->SetOutputType(out_var_name, framework::proto::VarType::LOD_TENSOR);
    }
    ctx->SetOutputDataType(out_var_name, ctx->GetInputDataType("W"));
  }
};

}  // namespace operators
}  // namespace paddle

namespace ops = paddle::operators;
REGISTER_OPERATOR(lookup_table, ops::LookupTableOp, ops::LookupTableOpMaker,
                  ops::LookupTableGradOpMaker<paddle::framework::OpDesc>,
                  ops::LookupTableGradOpMaker<paddle::imperative::OpBase>);

REGISTER_OPERATOR(lookup_table_grad, ops::LookupTableOpGrad,
                  ops::LookupTableGradOpNoBufferVarsInferer,
                  ops::LookupTableOpGradVarTypeInference);

REGISTER_OP_CPU_KERNEL(lookup_table, ops::LookupTableKernel<float>,
                       ops::LookupTableKernel<double>,
                       ops::LookupTableKernel<int8_t>);
REGISTER_OP_CPU_KERNEL(lookup_table_grad, ops::LookupTableGradKernel<float>,
                       ops::LookupTableGradKernel<double>);

/* ==========================  register checkpoint ===========================*/

REGISTER_OP_VERSION(lookup_table)
    .AddCheckpoint(
        R"ROC(
      Upgrade lookup_table add 1 attribute [entry_config].
    )ROC",
        paddle::framework::compatible::OpVersionDesc().NewAttr(
            "entry_config",
            "(std::string) embedding sparse feature entry config.", ""));

/* ========================================================================== */
<|endoftext|>


<commit_before>//===- CodeGeneratorBug.cpp - Debug code generation bugs ------------------===//
//
// This file implements program code generation debugging support.
//
//===----------------------------------------------------------------------===//

#include "BugDriver.h"
#include "SystemUtils.h"
#include "ListReducer.h"
#include "llvm/Constants.h"
#include "llvm/DerivedTypes.h"
#include "llvm/GlobalValue.h"
#include "llvm/iMemory.h"
#include "llvm/iTerminators.h"
#include "llvm/iOther.h"
#include "llvm/Module.h"
#include "llvm/Pass.h"
#include "llvm/Analysis/Verifier.h"
#include "llvm/Transforms/Utils/BasicBlockUtils.h"
#include "llvm/Transforms/Utils/Cloning.h"
#include "llvm/Transforms/Utils/Linker.h"
#include "Support/Statistic.h"
#include "Support/StringExtras.h"
#include <algorithm>
#include <set>

class ReduceMisCodegenFunctions : public ListReducer<Function*> {
  BugDriver &BD;
public:
  ReduceMisCodegenFunctions(BugDriver &bd) : BD(bd) {}

  virtual TestResult doTest(std::vector<Function*> &Prefix,
                            std::vector<Function*> &Suffix) {
    if (!Prefix.empty() && TestFuncs(Prefix))
      return KeepPrefix;
    if (!Suffix.empty() && TestFuncs(Suffix))
      return KeepSuffix;
    return NoFailure;
  }

  bool TestFuncs(const std::vector<Function*> &CodegenTest,
                 bool KeepFiles = false);

  void DisambiguateGlobalSymbols(Module *M);
};

bool ReduceMisCodegenFunctions::TestFuncs(const std::vector<Function*> &Funcs,
                                          bool KeepFiles)
{
  DEBUG(std::cerr << "Test functions are:\n");
  for (std::vector<Function*>::const_iterator I = Funcs.begin(),E = Funcs.end();
       I != E; ++I)
    DEBUG(std::cerr << "\t" << (*I)->getName() << "\n");

  // Clone the module for the two halves of the program we want.
  Module *SafeModule = CloneModule(BD.Program);

  // Make sure functions & globals are all external so that linkage
  // between the two modules will work.
  for (Module::iterator I = SafeModule->begin(), E = SafeModule->end();I!=E;++I)
    I->setLinkage(GlobalValue::ExternalLinkage);
  for (Module::giterator I=SafeModule->gbegin(),E = SafeModule->gend();I!=E;++I)
    I->setLinkage(GlobalValue::ExternalLinkage);

  DisambiguateGlobalSymbols(SafeModule);
  Module *TestModule = CloneModule(SafeModule);

  // Make sure global initializers exist only in the safe module (CBE->.so)
  for (Module::giterator I=TestModule->gbegin(),E = TestModule->gend();I!=E;++I)
    I->setInitializer(0);  // Delete the initializer to make it external

  // Remove the Test functions from the Safe module
  for (unsigned i = 0, e = Funcs.size(); i != e; ++i) {
    Function *TNOF = SafeModule->getFunction(Funcs[i]->getName(),
                                             Funcs[i]->getFunctionType());
    assert(TNOF && "Function doesn't exist in module!");
    DeleteFunctionBody(TNOF);       // Function is now external in this module!
  }

  // Remove the Safe functions from the Test module
  for (Module::iterator I=TestModule->begin(),E=TestModule->end(); I!=E; ++I) {
    bool funcFound = false;
    for (std::vector<Function*>::const_iterator F=Funcs.begin(),Fe=Funcs.end();
         F != Fe; ++F)
      if (I->getName() == (*F)->getName()) funcFound = true;

    if (!funcFound && !(BD.isExecutingJIT() && I->getName() == "main"))
      DeleteFunctionBody(I);
  }

  // This is only applicable if we are debugging the JIT:
  // Find all external functions in the Safe modules that are actually used
  // (called or taken address of), and make them call the JIT wrapper instead
  if (BD.isExecutingJIT()) {
    // Must delete `main' from Safe module if it has it
    for (Module::iterator I=SafeModule->begin(), E=SafeModule->end();I!=E;++I)
      if (I->getName() == "main") DeleteFunctionBody(I);

    // Add an external function "getPointerToNamedFunction" that JIT provides
    // Prototype: void *getPointerToNamedFunction(const char* Name)
    std::vector<const Type*> Params;
    Params.push_back(PointerType::get(Type::SByteTy)); // std::string&
    FunctionType *resolverTy = FunctionType::get(PointerType::get(Type::VoidTy),
                                                 Params, false /* isVarArg */);
    const std::string ResolverFunctionName = "getPointerToNamedFunction";
    Function *resolverFunc = new Function(resolverTy,
                                          GlobalValue::ExternalLinkage,
                                          ResolverFunctionName,
                                          SafeModule);

    // Use the function we just added to get addresses of functions we need
    // Iterate over the global declarations in the Safe module
    for (Module::iterator F=SafeModule->begin(),E=SafeModule->end(); F!=E; ++F){
      if (F->isExternal() && F->use_begin() != F->use_end() &&
          F->getName() != ResolverFunctionName) {
        // If it has a non-zero use list,
        // 1. Add a string constant with its name to the global file
        // The correct type is `const [ NUM x sbyte ]' where NUM is length of
        // function name + 1
        const std::string &Name = F->getName();
        GlobalVariable *funcName =
          new GlobalVariable(ArrayType::get(Type::SByteTy, Name.length()+1),
                             true /* isConstant */,
                             GlobalValue::InternalLinkage,
                             ConstantArray::get(Name),
                             Name + "_name",
                             SafeModule);

        // 2. Use `GetElementPtr *funcName, 0, 0' to convert the string to an
        // sbyte* so it matches the signature of the resolver function.
        Constant *Zero = Constant::getNullValue(Type::LongTy);
        std::vector<Constant*> GEPargs;
        GEPargs.push_back(Zero);
        GEPargs.push_back(Zero);

        // 3. Replace all uses of `func' with calls to resolver by:
        // (a) Iterating through the list of uses of this function
        // (b) Insert a cast instruction in front of each use
        // (c) Replace use of old call with new call

        // Insert code at the beginning of the function

        for (Value::use_iterator i=F->use_begin(), e=F->use_end(); i!=e; ++i) {
          if (Instruction* Inst = dyn_cast<Instruction>(*i)) {
            // GetElementPtr *funcName, ulong 0, ulong 0
            Value *GEP =
              ConstantExpr::getGetElementPtr(ConstantPointerRef::get(funcName),
                                             GEPargs);
            std::vector<Value*> ResolverArgs;
            ResolverArgs.push_back(GEP);
            // call resolver(GetElementPtr...)
            CallInst *resolve = new CallInst(resolverFunc, ResolverArgs,
                                             "resolver", Inst);
            // cast the result from the resolver to correctly-typed function
            CastInst *castResolver =
              new CastInst(resolve, PointerType::get(F->getFunctionType()),
                           "", Inst);
            // actually use the resolved function
            Inst->replaceUsesOfWith(F, castResolver);

            //BasicBlock::iterator ii(Inst);
            //ReplaceInstWithValue(Inst->getParent()->getInstList(),
            //                     ii, ResolverResult);
          }
        }
      }
    }
  }

  DEBUG(std::cerr << "Safe module:\n");
  for (Module::iterator I = SafeModule->begin(), E = SafeModule->end();I!=E;++I)
    if (!I->isExternal()) DEBUG(std::cerr << "\t" << I->getName() << "\n");
  for (Module::giterator I=SafeModule->gbegin(),E = SafeModule->gend();I!=E;++I)
    if (!I->isExternal()) DEBUG(std::cerr << "\t" << I->getName() << "\n");

  DEBUG(std::cerr << "Test module:\n");
  for (Module::iterator  I =TestModule->begin(),E = TestModule->end(); I!=E;++I)
    if (!I->isExternal()) DEBUG(std::cerr << "\t" << I->getName() << "\n");
  for (Module::giterator I=TestModule->gbegin(),E = TestModule->gend();I!=E;++I)
    if (!I->isExternal()) DEBUG(std::cerr << "\t" << I->getName() << "\n");

  // Write out the bytecode to be sent to CBE
  std::string SafeModuleBC = getUniqueFilename("bugpoint.safe.bc");
  if (verifyModule(*SafeModule)) {
    std::cerr << "Bytecode file corrupted!\n";
    exit(1);
  }
  if (BD.writeProgramToFile(SafeModuleBC, SafeModule)) {
    std::cerr << "Error writing bytecode to `" << SafeModuleBC << "'\nExiting.";
    exit(1);
  }

  // Make a shared library
  std::string SharedObject;
  BD.compileSharedObject(SafeModuleBC, SharedObject);

  // Remove all functions from the Test module EXCEPT for the ones specified in
  // Funcs.  We know which ones these are because they are non-external in
  // ToOptimize, but external in ToNotOptimize.
  //
  for (Module::iterator I = TestModule->begin(), E = TestModule->end();I!=E;++I)
    if (!I->isExternal()) {
      Function *TNOF = SafeModule->getFunction(I->getName(),
                                               I->getFunctionType());
      assert(TNOF && "Function doesn't exist in ToNotOptimize module??");
      if (!TNOF->isExternal())
        DeleteFunctionBody(I);
    }

  std::string TestModuleBC = getUniqueFilename("bugpoint.test.bc");
  if (verifyModule(*TestModule)) {
    std::cerr << "Bytecode file corrupted!\n";
    exit(1);
  }
  if (BD.writeProgramToFile(TestModuleBC, TestModule)) {
    std::cerr << "Error writing bytecode to `" << SafeModuleBC << "'\nExiting.";
    exit(1);
  }

  delete SafeModule;
  delete TestModule;

  // Run the code generator on the `Test' code, loading the shared library.
  // The function returns whether or not the new output differs from reference.
  int Result =  BD.diffProgram(TestModuleBC, SharedObject, false);
  if (KeepFiles) {
    std::cout << "You can reproduce the problem with the command line: \n"
              << "lli (or llc) -load " << SharedObject << " " << TestModuleBC
              << "\n";
  } else {
    removeFile(TestModuleBC);
    removeFile(SafeModuleBC);
    removeFile(SharedObject);
  }
  return Result;
}

namespace {
  struct Disambiguator {
    std::set<std::string>  SymbolNames;
    std::set<GlobalValue*> Symbols;
    uint64_t uniqueCounter;
    bool externalOnly;
  public:
    Disambiguator() : uniqueCounter(0), externalOnly(true) {}
    void setExternalOnly(bool value) { externalOnly = value; }
    void add(GlobalValue &V) {
      // If we're only processing externals and this isn't external, bail
      if (externalOnly && !V.isExternal()) return;
      // If we're already processed this symbol, don't add it again
      if (Symbols.count(&V) != 0) return;

      std::string SymName = V.getName();

      // If the symbol starts with a '.', replace it with 'x'
      // This solves the problem of not being able to find symbols in an .so
      // file when those symbol names start with '.'
      if (SymName[0] == '.') {
        SymName[0] = 'x';
        V.setName(SymName);
      }

      if (SymbolNames.count(SymName) == 0) {
        DEBUG(std::cerr << "Disambiguator: adding " << SymName
                        << ", no conflicts.\n");
        SymbolNames.insert(SymName);
      } else {
        // Mangle name before adding
        std::string newName;
        do {
          newName = SymName + "_" + utostr(uniqueCounter);
          if (SymbolNames.count(newName) == 0) break;
          else ++uniqueCounter;
        } while (1);
        //while (SymbolNames.count(V->getName()+utostr(uniqueCounter++))==0);
        DEBUG(std::cerr << "Disambiguator: conflict: " << SymName
                        << ", adding: " << newName << "\n");
        V.setName(newName);
        SymbolNames.insert(newName);
      }
      Symbols.insert(&V);
    }
  };
}

void ReduceMisCodegenFunctions::DisambiguateGlobalSymbols(Module *M) {
  // First, try not to cause collisions by minimizing chances of renaming an
  // already-external symbol, so take in external globals and functions as-is.
  Disambiguator D;
  DEBUG(std::cerr << "Disambiguating globals (external-only)\n");
  for (Module::giterator I = M->gbegin(), E = M->gend(); I != E; ++I) D.add(*I);
  DEBUG(std::cerr << "Disambiguating functions (external-only)\n");
  for (Module::iterator  I = M->begin(),  E = M->end();  I != E; ++I) D.add(*I);

  // Now just rename functions and globals as necessary, keeping what's already
  // in the set unique.
  D.setExternalOnly(false);
  DEBUG(std::cerr << "Disambiguating globals\n");
  for (Module::giterator I = M->gbegin(), E = M->gend(); I != E; ++I) D.add(*I);
  DEBUG(std::cerr << "Disambiguating globals\n");
  for (Module::iterator  I = M->begin(),  E = M->end();  I != E; ++I) D.add(*I);
}

bool BugDriver::debugCodeGenerator() {
  // See if we can pin down which functions are being miscompiled...
  //First, build a list of all of the non-external functions in the program.
  std::vector<Function*> MisCodegenFunctions;
  for (Module::iterator I = Program->begin(), E = Program->end(); I != E; ++I)
    if (!I->isExternal())
      MisCodegenFunctions.push_back(I);

  // If we are executing the JIT, we *must* keep the function `main' in the
  // module that is passed in, and not the shared library. However, we still
  // want to be able to debug the `main' function alone. Thus, we create a new
  // function `main' which just calls the old one.
  if (isExecutingJIT()) {
    // Get the `main' function
    Function *oldMain = Program->getNamedFunction("main");
    // Rename it
    oldMain->setName("old_main");
    // Create a NEW `main' function with same type
    Function *newMain = new Function(oldMain->getFunctionType(),
                                     GlobalValue::InternalLinkage,
                                     "main", Program);
    // Call the old main function and return its result
    BasicBlock *BB = new BasicBlock("entry", newMain);
    std::vector<Value*> args;
    for (Function::aiterator I=newMain->abegin(), E=newMain->aend(); I!=E; ++I)
      args.push_back(I);
    CallInst *call = new CallInst(oldMain, args);
    BB->getInstList().push_back(call);

    // if the type of old function wasn't void, return value of call
    ReturnInst *ret;
    if (oldMain->getReturnType() != Type::VoidTy) {
      ret = new ReturnInst(call);
    } else {
      ret = new ReturnInst();
    }

    // Add the return instruction to the BasicBlock
    BB->getInstList().push_back(ret);
  }

  // Do the reduction...
  ReduceMisCodegenFunctions(*this).reduceList(MisCodegenFunctions);

  std::cout << "\n*** The following functions are being miscompiled: ";
  PrintFunctionList(MisCodegenFunctions);
  std::cout << "\n";

  // Output a bunch of bytecode files for the user...
  ReduceMisCodegenFunctions(*this).TestFuncs(MisCodegenFunctions, true);

  return false;
}

<commit_msg>Implemented cleanups as suggested by Chris: * Use Module::getNamedFunction() to delete "main" instead of using a loop * Compare function pointers instead of function names to determine equivalence * Simplified creation of a 2-element vector containing zeroes * Manually performed LICM on code * Added an abort() in case a function we're considering occurs in something that   is not an instruction * Use DEBUG() around code sections instead of just in a statement in a loop,   because GCC's DCE may not be good enough to completely remove it in a release   build * Print out a command that can be directly copied-and-pasted to re-execute * Instead of just checking if a symbol begins with a dot and fixing it   accordingly, use Mangler and fix all the problems (invalid chars in C symbol   names) entirely * The new `main' function has external linkage<commit_after>//===- CodeGeneratorBug.cpp - Debug code generation bugs ------------------===//
//
// This file implements program code generation debugging support.
//
//===----------------------------------------------------------------------===//

#include "BugDriver.h"
#include "SystemUtils.h"
#include "ListReducer.h"
#include "llvm/Constants.h"
#include "llvm/DerivedTypes.h"
#include "llvm/GlobalValue.h"
#include "llvm/iMemory.h"
#include "llvm/iTerminators.h"
#include "llvm/iOther.h"
#include "llvm/Module.h"
#include "llvm/Pass.h"
#include "llvm/Analysis/Verifier.h"
#include "llvm/Support/Mangler.h"
#include "llvm/Transforms/Utils/BasicBlockUtils.h"
#include "llvm/Transforms/Utils/Cloning.h"
#include "llvm/Transforms/Utils/Linker.h"
#include "Support/Statistic.h"
#include "Support/StringExtras.h"
#include <algorithm>
#include <set>

class ReduceMisCodegenFunctions : public ListReducer<Function*> {
  BugDriver &BD;
public:
  ReduceMisCodegenFunctions(BugDriver &bd) : BD(bd) {}

  virtual TestResult doTest(std::vector<Function*> &Prefix,
                            std::vector<Function*> &Suffix) {
    if (!Prefix.empty() && TestFuncs(Prefix))
      return KeepPrefix;
    if (!Suffix.empty() && TestFuncs(Suffix))
      return KeepSuffix;
    return NoFailure;
  }

  bool TestFuncs(const std::vector<Function*> &CodegenTest,
                 bool KeepFiles = false);

  void DisambiguateGlobalSymbols(Module *M);
};

bool ReduceMisCodegenFunctions::TestFuncs(const std::vector<Function*> &Funcs,
                                          bool KeepFiles)
{
  DEBUG(std::cerr << "Test functions are:\n");
  for (std::vector<Function*>::const_iterator I = Funcs.begin(),E = Funcs.end();
       I != E; ++I)
    DEBUG(std::cerr << "\t" << (*I)->getName() << "\n");

  // Clone the module for the two halves of the program we want.
  Module *SafeModule = CloneModule(BD.Program);

  // Make sure functions & globals are all external so that linkage
  // between the two modules will work.
  for (Module::iterator I = SafeModule->begin(), E = SafeModule->end();I!=E;++I)
    I->setLinkage(GlobalValue::ExternalLinkage);
  for (Module::giterator I=SafeModule->gbegin(),E = SafeModule->gend();I!=E;++I)
    I->setLinkage(GlobalValue::ExternalLinkage);

  DisambiguateGlobalSymbols(SafeModule);
  Module *TestModule = CloneModule(SafeModule);

  // Make sure global initializers exist only in the safe module (CBE->.so)
  for (Module::giterator I=TestModule->gbegin(),E = TestModule->gend();I!=E;++I)
    I->setInitializer(0);  // Delete the initializer to make it external

  // Remove the Test functions from the Safe module
  for (unsigned i = 0, e = Funcs.size(); i != e; ++i) {
    Function *TNOF = SafeModule->getFunction(Funcs[i]->getName(),
                                             Funcs[i]->getFunctionType());
    assert(TNOF && "Function doesn't exist in module!");
    DeleteFunctionBody(TNOF);       // Function is now external in this module!
  }

  // Remove the Safe functions from the Test module
  for (Module::iterator I=TestModule->begin(),E=TestModule->end(); I!=E; ++I) {
    bool funcFound = false;
    for (std::vector<Function*>::const_iterator F=Funcs.begin(),Fe=Funcs.end();
         F != Fe; ++F)
      if (I->getName() == (*F)->getName()) funcFound = true;

    if (!funcFound && !(BD.isExecutingJIT() && I->getName() == "main"))
      DeleteFunctionBody(I);
  }

  // This is only applicable if we are debugging the JIT:
  // Find all external functions in the Safe modules that are actually used
  // (called or taken address of), and make them call the JIT wrapper instead
  if (BD.isExecutingJIT()) {
    // Must delete `main' from Safe module if it has it
    Function *safeMain = SafeModule->getNamedFunction("main");
    DeleteFunctionBody(safeMain);

    // Add an external function "getPointerToNamedFunction" that JIT provides
    // Prototype: void *getPointerToNamedFunction(const char* Name)
    std::vector<const Type*> Params;
    Params.push_back(PointerType::get(Type::SByteTy)); // std::string&
    FunctionType *resolverTy = FunctionType::get(PointerType::get(Type::VoidTy),
                                                 Params, false /* isVarArg */);
    Function *resolverFunc = new Function(resolverTy,
                                          GlobalValue::ExternalLinkage,
                                          "getPointerToNamedFunction",
                                          SafeModule);

    // Use the function we just added to get addresses of functions we need
    // Iterate over the global declarations in the Safe module
    for (Module::iterator F=SafeModule->begin(),E=SafeModule->end(); F!=E; ++F){
      if (F->isExternal() && !F->use_empty() && &(*F) != resolverFunc) {
        // If it has a non-zero use list,
        // 1. Add a string constant with its name to the global file
        // The correct type is `const [ NUM x sbyte ]' where NUM is length of
        // function name + 1
        const std::string &Name = F->getName();
        GlobalVariable *funcName =
          new GlobalVariable(ArrayType::get(Type::SByteTy, Name.length()+1),
                             true /* isConstant */,
                             GlobalValue::InternalLinkage,
                             ConstantArray::get(Name),
                             Name + "_name",
                             SafeModule);

        // 2. Use `GetElementPtr *funcName, 0, 0' to convert the string to an
        // sbyte* so it matches the signature of the resolver function.
        std::vector<Constant*> GEPargs(2, Constant::getNullValue(Type::LongTy));

        // 3. Replace all uses of `func' with calls to resolver by:
        // (a) Iterating through the list of uses of this function
        // (b) Insert a cast instruction in front of each use
        // (c) Replace use of old call with new call

        // GetElementPtr *funcName, ulong 0, ulong 0
        Value *GEP =
          ConstantExpr::getGetElementPtr(ConstantPointerRef::get(funcName),
                                         GEPargs);
        std::vector<Value*> ResolverArgs;
        ResolverArgs.push_back(GEP);

        // Insert code at the beginning of the function
        for (Value::use_iterator i=F->use_begin(), e=F->use_end(); i!=e; ++i) {
          if (Instruction* Inst = dyn_cast<Instruction>(*i)) {
            // call resolver(GetElementPtr...)
            CallInst *resolve = new CallInst(resolverFunc, ResolverArgs,
                                             "resolver", Inst);
            // cast the result from the resolver to correctly-typed function
            CastInst *castResolver =
              new CastInst(resolve, PointerType::get(F->getFunctionType()),
                           "", Inst);
            // actually use the resolved function
            Inst->replaceUsesOfWith(F, castResolver);
          } else {
            // FIXME: need to take care of cases where a function is used that
            // is not an instruction, e.g. global variable initializer...
            std::cerr << "Non-instruction is using an external function!\n";
            abort();
          }
        }
      }
    }
  }

  DEBUG(std::cerr << "Safe module:\n";
        typedef Module::iterator MI;
        typedef Module::giterator MGI;

        for (MI I = SafeModule->begin(), E = SafeModule->end(); I != E; ++I)
          if (!I->isExternal()) std::cerr << "\t" << I->getName() << "\n";
        for (MGI I = SafeModule->gbegin(), E = SafeModule->gend(); I!=E; ++I)
          if (!I->isExternal()) std::cerr << "\t" << I->getName() << "\n";

        std::cerr << "Test module:\n";
        for (MI I = TestModule->begin(), E = TestModule->end(); I != E; ++I)
          if (!I->isExternal()) std::cerr << "\t" << I->getName() << "\n";
        for (MGI I=TestModule->gbegin(),E = TestModule->gend(); I!= E; ++I)
          if (!I->isExternal()) std::cerr << "\t" << I->getName() << "\n";
        );

  // Write out the bytecode to be sent to CBE
  std::string SafeModuleBC = getUniqueFilename("bugpoint.safe.bc");
  if (verifyModule(*SafeModule)) {
    std::cerr << "Bytecode file corrupted!\n";
    exit(1);
  }
  if (BD.writeProgramToFile(SafeModuleBC, SafeModule)) {
    std::cerr << "Error writing bytecode to `" << SafeModuleBC << "'\nExiting.";
    exit(1);
  }

  // Make a shared library
  std::string SharedObject;
  BD.compileSharedObject(SafeModuleBC, SharedObject);

  // Remove all functions from the Test module EXCEPT for the ones specified in
  // Funcs.  We know which ones these are because they are non-external in
  // ToOptimize, but external in ToNotOptimize.
  //
  for (Module::iterator I = TestModule->begin(), E = TestModule->end();I!=E;++I)
    if (!I->isExternal()) {
      Function *TNOF = SafeModule->getFunction(I->getName(),
                                               I->getFunctionType());
      assert(TNOF && "Function doesn't exist in ToNotOptimize module??");
      if (!TNOF->isExternal())
        DeleteFunctionBody(I);
    }

  std::string TestModuleBC = getUniqueFilename("bugpoint.test.bc");
  if (verifyModule(*TestModule)) {
    std::cerr << "Bytecode file corrupted!\n";
    exit(1);
  }
  if (BD.writeProgramToFile(TestModuleBC, TestModule)) {
    std::cerr << "Error writing bytecode to `" << SafeModuleBC << "'\nExiting.";
    exit(1);
  }

  delete SafeModule;
  delete TestModule;

  // Run the code generator on the `Test' code, loading the shared library.
  // The function returns whether or not the new output differs from reference.
  int Result =  BD.diffProgram(TestModuleBC, SharedObject, false);
  if (KeepFiles) {
    std::cout << "You can reproduce the problem with the command line: \n"
              << (BD.isExecutingJIT() ? "lli" : "llc")
              << " -load " << SharedObject << " " << TestModuleBC
              << "\n";
  } else {
    removeFile(TestModuleBC);
    removeFile(SafeModuleBC);
    removeFile(SharedObject);
  }
  return Result;
}

namespace {
  struct Disambiguator {
    std::set<std::string>  SymbolNames;
    std::set<GlobalValue*> Symbols;
    uint64_t uniqueCounter;
    bool externalOnly;
  public:
    Disambiguator() : uniqueCounter(0), externalOnly(true) {}
    void setExternalOnly(bool value) { externalOnly = value; }
    void add(GlobalValue &V) {
      // If we're only processing externals and this isn't external, bail
      if (externalOnly && !V.isExternal()) return;
      // If we're already processed this symbol, don't add it again
      if (Symbols.count(&V) != 0) return;

      std::string SymName = V.getName();

      // Use the Mangler facility to make symbol names that will be valid in
      // shared objects.
      SymName = Mangler::makeNameProper(SymName);
      V.setName(SymName);

      if (SymbolNames.count(SymName) == 0) {
        DEBUG(std::cerr << "Disambiguator: adding " << SymName
                        << ", no conflicts.\n");
        SymbolNames.insert(SymName);
      } else {
        // Mangle name before adding
        std::string newName;
        do {
          newName = SymName + "_" + utostr(uniqueCounter);
          if (SymbolNames.count(newName) == 0) break;
          else ++uniqueCounter;
        } while (1);
        //while (SymbolNames.count(V->getName()+utostr(uniqueCounter++))==0);
        DEBUG(std::cerr << "Disambiguator: conflict: " << SymName
                        << ", adding: " << newName << "\n");
        V.setName(newName);
        SymbolNames.insert(newName);
      }
      Symbols.insert(&V);
    }
  };
}

void ReduceMisCodegenFunctions::DisambiguateGlobalSymbols(Module *M) {
  // First, try not to cause collisions by minimizing chances of renaming an
  // already-external symbol, so take in external globals and functions as-is.
  Disambiguator D;
  DEBUG(std::cerr << "Disambiguating globals (external-only)\n");
  for (Module::giterator I = M->gbegin(), E = M->gend(); I != E; ++I) D.add(*I);
  DEBUG(std::cerr << "Disambiguating functions (external-only)\n");
  for (Module::iterator  I = M->begin(),  E = M->end();  I != E; ++I) D.add(*I);

  // Now just rename functions and globals as necessary, keeping what's already
  // in the set unique.
  D.setExternalOnly(false);
  DEBUG(std::cerr << "Disambiguating globals\n");
  for (Module::giterator I = M->gbegin(), E = M->gend(); I != E; ++I) D.add(*I);
  DEBUG(std::cerr << "Disambiguating globals\n");
  for (Module::iterator  I = M->begin(),  E = M->end();  I != E; ++I) D.add(*I);
}

bool BugDriver::debugCodeGenerator() {
  // See if we can pin down which functions are being miscompiled...
  //First, build a list of all of the non-external functions in the program.
  std::vector<Function*> MisCodegenFunctions;
  for (Module::iterator I = Program->begin(), E = Program->end(); I != E; ++I)
    if (!I->isExternal())
      MisCodegenFunctions.push_back(I);

  // If we are executing the JIT, we *must* keep the function `main' in the
  // module that is passed in, and not the shared library. However, we still
  // want to be able to debug the `main' function alone. Thus, we create a new
  // function `main' which just calls the old one.
  if (isExecutingJIT()) {
    // Get the `main' function
    Function *oldMain = Program->getNamedFunction("main");
    // Rename it
    oldMain->setName("old_main");
    // Create a NEW `main' function with same type
    Function *newMain = new Function(oldMain->getFunctionType(),
                                     GlobalValue::ExternalLinkage,
                                     "main", Program);
    // Call the old main function and return its result
    BasicBlock *BB = new BasicBlock("entry", newMain);
    std::vector<Value*> args;
    for (Function::aiterator I=newMain->abegin(), E=newMain->aend(); I!=E; ++I)
      args.push_back(I);
    CallInst *call = new CallInst(oldMain, args);
    BB->getInstList().push_back(call);

    // if the type of old function wasn't void, return value of call
    ReturnInst *ret;
    if (oldMain->getReturnType() != Type::VoidTy) {
      ret = new ReturnInst(call);
    } else {
      ret = new ReturnInst();
    }

    // Add the return instruction to the BasicBlock
    BB->getInstList().push_back(ret);
  }

  // Do the reduction...
  ReduceMisCodegenFunctions(*this).reduceList(MisCodegenFunctions);

  std::cout << "\n*** The following functions are being miscompiled: ";
  PrintFunctionList(MisCodegenFunctions);
  std::cout << "\n";

  // Output a bunch of bytecode files for the user...
  ReduceMisCodegenFunctions(*this).TestFuncs(MisCodegenFunctions, true);

  return false;
}

<|endoftext|>


<commit_before>#include "vtkMultiProcessController.h"
#include "vtkDoubleArray.h"
#include "vtkCharArray.h"
#include "vtkIntArray.h"
#include "vtkUnsignedLongArray.h"
#include "vtkFloatArray.h"
#include "vtkIdTypeArray.h"
#include "vtkOutputPort.h"
#include "vtkDebugLeaks.h"
#include "vtkActor.h"
#include "vtkRenderWindow.h"
#include "vtkRenderer.h"
#include "vtkInputPort.h"
#include "vtkPolyDataMapper.h"
#include "vtkParallelFactory.h"
#include "vtkRTAnalyticSource.h"
#include "vtkContourFilter.h"
#include "vtkRenderWindowInteractor.h"

#include "vtkDebugLeaks.h"
#include "vtkRegressionTestImage.h"

static const int scMsgLength = 10;

struct GenericCommunicatorArgs_tmp
{
  int* retVal;
  int argc;
  char** argv;
};

static void UpdateXFreq(void* arg)
{
  vtkRTAnalyticSource* id = reinterpret_cast<vtkRTAnalyticSource*>(arg);
  id->SetXFreq(id->GetXFreq()+20);
}

static void DeleteAnArg(void*)
{
  return;
}

void Process1(vtkMultiProcessController *contr, void *arg)
{
  vtkCommunicator* comm = contr->GetCommunicator();

  int i;

  // Test receiving all supported types of arrays
  vtkIntArray* ia = vtkIntArray::New();
  if (!comm->Receive(ia, 1, 11))
    {
    cerr << "Server error: Error receiving data." << endl;
    }
  for (i=0; i<ia->GetNumberOfTuples(); i++)
    {
    if (ia->GetValue(i) != i)
      {
      cerr << "Server error: Corrupt integer array." << endl;
      }
    }
  ia->Delete();

  vtkUnsignedLongArray* ula = vtkUnsignedLongArray::New();
  if (!comm->Receive(ula, 1, 22))
    {
    cerr << "Server error: Error receiving data." << endl;
    }
  for (i=0; i<ula->GetNumberOfTuples(); i++)
    {
    if (ula->GetValue(i) != static_cast<unsigned long>(i))
      {
      cerr << "Server error: Corrupt unsigned long array." << endl;
      }
    }
  ula->Delete();

  vtkCharArray* ca = vtkCharArray::New();
  if (!comm->Receive(ca, 1, 33))
    {
    cerr << "Server error: Error receiving data." << endl;
    }
  for (i=0; i<ca->GetNumberOfTuples(); i++)
    {
    if (ca->GetValue(i) != static_cast<char>(i))
      {
      cerr << "Server error: Corrupt char array." << endl;
      }
    }
  ca->Delete();

  vtkUnsignedCharArray* uca = vtkUnsignedCharArray::New();
  if (!comm->Receive(uca, 1, 44))
    {
    cerr << "Server error: Error receiving data." << endl;
    }
  for (i=0; i<uca->GetNumberOfTuples(); i++)
    {
    if (uca->GetValue(i) != static_cast<unsigned char>(i))
      {
      cerr << "Server error: Corrupt unsigned char array." << endl;
      }
    }
  uca->Delete();

  vtkFloatArray* fa = vtkFloatArray::New();
  if (!comm->Receive(fa, 1, 7))
    {
    cerr << "Server error: Error receiving data." << endl;
    }
  for (i=0; i<fa->GetNumberOfTuples(); i++)
    {
    if (fa->GetValue(i) != static_cast<float>(i))
      {
      cerr << "Server error: Corrupt float array." << endl;
      }
    }
  fa->Delete();

  vtkDoubleArray* da = vtkDoubleArray::New();
  if (!comm->Receive(da, 1, 7))
    {
    cerr << "Server error: Error receiving data." << endl;
    }
  for (i=0; i<da->GetNumberOfTuples(); i++)
    {
    if (da->GetValue(i) != static_cast<double>(i))
      {
      cerr << "Server error: Corrupt double array." << endl;
      }
    }
  da->Delete();

  vtkIdTypeArray* ita = vtkIdTypeArray::New();
  if (!comm->Receive(ita, 1, 7))
    {
    cerr << "Server error: Error receiving data." << endl;
    }
  for (i=0; i<ita->GetNumberOfTuples(); i++)
    {
    if (ita->GetValue(i) != static_cast<vtkIdType>(i))
      {
      cerr << "Server error: Corrupt vtkIdType array." << endl;
      }
    }
  ita->Delete();

  vtkOutputPort* op = vtkOutputPort::New();
  op->SetController(contr);
  op->SetTag(45);

  float extent = 20;
  vtkRTAnalyticSource* id = vtkRTAnalyticSource::New();
  id->SetWholeExtent (-extent, extent, -extent, extent, -extent, extent);
  id->SetCenter(0, 0, 0);
  id->SetStandardDeviation( 0.5 );
  id->SetMaximum( 255.0 );
  id->SetXFreq( 60 );
  id->SetXMag( 10 );
  id->SetYFreq( 30 );
  id->SetYMag( 18 );
  id->SetZFreq( 40 );
  id->SetZMag( 5 );
  id->GetOutput()->SetSpacing(2.0/extent,2.0/extent,2.0/extent);

  op->SetInput(id->GetOutput());
  op->PipelineFlagOn();
  op->SetParameterMethod(UpdateXFreq, id);
  op->SetParameterMethodArgDelete(DeleteAnArg);
  op->WaitForUpdate();
  id->Delete();

  op->Delete();
}

void Process2(vtkMultiProcessController *contr, void *arg)
{
  GenericCommunicatorArgs_tmp* args =
    reinterpret_cast<GenericCommunicatorArgs_tmp*>(arg);

  vtkCommunicator* comm = contr->GetCommunicator();

  int i;

  // Test sending all supported types of arrays
  int datai[scMsgLength];
  for (i=0; i<scMsgLength; i++)
    {
    datai[i] = i;
    }
  vtkIntArray* ia = vtkIntArray::New();
  ia->SetArray(datai, 10, 1);
  if (!comm->Send(ia, 0, 11))
    {
    cerr << "Client error: Error sending data." << endl;
    }
  ia->Delete();

  unsigned long dataul[scMsgLength];
  for (i=0; i<scMsgLength; i++)
    {
    dataul[i] = static_cast<unsigned long>(i);
    }
  vtkUnsignedLongArray* ula = vtkUnsignedLongArray::New();
  ula->SetArray(dataul, 10, 1);
  if (!comm->Send(ula, 0, 22))
    {
    cerr << "Client error: Error sending data." << endl;
    }
  ula->Delete();

  char datac[scMsgLength];
  for (i=0; i<scMsgLength; i++)
    {
    datac[i] = static_cast<char>(i);
    }
  vtkCharArray* ca = vtkCharArray::New();
  ca->SetArray(datac, 10, 1);
  if (!comm->Send(ca, 0, 33))
    {
    cerr << "Client error: Error sending data." << endl;
    }
  ca->Delete();

  unsigned char datauc[scMsgLength];
  for (i=0; i<scMsgLength; i++)
    {
    datauc[i] = static_cast<unsigned char>(i);
    }
  vtkUnsignedCharArray* uca = vtkUnsignedCharArray::New();
  uca->SetArray(datauc, 10, 1);
  if (!comm->Send(uca, 0, 44))
    {
    cerr << "Client error: Error sending data." << endl;
    }
  uca->Delete();

  float dataf[scMsgLength];
  for (i=0; i<scMsgLength; i++)
    {
    dataf[i] = static_cast<float>(i);
    }
  vtkFloatArray* fa = vtkFloatArray::New();
  fa->SetArray(dataf, 10, 1);
  if (!comm->Send(fa, 0, 7))
    {
    cerr << "Client error: Error sending data." << endl;
    }
  fa->Delete();

  double datad[scMsgLength];
  for (i=0; i<scMsgLength; i++)
    {
    datad[i] = static_cast<double>(i);
    }
  vtkDoubleArray* da = vtkDoubleArray::New();
  da->SetArray(datad, 10, 1);
  if (!comm->Send(da, 0, 7))
    {
    cerr << "Client error: Error sending data." << endl;
    }
  da->Delete();

  vtkIdType datait[scMsgLength];
  for (i=0; i<scMsgLength; i++)
    {
    datait[i] = static_cast<vtkIdType>(i);
    }
  vtkIdTypeArray* ita = vtkIdTypeArray::New();
  ita->SetArray(datait, 10, 1);
  if (!comm->Send(ita, 0, 7))
    {
    cerr << "Client error: Error sending data." << endl;
    }
  ita->Delete();

  // Test the ports
  vtkInputPort* ip = vtkInputPort::New();
  ip->SetController(contr);
  ip->SetTag(45);
  ip->SetRemoteProcessId(0);

  // Get polydata
  ip->GetImageDataOutput()->Update();

  vtkContourFilter* cf = vtkContourFilter::New();
  cf->SetInput(ip->GetImageDataOutput());
  cf->SetNumberOfContours(1);
  cf->SetValue(0, 220);

  vtkPolyDataMapper* pmapper = vtkPolyDataMapper::New();
  pmapper->SetInput(cf->GetOutput());
  cf->Delete();

  vtkActor* pactor = vtkActor::New();
  pactor->SetMapper(pmapper);
  pmapper->UnRegister(0);

  vtkRenderer* ren = vtkRenderer::New();
  ren->AddActor(pactor);
  pactor->UnRegister(0);

  vtkRenderWindow* renWin = vtkRenderWindow::New();
  renWin->AddRenderer(ren);
  ren->UnRegister(0);

  vtkRenderWindowInteractor* iren = vtkRenderWindowInteractor::New();
  iren->SetRenderWindow(renWin);
  iren->Initialize();

  renWin->Render();
  renWin->Render();

  *(args->retVal) =
    vtkRegressionTester::Test(args->argc, args->argv, renWin, 10);

  if ( *(args->retVal) == vtkRegressionTester::DO_INTERACTOR)
    {
    iren->Start();
    }
  iren->Delete();

  contr->TriggerRMI(0, vtkMultiProcessController::BREAK_RMI_TAG);

  ip->Delete();
  renWin->Delete();
}

int main(int argc, char** argv)
{
  vtkDebugLeaks::PromptUserOff();

  vtkMultiProcessController* contr = vtkMultiProcessController::New();
  contr->Initialize(&argc, &argv);

  vtkParallelFactory* pf = vtkParallelFactory::New();
  vtkObjectFactory::RegisterFactory(pf);
  pf->Delete();

  // This is repeated for the sake of MPI. This one might not
  // get called by the parent process, the first one might not
  // get called by all others.
  vtkDebugLeaks::PromptUserOff();

  // When using MPI, the number of processes is determined
  // by the external program which launches this application.
  // However, when using threads, we need to set it ourselves.
  if (contr->IsA("vtkThreadedController"))
    {
    // Set the number of processes to 2 for this example.
    contr->SetNumberOfProcesses(2);
    }

  // Added for regression test.
  // ----------------------------------------------
  int retVal;
  GenericCommunicatorArgs_tmp args;
  args.retVal = &retVal;
  args.argc = argc;
  args.argv = argv;
  // ----------------------------------------------

  contr->SetMultipleMethod(0, Process1, 0);
  contr->SetMultipleMethod(1, Process2, &args);
  contr->MultipleMethodExecute();

  contr->Finalize();
  contr->Delete();

  return !retVal;
}
<commit_msg>Increasing coverage.<commit_after>#include "vtkMultiProcessController.h"
#include "vtkDoubleArray.h"
#include "vtkCharArray.h"
#include "vtkIntArray.h"
#include "vtkUnsignedLongArray.h"
#include "vtkFloatArray.h"
#include "vtkIdTypeArray.h"
#include "vtkOutputPort.h"
#include "vtkDebugLeaks.h"
#include "vtkActor.h"
#include "vtkRenderWindow.h"
#include "vtkRenderer.h"
#include "vtkInputPort.h"
#include "vtkPolyDataMapper.h"
#include "vtkParallelFactory.h"
#include "vtkRTAnalyticSource.h"
#include "vtkContourFilter.h"
#include "vtkRenderWindowInteractor.h"

#include "vtkDebugLeaks.h"
#include "vtkRegressionTestImage.h"

static const int scMsgLength = 10;

struct GenericCommunicatorArgs_tmp
{
  int* retVal;
  int argc;
  char** argv;
};

static void UpdateXFreq(void* arg)
{
  vtkRTAnalyticSource* id = reinterpret_cast<vtkRTAnalyticSource*>(arg);
  id->SetXFreq(id->GetXFreq()+20);
}

static void DeleteAnArg(void*)
{
  return;
}

void Process1(vtkMultiProcessController *contr, void *arg)
{
  vtkCommunicator* comm = contr->GetCommunicator();

  int i;

  // Test receiving all supported types of arrays
  vtkIntArray* ia = vtkIntArray::New();
  if (!comm->Receive(ia, 1, 11))
    {
    cerr << "Server error: Error receiving data." << endl;
    }
  for (i=0; i<ia->GetNumberOfTuples(); i++)
    {
    if (ia->GetValue(i) != i)
      {
      cerr << "Server error: Corrupt integer array." << endl;
      }
    }
  ia->Delete();

  vtkUnsignedLongArray* ula = vtkUnsignedLongArray::New();
  if (!comm->Receive(ula, 1, 22))
    {
    cerr << "Server error: Error receiving data." << endl;
    }
  for (i=0; i<ula->GetNumberOfTuples(); i++)
    {
    if (ula->GetValue(i) != static_cast<unsigned long>(i))
      {
      cerr << "Server error: Corrupt unsigned long array." << endl;
      }
    }
  ula->Delete();

  vtkCharArray* ca = vtkCharArray::New();
  if (!comm->Receive(ca, 1, 33))
    {
    cerr << "Server error: Error receiving data." << endl;
    }
  for (i=0; i<ca->GetNumberOfTuples(); i++)
    {
    if (ca->GetValue(i) != static_cast<char>(i))
      {
      cerr << "Server error: Corrupt char array." << endl;
      }
    }
  ca->Delete();

  vtkUnsignedCharArray* uca = vtkUnsignedCharArray::New();
  if (!comm->Receive(uca, 1, 44))
    {
    cerr << "Server error: Error receiving data." << endl;
    }
  for (i=0; i<uca->GetNumberOfTuples(); i++)
    {
    if (uca->GetValue(i) != static_cast<unsigned char>(i))
      {
      cerr << "Server error: Corrupt unsigned char array." << endl;
      }
    }
  uca->Delete();

  vtkFloatArray* fa = vtkFloatArray::New();
  if (!comm->Receive(fa, 1, 7))
    {
    cerr << "Server error: Error receiving data." << endl;
    }
  for (i=0; i<fa->GetNumberOfTuples(); i++)
    {
    if (fa->GetValue(i) != static_cast<float>(i))
      {
      cerr << "Server error: Corrupt float array." << endl;
      }
    }
  fa->Delete();

  vtkDoubleArray* da = vtkDoubleArray::New();
  if (!comm->Receive(da, 1, 7))
    {
    cerr << "Server error: Error receiving data." << endl;
    }
  for (i=0; i<da->GetNumberOfTuples(); i++)
    {
    if (da->GetValue(i) != static_cast<double>(i))
      {
      cerr << "Server error: Corrupt double array." << endl;
      }
    }
  da->Delete();

  vtkIdTypeArray* ita = vtkIdTypeArray::New();
  if (!comm->Receive(ita, 1, 7))
    {
    cerr << "Server error: Error receiving data." << endl;
    }
  for (i=0; i<ita->GetNumberOfTuples(); i++)
    {
    if (ita->GetValue(i) != static_cast<vtkIdType>(i))
      {
      cerr << "Server error: Corrupt vtkIdType array." << endl;
      }
    }
  ita->Delete();

  vtkOutputPort* op = vtkOutputPort::New();
  op->SetController(contr);
  op->SetTag(45);

  float extent = 20;
  vtkRTAnalyticSource* id = vtkRTAnalyticSource::New();
  id->SetWholeExtent (-extent, extent, -extent, extent, -extent, extent);
  id->SetCenter(0, 0, 0);
  id->SetStandardDeviation( 0.5 );
  id->SetMaximum( 255.0 );
  id->SetXFreq( 60 );
  id->SetXMag( 10 );
  id->SetYFreq( 30 );
  id->SetYMag( 18 );
  id->SetZFreq( 40 );
  id->SetZMag( 5 );
  id->GetOutput()->SetSpacing(2.0/extent,2.0/extent,2.0/extent);

  op->SetInput(id->GetOutput());
  op->PipelineFlagOn();
  op->SetParameterMethod(UpdateXFreq, id);
  op->SetParameterMethodArgDelete(DeleteAnArg);
  op->WaitForUpdate();
  id->Delete();

  op->Delete();
}

void Process2(vtkMultiProcessController *contr, void *arg)
{
  GenericCommunicatorArgs_tmp* args =
    reinterpret_cast<GenericCommunicatorArgs_tmp*>(arg);

  vtkCommunicator* comm = contr->GetCommunicator();

  int i;

  // Test sending all supported types of arrays
  int datai[scMsgLength];
  for (i=0; i<scMsgLength; i++)
    {
    datai[i] = i;
    }
  vtkIntArray* ia = vtkIntArray::New();
  ia->SetArray(datai, 10, 1);
  if (!comm->Send(ia, 0, 11))
    {
    cerr << "Client error: Error sending data." << endl;
    }
  ia->Delete();

  unsigned long dataul[scMsgLength];
  for (i=0; i<scMsgLength; i++)
    {
    dataul[i] = static_cast<unsigned long>(i);
    }
  vtkUnsignedLongArray* ula = vtkUnsignedLongArray::New();
  ula->SetArray(dataul, 10, 1);
  if (!comm->Send(ula, 0, 22))
    {
    cerr << "Client error: Error sending data." << endl;
    }
  ula->Delete();

  char datac[scMsgLength];
  for (i=0; i<scMsgLength; i++)
    {
    datac[i] = static_cast<char>(i);
    }
  vtkCharArray* ca = vtkCharArray::New();
  ca->SetArray(datac, 10, 1);
  if (!comm->Send(ca, 0, 33))
    {
    cerr << "Client error: Error sending data." << endl;
    }
  ca->Delete();

  unsigned char datauc[scMsgLength];
  for (i=0; i<scMsgLength; i++)
    {
    datauc[i] = static_cast<unsigned char>(i);
    }
  vtkUnsignedCharArray* uca = vtkUnsignedCharArray::New();
  uca->SetArray(datauc, 10, 1);
  if (!comm->Send(uca, 0, 44))
    {
    cerr << "Client error: Error sending data." << endl;
    }
  uca->Delete();

  float dataf[scMsgLength];
  for (i=0; i<scMsgLength; i++)
    {
    dataf[i] = static_cast<float>(i);
    }
  vtkFloatArray* fa = vtkFloatArray::New();
  fa->SetArray(dataf, 10, 1);
  if (!comm->Send(fa, 0, 7))
    {
    cerr << "Client error: Error sending data." << endl;
    }
  fa->Delete();

  double datad[scMsgLength];
  for (i=0; i<scMsgLength; i++)
    {
    datad[i] = static_cast<double>(i);
    }
  vtkDoubleArray* da = vtkDoubleArray::New();
  da->SetArray(datad, 10, 1);
  if (!comm->Send(da, 0, 7))
    {
    cerr << "Client error: Error sending data." << endl;
    }
  da->Delete();

  vtkIdType datait[scMsgLength];
  for (i=0; i<scMsgLength; i++)
    {
    datait[i] = static_cast<vtkIdType>(i);
    }
  vtkIdTypeArray* ita = vtkIdTypeArray::New();
  ita->SetArray(datait, 10, 1);
  if (!comm->Send(ita, 0, 7))
    {
    cerr << "Client error: Error sending data." << endl;
    }
  ita->Delete();

  // Test the ports
  vtkInputPort* ip = vtkInputPort::New();
  ip->SetController(contr);
  ip->SetTag(45);
  ip->SetRemoteProcessId(0);

  // Get polydata
  ip->GetImageDataOutput()->Update();

  vtkContourFilter* cf = vtkContourFilter::New();
  cf->SetInput(ip->GetImageDataOutput());
  cf->SetNumberOfContours(1);
  cf->SetValue(0, 220);

  vtkPolyDataMapper* pmapper = vtkPolyDataMapper::New();
  pmapper->SetInput(cf->GetOutput());
  cf->Delete();

  vtkActor* pactor = vtkActor::New();
  pactor->SetMapper(pmapper);
  pmapper->UnRegister(0);

  vtkRenderer* ren = vtkRenderer::New();
  ren->AddActor(pactor);
  pactor->UnRegister(0);

  vtkRenderWindow* renWin = vtkRenderWindow::New();
  renWin->AddRenderer(ren);
  ren->UnRegister(0);

  vtkRenderWindowInteractor* iren = vtkRenderWindowInteractor::New();
  iren->SetRenderWindow(renWin);
  iren->Initialize();

  renWin->Render();
  renWin->Render();

  *(args->retVal) =
    vtkRegressionTester::Test(args->argc, args->argv, renWin, 10);

  if ( *(args->retVal) == vtkRegressionTester::DO_INTERACTOR)
    {
    iren->Start();
    }
  iren->Delete();

  contr->TriggerRMI(0, vtkMultiProcessController::BREAK_RMI_TAG);

  ip->Delete();
  renWin->Delete();
}

int main(int argc, char** argv)
{
  vtkDebugLeaks::PromptUserOff();

  vtkMultiProcessController* contr = vtkMultiProcessController::New();
  contr->Initialize(&argc, &argv);
  contr->CreateOutputWindow();

  vtkParallelFactory* pf = vtkParallelFactory::New();
  vtkObjectFactory::RegisterFactory(pf);
  pf->Delete();

  // This is repeated for the sake of MPI. This one might not
  // get called by the parent process, the first one might not
  // get called by all others.
  vtkDebugLeaks::PromptUserOff();

  // When using MPI, the number of processes is determined
  // by the external program which launches this application.
  // However, when using threads, we need to set it ourselves.
  if (contr->IsA("vtkThreadedController"))
    {
    // Set the number of processes to 2 for this example.
    contr->SetNumberOfProcesses(2);
    }

  // Added for regression test.
  // ----------------------------------------------
  int retVal;
  GenericCommunicatorArgs_tmp args;
  args.retVal = &retVal;
  args.argc = argc;
  args.argv = argv;
  // ----------------------------------------------

  contr->SetMultipleMethod(0, Process1, 0);
  contr->SetMultipleMethod(1, Process2, &args);
  contr->MultipleMethodExecute();

  contr->Finalize();
  contr->Delete();

  return !retVal;
}
<|endoftext|>