KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > excalibur > instrument > manager > AbstractInstrumentSample


1 /*
2
3  ============================================================================
4                    The Apache Software License, Version 1.1
5  ============================================================================
6  
7  Copyright (C) 1999-2003 The Apache Software Foundation. All rights reserved.
8  
9  Redistribution and use in source and binary forms, with or without modifica-
10  tion, are permitted provided that the following conditions are met:
11  
12  1. Redistributions of source code must retain the above copyright notice,
13     this list of conditions and the following disclaimer.
14  
15  2. Redistributions in binary form must reproduce the above copyright notice,
16     this list of conditions and the following disclaimer in the documentation
17     and/or other materials provided with the distribution.
18  
19  3. The end-user documentation included with the redistribution, if any, must
20     include the following acknowledgment: "This product includes software
21     developed by the Apache Software Foundation (http://www.apache.org/)."
22     Alternately, this acknowledgment may appear in the software itself, if
23     and wherever such third-party acknowledgments normally appear.
24  
25  4. The names "Jakarta", "Avalon", "Excalibur" and "Apache Software Foundation"
26     must not be used to endorse or promote products derived from this software
27     without prior written permission. For written permission, please contact
28     apache@apache.org.
29  
30  5. Products derived from this software may not be called "Apache", nor may
31     "Apache" appear in their name, without prior written permission of the
32     Apache Software Foundation.
33  
34  THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
35  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
36  FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
37  APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
38  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU-
39  DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
40  OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
41  ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
42  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
43  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
44  
45  This software consists of voluntary contributions made by many individuals
46  on behalf of the Apache Software Foundation. For more information on the
47  Apache Software Foundation, please see <http://www.apache.org/>.
48  
49 */

50 package org.apache.excalibur.instrument.manager;
51
52 import java.util.StringTokenizer JavaDoc;
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 /**
62  * An AbstractInstrumentSample contains all of the functionality common to all
63  * InstrumentSamples.
64  *
65  * @author <a HREF="mailto:leif@tanukisoftware.com">Leif Mortenson</a>
66  * @version CVS $Revision: 1.5 $ $Date: 2003/02/25 16:28:16 $
67  * @since 4.1
68  */

