1 50 package org.apache.excalibur.instrument.manager; 51 52 import java.util.StringTokenizer ; 53 54 import org.apache.avalon.framework.configuration.Configuration; 55 import org.apache.avalon.framework.configuration.ConfigurationException; 56 import org.apache.avalon.framework.configuration.DefaultConfiguration; 57 import org.apache.avalon.framework.logger.AbstractLogEnabled; 58 import org.apache.excalibur.instrument.manager.interfaces.InstrumentSampleSnapshot; 59 import org.apache.excalibur.instrument.manager.interfaces.InstrumentSampleUtils; 60 61 69 abstract class AbstractInstrumentSample 70 extends AbstractLogEnabled 71 implements InstrumentSample 72 { 73 74 private InstrumentProxy m_instrumentProxy; 75 76 77 private boolean m_configured; 78 79 80 private String m_name; 81 82 83 private long m_interval; 84 85 86 private int m_size; 87 88 89 private String m_description; 90 91 92 private InstrumentSampleDescriptorLocal m_descriptor; 93 94 98 private long m_maxAge; 99 100 101 protected long m_time; 102 103 104 private long m_leaseExpirationTime; 105 106 107 private boolean m_expired; 108 109 110 private int m_historyIndex; 111 112 113 private int[] m_historyOld; 114 115 116 private int[] m_historyNew; 117 118 119 private InstrumentSampleListener[] m_listeners; 120 121 122 private int m_stateVersion; 123 124 127 139 protected AbstractInstrumentSample( InstrumentProxy instrumentProxy, 140 String name, 141 long interval, 142 int size, 143 String description, 144 long lease ) 145 { 146 m_instrumentProxy = instrumentProxy; 147 148 if( interval < 1 ) 149 { 150 throw new IllegalArgumentException ( "interval must be at least 1." ); 151 } 152 if( size < 1 ) 153 { 154 throw new IllegalArgumentException ( "size must be at least 1." ); 155 } 156 157 m_name = name; 158 m_interval = interval; 159 m_size = size; 160 m_description = description; 161 if( lease > 0 ) 162 { 163 m_leaseExpirationTime = System.currentTimeMillis() + lease; 164 } 165 else 166 { 167 m_leaseExpirationTime = 0; 169 } 170 171 m_maxAge = m_size * m_interval; 173 174 init(); 175 176 m_descriptor = new InstrumentSampleDescriptorLocalImpl( this ); 178 } 179 180 183 188 public InstrumentProxy getInstrumentProxy() 189 { 190 return m_instrumentProxy; 191 } 192 193 199 public boolean isConfigured() 200 { 201 return m_configured; 202 } 203 204 209 public final String getName() 210 { 211 return m_name; 212 } 213 214 219 public final long getInterval() 220 { 221 return m_interval; 222 } 223 224 229 public final int getSize() 230 { 231 return m_size; 232 } 233 234 239 public final String getDescription() 240 { 241 return m_description; 242 } 243 244 249 public InstrumentSampleDescriptorLocal getDescriptor() 250 { 251 return m_descriptor; 252 } 253 254 261 public final int getValue() 262 { 263 boolean update; 264 int value; 265 long time; 266 267 synchronized( this ) 268 { 269 long now = System.currentTimeMillis(); 270 update = update( now ); 271 value = getValueInner(); 272 time = m_time; 273 } 274 275 if( update ) 276 { 277 updateListeners( value, time ); 278 } 279 return value; 280 } 281 282 287 public final long getTime() 288 { 289 boolean update; 290 int value; 291 long time; 292 293 synchronized( this ) 294 { 295 long now = System.currentTimeMillis(); 296 update = update( now ); 297 value = getValueInner(); 298 time = m_time; 299 } 300 301 if( update ) 302 { 303 updateListeners( value, time ); 304 } 305 return time; 306 } 307 308 314 public long getLeaseExpirationTime() 315 { 316 return m_leaseExpirationTime; 317 } 318 319 328 public long extendLease( long lease ) 329 { 330 synchronized( this ) 331 { 332 if( ( m_leaseExpirationTime > 0 ) && ( !m_expired ) ) 334 { 335 long newLeaseExpirationTime = System.currentTimeMillis() + lease; 336 if( newLeaseExpirationTime > m_leaseExpirationTime ) 337 { 338 m_leaseExpirationTime = newLeaseExpirationTime; 339 stateChanged(); 340 } 341 } 342 343 return m_leaseExpirationTime; 344 } 345 } 346 347 352 public void expire() 353 { 354 update( m_leaseExpirationTime ); 356 357 m_expired = true; 358 } 359 360 365 public final InstrumentSampleSnapshot getSnapshot() 366 { 367 synchronized( this ) 368 { 369 long time = System.currentTimeMillis(); 370 update( time ); 371 372 return new InstrumentSampleSnapshot( 373 m_name, 374 m_interval, 375 m_size, 376 m_time, 377 getHistorySnapshot(), 378 m_stateVersion ); 379 } 380 } 381 382 391 public int getStateVersion() 392 { 393 return m_stateVersion; 394 } 395 396 402 public void addInstrumentSampleListener( InstrumentSampleListener listener ) 403 { 404 if( getLogger().isDebugEnabled() ) 405 { 406 getLogger().debug( "A InstrumentSampleListener was added to sample, " + m_name + " : " + 407 listener.getClass().getName() ); 408 } 409 410 synchronized( this ) 411 { 412 InstrumentSampleListener[] oldListeners = m_listeners; 417 InstrumentSampleListener[] newListeners; 418 if( oldListeners == null ) 419 { 420 newListeners = new InstrumentSampleListener[]{listener}; 421 } 422 else 423 { 424 newListeners = new InstrumentSampleListener[ oldListeners.length + 1 ]; 425 System.arraycopy( oldListeners, 0, newListeners, 0, oldListeners.length ); 426 newListeners[ oldListeners.length ] = listener; 427 } 428 429 m_listeners = newListeners; 431 } 432 } 433 434 440 public void removeInstrumentSampleListener( InstrumentSampleListener listener ) 441 { 442 if( getLogger().isDebugEnabled() ) 443 { 444 getLogger().debug( "A InstrumentSampleListener was removed from sample, " + m_name + 445 " : " + listener.getClass().getName() ); 446 } 447 448 synchronized( this ) 449 { 450 InstrumentSampleListener[] oldListeners = m_listeners; 455 InstrumentSampleListener[] newListeners; 456 if( oldListeners == null ) 457 { 458 newListeners = null; 461 } 462 else if( oldListeners.length == 1 ) 463 { 464 if( oldListeners[ 0 ] == listener ) 465 { 466 newListeners = null; 467 } 468 else 469 { 470 newListeners = oldListeners; 472 } 473 } 474 else 475 { 476 int pos = -1; 478 for( int i = 0; i < oldListeners.length; i++ ) 479 { 480 if( oldListeners[ i ] == listener ) 481 { 482 pos = i; 483 break; 484 } 485 } 486 487 if( pos < 0 ) 488 { 489 newListeners = oldListeners; 491 } 492 else 493 { 494 newListeners = new InstrumentSampleListener[ oldListeners.length - 1 ]; 495 if( pos > 0 ) 496 { 497 System.arraycopy( oldListeners, 0, newListeners, 0, pos ); 499 } 500 if( pos < oldListeners.length - 1 ) 501 { 502 System.arraycopy( oldListeners, pos + 1, 504 newListeners, pos, oldListeners.length - 1 - pos ); 505 } 506 } 507 } 508 509 m_listeners = newListeners; 511 } 512 } 513 514 522 protected void updateListeners( int value, long time ) 523 { 524 InstrumentSampleListener[] listeners = m_listeners; 526 if( listeners != null ) 527 { 528 for( int i = 0; i < listeners.length; i++ ) 529 { 530 listeners[ i ].setValue( getName(), value, time ); 531 } 532 } 533 } 534 535 541 public final Configuration saveState() 542 { 543 if( ( !isConfigured() ) && ( getLeaseExpirationTime() <= 0 ) ) 546 { 547 return null; 548 } 549 550 synchronized( this ) 551 { 552 DefaultConfiguration state = new DefaultConfiguration( "sample", "-" ); 553 state.setAttribute( "type", 554 InstrumentSampleUtils.getInstrumentSampleTypeName( getType() ) ); 555 state.setAttribute( "interval", Long.toString( m_interval ) ); 556 state.setAttribute( "size", Integer.toString( m_size ) ); 557 558 state.setAttribute( "time", Long.toString( m_time ) ); 559 if( getLeaseExpirationTime() > 0 ) 560 { 561 state.setAttribute( "lease-expiration", Long.toString( getLeaseExpirationTime() ) ); 562 state.setAttribute( "description", m_description ); 563 } 564 565 DefaultConfiguration samples = new DefaultConfiguration( "history", "-" ); 567 int[] history = getHistorySnapshot(); 568 569 StringBuffer sb = new StringBuffer (); 571 sb.append( history[ history.length - 1 ] ); 573 for( int i = history.length - 2; i >= 0; i-- ) 574 { 575 sb.append( ',' ); 576 sb.append( history[ i ] ); 577 } 578 samples.setValue( sb.toString() ); 579 state.addChild( samples ); 580 581 saveState( state ); 582 583 return state; 584 } 585 } 586 587 595 public final void loadState( Configuration state ) throws ConfigurationException 596 { 597 synchronized( this ) 598 { 599 long savedTime = m_time = state.getAttributeAsLong( "time" ); 601 602 m_leaseExpirationTime = state.getAttributeAsLong( "lease-expiration", 0 ); 604 605 m_historyIndex = 0; 607 608 Configuration history = state.getChild( "history" ); 612 613 String compactSamples = history.getValue(); 614 615 StringTokenizer st = new StringTokenizer ( compactSamples, "," ); 617 int[] sampleValues = new int[ st.countTokens() ]; 618 619 for( int i = 0; i < sampleValues.length; i++ ) 620 { 621 try 622 { 623 sampleValues[ i ] = Integer.parseInt( st.nextToken() ); 624 } 625 catch( NumberFormatException e ) 626 { 627 throw new ConfigurationException( "The compact sample data could not be " + 628 "loaded, because of a number format problem, for InstrumentSample: " + 629 m_name ); 630 } 631 } 632 633 int value; 635 if( sampleValues.length > 0 ) 636 { 637 value = sampleValues[ 0 ]; 638 639 for( int i = 0; i < m_size - 1; i++ ) 640 { 641 if( i < sampleValues.length - 1 ) 642 { 643 m_historyOld[ m_size - 2 - i ] = sampleValues[ i + 1 ]; 644 } 645 else 646 { 647 m_historyOld[ m_size - 2 - i ] = 0; 648 } 649 } 650 } 651 else 652 { 653 value = 0; 654 } 655 656 loadState( value, state ); 657 658 if( calculateSampleTime( System.currentTimeMillis() ) > savedTime ) 659 { 660 postSaveNeedsReset(); 664 } 665 666 if( m_leaseExpirationTime > 0 ) 667 { 668 getInstrumentProxy().getInstrumentableProxy().getInstrumentManager(). 671 registerLeasedInstrumentSample( this ); 672 } 673 } 674 675 stateChanged(); 676 } 677 678 681 684 void setConfigured() 685 { 686 m_configured = true; 687 } 688 689 692 private void init() 693 { 694 m_time = calculateSampleTime( System.currentTimeMillis() ); 698 699 m_historyIndex = 0; 705 m_historyOld = new int[ m_size - 1 ]; 706 m_historyNew = new int[ m_size - 1 ]; 707 } 708 709 714 protected void saveState( DefaultConfiguration state ) 715 { 716 } 717 718 729 protected abstract void loadState( int value, Configuration state ) 730 throws ConfigurationException; 731 732 736 protected abstract void postSaveNeedsReset(); 737 738 743 private long calculateSampleTime( long time ) 744 { 745 return ( time / m_interval ) * m_interval; 746 } 747 748 755 protected abstract int getValueInner(); 756 757 763 protected abstract void advanceToNextSample(); 764 765 774 protected boolean update( long time ) 775 { 776 if( m_expired ) 779 { 780 return false; 781 } 782 783 if( time - m_time >= m_interval ) 785 { 786 if( time - m_time >= m_maxAge ) 788 { 789 advanceToNextSample(); 791 init(); 792 } 793 else 794 { 795 while( time - m_time >= m_interval ) 797 { 798 m_historyNew[ m_historyIndex ] = getValueInner(); 800 801 m_time += m_interval; 803 advanceToNextSample(); 804 m_historyIndex++; 805 806 if( m_historyIndex >= m_size - 1 ) 807 { 808 int[] tmp = m_historyOld; 810 m_historyOld = m_historyNew; 811 m_historyNew = tmp; 812 813 m_historyIndex = 0; 815 } 816 } 817 } 818 return true; 819 } 820 else 821 { 822 return false; 823 } 824 } 825 826 833 private int[] getHistorySnapshot() 834 { 835 int[] history = new int[ m_size ]; 839 840 int sizem1 = m_size - 1; 841 842 if( m_size > 1 ) 843 { 844 if( m_historyIndex < sizem1 ) 846 { 847 System.arraycopy( m_historyOld, m_historyIndex, history, 0, sizem1 - m_historyIndex ); 849 } 850 851 if( m_historyIndex > 0 ) 852 { 853 System.arraycopy( m_historyNew, 0, history, sizem1 - m_historyIndex, m_historyIndex ); 855 } 856 } 857 history[ m_size - 1 ] = getValueInner(); 859 860 return history; 861 } 862 863 866 protected void stateChanged() 867 { 868 m_stateVersion++; 869 870 m_instrumentProxy.stateChanged(); 872 } 873 874 879 public String toString() 880 { 881 return "InstrumentSample[name=" + m_name + ", type=" + 882 InstrumentSampleUtils.getInstrumentSampleTypeName( getType() ) + ", interval=" + 883 m_interval + ", size=" + m_size + ", lease=" + m_leaseExpirationTime + "]"; 884 } 885 } 886 | Popular Tags |