Statistics
| Branch: | Revision:

root / trunk / Pithos.Network / PithosClient.cs @ 82db721b

History | View | Annotate | Download (14.5 kB)

1 4d301e8e Panagiotis Kanavos
// -----------------------------------------------------------------------
2 4d301e8e Panagiotis Kanavos
// <copyright file="PithosClient.cs" company="Microsoft">
3 4d301e8e Panagiotis Kanavos
// TODO: Update copyright text.
4 4d301e8e Panagiotis Kanavos
// </copyright>
5 4d301e8e Panagiotis Kanavos
// -----------------------------------------------------------------------
6 4d301e8e Panagiotis Kanavos
7 4d301e8e Panagiotis Kanavos
using System.Collections.Specialized;
8 4d301e8e Panagiotis Kanavos
using System.Diagnostics;
9 4d301e8e Panagiotis Kanavos
using System.Diagnostics.Contracts;
10 7d915c34 Panagiotis Kanavos
using System.IO;
11 4d301e8e Panagiotis Kanavos
using System.Net;
12 4d301e8e Panagiotis Kanavos
using System.Runtime.Serialization;
13 7d915c34 Panagiotis Kanavos
using System.Threading.Tasks;
14 4d301e8e Panagiotis Kanavos
15 4d301e8e Panagiotis Kanavos
namespace Pithos.Network
16 4d301e8e Panagiotis Kanavos
{
17 4d301e8e Panagiotis Kanavos
    using System;
18 4d301e8e Panagiotis Kanavos
    using System.Collections.Generic;
19 4d301e8e Panagiotis Kanavos
    using System.Linq;
20 4d301e8e Panagiotis Kanavos
    using System.Text;
21 4d301e8e Panagiotis Kanavos
22 4d301e8e Panagiotis Kanavos
    /// <summary>
23 4d301e8e Panagiotis Kanavos
    /// TODO: Update summary.
24 4d301e8e Panagiotis Kanavos
    /// </summary>
25 4d301e8e Panagiotis Kanavos
    public class PithosClient:WebClient
26 4d301e8e Panagiotis Kanavos
    {
27 4d301e8e Panagiotis Kanavos
        public int Timeout { get; set; }
28 4d301e8e Panagiotis Kanavos
29 4d301e8e Panagiotis Kanavos
        public bool TimedOut { get; set; }
30 4d301e8e Panagiotis Kanavos
31 4d301e8e Panagiotis Kanavos
        public HttpStatusCode StatusCode { get; private set; }
32 4d301e8e Panagiotis Kanavos
33 4d301e8e Panagiotis Kanavos
        public string StatusDescription { get; set; }
34 4d301e8e Panagiotis Kanavos
35 4d301e8e Panagiotis Kanavos
36 4d301e8e Panagiotis Kanavos
        public int Retries { get; set; }
37 4d301e8e Panagiotis Kanavos
38 4d301e8e Panagiotis Kanavos
        private readonly Dictionary<string, string> _parameters=new Dictionary<string, string>();
39 4d301e8e Panagiotis Kanavos
        public Dictionary<string, string> Parameters
40 4d301e8e Panagiotis Kanavos
        {
41 4d301e8e Panagiotis Kanavos
            get { return _parameters; }            
42 4d301e8e Panagiotis Kanavos
        }
43 4d301e8e Panagiotis Kanavos
44 4d301e8e Panagiotis Kanavos
        public PithosClient():base()
45 4d301e8e Panagiotis Kanavos
        {
46 4d301e8e Panagiotis Kanavos
            
47 4d301e8e Panagiotis Kanavos
        }
48 4d301e8e Panagiotis Kanavos
49 d15e99b4 Panagiotis Kanavos
       
50 4d301e8e Panagiotis Kanavos
        public PithosClient(PithosClient other)
51 4d301e8e Panagiotis Kanavos
            : base()
52 4d301e8e Panagiotis Kanavos
        {
53 4d301e8e Panagiotis Kanavos
            CopyHeaders(other);
54 4d301e8e Panagiotis Kanavos
            Timeout = other.Timeout;
55 4d301e8e Panagiotis Kanavos
            Retries = other.Retries;
56 82db721b Panagiotis Kanavos
            BaseAddress = other.BaseAddress;             
57 4d301e8e Panagiotis Kanavos
58 4d301e8e Panagiotis Kanavos
            foreach (var parameter in other.Parameters)
59 4d301e8e Panagiotis Kanavos
            {
60 4d301e8e Panagiotis Kanavos
                Parameters.Add(parameter.Key,parameter.Value);
61 4d301e8e Panagiotis Kanavos
            }
62 4d301e8e Panagiotis Kanavos
63 4d301e8e Panagiotis Kanavos
            this.Proxy = other.Proxy;
64 4d301e8e Panagiotis Kanavos
        }
65 4d301e8e Panagiotis Kanavos
66 4d301e8e Panagiotis Kanavos
        protected override WebRequest GetWebRequest(Uri address)
67 4d301e8e Panagiotis Kanavos
        {
68 4d301e8e Panagiotis Kanavos
            TimedOut = false;
69 4d301e8e Panagiotis Kanavos
            HttpWebRequest request = base.GetWebRequest(address) as HttpWebRequest;
70 4d301e8e Panagiotis Kanavos
            request.AutomaticDecompression = DecompressionMethods.Deflate | DecompressionMethods.GZip;
71 4d301e8e Panagiotis Kanavos
            if(Timeout>0)
72 4d301e8e Panagiotis Kanavos
                request.Timeout = Timeout;
73 4d301e8e Panagiotis Kanavos
            return request; 
74 4d301e8e Panagiotis Kanavos
        }
75 4d301e8e Panagiotis Kanavos
76 4d301e8e Panagiotis Kanavos
        protected override WebResponse GetWebResponse(WebRequest request, IAsyncResult result)
77 4d301e8e Panagiotis Kanavos
        {
78 4d301e8e Panagiotis Kanavos
            var response = (HttpWebResponse) base.GetWebResponse(request, result);
79 4d301e8e Panagiotis Kanavos
            StatusCode=response.StatusCode;
80 4d301e8e Panagiotis Kanavos
            StatusDescription=response.StatusDescription;
81 4d301e8e Panagiotis Kanavos
            return response;
82 4d301e8e Panagiotis Kanavos
        }
83 4d301e8e Panagiotis Kanavos
84 4d301e8e Panagiotis Kanavos
85 4d301e8e Panagiotis Kanavos
86 4d301e8e Panagiotis Kanavos
        protected override WebResponse GetWebResponse(WebRequest request)
87 4d301e8e Panagiotis Kanavos
        {
88 7d915c34 Panagiotis Kanavos
            try
89 7d915c34 Panagiotis Kanavos
            {
90 7d915c34 Panagiotis Kanavos
91 4d301e8e Panagiotis Kanavos
            var response = (HttpWebResponse)base.GetWebResponse(request);
92 4d301e8e Panagiotis Kanavos
            StatusCode = response.StatusCode;
93 4d301e8e Panagiotis Kanavos
            StatusDescription = response.StatusDescription;
94 4d301e8e Panagiotis Kanavos
            return response;
95 7d915c34 Panagiotis Kanavos
            }
96 7d915c34 Panagiotis Kanavos
            catch (WebException exc)
97 7d915c34 Panagiotis Kanavos
            {
98 82db721b Panagiotis Kanavos
                if (exc.Response!=null && exc.Response.ContentLength > 0)
99 7d915c34 Panagiotis Kanavos
                {
100 82db721b Panagiotis Kanavos
                    string content = GetContent(exc.Response);
101 7d915c34 Panagiotis Kanavos
                    Trace.TraceError(content);
102 7d915c34 Panagiotis Kanavos
                }
103 7d915c34 Panagiotis Kanavos
                throw;
104 7d915c34 Panagiotis Kanavos
            }
105 7d915c34 Panagiotis Kanavos
        }
106 7d915c34 Panagiotis Kanavos
107 7d915c34 Panagiotis Kanavos
        private static string GetContent(WebResponse webResponse)
108 7d915c34 Panagiotis Kanavos
        {
109 7d915c34 Panagiotis Kanavos
            string content;
110 7d915c34 Panagiotis Kanavos
            using (var stream = webResponse.GetResponseStream())
111 7d915c34 Panagiotis Kanavos
            using (var reader = new StreamReader(stream))
112 7d915c34 Panagiotis Kanavos
            {
113 7d915c34 Panagiotis Kanavos
                content = reader.ReadToEnd();
114 7d915c34 Panagiotis Kanavos
            }
115 7d915c34 Panagiotis Kanavos
            return content;
116 4d301e8e Panagiotis Kanavos
        }
117 4d301e8e Panagiotis Kanavos
118 4d301e8e Panagiotis Kanavos
        public string DownloadStringWithRetry(string address,int retries=0)
119 4d301e8e Panagiotis Kanavos
        {
120 4d301e8e Panagiotis Kanavos
            if (address == null)
121 4d301e8e Panagiotis Kanavos
                throw new ArgumentNullException("address");
122 4d301e8e Panagiotis Kanavos
123 4d301e8e Panagiotis Kanavos
            var actualAddress = GetActualAddress(address);
124 4d301e8e Panagiotis Kanavos
125 82db721b Panagiotis Kanavos
            TraceStart("GET",actualAddress);            
126 82db721b Panagiotis Kanavos
            
127 4d301e8e Panagiotis Kanavos
            var actualRetries = (retries == 0) ? Retries : retries;
128 d15e99b4 Panagiotis Kanavos
            
129 d15e99b4 Panagiotis Kanavos
130 7d915c34 Panagiotis Kanavos
            
131 7d915c34 Panagiotis Kanavos
            var task = Retry(() =>
132 4d301e8e Panagiotis Kanavos
            {
133 4d301e8e Panagiotis Kanavos
                var uriString = String.Join("/", BaseAddress, actualAddress);
134 4d301e8e Panagiotis Kanavos
                var content = base.DownloadString(uriString);
135 4d301e8e Panagiotis Kanavos
136 4d301e8e Panagiotis Kanavos
                if (StatusCode == HttpStatusCode.NoContent)
137 4d301e8e Panagiotis Kanavos
                    return String.Empty;
138 4d301e8e Panagiotis Kanavos
                return content;
139 4d301e8e Panagiotis Kanavos
140 4d301e8e Panagiotis Kanavos
            }, actualRetries);
141 4d301e8e Panagiotis Kanavos
142 7d915c34 Panagiotis Kanavos
            var result = task.Result;
143 4d301e8e Panagiotis Kanavos
            return result;
144 4d301e8e Panagiotis Kanavos
        }
145 4d301e8e Panagiotis Kanavos
146 4d301e8e Panagiotis Kanavos
        public void Head(string address,int retries=0)
147 4d301e8e Panagiotis Kanavos
        {
148 4d301e8e Panagiotis Kanavos
            RetryWithoutContent(address, retries, "HEAD");
149 4d301e8e Panagiotis Kanavos
        }
150 4d301e8e Panagiotis Kanavos
151 4d301e8e Panagiotis Kanavos
        public void PutWithRetry(string address, int retries = 0)
152 4d301e8e Panagiotis Kanavos
        {
153 4d301e8e Panagiotis Kanavos
            RetryWithoutContent(address, retries, "PUT");
154 4d301e8e Panagiotis Kanavos
        }
155 4d301e8e Panagiotis Kanavos
156 4d301e8e Panagiotis Kanavos
        public void DeleteWithRetry(string address,int retries=0)
157 4d301e8e Panagiotis Kanavos
        {
158 4d301e8e Panagiotis Kanavos
            RetryWithoutContent(address, retries, "DELETE");
159 4d301e8e Panagiotis Kanavos
        }
160 4d301e8e Panagiotis Kanavos
161 4d301e8e Panagiotis Kanavos
        public string GetHeaderValue(string headerName)
162 4d301e8e Panagiotis Kanavos
        {
163 4d301e8e Panagiotis Kanavos
            var values=this.ResponseHeaders.GetValues(headerName);
164 4d301e8e Panagiotis Kanavos
            if (values == null)
165 4d301e8e Panagiotis Kanavos
                throw new WebException(String.Format("The {0}  header is missing", headerName));
166 4d301e8e Panagiotis Kanavos
            else
167 4d301e8e Panagiotis Kanavos
                return values[0];
168 4d301e8e Panagiotis Kanavos
        }
169 4d301e8e Panagiotis Kanavos
170 4d301e8e Panagiotis Kanavos
        private void RetryWithoutContent(string address, int retries, string method)
171 4d301e8e Panagiotis Kanavos
        {
172 4d301e8e Panagiotis Kanavos
            if (address == null)
173 4d301e8e Panagiotis Kanavos
                throw new ArgumentNullException("address");
174 4d301e8e Panagiotis Kanavos
175 82db721b Panagiotis Kanavos
            var actualAddress = GetActualAddress(address);            
176 4d301e8e Panagiotis Kanavos
            var actualRetries = (retries == 0) ? Retries : retries;
177 82db721b Panagiotis Kanavos
178 7d915c34 Panagiotis Kanavos
            var task = Retry(() =>
179 4d301e8e Panagiotis Kanavos
            {
180 4d301e8e Panagiotis Kanavos
                var uriString = String.Join("/",BaseAddress ,actualAddress);
181 4d301e8e Panagiotis Kanavos
                var uri = new Uri(uriString);
182 4d301e8e Panagiotis Kanavos
                var request =  GetWebRequest(uri);
183 4d301e8e Panagiotis Kanavos
                request.Method = method;
184 4d301e8e Panagiotis Kanavos
                if (ResponseHeaders!=null)
185 4d301e8e Panagiotis Kanavos
                    ResponseHeaders.Clear();
186 4d301e8e Panagiotis Kanavos
187 82db721b Panagiotis Kanavos
                TraceStart(method, uriString);
188 82db721b Panagiotis Kanavos
189 4d301e8e Panagiotis Kanavos
                var response = (HttpWebResponse)GetWebResponse(request);
190 4d301e8e Panagiotis Kanavos
                StatusCode = response.StatusCode;
191 4d301e8e Panagiotis Kanavos
                StatusDescription = response.StatusDescription;                
192 4d301e8e Panagiotis Kanavos
                
193 4d301e8e Panagiotis Kanavos
194 4d301e8e Panagiotis Kanavos
                return 0;
195 4d301e8e Panagiotis Kanavos
            }, actualRetries);
196 4d301e8e Panagiotis Kanavos
197 7d915c34 Panagiotis Kanavos
            task.Wait();
198 4d301e8e Panagiotis Kanavos
        }
199 4d301e8e Panagiotis Kanavos
200 82db721b Panagiotis Kanavos
        private static void TraceStart(string method, string actualAddress)
201 82db721b Panagiotis Kanavos
        {
202 82db721b Panagiotis Kanavos
            Trace.WriteLine(String.Format("[{0}] {1} {2}", method, DateTime.Now, actualAddress));
203 82db721b Panagiotis Kanavos
        }
204 82db721b Panagiotis Kanavos
205 4d301e8e Panagiotis Kanavos
        private string GetActualAddress(string address)
206 4d301e8e Panagiotis Kanavos
        {
207 4d301e8e Panagiotis Kanavos
            if (Parameters.Count == 0)
208 4d301e8e Panagiotis Kanavos
                return address;
209 4d301e8e Panagiotis Kanavos
            var addressBuilder=new StringBuilder(address);            
210 4d301e8e Panagiotis Kanavos
211 4d301e8e Panagiotis Kanavos
            bool isFirst = true;
212 4d301e8e Panagiotis Kanavos
            foreach (var parameter in Parameters)
213 4d301e8e Panagiotis Kanavos
            {
214 4d301e8e Panagiotis Kanavos
                if(isFirst)
215 4d301e8e Panagiotis Kanavos
                    addressBuilder.AppendFormat("?{0}={1}", parameter.Key, parameter.Value);
216 4d301e8e Panagiotis Kanavos
                else
217 4d301e8e Panagiotis Kanavos
                    addressBuilder.AppendFormat("&{0}={1}", parameter.Key, parameter.Value);
218 4d301e8e Panagiotis Kanavos
                isFirst = false;
219 4d301e8e Panagiotis Kanavos
            }
220 4d301e8e Panagiotis Kanavos
            return addressBuilder.ToString();
221 4d301e8e Panagiotis Kanavos
        }
222 4d301e8e Panagiotis Kanavos
223 4d301e8e Panagiotis Kanavos
        public string DownloadStringWithRetry(Uri address,int retries=0)
224 4d301e8e Panagiotis Kanavos
        {
225 4d301e8e Panagiotis Kanavos
            if (address == null)
226 4d301e8e Panagiotis Kanavos
                throw new ArgumentNullException("address");
227 4d301e8e Panagiotis Kanavos
228 4d301e8e Panagiotis Kanavos
            var actualRetries = (retries == 0) ? Retries : retries;            
229 7d915c34 Panagiotis Kanavos
            var task = Retry(() =>
230 4d301e8e Panagiotis Kanavos
            {
231 4d301e8e Panagiotis Kanavos
                var content = base.DownloadString(address);
232 4d301e8e Panagiotis Kanavos
233 4d301e8e Panagiotis Kanavos
                if (StatusCode == HttpStatusCode.NoContent)
234 4d301e8e Panagiotis Kanavos
                    return String.Empty;
235 4d301e8e Panagiotis Kanavos
                return content;
236 4d301e8e Panagiotis Kanavos
237 4d301e8e Panagiotis Kanavos
            }, actualRetries);
238 4d301e8e Panagiotis Kanavos
239 7d915c34 Panagiotis Kanavos
            var result = task.Result;
240 4d301e8e Panagiotis Kanavos
            return result;
241 4d301e8e Panagiotis Kanavos
        }
242 4d301e8e Panagiotis Kanavos
243 d15e99b4 Panagiotis Kanavos
      
244 4d301e8e Panagiotis Kanavos
        /// <summary>
245 d15e99b4 Panagiotis Kanavos
        /// Copies headers from another PithosClient
246 4d301e8e Panagiotis Kanavos
        /// </summary>
247 4d301e8e Panagiotis Kanavos
        /// <param name="source">The PithosClient from which the headers are copied</param>
248 4d301e8e Panagiotis Kanavos
        public void CopyHeaders(PithosClient source)
249 4d301e8e Panagiotis Kanavos
        {
250 4d301e8e Panagiotis Kanavos
            Contract.Requires(source != null, "source can't be null");
251 4d301e8e Panagiotis Kanavos
            if (source == null)
252 4d301e8e Panagiotis Kanavos
                throw new ArgumentNullException("source", "source can't be null");
253 4d301e8e Panagiotis Kanavos
            CopyHeaders(source.Headers,Headers);
254 4d301e8e Panagiotis Kanavos
        }
255 4d301e8e Panagiotis Kanavos
        
256 4d301e8e Panagiotis Kanavos
        /// <summary>
257 d15e99b4 Panagiotis Kanavos
        /// Copies headers from one header collection to another
258 4d301e8e Panagiotis Kanavos
        /// </summary>
259 d15e99b4 Panagiotis Kanavos
        /// <param name="source">The source collection from which the headers are copied</param>
260 d15e99b4 Panagiotis Kanavos
        /// <param name="target">The target collection to which the headers are copied</param>
261 4d301e8e Panagiotis Kanavos
        public static void CopyHeaders(WebHeaderCollection source,WebHeaderCollection target)
262 4d301e8e Panagiotis Kanavos
        {
263 4d301e8e Panagiotis Kanavos
            Contract.Requires(source != null, "source can't be null");
264 4d301e8e Panagiotis Kanavos
            Contract.Requires(target != null, "target can't be null");
265 4d301e8e Panagiotis Kanavos
            if (source == null)
266 4d301e8e Panagiotis Kanavos
                throw new ArgumentNullException("source", "source can't be null");
267 4d301e8e Panagiotis Kanavos
            if (target == null)
268 4d301e8e Panagiotis Kanavos
                throw new ArgumentNullException("target", "target can't be null");
269 4d301e8e Panagiotis Kanavos
            for (int i = 0; i < source.Count; i++)
270 4d301e8e Panagiotis Kanavos
            {
271 4d301e8e Panagiotis Kanavos
                target.Add(source.GetKey(i), source[i]);
272 4d301e8e Panagiotis Kanavos
            }            
273 4d301e8e Panagiotis Kanavos
        }
274 4d301e8e Panagiotis Kanavos
275 4d301e8e Panagiotis Kanavos
        public void AssertStatusOK(string message)
276 4d301e8e Panagiotis Kanavos
        {
277 4d301e8e Panagiotis Kanavos
            if (StatusCode >= HttpStatusCode.BadRequest)
278 4d301e8e Panagiotis Kanavos
                throw new WebException(String.Format("{0} with code {1} - {2}", message, StatusCode, StatusDescription));
279 4d301e8e Panagiotis Kanavos
        }
280 4d301e8e Panagiotis Kanavos
281 7d915c34 Panagiotis Kanavos
        /*private Func<T> Retry<T>(Func< T> original, int retryCount)
282 4d301e8e Panagiotis Kanavos
        {
283 4d301e8e Panagiotis Kanavos
            return () =>
284 4d301e8e Panagiotis Kanavos
            {
285 4d301e8e Panagiotis Kanavos
                while (true)
286 4d301e8e Panagiotis Kanavos
                {
287 4d301e8e Panagiotis Kanavos
                    try
288 4d301e8e Panagiotis Kanavos
                    {
289 4d301e8e Panagiotis Kanavos
                        return original();
290 4d301e8e Panagiotis Kanavos
                    }
291 4d301e8e Panagiotis Kanavos
                    catch (WebException e)
292 4d301e8e Panagiotis Kanavos
                    {
293 4d301e8e Panagiotis Kanavos
                        var statusCode = ((HttpWebResponse)e.Response).StatusCode;
294 4d301e8e Panagiotis Kanavos
                        this.StatusCode = statusCode;
295 4d301e8e Panagiotis Kanavos
296 4d301e8e Panagiotis Kanavos
                        switch (e.Status)
297 4d301e8e Panagiotis Kanavos
                        {
298 4d301e8e Panagiotis Kanavos
                            case WebExceptionStatus.Timeout:
299 4d301e8e Panagiotis Kanavos
300 4d301e8e Panagiotis Kanavos
                                TimedOut = true;
301 4d301e8e Panagiotis Kanavos
                                if (retryCount == 0)
302 4d301e8e Panagiotis Kanavos
                                {
303 4d301e8e Panagiotis Kanavos
                                    Trace.TraceError("[ERROR] Timed out too many times. {0}\n", e);
304 4d301e8e Panagiotis Kanavos
                                    throw new RetryException("Timed out too many times.", e);
305 4d301e8e Panagiotis Kanavos
                                }
306 4d301e8e Panagiotis Kanavos
                                retryCount--;
307 4d301e8e Panagiotis Kanavos
                                Trace.TraceError(
308 4d301e8e Panagiotis Kanavos
                                    "[RETRY] Timed out after {0} ms. Will retry {1} more times\n{2}", Timeout,
309 4d301e8e Panagiotis Kanavos
                                    retryCount, e);
310 4d301e8e Panagiotis Kanavos
311 4d301e8e Panagiotis Kanavos
                                break;
312 4d301e8e Panagiotis Kanavos
                            case WebExceptionStatus.ProtocolError:
313 4d301e8e Panagiotis Kanavos
                                switch (statusCode)
314 4d301e8e Panagiotis Kanavos
                                {
315 4d301e8e Panagiotis Kanavos
                                    case HttpStatusCode.NotFound:
316 4d301e8e Panagiotis Kanavos
                                        {
317 4d301e8e Panagiotis Kanavos
                                            return default(T);
318 4d301e8e Panagiotis Kanavos
                                        }
319 4d301e8e Panagiotis Kanavos
                                    case HttpStatusCode.ServiceUnavailable:
320 4d301e8e Panagiotis Kanavos
                                        {
321 4d301e8e Panagiotis Kanavos
322 4d301e8e Panagiotis Kanavos
                                            TimedOut = false;
323 4d301e8e Panagiotis Kanavos
                                            if (retryCount == 0)
324 4d301e8e Panagiotis Kanavos
                                            {
325 4d301e8e Panagiotis Kanavos
                                                Trace.TraceError("[ERROR] Failed too many times. {0}\n", e);
326 4d301e8e Panagiotis Kanavos
                                                throw new RetryException("Failed too many times.", e);
327 4d301e8e Panagiotis Kanavos
                                            }
328 4d301e8e Panagiotis Kanavos
                                            retryCount--;
329 4d301e8e Panagiotis Kanavos
                                            Trace.TraceError(
330 4d301e8e Panagiotis Kanavos
                                                "[RETRY] Failed due to 503. Will retry {0} more times\n{1}", retryCount, e);
331 4d301e8e Panagiotis Kanavos
                                            break;
332 4d301e8e Panagiotis Kanavos
                                        }
333 4d301e8e Panagiotis Kanavos
                                    default:
334 4d301e8e Panagiotis Kanavos
                                        throw;
335 4d301e8e Panagiotis Kanavos
                                }
336 4d301e8e Panagiotis Kanavos
                                break;
337 4d301e8e Panagiotis Kanavos
                            default:
338 4d301e8e Panagiotis Kanavos
                                throw;
339 4d301e8e Panagiotis Kanavos
                        }
340 4d301e8e Panagiotis Kanavos
                    }
341 4d301e8e Panagiotis Kanavos
                }
342 4d301e8e Panagiotis Kanavos
            };
343 7d915c34 Panagiotis Kanavos
        }*/
344 7d915c34 Panagiotis Kanavos
        
345 7d915c34 Panagiotis Kanavos
        private Task<T> Retry<T>(Func< T> original, int retryCount)
346 7d915c34 Panagiotis Kanavos
        {
347 7d915c34 Panagiotis Kanavos
            return Task.Factory.StartNew(() => original()).ContinueWith(_original =>
348 7d915c34 Panagiotis Kanavos
                {
349 7d915c34 Panagiotis Kanavos
                    if(_original.IsFaulted )
350 7d915c34 Panagiotis Kanavos
                    {
351 7d915c34 Panagiotis Kanavos
                        var e = _original.Exception.InnerException;
352 7d915c34 Panagiotis Kanavos
                        if (e is WebException)
353 7d915c34 Panagiotis Kanavos
                        {
354 7d915c34 Panagiotis Kanavos
                            var we = (e as WebException);
355 82db721b Panagiotis Kanavos
356 82db721b Panagiotis Kanavos
                            var statusCode = HttpStatusCode.RequestTimeout;
357 82db721b Panagiotis Kanavos
                            if (we.Response != null)
358 82db721b Panagiotis Kanavos
                            {                                
359 82db721b Panagiotis Kanavos
                                statusCode = ((HttpWebResponse) we.Response).StatusCode;
360 82db721b Panagiotis Kanavos
                                this.StatusCode = statusCode;
361 82db721b Panagiotis Kanavos
                            }
362 7d915c34 Panagiotis Kanavos
363 7d915c34 Panagiotis Kanavos
                            if (we.Status==WebExceptionStatus.Timeout || 
364 7d915c34 Panagiotis Kanavos
                                (we.Status==WebExceptionStatus.ProtocolError && statusCode==HttpStatusCode.ServiceUnavailable))
365 7d915c34 Panagiotis Kanavos
                            {
366 7d915c34 Panagiotis Kanavos
                                TimedOut = true;
367 7d915c34 Panagiotis Kanavos
                                if (retryCount == 0)
368 7d915c34 Panagiotis Kanavos
                                {
369 7d915c34 Panagiotis Kanavos
                                    Trace.TraceError("[ERROR] Timed out too many times. {0}\n", e);
370 7d915c34 Panagiotis Kanavos
                                    throw new RetryException("Timed out too many times.", e);
371 7d915c34 Panagiotis Kanavos
                                }
372 7d915c34 Panagiotis Kanavos
                                Trace.TraceError(
373 7d915c34 Panagiotis Kanavos
                                    "[RETRY] Timed out after {0} ms. Will retry {1} more times\n{2}", Timeout,
374 7d915c34 Panagiotis Kanavos
                                    retryCount, e);
375 7d915c34 Panagiotis Kanavos
                                return Retry(original, retryCount - 1);
376 7d915c34 Panagiotis Kanavos
                            }
377 7d915c34 Panagiotis Kanavos
378 7d915c34 Panagiotis Kanavos
                            if (statusCode==HttpStatusCode.NotFound)
379 82db721b Panagiotis Kanavos
                                return Task<T>.Factory.StartNew(() => default(T));                            
380 7d915c34 Panagiotis Kanavos
                        }
381 7d915c34 Panagiotis Kanavos
                        throw e;
382 7d915c34 Panagiotis Kanavos
                    }
383 7d915c34 Panagiotis Kanavos
                    else                    
384 7d915c34 Panagiotis Kanavos
                        return Task<T>.Factory.StartNew(() => _original.Result);
385 7d915c34 Panagiotis Kanavos
                }).Unwrap();
386 4d301e8e Panagiotis Kanavos
        }
387 4d301e8e Panagiotis Kanavos
388 4d301e8e Panagiotis Kanavos
       
389 4d301e8e Panagiotis Kanavos
    }
390 4d301e8e Panagiotis Kanavos
391 4d301e8e Panagiotis Kanavos
    public class RetryException:Exception
392 4d301e8e Panagiotis Kanavos
    {
393 4d301e8e Panagiotis Kanavos
        public RetryException()
394 4d301e8e Panagiotis Kanavos
            :base()
395 4d301e8e Panagiotis Kanavos
        {
396 4d301e8e Panagiotis Kanavos
            
397 4d301e8e Panagiotis Kanavos
        }
398 4d301e8e Panagiotis Kanavos
399 4d301e8e Panagiotis Kanavos
        public RetryException(string message)
400 4d301e8e Panagiotis Kanavos
            :base(message)
401 4d301e8e Panagiotis Kanavos
        {
402 4d301e8e Panagiotis Kanavos
            
403 4d301e8e Panagiotis Kanavos
        }
404 4d301e8e Panagiotis Kanavos
405 4d301e8e Panagiotis Kanavos
        public RetryException(string message,Exception innerException)
406 4d301e8e Panagiotis Kanavos
            :base(message,innerException)
407 4d301e8e Panagiotis Kanavos
        {
408 4d301e8e Panagiotis Kanavos
            
409 4d301e8e Panagiotis Kanavos
        }
410 4d301e8e Panagiotis Kanavos
411 4d301e8e Panagiotis Kanavos
        public RetryException(SerializationInfo info,StreamingContext context)
412 4d301e8e Panagiotis Kanavos
            :base(info,context)
413 4d301e8e Panagiotis Kanavos
        {
414 4d301e8e Panagiotis Kanavos
            
415 4d301e8e Panagiotis Kanavos
        }
416 4d301e8e Panagiotis Kanavos
    }
417 4d301e8e Panagiotis Kanavos
}