Revision 5bcf6d70 trunk/Pithos.Network/CloudFilesClient.cs

b/trunk/Pithos.Network/CloudFilesClient.cs
1 1
using System;
2 2
using System.Collections.Generic;
3 3
using System.ComponentModel.Composition;
4
using System.Diagnostics;
4 5
using System.Diagnostics.Contracts;
5 6
using System.IO;
6 7
using System.Linq;
......
11 12
using Hammock.Caching;
12 13
using Hammock.Retries;
13 14
using Hammock.Serialization;
15
using Hammock.Tasks;
14 16
using Hammock.Web;
15 17
using Newtonsoft.Json;
16 18
using Pithos.Interfaces;
......
24 26
        private string _pithosAuthUrl = "http://pithos.dev.grnet.gr";
25 27

  
26 28
        private RestClient _client;
27
        private readonly TimeSpan _timeout = TimeSpan.FromSeconds(10);
29
        private readonly TimeSpan _shortTimeout = TimeSpan.FromSeconds(10);
28 30
        private readonly int _retries = 5;
29 31
        public string ApiKey { get; set; }
30 32
        public string UserName { get; set; }
31 33
        public Uri StorageUrl { get; set; }
32 34
        public string Token { get; set; }
35
        public Uri Proxy { get; set; }
33 36
        
34 37
        public string AuthUrl
