| 1 19 20 package org.apache.excalibur.instrument.manager.impl; 21 22 import java.io.File ; 23 import java.io.FileInputStream ; 24 import java.io.FileOutputStream ; 25 import java.io.InputStream ; 26 import java.io.IOException ; 27 import java.io.OutputStream ; 28 import java.io.OutputStreamWriter ; 29 import java.io.PrintWriter ; 30 import java.util.ArrayList ; 31 import java.util.Arrays ; 32 import java.util.Comparator ; 33 import java.util.HashMap ; 34 import java.util.Iterator ; 35 import java.util.List ; 36 import java.util.Map ; 37 38 import org.apache.avalon.framework.activity.Disposable; 39 import org.apache.avalon.framework.activity.Initializable; 40 import org.apache.avalon.framework.configuration.Configurable; 41 import org.apache.avalon.framework.configuration.Configuration; 42 import org.apache.avalon.framework.configuration.ConfigurationException; 43 import org.apache.avalon.framework.configuration.DefaultConfigurationBuilder; 44 import org.apache.avalon.framework.container.ContainerUtil; 45 import org.apache.avalon.framework.logger.AbstractLogEnabled; 46 import org.apache.avalon.framework.logger.Logger; 47 import org.apache.avalon.framework.service.ServiceException; 48 49 import org.apache.excalibur.instrument.AbstractInstrument; 50 import org.apache.excalibur.instrument.CounterInstrument; 51 import org.apache.excalibur.instrument.Instrument; 52 import org.apache.excalibur.instrument.InstrumentManager; 53 import org.apache.excalibur.instrument.Instrumentable; 54 import org.apache.excalibur.instrument.ValueInstrument; 55 56 import org.apache.excalibur.instrument.manager.DefaultInstrumentManager; 57 import org.apache.excalibur.instrument.manager.DefaultInstrumentManagerConnector; 58 import org.apache.excalibur.instrument.manager.InstrumentableDescriptor; 59 import org.apache.excalibur.instrument.manager.InstrumentDescriptor; 60 import org.apache.excalibur.instrument.manager.InstrumentSampleDescriptor; 61 import org.apache.excalibur.instrument.manager.InstrumentSampleUtils; 62 import org.apache.excalibur.instrument.manager.NoSuchInstrumentException; 63 import org.apache.excalibur.instrument.manager.NoSuchInstrumentSampleException; 64 import org.apache.excalibur.instrument.manager.NoSuchInstrumentableException; 65 66 72 public class DefaultInstrumentManagerImpl 73 extends AbstractLogEnabled 74 implements Configurable, Initializable, Disposable, DefaultInstrumentManager, 75 Instrumentable, Runnable  76 { 77 78 private String m_name; 79 80 81 private String m_description; 82 83 85 private int m_maxLeasedSamples; 86 87 89 private int m_maxLeasedSampleSize; 90 91 93 private long m_maxLeasedSampleLease; 94 95 96 private List m_connectors = new ArrayList (); 97 98 99 private File m_stateFile; 100 101 102 private long m_stateInterval; 103 104 105 private long m_lastStateSave; 106 107 108 private Object m_semaphore = new Object (); 109 110 111 private Map m_instrumentableProxies = new HashMap (); 112 113 114 private InstrumentableProxy[] m_instrumentableProxyArray; 115 116 117 private InstrumentableDescriptor[] m_instrumentableDescriptorArray; 118 119 120 private List m_leasedInstrumentSamples = new ArrayList (); 121 122 123 private InstrumentSample[] m_leasedInstrumentSampleArray; 124 125 126 private Logger m_translationLogger; 127 128 129 private Map m_nameTranslations = new HashMap (); 130 131 132 private String [][] m_nameTranslationArray; 133 134 138 private Thread m_runner; 139 140 141 private String m_instrumentableName = "instrument-manager"; 142 143 144 private ValueInstrument m_totalMemoryInstrument; 145 146 147 private ValueInstrument m_freeMemoryInstrument; 148 149 150 private ValueInstrument m_memoryInstrument; 151 152 153 private ValueInstrument m_activeThreadCountInstrument; 154 155 156 private CounterInstrument m_registrationsInstrument; 157 158 159 private int m_instrumentableCount; 160 161 162 private ValueInstrument m_instrumentablesInstrument; 163 164 165 private int m_instrumentCount; 166 167 168 private ValueInstrument m_instrumentsInstrument; 169 170 171 private int m_permanentSampleCount; 172 173 174 private int m_leasedSampleCount; 175 176 177 private ValueInstrument m_samplesInstrument; 178 179 180 private ValueInstrument m_leasedSamplesInstrument; 181 182 183 private CounterInstrument m_leaseRequestsInstrument; 184 185 186 private CounterInstrument m_stateSavesInstrument; 187 188 189 private ValueInstrument m_stateSaveTimeInstrument; 190 191 192 private int m_stateVersion; 193 194 197 205 public DefaultInstrumentManagerImpl( String name ) 206 { 207 this(); 208 } 209 210 213 public DefaultInstrumentManagerImpl() 214 { 215 m_totalMemoryInstrument = new ValueInstrument( "total-memory" ); 217 m_freeMemoryInstrument = new ValueInstrument( "free-memory" ); 218 m_memoryInstrument = new ValueInstrument( "memory" ); 219 m_activeThreadCountInstrument = new ValueInstrument( "active-thread-count" ); 220 m_registrationsInstrument = new CounterInstrument( "instrumentable-registrations" ); 221 m_instrumentablesInstrument = new ValueInstrument( "instrumentables" ); 222 m_instrumentsInstrument = new ValueInstrument( "instruments" ); 223 m_samplesInstrument = new ValueInstrument( "samples" ); 224 m_leasedSamplesInstrument = new ValueInstrument( "leased-samples" ); 225 m_leaseRequestsInstrument = new CounterInstrument( "lease-requests" ); 226 m_stateSavesInstrument = new CounterInstrument( "state-saves" ); 227 m_stateSaveTimeInstrument = new ValueInstrument( "state-save-time" ); 228 } 229 230 233 240 public void configure( Configuration configuration ) 241 throws ConfigurationException 242 { 243 m_translationLogger = getLogger().getChildLogger( "translation" ); 244 245 try 249 { 250 registerInstrumentable( this, getInstrumentableName() ); 251 } 252 catch ( Exception e ) 253 { 254 throw new ConfigurationException( 256 "Unable to register the InstrumentManager's own instruments.", e ); 257 } 258 259 synchronized( m_semaphore ) 260 { 261 m_name = configuration.getChild( "name" ).getValue( "instrument-manager" ); 263 m_description = configuration.getChild( "description" ).getValue( m_name ); 264 265 m_maxLeasedSamples = 267 configuration.getChild( "max-leased-samples" ).getValueAsInteger( 256 ); 268 m_maxLeasedSampleSize = 269 configuration.getChild( "max-leased-sample-size" ).getValueAsInteger( 2048 ); 270 m_maxLeasedSampleLease = 1000L * 271 configuration.getChild( "max-leased-sample-lease" ).getValueAsInteger( 86400 ); 272 273 Configuration translationsConf = configuration.getChild( "translations" ); 275 Configuration[] translationConfs = translationsConf.getChildren( "translation" ); 276 for( int i = 0; i < translationConfs.length; i++ ) 277 { 278 Configuration translationConf = translationConfs[i]; 279 String source = translationConf.getAttribute( "source" ); 280 String target = translationConf.getAttribute( "target" ); 281 try 282 { 283 registerNameTranslationInner( source, target ); 284 } 285 catch ( IllegalArgumentException e ) 286 { 287 throw new ConfigurationException( e.getMessage(), translationConf ); 288 } 289 } 290 291 Configuration instrumentablesConf = configuration.getChild( "instrumentables" ); 293 Configuration[] instrumentableConfs = 294 instrumentablesConf.getChildren( "instrumentable" ); 295 for( int i = 0; i < instrumentableConfs.length; i++ ) 296 { 297 Configuration instrumentableConf = instrumentableConfs[ i ]; 298 String instrumentableName = instrumentableConf.getAttribute( "name" ); 299 300 InstrumentableProxy instrumentableProxy = 302 (InstrumentableProxy)m_instrumentableProxies.get( instrumentableName ); 303 if ( instrumentableProxy == null ) 304 { 305 instrumentableProxy = new InstrumentableProxy( 306 this, null, instrumentableName, instrumentableName ); 307 instrumentableProxy.enableLogging( getLogger() ); 308 incrementInstrumentableCount(); 309 m_instrumentableProxies.put( instrumentableName, instrumentableProxy ); 310 311 m_instrumentableProxyArray = null; 313 m_instrumentableDescriptorArray = null; 314 } 315 instrumentableProxy.configure( instrumentableConf ); 317 } 318 319 Configuration stateFileConf = configuration.getChild( "state-file" ); 321 m_stateInterval = stateFileConf.getAttributeAsLong( "interval", 60000 ); 322 323 String stateFile = stateFileConf.getValue( null ); 324 if( stateFile != null ) 325 { 326 m_stateFile = new File ( stateFile ); 327 if( m_stateFile.exists() ) 328 { 329 try 330 { 331 loadStateFromFile( m_stateFile ); 332 } 333 catch( Exception e ) 334 { 335 String msg = "Unable to load the instrument manager state. The " 336 + "configuration may have been corrupted. A backup may have been " 337 + "made in the same directory when it was saved."; 338 339 if ( getLogger().isDebugEnabled() ) 340 { 341 getLogger().error( msg, e ); 342 } 343 else 344 { 345 getLogger().error( msg + " : " + e.toString() ); 346 } 347 } 348 } 349 } 350 351 Logger connLogger = getLogger().getChildLogger( "connector" ); 353 354 Configuration connectorsConf = configuration.getChild( "connectors" ); 356 Configuration[] connectorConfs = 357 connectorsConf.getChildren( "connector" ); 358 for( int i = 0; i < connectorConfs.length; i++ ) 359 { 360 Configuration connectorConf = connectorConfs[ i ]; 361 String className = connectorConf.getAttribute( "class" ); 362 if ( className.equals( "http" ) ) 364 { 365 className = "org.apache.excalibur.instrument.manager.http." 368 + "InstrumentManagerHTTPConnector"; 369 } 370 371 try 373 { 374 Class clazz = Class.forName( className ); 375 DefaultInstrumentManagerConnector connector = 376 (DefaultInstrumentManagerConnector)clazz.newInstance(); 377 378 connector.setInstrumentManager( this ); 380 ContainerUtil.enableLogging( connector, connLogger ); 381 ContainerUtil.configure( connector, connectorConf ); 382 ContainerUtil.start( connector ); 383 if ( connector instanceof Instrumentable ) 384 { 385 Instrumentable inst = (Instrumentable)connector; 386 registerInstrumentable( inst, 387 m_instrumentableName + ".connector." + inst.getInstrumentableName() ); 388 } 389 390 m_connectors.add( connector ); 391 } 392 catch ( Exception e ) 393 { 394 String msg = "Unable to create connector because: " + e; 395 396 if ( connectorConf.getAttributeAsBoolean( "optional", true ) ) 398 { 399 getLogger().warn( msg ); 400 } 401 else 402 { 403 throw new ConfigurationException( msg ); 404 } 405 } 406 } 407 } 408 } 409 410 413 418 public void initialize() 419 throws Exception  420 { 421 if( m_runner == null ) 422 { 423 m_runner = new Thread ( this, "InstrumentManagerRunner" ); 424 m_runner.start(); 425 } 426 } 427 428 431 434 public void dispose() 435 { 436 if( m_runner != null ) 437 { 438 m_runner = null; 439 } 440 441 for ( Iterator iter = m_connectors.iterator(); iter.hasNext(); ) 443 { 444 DefaultInstrumentManagerConnector connector = 445 (DefaultInstrumentManagerConnector)iter.next(); 446 try 447 { 448 ContainerUtil.stop( connector ); 449 ContainerUtil.dispose( connector ); 450 } 451 catch ( Exception e ) 452 { 453 getLogger().error( "Encountered an unexpected error shutting down a connector", e ); 454 } 455 } 456 457 saveState(); 458 } 459 460 463 474 public void registerInstrumentable( Instrumentable instrumentable, String instrumentableName ) 475 throws Exception  476 { 477 getLogger().debug( "Registering Instrumentable: " + instrumentableName ); 478 479 m_registrationsInstrument.increment(); 480 481 synchronized( m_semaphore ) 482 { 483 int pos = instrumentableName.indexOf( '.' ); 487 if ( pos >= 0 ) 488 { 489 String parentName = instrumentableName.substring( 0, pos ); 490 String childName = 491 instrumentableName.substring( pos + 1 ); 492 InstrumentableProxy instrumentableProxy = 493 (InstrumentableProxy)m_instrumentableProxies.get( parentName ); 494 if ( instrumentableProxy == null ) 495 { 496 instrumentableProxy = new InstrumentableProxy( 498 this, null, parentName, parentName ); 499 instrumentableProxy.enableLogging( getLogger() ); 500 incrementInstrumentableCount(); 501 m_instrumentableProxies.put( parentName, instrumentableProxy ); 504 505 m_instrumentableProxyArray = null; 507 m_instrumentableDescriptorArray = null; 508 509 registerDummyInstrumentableInner( 511 instrumentable, instrumentableProxy, parentName, childName ); 512 } 513 else 514 { 515 registerDummyInstrumentableInner( 517 instrumentable, instrumentableProxy, parentName, childName ); 518 } 519 } else { 520 InstrumentableProxy instrumentableProxy = 525 (InstrumentableProxy)m_instrumentableProxies.get( instrumentableName ); 526 if( instrumentableProxy == null ) 527 { 528 instrumentableProxy = new InstrumentableProxy( 530 this, null, instrumentableName, instrumentableName ); 531 instrumentableProxy.enableLogging( getLogger() ); 532 incrementInstrumentableCount(); 533 m_instrumentableProxies.put( instrumentableName, instrumentableProxy ); 536 537 m_instrumentableProxyArray = null; 539 m_instrumentableDescriptorArray = null; 540 541 registerInstrumentableInner( 543 instrumentable, instrumentableProxy, instrumentableName ); 544 } 545 else 546 { 547 registerInstrumentableInner( 549 instrumentable, instrumentableProxy, instrumentableName ); 550 } 551 } 552 } 553 554 stateChanged(); 555 } 556 557 560 565 public String getName() 566 { 567 return m_name; 568 } 569 570 575 public String getDescription() 576 { 577 return m_description; 578 } 579 580 601 public void registerNameTranslation( String source, String target ) 602 throws IllegalArgumentException  603 { 604 synchronized( m_semaphore ) 605 { 606 registerNameTranslationInner( source, target ); 607 } 608 } 609 610 621 public InstrumentableDescriptor getInstrumentableDescriptor( String instrumentableName ) 622 throws NoSuchInstrumentableException 623 { 624 InstrumentableProxy proxy = getInstrumentableProxy( instrumentableName ); 625 if( proxy == null ) 626 { 627 throw new NoSuchInstrumentableException( 628 "No instrumentable can be found using name: " + instrumentableName ); 629 } 630 631 return proxy.getDescriptor(); 632 } 633 634 640 public InstrumentableDescriptor[] getInstrumentableDescriptors() 641 { 642 InstrumentableDescriptor[] descriptors = m_instrumentableDescriptorArray; 643 if( descriptors == null ) 644 { 645 descriptors = updateInstrumentableDescriptorArray(); 646 } 647 return descriptors; 648 } 649 650 661 public InstrumentableDescriptor locateInstrumentableDescriptor( String instrumentableName ) 662 throws NoSuchInstrumentableException 663 { 664 InstrumentableProxy instrumentableProxy = 665 locateDeepestInstrumentableProxy( instrumentableName ); 666 if ( instrumentableProxy != null ) 667 { 668 if ( instrumentableProxy.getName().equals( instrumentableName ) ) 669 { 670 return instrumentableProxy.getDescriptor(); 672 } 673 } 674 675 throw new NoSuchInstrumentableException( 677 "No instrumentable can be found with the name: " + instrumentableName ); 678 } 679 680 691 public InstrumentDescriptor locateInstrumentDescriptor( String instrumentName ) 692 throws NoSuchInstrumentException 693 { 694 InstrumentableProxy instrumentableProxy = 695 locateDeepestInstrumentableProxy( instrumentName ); 696 if ( instrumentableProxy != null ) 697 { 698 InstrumentProxy instrumentProxy = 700 instrumentableProxy.getInstrumentProxy( instrumentName ); 701 if ( instrumentProxy != null ) 702 { 703 if ( instrumentProxy.getName().equals( instrumentName ) ) 704 { 705 return instrumentProxy.getDescriptor(); 707 } 708 } 709 } 710 711 throw new NoSuchInstrumentException( 713 "No instrument can be found with the name: " + instrumentName ); 714 } 715 716 727 public InstrumentSampleDescriptor locateInstrumentSampleDescriptor( String sampleName ) 728 throws NoSuchInstrumentSampleException 729 { 730 InstrumentableProxy instrumentableProxy = 731 locateDeepestInstrumentableProxy( sampleName ); 732 if ( instrumentableProxy != null ) 733 { 734 InstrumentProxy instrumentProxy = 736 instrumentableProxy.getInstrumentProxy( sampleName ); 737 if ( instrumentProxy != null ) 738 { 739 InstrumentSample sample = instrumentProxy.getInstrumentSample( sampleName ); 741 if ( sample != null ) 742 { 743 if ( sample.getName().equals( sampleName ) ) 744 { 745 |