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