mirror of https://github.com/OpenIdentityPlatform/OpenDJ.git

boli
17.19.2008 63463be883ebb6a2140ee4f66faeb9629bad89ad
This fix removes the option to use nanosecond etime resolution as a JVM property. It is now a global configuration attribute. Due to the 10% throughput decrease I saw when using System.nanoTime, the default still uses System.currentTimeMillis to timestamp operations. System.nanoTime will only be used when the ds-cfg-etime-resolution attribute is set to nano-seconds.

Fix for issue 2499
9 files modified
576 ■■■■■ changed files
opendj-sdk/opends/resource/config/config.ldif 1 ●●●● patch | view | raw | blame | history
opendj-sdk/opends/resource/schema/02-config.ldif 8 ●●●● patch | view | raw | blame | history
opendj-sdk/opends/src/admin/defn/org/opends/server/admin/std/GlobalConfiguration.xml 32 ●●●●● patch | view | raw | blame | history
opendj-sdk/opends/src/server/org/opends/server/core/CoreConfigManager.java 12 ●●●●● patch | view | raw | blame | history
opendj-sdk/opends/src/server/org/opends/server/core/SearchOperationBasis.java 16 ●●●●● patch | view | raw | blame | history
opendj-sdk/opends/src/server/org/opends/server/loggers/AccessLogger.java 415 ●●●● patch | view | raw | blame | history
opendj-sdk/opends/src/server/org/opends/server/types/AbstractOperation.java 63 ●●●● patch | view | raw | blame | history
opendj-sdk/opends/src/server/org/opends/server/util/ServerConstants.java 10 ●●●● patch | view | raw | blame | history
opendj-sdk/opends/src/server/org/opends/server/util/TimeThread.java 19 ●●●●● patch | view | raw | blame | history
opendj-sdk/opends/resource/config/config.ldif
@@ -49,6 +49,7 @@
ds-cfg-return-bind-error-messages: false
ds-cfg-idle-time-limit: 0 seconds
ds-cfg-save-config-on-successful-startup: true
ds-cfg-etime-resolution: milli-seconds
ds-cfg-allowed-task: org.opends.server.tasks.AddSchemaFileTask
ds-cfg-allowed-task: org.opends.server.tasks.BackupTask
ds-cfg-allowed-task: org.opends.server.tasks.DisconnectClientTask
opendj-sdk/opends/resource/schema/02-config.ldif
@@ -2172,6 +2172,11 @@
  SYNTAX 1.3.6.1.4.1.1466.115.121.1.12
  SINGLE-VALUE
  X-ORIGIN 'OpenDS Directory Server' )
attributeTypes: ( 1.3.6.1.4.1.26027.1.1.442
  NAME 'ds-cfg-etime-resolution'
  SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
  SINGLE-VALUE
  X-ORIGIN 'OpenDS Directory Server' )
attributeTypes: ( 1.3.6.1.4.1.26027.1.1.444
  NAME 'ds-task-reset-generation-id-new-value'
  SYNTAX 1.3.6.1.4.1.1466.115.121.1.27
@@ -2582,7 +2587,8 @@
        ds-cfg-return-bind-error-messages $
        ds-cfg-idle-time-limit $
        ds-cfg-workflow-configuration-mode $
        ds-cfg-save-config-on-successful-startup )
        ds-cfg-save-config-on-successful-startup $
        ds-cfg-etime-resolution )
  X-ORIGIN 'OpenDS Directory Server' )
