001    /*
002     * CDDL HEADER START
003     *
004     * The contents of this file are subject to the terms of the
005     * Common Development and Distribution License, Version 1.0 only
006     * (the "License").  You may not use this file except in compliance
007     * with the License.
008     *
009     * You can obtain a copy of the license at
010     * trunk/opends/resource/legal-notices/OpenDS.LICENSE
011     * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
012     * See the License for the specific language governing permissions
013     * and limitations under the License.
014     *
015     * When distributing Covered Code, include this CDDL HEADER in each
016     * file and include the License file at
017     * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
018     * add the following below this CDDL HEADER, with the fields enclosed
019     * by brackets "[]" replaced with your own identifying information:
020     *      Portions Copyright [yyyy] [name of copyright owner]
021     *
022     * CDDL HEADER END
023     *
024     *
025     *      Copyright 2006-2008 Sun Microsystems, Inc.
026     */
027    package org.opends.server.api;
028    import org.opends.messages.Message;
029    
030    
031    
032    import org.opends.server.admin.std.server.WorkQueueCfg;
033    import org.opends.server.config.ConfigException;
034    import org.opends.server.types.AbstractOperation;
035    import org.opends.server.types.DirectoryException;
036    import org.opends.server.types.InitializationException;
037    
038    
039    
040    /**
041     * This class defines the structure and methods that must be
042     * implemented by a Directory Server work queue.  The work queue is
043     * the component of the server that accepts requests from connection
044     * handlers and ensures that they are properly processed.  The manner
045     * in which the work queue is able to accomplish this may vary between
046     * implementations, but in general it is assumed that one or more
047     * worker threads will be associated with the queue and may be used to
048     * process requests in parallel.
049     *
050     * @param  <T>  The type of configuration handled by this work queue.
051     */
052    @org.opends.server.types.PublicAPI(
053         stability=org.opends.server.types.StabilityLevel.VOLATILE,
054         mayInstantiate=false,
055         mayExtend=true,
056         mayInvoke=true)
057    public abstract class WorkQueue<T extends WorkQueueCfg>
058    {
059      /**
060       * Initializes this work queue based on the information in the
061       * provided configuration entry.
062       *
063       * @param  configuration  The configuration to use to initialize
064       *                        the work queue.
065       *
066       * @throws  ConfigException  If the provided configuration entry
067       *                           does not have a valid work queue
068       *                           configuration.
069       *
070       * @throws  InitializationException  If a problem occurs during
071       *                                   initialization that is not
072       *                                   related to the server
073       *                                   configuration.
074       */
075      public abstract void initializeWorkQueue(T configuration)
076             throws ConfigException, InitializationException;
077    
078    
079    
080      /**
081       * Performs any necessary finalization for this work queue,
082       * including ensuring that all active operations are interrupted or
083       * will be allowed to complete, and that all pending operations will
084       * be cancelled.
085       *
086       * @param  reason  The human-readable reason that the work queue is
087       *                 being shut down.
088       */
089      public abstract void finalizeWorkQueue(Message reason);
090    
091    
092    
093      /**
094       * Submits an operation to be processed in the server.
095       *
096       * @param  operation  The operation to be processed.
097       *
098       * @throws  DirectoryException  If the provided operation is not
099       *                              accepted for some reason (e.g., if
100       *                              the server is shutting down or
101       *                              already has too many pending
102       *                              requests in the queue).
103       */
104      public abstract void submitOperation(AbstractOperation operation)
105             throws DirectoryException;
106    
107    
108    
109      /**
110       * Indicates whether the work queue is currently processing any
111       * requests.  Note that this is a point-in-time determination, and
112       * if any component of the server wishes to depend on a quiescent
113       * state then it should use some external mechanism to ensure that
114       * no other requests are submitted to the queue.
115       *
116       * @return  {@code true} if the work queue is currently idle, or
117       *          {@code false} if it is being used to process one or more
118       *          operations.
119       */
120      public abstract boolean isIdle();
121    
122    
123    
124      /**
125       * Waits for the work queue to become idle before returning.  Note
126       * that this is a point-in-time determination, and if any component
127       * of the server wishes to depend on a quiescent state then it
128       * should use some external mechanism to ensure that no other
129       * requests are submitted to the queue.
130       *
131       * @param  timeLimit  The maximum length of time in milliseconds
132       *                    that this method should wait for the queue to
133       *                    become idle before giving up.  A time limit
134       *                    that is less than or equal to zero indicates
135       *                    that there should not be a time limit.
136       *
137       * @return  {@code true} if the work queue is idle at the time that
138       *          this method returns, or {@code false} if the wait time
139       *          limit was reached before the server became idle.
140       */
141      public boolean waitUntilIdle(long timeLimit)
142      {
143        long stopWaitingTime;
144        if (timeLimit <= 0)
145        {
146          stopWaitingTime = Long.MAX_VALUE;
147        }
148        else
149        {
150          stopWaitingTime = System.currentTimeMillis() + timeLimit;
151        }
152    
153        while (System.currentTimeMillis() < stopWaitingTime)
154        {
155          if (isIdle())
156          {
157            return true;
158          }
159    
160          try
161          {
162            Thread.sleep(1);
163          } catch (InterruptedException ie) {}
164        }
165    
166        return false;
167      }
168    }
169