root / trunk / Pithos.Core / Agents / FileEventIdleBatch.cs @ 6b0de454
History | View | Annotate | Download (5.9 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.Diagnostics.Contracts; |
45 |
using System.IO; |
46 |
using System.Linq; |
47 |
using System.Reflection; |
48 |
using log4net; |
49 |
|
50 |
namespace Pithos.Core.Agents |
51 |
{ |
52 |
public class FileEventIdleBatch |
53 |
{ |
54 |
|
55 |
//Requirements |
56 |
//------------ |
57 |
//* The class should group workflow actions according to file name and type |
58 |
//* The class should pass all batched actions to a continuation when |
59 |
//* the batch is triggered. |
60 |
//* Actions should not survice a trigger |
61 |
|
62 |
private static readonly ILog Log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); |
63 |
|
64 |
private readonly IdleBatch<FileSystemEventArgs> _idleBatch; |
65 |
private readonly Action<Dictionary<string, FileSystemEventArgs[]>> _callback; |
66 |
|
67 |
public FileEventIdleBatch(int idleTimeout, Action<Dictionary<string, FileSystemEventArgs[]>> callback) |
68 |
{ |
69 |
_callback = callback; |
70 |
_idleBatch = new IdleBatch<FileSystemEventArgs>(idleTimeout, Process); |
71 |
} |
72 |
|
73 |
public void Post(FileSystemEventArgs arg) |
74 |
{ |
75 |
if (arg is RenamedEventArgs) |
76 |
throw new ArgumentException("arg"); |
77 |
Contract.EndContractBlock(); |
78 |
if (Log.IsDebugEnabled) |
79 |
Log.DebugFormat("Batch Post {0}:{1}", arg.ChangeType.ToString("g"), arg.FullPath); |
80 |
|
81 |
_idleBatch.Post(arg); |
82 |
} |
83 |
|
84 |
public void ForceTrigger() |
85 |
{ |
86 |
_idleBatch.ForceTrigger(); |
87 |
} |
88 |
|
89 |
|
90 |
protected virtual void Process(FileSystemEventArgs[] args) |
91 |
{ |
92 |
var dict = new Dictionary<string, FileSystemEventArgs[]>(); |
93 |
foreach (var arg in args) |
94 |
{ |
95 |
|
96 |
if (arg.ChangeType == WatcherChangeTypes.Created ) |
97 |
dict[arg.FullPath] = new[] { arg }; |
98 |
else if (arg.ChangeType == WatcherChangeTypes.Renamed) |
99 |
{ |
100 |
var renamedArg = (MovedEventArgs)arg; |
101 |
FileSystemEventArgs[] oldValue; |
102 |
if (dict.TryGetValue(renamedArg.OldFullPath, out oldValue)) |
103 |
{ |
104 |
dict.Remove(renamedArg.OldFullPath); |
105 |
var last = oldValue.Last(); |
106 |
if (last.ChangeType == WatcherChangeTypes.Created) |
107 |
{ |
108 |
var createRenamed = new FileSystemEventArgs(WatcherChangeTypes.Created, Path.GetDirectoryName(renamedArg.FullPath), |
109 |
renamedArg.Name); |
110 |
dict[renamedArg.FullPath] = new[] {createRenamed}; |
111 |
} |
112 |
else |
113 |
dict[renamedArg.FullPath] = new[] { renamedArg }; |
114 |
} |
115 |
else |
116 |
dict[renamedArg.FullPath] = new[] { renamedArg}; |
117 |
} |
118 |
else |
119 |
{ |
120 |
FileSystemEventArgs[] oldValue; |
121 |
var hasValue=dict.TryGetValue(arg.FullPath, out oldValue); |
122 |
var last = hasValue?oldValue.LastOrDefault():null; |
123 |
|
124 |
if (last==null || last.ChangeType == WatcherChangeTypes.Changed) |
125 |
{ |
126 |
dict[arg.FullPath] = new[] { arg}; |
127 |
} |
128 |
else if (arg.ChangeType == WatcherChangeTypes.Deleted) |
129 |
{ |
130 |
if (last.ChangeType == WatcherChangeTypes.Created) |
131 |
dict.Remove(arg.FullPath); |
132 |
else |
133 |
{ |
134 |
dict[arg.FullPath] = new[] { arg }; |
135 |
} |
136 |
} |
137 |
else if (last.ChangeType == WatcherChangeTypes.Renamed && arg.ChangeType == WatcherChangeTypes.Changed) |
138 |
{ |
139 |
var newValue = oldValue.Concat(new[] { arg }).ToArray(); |
140 |
dict[arg.FullPath] = newValue; |
141 |
} |
142 |
|
143 |
} |
144 |
} |
145 |
_callback(dict); |
146 |
} |
147 |
|
148 |
} |
149 |
|
150 |
} |