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