35 38
        {
......
56 59

  
57 60
            string authUrl = UsePithos ? String.Format("{0}/{1}/{2}", AuthUrl, VersionPath,UserName) 
58 61
                                    : String.Format("{0}/{1}", AuthUrl, VersionPath);
59
            var authClient = new RestClient{Path=authUrl};            
62
            
63
            var proxy = Proxy != null ? Proxy.ToString():null;
64
            
65
            var authClient = new RestClient{Path=authUrl,Proxy=proxy};            
66
            
60 67
            authClient.AddHeader("X-Auth-User", UserName);
61 68
            authClient.AddHeader("X-Auth-Key", ApiKey);            
62 69
            
......
87 94
            var retryPolicy = new RetryPolicy { RetryCount = _retries };
88 95
            retryPolicy.RetryConditions.Add(new TimeoutRetryCondition());
89 96

  
90
            _client = new RestClient { Authority = StorageUrl.AbsoluteUri, RetryPolicy = retryPolicy, Timeout = _timeout,Path=UserName };
97
            _client = new RestClient { Authority = StorageUrl.AbsoluteUri, Path = UserName, Proxy = proxy, RetryPolicy = retryPolicy, };
91 98
            
92 99
            _client.AddHeader("X-Auth-Token", Token);
93 100
            if (UsePithos)
......
105 112
            //appends a / unless a Path is specified.
106 113
            
107 114
            //Create a request with a complete path
108
            var request = new RestRequest{Path=StorageUrl.ToString()};
115
            var request = new RestRequest { Path = StorageUrl.ToString(), Timeout = _shortTimeout };
109 116
            request.AddParameter("format","json");
110 117
            //Create a client clone
111
            var client = new RestClient();
118
            var client = new RestClient{Proxy=Proxy.ToString()};
112 119
            foreach (var header in _client.GetAllHeaders())
113 120
            {
114 121
                client.AddHeader(header.Name,header.Value);
......
116 123

  
117 124
            var response = client.Request(request);
118 125

  
119
            ThrowIfNotStatusOK(response, "List Containers failed");
120

  
121 126
            if (response.StatusCode == HttpStatusCode.NoContent)
122 127
                return new List<ContainerInfo>();
123 128

  
129
            ThrowIfNotStatusOK(response, "List Containers failed");
130

  
131

  
124 132
            var infos=JsonConvert.DeserializeObject<IList<ContainerInfo>>(response.Content);
125 133
            
126 134
            return infos;
......
131 139
            if (String.IsNullOrWhiteSpace(container))
132 140
                throw new ArgumentNullException("container", "The container property can't be empty");
133 141

  
134
            var request = new RestRequest{Path=container};
142
            var request = new RestRequest { Path = container, Timeout = _shortTimeout };
135 143
            request.AddParameter("format", "json");
136 144
            var response = _client.Request(request);
137
            if (response.TimedOut)
138
                return new List<ObjectInfo>();
139

  
140
            ThrowIfNotStatusOK(response, "List Objects failed");
141

  
142
            if (response.StatusCode == HttpStatusCode.NoContent)
143
                return new List<ObjectInfo>();
144 145
            
145

  
146
            var infos = JsonConvert.DeserializeObject<IList<ObjectInfo>>(response.Content);
146
            var infos = InfosFromContent(response);
147 147

  
148 148
            return infos;
149 149
        }
150 150

  
151 151

  
152

  
152 153
        public IList<ObjectInfo> ListObjects(string container,string folder)
153 154
        {
154 155
            if (String.IsNullOrWhiteSpace(container))
155 156
                throw new ArgumentNullException("container", "The container property can't be empty");
156 157

  
157
            var request = new RestRequest{Path=container};
158
            var request = new RestRequest { Path = container, Timeout = _shortTimeout };
158 159
            request.AddParameter("format", "json");
159 160
            request.AddParameter("path", folder);
160 161
            var response = _client.Request(request);
162
            
163
            var infos = InfosFromContent(response);
164

  
165
            return infos;
166
        }
167

  
168
        private static IList<ObjectInfo> InfosFromContent(RestResponse response)
169
        {
161 170
            if (response.TimedOut)
162 171
                return new List<ObjectInfo>();
163 172

  
164
            ThrowIfNotStatusOK(response, "List Objects failed");
173
            if (response.StatusCode == 0)
174
                return new List<ObjectInfo>();
165 175

  
166 176
            if (response.StatusCode == HttpStatusCode.NoContent)
167 177
                return new List<ObjectInfo>();
168
            
169 178

  
170
            var infos = JsonConvert.DeserializeObject<IList<ObjectInfo>>(response.Content);
171 179

  
180
            var statusCode = (int)response.StatusCode;
181
            if (statusCode < 200 || statusCode >= 300)
182
            {
183
                Trace.TraceWarning("ListObjects failed with code {1} - {2}", response.StatusCode, response.StatusDescription);
184
                return new List<ObjectInfo>();
185
            }
186

  
187
            var infos = JsonConvert.DeserializeObject<IList<ObjectInfo>>(response.Content);
172 188
            return infos;
173 189
        }
174 190

  
......
177 193
            if (String.IsNullOrWhiteSpace(container))
178 194
                throw new ArgumentNullException("container", "The container property can't be empty");
179 195

  
180
            var request = new RestRequest {Path = container, Method = WebMethod.Head};
196
            var request = new RestRequest { Path = container, Method = WebMethod.Head, Timeout = _shortTimeout };
181 197
            var response = _client.Request(request);
182 198

  
183 199
            switch(response.StatusCode)
......
198 214
            if (String.IsNullOrWhiteSpace(objectName))
199 215
                throw new ArgumentNullException("objectName", "The objectName property can't be empty");
200 216

  
201
            
202
            var request = new RestRequest { Path = container + "/" + objectName, Method = WebMethod.Head };
217

  
218
            var request = new RestRequest { Path = container + "/" + objectName, Method = WebMethod.Head, Timeout = _shortTimeout };
203 219
            var response = _client.Request(request);
204 220

  
205 221
            switch (response.StatusCode)
......
223 239
                throw new ArgumentNullException("objectName", "The objectName property can't be empty");
224 240

  
225 241

  
226
            var request = new RestRequest { Path = container + "/" + objectName, Method = WebMethod.Head };
242
            var request = new RestRequest { Path = container + "/" + objectName, Method = WebMethod.Head, Timeout = _shortTimeout };
227 243
            var response = _client.Request(request);
228 244

  
229 245
            if (response.TimedOut)
......
256 272
                throw new ArgumentNullException("folder", "The folder property can't be empty");
257 273

  
258 274
            var folderUrl=String.Format("{0}/{1}",container,folder);
259
            var request = new RestRequest { Path = folderUrl, Method = WebMethod.Put };
275
            var request = new RestRequest { Path = folderUrl, Method = WebMethod.Put, Timeout = _shortTimeout };
260 276
            request.AddHeader("Content-Type", @"application/directory");
261 277
            request.AddHeader("Content-Length", "0");
262 278

  
......
272 288
            if (String.IsNullOrWhiteSpace(container))
273 289
                throw new ArgumentNullException("container", "The container property can't be empty");
274 290

  
275
            var request = new RestRequest {Path = container, Method = WebMethod.Head};
291
            var request = new RestRequest { Path = container, Method = WebMethod.Head, Timeout = _shortTimeout };
276 292
            var response = _client.Request(request);
277 293

  
278 294
            switch(response.StatusCode)
......
298 314
            if (String.IsNullOrWhiteSpace(container))
299 315
                throw new ArgumentNullException("container", "The container property can't be empty");
300 316

  
301
            var request = new RestRequest { Path = container, Method = WebMethod.Put };
317
            var request = new RestRequest { Path = container, Method = WebMethod.Put, Timeout = _shortTimeout };
302 318
            
303 319
            var response = _client.Request(request);
304 320
                        
......
311 327
            if (String.IsNullOrWhiteSpace(container))
312 328
                throw new ArgumentNullException("container", "The container property can't be empty");
313 329

  
314
            var request = new RestRequest { Path = container , Method = WebMethod.Delete };
330
            var request = new RestRequest { Path = container, Method = WebMethod.Delete, Timeout = _shortTimeout };
315 331
            var response = _client.Request(request);
316 332

  
317 333
            if (response.StatusCode == HttpStatusCode.NotFound || response.StatusCode == HttpStatusCode.NoContent)
......
321 337

  
322 338
        }
