Minor fix creating the address
[pithos-ms-client] / trunk / Pithos.Network / PithosClient.cs
index 2942fce..e323dbc 100644 (file)
@@ -7,8 +7,10 @@
 using System.Collections.Specialized;
 using System.Diagnostics;
 using System.Diagnostics.Contracts;
+using System.IO;
 using System.Net;
 using System.Runtime.Serialization;
+using System.Threading.Tasks;
 
 namespace Pithos.Network
 {
@@ -51,8 +53,7 @@ namespace Pithos.Network
             CopyHeaders(other);
             Timeout = other.Timeout;
             Retries = other.Retries;
-            BaseAddress = other.BaseAddress;
-            
+            BaseAddress = other.BaseAddress;             
 
             foreach (var parameter in other.Parameters)
             {
@@ -84,10 +85,34 @@ namespace Pithos.Network
 
         protected override WebResponse GetWebResponse(WebRequest request)
         {
+            try
+            {
+
             var response = (HttpWebResponse)base.GetWebResponse(request);
             StatusCode = response.StatusCode;
             StatusDescription = response.StatusDescription;
             return response;
+            }
+            catch (WebException exc)
+            {
+                if (exc.Response!=null && exc.Response.ContentLength > 0)
+                {
+                    string content = GetContent(exc.Response);
+                    Trace.TraceError(content);
+                }
+                throw;
+            }
+        }
+
+        private static string GetContent(WebResponse webResponse)
+        {
+            string content;
+            using (var stream = webResponse.GetResponseStream())
+            using (var reader = new StreamReader(stream))
+            {
+                content = reader.ReadToEnd();
+            }
+            return content;
         }
 
         public string DownloadStringWithRetry(string address,int retries=0)
@@ -97,12 +122,15 @@ namespace Pithos.Network
 
             var actualAddress = GetActualAddress(address);
 
+            TraceStart("GET",actualAddress);            
+            
             var actualRetries = (retries == 0) ? Retries : retries;
             
 
-            var func = Retry(() =>
+            
+            var task = Retry(() =>
             {
-                var uriString = String.Join("/", BaseAddress, actualAddress);
+                var uriString = String.Join("/", BaseAddress.TrimEnd('/'), actualAddress);
                 var content = base.DownloadString(uriString);
 
                 if (StatusCode == HttpStatusCode.NoContent)
@@ -111,7 +139,7 @@ namespace Pithos.Network
 
             }, actualRetries);
 
-            var result = func();
+            var result = task.Result;
             return result;
         }
 
@@ -144,10 +172,10 @@ namespace Pithos.Network
             if (address == null)
                 throw new ArgumentNullException("address");
 
-            var actualAddress = GetActualAddress(address);
-
+            var actualAddress = GetActualAddress(address);            
             var actualRetries = (retries == 0) ? Retries : retries;
-            var func = Retry(() =>
+
+            var task = Retry(() =>
             {
                 var uriString = String.Join("/",BaseAddress ,actualAddress);
                 var uri = new Uri(uriString);
@@ -156,6 +184,8 @@ namespace Pithos.Network
                 if (ResponseHeaders!=null)
                     ResponseHeaders.Clear();
 
+                TraceStart(method, uriString);
+
                 var response = (HttpWebResponse)GetWebResponse(request);
                 StatusCode = response.StatusCode;
                 StatusDescription = response.StatusDescription;                
@@ -164,7 +194,12 @@ namespace Pithos.Network
                 return 0;
             }, actualRetries);
 
-            func();
+            task.Wait();
+        }
+
+        private static void TraceStart(string method, string actualAddress)
+        {
+            Trace.WriteLine(String.Format("[{0}] {1} {2}", method, DateTime.Now, actualAddress));
         }
 
         private string GetActualAddress(string address)
@@ -191,7 +226,7 @@ namespace Pithos.Network
                 throw new ArgumentNullException("address");
 
             var actualRetries = (retries == 0) ? Retries : retries;            
-            var func = Retry(() =>
+            var task = Retry(() =>
             {
                 var content = base.DownloadString(address);
 
@@ -201,7 +236,7 @@ namespace Pithos.Network
 
             }, actualRetries);
 
-            var result = func();
+            var result = task.Result;
             return result;
         }
 
@@ -243,7 +278,7 @@ namespace Pithos.Network
                 throw new WebException(String.Format("{0} with code {1} - {2}", message, StatusCode, StatusDescription));
         }
 
-        private Func<T> Retry<T>(Func< T> original, int retryCount)
+        /*private Func<T> Retry<T>(Func< T> original, int retryCount)
         {
             return () =>
             {
@@ -305,6 +340,49 @@ namespace Pithos.Network
                     }
                 }
             };
+        }*/
+        
+        private Task<T> Retry<T>(Func< T> original, int retryCount)
+        {
+            return Task.Factory.StartNew(() => original()).ContinueWith(_original =>
+                {
+                    if(_original.IsFaulted )
+                    {
+                        var e = _original.Exception.InnerException;
+                        if (e is WebException)
+                        {
+                            var we = (e as WebException);
+
+                            var statusCode = HttpStatusCode.RequestTimeout;
+                            if (we.Response != null)
+                            {                                
+                                statusCode = ((HttpWebResponse) we.Response).StatusCode;
+                                this.StatusCode = statusCode;
+                            }
+
+                            if (we.Status==WebExceptionStatus.Timeout || 
+                                (we.Status==WebExceptionStatus.ProtocolError && statusCode==HttpStatusCode.ServiceUnavailable))
+                            {
+                                TimedOut = true;
+                                if (retryCount == 0)
+                                {
+                                    Trace.TraceError("[ERROR] Timed out too many times. {0}\n", e);
+                                    throw new RetryException("Timed out too many times.", e);
+                                }
+                                Trace.TraceError(
+                                    "[RETRY] Timed out after {0} ms. Will retry {1} more times\n{2}", Timeout,
+                                    retryCount, e);
+                                return Retry(original, retryCount - 1);
+                            }
+
+                            if (statusCode==HttpStatusCode.NotFound)
+                                return Task<T>.Factory.StartNew(() => default(T));                            
+                        }
+                        throw e;
+                    }
+                    else                    
+                        return Task<T>.Factory.StartNew(() => _original.Result);
+                }).Unwrap();
         }