/search.css" rel="stylesheet" type="text/css"/> /search.js">
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" // debug 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 , m_majorIndex("") 00030 , m_minorIndex("") 00031 { 00032 TClass* cl = TClass::GetClass(classname.c_str()); 00033 if (!cl) { 00034 log << MSG::ERROR << "Failed to get class for " 00035 << classname << endreq; 00036 } 00037 00038 } 00039 00040 00041 RootOutputStream::~RootOutputStream() 00042 { 00043 this->close(); 00044 } 00045 00046 void RootOutputStream::setIndexExpression(const std::string& majorIndex, const std::string& minorIndex) 00047 { 00048 m_majorIndex = majorIndex; 00049 m_minorIndex = minorIndex; 00050 } 00051 00052 string RootOutputStream::path() 00053 { 00054 return m_treepath; 00055 } 00056 00057 00059 bool RootOutputStream::write() 00060 { 00061 if (!m_tree) { 00062 log << MSG::ERROR << "write(): no tree" 00063 << endreq; 00064 return false; 00065 } 00066 00067 int nbytes = m_tree->Fill(); 00068 log << MSG::DEBUG << "Wrote " << nbytes 00069 << " bytes to entry " << m_entries 00070 << " of tree " << m_treepath 00071 << endreq; 00072 00073 // Debugging #445. 00074 //TObject* dir = m_file->Get("Event/Sim"); 00075 //if (dir) dir->ls(); 00076 00077 ++m_entries; 00078 return nbytes > 0; 00079 } 00080 00081 int RootOutputStream::entries() 00082 { 00083 return m_entries; 00084 } 00085 00086 int RootOutputStream::fileEntries() 00087 { 00088 return m_tree->GetEntries(); 00089 } 00090 00091 bool RootOutputStream::close() 00092 { 00093 if (!m_file) return true; 00094 if (!m_tree) return true; 00095 00096 log << MSG::DEBUG << "Closing file " << m_file->GetName() << endreq; 00097 00098 if (m_majorIndex.size() || m_minorIndex.size()) { 00099 log << MSG::DEBUG 00100 << "Building index using major=\"" << m_majorIndex 00101 << "\", minor=\"" << m_minorIndex << "\"" << endreq; 00102 m_tree->BuildIndex(m_majorIndex.c_str(),m_minorIndex.c_str()); 00103 } 00104 00105 m_dir->cd(); 00106 m_tree->Write(NULL,TObject::kOverwrite); // for kOverwrite see #445 00107 RootOutputFileManager::get().close_file(m_file); 00108 m_file = 0; 00109 m_tree = 0; 00110 m_dir = 0; 00111 return true; 00112 } 00113 00114 00116 bool RootOutputStream::newFile(const string& filename, 00117 const string& treepath, 00118 const string& branchname) 00119 { 00120 // Only start a new file if filename differes 00121 if (m_file && filename == m_file->GetName()) { 00122 return true; 00123 } 00124 00125 if ("" != treepath) m_treepath = treepath; 00126 if ("" != branchname) m_branchname = branchname; 00127 00128 if ("" == m_treepath || "" == m_branchname) { 00129 log << MSG::ERROR 00130 << "newFile(): tree path or branch name are empty" 00131 << endreq; 00132 return false; 00133 } 00134 00135 this->close(); 00136 00137 m_file = RootOutputFileManager::get().get_file(filename); 00138 00139 // Make the directories up to but not including last one which is 00140 // the tree name. 00141 m_dir = m_file; 00142 string::size_type last = 0, slash = m_treepath.find('/'); 00143 for (; slash != string::npos; slash = m_treepath.find('/',last)) { 00144 if (!slash) { 00145 last = slash + 1; 00146 continue; // skip initial '/' 00147 } 00148 string subdir = m_treepath.substr(last,slash-last); 00149 TDirectory* dir = m_dir->GetDirectory(subdir.c_str()); 00150 if (dir) m_dir = dir; 00151 else m_dir = m_dir->mkdir(subdir.c_str()); 00152 last = slash + 1; 00153 } 00154 if (last) { 00155 string subdir = m_treepath.substr(0,last-1); 00156 m_file->cd(subdir.c_str()); 00157 } 00158 00159 string title = "Tree at " + m_treepath + " holding " + m_branchname; 00160 string treename = m_treepath.substr(last); 00161 00162 m_tree = new TTree(treename.c_str(),title.c_str()); 00163 m_tree->Branch(m_branchname.c_str(),m_classname.c_str(),m_addr); 00164 00165 bool ok = handle_user_data(); 00166 if (!ok) return false; 00167 00168 log << MSG::DEBUG 00169 << "newFile(): " << title << " in file " << filename 00170 << endreq; 00171 00172 return true; 00173 } 00174 00175 bool RootOutputStream::handle_user_data() 00176 { 00177 RootIOUserData ud; 00178 RootIOUserData::ProxyCollection& proxies = ud.output(m_treepath); 00179 RootIOUserData::ProxyCollection::iterator it, done = proxies.end(); 00180 00181 log << MSG::DEBUG << "newFile(): handling user data with " 00182 << proxies.size() << " proxies at treepath=" << m_treepath 00183 << " (one of " << ud.outputMap().size() << ")" 00184 << endreq; 00185 00186 bool ret = true; 00187 00188 for (it = proxies.begin(); it != done; ++it) { 00189 RootIOUserDataProxy* udp = it->second; 00190 bool ok = udp->branch(m_tree); 00191 if (ok) { 00192 log << MSG::DEBUG << "newFile(): initiated user data type: " 00193 << udp->cppType() << " name: " << udp->varName() << endreq; 00194 } 00195 else { 00196 log << MSG::ERROR << "newFile(): failed to initiate user data type: " 00197 << udp->cppType() << " name: " << udp->varName() << endreq; 00198 ret = false; 00199 } 00200 } 00201 return ret; 00202 } 00203