SOLR-1748, SOLR-1747, SOLR-1746, SOLR-1745, SOLR-1744: Streams and Readers retrieved from ContentStreams are not closed in various places, resulting in file descriptor leaks.

git-svn-id: https://svn.apache.org/repos/asf/lucene/solr/trunk@906553 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Mark Robert Miller 2010-02-04 16:26:38 +00:00
parent 1444299662
commit db62a20003
6 changed files with 108 additions and 60 deletions

View File

@ -850,6 +850,11 @@ Bug Fixes
caused an error to be returned, although the deletes were caused an error to be returned, although the deletes were
still executed. (asmodean via yonik) still executed. (asmodean via yonik)
76. SOLR-1748, SOLR-1747, SOLR-1746, SOLR-1745, SOLR-1744: Streams and Readers
retrieved from ContentStreams are not closed in various places, resulting
in file descriptor leaks.
(Christoff Brill, Mark Miller)
Other Changes Other Changes
---------------------- ----------------------
1. Upgraded to Lucene 2.4.0 (yonik) 1. Upgraded to Lucene 2.4.0 (yonik)

View File

@ -49,7 +49,15 @@ public class BinaryUpdateRequestHandler extends ContentStreamHandlerBase {
protected ContentStreamLoader newLoader(SolrQueryRequest req, final UpdateRequestProcessor processor) { protected ContentStreamLoader newLoader(SolrQueryRequest req, final UpdateRequestProcessor processor) {
return new ContentStreamLoader() { return new ContentStreamLoader() {
public void load(SolrQueryRequest req, SolrQueryResponse rsp, ContentStream stream) throws Exception { public void load(SolrQueryRequest req, SolrQueryResponse rsp, ContentStream stream) throws Exception {
parseAndLoadDocs(req, rsp, stream.getStream(), processor); InputStream is = null;
try {
is = stream.getStream();
parseAndLoadDocs(req, rsp, is, processor);
} finally {
if(is != null) {
is.close();
}
}
} }
}; };
} }

View File

@ -18,6 +18,7 @@
package org.apache.solr.handler; package org.apache.solr.handler;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList; import java.util.ArrayList;
import org.apache.commons.io.IOUtils; import org.apache.commons.io.IOUtils;
@ -45,7 +46,12 @@ public class DumpRequestHandler extends RequestHandlerBase
stream.add( "sourceInfo", content.getSourceInfo() ); stream.add( "sourceInfo", content.getSourceInfo() );
stream.add( "size", content.getSize() ); stream.add( "size", content.getSize() );
stream.add( "contentType", content.getContentType() ); stream.add( "contentType", content.getContentType() );
stream.add( "stream", IOUtils.toString( content.getStream() ) ); InputStream is = content.getStream();
try {
stream.add( "stream", IOUtils.toString(is) );
} finally {
is.close();
}
streams.add( stream ); streams.add( stream );
} }
rsp.add( "streams", streams ); rsp.add( "streams", streams );

View File

