Revision a27aa447 trunk/Pithos.Network/CloudFilesClient.cs
b/trunk/Pithos.Network/CloudFilesClient.cs | ||
---|---|---|
453 | 453 |
|
454 | 454 |
} |
455 | 455 |
|
456 |
public Task<string> PutHashMap(string container, string objectName, TreeHash hash)
|
|
456 |
public Task<IList<string>> PutHashMap(string container, string objectName, TreeHash hash)
|
|
457 | 457 |
{ |
458 | 458 |
if (String.IsNullOrWhiteSpace(container)) |
459 | 459 |
throw new ArgumentNullException("container"); |
... | ... | |
482 | 482 |
|
483 | 483 |
return uploadTask.ContinueWith(t => |
484 | 484 |
{ |
485 |
|
|
485 |
|
|
486 |
var empty = (IList<string>)new List<string>(); |
|
486 | 487 |
|
487 | 488 |
|
488 | 489 |
//The server will respond either with 201-created if all blocks were already on the server |
489 |
if (client.StatusCode == HttpStatusCode.Created) |
|
490 |
if (client.StatusCode == HttpStatusCode.Created) |
|
491 |
{ |
|
490 | 492 |
//in which case we return an empty hash list |
491 |
return t.Result; |
|
493 |
return empty; |
|
494 |
} |
|
492 | 495 |
//or with a 409-conflict and return the list of missing parts |
493 | 496 |
//A 409 will cause an exception so we need to check t.IsFaulted to avoid propagating the exception |
494 | 497 |
if (t.IsFaulted) |
... | ... | |
502 | 505 |
using (var stream = response.GetResponseStream()) |
503 | 506 |
using(var reader=new StreamReader(stream)) |
504 | 507 |
{ |
505 |
var content=reader.ReadToEnd(); |
|
506 |
return content; |
|
508 |
//We need to cleanup the content before returning it because it contains |
|
509 |
//error content after the list of hashes |
|
510 |
var hashes = new List<string>(); |
|
511 |
string line=null; |
|
512 |
//All lines up to the first empty line are hashes |
|
513 |
while(!String.IsNullOrWhiteSpace(line=reader.ReadLine())) |
|
514 |
{ |
|
515 |
hashes.Add(line); |
|
516 |
} |
|
517 |
|
|
518 |
return hashes; |
|
507 | 519 |
} |
508 | 520 |
} |
509 | 521 |
else |
... | ... | |
516 | 528 |
{ |
517 | 529 |
Trace.TraceWarning("Unexcpected status code when putting map: {0} - {1}",client.StatusCode,client.StatusDescription); |
518 | 530 |
} |
519 |
return t.Result;
|
|
531 |
return empty;
|
|
520 | 532 |
}); |
521 | 533 |
|
522 | 534 |
} |
523 | 535 |
|
536 |
public Task<byte[]> GetBlock(string container, Uri relativeUrl, long start, long? end=null) |
|
537 |
{ |
|
538 |
if (String.IsNullOrWhiteSpace(Token)) |
|
539 |
throw new InvalidOperationException("Invalid Token"); |
|
540 |
if (StorageUrl == null) |
|
541 |
throw new InvalidOperationException("Invalid Storage Url"); |
|
542 |
if (String.IsNullOrWhiteSpace(container)) |
|
543 |
throw new ArgumentNullException("container"); |
|
544 |
if (relativeUrl== null) |
|
545 |
throw new ArgumentNullException("relativeUrl"); |
|
546 |
if (end.HasValue && end<0) |
|
547 |
throw new ArgumentOutOfRangeException("end"); |
|
548 |
if (start<0) |
|
549 |
throw new ArgumentOutOfRangeException("start"); |
|
550 |
Contract.EndContractBlock(); |
|
551 |
|
|
552 |
var builder = GetAddressBuilder(container, relativeUrl.ToString()); |
|
553 |
|
|
554 |
var uri = builder.Uri; |
|
555 |
|
|
556 |
//Don't use a timeout because putting the hashmap may be a long process |
|
557 |
var client = new RestClient(_baseClient) {Timeout = 0, RangeFrom = start, RangeTo = end}; |
|
558 |
return client.DownloadDataTask(uri) |
|
559 |
.ContinueWith(t=> |
|
560 |
{ |
|
561 |
client.Dispose(); |
|
562 |
return t.Result; |
|
563 |
}); |
|
564 |
} |
|
565 |
|
|
566 |
|
|
567 |
public Task PostBlock(string container,byte[] block) |
|
568 |
{ |
|
569 |
if (String.IsNullOrWhiteSpace(container)) |
|
570 |
throw new ArgumentNullException("container"); |
|
571 |
if (block == null) |
|
572 |
throw new ArgumentNullException("block"); |
|
573 |
if (String.IsNullOrWhiteSpace(Token)) |
|
574 |
throw new InvalidOperationException("Invalid Token"); |
|
575 |
if (StorageUrl == null) |
|
576 |
throw new InvalidOperationException("Invalid Storage Url"); |
|
577 |
Contract.EndContractBlock(); |
|
578 |
|
|
579 |
var builder = GetAddressBuilder(container, ""); |
|
580 |
//We are doing an update |
|
581 |
builder.Query = "update"; |
|
582 |
var uri = builder.Uri; |
|
583 |
|
|
584 |
//Don't use a timeout because putting the hashmap may be a long process |
|
585 |
var client = new RestClient(_baseClient) { Timeout = 0 }; |
|
586 |
client.Headers[HttpRequestHeader.ContentType] = "application/octet-stream"; |
|
587 |
|
|
588 |
Trace.TraceInformation("[BLOCK POST] START"); |
|
589 |
|
|
590 |
//Not much point to this as the server will timeout if we try to get the |
|
591 |
//hashmap too quickly. |
|
592 |
var tcs = new TaskCompletionSource<bool>(); |
|
593 |
|
|
594 |
client.UploadProgressChanged += (sender, args) => |
|
595 |
{ |
|
596 |
Trace.TraceInformation("[BLOCK POST PROGRESS] {0}% {1} of {2}", |
|
597 |
args.ProgressPercentage, args.BytesSent, |
|
598 |
args.TotalBytesToSend); |
|
599 |
if (args.BytesSent == args.TotalBytesToSend) |
|
600 |
tcs.SetResult(false); |
|
601 |
}; |
|
602 |
|
|
603 |
client.UploadFileCompleted += (sender, args) => |
|
604 |
{ |
|
605 |
if (args.Error != null) |
|
606 |
tcs.SetException(args.Error); |
|
607 |
else |
|
608 |
{ |
|
609 |
Trace.TraceInformation("[BLOCK POST PROGRESS] Completed "); |
|
610 |
tcs.TrySetResult(true); |
|
611 |
} |
|
612 |
}; |
|
613 |
|
|
614 |
|
|
615 |
|
|
616 |
client.UploadDataTask(uri, "POST", block); |
|
617 |
|
|
618 |
//Send the block |
|
619 |
var uploadTask = tcs.Task |
|
620 |
.ContinueWith(upload => |
|
621 |
{ |
|
622 |
client.Dispose(); |
|
623 |
|
|
624 |
if (upload.IsFaulted) |
|
625 |
{ |
|
626 |
var exception = upload.Exception.InnerException; |
|
627 |
Trace.TraceError("[BLOCK POST] FAIL with \r{0}", exception); |
|
628 |
throw exception; |
|
629 |
} |
|
630 |
else |
|
631 |
{ |
|
632 |
Trace.TraceInformation("[BLOCK POST] END"); |
|
633 |
} |
|
634 |
}); |
|
635 |
return uploadTask; |
|
636 |
} |
|
637 |
|
|
524 | 638 |
|
525 | 639 |
public Task<TreeHash> GetHashMap(string container, string objectName) |
526 | 640 |
{ |
... | ... | |
637 | 751 |
client.Dispose(); |
638 | 752 |
|
639 | 753 |
if (upload.IsFaulted) |
640 |
{ |
|
641 |
Trace.TraceError("[PUT] FAIL for {0} with \r{1}",objectName,upload.Exception); |
|
754 |
{ |
|
755 |
var exc = upload.Exception.InnerException; |
|
756 |
Trace.TraceError("[PUT] FAIL for {0} with \r{1}",objectName,exc); |
|
757 |
throw exc; |
|
642 | 758 |
} |
643 | 759 |
else |
644 | 760 |
Trace.TraceInformation("[PUT] END {0}", objectName); |
Also available in: Unified diff