/search.css" rel="stylesheet" type="text/css"/> /search.js">
00001 #include "RootIOSvc/RootInputStream.h" 00002 #include "RootIOSvc/RootInputFile.h" 00003 00004 RootInputStream::RootInputStream(void* addr, /*int clid,*/ 00005 const std::string& treepath, 00006 const std::string& branchname) 00007 : RootIOStream(addr) 00008 , m_files() 00009 , m_entry(-1) 00010 , m_clid(0) 00011 , m_entries(-1) 00012 , m_treepath(treepath) 00013 , m_branchname(branchname) 00014 , log("RootInputStream") 00015 { 00016 } 00017 00018 00019 RootInputStream::~RootInputStream() 00020 { 00021 // close file if needed 00022 } 00023 00024 int RootInputStream::clID() 00025 { 00026 return m_clid; 00027 } 00028 00029 std::string RootInputStream::path() 00030 { 00031 return m_treepath; 00032 } 00033 00034 std::string RootInputStream::filename() 00035 { 00036 RootInputFile* rif = m_files.current(); 00037 if (rif) return rif->filename(); 00038 return ""; 00039 } 00040 00041 int RootInputStream::fileNumber() 00042 { 00043 return m_files.index(); 00044 } 00045 00046 bool RootInputStream::append(const std::string& filename, bool ignore_missing) 00047 { 00048 if ("" == m_treepath || "" == m_branchname) { 00049 log << MSG::ERROR << "Can not guess tree path or branch name for " 00050 << filename << endreq; 00051 return false; 00052 } 00053 00054 int clid = RootInputFile::TestForObject(filename,m_treepath,m_branchname, true); 00055 if (m_clid && clid && clid != m_clid) { 00056 log << MSG::ERROR << "Bad class ID from new file " << filename 00057 << " for " << m_treepath 00058 << "; got " << clid << " (had " << m_clid << ")" 00059 << endreq; 00060 return false; 00061 } else if (!clid) { // not present 00062 if (ignore_missing) { 00063 // Even if this file is missing the path, we still need to add a 00064 // dummy entry to the input stream, since all input streams must 00065 // have the same number of files. 00066 m_files.push_back(new RootInputFile("","","")); 00067 } else { 00068 log << MSG::ERROR << "Missing class ID " << m_clid 00069 << " for " << m_treepath 00070 << " in file " << filename << endreq; 00071 return false; 00072 } 00073 } else { // we found it 00074 m_clid = clid; 00075 m_files.push_back(new RootInputFile(filename,m_treepath,m_branchname)); 00076 } 00077 00078 if (1 == m_files.size()) { 00079 m_files.next(); 00080 } 00081 return true; 00082 } 00083 00084 bool RootInputStream::append(const std::string& filename, 00085 const std::string& treepath, 00086 const std::string& branchname, 00087 bool ignore_missing) 00088 { 00089 if ("" != m_treepath) m_treepath = treepath; 00090 if ("" != m_branchname) m_branchname = branchname; 00091 00092 return append(filename, ignore_missing); 00093 } 00094 00095 // read expects corectly positioned and open file 00096 bool RootInputStream::read() 00097 { 00098 RootInputFile* rif = m_files.current(); 00099 if (!rif) { 00100 log << MSG::ERROR << "No current file" << endreq; 00101 return false; 00102 } 00103 00104 int nbytes = 0; 00105 bool ok = rif->read(m_addr,nbytes); 00106 log << MSG::DEBUG << "read() " << nbytes 00107 << " bytes at entry " << m_entry 00108 << " from file \"" << rif->filename() 00109 << "\" to path \"" << this->path() 00110 << endreq; 00111 return ok; 00112 } 00113 00114 bool RootInputStream::setEntry(int entry, bool read) 00115 { 00116 int steps = entry - m_entry; 00117 log << MSG::DEBUG << "setEntry(entry="<<entry<<",read="<<read<<") steps = " << steps 00118 << " (stream=\"" << this->path() << "\")" 00119 << endreq; 00120 if (steps < 0) return prev(-steps, read); 00121 if (steps > 0) return next(steps, read); 00122 return true; // no change 00123 } 00124 00125 bool RootInputStream::setFileEntry(int file, int entry, bool read) 00126 { 00127 if (!m_files.jump(file)) { 00128 log << MSG::ERROR 00129 << "jump("<<file<<"): failed" 00130 << endreq; 00131 return false; 00132 } 00133 RootInputFile* rif = m_files.current(); 00134 if (!rif) { 00135 log << MSG::ERROR << "Failed to get current file #" << file << endreq; 00136 return false; 00137 } 00138 if (!rif->setEntry(entry)) { 00139 log << MSG::ERROR << "Failed to set entry " << entry << " on file #" << file << endreq; 00140 return false; 00141 } 00142 00144 int totEntries = m_files.entriesBefore(file); 00145 if (totEntries < 0) { 00146 log << MSG::ERROR << "Failed to get sane number of entries before file#" << file << endreq; 00147 return false; 00148 } 00149 m_entry = totEntries + entry; 00150 log << MSG::DEBUG << "setFileEntry(file="<<file<<",entry="<<entry<<",read="<<read<<") " 00151 << "totEntries=" << totEntries <<" m_entry=" << m_entry 00152 << " (stream=\"" << this->path() 00153 << "\", filename=\"" << rif->filename() << "\")" 00154 << endreq; 00155 00156 if (read) return this->read(); 00157 return true; 00158 00159 } 00160 00161 bool RootInputStream::next(int nsteps, bool read) 00162 { 00163 RootInputFile* rif = m_files.current(); 00164 00165 if (!rif) { 00166 log << MSG::ERROR << "No files" << endreq; 00167 return false; 00168 } 00169 00170 log << MSG::DEBUG << "next(nsteps="<<nsteps<<",read="<<read<<")" 00171 << " (stream=\"" << this->path() << "\")" 00172 << endreq; 00173 00174 while (nsteps) { 00175 00176 // must leave current file? 00177 if (rif->entry() + nsteps >= rif->entries()) { 00178 00179 // burn what steps current file provides 00180 int jump = rif->entries() - (rif->entry() + 1); 00181 nsteps -= jump; 00182 m_entry += jump; 00183 if (!m_files.next()) { 00184 log << MSG::INFO 00185 << "next(): no more files to go to next:" 00186 << " jump = " << jump 00187 << " nsteps = " << nsteps 00188 << " entry = " << m_entry 00189 << " tentries=" << rif->entries() << endreq; 00190 return false; 00191 } 00192 rif = m_files.current(); 00193 continue; 00194 } 00195 00196 // Current file has enough entries left 00197 rif->next(nsteps); 00198 m_entry += nsteps; 00199 nsteps = 0; 00200 break; 00201 } 00202 log << MSG::DEBUG << "next(): at stream entry " << m_entry 00203 << " (file: " << rif->filename() << " file entry: " << rif->entry() << ")" 00204 << " (stream=\"" << this->path() << "\")" 00205 << endreq; 00206 if (read) return this->read(); 00207 return true; 00208 } 00209 00210 bool RootInputStream::prev(int nsteps, bool read) 00211 { 00212 RootInputFile* rif = m_files.current(); 00213 if (!rif) { 00214 log << MSG::ERROR << "No files yet, cannot go prev" << endreq; 00215 return false; 00216 } 00217 00218 log << MSG::DEBUG << "prev(nsteps="<<nsteps<<",read="<<read<<")" 00219 << " (stream=\"" << this->path() << "\")" 00220 << endreq; 00221 00222 while (nsteps) { 00223 00224 // must leave current file? 00225 if (rif->entry()-nsteps < 0) { 00226 00227 // Burn what steps this file provides 00228 int jump = 1 + rif->entry(); 00229 nsteps -= jump; 00230 m_entry -= jump; 00231 if (!m_files.prev()) { 00232 log << MSG::ERROR << "Already at first file, cannot go prev" 00233 << endreq; 00234 return false; 00235 } 00236 rif = m_files.current(); 00237 rif->ending(); // position file entry at end 00238 continue; 00239 } 00240 00241 // Can stay in current file 00242 rif->prev(nsteps); 00243 m_entry -= nsteps; 00244 nsteps = 0; 00245 break; 00246 } 00247 00248 log << MSG::DEBUG << "prev(): at stream entry " << m_entry 00249 << " (file: " << rif->filename() << " file entry: " << rif->entry() << ")" 00250 << " (stream=\"" << this->path() << "\")" 00251 << endreq; 00252 00253 if (read) return this->read(); 00254 return true; 00255 } 00256 00257 00258 bool RootInputStream::first(bool read) 00259 { 00260 bool okay = m_files.first(); 00261 if (!okay) { 00262 log << MSG::ERROR << "first(): failed to go to first file in stream" 00263 << endreq; 00264 return false; 00265 } 00266 00267 RootInputFile* rif = m_files.current(); 00268 if (!rif) { 00269 log << MSG::ERROR << "first(): failed to get current file in stream" 00270 << endreq; 00271 return false; 00272 } 00273 00274 okay = rif->beginning(); 00275 if (!okay) return false; 00276 00277 if (read) return this->read(); 00278 return true; 00279 } 00280 00281 00282 bool RootInputStream::last(bool read) 00283 { 00284 bool okay = m_files.last(); 00285 if (!okay) { 00286 log << MSG::ERROR << "last(): failed to go to last file in stream" 00287 << endreq; 00288 return false; 00289 } 00290 00291 RootInputFile* rif = m_files.current(); 00292 if (!rif) { 00293 log << MSG::ERROR << "last(): failed to get current file in stream" 00294 << endreq; 00295 return false; 00296 } 00297 00298 okay = rif->ending(); 00299 if (!okay) return false; 00300 00301 if (read) return this->read(); 00302 return true; 00303 } 00304 00305 int RootInputStream::entries() 00306 { 00307 if( m_entries>=0 ) { 00308 return m_entries; 00309 } else { 00310 m_entries=0; 00311 RootInputFileList::iterator it,itend = m_files.end(); 00312 for( it=m_files.begin(); it!=itend; it++ ) { 00313 m_entries+= (*it)->entries(); 00314 } 00315 return m_entries; 00316 } 00317 }