objectClasses: ( 1.3.6.1.4.1.26027.1.2.40
  NAME 'ds-cfg-root-dn-user'
opendj-sdk/opends/src/admin/defn/org/opends/server/admin/std/GlobalConfiguration.xml
@@ -778,4 +778,36 @@
      </ldap:attribute>
    </adm:profile>
  </adm:property>
  <adm:property name="etime-resolution" mandatory="false">
    <adm:synopsis>
      The resolution to use for operation elapsed processing time (etime)
      measurements.
    </adm:synopsis>
    <adm:default-behavior>
      <adm:defined>
        <adm:value>
          milli-seconds
        </adm:value>
      </adm:defined>
    </adm:default-behavior>
    <adm:syntax>
      <adm:enumeration>
        <adm:value name="milli-seconds">
          <adm:synopsis>
            Use milli-second resolution.
          </adm:synopsis>
        </adm:value>
        <adm:value name="nano-seconds">
          <adm:synopsis>
            Use nano-second resolution.
          </adm:synopsis>
        </adm:value>
      </adm:enumeration>
    </adm:syntax>
    <adm:profile name="ldap">
      <ldap:attribute>
        <ldap:name>ds-cfg-etime-resolution</ldap:name>
      </ldap:attribute>
    </adm:profile>
  </adm:property>
</adm:managed-object>
opendj-sdk/opends/src/server/org/opends/server/core/CoreConfigManager.java
@@ -22,7 +22,7 @@
 * CDDL HEADER END
 *
 *
 *      Portions Copyright 2006-2007 Sun Microsystems, Inc.
 *      Portions Copyright 2006-2008 Sun Microsystems, Inc.
 */
package org.opends.server.core;
import org.opends.messages.Message;
@@ -42,12 +42,7 @@
import org.opends.server.admin.std.server.RootCfg;
import org.opends.server.admin.server.ServerManagementContext;
import org.opends.server.config.ConfigException;
import org.opends.server.types.AcceptRejectWarn;
import org.opends.server.types.ConfigChangeResult;
import org.opends.server.types.InitializationException;
import org.opends.server.types.Privilege;
import org.opends.server.types.ResultCode;
import org.opends.server.types.WritabilityMode;
import org.opends.server.types.*;
import static org.opends.messages.ConfigMessages.*;
@@ -357,6 +352,9 @@
    {
      DirectoryServer.setWorkflowConfigurationMode(newMode);
    }
    AbstractOperation.setUseNanoTime(globalConfig.getEtimeResolution() ==
      GlobalCfgDefn.EtimeResolution.NANO_SECONDS);
  }
opendj-sdk/opends/src/server/org/opends/server/core/SearchOperationBasis.java
@@ -22,7 +22,7 @@
 * CDDL HEADER END
 *
 *
 *      Portions Copyright 2007 Sun Microsystems, Inc.
 *      Portions Copyright 2006-2008 Sun Microsystems, Inc.
 */
