forked from Ken98045/On-Guard
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathHIstory.cs
135 lines (115 loc) · 3.61 KB
/
HIstory.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Threading;
using System.IO;
// In general using old style threading seems a more natural model for what the History collection needs to do.
// Similarly, none of the pre-defined concurrent collections seem appropriate either.
namespace SAAI
{
public class History : IDisposable
{
readonly int _historyLength;
readonly Thread _thread;
readonly ManualResetEvent _stopEvent = new ManualResetEvent(false);
readonly object _lock = new object();
private bool disposedValue;
readonly SortedList<DateTime, Frame> _historyList = new SortedList<DateTime, Frame>();
public History(int historyInSeconds)
{
_historyLength = historyInSeconds;
_thread = new Thread(CleanupOldFrames);
_thread.IsBackground = true;
_thread.Start();
}
protected virtual void Dispose(bool disposing)
{
if (!disposedValue)
{
if (disposing)
{
_stopEvent.Set();
_thread.Join(2000);
_stopEvent.Dispose();
}
disposedValue = true;
}
}
public void Dispose()
{
// Do not change this code. Put cleanup code in 'Dispose(bool disposing)' method
Dispose(disposing: true);
GC.SuppressFinalize(this);
}
public void Add(Frame frame)
{
lock (_lock)
{
DateTime createTime = File.GetCreationTime(frame.Item.PendingFile);
_historyList[createTime] = new Frame(frame);
}
}
public List<Frame> GetFramesInTimespan(TimeSpan span, DateTime target, TimeDirection direction)
{
List<Frame> result = new List<Frame>();
lock (_historyList)
{
IEnumerable<DateTime> selectResult = null;
switch (direction)
{
case TimeDirection.Before:
selectResult = _historyList.Keys.Where(fileTime => fileTime < target && ((target - fileTime).TotalSeconds < span.TotalSeconds));
break;
case TimeDirection.After:
selectResult = _historyList.Keys.Where(fileTime => fileTime > target && ((fileTime - target).TotalSeconds < span.TotalSeconds));
break;
case TimeDirection.Both:
selectResult = _historyList.Keys.Where(fileTime => (fileTime < target && ((target - fileTime).TotalSeconds < span.TotalSeconds)) || (fileTime > target && ((fileTime - target).TotalSeconds < span.TotalSeconds)));
break;
}
foreach (var ft in selectResult)
{
result.Add(_historyList[ft]);
}
}
return result;
}
void CleanupOldFrames()
{
while (true)
{
bool waitResult = _stopEvent.WaitOne(500);
if (waitResult)
{
break; // history is disposing, exit immediately
}
// remove old frames as determined by the history length.
while (_historyList.Count > 0)
{
TimeSpan span = DateTime.Now - _historyList.Keys[0];
if (span.TotalSeconds >= _historyLength)
{
Frame frameToDelete = _historyList.Values[0];
lock (_historyList)
{
_historyList.RemoveAt(0);
}
Thread.Sleep(0); // don't be hog, not really a problem, but....
}
else
{
break;
}
}
}
}
}
public enum TimeDirection
{
Both = 0,
Before = 1,
After = 2
}
}