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

neil_a_wilson
22.56.2007 fe2343005776d1d53a99b3826a2c0d5d2c0f500e
Update the start-ds script and associated Directory Server code to ensure that
the PID file is only written if the server is not already running. If it's not
being used to try to start the server, then just invoke the command without a
PID file. If it is trying to start the server but the server is already
running, then exit with an error.

OpenDS Issue Number: 1251
4 files modified
317 ■■■■ changed files
opends/resource/bin/start-ds 18 ●●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/core/DirectoryServer.java 283 ●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/core/PluginConfigManager.java 4 ●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/messages/CoreMessages.java 12 ●●●●● patch | view | raw | blame | history
opends/resource/bin/start-ds
@@ -23,7 +23,7 @@
# CDDL HEADER END
#
#
#      Portions Copyright 2006 Sun Microsystems, Inc.
#      Portions Copyright 2006-2007 Sun Microsystems, Inc.
# Capture the current working directory so that we can change to it later.
@@ -104,6 +104,22 @@
export SCRIPT_NAME_ARG
# See if the provided set of arguments were sufficient for us to be able to
# start the server or perform the requested operation.  An exit code of 99
# means that it should be possible to start the server.  An exit code of 98
# means that the server is already running and we shouldn't try to start it.
# An exit code of anything else means that we're not trying to start the server
# and we can just exit with that exit code.
${JAVA_BIN} ${SCRIPT_NAME_ARG} org.opends.server.core.DirectoryServer \
            --configClass org.opends.server.extensions.ConfigFileHandler \
            --configFile "${CONFIG_FILE}" --checkStartability "${@}"
EC=${?}
if test ${EC} -ne 99
then
  exit ${EC}
fi
# See if an "-N" or a "--nodetach" argument was provided as a command-line
# argument.  If it was, then don't use nohup to send to the  background, and
# send all output to both the console and a lot file.
opends/src/server/org/opends/server/core/DirectoryServer.java
@@ -195,6 +195,14 @@
  /**
   * Indicates whether the server currently holds an exclusive lock on the
   * server lock fiie.
   */
  private static boolean serverLocked = false;
  // The policy to use regarding single structural objectclass enforcement.
  private AcceptRejectWarn singleStructuralClassPolicy;
@@ -927,31 +935,36 @@
      // Acquire an exclusive lock for the Directory Server process.
      String lockFile = LockFileManager.getServerLockFileName();
      try
      if (! serverLocked)
      {
        StringBuilder failureReason = new StringBuilder();
        if (! LockFileManager.acquireExclusiveLock(lockFile, failureReason))
        String lockFile = LockFileManager.getServerLockFileName();
        try
        {
          StringBuilder failureReason = new StringBuilder();
          if (! LockFileManager.acquireExclusiveLock(lockFile, failureReason))
          {
            int    msgID   = MSGID_CANNOT_ACQUIRE_EXCLUSIVE_SERVER_LOCK;
            String message = getMessage(msgID, lockFile,
                                        String.valueOf(failureReason));
            throw new InitializationException(msgID, message);
          }
          serverLocked = true;
        }
        catch (InitializationException ie)
        {
          throw ie;
        }
        catch (Exception e)
        {
          assert debugException(CLASS_NAME, "startServer", e);
          int    msgID   = MSGID_CANNOT_ACQUIRE_EXCLUSIVE_SERVER_LOCK;
          String message = getMessage(msgID, lockFile,
                                      String.valueOf(failureReason));
          throw new InitializationException(msgID, message);
                                      stackTraceToSingleLineString(e));
          throw new InitializationException(msgID, message, e);
        }
      }
      catch (InitializationException ie)
      {
        throw ie;
      }
      catch (Exception e)
      {
        assert debugException(CLASS_NAME, "startServer", e);
        int    msgID   = MSGID_CANNOT_ACQUIRE_EXCLUSIVE_SERVER_LOCK;
        String message = getMessage(msgID, lockFile,
                                    stackTraceToSingleLineString(e));
        throw new InitializationException(msgID, message, e);
      }
      // Initialize all the schema elements.
@@ -2437,7 +2450,24 @@
  {
    assert debugEnter(CLASS_NAME, "getServerRoot");
    return directoryServer.configHandler.getServerRoot();
    if (directoryServer.configHandler == null)
    {
      String serverRoot = System.getenv(ENV_VAR_INSTANCE_ROOT);
      if (serverRoot != null)
      {
        return serverRoot;
      }
      else
      {
        // We don't know where the server root is, so we'll have to assume it's
        // the current working directory.
        return System.getProperty("user.dir");
      }
    }
    else
    {
      return directoryServer.configHandler.getServerRoot();
    }
  }
