1 19 20 package org.apache.excalibur.instrument.manager.impl; 21 22 import java.io.PrintWriter ; 23 import java.util.StringTokenizer ; 24 import java.util.Calendar ; 25 26 import org.apache.avalon.framework.configuration.Configuration; 27 import org.apache.avalon.framework.configuration.ConfigurationException; 28 import org.apache.avalon.framework.logger.AbstractLogEnabled; 29 30 import org.apache.excalibur.instrument.manager.InstrumentSampleDescriptor; 31 import org.apache.excalibur.instrument.manager.InstrumentSampleListener; 32 import org.apache.excalibur.instrument.manager.InstrumentSampleSnapshot; 33 import org.apache.excalibur.instrument.manager.InstrumentSampleUtils; 34 35 41 abstract class AbstractInstrumentSample 42 extends AbstractLogEnabled 43 implements InstrumentSample 44 { 45 46 private static long m_zoneOffset; 47 48 49 private InstrumentProxy m_instrumentProxy; 50 51 52 private boolean m_configured; 53 54 55 private String m_name; 56 57 58 private long m_interval; 59 60 61 private int m_size; 62 63 64 private String m_description; 65 66 67 private InstrumentSampleDescriptor m_descriptor; 68 69 73 private long m_maxAge; 74 75 76 protected long m_time; 77 78 79 private long m_leaseExpirationTime; 80 81 82 private boolean m_expired; 83 84 85 private int m_historyIndex; 86 87 88 private int[] m_historyOld; 89 90 91 private int[] m_historyNew; 92 93 94 private InstrumentSampleListener[] m_listeners; 95 96 97 private int m_stateVersion; 98 99 102 static 103 { 104 Calendar now = Calendar.getInstance(); 105 m_zoneOffset = now.get( Calendar.ZONE_OFFSET ); 106 } 107 108 111 123 protected AbstractInstrumentSample( InstrumentProxy instrumentProxy, 124 String name, 125 long interval, 126 int size, 127 String description, 128 long lease ) 129 { 130 m_instrumentProxy = instrumentProxy; 131 132 if( interval < 1 ) 133 { 134 throw new IllegalArgumentException ( "interval must be at least 1." ); 135 } 136 if( size < 1 ) 137 { 138 throw new IllegalArgumentException ( "size must be at least 1." ); 139 } 140 141 m_name = name; 142 m_interval = interval; 143 m_size = size; 144 m_description = description; 145 if( lease > 0 ) 146 { 147 m_leaseExpirationTime = System.currentTimeMillis() + lease; 148 } 149 else 150 { 151 m_leaseExpirationTime = 0; 153 } 154 155 m_maxAge = m_size * m_interval; 157 158 init( 0 ); 159 160 m_descriptor = new InstrumentSampleDescriptorImpl( this ); 162 } 163 164 167 172 public InstrumentProxy getInstrumentProxy() 173 { 174 return m_instrumentProxy; 175 } 176 177 183 public boolean isConfigured() 184 { 185 return m_configured; 186 } 187 188 193 public final String getName() 194 { 195 return m_name; 196 } 197 198 203 public final long getInterval() 204 { 205 return m_interval; 206 } 207 208 213 public final int getSize() 214 { 215 return m_size; 216 } 217 218 223 public final String getDescription() 224 { 225 return m_description; 226 } 227 228 233 public InstrumentSampleDescriptor getDescriptor() 234 { 235 return m_descriptor; 236 } 237 238 245 public final int getValue() 246 { 247 boolean update; 248 int value; 249 long time; 250 251 synchronized( this ) 252 { 253 long now = System.currentTimeMillis(); 254 update = update( now, false ); 255 value = getValueInner(); 256 time = m_time; 257 } 258 259 if( update ) 260 { 261 updateListeners( value, time ); 262 } 263 return value; 264 } 265 266 271 public final long getTime() 272 { 273 boolean update; 274 int value; 275 long time; 276 277 synchronized( this ) 278 { 279 long now = System.currentTimeMillis(); 280 update = update( now, false ); 281 value = getValueInner(); 282 time = m_time; 283 } 284 285 if( update ) 286 { 287 updateListeners( value, time ); 288 } 289 return time; 290 } 291 292 298 public long getLeaseExpirationTime() 299 { 300 return m_leaseExpirationTime; 301 } 302 303 312 public long extendLease( long lease ) 313 { 314 DefaultInstrumentManagerImpl manager = 315 m_instrumentProxy.getInstrumentableProxy().getInstrumentManager(); 316 317 lease = Math.max( 1, Math.min( lease, manager.getMaxLeasedSampleLease() ) ); 319 320 322 manager.incrementLeaseRequests(); 323 324 synchronized( this ) 325 { 326 if( ( m_leaseExpirationTime > 0 ) && ( !m_expired ) ) 328 { 329 long newLeaseExpirationTime = System.currentTimeMillis() + lease; 330 if( newLeaseExpirationTime > m_leaseExpirationTime ) 331 { 332 m_leaseExpirationTime = newLeaseExpirationTime; 333 stateChanged(); 334 } 335 } 336 337 return m_leaseExpirationTime; 338 } 339 } 340 341 346 public void expire() 347 { 348 update( m_leaseExpirationTime, false ); 350 351 m_expired = true; 352 } 353 354 359 public final InstrumentSampleSnapshot getSnapshot() 360 { 361 synchronized( this ) 362 { 363 long time = System.currentTimeMillis(); 364 update( time, false ); 365 366 return new InstrumentSampleSnapshot( 367 m_name, 368 m_interval, 369 m_size, 370 m_time, 371 getHistorySnapshot(), 372 m_stateVersion ); 373 } 374 } 375 376 385 public int getStateVersion() 386 { 387 return m_stateVersion; 388 } 389 390 396 public void addInstrumentSampleListener( InstrumentSampleListener listener ) 397 { 398 if( getLogger().isDebugEnabled() ) 399 { 400 getLogger().debug( "An InstrumentSampleListener was added to sample, " + m_name 401 + " : " + listener.getClass().getName() ); 402 } 403 404 synchronized( this ) 405 { 406 InstrumentSampleListener[] oldListeners = m_listeners; 411 InstrumentSampleListener[] newListeners; 412 if( oldListeners == null ) 413 { 414 newListeners = new InstrumentSampleListener[]{listener}; 415 } 416 else 417 { 418 newListeners = new InstrumentSampleListener[ oldListeners.length + 1 ]; 419 System.arraycopy( oldListeners, 0, newListeners, 0, oldListeners.length ); 420 newListeners[ oldListeners.length ] = listener; 421 } 422 423 m_listeners = newListeners; 425 } 426 } 427 428 434 public void removeInstrumentSampleListener( InstrumentSampleListener listener ) 435 { 436 if( getLogger().isDebugEnabled() ) 437 { 438 getLogger().debug( "An InstrumentSampleListener was removed from sample, " + m_name 439 + " : " + listener.getClass().getName() ); 440 } 441 442 synchronized( this ) 443 { 444 InstrumentSampleListener[] oldListeners = m_listeners; 449 InstrumentSampleListener[] newListeners; 450 if( oldListeners == null ) 451 { 452 newListeners = null; 455 } 456 else if( oldListeners.length == 1 ) 457 { 458 if( oldListeners[ 0 ] == listener ) 459 { 460 newListeners = null; 461 } 462 else 463 { 464 newListeners = oldListeners; 466 } 467 } 468 else 469 { 470 int pos = -1; 472 for( int i = 0; i < oldListeners.length; i++ ) 473 { 474 if( oldListeners[ i ] == listener ) 475 { 476 pos = i; 477 break; 478 } 479 } 480 481 if( pos < 0 ) 482 { 483 newListeners = oldListeners; 485 } 486 else 487 { 488 newListeners = new InstrumentSampleListener[ oldListeners.length - 1 ]; 489 if( pos > 0 ) 490 { 491 System.arraycopy( oldListeners, 0, newListeners, 0, pos ); 493 } 494 if( pos < oldListeners.length - 1 ) 495 { 496 System.arraycopy( oldListeners, pos + 1, 498 newListeners, pos, oldListeners.length - 1 - pos ); 499 } 500 } 501 } 502 503 m_listeners = newListeners; 505 } 506 } 507 508 516 protected void updateListeners( int value, long time ) 517 { 518 InstrumentSampleListener[] listeners = m_listeners; 520 if( listeners != null ) 521 { 522 for( int i = 0; i < listeners.length; i++ ) 523 { 524 listeners[ i ].setValue( getName(), value, time ); 525 } 526 } 527 } 528 529 534 public void writeState( PrintWriter out ) 535 { 536 if( ( !isConfigured() ) && ( getLeaseExpirationTime() <= 0 ) ) 539 { 540 return; 541 } 542 543 boolean update; 544 int value; 545 long time; 546 547 synchronized( this ) 548 { 549 550 long now = System.currentTimeMillis(); 552 update = update( now, false ); 553 value = getValueInner(); 554 time = m_time; 555 556 String history = getHistoryList(); 557 558 if( ( getLeaseExpirationTime() == 0 ) && ( history == null ) ) 559 { 560 } 564 else 565 { 566 out.print( "<sample name=\"" ); 568 out.print( XMLUtil.getXMLSafeString( m_name ) ); 569 out.print( "\" type=\"" ); 570 out.print( InstrumentSampleUtils.getInstrumentSampleTypeName( getType() ) ); 571 out.print( "\" interval=\"" ); 572 out.print( m_interval ); 573 out.print( "\" size=\"" ); 574 out.print( m_size ); 575 out.print( "\" time=\"" ); 576 out.print( m_time ); 577 out.print( "\"" ); 578 if( getLeaseExpirationTime() != 0 ) 579 { 580 out.print( " lease-expiration=\"" ); 581 out.print( getLeaseExpirationTime() ); 582 out.print( "\"" ); 583 584 out.print( " description=\"" ); 587 out.print( XMLUtil.getXMLSafeString( m_description ) ); 588 out.print( "\"" ); 589 } 590 591 writeStateAttributes( out ); 593 594 if ( history == null ) 595 { 596 out.println( "/>" ); 598 } 599 else 600 { 601 out.println( ">" ); 603 604 out.print( "<history>" ); 606 out.print( history ); 607 out.println( "</history>" ); 608 609 out.println( "</sample>" ); 611 } 612 } 613 } 614 615 if ( update ) 616 { 617 updateListeners( value, time ); 618 } 619 } 620 621 629 public final void loadState( Configuration state ) throws ConfigurationException 630 { 631 boolean update; 632 int sampleValue; 633 long sampleTime; 634 635 synchronized( this ) 636 { 637 long savedTime = m_time = state.getAttributeAsLong( "time" ); 639 640 642 long leaseExpirationTime = state.getAttributeAsLong( "lease-expiration", 0 ); 643 if ( ( m_leaseExpirationTime != 0 ) && ( leaseExpirationTime > m_leaseExpirationTime ) ) 644 { 645 m_leaseExpirationTime = leaseExpirationTime; 646 } 647 648 m_historyIndex = 0; 650 651 int[] sampleValues; 652 653 Configuration history = state.getChild( "history", false ); 657 if ( history == null ) 658 { 659 sampleValues = new int[0]; 661 } 662 else 663 { 664 String compactSamples = history.getValue(); 665 666 StringTokenizer st = new StringTokenizer ( compactSamples, "," ); 668 sampleValues = new int[ st.countTokens() ]; 669 670 for( int i = 0; i < sampleValues.length; i++ ) 671 { 672 String token = st.nextToken(); 673 try 674 { 675 sampleValues[ i ] = Integer.parseInt( token ); 676 } 677 catch( NumberFormatException e ) 678 { 679 throw new ConfigurationException( "The compact sample data could not be " + 680 "loaded, because of a number format " + 681 "problem '" + token + "', " + 682 "for InstrumentSample: " + 683 m_name, history ); 684 } 685 } 686 } 687 688 int value; 690 if( sampleValues.length > 0 ) 691 { 692 value = sampleValues[ 0 ]; 693 } 694 else 695 { 696 value = 0; 697 } 698 699 for( int i = 0; i < m_size - 1; i++ ) 700 { 701 if( i < sampleValues.length - 1 ) 702 { 703 m_historyOld[ m_size - 2 - i ] = sampleValues[ i + 1 ]; 704 } 705 else 706 { 707 m_historyOld[ m_size - 2 - i ] = 0; 708 } 709 } 710 711 loadState( value, state ); 712 713 long now = System.currentTimeMillis(); 715 update = update( now, true ); 716 sampleValue = getValueInner(); 717 sampleTime = m_time; 718 719 if( m_leaseExpirationTime > 0 ) 720 { 721 getInstrumentProxy().getInstrumentableProxy().getInstrumentManager(). 724 registerLeasedInstrumentSample( this ); 725 } 726 } 727 728 stateChanged(); 729 730 if ( update ) 731 { 732 updateListeners( sampleValue, sampleTime ); 733 } 734 } 735 736 739 742 void setConfigured() 743 { 744 m_configured = true; 745 } 746 747 752 private void init( int fillValue ) 753 { 754 m_time = calculateSampleTime( System.currentTimeMillis() ); 758 759 m_historyIndex = 0; 764 if ( m_historyOld == null ) 765 { 766 m_historyOld = new int[ m_size - 1 ]; 767 m_historyNew = new int[ m_size - 1 ]; 768 } 769 for ( int i = 0; i < m_historyOld.length; i++ ) 770 { 771 m_historyOld[i] = fillValue; 772 m_historyNew[i] = fillValue; 773 } 774 } 775 776 781 protected void writeStateAttributes( PrintWriter out ) 782 { 783 } 784 785 796 protected abstract void loadState( int value, Configuration state ) 797 throws ConfigurationException; 798 799 804 private long calculateSampleTime( long time ) 805 { 806 long offset = ( time + m_zoneOffset ) % m_interval; 811 return time - offset; 812 } 813 814 821 protected abstract int getValueInner(); 822 823 831 protected abstract void advanceToNextSample( boolean reset ); 832 833 838 protected abstract int getFillValue(); 839 840 850 protected boolean update( long time, boolean reset ) 851 { 852 if( m_expired ) 855 { 856 return false; 857 } 858 859 if( time - m_time >= m_interval ) 861 { 862 if( time - m_time >= m_maxAge ) 864 { 865 advanceToNextSample( reset ); 867 init( getFillValue() ); 868 } 869 else 870 { 871 while( time - m_time >= m_interval ) 873 { 874 m_historyNew[ m_historyIndex ] = getValueInner(); 876 877 m_time += m_interval; 879 advanceToNextSample( reset ); 880 m_historyIndex++; 881 882 if( m_historyIndex >= m_size - 1 ) 883 { 884 int[] tmp = m_historyOld; 886 m_historyOld = m_historyNew; 887 m_historyNew = tmp; 888 889 m_historyIndex = 0; 891 } 892 } 893 } 894 return true; 895 } 896 else 897 { 898 return false; 899 } 900 } 901 902 909 private int[] getHistorySnapshot() 910 { 911 int[] history = new int[ m_size ]; 915 916 int sizem1 = m_size - 1; 917 918 if( m_size > 1 ) 919 { 920 if( m_historyIndex < sizem1 ) 922 { 923 System.arraycopy( m_historyOld, m_historyIndex, history, 0, sizem1 - m_historyIndex ); 925 } 926 927 if( m_historyIndex > 0 ) 928 { 929 System.arraycopy( m_historyNew, 0, history, sizem1 - m_historyIndex, m_historyIndex ); 931 } 932 } 933 history[ m_size - 1 ] = getValueInner(); 935 936 return history; 937 } 938 939 946 private String getHistoryList() 947 { 948 int[] history = getHistorySnapshot(); 949 950 boolean found = false; 953 for ( int i = history.length - 1; i >= 0; i-- ) 954 { 955 if ( history[i] != 0 ) 956 { 957 found = true; 958 break; 959 } 960 } 961 962 if ( !found ) 963 { 964 return null; 965 } 966 967 StringBuffer sb = new StringBuffer (); 969 970 sb.append( history[ history.length - 1 ] ); 972 for( int i = history.length - 2; i >= 0; i-- ) 973 { 974 sb.append( ',' ); 975 sb.append( history[ i ] ); 976 } 977 978 return sb.toString(); 979 } 980 981 984 protected void stateChanged() 985 { 986 m_stateVersion++; 987 988 m_instrumentProxy.stateChanged(); 990 } 991 992 995 void makePermanent() 996 { 997 m_leaseExpirationTime = 0; 998 } 999 1000 1005 public String toString() 1006 { 1007 return "InstrumentSample[name=" + m_name + ", type=" + 1008 InstrumentSampleUtils.getInstrumentSampleTypeName( getType() ) + ", interval=" + 1009 m_interval + ", size=" + m_size + ", lease=" + m_leaseExpirationTime + "]"; 1010 } 1011} 1012 | Popular Tags |