Make Log thread-safe.
Since logging is exposed via static methods, it need to be thread-safe or multiple threads trying to log at the same time will cause bad things to happen.
This commit is contained in:
@@ -22,7 +22,7 @@ namespace OpenRA.Network
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
NatUtility.Logger = Log.Channels["server"].Writer;
|
NatUtility.Logger = Log.Channel("server").Writer;
|
||||||
NatUtility.Verbose = Game.Settings.Server.VerboseNatDiscovery;
|
NatUtility.Verbose = Game.Settings.Server.VerboseNatDiscovery;
|
||||||
NatUtility.DeviceFound += DeviceFound;
|
NatUtility.DeviceFound += DeviceFound;
|
||||||
Game.Settings.Server.NatDeviceAvailable = false;
|
Game.Settings.Server.NatDeviceAvailable = false;
|
||||||
|
|||||||
@@ -17,12 +17,12 @@ namespace OpenRA
|
|||||||
public struct ChannelInfo
|
public struct ChannelInfo
|
||||||
{
|
{
|
||||||
public string Filename;
|
public string Filename;
|
||||||
public StreamWriter Writer;
|
public TextWriter Writer;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class Log
|
public static class Log
|
||||||
{
|
{
|
||||||
public static readonly Dictionary<string, ChannelInfo> Channels = new Dictionary<string, ChannelInfo>();
|
static readonly Dictionary<string, ChannelInfo> Channels = new Dictionary<string, ChannelInfo>();
|
||||||
|
|
||||||
static IEnumerable<string> FilenamesForChannel(string channelName, string baseFilename)
|
static IEnumerable<string> FilenamesForChannel(string channelName, string baseFilename)
|
||||||
{
|
{
|
||||||
@@ -33,56 +33,63 @@ namespace OpenRA
|
|||||||
yield return Path.Combine(path, i > 0 ? "{0}.{1}".F(baseFilename, i) : baseFilename);
|
yield return Path.Combine(path, i > 0 ? "{0}.{1}".F(baseFilename, i) : baseFilename);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static ChannelInfo Channel(string channelName)
|
||||||
|
{
|
||||||
|
ChannelInfo info;
|
||||||
|
lock (Channels)
|
||||||
|
if (!Channels.TryGetValue(channelName, out info))
|
||||||
|
throw new Exception("Tried logging to non-existent channel " + channelName);
|
||||||
|
|
||||||
|
return info;
|
||||||
|
}
|
||||||
|
|
||||||
public static void AddChannel(string channelName, string baseFilename)
|
public static void AddChannel(string channelName, string baseFilename)
|
||||||
{
|
{
|
||||||
if (Channels.ContainsKey(channelName)) return;
|
lock (Channels)
|
||||||
|
|
||||||
if (string.IsNullOrEmpty(baseFilename))
|
|
||||||
{
|
{
|
||||||
Channels.Add(channelName, new ChannelInfo());
|
if (Channels.ContainsKey(channelName)) return;
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (var filename in FilenamesForChannel(channelName, baseFilename))
|
if (string.IsNullOrEmpty(baseFilename))
|
||||||
try
|
|
||||||
{
|
{
|
||||||
var writer = File.CreateText(filename);
|
Channels.Add(channelName, new ChannelInfo());
|
||||||
writer.AutoFlush = true;
|
|
||||||
|
|
||||||
Channels.Add(channelName,
|
|
||||||
new ChannelInfo()
|
|
||||||
{
|
|
||||||
Filename = filename,
|
|
||||||
Writer = writer
|
|
||||||
});
|
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
catch (IOException) { }
|
|
||||||
|
foreach (var filename in FilenamesForChannel(channelName, baseFilename))
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var writer = File.CreateText(filename);
|
||||||
|
writer.AutoFlush = true;
|
||||||
|
|
||||||
|
Channels.Add(channelName,
|
||||||
|
new ChannelInfo
|
||||||
|
{
|
||||||
|
Filename = filename,
|
||||||
|
Writer = TextWriter.Synchronized(writer)
|
||||||
|
});
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
catch (IOException) { }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void Write(string channel, string value)
|
public static void Write(string channel, string value)
|
||||||
{
|
{
|
||||||
ChannelInfo info;
|
var writer = Channel(channel).Writer;
|
||||||
if (!Channels.TryGetValue(channel, out info))
|
if (writer == null)
|
||||||
throw new Exception("Tried logging to non-existent channel " + channel);
|
|
||||||
|
|
||||||
if (info.Writer == null)
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
info.Writer.WriteLine(value);
|
writer.WriteLine(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void Write(string channel, string format, params object[] args)
|
public static void Write(string channel, string format, params object[] args)
|
||||||
{
|
{
|
||||||
ChannelInfo info;
|
var writer = Channel(channel).Writer;
|
||||||
if (!Channels.TryGetValue(channel, out info))
|
if (writer == null)
|
||||||
throw new Exception("Tried logging to non-existent channel " + channel);
|
|
||||||
|
|
||||||
if (info.Writer == null)
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
info.Writer.WriteLine(format, args);
|
writer.WriteLine(format, args);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user