diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs b/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs index 1156bbb3de..db35a2ffc1 100644 --- a/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs +++ b/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs @@ -245,6 +245,19 @@ namespace OpenSim.Region.ClientStack.LindenUDP Watchdog.StartThread(IncomingPacketHandler, "Incoming Packets (" + m_scene.RegionInfo.RegionName + ")", ThreadPriority.Normal, false); Watchdog.StartThread(OutgoingPacketHandler, "Outgoing Packets (" + m_scene.RegionInfo.RegionName + ")", ThreadPriority.Normal, false); m_elapsedMSSinceLastStatReport = Environment.TickCount; + System.Timers.Timer packet_type_timer = new System.Timers.Timer(60000); + packet_type_timer.Elapsed +=new System.Timers.ElapsedEventHandler(packet_type_timer_Elapsed); + packet_type_timer.AutoReset = true; + packet_type_timer.Start(); + } + + void packet_type_timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e) + { + for (int i = 0; i < 9; ++i) + { + int val = Interlocked.Exchange(ref OutgoingPacket.CatCounts[i], 0); + m_log.WarnFormat("OutgoingPacket type {0} count = {1}", i, val); + } } public new void Stop() diff --git a/OpenSim/Region/ClientStack/LindenUDP/OutgoingPacket.cs b/OpenSim/Region/ClientStack/LindenUDP/OutgoingPacket.cs index 1a1a1cb4e3..732f2b4b61 100644 --- a/OpenSim/Region/ClientStack/LindenUDP/OutgoingPacket.cs +++ b/OpenSim/Region/ClientStack/LindenUDP/OutgoingPacket.cs @@ -28,6 +28,7 @@ using System; using OpenSim.Framework; using OpenMetaverse; +using System.Threading; namespace OpenSim.Region.ClientStack.LindenUDP { @@ -53,6 +54,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP /// Category this packet belongs to public ThrottleOutPacketType Category; + public static int[] CatCounts = new int[9]; + /// /// Default constructor /// @@ -65,6 +68,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP Client = client; Buffer = buffer; Category = category; + int type = (int)category; + if (category == ThrottleOutPacketType.Unknown) + type = 8; + Interlocked.Increment(ref OutgoingPacket.CatCounts[type]); } } } diff --git a/OpenSim/Region/CoreModules/RegionSync/RegionSyncModule/PhysEngineToSceneConnector.cs b/OpenSim/Region/CoreModules/RegionSync/RegionSyncModule/PhysEngineToSceneConnector.cs index 543d17a055..6153bdca1f 100644 --- a/OpenSim/Region/CoreModules/RegionSync/RegionSyncModule/PhysEngineToSceneConnector.cs +++ b/OpenSim/Region/CoreModules/RegionSync/RegionSyncModule/PhysEngineToSceneConnector.cs @@ -64,10 +64,6 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule // The client connection to the RegionSyncServer private TcpClient m_client = new TcpClient(); - - //KittyL: Comment out m_statsTimer for now, will figure out whether we need it for PhysEngine later - //private System.Timers.Timer m_statsTimer = new System.Timers.Timer(30000); - // The queue of incoming messages which need handling //private Queue m_inQ = new Queue(); @@ -105,11 +101,10 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule m_addrString = addr; m_port = port; m_debugWithViewer = debugWithViewer; - //m_statsTimer.Elapsed += new System.Timers.ElapsedEventHandler(StatsTimerElapsed); m_sysConfig = sysConfig; - SceneToPhysEngineSyncServer.logEnabled = m_sysConfig.GetBoolean("LogEnabled", false); - SceneToPhysEngineSyncServer.logDir = m_sysConfig.GetString("LogDir", "."); + SceneToPhysEngineSyncServer.logEnabled = m_sysConfig.GetBoolean("PhysLogEnabled", false); + SceneToPhysEngineSyncServer.logDir = m_sysConfig.GetString("PhysLogDir", "."); //assume we are connecting to the whole scene as one big quark m_subscribedQuarks = new QuarkSubsriptionInfo(0, 0, (int)Constants.RegionSize, (int)Constants.RegionSize); @@ -534,5 +529,29 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule #endregion Handlers for events/updates from Scene + public string StatisticIdentifier() + { + return "PhysEngineToSceneConnector"; + } + + public string StatisticLine(bool clearFlag) + { + string ret = ""; + /* + lock (stats) + { + ret = String.Format("{0},{1},{2},{3},{4},{5}", + msgsIn, msgsOut, bytesIn, bytesOut + ); + if (clearFlag) + msgsIn = msgsOut = bytesIn = bytesOut = 0; + } + */ + return ret; + } + public string StatisticTitle() + { + return "msgsIn,msgsOut,bytesIn,bytesOut"; + } } } diff --git a/OpenSim/Region/CoreModules/RegionSync/RegionSyncModule/SceneToPhysEngineConnector.cs b/OpenSim/Region/CoreModules/RegionSync/RegionSyncModule/SceneToPhysEngineConnector.cs index c2e0c0cf8f..399b35a11d 100644 --- a/OpenSim/Region/CoreModules/RegionSync/RegionSyncModule/SceneToPhysEngineConnector.cs +++ b/OpenSim/Region/CoreModules/RegionSync/RegionSyncModule/SceneToPhysEngineConnector.cs @@ -27,7 +27,7 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule // The SceneToPhysEngineConnector acts as a thread on the RegionSyncServer to handle incoming // messages from PhysEngineToSceneConnectors that run on Physics Engines. It connects the // authoratative Scene with remote script engines. - public class SceneToPhysEngineConnector + public class SceneToPhysEngineConnector : ISyncStatistics { #region SceneToPhysEngineConnector members @@ -38,9 +38,6 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule private long bytesIn; private long bytesOut; private long pollBlocks; - private int lastTotalCount; - private int lastLocalCount; - private int lastRemoteCount; private int msgCount = 0; @@ -49,7 +46,7 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule // Set the addr and port for TcpListener private IPAddress m_addr; private Int32 m_port; - private int m_connection_number; + private static int m_connection_number = 0; private Scene m_scene; object m_syncRoot = new object(); @@ -93,32 +90,33 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule get { return m_connection_number; } } - public string GetStats() + public string StatisticIdentifier() { - string ret; - //lock (m_syncRoot) - // syncedAvCount = m_syncedAvatars.Count; + return "SceneToPhysEngineConnector" + ConnectionNum.ToString(); + } + + public string StatisticLine(bool clearFlag) + { + string ret = ""; lock (stats) { double secondsSinceLastStats = DateTime.Now.Subtract(lastStatTime).TotalSeconds; lastStatTime = DateTime.Now; - // ret = String.Format("[{0,4}/{1,4}], [{2,4}/{3,4}], [{4,4}/{5,4}], [{6,4} ({7,4})], [{8,8} ({9,8:00.00})], [{10,4} ({11,4})], [{12,8} ({13,8:00.00})], [{14,8} ({15,4}]", - ret = String.Format("[{0,4}/{1,4}], [{2,6}/{3,6}], [{4,4}/{5,4}], [{6,6} ({7,6})], [{8,4} ({9,4})]", - //lastTotalCount, totalAvCount, // TOTAL AVATARS - //lastLocalCount, syncedAvCount, // LOCAL TO THIS CLIENT VIEW - //lastRemoteCount, totalAvCount - syncedAvCount, // REMOTE (SHOULD = TOTAL - LOCAL) - msgsIn, (int)(msgsIn / secondsSinceLastStats), - bytesIn, 8 * (bytesIn / secondsSinceLastStats / 1000000), // IN - msgsOut, (int)(msgsOut / secondsSinceLastStats), - bytesOut, 8 * (bytesOut / secondsSinceLastStats / 1000000), // OUT - pollBlocks, (int)(pollBlocks / secondsSinceLastStats)); // NUMBER OF TIMES WE BLOCKED WRITING TO SOCKET - - msgsIn = msgsOut = bytesIn = bytesOut = pollBlocks = 0; + ret = String.Format("{0},{1},{2},{3},{4}", + msgsIn, msgsOut, bytesIn, bytesOut, pollBlocks + ); + if (clearFlag) + msgsIn = msgsOut = bytesIn = bytesOut = pollBlocks = 0; } return ret; } + public string StatisticTitle() + { + return "msgsIn,msgsOut,bytesIn,bytesOut,pollBlocks"; + } + // Check if the client is connected public bool Connected { get { return m_tcpclient.Connected; } } @@ -163,6 +161,8 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule //m_log.WarnFormat("{0} Started thread: {1}", LogHeader, m_receive_loop.Name); m_receive_loop.Start(); + SyncStatisticCollector.Register(this); + //tell the remote script engine about the locX, locY of this authoritative scene // SendSceneLoc(); m_log.DebugFormat("{0}: SceneToPhysEngineConnector initialized", LogHeader); diff --git a/OpenSim/Region/CoreModules/RegionSync/RegionSyncModule/SceneToPhysEngineSyncServer.cs b/OpenSim/Region/CoreModules/RegionSync/RegionSyncModule/SceneToPhysEngineSyncServer.cs index a4cbb96c81..a4e34b5166 100644 --- a/OpenSim/Region/CoreModules/RegionSync/RegionSyncModule/SceneToPhysEngineSyncServer.cs +++ b/OpenSim/Region/CoreModules/RegionSync/RegionSyncModule/SceneToPhysEngineSyncServer.cs @@ -174,7 +174,7 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule m_log.Warn(LogHeader + " Synchronized"); foreach (SceneToPhysEngineConnector pec in m_physEngineConnectors) { - m_log.Warn(pec.GetStats()); + m_log.Warn(pec.StatisticLine(true)); } } } @@ -681,7 +681,7 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule #region Message Logging public static bool logInput = false; public static bool logOutput = true; - public static bool logEnabled = true; + public static bool logEnabled = false; private class PhysMsgLogger { public DateTime startTime; diff --git a/OpenSim/Region/CoreModules/RegionSync/RegionSyncModule/SymmetricSync/RegionSyncModule.cs b/OpenSim/Region/CoreModules/RegionSync/RegionSyncModule/SymmetricSync/RegionSyncModule.cs index b5bd8aa659..5ee27bff5f 100644 --- a/OpenSim/Region/CoreModules/RegionSync/RegionSyncModule/SymmetricSync/RegionSyncModule.cs +++ b/OpenSim/Region/CoreModules/RegionSync/RegionSyncModule/SymmetricSync/RegionSyncModule.cs @@ -31,7 +31,7 @@ using OpenMetaverse.StructuredData; namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule { [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "AttachmentsModule")] - public class RegionSyncModule : INonSharedRegionModule, IRegionSyncModule, ICommandableModule + public class RegionSyncModule : INonSharedRegionModule, IRegionSyncModule, ICommandableModule, ISyncStatistics //public class RegionSyncModule : IRegionModule, IRegionSyncModule, ICommandableModule { #region INonSharedRegionModule @@ -73,6 +73,13 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule m_log.Warn("[REGION SYNC MODULE] Initialised for actor "+ m_actorID); //The ActorType configuration will be read in and process by an ActorSyncModule, not here. + + // parameters for statistic logging + SyncStatisticCollector.LogEnabled = m_sysConfig.GetBoolean("SyncLogEnabled", false); + SyncStatisticCollector.LogDirectory = m_sysConfig.GetString("SyncLogDirectory", "."); + SyncStatisticCollector.LogInterval = m_sysConfig.GetInt("SyncLogInterval", 5000); + SyncStatisticCollector.LogMaxFileTimeMin = m_sysConfig.GetInt("SyncLogMaxFileTimeMin", 5); + SyncStatisticCollector.LogFileHeader = m_sysConfig.GetString("SyncLogFileHeader", "sync-"); } //Called after Initialise() @@ -122,6 +129,9 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule //Start symmetric synchronization initialization automatically //SyncStart(null); + + // connect to statistics system + SyncStatisticCollector.Register(this); } @@ -748,6 +758,7 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule sog.UpdateTaintedBucketSyncInfo(bucketName, timeStamp); //this update the timestamp and clear the taint info of the bucket string sogxml = SceneObjectSerializer.ToXml2Format(sog); SymmetricSyncMessage syncMsg = new SymmetricSyncMessage(SymmetricSyncMessage.MsgType.UpdatedObject, sogxml); + lock (m_stats) m_statSOGBucketOut++; SendObjectUpdateToRelevantSyncConnectors(sog, syncMsg); //clear the taints @@ -807,6 +818,7 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule SymmetricSyncMessage syncMsg = new SymmetricSyncMessage(SymmetricSyncMessage.MsgType.UpdatedBucketProperties, OSDParser.SerializeJsonString(data)); //m_log.DebugFormat("{0}: PhysBucketSender for {1}, pos={2}", LogHeader, updatedPart.UUID.ToString(), pa.Position.ToString()); + lock (m_stats) m_statPhysBucketOut++; SendObjectUpdateToRelevantSyncConnectors(updatedPart, syncMsg); //clear the taints @@ -1261,16 +1273,19 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule m_scene.EventManager.TriggerOnSymmetricSyncStop(); } } - - - } private void SyncStatus(Object[] args) { - //TO BE IMPLEMENTED - m_log.Warn("[REGION SYNC MODULE]: SyncStatus() TO BE IMPLEMENTED !!!"); - + int connectorCount = 0; + m_log.Warn(LogHeader + ": " + this.StatisticTitle()); + m_log.Warn(LogHeader + ": " + this.StatisticLine(true)); + ForEachSyncConnector(delegate(SyncConnector connector) + { + if (connectorCount++ == 0) + m_log.WarnFormat("[REGION SYNC MODULE]: Description: {0}", connector.StatisticTitle()); + m_log.WarnFormat("{0}: {1}: {2}", "[REGION SYNC MODULE}", connector.Description, connector.StatisticLine(true)); + }); } private void SyncStateReport(Object[] args) @@ -1516,6 +1531,7 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule /// ActorID of the sender public void HandleIncomingMessage(SymmetricSyncMessage msg, string senderActorID) { + lock (m_stats) m_statMsgsIn++; //Added senderActorID, so that we don't have to include actorID in sync messages -- TODO switch (msg.Type) { @@ -1647,6 +1663,7 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule { string sogxml = Encoding.ASCII.GetString(msg.Data, 0, msg.Length); SceneObjectGroup sog = SceneObjectSerializer.FromXml2Format(sogxml); + lock (m_stats) m_statSOGBucketIn++; //SYNC DEBUG /* @@ -1698,6 +1715,8 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule return; } + lock (m_stats) m_statPhysBucketIn++; + UUID partUUID = data["UUID"].AsUUID(); string bucketName = data["Bucket"].AsString(); @@ -1936,6 +1955,7 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule return; } + lock (m_stats) m_statEventIn++; string init_actorID = data["actorID"].AsString(); ulong evSeqNum = data["seqNum"].AsULong(); @@ -2563,6 +2583,7 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule SymmetricSyncMessage rsm = new SymmetricSyncMessage(msgType, OSDParser.SerializeJsonString(data)); //send to actors who are interested in the event + lock (m_stats) m_statEventOut++; SendSceneEventToRelevantSyncConnectors(m_actorID, rsm); } @@ -2584,6 +2605,50 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule #endregion //RegionSyncModule members and functions + #region ISyncStatistics + private object m_stats = new object(); + private int m_statMsgsIn = 0; + private int m_statMsgsOut = 0; + private int m_statSOGBucketIn = 0; + private int m_statSOGBucketOut = 0; + private int m_statPhysBucketIn = 0; + private int m_statPhysBucketOut = 0; + private int m_statEventIn = 0; + private int m_statEventOut = 0; + public string StatisticIdentifier() + { + // RegionSyncModule(actor/region) + return "RegionSyncModule" + "(" + ActorID + "/" + m_scene.RegionInfo.RegionName + ")"; + } + + public string StatisticLine(bool clearFlag) + { + string statLine = ""; + lock (m_stats) + { + statLine = String.Format("{0},{1},{2},{3},{4},{5},{6},{7}", + m_statMsgsIn, m_statMsgsOut, + m_statSOGBucketIn, m_statSOGBucketOut, + m_statPhysBucketIn, m_statPhysBucketOut, + m_statEventIn, m_statEventOut + ); + if (clearFlag) + { + m_statMsgsIn = m_statMsgsOut = 0; + m_statSOGBucketIn = m_statSOGBucketOut = 0; + m_statPhysBucketIn = m_statPhysBucketOut = 0; + m_statEventIn = m_statEventOut = 0; + } + } + return statLine; + } + + public string StatisticTitle() + { + return "MsgsIn,MsgsOut,SOGIn,SOGOut,PhysIn,PhysOut,EventIn,EventOut"; + } + #endregion ISyncStatistics + } public class RegionSyncListenerInfo diff --git a/OpenSim/Region/CoreModules/RegionSync/RegionSyncModule/SymmetricSync/ScriptEngineSyncModule.cs b/OpenSim/Region/CoreModules/RegionSync/RegionSyncModule/SymmetricSync/ScriptEngineSyncModule.cs index e10292d5ec..30cda59a49 100755 --- a/OpenSim/Region/CoreModules/RegionSync/RegionSyncModule/SymmetricSync/ScriptEngineSyncModule.cs +++ b/OpenSim/Region/CoreModules/RegionSync/RegionSyncModule/SymmetricSync/ScriptEngineSyncModule.cs @@ -172,7 +172,7 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule { if (entity is SceneObjectGroup) { - m_log.Warn(LogHeader + ": start script for obj " + entity.UUID); + m_log.Debug(LogHeader + ": start script for obj " + entity.UUID); SceneObjectGroup sog = (SceneObjectGroup)entity; sog.CreateScriptInstances(0, false, m_scene.DefaultScriptEngine, 0); sog.ResumeScripts(); diff --git a/OpenSim/Region/CoreModules/RegionSync/RegionSyncModule/SymmetricSync/SyncConnector.cs b/OpenSim/Region/CoreModules/RegionSync/RegionSyncModule/SymmetricSync/SyncConnector.cs index 93a5dab3c8..2ae9608991 100755 --- a/OpenSim/Region/CoreModules/RegionSync/RegionSyncModule/SymmetricSync/SyncConnector.cs +++ b/OpenSim/Region/CoreModules/RegionSync/RegionSyncModule/SymmetricSync/SyncConnector.cs @@ -14,7 +14,7 @@ using OpenMetaverse; namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule { // For implementations, a lot was copied from RegionSyncClientView, especially the SendLoop/ReceiveLoop. - public class SyncConnector + public class SyncConnector : ISyncStatistics { private TcpClient m_tcpConnection = null; private RegionSyncListenerInfo m_remoteListenerInfo = null; @@ -33,13 +33,14 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule private long msgsOut=0; private long bytesIn=0; private long bytesOut=0; - private int msgCount = 0; + private DateTime lastStatTime; // A queue for outgoing traffic. private BlockingUpdateQueue m_outQ = new BlockingUpdateQueue(); private RegionSyncModule m_regionSyncModule = null; - private int m_connectorNum; + // unique connector number across all regions + private static int m_connectorNum = 0; public int ConnectorNum { get { return m_connectorNum; } @@ -69,8 +70,9 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule get { if (m_syncOtherSideRegionName == null) - return String.Format("SyncConnector #{0}", m_connectorNum); - return String.Format("SyncConnector #{0} (Actor {2}, Region {1:10})", m_connectorNum, m_syncOtherSideRegionName, m_syncOtherSideActorID); + return String.Format("SyncConnector{0}", m_connectorNum); + return String.Format("SyncConnector{0}({2}/{1:10})", + m_connectorNum, m_syncOtherSideRegionName, m_syncOtherSideActorID); } } @@ -84,6 +86,8 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule m_tcpConnection = tcpclient; m_connectorNum = connectorNum; m_regionSyncModule = syncModule; + lastStatTime = DateTime.Now; + SyncStatisticCollector.Register(this); m_log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); } @@ -97,6 +101,8 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule m_remoteListenerInfo = listenerInfo; m_connectorNum = connectorNum; m_regionSyncModule = syncModule; + lastStatTime = DateTime.Now; + SyncStatisticCollector.Register(this); m_log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); } @@ -261,7 +267,8 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule private void HandleMessage(SymmetricSyncMessage msg) { - msgCount++; + msgsIn++; + bytesIn += msg.Data.Length; switch (msg.Type) { case SymmetricSyncMessage.MsgType.RegionName: @@ -294,5 +301,32 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule //Later on, we may deliver messages to different modules, say sync message to RegionSyncModule and event message to ActorSyncModule. m_regionSyncModule.HandleIncomingMessage(msg, m_syncOtherSideActorID); } + + public string StatisticIdentifier() + { + return this.Description; + } + + public string StatisticLine(bool clearFlag) + { + string statLine = ""; + lock (stats) + { + double secondsSinceLastStats = DateTime.Now.Subtract(lastStatTime).TotalSeconds; + lastStatTime = DateTime.Now; + statLine = String.Format("{0},{1},{2},{3},{4},{5},{6}", + msgsIn, msgsOut, bytesIn, bytesOut, m_outQ.Count, + 8 * (bytesIn / secondsSinceLastStats / 1000000), + 8 * (bytesOut / secondsSinceLastStats / 1000000) ); + if (clearFlag) + msgsIn = msgsOut = bytesIn = bytesOut = 0; + } + return statLine; + } + + public string StatisticTitle() + { + return "msgsIn,msgsOut,bytesIn,bytesOut,queueSize,Mbps In,Mbps Out"; + } } } \ No newline at end of file diff --git a/OpenSim/Region/CoreModules/RegionSync/RegionSyncModule/SymmetricSync/SyncStatisticCollector.cs b/OpenSim/Region/CoreModules/RegionSync/RegionSyncModule/SymmetricSync/SyncStatisticCollector.cs new file mode 100755 index 0000000000..18fba4906c --- /dev/null +++ b/OpenSim/Region/CoreModules/RegionSync/RegionSyncModule/SymmetricSync/SyncStatisticCollector.cs @@ -0,0 +1,162 @@ +/* Copyright 2011 (c) Intel Corporation + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * The name of the copyright holder may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +using System; +using System.Collections.Generic; +using System.IO; +using System.Text; +using System.Timers; + +namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule +{ + public interface ISyncStatistics + { + // return an identifier for this statistics source + string StatisticIdentifier(); + // a line of comma separated values + string StatisticLine(bool clearFlag); + // a line of comma separated field descriptions (describes what StatisticLine returns) + string StatisticTitle(); + } + + public class SyncStatisticCollector + { + public static bool LogEnabled = false; + public static string LogDirectory = "."; + public static int LogInterval = 5000; + public static int LogMaxFileTimeMin = 5; // 5 minutes + public static string LogFileHeader = "stats-"; + + private static List s_staters = new List(); + private static object s_statersLock = new object(); + private static Timer s_timer = null; + + static SyncStatisticCollector() + { + } + + public SyncStatisticCollector() + { + } + + /// + /// Any implementor of ISyncStatistics will call Register to put themselves in + /// the list of routines to collect statistics from. This will run periodically + /// and suck statistics from the registered routines. + /// + /// + public static void Register(ISyncStatistics stat) + { + if (!LogEnabled) return; + lock (SyncStatisticCollector.s_statersLock) + { + // set up logging timer + if (SyncStatisticCollector.s_timer == null) + { + SyncStatisticCollector.s_timer = new Timer(); + SyncStatisticCollector.s_timer.Interval = LogInterval; + SyncStatisticCollector.s_timer.Enabled = true; + SyncStatisticCollector.s_timer.Elapsed += Tick; + + } + SyncStatisticCollector.s_staters.Add(stat); + } + return; + } + + public static void Close() + { + lock (SyncStatisticCollector.s_statersLock) + { + SyncStatisticCollector.LogEnabled = false; + if (SyncStatisticCollector.s_timer != null) + { + SyncStatisticCollector.s_timer.Enabled = false; + SyncStatisticCollector.s_timer.Dispose(); + SyncStatisticCollector.s_timer = null; + } + if (SyncStatisticCollector.LogFile != null) + { + SyncStatisticCollector.LogFile.Close(); + SyncStatisticCollector.LogFile.Dispose(); + SyncStatisticCollector.LogFile = null; + } + } + } + + + private static void Tick(object sender, EventArgs e) + { + if (!LogEnabled) return; + lock (SyncStatisticCollector.s_statersLock) + { + foreach (ISyncStatistics iss in s_staters) + { + LogWriter(iss.StatisticIdentifier() + "," + iss.StatisticLine(true)); + } + } + return; + } + + private static DateTime LogStartTime; + private static System.IO.TextWriter LogFile = null; + private static void LogWriter(string line) + { + try + { + DateTime now = DateTime.Now; + if (LogFile == null || (now > (LogStartTime + new TimeSpan(0, LogMaxFileTimeMin, 0)))) + { + if (LogFile != null) + { + LogFile.Close(); + LogFile.Dispose(); + LogFile = null; + } + + // First log file or time has expired, start writing to a new log file + LogStartTime = now; + string path = (LogDirectory.Length > 0 ? LogDirectory + + System.IO.Path.DirectorySeparatorChar.ToString() : "") + + String.Format("{0}{1}.log", LogFileHeader, now.ToString("yyyyMMddHHmmss")); + LogFile = new StreamWriter(File.Open(path, FileMode.Append, FileAccess.Write)); + } + if (LogFile != null) + { + StringBuilder buff = new StringBuilder(); + // buff.Append(now.ToString("yyyyMMddHHmmssfff")); + buff.Append(now.ToString("yyyyMMddHHmmss")); + buff.Append(","); + buff.Append(line); + buff.Append("\r\n"); + LogFile.Write(buff.ToString()); + } + } + catch (Exception e) + { + // m_log.ErrorFormat("{0}: FAILURE WRITING TO LOGFILE: {1}", LogHeader, e); + LogEnabled = false; + } + return; + } + } +} diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs index 14bd92880c..6d618588ad 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs @@ -2795,7 +2795,8 @@ namespace OpenSim.Region.Framework.Scenes m_parentGroup.AbsolutePosition = newpos; return; } - //m_log.DebugFormat("[PHYSICS]: TerseUpdate: UUID={0}, newpos={1}", PhysActor.UUID.ToString(), newpos.ToString()); + + // m_log.DebugFormat("[PHYSICS]: TerseUpdate: UUID={0}, newpos={1}", PhysActor.UUID.ToString(), newpos.ToString()); //m_parentGroup.RootPart.m_groupPosition = newpos; } //ScheduleTerseUpdate(); @@ -5549,8 +5550,6 @@ namespace OpenSim.Region.Framework.Scenes //m_log.Debug("Received Physics Bucket updates for " + localPart.Name + ". GroupPosition: " + data["GroupPosition"].AsVector3().ToString() // + ", Position = " + data["Position"].AsVector3().ToString()); - //m_log.DebugFormat("{0}: PhysicsBucketUpdateProcessor. pos={1}", "[SCENE OBJECT PART]", data["Position"].AsVector3().ToString()); - lock (m_bucketUpdateLocks[bucketName]) { localPart.GroupPosition = data["GroupPosition"].AsVector3(); @@ -5655,6 +5654,7 @@ namespace OpenSim.Region.Framework.Scenes { bucketSynInfo.TaintBucketLocally(); } + // m_log.DebugFormat("{0}: TaintBucketSyncInfo: FullUpdate", "[SCENE OBJECT PART]"); } else { @@ -5664,6 +5664,8 @@ namespace OpenSim.Region.Framework.Scenes // m_log.Debug(this.Name + ": " + property.ToString() + " just changed. Tainted " + bucketName); + // m_log.DebugFormat("{0}: TaintBucketSyncInfo: tainting bucket {1} for {2}", + // "[SCENE OBJECT PART]", bucketName, property.ToString()); } } }