ATLAS Offline Software
Loading...
Searching...
No Matches
VP1HttpGetFile_Private.h
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// Internal classes for VP1HttpGetFile //
9// //
10// Author: Thomas H. Kittelmann (Thomas.Kittelmann@cern.ch) //
11// Initial version: June 2008 //
12// //
14
15#include <QThread>
16#include <QMutex>
17#include <QTimer>
18#include <QDateTime>
19#include <QFileInfo>
20#include <QFile>
21#include <QDir>
22#include <QUrl>
23
24//#include <QHttp> // Qt 4
25//#include <QNetworkAccessManager> // TODO: use this to port to Qt5
26
27#include "VP1Gui/VP1MD5Sum.h"
28
29class VP1HttpGetFile_DownloadThread : public QThread {
30
31 Q_OBJECT
32
33public:
34
36 const QString& localtargetfile,
37 const QString& expectedMD5Sum,
38 const QString& data,
39 QObject * parent = 0);
41
42 //For accessing the results:
43 bool errors() const { m_mutex.lock(); bool err=!m_errorString.isEmpty(); m_mutex.unlock(); return err; }
44 QString errorString() const { m_mutex.lock(); QString err = m_errorString; m_mutex.unlock(); return err; }
45
46 const QString& urltofile() const { return m_urltofile; }
47 const QString& localtargetfile() const { return m_localtargetfile; }
48 const QString& expectedMD5Sum() const { return m_expectedMD5Sum; }
49 const QString& data() const { return m_data; }
50
51protected:
52 void run();
53public Q_SLOTS:
55private Q_SLOTS:
56 void done(bool);
58private:
59 const QString m_urltofile;
60 const QString m_localtargetfile;
61 const QString m_expectedMD5Sum;
62 const QString m_data;
64 mutable QMutex m_mutex;//Protects m_errors;
65// QHttp * m_http; // Old Qt4 code --> TODO: need to be ported to Qt5!!
67 DOWNLOADFINISHSTATUS m_downloadFinishedStatus;//-1: not finished, 0: error, 1: no-error
69 qint64 m_lastcheckedsize;//-2 never checked, -1 does not exists.
71 void endInFailure(const QString&, CLEANUPOPT );
72};
73
74//Remember that we are also included from the qt moc file:
75#ifdef VP1HttpGetFile_cxx
76
77//____________________________________________________________________
79 const QString& localtargetfile,
80 const QString& expectedMD5Sum,
81 const QString& data,
82 QObject * parent )
83 : QThread(parent),
84 m_urltofile(urltofile),
85 m_localtargetfile(localtargetfile),
86 m_expectedMD5Sum(expectedMD5Sum),
87 m_data(data),
88 m_errorString("Download not finished"),
89// m_http(0),
90 m_downloadFinishedStatus(NOTFINISHED),
91 m_lastChangeTime(0),
92 m_lastcheckedsize(-2)
93{
94}
95
96//____________________________________________________________________
97void VP1HttpGetFile_DownloadThread::endInFailure(const QString& err, CLEANUPOPT opt)
98{
99 m_mutex.lock();
100
101 if (opt==CLEANUPLOCALFILE&&QFile::exists(m_localtargetfile))
102 QFile::remove(m_localtargetfile);
103
104 m_errorString = err.isEmpty() ? "Unspecified error" : err;
105 m_mutex.unlock();
106}
107
108//____________________________________________________________________
110{
111 // TODO: to be ported to Qt5!!
112// if (!m_http)
113// return;
114// unsigned currentTime = QDateTime::currentDateTime().toTime_t();
115// if (currentTime>m_lastChangeTime+10) {//10s
116// m_downloadFinishedStatus = STALLEDERROR;
117// quit();
118// }
119}
120
121//____________________________________________________________________
123{
125 quit();
126}
127
128//____________________________________________________________________
130{
131 //We monitor that filesize of files downloaded is strictly
132 //increasing (and that a created file does not disappear):
133 QFileInfo fi(m_localtargetfile);
134 qint64 currentsize = fi.exists() ? fi.size() : -1;
135 if (currentsize < m_lastcheckedsize) {
137 quit();
138 }
139
140 //For stall-detection:
141 if (currentsize > m_lastcheckedsize)
142 m_lastChangeTime = QDateTime::currentDateTime().toTime_t();
143
144 m_lastcheckedsize = currentsize;
145}
146
147//____________________________________________________________________
149
150 // NOTE!! TODO: This has to be ported to Qt 5!!!
151 /*
153 // Input validation //
155
156 //Input validation ==> MD5 sum
157
158 if ( !m_expectedMD5Sum.isEmpty() && !VP1MD5Sum::validMD5Sum(m_expectedMD5Sum) ) {
159 endInFailure("Invalid target md5sum: "+m_expectedMD5Sum,CLEANUPLOCALFILE);
160 return;
161 }
162
163 //Input validation ==> URL
164
165 if (m_urltofile.isEmpty()) {
166 endInFailure("Empty URL",DONTTOUCHLOCALFILE);
167 return;
168 }
169
170 QUrl url(m_urltofile.contains("://") ? m_urltofile : "http://" + m_urltofile);
171 if (!url.isValid()||url.host().isEmpty()) {
172 endInFailure("Invalid URL: "+m_urltofile,DONTTOUCHLOCALFILE);
173 return;
174 }
175 //Input validation ==> Target file
176
177 //File can not exist already and we abort if we are already
178 //downloading a file to that location:
179 QFileInfo fi(m_localtargetfile);
180 if (fi.exists()) {
181 //In one case we might still end well: if we know the target
182 //checksum and if the file has it (this also does away with
183 //several problems of "simultaneous downloads started":
184 if (!m_expectedMD5Sum.isEmpty()&&VP1MD5Sum::sumMatches(m_localtargetfile,m_expectedMD5Sum))
185 return;
186 endInFailure ("Download target already exists: "+m_localtargetfile,DONTTOUCHLOCALFILE);
187 return;
188 }
189 if (!fi.dir().exists()) {
190 endInFailure("Directory ("+fi.dir().absolutePath()+") for download target does not exist: "+m_localtargetfile,DONTTOUCHLOCALFILE);
191 return;
192 }
193
194 //Open target file:
195 QFile file(m_localtargetfile);
196 if (!file.open(QIODevice::WriteOnly)) {
197 endInFailure("Could not open file for write access: "+m_localtargetfile,DONTTOUCHLOCALFILE);
198 return;
199 }
200
202 // HTTP request and event loop //
204
205 m_http = new QHttp(0);
206
207 connect(m_http,SIGNAL(done(bool)),this,SLOT(done(bool)));
208 connect(m_http,SIGNAL(dataReadProgress(int,int)),this,SLOT(dataReadProgress()));
209
210 QHttpRequestHeader header("GET", url.path()+(url.hasQuery()?"?"+url.encodedQuery():QString("")));
211 // ^^^ Todo: We could support username/passwd part of url also.
212 header.setValue("Host", url.host());
213 header.setValue("User-Agent", "ATLASVP1");
214 m_http->setHost(url.host());
215 m_lastChangeTime = QDateTime::currentDateTime().toTime_t();
216
217 //Go:
218 m_http->request(header,0,&file);
219 QTimer timer(0);
220 connect(&timer, SIGNAL(timeout()), this, SLOT(checkForStall()));
221 timer.start(1000);//1s
222 exec();
223 timer.stop();
224
225 //Cleanup http:
226 m_http->blockSignals(true);
227 if (m_http->hasPendingRequests())
228 m_http->clearPendingRequests();
229 if (m_http->currentId()!=0)
230 m_http->abort();
231 delete m_http;
232 m_http = 0;
233
234 file.close();
235
236 //Errors?
237 if (m_downloadFinishedStatus!=NOERRORS) {
238 switch(m_downloadFinishedStatus) {
239 case HTTPERROR:
240 endInFailure("Download finished with error "+m_http->errorString(),CLEANUPLOCALFILE);
241 return;
242 case STALLEDERROR:
243 endInFailure("Download stalled",CLEANUPLOCALFILE);
244 return;
245 case SIZEDECREASEDERROR:
246 endInFailure("Aborted since file was either removed or decreased in size.",CLEANUPLOCALFILE);
247 return;
248 default:
249 endInFailure("Unexpected download status (SHOULD NEVER HAPPEN)",CLEANUPLOCALFILE);
250 return;
251 }
252 }
253
255 // Checksum test //
257
258 if (!m_expectedMD5Sum.isEmpty()) {
259 bool match = VP1MD5Sum::sumMatches(m_localtargetfile,m_expectedMD5Sum);
260 if (!match) {
261 endInFailure("Checksum did not match",CLEANUPLOCALFILE);
262 return;
263 }
264 }
265
266 //All ok:
267
268 m_mutex.lock();
269 m_errorString = "";
270 m_mutex.unlock();
271 */
272
273}
274
275#endif
char data[hepevt_bytes_allocation_ATLAS]
Definition HepEvt.cxx:11
DOWNLOADFINISHSTATUS m_downloadFinishedStatus
void endInFailure(const QString &, CLEANUPOPT)
VP1HttpGetFile_DownloadThread(const QString &urltofile, const QString &localtargetfile, const QString &expectedMD5Sum, const QString &data, QObject *parent=0)
const QString & localtargetfile() const
const QString & expectedMD5Sum() const