some cleanup.. remove some stats that only some do look at once on a lifetime
parent
8e3a50212c
commit
d9a300fa8e
|
@ -36,14 +36,8 @@ namespace OpenSim.Framework
|
||||||
public readonly DateTime StartedTime = DateTime.Now;
|
public readonly DateTime StartedTime = DateTime.Now;
|
||||||
public AgentCircuitData agentcircuit = null;
|
public AgentCircuitData agentcircuit = null;
|
||||||
|
|
||||||
public Dictionary<uint, byte[]> needAck;
|
|
||||||
|
|
||||||
public List<byte[]> out_packets = new List<byte[]>();
|
|
||||||
public Dictionary<uint, uint> pendingAcks = new Dictionary<uint,uint>();
|
|
||||||
public EndPoint proxyEP;
|
public EndPoint proxyEP;
|
||||||
|
|
||||||
public uint sequence;
|
|
||||||
public byte[] usecircuit;
|
|
||||||
public EndPoint userEP;
|
public EndPoint userEP;
|
||||||
|
|
||||||
public int resendThrottle;
|
public int resendThrottle;
|
||||||
|
@ -59,9 +53,5 @@ namespace OpenSim.Framework
|
||||||
public int targetThrottle;
|
public int targetThrottle;
|
||||||
|
|
||||||
public int maxThrottle;
|
public int maxThrottle;
|
||||||
|
|
||||||
public Dictionary<string, int> SyncRequests = new Dictionary<string,int>();
|
|
||||||
public Dictionary<string, int> AsyncRequests = new Dictionary<string,int>();
|
|
||||||
public Dictionary<string, int> GenericRequests = new Dictionary<string,int>();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -705,29 +705,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
/// </param>
|
/// </param>
|
||||||
/// <returns>true if the handler was added. This is currently always the case.</returns>
|
/// <returns>true if the handler was added. This is currently always the case.</returns>
|
||||||
public bool AddLocalPacketHandler(PacketType packetType, PacketMethod handler, bool doAsync)
|
public bool AddLocalPacketHandler(PacketType packetType, PacketMethod handler, bool doAsync)
|
||||||
{
|
|
||||||
return AddLocalPacketHandler(packetType, handler, doAsync, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Add a handler for the given packet type.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="packetType"></param>
|
|
||||||
/// <param name="handler"></param>
|
|
||||||
/// <param name="doAsync">
|
|
||||||
/// If true, when the packet is received handle it on a different thread. Whether this is given direct to
|
|
||||||
/// a threadpool thread or placed in a queue depends on the inEngine parameter.
|
|
||||||
/// </param>
|
|
||||||
/// <param name="inEngine">
|
|
||||||
/// If async is false then this parameter is ignored.
|
|
||||||
/// If async is true and inEngine is false, then the packet is sent directly to a
|
|
||||||
/// threadpool thread.
|
|
||||||
/// If async is true and inEngine is true, then the packet is sent to the IncomingPacketAsyncHandlingEngine.
|
|
||||||
/// This may result in slower handling but reduces the risk of overloading the simulator when there are many
|
|
||||||
/// simultaneous async requests.
|
|
||||||
/// </param>
|
|
||||||
/// <returns>true if the handler was added. This is currently always the case.</returns>
|
|
||||||
public bool AddLocalPacketHandler(PacketType packetType, PacketMethod handler, bool doAsync, bool inEngine)
|
|
||||||
{
|
{
|
||||||
bool result = false;
|
bool result = false;
|
||||||
lock (m_packetHandlers)
|
lock (m_packetHandlers)
|
||||||
|
@ -735,7 +712,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
if (!m_packetHandlers.ContainsKey(packetType))
|
if (!m_packetHandlers.ContainsKey(packetType))
|
||||||
{
|
{
|
||||||
m_packetHandlers.Add(
|
m_packetHandlers.Add(
|
||||||
packetType, new PacketProcessor() { method = handler, Async = doAsync, InEngine = inEngine });
|
packetType, new PacketProcessor() { method = handler, Async = doAsync});
|
||||||
result = true;
|
result = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -770,31 +747,16 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
PacketProcessor pprocessor;
|
PacketProcessor pprocessor;
|
||||||
if (m_packetHandlers.TryGetValue(packet.Type, out pprocessor))
|
if (m_packetHandlers.TryGetValue(packet.Type, out pprocessor))
|
||||||
{
|
{
|
||||||
ClientInfo cinfo = UDPClient.GetClientInfo();
|
|
||||||
|
|
||||||
//there is a local handler for this packet type
|
//there is a local handler for this packet type
|
||||||
if (pprocessor.Async)
|
if (pprocessor.Async)
|
||||||
{
|
{
|
||||||
if (!cinfo.AsyncRequests.ContainsKey(packet.Type.ToString()))
|
|
||||||
cinfo.AsyncRequests[packet.Type.ToString()] = 0;
|
|
||||||
cinfo.AsyncRequests[packet.Type.ToString()]++;
|
|
||||||
|
|
||||||
object obj = new AsyncPacketProcess(this, pprocessor.method, packet);
|
object obj = new AsyncPacketProcess(this, pprocessor.method, packet);
|
||||||
/*
|
|
||||||
if (pprocessor.InEngine)
|
|
||||||
m_udpServer.IpahEngine.QueueJob(packet.Type.ToString(), () => ProcessSpecificPacketAsync(obj));
|
|
||||||
else
|
|
||||||
Util.FireAndForget(ProcessSpecificPacketAsync, obj, packet.Type.ToString());
|
|
||||||
*/
|
|
||||||
m_asyncPacketProcess.QueueJob(packet.Type.ToString(), () => ProcessSpecificPacketAsync(obj));
|
m_asyncPacketProcess.QueueJob(packet.Type.ToString(), () => ProcessSpecificPacketAsync(obj));
|
||||||
result = true;
|
result = true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (!cinfo.SyncRequests.ContainsKey(packet.Type.ToString()))
|
|
||||||
cinfo.SyncRequests[packet.Type.ToString()] = 0;
|
|
||||||
cinfo.SyncRequests[packet.Type.ToString()]++;
|
|
||||||
|
|
||||||
result = pprocessor.method(this, packet);
|
result = pprocessor.method(this, packet);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -809,11 +771,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
}
|
}
|
||||||
if (found)
|
if (found)
|
||||||
{
|
{
|
||||||
ClientInfo cinfo = UDPClient.GetClientInfo();
|
|
||||||
if (!cinfo.GenericRequests.ContainsKey(packet.Type.ToString()))
|
|
||||||
cinfo.GenericRequests[packet.Type.ToString()] = 0;
|
|
||||||
cinfo.GenericRequests[packet.Type.ToString()]++;
|
|
||||||
|
|
||||||
result = method(this, packet);
|
result = method(this, packet);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5995,10 +5952,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
AddLocalPacketHandler(PacketType.ParcelBuy, HandleParcelBuyRequest, false);
|
AddLocalPacketHandler(PacketType.ParcelBuy, HandleParcelBuyRequest, false);
|
||||||
AddLocalPacketHandler(PacketType.UUIDGroupNameRequest, HandleUUIDGroupNameRequest);
|
AddLocalPacketHandler(PacketType.UUIDGroupNameRequest, HandleUUIDGroupNameRequest);
|
||||||
AddLocalPacketHandler(PacketType.ObjectGroup, HandleObjectGroupRequest);
|
AddLocalPacketHandler(PacketType.ObjectGroup, HandleObjectGroupRequest);
|
||||||
AddLocalPacketHandler(PacketType.GenericMessage, HandleGenericMessage, true, true);
|
AddLocalPacketHandler(PacketType.GenericMessage, HandleGenericMessage);
|
||||||
AddLocalPacketHandler(PacketType.AvatarPropertiesRequest, HandleAvatarPropertiesRequest, true, true);
|
AddLocalPacketHandler(PacketType.AvatarPropertiesRequest, HandleAvatarPropertiesRequest);
|
||||||
AddLocalPacketHandler(PacketType.ChatFromViewer, HandleChatFromViewer);
|
AddLocalPacketHandler(PacketType.ChatFromViewer, HandleChatFromViewer);
|
||||||
AddLocalPacketHandler(PacketType.AvatarPropertiesUpdate, HandlerAvatarPropertiesUpdate, true, true);
|
AddLocalPacketHandler(PacketType.AvatarPropertiesUpdate, HandlerAvatarPropertiesUpdate);
|
||||||
AddLocalPacketHandler(PacketType.ScriptDialogReply, HandlerScriptDialogReply);
|
AddLocalPacketHandler(PacketType.ScriptDialogReply, HandlerScriptDialogReply);
|
||||||
AddLocalPacketHandler(PacketType.ImprovedInstantMessage, HandlerImprovedInstantMessage);
|
AddLocalPacketHandler(PacketType.ImprovedInstantMessage, HandlerImprovedInstantMessage);
|
||||||
AddLocalPacketHandler(PacketType.AcceptFriendship, HandlerAcceptFriendship);
|
AddLocalPacketHandler(PacketType.AcceptFriendship, HandlerAcceptFriendship);
|
||||||
|
@ -6040,8 +5997,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
AddLocalPacketHandler(PacketType.ObjectExtraParams, HandleObjectExtraParams);
|
AddLocalPacketHandler(PacketType.ObjectExtraParams, HandleObjectExtraParams);
|
||||||
AddLocalPacketHandler(PacketType.ObjectDuplicate, HandleObjectDuplicate);
|
AddLocalPacketHandler(PacketType.ObjectDuplicate, HandleObjectDuplicate);
|
||||||
AddLocalPacketHandler(PacketType.RequestMultipleObjects, HandleRequestMultipleObjects);
|
AddLocalPacketHandler(PacketType.RequestMultipleObjects, HandleRequestMultipleObjects);
|
||||||
AddLocalPacketHandler(PacketType.ObjectSelect, HandleObjectSelect, true, true);
|
AddLocalPacketHandler(PacketType.ObjectSelect, HandleObjectSelect);
|
||||||
AddLocalPacketHandler(PacketType.ObjectDeselect, HandleObjectDeselect, true, true);
|
AddLocalPacketHandler(PacketType.ObjectDeselect, HandleObjectDeselect);
|
||||||
AddLocalPacketHandler(PacketType.ObjectPosition, HandleObjectPosition);
|
AddLocalPacketHandler(PacketType.ObjectPosition, HandleObjectPosition);
|
||||||
AddLocalPacketHandler(PacketType.ObjectScale, HandleObjectScale);
|
AddLocalPacketHandler(PacketType.ObjectScale, HandleObjectScale);
|
||||||
AddLocalPacketHandler(PacketType.ObjectRotation, HandleObjectRotation);
|
AddLocalPacketHandler(PacketType.ObjectRotation, HandleObjectRotation);
|
||||||
|
@ -6185,8 +6142,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
AddLocalPacketHandler(PacketType.PickDelete, HandlePickDelete);
|
AddLocalPacketHandler(PacketType.PickDelete, HandlePickDelete);
|
||||||
AddLocalPacketHandler(PacketType.PickGodDelete, HandlePickGodDelete);
|
AddLocalPacketHandler(PacketType.PickGodDelete, HandlePickGodDelete);
|
||||||
AddLocalPacketHandler(PacketType.PickInfoUpdate, HandlePickInfoUpdate);
|
AddLocalPacketHandler(PacketType.PickInfoUpdate, HandlePickInfoUpdate);
|
||||||
AddLocalPacketHandler(PacketType.AvatarNotesUpdate, HandleAvatarNotesUpdate, true, true);
|
AddLocalPacketHandler(PacketType.AvatarNotesUpdate, HandleAvatarNotesUpdate);
|
||||||
AddLocalPacketHandler(PacketType.AvatarInterestsUpdate, HandleAvatarInterestsUpdate, true, true);
|
AddLocalPacketHandler(PacketType.AvatarInterestsUpdate, HandleAvatarInterestsUpdate);
|
||||||
AddLocalPacketHandler(PacketType.GrantUserRights, HandleGrantUserRights);
|
AddLocalPacketHandler(PacketType.GrantUserRights, HandleGrantUserRights);
|
||||||
AddLocalPacketHandler(PacketType.PlacesQuery, HandlePlacesQuery);
|
AddLocalPacketHandler(PacketType.PlacesQuery, HandlePlacesQuery);
|
||||||
AddLocalPacketHandler(PacketType.UpdateMuteListEntry, HandleUpdateMuteListEntry);
|
AddLocalPacketHandler(PacketType.UpdateMuteListEntry, HandleUpdateMuteListEntry);
|
||||||
|
@ -13436,7 +13393,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
SendAssetNotFound(req);
|
SendAssetNotFound(req);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (transferRequest.TransferInfo.SourceType == (int)SourceType.Asset)
|
if (transferRequest.TransferInfo.SourceType == (int)SourceType.Asset)
|
||||||
|
@ -13513,11 +13469,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool Async { get; set; }
|
public bool Async { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// If async is true, should this packet be handled in the async engine or given directly to a threadpool
|
|
||||||
/// thread?
|
|
||||||
/// </summary>
|
|
||||||
public bool InEngine { get; set; }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public class AsyncPacketProcess
|
public class AsyncPacketProcess
|
||||||
|
|
|
@ -247,11 +247,10 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
|
||||||
{
|
{
|
||||||
FriendInfo[] friends = GetFriendsFromCache(principalID);
|
FriendInfo[] friends = GetFriendsFromCache(principalID);
|
||||||
FriendInfo finfo = GetFriend(friends, friendID);
|
FriendInfo finfo = GetFriend(friends, friendID);
|
||||||
if (finfo != null)
|
if (finfo != null && finfo.TheirFlags != -1)
|
||||||
{
|
{
|
||||||
return finfo.TheirFlags;
|
return finfo.TheirFlags;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -756,7 +755,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
|
||||||
if (friend == null)
|
if (friend == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if((friend.TheirFlags & (int)FriendRights.CanSeeOnMap) == 0)
|
if(friend.TheirFlags == -1 || (friend.TheirFlags & (int)FriendRights.CanSeeOnMap) == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
Scene hunterScene = (Scene)remoteClient.Scene;
|
Scene hunterScene = (Scene)remoteClient.Scene;
|
||||||
|
|
|
@ -214,7 +214,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
|
||||||
FriendInfo[] friends = GetFriendsFromCache(client.AgentId);
|
FriendInfo[] friends = GetFriendsFromCache(client.AgentId);
|
||||||
foreach (FriendInfo f in friends)
|
foreach (FriendInfo f in friends)
|
||||||
{
|
{
|
||||||
client.SendChangeUserRights(new UUID(f.Friend), client.AgentId, f.TheirFlags);
|
int rights = f.TheirFlags;
|
||||||
|
if(rights != -1 )
|
||||||
|
client.SendChangeUserRights(new UUID(f.Friend), client.AgentId, rights);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -124,15 +124,6 @@ namespace OpenSim.Region.OptionalModules.UDP.Linden
|
||||||
"Without the 'full' option, only root agents are shown."
|
"Without the 'full' option, only root agents are shown."
|
||||||
+ " With the 'full' option child agents are also shown.",
|
+ " With the 'full' option child agents are also shown.",
|
||||||
(mod, cmd) => MainConsole.Instance.Output(GetThrottlesReport(cmd)));
|
(mod, cmd) => MainConsole.Instance.Output(GetThrottlesReport(cmd)));
|
||||||
|
|
||||||
scene.AddCommand(
|
|
||||||
"Comms", this, "show client stats",
|
|
||||||
"show client stats [first_name last_name]",
|
|
||||||
"Show client request stats",
|
|
||||||
"Without the 'first_name last_name' option, all clients are shown."
|
|
||||||
+ " With the 'first_name last_name' option only a specific client is shown.",
|
|
||||||
(mod, cmd) => MainConsole.Instance.Output(HandleClientStatsReport(cmd)));
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void RemoveRegion(Scene scene)
|
public void RemoveRegion(Scene scene)
|
||||||
|
@ -540,107 +531,6 @@ namespace OpenSim.Region.OptionalModules.UDP.Linden
|
||||||
return report.ToString();
|
return report.ToString();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Show client stats data
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="showParams"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
protected string HandleClientStatsReport(string[] showParams)
|
|
||||||
{
|
|
||||||
// NOTE: This writes to m_log on purpose. We want to store this information
|
|
||||||
// in case we need to analyze it later.
|
|
||||||
//
|
|
||||||
if (showParams.Length <= 4)
|
|
||||||
{
|
|
||||||
m_log.InfoFormat("[INFO]: {0,-12} {1,-20} {2,-6} {3,-11} {4,-11} {5,-16}", "Region", "Name", "Root", "Time", "Reqs/min", "AgentUpdates");
|
|
||||||
foreach (Scene scene in m_scenes.Values)
|
|
||||||
{
|
|
||||||
scene.ForEachClient(
|
|
||||||
delegate(IClientAPI client)
|
|
||||||
{
|
|
||||||
if (client is LLClientView)
|
|
||||||
{
|
|
||||||
LLClientView llClient = client as LLClientView;
|
|
||||||
ClientInfo cinfo = llClient.UDPClient.GetClientInfo();
|
|
||||||
int avg_reqs = cinfo.AsyncRequests.Values.Sum() + cinfo.GenericRequests.Values.Sum() + cinfo.SyncRequests.Values.Sum();
|
|
||||||
avg_reqs = avg_reqs / ((DateTime.Now - cinfo.StartedTime).Minutes + 1);
|
|
||||||
|
|
||||||
string childAgentStatus;
|
|
||||||
|
|
||||||
if (llClient.SceneAgent != null)
|
|
||||||
childAgentStatus = llClient.SceneAgent.IsChildAgent ? "N" : "Y";
|
|
||||||
else
|
|
||||||
childAgentStatus = "Off!";
|
|
||||||
|
|
||||||
m_log.InfoFormat("[INFO]: {0,-12} {1,-20} {2,-6} {3,-11} {4,-11} {5,-16}",
|
|
||||||
scene.RegionInfo.RegionName, llClient.Name,
|
|
||||||
childAgentStatus,
|
|
||||||
(DateTime.Now - cinfo.StartedTime).Minutes,
|
|
||||||
avg_reqs,
|
|
||||||
string.Format(
|
|
||||||
"{0} ({1:0.00}%)",
|
|
||||||
llClient.TotalAgentUpdates,
|
|
||||||
cinfo.SyncRequests.ContainsKey("AgentUpdate")
|
|
||||||
? (float)cinfo.SyncRequests["AgentUpdate"] / llClient.TotalAgentUpdates * 100
|
|
||||||
: 0));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
return string.Empty;
|
|
||||||
}
|
|
||||||
|
|
||||||
string fname = "", lname = "";
|
|
||||||
|
|
||||||
if (showParams.Length > 3)
|
|
||||||
fname = showParams[3];
|
|
||||||
if (showParams.Length > 4)
|
|
||||||
lname = showParams[4];
|
|
||||||
|
|
||||||
foreach (Scene scene in m_scenes.Values)
|
|
||||||
{
|
|
||||||
scene.ForEachClient(
|
|
||||||
delegate(IClientAPI client)
|
|
||||||
{
|
|
||||||
if (client is LLClientView)
|
|
||||||
{
|
|
||||||
LLClientView llClient = client as LLClientView;
|
|
||||||
|
|
||||||
if (llClient.Name == fname + " " + lname)
|
|
||||||
{
|
|
||||||
|
|
||||||
ClientInfo cinfo = llClient.GetClientInfo();
|
|
||||||
AgentCircuitData aCircuit = scene.AuthenticateHandler.GetAgentCircuitData(llClient.CircuitCode);
|
|
||||||
if (aCircuit == null) // create a dummy one
|
|
||||||
aCircuit = new AgentCircuitData();
|
|
||||||
|
|
||||||
if (!llClient.SceneAgent.IsChildAgent)
|
|
||||||
m_log.InfoFormat("[INFO]: {0} # {1} # {2}", llClient.Name, Util.GetViewerName(aCircuit), aCircuit.Id0);
|
|
||||||
|
|
||||||
int avg_reqs = cinfo.AsyncRequests.Values.Sum() + cinfo.GenericRequests.Values.Sum() + cinfo.SyncRequests.Values.Sum();
|
|
||||||
avg_reqs = avg_reqs / ((DateTime.Now - cinfo.StartedTime).Minutes + 1);
|
|
||||||
|
|
||||||
m_log.InfoFormat("[INFO]:");
|
|
||||||
m_log.InfoFormat("[INFO]: {0} # {1} # Time: {2}min # Avg Reqs/min: {3}", scene.RegionInfo.RegionName,
|
|
||||||
(llClient.SceneAgent.IsChildAgent ? "Child" : "Root"), (DateTime.Now - cinfo.StartedTime).Minutes, avg_reqs);
|
|
||||||
|
|
||||||
Dictionary<string, int> sortedDict = (from entry in cinfo.AsyncRequests orderby entry.Value descending select entry)
|
|
||||||
.ToDictionary(pair => pair.Key, pair => pair.Value);
|
|
||||||
PrintRequests("TOP ASYNC", sortedDict, cinfo.AsyncRequests.Values.Sum());
|
|
||||||
|
|
||||||
sortedDict = (from entry in cinfo.SyncRequests orderby entry.Value descending select entry)
|
|
||||||
.ToDictionary(pair => pair.Key, pair => pair.Value);
|
|
||||||
PrintRequests("TOP SYNC", sortedDict, cinfo.SyncRequests.Values.Sum());
|
|
||||||
|
|
||||||
sortedDict = (from entry in cinfo.GenericRequests orderby entry.Value descending select entry)
|
|
||||||
.ToDictionary(pair => pair.Key, pair => pair.Value);
|
|
||||||
PrintRequests("TOP GENERIC", sortedDict, cinfo.GenericRequests.Values.Sum());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
return string.Empty;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void PrintRequests(string type, Dictionary<string, int> sortedDict, int sum)
|
private void PrintRequests(string type, Dictionary<string, int> sortedDict, int sum)
|
||||||
{
|
{
|
||||||
m_log.InfoFormat("[INFO]:");
|
m_log.InfoFormat("[INFO]:");
|
||||||
|
|
Loading…
Reference in New Issue