View Javadoc
1   /*
2    * #%L
3    * ProfilingStatus.java - mongodb-async-driver - Allanbank Consulting, Inc.
4    * %%
5    * Copyright (C) 2011 - 2014 Allanbank Consulting, Inc.
6    * %%
7    * Licensed under the Apache License, Version 2.0 (the "License");
8    * you may not use this file except in compliance with the License.
9    * You may obtain a copy of the License at
10   * 
11   *      http://www.apache.org/licenses/LICENSE-2.0
12   * 
13   * Unless required by applicable law or agreed to in writing, software
14   * distributed under the License is distributed on an "AS IS" BASIS,
15   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16   * See the License for the specific language governing permissions and
17   * limitations under the License.
18   * #L%
19   */
20  package com.allanbank.mongodb;
21  
22  import java.io.Serializable;
23  
24  /**
25   * ProfilingStatus provides a container for the {@link Level} and number of
26   * milliseconds beyond which to consider an operation to be slow.
27   * 
28   * @api.yes This class is part of the driver's API. Public and protected members
29   *          will be deprecated for at least 1 non-bugfix release (version
30   *          numbers are <major>.<minor>.<bugfix>) before being
31   *          removed or modified.
32   * @copyright 2012-2013, Allanbank Consulting, Inc., All Rights Reserved
33   */
34  public class ProfilingStatus implements Comparable<ProfilingStatus>,
35          Serializable {
36  
37      /**
38       * The default threshold ({@value} )for the number of milliseconds beyond
39       * considering an operation slow.
40       */
41      public static final long DEFAULT_SLOW_MS = 100;
42  
43      /** The off profiling state. */
44      public static final ProfilingStatus OFF = new ProfilingStatus(Level.NONE);
45  
46      /** The all profiling state. */
47      public static final ProfilingStatus ON = new ProfilingStatus(Level.ALL);
48  
49      /** The serialization version of the class. */
50      private static final long serialVersionUID = 181636899391154872L;
51  
52      /**
53       * Creates a profiling state to profile operations taking more than
54       * {@code slowMillis} to complete.
55       * 
56       * @param slowMillis
57       *            The number of milliseconds beyond which to consider an
58       *            operation to be slow.
59       * @return The slow profiling state.
60       */
61      public static final ProfilingStatus slow(final int slowMillis) {
62          return new ProfilingStatus(Level.SLOW_ONLY, slowMillis);
63      }
64  
65      /** The profiling level. */
66      private final Level myLevel;
67  
68      /**
69       * The number of milliseconds beyond which to consider an operation to be
70       * slow.
71       */
72      private final long mySlowMillisThreshold;
73  
74      /**
75       * Creates a new ProfilingStatus.
76       * 
77       * @param level
78       *            The profiling level to use.
79       */
80      private ProfilingStatus(final Level level) {
81          this(level, DEFAULT_SLOW_MS);
82      }
83  
84      /**
85       * Creates a new ProfilingStatus.
86       * 
87       * @param level
88       *            The profiling level to use.
89       * @param slowMillis
90       *            The number of milliseconds beyond which to consider an
91       *            operation to be slow.
92       */
93      private ProfilingStatus(final Level level, final long slowMillis) {
94          myLevel = level;
95          mySlowMillisThreshold = slowMillis;
96      }
97  
98      /**
99       * {@inheritDoc}
100      * <p>
101      * Overridden to return an ordering based on the tuple ordering of (level,
102      * slowMs).
103      * </p>
104      */
105     @Override
106     public int compareTo(final ProfilingStatus other) {
107         int diff = myLevel.getValue() - other.myLevel.getValue();
108         if (diff == 0) {
109             if (mySlowMillisThreshold < other.mySlowMillisThreshold) {
110                 diff = -1;
111             }
112             else if (mySlowMillisThreshold == other.mySlowMillisThreshold) {
113                 diff = 0;
114             }
115             else {
116                 diff = 1;
117             }
118 
119         }
120         return diff;
121     }
122 
123     /**
124      * {@inheritDoc}
125      * <p>
126      * Overridden to compare this object to the passed object.
127      * </p>
128      */
129     @Override
130     public boolean equals(final Object object) {
131         boolean result = false;
132         if (this == object) {
133             result = true;
134         }
135         else if ((object != null) && (getClass() == object.getClass())) {
136             final ProfilingStatus other = (ProfilingStatus) object;
137 
138             result = (myLevel == other.myLevel)
139                     && (mySlowMillisThreshold == other.mySlowMillisThreshold);
140         }
141         return result;
142     }
143 
144     /**
145      * Returns the profiling level to use.
146      * 
147      * @return The profiling level to use.
148      */
149     public Level getLevel() {
150         return myLevel;
151     }
152 
153     /**
154      * Returns the number of milliseconds beyond which to consider an operation
155      * to be slow.
156      * 
157      * @return The number of milliseconds beyond which to consider an operation
158      *         to be slow.
159      */
160     public long getSlowMillisThreshold() {
161         return mySlowMillisThreshold;
162     }
163 
164     /**
165      * {@inheritDoc}
166      * <p>
167      * Overridden to generate a suitable hash of the objects state.
168      * </p>
169      */
170     @Override
171     public int hashCode() {
172         int result = 1;
173         result = (31 * result) + ((myLevel == null) ? 0 : myLevel.hashCode());
174         result = (31 * result)
175                 + (int) (mySlowMillisThreshold ^ (mySlowMillisThreshold >>> 32));
176         return result;
177     }
178 
179     /**
180      * {@inheritDoc}
181      * <p>
182      * Overridden to return a readable form of the object.
183      * </p>
184      */
185     @Override
186     public String toString() {
187         if (myLevel == Level.SLOW_ONLY) {
188             return myLevel.name() + "(" + mySlowMillisThreshold + " ms)";
189         }
190         return myLevel.name();
191     }
192 
193     /**
194      * Hook into serialization to replace <tt>this</tt> object with the local
195      * {@link #ON} or {@link #OFF} instance as appropriate.
196      * 
197      * @return Either the {@link #ON} or {@link #OFF} instance if <tt>this</tt>
198      *         instance equals one of those instances otherwise <tt>this</tt>
199      *         instance.
200      */
201     private Object readResolve() {
202         if (this.equals(ON)) {
203             return ON;
204         }
205         else if (this.equals(OFF)) {
206             return OFF;
207         }
208         else {
209             return this;
210         }
211     }
212 
213     /**
214      * Level provides the set of available profiling levels provided by the
215      * MongoDB server.
216      * 
217      * @api.yes This class is part of the driver's API. Public and protected
218      *          members will be deprecated for at least 1 non-bugfix release
219      *          (version numbers are &lt;major&gt;.&lt;minor&gt;.&lt;bugfix&gt;)
220      *          before being removed or modified.
221      * @copyright 2012-2013, Allanbank Consulting, Inc., All Rights Reserved
222      */
223     public static enum Level {
224 
225         /** Profile all operations. */
226         ALL(2),
227 
228         /** Profile no operations. */
229         NONE(0),
230 
231         /** Only profile slow operations. */
232         SLOW_ONLY(1);
233 
234         /**
235          * Returns the {@link Level} for the specified value.
236          * 
237          * @param value
238          *            The value of the profile level.
239          * @return The profile level for the value.
240          */
241         public static Level fromValue(final int value) {
242             for (final Level level : values()) {
243                 if (level.getValue() == value) {
244                     return level;
245                 }
246             }
247 
248             return null;
249         }
250 
251         /** The profile level value to send to MongoDB. */
252         private final int myValue;
253 
254         /**
255          * Creates a new Level.
256          * 
257          * @param value
258          *            The profile level value to send to MongoDB.
259          */
260         private Level(final int value) {
261             myValue = value;
262         }
263 
264         /**
265          * Returns the profile level value to send to MongoDB.
266          * 
267          * @return The profile level value to send to MongoDB.
268          */
269         public int getValue() {
270             return myValue;
271         }
272     }
273 }