aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--OpenSim/Region/UserStatistics/ActiveConnectionsAJAX.cs8
-rw-r--r--OpenSim/Region/UserStatistics/Clients_report.cs299
-rw-r--r--OpenSim/Region/UserStatistics/Default_Report.cs10
-rw-r--r--OpenSim/Region/UserStatistics/HTMLUtil.cs28
-rw-r--r--OpenSim/Region/UserStatistics/IStatsReport.cs1
-rw-r--r--OpenSim/Region/UserStatistics/LogLinesAJAX.cs5
-rw-r--r--OpenSim/Region/UserStatistics/Prototype_distributor.cs5
-rw-r--r--OpenSim/Region/UserStatistics/SimStatsAJAX.cs5
-rw-r--r--OpenSim/Region/UserStatistics/Updater_distributor.cs4
-rw-r--r--OpenSim/Region/UserStatistics/WebStatsModule.cs5
10 files changed, 364 insertions, 6 deletions
diff --git a/OpenSim/Region/UserStatistics/ActiveConnectionsAJAX.cs b/OpenSim/Region/UserStatistics/ActiveConnectionsAJAX.cs
index 9451932..bbaaf44 100644
--- a/OpenSim/Region/UserStatistics/ActiveConnectionsAJAX.cs
+++ b/OpenSim/Region/UserStatistics/ActiveConnectionsAJAX.cs
@@ -39,9 +39,15 @@ namespace OpenSim.Region.UserStatistics
39{ 39{
40 public class ActiveConnectionsAJAX : IStatsController 40 public class ActiveConnectionsAJAX : IStatsController
41 { 41 {
42 private Vector3 DefaultNeighborPosition = new Vector3(128, 128, 70);
43
42 #region IStatsController Members 44 #region IStatsController Members
43 45
44 private Vector3 DefaultNeighborPosition = new Vector3(128, 128, 70); 46 public string ReportName
47 {
48 get { return ""; }
49 }
50
45 public Hashtable ProcessModel(Hashtable pParams) 51 public Hashtable ProcessModel(Hashtable pParams)
46 { 52 {
47 53
diff --git a/OpenSim/Region/UserStatistics/Clients_report.cs b/OpenSim/Region/UserStatistics/Clients_report.cs
new file mode 100644
index 0000000..bc43e18
--- /dev/null
+++ b/OpenSim/Region/UserStatistics/Clients_report.cs
@@ -0,0 +1,299 @@
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
28using System;
29using System.Collections;
30using System.Collections.Generic;
31using System.Text;
32using Mono.Data.SqliteClient;
33using OpenMetaverse;
34using OpenSim.Region.Environment.Scenes;
35
36namespace OpenSim.Region.UserStatistics
37{
38 public class Clients_report : IStatsController
39 {
40 #region IStatsController Members
41
42 public string ReportName
43 {
44 get { return "Client"; }
45 }
46
47 public Hashtable ProcessModel(Hashtable pParams)
48 {
49 SqliteConnection dbConn = (SqliteConnection)pParams["DatabaseConnection"];
50
51
52 List<ClientVersionData> clidata = new List<ClientVersionData>();
53 List<ClientVersionData> cliRegData = new List<ClientVersionData>();
54 Hashtable regionTotals = new Hashtable();
55
56 Hashtable modeldata = new Hashtable();
57 modeldata.Add("Scenes", pParams["Scenes"]);
58 modeldata.Add("Reports", pParams["Reports"]);
59 int totalclients = 0;
60 int totalregions = 0;
61
62 lock (dbConn)
63 {
64 string sql = "select count(distinct region_id) as regcnt from stats_session_data";
65
66 SqliteCommand cmd = new SqliteCommand(sql, dbConn);
67 SqliteDataReader sdr = cmd.ExecuteReader();
68 if (sdr.HasRows)
69 {
70 sdr.Read();
71 totalregions = Convert.ToInt32(sdr["regcnt"]);
72 }
73
74
75 sql =
76 "select client_version, count(*) as cnt, avg(avg_sim_fps) as simfps from stats_session_data group by client_version order by count(*) desc LIMIT 10;";
77
78 cmd = new SqliteCommand(sql, dbConn);
79 sdr = cmd.ExecuteReader();
80 if (sdr.HasRows)
81 {
82 while (sdr.Read())
83 {
84 ClientVersionData udata = new ClientVersionData();
85 udata.version = sdr["client_version"].ToString();
86 udata.count = Convert.ToInt32(sdr["cnt"]);
87 udata.fps = Convert.ToSingle(sdr["simfps"]);
88 clidata.Add(udata);
89 totalclients += udata.count;
90
91 }
92 }
93 sdr.Close();
94 sdr.Dispose();
95
96 if (totalregions > 1)
97 {
98 sql =
99 "select region_id, client_version, count(*) as cnt, avg(avg_sim_fps) as simfps from stats_session_data group by region_id, client_version order by region_id, count(*) desc;";
100 cmd = new SqliteCommand(sql, dbConn);
101
102 sdr = cmd.ExecuteReader();
103
104 if (sdr.HasRows)
105 {
106 while (sdr.Read())
107 {
108 ClientVersionData udata = new ClientVersionData();
109 udata.version = sdr["client_version"].ToString();
110 udata.count = Convert.ToInt32(sdr["cnt"]);
111 udata.fps = Convert.ToSingle(sdr["simfps"]);
112 udata.region_id = UUID.Parse(sdr["region_id"].ToString());
113 cliRegData.Add(udata);
114 }
115 }
116 sdr.Close();
117 sdr.Dispose();
118
119
120 }
121
122 }
123
124 foreach (ClientVersionData cvd in cliRegData)
125 {
126
127 if (regionTotals.ContainsKey(cvd.region_id))
128 {
129 int regiontotal = (int)regionTotals[cvd.region_id];
130 regiontotal += cvd.count;
131 regionTotals[cvd.region_id] = regiontotal;
132 }
133 else
134 {
135 regionTotals.Add(cvd.region_id, cvd.count);
136 }
137
138
139
140 }
141
142 modeldata["ClientData"] = clidata;
143 modeldata["ClientRegionData"] = cliRegData;
144 modeldata["RegionTotals"] = regionTotals;
145 modeldata["Total"] = totalclients;
146
147 return modeldata;
148 }
149
150 public string RenderView(Hashtable pModelResult)
151 {
152 List<ClientVersionData> clidata = (List<ClientVersionData>) pModelResult["ClientData"];
153 int totalclients = (int)pModelResult["Total"];
154 Hashtable regionTotals = (Hashtable) pModelResult["RegionTotals"];
155 List<ClientVersionData> cliRegData = (List<ClientVersionData>) pModelResult["ClientRegionData"];
156 List<Scene> m_scenes = (List<Scene>)pModelResult["Scenes"];
157 Dictionary<string, IStatsController> reports = (Dictionary<string, IStatsController>)pModelResult["Reports"];
158
159 const string STYLESHEET =
160 @"
161<STYLE>
162body
163{
164 font-size:15px; font-family:Helvetica, Verdana; color:Black;
165}
166TABLE.defaultr { }
167TR.defaultr { padding: 5px; }
168TD.header { font-weight:bold; padding:5px; }
169TD.content {}
170TD.contentright { text-align: right; }
171TD.contentcenter { text-align: center; }
172TD.align_top { vertical-align: top; }
173</STYLE>
174";
175
176 StringBuilder output = new StringBuilder();
177 HTMLUtil.HtmlHeaders_O(ref output);
178 output.Append(STYLESHEET);
179 HTMLUtil.HtmlHeaders_C(ref output);
180
181 HTMLUtil.AddReportLinks(ref output, reports, "");
182
183 HTMLUtil.TABLE_O(ref output, "defaultr");
184 HTMLUtil.TR_O(ref output, "");
185 HTMLUtil.TD_O(ref output, "header");
186 output.Append("ClientVersion");
187 HTMLUtil.TD_C(ref output);
188 HTMLUtil.TD_O(ref output, "header");
189 output.Append("Count/%");
190 HTMLUtil.TD_C(ref output);
191 HTMLUtil.TD_O(ref output, "header");
192 output.Append("SimFPS");
193 HTMLUtil.TD_C(ref output);
194 HTMLUtil.TR_C(ref output);
195
196 foreach (ClientVersionData cvd in clidata)
197 {
198 HTMLUtil.TR_O(ref output, "");
199 HTMLUtil.TD_O(ref output, "content");
200 output.Append(cvd.version);
201 HTMLUtil.TD_C(ref output);
202 HTMLUtil.TD_O(ref output, "content");
203 output.Append(cvd.count);
204 output.Append("/");
205 if (totalclients > 0)
206 output.Append((((float)cvd.count / (float)totalclients)*100).ToString());
207 else
208 output.Append(0);
209
210 output.Append("%");
211 HTMLUtil.TD_C(ref output);
212 HTMLUtil.TD_O(ref output, "content");
213 output.Append(cvd.fps);
214 HTMLUtil.TD_C(ref output);
215 HTMLUtil.TR_C(ref output);
216 }
217 HTMLUtil.TABLE_C(ref output);
218
219 if (cliRegData.Count > 0)
220 {
221 HTMLUtil.TABLE_O(ref output, "defaultr");
222 HTMLUtil.TR_O(ref output, "");
223 HTMLUtil.TD_O(ref output, "header");
224 output.Append("Region");
225 HTMLUtil.TD_C(ref output);
226 HTMLUtil.TD_O(ref output, "header");
227 output.Append("ClientVersion");
228 HTMLUtil.TD_C(ref output);
229 HTMLUtil.TD_O(ref output, "header");
230 output.Append("Count/%");
231 HTMLUtil.TD_C(ref output);
232 HTMLUtil.TD_O(ref output, "header");
233 output.Append("SimFPS");
234 HTMLUtil.TD_C(ref output);
235 HTMLUtil.TR_C(ref output);
236
237 foreach (ClientVersionData cvd in cliRegData)
238 {
239 HTMLUtil.TR_O(ref output, "");
240 HTMLUtil.TD_O(ref output, "content");
241 output.Append(regionNamefromUUID(m_scenes, cvd.region_id));
242 HTMLUtil.TD_C(ref output);
243 HTMLUtil.TD_O(ref output, "content");
244 output.Append(cvd.version);
245 HTMLUtil.TD_C(ref output);
246 HTMLUtil.TD_O(ref output, "content");
247 output.Append(cvd.count);
248 output.Append("/");
249 if ((int)regionTotals[cvd.region_id] > 0)
250 output.Append((((float)cvd.count / (float)((int)regionTotals[cvd.region_id])) * 100).ToString());
251 else
252 output.Append(0);
253
254 output.Append("%");
255 HTMLUtil.TD_C(ref output);
256 HTMLUtil.TD_O(ref output, "content");
257 output.Append(cvd.fps);
258 HTMLUtil.TD_C(ref output);
259 HTMLUtil.TR_C(ref output);
260 }
261 HTMLUtil.TABLE_C(ref output);
262
263 }
264
265 output.Append("</BODY>");
266 output.Append("</HTML>");
267 return output.ToString();
268 }
269 public string regionNamefromUUID(List<Scene> scenes, UUID region_id)
270 {
271 string returnstring = string.Empty;
272 foreach (Scene sn in scenes)
273 {
274 if (region_id == sn.RegionInfo.originRegionID)
275 {
276 returnstring = sn.RegionInfo.RegionName;
277 break;
278 }
279 }
280
281 if (returnstring.Length == 0)
282 {
283 returnstring = region_id.ToString();
284 }
285
286 return returnstring;
287 }
288
289 #endregion
290 }
291
292 public struct ClientVersionData
293 {
294 public UUID region_id;
295 public string version;
296 public int count;
297 public float fps;
298 }
299}
diff --git a/OpenSim/Region/UserStatistics/Default_Report.cs b/OpenSim/Region/UserStatistics/Default_Report.cs
index 5d4cfc0..55cb454 100644
--- a/OpenSim/Region/UserStatistics/Default_Report.cs
+++ b/OpenSim/Region/UserStatistics/Default_Report.cs
@@ -41,9 +41,9 @@ namespace OpenSim.Region.UserStatistics
41 public class Default_Report : IStatsController 41 public class Default_Report : IStatsController
42 { 42 {
43 43
44 public Default_Report() 44 public string ReportName
45 { 45 {
46 46 get { return "Home"; }
47 } 47 }
48 48
49 #region IStatsController Members 49 #region IStatsController Members
@@ -55,9 +55,11 @@ namespace OpenSim.Region.UserStatistics
55 55
56 stats_default_page_values mData = rep_DefaultReport_data(conn, m_scene); 56 stats_default_page_values mData = rep_DefaultReport_data(conn, m_scene);
57 mData.sim_stat_data = (Dictionary<UUID,USimStatsData>)pParams["SimStats"]; 57 mData.sim_stat_data = (Dictionary<UUID,USimStatsData>)pParams["SimStats"];
58 mData.stats_reports = (Dictionary<string, IStatsController>) pParams["Reports"];
58 59
59 Hashtable nh = new Hashtable(); 60 Hashtable nh = new Hashtable();
60 nh.Add("hdata", mData); 61 nh.Add("hdata", mData);
62 nh.Add("Reports", pParams["Reports"]);
61 63
62 return nh; 64 return nh;
63 } 65 }
@@ -73,6 +75,7 @@ namespace OpenSim.Region.UserStatistics
73 public string rep_Default_report_view(stats_default_page_values values) 75 public string rep_Default_report_view(stats_default_page_values values)
74 { 76 {
75 77
78
76 StringBuilder output = new StringBuilder(); 79 StringBuilder output = new StringBuilder();
77 80
78 81
@@ -123,7 +126,7 @@ TD.align_top { vertical-align: top; }
123 126
124 output.Append(STYLESHEET); 127 output.Append(STYLESHEET);
125 HTMLUtil.HtmlHeaders_C(ref output); 128 HTMLUtil.HtmlHeaders_C(ref output);
126 129 HTMLUtil.AddReportLinks(ref output, values.stats_reports, "");
127 HTMLUtil.TABLE_O(ref output, TableClass); 130 HTMLUtil.TABLE_O(ref output, TableClass);
128 HTMLUtil.TR_O(ref output, TRClass); 131 HTMLUtil.TR_O(ref output, TRClass);
129 HTMLUtil.TD_O(ref output, TDHeaderClass); 132 HTMLUtil.TD_O(ref output, TDHeaderClass);
@@ -242,5 +245,6 @@ TD.align_top { vertical-align: top; }
242 public float avg_client_resends; 245 public float avg_client_resends;
243 public Scene[] all_scenes; 246 public Scene[] all_scenes;
244 public Dictionary<UUID, USimStatsData> sim_stat_data; 247 public Dictionary<UUID, USimStatsData> sim_stat_data;
248 public Dictionary<string, IStatsController> stats_reports;
245 } 249 }
246} 250}
diff --git a/OpenSim/Region/UserStatistics/HTMLUtil.cs b/OpenSim/Region/UserStatistics/HTMLUtil.cs
index bc21c55..173f75e 100644
--- a/OpenSim/Region/UserStatistics/HTMLUtil.cs
+++ b/OpenSim/Region/UserStatistics/HTMLUtil.cs
@@ -208,5 +208,33 @@ namespace OpenSim.Region.UserStatistics
208 o.Append("</HEAD>"); 208 o.Append("</HEAD>");
209 o.Append("<BODY>"); 209 o.Append("<BODY>");
210 } 210 }
211
212 public static void AddReportLinks( ref StringBuilder o, Dictionary<string, IStatsController> reports, string pClass)
213 {
214 int repcount = 0;
215 foreach (string str in reports.Keys)
216 {
217 if (reports[str].ReportName.Length > 0)
218 {
219 if (repcount > 0)
220 {
221 o.Append("|&nbsp;&nbsp;");
222 }
223
224 o.Append("<A");
225 if (pClass.Length > 0)
226 {
227 GenericClass(ref o, pClass);
228
229 }
230 o.Append(" href=\"");
231 o.Append(str);
232 o.Append("\">");
233 o.Append(reports[str].ReportName);
234 o.Append("</A>&nbsp;&nbsp;");
235 repcount++;
236 }
237 }
238 }
211 } 239 }
212} 240}
diff --git a/OpenSim/Region/UserStatistics/IStatsReport.cs b/OpenSim/Region/UserStatistics/IStatsReport.cs
index effe66e..e0ecce4 100644
--- a/OpenSim/Region/UserStatistics/IStatsReport.cs
+++ b/OpenSim/Region/UserStatistics/IStatsReport.cs
@@ -31,6 +31,7 @@ namespace OpenSim.Region.UserStatistics
31{ 31{
32 public interface IStatsController 32 public interface IStatsController
33 { 33 {
34 string ReportName { get; }
34 Hashtable ProcessModel(Hashtable pParams); 35 Hashtable ProcessModel(Hashtable pParams);
35 string RenderView(Hashtable pModelResult); 36 string RenderView(Hashtable pModelResult);
36 } 37 }
diff --git a/OpenSim/Region/UserStatistics/LogLinesAJAX.cs b/OpenSim/Region/UserStatistics/LogLinesAJAX.cs
index 0ffe9f6..1f55d51 100644
--- a/OpenSim/Region/UserStatistics/LogLinesAJAX.cs
+++ b/OpenSim/Region/UserStatistics/LogLinesAJAX.cs
@@ -50,6 +50,11 @@ namespace OpenSim.Region.UserStatistics
50 50
51 #region IStatsController Members 51 #region IStatsController Members
52 52
53 public string ReportName
54 {
55 get { return ""; }
56 }
57
53 public Hashtable ProcessModel(Hashtable pParams) 58 public Hashtable ProcessModel(Hashtable pParams)
54 { 59 {
55 Hashtable nh = new Hashtable(); 60 Hashtable nh = new Hashtable();
diff --git a/OpenSim/Region/UserStatistics/Prototype_distributor.cs b/OpenSim/Region/UserStatistics/Prototype_distributor.cs
index 749831e..53ae557 100644
--- a/OpenSim/Region/UserStatistics/Prototype_distributor.cs
+++ b/OpenSim/Region/UserStatistics/Prototype_distributor.cs
@@ -38,7 +38,10 @@ namespace OpenSim.Region.UserStatistics
38 { 38 {
39 private string prototypejs=string.Empty; 39 private string prototypejs=string.Empty;
40 40
41 41 public string ReportName
42 {
43 get { return ""; }
44 }
42 public Hashtable ProcessModel(Hashtable pParams) 45 public Hashtable ProcessModel(Hashtable pParams)
43 { 46 {
44 Hashtable pResult = new Hashtable(); 47 Hashtable pResult = new Hashtable();
diff --git a/OpenSim/Region/UserStatistics/SimStatsAJAX.cs b/OpenSim/Region/UserStatistics/SimStatsAJAX.cs
index 25fd520..be213aa 100644
--- a/OpenSim/Region/UserStatistics/SimStatsAJAX.cs
+++ b/OpenSim/Region/UserStatistics/SimStatsAJAX.cs
@@ -41,6 +41,11 @@ namespace OpenSim.Region.UserStatistics
41 { 41 {
42 #region IStatsController Members 42 #region IStatsController Members
43 43
44 public string ReportName
45 {
46 get { return ""; }
47 }
48
44 public Hashtable ProcessModel(Hashtable pParams) 49 public Hashtable ProcessModel(Hashtable pParams)
45 { 50 {
46 List<Scene> m_scene = (List<Scene>)pParams["Scenes"]; 51 List<Scene> m_scene = (List<Scene>)pParams["Scenes"];
diff --git a/OpenSim/Region/UserStatistics/Updater_distributor.cs b/OpenSim/Region/UserStatistics/Updater_distributor.cs
index 663adc9..9593cc9 100644
--- a/OpenSim/Region/UserStatistics/Updater_distributor.cs
+++ b/OpenSim/Region/UserStatistics/Updater_distributor.cs
@@ -38,6 +38,10 @@ namespace OpenSim.Region.UserStatistics
38 { 38 {
39 private string updaterjs = string.Empty; 39 private string updaterjs = string.Empty;
40 40
41 public string ReportName
42 {
43 get { return ""; }
44 }
41 45
42 public Hashtable ProcessModel(Hashtable pParams) 46 public Hashtable ProcessModel(Hashtable pParams)
43 { 47 {
diff --git a/OpenSim/Region/UserStatistics/WebStatsModule.cs b/OpenSim/Region/UserStatistics/WebStatsModule.cs
index 09c23a2..8a640d0 100644
--- a/OpenSim/Region/UserStatistics/WebStatsModule.cs
+++ b/OpenSim/Region/UserStatistics/WebStatsModule.cs
@@ -105,13 +105,15 @@ namespace OpenSim.Region.UserStatistics
105 ActiveConnectionsAJAX ajConnections = new ActiveConnectionsAJAX(); 105 ActiveConnectionsAJAX ajConnections = new ActiveConnectionsAJAX();
106 SimStatsAJAX ajSimStats = new SimStatsAJAX(); 106 SimStatsAJAX ajSimStats = new SimStatsAJAX();
107 LogLinesAJAX ajLogLines = new LogLinesAJAX(); 107 LogLinesAJAX ajLogLines = new LogLinesAJAX();
108 Clients_report clientReport = new Clients_report();
109
108 reports.Add("", rep); 110 reports.Add("", rep);
109 reports.Add("index.aspx", rep);
110 reports.Add("prototype.js", protodep); 111 reports.Add("prototype.js", protodep);
111 reports.Add("updater.js", updatedep); 112 reports.Add("updater.js", updatedep);
112 reports.Add("activeconnectionsajax.ajax", ajConnections); 113 reports.Add("activeconnectionsajax.ajax", ajConnections);
113 reports.Add("simstatsajax.ajax", ajSimStats); 114 reports.Add("simstatsajax.ajax", ajSimStats);
114 reports.Add("activelogajax.ajax", ajLogLines); 115 reports.Add("activelogajax.ajax", ajLogLines);
116 reports.Add("clients.report", clientReport);
115 117
116 scene.CommsManager.HttpServer.AddHTTPHandler("/SStats/", HandleStatsRequest); 118 scene.CommsManager.HttpServer.AddHTTPHandler("/SStats/", HandleStatsRequest);
117 scene.CommsManager.HttpServer.AddHTTPHandler("/CAPS/VS/", HandleUnknownCAPSRequest); 119 scene.CommsManager.HttpServer.AddHTTPHandler("/CAPS/VS/", HandleUnknownCAPSRequest);
@@ -192,6 +194,7 @@ namespace OpenSim.Region.UserStatistics
192 repParams["Scenes"] = m_scene; 194 repParams["Scenes"] = m_scene;
193 repParams["SimStats"] = m_simstatsCounters; 195 repParams["SimStats"] = m_simstatsCounters;
194 repParams["LogLines"] = m_loglines; 196 repParams["LogLines"] = m_loglines;
197 repParams["Reports"] = reports;
195 198
196 concurrencyCounter++; 199 concurrencyCounter++;
197 200