69 abstract class AbstractInstrumentSample
70     extends AbstractLogEnabled
71     implements InstrumentSample
72 {
73     /** The InstrumentProxy which owns the InstrumentSample. */
74     private InstrumentProxy m_instrumentProxy;
75
76     /** Configured flag. */
77     private boolean m_configured;
78
79     /** The name of the new InstrumentSample. */
80     private String JavaDoc m_name;
81
82     /** The sample interval of the new InstrumentSample. */
83     private long m_interval;
84
85     /** The number of samples to store as history. */
86     private int m_size;
87
88     /** The description of the new InstrumentSample. */
89     private String JavaDoc m_description;
90
91     /** The Descriptor for the InstrumentSample. */
92     private InstrumentSampleDescriptorLocal m_descriptor;
93
94     /**
95      * The maximum amount of time between updates before history will be
96      * wiped clean.
97      */

98     private long m_maxAge;
99
100     /** The UNIX time of the beginning of the sample. */
101     protected long m_time;
102
103     /** The time that the current lease expires. */
104     private long m_leaseExpirationTime;
105
106     /** True if the lease has expired. */
107     private boolean m_expired;
108
109     /** The Index into the history arrays. */
110     private int m_historyIndex;
111
112     /** The Old half of the history array. */
113     private int[] m_historyOld;
114
115     /** The New half of the history array. */
116     private int[] m_historyNew;
117
118     /** Array of registered InstrumentSampleListeners. */
119     private InstrumentSampleListener[] m_listeners;
120
121     /** State Version. */
122     private int m_stateVersion;
123
124     /*---------------------------------------------------------------
125      * Constructors
126      *-------------------------------------------------------------*/

127     /**
128      * Creates a new AbstractInstrumentSample
129      *
130      * @param instrumentProxy The InstrumentProxy which owns the
131      * InstrumentSample.
132      * @param name The name of the new InstrumentSample.
133      * @param interval The sample interval of the new InstrumentSample.
134      * @param size The number of samples to store as history. Assumes that
135      * size is at least 1.
136      * @param description The description of the new InstrumentSample.
137      * @param lease The length of the lease in milliseconds.
138      */

139     protected AbstractInstrumentSample( InstrumentProxy instrumentProxy,
140                                         String JavaDoc name,
141                                         long interval,
142                                         int size,
143                                         String JavaDoc description,
144                                         long lease )
145     {
146         m_instrumentProxy = instrumentProxy;
147
148         if( interval < 1 )
149         {
150             throw new IllegalArgumentException JavaDoc( "interval must be at least 1." );
151         }
152         if( size < 1 )
153         {
154             throw new IllegalArgumentException JavaDoc( "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             // Permanent lease.
168
m_leaseExpirationTime = 0;
169         }
170
171         // Calculate the maxAge
172
m_maxAge = m_size * m_interval;
173
174         init();
175
176         // Create the descriptor
177
m_descriptor = new InstrumentSampleDescriptorLocalImpl( this );
178     }
179
180     /*---------------------------------------------------------------
181      * InstrumentSample Methods
182      *-------------------------------------------------------------*/

183     /**
184      * Returns the InstrumentProxy which owns the InstrumentSample.
185      *
186      * @return The InstrumentProxy which owns the InstrumentSample.
187      */

188     public InstrumentProxy getInstrumentProxy()
189     {
190         return m_instrumentProxy;
191     }
192
193     /**
194      * Returns true if the Instrument was configured in the instrumentables
195      * section of the configuration.
196      *
197      * @return True if configured.
198      */

199     public boolean isConfigured()
200     {
201         return m_configured;
202     }
203
204     /**
205      * Returns the name of the sample.
206      *
207      * @return The name of the sample.
208      */

209     public final String JavaDoc getName()
210     {
211         return m_name;
212     }
213
214     /**
215      * Returns the sample interval. The period of each sample in millisends.
216      *
217      * @return The sample interval.
218      */

219     public final long getInterval()
220     {
221         return m_interval;
222     }
223
224     /**
225      * Returns the number of samples in the sample history.
226      *
227      * @return The size of the sample history.
228      */

229     public final int getSize()
230     {
231         return m_size;
232     }
233
234     /**
235      * Returns the description of the sample.
236      *
237      * @return The description of the sample.
238      */

239     public final String JavaDoc getDescription()
240     {
241         return m_description;
242     }
243
244     /**
245      * Returns a Descriptor for the InstrumentSample.
246      *
247      * @return A Descriptor for the InstrumentSample.
248      */

249     public InstrumentSampleDescriptorLocal getDescriptor()
250     {
251         return m_descriptor;
252     }
253
254     /**
255      * Obtain the value of the sample. All samples are integers, so the profiled
256      * objects must measure quantity (numbers of items), rate (items/period), time in
257      * milliseconds, etc.
258      *
259      * @return The sample value.
260      */

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     /**
283      * Obtain the UNIX time of the beginning of the sample.
284      *
285      * @return The UNIX time of the beginning of the sample.
286      */

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     /**
309      * Returns the time that the current lease expires. Permanent samples will
310      * return a value of 0.
311      *
312      * @return The time that the current lease expires.
313      */

314     public long getLeaseExpirationTime()
315     {
316         return m_leaseExpirationTime;
317     }
318
319     /**
320      * Extends the lease to be lease milliseconds from the current time.
321      * Ignored if the lease has already expired.
322      *
323      * @param lease The length of the lease in milliseconds.
324      *
325      * @return The new lease expiration time. Returns 0 if the sample is
326      * permanent.
327      */

328     public long extendLease( long lease )
329     {
330         synchronized( this )
331         {
332             // Only extend the lease if it is not permanent.
333
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     /**
348      * Tells the sample that its lease has expired. No new references to
349      * the sample will be made available, but clients which already have
350      * access to the sample may continue to use it.
351      */

352     public void expire()
353     {
354         // Update to the time that we expire at.
355
update( m_leaseExpirationTime );
356
357         m_expired = true;
358     }
359
360     /**
361      * Obtains a static snapshot of the InstrumentSample.
362      *
363      * @return A static snapshot of the InstrumentSample.
364      */

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     /**
383      * Returns the stateVersion of the sample. The state version will be
384      * incremented each time any of the configuration of the sample is
385      * modified.
386      * Clients can use this value to tell whether or not anything has
387      * changed without having to do an exhaustive comparison.
388      *
389      * @return The state version of the sample.
390      */

391     public int getStateVersion()
392     {
393         return m_stateVersion;
394     }
395
396     /**
397      * Registers a InstrumentSampleListener with a InstrumentSample given a name.
398      *
399      * @param listener The listener which should start receiving updates from the
400      * InstrumentSample.
401      */

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             // Store the listeners in an array. This makes it possible to
413
// avoid synchronization while propagating events. Never change
414
// the contents of the listener array once it has been set to the
415
// m_listeners field.
416
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             // Update the m_listeners field.
430
m_listeners = newListeners;
431         }
432     }
433
434     /**
435      * Unregisters a InstrumentSampleListener from a InstrumentSample given a name.
436      *
437      * @param listener The listener which should stop receiving updates from the
438      * InstrumentSample.
439      */

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             // Store the listeners in an array. This makes it possible to
451
// avoid synchronization while propagating events. Never change
452
// the contents of the listener array once it has been set to the
453
// m_listeners field.
454
InstrumentSampleListener[] oldListeners = m_listeners;
455             InstrumentSampleListener[] newListeners;
456             if( oldListeners == null )
457             {
458                 // Means that this method should not have been called, but
459
// don't throw an error.
460
newListeners = null;
461             }
462             else if( oldListeners.length == 1 )
463             {
464                 if( oldListeners[ 0 ] == listener )
465                 {
466                     newListeners = null;
467                 }
468                 else
469                 {
470                     // The listener was not in the list.
471
newListeners = oldListeners;
472                 }
473             }
474             else
475             {
476                 // Look for the listener in the array.
477
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                     // The listener was not in the list.
490
newListeners = oldListeners;
491                 }
492                 else
493                 {
494                     newListeners = new InstrumentSampleListener[ oldListeners.length - 1 ];
495                     if( pos > 0 )
496                     {
497                         // Copy the head of the array
498
System.arraycopy( oldListeners, 0, newListeners, 0, pos );
499                     }
500                     if( pos < oldListeners.length - 1 )
501                     {
502                         // Copy the tail of the array
503
System.arraycopy( oldListeners, pos + 1,
504                                           newListeners, pos, oldListeners.length - 1 - pos );
505                     }
506                 }
507             }
508
509             // Update the m_listeners field.
510
m_listeners = newListeners;
511         }
512     }
513
514     /**
515      * Notifies any listeners of a change.
516      * <p>
517      * Make sure that this is called OUTSIDE of a synchrinization block.
518      *
519      * @param value The new value.
520      * @param time The time that the new value was set.
521      */

