Revision 7d915c34 trunk/Pithos.Network/PithosClient.cs
b/trunk/Pithos.Network/PithosClient.cs | ||
---|---|---|
7 | 7 |
using System.Collections.Specialized; |
8 | 8 |
using System.Diagnostics; |
9 | 9 |
using System.Diagnostics.Contracts; |
10 |
using System.IO; |
|
10 | 11 |
using System.Net; |
11 | 12 |
using System.Runtime.Serialization; |
13 |
using System.Threading.Tasks; |
|
12 | 14 |
|
13 | 15 |
namespace Pithos.Network |
14 | 16 |
{ |
... | ... | |
84 | 86 |
|
85 | 87 |
protected override WebResponse GetWebResponse(WebRequest request) |
86 | 88 |
{ |
89 |
try |
|
90 |
{ |
|
91 |
|
|
87 | 92 |
var response = (HttpWebResponse)base.GetWebResponse(request); |
88 | 93 |
StatusCode = response.StatusCode; |
89 | 94 |
StatusDescription = response.StatusDescription; |
90 | 95 |
return response; |
96 |
} |
|
97 |
catch (WebException exc) |
|
98 |
{ |
|
99 |
if (exc.Response.ContentLength > 0) |
|
100 |
{ |
|
101 |
string content; |
|
102 |
content = GetContent(exc.Response); |
|
103 |
Trace.TraceError(content); |
|
104 |
} |
|
105 |
throw; |
|
106 |
} |
|
107 |
} |
|
108 |
|
|
109 |
private static string GetContent(WebResponse webResponse) |
|
110 |
{ |
|
111 |
string content; |
|
112 |
using (var stream = webResponse.GetResponseStream()) |
|
113 |
using (var reader = new StreamReader(stream)) |
|
114 |
{ |
|
115 |
content = reader.ReadToEnd(); |
|
116 |
} |
|
117 |
return content; |
|
91 | 118 |
} |
92 | 119 |
|
93 | 120 |
public string DownloadStringWithRetry(string address,int retries=0) |
... | ... | |
100 | 127 |
var actualRetries = (retries == 0) ? Retries : retries; |
101 | 128 |
|
102 | 129 |
|
103 |
var func = Retry(() => |
|
130 |
|
|
131 |
var task = Retry(() => |
|
104 | 132 |
{ |
105 | 133 |
var uriString = String.Join("/", BaseAddress, actualAddress); |
106 | 134 |
var content = base.DownloadString(uriString); |
... | ... | |
111 | 139 |
|
112 | 140 |
}, actualRetries); |
113 | 141 |
|
114 |
var result = func();
|
|
142 |
var result = task.Result;
|
|
115 | 143 |
return result; |
116 | 144 |
} |
117 | 145 |
|
... | ... | |
147 | 175 |
var actualAddress = GetActualAddress(address); |
148 | 176 |
|
149 | 177 |
var actualRetries = (retries == 0) ? Retries : retries; |
150 |
var func = Retry(() =>
|
|
178 |
var task = Retry(() =>
|
|
151 | 179 |
{ |
152 | 180 |
var uriString = String.Join("/",BaseAddress ,actualAddress); |
153 | 181 |
var uri = new Uri(uriString); |
... | ... | |
164 | 192 |
return 0; |
165 | 193 |
}, actualRetries); |
166 | 194 |
|
167 |
func();
|
|
195 |
task.Wait();
|
|
168 | 196 |
} |
169 | 197 |
|
170 | 198 |
private string GetActualAddress(string address) |
... | ... | |
191 | 219 |
throw new ArgumentNullException("address"); |
192 | 220 |
|
193 | 221 |
var actualRetries = (retries == 0) ? Retries : retries; |
194 |
var func = Retry(() =>
|
|
222 |
var task = Retry(() =>
|
|
195 | 223 |
{ |
196 | 224 |
var content = base.DownloadString(address); |
197 | 225 |
|
... | ... | |
201 | 229 |
|
202 | 230 |
}, actualRetries); |
203 | 231 |
|
204 |
var result = func();
|
|
232 |
var result = task.Result;
|
|
205 | 233 |
return result; |
206 | 234 |
} |
207 | 235 |
|
... | ... | |
243 | 271 |
throw new WebException(String.Format("{0} with code {1} - {2}", message, StatusCode, StatusDescription)); |
244 | 272 |
} |
245 | 273 |
|
246 |
private Func<T> Retry<T>(Func< T> original, int retryCount) |
|
274 |
/*private Func<T> Retry<T>(Func< T> original, int retryCount)
|
|
247 | 275 |
{ |
248 | 276 |
return () => |
249 | 277 |
{ |
... | ... | |
305 | 333 |
} |
306 | 334 |
} |
307 | 335 |
}; |
336 |
}*/ |
|
337 |
|
|
338 |
private Task<T> Retry<T>(Func< T> original, int retryCount) |
|
339 |
{ |
|
340 |
return Task.Factory.StartNew(() => original()).ContinueWith(_original => |
|
341 |
{ |
|
342 |
if(_original.IsFaulted ) |
|
343 |
{ |
|
344 |
var e = _original.Exception.InnerException; |
|
345 |
if (e is WebException) |
|
346 |
{ |
|
347 |
var we = (e as WebException); |
|
348 |
var statusCode = ((HttpWebResponse) we.Response).StatusCode; |
|
349 |
this.StatusCode = statusCode; |
|
350 |
|
|
351 |
if (we.Status==WebExceptionStatus.Timeout || |
|
352 |
(we.Status==WebExceptionStatus.ProtocolError && statusCode==HttpStatusCode.ServiceUnavailable)) |
|
353 |
{ |
|
354 |
TimedOut = true; |
|
355 |
if (retryCount == 0) |
|
356 |
{ |
|
357 |
Trace.TraceError("[ERROR] Timed out too many times. {0}\n", e); |
|
358 |
throw new RetryException("Timed out too many times.", e); |
|
359 |
} |
|
360 |
Trace.TraceError( |
|
361 |
"[RETRY] Timed out after {0} ms. Will retry {1} more times\n{2}", Timeout, |
|
362 |
retryCount, e); |
|
363 |
return Retry(original, retryCount - 1); |
|
364 |
} |
|
365 |
|
|
366 |
if (statusCode==HttpStatusCode.NotFound) |
|
367 |
return new Task<T>(() => default(T)); |
|
368 |
} |
|
369 |
throw e; |
|
370 |
} |
|
371 |
else |
|
372 |
return Task<T>.Factory.StartNew(() => _original.Result); |
|
373 |
}).Unwrap(); |
|
308 | 374 |
} |
309 | 375 |
|
310 | 376 |
|
Also available in: Unified diff