Revision b13a68e4

b/trunk/Pithos.Network/CloudFilesClient.cs
66 66
    [Export(typeof(ICloudClient))]
67 67
    public class CloudFilesClient:ICloudClient
68 68
    {
69
        private const string TOKEN_HEADER = "X-Auth-Token";
69 70
        private static readonly ILog Log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
70 71

  
71 72
        //CloudFilesClient uses *_baseClient* internally to communicate with the server
......
73 74
        private RestClient _baseClient;
74 75

  
75 76
        private HttpClient _baseHttpClient;
77
        private HttpClient _baseHttpClientNoTimeout;
76 78
        
77 79

  
78 80
        //During authentication the client provides a UserName 
......
94 96
            set
95 97
            {
96 98
                _token = value;
97
                _baseClient.Headers["X-Auth-Token"] = value;
99
                _baseClient.Headers[TOKEN_HEADER] = value;
98 100
            }
99 101
        }
100 102

  
......
190 192
                BaseAddress = StorageUrl,
191 193
                Timeout = TimeSpan.FromSeconds(30)
192 194
            };
193
            _baseHttpClient.DefaultRequestHeaders.Add("X-Auth-Token", Token);
195
            _baseHttpClient.DefaultRequestHeaders.Add(TOKEN_HEADER, Token);
196

  
197
            _baseHttpClientNoTimeout = new HttpClient(httpClientHandler)
198
            {
199
                BaseAddress = StorageUrl,
200
                Timeout = TimeSpan.FromMilliseconds(-1)
201
            };
202
            _baseHttpClientNoTimeout.DefaultRequestHeaders.Add(TOKEN_HEADER, Token);
194 203

  
195 204

  
196 205
        }
......
252 261
                    if (String.IsNullOrWhiteSpace(storageUrl))
253 262
                        throw new InvalidOperationException("Failed to obtain storage url");
254 263

  
255
                    token = response.Headers.GetValues("X-Auth-Token").First();
264
                    token = response.Headers.GetValues(TOKEN_HEADER).First();
256 265
                    if (String.IsNullOrWhiteSpace(token))
257 266
                        throw new InvalidOperationException("Failed to obtain token url");
258 267

  
......
284 293
                    BaseAddress = StorageUrl,
285 294
                    Timeout = TimeSpan.FromSeconds(30)
286 295
                };
287
                _baseHttpClient.DefaultRequestHeaders.Add("X-Auth-Token", token);
296
                _baseHttpClient.DefaultRequestHeaders.Add(TOKEN_HEADER, token);
297

  
298
                _baseHttpClientNoTimeout = new HttpClient(httpClientHandler)
299
                {
300
                    BaseAddress = StorageUrl,
301
                    Timeout = TimeSpan.FromMilliseconds(-1)
302
                };
303
                _baseHttpClientNoTimeout.DefaultRequestHeaders.Add(TOKEN_HEADER, token);
288 304

  
289 305
                /* var keys = authClient.ResponseHeaders.AllKeys.AsQueryable();
290 306
                groups = (from key in keys
......
1396 1412

  
1397 1413
        }
1398 1414

  
1415
        public async Task<IList<string>> PutHashMap(string account, Uri container, Uri objectName, TreeHash hash)
1416
        {
1417
            if (container == null)
1418
                throw new ArgumentNullException("container", "The container property can't be empty");
1419
            if (container.IsAbsoluteUri)
1420
                throw new ArgumentException("The container must be relative","container");
1421
            if (objectName == null)
1422
                throw new ArgumentNullException("objectName", "The objectName property can't be empty");
1423
            if (objectName.IsAbsoluteUri)
1424
                throw new ArgumentException("The objectName must be relative","objectName");
1425
            if (hash == null)
1426
                throw new ArgumentNullException("hash");
1427
            if (String.IsNullOrWhiteSpace(Token))
1428
                throw new InvalidOperationException("Invalid Token");
1429
            if (StorageUrl == null)
1430
                throw new InvalidOperationException("Invalid Storage Url");
1431
            Contract.EndContractBlock();
1432

  
1433
            
1434

  
1435
            //The container and objectName are relative names. They are joined with the client's
1436
            //BaseAddress to create the object's absolute address
1437

  
1438
            var targetUri = GetTargetUri(account).Combine(container).Combine(objectName);
1439
  
1440

  
1441
            var uri = new Uri(String.Format("{0}?format=json&hashmap",targetUri),UriKind.Absolute);
1442

  
1443
            
1444
            //Send the tree hash as Json to the server            
1445
            var jsonHash = hash.ToJson();
1446
            if (Log.IsDebugEnabled)
1447
                Log.DebugFormat("Hashes:\r\n{0}", jsonHash);
1448

  
1449
            var message = new HttpRequestMessage(HttpMethod.Put, uri)
1450
            {
1451
                Content = new StringContent(jsonHash)
1452
            };
1453
            message.Headers.Add("ETag",hash.TopHash.ToHashString());
1454
            
1455
            //Don't use a timeout because putting the hashmap may be a long process
1456

  
1457
            using(var response=await _baseHttpClientNoTimeout.SendAsyncWithRetries(message,3))
1458
            {
1459
                var empty = (IList<string>)new List<string>();
1460
                
1461
                switch (response.StatusCode)
1462
                {
1463
                    case HttpStatusCode.Created:
1464
                        //The server will respond either with 201-created if all blocks were already on the server
1465
                        return empty;
1466
                    case HttpStatusCode.Conflict:
1467
                        //or with a 409-conflict and return the list of missing parts
1468
                        using (var stream = await response.Content.ReadAsStreamAsync())
1469
                        using(var reader=stream.GetLoggedReader(Log))
1470
                        {                            
1471
                            var serializer = new JsonSerializer();                            
1472
                            serializer.Error += (sender, args) => Log.ErrorFormat("Deserialization error at [{0}] [{1}]", args.ErrorContext.Error, args.ErrorContext.Member);
1473
                            var hashes = (List<string>)serializer.Deserialize(reader, typeof(List<string>));
1474
                            return hashes;
1475
                        }                        
1476
                    default:
1477
                        //All other cases are unexpected
1478
                        //Ensure that failure codes raise exceptions
1479
                        response.EnsureSuccessStatusCode();
1480
                        //And log any other codes as warngings, but continute processing
1481
                        Log.WarnFormat("Unexcpected status code when putting map: {0} - {1}",response.StatusCode,response.ReasonPhrase);
1482
                        return empty;
1483
                }
1484
            }
1485

  
1486
        }
1487

  
1488
/*
1399 1489
        public Task<IList<string>> PutHashMap(string account, Uri container, Uri objectName, TreeHash hash)
1400 1490
        {
1401 1491
            if (container == null)
......
1487 1577

  
1488 1578
        }
1489 1579

  
1580
*/
1490 1581

  
1491 1582
        public async Task<byte[]> GetBlock(string account, Uri container, Uri relativeUrl, long start, long? end, CancellationToken cancellationToken)
1492 1583
        {

Also available in: Unified diff