@ -23,11 +23,9 @@ import java.net.MalformedURLException;
import java.net.URL; import java.net.URL;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Comparator; import java.util.Comparator;
import java.util.HashSet;
import java.util.Iterator; import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set;
import java.util.regex.Pattern; import java.util.regex.Pattern;
import org.apache.lucene.document.Document; import org.apache.lucene.document.Document;
@ -40,7 +38,6 @@ import org.apache.lucene.search.TermQuery;
import org.apache.lucene.search.similar.MoreLikeThis; import org.apache.lucene.search.similar.MoreLikeThis;
import org.apache.solr.common.SolrException; import org.apache.solr.common.SolrException;
import org.apache.solr.common.params.CommonParams; import org.apache.solr.common.params.CommonParams;
import org.apache.solr.common.params.DisMaxParams;
import org.apache.solr.common.params.FacetParams; import org.apache.solr.common.params.FacetParams;
import org.apache.solr.common.params.MoreLikeThisParams; import org.apache.solr.common.params.MoreLikeThisParams;
import org.apache.solr.common.params.SolrParams; import org.apache.solr.common.params.SolrParams;
@ -84,23 +81,6 @@ public class MoreLikeThisHandler extends RequestHandlerBase
SolrParams params = req.getParams(); SolrParams params = req.getParams();
SolrIndexSearcher searcher = req.getSearcher(); SolrIndexSearcher searcher = req.getSearcher();
// Parse Required Params
// This will either have a single Reader or valid query
Reader reader = null;
String q = params.get( CommonParams.Q );
if( q == null || q.trim().length() <1 ) {
Iterable<ContentStream> streams = req.getContentStreams();
if( streams != null ) {
Iterator<ContentStream> iter = streams.iterator();
if( iter.hasNext() ) {
reader = iter.next().getReader();
}
if( iter.hasNext() ) {
throw new SolrException( SolrException.ErrorCode.BAD_REQUEST,
"MoreLikeThis does not support multiple ContentStreams" );
}
}
}
MoreLikeThisHelper mlt = new MoreLikeThisHelper( params, searcher ); MoreLikeThisHelper mlt = new MoreLikeThisHelper( params, searcher );
List<Query> filters = SolrPluginUtils.parseFilterQueries(req); List<Query> filters = SolrPluginUtils.parseFilterQueries(req);
@ -110,6 +90,27 @@ public class MoreLikeThisHandler extends RequestHandlerBase
List<InterestingTerm> interesting = (termStyle == TermStyle.NONE ) List<InterestingTerm> interesting = (termStyle == TermStyle.NONE )
? null : new ArrayList<InterestingTerm>( mlt.mlt.getMaxQueryTerms() ); ? null : new ArrayList<InterestingTerm>( mlt.mlt.getMaxQueryTerms() );
DocListAndSet mltDocs = null;
String q = params.get( CommonParams.Q );
// Parse Required Params
// This will either have a single Reader or valid query
Reader reader = null;
try {
if (q == null || q.trim().length() < 1) {
Iterable<ContentStream> streams = req.getContentStreams();
if (streams != null) {
Iterator<ContentStream> iter = streams.iterator();
if (iter.hasNext()) {
reader = iter.next().getReader();
}
if (iter.hasNext()) {
throw new SolrException(SolrException.ErrorCode.BAD_REQUEST,
"MoreLikeThis does not support multiple ContentStreams");
}
}
}
// What fields do we need to return // What fields do we need to return
String fl = params.get(CommonParams.FL); String fl = params.get(CommonParams.FL);
int flags = 0; int flags = 0;
@ -117,39 +118,47 @@ public class MoreLikeThisHandler extends RequestHandlerBase
flags |= SolrPluginUtils.setReturnFields(fl, rsp); flags |= SolrPluginUtils.setReturnFields(fl, rsp);
} }
int start = params.getInt( CommonParams.START, 0 ); int start = params.getInt(CommonParams.START, 0);
int rows = params.getInt( CommonParams.ROWS, 10 ); int rows = params.getInt(CommonParams.ROWS, 10);
DocListAndSet mltDocs = null;
// Find documents MoreLikeThis - either with a reader or a query // Find documents MoreLikeThis - either with a reader or a query
//-------------------------------------------------------------------------------- // --------------------------------------------------------------------------------
if( reader != null ) { if (reader != null) {
mltDocs = mlt.getMoreLikeThis( reader, start, rows, filters, interesting, flags ); mltDocs = mlt.getMoreLikeThis(reader, start, rows, filters,
} interesting, flags);
else if( q != null ) { } else if (q != null) {
// Matching options // Matching options
boolean includeMatch = params.getBool( MoreLikeThisParams.MATCH_INCLUDE, true ); boolean includeMatch = params.getBool(MoreLikeThisParams.MATCH_INCLUDE,
int matchOffset = params.getInt( MoreLikeThisParams.MATCH_OFFSET, 0 ); true);
int matchOffset = params.getInt(MoreLikeThisParams.MATCH_OFFSET, 0);
// Find the base match // Find the base match
Query query = QueryParsing.parseQuery(q, params.get(CommonParams.DF), params, req.getSchema()); Query query = QueryParsing.parseQuery(q, params.get(CommonParams.DF),
DocList match = searcher.getDocList(query, null, null, matchOffset, 1, flags ); // only get the first one... params, req.getSchema());
if( includeMatch ) { DocList match = searcher.getDocList(query, null, null, matchOffset, 1,
rsp.add( "match", match ); flags); // only get the first one...
if (includeMatch) {
rsp.add("match", match);
} }
// This is an iterator, but we only handle the first match // This is an iterator, but we only handle the first match
DocIterator iterator = match.iterator(); DocIterator iterator = match.iterator();
if( iterator.hasNext() ) { if (iterator.hasNext()) {
// do a MoreLikeThis query for each document in results // do a MoreLikeThis query for each document in results
int id = iterator.nextDoc(); int id = iterator.nextDoc();
mltDocs = mlt.getMoreLikeThis( id, start, rows, filters, interesting, flags ); mltDocs = mlt.getMoreLikeThis(id, start, rows, filters, interesting,
flags);
}
} else {
throw new SolrException(SolrException.ErrorCode.BAD_REQUEST,
"MoreLikeThis requires either a query (?q=) or text to find similar documents.");
}
} finally {
if (reader != null) {
reader.close();
} }
} }
else {
throw new SolrException( SolrException.ErrorCode.BAD_REQUEST,
"MoreLikeThis requires either a query (?q=) or text to find similar documents." );
}
if( mltDocs == null ) { if( mltDocs == null ) {
mltDocs = new DocListAndSet(); // avoid NPE mltDocs = new DocListAndSet(); // avoid NPE
} }

