001: /*
002: * JBoss, Home of Professional Open Source.
003: * Copyright 2006, Red Hat Middleware LLC, and individual contributors
004: * as indicated by the @author tags. See the copyright.txt file in the
005: * distribution for a full listing of individual contributors.
006: *
007: * This is free software; you can redistribute it and/or modify it
008: * under the terms of the GNU Lesser General Public License as
009: * published by the Free Software Foundation; either version 2.1 of
010: * the License, or (at your option) any later version.
011: *
012: * This software is distributed in the hope that it will be useful,
013: * but WITHOUT ANY WARRANTY; without even the implied warranty of
014: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
015: * Lesser General Public License for more details.
016: *
017: * You should have received a copy of the GNU Lesser General Public
018: * License along with this software; if not, write to the Free
019: * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
020: * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
021: */
022: package org.jboss.varia.stats.report;
023:
024: import org.jboss.varia.stats.TxReport;
025: import org.jboss.varia.stats.CacheListener;
026:
027: import java.util.Map;
028: import java.util.Iterator;
029: import java.util.HashMap;
030:
031: /**
032: * @author <a href="mailto:alex@jboss.org">Alexey Loubyansky</a>
033: * @version <tt>$Revision: 57210 $</tt>
034: */
035: public class CacheReportGenerator extends ReportGenerator {
036: protected void content(String reportName, StringBuffer content)
037: throws Exception {
038: StringBuffer contentionBuf = new StringBuffer();
039: contentionBuf
040: .append("<table><tr><th>Lock Contention Per Table</th><th>Total time</th><th>Max time</th><th>count</th></tr>");
041: int contentionTotal = 0;
042: int contentionTimeTotal = 0;
043: long maxContentionTime = 0;
044: StringBuffer evictionBuf = new StringBuffer();
045: evictionBuf
046: .append("<table><tr><th>Eviction per table</th><th>count</th></tr>");
047: int evictionTotal = 0;
048: StringBuffer hitsBuf = new StringBuffer();
049: hitsBuf
050: .append("<table><tr><th>Hits per table</th><th>count</th></tr>");
051: int hitsTotal = 0;
052: StringBuffer missesBuf = new StringBuffer();
053: missesBuf
054: .append("<table><tr><th>Misses per table</th><th>count</th></tr>");
055: int missesTotal = 0;
056:
057: StringBuffer reportsTable = new StringBuffer();
058: reportsTable
059: .append("<table><tr><th>Transaction started by</th><th>Total</th></tr>");
060:
061: int txTotal = 0;
062:
063: Map contention = new HashMap();
064: Map eviction = new HashMap();
065: Map hits = new HashMap();
066: Map misses = new HashMap();
067:
068: Iterator reports = getReportsIterator();
069: while (reports.hasNext()) {
070: TxReport report = (TxReport) reports.next();
071:
072: Map contentionMap = (Map) report.getStats().get(
073: CacheListener.ContentionStats.NAME);
074: Map evictionMap = (Map) report.getStats().get(
075: CacheListener.EvictionStats.NAME);
076: Map hitsMap = (Map) report.getStats().get(
077: CacheListener.HitStats.NAME);
078: Map missesMap = (Map) report.getStats().get(
079: CacheListener.MissStats.NAME);
080:
081: txTotal += report.getCount();
082:
083: if (contentionMap == null && evictionMap == null
084: && hitsMap == null && missesMap == null) {
085: continue;
086: }
087:
088: reportsTable.append("<tr><td>");
089:
090: boolean selected = report.getName().equals(reportName);
091: if (!selected) {
092: reportsTable.append("<a href='HtmlAdaptor?").append(
093: "action=invokeOpByName&name=").append(
094: getServiceName()).append(
095: "&methodName=generate&").append(
096: "argType=java.lang.String&arg0=").append(
097: report.getName()).append("'>");
098: }
099:
100: reportsTable.append(report.getName());
101:
102: if (!selected) {
103: reportsTable.append("</a>");
104: }
105:
106: reportsTable.append("</td><td>").append(report.getCount())
107: .append("</td></tr>");
108:
109: if (selected || reportName == null
110: || reportName.trim().length() == 0) {
111: if (contentionMap != null) {
112: for (Iterator items = contentionMap.values()
113: .iterator(); items.hasNext();) {
114: CacheListener.ContentionStats item = (CacheListener.ContentionStats) items
115: .next();
116:
117: Contention c = (Contention) contention.get(item
118: .getValue());
119: if (c == null) {
120: c = new Contention(item.getValue());
121: contention.put(c.tableName, c);
122: }
123:
124: c.total += item.getContentionTimeTotal();
125: c.count += item.getCount();
126: if (c.maxTime < item.getMaxContentionTime()) {
127: c.maxTime = item.getMaxContentionTime();
128: }
129:
130: contentionTotal += item.getCount();
131: contentionTimeTotal += item
132: .getContentionTimeTotal();
133: if (item.getMaxContentionTime() > maxContentionTime) {
134: maxContentionTime = item
135: .getMaxContentionTime();
136: }
137: }
138: }
139:
140: if (evictionMap != null) {
141: for (Iterator items = evictionMap.values()
142: .iterator(); items.hasNext();) {
143: CacheListener.EvictionStats item = (CacheListener.EvictionStats) items
144: .next();
145:
146: Eviction e = (Eviction) eviction.get(item
147: .getTableName());
148: if (e == null) {
149: e = new Eviction(item.getTableName());
150: eviction.put(e.tableName, e);
151: }
152: e.count += item.getCount();
153:
154: evictionTotal += item.getCount();
155: }
156: }
157:
158: if (hitsMap != null) {
159: for (Iterator items = hitsMap.values().iterator(); items
160: .hasNext();) {
161: CacheListener.HitStats item = (CacheListener.HitStats) items
162: .next();
163:
164: Hit h = (Hit) hits.get(item.getTableName());
165: if (h == null) {
166: h = new Hit(item.getTableName());
167: hits.put(h.tableName, h);
168: }
169: h.partitionHit(item.getPartitionIndex(), item
170: .getCount());
171:
172: hitsTotal += item.getCount();
173: }
174: }
175:
176: if (missesMap != null) {
177: for (Iterator items = missesMap.values().iterator(); items
178: .hasNext();) {
179: CacheListener.MissStats item = (CacheListener.MissStats) items
180: .next();
181: Miss m = (Miss) misses.get(item.getValue());
182: if (m == null) {
183: m = new Miss(item.getValue());
184: misses.put(m.tableName, m);
185: }
186: m.count += item.getCount();
187: missesTotal += item.getCount();
188: }
189: }
190: }
191: }
192:
193: reportsTable.append("<tr><td>");
194:
195: boolean select = reportName != null
196: && reportName.trim().length() > 0;
197: if (select) {
198: reportsTable.append("<a href='HtmlAdaptor?").append(
199: "action=invokeOpByName&name=").append(
200: getServiceName()).append("&methodName=generate&")
201: .append("argType=java.lang.String&arg0=").append(
202: "'>");
203: }
204:
205: reportsTable.append("all transactions");
206:
207: if (select) {
208: reportsTable.append("</a>");
209: }
210:
211: reportsTable.append("</td><td>").append(txTotal).append(
212: "</td></tr></table>");
213:
214: for (Iterator i = contention.values().iterator(); i.hasNext();) {
215: Contention c = (Contention) i.next();
216: contentionBuf.append("<tr><td>").append(c.tableName)
217: .append("</td><td>").append(c.total).append(
218: "</td><td>").append(c.maxTime).append(
219: "</td><td>").append(c.count).append(
220: "</td></tr>");
221: }
222:
223: for (Iterator i = eviction.values().iterator(); i.hasNext();) {
224: Eviction e = (Eviction) i.next();
225: evictionBuf.append("<tr><td>").append(e.tableName).append(
226: "</td><td>").append(e.count).append("</td></tr>");
227: }
228:
229: StringBuffer partitionBuf = new StringBuffer();
230: partitionBuf.append("<table>");
231: for (Iterator i = hits.values().iterator(); i.hasNext();) {
232: Hit h = (Hit) i.next();
233: hitsBuf.append("<tr><td>").append(h.tableName).append(
234: "</td><td>").append(h.count).append("</td></tr>");
235:
236: if (h.partitions != null && h.partitions.length > 0) {
237: partitionBuf.append("<tr><td>");
238:
239: partitionBuf
240: .append("<table><tr><th>Table: ")
241: .append(h.tableName)
242: .append("</th></tr>")
243: .append(
244: "<tr><th>Partition index</th><th>count</th><th>%</th></tr>");
245: for (int pI = 0; pI < h.partitions.length; ++pI) {
246: final int hit = h.partitions[pI];
247: partitionBuf
248: .append("<tr><td>")
249: .append(pI)
250: .append("</td><td>")
251: .append(hit)
252: .append("</td><td>")
253: .append(
254: (int) (100 * ((double) hit / h.maxHitPerPartition)))
255: .append("</td></tr>");
256: }
257: partitionBuf.append("</table>");
258:
259: partitionBuf.append("</td></tr>");
260: }
261: }
262: partitionBuf.append("</table>");
263:
264: for (Iterator i = misses.values().iterator(); i.hasNext();) {
265: Miss m = (Miss) i.next();
266: missesBuf.append("<tr><td>").append(m.tableName).append(
267: "</td><td>").append(m.count).append("</td></tr>");
268: }
269:
270: contentionBuf
271: .append(
272: "<tr><td><font color='red'>total</font></td><td><font color='red'>")
273: .append(contentionTimeTotal).append(
274: "</font></td><td><font color='red'>").append(
275: maxContentionTime).append(
276: "</font></td><td><font color='red'>").append(
277: contentionTotal).append("</font></td></tr>")
278: .append("</table>");
279: evictionBuf
280: .append(
281: "<tr><td><font color='red'>total</font></td><td><font color='red'>")
282: .append(evictionTotal).append("</font></td></tr>")
283: .append("</table>");
284: hitsBuf
285: .append(
286: "<tr><td><font color='red'>total</font></td><td><font color='red'>")
287: .append(hitsTotal).append("</font></td></tr>").append(
288: "</table>");
289: missesBuf
290: .append(
291: "<tr><td><font color='red'>total</font></td><td><font color='red'>")
292: .append(missesTotal).append("</font></td></tr>")
293: .append("</table>");
294:
295: content.append("<table><tr valign='top'><td>").append(
296: reportsTable).append("</td><td>").append(contentionBuf)
297: .append("</td><td>").append(evictionBuf).append(
298: "</td><td>").append(hitsBuf)
299: .append("</td><td>").append(missesBuf).append(
300: "</td></tr></table>");
301:
302: content.append(partitionBuf);
303: }
304:
305: // Inner
306:
307: class Contention {
308: public final String tableName;
309: public int total;
310: public long maxTime;
311: public int count;
312:
313: public Contention(String tableName) {
314: this .tableName = tableName;
315: }
316: }
317:
318: class Eviction {
319: public final String tableName;
320: public int count;
321:
322: public Eviction(String tableName) {
323: this .tableName = tableName;
324: }
325: }
326:
327: class Hit {
328: public final String tableName;
329: public int count;
330: private int[] partitions;
331: private int maxHitPerPartition;
332:
333: public Hit(String tableName) {
334: this .tableName = tableName;
335: }
336:
337: public void partitionHit(int partitionIndex, int count) {
338: if (partitions == null) {
339: partitions = new int[partitionIndex + 1];
340: } else if (partitions.length < partitionIndex + 1) {
341: int[] tmp = partitions;
342: partitions = new int[partitionIndex + 1];
343: System.arraycopy(tmp, 0, partitions, 0, tmp.length);
344: }
345: partitions[partitionIndex] += count;
346: this .count += count;
347:
348: if (maxHitPerPartition < partitions[partitionIndex]) {
349: maxHitPerPartition = partitions[partitionIndex];
350: }
351: }
352: }
353:
354: class Miss {
355: public final String tableName;
356: public int count;
357:
358: public Miss(String tableName) {
359: this.tableName = tableName;
360: }
361: }
362: }
|