522     protected void updateListeners( int value, long time )
523     {
524         // Get a local reference to the listeners, so that synchronization can be avoided.
525
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     /**
536      * Saves the current state into a Configuration.
537      *
538      * @return The state as a Configuration. Returns null if the configuration
539      * would not contain any information.
540      */

541     public final Configuration saveState()
542     {
543         // If this sample is not configured and its lease time is 0, then it
544
// is an artifact of a previous state file, so it should not be saved.
545
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             // Save the history samples so that the newest is first.
566
DefaultConfiguration samples = new DefaultConfiguration( "history", "-" );
567             int[] history = getHistorySnapshot();
568
569             // Build up a string of the sample points.
570
StringBuffer JavaDoc sb = new StringBuffer JavaDoc();
571             // Store the first value outside the loop to simplify the loop.
572
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     /**
588      * Loads the state into the InstrumentSample.
589      *
590      * @param state Configuration object to load state from.
591      *
592      * @throws ConfigurationException If there were any problems loading the
593      * state.
594      */

595     public final void loadState( Configuration state ) throws ConfigurationException
596     {
597         synchronized( this )
598         {
599             // Set the time
600
long savedTime = m_time = state.getAttributeAsLong( "time" );
601
602             // Load the lease expiration time
603
m_leaseExpirationTime = state.getAttributeAsLong( "lease-expiration", 0 );
604
605             // Set the history index.
606
m_historyIndex = 0;
607
608             // Read in the samples, don't trust that the number will be correct.
609
// First sample is the current value, following sames go back in
610
// time from newest to oldest.
611
Configuration history = state.getChild( "history" );
612
613             String JavaDoc compactSamples = history.getValue();
614
615             // Sample values are stored in newest to oldest order.
616
StringTokenizer JavaDoc st = new StringTokenizer JavaDoc( 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 JavaDoc 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             // Get the current value
634
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                 // The sample period changed since the save.
661
// This will usually happen, but not always for long
662
// intervals.
663
postSaveNeedsReset();
664             }
665
666             if( m_leaseExpirationTime > 0 )
667             {
668                 // This is a sample that was leased in a previous JVM invocation
669
// and needs to be registered with the InstrumentManager
670
getInstrumentProxy().getInstrumentableProxy().getInstrumentManager().
671                     registerLeasedInstrumentSample( this );
672             }
673         }
674
675         stateChanged();
676     }
677
678     /*---------------------------------------------------------------
679      * Methods
680      *-------------------------------------------------------------*/

681     /**
682      * Sets the configured flag.
683      */

684     void setConfigured()
685     {
686         m_configured = true;
687     }
688
689     /**
690      * Initializes the sample
691      */

692     private void init()
693     {
694         // Calculate an interval time based on the current time by removing the modulous
695
// value of the current time. This will allign the intervals to the start of computer
696
// time.
697
m_time = calculateSampleTime( System.currentTimeMillis() );
698
699         // Create the arrays which will hold the history points.
700
// History is build with m_value holding the current value and all previous values
701
// spanning accross 2 arrays that switch places as time progresses. This completely
702
// removes the need to manage large lists or do array copies.
703
// All history values are 0 initially.
704
m_historyIndex = 0;
705         m_historyOld = new int[ m_size - 1 ];
706         m_historyNew = new int[ m_size - 1 ];
707     }
708
709     /**
710      * Allow subclasses to add information into the saved state.
711      *
712      * @param state State configuration.
713      */

714     protected void saveState( DefaultConfiguration state )
715     {
716     }
717
718     /**
719      * Used to load the state, called from AbstractInstrumentSample.loadState();
720      * <p>
721      * Should only be called when synchronized.
722      *
723      * @param value Current value loaded from the state.
724      * @param state Configuration object to load state from.
725      *
726      * @throws ConfigurationException If there were any problems loading the
727      * state.
728      */

729     protected abstract void loadState( int value, Configuration state )
730         throws ConfigurationException;
731
732     /**
733      * Called after a state is loaded if the sample period is not the same
734      * as the last period saved.
735      */

736     protected abstract void postSaveNeedsReset();
737
738     /**
739      * Calculates the time of the sample which contains the specified time.
740      *
741      * @param time Time whose sample time is requested.
742      */

743     private long calculateSampleTime( long time )
744     {
745         return ( time / m_interval ) * m_interval;
746     }
747
748     /**
749      * Gets the current value. Does not update.
750      * <p>
751      * Should only be called when synchronized.
752      *
753      * @return The current value.
754      */

755     protected abstract int getValueInner();
756
757     /**
758      * The current sample has already been stored. Reset the current sample
759      * and move on to the next.
760      * <p>
761      * Should only be called when synchronized.
762      */

763     protected abstract void advanceToNextSample();
764
765     /**
766      * Brings the InstrumentSample's time up to date so that a new value can be added.
767      * <p>
768      * Should only be called when synchronized.
769      *
770      * @param time The time to which the InstrumentSample should be brought up to date.
771      *
772      * @return True if listeners should be notified.
773      */

774     protected boolean update( long time )
775     {
776         //System.out.println("update(" + time + ")");
777
// If the lease has already expired, then do nothing
778
if( m_expired )
779         {
780             return false;
781         }
782
783         // See if we are already up to date.
784
if( time - m_time >= m_interval )
785         {
786             // Needs to move to a new sample.
787
if( time - m_time >= m_maxAge )
788             {
789                 // The history is too old, reset the sample.
790
advanceToNextSample();
791                 init();
792             }
793             else
794             {
795                 // Advance the history index.
796
while( time - m_time >= m_interval )
797                 {
798                     // Store the current value into the end of the history.
799
m_historyNew[ m_historyIndex ] = getValueInner();
800
801                     // Advance to the next sample.
802
m_time += m_interval;
803                     advanceToNextSample();
804                     m_historyIndex++;
805
806                     if( m_historyIndex >= m_size - 1 )
807                     {
808                         // Need to swap the history arrays
809
int[] tmp = m_historyOld;
810                         m_historyOld = m_historyNew;
811                         m_historyNew = tmp;
812
813                         // Reset the history index
814
m_historyIndex = 0;
815                     }
816                 }
817             }
818             return true;
819         }
820         else
821         {
822             return false;
823         }
824     }
825
826     /**
827      * Gets a snapshot of the samples.
828      * <p>
829      * Should only be called after an update when synchronized.
830      *
831      * @return A snapshot of the samples in the InstrumentSample.
832      */

833     private int[] getHistorySnapshot()
834     {
835         // Create a new array to hold the snapshot of the history data.
836
// This method is a little slow but normal collection of sample points is
837
// extremely fast.
838
int[] history = new int[ m_size ];
839
840         int sizem1 = m_size - 1;
841
842         if( m_size > 1 )
843         {
844             // Copy samples from the old history first.
845
if( m_historyIndex < sizem1 )
846             {
847                 // Copy the last (size - 1 - historyIndex) samples from the old history.
848
System.arraycopy( m_historyOld, m_historyIndex, history, 0, sizem1 - m_historyIndex );
849             }
850
851             if( m_historyIndex > 0 )
852             {
853                 // Copy the first (historyIndex) samples from the new history.
854
System.arraycopy( m_historyNew, 0, history, sizem1 - m_historyIndex, m_historyIndex );
855             }
856         }
857         // Get the final sample from the current sample value.
858
history[ m_size - 1 ] = getValueInner();
859
860         return history;
861     }
862
863     /**
864      * Called whenever the state of the sample is changed.
865      */

866     protected void stateChanged()
867     {
868         m_stateVersion++;
869
870         // Propagate to the parent
871
m_instrumentProxy.stateChanged();
872     }
873
874     /**
875      * Returns a string representation of the sample.
876      *
877      * @return A string representation of the sample.
878      */

879     public String JavaDoc 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