diff options
Diffstat (limited to 'OpenSim/Region/UserStatistics/WebStatsModule.cs')
-rw-r--r-- | OpenSim/Region/UserStatistics/WebStatsModule.cs | 1206 |
1 files changed, 0 insertions, 1206 deletions
diff --git a/OpenSim/Region/UserStatistics/WebStatsModule.cs b/OpenSim/Region/UserStatistics/WebStatsModule.cs deleted file mode 100644 index 8ccb751..0000000 --- a/OpenSim/Region/UserStatistics/WebStatsModule.cs +++ /dev/null | |||
@@ -1,1206 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (c) Contributors, http://opensimulator.org/ | ||
3 | * See CONTRIBUTORS.TXT for a full list of copyright holders. | ||
4 | * | ||
5 | * Redistribution and use in source and binary forms, with or without | ||
6 | * modification, are permitted provided that the following conditions are met: | ||
7 | * * Redistributions of source code must retain the above copyright | ||
8 | * notice, this list of conditions and the following disclaimer. | ||
9 | * * Redistributions in binary form must reproduce the above copyright | ||
10 | * notice, this list of conditions and the following disclaimer in the | ||
11 | * documentation and/or other materials provided with the distribution. | ||
12 | * * Neither the name of the OpenSimulator Project nor the | ||
13 | * names of its contributors may be used to endorse or promote products | ||
14 | * derived from this software without specific prior written permission. | ||
15 | * | ||
16 | * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY | ||
17 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | ||
18 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | ||
19 | * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY | ||
20 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | ||
21 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | ||
22 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | ||
23 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
24 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | ||
25 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
26 | */ | ||
27 | |||
28 | using System; | ||
29 | using System.Collections; | ||
30 | using System.Collections.Generic; | ||
31 | using System.IO; | ||
32 | using System.Net; // to be used for REST-->Grid shortly | ||
33 | using System.Reflection; | ||
34 | using System.Text; | ||
35 | using System.Threading; | ||
36 | using log4net; | ||
37 | using Nini.Config; | ||
38 | using OpenMetaverse; | ||
39 | using OpenMetaverse.StructuredData; | ||
40 | using OpenSim.Framework; | ||
41 | using OpenSim.Framework.Servers; | ||
42 | using OpenSim.Framework.Servers.HttpServer; | ||
43 | using OpenSim.Region.Framework.Interfaces; | ||
44 | using OpenSim.Region.Framework.Scenes; | ||
45 | using Mono.Data.SqliteClient; | ||
46 | using Mono.Addins; | ||
47 | |||
48 | using Caps = OpenSim.Framework.Capabilities.Caps; | ||
49 | |||
50 | using OSD = OpenMetaverse.StructuredData.OSD; | ||
51 | using OSDMap = OpenMetaverse.StructuredData.OSDMap; | ||
52 | |||
53 | [assembly: Addin("WebStats", OpenSim.VersionInfo.VersionNumber)] | ||
54 | [assembly: AddinDependency("OpenSim.Region.Framework", OpenSim.VersionInfo.VersionNumber)] | ||
55 | |||
56 | namespace OpenSim.Region.UserStatistics | ||
57 | { | ||
58 | [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "WebStatsModule")] | ||
59 | public class WebStatsModule : ISharedRegionModule | ||
60 | { | ||
61 | private static readonly ILog m_log = | ||
62 | LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); | ||
63 | |||
64 | private static SqliteConnection dbConn; | ||
65 | |||
66 | /// <summary> | ||
67 | /// User statistics sessions keyed by agent ID | ||
68 | /// </summary> | ||
69 | private Dictionary<UUID, UserSession> m_sessions = new Dictionary<UUID, UserSession>(); | ||
70 | |||
71 | private List<Scene> m_scenes = new List<Scene>(); | ||
72 | private Dictionary<string, IStatsController> reports = new Dictionary<string, IStatsController>(); | ||
73 | private Dictionary<UUID, USimStatsData> m_simstatsCounters = new Dictionary<UUID, USimStatsData>(); | ||
74 | private const int updateStatsMod = 6; | ||
75 | private int updateLogMod = 1; | ||
76 | private volatile int updateLogCounter = 0; | ||
77 | private volatile int concurrencyCounter = 0; | ||
78 | private bool enabled = false; | ||
79 | private string m_loglines = String.Empty; | ||
80 | private volatile int lastHit = 12000; | ||
81 | |||
82 | #region ISharedRegionModule | ||
83 | |||
84 | public virtual void Initialise(IConfigSource config) | ||
85 | { | ||
86 | IConfig cnfg = config.Configs["WebStats"]; | ||
87 | |||
88 | if (cnfg != null) | ||
89 | enabled = cnfg.GetBoolean("enabled", false); | ||
90 | } | ||
91 | |||
92 | public virtual void PostInitialise() | ||
93 | { | ||
94 | if (!enabled) | ||
95 | return; | ||
96 | |||
97 | if (Util.IsWindows()) | ||
98 | Util.LoadArchSpecificWindowsDll("sqlite3.dll"); | ||
99 | |||
100 | //IConfig startupConfig = config.Configs["Startup"]; | ||
101 | |||
102 | dbConn = new SqliteConnection("URI=file:LocalUserStatistics.db,version=3"); | ||
103 | dbConn.Open(); | ||
104 | CreateTables(dbConn); | ||
105 | |||
106 | Prototype_distributor protodep = new Prototype_distributor(); | ||
107 | Updater_distributor updatedep = new Updater_distributor(); | ||
108 | ActiveConnectionsAJAX ajConnections = new ActiveConnectionsAJAX(); | ||
109 | SimStatsAJAX ajSimStats = new SimStatsAJAX(); | ||
110 | LogLinesAJAX ajLogLines = new LogLinesAJAX(); | ||
111 | Default_Report defaultReport = new Default_Report(); | ||
112 | Clients_report clientReport = new Clients_report(); | ||
113 | Sessions_Report sessionsReport = new Sessions_Report(); | ||
114 | |||
115 | reports.Add("prototype.js", protodep); | ||
116 | reports.Add("updater.js", updatedep); | ||
117 | reports.Add("activeconnectionsajax.html", ajConnections); | ||
118 | reports.Add("simstatsajax.html", ajSimStats); | ||
119 | reports.Add("activelogajax.html", ajLogLines); | ||
120 | reports.Add("default.report", defaultReport); | ||
121 | reports.Add("clients.report", clientReport); | ||
122 | reports.Add("sessions.report", sessionsReport); | ||
123 | |||
124 | reports.Add("sim.css", new Prototype_distributor("sim.css")); | ||
125 | reports.Add("sim.html", new Prototype_distributor("sim.html")); | ||
126 | reports.Add("jquery.js", new Prototype_distributor("jquery.js")); | ||
127 | |||
128 | //// | ||
129 | // Add Your own Reports here (Do Not Modify Lines here Devs!) | ||
130 | //// | ||
131 | |||
132 | //// | ||
133 | // End Own reports section | ||
134 | //// | ||
135 | |||
136 | MainServer.Instance.AddHTTPHandler("/SStats/", HandleStatsRequest); | ||
137 | MainServer.Instance.AddHTTPHandler("/CAPS/VS/", HandleUnknownCAPSRequest); | ||
138 | } | ||
139 | |||
140 | public virtual void AddRegion(Scene scene) | ||
141 | { | ||
142 | if (!enabled) | ||
143 | return; | ||
144 | |||
145 | lock (m_scenes) | ||
146 | { | ||
147 | m_scenes.Add(scene); | ||
148 | updateLogMod = m_scenes.Count * 2; | ||
149 | |||
150 | m_simstatsCounters.Add(scene.RegionInfo.RegionID, new USimStatsData(scene.RegionInfo.RegionID)); | ||
151 | |||
152 | scene.EventManager.OnRegisterCaps += OnRegisterCaps; | ||
153 | scene.EventManager.OnDeregisterCaps += OnDeRegisterCaps; | ||
154 | scene.EventManager.OnClientClosed += OnClientClosed; | ||
155 | scene.EventManager.OnMakeRootAgent += OnMakeRootAgent; | ||
156 | scene.StatsReporter.OnSendStatsResult += ReceiveClassicSimStatsPacket; | ||
157 | } | ||
158 | } | ||
159 | |||
160 | public void RegionLoaded(Scene scene) | ||
161 | { | ||
162 | } | ||
163 | |||
164 | public void RemoveRegion(Scene scene) | ||
165 | { | ||
166 | if (!enabled) | ||
167 | return; | ||
168 | |||
169 | lock (m_scenes) | ||
170 | { | ||
171 | m_scenes.Remove(scene); | ||
172 | updateLogMod = m_scenes.Count * 2; | ||
173 | m_simstatsCounters.Remove(scene.RegionInfo.RegionID); | ||
174 | } | ||
175 | } | ||
176 | |||
177 | public virtual void Close() | ||
178 | { | ||
179 | if (!enabled) | ||
180 | return; | ||
181 | |||
182 | dbConn.Close(); | ||
183 | dbConn.Dispose(); | ||
184 | m_sessions.Clear(); | ||
185 | m_scenes.Clear(); | ||
186 | reports.Clear(); | ||
187 | m_simstatsCounters.Clear(); | ||
188 | } | ||
189 | |||
190 | public virtual string Name | ||
191 | { | ||
192 | get { return "ViewerStatsModule"; } | ||
193 | } | ||
194 | |||
195 | public Type ReplaceableInterface | ||
196 | { | ||
197 | get { return null; } | ||
198 | } | ||
199 | |||
200 | #endregion | ||
201 | |||
202 | private void ReceiveClassicSimStatsPacket(SimStats stats) | ||
203 | { | ||
204 | if (!enabled) | ||
205 | return; | ||
206 | |||
207 | try | ||
208 | { | ||
209 | // Ignore the update if there's a report running right now | ||
210 | // ignore the update if there hasn't been a hit in 30 seconds. | ||
211 | if (concurrencyCounter > 0 || System.Environment.TickCount - lastHit > 30000) | ||
212 | return; | ||
213 | |||
214 | // We will conduct this under lock so that fields such as updateLogCounter do not potentially get | ||
215 | // confused if a scene is removed. | ||
216 | // XXX: Possibly the scope of this lock could be reduced though it's not critical. | ||
217 | lock (m_scenes) | ||
218 | { | ||
219 | if (updateLogMod != 0 && updateLogCounter++ % updateLogMod == 0) | ||
220 | { | ||
221 | m_loglines = readLogLines(10); | ||
222 | |||
223 | if (updateLogCounter > 10000) | ||
224 | updateLogCounter = 1; | ||
225 | } | ||
226 | |||
227 | USimStatsData ss = m_simstatsCounters[stats.RegionUUID]; | ||
228 | |||
229 | if ((++ss.StatsCounter % updateStatsMod) == 0) | ||
230 | { | ||
231 | ss.ConsumeSimStats(stats); | ||
232 | } | ||
233 | } | ||
234 | } | ||
235 | catch (KeyNotFoundException) | ||
236 | { | ||
237 | } | ||
238 | } | ||
239 | |||
240 | private Hashtable HandleUnknownCAPSRequest(Hashtable request) | ||
241 | { | ||
242 | //string regpath = request["uri"].ToString(); | ||
243 | int response_code = 200; | ||
244 | string contenttype = "text/html"; | ||
245 | UpdateUserStats(ParseViewerStats(request["body"].ToString(), UUID.Zero), dbConn); | ||
246 | Hashtable responsedata = new Hashtable(); | ||
247 | |||
248 | responsedata["int_response_code"] = response_code; | ||
249 | responsedata["content_type"] = contenttype; | ||
250 | responsedata["keepalive"] = false; | ||
251 | responsedata["str_response_string"] = string.Empty; | ||
252 | return responsedata; | ||
253 | } | ||
254 | |||
255 | private Hashtable HandleStatsRequest(Hashtable request) | ||
256 | { | ||
257 | lastHit = System.Environment.TickCount; | ||
258 | Hashtable responsedata = new Hashtable(); | ||
259 | string regpath = request["uri"].ToString(); | ||
260 | int response_code = 404; | ||
261 | string contenttype = "text/html"; | ||
262 | bool jsonFormatOutput = false; | ||
263 | |||
264 | string strOut = string.Empty; | ||
265 | |||
266 | // The request patch should be "/SStats/reportName" where 'reportName' | ||
267 | // is one of the names added to the 'reports' hashmap. | ||
268 | regpath = regpath.Remove(0, 8); | ||
269 | if (regpath.Length == 0) regpath = "default.report"; | ||
270 | if (reports.ContainsKey(regpath)) | ||
271 | { | ||
272 | IStatsController rep = reports[regpath]; | ||
273 | Hashtable repParams = new Hashtable(); | ||
274 | |||
275 | if (request.ContainsKey("json")) | ||
276 | jsonFormatOutput = true; | ||
277 | |||
278 | if (request.ContainsKey("requestvars")) | ||
279 | repParams["RequestVars"] = request["requestvars"]; | ||
280 | else | ||
281 | repParams["RequestVars"] = new Hashtable(); | ||
282 | |||
283 | if (request.ContainsKey("querystringkeys")) | ||
284 | repParams["QueryStringKeys"] = request["querystringkeys"]; | ||
285 | else | ||
286 | repParams["QueryStringKeys"] = new string[0]; | ||
287 | |||
288 | |||
289 | repParams["DatabaseConnection"] = dbConn; | ||
290 | repParams["Scenes"] = m_scenes; | ||
291 | repParams["SimStats"] = m_simstatsCounters; | ||
292 | repParams["LogLines"] = m_loglines; | ||
293 | repParams["Reports"] = reports; | ||
294 | |||
295 | concurrencyCounter++; | ||
296 | |||
297 | if (jsonFormatOutput) | ||
298 | { | ||
299 | strOut = rep.RenderJson(rep.ProcessModel(repParams)); | ||
300 | contenttype = "text/json"; | ||
301 | } | ||
302 | else | ||
303 | { | ||
304 | strOut = rep.RenderView(rep.ProcessModel(repParams)); | ||
305 | } | ||
306 | |||
307 | if (regpath.EndsWith("js")) | ||
308 | { | ||
309 | contenttype = "text/javascript"; | ||
310 | } | ||
311 | |||
312 | if (regpath.EndsWith("css")) | ||
313 | { | ||
314 | contenttype = "text/css"; | ||
315 | } | ||
316 | |||
317 | concurrencyCounter--; | ||
318 | |||
319 | response_code = 200; | ||
320 | } | ||
321 | else | ||
322 | { | ||
323 | strOut = MainServer.Instance.GetHTTP404(""); | ||
324 | } | ||
325 | |||
326 | responsedata["int_response_code"] = response_code; | ||
327 | responsedata["content_type"] = contenttype; | ||
328 | responsedata["keepalive"] = false; | ||
329 | responsedata["str_response_string"] = strOut; | ||
330 | |||
331 | return responsedata; | ||
332 | } | ||
333 | |||
334 | private void CreateTables(SqliteConnection db) | ||
335 | { | ||
336 | using (SqliteCommand createcmd = new SqliteCommand(SQL_STATS_TABLE_CREATE, db)) | ||
337 | { | ||
338 | createcmd.ExecuteNonQuery(); | ||
339 | } | ||
340 | } | ||
341 | |||
342 | private void OnRegisterCaps(UUID agentID, Caps caps) | ||
343 | { | ||
344 | // m_log.DebugFormat("[WEB STATS MODULE]: OnRegisterCaps: agentID {0} caps {1}", agentID, caps); | ||
345 | |||
346 | string capsPath = "/CAPS/VS/" + UUID.Random(); | ||
347 | caps.RegisterHandler( | ||
348 | "ViewerStats", | ||
349 | new RestStreamHandler( | ||
350 | "POST", | ||
351 | capsPath, | ||
352 | (request, path, param, httpRequest, httpResponse) | ||
353 | => ViewerStatsReport(request, path, param, agentID, caps), | ||
354 | "ViewerStats", | ||
355 | agentID.ToString())); | ||
356 | } | ||
357 | |||
358 | private void OnDeRegisterCaps(UUID agentID, Caps caps) | ||
359 | { | ||
360 | } | ||
361 | |||
362 | protected virtual void AddEventHandlers() | ||
363 | { | ||
364 | lock (m_scenes) | ||
365 | { | ||
366 | updateLogMod = m_scenes.Count * 2; | ||
367 | foreach (Scene scene in m_scenes) | ||
368 | { | ||
369 | scene.EventManager.OnRegisterCaps += OnRegisterCaps; | ||
370 | scene.EventManager.OnDeregisterCaps += OnDeRegisterCaps; | ||
371 | scene.EventManager.OnClientClosed += OnClientClosed; | ||
372 | scene.EventManager.OnMakeRootAgent += OnMakeRootAgent; | ||
373 | } | ||
374 | } | ||
375 | } | ||
376 | |||
377 | private void OnMakeRootAgent(ScenePresence agent) | ||
378 | { | ||
379 | // m_log.DebugFormat( | ||
380 | // "[WEB STATS MODULE]: Looking for session {0} for {1} in {2}", | ||
381 | // agent.ControllingClient.SessionId, agent.Name, agent.Scene.Name); | ||
382 | |||
383 | lock (m_sessions) | ||
384 | { | ||
385 | UserSession uid; | ||
386 | |||
387 | if (!m_sessions.ContainsKey(agent.UUID)) | ||
388 | { | ||
389 | UserSessionData usd = UserSessionUtil.newUserSessionData(); | ||
390 | uid = new UserSession(); | ||
391 | uid.name_f = agent.Firstname; | ||
392 | uid.name_l = agent.Lastname; | ||
393 | uid.session_data = usd; | ||
394 | |||
395 | m_sessions.Add(agent.UUID, uid); | ||
396 | } | ||
397 | else | ||
398 | { | ||
399 | uid = m_sessions[agent.UUID]; | ||
400 | } | ||
401 | |||
402 | uid.region_id = agent.Scene.RegionInfo.RegionID; | ||
403 | uid.session_id = agent.ControllingClient.SessionId; | ||
404 | } | ||
405 | } | ||
406 | |||
407 | private void OnClientClosed(UUID agentID, Scene scene) | ||
408 | { | ||
409 | lock (m_sessions) | ||
410 | { | ||
411 | if (m_sessions.ContainsKey(agentID) && m_sessions[agentID].region_id == scene.RegionInfo.RegionID) | ||
412 | { | ||
413 | m_sessions.Remove(agentID); | ||
414 | } | ||
415 | } | ||
416 | } | ||
417 | |||
418 | private string readLogLines(int amount) | ||
419 | { | ||
420 | Encoding encoding = Encoding.ASCII; | ||
421 | int sizeOfChar = encoding.GetByteCount("\n"); | ||
422 | byte[] buffer = encoding.GetBytes("\n"); | ||
423 | string logfile = Util.logFile(); | ||
424 | FileStream fs = new FileStream(logfile, FileMode.Open, FileAccess.Read, FileShare.ReadWrite); | ||
425 | Int64 tokenCount = 0; | ||
426 | Int64 endPosition = fs.Length / sizeOfChar; | ||
427 | |||
428 | for (Int64 position = sizeOfChar; position < endPosition; position += sizeOfChar) | ||
429 | { | ||
430 | fs.Seek(-position, SeekOrigin.End); | ||
431 | fs.Read(buffer, 0, buffer.Length); | ||
432 | |||
433 | if (encoding.GetString(buffer) == "\n") | ||
434 | { | ||
435 | tokenCount++; | ||
436 | if (tokenCount == amount) | ||
437 | { | ||
438 | byte[] returnBuffer = new byte[fs.Length - fs.Position]; | ||
439 | fs.Read(returnBuffer, 0, returnBuffer.Length); | ||
440 | fs.Close(); | ||
441 | fs.Dispose(); | ||
442 | return encoding.GetString(returnBuffer); | ||
443 | } | ||
444 | } | ||
445 | } | ||
446 | |||
447 | // handle case where number of tokens in file is less than numberOfTokens | ||
448 | fs.Seek(0, SeekOrigin.Begin); | ||
449 | buffer = new byte[fs.Length]; | ||
450 | fs.Read(buffer, 0, buffer.Length); | ||
451 | fs.Close(); | ||
452 | fs.Dispose(); | ||
453 | return encoding.GetString(buffer); | ||
454 | } | ||
455 | |||
456 | /// <summary> | ||
457 | /// Callback for a viewerstats cap | ||
458 | /// </summary> | ||
459 | /// <param name="request"></param> | ||
460 | /// <param name="path"></param> | ||
461 | /// <param name="param"></param> | ||
462 | /// <param name="agentID"></param> | ||
463 | /// <param name="caps"></param> | ||
464 | /// <returns></returns> | ||
465 | private string ViewerStatsReport(string request, string path, string param, | ||
466 | UUID agentID, Caps caps) | ||
467 | { | ||
468 | // m_log.DebugFormat("[WEB STATS MODULE]: Received viewer starts report from {0}", agentID); | ||
469 | |||
470 | UpdateUserStats(ParseViewerStats(request, agentID), dbConn); | ||
471 | |||
472 | return String.Empty; | ||
473 | } | ||
474 | |||
475 | private UserSession ParseViewerStats(string request, UUID agentID) | ||
476 | { | ||
477 | UserSession uid = new UserSession(); | ||
478 | UserSessionData usd; | ||
479 | OSD message = OSDParser.DeserializeLLSDXml(request); | ||
480 | OSDMap mmap; | ||
481 | |||
482 | lock (m_sessions) | ||
483 | { | ||
484 | if (agentID != UUID.Zero) | ||
485 | { | ||
486 | if (!m_sessions.ContainsKey(agentID)) | ||
487 | { | ||
488 | m_log.WarnFormat("[WEB STATS MODULE]: no session for stat disclosure for agent {0}", agentID); | ||
489 | return new UserSession(); | ||
490 | } | ||
491 | |||
492 | uid = m_sessions[agentID]; | ||
493 | |||
494 | // m_log.DebugFormat("[WEB STATS MODULE]: Got session {0} for {1}", uid.session_id, agentID); | ||
495 | } | ||
496 | else | ||
497 | { | ||
498 | // parse through the beginning to locate the session | ||
499 | if (message.Type != OSDType.Map) | ||
500 | return new UserSession(); | ||
501 | |||
502 | mmap = (OSDMap)message; | ||
503 | { | ||
504 | UUID sessionID = mmap["session_id"].AsUUID(); | ||
505 | |||
506 | if (sessionID == UUID.Zero) | ||
507 | return new UserSession(); | ||
508 | |||
509 | |||
510 | // search through each session looking for the owner | ||
511 | foreach (UUID usersessionid in m_sessions.Keys) | ||
512 | { | ||
513 | // got it! | ||
514 | if (m_sessions[usersessionid].session_id == sessionID) | ||
515 | { | ||
516 | agentID = usersessionid; | ||
517 | uid = m_sessions[usersessionid]; | ||
518 | break; | ||
519 | } | ||
520 | |||
521 | } | ||
522 | |||
523 | // can't find a session | ||
524 | if (agentID == UUID.Zero) | ||
525 | { | ||
526 | return new UserSession(); | ||
527 | } | ||
528 | } | ||
529 | } | ||
530 | } | ||
531 | |||
532 | usd = uid.session_data; | ||
533 | |||
534 | if (message.Type != OSDType.Map) | ||
535 | return new UserSession(); | ||
536 | |||
537 | mmap = (OSDMap)message; | ||
538 | { | ||
539 | if (mmap["agent"].Type != OSDType.Map) | ||
540 | return new UserSession(); | ||
541 | OSDMap agent_map = (OSDMap)mmap["agent"]; | ||
542 | usd.agent_id = agentID; | ||
543 | usd.name_f = uid.name_f; | ||
544 | usd.name_l = uid.name_l; | ||
545 | usd.region_id = uid.region_id; | ||
546 | usd.a_language = agent_map["language"].AsString(); | ||
547 | usd.mem_use = (float)agent_map["mem_use"].AsReal(); | ||
548 | usd.meters_traveled = (float)agent_map["meters_traveled"].AsReal(); | ||
549 | usd.regions_visited = agent_map["regions_visited"].AsInteger(); | ||
550 | usd.run_time = (float)agent_map["run_time"].AsReal(); | ||
551 | usd.start_time = (float)agent_map["start_time"].AsReal(); | ||
552 | usd.client_version = agent_map["version"].AsString(); | ||
553 | |||
554 | UserSessionUtil.UpdateMultiItems(ref usd, agent_map["agents_in_view"].AsInteger(), | ||
555 | (float)agent_map["ping"].AsReal(), | ||
556 | (float)agent_map["sim_fps"].AsReal(), | ||
557 | (float)agent_map["fps"].AsReal()); | ||
558 | |||
559 | if (mmap["downloads"].Type != OSDType.Map) | ||
560 | return new UserSession(); | ||
561 | OSDMap downloads_map = (OSDMap)mmap["downloads"]; | ||
562 | usd.d_object_kb = (float)downloads_map["object_kbytes"].AsReal(); | ||
563 | usd.d_texture_kb = (float)downloads_map["texture_kbytes"].AsReal(); | ||
564 | usd.d_world_kb = (float)downloads_map["workd_kbytes"].AsReal(); | ||
565 | |||
566 | // m_log.DebugFormat("[WEB STATS MODULE]: mmap[\"session_id\"] = [{0}]", mmap["session_id"].AsUUID()); | ||
567 | |||
568 | usd.session_id = mmap["session_id"].AsUUID(); | ||
569 | |||
570 | if (mmap["system"].Type != OSDType.Map) | ||
571 | return new UserSession(); | ||
572 | OSDMap system_map = (OSDMap)mmap["system"]; | ||
573 | |||
574 | usd.s_cpu = system_map["cpu"].AsString(); | ||
575 | usd.s_gpu = system_map["gpu"].AsString(); | ||
576 | usd.s_os = system_map["os"].AsString(); | ||
577 | usd.s_ram = system_map["ram"].AsInteger(); | ||
578 | |||
579 | if (mmap["stats"].Type != OSDType.Map) | ||
580 | return new UserSession(); | ||
581 | |||
582 | OSDMap stats_map = (OSDMap)mmap["stats"]; | ||
583 | { | ||
584 | |||
585 | if (stats_map["failures"].Type != OSDType.Map) | ||
586 | return new UserSession(); | ||
587 | OSDMap stats_failures = (OSDMap)stats_map["failures"]; | ||
588 | usd.f_dropped = stats_failures["dropped"].AsInteger(); | ||
589 | usd.f_failed_resends = stats_failures["failed_resends"].AsInteger(); | ||
590 | usd.f_invalid = stats_failures["invalid"].AsInteger(); | ||
591 | usd.f_resent = stats_failures["resent"].AsInteger(); | ||
592 | usd.f_send_packet = stats_failures["send_packet"].AsInteger(); | ||
593 | |||
594 | if (stats_map["net"].Type != OSDType.Map) | ||
595 | return new UserSession(); | ||
596 | OSDMap stats_net = (OSDMap)stats_map["net"]; | ||
597 | { | ||
598 | if (stats_net["in"].Type != OSDType.Map) | ||
599 | return new UserSession(); | ||
600 | |||
601 | OSDMap net_in = (OSDMap)stats_net["in"]; | ||
602 | usd.n_in_kb = (float)net_in["kbytes"].AsReal(); | ||
603 | usd.n_in_pk = net_in["packets"].AsInteger(); | ||
604 | |||
605 | if (stats_net["out"].Type != OSDType.Map) | ||
606 | return new UserSession(); | ||
607 | OSDMap net_out = (OSDMap)stats_net["out"]; | ||
608 | |||
609 | usd.n_out_kb = (float)net_out["kbytes"].AsReal(); | ||
610 | usd.n_out_pk = net_out["packets"].AsInteger(); | ||
611 | } | ||
612 | } | ||
613 | } | ||
614 | |||
615 | uid.session_data = usd; | ||
616 | m_sessions[agentID] = uid; | ||
617 | |||
618 | // m_log.DebugFormat( | ||
619 | // "[WEB STATS MODULE]: Parse data for {0} {1}, session {2}", uid.name_f, uid.name_l, uid.session_id); | ||
620 | |||
621 | return uid; | ||
622 | } | ||
623 | |||
624 | private void UpdateUserStats(UserSession uid, SqliteConnection db) | ||
625 | { | ||
626 | // m_log.DebugFormat( | ||
627 | // "[WEB STATS MODULE]: Updating user stats for {0} {1}, session {2}", uid.name_f, uid.name_l, uid.session_id); | ||
628 | |||
629 | if (uid.session_id == UUID.Zero) | ||
630 | return; | ||
631 | |||
632 | lock (db) | ||
633 | { | ||
634 | using (SqliteCommand updatecmd = new SqliteCommand(SQL_STATS_TABLE_INSERT, db)) | ||
635 | { | ||
636 | updatecmd.Parameters.Add(new SqliteParameter(":session_id", uid.session_data.session_id.ToString())); | ||
637 | updatecmd.Parameters.Add(new SqliteParameter(":agent_id", uid.session_data.agent_id.ToString())); | ||
638 | updatecmd.Parameters.Add(new SqliteParameter(":region_id", uid.session_data.region_id.ToString())); | ||
639 | updatecmd.Parameters.Add(new SqliteParameter(":last_updated", (int) uid.session_data.last_updated)); | ||
640 | updatecmd.Parameters.Add(new SqliteParameter(":remote_ip", uid.session_data.remote_ip)); | ||
641 | updatecmd.Parameters.Add(new SqliteParameter(":name_f", uid.session_data.name_f)); | ||
642 | updatecmd.Parameters.Add(new SqliteParameter(":name_l", uid.session_data.name_l)); | ||
643 | updatecmd.Parameters.Add(new SqliteParameter(":avg_agents_in_view", uid.session_data.avg_agents_in_view)); | ||
644 | updatecmd.Parameters.Add(new SqliteParameter(":min_agents_in_view", | ||
645 | (int) uid.session_data.min_agents_in_view)); | ||
646 | updatecmd.Parameters.Add(new SqliteParameter(":max_agents_in_view", | ||
647 | (int) uid.session_data.max_agents_in_view)); | ||
648 | updatecmd.Parameters.Add(new SqliteParameter(":mode_agents_in_view", | ||
649 | (int) uid.session_data.mode_agents_in_view)); | ||
650 | updatecmd.Parameters.Add(new SqliteParameter(":avg_fps", uid.session_data.avg_fps)); | ||
651 | updatecmd.Parameters.Add(new SqliteParameter(":min_fps", uid.session_data.min_fps)); | ||
652 | updatecmd.Parameters.Add(new SqliteParameter(":max_fps", uid.session_data.max_fps)); | ||
653 | updatecmd.Parameters.Add(new SqliteParameter(":mode_fps", uid.session_data.mode_fps)); | ||
654 | updatecmd.Parameters.Add(new SqliteParameter(":a_language", uid.session_data.a_language)); | ||
655 | updatecmd.Parameters.Add(new SqliteParameter(":mem_use", uid.session_data.mem_use)); | ||
656 | updatecmd.Parameters.Add(new SqliteParameter(":meters_traveled", uid.session_data.meters_traveled)); | ||
657 | updatecmd.Parameters.Add(new SqliteParameter(":avg_ping", uid.session_data.avg_ping)); | ||
658 | updatecmd.Parameters.Add(new SqliteParameter(":min_ping", uid.session_data.min_ping)); | ||
659 | updatecmd.Parameters.Add(new SqliteParameter(":max_ping", uid.session_data.max_ping)); | ||
660 | updatecmd.Parameters.Add(new SqliteParameter(":mode_ping", uid.session_data.mode_ping)); | ||
661 | updatecmd.Parameters.Add(new SqliteParameter(":regions_visited", uid.session_data.regions_visited)); | ||
662 | updatecmd.Parameters.Add(new SqliteParameter(":run_time", uid.session_data.run_time)); | ||
663 | updatecmd.Parameters.Add(new SqliteParameter(":avg_sim_fps", uid.session_data.avg_sim_fps)); | ||
664 | updatecmd.Parameters.Add(new SqliteParameter(":min_sim_fps", uid.session_data.min_sim_fps)); | ||
665 | updatecmd.Parameters.Add(new SqliteParameter(":max_sim_fps", uid.session_data.max_sim_fps)); | ||
666 | updatecmd.Parameters.Add(new SqliteParameter(":mode_sim_fps", uid.session_data.mode_sim_fps)); | ||
667 | updatecmd.Parameters.Add(new SqliteParameter(":start_time", uid.session_data.start_time)); | ||
668 | updatecmd.Parameters.Add(new SqliteParameter(":client_version", uid.session_data.client_version)); | ||
669 | updatecmd.Parameters.Add(new SqliteParameter(":s_cpu", uid.session_data.s_cpu)); | ||
670 | updatecmd.Parameters.Add(new SqliteParameter(":s_gpu", uid.session_data.s_gpu)); | ||
671 | updatecmd.Parameters.Add(new SqliteParameter(":s_os", uid.session_data.s_os)); | ||
672 | updatecmd.Parameters.Add(new SqliteParameter(":s_ram", uid.session_data.s_ram)); | ||
673 | updatecmd.Parameters.Add(new SqliteParameter(":d_object_kb", uid.session_data.d_object_kb)); | ||
674 | updatecmd.Parameters.Add(new SqliteParameter(":d_texture_kb", uid.session_data.d_texture_kb)); | ||
675 | updatecmd.Parameters.Add(new SqliteParameter(":d_world_kb", uid.session_data.d_world_kb)); | ||
676 | updatecmd.Parameters.Add(new SqliteParameter(":n_in_kb", uid.session_data.n_in_kb)); | ||
677 | updatecmd.Parameters.Add(new SqliteParameter(":n_in_pk", uid.session_data.n_in_pk)); | ||
678 | updatecmd.Parameters.Add(new SqliteParameter(":n_out_kb", uid.session_data.n_out_kb)); | ||
679 | updatecmd.Parameters.Add(new SqliteParameter(":n_out_pk", uid.session_data.n_out_pk)); | ||
680 | updatecmd.Parameters.Add(new SqliteParameter(":f_dropped", uid.session_data.f_dropped)); | ||
681 | updatecmd.Parameters.Add(new SqliteParameter(":f_failed_resends", uid.session_data.f_failed_resends)); | ||
682 | updatecmd.Parameters.Add(new SqliteParameter(":f_invalid", uid.session_data.f_invalid)); | ||
683 | updatecmd.Parameters.Add(new SqliteParameter(":f_off_circuit", uid.session_data.f_off_circuit)); | ||
684 | updatecmd.Parameters.Add(new SqliteParameter(":f_resent", uid.session_data.f_resent)); | ||
685 | updatecmd.Parameters.Add(new SqliteParameter(":f_send_packet", uid.session_data.f_send_packet)); | ||
686 | |||
687 | // StringBuilder parameters = new StringBuilder(); | ||
688 | // SqliteParameterCollection spc = updatecmd.Parameters; | ||
689 | // foreach (SqliteParameter sp in spc) | ||
690 | // parameters.AppendFormat("{0}={1},", sp.ParameterName, sp.Value); | ||
691 | // | ||
692 | // m_log.DebugFormat("[WEB STATS MODULE]: Parameters {0}", parameters); | ||
693 | |||
694 | // m_log.DebugFormat("[WEB STATS MODULE]: Database stats update for {0}", uid.session_data.agent_id); | ||
695 | |||
696 | updatecmd.ExecuteNonQuery(); | ||
697 | } | ||
698 | } | ||
699 | } | ||
700 | |||
701 | #region SQL | ||
702 | private const string SQL_STATS_TABLE_CREATE = @"CREATE TABLE IF NOT EXISTS stats_session_data ( | ||
703 | session_id VARCHAR(36) NOT NULL PRIMARY KEY, | ||
704 | agent_id VARCHAR(36) NOT NULL DEFAULT '', | ||
705 | region_id VARCHAR(36) NOT NULL DEFAULT '', | ||
706 | last_updated INT NOT NULL DEFAULT '0', | ||
707 | remote_ip VARCHAR(16) NOT NULL DEFAULT '', | ||
708 | name_f VARCHAR(50) NOT NULL DEFAULT '', | ||
709 | name_l VARCHAR(50) NOT NULL DEFAULT '', | ||
710 | avg_agents_in_view FLOAT NOT NULL DEFAULT '0', | ||
711 | min_agents_in_view INT NOT NULL DEFAULT '0', | ||
712 | max_agents_in_view INT NOT NULL DEFAULT '0', | ||
713 | mode_agents_in_view INT NOT NULL DEFAULT '0', | ||
714 | avg_fps FLOAT NOT NULL DEFAULT '0', | ||
715 | min_fps FLOAT NOT NULL DEFAULT '0', | ||
716 | max_fps FLOAT NOT NULL DEFAULT '0', | ||
717 | mode_fps FLOAT NOT NULL DEFAULT '0', | ||
718 | a_language VARCHAR(25) NOT NULL DEFAULT '', | ||
719 | mem_use FLOAT NOT NULL DEFAULT '0', | ||
720 | meters_traveled FLOAT NOT NULL DEFAULT '0', | ||
721 | avg_ping FLOAT NOT NULL DEFAULT '0', | ||
722 | min_ping FLOAT NOT NULL DEFAULT '0', | ||
723 | max_ping FLOAT NOT NULL DEFAULT '0', | ||
724 | mode_ping FLOAT NOT NULL DEFAULT '0', | ||
725 | regions_visited INT NOT NULL DEFAULT '0', | ||
726 | run_time FLOAT NOT NULL DEFAULT '0', | ||
727 | avg_sim_fps FLOAT NOT NULL DEFAULT '0', | ||
728 | min_sim_fps FLOAT NOT NULL DEFAULT '0', | ||
729 | max_sim_fps FLOAT NOT NULL DEFAULT '0', | ||
730 | mode_sim_fps FLOAT NOT NULL DEFAULT '0', | ||
731 | start_time FLOAT NOT NULL DEFAULT '0', | ||
732 | client_version VARCHAR(255) NOT NULL DEFAULT '', | ||
733 | s_cpu VARCHAR(255) NOT NULL DEFAULT '', | ||
734 | s_gpu VARCHAR(255) NOT NULL DEFAULT '', | ||
735 | s_os VARCHAR(2255) NOT NULL DEFAULT '', | ||
736 | s_ram INT NOT NULL DEFAULT '0', | ||
737 | d_object_kb FLOAT NOT NULL DEFAULT '0', | ||
738 | d_texture_kb FLOAT NOT NULL DEFAULT '0', | ||
739 | d_world_kb FLOAT NOT NULL DEFAULT '0', | ||
740 | n_in_kb FLOAT NOT NULL DEFAULT '0', | ||
741 | n_in_pk INT NOT NULL DEFAULT '0', | ||
742 | n_out_kb FLOAT NOT NULL DEFAULT '0', | ||
743 | n_out_pk INT NOT NULL DEFAULT '0', | ||
744 | f_dropped INT NOT NULL DEFAULT '0', | ||
745 | f_failed_resends INT NOT NULL DEFAULT '0', | ||
746 | f_invalid INT NOT NULL DEFAULT '0', | ||
747 | f_off_circuit INT NOT NULL DEFAULT '0', | ||
748 | f_resent INT NOT NULL DEFAULT '0', | ||
749 | f_send_packet INT NOT NULL DEFAULT '0' | ||
750 | );"; | ||
751 | |||
752 | private const string SQL_STATS_TABLE_INSERT = @"INSERT OR REPLACE INTO stats_session_data ( | ||
753 | session_id, agent_id, region_id, last_updated, remote_ip, name_f, name_l, avg_agents_in_view, min_agents_in_view, max_agents_in_view, | ||
754 | mode_agents_in_view, avg_fps, min_fps, max_fps, mode_fps, a_language, mem_use, meters_traveled, avg_ping, min_ping, max_ping, mode_ping, | ||
755 | regions_visited, run_time, avg_sim_fps, min_sim_fps, max_sim_fps, mode_sim_fps, start_time, client_version, s_cpu, s_gpu, s_os, s_ram, | ||
756 | d_object_kb, d_texture_kb, d_world_kb, n_in_kb, n_in_pk, n_out_kb, n_out_pk, f_dropped, f_failed_resends, f_invalid, f_off_circuit, | ||
757 | f_resent, f_send_packet | ||
758 | ) | ||
759 | VALUES | ||
760 | ( | ||
761 | :session_id, :agent_id, :region_id, :last_updated, :remote_ip, :name_f, :name_l, :avg_agents_in_view, :min_agents_in_view, :max_agents_in_view, | ||
762 | :mode_agents_in_view, :avg_fps, :min_fps, :max_fps, :mode_fps, :a_language, :mem_use, :meters_traveled, :avg_ping, :min_ping, :max_ping, :mode_ping, | ||
763 | :regions_visited, :run_time, :avg_sim_fps, :min_sim_fps, :max_sim_fps, :mode_sim_fps, :start_time, :client_version, :s_cpu, :s_gpu, :s_os, :s_ram, | ||
764 | :d_object_kb, :d_texture_kb, :d_world_kb, :n_in_kb, :n_in_pk, :n_out_kb, :n_out_pk, :f_dropped, :f_failed_resends, :f_invalid, :f_off_circuit, | ||
765 | :f_resent, :f_send_packet | ||
766 | ) | ||
767 | "; | ||
768 | |||
769 | #endregion | ||
770 | |||
771 | } | ||
772 | |||
773 | public static class UserSessionUtil | ||
774 | { | ||
775 | public static UserSessionData newUserSessionData() | ||
776 | { | ||
777 | UserSessionData obj = ZeroSession(new UserSessionData()); | ||
778 | return obj; | ||
779 | } | ||
780 | |||
781 | public static void UpdateMultiItems(ref UserSessionData s, int agents_in_view, float ping, float sim_fps, float fps) | ||
782 | { | ||
783 | // don't insert zero values here or it'll skew the statistics. | ||
784 | if (agents_in_view == 0 && fps == 0 && sim_fps == 0 && ping == 0) | ||
785 | return; | ||
786 | s._agents_in_view.Add(agents_in_view); | ||
787 | s._fps.Add(fps); | ||
788 | s._sim_fps.Add(sim_fps); | ||
789 | s._ping.Add(ping); | ||
790 | |||
791 | int[] __agents_in_view = s._agents_in_view.ToArray(); | ||
792 | |||
793 | s.avg_agents_in_view = ArrayAvg_i(__agents_in_view); | ||
794 | s.min_agents_in_view = ArrayMin_i(__agents_in_view); | ||
795 | s.max_agents_in_view = ArrayMax_i(__agents_in_view); | ||
796 | s.mode_agents_in_view = ArrayMode_i(__agents_in_view); | ||
797 | |||
798 | float[] __fps = s._fps.ToArray(); | ||
799 | s.avg_fps = ArrayAvg_f(__fps); | ||
800 | s.min_fps = ArrayMin_f(__fps); | ||
801 | s.max_fps = ArrayMax_f(__fps); | ||
802 | s.mode_fps = ArrayMode_f(__fps); | ||
803 | |||
804 | float[] __sim_fps = s._sim_fps.ToArray(); | ||
805 | s.avg_sim_fps = ArrayAvg_f(__sim_fps); | ||
806 | s.min_sim_fps = ArrayMin_f(__sim_fps); | ||
807 | s.max_sim_fps = ArrayMax_f(__sim_fps); | ||
808 | s.mode_sim_fps = ArrayMode_f(__sim_fps); | ||
809 | |||
810 | float[] __ping = s._ping.ToArray(); | ||
811 | s.avg_ping = ArrayAvg_f(__ping); | ||
812 | s.min_ping = ArrayMin_f(__ping); | ||
813 | s.max_ping = ArrayMax_f(__ping); | ||
814 | s.mode_ping = ArrayMode_f(__ping); | ||
815 | } | ||
816 | |||
817 | #region Statistics | ||
818 | |||
819 | public static int ArrayMin_i(int[] arr) | ||
820 | { | ||
821 | int cnt = arr.Length; | ||
822 | if (cnt == 0) | ||
823 | return 0; | ||
824 | |||
825 | Array.Sort(arr); | ||
826 | return arr[0]; | ||
827 | } | ||
828 | |||
829 | public static int ArrayMax_i(int[] arr) | ||
830 | { | ||
831 | int cnt = arr.Length; | ||
832 | if (cnt == 0) | ||
833 | return 0; | ||
834 | |||
835 | Array.Sort(arr); | ||
836 | return arr[cnt-1]; | ||
837 | } | ||
838 | |||
839 | public static float ArrayMin_f(float[] arr) | ||
840 | { | ||
841 | int cnt = arr.Length; | ||
842 | if (cnt == 0) | ||
843 | return 0; | ||
844 | |||
845 | Array.Sort(arr); | ||
846 | return arr[0]; | ||
847 | } | ||
848 | |||
849 | public static float ArrayMax_f(float[] arr) | ||
850 | { | ||
851 | int cnt = arr.Length; | ||
852 | if (cnt == 0) | ||
853 | return 0; | ||
854 | |||
855 | Array.Sort(arr); | ||
856 | return arr[cnt - 1]; | ||
857 | } | ||
858 | |||
859 | public static float ArrayAvg_i(int[] arr) | ||
860 | { | ||
861 | int cnt = arr.Length; | ||
862 | |||
863 | if (cnt == 0) | ||
864 | return 0; | ||
865 | |||
866 | float result = arr[0]; | ||
867 | |||
868 | for (int i = 1; i < cnt; i++) | ||
869 | result += arr[i]; | ||
870 | |||
871 | return result / cnt; | ||
872 | } | ||
873 | |||
874 | public static float ArrayAvg_f(float[] arr) | ||
875 | { | ||
876 | int cnt = arr.Length; | ||
877 | |||
878 | if (cnt == 0) | ||
879 | return 0; | ||
880 | |||
881 | float result = arr[0]; | ||
882 | |||
883 | for (int i = 1; i < cnt; i++) | ||
884 | result += arr[i]; | ||
885 | |||
886 | return result / cnt; | ||
887 | } | ||
888 | |||
889 | public static float ArrayMode_f(float[] arr) | ||
890 | { | ||
891 | List<float> mode = new List<float>(); | ||
892 | |||
893 | float[] srtArr = new float[arr.Length]; | ||
894 | float[,] freq = new float[arr.Length, 2]; | ||
895 | Array.Copy(arr, srtArr, arr.Length); | ||
896 | Array.Sort(srtArr); | ||
897 | |||
898 | float tmp = srtArr[0]; | ||
899 | int index = 0; | ||
900 | int i = 0; | ||
901 | while (i < srtArr.Length) | ||
902 | { | ||
903 | freq[index, 0] = tmp; | ||
904 | |||
905 | while (tmp == srtArr[i]) | ||
906 | { | ||
907 | freq[index, 1]++; | ||
908 | i++; | ||
909 | |||
910 | if (i > srtArr.Length - 1) | ||
911 | break; | ||
912 | } | ||
913 | |||
914 | if (i < srtArr.Length) | ||
915 | { | ||
916 | tmp = srtArr[i]; | ||
917 | index++; | ||
918 | } | ||
919 | |||
920 | } | ||
921 | |||
922 | Array.Clear(srtArr, 0, srtArr.Length); | ||
923 | |||
924 | for (i = 0; i < srtArr.Length; i++) | ||
925 | srtArr[i] = freq[i, 1]; | ||
926 | |||
927 | Array.Sort(srtArr); | ||
928 | |||
929 | if ((srtArr[srtArr.Length - 1]) == 0 || (srtArr[srtArr.Length - 1]) == 1) | ||
930 | return 0; | ||
931 | |||
932 | float freqtest = (float)freq.Length / freq.Rank; | ||
933 | |||
934 | for (i = 0; i < freqtest; i++) | ||
935 | { | ||
936 | if (freq[i, 1] == srtArr[index]) | ||
937 | mode.Add(freq[i, 0]); | ||
938 | |||
939 | } | ||
940 | |||
941 | return mode.ToArray()[0]; | ||
942 | } | ||
943 | |||
944 | public static int ArrayMode_i(int[] arr) | ||
945 | { | ||
946 | List<int> mode = new List<int>(); | ||
947 | |||
948 | int[] srtArr = new int[arr.Length]; | ||
949 | int[,] freq = new int[arr.Length, 2]; | ||
950 | Array.Copy(arr, srtArr, arr.Length); | ||
951 | Array.Sort(srtArr); | ||
952 | |||
953 | int tmp = srtArr[0]; | ||
954 | int index = 0; | ||
955 | int i = 0; | ||
956 | while (i < srtArr.Length) | ||
957 | { | ||
958 | freq[index, 0] = tmp; | ||
959 | |||
960 | while (tmp == srtArr[i]) | ||
961 | { | ||
962 | freq[index, 1]++; | ||
963 | i++; | ||
964 | |||
965 | if (i > srtArr.Length - 1) | ||
966 | break; | ||
967 | } | ||
968 | |||
969 | if (i < srtArr.Length) | ||
970 | { | ||
971 | tmp = srtArr[i]; | ||
972 | index++; | ||
973 | } | ||
974 | |||
975 | } | ||
976 | |||
977 | Array.Clear(srtArr, 0, srtArr.Length); | ||
978 | |||
979 | for (i = 0; i < srtArr.Length; i++) | ||
980 | srtArr[i] = freq[i, 1]; | ||
981 | |||
982 | Array.Sort(srtArr); | ||
983 | |||
984 | if ((srtArr[srtArr.Length - 1]) == 0 || (srtArr[srtArr.Length - 1]) == 1) | ||
985 | return 0; | ||
986 | |||
987 | float freqtest = (float)freq.Length / freq.Rank; | ||
988 | |||
989 | for (i = 0; i < freqtest; i++) | ||
990 | { | ||
991 | if (freq[i, 1] == srtArr[index]) | ||
992 | mode.Add(freq[i, 0]); | ||
993 | |||
994 | } | ||
995 | |||
996 | return mode.ToArray()[0]; | ||
997 | } | ||
998 | |||
999 | #endregion | ||
1000 | |||
1001 | private static UserSessionData ZeroSession(UserSessionData s) | ||
1002 | { | ||
1003 | s.session_id = UUID.Zero; | ||
1004 | s.agent_id = UUID.Zero; | ||
1005 | s.region_id = UUID.Zero; | ||
1006 | s.last_updated = Util.UnixTimeSinceEpoch(); | ||
1007 | s.remote_ip = ""; | ||
1008 | s.name_f = ""; | ||
1009 | s.name_l = ""; | ||
1010 | s.avg_agents_in_view = 0; | ||
1011 | s.min_agents_in_view = 0; | ||
1012 | s.max_agents_in_view = 0; | ||
1013 | s.mode_agents_in_view = 0; | ||
1014 | s.avg_fps = 0; | ||
1015 | s.min_fps = 0; | ||
1016 | s.max_fps = 0; | ||
1017 | s.mode_fps = 0; | ||
1018 | s.a_language = ""; | ||
1019 | s.mem_use = 0; | ||
1020 | s.meters_traveled = 0; | ||
1021 | s.avg_ping = 0; | ||
1022 | s.min_ping = 0; | ||
1023 | s.max_ping = 0; | ||
1024 | s.mode_ping = 0; | ||
1025 | s.regions_visited = 0; | ||
1026 | s.run_time = 0; | ||
1027 | s.avg_sim_fps = 0; | ||
1028 | s.min_sim_fps = 0; | ||
1029 | s.max_sim_fps = 0; | ||
1030 | s.mode_sim_fps = 0; | ||
1031 | s.start_time = 0; | ||
1032 | s.client_version = ""; | ||
1033 | s.s_cpu = ""; | ||
1034 | s.s_gpu = ""; | ||
1035 | s.s_os = ""; | ||
1036 | s.s_ram = 0; | ||
1037 | s.d_object_kb = 0; | ||
1038 | s.d_texture_kb = 0; | ||
1039 | s.d_world_kb = 0; | ||
1040 | s.n_in_kb = 0; | ||
1041 | s.n_in_pk = 0; | ||
1042 | s.n_out_kb = 0; | ||
1043 | s.n_out_pk = 0; | ||
1044 | s.f_dropped = 0; | ||
1045 | s.f_failed_resends = 0; | ||
1046 | s.f_invalid = 0; | ||
1047 | s.f_off_circuit = 0; | ||
1048 | s.f_resent = 0; | ||
1049 | s.f_send_packet = 0; | ||
1050 | s._ping = new List<float>(); | ||
1051 | s._fps = new List<float>(); | ||
1052 | s._sim_fps = new List<float>(); | ||
1053 | s._agents_in_view = new List<int>(); | ||
1054 | return s; | ||
1055 | } | ||
1056 | } | ||
1057 | #region structs | ||
1058 | |||
1059 | public class UserSession | ||
1060 | { | ||
1061 | public UUID session_id; | ||
1062 | public UUID region_id; | ||
1063 | public string name_f; | ||
1064 | public string name_l; | ||
1065 | public UserSessionData session_data; | ||
1066 | } | ||
1067 | |||
1068 | public struct UserSessionData | ||
1069 | { | ||
1070 | public UUID session_id; | ||
1071 | public UUID agent_id; | ||
1072 | public UUID region_id; | ||
1073 | public float last_updated; | ||
1074 | public string remote_ip; | ||
1075 | public string name_f; | ||
1076 | public string name_l; | ||
1077 | public float avg_agents_in_view; | ||
1078 | public float min_agents_in_view; | ||
1079 | public float max_agents_in_view; | ||
1080 | public float mode_agents_in_view; | ||
1081 | public float avg_fps; | ||
1082 | public float min_fps; | ||
1083 | public float max_fps; | ||
1084 | public float mode_fps; | ||
1085 | public string a_language; | ||
1086 | public float mem_use; | ||
1087 | public float meters_traveled; | ||
1088 | public float avg_ping; | ||
1089 | public float min_ping; | ||
1090 | public float max_ping; | ||
1091 | public float mode_ping; | ||
1092 | public int regions_visited; | ||
1093 | public float run_time; | ||
1094 | public float avg_sim_fps; | ||
1095 | public float min_sim_fps; | ||
1096 | public float max_sim_fps; | ||
1097 | public float mode_sim_fps; | ||
1098 | public float start_time; | ||
1099 | public string client_version; | ||
1100 | public string s_cpu; | ||
1101 | public string s_gpu; | ||
1102 | public string s_os; | ||
1103 | public int s_ram; | ||
1104 | public float d_object_kb; | ||
1105 | public float d_texture_kb; | ||
1106 | public float d_world_kb; | ||
1107 | public float n_in_kb; | ||
1108 | public int n_in_pk; | ||
1109 | public float n_out_kb; | ||
1110 | public int n_out_pk; | ||
1111 | public int f_dropped; | ||
1112 | public int f_failed_resends; | ||
1113 | public int f_invalid; | ||
1114 | public int f_off_circuit; | ||
1115 | public int f_resent; | ||
1116 | public int f_send_packet; | ||
1117 | public List<float> _ping; | ||
1118 | public List<float> _fps; | ||
1119 | public List<float> _sim_fps; | ||
1120 | public List<int> _agents_in_view; | ||
1121 | } | ||
1122 | |||
1123 | #endregion | ||
1124 | |||
1125 | public class USimStatsData | ||
1126 | { | ||
1127 | private UUID m_regionID = UUID.Zero; | ||
1128 | private volatile int m_statcounter = 0; | ||
1129 | private volatile float m_timeDilation; | ||
1130 | private volatile float m_simFps; | ||
1131 | private volatile float m_physicsFps; | ||
1132 | private volatile float m_agentUpdates; | ||
1133 | private volatile float m_rootAgents; | ||
1134 | private volatile float m_childAgents; | ||
1135 | private volatile float m_totalPrims; | ||
1136 | private volatile float m_activePrims; | ||
1137 | private volatile float m_totalFrameTime; | ||
1138 | private volatile float m_netFrameTime; | ||
1139 | private volatile float m_physicsFrameTime; | ||
1140 | private volatile float m_otherFrameTime; | ||
1141 | private volatile float m_imageFrameTime; | ||
1142 | private volatile float m_inPacketsPerSecond; | ||
1143 | private volatile float m_outPacketsPerSecond; | ||
1144 | private volatile float m_unackedBytes; | ||
1145 | private volatile float m_agentFrameTime; | ||
1146 | private volatile float m_pendingDownloads; | ||
1147 | private volatile float m_pendingUploads; | ||
1148 | private volatile float m_activeScripts; | ||
1149 | private volatile float m_scriptLinesPerSecond; | ||
1150 | |||
1151 | public UUID RegionId { get { return m_regionID; } } | ||
1152 | public int StatsCounter { get { return m_statcounter; } set { m_statcounter = value;}} | ||
1153 | public float TimeDilation { get { return m_timeDilation; } } | ||
1154 | public float SimFps { get { return m_simFps; } } | ||
1155 | public float PhysicsFps { get { return m_physicsFps; } } | ||
1156 | public float AgentUpdates { get { return m_agentUpdates; } } | ||
1157 | public float RootAgents { get { return m_rootAgents; } } | ||
1158 | public float ChildAgents { get { return m_childAgents; } } | ||
1159 | public float TotalPrims { get { return m_totalPrims; } } | ||
1160 | public float ActivePrims { get { return m_activePrims; } } | ||
1161 | public float TotalFrameTime { get { return m_totalFrameTime; } } | ||
1162 | public float NetFrameTime { get { return m_netFrameTime; } } | ||
1163 | public float PhysicsFrameTime { get { return m_physicsFrameTime; } } | ||
1164 | public float OtherFrameTime { get { return m_otherFrameTime; } } | ||
1165 | public float ImageFrameTime { get { return m_imageFrameTime; } } | ||
1166 | public float InPacketsPerSecond { get { return m_inPacketsPerSecond; } } | ||
1167 | public float OutPacketsPerSecond { get { return m_outPacketsPerSecond; } } | ||
1168 | public float UnackedBytes { get { return m_unackedBytes; } } | ||
1169 | public float AgentFrameTime { get { return m_agentFrameTime; } } | ||
1170 | public float PendingDownloads { get { return m_pendingDownloads; } } | ||
1171 | public float PendingUploads { get { return m_pendingUploads; } } | ||
1172 | public float ActiveScripts { get { return m_activeScripts; } } | ||
1173 | public float ScriptLinesPerSecond { get { return m_scriptLinesPerSecond; } } | ||
1174 | |||
1175 | public USimStatsData(UUID pRegionID) | ||
1176 | { | ||
1177 | m_regionID = pRegionID; | ||
1178 | } | ||
1179 | |||
1180 | public void ConsumeSimStats(SimStats stats) | ||
1181 | { | ||
1182 | m_regionID = stats.RegionUUID; | ||
1183 | m_timeDilation = stats.StatsBlock[0].StatValue; | ||
1184 | m_simFps = stats.StatsBlock[1].StatValue; | ||
1185 | m_physicsFps = stats.StatsBlock[2].StatValue; | ||
1186 | m_agentUpdates = stats.StatsBlock[3].StatValue; | ||
1187 | m_rootAgents = stats.StatsBlock[4].StatValue; | ||
1188 | m_childAgents = stats.StatsBlock[5].StatValue; | ||
1189 | m_totalPrims = stats.StatsBlock[6].StatValue; | ||
1190 | m_activePrims = stats.StatsBlock[7].StatValue; | ||
1191 | m_totalFrameTime = stats.StatsBlock[8].StatValue; | ||
1192 | m_netFrameTime = stats.StatsBlock[9].StatValue; | ||
1193 | m_physicsFrameTime = stats.StatsBlock[10].StatValue; | ||
1194 | m_otherFrameTime = stats.StatsBlock[11].StatValue; | ||
1195 | m_imageFrameTime = stats.StatsBlock[12].StatValue; | ||
1196 | m_inPacketsPerSecond = stats.StatsBlock[13].StatValue; | ||
1197 | m_outPacketsPerSecond = stats.StatsBlock[14].StatValue; | ||
1198 | m_unackedBytes = stats.StatsBlock[15].StatValue; | ||
1199 | m_agentFrameTime = stats.StatsBlock[16].StatValue; | ||
1200 | m_pendingDownloads = stats.StatsBlock[17].StatValue; | ||
1201 | m_pendingUploads = stats.StatsBlock[18].StatValue; | ||
1202 | m_activeScripts = stats.StatsBlock[19].StatValue; | ||
1203 | m_scriptLinesPerSecond = stats.ExtraStatsBlock[0].StatValue; | ||
1204 | } | ||
1205 | } | ||
1206 | } \ No newline at end of file | ||