@@ -7483,6 +7513,8 @@
                     ErrorLogSeverity.SEVERE_WARNING, message, msgID);
            // FIXME -- Do we need to send an admin alert?
          }
          serverLocked = false;
        }
        catch (Exception e2)
        {
@@ -8092,52 +8124,16 @@
   */
  public static void main(String[] args)
  {
    // Configure the JVM to delete the PID file on exit, if it exists.
    boolean pidFileMarkedForDeletion      = false;
    boolean startingFileMarkedForDeletion = false;
    try
    {
      String pidFilePath;
      String startingFilePath;
      String serverRoot = System.getenv(ENV_VAR_INSTANCE_ROOT);
      if (serverRoot == null)
      {
        pidFilePath      = "logs/server.pid";
        startingFilePath = "logs/server.starting";
      }
      else
      {
        pidFilePath      = serverRoot + File.separator + "logs" +
                           File.separator + "server.pid";
        startingFilePath = serverRoot + File.separator + "logs" +
                           File.separator + "server.starting";
      }
      File pidFile = new File(pidFilePath);
      if (pidFile.exists())
      {
        pidFile.deleteOnExit();
        pidFileMarkedForDeletion = true;
      }
      File startingFile = new File(startingFilePath);
      if (startingFile.exists())
      {
        startingFile.deleteOnExit();
        startingFileMarkedForDeletion = true;
      }
    } catch (Exception e) {}
    // Define the arguments that may be provided to the server.
    BooleanArgument displayUsage = null;
    BooleanArgument dumpMessages = null;
    BooleanArgument fullVersion  = null;
    BooleanArgument noDetach     = null;
    BooleanArgument systemInfo   = null;
    BooleanArgument version      = null;
    StringArgument  configClass  = null;
    StringArgument  configFile   = null;
    BooleanArgument checkStartability = null;
    BooleanArgument displayUsage      = null;
    BooleanArgument dumpMessages      = null;
    BooleanArgument fullVersion       = null;
    BooleanArgument noDetach          = null;
    BooleanArgument systemInfo        = null;
    BooleanArgument version           = null;
    StringArgument  configClass       = null;
    StringArgument  configFile        = null;
    // Create the command-line argument parser for use with this program.
@@ -8167,6 +8163,13 @@
      argParser.addArgument(configFile);
      checkStartability = new BooleanArgument("checkstartability", null,
                              "checkStartability",
                              MSGID_DSCORE_DESCRIPTION_CHECK_STARTABILITY);
      checkStartability.setHidden(true);
      argParser.addArgument(checkStartability);
      version = new BooleanArgument("version", 'v', "version",
                                    MSGID_DSCORE_DESCRIPTION_VERSION);
      argParser.addArgument(version);
@@ -8226,7 +8229,90 @@
    // If we should just display usage information, then print it and exit.
    if (displayUsage.isPresent())
    if (checkStartability.isPresent())
    {
      // This option should only be used if a PID file already exists in the
      // server logs directory, and we need to check which of the following
      // conditions best describes the current usage:
      // - We're trying to start the server, but it's already running.  The
      //   attempt to start the server should fail, and the server process will
      //   exit with a result code of 98.
      // - We're trying to start the server and it's not already running.  We
      //   won't start it in this invocation, but the script used to get to this
      //   point should go ahead and overwrite the PID file and retry the
      //   startup process.  The server process will exit with a result code of
      //   99.
      // - We're not trying to start the server, but instead are trying to do
      //   something else like display the version number.  In that case, we
      //   don't need to write the PID file at all and can just execute the
      //   intended command.  If that command was successful, then we'll have an
      //   exit code of 0.  Otherwise, it will have an exit code that is
      //   something other than 0, 98, or 99 to indicate that a problem
      // occurred.
      if (displayUsage.isPresent())
      {
        // We're just trying to display usage, and that's already been done so
        // exit with a code of zero.
        System.exit(0);
      }
      else if (fullVersion.isPresent() || version.isPresent() ||
               systemInfo.isPresent() || dumpMessages.isPresent())
      {
        // We're not really trying to start, so rebuild the argument list
        // without the "--checkStartability" argument and try again.  Exit with
        // whatever that exits with.
        LinkedList<String> newArgList = new LinkedList<String>();
        for (String arg : args)
        {
          if (! arg.equalsIgnoreCase("--checkstartability"))
          {
            newArgList.add(arg);
          }
        }
        String[] newArgs = new String[newArgList.size()];
        newArgList.toArray(newArgs);
        main(newArgs);
        System.exit(0);
      }
      else
      {
        // We're trying to start the server, so see if it's already running by
        // trying to grab an exclusive lock on the server lock file.  If it
        // succeeds, then the server isn't running and we can try to start.
        // Otherwise, the server is running and this attempt should fail.
        String lockFile = LockFileManager.getServerLockFileName();
        try
        {
          StringBuilder failureReason = new StringBuilder();
          if (LockFileManager.acquireExclusiveLock(lockFile, failureReason))
          {
            // The server isn't running, so it can be started.
            LockFileManager.releaseLock(lockFile, failureReason);
            System.exit(99);
          }
          else
          {
            // The server's already running.
            int    msgID   = MSGID_CANNOT_ACQUIRE_EXCLUSIVE_SERVER_LOCK;
            String message = getMessage(msgID, lockFile,
                                        String.valueOf(failureReason));
            System.err.println(message);
            System.exit(98);
          }
        }
        catch (Exception e)
        {
          // We'll treat this as if the server is running because we won't
          // be able to start it anyway.
          int    msgID   = MSGID_CANNOT_ACQUIRE_EXCLUSIVE_SERVER_LOCK;
          String message = getMessage(msgID, lockFile,
                                      stackTraceToSingleLineString(e));
          System.err.println(message);
          System.exit(98);
        }
      }
    }
    else if (displayUsage.isPresent())
    {
      System.exit(0);
    }
@@ -8318,6 +8404,71 @@
    }
    // At this point, we know that we're going to try to start the server.
    // Attempt to grab an exclusive lock for the Directory Server process.
    String lockFile = LockFileManager.getServerLockFileName();
    try
    {
      StringBuilder failureReason = new StringBuilder();
      if (! LockFileManager.acquireExclusiveLock(lockFile, failureReason))
      {
        int    msgID   = MSGID_CANNOT_ACQUIRE_EXCLUSIVE_SERVER_LOCK;
        String message = getMessage(msgID, lockFile,
                                    String.valueOf(failureReason));
        System.err.println(message);
        System.exit(1);
      }
    }
    catch (Exception e)
    {
      assert debugException(CLASS_NAME, "startServer", e);
      int    msgID   = MSGID_CANNOT_ACQUIRE_EXCLUSIVE_SERVER_LOCK;
      String message = getMessage(msgID, lockFile,
                                  stackTraceToSingleLineString(e));
      System.err.println(message);
      System.exit(1);
    }
    serverLocked = true;
    // Configure the JVM to delete the PID file on exit, if it exists.
    boolean pidFileMarkedForDeletion      = false;
    boolean startingFileMarkedForDeletion = false;
    try
    {
      String pidFilePath;
      String startingFilePath;
      String serverRoot = System.getenv(ENV_VAR_INSTANCE_ROOT);
      if (serverRoot == null)
      {
        pidFilePath      = "logs/server.pid";
        startingFilePath = "logs/server.starting";
      }
      else
      {
        pidFilePath      = serverRoot + File.separator + "logs" +
                           File.separator + "server.pid";
        startingFilePath = serverRoot + File.separator + "logs" +
                           File.separator + "server.starting";
      }
      File pidFile = new File(pidFilePath);
      if (pidFile.exists())
      {
        pidFile.deleteOnExit();
        pidFileMarkedForDeletion = true;
      }
      File startingFile = new File(startingFilePath);
      if (startingFile.exists())
      {
        startingFile.deleteOnExit();
        startingFileMarkedForDeletion = true;
      }
    } catch (Exception e) {}
    // Redirect standard output and standard error to the server.out file.  If
    // the server hasn't detached from the terminal, then also continue writing
    // to the original standard output and standard error.  Also, configure the
opends/src/server/org/opends/server/core/PluginConfigManager.java
@@ -212,6 +212,8 @@
    searchResultEntryPlugins     = new DirectoryServerPlugin[0];
    searchResultReferencePlugins = new DirectoryServerPlugin[0];
    intermediateResponsePlugins  = new DirectoryServerPlugin[0];
    registeredPlugins            =
         new ConcurrentHashMap<DN,DirectoryServerPlugin>();
  }
