Added automatic download retrying in the case of network errors
This commit is contained in:
parent
76c30e54c7
commit
8b44585824
4 changed files with 60 additions and 16 deletions
|
@ -16,6 +16,8 @@
|
|||
|
||||
TDownloadFinishedFunction m_finishObserver;
|
||||
TDownloadProgressFunction m_progressObserver;
|
||||
|
||||
NSInteger m_retryCounter;
|
||||
}
|
||||
|
||||
- (void) dealloc;
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
#include "../../platform/download_manager.hpp"
|
||||
|
||||
#define TIMEOUT_IN_SECONDS 15.0
|
||||
#define MAX_AUTOMATIC_RETRIES 3
|
||||
|
||||
@implementation IPhoneDownload
|
||||
|
||||
|
@ -37,6 +38,22 @@
|
|||
[super dealloc];
|
||||
}
|
||||
|
||||
- (NSMutableURLRequest *) CreateRequest
|
||||
{
|
||||
// Create the request.
|
||||
NSMutableURLRequest * request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString: [NSString stringWithUTF8String:m_url.c_str()]]
|
||||
cachePolicy:NSURLRequestReloadIgnoringLocalCacheData timeoutInterval:TIMEOUT_IN_SECONDS];
|
||||
long long fileSize = ftello(m_file);
|
||||
if (fileSize > 0)
|
||||
{
|
||||
NSLog(@"Resuming download for file %s from position %qi", m_requestedFileName.c_str(), fileSize);
|
||||
NSString * val = [[NSString alloc] initWithFormat: @"bytes=%qi-", fileSize];
|
||||
[request addValue:val forHTTPHeaderField:@"Range"];
|
||||
[val release];
|
||||
}
|
||||
return request;
|
||||
}
|
||||
|
||||
- (BOOL) StartDownloadWithUrl: (char const *)originalUrl andFile: (char const *)file
|
||||
andFinishFunc: (TDownloadFinishedFunction &)finishFunc andProgressFunc: (TDownloadProgressFunction &)progressFunc
|
||||
andUseResume: (BOOL)resume
|
||||
|
@ -44,6 +61,8 @@
|
|||
m_finishObserver = finishFunc;
|
||||
m_progressObserver = progressFunc;
|
||||
|
||||
m_retryCounter = 0;
|
||||
|
||||
// try to create file first
|
||||
std::string tmpFile = file;
|
||||
tmpFile += DOWNLOADING_FILE_EXTENSION;
|
||||
|
@ -60,19 +79,9 @@
|
|||
m_requestedFileName = file;
|
||||
m_url = originalUrl;
|
||||
|
||||
// Create the request.
|
||||
NSMutableURLRequest * request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString: [NSString stringWithUTF8String:m_url.c_str()]]
|
||||
cachePolicy:NSURLRequestReloadIgnoringLocalCacheData timeoutInterval:TIMEOUT_IN_SECONDS];
|
||||
long long fileSize = ftello(m_file);
|
||||
if (resume && fileSize > 0)
|
||||
{
|
||||
NSString * val = [[NSString alloc] initWithFormat: @"bytes=%qi-", fileSize];
|
||||
[request addValue:val forHTTPHeaderField:@"Range"];
|
||||
[val release];
|
||||
}
|
||||
// create the connection with the request and start loading the data
|
||||
m_connection = [[NSURLConnection alloc] initWithRequest:request delegate:self];
|
||||
// [request release];
|
||||
m_connection = [[NSURLConnection alloc] initWithRequest:[self CreateRequest] delegate:self];
|
||||
|
||||
if (m_connection == 0)
|
||||
{
|
||||
NSLog(@"Can't create connection for url %s", originalUrl);
|
||||
|
@ -131,7 +140,25 @@
|
|||
- (void) connection: (NSURLConnection *)connection didFailWithError: (NSError *)error
|
||||
{
|
||||
// inform the user
|
||||
NSLog(@"Connection failed! Error - %@ %s", [error localizedDescription], m_url.c_str());
|
||||
NSLog(@"Connection failed for url %s\n%@", m_url.c_str(), [error localizedDescription]);
|
||||
|
||||
// retry connection if it's network-specific error
|
||||
if ([error code] < 0 && ++m_retryCounter <= MAX_AUTOMATIC_RETRIES)
|
||||
{
|
||||
[m_connection release];
|
||||
// create the connection with the request and start loading the data
|
||||
m_connection = [[NSURLConnection alloc] initWithRequest:[self CreateRequest] delegate:self];
|
||||
|
||||
if (m_connection)
|
||||
{
|
||||
NSLog(@"Retrying %d time", m_retryCounter);
|
||||
return; // successfully restarted connection
|
||||
}
|
||||
|
||||
NSLog(@"Can't retry connection");
|
||||
// notify observer about error and exit after this if-block
|
||||
}
|
||||
|
||||
if (m_finishObserver)
|
||||
m_finishObserver(m_url.c_str(), false);
|
||||
// and selfdestruct...
|
||||
|
|
|
@ -4,11 +4,15 @@
|
|||
#include "../base/logging.hpp"
|
||||
#include "../base/assert.hpp"
|
||||
|
||||
// How many times we try to automatically reconnect in the case of network errors
|
||||
#define MAX_AUTOMATIC_RETRIES 2
|
||||
|
||||
QtDownload::QtDownload(QtDownloadManager & manager, char const * url,
|
||||
char const * fileName, TDownloadFinishedFunction & finish,
|
||||
TDownloadProgressFunction & progress, bool useResume)
|
||||
: QObject(&manager), m_currentUrl(url), m_reply(0), m_file(0),
|
||||
m_httpRequestAborted(false), m_finish(finish), m_progress(progress)
|
||||
m_httpRequestAborted(false), m_finish(finish), m_progress(progress),
|
||||
m_retryCounter(0)
|
||||
{
|
||||
// use temporary file for download
|
||||
QString tmpFileName(fileName);
|
||||
|
@ -91,9 +95,18 @@ void QtDownload::OnHttpFinished()
|
|||
m_file->close();
|
||||
|
||||
QVariant redirectionTarget = m_reply->attribute(QNetworkRequest::RedirectionTargetAttribute);
|
||||
if (m_reply->error())
|
||||
QNetworkReply::NetworkError netError = m_reply->error();
|
||||
if (netError)
|
||||
{
|
||||
m_file->remove();
|
||||
if (netError <= QNetworkReply::UnknownNetworkError && ++m_retryCounter <= MAX_AUTOMATIC_RETRIES)
|
||||
{ // try one more time
|
||||
m_reply->deleteLater();
|
||||
StartRequest();
|
||||
return;
|
||||
}
|
||||
// do not delete file if we can resume it's downloading later
|
||||
if (m_file->pos() == 0)
|
||||
m_file->remove();
|
||||
delete m_file;
|
||||
m_file = 0;
|
||||
|
||||
|
@ -128,6 +141,7 @@ void QtDownload::OnHttpFinished()
|
|||
QFile::remove(originalFileName);
|
||||
if (!m_file->rename(originalFileName))
|
||||
{ // sh*t... file is locked and can't be removed
|
||||
m_file->remove();
|
||||
// report error to GUI
|
||||
LOG(LERROR, ("File exists and can't be replaced by downloaded one:", qPrintable(originalFileName)));
|
||||
resultForGui = false;
|
||||
|
|
|
@ -17,6 +17,7 @@ private:
|
|||
bool m_httpRequestAborted;
|
||||
TDownloadFinishedFunction m_finish;
|
||||
TDownloadProgressFunction m_progress;
|
||||
int m_retryCounter;
|
||||
|
||||
QtDownload(QtDownloadManager & manager, char const * url, char const * fileName,
|
||||
TDownloadFinishedFunction & finish, TDownloadProgressFunction & progress,
|
||||
|
|
Reference in a new issue