SOLR-14677: Always close DIH EntityProcessor/DataSource (#1741)

Prior to this commit, the wrapup logic at the end of
DocBuilder.execute() closed out a series of DIH objects, but did so
in a way that an exception closing any of them resulted in the remainder
staying open.  This is especially problematic since Writer.close()
throws exceptions that DIH uses to determine the success/failure of the
run.

In practice this caused network errors sending DIH data to other Solr
nodes to result in leaked JDBC connections.

This commit changes DocBuilder's termination logic to handle exceptions
more gracefully, ensuring that errors closing a DIHWriter (for example)
don't prevent the closure of entity-processor and DataSource objects.
This commit is contained in:
Jason Gerlowski 2020-08-13 21:21:31 -04:00 committed by GitHub
parent bed3b8fbfb
commit 216aec03a6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 29 additions and 9 deletions

View File

@ -182,6 +182,8 @@ Bug Fixes
* SOLR-14751: Zookeeper Admin screen not working for old ZK versions (janhoy) * SOLR-14751: Zookeeper Admin screen not working for old ZK versions (janhoy)
* SOLR-14677: Improve DIH termination logic to close all DataSources, EntityProcessors (Jason Gerlowski)
Other Changes Other Changes
--------------------- ---------------------

View File

@ -16,6 +16,7 @@
*/ */
package org.apache.solr.handler.dataimport; package org.apache.solr.handler.dataimport;
import java.io.Closeable;
import java.util.Properties; import java.util.Properties;
/** /**
@ -35,7 +36,7 @@ import java.util.Properties;
* *
* @since solr 1.3 * @since solr 1.3
*/ */
public abstract class DataSource<T> { public abstract class DataSource<T> implements Closeable {
/** /**
* Initializes the DataSource with the <code>Context</code> and * Initializes the DataSource with the <code>Context</code> and

View File

@ -18,6 +18,7 @@ package org.apache.solr.handler.dataimport;
import org.apache.solr.common.SolrException; import org.apache.solr.common.SolrException;
import org.apache.solr.common.SolrInputDocument; import org.apache.solr.common.SolrInputDocument;
import org.apache.solr.common.util.IOUtils;
import org.apache.solr.core.SolrCore; import org.apache.solr.core.SolrCore;
import org.apache.solr.handler.dataimport.config.ConfigNameConstants; import org.apache.solr.handler.dataimport.config.ConfigNameConstants;
import org.apache.solr.handler.dataimport.config.DIHConfiguration; import org.apache.solr.handler.dataimport.config.DIHConfiguration;
@ -272,24 +273,39 @@ public class DocBuilder {
} catch(Exception e) } catch(Exception e)
{ {
throw new RuntimeException(e); throw new RuntimeException(e);
} finally } finally {
{ // Cannot use IOUtils.closeQuietly since DIH relies on exceptions bubbling out of writer.close() to indicate
if (writer != null) { // success/failure of the run.
writer.close(); RuntimeException raisedDuringClose = null;
try {
if (writer != null) {
writer.close();
}
} catch (RuntimeException e) {
if (log.isWarnEnabled()) {
log.warn("Exception encountered while closing DIHWriter " + writer + "; temporarily suppressing to ensure other DocBuilder elements are closed", e); // logOk
}
raisedDuringClose = e;
} }
if (epwList != null) { if (epwList != null) {
closeEntityProcessorWrappers(epwList); closeEntityProcessorWrappers(epwList);
} }
if(reqParams.isDebug()) { if(reqParams.isDebug()) {
reqParams.getDebugInfo().debugVerboseOutput = getDebugLogger().output; reqParams.getDebugInfo().debugVerboseOutput = getDebugLogger().output;
} }
if (raisedDuringClose != null) {
throw raisedDuringClose;
}
} }
} }
private void closeEntityProcessorWrappers(List<EntityProcessorWrapper> epwList) { private void closeEntityProcessorWrappers(List<EntityProcessorWrapper> epwList) {
for(EntityProcessorWrapper epw : epwList) { for(EntityProcessorWrapper epw : epwList) {
epw.close(); IOUtils.closeQuietly(epw);
if(epw.getDatasource()!=null) {
epw.getDatasource().close(); if(epw.getDatasource() != null) {
IOUtils.closeQuietly(epw.getDatasource());
} }
closeEntityProcessorWrappers(epw.getChildren()); closeEntityProcessorWrappers(epw.getChildren());
} }

View File

@ -16,6 +16,7 @@
*/ */
package org.apache.solr.handler.dataimport; package org.apache.solr.handler.dataimport;
import java.io.Closeable;
import java.util.Map; import java.util.Map;
/** /**
@ -36,7 +37,7 @@ import java.util.Map;
* *
* @since solr 1.3 * @since solr 1.3
*/ */
public abstract class EntityProcessor { public abstract class EntityProcessor implements Closeable {
/** /**
* This method is called when it starts processing an entity. When it comes * This method is called when it starts processing an entity. When it comes