SOLR-5623: Better diagnosis of RuntimeExceptions in analysis

git-svn-id: https://svn.apache.org/repos/asf/lucene/dev/trunk@1564584 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Benson Margulies 2014-02-05 00:32:03 +00:00
parent 5111571d13
commit 178ec39037
4 changed files with 182 additions and 0 deletions

View File

@ -155,6 +155,23 @@ public class DirectUpdateHandler2 extends UpdateHandler implements SolrCoreState
@Override
public int addDoc(AddUpdateCommand cmd) throws IOException {
try {
return addDoc0(cmd);
} catch (RuntimeException t) {
throw new SolrException(SolrException.ErrorCode.SERVER_ERROR, String.format("Exception writing document id %s to the index; possible analysis error.",
cmd.getPrintableId()), t);
}
}
/**
* This is the implementation of {@link #addDoc0(AddUpdateCommand)}. It is factored out to allow an exception
* handler to decorate RuntimeExceptions with information about the document being handled.
* @param cmd the command.
* @return the count.
* @throws IOException
*/
private int addDoc0(AddUpdateCommand cmd) throws IOException {
int rc = -1;
RefCounted<IndexWriter> iw = solrCoreState.getIndexWriter(core);
try {

View File

@ -0,0 +1,44 @@
<?xml version="1.0" ?>
<!--
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<!--
Striped down schema used by AnalysisErrorHandlingTest. The goal here is to have one
text field that blows up in analysis, and an ID field for diagnosis.
-->
<schema name="test" version="1.5">
<types>
<fieldtype name="long" class="solr.TrieLongField" stored="true" indexed="true" />
<fieldtype name="sint" class="solr.SortableIntField" />
<fieldtype name="text" class="solr.TextField">
<analyzer>
<tokenizer class="solr.StandardTokenizerFactory"/>
<filter class="org.apache.solr.analysis.ThrowingMockTokenFilterFactory" exceptionClassName="java.lang.RuntimeException"/>
</analyzer>
</fieldtype>
</types>
<fields>
<field name="id" type="sint" indexed="true" stored="true" multiValued="false"/>
<field name="text" type="text" indexed="true" stored="true"/>
<field name="_version_" type="long" />
</fields>
<defaultSearchField>text</defaultSearchField>
<uniqueKey>id</uniqueKey>
</schema>

View File

@ -0,0 +1,70 @@
package org.apache.solr.analysis;
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import org.apache.lucene.analysis.TokenFilter;
import org.apache.lucene.analysis.TokenStream;
import org.apache.lucene.analysis.util.TokenFilterFactory;
import java.io.IOException;
import java.util.Map;
/**
* Token filter factory that misbehaves on command.
*/
public class ThrowingMockTokenFilterFactory extends TokenFilterFactory {
private Class<? extends RuntimeException> exceptionClass;
/**
* Initialize this factory via a set of key-value pairs.
*
* @param args the options.
*/
@SuppressWarnings("unchecked")
public ThrowingMockTokenFilterFactory(Map<String, String> args) {
super(args);
String exceptionClassName = args.get("exceptionClassName");
if (exceptionClassName == null) {
throw new RuntimeException("Required parameter exceptionClassName is missing");
}
try {
exceptionClass = (Class<? extends RuntimeException>)Class.forName(exceptionClassName);
} catch (ClassNotFoundException e) {
throw new RuntimeException(e);
}
}
@Override
public TokenStream create(TokenStream input) {
return new TokenFilter(input) {
@Override
public boolean incrementToken() throws IOException {
if (input.incrementToken()) {
try {
throw exceptionClass.newInstance();
} catch (IllegalAccessException | InstantiationException iae) {
throw new RuntimeException(iae);
}
}
return false;
}
};
}
}

View File

@ -0,0 +1,51 @@
package org.apache.solr.update;
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import org.apache.solr.SolrTestCaseJ4;
import org.apache.solr.common.SolrException;
import org.junit.BeforeClass;
import org.junit.Test;
/**
* Test that runtime exceptions thrown during analysis
* result in Solr errors that contain the document ID.
*/
public class AnalysisErrorHandlingTest extends SolrTestCaseJ4 {
public String getCoreName() { return "basic"; }
@BeforeClass
public static void beforeTests() throws Exception {
initCore("solrconfig-basic.xml","solr/analysisconfs/analysis-err-schema.xml");
}
@Test
public void testMultipleUpdatesPerAdd() {
clearIndex();
try {
h.update("<add><doc><field name=\"id\">1</field><field name=\"text\">Alas Poor Yorik</field></doc></add>");
fail("Failed to even throw the exception we are stewing over.");
} catch (SolrException se) {
assertTrue(se.getMessage().contains("Exception writing document id 1 to the index"));
}
}
}