SlicingMeasurementConsumer.java

biz/hammurapi/metrics/SlicingMeasurementConsumer.java

Violations

Inspector Message Severity Location
Java Inspector 048 Copyrights information should be present in each file. 1
Java Inspector 044 Use 'wait ()' and 'notifyAll ()' instead of polling loops 2 379:62
Java Inspector 083 Do not use printStackTrace() for exception logging. 2 367:91
Java Inspector 089 Type documentation is too short. It is only 2 words. Should be at least 3 words. 2 41:1
Java Inspector 089 Undocumented method 2 66:9
Java Inspector 089 Undocumented parameter sliceConsumer 2 77:9
Java Inspector 089 Undocumented parameter sliceConsumer 2 90:9
Java Inspector 089 Undocumented method 2 106:9
Java Inspector 089 Constructor is not properly documented 2 133:17
Java Inspector 089 Parameter category is not documented 2 133:17
Java Inspector 089 Undocumented method 2 138:17
Java Inspector 089 Undocumented method 2 154:17
Java Inspector 089 Undocumented method 2 158:17
Java Inspector 089 Undocumented method 2 162:17
Java Inspector 089 Method is not properly documented 2 171:9
Java Inspector 089 Parameter category is not documented 2 171:9
Java Inspector 089 Undocumented method 2 186:9
Java Inspector 089 Undocumented method 2 242:41
Java Inspector 089 Undocumented method 2 246:41
Java Inspector 089 Undocumented method 2 250:41
Java Inspector 089 Undocumented method 2 254:41
Java Inspector 089 Undocumented method 2 258:41
Java Inspector 089 Undocumented method 2 262:41
Java Inspector 089 Undocumented method 2 266:41
Java Inspector 089 Undocumented method 2 270:41
Java Inspector 089 Undocumented method 2 274:41
Java Inspector 089 Undocumented method 2 278:41
Java Inspector 089 Undocumented method 2 282:41
Java Inspector 089 Undocumented method 2 286:41
Java Inspector 089 Undocumented method 2 358:25
Java Inspector 089 Undocumented field 2 391:5
Java Inspector 089 Undocumented field 2 392:5
Java Inspector 089 Undocumented exception ConfigurationException 2 399:9
Java Inspector 089 Undocumented method 2 406:25
Java Inspector 089 Undocumented exception ConfigurationException 2 426:9
Java Inspector 089 Undocumented method 2 432:9
Java Inspector 089 Undocumented method 2 436:9
Java Inspector 089 Undocumented method 2 440:9
Java Inspector 089 Undocumented method 2 444:9
Java Inspector 089 Undocumented method 2 448:9
Java Inspector 089 Undocumented method 2 452:9
Java Inspector 089 Undocumented method 2 456:9
Java Inspector 089 Undocumented method 2 460:9
Java Inspector 025 Avoid hardwired numeric literals. Allowed literals: [1, -1, 0] 3 60:27
Java Inspector 025 Avoid hardwired numeric literals. Allowed literals: [1, -1, 0] 3 61:30
Java Inspector 026 Avoid hardwired string literals. Allowed literals: [] 3 239:57
Java Inspector 026 Avoid hardwired string literals. Allowed literals: [] 3 283:52
Java Inspector 026 Avoid hardwired string literals. Allowed literals: [] 3 342:41
Java Inspector 051 It is good practice to call in any case super() in a constructor. 3 77:9
Java Inspector 054 Discourage usage of instance variables like a, j by enforcing minimal variable name length (3). 3 392:5

Source code

