Revision ec1a1baf trunk/Pithos.Core/Agents/PollAgent.cs

b/trunk/Pithos.Core/Agents/PollAgent.cs
47 47
using System.IO;
48 48
using System.Threading;
49 49
using System.Threading.Tasks;
50
using System.Threading.Tasks.Dataflow;
51 50
using Castle.ActiveRecord;
52 51
using Pithos.Interfaces;
53 52
using Pithos.Network;
......
58 57
    using System;
59 58
    using System.Collections.Generic;
60 59
    using System.Linq;
61
    using System.Text;
62 60

  
63 61
    /// <summary>
64 62
    /// PollAgent periodically polls the server to detect object changes. The agent retrieves a listing of all
......
87 85
        //The Sync Event signals a manual synchronisation
88 86
        private readonly AsyncManualResetEvent _syncEvent = new AsyncManualResetEvent();
89 87

  
90
        private ConcurrentDictionary<string, DateTime> _lastSeen = new ConcurrentDictionary<string, DateTime>();
91
        private readonly ConcurrentBag<AccountInfo> _accounts = new ConcurrentBag<AccountInfo>();
88
        private readonly ConcurrentDictionary<string, DateTime> _lastSeen = new ConcurrentDictionary<string, DateTime>();
89
        private readonly ConcurrentDictionary<string, AccountInfo> _accounts = new ConcurrentDictionary<string,AccountInfo>();
92 90

  
93 91

  
94 92
        /// <summary>
......
111 109
            UpdateStatus(PithosStatus.Syncing);
112 110
            StatusNotification.Notify(new PollNotification());
113 111

  
114
            using (log4net.ThreadContext.Stacks["Retrieve Remote"].Push("All accounts"))
112
            using (ThreadContext.Stacks["Retrieve Remote"].Push("All accounts"))
115 113
            {
116 114
                //If this poll fails, we will retry with the same since value
117 115
                var nextSince = since;
......
121 119
                    //This is done to ensure there are no discrepancies due to clock differences
122 120
                    var current = DateTime.Now.AddSeconds(-1);
123 121

  
124
                    var tasks = from accountInfo in _accounts
122
                    var tasks = from accountInfo in _accounts.Values
125 123
                                select ProcessAccountFiles(accountInfo, since);
126 124

  
127 125
                    await TaskEx.WhenAll(tasks.ToList());
......
195 193
                var client = new CloudFilesClient(accountInfo);
196 194

  
197 195
                //We don't need to check the trash container
198
                var containers = client.ListContainers(accountInfo.UserName).Where(c=>c.Name!="trash");
196
                var containers = client.ListContainers(accountInfo.UserName)
197
                    .Where(c=>c.Name!="trash")
198
                    .ToList();
199 199

  
200 200

  
201 201
                CreateContainerFolders(accountInfo, containers);
......
206 206
                    await NetworkAgent.GetDeleteAwaiter();
207 207
                    //Get the poll time now. We may miss some deletions but it's better to keep a file that was deleted
208 208
                    //than delete a file that was created while we were executing the poll                    
209
                    var pollTime = DateTime.Now;
210 209

  
211 210
                    //Get the list of server objects changed since the last check
212 211
                    //The name of the container is passed as state in order to create a dictionary of tasks in a subsequent step
213 212
                    var listObjects = (from container in containers
214 213
                                       select Task<IList<ObjectInfo>>.Factory.StartNew(_ =>
215 214
                                             client.ListObjects(accountInfo.UserName, container.Name, since), container.Name)).ToList();
216
                    //BUG: Can't detect difference between no changes or no objects
217
                    //ListObjects returns nothing if there are no changes since the last check time (since value)                    
218
                    //TODO: Must detect the difference between no server objects and no change
219

  
220
                    //NOTE: One option is to "mark" all result lists with their container name, or 
221
                    //rather the url of the container
222
                    //Another option 
223 215

  
224 216
                    var listShared = Task<IList<ObjectInfo>>.Factory.StartNew(_ => 
225 217
                        client.ListSharedObjects(since), "shared");
......
263 255

  
264 256
                        var differencer = _differencer.PostSnapshot(accountInfo, cleanRemotes);
265 257

  
266
                        ProcessDeletedFiles(accountInfo, differencer.Deleted.FilterDirectlyBelow(SelectiveUris), pollTime);
258
                        ProcessDeletedFiles(accountInfo, differencer.Deleted.FilterDirectlyBelow(SelectiveUris));
267 259

  
268 260
                        // @@@ NEED To add previous state here as well, To compare with previous hash
269 261

  
......
301 293
            }
302 294
        }
303 295

  
304
        AccountsDifferencer _differencer = new AccountsDifferencer();
296
        readonly AccountsDifferencer _differencer = new AccountsDifferencer();
305 297
        private List<Uri> _selectiveUris=new List<Uri>();
306 298

  
307 299
        /// <summary>
......
309 301
        /// </summary>
310 302
        /// <param name="accountInfo"></param>
311 303
        /// <param name="cloudFiles"></param>
312
        /// <param name="pollTime"></param>
313
        private void ProcessDeletedFiles(AccountInfo accountInfo, IEnumerable<ObjectInfo> cloudFiles, DateTime pollTime)
304
        private void ProcessDeletedFiles(AccountInfo accountInfo, IEnumerable<ObjectInfo> cloudFiles)
314 305
        {
315 306
            if (accountInfo == null)
316 307
                throw new ArgumentNullException("accountInfo");
......
504 495
            }
505 496
        }
506 497

  
507
        private void ProcessTrashedFiles(AccountInfo accountInfo, IEnumerable<ObjectInfo> trashObjects)
508
        {
509
            var fileAgent = FileAgent.GetFileAgent(accountInfo);
510
            foreach (var trashObject in trashObjects)
511
            {
512
                var barePath = trashObject.RelativeUrlToFilePath(accountInfo.UserName);
513
                //HACK: Assume only the "pithos" container is used. Must find out what happens when
514
                //deleting a file from a different container
515
                var relativePath = Path.Combine("pithos", barePath);
516
                fileAgent.Delete(relativePath);
517
            }
518
        }
519

  
520 498
        /// <summary>
521 499
        /// Notify the UI to update the visual status
522 500
        /// </summary>
......
561 539

  
562 540
        public void AddAccount(AccountInfo accountInfo)
563 541
        {
564
            if (!_accounts.Contains(accountInfo))
565
                _accounts.Add(accountInfo);
542
            //Avoid adding a duplicate accountInfo
543
            _accounts.TryAdd(accountInfo.UserName, accountInfo);
544
        }
545

  
546
        public void RemoveAccount(AccountInfo accountInfo)
547
        {
548
            AccountInfo account;
549
            _accounts.TryRemove(accountInfo.UserName,out account);
566 550
        }
567 551
    }
568 552
}

Also available in: Unified diff