-// -----------------------------------------------------------------------
-// <copyright file="WorkflowAgent.cs" company="GRNET">
-// Copyright 2011 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.
-// </copyright>
-// -----------------------------------------------------------------------
-
+#region
+/* -----------------------------------------------------------------------
+ * <copyright file="WorkflowAgent.cs" company="GRNet">
+ *
+ * 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.
+ * </copyright>
+ * -----------------------------------------------------------------------
+ */
+#endregion
using System;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.Diagnostics.Contracts;
using System.IO;
using System.Linq;
+using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using Castle.ActiveRecord;
[Export]
public class WorkflowAgent
{
+ private static readonly ILog Log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
+
readonly Agent<WorkflowState> _agent;
public IStatusNotification StatusNotification { get; set; }
[System.ComponentModel.Composition.Import]
public NetworkAgent NetworkAgent { get; set; }
- private static readonly ILog Log = LogManager.GetLogger("WorkflowAgent");
+ [System.ComponentModel.Composition.Import]
+ public IPithosSettings Settings { get; set; }
+
+ [System.ComponentModel.Composition.Import]
+ public Selectives Selectives { get; set; }
public WorkflowAgent()
{
if (Log.IsDebugEnabled) Log.DebugFormat("Skipping {0}", state.FileName);
return CompletedTask<object>.Default;
- }
+ }
- var info = Directory.Exists(state.Path) ? (FileSystemInfo)new DirectoryInfo(state.Path) : new FileInfo(state.Path);
+ var info = FileInfoExtensions.FromPath(state.Path);// Directory.Exists(state.Path) ? (FileSystemInfo)new DirectoryInfo(state.Path) : new FileInfo(state.Path);
//Bypass deleted files, unless the status is Deleted
if (!info.Exists && state.Status != FileStatus.Deleted)
case FileStatus.Modified:
NetworkAgent.Post(new CloudUploadAction(accountInfo, info, fileState,
accountInfo.BlockSize,
- accountInfo.BlockHash));
+ accountInfo.BlockHash,state,state.IsCreation));
break;
case FileStatus.Deleted:
DeleteChildObjects(state, fileState);
- NetworkAgent.Post(new CloudDeleteAction(accountInfo, info, fileState));
+ NetworkAgent.Post(new CloudDeleteAction(accountInfo, info, fileState,state));
break;
case FileStatus.Renamed:
+ if (state.OldPath == null)
+ {
+ //We reach this point only if the app closed before propagating a rename to the server
+ Log.WarnFormat("Unfinished rename [{0}]",state.Path);
+ StatusKeeper.SetFileState(state.Path,FileStatus.Conflict,FileOverlayStatus.Conflict, "Rename without old path");
+ break;
+ }
FileSystemInfo oldInfo = Directory.Exists(state.OldPath)
? (FileSystemInfo) new DirectoryInfo(state.OldPath)
: new FileInfo(state.OldPath);
: new FileInfo(state.Path);
NetworkAgent.Post(new CloudMoveAction(accountInfo, CloudActionType.RenameCloud,
oldInfo,
- newInfo));
+ newInfo,state));
//TODO: Do I have to move children as well or will Pithos handle this?
//Need to find all children of the OLD filepath
- MoveChildObjects(state);
+ //MoveChildObjects(state);
break;
}
}
}
}
+
private void DeleteChildObjects(WorkflowState state, FileState fileState)
{
if (fileState != null)
var childInfo = child.IsFolder
? (FileSystemInfo) new DirectoryInfo(child.FilePath)
: new FileInfo(child.FilePath);
- NetworkAgent.Post(new CloudDeleteAction(state.AccountInfo, childInfo, child));
+ NetworkAgent.Post(new CloudDeleteAction(state.AccountInfo, childInfo, child,state));
}
}
}
- private void MoveChildObjects(WorkflowState state)
+ /*private void MoveChildObjects(WorkflowState state)
{
var oldFileState = StatusKeeper.GetStateByFilePath(state.OldPath);
if (oldFileState != null)
oldMoveInfo, newMoveInfo));
}
}
- }
+ }*/
//Starts interrupted files for a specific account
public void RestartInterruptedFiles(AccountInfo accountInfo)
{
- StatusNotification.NotifyChange("Restart processing interrupted files", TraceLevel.Verbose);
-
- using (log4net.ThreadContext.Stacks["Workflow"].Push("Restart"))
+ StatusKeeper.CleanupOrphanStates();
+ using (log4net.ThreadContext.Stacks["Operation"].Push("RestartInterrupted"))
{
if (Log.IsDebugEnabled)
Log.Debug("Starting interrupted files");
.ToLower();
-
+
+
var account = accountInfo;
- var pendingEntries = from state in FileState.Queryable
+ var pendingEntries = (from state in FileState.Queryable
where state.FileStatus != FileStatus.Unchanged &&
+ state.FileStatus != FileStatus.Forbidden &&
+ state.FileStatus != FileStatus.Conflict &&
!state.FilePath.StartsWith(cachePath) &&
!state.FilePath.EndsWith(".ignore") &&
- state.FilePath.StartsWith(account.AccountPath)
- select state;
- var pendingStates = new List<WorkflowState>();
- foreach (var state in pendingEntries)
- {
- pendingStates.Add(new WorkflowState(account, state));
- }
+ state.FilePath.StartsWith(account.AccountPath)
+ select state).ToList();
+ if (pendingEntries.Count>0)
+ StatusNotification.NotifyChange("Restart processing interrupted files", TraceLevel.Verbose);
+
+ var pendingStates = pendingEntries
+ .Select(state => new WorkflowState(account, state))
+ .ToList();
+
+
if (Log.IsDebugEnabled)
Log.DebugFormat("Found {0} interrupted files", pendingStates.Count);
-
- foreach (var entry in pendingStates)
- {
- Post(entry);
- }
+ pendingStates.ForEach(Post);
}
}
return;*/
//TODO: Need to handle folder renames
+
+ if (!Selectives.IsSelected(workflowState.AccountInfo, workflowState.Path))
+ {
+ if (!workflowState.IsCreation || File.Exists(workflowState.Path))
+ {
+ Log.InfoFormat("File skipped, not under a selected folder [{0}] ", workflowState.Path);
+ return;
+ }
+ }
+
Debug.Assert(workflowState.Path.StartsWith(workflowState.AccountInfo.AccountPath, StringComparison.InvariantCultureIgnoreCase), "File from wrong account posted");
_agent.Post(workflowState);