ATLAS Offline Software
Loading...
Searching...
No Matches
VP1EvtsOnServerInfo.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
3*/
4
5
7// //
8// Implementation of class VP1EvtsOnServerInfo //
9// //
10// Author: Thomas H. Kittelmann (Thomas.Kittelmann@cern.ch) //
11// Initial version: May 2008 //
12// //
14
16#include "VP1Gui/VP1MD5Sum.h"
17#include <QFileInfo>
18#include <QTextStream>
19#include <QtCoreVersion>
20#include <map>
21
22
23//____________________________________________________________________
25public:
26 Imp(const QString& infofile)
27 {
28 error = init(infofile);
29 }
30
31 QString error;
32 QString init(const QString& infofile);
33
34 QList<VP1EventFile> events;//if invalid, we make a list with one dummy
35 //event (to avoid crashes if user forget to
36 //check isValid())
37};
38
39
40//____________________________________________________________________
42 : m_d(new Imp(infofile))
43{
44}
45
46//____________________________________________________________________
51
52//____________________________________________________________________
54{
55 return m_d->error.isEmpty();
56}
57
58//____________________________________________________________________
59const QString& VP1EvtsOnServerInfo::error() const
60{
61 return m_d->error;
62}
63
64//____________________________________________________________________
65QStringList VP1EvtsOnServerInfo::print() const
66{
67 QStringList l;
68 if (!isValid()) {
69 l << "Invalid. Reason: " + error();
70 return l;
71 }
72 l << "Valid with "+QString::number(numberOfEvents())+" files:";
73 for(VP1EventFile evt : events())
74 l << " "+evt.print();
75 l << "Events within 10 minutes of latest:";
76 for(VP1EventFile evt : events(10*60))
77 l << " "+evt.print();
78 l << "Events with same run number as latest:";
79 for(VP1EventFile evt : events(-1,true))
80 l << " "+evt.print();
81 l << "Events with same run number as latest and within 1 minute:";
82 for(VP1EventFile evt : events(1*60,true))
83 l << " "+evt.print();
84
85 return l;
86}
87
88//____________________________________________________________________
89QString VP1EvtsOnServerInfo::Imp::init(const QString& infofile)
90{
91 //Example of file we are trying to parse:
92 //
93 //begin_copyresult
94 //source dir /client/VP1_events
95 //dest dir /www/web_files/html/vp1events
96 //vp1_69629_5487_1211316972.pool.root copy success
97 //end_copyresult
98 //begin_checksums
99 //vp1_69629_5487_1211316972.pool.root 30fa3c9a05251a4d741fce52c304a341
100 //vp1_69629_5270_1211316960.pool.root 7a38564cdd2f2951e76ec37c565dbbf9
101 //vp1_69629_3968_1211316900.pool.root 6c716952a7fdb0371b1541a45d0029f8
102 //end_checksums
103 //
104 //The format of the event file names are: vp1_[run#]_[evt#]_[unixtime].pool.root
105 //
106 //In principle we are only interested in the checksums section, but
107 //it might be a good sanity check to see that the last copied file
108 //(from copyresult) is also the one with the highest time.
109
111 // Basic check that file exists, is readable, etc. //
113
114 if (infofile.isEmpty())
115 return "Given empty path to info file";
116 QFileInfo fi(infofile);
117 if (!fi.exists())
118 return "infofile "+infofile+" does not exist";
119 if (!fi.isReadable())
120 return "infofile "+infofile+" is not readable";
121 if (fi.size()==0)
122 return "infofile "+infofile+" is not empty";
123
125 // Read file into stringlist, ignoring empty lines and excess whitespace //
127
128 int i_begin_copyresult(-1), i_end_copyresult(-1);
129 int i_begin_checksums(-1), i_end_checksums(-1);
130
131
132 QStringList lines;
133 QFile file(infofile);
134 if (!file.open(QFile::ReadOnly))
135 return "Could not open file in readonly mode";
136
137 //Just to avoid any potential performance problems if pointed to a
138 //wrong input file:
139 const qint64 max_linelength(1000);
140 const qint64 max_numberoflines(2000);
141 qint64 ilines(0);
142
143 QTextStream stream(&file);
144 while (!stream.atEnd()) {
145
146 if (ilines++>max_numberoflines)
147 return "Too many lines in file";
148
149 //Read and prune next line:
150 QString rawline = stream.readLine(max_linelength).simplified();
151 if (rawline.isEmpty())
152 continue;
153
154 //Get section boundaries:
155 if (rawline=="begin_copyresult") {
156 if (i_begin_copyresult!=-1)
157 return "Saw two lines with begin_copyresult";
158 i_begin_copyresult = lines.count();
159 } else if (rawline=="end_copyresult") {
160 if (i_end_copyresult!=-1)
161 return "Saw two lines with end_copyresult";
162 i_end_copyresult = lines.count();
163 } else if (rawline=="begin_checksums") {
164 if (i_begin_checksums!=-1)
165 return "Saw two lines with begin_checksums";
166 i_begin_checksums = lines.count();
167 } else if (rawline=="end_checksums") {
168 if (i_end_checksums!=-1)
169 return "Saw two lines with end_checksums";
170 i_end_checksums = lines.count();
171 }
172
173 //Store line:
174 lines << rawline;
175 }
176 if (lines.isEmpty())
177 return "Did not read any lines from file";
178
179 //copy result is only used for a sanity check, so we keep it optional
180 const bool hascopyresult(i_begin_copyresult!=-1||i_end_copyresult!=-1);
181
182 if (i_begin_checksums==-1) return "File did not have begin_checksums line";
183 if (i_end_checksums==-1) return "File did not have end_checksums line";
184 if (i_end_checksums<=i_begin_checksums) return "checksum section delimiters out of order";
185
186 if (hascopyresult) {
187 if (i_begin_copyresult==-1) return "File had end_copyresult but no begin_copyresult line";
188 if (i_end_copyresult==-1) return "File had begin_copyresult but no end_copyresult line";
189 if (i_end_copyresult<=i_begin_copyresult) return "copyresult section delimiters out of order";
190 if (i_begin_copyresult>i_begin_checksums&&i_begin_copyresult<i_end_checksums)
191 return "copyresult and checksum sections mixed";
192 if (i_end_copyresult>i_begin_checksums&&i_end_copyresult<i_end_checksums)
193 return "copyresult and checksum sections mixed";
194 }
195
197 // Let the parsing begin!! //
199
200 for (int i = i_begin_checksums+1;i < i_end_checksums; ++i) {
201#if QTCORE_VERSION >= 0x050E00
202 QStringList parts = lines.at(i).split ( ' ', Qt::SkipEmptyParts );
203#else
204 QStringList parts = lines.at(i).split ( ' ', QString::SkipEmptyParts );
205#endif
206 if (parts.count()!=2)
207 return "Invalid line in checksums section";
208 QString filename(parts.at(0));
209 QString md5sum(VP1MD5Sum::sumToStandardFormat(parts.at(1)));
210 if (!VP1MD5Sum::validMD5Sum(md5sum))
211 return "Invalid md5sum in checksums section: "+md5sum;
212 VP1EventFile evt(filename,md5sum);
213 if (!evt.isValid())
214 return "Failed to decode event file information from filename: "+filename;
215 events << evt;
216 }
217
218 std::sort(events.begin(), events.end());
219
220 if (hascopyresult) {
221 //Todo: Use the copy result lines for a sanity check of that the
222 //newest file is also the one copied last (if copy succesful).
223 }
224
225 return "";
226}
227
228//____________________________________________________________________
229unsigned long long VP1EvtsOnServerInfo::numberOfEvents() const
230{
231 return m_d->events.count();
232}
233
234//____________________________________________________________________
236{
237 return m_d->events.isEmpty() ? VP1EventFile() : m_d->events.at(0);
238}
239
240//____________________________________________________________________
241QList<VP1EventFile> VP1EvtsOnServerInfo::events(int timecut, bool requireNewestRunNumber ) const
242{
243 //Notice: Logic here must be similar to logic in VP1AvailEvents::isConsideredFresh
244
245 if ( m_d->events.isEmpty() )
246 return m_d->events;
247
248 if (timecut==0) {
249 QList<VP1EventFile> l;
250 l << m_d->events.at(0);
251 return l;
252 }
253 const unsigned newestRawTime = m_d->events.at(0).rawTime();
254 const int newestRunNumber = m_d->events.at(0).runNumber();
255
256 const unsigned minTime = (timecut<0&&unsigned(timecut)>newestRawTime) ? 0 : newestRawTime-timecut;
257
258 QList<VP1EventFile> out;
259 for (VP1EventFile evt : m_d->events) {
260 if (minTime>0&&evt.rawTime()<minTime)
261 continue;
262 if (requireNewestRunNumber&&evt.runNumber()!=newestRunNumber)
263 continue;
264 out << evt;
265 }
266 return out;
267}
Imp(const QString &infofile)
QList< VP1EventFile > events
QString init(const QString &infofile)
unsigned long long numberOfEvents() const
VP1EventFile newestEvent() const
const QString & error() const
QStringList print() const
VP1EvtsOnServerInfo(const QString &infofile)
QList< VP1EventFile > events(int timecut=-1, bool requireNewestRunNumber=false) const
static bool validMD5Sum(const QString &)
Definition VP1MD5Sum.cxx:88
static QString sumToStandardFormat(const QString &)
Definition VP1MD5Sum.cxx:96
void sort(typename DataModel_detail::iterator< DVL > beg, typename DataModel_detail::iterator< DVL > end)
Specialization of sort for DataVector/List.
TFile * file