001    /*
002     * Copyright 2008-2015 UnboundID Corp.
003     * All Rights Reserved.
004     */
005    /*
006     * Copyright (C) 2015 UnboundID Corp.
007     *
008     * This program is free software; you can redistribute it and/or modify
009     * it under the terms of the GNU General Public License (GPLv2 only)
010     * or the terms of the GNU Lesser General Public License (LGPLv2.1 only)
011     * as published by the Free Software Foundation.
012     *
013     * This program is distributed in the hope that it will be useful,
014     * but WITHOUT ANY WARRANTY; without even the implied warranty of
015     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
016     * GNU General Public License for more details.
017     *
018     * You should have received a copy of the GNU General Public License
019     * along with this program; if not, see <http://www.gnu.org/licenses>.
020     */
021    package com.unboundid.ldap.sdk.unboundidds.monitors;
022    
023    
024    
025    import java.util.Collections;
026    import java.util.LinkedHashMap;
027    import java.util.Map;
028    
029    import com.unboundid.ldap.sdk.Entry;
030    import com.unboundid.util.NotMutable;
031    import com.unboundid.util.ThreadSafety;
032    import com.unboundid.util.ThreadSafetyLevel;
033    
034    import static com.unboundid.ldap.sdk.unboundidds.monitors.MonitorMessages.*;
035    
036    
037    
038    /**
039     * <BLOCKQUOTE>
040     *   <B>NOTE:</B>  This class is part of the Commercial Edition of the UnboundID
041     *   LDAP SDK for Java.  It is not available for use in applications that
042     *   include only the Standard Edition of the LDAP SDK, and is not supported for
043     *   use in conjunction with non-UnboundID products.
044     * </BLOCKQUOTE>
045     * This class defines a monitor entry that provides information about the state
046     * of the UnboundID work queue.  This has replaced the traditional work queue as
047     * the default work queue implementation used by the UnboundID Directory Server,
048     * and the monitor information that it may make available includes:
049     * <UL>
050     *   <LI>The number of requests that were rejected because the work queue was
051     *       already at its maximum capacity.</LI>
052     *   <LI>The number of operations currently held in the work queue waiting to be
053     *       picked for processing by a worker thread.</LI>
054     *   <LI>The average number of operations held in the work queue since startup
055     *       as observed from periodic polling.</LI>
056     *   <LI>The maximum number of operations held in the work queue at any time
057     *       since startup as observed from periodic polling.</LI>
058     * </UL>
059     * The server should present at most one UnboundID work queue monitor entry.
060     * It can be retrieved using the
061     * {@link MonitorManager#getUnboundIDWorkQueueMonitorEntry} method.  This entry
062     * provides specific methods for accessing information about the state of
063     * the work queue (e.g., the
064     * {@link UnboundIDWorkQueueMonitorEntry#getCurrentSize} method may be used
065     * to retrieve the number of operations currently held in the work queue).
066     * Alternately, this information may be accessed using the generic API.  See the
067     * {@link MonitorManager} class documentation for an example that demonstrates
068     * the use of the generic API for accessing monitor data.
069     */
070    @NotMutable()
071    @ThreadSafety(level=ThreadSafetyLevel.COMPLETELY_THREADSAFE)
072    public final class UnboundIDWorkQueueMonitorEntry
073           extends MonitorEntry
074    {
075      /**
076       * The structural object class used in LDAP statistics monitor entries.
077       */
078      static final String UNBOUNDID_WORK_QUEUE_MONITOR_OC =
079           "ds-unboundid-work-queue-monitor-entry";
080    
081    
082    
083      /**
084       * The name of the attribute that contains the average worker thread percent
085       * busy.
086       */
087      private static final String ATTR_AVERAGE_QUEUE_TIME_MILLIS =
088           "average-operation-queue-time-millis";
089    
090    
091    
092      /**
093       * The name of the attribute that contains the average worker thread percent
094       * busy.
095       */
096      private static final String ATTR_AVERAGE_PCT_BUSY =
097           "average-worker-thread-percent-busy";
098    
099    
100    
101      /**
102       * The name of the attribute that contains the average observed work queue
103       * size.
104       */
105      private static final String ATTR_AVERAGE_SIZE = "average-queue-size";
106    
107    
108    
109      /**
110       * The name of the attribute that contains the current work queue size.
111       */
112      private static final String ATTR_CURRENT_PCT_BUSY =
113           "current-worker-thread-percent-busy";
114    
115    
116    
117      /**
118       * The name of the attribute that contains the current work queue size.
119       */
120      private static final String ATTR_CURRENT_SIZE = "current-queue-size";
121    
122    
123    
124      /**
125       * The name of the attribute that contains the maximum observed work queue
126       * size.
127       */
128      private static final String ATTR_MAX_SIZE = "max-queue-size";
129    
130    
131    
132      /**
133       * The name of the attribute that contains the maximum worker thread percent
134       * busy.
135       */
136      private static final String ATTR_MAX_PCT_BUSY =
137           "max-worker-thread-percent-busy";
138    
139    
140    
141      /**
142       * The name of the attribute that contains the number of busy worker threads.
143       */
144      private static final String ATTR_NUM_BUSY_WORKER_THREADS =
145           "num-busy-worker-threads";
146    
147    
148    
149      /**
150       * The name of the attribute that contains the number of worker threads.
151       */
152      private static final String ATTR_NUM_WORKER_THREADS = "num-worker-threads";
153    
154    
155    
156      /**
157       * The name of the attribute that contains the average worker thread percent
158       * busy.
159       */
160      private static final String ATTR_RECENT_AVERAGE_SIZE =
161           "recent-average-queue-size";
162    
163    
164    
165      /**
166       * The name of the attribute that contains the average worker thread percent
167       * busy.
168       */
169      private static final String ATTR_RECENT_QUEUE_TIME_MILLIS =
170           "recent-operation-queue-time-millis";
171    
172    
173    
174      /**
175       * The name of the attribute that contains the recent worker thread percent
176       * busy.
177       */
178      private static final String ATTR_RECENT_PCT_BUSY =
179           "recent-worker-thread-percent-busy";
180    
181    
182    
183      /**
184       * The name of the attribute that contains the total number of requests that
185       * have been rejected because the work queue was full.
186       */
187      private static final String ATTR_REQUESTS_REJECTED = "rejected-count";
188    
189    
190    
191      /**
192       * The name of the attribute that contains the current size of the work queue
193       * reserved for operations processed as part of administrative sessions.
194       */
195      private static final String ATTR_CURRENT_ADMIN_QUEUE_SIZE =
196           "current-administrative-session-queue-size";
197    
198    
199    
200      /**
201       * The name of the attribute that contains the number of worker threads that
202       * are currently busy processing operations as part of an administrative
203       * session.
204       */
205      private static final String ATTR_MAX_ADMIN_SESSION_QUEUE_SIZE =
206           "max-administrative-session-queue-size";
207    
208    
209    
210      /**
211       * The name of the attribute that contains the total number of worker threads
212       * reserved for processing operations that are part of an administrative
213       * session.
214       */
215      private static final String ATTR_NUM_ADMIN_WORKER_THREADS =
216           "num-administrative-session-worker-threads";
217    
218    
219    
220      /**
221       * The name of the attribute that contains the number of worker threads that
222       * are currently busy processing operations as part of an administrative
223       * session.
224       */
225      private static final String ATTR_NUM_BUSY_ADMIN_WORKER_THREADS =
226           "num-busy-administrative-session-worker-threads";
227    
228    
229    
230      /**
231       * The serial version UID for this serializable class.
232       */
233      private static final long serialVersionUID = -304216058351812232L;
234    
235    
236    
237      // The average queue time in milliseconds.
238      private final Long averageQueueTimeMillis;
239    
240      // The average worker thread percent busy.
241      private final Long averagePercentBusy;
242    
243      // The average work queue size.
244      private final Long averageSize;
245    
246      // The current administrative session work queue size.
247      private final Long currentAdminSize;
248    
249      // The current work queue size.
250      private final Long currentSize;
251    
252      // The current worker thread percent busy.
253      private final Long currentPercentBusy;
254    
255      // The maximum administrative session work queue size.
256      private final Long maxAdminSize;
257    
258      // The maximum worker thread percent busy.
259      private final Long maxPercentBusy;
260    
261      // The maximum work queue size.
262      private final Long maxSize;
263    
264      // The number of administrative session worker threads.
265      private final Long numAdminWorkerThreads;
266    
267      // The number of busy worker threads.
268      private final Long numBusyWorkerThreads;
269    
270      // The number of busy administrative session worker threads.
271      private final Long numBusyAdminWorkerThreads;
272    
273      // The number of worker threads.
274      private final Long numWorkerThreads;
275    
276      // The recent average work queue size.
277      private final Long recentAverageSize;
278    
279      // The recent queue time in milliseconds.
280      private final Long recentQueueTimeMillis;
281    
282      // The recent worker thread percent busy.
283      private final Long recentPercentBusy;
284    
285      // The total number of requests rejected due to a full work queue.
286      private final Long requestsRejected;
287    
288    
289    
290      /**
291       * Creates a new UnboundID work queue monitor entry from the provided entry.
292       *
293       * @param  entry  The entry to be parsed as a traditional work queue monitor
294       *                entry.  It must not be {@code null}.
295       */
296      public UnboundIDWorkQueueMonitorEntry(final Entry entry)
297      {
298        super(entry);
299    
300        averageSize               = getLong(ATTR_AVERAGE_SIZE);
301        currentSize               = getLong(ATTR_CURRENT_SIZE);
302        recentAverageSize         = getLong(ATTR_RECENT_AVERAGE_SIZE);
303        maxSize                   = getLong(ATTR_MAX_SIZE);
304        requestsRejected          = getLong(ATTR_REQUESTS_REJECTED);
305        numBusyWorkerThreads      = getLong(ATTR_NUM_BUSY_WORKER_THREADS);
306        numWorkerThreads          = getLong(ATTR_NUM_WORKER_THREADS);
307        currentPercentBusy        = getLong(ATTR_CURRENT_PCT_BUSY);
308        averagePercentBusy        = getLong(ATTR_AVERAGE_PCT_BUSY);
309        recentPercentBusy         = getLong(ATTR_RECENT_PCT_BUSY);
310        maxPercentBusy            = getLong(ATTR_MAX_PCT_BUSY);
311        averageQueueTimeMillis    = getLong(ATTR_AVERAGE_QUEUE_TIME_MILLIS);
312        recentQueueTimeMillis     = getLong(ATTR_RECENT_QUEUE_TIME_MILLIS);
313        currentAdminSize          = getLong(ATTR_CURRENT_ADMIN_QUEUE_SIZE);
314        maxAdminSize              = getLong(ATTR_MAX_ADMIN_SESSION_QUEUE_SIZE);
315        numAdminWorkerThreads     = getLong(ATTR_NUM_ADMIN_WORKER_THREADS);
316        numBusyAdminWorkerThreads = getLong(ATTR_NUM_BUSY_ADMIN_WORKER_THREADS);
317      }
318    
319    
320    
321      /**
322       * Retrieves the average number of operations observed in the work queue.
323       *
324       * @return  The average number of operations observed in the work queue, or
325       *          {@code null} if that information was not included in the monitor
326       *          entry.
327       */
328      public Long getAverageSize()
329      {
330        return averageSize;
331      }
332    
333    
334    
335      /**
336       * Retrieves the average number of operations observed in the work queue over
337       * a recent interval.
338       *
339       * @return  The average number of operations observed in the work queue over a
340       *          recent interval, or {@code null} if that information was not
341       *          included in the monitor entry.
342       */
343      public Long getRecentAverageSize()
344      {
345        return recentAverageSize;
346      }
347    
348    
349    
350      /**
351       * Retrieves the number of operations that are currently in the work queue
352       * waiting to be processed.
353       *
354       * @return  The number of operations that are currently in the work queue
355       *          waiting to be processed, or {@code null} if that information was
356       *          not included in the monitor entry.
357       */
358      public Long getCurrentSize()
359      {
360        return currentSize;
361      }
362    
363    
364    
365      /**
366       * Retrieves the maximum number of operations observed in the work queue at
367       * any given time.
368       *
369       * @return  The total number of operations observed in the work queue at any
370       *          given time, or {@code null} if that information was not included
371       *          in the monitor entry.
372       */
373      public Long getMaxSize()
374      {
375        return maxSize;
376      }
377    
378    
379    
380      /**
381       * Retrieves the total number of operation requests that were rejected because
382       * the work queue was at its maximum capacity.
383       *
384       * @return  The total number of operation requests rejected because the work
385       *          queue was at its maximum capacity, or {@code null} if that
386       *          information was not included in the monitor entry.
387       */
388      public Long getRequestsRejectedDueToQueueFull()
389      {
390        return requestsRejected;
391      }
392    
393    
394    
395      /**
396       * Retrieves the number of worker threads configured for the work queue.
397       *
398       * @return  The number of worker threads configured for the work queue, or
399       *          {@code null} if that information was not included in the monitor
400       *          entry.
401       */
402      public Long getNumWorkerThreads()
403      {
404        return numWorkerThreads;
405      }
406    
407    
408    
409      /**
410       * Retrieves the number of worker threads that are currently busy processing
411       * an operation.
412       *
413       * @return  The number of worker threads that are currently busy processing an
414       *          operation, or {@code null} if that information was not included in
415       *          the monitor entry.
416       */
417      public Long getNumBusyWorkerThreads()
418      {
419        return numBusyWorkerThreads;
420      }
421    
422    
423    
424      /**
425       * Retrieves the percentage of worker threads that are currently busy
426       * processing an operation.
427       *
428       * @return  The percentage of worker threads that are currently busy
429       *          processing an operation, or {@code null} if that information was
430       *          not included in the monitor entry.
431       */
432      public Long getCurrentWorkerThreadPercentBusy()
433      {
434        return currentPercentBusy;
435      }
436    
437    
438    
439      /**
440       * Retrieves the average percentage of the time since startup that worker
441       * threads have spent busy processing operations.
442       *
443       * @return  The average percentage of the time since startup that worker
444       *          threads have spent busy processing operations, or {@code null} if
445       *          that information was not included in the monitor entry.
446       */
447      public Long getAverageWorkerThreadPercentBusy()
448      {
449        return averagePercentBusy;
450      }
451    
452    
453    
454      /**
455       * Retrieves the percentage of the time over a recent interval that worker
456       * threads have spent busy processing operations.
457       *
458       * @return  The percentage of the time over a recent interval that worker
459       *          threads have spent busy processing operations, or {@code null} if
460       *          that information was not included in the monitor entry.
461       */
462      public Long getRecentWorkerThreadPercentBusy()
463      {
464        return recentPercentBusy;
465      }
466    
467    
468    
469      /**
470       * Retrieves the maximum percentage of the time over any interval that worker
471       * threads have spent busy processing operations.
472       *
473       * @return  The maximum percentage of the time over any interval that worker
474       *          threads have spent busy processing operations, or {@code null} if
475       *          that information was not included in the monitor entry.
476       */
477      public Long getMaxWorkerThreadPercentBusy()
478      {
479        return maxPercentBusy;
480      }
481    
482    
483    
484      /**
485       * Retrieves the average length of time in milliseconds that operations have
486       * been required to wait on the work queue before being picked up by a worker
487       * thread.
488       *
489       * @return  The average length of time in milliseconds that operations have
490       *          been required to wait on the work queue, or {@code null} if that
491       *          information was not included in the monitor entry.
492       */
493      public Long getAverageOperationQueueTimeMillis()
494      {
495        return averageQueueTimeMillis;
496      }
497    
498    
499    
500      /**
501       * Retrieves the average length of time in milliseconds that
502       * recently-processed operations have been required to wait on the work queue
503       * before being picked up by a worker thread.
504       *
505       * @return  The average length of time in milliseconds that recently-processed
506       *          operations have been required to wait on the work queue, or
507       *          {@code null} if that information was not included in the monitor
508       *          entry.
509       */
510      public Long getRecentOperationQueueTimeMillis()
511      {
512        return recentQueueTimeMillis;
513      }
514    
515    
516    
517      /**
518       * Retrieves the number of operations that are currently waiting to be
519       * processed in the portion of the work queue reserved for operations that are
520       * part of an administrative session.
521       *
522       * @return  The number of operations that are currently waiting to be
523       *          processed in the portion of the work queue reserved for operations
524       *          that are part of an administrative session, or {@code null} if
525       *          that information was not included in the monitor entry.
526       */
527      public Long getCurrentAdministrativeSessionQueueSize()
528      {
529        return currentAdminSize;
530      }
531    
532    
533    
534      /**
535       * Retrieves the maximum number of operations observed in the dedicated
536       * administrative session queue at any given time.
537       *
538       * @return  The total number of operations observed in the dedicated
539       *          administrative session queue at any given time, or {@code null} if
540       *          that information was not included in the monitor entry.
541       */
542      public Long getMaxAdministrativeSessionQueueSize()
543      {
544        return maxAdminSize;
545      }
546    
547    
548    
549      /**
550       * Retrieves the number of worker threads that have been reserved for
551       * processing operations that are part of an administrative session.
552       *
553       * @return  The number of worker threads that have been reserved for
554       *          processing operations that are part of an administrative session,
555       *          or {@code null} if that information was not included in the
556       *          monitor entry.
557       */
558      public Long getNumAdministrativeSessionWorkerThreads()
559      {
560        return numAdminWorkerThreads;
561      }
562    
563    
564    
565      /**
566       * Retrieves the number of worker threads that are currently busy processing
567       * an operation which is part of an administrative session.
568       *
569       * @return  The number of worker threads that are currently busy processing an
570       *          operation which is part of an administrative session, or
571       *          {@code null} if that information was not included in the monitor
572       *          entry.
573       */
574      public Long getNumBusyAdministrativeSessionWorkerThreads()
575      {
576        return numBusyAdminWorkerThreads;
577      }
578    
579    
580    
581      /**
582       * {@inheritDoc}
583       */
584      @Override()
585      public String getMonitorDisplayName()
586      {
587        return INFO_UNBOUNDID_WORK_QUEUE_MONITOR_DISPNAME.get();
588      }
589    
590    
591    
592      /**
593       * {@inheritDoc}
594       */
595      @Override()
596      public String getMonitorDescription()
597      {
598        return INFO_UNBOUNDID_WORK_QUEUE_MONITOR_DESC.get();
599      }
600    
601    
602    
603      /**
604       * {@inheritDoc}
605       */
606      @Override()
607      public Map<String,MonitorAttribute> getMonitorAttributes()
608      {
609        final LinkedHashMap<String,MonitorAttribute> attrs =
610             new LinkedHashMap<String,MonitorAttribute>();
611    
612        if (requestsRejected != null)
613        {
614          addMonitorAttribute(attrs,
615               ATTR_REQUESTS_REJECTED,
616               INFO_UNBOUNDID_WORK_QUEUE_DISPNAME_REQUESTS_REJECTED.get(),
617               INFO_UNBOUNDID_WORK_QUEUE_DESC_REQUESTS_REJECTED.get(),
618               requestsRejected);
619        }
620    
621        if (currentSize != null)
622        {
623          addMonitorAttribute(attrs,
624               ATTR_CURRENT_SIZE,
625               INFO_UNBOUNDID_WORK_QUEUE_DISPNAME_CURRENT_SIZE.get(),
626               INFO_UNBOUNDID_WORK_QUEUE_DESC_CURRENT_SIZE.get(),
627               currentSize);
628        }
629    
630        if (recentAverageSize != null)
631        {
632          addMonitorAttribute(attrs,
633               ATTR_RECENT_AVERAGE_SIZE,
634               INFO_UNBOUNDID_WORK_QUEUE_DISPNAME_RECENT_AVERAGE_SIZE.get(),
635               INFO_UNBOUNDID_WORK_QUEUE_DESC_RECENT_AVERAGE_SIZE.get(),
636               recentAverageSize);
637        }
638    
639        if (averageSize != null)
640        {
641          addMonitorAttribute(attrs,
642               ATTR_AVERAGE_SIZE,
643               INFO_UNBOUNDID_WORK_QUEUE_DISPNAME_AVERAGE_SIZE.get(),
644               INFO_UNBOUNDID_WORK_QUEUE_DESC_AVERAGE_SIZE.get(),
645               averageSize);
646        }
647    
648        if (maxSize != null)
649        {
650          addMonitorAttribute(attrs,
651               ATTR_MAX_SIZE,
652               INFO_UNBOUNDID_WORK_QUEUE_DISPNAME_MAX_SIZE.get(),
653               INFO_UNBOUNDID_WORK_QUEUE_DESC_MAX_SIZE.get(),
654               maxSize);
655        }
656    
657        if (numWorkerThreads != null)
658        {
659          addMonitorAttribute(attrs,
660               ATTR_NUM_WORKER_THREADS,
661               INFO_UNBOUNDID_WORK_QUEUE_DISPNAME_NUM_THREADS.get(),
662               INFO_UNBOUNDID_WORK_QUEUE_DESC_NUM_THREADS.get(),
663               numWorkerThreads);
664        }
665    
666        if (numBusyWorkerThreads != null)
667        {
668          addMonitorAttribute(attrs,
669               ATTR_NUM_BUSY_WORKER_THREADS,
670               INFO_UNBOUNDID_WORK_QUEUE_DISPNAME_NUM_BUSY_THREADS.get(),
671               INFO_UNBOUNDID_WORK_QUEUE_DESC_NUM_BUSY_THREADS.get(),
672               numBusyWorkerThreads);
673        }
674    
675        if (currentPercentBusy != null)
676        {
677          addMonitorAttribute(attrs,
678               ATTR_CURRENT_PCT_BUSY,
679               INFO_UNBOUNDID_WORK_QUEUE_DISPNAME_CURRENT_PCT_BUSY.get(),
680               INFO_UNBOUNDID_WORK_QUEUE_DESC_CURRENT_PCT_BUSY.get(),
681               currentPercentBusy);
682        }
683    
684        if (averagePercentBusy != null)
685        {
686          addMonitorAttribute(attrs,
687               ATTR_AVERAGE_PCT_BUSY,
688               INFO_UNBOUNDID_WORK_QUEUE_DISPNAME_AVG_PCT_BUSY.get(),
689               INFO_UNBOUNDID_WORK_QUEUE_DESC_AVG_PCT_BUSY.get(),
690               averagePercentBusy);
691        }
692    
693        if (recentPercentBusy != null)
694        {
695          addMonitorAttribute(attrs,
696               ATTR_RECENT_PCT_BUSY,
697               INFO_UNBOUNDID_WORK_QUEUE_DISPNAME_RECENT_PCT_BUSY.get(),
698               INFO_UNBOUNDID_WORK_QUEUE_DESC_RECENT_PCT_BUSY.get(),
699               recentPercentBusy);
700        }
701    
702        if (maxPercentBusy != null)
703        {
704          addMonitorAttribute(attrs,
705               ATTR_MAX_PCT_BUSY,
706               INFO_UNBOUNDID_WORK_QUEUE_DISPNAME_MAX_PCT_BUSY.get(),
707               INFO_UNBOUNDID_WORK_QUEUE_DESC_MAX_PCT_BUSY.get(),
708               maxPercentBusy);
709        }
710    
711        if (averageQueueTimeMillis != null)
712        {
713          addMonitorAttribute(attrs,
714               ATTR_AVERAGE_QUEUE_TIME_MILLIS,
715               INFO_UNBOUNDID_WORK_QUEUE_DISPNAME_AVG_QUEUE_TIME.get(),
716               INFO_UNBOUNDID_WORK_QUEUE_DESC_AVG_QUEUE_TIME.get(),
717               averageQueueTimeMillis);
718        }
719    
720        if (recentQueueTimeMillis != null)
721        {
722          addMonitorAttribute(attrs,
723               ATTR_RECENT_QUEUE_TIME_MILLIS,
724               INFO_UNBOUNDID_WORK_QUEUE_DISPNAME_RECENT_QUEUE_TIME.get(),
725               INFO_UNBOUNDID_WORK_QUEUE_DESC_RECENT_QUEUE_TIME.get(),
726               recentQueueTimeMillis);
727        }
728    
729        if (currentAdminSize != null)
730        {
731          addMonitorAttribute(attrs,
732               ATTR_CURRENT_ADMIN_QUEUE_SIZE,
733               INFO_UNBOUNDID_WORK_QUEUE_DISPNAME_CURRENT_ADMIN_QUEUE_SIZE.get(),
734               INFO_UNBOUNDID_WORK_QUEUE_DESC_CURRENT_ADMIN_QUEUE_SIZE.get(),
735               currentAdminSize);
736        }
737    
738        if (maxAdminSize != null)
739        {
740          addMonitorAttribute(attrs,
741               ATTR_MAX_ADMIN_SESSION_QUEUE_SIZE,
742               INFO_UNBOUNDID_WORK_QUEUE_DISPNAME_MAX_ADMIN_QUEUE_SIZE.get(),
743               INFO_UNBOUNDID_WORK_QUEUE_DESC_MAX_ADMIN_QUEUE_SIZE.get(),
744               maxAdminSize);
745        }
746    
747        if (numAdminWorkerThreads != null)
748        {
749          addMonitorAttribute(attrs,
750               ATTR_NUM_ADMIN_WORKER_THREADS,
751               INFO_UNBOUNDID_WORK_QUEUE_DISPNAME_NUM_ADMIN_THREADS.get(),
752               INFO_UNBOUNDID_WORK_QUEUE_DESC_NUM_ADMIN_THREADS.get(),
753               numAdminWorkerThreads);
754        }
755    
756        if (numBusyAdminWorkerThreads != null)
757        {
758          addMonitorAttribute(attrs,
759               ATTR_NUM_BUSY_ADMIN_WORKER_THREADS,
760               INFO_UNBOUNDID_WORK_QUEUE_DISPNAME_NUM_BUSY_ADMIN_THREADS.get(),
761               INFO_UNBOUNDID_WORK_QUEUE_DESC_NUM_BUSY_ADMIN_THREADS.get(),
762               numBusyAdminWorkerThreads);
763        }
764    
765        return Collections.unmodifiableMap(attrs);
766      }
767    }