1 19 20 package org.apache.excalibur.instrument.manager.impl; 21 22 import java.io.PrintWriter ; 23 import java.util.Arrays ; 24 import java.util.Comparator ; 25 import java.util.HashMap ; 26 27 import org.apache.avalon.framework.configuration.Configurable; 28 import org.apache.avalon.framework.configuration.Configuration; 29 import org.apache.avalon.framework.configuration.ConfigurationException; 30 import org.apache.avalon.framework.logger.AbstractLogEnabled; 31 import org.apache.avalon.framework.logger.Logger; 32 33 import org.apache.excalibur.instrument.manager.CounterInstrumentListener; 34 import org.apache.excalibur.instrument.manager.DefaultInstrumentManager; 35 import org.apache.excalibur.instrument.manager.InstrumentDescriptor; 36 import org.apache.excalibur.instrument.manager.InstrumentListener; 37 import org.apache.excalibur.instrument.manager.InstrumentSampleDescriptor; 38 import org.apache.excalibur.instrument.manager.InstrumentSampleUtils; 39 import org.apache.excalibur.instrument.manager.ValueInstrumentListener; 40 41 55 public class InstrumentProxy 56 extends AbstractLogEnabled 57 implements org.apache.excalibur.instrument.InstrumentProxy, Configurable 58 { 59 60 private InstrumentableProxy m_instrumentableProxy; 61 62 63 private boolean m_configured; 64 65 66 private boolean m_registered; 67 68 69 private String m_name; 70 71 72 private String m_description; 73 74 75 private InstrumentDescriptor m_descriptor; 76 77 78 private int m_type; 79 80 81 private InstrumentListener[] m_listeners; 82 83 84 private HashMap m_samples = new HashMap (); 85 86 87 private InstrumentSample[] m_sampleArray; 88 89 90 private InstrumentSampleDescriptor[] m_sampleDescriptorArray; 91 92 93 private Logger m_valueLogger; 94 95 96 private int m_lastValue; 97 98 99 private int m_stateVersion; 100 101 104 112 InstrumentProxy( InstrumentableProxy instrumentableProxy, 113 String name, 114 String description ) 115 { 116 m_instrumentableProxy = instrumentableProxy; 117 m_name = name; 118 m_description = description; 119 120 m_descriptor = new InstrumentDescriptorImpl( this ); 122 } 123 124 127 public void enableLogging( Logger logger ) 128 { 129 super.enableLogging( logger ); 130 131 m_valueLogger = logger.getChildLogger( "values" ); 134 } 135 136 139 149 public void configure( Configuration configuration ) 150 throws ConfigurationException 151 { 152 synchronized(this) 153 { 154 m_description = configuration.getAttribute( "description", m_description ); 156 157 if ( getLogger().isDebugEnabled() ) 158 { 159 getLogger().debug( "Configuring Instrument: " + m_name + " as \"" + 160 m_description + "\"" ); 161 } 162 163 m_configured = true; 164 165 Configuration[] sampleConfs = configuration.getChildren( "sample" ); 167 for ( int i = 0; i < sampleConfs.length; i++ ) 168 { 169 Configuration sampleConf = sampleConfs[i]; 170 171 int sampleType = InstrumentSampleUtils.resolveInstrumentSampleType( 172 sampleConf.getAttribute( "type" ) ); 173 long sampleInterval = sampleConf.getAttributeAsLong( "interval" ); 174 int sampleSize = sampleConf.getAttributeAsInteger( "size", 1 ); 175 176 String sampleName = InstrumentSampleUtils.generateFullInstrumentSampleName( 179 m_name, sampleType, sampleInterval, sampleSize ); 180 181 String defaultDescription = InstrumentSampleUtils.generateInstrumentSampleName( 182 sampleType, sampleInterval, sampleSize ); 183 String sampleDescription = 184 sampleConf.getAttribute( "description", defaultDescription ); 185 186 if ( getLogger().isDebugEnabled() ) 187 { 188 getLogger().debug( "Configuring InstrumentSample: " + sampleName + 189 " as \"" + sampleDescription + "\"" ); 190 } 191 192 String fullSampleName = InstrumentSampleUtils.generateFullInstrumentSampleName( 194 m_name, sampleType, sampleInterval, sampleSize ); 195 InstrumentSample sample = getInstrumentSample( fullSampleName ); 196 if ( sample == null ) 197 { 198 AbstractInstrumentSample instrumentSample = 199 (AbstractInstrumentSample)InstrumentSampleFactory.getInstrumentSample( this, 200 sampleType, sampleName, sampleInterval, sampleSize, sampleDescription, 0 ); 201 instrumentSample.enableLogging( getLogger() ); 202 instrumentSample.setConfigured(); 203 204 addInstrumentSample( instrumentSample ); 205 } 206 else 207 { 208 if ( sample instanceof AbstractInstrumentSample ) 210 { 211 AbstractInstrumentSample instrumentSample = 212 (AbstractInstrumentSample)sample; 213 instrumentSample.setConfigured(); 214 instrumentSample.makePermanent(); 216 } 217 else 218 { 219 getLogger().warn( 222 "Instrument sample was configured but already existed and " 223 + "could not be cast to an AbstractInstrumentSample. " 224 + "Name: " + fullSampleName + ", Class: " 225 + sample.getClass().getName() ); 226 } 227 } 228 } 229 } 230 } 231 232 235 241 public boolean isActive() { 242 return m_listeners != null; 243 } 244 245 252 public void increment( int count ) 253 { 254 if ( m_type != DefaultInstrumentManager.INSTRUMENT_TYPE_COUNTER ) 255 { 256 throw new IllegalStateException ( 258 "The proxy is not configured to handle CounterInstruments." ); 259 } 260 261 InstrumentListener[] listeners = m_listeners; 263 if ( listeners != null ) 264 { 265 if ( m_valueLogger.isDebugEnabled() ) 266 { 267 m_valueLogger.debug( "increment() called for Instrument, " + m_name ); 268 } 269 270 long time = System.currentTimeMillis(); 271 for ( int i = 0; i < listeners.length; i++ ) 272 { 273 CounterInstrumentListener listener = 274 (CounterInstrumentListener)listeners[i]; 275 listener.increment( getName(), count, time ); 276 } 277 } 278 } 279 280 287 public void setValue( int value ) 288 { 289 if ( m_type != DefaultInstrumentManager.INSTRUMENT_TYPE_VALUE ) 290 { 291 throw new IllegalStateException ( 293 "The proxy is not configured to handle ValueInstruments." ); 294 } 295 296 m_lastValue = value; 300 301 InstrumentListener[] listeners = m_listeners; 303 if ( listeners != null ) 304 { 305 if ( m_valueLogger.isDebugEnabled() ) 306 { 307 m_valueLogger.debug( "setValue( " + value + " ) called for Instrument, " + m_name ); 308 } 309 310 long time = System.currentTimeMillis(); 311 for ( int i = 0; i < listeners.length; i++ ) 312 { 313 ValueInstrumentListener listener = 314 (ValueInstrumentListener)listeners[i]; 315 listener.setValue( getName(), value, time ); 316 } 317 } 318 } 319 320 323 328 InstrumentableProxy getInstrumentableProxy() 329 { 330 return m_instrumentableProxy; 331 } 332 333 339 boolean isConfigured() 340 { 341 return m_configured; 342 } 343 344 350 boolean isRegistered() 351 { 352 return m_registered; 353 } 354 355 359 void setRegistered() 360 { 361 if ( !m_registered ) 362 { 363 m_registered = true; 364 stateChanged(); 365 } 366 } 367 368 375 String getName() 376 { 377 return m_name; 378 } 379 380 387 void setDescription( String description ) 388 { 389 String oldDescription = m_description; if ( ( oldDescription == description ) || ( ( description != null ) && description.equals( oldDescription ) ) ) 391 { 392 } 394 else 395 { 396 m_description = description; 397 stateChanged(); 398 } 399 } 400 401 406 String getDescription() 407 { 408 return m_description; 409 } 410 411 416 InstrumentDescriptor getDescriptor() 417 { 418 return m_descriptor; 419 } 420 421 426 void setType( int type ) 427 { 428 synchronized(this) 429 { 430 if ( m_type != DefaultInstrumentManager.INSTRUMENT_TYPE_NONE ) 431 { 432 throw new IllegalStateException ( "Type already set." ); 433 } 434 switch ( type ) 435 { 436 case DefaultInstrumentManager.INSTRUMENT_TYPE_COUNTER: 437 case DefaultInstrumentManager.INSTRUMENT_TYPE_VALUE: 438 m_type = type; 439 break; 440 default: 441 throw new IllegalStateException ( type + " is not a valid type." ); 442 } 443 } 444 } 445 446 451 int getType() 452 { 453 return m_type; 454 } 455 456 466 void addCounterInstrumentListener( CounterInstrumentListener listener ) 467 { 468 if ( m_type != DefaultInstrumentManager.INSTRUMENT_TYPE_COUNTER ) 469 { 470 throw new IllegalStateException ( 472 "The proxy is not configured to handle CounterInstruments." ); 473 } 474 475 if ( getLogger().isDebugEnabled() ) 476 { 477 getLogger().debug( "A CounterInstrumentListener was added to Instrument, " + 478 m_name + " : " + listener.getClass().getName() ); 479 } 480 481 addInstrumentListener( listener ); 482 } 483 484 493 void removeCounterInstrumentListener( CounterInstrumentListener listener ) 494 { 495 if ( m_type != DefaultInstrumentManager.INSTRUMENT_TYPE_COUNTER ) 496 { 497 throw new IllegalStateException ( 499 "The proxy is not configured to handle CounterInstruments." ); 500 } 501 502 if ( getLogger().isDebugEnabled() ) 503 { 504 getLogger().debug( "A CounterInstrumentListener was removed from Instrument, " + 505 m_name + " : " + listener.getClass().getName() ); 506 } 507 508 removeInstrumentListener( listener ); 509 } 510 511 521 void addValueInstrumentListener( ValueInstrumentListener listener ) 522 { 523 if ( m_type != DefaultInstrumentManager.INSTRUMENT_TYPE_VALUE ) 524 { 525 throw new IllegalStateException ( 527 "The proxy is not configured to handle ValueInstruments." ); 528 } 529 530 if ( getLogger().isDebugEnabled() ) 531 { 532 getLogger().debug( "A ValueInstrumentListener was added to Instrument, " + m_name + 533 " : " + listener.getClass().getName() ); 534 } 535 536 addInstrumentListener( listener ); 537 538 long time = System.currentTimeMillis(); 540 listener.setValue( getName(), m_lastValue, time ); 541 } 542 543 552 void removeValueInstrumentListener( ValueInstrumentListener listener ) 553 { 554 if ( m_type != DefaultInstrumentManager.INSTRUMENT_TYPE_VALUE ) 555 { 556 throw new IllegalStateException ( 558 "The proxy is not configured to handle ValueInstruments." ); 559 } 560 561 if ( getLogger().isDebugEnabled() ) 562 { 563 getLogger().debug( "A ValueInstrumentListener was removed from Instrument, " + m_name + 564 " : " + listener.getClass().getName() ); 565 } 566 567 removeInstrumentListener( listener ); 568 } 569 570 575 private void addInstrumentSample( InstrumentSample instrumentSample ) 576 { 577 synchronized(this) 578 { 579 if ( m_type == DefaultInstrumentManager.INSTRUMENT_TYPE_NONE ) 582 { 583 setType( instrumentSample.getInstrumentType() ); 584 } 585 else if ( m_type != instrumentSample.getInstrumentType() ) 586 { 587 throw new IllegalStateException ( "The sample '" + instrumentSample.getName() + 589 "' had its type set to " + getTypeName( m_type ) + 590 " by another sample. This sample has a type of " + 591 getTypeName( instrumentSample.getInstrumentType() ) + " and is not compatible." ); 592 } 593 594 String sampleName = instrumentSample.getName(); 596 if ( m_samples.get( sampleName ) != null ) 597 { 598 throw new IllegalStateException ( "More than one sample with the same name, '" + 599 sampleName + "', can not be configured." ); 600 } 601 602 m_samples.put( sampleName, instrumentSample ); 604 605 m_sampleArray = null; 607 m_sampleDescriptorArray = null; 608 609 switch ( m_type ) 611 { 612 case DefaultInstrumentManager.INSTRUMENT_TYPE_COUNTER: 613 addCounterInstrumentListener( (CounterInstrumentSample)instrumentSample ); 614 break; 615 616 case DefaultInstrumentManager.INSTRUMENT_TYPE_VALUE: 617 addValueInstrumentListener( (AbstractValueInstrumentSample)instrumentSample ); 618 break; 619 620 default: 621 throw new IllegalStateException ( 622 "Don't know how to deal with the type: " + m_type ); 623 } 624 } 625 626 if ( instrumentSample.getLeaseExpirationTime() == 0 ) 627 { 628 m_instrumentableProxy.getInstrumentManager().incrementPermanentSampleCount(); 629 } 630 else 631 { 632 m_instrumentableProxy.getInstrumentManager().incrementLeasedSampleCount(); 633 } 634 635 stateChanged(); 636 } 637 638 643 void removeInstrumentSample( InstrumentSample instrumentSample ) 644 { 645 synchronized(this) 646 { 647 switch ( m_type ) 649 { 650 case DefaultInstrumentManager.INSTRUMENT_TYPE_COUNTER: 651 removeCounterInstrumentListener( (CounterInstrumentSample)instrumentSample ); 652 break; 653 654 case DefaultInstrumentManager.INSTRUMENT_TYPE_VALUE: 655 removeValueInstrumentListener( (AbstractValueInstrumentSample)instrumentSample ); 656 break; 657 658 default: 659 throw new IllegalStateException ( 660 "Don't know how to deal with the type: " + m_type ); 661 } 662 663 m_samples.remove( instrumentSample.getName() ); 665 666 m_sampleArray = null; 668 m_sampleDescriptorArray = null; 669 } 670 671 m_instrumentableProxy.getInstrumentManager().decrementLeasedSampleCount(); 672 673 stateChanged(); 674 } 675 676 683 InstrumentSample getInstrumentSample( String instrumentSampleName ) 684 { 685 synchronized(this) 686 { 687 return (InstrumentSample)m_samples.get( instrumentSampleName ); 688 } 689 } 690 691 696 InstrumentSample[] getInstrumentSamples() 697 { 698 InstrumentSample[] samples = m_sampleArray; 699 if ( samples == null ) 700 { 701 samples = updateInstrumentSampleArray(); 702 } 703 return samples; 704 } 705 706 728 InstrumentSample createInstrumentSample( String sampleDescription, 729 long sampleInterval, 730 int sampleSize, 731 long sampleLease, 732 int sampleType ) 733 { 734 if ( getLogger().isDebugEnabled() ) 735 { 736 getLogger().debug( "Create new sample for " + m_name + ": interval=" + sampleInterval + 737 ", size=" + sampleSize + ", lease=" + sampleLease + ", type=" + 738 InstrumentSampleUtils.getInstrumentSampleTypeName( sampleType ) ); 739 } 740 741 DefaultInstrumentManagerImpl manager = m_instrumentableProxy.getInstrumentManager(); 742 743 sampleSize = Math.max( 1, Math.min( sampleSize, manager.getMaxLeasedSampleSize() ) ); 745 746 String sampleName = InstrumentSampleUtils.generateFullInstrumentSampleName( 748 m_name, sampleType, sampleInterval, sampleSize ); 749 750 InstrumentSample instrumentSample; 751 synchronized( this ) 752 { 753 instrumentSample = getInstrumentSample( sampleName ); 755 if ( instrumentSample != null ) 756 { 757 instrumentSample.extendLease( sampleLease ); 759 } 760 else 761 { 762 764 boolean expired = false; 766 sampleLease = 767 Math.max( 1, Math.min( sampleLease, manager.getMaxLeasedSampleLease() ) ); 768 if ( ( manager.getLeaseSampleCount() >= manager.getMaxLeasedSamples() ) 769 || ( sampleLease == 1 ) ) 770 { 771 sampleLease = 1; 774 expired = true; 775 } 776 777 instrumentSample = InstrumentSampleFactory.getInstrumentSample( 778 this, sampleType, sampleName, sampleInterval, sampleSize, 779 sampleDescription, sampleLease ); 780 instrumentSample.enableLogging( getLogger() ); 781 782 if ( !expired ) 784 { 785 m_instrumentableProxy.getInstrumentManager().incrementLeaseRequests(); 786 787 addInstrumentSample( instrumentSample ); 788 789 getInstrumentableProxy().getInstrumentManager(). 791 registerLeasedInstrumentSample( instrumentSample ); 792 } 793 } 794 } 795 796 return instrumentSample; 797 } 798 799 806 InstrumentSampleDescriptor[] getInstrumentSampleDescriptors() 807 { 808 InstrumentSampleDescriptor[] descriptors = m_sampleDescriptorArray; 809 if ( descriptors == null ) 810 { 811 descriptors = updateInstrumentSampleDescriptorArray(); 812 } 813 return descriptors; 814 } 815 816 825 int getStateVersion() 826 { 827 return m_stateVersion; 828 } 829 830 837 private void addInstrumentListener( InstrumentListener listener ) 838 { 839 synchronized(this) 840 { 841 InstrumentListener[] oldListeners = m_listeners; 846 InstrumentListener[] newListeners; 847 if ( oldListeners == null ) 848 { 849 newListeners = new InstrumentListener[] { listener }; 850 } 851 else 852 { 853 newListeners = new InstrumentListener[ oldListeners.length + 1 ]; 854 System.arraycopy( oldListeners, 0, newListeners, 0, oldListeners.length ); 855 newListeners[ oldListeners.length ] = listener; 856 } 857 858 m_listeners = newListeners; 860 } 861 } 862 863 870 private void removeInstrumentListener( InstrumentListener listener ) 871 { 872 synchronized(this) 873 { 874 InstrumentListener[] oldListeners = m_listeners; 879 InstrumentListener[] newListeners; 880 if ( oldListeners == null ) 881 { 882 newListeners = null; 885 } 886 else if ( oldListeners.length == 1 ) 887 { 888 if ( oldListeners[0] == listener ) 889 { 890 newListeners = null; 891 } 892 else 893 { 894 newListeners = oldListeners; 896 } 897 } 898 else 899 { 900 int pos = -1; 902 for ( int i = 0; i < oldListeners.length; i++ ) 903 { 904 if ( oldListeners[i] == listener ) 905 { 906 pos = i; 907 break; 908 } 909 } 910 911 if ( pos < 0 ) 912 { 913 newListeners = oldListeners; 915 } 916 else 917 { 918 newListeners = new InstrumentListener[ oldListeners.length - 1 ]; 919 if ( pos > 0 ) 920 { 921 System.arraycopy( oldListeners, 0, newListeners, 0, pos ); 923 } 924 if ( pos < oldListeners.length - 1 ) 925 { 926 System.arraycopy( oldListeners, pos + 1, 928 newListeners, pos, oldListeners.length - 1 - pos ); 929 } 930 } 931 } 932 933 m_listeners = newListeners; 935 } 936 } 937 938 944 private InstrumentSample[] updateInstrumentSampleArray() 945 { 946 synchronized(this) 947 { 948 InstrumentSample[] sampleArray = new InstrumentSample[ m_samples.size() ]; 949 m_samples.values().toArray( sampleArray ); 950 951 Arrays.sort( sampleArray, new Comparator () 955 { 956 public int compare( Object o1, Object o2 ) 957 { 958 return ((InstrumentSample)o1).getDescription(). 959 compareTo( ((InstrumentSample)o2).getDescription() ); 960 } 961 962 public boolean equals( Object obj ) 963 { 964 return false; 965 } 966 } ); 967 968 969 m_sampleArray = sampleArray; 972 973 return sampleArray; 974 } 975 } 976 977 983 private InstrumentSampleDescriptor[] updateInstrumentSampleDescriptorArray() 984 { 985 synchronized(this) 986 { 987 InstrumentSample[] sampleArray = m_sampleArray; 991 if ( sampleArray == null ) 992 { 993 sampleArray = updateInstrumentSampleArray(); 994 } 995 996 InstrumentSampleDescriptor[] sampleDescriptorArray = 997 new InstrumentSampleDescriptor[ m_sampleArray.length ]; 998 for ( int i = 0; i < sampleArray.length; i++ ) 999 { 1000 sampleDescriptorArray[i] = sampleArray[i].getDescriptor(); 1001 } 1002 1003 m_sampleDescriptorArray = sampleDescriptorArray; 1006 1007 return sampleDescriptorArray; 1008 } 1009 } 1010 1011 1016 void writeState( PrintWriter out ) 1017 { 1018 1021 InstrumentSample[] samples = getInstrumentSamples(); 1023 for ( int i = 0; i < samples.length; i++ ) 1024 { 1025 samples[i].writeState( out ); 1026 } 1027 } 1028 1029 1041 InstrumentSample loadSampleState( Configuration state ) throws ConfigurationException 1042 { 1043 InstrumentSample sample; 1045 synchronized( this ) 1046 { 1047 Configuration instrumentSampleConf = state; 1048 1049 int sampleType = InstrumentSampleUtils.resolveInstrumentSampleType( 1050 instrumentSampleConf.getAttribute( "type" ) ); 1051 long sampleInterval = instrumentSampleConf.getAttributeAsLong( "interval" ); 1052 int sampleSize = instrumentSampleConf.getAttributeAsInteger( "size", 1 ); 1053 1054 String fullSampleName = InstrumentSampleUtils.generateFullInstrumentSampleName( 1057 m_name, sampleType, sampleInterval, sampleSize ); 1058 sample = getInstrumentSample( fullSampleName ); 1059 if ( sample == null ) 1060 { 1061 long leaseExpirationTime = 1063 instrumentSampleConf.getAttributeAsLong( "lease-expiration", 0 ); 1064 if ( leaseExpirationTime > 0 ) 1065 { 1066 1067 String sampleName = InstrumentSampleUtils.generateInstrumentSampleName( 1068 sampleType, sampleInterval, sampleSize ); 1069 String sampleDescription = 1070 instrumentSampleConf.getAttribute( "description", sampleName ); 1071 1072 AbstractInstrumentSample instrumentSample = 1076 (AbstractInstrumentSample)InstrumentSampleFactory.getInstrumentSample( 1077 this, sampleType, fullSampleName, sampleInterval, sampleSize, 1078 sampleDescription, 1 ); 1079 instrumentSample.enableLogging( getLogger() ); 1080 instrumentSample.loadState( instrumentSampleConf ); 1081 1082 addInstrumentSample( instrumentSample ); 1083 1084 sample = instrumentSample; 1085 } 1086 else 1087 { 1088 getLogger().info( "InstrumentSample entry ignored while loading state " + 1090 "because the sample does not exist: " + fullSampleName ); 1091 } 1092 } 1093 else 1094 { 1095 sample.loadState( instrumentSampleConf ); 1096 } 1097 } 1098 1099 1101 return sample; 1102 } 1103 1104 1107 protected void stateChanged() 1108 { 1109 m_stateVersion++; 1110 1111 m_instrumentableProxy.stateChanged(); 1113 } 1114 1115 1122 public static String getTypeName( int type ) 1123 { 1124 switch ( type ) 1125 { 1126 case DefaultInstrumentManager.INSTRUMENT_TYPE_NONE: 1127 return "none"; 1128 case DefaultInstrumentManager.INSTRUMENT_TYPE_COUNTER: 1129 return "counter"; 1130 case DefaultInstrumentManager.INSTRUMENT_TYPE_VALUE: 1131 return "value"; 1132 default: 1133 throw new IllegalArgumentException ( type + " is not a known Instrument type." ); 1134 } 1135 } 1136} 1137 | Popular Tags |