X-Git-Url: https://code.grnet.gr/git/pithos-ms-client/blobdiff_plain/c28a075a5149de9d2d7fe8710bb3cf226f6bacc8..d436a267454a7fa1f5e78795285e762f3ddf56b6:/trunk/Pithos.Core/Agents/FileAgent.cs
diff --git a/trunk/Pithos.Core/Agents/FileAgent.cs b/trunk/Pithos.Core/Agents/FileAgent.cs
index ba323a3..a29ef4e 100644
--- a/trunk/Pithos.Core/Agents/FileAgent.cs
+++ b/trunk/Pithos.Core/Agents/FileAgent.cs
@@ -1,37 +1,183 @@
-using System;
+#region
+/* -----------------------------------------------------------------------
+ *
+ *
+ * Copyright 2011-2012 GRNET S.A. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ *
+ * THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and
+ * documentation are those of the authors and should not be
+ * interpreted as representing official policies, either expressed
+ * or implied, of GRNET S.A.
+ *
+ * -----------------------------------------------------------------------
+ */
+#endregion
+using System;
using System.Collections.Generic;
-using System.ComponentModel.Composition;
-using System.Diagnostics;
using System.Diagnostics.Contracts;
using System.IO;
using System.Linq;
-using System.Text;
+using System.Reflection;
using System.Threading.Tasks;
using Pithos.Interfaces;
using Pithos.Network;
using log4net;
-using log4net.Core;
namespace Pithos.Core.Agents
{
- [Export]
+// [Export]
public class FileAgent
{
- Agent _agent;
+ private static readonly ILog Log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
+
+ /*
+ Agent _agent;
+ */
private FileSystemWatcher _watcher;
+ private FileSystemWatcherAdapter _adapter;
+ private FileEventIdleBatch _eventIdleBatch;
- [Import]
+ //[Import]
public IStatusKeeper StatusKeeper { get; set; }
- [Import]
+
+ public IStatusNotification StatusNotification { get; set; }
+ //[Import]
public IPithosWorkflow Workflow { get; set; }
- [Import]
- public WorkflowAgent WorkflowAgent { get; set; }
+ //[Import]
+ //public WorkflowAgent WorkflowAgent { get; set; }
private AccountInfo AccountInfo { get; set; }
- private string RootPath { get; set; }
+ internal string RootPath { get; set; }
+
+ public TimeSpan IdleTimeout { get; set; }
- private static readonly ILog Log = LogManager.GetLogger("FileAgent");
+ public PollAgent PollAgent { get; set; }
+
+ private void ProcessBatchedEvents(Dictionary fileEvents)
+ {
+ var paths = new HashSet();
+ var events = from evts in fileEvents.Values
+ from evt in evts
+ select evt;
+ foreach (var evt in events)
+ {
+ paths.Add(evt.FullPath);
+ if (evt is MovedEventArgs)
+ {
+ paths.Add((evt as MovedEventArgs).OldFullPath);
+ }
+ }
+
+ PollAgent.SynchNow(paths);
+ }
+
+/*
+ private void ProcessBatchedEvents(Dictionary fileEvents)
+ {
+ StatusNotification.SetPithosStatus(PithosStatus.LocalSyncing,String.Format("Uploading {0} files",fileEvents.Count));
+ //Start with events that do not originate in one of the ignored folders
+ var initialEvents = from evt in fileEvents
+ where !IgnorePaths(evt.Key)
+ select evt;
+
+ IEnumerable> cleanEvents;
+
+
+ var selectiveEnabled = Selectives.IsSelectiveEnabled(AccountInfo.AccountKey);
+ //When selective sync is enabled,
+ if (selectiveEnabled)
+ {
+ //Include all selected items
+ var selectedEvents = from evt in initialEvents
+ where Selectives.IsSelected(AccountInfo, evt.Key)
+ select evt;
+ //And all folder creations in the unselected folders
+ var folderCreations = from evt in initialEvents
+ let folderPath=evt.Key
+ //The original folder may not exist due to renames. Just make sure that the path is not a file
+ where !File.Exists(folderPath)
+ //We only want unselected items
+ && !Selectives.IsSelected(AccountInfo, folderPath)
+ //Is there any creation event related to the folder?
+ && evt.Value.Any(arg => arg.ChangeType == WatcherChangeTypes.Created)
+ select evt;
+ cleanEvents = selectedEvents.Union(folderCreations).ToList();
+ }
+ //If selective is disabled, only exclude the shared folders
+ else
+ {
+ cleanEvents = (from evt in initialEvents
+ where !evt.Key.IsSharedTo(AccountInfo)
+ select evt).ToList();
+ }
+
+
+ foreach (var fileEvent in cleanEvents)
+ {
+ //var filePath = fileEvent.Key;
+ var changes = fileEvent.Value;
+
+ var isNotFile = !File.Exists(fileEvent.Key);
+ foreach (var change in changes)
+ {
+ if (change.ChangeType == WatcherChangeTypes.Renamed)
+ {
+ var rename = (MovedEventArgs) change;
+ _agent.Post(new WorkflowState(change)
+ {
+ AccountInfo = AccountInfo,
+ OldPath = rename.OldFullPath,
+ OldFileName = Path.GetFileName(rename.OldName),
+ Path = rename.FullPath,
+ FileName = Path.GetFileName(rename.Name),
+ TriggeringChange = rename.ChangeType
+ });
+ }
+ else
+ {
+ var isCreation = selectiveEnabled && isNotFile && change.ChangeType == WatcherChangeTypes.Created;
+ _agent.Post(new WorkflowState(change)
+ {
+ AccountInfo = AccountInfo,
+ Path = change.FullPath,
+ FileName = Path.GetFileName(change.Name),
+ TriggeringChange = change.ChangeType,
+ IsCreation=isCreation
+ });
+ }
+ }
+ }
+ StatusNotification.SetPithosStatus(PithosStatus.LocalComplete);
+ }
+*/
public void Start(AccountInfo accountInfo,string rootPath)
{
@@ -41,18 +187,28 @@ namespace Pithos.Core.Agents
throw new ArgumentNullException("rootPath");
if (!Path.IsPathRooted(rootPath))
throw new ArgumentException("rootPath must be an absolute path","rootPath");
- Contract.EndContractBlock();
+ if (IdleTimeout == null)
+ throw new InvalidOperationException("IdleTimeout must have a valid value");
+ Contract.EndContractBlock();
AccountInfo = accountInfo;
RootPath = rootPath;
- _watcher = new FileSystemWatcher(rootPath);
- _watcher.IncludeSubdirectories = true;
- _watcher.Changed += OnFileEvent;
- _watcher.Created += OnFileEvent;
- _watcher.Deleted += OnFileEvent;
- _watcher.Renamed += OnRenameEvent;
+
+ _eventIdleBatch = new FileEventIdleBatch(PollAgent,(int)IdleTimeout.TotalMilliseconds, ProcessBatchedEvents);
+
+ _watcher = new FileSystemWatcher(rootPath) { IncludeSubdirectories = true, InternalBufferSize = 8 * 4096 };
+ _adapter = new FileSystemWatcherAdapter(_watcher);
+
+ _adapter.Changed += OnFileEvent;
+ _adapter.Created += OnFileEvent;
+ _adapter.Deleted += OnFileEvent;
+ //_adapter.Renamed += OnRenameEvent;
+ _adapter.Moved += OnMoveEvent;
_watcher.EnableRaisingEvents = true;
+/*
+
+
_agent = Agent.Start(inbox =>
{
@@ -60,22 +216,23 @@ namespace Pithos.Core.Agents
loop = () =>
{
var message = inbox.Receive();
- var process=message.Then(Process,inbox.CancellationToken);
-
+ var process=message.Then(Process,inbox.CancellationToken);
inbox.LoopAsync(process,loop,ex=>
Log.ErrorFormat("[ERROR] File Event Processing:\r{0}", ex));
};
loop();
- });
+ });*/
}
+/*
private Task