| 1 50 package org.apache.excalibur.instrument.manager; 51 52 import java.io.ByteArrayOutputStream ; 53 import java.io.File ; 54 import java.io.FileInputStream ; 55 import java.io.FileOutputStream ; 56 import java.io.InputStream ; 57 import java.io.OutputStream ; 58 import java.util.ArrayList ; 59 import java.util.Arrays ; 60 import java.util.Comparator ; 61 import java.util.HashMap ; 62 import java.util.Iterator ; 63 64 import org.apache.avalon.framework.activity.Disposable; 65 import org.apache.avalon.framework.activity.Initializable; 66 import org.apache.avalon.framework.configuration.Configurable; 67 import org.apache.avalon.framework.configuration.Configuration; 68 import org.apache.avalon.framework.configuration.ConfigurationException; 69 import org.apache.avalon.framework.configuration.DefaultConfiguration; 70 import org.apache.avalon.framework.configuration.DefaultConfigurationBuilder; 71 import org.apache.avalon.framework.configuration.DefaultConfigurationSerializer; 72 import org.apache.avalon.framework.container.ContainerUtil; 73 import org.apache.avalon.framework.logger.AbstractLogEnabled; 74 import org.apache.avalon.framework.logger.Logger; 75 import org.apache.avalon.framework.service.ServiceException; 76 import org.apache.excalibur.instrument.AbstractInstrument; 77 import org.apache.excalibur.instrument.CounterInstrument; 78 import org.apache.excalibur.instrument.Instrument; 79 import org.apache.excalibur.instrument.InstrumentManager; 80 import org.apache.excalibur.instrument.Instrumentable; 81 import org.apache.excalibur.instrument.ValueInstrument; 82 import org.apache.excalibur.instrument.manager.interfaces.InstrumentManagerClient; 83 import org.apache.excalibur.instrument.manager.interfaces.NoSuchInstrumentException; 84 import org.apache.excalibur.instrument.manager.interfaces.NoSuchInstrumentSampleException; 85 import org.apache.excalibur.instrument.manager.interfaces.NoSuchInstrumentableException; 86 87 93 public class DefaultInstrumentManager 94 extends AbstractLogEnabled 95 implements Configurable, Initializable, Disposable, InstrumentManager, 96 Instrumentable, Runnable  97 { 98 public static final String INSTRUMENT_TOTAL_MEMORY = "total-memory"; 99 public static final String INSTRUMENT_FREE_MEMORY = "free-memory"; 100 public static final String INSTRUMENT_MEMORY = "memory"; 101 public static final String INSTRUMENT_ACTIVE_THREAD_COUNT = "active-thread-count"; 102 103 104 private String m_name; 105 106 107 private String m_description; 108 109 110 private Configuration m_configuration; 111 112 113 private ArrayList m_connectors = new ArrayList (); 114 115 116 private File m_stateFile; 117 118 119 private long m_stateInterval; 120 121 122 private long m_lastStateSave; 123 124 125 private Object m_semaphore = new Object (); 126 127 128 private HashMap m_instrumentableProxies = new HashMap (); 129 130 131 private InstrumentableProxy[] m_instrumentableProxyArray; 132 133 134 private InstrumentableDescriptorLocal[] m_instrumentableDescriptorArray; 135 136 137 private ArrayList m_leasedInstrumentSamples = new ArrayList (); 138 139 140 private InstrumentSample[] m_leasedInstrumentSampleArray; 141 142 146 private Thread m_runner; 147 148 149 private String m_instrumentableName = "instrument-manager"; 150 151 152 private ValueInstrument m_totalMemoryInstrument; 153 154 155 private ValueInstrument m_freeMemoryInstrument; 156 157 158 private ValueInstrument m_memoryInstrument; 159 160 161 private ValueInstrument m_activeThreadCountInstrument; 162 163 164 private int m_stateVersion; 165 166 169 177 public DefaultInstrumentManager( String name ) 178 { 179 this(); 180 } 181 182 185 public DefaultInstrumentManager() 186 { 187 m_totalMemoryInstrument = new ValueInstrument( INSTRUMENT_TOTAL_MEMORY ); 189 m_freeMemoryInstrument = new ValueInstrument( INSTRUMENT_FREE_MEMORY ); 190 m_memoryInstrument = new ValueInstrument( INSTRUMENT_MEMORY ); 191 m_activeThreadCountInstrument = new ValueInstrument( INSTRUMENT_ACTIVE_THREAD_COUNT ); 192 } 193 194 197 204 public void configure( Configuration configuration ) 205 throws ConfigurationException 206 { 207 synchronized( m_semaphore ) 208 { 209 m_configuration = configuration; 210 211 m_name = configuration.getChild( "name" ).getValue( "instrument-manager" ); 213 m_description = configuration.getChild( "description" ).getValue( m_name ); 214 215 Logger connLogger = getLogger().getChildLogger( "connector" ); 217 218 Configuration connectorsConf = configuration.getChild( "connectors" ); 220 Configuration[] connectorConfs = 221 connectorsConf.getChildren( "connector" ); 222 for( int i = 0; i < connectorConfs.length; i++ ) 223 { 224 Configuration connectorConf = connectorConfs[ i ]; 225 String className = connectorConf.getAttribute( "class" ); 226 if ( className.equals( "altrmi" ) ) 228 { 229 className = "org.apache.excalibur.instrument.manager.altrmi." 230 + "InstrumentManagerAltrmiConnector"; 231 } 232 233 try 235 { 236 Class clazz = Class.forName( className ); 237 InstrumentManagerConnector connector = 238 (InstrumentManagerConnector)clazz.newInstance(); 239 240 connector.setInstrumentManager( this ); 242 ContainerUtil.enableLogging( connector, connLogger ); 243 ContainerUtil.configure( connector, connectorConf ); 244 ContainerUtil.start( connector ); 245 246 m_connectors.add( connector ); 247 } 248 catch ( Exception e ) 249 { 250 throw new ConfigurationException( "Unable to create connector because: " 251 + e ); 252 } 253 } 254 255 Configuration instrumentablesConf = configuration.getChild( "instrumentables" ); 257 Configuration[] instrumentableConfs = 258 instrumentablesConf.getChildren( "instrumentable" ); 259 for( int i = 0; i < instrumentableConfs.length; i++ ) 260 { 261 Configuration instrumentableConf = instrumentableConfs[ i ]; 262 String instrumentableName = instrumentableConf.getAttribute( "name" ); 263 264 InstrumentableProxy instrumentableProxy = new InstrumentableProxy( 265 this, null, instrumentableName, instrumentableName ); 266 instrumentableProxy.enableLogging( getLogger() ); 267 instrumentableProxy.configure( instrumentableConf ); 268 m_instrumentableProxies.put( instrumentableName, instrumentableProxy ); 269 270 m_instrumentableProxyArray = null; 272 m_instrumentableDescriptorArray = null; 273 } 274 275 Configuration stateFileConf = configuration.getChild( "state-file" ); 277 m_stateInterval = stateFileConf.getAttributeAsLong( "interval", 60000 ); 278 279 String stateFile = stateFileConf.getValue( null ); 280 if( stateFile != null ) 281 { 282 m_stateFile = new File ( stateFile ); 283 if( m_stateFile.exists() ) 284 { 285 try 286 { 287 loadStateFromFile( m_stateFile ); 288 } 289 catch( Exception e ) 290 { 291 getLogger().error( 292 "Unable to load the instrument manager state. The configuration " + 293 "may have been corruptped. A backup may have been made in the same " + 294 "directory when it was saved.", e ); 295 } 296 } 297 } 298 } 299 } 300 301 304 309 public void initialize() 310 throws Exception  311 { 312 registerInstrumentable( this, getInstrumentableName() ); 314 315 if( m_runner == null ) 316 { 317 m_runner = new Thread ( this, "InstrumentManagerRunner" ); 318 m_runner.start(); 319 } 320 } 321 322 325 328 public void dispose() 329 { 330 if( m_runner != null ) 331 { 332 m_runner = null; 333 } 334 335 for ( Iterator iter = m_connectors.iterator(); iter.hasNext(); ) 337 { 338 InstrumentManagerConnector connector = (InstrumentManagerConnector)iter.next(); 339 try 340 { 341 ContainerUtil.stop( connector ); 342 ContainerUtil.dispose( connector ); 343 } 344 catch ( Exception e ) 345 { 346 getLogger().error( "Encountered an unexpected error shutting down a connector", e ); 347 } 348 } 349 350 saveState(); 351 } 352 353 356 367 public void registerInstrumentable( Instrumentable instrumentable, String instrumentableName ) 368 throws Exception  369 { 370 getLogger().debug( "Registering Instrumentable: " + instrumentableName ); 371 372 synchronized( m_semaphore ) 373 { 374 int pos = instrumentableName.indexOf( '.' ); 378 if ( pos >= 0 ) 379 { 380 String parentName = instrumentableName.substring( 0, pos ); 381 String childName = 382 instrumentableName.substring( pos + 1 ); 383 InstrumentableProxy instrumentableProxy = 384 (InstrumentableProxy)m_instrumentableProxies.get( parentName ); 385 if( instrumentableProxy == null ) 386 { 387 instrumentableProxy = new InstrumentableProxy( 389 this, null, parentName, parentName ); 390 instrumentableProxy.enableLogging( getLogger() ); 391 m_instrumentableProxies.put( parentName, instrumentableProxy ); 394 395 m_instrumentableProxyArray = null; 397 m_instrumentableDescriptorArray = null; 398 399 registerDummyInstrumentableInner( 401 instrumentable, instrumentableProxy, parentName, childName ); 402 } 403 else 404 { 405 registerDummyInstrumentableInner( 407 instrumentable, instrumentableProxy, parentName, childName ); 408 } 409 } else { 410 InstrumentableProxy instrumentableProxy = 415 (InstrumentableProxy)m_instrumentableProxies.get( instrumentableName ); 416 if( instrumentableProxy == null ) 417 { 418 instrumentableProxy = new InstrumentableProxy( 420 this, null, instrumentableName, instrumentableName ); 421 instrumentableProxy.enableLogging( getLogger() ); 422 m_instrumentableProxies.put( instrumentableName, instrumentableProxy ); 425 426 m_instrumentableProxyArray = null; 428 m_instrumentableDescriptorArray = null; 429 430 registerInstrumentableInner( 432 instrumentable, instrumentableProxy, instrumentableName ); 433 } 434 else 435 { 436 registerInstrumentableInner( 438 instrumentable, instrumentableProxy, instrumentableName ); 439 } 440 } 441 } 442 443 stateChanged(); 444 } 445 446 447 450 455 public String getName() 456 { 457 return m_name; 458 } 459 460 465 public String getDescription() 466 { 467 return m_description; 468 } 469 470 481 public InstrumentableDescriptorLocal getInstrumentableDescriptor( String instrumentableName ) 482 throws NoSuchInstrumentableException 483 { 484 InstrumentableProxy proxy = getInstrumentableProxy( instrumentableName ); 485 if( proxy == null ) 486 { 487 throw new NoSuchInstrumentableException( 488 "No instrumentable can be found using name: " + instrumentableName ); 489 } 490 491 return proxy.getDescriptor(); 492 } 493 494 501 public InstrumentableDescriptorLocal[] getInstrumentableDescriptors() 502 { 503 InstrumentableDescriptorLocal[] descriptors = m_instrumentableDescriptorArray; 504 if( descriptors == null ) 505 { 506 descriptors = updateInstrumentableDescriptorArray(); 507 } 508 return descriptors; 509 } 510 511 522 public InstrumentableDescriptorLocal locateInstrumentableDescriptor( String instrumentableName ) 523 throws NoSuchInstrumentableException 524 { 525 InstrumentableProxy instrumentableProxy = 526 locateDeepestInstrumentableProxy( instrumentableName ); 527 if ( instrumentableProxy != null ) 528 { 529 if ( instrumentableProxy.getName().equals( instrumentableName ) ) 530 { 531 return instrumentableProxy.getDescriptor(); 533 } 534 } 535 536 throw new NoSuchInstrumentableException( 538 "No instrumentable can be found with the name: " + instrumentableName ); 539 } 540 541 551 public InstrumentDescriptorLocal locateInstrumentDescriptor( String instrumentName ) 552 throws NoSuchInstrumentException 553 { 554 InstrumentableProxy instrumentableProxy = 555 locateDeepestInstrumentableProxy( instrumentName ); 556 if ( instrumentableProxy != null ) 557 { 558 InstrumentProxy instrumentProxy = 560 instrumentableProxy.getInstrumentProxy( instrumentName ); 561 if ( instrumentProxy != null ) 562 { 563 if ( instrumentProxy.getName().equals( instrumentName ) ) 564 { 565 return instrumentProxy.getDescriptor(); 567 } 568 } 569 } 570 571 throw new NoSuchInstrumentException( 573 "No instrument can be found with the name: " + instrumentName ); 574 } 575 576 587 public InstrumentSampleDescriptorLocal locateInstrumentSampleDescriptor( String sampleName ) 588 throws NoSuchInstrumentSampleException 589 { 590 InstrumentableProxy instrumentableProxy = 591 locateDeepestInstrumentableProxy( sampleName ); 592 if ( instrumentableProxy != null ) 593 { 594 InstrumentProxy instrumentProxy = 596 instrumentableProxy.getInstrumentProxy( sampleName ); 597 if ( instrumentProxy != null ) 598 { 599 InstrumentSample sample = instrumentProxy.getInstrumentSample( sampleName ); 601 if ( sample != null ) 602 { 603 if ( sample.getName().equals( sampleName ) ) 604 { 605 return sample.getDescriptor(); 607 } 608 } 609 } 610 } 611 612 throw new NoSuchInstrumentException( 614 "No instrument sample can be found with the name: " + sampleName ); 615 } 616 617 626 int getStateVersion() 627 { 628 return m_stateVersion; 629 } 630 631 634 public void invokeGarbageCollection() 635 { 636 System.gc(); 637 } 638 639 640 641 648 public void loadStateFromFile( File stateFile ) 649 throws Exception  650 { 651 long now = System.currentTimeMillis(); 652 getLogger().debug( "Loading Instrument Manager state from: " + 653 stateFile.getAbsolutePath() ); 654 655 FileInputStream is = new FileInputStream ( stateFile ); 656 try 657 { 658 loadStateFromStream( is ); 659 } 660 finally 661 { 662 is.close(); 663 } 664 665 getLogger().debug( "Loading Instrument Manager state took " + 666 ( System.currentTimeMillis() - now ) + "ms." ); 667 } 668 669 676 public void loadStateFromStream( InputStream is ) 677 throws Exception  678 { 679 DefaultConfigurationBuilder builder = new DefaultConfigurationBuilder(); 681 Configuration stateConfig = builder.build( is ); 682 683 loadStateFromConfiguration( stateConfig ); 684 } 685 686 694 public void loadStateFromConfiguration( Configuration state ) 695 throws ConfigurationException 696 { 697 Configuration[] instrumentableConfs = state.getChildren( "instrumentable" ); 698 for( int i = 0; i < instrumentableConfs.length; i++ ) 699 { 700 Configuration instrumentableConf = instrumentableConfs[ i ]; 701 String instrumentableName = instrumentableConf.getAttribute( "name" ); 702 InstrumentableProxy instrumentableProxy = getInstrumentableProxy( instrumentableName ); 703 if( instrumentableProxy == null ) 704 { 705 instrumentableProxy = new InstrumentableProxy( 709 this, null, instrumentableName, instrumentableName ); 710 instrumentableProxy.enableLogging( getLogger() ); 711 m_instrumentableProxies.put( instrumentableName, instrumentableProxy ); 712 713 m_instrumentableProxyArray = null; 715 m_instrumentableDescriptorArray = null; 716 } 717 718 instrumentableProxy.loadState( instrumentableConf ); 719 } 720 721 stateChanged(); 722 } 723 724 733 public void saveStateToFile( File stateFile ) 734 throws Exception  735 { 736 long now = System.currentTimeMillis(); 737 getLogger().debug( "Saving Instrument Manager state to: " + stateFile.getAbsolutePath() ); 738 739 ByteArrayOutputStream os = new ByteArrayOutputStream (); 744 byte[] data; 745 try 746 { 747 saveStateToStream( os ); 748 data = os.toByteArray(); 749 } 750 finally 751 { 752 os.close(); 753 } 754 755 File renameFile = null; 758 boolean success = false; 759 if( stateFile.exists() ) 760 { 761 renameFile = new File ( stateFile.getAbsolutePath() + "." + now + ".backup" ); 762 stateFile.renameTo( renameFile ); 763 } 764 765 FileOutputStream fos = new FileOutputStream ( stateFile ); 767 try 768 { 769 fos.write( data ); 770 success = true; 771 } 772 finally 773 { 774 fos.close(); 775 776 if ( !success ) 777 { 778 stateFile.delete(); 780 } 781 782 if ( renameFile != null ) 784 { 785 if ( success ) 786 { 787 renameFile.delete(); 789 } 790 else 791 { 792 renameFile.renameTo( stateFile ); 794 } 795 |