root / trunk / Pithos.Core / Agents / FileEventIdleBatch.cs @ 79f92570
History | View | Annotate | Download (5.7 kB)
1 |
#region |
---|---|
2 |
/* ----------------------------------------------------------------------- |
3 |
* <copyright file="FileEventIdleBatch.cs" company="GRNet"> |
4 |
* |
5 |
* Copyright 2011-2012 GRNET S.A. All rights reserved. |
6 |
* |
7 |
* Redistribution and use in source and binary forms, with or |
8 |
* without modification, are permitted provided that the following |
9 |
* conditions are met: |
10 |
* |
11 |
* 1. Redistributions of source code must retain the above |
12 |
* copyright notice, this list of conditions and the following |
13 |
* disclaimer. |
14 |
* |
15 |
* 2. Redistributions in binary form must reproduce the above |
16 |
* copyright notice, this list of conditions and the following |
17 |
* disclaimer in the documentation and/or other materials |
18 |
* provided with the distribution. |
19 |
* |
20 |
* |
21 |
* THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS |
22 |
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
23 |
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
24 |
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR |
25 |
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
26 |
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
27 |
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF |
28 |
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED |
29 |
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
30 |
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN |
31 |
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
32 |
* POSSIBILITY OF SUCH DAMAGE. |
33 |
* |
34 |
* The views and conclusions contained in the software and |
35 |
* documentation are those of the authors and should not be |
36 |
* interpreted as representing official policies, either expressed |
37 |
* or implied, of GRNET S.A. |
38 |
* </copyright> |
39 |
* ----------------------------------------------------------------------- |
40 |
*/ |
41 |
#endregion |
42 |
using System; |
43 |
using System.Collections.Generic; |
44 |
using System.IO; |
45 |
using System.Linq; |
46 |
using System.Reflection; |
47 |
using log4net; |
48 |
|
49 |
namespace Pithos.Core.Agents |
50 |
{ |
51 |
public class FileEventIdleBatch |
52 |
{ |
53 |
|
54 |
//Requirements |
55 |
//------------ |
56 |
//* The class should group workflow actions according to file name and type |
57 |
//* The class should pass all batched actions to a continuation when |
58 |
//* the batch is triggered. |
59 |
//* Actions should not survice a trigger |
60 |
|
61 |
private static readonly ILog Log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); |
62 |
|
63 |
private readonly IdleBatch<FileSystemEventArgs> _idleBatch; |
64 |
private readonly Action<Dictionary<string, FileSystemEventArgs[]>> _callback; |
65 |
|
66 |
public FileEventIdleBatch(int idleTimeout, Action<Dictionary<string, FileSystemEventArgs[]>> callback) |
67 |
{ |
68 |
_callback = callback; |
69 |
_idleBatch = new IdleBatch<FileSystemEventArgs>(idleTimeout, Process); |
70 |
} |
71 |
|
72 |
public void Post(FileSystemEventArgs arg) |
73 |
{ |
74 |
if (Log.IsDebugEnabled) |
75 |
Log.DebugFormat("Batch Post {0}:{1}", arg.ChangeType.ToString("g"), arg.FullPath); |
76 |
|
77 |
_idleBatch.Post(arg); |
78 |
} |
79 |
|
80 |
public void ForceTrigger() |
81 |
{ |
82 |
_idleBatch.ForceTrigger(); |
83 |
} |
84 |
|
85 |
|
86 |
protected virtual void Process(FileSystemEventArgs[] args) |
87 |
{ |
88 |
var dict = new Dictionary<string, FileSystemEventArgs[]>(); |
89 |
foreach (var arg in args) |
90 |
{ |
91 |
|
92 |
if (arg.ChangeType == WatcherChangeTypes.Created ) |
93 |
dict[arg.FullPath] = new[] { arg }; |
94 |
else if (arg.ChangeType == WatcherChangeTypes.Renamed) |
95 |
{ |
96 |
var renamedArg = (RenamedEventArgs)arg; |
97 |
FileSystemEventArgs[] oldValue; |
98 |
if (dict.TryGetValue(renamedArg.OldFullPath, out oldValue)) |
99 |
{ |
100 |
dict.Remove(renamedArg.OldFullPath); |
101 |
var last = oldValue.Last(); |
102 |
if (last.ChangeType == WatcherChangeTypes.Created) |
103 |
{ |
104 |
var createRenamed = new FileSystemEventArgs(WatcherChangeTypes.Created, Path.GetDirectoryName(renamedArg.FullPath), |
105 |
renamedArg.Name); |
106 |
dict[renamedArg.FullPath] = new[] {createRenamed}; |
107 |
} |
108 |
else |
109 |
dict[renamedArg.FullPath] = new[] { renamedArg }; |
110 |
} |
111 |
else |
112 |
dict[renamedArg.FullPath] = new[] { renamedArg}; |
113 |
} |
114 |
else |
115 |
{ |
116 |
FileSystemEventArgs[] oldValue; |
117 |
var hasValue=dict.TryGetValue(arg.FullPath, out oldValue); |
118 |
var last = hasValue?oldValue.LastOrDefault():null; |
119 |
|
120 |
if (last==null || last.ChangeType == WatcherChangeTypes.Changed) |
121 |
{ |
122 |
dict[arg.FullPath] = new[] { arg}; |
123 |
} |
124 |
else if (arg.ChangeType == WatcherChangeTypes.Deleted) |
125 |
{ |
126 |
if (last.ChangeType == WatcherChangeTypes.Created) |
127 |
dict.Remove(arg.FullPath); |
128 |
else |
129 |
{ |
130 |
dict[arg.FullPath] = new[] { arg }; |
131 |
} |
132 |
} |
133 |
else if (last.ChangeType == WatcherChangeTypes.Renamed && arg.ChangeType == WatcherChangeTypes.Changed) |
134 |
{ |
135 |
var newValue = oldValue.Concat(new[] { arg }).ToArray(); |
136 |
dict[arg.FullPath] = newValue; |
137 |
} |
138 |
|
139 |
} |
140 |
} |
141 |
_callback(dict); |
142 |
} |
143 |
|
144 |
} |
145 |
|
146 |
} |