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

kenneth_suter
22.26.2007 f885ac10414d4e16cf99564adc3451d98f4ef202
This commit:

- Splits the reinitialization code for DirectoryServer.restart() method into a different method that can be called separately. This is necessary because quicksetup applications register writers with the log publishers before starting the server in order to listen for startup messages. Since the call to bootstrapServer removes all currently registered log publishers so there needs to be a way to re-register the writers with the server before calling startServer().

- Adds an upgrader step 'Preparing Customizations...' to give the user something to look at during the somewhat time-consuming process of starting starting the server prior to making customization changes.

- Adds a check for port access before the upgrader starts the server for the last time. If the port check fails, the upgrader exits successfully but with a warning. I have discovered that there are problems with the server's stopping and starting connection handlers asynchronously and the upgrader requesting quick stopping and starting of the server as it does to apply customizations and verify the upgrade. This is somewhat mitigated by the InProcessServerController having some sleep time added to the startServer and stopServer methods. Neil mentions that this should be resolved in the server code in the near future at which time we can remove the sleep calls.

- Added code to make sure the server has been stopped before upgrade continues.

- Changed the way the InProcessServerController writers are registered with the server after discovering that the set of log publishers is reinitialized when the server is bootstrapped.

4 files modified
298 ■■■■ changed files
opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/resources/Resources.properties 1 ●●●● patch | view | raw | blame | history
opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/upgrader/Upgrader.java 21 ●●●●● patch | view | raw | blame | history
opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/util/InProcessServerController.java 252 ●●●●● patch | view | raw | blame | history
opendj-sdk/opends/src/server/org/opends/server/core/DirectoryServer.java 24 ●●●● patch | view | raw | blame | history
opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/resources/Resources.properties
@@ -809,6 +809,7 @@
summary-upgrade-calculating-config-customization=Calculating Configuration \
  Customizations...
summary-upgrade-upgrading-components=Upgrading Components...
summary-upgrade-preparing-customizations=Preparing Customizations...
summary-upgrade-applying-schema-customization=Applying Schema \
  Customizations...
summary-upgrade-applying-config-customization=Applying Configuration \
opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/upgrader/Upgrader.java
@@ -145,6 +145,8 @@
    UPGRADING_COMPONENTS("summary-upgrade-upgrading-components", 60),
    PREPARING_CUSTOMIZATIONS("summary-upgrade-preparing-customizations", 65),
    APPLYING_SCHEMA_CUSTOMIZATIONS(
            "summary-upgrade-applying-schema-customization", 70),
