001    /*
002    Copyright (c) 1996-2011, Damon Hart-Davis
003    All rights reserved.
004    
005    Redistribution and use in source and binary forms, with or without
006    modification, are permitted provided that the following conditions are
007    met:
008    
009      * Redistributions of source code must retain the above copyright
010        notice, this list of conditions and the following disclaimer.
011    
012      * Redistributions in binary form must reproduce the above copyright
013        notice, this list of conditions and the following disclaimer in the
014        documentation and/or other materials provided with the
015        distribution.
016    
017    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
018    IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
019    TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
020    PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
021    OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
022    SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
023    LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
024    DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
025    THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
026    (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
027    OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
028    */
029    package org.hd.d.pg2k.svrCore;
030    
031    import org.hd.d.pg2k.svrCore.vars.BasicVarMgrInterface;
032    import org.hd.d.pg2k.svrCore.vars.InstanceID;
033    import org.hd.d.pg2k.svrCore.vars.SimpleNumberStats;
034    import org.hd.d.pg2k.svrCore.vars.SimpleVarStats;
035    import org.hd.d.pg2k.svrCore.vars.SimpleVariableDefinition;
036    import org.hd.d.pg2k.svrCore.vars.SimpleVariableValue;
037    import org.hd.d.pg2k.svrCore.vars.SystemVariables;
038    
039        /**This class has tools handling common SystemVariables.
040         */
041        public final class VarTools
042            {
043            /**Prevent creation of instances of this class. */
044            private VarTools() { }
045    
046            /**Minimum age of globalMap entry we will discard, ms; strictly positive. */
047            public static final int MIN_AGE_MS = 2*SystemVariables.MAX_VALUE_DISTRIBUTION_LATENCY_MS;
048    
049    
050    
051    
052    
053            /**Robustly computes simple stats on a named generic variable.
054             * The stats instance produced is
055             * @see #generateSimpleNumberStats
056             *
057             *
058             * @param maxAge_ms  maximum age of globalMap entry we will use in ms;
059             *     will be coerced upwards to a minimum value based on allowed
060             *     variable-propagation latency
061             *
062             * Catches most exceptions and returns null in case of error.
063             * <p>
064             * Computes the system ID automatically, if available.
065             */
066            public static final SimpleVarStats generateSimpleStats(
067                                    final BasicVarMgrInterface dataSource,
068                                    final SimpleVariableDefinition def,
069                                    final int maxAge_ms)
070                {
071                if((dataSource == null) ||
072                   (def == null))
073                    { throw new IllegalArgumentException(); }
074    
075                try
076                    {
077                    final SimpleVariableValue sys =
078                        dataSource.getVariable(SystemVariables.LOCAL_SYS_ID);
079                    // Build and return the requested stats...
080                    return(new SimpleVarStats(dataSource.getVariable(def),
081                        System.currentTimeMillis() -
082                            Math.max(maxAge_ms, MIN_AGE_MS),
083                        (sys == null) ? null : (InstanceID) sys.getValue()));
084                    }
085                catch(final Exception e)
086                    { return(null); }
087                }
088    
089            /**Robustly computes simple stats on a named TYPE_NUMBER variable.
090             * @see #generateSimpleNumberStats
091             *
092             * @param maxAge_ms  maximum age of globalMap entry we will use in ms;
093             *     will be coerced upwards to a minimum value based on allowed
094             *     variable-propagation latency
095             *
096             * Catches most exceptions and returns null in case of error.
097             * <p>
098             * Computes the system ID automatically, if available.
099             */
100            public static final SimpleNumberStats generateSimpleNumberStats(
101                                    final BasicVarMgrInterface dataSource,
102                                    final SimpleVariableDefinition def,
103                                    final int maxAge_ms,
104                                    final String decimalFormatPattern)
105                {
106                if((dataSource == null) ||
107                   (def == null))
108                    { throw new IllegalArgumentException(); }
109    
110                try
111                    {
112                    final SimpleVariableValue sys =
113                        dataSource.getVariable(SystemVariables.LOCAL_SYS_ID);
114                    return(generateSimpleNumberStats(dataSource.getVariable(def),
115                                               maxAge_ms,
116                                               decimalFormatPattern,
117                                               (sys == null) ? null : (InstanceID) sys.getValue()));
118                    }
119                catch(final Exception e)
120                    { return(null); }
121                }
122    
123    
124            /**Robustly computes simple stats on a TYPE_NUMBER variable.
125             * Intended to be used both in normal code and
126             * directly in JSP pages
127             * (eg is robust, never throws exceptions, HMTL-friendly toString()).
128             * <p>
129             * Returns an immutable object containing the stats
130             * which has a toString() which renders a relatively
131             * admin-human-friendly simple String containing all the stats,
132             * or null if the variable presented is null or not numeric
133             * or for some reason not suitable.
134             * <p>
135             * A local value is treated like a global with one entry
136             * but flagged as local.
137             * <p>
138             * Only the young-enough members of a global are used;
139             * if none are young enough then the main value is used
140             * and flagged as old.
141             *
142             * @param sysID  identifies this system so we can select the local
143             *     value of a global variable if available; can be null
144             * @param maxAge  maximum age of globalMap entries to be used;
145             *     coerced to be at least a little larger than the refresh
146             *
147             * @return null if variable is unsuitable, else encapsulated stats
148             */
149            public static final SimpleNumberStats generateSimpleNumberStats(
150                                    final SimpleVariableValue var,
151                                    final int maxAge,
152                                    final String decimalFormatPattern,
153                                    final InstanceID sysID)
154                {
155                // Return null if the variable is unsuitable.
156                if((var == null) ||
157                   (var.getDef().getType() != SimpleVariableDefinition.TYPE_NUMBER) ||
158                   (var.getValue() == null))
159                    { return(null); }
160    
161                // Build and return the requested stats...
162                return(new SimpleNumberStats(var,
163                    System.currentTimeMillis() -
164                        Math.max(maxAge, MIN_AGE_MS),
165                    sysID, decimalFormatPattern
166                ));
167                }
168            }