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