1 |
|
package org.apache.jcs.auxiliary.disk.block; |
2 |
|
|
3 |
|
|
4 |
|
|
5 |
|
|
6 |
|
|
7 |
|
|
8 |
|
|
9 |
|
|
10 |
|
|
11 |
|
|
12 |
|
|
13 |
|
|
14 |
|
|
15 |
|
|
16 |
|
|
17 |
|
|
18 |
|
|
19 |
|
|
20 |
|
|
21 |
|
|
22 |
|
import java.io.File; |
23 |
|
import java.io.IOException; |
24 |
|
import java.io.Serializable; |
25 |
|
import java.util.ArrayList; |
26 |
|
import java.util.Arrays; |
27 |
|
import java.util.HashSet; |
28 |
|
import java.util.Iterator; |
29 |
|
import java.util.List; |
30 |
|
import java.util.Map; |
31 |
|
import java.util.Set; |
32 |
|
|
33 |
|
import org.apache.commons.logging.Log; |
34 |
|
import org.apache.commons.logging.LogFactory; |
35 |
|
import org.apache.jcs.auxiliary.AuxiliaryCacheAttributes; |
36 |
|
import org.apache.jcs.auxiliary.disk.AbstractDiskCache; |
37 |
|
import org.apache.jcs.engine.CacheConstants; |
38 |
|
import org.apache.jcs.engine.behavior.ICacheElement; |
39 |
|
import org.apache.jcs.engine.control.group.GroupAttrName; |
40 |
|
import org.apache.jcs.engine.control.group.GroupId; |
41 |
|
import org.apache.jcs.engine.stats.StatElement; |
42 |
|
import org.apache.jcs.engine.stats.Stats; |
43 |
|
import org.apache.jcs.engine.stats.behavior.IStatElement; |
44 |
|
import org.apache.jcs.engine.stats.behavior.IStats; |
45 |
|
|
46 |
|
import EDU.oswego.cs.dl.util.concurrent.WriterPreferenceReadWriteLock; |
47 |
|
|
48 |
|
|
49 |
|
|
50 |
|
|
51 |
|
|
52 |
|
|
53 |
|
public class BlockDiskCache |
54 |
|
extends AbstractDiskCache |
55 |
|
{ |
56 |
|
|
57 |
|
private static final long serialVersionUID = 1L; |
58 |
|
|
59 |
|
|
60 |
|
private static final Log log = LogFactory.getLog( BlockDiskCache.class ); |
61 |
|
|
62 |
|
|
63 |
|
private final String logCacheName; |
64 |
|
|
65 |
|
|
66 |
|
private String fileName; |
67 |
|
|
68 |
|
|
69 |
|
private BlockDisk dataFile; |
70 |
|
|
71 |
|
|
72 |
|
private BlockDiskCacheAttributes blockDiskCacheAttributes; |
73 |
|
|
74 |
|
|
75 |
|
private File rootDirectory; |
76 |
|
|
77 |
|
|
78 |
|
private BlockDiskKeyStore keyStore; |
79 |
|
|
80 |
|
|
81 |
|
|
82 |
|
|
83 |
|
|
84 |
|
|
85 |
|
|
86 |
|
private WriterPreferenceReadWriteLock storageLock = new WriterPreferenceReadWriteLock(); |
87 |
|
|
88 |
|
|
89 |
|
|
90 |
|
|
91 |
|
|
92 |
|
|
93 |
|
public BlockDiskCache( BlockDiskCacheAttributes cacheAttributes ) |
94 |
|
{ |
95 |
|
super( cacheAttributes ); |
96 |
|
|
97 |
|
this.blockDiskCacheAttributes = cacheAttributes; |
98 |
|
this.logCacheName = "Region [" + getCacheName() + "] "; |
99 |
|
|
100 |
|
if ( log.isInfoEnabled() ) |
101 |
|
{ |
102 |
|
log.info( logCacheName + "Constructing BlockDiskCache with attributes " + cacheAttributes ); |
103 |
|
} |
104 |
|
|
105 |
|
this.fileName = getCacheName(); |
106 |
|
String rootDirName = cacheAttributes.getDiskPath(); |
107 |
|
this.rootDirectory = new File( rootDirName ); |
108 |
|
this.rootDirectory.mkdirs(); |
109 |
|
|
110 |
|
if ( log.isInfoEnabled() ) |
111 |
|
{ |
112 |
|
log.info( logCacheName + "Cache file root directory: [" + rootDirName + "]" ); |
113 |
|
} |
114 |
|
|
115 |
|
try |
116 |
|
{ |
117 |
|
if ( this.blockDiskCacheAttributes.getBlockSizeBytes() > 0 ) |
118 |
|
{ |
119 |
|
this.dataFile = new BlockDisk( class="keyword">new File( rootDirectory, fileName + ".data" ), |
120 |
|
this.blockDiskCacheAttributes.getBlockSizeBytes() ); |
121 |
|
} |
122 |
|
else |
123 |
|
{ |
124 |
|
this.dataFile = new BlockDisk( class="keyword">new File( rootDirectory, fileName + ".data" ) ); |
125 |
|
} |
126 |
|
|
127 |
|
keyStore = new BlockDiskKeyStore( this.blockDiskCacheAttributes, class="keyword">this ); |
128 |
|
|
129 |
|
boolean alright = verifyDisk(); |
130 |
|
|
131 |
|
if ( keyStore.size() == 0 || !alright ) |
132 |
|
{ |
133 |
|
this.reset(); |
134 |
|
} |
135 |
|
|
136 |
|
|
137 |
|
alive = true; |
138 |
|
if ( log.isInfoEnabled() ) |
139 |
|
{ |
140 |
|
log.info( logCacheName + "Block Disk Cache is alive." ); |
141 |
|
} |
142 |
|
} |
143 |
|
catch ( Exception e ) |
144 |
|
{ |
145 |
|
log.error( logCacheName + "Failure initializing for fileName: " + fileName + " and root directory: " |
146 |
|
+ rootDirName, e ); |
147 |
|
} |
148 |
|
ShutdownHook shutdownHook = new ShutdownHook(); |
149 |
|
Runtime.getRuntime().addShutdownHook( shutdownHook ); |
150 |
|
} |
151 |
|
|
152 |
|
|
153 |
|
|
154 |
|
|
155 |
|
|
156 |
|
|
157 |
|
|
158 |
|
protected boolean verifyDisk() |
159 |
|
{ |
160 |
|
boolean alright = false; |
161 |
|
|
162 |
|
|
163 |
|
try |
164 |
|
{ |
165 |
|
int maxToTest = 100; |
166 |
|
int count = 0; |
167 |
|
Set keySet = this.keyStore.entrySet(); |
168 |
|
Iterator it = keySet.iterator(); |
169 |
|
while ( it.hasNext() && count < maxToTest ) |
170 |
|
{ |
171 |
|
count++; |
172 |
|
Map.Entry entry = (Map.Entry) it.next(); |
173 |
|
Object data = this.dataFile.read( (int[]) entry.getValue() ); |
174 |
|
if ( data == null ) |
175 |
|
{ |
176 |
|
throw new Exception( "Couldn't find data for key [" + entry.getKey() + "]" ); |
177 |
|
} |
178 |
|
} |
179 |
|
alright = true; |
180 |
|
} |
181 |
|
catch ( Exception e ) |
182 |
|
{ |
183 |
|
log.warn( "Problem verifying disk. Message [" + e.getMessage() + "]" ); |
184 |
|
alright = false; |
185 |
|
} |
186 |
|
return alright; |
187 |
|
} |
188 |
|
|
189 |
|
|
190 |
|
|
191 |
|
|
192 |
|
|
193 |
|
|
194 |
|
|
195 |
|
public Set getGroupKeys( String groupName ) |
196 |
|
{ |
197 |
|
GroupId groupId = new GroupId( cacheName, groupName ); |
198 |
|
HashSet keys = new HashSet(); |
199 |
|
try |
200 |
|
{ |
201 |
|
storageLock.readLock().acquire(); |
202 |
|
|
203 |
|
for ( Iterator itr = this.keyStore.keySet().iterator(); itr.hasNext(); ) |
204 |
|
{ |
205 |
|
Object k = itr.next(); |
206 |
|
if ( k instanceof GroupAttrName && ( (GroupAttrName) k ).groupId.equals( groupId ) ) |
207 |
|
{ |
208 |
|
keys.add( ( (GroupAttrName) k ).attrName ); |
209 |
|
} |
210 |
|
} |
211 |
|
} |
212 |
|
catch ( Exception e ) |
213 |
|
{ |
214 |
|
log.error( logCacheName + "Failure getting from disk, group = " + groupName, e ); |
215 |
|
} |
216 |
|
finally |
217 |
|
{ |
218 |
|
storageLock.readLock().release(); |
219 |
|
} |
220 |
|
|
221 |
|
return keys; |
222 |
|
} |
223 |
|
|
224 |
|
|
225 |
|
|
226 |
|
|
227 |
|
|
228 |
|
|
229 |
|
|
230 |
|
public int getSize() |
231 |
|
{ |
232 |
|
return this.keyStore.size(); |
233 |
|
} |
234 |
|
|
235 |
|
|
236 |
|
|
237 |
|
|
238 |
|
|
239 |
|
|
240 |
|
|
241 |
|
|
242 |
|
|
243 |
|
|
244 |
|
|
245 |
|
|
246 |
|
|
247 |
|
protected ICacheElement doGet( Serializable key ) |
248 |
|
{ |
249 |
|
if ( !alive ) |
250 |
|
{ |
251 |
|
if ( log.isDebugEnabled() ) |
252 |
|
{ |
253 |
|
log.debug( logCacheName + "No longer alive so returning null for key = " + key ); |
254 |
|
} |
255 |
|
return null; |
256 |
|
} |
257 |
|
|
258 |
|
if ( log.isDebugEnabled() ) |
259 |
|
{ |
260 |
|
log.debug( logCacheName + "Trying to get from disk: " + key ); |
261 |
|
} |
262 |
|
|
263 |
|
ICacheElement object = null; |
264 |
|
try |
265 |
|
{ |
266 |
|
storageLock.readLock().acquire(); |
267 |
|
try |
268 |
|
{ |
269 |
|
int[] ded = this.keyStore.get( key ); |
270 |
|
if ( ded != null ) |
271 |
|
{ |
272 |
|
object = (ICacheElement) this.dataFile.read( ded ); |
273 |
|
} |
274 |
|
} |
275 |
|
finally |
276 |
|
{ |
277 |
|
storageLock.readLock().release(); |
278 |
|
} |
279 |
|
} |
280 |
|
catch ( IOException ioe ) |
281 |
|
{ |
282 |
|
log.error( logCacheName + "Failure getting from disk--IOException, key = " + key, ioe ); |
283 |
|
reset(); |
284 |
|
} |
285 |
|
catch ( Exception e ) |
286 |
|
{ |
287 |
|
log.error( logCacheName + "Failure getting from disk, key = " + key, e ); |
288 |
|
} |
289 |
|
|
290 |
|
return object; |
291 |
|
} |
292 |
|
|
293 |
|
|
294 |
|
|
295 |
|
|
296 |
|
|
297 |
|
|
298 |
|
|
299 |
|
|
300 |
|
|
301 |
|
|
302 |
|
|
303 |
|
|
304 |
|
|
305 |
|
|
306 |
|
protected void doUpdate( ICacheElement element ) |
307 |
|
{ |
308 |
|
if ( !alive ) |
309 |
|
{ |
310 |
|
if ( log.isDebugEnabled() ) |
311 |
|
{ |
312 |
|
log.debug( logCacheName + "No longer alive; aborting put of key = " + element.getKey() ); |
313 |
|
} |
314 |
|
return; |
315 |
|
} |
316 |
|
|
317 |
|
int[] old = null; |
318 |
|
try |
319 |
|
{ |
320 |
|
|
321 |
|
storageLock.writeLock().acquire(); |
322 |
|
try |
323 |
|
{ |
324 |
|
old = this.keyStore.get( element.getKey() ); |
325 |
|
|
326 |
|
if ( old != null ) |
327 |
|
{ |
328 |
|
this.dataFile.freeBlocks( old ); |
329 |
|
} |
330 |
|
|
331 |
|
int[] blocks = this.dataFile.write( element ); |
332 |
|
|
333 |
|
this.keyStore.put( element.getKey(), blocks ); |
334 |
|
} |
335 |
|
finally |
336 |
|
{ |
337 |
|
storageLock.writeLock().release(); |
338 |
|
} |
339 |
|
|
340 |
|
if ( log.isDebugEnabled() ) |
341 |
|
{ |
342 |
|
log.debug( logCacheName + "Put to file [" + fileName + "] key [" + element.getKey() + "]" ); |
343 |
|
} |
344 |
|
} |
345 |
|
catch ( Exception e ) |
346 |
|
{ |
347 |
|
log.error( logCacheName + "Failure updating element, key: " + element.getKey() + " old: " + old, e ); |
348 |
|
} |
349 |
|
if ( log.isDebugEnabled() ) |
350 |
|
{ |
351 |
|
log.debug( logCacheName + "Storing element on disk, key: " + element.getKey() ); |
352 |
|
} |
353 |
|
} |
354 |
|
|
355 |
|
|
356 |
|
|
357 |
|
|
358 |
|
|
359 |
|
|
360 |
|
|
361 |
|
|
362 |
|
protected boolean doRemove( Serializable key ) |
363 |
|
{ |
364 |
|
if ( !alive ) |
365 |
|
{ |
366 |
|
if ( log.isDebugEnabled() ) |
367 |
|
{ |
368 |
|
log.debug( logCacheName + "No longer alive so returning false for key = " + key ); |
369 |
|
} |
370 |
|
return false; |
371 |
|
} |
372 |
|
|
373 |
|
boolean reset = false; |
374 |
|
boolean removed = false; |
375 |
|
try |
376 |
|
{ |
377 |
|
storageLock.writeLock().acquire(); |
378 |
|
|
379 |
|
if ( key instanceof String && key.toString().endsWith( CacheConstants.NAME_COMPONENT_DELIMITER ) ) |
380 |
|
{ |
381 |
|
|
382 |
|
|
383 |
|
Iterator iter = this.keyStore.entrySet().iterator(); |
384 |
|
|
385 |
|
while ( iter.hasNext() ) |
386 |
|
{ |
387 |
|
Map.Entry entry = (Map.Entry) iter.next(); |
388 |
|
|
389 |
|
Object k = entry.getKey(); |
390 |
|
|
391 |
|
if ( k instanceof String && k.toString().startsWith( key.toString() ) ) |
392 |
|
{ |
393 |
|
int[] ded = this.keyStore.get( key ); |
394 |
|
this.dataFile.freeBlocks( ded ); |
395 |
|
iter.remove(); |
396 |
|
removed = true; |
397 |
|
|
398 |
|
} |
399 |
|
} |
400 |
|
} |
401 |
|
else if ( key instanceof GroupId ) |
402 |
|
{ |
403 |
|
|
404 |
|
Iterator iter = this.keyStore.entrySet().iterator(); |
405 |
|
while ( iter.hasNext() ) |
406 |
|
{ |
407 |
|
Map.Entry entry = (Map.Entry) iter.next(); |
408 |
|
Object k = entry.getKey(); |
409 |
|
|
410 |
|
if ( k instanceof GroupAttrName && ( (GroupAttrName) k ).groupId.equals( key ) ) |
411 |
|
{ |
412 |
|
int[] ded = this.keyStore.get( key ); |
413 |
|
this.dataFile.freeBlocks( ded ); |
414 |
|
iter.remove(); |
415 |
|
removed = true; |
416 |
|
} |
417 |
|
} |
418 |
|
} |
419 |
|
else |
420 |
|
{ |
421 |
|
|
422 |
|
int[] ded = this.keyStore.remove( key ); |
423 |
|
removed = ( ded != null ); |
424 |
|
if ( ded != null ) |
425 |
|
{ |
426 |
|
this.dataFile.freeBlocks( ded ); |
427 |
|
} |
428 |
|
|
429 |
|
if ( log.isDebugEnabled() ) |
430 |
|
{ |
431 |
|
log.debug( logCacheName + "Disk removal: Removed from key hash, key [" + key + "] removed = " |
432 |
|
+ removed ); |
433 |
|
} |
434 |
|
} |
435 |
|
} |
436 |
|
catch ( Exception e ) |
437 |
|
{ |
438 |
|
log.error( logCacheName + "Problem removing element.", e ); |
439 |
|
reset = true; |
440 |
|
} |
441 |
|
finally |
442 |
|
{ |
443 |
|
storageLock.writeLock().release(); |
444 |
|
} |
445 |
|
|
446 |
|
if ( reset ) |
447 |
|
{ |
448 |
|
reset(); |
449 |
|
} |
450 |
|
|
451 |
|
return removed; |
452 |
|
} |
453 |
|
|
454 |
|
|
455 |
|
|
456 |
|
|
457 |
|
|
458 |
|
|
459 |
|
|
460 |
|
protected void doRemoveAll() |
461 |
|
{ |
462 |
|
try |
463 |
|
{ |
464 |
|
reset(); |
465 |
|
} |
466 |
|
catch ( Exception e ) |
467 |
|
{ |
468 |
|
log.error( logCacheName + "Problem removing all.", e ); |
469 |
|
reset(); |
470 |
|
} |
471 |
|
} |
472 |
|
|
473 |
|
|
474 |
|
|
475 |
|
|
476 |
|
|
477 |
|
|
478 |
|
|
479 |
|
public void doDispose() |
480 |
|
{ |
481 |
|
Runnable disR = new Runnable() |
482 |
|
{ |
483 |
|
public void run() |
484 |
|
{ |
485 |
|
try |
486 |
|
{ |
487 |
|
disposeInternal(); |
488 |
|
} |
489 |
|
catch ( InterruptedException e ) |
490 |
|
{ |
491 |
|
log.warn( "Interrupted while diposing." ); |
492 |
|
} |
493 |
|
} |
494 |
|
}; |
495 |
|
Thread t = new Thread( disR, "BlockDiskCache-DisposalThread" ); |
496 |
|
t.start(); |
497 |
|
|
498 |
|
try |
499 |
|
{ |
500 |
|
t.join( 60 * 1000 ); |
501 |
|
} |
502 |
|
catch ( InterruptedException ex ) |
503 |
|
{ |
504 |
|
log.error( logCacheName + "Interrupted while waiting for disposal thread to finish.", ex ); |
505 |
|
} |
506 |
|
} |
507 |
|
|
508 |
|
|
509 |
|
|
510 |
|
|
511 |
|
|
512 |
|
private void disposeInternal() |
513 |
|
throws InterruptedException |
514 |
|
{ |
515 |
|
if ( !alive ) |
516 |
|
{ |
517 |
|
log.error( logCacheName + "Not alive and dispose was called, filename: " + fileName ); |
518 |
|
return; |
519 |
|
} |
520 |
|
storageLock.writeLock().acquire(); |
521 |
|
try |
522 |
|
{ |
523 |
|
|
524 |
|
alive = false; |
525 |
|
|
526 |
|
this.keyStore.saveKeys(); |
527 |
|
|
528 |
|
try |
529 |
|
{ |
530 |
|
if ( log.isDebugEnabled() ) |
531 |
|
{ |
532 |
|
log.debug( logCacheName + "Closing files, base filename: " + fileName ); |
533 |
|
} |
534 |
|
dataFile.close(); |
535 |
|
|
536 |
|
|
537 |
|
|
538 |
|
|
539 |
|
|
540 |
|
} |
541 |
|
catch ( IOException e ) |
542 |
|
{ |
543 |
|
log.error( logCacheName + "Failure closing files in dispose, filename: " + fileName, e ); |
544 |
|
} |
545 |
|
} |
546 |
|
finally |
547 |
|
{ |
548 |
|
storageLock.writeLock().release(); |
549 |
|
} |
550 |
|
|
551 |
|
if ( log.isInfoEnabled() ) |
552 |
|
{ |
553 |
|
log.info( logCacheName + "Shutdown complete." ); |
554 |
|
} |
555 |
|
} |
556 |
|
|
557 |
|
|
558 |
|
|
559 |
|
|
560 |
|
|
561 |
|
|
562 |
|
|
563 |
|
public AuxiliaryCacheAttributes getAuxiliaryCacheAttributes() |
564 |
|
{ |
565 |
|
return this.blockDiskCacheAttributes; |
566 |
|
} |
567 |
|
|
568 |
|
|
569 |
|
|
570 |
|
|
571 |
|
|
572 |
|
|
573 |
|
private void reset() |
574 |
|
{ |
575 |
|
if ( log.isWarnEnabled() ) |
576 |
|
{ |
577 |
|
log.warn( logCacheName + "Reseting cache" ); |
578 |
|
} |
579 |
|
|
580 |
|
try |
581 |
|
{ |
582 |
|
storageLock.writeLock().acquire(); |
583 |
|
|
584 |
|
if ( dataFile != null ) |
585 |
|
{ |
586 |
|
dataFile.close(); |
587 |
|
} |
588 |
|
|
589 |
|
File dataFileTemp = new File( this.rootDirectory, fileName + ".data" ); |
590 |
|
dataFileTemp.delete(); |
591 |
|
|
592 |
|
if ( this.blockDiskCacheAttributes.getBlockSizeBytes() > 0 ) |
593 |
|
{ |
594 |
|
this.dataFile = new BlockDisk( class="keyword">new File( rootDirectory, fileName + ".data" ), |
595 |
|
this.blockDiskCacheAttributes.getBlockSizeBytes() ); |
596 |
|
} |
597 |
|
else |
598 |
|
{ |
599 |
|
this.dataFile = new BlockDisk( class="keyword">new File( rootDirectory, fileName + ".data" ) ); |
600 |
|
} |
601 |
|
|
602 |
|
this.keyStore.reset(); |
603 |
|
} |
604 |
|
catch ( Exception e ) |
605 |
|
{ |
606 |
|
log.error( logCacheName + "Failure reseting state", e ); |
607 |
|
} |
608 |
|
finally |
609 |
|
{ |
610 |
|
storageLock.writeLock().release(); |
611 |
|
} |
612 |
|
} |
613 |
|
|
614 |
|
|
615 |
|
|
616 |
|
|
617 |
|
|
618 |
|
|
619 |
|
protected void freeBlocks( int[] blocksToFree ) |
620 |
|
{ |
621 |
|
this.dataFile.freeBlocks( blocksToFree ); |
622 |
|
} |
623 |
|
|
624 |
|
|
625 |
|
|
626 |
|
|
627 |
|
|
628 |
112 |
class ShutdownHook |
629 |
|
extends Thread |
630 |
|
{ |
631 |
|
|
632 |
|
public void run() |
633 |
|
{ |
634 |
112 |
if ( alive ) |
635 |
|
{ |
636 |
112 |
log.warn( logCacheName + "Disk cache not shutdown properly, shutting down now." ); |
637 |
112 |
doDispose(); |
638 |
|
} |
639 |
111 |
} |
640 |
|
} |
641 |
|
|
642 |
|
|
643 |
|
|
644 |
|
|
645 |
|
|
646 |
|
|
647 |
|
public String getStats() |
648 |
|
{ |
649 |
|
return getStatistics().toString(); |
650 |
|
} |
651 |
|
|
652 |
|
|
653 |
|
|
654 |
|
|
655 |
|
|
656 |
|
|
657 |
|
|
658 |
|
public IStats getStatistics() |
659 |
|
{ |
660 |
|
IStats stats = new Stats(); |
661 |
|
stats.setTypeName( "Block Disk Cache" ); |
662 |
|
|
663 |
|
ArrayList elems = new ArrayList(); |
664 |
|
|
665 |
|
IStatElement se = null; |
666 |
|
|
667 |
|
se = new StatElement(); |
668 |
|
se.setName( "Is Alive" ); |
669 |
|
se.setData( "" + alive ); |
670 |
|
elems.add( se ); |
671 |
|
|
672 |
|
se = new StatElement(); |
673 |
|
se.setName( "Key Map Size" ); |
674 |
|
se.setData( "" + this.keyStore.size() ); |
675 |
|
elems.add( se ); |
676 |
|
|
677 |
|
try |
678 |
|
{ |
679 |
|
se = new StatElement(); |
680 |
|
se.setName( "Data File Length" ); |
681 |
|
if ( this.dataFile != null ) |
682 |
|
{ |
683 |
|
se.setData( "" + this.dataFile.length() ); |
684 |
|
} |
685 |
|
else |
686 |
|
{ |
687 |
|
se.setData( "-1" ); |
688 |
|
} |
689 |
|
elems.add( se ); |
690 |
|
} |
691 |
|
catch ( Exception e ) |
692 |
|
{ |
693 |
|
log.error( e ); |
694 |
|
} |
695 |
|
|
696 |
|
se = new StatElement(); |
697 |
|
se.setName( "Block Size Bytes" ); |
698 |
|
se.setData( "" + this.dataFile.getBlockSizeBytes() ); |
699 |
|
elems.add( se ); |
700 |
|
|
701 |
|
se = new StatElement(); |
702 |
|
se.setName( "Number Of Blocks" ); |
703 |
|
se.setData( "" + this.dataFile.getNumberOfBlocks() ); |
704 |
|
elems.add( se ); |
705 |
|
|
706 |
|
se = new StatElement(); |
707 |
|
se.setName( "Average Put Size Bytes" ); |
708 |
|
se.setData( "" + this.dataFile.getAveragePutSizeBytes() ); |
709 |
|
elems.add( se ); |
710 |
|
|
711 |
|
se = new StatElement(); |
712 |
|
se.setName( "Empty Blocks" ); |
713 |
|
se.setData( "" + this.dataFile.getEmptyBlocks() ); |
714 |
|
elems.add( se ); |
715 |
|
|
716 |
|
|
717 |
|
|
718 |
|
IStats sStats = super.getStatistics(); |
719 |
|
IStatElement[] sSEs = sStats.getStatElements(); |
720 |
|
List sL = Arrays.asList( sSEs ); |
721 |
|
elems.addAll( sL ); |
722 |
|
|
723 |
|
|
724 |
|
IStatElement[] ses = (IStatElement[]) elems.toArray( new StatElement[0] ); |
725 |
|
stats.setStatElements( ses ); |
726 |
|
|
727 |
|
return stats; |
728 |
|
} |
729 |
|
} |