View File

@ -18,6 +18,7 @@
package org.apache.solr.response; package org.apache.solr.response;
import java.io.IOException; import java.io.IOException;
import java.io.Reader;
import java.io.Writer; import java.io.Writer;
import org.apache.commons.io.IOUtils; import org.apache.commons.io.IOUtils;
@ -81,7 +82,12 @@ public class RawResponseWriter implements QueryResponseWriter
if( obj != null && (obj instanceof ContentStream ) ) { if( obj != null && (obj instanceof ContentStream ) ) {
// copy the contents to the writer... // copy the contents to the writer...
ContentStream content = (ContentStream)obj; ContentStream content = (ContentStream)obj;
IOUtils.copy( content.getReader(), writer ); Reader reader = content.getReader();
try {
IOUtils.copy( reader, writer );
} finally {
reader.close();
}
} }
else { else {
getBaseWriter( request ).write( writer, request, response ); getBaseWriter( request ).write( writer, request, response );

View File

@ -20,6 +20,7 @@ package org.apache.solr.client.solrj.impl;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.OutputStream; import java.io.OutputStream;
import java.io.Reader;
import java.net.MalformedURLException; import java.net.MalformedURLException;
import java.net.URL; import java.net.URL;
import java.util.*; import java.util.*;
@ -246,6 +247,7 @@ public class CommonsHttpSolrServer extends SolrServer
public NamedList<Object> request(final SolrRequest request, ResponseParser processor) throws SolrServerException, IOException { public NamedList<Object> request(final SolrRequest request, ResponseParser processor) throws SolrServerException, IOException {
HttpMethod method = null; HttpMethod method = null;
InputStream is = null;
SolrParams params = request.getParams(); SolrParams params = request.getParams();
Collection<ContentStream> streams = requestWriter.getContentStreams(request); Collection<ContentStream> streams = requestWriter.getContentStreams(request);
String path = requestWriter.getPath(request); String path = requestWriter.getPath(request);
@ -333,7 +335,12 @@ public class CommonsHttpSolrServer extends SolrServer
@Override @Override
protected void sendData(OutputStream out) protected void sendData(OutputStream out)
throws IOException { throws IOException {
IOUtils.copy(c.getReader(), out); Reader reader = c.getReader();
try {
IOUtils.copy(reader, out);
} finally {
reader.close();
}
} }
}); });
} }
@ -378,7 +385,8 @@ public class CommonsHttpSolrServer extends SolrServer
); );
} else { } else {
post.setRequestEntity(new InputStreamRequestEntity(contentStream[0].getStream(), contentStream[0].getContentType())); is = contentStream[0].getStream();
post.setRequestEntity(new InputStreamRequestEntity(is, contentStream[0].getContentType()));
} }
method = post; method = post;
} }
@ -391,6 +399,9 @@ public class CommonsHttpSolrServer extends SolrServer
// This is generally safe to retry on // This is generally safe to retry on
method.releaseConnection(); method.releaseConnection();
method = null; method = null;
if(is != null) {
is.close();
}
// If out of tries then just rethrow (as normal error). // If out of tries then just rethrow (as normal error).
if( ( tries < 1 ) ) { if( ( tries < 1 ) ) {
throw r; throw r;
@ -473,6 +484,9 @@ public class CommonsHttpSolrServer extends SolrServer
} }
finally { finally {
method.releaseConnection(); method.releaseConnection();
if(is != null) {
is.close();
}
} }
} }