@@ -861,9 +863,15 @@
      if (schemaCustomizationPresent || configCustimizationPresent) {
        try {
          LOG.log(Level.INFO, "starting server");
          setCurrentProgressStep(
                  UpgradeProgressStep.PREPARING_CUSTOMIZATIONS);
          startServerWithoutConnectionHandlers();
          notifyListeners(formatter.getFormattedDone() +
                  formatter.getLineBreak());
          LOG.log(Level.INFO, "start server finished");
        } catch (ApplicationException e) {
          notifyListeners(formatter.getFormattedError() +
                  formatter.getLineBreak());
          LOG.log(Level.INFO,
                  "Error starting server in process in order to apply custom" +
                          "schema and/or configuration", e);
@@ -963,6 +971,15 @@
          try {
            LOG.log(Level.INFO, "starting server");
            setCurrentProgressStep(UpgradeProgressStep.STARTING_SERVER);
            int port = getInstallation().getCurrentConfiguration().getPort();
            if (port != -1 && !Utils.canUseAsPort(port)) {
              throw new ApplicationException(
                      ApplicationException.Type.APPLICATION,
                      "The server can not be started as another application " +
                              "is using port " + port + ".  Check that you " +
                              "have access to this port before restarting " +
                              "the server.", null);
            }
            control.startServer(true);
            notifyListeners(formatter.getFormattedDone() +
                    formatter.getLineBreak());
@@ -1457,6 +1474,10 @@
  private void initialize() throws ApplicationException {
    try {
      if (getInstallation().getStatus().isServerRunning()) {
        new ServerController(getInstallation()).stopServer(true);
      }
      BuildInformation fromVersion = getCurrentBuildInformation();
      BuildInformation toVersion = getStagedBuildInformation();
      this.historicalOperationId =
opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/util/InProcessServerController.java
@@ -41,6 +41,7 @@
import org.opends.server.types.LDIFImportConfig;
import org.opends.server.types.ByteStringFactory;
import org.opends.server.types.ByteString;
import org.opends.server.types.InitializationException;
import org.opends.server.api.DebugLogPublisher;
import org.opends.server.api.ErrorLogPublisher;
import org.opends.server.api.AccessLogPublisher;
@@ -50,6 +51,7 @@
import org.opends.server.protocols.internal.InternalClientConnection;
import org.opends.server.core.ModifyOperation;
import org.opends.server.core.DirectoryServer;
import org.opends.server.config.ConfigException;
import java.util.logging.Logger;
import java.util.logging.Level;
@@ -70,6 +72,87 @@
  static private final Logger LOG =
          Logger.getLogger(InProcessServerController.class.getName());
  /**
   * Indicates that the server has already been started once and that a
   * restart should happen instead.
   */
  static private boolean serverHasBeenStarted = false;
  /**
   * Pushes messages published by the server loggers into OperationOutput.
   */
  static private abstract class ServerControllerTextWriter
          implements TextWriter
  {
    private int bytesWritten = 0;
    private OperationOutput output = null;
    abstract void storeRecord(String record, OperationOutput output);
    ServerControllerTextWriter() {
      // do nothing
    }
    ServerControllerTextWriter(OperationOutput output) {
      setOutput(output);
    }
    public void setOutput(OperationOutput ouput) {
      this.output = ouput;
    }
    public void writeRecord(String record) {
      if (record != null) {
        bytesWritten += bytesWritten;
        if (output != null) {
          storeRecord(record, output);
        }
      }
    }
    public void flush() {
      // do nothing;
    }
    public void shutdown() {
      // do nothing;
    }
    public long getBytesWritten() {
      return bytesWritten;
    }
  }
  static private ServerControllerTextWriter debugWriter =
          new ServerControllerTextWriter() {
    void storeRecord(String record,
                     OperationOutput output) {
      LOG.log(Level.INFO, "server start (debug log): " +
              record);
      output.addDebugMessage(record);
    }};
  static private ServerControllerTextWriter errorWriter =
          new ServerControllerTextWriter() {
    void storeRecord(String record,
                     OperationOutput output) {
      LOG.log(Level.INFO, "server start (error log): " +
              record);
      output.addErrorMessage(record);
    }
  };
  static private ServerControllerTextWriter accessWriter =
          new ServerControllerTextWriter() {
    void storeRecord(String record,
                     OperationOutput output) {
      LOG.log(Level.INFO, "server start (access log): " +
              record);
      output.addAccessMessage(record);
    }
  };
  private Installation installation;
  /**
@@ -148,9 +231,22 @@
    LOG.log(Level.INFO, "Shutting down in process server");
    StandardOutputSuppressor.suppress();
    try {
      org.opends.server.core.DirectoryServer.shutDown(
              ServerController.class.getName(),
      DirectoryServer.shutDown(getClass().getName(),
              "quicksetup requests shutdown");
      // Note:  this should not be necessary in the future when a
      // the shutdown method will not return until everything is
      // cleaned up.
      // Connection handlers are stopped and started asynchonously.
      // Give the connection handlers time to let go of any resources
      // before continuing.
      try {
        Thread.sleep(3000);
      } catch (InterruptedException e) {
        // do nothing;
      }
    } finally {
      StandardOutputSuppressor.unsuppress();
    }
@@ -169,18 +265,24 @@
   *  attempting to initialize and start the
   *  Directory Server.
   */
  public OperationOutput startServer()
  public synchronized OperationOutput startServer()
          throws
          org.opends.server.types.InitializationException,
          org.opends.server.config.ConfigException {
          InitializationException,
          ConfigException {
    OperationOutput output = new OperationOutput();
    setOutputForWriters(output);
    // Properties systemProperties = System.getProperties();
    // systemProperties.list(System.out);
    StandardOutputSuppressor.suppress();
    try {
      org.opends.server.core.DirectoryServer directoryServer =
              org.opends.server.core.DirectoryServer.getInstance();
      // The server's startServer method should not be called directly
      // more than once since it leave the server corrupted.  Restart
      // is the correct choice in this case.
      if (!serverHasBeenStarted) {
        DirectoryServer directoryServer = DirectoryServer.getInstance();
      // Bootstrap and start the Directory Server.
      LOG.log(Level.FINER, "Bootstrapping directory server");
@@ -190,61 +292,43 @@
      String configClass = "org.opends.server.extensions.ConfigFileHandler";
      String configPath = Utils.getPath(
              installation.getCurrentConfigurationFile());
      directoryServer.initializeConfiguration(configClass, configPath);
      try {
        DebugLogPublisher startupDebugPublisher =
                TextDebugLogPublisher.getStartupTextDebugPublisher(
                        new ServerControllerTextWriter(output) {
                          void storeRecord(String record,
                                           OperationOutput output) {
                            LOG.log(Level.INFO, "server start (debug log): " +
                                    record);
                            output.addDebugMessage(record);
                          }
                        });
        DebugLogger.addDebugLogPublisher(DN.NULL_DN,
                startupDebugPublisher);
        ErrorLogPublisher startupErrorPublisher =
                TextErrorLogPublisher.getStartupTextErrorPublisher(
                        new ServerControllerTextWriter(output) {
                          void storeRecord(String record,
                                           OperationOutput output) {
                            LOG.log(Level.INFO, "server start (error log): " +
                                    record);
                            output.addErrorMessage(record);
                          }
                        });
        ErrorLogger.addErrorLogPublisher(DN.NULL_DN,
                startupErrorPublisher);
        AccessLogPublisher startupAccessPublisher =
                TextAccessLogPublisher.getStartupTextAccessPublisher(
                        new ServerControllerTextWriter(output) {
                          void storeRecord(String record,
                                           OperationOutput output) {
                            LOG.log(Level.INFO, "server start (access log): " +
                                    record);
                            output.addAccessMessage(record);
                          }
                        });
        AccessLogger.addAccessLogPublisher(DN.NULL_DN,
                startupAccessPublisher);
      } catch (Exception e) {
        LOG.log(Level.INFO, "Error installing test log publishers: " +
                e.toString());
      } else {
        LOG.log(Level.FINER, "Reinitializing the server");
        DirectoryServer.reinitialize();
      }
      LOG.log(Level.FINER, "Invoking start server");
      // Must be done following bootstrap
      registerListenersForOuput();
      LOG.log(Level.FINER, "Invoking server start");
      // It is important to get a new instance after calling reinitalize()
      DirectoryServer directoryServer = DirectoryServer.getInstance();
      directoryServer.startServer();
      serverHasBeenStarted = true;
      // Note:  this should not be necessary in the future.  This
      // seems necessary currenty for the case in which shutdown
      // is called immediately afterward as is done by the upgrader.
      // Connection handlers are stopped and started asynchonously.
      // Give the connection handlers time to initialize before
      // continuing.
      try {
        Thread.sleep(3000);
      } catch (InterruptedException e) {
        // do nothing;
      }
    } finally {
      StandardOutputSuppressor.unsuppress();
      setOutputForWriters(null);
    }
    return output;
  }
@@ -338,39 +422,43 @@
    return modsMsg.toString();
  }
  /**
   * Pushes messages published by the server loggers into OperationOutput.
   */
  private abstract class ServerControllerTextWriter implements TextWriter {
    private int bytesWritten = 0;
    private OperationOutput output = null;
    abstract void storeRecord(String record, OperationOutput output);
    ServerControllerTextWriter(OperationOutput output) {
      this.output = output;
  static private void setOutputForWriters(OperationOutput output) {
    debugWriter.setOutput(output);
    errorWriter.setOutput(output);
    accessWriter.setOutput(output);
    }
    public void writeRecord(String record) {
      if (record != null) {
        bytesWritten += bytesWritten;
        storeRecord(record, output);
  static private void registerListenersForOuput() {
    try {
      DebugLogPublisher startupDebugPublisher =
              TextDebugLogPublisher.getStartupTextDebugPublisher(debugWriter);
      DebugLogger.addDebugLogPublisher(
              DN.decode("cn=QuickSetup,cn=Loggers,cn=config"),
              startupDebugPublisher);
      ErrorLogPublisher startupErrorPublisher =
              TextErrorLogPublisher.getStartupTextErrorPublisher(errorWriter);
      ErrorLogger.addErrorLogPublisher(
              DN.decode("cn=QuickSetup,cn=Loggers,cn=config"),
              startupErrorPublisher);
      AccessLogPublisher startupAccessPublisher =
              TextAccessLogPublisher.getStartupTextAccessPublisher(
                      accessWriter);
      AccessLogger.addAccessLogPublisher(
              DN.decode("cn=QuickSetup,cn=Loggers,cn=config"),
              startupAccessPublisher);
    } catch (Exception e) {
      LOG.log(Level.INFO, "Error installing test log publishers: " +
              e.toString());
      }
    }
    public void flush() {
      // do nothing;
    }
    public void shutdown() {
      // do nothing;
    }
    public long getBytesWritten() {
      return bytesWritten;
    }
  static private void unregisterListenersForOutput() {
    DebugLogger.removeDebugLogPublisher(DN.NULL_DN);
    ErrorLogger.removeErrorLogPublisher(DN.NULL_DN);
    AccessLogger.removeAccessLogPublisher(DN.NULL_DN);
  }
}
opendj-sdk/opends/src/server/org/opends/server/core/DirectoryServer.java
@@ -8143,13 +8143,8 @@
  {
    try
    {
      String configClass = directoryServer.configClass;
      String configFile  = directoryServer.configFile;
      shutDown(className, reason);
      getNewInstance();
      directoryServer.bootstrapServer();
      directoryServer.initializeConfiguration(configClass, configFile);
      reinitialize();
      directoryServer.startServer();
    }
    catch (Exception e)
@@ -8163,7 +8158,22 @@
    }
  }
  /**
   * Reinitializes the server following a shutdown, preparing it for
   * a call to <code>startServer</code>.
   *
   * @throws  InitializationException  If a problem occurs while trying to
   *                                   initialize the config handler or
   *                                   bootstrap that server.
   */
  public static void reinitialize() throws InitializationException
  {
    String configClass = directoryServer.configClass;
    String configFile  = directoryServer.configFile;
    getNewInstance();
    directoryServer.bootstrapServer();
    directoryServer.initializeConfiguration(configClass, configFile);
  }
  /**
   * Retrieves the maximum number of concurrent client connections that may be