/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License, Version 1.0 only
* (the "License"). You may not use this file except in compliance
* with the License.
*
* You can obtain a copy of the license at
* trunk/opends/resource/legal-notices/OpenDS.LICENSE
* or https://OpenDS.dev.java.net/OpenDS.LICENSE.
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at
* trunk/opends/resource/legal-notices/OpenDS.LICENSE. If applicable,
* add the following below this CDDL HEADER, with the fields enclosed
* by brackets "[]" replaced with your own identifying information:
* Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*
*
* Copyright 2006-2010 Sun Microsystems, Inc.
* Portions copyright 2013 ForgeRock AS.
*/
package org.opends.server.api;
import static org.opends.messages.CoreMessages.*;
import static org.opends.server.loggers.ErrorLogger.*;
import org.opends.messages.Message;
import org.opends.server.admin.std.server.WorkQueueCfg;
import org.opends.server.config.ConfigException;
import org.opends.server.types.DirectoryException;
import org.opends.server.types.InitializationException;
import org.opends.server.types.Operation;
/**
* This class defines the structure and methods that must be
* implemented by a Directory Server work queue. The work queue is
* the component of the server that accepts requests from connection
* handlers and ensures that they are properly processed. The manner
* in which the work queue is able to accomplish this may vary between
* implementations, but in general it is assumed that one or more
* worker threads will be associated with the queue and may be used to
* process requests in parallel.
*
* @param <T> The type of configuration handled by this work queue.
*/
@org.opends.server.types.PublicAPI(
stability=org.opends.server.types.StabilityLevel.VOLATILE,
mayInstantiate=false,
mayExtend=true,
mayInvoke=true)
public abstract class WorkQueue<T extends WorkQueueCfg>
{
/**
* Initializes this work queue based on the information in the
* provided configuration entry.
*
* @param configuration The configuration to use to initialize
* the work queue.
*
* @throws ConfigException If the provided configuration entry
* does not have a valid work queue
* configuration.
*
* @throws InitializationException If a problem occurs during
* initialization that is not
* related to the server
* configuration.
*/
public abstract void initializeWorkQueue(T configuration)
throws ConfigException, InitializationException;
/**
* Performs any necessary finalization for this work queue,
* including ensuring that all active operations are interrupted or
* will be allowed to complete, and that all pending operations will
* be cancelled.
*
* @param reason The human-readable reason that the work queue is
* being shut down.
*/
public abstract void finalizeWorkQueue(Message reason);
/**
* Submits an operation to be processed in the server.
*
* @param operation The operation to be processed.
*
* @throws DirectoryException If the provided operation is not
* accepted for some reason (e.g., if
* the server is shutting down or
* already has too many pending
* requests in the queue).
*/
public abstract void submitOperation(Operation operation)
throws DirectoryException;
/**
* Tries to submit an operation to be processed in the server, without
* blocking.
*
* @param operation
* The operation to be processed.
* @return true if the operation could be submitted to the queue, false if the
* queue was full
* @throws DirectoryException
* If the provided operation is not accepted for some reason (e.g.,
* if the server is shutting down).
*/
public abstract boolean trySubmitOperation(Operation operation)
throws DirectoryException;
/**
* Indicates whether the work queue is currently processing any
* requests. Note that this is a point-in-time determination, and
* if any component of the server wishes to depend on a quiescent
* state then it should use some external mechanism to ensure that
* no other requests are submitted to the queue.
*
* @return {@code true} if the work queue is currently idle, or
* {@code false} if it is being used to process one or more
* operations.
*/
public abstract boolean isIdle();
/**
* Return the maximum number of worker threads that can be used by this
* WorkQueue (The WorkQueue could have a thread pool which adjusts its size).
*
* @return the maximum number of worker threads that can be used by this
* WorkQueue
*/
public abstract int getNumWorkerThreads();
/**
* Computes the number of worker threads to use by the working queue based on
* the configured number.
*
* @param configuredNumWorkerThreads
* the configured number of worker threads to use
* @return the number of worker threads to use
*/
protected int computeNumWorkerThreads(Integer configuredNumWorkerThreads)
{
if (configuredNumWorkerThreads != null)
{
return configuredNumWorkerThreads;
}
else
{
// Automatically choose based on the number of processors.
int cpus = Runtime.getRuntime().availableProcessors();
int value = Math.max(24, cpus * 2);
Message message = INFO_ERGONOMIC_SIZING_OF_WORKER_THREAD_POOL.get(value);
logError(message);
return value;
}
}
/**
* Waits for the work queue to become idle before returning. Note
* that this is a point-in-time determination, and if any component
* of the server wishes to depend on a quiescent state then it
* should use some external mechanism to ensure that no other
* requests are submitted to the queue.
*
* @param timeLimit The maximum length of time in milliseconds
* that this method should wait for the queue to
* become idle before giving up. A time limit
* that is less than or equal to zero indicates
* that there should not be a time limit.
*
* @return {@code true} if the work queue is idle at the time that
* this method returns, or {@code false} if the wait time
* limit was reached before the server became idle.
*/
public boolean waitUntilIdle(long timeLimit)
{
long stopWaitingTime;
if (timeLimit <= 0)
{
stopWaitingTime = Long.MAX_VALUE;
}
else
{
stopWaitingTime = System.currentTimeMillis() + timeLimit;
}
while (System.currentTimeMillis() < stopWaitingTime)
{
if (isIdle())
{
return true;
}
try
{
Thread.sleep(1);
} catch (InterruptedException ie) {}
}
return false;
}
}