@@ -241,7 +243,7 @@
    assert debugEnter(CLASS_NAME, "initializePluginConfig");
    registeredPlugins = new ConcurrentHashMap<DN,DirectoryServerPlugin>();
    registeredPlugins.clear();
    // Get the configuration entry that is the root of all the plugins in the
opends/src/server/org/opends/server/messages/CoreMessages.java
@@ -6239,6 +6239,15 @@
  /**
   * The message ID for the message that will be used as the description for the
   * checkStartability command-line argument.  This does not take any arguments.
   */
  public static final int MSGID_DSCORE_DESCRIPTION_CHECK_STARTABILITY =
       CATEGORY_MASK_CORE | SEVERITY_MASK_INFORMATIONAL | 596;
  /**
   * Associates a set of generic messages with the message IDs defined
   * in this class.
   */
@@ -7553,6 +7562,9 @@
                    "Specifies the path to the file containing the " +
                    "information needed by the configuration handler to " +
                    "obtain the Directory Server configuration.");
    registerMessage(MSGID_DSCORE_DESCRIPTION_CHECK_STARTABILITY,
                    "Used to determine whether to write a server PID file " +
                    "and attempt to start the server.");
    registerMessage(MSGID_DSCORE_DESCRIPTION_VERSION,
                    "Display Directory Server version information");
    registerMessage(MSGID_DSCORE_DESCRIPTION_FULLVERSION,