• R/O
  • HTTP
  • SSH
  • HTTPS

Commit

Tags
Aucun tag

Frequently used words (click to add to your profile)

javac++androidlinuxc#windowsobjective-ccocoa誰得qtpythonphprubygameguibathyscaphec計画中(planning stage)翻訳omegatframeworktwitterdomtestvb.netdirectxゲームエンジンbtronarduinopreviewer

The MinGW.org Installation Manager Tool


Commit MetaInfo

Révision8c77cf991cd3599c28525bf973e3f88bcf99231c (tree)
l'heure2013-08-26 16:35:01
AuteurKeith Marshall <keithmarshall@user...>
CommiterKeith Marshall

Message de Log

Implement retry throttling for failed internet connections.

Change Summary

Modification

--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,19 @@
1+2013-08-26 Keith Marshall <keithmarshall@users.sourceforge.net>
2+
3+ Implement retry throttling for failed internet connections.
4+
5+ * src/pkginet.h (INTERNET_RETRY_ATTEMPTS): New macro; define it.
6+ (INTERNET_RETRY_INTERVAL, INTERNET_DELAY_FACTOR): Likewise.
7+
8+ * src/pkginet.cpp (INTERNET_RETRY_REQUESTER): New typedef.
9+ (pkgInternetAgent::connection_delay, pkgInternetAgent::delay_factor):
10+ (pkgInternetAgent::retries, pkgInternetAgent::retry_interval): New
11+ private member variables; declare them.
12+ (pkgInternetAgent::OpenURL): Use them; they must be initialised by...
13+ (pkgInternetAgent::SetRetryOptions): ...this new method; implement it.
14+ (pkgActionItem::DownloadSingleArchive): Invoke it.
15+ (pkgXmlDocument::SyncRepository): Likewise.
16+
117 2013-08-24 Keith Marshall <keithmarshall@users.sourceforge.net>
218
319 Reassign default URL for download of setup tool components.
--- a/src/pkginet.cpp
+++ b/src/pkginet.cpp
@@ -244,6 +244,23 @@ int pkgDownloadMeter::SizeFormat( char *buf, unsigned long filesize )
244244 return retval;
245245 }
246246
247+/* To facilitate the implementation of the pkgInternetAgent class, which
248+ * is declared below:
249+ */
250+#if IMPLEMENTATION_LEVEL == SETUP_TOOL_COMPONENT
251+
252+/* Within the setup tool, the pkgInternetAgent::SetRetryOptions() method
253+ * requires a pointer to a pkgSetupAction...
254+ */
255+ typedef pkgSetupAction *INTERNET_RETRY_REQUESTER;
256+
257+#else
258+/* ...whereas, in the general case, it requires a pointer to a pkgXmlNode.
259+ */
260+ typedef pkgXmlNode *INTERNET_RETRY_REQUESTER;
261+
262+#endif
263+
247264 class pkgInternetAgent
248265 {
249266 /* A minimal, locally implemented class, instantiated ONCE as a
@@ -252,6 +269,7 @@ class pkgInternetAgent
252269 */
253270 private:
254271 HINTERNET SessionHandle;
272+ int connection_delay, delay_factor, retries, retry_interval;
255273
256274 public:
257275 inline pkgInternetAgent():SessionHandle( NULL )
@@ -272,6 +290,7 @@ class pkgInternetAgent
272290 if( SessionHandle != NULL )
273291 Close( SessionHandle );
274292 }
293+ void SetRetryOptions( INTERNET_RETRY_REQUESTER, const char* );
275294 HINTERNET OpenURL( const char* );
276295
277296 /* Remaining methods are simple inline wrappers for the
@@ -353,6 +372,32 @@ pkgInternetStreamingAgent::~pkgInternetStreamingAgent()
353372 free( (void *)(dest_file) );
354373 }
355374
375+void pkgInternetAgent::SetRetryOptions
376+( INTERNET_RETRY_REQUESTER referrer, const char *url_template )
377+{
378+ /* Initialisation method, invoked immediately prior to the start
379+ * of each archive download request, to establish the options for
380+ * retrying any failed host connection request.
381+ *
382+ * The first of any sequence of connection attempts may always be
383+ * initiated immediately.
384+ */
385+ connection_delay = 0;
386+
387+ /* If any further attempts are necessary, we will delay them
388+ * at progressively increasing intervals, to give us the best
389+ * possible chance to circumvent throttling of excess frequency
390+ * connection requests, by the download server.
391+ *
392+ * FIXME: for each change of host domain, we should establish
393+ * settings by consulting the configuration profile; for the
394+ * time being, we simply assign fixed defaults.
395+ */
396+ delay_factor = INTERNET_DELAY_FACTOR;
397+ retry_interval = INTERNET_RETRY_INTERVAL;
398+ retries = INTERNET_RETRY_ATTEMPTS;
399+}
400+
356401 HINTERNET pkgInternetAgent::OpenURL( const char *URL )
357402 {
358403 /* Open an internet data stream.
@@ -378,8 +423,24 @@ HINTERNET pkgInternetAgent::OpenURL( const char *URL )
378423 /* Aggressively attempt to acquire a resource handle, which we may use
379424 * to access the specified URL; (schedule a maximum of five attempts).
380425 */
381- int retries = 5;
382426 do { pkgDownloadMeter::SpinWait( 1, URL );
427+
428+ /* Distribute retries at geometrically incrementing intervals.
429+ */
430+ if( connection_delay > 0 )
431+ /* This is not the first time we've tried to open this URL;
432+ * compute the appropriate retry interval, and wait between
433+ * successive attempts to establish the connection.
434+ */
435+ Sleep( connection_delay = delay_factor * connection_delay );
436+ else
437+ /* This is the first attempt to open this URL; don't wait,
438+ * but set up the baseline, in milliseconds, for interval
439+ * computation, in the event that further attempts may be
440+ * required.
441+ */
442+ connection_delay = retry_interval;
443+
383444 ResourceHandle = InternetOpenUrl
384445 (
385446 /* Here, we attempt to assign a URL specific resource handle,
@@ -405,14 +466,18 @@ HINTERNET pkgInternetAgent::OpenURL( const char *URL )
405466 * unless we have exhausted the specified retry limit...
406467 */
407468 if( --retries < 1 )
408- /*
409- * ...in which case, we diagnose failure to open the URL.
469+ {
470+ /* ...in which case, we diagnose failure to open the URL.
410471 */
472+ DEBUG_INVOKE_IF( DEBUG_REQUEST( DEBUG_TRACE_INTERNET_REQUESTS ),
473+ dmh_printf( "%s\nConnection failed(status=%u); abandoned.\n",
474+ URL, GetLastError() )
475+ );
411476 dmh_notify( DMH_ERROR, "%s:cannot open URL\n", URL );
412-
477+ }
413478 else DEBUG_INVOKE_IF( DEBUG_REQUEST( DEBUG_TRACE_INTERNET_REQUESTS ),
414- dmh_printf( "%s\nConnecting ... failed(status=%u); retrying...\n",
415- URL, GetLastError() )
479+ dmh_printf( "%s\nConnecting ... failed(status=%u); retrying in %ds...\n",
480+ URL, GetLastError(), delay_factor * connection_delay / 1000 )
416481 );
417482 }
418483 else
@@ -771,11 +836,18 @@ void pkgActionItem::DownloadSingleArchive
771836 if( url_template != NULL )
772837 {
773838 /* ...from the URL constructed from the template specified in
774- * the package repository catalogue (configuration database)...
839+ * the package repository catalogue (configuration database).
775840 */
776841 const char *mirror = get_host_info( Selection(), mirror_key );
777842 char package_url[mkpath( NULL, url_template, package_name, mirror )];
778843 mkpath( package_url, url_template, package_name, mirror );
844+
845+ /* Enable retrying of failed connection attempts, according to the
846+ * preferences, if any, which have been configured for the repository
847+ * associated with the current URL template, or with default settings
848+ * otherwise, then initiate the package download process.
849+ */
850+ pkgDownloadAgent.SetRetryOptions( Selection(), url_template );
779851 if( download.Get( package_url ) > 0 )
780852 /*
781853 * Download was successful; clear the pending and failure flags.
@@ -992,12 +1064,17 @@ void pkgXmlDocument::SyncRepository( const char *name, pkgXmlNode *repository )
9921064 const char *mirror = repository->GetPropVal( mirror_key, NULL );
9931065 char catalogue_url[mkpath( NULL, url_template, name, mirror )];
9941066 mkpath( catalogue_url, url_template, name, mirror );
995-//dmh_printf( "SyncRepository: get %s ...\n", catalogue_url );
1067+
1068+ /* Enable retries according to the preferences, if any, as
1069+ * configured for the repository, or adopt default settings
1070+ * otherwise, then initiate the download process for the
1071+ * catalogue file.
1072+ */
1073+ pkgDownloadAgent.SetRetryOptions( repository, url_template );
9961074 if( download.Get( catalogue_url ) <= 0 )
9971075 dmh_notify( DMH_ERROR,
9981076 "Sync Repository: %s: download failed\n", catalogue_url
9991077 );
1000-//dmh_printf( "SyncRepository: get %s completed\n", catalogue_url );
10011078 }
10021079
10031080 /* We will only replace our current working copy of this catalogue,
--- a/src/pkginet.h
+++ b/src/pkginet.h
@@ -28,6 +28,28 @@
2828 */
2929 #define PKGINET_H 1
3030
31+/* profile.xml may specify the maximum number of retries which will
32+ * be permitted, for each configured repository, when any attempt to
33+ * establish a download connection fails. In the event that this is
34+ * not specified in profile.xml, the following default will apply:
35+ */
36+#define INTERNET_RETRY_ATTEMPTS 5
37+
38+/* In the default case, when profile.xml doesn't stipulate options,
39+ * specify the interval, in milliseconds, to wait between successive
40+ * retries to open any one URL. The first attempt for each individual
41+ * URL is immediate; if it fails, the first retry is scheduled after
42+ *
43+ * INTERNET_RETRY_INTERVAL * INTERNET_DELAY_FACTOR milliseconds
44+ *
45+ * In the event that further retries are necessary, they are scheduled
46+ * at geometrically incrementing intervals, by multiplying the interval
47+ * from the preceding attempt by INTERNET_DELAY_FACTOR, prior to each
48+ * successive connection attempt.
49+ */
50+#define INTERNET_DELAY_FACTOR 2
51+#define INTERNET_RETRY_INTERVAL 1000
52+
3153 class pkgDownloadMeter
3254 {
3355 /* Abstract base class, from which facilities for monitoring the