323 339

  
324

  
340
        /// <summary>
341
        /// 
342
        /// </summary>
343
        /// <param name="container"></param>
344
        /// <param name="objectName"></param>
345
        /// <returns></returns>
346
        /// <remarks>>This method should have no timeout or a very long one</remarks>
325 347
        public Stream GetObject(string container, string objectName)
326 348
        {
327 349
            if (String.IsNullOrWhiteSpace(container))
......
342 364
                throw new WebException(String.Format("GetObject failed with unexpected status code {0}", response.StatusCode));
343 365
        }
344 366

  
367
        /// <summary>
368
        /// 
369
        /// </summary>
370
        /// <param name="container"></param>
371
        /// <param name="objectName"></param>
372
        /// <param name="fileName"></param>
373
        /// <remarks>>This method should have no timeout or a very long one</remarks>
345 374
        public void PutObject(string container, string objectName, string fileName)
346 375
        {
347 376
            if (String.IsNullOrWhiteSpace(container))
......
357 386
            string url = container + "/" + objectName;
358 387

  
359 388
            var request = new RestRequest {Path=url,Method=WebMethod.Put};           
360

  
389
            request.TaskOptions=new TaskOptions<int>{RateLimitPercent=0.5};
361 390
            
362 391
            string hash = CalculateHash(fileName);
363 392

  
364 393
            request.AddPostContent(File.ReadAllBytes(fileName));
365 394
            request.AddHeader("Content-Type","application/octet-stream");
366 395
            request.AddHeader("ETag",hash);
367
            var response=_client.Request(request);             
368

  
396
            var response=_client.Request(request);
397
            _client.TaskOptions = new TaskOptions<int> {RateLimitPercent = 0.5};
369 398
            if (response.StatusCode == HttpStatusCode.Created)
370 399
                return;
371 400
            if (response.StatusCode == HttpStatusCode.LengthRequired)
......
395 424
            if (String.IsNullOrWhiteSpace(objectName))
396 425
                throw new ArgumentNullException("objectName", "The objectName property can't be empty");
397 426

  
398
            var request = new RestRequest { Path = container + "/" + objectName, Method = WebMethod.Delete };
427
            var request = new RestRequest { Path = container + "/" + objectName, Method = WebMethod.Delete, Timeout=_shortTimeout };
399 428
            var response = _client.Request(request);
400 429

  
401 430
            if (response.StatusCode == HttpStatusCode.NotFound || response.StatusCode == HttpStatusCode.NoContent)

Also available in: Unified diff