Revision 159098f7

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);
......
619 627
            }
620 628
        }
621 629

  
630
        private string MoveForServerMove(AccountInfo accountInfo, StateTuple tuple)
631
        {
632
            var relativePath = tuple.ObjectInfo.RelativeUrlToFilePath(accountInfo.UserName);
633
            var serverPath = Path.Combine(accountInfo.AccountPath, relativePath);
634

  
635
            if (tuple.FilePath == serverPath) return serverPath;
636

  
637
            if (tuple.FileInfo.Exists)
638
            {                    
639
                var fi = tuple.FileInfo as FileInfo;
640
                if (fi != null)
641
                    fi.MoveTo(serverPath);
642
                var di = tuple.FileInfo as DirectoryInfo;
643
                if (di != null)
644
                    di.MoveTo(serverPath);
645
                StatusKeeper.StoreInfo(serverPath, tuple.ObjectInfo);
646
            }
647
            else
648
            {
649
                Debug.Assert(false, "File does not exist");
650
            }
651
            return serverPath;
652
        }
653

  
622 654
        private void DeleteCloudFile(AccountInfo accountInfo, StateTuple tuple)
623 655
        {
624 656
            StatusKeeper.SetFileState(tuple.FilePath, FileStatus.Deleted,
......
647 679
            IEnumerable<Tuple<FileSystemInfo, string>> files, 
648 680
            IEnumerable<FileState> states)
649 681
        {
650
            var dct = new Dictionary<string, StateTuple>();
682
            var tuplesByPath = new Dictionary<string, StateTuple>();
651 683
            foreach (var file in files)
652 684
            {
653 685
                var fsInfo = file.Item1;
654 686
                var fileHash = fsInfo is DirectoryInfo? MERKLE_EMPTY:file.Item2;
655 687

  
656
                dct[fsInfo.FullName] = new StateTuple {FileInfo = fsInfo, MD5 = fileHash};
688
                tuplesByPath[fsInfo.FullName] = new StateTuple {FileInfo = fsInfo, MD5 = fileHash};
657 689
            }
658 690
            foreach (var state in states)
659 691
            {
660 692
                StateTuple hashTuple;
661
                if (dct.TryGetValue(state.FilePath, out hashTuple))
693
                if (tuplesByPath.TryGetValue(state.FilePath, out hashTuple))
662 694
                {
663 695
                    hashTuple.FileState = state;
664 696
                }
665 697
                else
666 698
                {
667 699
                    var fsInfo = FileInfoExtensions.FromPath(state.FilePath);
668
                    dct[state.FilePath] = new StateTuple {FileInfo = fsInfo, FileState = state};
700
                    tuplesByPath[state.FilePath] = new StateTuple {FileInfo = fsInfo, FileState = state};
669 701
                }
670 702
            }
703

  
704
            var tuplesByID = tuplesByPath.Values
705
                .Where(tuple => tuple.FileState != null && tuple.FileState.ObjectID!=null)
706
                .ToDictionary(tuple=>tuple.FileState.ObjectID,tuple=>tuple);//new Dictionary<Guid, StateTuple>();
707

  
671 708
            foreach (var info in infos)
672 709
            {
673 710
                StateTuple hashTuple;
674 711
                var filePath = info.Item1;
675 712
                var objectInfo = info.Item2;
676
                if (dct.TryGetValue(filePath, out hashTuple))
713
                var objectID = objectInfo.UUID;
714

  
715
                if (tuplesByID.TryGetValue(objectID, out hashTuple))
716
                {
717
                    hashTuple.ObjectInfo = objectInfo;                    
718
                }
719
                else if (tuplesByPath.TryGetValue(filePath, out hashTuple))
677 720
                {
678 721
                    hashTuple.ObjectInfo = objectInfo;
679 722
                }
680 723
                else
681 724
                {
682 725
                    var fsInfo = FileInfoExtensions.FromPath(filePath);
683
                    dct[filePath] = new StateTuple {FileInfo = fsInfo, ObjectInfo = objectInfo};
726
                    var tuple = new StateTuple {FileInfo = fsInfo, ObjectInfo = objectInfo};
727
                    tuplesByPath[filePath] = tuple;
728
                    tuplesByID[objectInfo.UUID] = tuple;
684 729
                }
685 730
            }
686
            return dct.Values;
731
            return tuplesByPath.Values;
687 732
        }
688 733

  
689 734
        /// <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