Source

mana-core-athenarootcomps / src / RootConnection.cxx

Full commit
///////////////////////// -*- C++ -*- /////////////////////////////
// RootConnection.cxx 
// Implementation file for class RootConnection
// Author Peter van Gemmeren <gemmeren@anl.gov>
// Author: S.Binet<binet@cern.ch>
/////////////////////////////////////////////////////////////////// 

// AthenaRootComps includes
#include "RootConnection.h"

// fwk
#include "GaudiKernel/ServiceHandle.h"

// ROOT
#include "TFile.h"
#include "TTree.h"
#include "TBranch.h"
#include "TBranchElement.h"
#include "TLeaf.h"

// Reflex
#include "Reflex/Type.h"

// stl
#include "CxxUtils/unordered_map.h" // move to stl when available.

namespace {
  
  char typecode_from_typeid(const std::type_info &ti) 
  {
    if        (ti == typeid(char*))     { return 'C';
    } else if (ti == typeid(Char_t))    { return 'B';
    } else if (ti == typeid(UChar_t))   { return 'b';
    } else if (ti == typeid(Short_t))   { return 'S';
    } else if (ti == typeid(UShort_t))  { return 's';
    } else if (ti == typeid(Int_t))     { return 'I';
    } else if (ti == typeid(UInt_t))    { return 'i';
    } else if (ti == typeid(Float_t))   { return 'F';
    } else if (ti == typeid(Double_t))  { return 'D';
    } else if (ti == typeid(Long64_t))  { return 'L';
    } else if (ti == typeid(ULong64_t)) { return 'l';
    } else if (ti == typeid(Bool_t))    { return 'O';
    } else {
      return '\0';
    }
  }
} //> anon-namespace

namespace Athena {

RootConnection::RootConnection(const IInterface* own, 
                               IIoSvc::Fd fd) :
  m_fd(fd),
  m_fid(), 
  m_pfn(), 
  m_age(0), 
  m_owner(own), 
  m_file(NULL), 
  m_tree(NULL), 
  m_branch(NULL),
  m_treeName("CollectionTree"),
  m_descr()
{
  m_pfn = ServiceHandle<IIoSvc>("AthIoSvc", "RootConnection")->fname(fd);
}

RootConnection::~RootConnection() 
{
  for (BranchDescriptors_t::iterator 
	 itr = m_descr.begin(), 
	 iend= m_descr.end();
       itr != iend;
       ++itr) {
    delete itr->second;
  }
}

StatusCode 
RootConnection::connectRead() 
{
  m_file = TFile::Open(m_pfn.c_str());
  TDirectory::TContext dir_ctx(m_file);

  if ( m_file && !m_file->IsZombie() )   {
    return StatusCode::SUCCESS;
  }
  else if ( m_file ) {
    delete m_file; m_file = NULL;
  }
  return StatusCode::FAILURE;
}

StatusCode
RootConnection::connectWrite(IIoSvc::IoType mode) 
{
  if (m_file == 0) {
    delete m_tree; m_tree = 0;
    m_file = TFile::Open(m_pfn.c_str(), 
                         IIoSvc::IoTypeName(mode).c_str(), 
                         "AthenaRoot event data file");
  }

  if (m_file != 0 && m_tree == 0) {
    int splitlevel = 0;
    m_tree = new TTree(m_treeName.c_str(), "Main event data tree", splitlevel);
  }
  return StatusCode::SUCCESS;
}

StatusCode 
RootConnection::commit() 
{
  if (m_file == 0 || m_tree == 0) {
    return StatusCode::FAILURE;
  }

  m_tree->SetEntries(m_branch->GetEntries());

  //FIXME: call OptimizeBaskets()
  //m_tree->AutoSave();
  //m_tree->FlushBaskets();
  return StatusCode::SUCCESS;
}

StatusCode 
RootConnection::disconnect() 
{
  if (!this->commit().isSuccess()) {
    return StatusCode::FAILURE;
  }
  if (m_tree != 0 && m_file->IsWritable()) {
    m_tree->Write(); m_tree = 0;
  }
  m_file->Close(); m_file = 0;
  return StatusCode::SUCCESS;
}

bool
RootConnection::isConnected() const 
{
   return false;
}

StatusCode
RootConnection::read(void* const /*data*/, size_t /*len*/) 
{
   return StatusCode::FAILURE;
}

StatusCode 
RootConnection::write(const void* data, unsigned long& len) 
{
  if (m_file == 0 || m_tree == 0 || m_branch == 0) {
    return(StatusCode::FAILURE);
  }
  BranchDescr* descr = m_descr[m_branch];
  descr->buffer = (void*)data;
  if (descr->typecode == '\0') {
    m_branch->SetAddress(&descr->buffer);
  } else {
    m_branch->SetAddress(descr->buffer);
  }
  int32_t nbytes = m_branch->Fill();
  if (nbytes < 0) {
    return StatusCode::FAILURE;
  }
  len = m_branch->GetEntryNumber();
  return StatusCode::SUCCESS;
}

StatusCode
RootConnection::setContainer(const std::string& container, 
                             const std::string& type, 
                             const void* data) 
{
  if (m_file == 0 || m_tree == 0) {
    return StatusCode::FAILURE;
  }
  const std::string& name = container;
  m_branch = m_tree->GetBranch(name.c_str());
  if (m_branch == 0 && m_file->IsWritable()) {
    int bufsize = 32000;	//FIXME: Make configurable
    int splitlevel = 0;	//FIXME: Make configurable
    Reflex::Type rflx_type = Reflex::Type::ByName(type);
    BranchDescr *brdescr = new BranchDescr;
    brdescr->typecode = ::typecode_from_typeid(rflx_type.TypeInfo());
    brdescr->buffer = ((void*)data);
    if (brdescr->typecode != '\0') {
      m_branch = m_tree->Branch(name.c_str(),
				(void*)brdescr->buffer,
				(name+"/"+brdescr->typecode).c_str(),
				bufsize);
    } else {
      m_branch = m_tree->Bronch((name+"").c_str(), 
				type.c_str(), 
				(void*)&brdescr->buffer, 
				bufsize, 
				splitlevel);
    }
    if (m_branch != 0) {
      // let the Athena framework deal with deletion
      m_branch->SetAutoDelete(kFALSE);

      int level = 1;	//FIXME: Make configurable
      m_branch->SetCompressionLevel(level);

      m_descr.insert(std::make_pair(m_branch, brdescr));
    }
  }
  if (m_branch == 0) {
    return StatusCode::FAILURE;
  }
  return StatusCode::SUCCESS;
}

void
RootConnection::setTreeName(const std::string& n)
{
  m_treeName = n;
}

}//> namespace Athena