Repository navigation
Expand file tree
/
Copy pathlog.cs
More file actions
160 lines (138 loc) · 4.18 KB
/
Copy pathlog.cs
File metadata and controls
160 lines (138 loc) · 4.18 KB
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
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Text;
using System.Threading;
internal enum LogLevel { TRACE, DEBUG, INFO, WARNING, ERROR, FATAL };
class Log
{
private static string _logfile = null;
private static string _disassembly = null;
private static bool _echo = false;
private static long _clock = 0;
private static ushort _cs = 0;
private static ushort _ip = 0;
private static LogLevel _ll = LogLevel.INFO;
private static SortedDictionary<string, Tuple<string, string> > disassembly = new();
private static readonly System.Threading.Lock _disassembly_lock = new();
private static readonly System.Threading.Lock _logging_lock = new(); // for windows
private static BlockingCollection<string> _log_queue = new(1024);
private static Thread _thread = null;
public static void SetLogFile(string file)
{
_logfile = file;
_thread = new Thread(Log.LogWriter);
_thread.Name = "LogWriter";
_thread.Start();
}
public static void EndLogging()
{
_log_queue.CompleteAdding();
if (_thread != null)
_thread.Join();
}
public static void SetLogLevel(LogLevel ll)
{
_ll = ll;
}
public static LogLevel StringToLogLevel(string name)
{
name = name.ToLower();
if (name == "trace")
return LogLevel.TRACE;
if (name == "debug")
return LogLevel.DEBUG;
if (name == "info")
return LogLevel.INFO;
if (name == "warning")
return LogLevel.WARNING;
if (name == "error")
return LogLevel.ERROR;
if (name == "fatal")
return LogLevel.FATAL;
Log.Cnsl($"Loglevel \"{name}\" not understood, using debug instead");
return LogLevel.DEBUG;
}
public static void SetMeta(long clock, ushort cs, ushort ip)
{
_clock = clock;
_cs = cs;
_ip = ip;
}
public static void SetDisassemblyFile(string file)
{
_disassembly = file;
}
public static void EchoToConsole(bool state)
{
_echo = state;
}
public static void Disassemble(string prefix, string assembly)
{
DoLog(prefix + " " + assembly, LogLevel.DEBUG);
}
public static void EmitDisassembly()
{
#if DEBUG
if (_disassembly != null)
{
lock(_disassembly_lock)
{
foreach(KeyValuePair<string, Tuple<string, string> > entry in disassembly)
{
File.AppendAllText(_disassembly, $"{entry.Value.Item1} {entry.Value.Item2}" + Environment.NewLine);
}
}
}
#endif
}
public static void LogWriter()
{
FileStream _file_handle = new FileStream(_logfile, FileMode.OpenOrCreate, FileAccess.ReadWrite);
while(_log_queue.IsCompleted == false || _log_queue.Count > 0)
{
string item;
if (_log_queue.TryTake(out item, 1500))
{
if (item == null)
_file_handle.SetLength(0);
else
{
byte[] data = new UTF8Encoding(true).GetBytes(item + Environment.NewLine);
_file_handle.Write(data, 0, data.Length);
}
}
else
{
_file_handle.Flush();
}
}
_file_handle.Close();
Console.WriteLine("Log writer thread stopped");
}
public static void TruncateLogfile()
{
_log_queue.Add(null);
}
public static void Cnsl(string what)
{
Console.WriteLine(what);
if (_logfile != null)
_log_queue.Add(what);
}
public static void DoLog(string what, LogLevel ll)
{
if ((_logfile == null && _echo == false) || ll < _ll)
return;
try
{
string output = $"{_clock} {_cs:X4}:{_ip:X4} | {ll} | " + what;
_log_queue.Add(output);
}
catch(System.InvalidOperationException e)
{
// in case the queue was closed in an other thread
}
if (_echo)
Log.Cnsl(what);
}
}