00001 #include "RootIOSvc/RootOutputStream.h"
00002 #include "RootIOSvc/RootIOUserData.h"
00003 #include "RootIOSvc/RootIOUserDataProxy.h"
00004 #include "RootIOSvc/RootIOBaseObject.h"
00005 #include "RootOutputFileManager.h"
00006
00007 #include "TFile.h"
00008 #include "TTree.h"
00009
00010 #include "TClass.h"
00011
00012 #include <map>
00013
00014 using namespace std;
00015
00016 RootOutputStream::RootOutputStream(void* addr,
00017 const string& classname,
00018 const string& treepath,
00019 const string& branchname)
00020 : RootIOStream(addr)
00021 , m_file(0)
00022 , m_tree(0)
00023 , m_dir(0)
00024 , m_classname(classname)
00025 , m_treepath(treepath)
00026 , m_branchname(branchname)
00027 , m_entries(0)
00028 , log("RootOutputStream")
00029 {
00030 TClass* cl = TClass::GetClass(classname.c_str());
00031 if (!cl) {
00032 log << MSG::ERROR << "Failed to get class for "
00033 << classname << endreq;
00034 }
00035
00036 }
00037
00038
00039 RootOutputStream::~RootOutputStream()
00040 {
00041 this->close();
00042 }
00043
00044 string RootOutputStream::path()
00045 {
00046 return m_treepath;
00047 }
00048
00049
00051 bool RootOutputStream::write()
00052 {
00053 if (!m_tree) {
00054 log << MSG::ERROR << "write(): no tree"
00055 << endreq;
00056 return false;
00057 }
00058
00059 int nbytes = m_tree->Fill();
00060 log << MSG::DEBUG << "Wrote " << nbytes
00061 << " bytes to entry " << m_entries
00062 << " of tree " << m_treepath
00063 << endreq;
00064
00065
00066
00067
00068
00069 ++m_entries;
00070 return nbytes > 0;
00071 }
00072
00073 int RootOutputStream::entries()
00074 {
00075 return m_entries;
00076 }
00077
00078 int RootOutputStream::fileEntries()
00079 {
00080 return m_tree->GetEntries();
00081 }
00082
00083 bool RootOutputStream::close()
00084 {
00085 if (!m_file) return true;
00086 if (!m_tree) return true;
00087
00088 log << MSG::DEBUG << "Closing file " << m_file->GetName() << endreq;
00089
00090 m_dir->cd();
00091 m_tree->Write(NULL,TObject::kOverwrite);
00092 RootOutputFileManager::get().close_file(m_file);
00093 m_file = 0;
00094 m_tree = 0;
00095 m_dir = 0;
00096 return true;
00097 }
00098
00099
00101 bool RootOutputStream::newFile(const string& filename,
00102 const string& treepath,
00103 const string& branchname)
00104 {
00105
00106 if (m_file && filename == m_file->GetName()) {
00107 return true;
00108 }
00109
00110 if ("" != treepath) m_treepath = treepath;
00111 if ("" != branchname) m_branchname = branchname;
00112
00113 if ("" == m_treepath || "" == m_branchname) {
00114 log << MSG::ERROR
00115 << "newFile(): tree path or branch name are empty"
00116 << endreq;
00117 return false;
00118 }
00119
00120 this->close();
00121
00122 m_file = RootOutputFileManager::get().get_file(filename);
00123
00124
00125
00126 m_dir = m_file;
00127 string::size_type last = 0, slash = m_treepath.find('/');
00128 for (; slash != string::npos; slash = m_treepath.find('/',last)) {
00129 if (!slash) {
00130 last = slash + 1;
00131 continue;
00132 }
00133 string subdir = m_treepath.substr(last,slash-last);
00134 TDirectory* dir = m_dir->GetDirectory(subdir.c_str());
00135 if (dir) m_dir = dir;
00136 else m_dir = m_dir->mkdir(subdir.c_str());
00137 last = slash + 1;
00138 }
00139 if (last) {
00140 string subdir = m_treepath.substr(0,last-1);
00141 m_file->cd(subdir.c_str());
00142 }
00143
00144 string title = "Tree at " + m_treepath + " holding " + m_branchname;
00145 string treename = m_treepath.substr(last);
00146
00147 m_tree = new TTree(treename.c_str(),title.c_str());
00148 m_tree->Branch(m_branchname.c_str(),m_classname.c_str(),m_addr);
00149
00150 bool ok = handle_user_data();
00151 if (!ok) return false;
00152
00153 log << MSG::DEBUG
00154 << "newFile(): " << title << " in file " << filename
00155 << endreq;
00156
00157 return true;
00158 }
00159
00160 bool RootOutputStream::handle_user_data()
00161 {
00162 RootIOUserData ud;
00163 RootIOUserData::ProxyCollection& proxies = ud.output(m_treepath);
00164 RootIOUserData::ProxyCollection::iterator it, done = proxies.end();
00165
00166 log << MSG::DEBUG << "newFile(): handling user data with "
00167 << proxies.size() << " proxies at treepath=" << m_treepath
00168 << " (one of " << ud.outputMap().size() << ")"
00169 << endreq;
00170
00171 bool ret = true;
00172
00173 for (it = proxies.begin(); it != done; ++it) {
00174 RootIOUserDataProxy* udp = it->second;
00175 bool ok = udp->branch(m_tree);
00176 if (ok) {
00177 log << MSG::DEBUG << "newFile(): initiated user data type: "
00178 << udp->cppType() << " name: " << udp->varName() << endreq;
00179 }
00180 else {
00181 log << MSG::ERROR << "newFile(): failed to initiate user data type: "
00182 << udp->cppType() << " name: " << udp->varName() << endreq;
00183 ret = false;
00184 }
00185 }
00186 return ret;
00187 }
00188