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

Gaetan Boismal
01.22.2016 4a17c7f153f4912f376b5976eea7caa501187442
OPENDJ-3046 Cleanup server offline tools environment

When the various tools run in offline mode they initialise some parts of the directory server in order to perform their tasks.
Usually the tool will exit when it has finished processing and the state of this environment is not a problem.
However, if the tool is used within another process then some initialised components may be left over (e.g ads-trustore or admin data backends).
Extract a method from the DirectoryServer#shutdown() to shutdwon backends only and use it straight after TaskTool#processLocal.
5 files modified
336 ■■■■■ changed files
opendj-server-legacy/src/main/java/org/opends/server/core/DirectoryServer.java 96 ●●●● patch | view | raw | blame | history
opendj-server-legacy/src/main/java/org/opends/server/tools/ExportLDIF.java 6 ●●●●● patch | view | raw | blame | history
opendj-server-legacy/src/main/java/org/opends/server/tools/ImportLDIF.java 6 ●●●●● patch | view | raw | blame | history
opendj-server-legacy/src/main/java/org/opends/server/tools/RebuildIndex.java 6 ●●●●● patch | view | raw | blame | history
opendj-server-legacy/src/main/java/org/opends/server/tools/tasks/TaskTool.java 222 ●●●● patch | view | raw | blame | history
opendj-server-legacy/src/main/java/org/opends/server/core/DirectoryServer.java
@@ -5375,53 +5375,7 @@
      }
    }
    // Shut down the backends.
    for (Backend<?> backend : directoryServer.backends.values())
    {
      try
      {
        for (BackendInitializationListener listener : getBackendInitializationListeners())
        {
          listener.performBackendPreFinalizationProcessing(backend);
        }
        // Deregister all the local backend workflow elements that have been
        // registered with the server.
        LocalBackendWorkflowElement.removeAll();
        for (BackendInitializationListener listener :
             directoryServer.backendInitializationListeners)
        {
          listener.performBackendPostFinalizationProcessing(backend);
        }
        backend.finalizeBackend();
        // Remove the shared lock for this backend.
        try
        {
          String lockFile = LockFileManager.getBackendLockFileName(backend);
          StringBuilder failureReason = new StringBuilder();
          if (! LockFileManager.releaseLock(lockFile, failureReason))
          {
            logger.warn(WARN_SHUTDOWN_CANNOT_RELEASE_SHARED_BACKEND_LOCK, backend.getBackendID(), failureReason);
            // FIXME -- Do we need to send an admin alert?
          }
        }
        catch (Exception e2)
        {
          logger.traceException(e2);
          logger.warn(WARN_SHUTDOWN_CANNOT_RELEASE_SHARED_BACKEND_LOCK,
              backend.getBackendID(), stackTraceToSingleLineString(e2));
          // FIXME -- Do we need to send an admin alert?
        }
      }
      catch (Exception e)
      {
        logger.traceException(e);
      }
    }
    shutdownBackends();
    if (directoryServer.configurationHandler != null) {
      directoryServer.configurationHandler.finalize();
@@ -5473,6 +5427,54 @@
    directoryServer = getNewInstance(envConfig);
  }
  /** Shutdown directory server backends. */
  public static void shutdownBackends()
  {
    for (Backend<?> backend : directoryServer.backends.values())
    {
      try
      {
        for (BackendInitializationListener listener : getBackendInitializationListeners())
        {
          listener.performBackendPreFinalizationProcessing(backend);
        }
        for (BackendInitializationListener listener : directoryServer.backendInitializationListeners)
        {
          listener.performBackendPostFinalizationProcessing(backend);
        }
        backend.finalizeBackend();
        // Remove the shared lock for this backend.
        try
        {
          String lockFile = LockFileManager.getBackendLockFileName(backend);
          StringBuilder failureReason = new StringBuilder();
          if (! LockFileManager.releaseLock(lockFile, failureReason))
          {
            logger.warn(WARN_SHUTDOWN_CANNOT_RELEASE_SHARED_BACKEND_LOCK, backend.getBackendID(), failureReason);
            // FIXME -- Do we need to send an admin alert?
          }
        }
        catch (Exception e2)
        {
          logger.traceException(e2);
          logger.warn(WARN_SHUTDOWN_CANNOT_RELEASE_SHARED_BACKEND_LOCK,
              backend.getBackendID(), stackTraceToSingleLineString(e2));
          // FIXME -- Do we need to send an admin alert?
        }
      }
      catch (Exception e)
      {
        logger.traceException(e);
      }
    }
    // Deregister all the local backend workflow elements that have been registered with the server.
    LocalBackendWorkflowElement.removeAll();
  }
  /**
   * Destroy key structures in the current Directory Server instance in a manner
   * that can help detect any inappropriate cached references to server
opendj-server-legacy/src/main/java/org/opends/server/tools/ExportLDIF.java
@@ -631,6 +631,12 @@
    return !errorOccurred ? 0 : 1;
  }
  @Override
  protected void cleanup()
  {
    DirectoryServer.shutdownBackends();
  }
  private Set<AttributeType> toAttributeTypes(StringArgument attributeArg)
  {
    if (attributeArg == null)
opendj-server-legacy/src/main/java/org/opends/server/tools/ImportLDIF.java
@@ -930,6 +930,12 @@
    return retCode;
  }
  @Override
  protected void cleanup()
  {
    DirectoryServer.shutdownBackends();
  }
  private boolean useBackend(Set<DN> includeBranches, List<DN> dnlist)
  {
    for (DN baseDN : dnlist)
opendj-server-legacy/src/main/java/org/opends/server/tools/RebuildIndex.java
@@ -292,6 +292,12 @@
    return rebuildIndex(currentBackend, rebuildConfig);
  }
  @Override
  protected void cleanup()
  {
    DirectoryServer.shutdownBackends();
  }
  /**
   * Configures the rebuild index process. i.e.: decodes the selected DN and
   * retrieves the backend which holds it. Finally, initializes and sets the
opendj-server-legacy/src/main/java/org/opends/server/tools/tasks/TaskTool.java
@@ -110,6 +110,17 @@
                                      PrintStream err);
  /**
   * Cleanup task environment after offline run.
   * Default implementation does nothing.
   * Tasks which initialize some static part of the DirectoryServer instance (e.g admin data local backends) must
   * override this method to shutdown all needed component to prevent JVM environment alteration.
   */
  protected void cleanup()
  {
    // Do nothing by default.
  }
  /**
   * Creates an argument parser prepopulated with arguments for processing
   * input for scheduling tasks with the task backend.
   *
@@ -170,7 +181,7 @@
   */
  protected void validateTaskArgs() throws ArgumentException, ClientException
  {
    if (processAsTask())
    if (isRemoteTask())
    {
      taskScheduleArgs.validateArgs();
    }
@@ -232,11 +243,9 @@
  protected int process(LDAPConnectionArgumentParser argParser,
                        boolean initializeServer,
                        PrintStream out, PrintStream err) {
    int ret;
    if (testIfOffline())
    {
      if (!processAsTask())
      if (!isRemoteTask())
      {
        return RUN_OFFLINE;
      }
@@ -246,115 +255,124 @@
      }
    }
    if (processAsTask())
    if (!isRemoteTask())
    {
      if (initializeServer)
      try
      {
        try
        {
          DirectoryServer.bootstrapClient();
          DirectoryServer.initializeJMX();
        }
        catch (Exception e)
        {
          printWrappedText(err, ERR_SERVER_BOOTSTRAP_ERROR.get(getExceptionMessage(e)));
          return 1;
        }
      }
      LDAPConnection conn = null;
      try {
        conn = argParser.connect(out, err);
        TaskClient tc = new TaskClient(conn);
        TaskEntry taskEntry = tc.schedule(this);
        LocalizableMessage startTime = taskEntry.getScheduledStartTime();
        if (taskEntry.getTaskState() == TaskState.RECURRING) {
          printWrappedText(out, INFO_TASK_TOOL_RECURRING_TASK_SCHEDULED.get(taskEntry.getType(), taskEntry.getId()));
        } else if (startTime == null || startTime.length() == 0) {
          printWrappedText(out, INFO_TASK_TOOL_TASK_SCHEDULED_NOW.get(taskEntry.getType(), taskEntry.getId()));
        } else {
          printWrappedText(out, INFO_TASK_TOOL_TASK_SCHEDULED_FUTURE.get(
              taskEntry.getType(), taskEntry.getId(), taskEntry.getScheduledStartTime()));
        }
        if (!taskScheduleArgs.startArg.isPresent()) {
          // Poll the task printing log messages until finished
          String taskId = taskEntry.getId();
          Set<LocalizableMessage> printedLogMessages = new HashSet<>();
          do {
            taskEntry = tc.getTaskEntry(taskId);
            List<LocalizableMessage> logs = taskEntry.getLogMessages();
            for (LocalizableMessage log : logs) {
              if (printedLogMessages.add(log)) {
                out.println(log);
              }
            }
            try {
              Thread.sleep(SYNCHRONOUS_TASK_POLL_INTERVAL);
            } catch (InterruptedException e) {
              // ignore
            }
          } while (!taskEntry.isDone());
          if (TaskState.isSuccessful(taskEntry.getTaskState())) {
            if (taskEntry.getTaskState() != TaskState.RECURRING) {
              printWrappedText(out, INFO_TASK_TOOL_TASK_SUCESSFULL.get(taskEntry.getType(), taskEntry.getId()));
            }
            return 0;
          } else {
            printWrappedText(out, INFO_TASK_TOOL_TASK_NOT_SUCESSFULL.get(taskEntry.getType(), taskEntry.getId()));
            return 1;
          }
        }
        ret = 0;
      } catch (LDAPConnectionException e) {
        if (isWrongPortException(e,
            Integer.valueOf(argParser.getArguments().getPort())))
        {
          printWrappedText(err, ERR_TASK_LDAP_FAILED_TO_CONNECT_WRONG_PORT.get(
              argParser.getArguments().getHostName(), argParser.getArguments().getPort()));
        } else {
          printWrappedText(err, ERR_TASK_TOOL_START_TIME_NO_LDAP.get(e.getMessage()));
        }
        ret = 1;
      } catch (DecodeException ae) {
        printWrappedText(err, ERR_TASK_TOOL_DECODE_ERROR.get(ae.getMessage()));
        ret = 1;
      } catch (IOException ioe) {
        printWrappedText(err, ERR_TASK_TOOL_IO_ERROR.get(ioe));
        ret = 1;
      } catch (LDAPException le) {
        printWrappedText(err, ERR_TASK_TOOL_LDAP_ERROR.get(le.getMessage()));
        ret = 1;
      } catch (OpenDsException e) {
        printWrappedText(err, e.getMessageObject());
        ret = 1;
      } catch (ArgumentException e) {
        argParser.displayMessageAndUsageReference(err, e.getMessageObject());
        ret = 1;
        return processLocal(initializeServer, out, err);
      }
      finally
      {
        if (conn != null)
        if (initializeServer)
        {
          try
          {
            conn.close(null);
          }
          catch (Throwable t)
          {
            // Ignore.
          }
          cleanup();
        }
      }
    } else {
      ret = processLocal(initializeServer, out, err);
    }
    return ret;
    if (initializeServer)
    {
      try
      {
        DirectoryServer.bootstrapClient();
        DirectoryServer.initializeJMX();
      }
      catch (Exception e)
      {
        printWrappedText(err, ERR_SERVER_BOOTSTRAP_ERROR.get(getExceptionMessage(e)));
        return 1;
      }
    }
    LDAPConnection conn = null;
    try {
      conn = argParser.connect(out, err);
      TaskClient tc = new TaskClient(conn);
      TaskEntry taskEntry = tc.schedule(this);
      LocalizableMessage startTime = taskEntry.getScheduledStartTime();
      if (taskEntry.getTaskState() == TaskState.RECURRING) {
        printWrappedText(out, INFO_TASK_TOOL_RECURRING_TASK_SCHEDULED.get(taskEntry.getType(), taskEntry.getId()));
      } else if (startTime == null || startTime.length() == 0) {
        printWrappedText(out, INFO_TASK_TOOL_TASK_SCHEDULED_NOW.get(taskEntry.getType(), taskEntry.getId()));
      } else {
        printWrappedText(out, INFO_TASK_TOOL_TASK_SCHEDULED_FUTURE.get(
            taskEntry.getType(), taskEntry.getId(), taskEntry.getScheduledStartTime()));
      }
      if (!taskScheduleArgs.startArg.isPresent()) {
        // Poll the task printing log messages until finished
        String taskId = taskEntry.getId();
        Set<LocalizableMessage> printedLogMessages = new HashSet<>();
        do {
          taskEntry = tc.getTaskEntry(taskId);
          List<LocalizableMessage> logs = taskEntry.getLogMessages();
          for (LocalizableMessage log : logs) {
            if (printedLogMessages.add(log)) {
              out.println(log);
            }
          }
          try {
            Thread.sleep(SYNCHRONOUS_TASK_POLL_INTERVAL);
          } catch (InterruptedException e) {
            // ignore
          }
        } while (!taskEntry.isDone());
        if (TaskState.isSuccessful(taskEntry.getTaskState())) {
          if (taskEntry.getTaskState() != TaskState.RECURRING) {
            printWrappedText(out, INFO_TASK_TOOL_TASK_SUCESSFULL.get(taskEntry.getType(), taskEntry.getId()));
          }
          return 0;
        } else {
          printWrappedText(out, INFO_TASK_TOOL_TASK_NOT_SUCESSFULL.get(taskEntry.getType(), taskEntry.getId()));
          return 1;
        }
      }
      return 0;
    } catch (LDAPConnectionException e) {
      if (isWrongPortException(e,
          Integer.valueOf(argParser.getArguments().getPort())))
      {
        printWrappedText(err, ERR_TASK_LDAP_FAILED_TO_CONNECT_WRONG_PORT.get(
            argParser.getArguments().getHostName(), argParser.getArguments().getPort()));
      } else {
        printWrappedText(err, ERR_TASK_TOOL_START_TIME_NO_LDAP.get(e.getMessage()));
      }
      return 1;
    } catch (DecodeException ae) {
      printWrappedText(err, ERR_TASK_TOOL_DECODE_ERROR.get(ae.getMessage()));
      return 1;
    } catch (IOException ioe) {
      printWrappedText(err, ERR_TASK_TOOL_IO_ERROR.get(ioe));
      return 1;
    } catch (LDAPException le) {
      printWrappedText(err, ERR_TASK_TOOL_LDAP_ERROR.get(le.getMessage()));
      return 1;
    } catch (OpenDsException e) {
      printWrappedText(err, e.getMessageObject());
      return 1;
    } catch (ArgumentException e) {
      argParser.displayMessageAndUsageReference(err, e.getMessageObject());
      return 1;
    }
    finally
    {
      if (conn != null)
      {
        try
        {
          conn.close(null);
        }
        catch (Throwable t)
        {
          // Ignore.
        }
      }
    }
  }
  private boolean processAsTask() {
  private boolean isRemoteTask() {
    return argParser.connectionArgumentsPresent();
  }