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

Yubao Liu
27.10.2021 d2b82394be5cf3f2a85cbee7d3044a367eda22c0
avoid forcibly interrupting JE thread (#157)

When LDIF is invalid, for example:

```
version: 1

dn: dc=test2,dc=cn
objectclass: domain
objectclass: top
dc: test <--- wrong, should be "test2"

dn: ou=groups,dc=test2,dc=cn
objectClass: organizationalUnit
objectClass: top
ou: groups

```

This will trigger `DnValidationCursorDecorator.throwIfOrphan(dn)`,
make `OnDiskMergeImporter.waitTaksTermination()` exit early and
`OnDiskMergeImporter.invokeParallel()` immediately call `executor.shutdownNow()`,
this leads to this exception and disabled JE backend:

```
category=TOOLS severity=ERROR msgID=96 msg=An error occurred while attempting to process the LDIF import: ThreadInterruptedException((JE 18.3.12) Environment must be closed, caused by: com.sleepycat.je.ThreadInterruptedException: Environment invalid because of previous exception: (JE 18.3.12) /home/opendj/db/userRoot java.lang.InterruptedException THREAD_INTERRUPTED: InterruptedException may cause incorrect internal state, unable to continue. Environment is invalid and must be closed.)
category=CONFIG severity=ERROR msgID=646 msg=org.forgerock.opendj.config.server.ConfigChangeListenerAdaptor.applyConfigurationChange failed for entry ds-cfg-backend-id=userRoot,cn=Backends,cn=config: result code=Other, admin action required=false, messages="An error occurred while trying to initialize a backend loaded from class org.opends.server.backends.jeb.JEBackend with the information in configuration entry ds-cfg-backend-id=userRoot,cn=Backends,cn=config: InitializationException: The database environment could not be opened: com.sleepycat.je.ThreadInterruptedException: (JE 18.3.12) Environment must be closed, caused by: com.sleepycat.je.ThreadInterruptedException: Environment invalid because of previous exception: (JE 18.3.12) /home/opendj/db/userRoot java.lang.InterruptedException THREAD_INTERRUPTED: InterruptedException may cause incorrect internal state, unable to continue. Environment is invalid and must be closed. (BackendImpl.java:972 BackendImpl.java:179 BackendConfigManager.java:1063 BackendConfigManager.java:1045 BackendConfigManager.java:275 BackendConfigManager.java:887 BackendConfigManager.java:77 ServerManagedObjectChangeListenerAdaptor.java:50 ConfigChangeListenerAdaptor.java:281 ConfigurationHandler.java:648 ConfigurationBackend.java:497 LocalBackendModifyOperation.java:493 LocalBackendModifyOperation.java:280 LocalBackendWorkflowElement.java:620 LocalBackendWorkflowElement.java:743 ModifyOperationBasis.java:337 InternalClientConnection.java:1322 InternalClientConnection.java:1404 TaskUtils.java:205 TaskUtils.java:173 ImportTask.java:700 ...). This backend will be disabled"
```
1 files modified
20 ■■■■■ changed files
opendj-server-legacy/src/main/java/org/opends/server/backends/pluggable/OnDiskMergeImporter.java 20 ●●●●● patch | view | raw | blame | history
opendj-server-legacy/src/main/java/org/opends/server/backends/pluggable/OnDiskMergeImporter.java
@@ -139,6 +139,7 @@
import com.forgerock.opendj.util.Predicate;
import net.jcip.annotations.NotThreadSafe;
import org.forgerock.i18n.LocalizableMessage;
/**
 * Imports LDIF data contained in files into the database. Because of the B-Tree structure used in backend, import is
@@ -2787,10 +2788,27 @@
  private static <K> List<K> waitTasksTermination(CompletionService<K> completionService, int nbTasks)
      throws InterruptedException, ExecutionException
  {
    InterruptedException ie = null;
    ExecutionException ee = null;
    final List<K> results = new ArrayList<>(nbTasks);
    for (int i = 0; i < nbTasks; i++)
    {
      results.add(completionService.take().get());
      try {
        results.add(completionService.take().get());
      } catch (Exception e) {
        logger.error(LocalizableMessage.raw("failed to execute task"), e);
        if (e instanceof InterruptedException) {
          ie = (InterruptedException) e;
        } else if (e instanceof ExecutionException) {
          ee = (ExecutionException) e;
        }
      }
    }
    if (ie != null) {
      throw ie;
    }
    if (ee != null) {
        throw ee;
    }
    return results;
  }