Statistics
| Branch: | Revision:

root / trunk / Pithos.Client.WPF / FileProperties / ConflictResolver.cs @ 368e06fd

History | View | Annotate | Download (5.2 kB)

1
using System;
2
using System.Collections.Generic;
3
using System.ComponentModel.Composition;
4
using System.Linq;
5
using System.Text;
6
using Caliburn.Micro;
7
using Pithos.Core;
8
using Pithos.Core.Agents;
9
using Pithos.Interfaces;
10
using Pithos.Network;
11

    
12
namespace Pithos.Client.WPF.FileProperties
13
{
14
    [Export(typeof(IConflictResolver))]
15
    public class ConflictResolver : IConflictResolver
16
    {
17
        [Import]
18
        public IStatusKeeper StatusAgent { get; set; }
19

    
20
        [Import]
21
        public ShellViewModel Shell { get; set; }
22

    
23
        [Import]
24
        public NetworkAgent NetworkAgent { get; set; }
25

    
26
        public void Resolve(IEnumerable<ConflictFile> conflicts)
27
        {
28
            KeepServer(conflicts.Where(c => c.Action == ConflictAction.KeepServer));
29
            KeepLocal(conflicts.Where(c => c.Action == ConflictAction.KeepLocal));
30
            //KeepBoth(conflicts.Where(c => c.Action == ConflictAction.KeepBoth));
31
            ClearLocal(conflicts.Where(c => c.Action == ConflictAction.ClearLocal));
32
        }
33

    
34

    
35
        //Clearing the local state means that we clear the conflict state of the local file.
36
        //This is needed to clear wrong conflicts
37
        private void ClearLocal(IEnumerable<ConflictFile> conflicts)
38
        {
39
            //This can be done simply by changing the local Filestate status to normal
40
            conflicts.Apply(clear =>
41
                StatusAgent.SetFileState(clear.FilePath, FileStatus.Unchanged, FileOverlayStatus.Normal, ""));    
42

    
43
        }
44

    
45

    
46
        //Keeping the server version means that we need to 
47
        //download the server's version of the file.
48
        private void KeepServer(IEnumerable<ConflictFile> conflicts)
49
        {
50

    
51
            //This can be done either by scheduling the appropriate action, ignoring the hash
52
            //Or directly downloading the file.
53

    
54
            //This can be done either by scheduling the appropriate action, ignoring the hash
55
            //Or directly uploading the file.
56
            var monitors = Shell.Monitors.Select(m => m.Value);
57

    
58
            //Files that were not deleted
59
            var filesToDelete= from conflict in conflicts  
60
                          where conflict.State.OverlayStatus == FileOverlayStatus.Deleted
61
                          let info=FileInfoExtensions.FromPath(conflict.FilePath)
62
                          where info.Exists
63
                          select info;
64
            filesToDelete.Apply(f=>
65
                                    {
66
                                        f.Delete();
67
                                        StatusAgent.ClearFileStatus(f.FullName);
68
                                    });
69

    
70
            //Files that were not deleted
71
            var downloadActions = from conflict in conflicts  
72
                          where conflict.State.OverlayStatus != FileOverlayStatus.Deleted
73
                          let monitor=monitors.First(m=> conflict.FilePath.StartsWith(m.Account.AccountPath, StringComparison.InvariantCultureIgnoreCase))
74
                          let account = monitor.Account
75
                          let info = monitor.GetObjectInfo(conflict.FilePath)
76
                          select new CloudDownloadAction(account, info, "Resolver");
77

    
78
            downloadActions.Apply(action=> StatusAgent.SetFileState(action.FileState.FilePath,FileStatus.Unchanged,FileOverlayStatus.Normal,"Resolve by downloading"));
79
            downloadActions.Apply(NetworkAgent.Post);            
80

    
81
        }
82

    
83
        //Keeping the server version means that we need to 
84
        //upload the local version of the file to the server
85
        private void KeepLocal(IEnumerable<ConflictFile> conflicts)
86
        {
87

    
88
            var accounts = (from monitor in Shell.Monitors                           
89
                           select monitor.Value.Account).ToList();
90

    
91
            //This can be done either by scheduling the appropriate action, ignoring the hash
92
            //Or directly uploading the file.
93
            var actions = from conflict in conflicts
94
                          let account = accounts.First(acc => conflict.FilePath.StartsWith(acc.AccountPath, StringComparison.InvariantCultureIgnoreCase))
95
                          let info = FileInfoExtensions.FromPath(conflict.FilePath)
96
                          select new CloudUploadAction(account, info, conflict.State, 
97
                              account.BlockSize, account.BlockHash,"Resolver");
98

    
99
            actions.Apply(action => StatusAgent.SetFileState(action.FileState.FilePath, FileStatus.Modified, FileOverlayStatus.Normal, "Resolve by downloading"));
100
            actions.Apply(NetworkAgent.Post);
101
        }
102

    
103
        //Keeping both versions means that we need to copy one of them
104
        //somewhere and keep the other 
105
        private void KeepBoth(IEnumerable<ConflictFile> conflicts)
106
        {
107
            //We can copy the rename the local file to another name and download the server file
108
            //Or rename the server file and upload the local file
109

    
110
            //Downloading the server file is probably much faster with ADSL connections
111

    
112
            //We could probably use the local file as a source of blocks to download fewer data,
113
            //We create a hashmap of the local file, download the differences from the server
114
            //and merge common and changed blocks to create the new file.
115
        }
116
    }
117
}