-
Notifications
You must be signed in to change notification settings - Fork 0
/
MemContextProvider.cs
174 lines (160 loc) · 5.22 KB
/
MemContextProvider.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
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
using System.Collections.Generic;
using System.IO;
namespace Dejavu
{
/// <summary>
/// This provider writes and reads context from runtime memory and allows dumping of data manually
/// </summary>
public class MemContextProvider : IProvideContext
{
private IDictionary<int, Queue<ContextEntry>> m_contextEntryCache;
private static object ms_writeLock = new object();
private string m_recordID;
private string m_replayID;
private readonly ISerializeObject m_objectSerializer;
public MemContextProvider(
ISerializeObject objectSerializer
)
{
m_objectSerializer = objectSerializer;
}
private IDictionary<int, Queue<ContextEntry>> LoadContextEntry(StreamReader streamReader)
{
var cache = new Dictionary<int, Queue<ContextEntry>>();
while (true)
{
var indexValue = streamReader.ReadLine();
if (string.IsNullOrEmpty(indexValue) ||
!int.TryParse(indexValue, out int threadIndex))
{
break;
}
if (!cache.TryGetValue(threadIndex, out Queue<ContextEntry> queue))
{
queue = new Queue<ContextEntry>();
cache[threadIndex] = queue;
}
var entryContent = streamReader.ReadLine();
if (string.IsNullOrEmpty(entryContent))
{
queue.Enqueue(null);
}
else
{
var contextEntry = m_objectSerializer.Deserialize(
entryContent,
typeof(ContextEntry)
);
queue.Enqueue((ContextEntry)contextEntry);
}
}
return cache;
}
private void SaveContextEntry(StreamWriter streamWriter, IDictionary<int, Queue<ContextEntry>> cache)
{
foreach (var cacheItem in cache)
{
var threadIndex = cacheItem.Key;
var queue = cacheItem.Value;
while (queue.Count > 0)
{
var contextEntry = queue.Dequeue();
var entryContent = m_objectSerializer.Serialize(contextEntry);
streamWriter.WriteLine(threadIndex);
streamWriter.WriteLine(entryContent);
}
}
streamWriter.Flush();
}
public bool StartRecording(string recordID)
{
if (!string.IsNullOrEmpty(m_recordID))
{
return false;
}
m_recordID = recordID;
m_contextEntryCache = new Dictionary<int, Queue<ContextEntry>>();
return true;
}
public bool StopRecording(string recordID, StreamWriter streamWriter)
{
if (m_recordID != recordID)
{
return false;
}
lock (ms_writeLock)
{
SaveContextEntry(
streamWriter,
m_contextEntryCache
);
m_recordID = string.Empty;
m_contextEntryCache = null;
return true;
}
}
public string GetRecordID()
{
return m_recordID;
}
public bool StartReplaying(string replayID, StreamReader streamReader)
{
if (!string.IsNullOrEmpty(m_replayID))
{
return false;
}
m_replayID = replayID;
m_contextEntryCache = LoadContextEntry(streamReader);
return true;
}
public bool StopReplaying(string replayID)
{
if (m_replayID != replayID)
{
return false;
}
m_replayID = string.Empty;
m_contextEntryCache = null;
return true;
}
public string GetReplayID()
{
return m_replayID;
}
public void InsertEntry(string contextID, int threadIndex, ContextEntry contextEntry)
{
if (m_contextEntryCache == null)
{
return;
}
lock (ms_writeLock)
{
if (!m_contextEntryCache.TryGetValue(threadIndex, out Queue<ContextEntry> queue))
{
queue = new Queue<ContextEntry>();
m_contextEntryCache[threadIndex] = queue;
}
queue.Enqueue(contextEntry);
}
}
public ContextEntry GetNextEntry(string contextID, int threadIndex)
{
if (m_contextEntryCache == null)
{
return null;
}
if (!m_contextEntryCache.TryGetValue(
threadIndex,
out Queue<ContextEntry> contextEntryQueue
))
{
return null;
}
if (contextEntryQueue.Count == 0)
{
return null;
}
return contextEntryQueue.Dequeue();
}
}
}