Revision e4067290
b/trunk/Pithos.Core/Agents/PollAgent.cs | ||
---|---|---|
503 | 503 |
//Don't use the tuple info, it may have been deleted |
504 | 504 |
var localInfo = FileInfoExtensions.FromPath(localFilePath); |
505 | 505 |
|
506 |
|
|
506 | 507 |
// Local file unchanged? If both C and L are null, make sure it's because |
507 | 508 |
//both the file is missing and the state checksum is not missing |
508 | 509 |
if (tuple.C == tuple.L && (localInfo.Exists || tuple.FileState==null)) |
... | ... | |
512 | 513 |
if (tuple.S == tuple.L) |
513 | 514 |
{ |
514 | 515 |
// No server changes |
515 |
; |
|
516 |
//Has the file been renamed on the server? |
|
517 |
MoveForServerMove(accountInfo, tuple); |
|
516 | 518 |
} |
517 | 519 |
else |
518 | 520 |
{ |
... | ... | |
534 | 536 |
{ |
535 | 537 |
//Server file exists |
536 | 538 |
//downloadServerObject() // Result: L = S |
537 |
StatusKeeper.SetFileState(localFilePath, FileStatus.Modified, |
|
539 |
//If the file has moved on the server, move it locally before downloading |
|
540 |
var targetPath=MoveForServerMove(accountInfo,tuple); |
|
541 |
|
|
542 |
StatusKeeper.SetFileState(targetPath, FileStatus.Modified, |
|
538 | 543 |
FileOverlayStatus.Modified, ""); |
539 | 544 |
NetworkAgent.Downloader.DownloadCloudFile(accountInfo, |
540 | 545 |
tuple.ObjectInfo, |
541 |
localFilePath, token).Wait(token);
|
|
546 |
targetPath, token).Wait(token);
|
|
542 | 547 |
//updateRecord( L = S ) |
543 |
StatusKeeper.UpdateFileChecksum(localFilePath, tuple.ObjectInfo.ETag,
|
|
548 |
StatusKeeper.UpdateFileChecksum(targetPath, tuple.ObjectInfo.ETag,
|
|
544 | 549 |
tuple.ObjectInfo.X_Object_Hash); |
545 | 550 |
|
546 |
StatusKeeper.SetFileState(localFilePath, FileStatus.Unchanged, |
|
551 |
StatusKeeper.StoreInfo(targetPath, tuple.ObjectInfo); |
|
552 |
|
|
553 |
/* |
|
554 |
StatusKeeper.SetFileState(targetPath, FileStatus.Unchanged, |
|
547 | 555 |
FileOverlayStatus.Normal, ""); |
556 |
*/ |
|
548 | 557 |
} |
549 | 558 |
} |
550 | 559 |
} |
... | ... | |
576 | 585 |
"Poll", isUnselected); |
577 | 586 |
NetworkAgent.Uploader.UploadCloudFile(action, token).Wait(token); |
578 | 587 |
|
579 |
|
|
580 | 588 |
//updateRecord( S = C ) |
581 |
StatusKeeper.SetFileState(localFilePath, FileStatus.Unchanged,
|
|
582 |
FileOverlayStatus.Normal, ""); |
|
589 |
//State updated by the uploader
|
|
590 |
|
|
583 | 591 |
if (isUnselected) |
584 | 592 |
{ |
585 | 593 |
ProcessChildren(accountInfo, tuple, agent, token); |
... | ... | |
595 | 603 |
{ |
596 | 604 |
// (Identical Changes) Result: L = S |
597 | 605 |
//doNothing() |
598 |
StatusKeeper.UpdateFileChecksum(localFilePath, tuple.ObjectInfo.ETag, |
|
599 |
tuple.ObjectInfo.X_Object_Hash); |
|
600 |
StatusKeeper.SetFileState(localFilePath, FileStatus.Unchanged, |
|
601 |
FileOverlayStatus.Normal, ""); |
|
606 |
//Detect server moves |
|
607 |
var targetPath=MoveForServerMove(accountInfo, tuple); |
|
608 |
StatusKeeper.StoreInfo(targetPath,tuple.ObjectInfo); |
|
602 | 609 |
} |
603 | 610 |
else |
604 | 611 |
{ |
... | ... | |
619 | 626 |
} |
620 | 627 |
} |
621 | 628 |
|
629 |
private string MoveForServerMove(AccountInfo accountInfo, StateTuple tuple) |
|
630 |
{ |
|
631 |
var relativePath = tuple.ObjectInfo.RelativeUrlToFilePath(accountInfo.UserName); |
|
632 |
var serverPath = Path.Combine(accountInfo.AccountPath, relativePath); |
|
633 |
|
|
634 |
if (tuple.FilePath == serverPath) return serverPath; |
|
635 |
|
|
636 |
if (tuple.FileInfo.Exists) |
|
637 |
{ |
|
638 |
var fi = tuple.FileInfo as FileInfo; |
|
639 |
if (fi != null) |
|
640 |
fi.MoveTo(serverPath); |
|
641 |
var di = tuple.FileInfo as DirectoryInfo; |
|
642 |
if (di != null) |
|
643 |
di.MoveTo(serverPath); |
|
644 |
StatusKeeper.StoreInfo(serverPath, tuple.ObjectInfo); |
|
645 |
} |
|
646 |
else |
|
647 |
{ |
|
648 |
Debug.Assert(false, "File does not exist"); |
|
649 |
} |
|
650 |
return serverPath; |
|
651 |
} |
|
652 |
|
|
622 | 653 |
private void DeleteCloudFile(AccountInfo accountInfo, StateTuple tuple) |
623 | 654 |
{ |
624 | 655 |
StatusKeeper.SetFileState(tuple.FilePath, FileStatus.Deleted, |
... | ... | |
647 | 678 |
IEnumerable<Tuple<FileSystemInfo, string>> files, |
648 | 679 |
IEnumerable<FileState> states) |
649 | 680 |
{ |
650 |
var dct = new Dictionary<string, StateTuple>();
|
|
681 |
var tuplesByPath = new Dictionary<string, StateTuple>();
|
|
651 | 682 |
foreach (var file in files) |
652 | 683 |
{ |
653 | 684 |
var fsInfo = file.Item1; |
654 | 685 |
var fileHash = fsInfo is DirectoryInfo? MERKLE_EMPTY:file.Item2; |
655 | 686 |
|
656 |
dct[fsInfo.FullName] = new StateTuple {FileInfo = fsInfo, MD5 = fileHash};
|
|
687 |
tuplesByPath[fsInfo.FullName] = new StateTuple {FileInfo = fsInfo, MD5 = fileHash};
|
|
657 | 688 |
} |
658 | 689 |
foreach (var state in states) |
659 | 690 |
{ |
660 | 691 |
StateTuple hashTuple; |
661 |
if (dct.TryGetValue(state.FilePath, out hashTuple))
|
|
692 |
if (tuplesByPath.TryGetValue(state.FilePath, out hashTuple))
|
|
662 | 693 |
{ |
663 | 694 |
hashTuple.FileState = state; |
664 | 695 |
} |
665 | 696 |
else |
666 | 697 |
{ |
667 | 698 |
var fsInfo = FileInfoExtensions.FromPath(state.FilePath); |
668 |
dct[state.FilePath] = new StateTuple {FileInfo = fsInfo, FileState = state};
|
|
699 |
tuplesByPath[state.FilePath] = new StateTuple {FileInfo = fsInfo, FileState = state};
|
|
669 | 700 |
} |
670 | 701 |
} |
702 |
|
|
703 |
var tuplesByID = tuplesByPath.Values |
|
704 |
.Where(tuple => tuple.FileState != null && tuple.FileState.ObjectID!=null) |
|
705 |
.ToDictionary(tuple=>tuple.FileState.ObjectID,tuple=>tuple);//new Dictionary<Guid, StateTuple>(); |
|
706 |
|
|
671 | 707 |
foreach (var info in infos) |
672 | 708 |
{ |
673 | 709 |
StateTuple hashTuple; |
674 | 710 |
var filePath = info.Item1; |
675 | 711 |
var objectInfo = info.Item2; |
676 |
if (dct.TryGetValue(filePath, out hashTuple)) |
|
712 |
var objectID = objectInfo.UUID; |
|
713 |
|
|
714 |
if (tuplesByID.TryGetValue(objectID, out hashTuple)) |
|
715 |
{ |
|
716 |
hashTuple.ObjectInfo = objectInfo; |
|
717 |
} |
|
718 |
else if (tuplesByPath.TryGetValue(filePath, out hashTuple)) |
|
677 | 719 |
{ |
678 | 720 |
hashTuple.ObjectInfo = objectInfo; |
679 | 721 |
} |
680 | 722 |
else |
681 | 723 |
{ |
682 | 724 |
var fsInfo = FileInfoExtensions.FromPath(filePath); |
683 |
dct[filePath] = new StateTuple {FileInfo = fsInfo, ObjectInfo = objectInfo}; |
|
725 |
var tuple = new StateTuple {FileInfo = fsInfo, ObjectInfo = objectInfo}; |
|
726 |
tuplesByPath[filePath] = tuple; |
|
727 |
tuplesByID[objectInfo.UUID] = tuple; |
|
684 | 728 |
} |
685 | 729 |
} |
686 |
return dct.Values;
|
|
730 |
return tuplesByPath.Values;
|
|
687 | 731 |
} |
688 | 732 |
|
689 | 733 |
/// <summary> |
b/trunk/Pithos.Core/Agents/StatusAgent.cs | ||
---|---|---|
661 | 661 |
using (var connection = GetConnection()) |
662 | 662 |
using (var command = new SQLiteCommand(connection)) |
663 | 663 |
{ |
664 |
if (StateExists(path, connection)) |
|
664 |
//If the ID exists, update the status |
|
665 |
if (StateExistsByID(objectInfo.UUID,connection)) |
|
665 | 666 |
command.CommandText = |
666 |
"update FileState set FileStatus= :fileStatus where FilePath = :path COLLATE NOCASE "; |
|
667 |
"update FileState set FilePath=:path,FileStatus= :fileStatus, Checksum=:checksum, ShortHash=:shortHash,Version=:version,VersionTimeStamp=:versionTimeStamp where ObjectID = :objectID "; |
|
668 |
else if (StateExists(path, connection)) |
|
669 |
//If the ID doesn't exist, try to update using the path, and store the ID as well. |
|
670 |
command.CommandText = |
|
671 |
"update FileState set FileStatus= :fileStatus, ObjectID=:objectID, Checksum=:checksum, ShortHash=:shortHash,Version=:version,VersionTimeStamp=:versionTimeStamp where FilePath = :path COLLATE NOCASE "; |
|
667 | 672 |
else |
668 | 673 |
{ |
669 | 674 |
command.CommandText = |
... | ... | |
702 | 707 |
|
703 | 708 |
} |
704 | 709 |
|
710 |
private bool StateExistsByID(string objectId,SQLiteConnection connection) |
|
711 |
{ |
|
712 |
using (var command = new SQLiteCommand("Select count(*) from FileState where ObjectId=:id", connection)) |
|
713 |
{ |
|
714 |
command.Parameters.AddWithValue("id", objectId); |
|
715 |
var result = command.ExecuteScalar(); |
|
716 |
return ((long)result >= 1); |
|
717 |
} |
|
718 |
|
|
719 |
} |
|
720 |
|
|
705 | 721 |
public void SetFileStatus(string path, FileStatus status) |
706 | 722 |
{ |
707 | 723 |
if (String.IsNullOrWhiteSpace(path)) |
b/trunk/Pithos.Core/Agents/Uploader.cs | ||
---|---|---|
183 | 183 |
|
184 | 184 |
await UploadWithHashMap(accountInfo, cloudFile, fileInfo as FileInfo, cloudFile.Name, treeHash,cancellationToken); |
185 | 185 |
} |
186 |
//If everything succeeds, change the file and overlay status to normal |
|
187 |
StatusKeeper.SetFileState(fullFileName, FileStatus.Unchanged, FileOverlayStatus.Normal, ""); |
|
186 |
var currentInfo=client.GetObjectInfo(cloudFile.Account, cloudFile.Container, cloudFile.Name); |
|
187 |
//If there is no stored ObjectID in the file state, add it |
|
188 |
if (action.FileState == null || action.FileState.ObjectID == null) |
|
189 |
{ |
|
190 |
StatusKeeper.StoreInfo(fullFileName,currentInfo); |
|
191 |
} |
|
192 |
else |
|
193 |
//If everything succeeds, change the file and overlay status to normal |
|
194 |
StatusKeeper.SetFileState(fullFileName, FileStatus.Unchanged, FileOverlayStatus.Normal, ""); |
|
188 | 195 |
} |
189 | 196 |
catch (WebException exc) |
190 | 197 |
{ |
b/trunk/Pithos.Core/FileState.cs | ||
---|---|---|
73 | 73 |
|
74 | 74 |
|
75 | 75 |
//[Property(Unique = true, UniqueKey = "IX_FileState_ObjectID")] |
76 |
[Property] |
|
76 | 77 |
public string ObjectID { get; set; } |
77 | 78 |
|
78 | 79 |
[Property(Unique = true, UniqueKey = "IX_FileState_FilePath")] |
b/trunk/Pithos.Network/CloudFilesClient.cs | ||
---|---|---|
789 | 789 |
Container = container, |
790 | 790 |
Name = objectName, |
791 | 791 |
ETag = client.GetHeaderValue("ETag"), |
792 |
UUID=client.GetHeaderValue("X-Object-UUID"), |
|
792 | 793 |
X_Object_Hash = client.GetHeaderValue("X-Object-Hash"), |
793 | 794 |
Content_Type = client.GetHeaderValue("Content-Type"), |
794 | 795 |
Bytes = Convert.ToInt64(client.GetHeaderValue("Content-Length",true)), |
Also available in: Unified diff