package org.opends.server.core;
@@ -627,8 +627,9 @@
    // See if the time limit has expired.  If so, then don't send the entry and
    // indicate that the search should end.
    if ((getTimeLimit() > 0) && (TimeThread.getTime() >=
                                                getTimeLimitExpiration()))
    if ((getTimeLimit() > 0) &&
        ((getUseNanoTime() ? TimeThread.getNanoTime() :
                             TimeThread.getTime()) >= getTimeLimitExpiration()))
    {
      setResultCode(ResultCode.TIME_LIMIT_EXCEEDED);
      appendErrorMessage(ERR_SEARCH_TIME_LIMIT_EXCEEDED.get(getTimeLimit()));
@@ -1054,8 +1055,9 @@
    // See if the time limit has expired.  If so, then don't send the entry and
    // indicate that the search should end.
    if ((getTimeLimit() > 0) && (TimeThread.getTime() >=
                                        getTimeLimitExpiration()))
    if ((getTimeLimit() > 0) &&
        ((getUseNanoTime() ? TimeThread.getNanoTime() :
                             TimeThread.getTime()) >= getTimeLimitExpiration()))
    {
      setResultCode(ResultCode.TIME_LIMIT_EXCEEDED);
      appendErrorMessage(ERR_SEARCH_TIME_LIMIT_EXCEEDED.get(getTimeLimit()));
@@ -1623,8 +1625,8 @@
    else
    {
      // FIXME -- Factor in the user's effective time limit.
      timeLimitExpiration =
        getProcessingStartTime() + (1000L * timeLimit);
      timeLimitExpiration = getProcessingStartTime() +
          ((getUseNanoTime() ? 1000000000L : 1000L) * timeLimit);
    }
    setTimeLimitExpiration(timeLimitExpiration);
opendj-sdk/opends/src/server/org/opends/server/loggers/AccessLogger.java
@@ -71,23 +71,24 @@
  private static final DebugTracer TRACER = getTracer();
  // The set of access loggers that have been registered with the server.  It
   // will initially be empty.
   static CopyOnWriteArrayList<AccessLogPublisher> accessPublishers =
       new CopyOnWriteArrayList<AccessLogPublisher>();
  // will initially be empty.
  static CopyOnWriteArrayList<AccessLogPublisher> accessPublishers =
      new CopyOnWriteArrayList<AccessLogPublisher>();
   // The singleton instance of this class for configuration purposes.
   static final AccessLogger instance = new AccessLogger();
  // The singleton instance of this class for configuration purposes.
  static final AccessLogger instance = new AccessLogger();
   /**
    * Retrieve the singleton instance of this class.
    *
    * @return The singleton instance of this logger.
    */
   public static AccessLogger getInstance()
   {
     return instance;
   }
  /**
   * Retrieve the singleton instance of this class.
   *
   * @return The singleton instance of this logger.
   */
  public static AccessLogger getInstance()
  {
    return instance;
  }
  /**
   * Add an access log publisher to the access logger.
@@ -144,101 +145,101 @@
   *           If a problem occurs during initialization that is not
   *           related to the server configuration.
   */
   public void initializeAccessLogger(List<AccessLogPublisherCfg> configs)
       throws ConfigException, InitializationException
   {
     for(AccessLogPublisherCfg config : configs)
     {
       config.addAccessChangeListener(this);
  public void initializeAccessLogger(List<AccessLogPublisherCfg> configs)
      throws ConfigException, InitializationException
  {
    for(AccessLogPublisherCfg config : configs)
    {
      config.addAccessChangeListener(this);
       if(config.isEnabled())
       {
         AccessLogPublisher AccessLogPublisher = getAccessPublisher(config);
      if(config.isEnabled())
      {
        AccessLogPublisher AccessLogPublisher = getAccessPublisher(config);
         addAccessLogPublisher(AccessLogPublisher);
       }
     }
   }
        addAccessLogPublisher(AccessLogPublisher);
      }
    }
  }
  /**
   * {@inheritDoc}
   */
   public boolean isConfigurationAddAcceptable(
          AccessLogPublisherCfg config,
          List<Message> unacceptableReasons)
   {
     return !config.isEnabled() ||
         isJavaClassAcceptable(config, unacceptableReasons);
   }
  public boolean isConfigurationAddAcceptable(
      AccessLogPublisherCfg config,
      List<Message> unacceptableReasons)
  {
    return !config.isEnabled() ||
        isJavaClassAcceptable(config, unacceptableReasons);
  }
  /**
   * {@inheritDoc}
   */
   public boolean isConfigurationChangeAcceptable(
          AccessLogPublisherCfg config,
          List<Message> unacceptableReasons)
   {
     return !config.isEnabled() ||
         isJavaClassAcceptable(config, unacceptableReasons);
   }
  public boolean isConfigurationChangeAcceptable(
      AccessLogPublisherCfg config,
      List<Message> unacceptableReasons)
  {
    return !config.isEnabled() ||
        isJavaClassAcceptable(config, unacceptableReasons);
  }
  /**
   * {@inheritDoc}
   */
   public ConfigChangeResult applyConfigurationAdd(AccessLogPublisherCfg config)
   {
     // Default result code.
     ResultCode resultCode = ResultCode.SUCCESS;
     boolean adminActionRequired = false;
     ArrayList<Message> messages = new ArrayList<Message>();
  public ConfigChangeResult applyConfigurationAdd(AccessLogPublisherCfg config)
  {
    // Default result code.
    ResultCode resultCode = ResultCode.SUCCESS;
    boolean adminActionRequired = false;
    ArrayList<Message> messages = new ArrayList<Message>();
     config.addAccessChangeListener(this);
    config.addAccessChangeListener(this);
     if(config.isEnabled())
     {
       try
       {
         AccessLogPublisher AccessLogPublisher = getAccessPublisher(config);
    if(config.isEnabled())
    {
      try
      {
        AccessLogPublisher AccessLogPublisher = getAccessPublisher(config);
         addAccessLogPublisher(AccessLogPublisher);
       }
       catch(ConfigException e)
       {
         if (debugEnabled())
         {
           TRACER.debugCaught(DebugLogLevel.ERROR, e);
         }
         messages.add(e.getMessageObject());
         resultCode = DirectoryServer.getServerErrorResultCode();
       }
       catch (Exception e)
       {
         if (debugEnabled())
         {
           TRACER.debugCaught(DebugLogLevel.ERROR, e);
         }
        addAccessLogPublisher(AccessLogPublisher);
      }
      catch(ConfigException e)
      {
        if (debugEnabled())
        {
          TRACER.debugCaught(DebugLogLevel.ERROR, e);
        }
        messages.add(e.getMessageObject());
        resultCode = DirectoryServer.getServerErrorResultCode();
      }
      catch (Exception e)
      {
        if (debugEnabled())
        {
          TRACER.debugCaught(DebugLogLevel.ERROR, e);
        }
         messages.add(ERR_CONFIG_LOGGER_CANNOT_CREATE_LOGGER.get(
                 String.valueOf(config.dn().toString()),
                 stackTraceToSingleLineString(e)));
         resultCode = DirectoryServer.getServerErrorResultCode();
       }
     }
     return new ConfigChangeResult(resultCode, adminActionRequired, messages);
   }
        messages.add(ERR_CONFIG_LOGGER_CANNOT_CREATE_LOGGER.get(
            String.valueOf(config.dn().toString()),
            stackTraceToSingleLineString(e)));
        resultCode = DirectoryServer.getServerErrorResultCode();
      }
    }
    return new ConfigChangeResult(resultCode, adminActionRequired, messages);
  }
  /**
   * {@inheritDoc}
   */
   public ConfigChangeResult applyConfigurationChange(
       AccessLogPublisherCfg config)
   {
     // Default result code.
     ResultCode resultCode = ResultCode.SUCCESS;
     boolean adminActionRequired = false;
     ArrayList<Message> messages = new ArrayList<Message>();
  public ConfigChangeResult applyConfigurationChange(
      AccessLogPublisherCfg config)
  {
    // Default result code.
    ResultCode resultCode = ResultCode.SUCCESS;
    boolean adminActionRequired = false;
    ArrayList<Message> messages = new ArrayList<Message>();
     DN dn = config.dn();
    DN dn = config.dn();
    AccessLogPublisher accessLogPublisher = null;
    for(AccessLogPublisher publisher : accessPublishers)
@@ -250,47 +251,47 @@
      }
    }
     if(accessLogPublisher == null)
     {
       if(config.isEnabled())
       {
         // Needs to be added and enabled.
         return applyConfigurationAdd(config);
       }
     }
     else
     {
       if(config.isEnabled())
       {
         // The publisher is currently active, so we don't need to do anything.
         // Changes to the class name cannot be
         // applied dynamically, so if the class name did change then
         // indicate that administrative action is required for that
         // change to take effect.
         String className = config.getJavaClass();
         if(!className.equals(accessLogPublisher.getClass().getName()))
         {
           adminActionRequired = true;
         }
       }
       else
       {
         // The publisher is being disabled so shut down and remove.
         removeAccessLogPublisher(accessLogPublisher);
       }
     }
    if(accessLogPublisher == null)
    {
      if(config.isEnabled())
      {
        // Needs to be added and enabled.
        return applyConfigurationAdd(config);
      }
    }
    else
    {
      if(config.isEnabled())
      {
        // The publisher is currently active, so we don't need to do anything.
        // Changes to the class name cannot be
        // applied dynamically, so if the class name did change then
        // indicate that administrative action is required for that
        // change to take effect.
        String className = config.getJavaClass();
        if(!className.equals(accessLogPublisher.getClass().getName()))
        {
          adminActionRequired = true;
        }
      }
      else
      {
        // The publisher is being disabled so shut down and remove.
        removeAccessLogPublisher(accessLogPublisher);
      }
    }
     return new ConfigChangeResult(resultCode, adminActionRequired, messages);
   }
    return new ConfigChangeResult(resultCode, adminActionRequired, messages);
  }
  /**
   * {@inheritDoc}
   */
   public boolean isConfigurationDeleteAcceptable(
          AccessLogPublisherCfg config,
          List<Message> unacceptableReasons)
   {
     DN dn = config.dn();
  public boolean isConfigurationDeleteAcceptable(
      AccessLogPublisherCfg config,
      List<Message> unacceptableReasons)
  {
    DN dn = config.dn();
    AccessLogPublisher accessLogPublisher = null;
    for(AccessLogPublisher publisher : accessPublishers)
@@ -302,14 +303,14 @@
      }
    }
     return accessLogPublisher != null;
    return accessLogPublisher != null;
   }
  }
  /**
   * {@inheritDoc}
   */
   public ConfigChangeResult applyConfigurationDelete(
  public ConfigChangeResult applyConfigurationDelete(
      AccessLogPublisherCfg config)
  {
    // Default result code.
@@ -338,92 +339,92 @@
    return new ConfigChangeResult(resultCode, adminActionRequired);
  }
   private boolean isJavaClassAcceptable(AccessLogPublisherCfg config,
                                         List<Message> unacceptableReasons)
   {
     String className = config.getJavaClass();
     AccessLogPublisherCfgDefn d = AccessLogPublisherCfgDefn.getInstance();
     ClassPropertyDefinition pd =
         d.getJavaClassPropertyDefinition();
     // Load the class and cast it to a DebugLogPublisher.
     AccessLogPublisher publisher = null;
     Class<? extends AccessLogPublisher> theClass;
     try {
       theClass = pd.loadClass(className, AccessLogPublisher.class);
       publisher = theClass.newInstance();
     } catch (Exception e) {
       Message message = ERR_CONFIG_LOGGER_INVALID_ACCESS_LOGGER_CLASS.get(
               className,
               config.dn().toString(),
               String.valueOf(e));
       unacceptableReasons.add(message);
       return false;
     }
     // Check that the implementation class implements the correct interface.
     try {
       // Determine the initialization method to use: it must take a
       // single parameter which is the exact type of the configuration
       // object.
       Method method = theClass.getMethod("isConfigurationAcceptable",
                                          AccessLogPublisherCfg.class,
                                          List.class);
       Boolean acceptable = (Boolean) method.invoke(publisher, config,
                                                    unacceptableReasons);
  private boolean isJavaClassAcceptable(AccessLogPublisherCfg config,
                                        List<Message> unacceptableReasons)
  {
    String className = config.getJavaClass();
    AccessLogPublisherCfgDefn d = AccessLogPublisherCfgDefn.getInstance();
    ClassPropertyDefinition pd =
        d.getJavaClassPropertyDefinition();
    // Load the class and cast it to a DebugLogPublisher.
    AccessLogPublisher publisher = null;
    Class<? extends AccessLogPublisher> theClass;
    try {
      theClass = pd.loadClass(className, AccessLogPublisher.class);
      publisher = theClass.newInstance();
    } catch (Exception e) {
      Message message = ERR_CONFIG_LOGGER_INVALID_ACCESS_LOGGER_CLASS.get(
          className,
          config.dn().toString(),
          String.valueOf(e));
      unacceptableReasons.add(message);
      return false;
    }
    // Check that the implementation class implements the correct interface.
    try {
      // Determine the initialization method to use: it must take a
      // single parameter which is the exact type of the configuration
      // object.
      Method method = theClass.getMethod("isConfigurationAcceptable",
          AccessLogPublisherCfg.class,
          List.class);
      Boolean acceptable = (Boolean) method.invoke(publisher, config,
          unacceptableReasons);
       if (! acceptable)
       {
         return false;
       }
     } catch (Exception e) {
       Message message = ERR_CONFIG_LOGGER_INVALID_ACCESS_LOGGER_CLASS.get(
               className,
               config.dn().toString(),
               String.valueOf(e));
       unacceptableReasons.add(message);
       return false;
     }
     // The class is valid as far as we can tell.
     return true;
   }
      if (! acceptable)
      {
        return false;
      }
    } catch (Exception e) {
      Message message = ERR_CONFIG_LOGGER_INVALID_ACCESS_LOGGER_CLASS.get(
          className,
          config.dn().toString(),
          String.valueOf(e));
      unacceptableReasons.add(message);
      return false;
    }
    // The class is valid as far as we can tell.
    return true;
  }
   private AccessLogPublisher getAccessPublisher(AccessLogPublisherCfg config)
       throws ConfigException {
     String className = config.getJavaClass();
     AccessLogPublisherCfgDefn d = AccessLogPublisherCfgDefn.getInstance();
     ClassPropertyDefinition pd =
         d.getJavaClassPropertyDefinition();
     // Load the class and cast it to a AccessLogPublisher.
     Class<? extends AccessLogPublisher> theClass;
     AccessLogPublisher AccessLogPublisher;
     try {
       theClass = pd.loadClass(className, AccessLogPublisher.class);
       AccessLogPublisher = theClass.newInstance();
  private AccessLogPublisher getAccessPublisher(AccessLogPublisherCfg config)
      throws ConfigException {
    String className = config.getJavaClass();
    AccessLogPublisherCfgDefn d = AccessLogPublisherCfgDefn.getInstance();
    ClassPropertyDefinition pd =
        d.getJavaClassPropertyDefinition();
    // Load the class and cast it to a AccessLogPublisher.
    Class<? extends AccessLogPublisher> theClass;
    AccessLogPublisher AccessLogPublisher;
    try {
      theClass = pd.loadClass(className, AccessLogPublisher.class);
      AccessLogPublisher = theClass.newInstance();
       // Determine the initialization method to use: it must take a
       // single parameter which is the exact type of the configuration
       // object.
       Method method = theClass.getMethod("initializeAccessLogPublisher", config
      // Determine the initialization method to use: it must take a
      // single parameter which is the exact type of the configuration
      // object.
      Method method = theClass.getMethod("initializeAccessLogPublisher", config
          .configurationClass());
       method.invoke(AccessLogPublisher, config);
     }
     catch (InvocationTargetException ite)
     {
       // Rethrow the exceptions thrown be the invoked method.
       Throwable e = ite.getTargetException();
       Message message = ERR_CONFIG_LOGGER_INVALID_ACCESS_LOGGER_CLASS.get(
           className, config.dn().toString(), stackTraceToSingleLineString(e));
       throw new ConfigException(message, e);
     }
     catch (Exception e)
     {
       Message message = ERR_CONFIG_LOGGER_INVALID_ACCESS_LOGGER_CLASS.get(
           className, config.dn().toString(), String.valueOf(e));
       throw new ConfigException(message, e);
     }
      method.invoke(AccessLogPublisher, config);
    }
    catch (InvocationTargetException ite)
    {
      // Rethrow the exceptions thrown be the invoked method.
      Throwable e = ite.getTargetException();
      Message message = ERR_CONFIG_LOGGER_INVALID_ACCESS_LOGGER_CLASS.get(
          className, config.dn().toString(), stackTraceToSingleLineString(e));
      throw new ConfigException(message, e);
    }
    catch (Exception e)
    {
      Message message = ERR_CONFIG_LOGGER_INVALID_ACCESS_LOGGER_CLASS.get(
          className, config.dn().toString(), String.valueOf(e));
      throw new ConfigException(message, e);
    }
     // The access publisher has been successfully initialized.
     return AccessLogPublisher;
   }
    // The access publisher has been successfully initialized.
    return AccessLogPublisher;
  }
@@ -569,7 +570,7 @@
  /**
 * Writes a message to the access logger with information about the compare
   * Writes a message to the access logger with information about the compare
   * request associated with the provided compare operation.
   *
   * @param  compareOperation  The compare operation containing the information
opendj-sdk/opends/src/server/org/opends/server/types/AbstractOperation.java
@@ -22,7 +22,7 @@
 * CDDL HEADER END
 *
 *
 *      Portions Copyright 2007 Sun Microsystems, Inc.
 *      Portions Copyright 2006-2008 Sun Microsystems, Inc.
 */
package org.opends.server.types;
import org.opends.messages.Message;
@@ -74,16 +74,6 @@
   */
  protected static boolean useNanoTime = false;
  static
  {
    if(System.getProperty(PROPERTY_ETIME_NANO) != null &&
         System.getProperty(PROPERTY_ETIME_NANO).
            equalsIgnoreCase("true"))
    {
      useNanoTime = true;
    }
  }
  /**
   * The client connection with which this operation is associated.
@@ -104,6 +94,12 @@
  protected final long operationID;
  /**
   * Wether nanotime was used for this operation.
   */
  protected final boolean usingNanoTime;
  // Indicates whether this is an internal operation triggered within
  // the server itself rather than requested by an external client.
@@ -172,6 +168,7 @@
    this.clientConnection = clientConnection;
    this.operationID      = operationID;
    this.messageID        = messageID;
    this.usingNanoTime    = useNanoTime;
    if (requestControls == null)
    {
@@ -1045,7 +1042,7 @@
   */
  public final void setProcessingStartTime()
  {
    if(useNanoTime)
    if(usingNanoTime)
    {
      processingStartTime = System.nanoTime();
    }
@@ -1078,7 +1075,7 @@
   */
  public final void setProcessingStopTime()
  {
    if(useNanoTime)
    if(usingNanoTime)
    {
      this.processingStopTime = System.nanoTime();
    }
@@ -1091,12 +1088,13 @@
  /**
   * Retrieves the length of time in milliseconds that the server
   * spent processing this operation.  This should not be called until
   * after the server has sent the response to the client.
   * Retrieves the length of time in milliseconds or nanoseconds that
   * the server spent processing this operation.  This should not be
   * called until after the server has sent the response to the
   * client.
   *
   * @return  The length of time in milliseconds that the server spent
   *          processing this operation.
   * @return  The length of time in milliseconds or nanoseconds that
   *          the server spent processing this operation.
   */
  public final long getProcessingTime()
  {
@@ -1106,6 +1104,35 @@
  /**
   * Set whether to use nanoTime for the processing time methods.
   *
   * @param useNanoTime <code>true</code> to use System.nanoTime
   *                    or <code>false</code> to use
   *                    System.currentTimeMillis
   */
  public static void setUseNanoTime(boolean useNanoTime)
  {
    AbstractOperation.useNanoTime = useNanoTime;
  }
  /**
   * Get whether this operation used System.nanoTime or
   * System.currentTimeMillis for the processing time methods.
   *
   * @return  <code>true</code> if System.nanoTime is used or
   *          <code>false</code> if System.currentTimeMillis
   *          was used.
   */
  public final boolean getUseNanoTime()
  {
    return usingNanoTime;
  }
  /**
   * Performs the work of actually processing this operation.  This
   * should include all processing for the operation, including
   * invoking pre-parse and post-response plugins, logging messages
opendj-sdk/opends/src/server/org/opends/server/util/ServerConstants.java
@@ -22,7 +22,7 @@
 * CDDL HEADER END
 *
 *
 *      Portions Copyright 2006-2007 Sun Microsystems, Inc.
 *      Portions Copyright 2006-2008 Sun Microsystems, Inc.
 */
package org.opends.server.util;
@@ -2770,14 +2770,6 @@
       "org.opends.server.UseLastKnownGoodConfiguration";
  /**
   * The name of the system property that can be used to configure the
   * server to report etimes in nanoseconds instead of milliseconds.
   */
  public static final String PROPERTY_ETIME_NANO =
      "org.opends.server.etime.nano";
  /**
   * The column at which to wrap long lines of output in the command-line tools.
opendj-sdk/opends/src/server/org/opends/server/util/TimeThread.java
@@ -22,7 +22,7 @@
 * CDDL HEADER END
 *
 *
 *      Portions Copyright 2006-2007 Sun Microsystems, Inc.
 *      Portions Copyright 2006-2008 Sun Microsystems, Inc.
 */
package org.opends.server.util;
@@ -93,6 +93,9 @@
  // The current time in milliseconds since the epoch.
  private static volatile long time;
  // The current time in nanoseconds.
  private static volatile long nanoTime;
  // The date formatter that will be used to obtain the generalized time.
  private static SimpleDateFormat generalizedTimeFormatter;
@@ -139,6 +142,7 @@
    calendar        = new GregorianCalendar();
    date            = calendar.getTime();
    time            = date.getTime();
    nanoTime        = System.nanoTime();
    generalizedTime = generalizedTimeFormatter.format(date);
    localTimestamp  = localTimestampFormatter.format(date);
    gmtTimestamp    = gmtTimestampFormatter.format(date);
@@ -163,6 +167,7 @@
        calendar        = new GregorianCalendar();
        date            = calendar.getTime();
        time            = date.getTime();
        nanoTime        = System.nanoTime();
        generalizedTime = generalizedTimeFormatter.format(date);
        localTimestamp  = localTimestampFormatter.format(date);
        gmtTimestamp    = gmtTimestampFormatter.format(date);
@@ -223,6 +228,18 @@
    return time;
  }
  /**
   * Retrieves the time in nanoseconds from the most precise available system
   * timer. The value retured represents nanoseconds since some fixed but
   * arbitrary time.
   *
   * @return The time in nanoseconds from some fixed but arbitrary time.
   */
  public static long getNanoTime()
  {
    return nanoTime;
  }
  /**