1/*
2 * hgcommons 9
3 * Hammurapi Group Common Library
4 * Copyright (C) 2003 Hammurapi Group
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 *
20 * URL: http://www.hammurapi.biz/hammurapi-biz/ef/xmenu/hammurapi-group/products/products/hgcommons/index.html
21 * e-Mail: support@hammurapi.biz
22 */
23package biz.hammurapi.metrics;
24
25import java.util.Collection;
26import java.util.HashMap;
27import java.util.Iterator;
28import java.util.LinkedList;
29import java.util.Map;
30import java.util.Timer;
31import java.util.TimerTask;
32
33import biz.hammurapi.config.Component;
34import biz.hammurapi.config.ConfigurationException;
35
36/**
37 * Slices metrics.
38 * @author Pavel Vlasov
39 * @version $Revision: 1.3 $
40 */
41public class SlicingMeasurementConsumer implements MeasurementConsumer, Component {
42
43 private class SliceEntry {
44 String category;
45 Slice slice;
46 /**
47 * @param category
48 * @param slice
49 */
50 SliceEntry(String category, Slice slice) {
51 super();
52 this.category = category;
53 this.slice = slice;
54 }
55 }
56
57 private Map slices=new HashMap();
58 private LinkedList sliceQueue=new LinkedList();
59 private boolean keepMeasurements=false;
60 private long tick=60000;
61 private int maxQueue=1000;
62 private SliceConsumer sliceConsumer=new ConsoleSliceConsumer();
63 private Timer timer;
64 private boolean isOwnTimer;
65
66 protected SliceConsumer getSliceConsumer() {
67 return sliceConsumer;
68 }
69
70 /**
71 * Creates a new instance with internal timer.
72 * @param tick Slice size in milliseconds
73 * @param keepMeasurements If true individual measurements are reported, only aggregated values otherwise
74 * @param maxQueue Maximum number of slices pending to be consumed. 0 - no limit. If sampling ratio is higher than
75 * consuming ration then excessive slices will be dropped with a notice on console.
76 */
77 public SlicingMeasurementConsumer(long tick, boolean keepMeasurements, int maxQueue, SliceConsumer sliceConsumer) {
78 this(tick, keepMeasurements, maxQueue, sliceConsumer, null);
79 }
80
81 /**
82 * Creates a new instance with internal timer.
83 * @param tick Slice size in milliseconds
84 * @param keepMeasurements If true individual measurements are reported, only aggregated values otherwise
85 * @param maxQueue Maximum number of slices pending to be consumed. 0 - no limit. If sampling ratio is higher than
86 * consuming ration then excessive slices will be dropped with a notice on console.
87 * @param timer Timer to use for slicing metrics and passing them to slice consumer. If it is null then an internal timer is
88 * created.
89 */
90 public SlicingMeasurementConsumer(long tick, boolean keepMeasurements, int maxQueue, SliceConsumer sliceConsumer, Timer timer) {
91 super();
92 this.keepMeasurements = keepMeasurements;
93 this.tick=tick;
94 this.maxQueue=maxQueue;
95 this.sliceConsumer=sliceConsumer;
96 this.timer=timer;
97 }
98
99 /**
100 * Default constructor with default settings.
101 */
102 public SlicingMeasurementConsumer() {
103 super();
104 }
105
106 public void addMeasurement(String name, double value, long time) {
107 synchronized (slices) {
108 Slice slice=(Slice) slices.get(name);
109 if (slice==null) {
110 slice=new SimpleSlice(name, keepMeasurements);
111 slices.put(name, slice);
112 }
113 slice.add(value, time);
114
115 if (slice.getTo()-slice.getFrom()>=tick) {
116 slices.remove(name);
117 addSliceToQueue(null, slice);
118 }
119 }
120 }
121
122 private Map instances=new HashMap();
123
124 private class CategorizedConsumer implements MeasurementConsumer, Component {
125
126
127 String category;
128 Map slices=new HashMap();
129
130 /**
131 * @param category
132 */
133 public CategorizedConsumer(String category) {
134 super();
135 this.category = category;
136 }
137
138 public void addMeasurement(String name, double value, long time) {
139 synchronized (slices) {
140 Slice slice=(Slice) slices.get(name);
141 if (slice==null) {
142 slice=new SimpleSlice(name, keepMeasurements);
143 slices.put(name, slice);
144 }
145 slice.add(value, time);
146
147 if (slice.getTo()-slice.getFrom()>=tick) {
148 slices.remove(name);
149 addSliceToQueue(category, slice);
150 }
151 }
152 }
153
154 public void start() throws ConfigurationException {
155 SlicingMeasurementConsumer.this.start();
156 }
157
158 public void stop() throws ConfigurationException {
159 SlicingMeasurementConsumer.this.stop();
160 }
161
162 public void setOwner(Object owner) {
163 // Ignore
164 }
165 }
166
167 /**
168 * @param category
169 * @return Instance for a category.
170 */
171 public MeasurementConsumer getCategoryInstance(final String category) {
172 synchronized (instances) {
173 MeasurementConsumer ret = (MeasurementConsumer) instances.get(category);
174 if (ret==null) {
175 ret = new CategorizedConsumer(category);
176 instances.put(category, ret);
177 }
178 return ret;
179 }
180 }
181
182 private int droppedCounter;
183 private long firstDropped;
184 private Thread slicingThread;
185
186 public void shutdown() {
187 to=System.currentTimeMillis();
188
189 synchronized (slices) {
190 Iterator it=slices.values().iterator();
191 while (it.hasNext()) {
192 Slice slice=(Slice) it.next();
193 it.remove();
194 addSliceToQueue(null, slice);
195 }
196 }
197
198 synchronized (instances) {
199 Iterator iit=instances.values().iterator();
200 while (iit.hasNext()) {
201 CategorizedConsumer cConsumer=(CategorizedConsumer) iit.next();
202 synchronized (cConsumer.slices) {
203 Iterator it=cConsumer.slices.values().iterator();
204 while (it.hasNext()) {
205 Slice slice=(Slice) it.next();
206 it.remove();
207 addSliceToQueue(cConsumer.category, slice);
208 }
209 }
210 }
211 }
212
213// MeasurementCategoryFactory.unregister(this); - Unregister explicitly!!!
214 addSliceToQueue(null,null);
215 try {
216 slicingThread.join();
217 } catch (InterruptedException e) {
218 throw new MetricsException(e);
219 }
220
221 // Stop the time is it is our own.
222 if (isOwnTimer) {
223 timer.cancel();
224 }
225 }
226
227 /**
228 *
229 */
230 private void addSliceToQueue(String category, final Slice slice) {
231 synchronized (sliceQueue) {
232 if (slice!=null && maxQueue!=0 && sliceQueue.size()>maxQueue) {
233 firstDropped=slice.getTo();
234 droppedCounter++;
235 } else {
236 if (droppedCounter>0) {
237 sliceQueue.add(
238 new SliceEntry(
239 "DroppedSlices",
240 new Slice() {
241
242 public long getFrom() {
243 return firstDropped;
244 }
245
246 public long getTo() {
247 return slice.getTo();
248 }
249
250 public int getNumber() {
251 return droppedCounter;
252 }
253
254 public double getMin() {
255 return 0;
256 }
257
258 public double getMax() {
259 return 0;
260 }
261
262 public double getAvg() {
263 return 0;
264 }
265
266 public double getTotal() {
267 return 0;
268 }
269
270 public void add(double value, long time) {
271 throw new UnsupportedOperationException();
272 }
273
274 public void add(Metric metric) {
275 throw new UnsupportedOperationException();
276 }
277
278 public Collection getMeasurements() {
279 return null;
280 }
281
282 public String getName() {
283 return "DROPPED SLICES";
284 }
285
286 public double getDeviation() {
287 return 0;
288 }
289
290 }));
291 droppedCounter=0;
292 }
293
294 sliceQueue.add(slice==null ? null : new SliceEntry(category, slice));
295 sliceQueue.notifyAll();
296 }
297 }
298 }
299
300 /**
301 *
302 */
303 private void onTick() {
304 long now=System.currentTimeMillis();
305
306 synchronized (slices) {
307 Iterator it=slices.values().iterator();
308 while (it.hasNext()) {
309 Slice slice=(Slice) it.next();
310 if (now-slice.getFrom()>=tick) {
311 it.remove();
312 addSliceToQueue(null, slice);
313 }
314 }
315 }
316
317 synchronized (instances) {
318 Iterator iit=instances.values().iterator();
319 while (iit.hasNext()) {
320 CategorizedConsumer cConsumer=(CategorizedConsumer) iit.next();
321 synchronized (cConsumer.slices) {
322 Iterator it=cConsumer.slices.values().iterator();
323 while (it.hasNext()) {
324 Slice slice=(Slice) it.next();
325 if (now-slice.getFrom()>=tick) {
326 it.remove();
327 addSliceToQueue(cConsumer.category, slice);
328 }
329 }
330 }
331 }
332 }
333
334 if (sliceConsumer instanceof HousekeepingSliceConsumer) {
335 ((HousekeepingSliceConsumer) sliceConsumer).onTick(now);
336 }
337 }
338
339 {
340 slicingThread=new Thread() {
341 {
342 setName("Slice queue processor");
343 setDaemon(true);
344 setPriority(Thread.MIN_PRIORITY);
345 start();
346 }
347
348 private SliceEntry getSliceEntry() throws InterruptedException {
349 synchronized (sliceQueue) {
350 while (sliceQueue.isEmpty()) {
351 sliceQueue.wait();
352 }
353
354 return (SliceEntry) sliceQueue.removeFirst();
355 }
356 }
357
358 public void run() {
359 while (true) {
360 try {
361 SliceEntry entry=getSliceEntry();
362 if (entry==null) {
363 if (sliceConsumer instanceof Component) {
364 try {
365 ((Component) sliceConsumer).stop();
366 } catch (ConfigurationException e1) {
367 e1.printStackTrace();
368 }
369 }
370 return;
371 }
372
373 // Put entry back to queue if slice consumer is unable to consume
374 // and sleep.
375 if (!sliceConsumer.consumeSlice(entry.category, entry.slice)) {
376 synchronized (sliceQueue) {
377 sliceQueue.add(entry);
378 }
379 sleep(tick);
380 }
381 } catch (InterruptedException e) {
382 return;
383 }
384 }
385 }
386 };
387 }
388
389 private int useCounter;
390
391 protected long from;
392 protected long to;
393
394 private TimerTask tickTask;
395
396 /**
397 * Increments use counter
398 */
399 public void start() throws ConfigurationException {
400 if (timer==null) {
401 timer=new Timer(true);
402 isOwnTimer=true;
403 }
404
405 tickTask = new TimerTask() {
406 public void run() {
407 onTick();
408 }
409 };
410
411 timer.scheduleAtFixedRate(tickTask, tick, tick);
412
413 if (useCounter==0) {
414 from=System.currentTimeMillis();
415 if (sliceConsumer instanceof Component) {
416 ((Component) sliceConsumer).start();
417 }
418 }
419
420 ++useCounter;
421 }
422
423 /**
424 * Decrements use counter and invokes shutdown() when counter==0
425 */
426 public void stop() throws ConfigurationException {
427 if (--useCounter==0) {
428 shutdown();
429 }
430 }
431
432 public void setOwner(Object owner) {
433 // Ignore
434 }
435
436 public int getMaxQueue() {
437 return maxQueue;
438 }
439
440 public void setMaxQueue(int maxQueue) {
441 this.maxQueue = maxQueue;
442 }
443
444 public long getTick() {
445 return tick;
446 }
447
448 public void setTick(long tick) {
449 this.tick = tick;
450 }
451
452 public void setSliceConsumer(SliceConsumer sliceConsumer) {
453 this.sliceConsumer = sliceConsumer;
454 }
455
456 public boolean isKeepMeasurements() {
457 return keepMeasurements;
458 }
459
460 public void setKeepMeasurements(boolean keepMeasurements) {
461 this.keepMeasurements = keepMeasurements;
462 }
463
464
465}
466