ATLAS Offline Software
Loading...
Searching...
No Matches
VP1AvailEvents.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
3*/
4
5
7// //
8// Implementation of class VP1AvailEvents //
9// //
10// Author: Thomas H. Kittelmann (Thomas.Kittelmann@cern.ch) //
11// Initial version: May 2008 //
12// //
14
16#include "VP1Base/VP1Msg.h"
17#include <QFileInfo>
18#include <QDirIterator>
19#include <QTimer>
20
21#include <algorithm>
22#include <set>
23#include <map>
24#include <iostream>
25
26//____________________________________________________________________
28public:
31 QString tmpDir;
33 //subdirs in tmpDir, generated on the fly:
36
37 //Returns empty in case of problems:
38 QString attemptGenerationOfTmpSubdir(const QString& preferredname, QString& cachevar);
39
40 class EventID {
41 public:
42 EventID(int r, unsigned long long e) : eventNumber(e), runNumber(r) {}
43 unsigned long long eventNumber;
45 bool operator==(const EventID & o) const{
47 }
48 bool operator<(const EventID & o) const
49 {
50 //This ordering is not "newer". It is solely to be able to use in a set.
52 }
53 };
54
55 static EventID evtToID(const VP1EventFile& evt) {
56 return EventID(evt.runNumber(),evt.eventNumber());
57 }
58
59 QList<EventID> historyOrdered;
60 std::set<EventID> historySorted;
61 QList<VP1EventFile> lastAllLocal;
62 QList<VP1EventFile> lastFresh;
63
64 std::map<QString,std::pair<QDateTime,QList<VP1EventFile> > > dircache;//dirname -> (modtime,result)
65
67};
68
69
70//____________________________________________________________________
71VP1AvailEvents::VP1AvailEvents(int timeCutForNew, const QString& td, int maxLocalFilesToKeep, QObject * parent)
72 : QObject(parent), m_d(new Imp)
73{
74 m_d->theclass = this;
75 m_d->timeCutForNew = timeCutForNew;
76 m_d->tmpDir = QString(td + (td.endsWith("/")?"":"/")).replace("//","/");
77 m_d->maxLocalFilesToKeep = maxLocalFilesToKeep;
78}
79
80//____________________________________________________________________
82{
83 //Fixme: These two remove commands only has an effect when dir is empty!!
84 if (!m_d->tmpActiveRetrievalDir.isEmpty()&&m_d->tmpActiveRetrievalDir!="bad")
85 QFile::remove(m_d->tmpActiveRetrievalDir);
86 if (!m_d->tmpLocalFileDir.isEmpty()&&m_d->tmpLocalFileDir!="bad")
87 QFile::remove(m_d->tmpLocalFileDir);
88 delete m_d;
89}
90
91//____________________________________________________________________
93{
94 return m_d->timeCutForNew;
95}
96
97//____________________________________________________________________
99{
100 return m_d->maxLocalFilesToKeep;
101}
102
103//____________________________________________________________________
104const QString& VP1AvailEvents::tmpDir() const
105{
106 return m_d->tmpDir;
107}
108
109//____________________________________________________________________
110QList<VP1EventFile> VP1AvailEvents::freshEvents(VP1EventFile newestEvt, const QList<VP1EventFile>& inputEventList) const
111{
112 QList<VP1EventFile> l;
113 if (!newestEvt.isValid())
114 return l;
115 std::set<Imp::EventID>::const_iterator histIt, histItE(m_d->historySorted.end());
116 if (m_d->timeCutForNew==0) {
117 if (m_d->historySorted.find(Imp::evtToID(newestEvt))==histItE)
118 l << newestEvt;
119 return l;
120 }
121 for(VP1EventFile evt : inputEventList)
122 if (m_d->historySorted.find(Imp::evtToID(evt))==histItE && isConsideredFresh(evt,newestEvt))
123 l << evt;
124 return l;
125}
126
127
128//____________________________________________________________________
129QList<VP1EventFile> VP1AvailEvents::freshEvents() const
130{
132}
133
134//____________________________________________________________________
136{
137 QList<VP1EventFile> evts(allLocalEvents());
138 if (evts.isEmpty())
139 return VP1EventFile();//invalid
140 return evts.front();
141}
142
143//____________________________________________________________________
145{
146 m_d->historyOrdered << Imp::EventID(run,event);
147 m_d->historySorted.insert(Imp::EventID(run,event));
148}
149
150//____________________________________________________________________
152{
153 //First we cleanup:
154 m_d->cleanupTmpLocalFiles();
155
156 //Then we schedule a check for event list changes:
157 QTimer::singleShot(10, this, SLOT(actualCheckForEventListChanges()));
158}
159
160//____________________________________________________________________
162{
163 QList<VP1EventFile> allLocal = allLocalEvents();
164 QList<VP1EventFile> fresh = freshEvents();
165 if (m_d->lastAllLocal != allLocal) {
166 m_d->lastAllLocal = std::move(allLocal);
168 }
169 if (m_d->lastFresh != fresh) {
170 m_d->lastFresh = std::move(fresh);
172 }
173}
174
175//____________________________________________________________________
177{
178 //We schedule the cleanup to take place shortly. The check for event
179 //list changes will be scheduled after the cleanup:
180
181 //Then we schedule a check for event list changes:
182 QTimer::singleShot(10, this, SLOT(actualCleanup()));
183
184}
185
186//____________________________________________________________________
187bool VP1AvailEvents::inHistory(int run, int event) const
188{
189 return m_d->historySorted.find(Imp::EventID(run,event))!=m_d->historySorted.end();
190}
191
192
193//____________________________________________________________________
195{
196 std::map<QString,std::pair<QDateTime,QList<VP1EventFile> > >::iterator it = m_d->dircache.find(dir);
197 if (it!=m_d->dircache.end())
198 m_d->dircache.erase(it);
199}
200
201//____________________________________________________________________
202QList<VP1EventFile> VP1AvailEvents::allEventFilesInDir(const QString& dir) const
203{
204 if (dir.isEmpty())
205 return QList<VP1EventFile>();
206
207 QFileInfo fi_dir(dir);
208 if (!fi_dir.exists()||!fi_dir.isDir())
209 return QList<VP1EventFile>();
210
211 QDateTime modtime = fi_dir.lastModified();
212 if (abs(modtime.time().msecsTo(QTime::currentTime()))>50) {
213 std::map<QString,std::pair<QDateTime,QList<VP1EventFile> > >::iterator it = m_d->dircache.find(dir);
214 if (it!=m_d->dircache.end()&&it->second.first==modtime)
215 return it->second.second;
216 }
217
218 QStringList filters;
219 filters << "*_*.pool.root";
220 //fixme
221 QDirIterator itDir(dir,filters,QDir::Files | QDir::NoDotAndDotDot | QDir::Readable | QDir::CaseSensitive);
222
223 QList<VP1EventFile> l;
224 while (itDir.hasNext()) {
225 QString fn = itDir.next();
226 fn.replace("//","/");
227 VP1EventFile evt(fn);
228 if (evt.isValid())
229 l << evt;
230 else
231 message("Could not decode event file name: "+fn);
232 }
233
234 std::sort(l.begin(), l.end());
235
236 m_d->dircache[dir]=std::make_pair(modtime,l);
237 return l;
238}
239
240//____________________________________________________________________
241QList<VP1EventFile> VP1AvailEvents::allLocalEvents() const
242{
244}
245
246
247//____________________________________________________________________
248QString VP1AvailEvents::Imp::attemptGenerationOfTmpSubdir(const QString& preferredname, QString& cachevar)
249{
250 if (!cachevar.isEmpty())
251 return cachevar=="bad"?"":cachevar;
252
253 QFileInfo fi(tmpDir);
254 if (!( fi.exists()&&fi.isDir())) {
255 theclass->message("Could not create subdir in "+tmpDir+", since it does not exists or is not a directory" );
256 cachevar="bad";
257 return "";
258 }
259 int i(0);
260 while (true) {
261 ++i;
262 QString dir = tmpDir+(tmpDir.endsWith("/")?"":"/")+preferredname+(i==1?QString(""):QString::number(i))+"/";
263 if (!QFile::exists(dir)) {
264 bool ok = QDir().mkdir(dir);
265 if (!ok) {
266 theclass->message("Could not create directory:: "+dir );
267 cachevar="bad";
268 return "";
269 }
270 cachevar = dir;
271 return dir;
272 }
273 }
274}
275
276//____________________________________________________________________
278{
279 return m_d->attemptGenerationOfTmpSubdir("activeretrievals",m_d->tmpActiveRetrievalDir);
280}
281
282//____________________________________________________________________
284{
285 return m_d->attemptGenerationOfTmpSubdir("eventfiles",m_d->tmpLocalFileDir);
286}
287
288//____________________________________________________________________
290{
291 if (maxLocalFilesToKeep<=2)
292 return;
293 if (tmpLocalFileDir.isEmpty())
294 return;
295 QString dir = theclass->tmpLocalFileDir();
296 if (dir.isEmpty())
297 return;
298
299 QList<VP1EventFile> events = theclass->allLocalEvents();
300 int ntoremove = events.count()-maxLocalFilesToKeep;
301 if (ntoremove<=3)//3 instead of 0 to keep down the times we call the machinery below.
302 return;
303
304 //Rules of engagement:
305 //We never delete the current event. We never delete the previous
306 //event. We never delete the maxLocalFilesToKeep newest of the fresh
307 //events.
308
309 QList<Imp::EventID> protectedEvents;
310 if (!historyOrdered.isEmpty()) {
311 protectedEvents << historyOrdered.back();
312 if (historyOrdered.count()>1)
313 protectedEvents << historyOrdered.at(historyOrdered.count()-2);
314 }
315 QList<VP1EventFile> freshEvts = theclass->freshEvents();
316 int ifreshkept(0);
317 for (VP1EventFile evt : theclass->freshEvents()) {
318 protectedEvents << Imp::evtToID(evt);
319 if (++ifreshkept==maxLocalFilesToKeep)
320 break;
321 }
322
323 //Remove:
324 for (int i = events.count()-1; i>=0; --i ) {
325 if (protectedEvents.contains(Imp::evtToID(events.at(i)))) {
326 continue;
327 }
328 QFile::remove(events.at(i).fileName());
329 if (--ntoremove<=0)
330 break;
331 }
332 theclass->invalidateDirCache(theclass->tmpLocalFileDir());
333}
334
335//____________________________________________________________________
336bool VP1AvailEvents::isConsideredFresh ( const VP1EventFile& evt, const VP1EventFile& newestEvt ) const
337{
338 //Notice: Logic here must be similar to logic in VP1EvtsOnServerInfo::events
339
340 if (m_d->timeCutForNew==0) {
341 //Special case where only the newest event is fresh
342 return evt.rawTime()==newestEvt.rawTime() && evt.runNumber()==newestEvt.runNumber();
343 }
344 if (requireNewestRunNumber()&&evt.runNumber()!=newestEvt.runNumber())
345 return false;
346 const unsigned oldest_time = (m_d->timeCutForNew<0||unsigned(m_d->timeCutForNew)>newestEvt.rawTime()) ? 0 : newestEvt.rawTime() - m_d->timeCutForNew;
347 return evt.rawTime() >= oldest_time;
348}
349
350//____________________________________________________________________
351void VP1AvailEvents::messageDebug(const QString& s) const
352{
353 std::cout<<VP1Msg::prefix_verbose()<<": "<<s.toStdString()<<std::endl;
354}
bool operator==(const EventID &o) const
EventID(int r, unsigned long long e)
bool operator<(const EventID &o) const
VP1AvailEvents * theclass
QList< VP1EventFile > lastAllLocal
QList< VP1EventFile > lastFresh
std::map< QString, std::pair< QDateTime, QList< VP1EventFile > > > dircache
static EventID evtToID(const VP1EventFile &evt)
QString attemptGenerationOfTmpSubdir(const QString &preferredname, QString &cachevar)
std::set< EventID > historySorted
QList< EventID > historyOrdered
QList< VP1EventFile > allLocalEvents() const
void setCurrentEvent(int run, int event)
QList< VP1EventFile > freshEvents() const
virtual ~VP1AvailEvents()
void messageDebug(const QString &) const
QString tmpLocalFileDir() const
void message(const QString &) const
VP1AvailEvents(int timeCutForNew, const QString &tmpdir, int maxLocalFilesToKeep=-1, QObject *parent=0)
const QString & tmpDir() const
void allLocalEventsChanged()
bool requireNewestRunNumber() const
int timeCutForNew() const
bool inHistory(int run, int event) const
QList< VP1EventFile > allEventFilesInDir(const QString &dir) const
VP1EventFile newestEvent() const
int maxLocalFilesToKeep() const
void actualCheckForEventListChanges()
void invalidateDirCache(const QString &dir)
bool isConsideredFresh(const VP1EventFile &evt, const VP1EventFile &newestEvt) const
void cleanupAndCheckForEventListChanges()
void freshEventsChanged()
QString tmpActiveRetrievalDir()
int runNumber() const
unsigned rawTime() const
bool isValid() const
static const char * prefix_verbose()
Definition VP1Msg.h:59
int r
Definition globals.cxx:22
Definition run.py:1
void sort(typename DataModel_detail::iterator< DVL > beg, typename DataModel_detail::iterator< DVL > end)
Specialization of sort for DataVector/List.