[CORE] Support parsing lucene minor version strings
We parse the version that is shipped with the Lucene segments in order to find the version of lucene that wrote a particular segment. Yet, some lucene version ie: * 4.3.1 (Elasticsearch 0.90.2) * 4.5.1 (Elasticsearch 0.90.7) * 3.6.1 (pre Elasticsearch 0.90.0) wrote illegal strings containing the minor version which causes IAE exceptions being thrown from lucenes parsing method. Closes #7055
This commit is contained in:
parent
07c9b5b08d
commit
d2493ea48a
|
@ -66,3 +66,6 @@ java.nio.channels.ReadableByteChannel#read(java.nio.ByteBuffer)
|
|||
java.nio.channels.ScatteringByteChannel#read(java.nio.ByteBuffer[])
|
||||
java.nio.channels.ScatteringByteChannel#read(java.nio.ByteBuffer[], int, int)
|
||||
java.nio.channels.FileChannel#read(java.nio.ByteBuffer, long)
|
||||
|
||||
@defaultMessage Use Lucene.parseLenient instead it strips off minor version
|
||||
org.apache.lucene.util.Version#parseLeniently(java.lang.String)
|
||||
|
|
3
pom.xml
3
pom.xml
|
@ -1169,6 +1169,9 @@
|
|||
<!-- start exclude for Channels utility class -->
|
||||
<exclude>org/elasticsearch/common/io/Channels.class</exclude>
|
||||
<!-- end exclude for Channels -->
|
||||
<!-- start exclude for Lucene utility class -->
|
||||
<exclude>org/elasticsearch/common/lucene/Lucene$LenientParser.class</exclude>
|
||||
<!-- end exclude for Lucene -->
|
||||
</excludes>
|
||||
<bundledSignatures>
|
||||
<!-- This will automatically choose the right signatures based on 'targetVersion': -->
|
||||
|
|
|
@ -33,6 +33,7 @@ import org.elasticsearch.ElasticsearchException;
|
|||
import org.elasticsearch.ElasticsearchIllegalArgumentException;
|
||||
import org.elasticsearch.ExceptionsHelper;
|
||||
import org.elasticsearch.common.Nullable;
|
||||
import org.elasticsearch.common.Strings;
|
||||
import org.elasticsearch.common.io.stream.StreamInput;
|
||||
import org.elasticsearch.common.io.stream.StreamOutput;
|
||||
import org.elasticsearch.common.logging.ESLogger;
|
||||
|
@ -40,8 +41,10 @@ import org.elasticsearch.index.analysis.AnalyzerScope;
|
|||
import org.elasticsearch.index.analysis.NamedAnalyzer;
|
||||
import org.elasticsearch.index.fielddata.IndexFieldData;
|
||||
|
||||
import static org.elasticsearch.common.lucene.search.NoopCollector.NOOP_COLLECTOR;
|
||||
import java.io.IOException;
|
||||
import java.util.Locale;
|
||||
|
||||
import static org.elasticsearch.common.lucene.search.NoopCollector.NOOP_COLLECTOR;
|
||||
|
||||
/**
|
||||
*
|
||||
|
@ -537,4 +540,27 @@ public class Lucene {
|
|||
public static boolean isCorruptionException(Throwable t) {
|
||||
return ExceptionsHelper.unwrap(t, CorruptIndexException.class) != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses the version string lenient and returns the the default value if the given string is null or emtpy
|
||||
*/
|
||||
public static Version parseVersionLenient(String toParse, Version defaultValue) {
|
||||
return LenientParser.parse(toParse, defaultValue);
|
||||
}
|
||||
|
||||
private static final class LenientParser {
|
||||
public static Version parse(String toParse, Version defaultValue) {
|
||||
if (Strings.hasLength(toParse)) {
|
||||
try {
|
||||
return Version.parseLeniently(toParse);
|
||||
} catch (IllegalArgumentException e) {
|
||||
final String parsedMatchVersion = toParse
|
||||
.toUpperCase(Locale.ROOT)
|
||||
.replaceFirst("^(\\d+)\\.(\\d+).(\\d+)$", "LUCENE_$1_$2");
|
||||
return Version.valueOf(parsedMatchVersion);
|
||||
}
|
||||
}
|
||||
return defaultValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -24,6 +24,7 @@ import org.apache.lucene.util.Version;
|
|||
import org.elasticsearch.ElasticsearchParseException;
|
||||
import org.elasticsearch.common.Nullable;
|
||||
import org.elasticsearch.common.ParseField;
|
||||
import org.elasticsearch.common.lucene.Lucene;
|
||||
import org.elasticsearch.common.unit.ByteSizeValue;
|
||||
import org.elasticsearch.common.xcontent.ToXContent;
|
||||
import org.elasticsearch.common.xcontent.XContentBuilder;
|
||||
|
@ -255,7 +256,7 @@ public class BlobStoreIndexShardSnapshot {
|
|||
} else if ("part_size".equals(currentFieldName)) {
|
||||
partSize = new ByteSizeValue(parser.longValue());
|
||||
} else if ("written_by".equals(currentFieldName)) {
|
||||
writtenBy = Version.parseLeniently(parser.text());
|
||||
writtenBy = Lucene.parseVersionLenient(parser.text(), null);
|
||||
} else {
|
||||
throw new ElasticsearchParseException("unknown parameter [" + currentFieldName + "]");
|
||||
}
|
||||
|
|
|
@ -448,7 +448,7 @@ public class Store extends AbstractIndexShardComponent implements CloseableIndex
|
|||
Version maxVersion = Version.LUCENE_3_0; // we don't know which version was used to write so we take the max version.
|
||||
Set<String> added = new HashSet<>();
|
||||
for (SegmentCommitInfo info : segmentCommitInfos) {
|
||||
final Version version = Version.parseLeniently(info.info.getVersion());
|
||||
final Version version = Lucene.parseVersionLenient(info.info.getVersion(), Version.LUCENE_3_0);
|
||||
if (version.onOrAfter(maxVersion)) {
|
||||
maxVersion = version;
|
||||
}
|
||||
|
|
|
@ -19,12 +19,12 @@
|
|||
|
||||
package org.elasticsearch.index.store;
|
||||
|
||||
import org.apache.lucene.store.Directory;
|
||||
import org.apache.lucene.util.Version;
|
||||
import org.elasticsearch.common.Nullable;
|
||||
import org.elasticsearch.common.io.stream.StreamInput;
|
||||
import org.elasticsearch.common.io.stream.StreamOutput;
|
||||
import org.elasticsearch.common.io.stream.Streamable;
|
||||
import org.elasticsearch.common.lucene.Lucene;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
|
@ -102,7 +102,7 @@ public class StoreFileMetaData implements Streamable {
|
|||
checksum = in.readOptionalString();
|
||||
if (in.getVersion().onOrAfter(org.elasticsearch.Version.V_1_3_0)) {
|
||||
String versionString = in.readOptionalString();
|
||||
writtenBy = versionString == null ? null : Version.parseLeniently(versionString);
|
||||
writtenBy = Lucene.parseVersionLenient(versionString, null);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -21,10 +21,10 @@ package org.elasticsearch.indices.recovery;
|
|||
|
||||
import org.apache.lucene.util.Version;
|
||||
import org.elasticsearch.common.Nullable;
|
||||
import org.elasticsearch.common.bytes.BytesArray;
|
||||
import org.elasticsearch.common.bytes.BytesReference;
|
||||
import org.elasticsearch.common.io.stream.StreamInput;
|
||||
import org.elasticsearch.common.io.stream.StreamOutput;
|
||||
import org.elasticsearch.common.lucene.Lucene;
|
||||
import org.elasticsearch.index.shard.ShardId;
|
||||
import org.elasticsearch.index.store.StoreFileMetaData;
|
||||
import org.elasticsearch.transport.TransportRequest;
|
||||
|
@ -101,7 +101,7 @@ public final class RecoveryFileChunkRequest extends TransportRequest { // publi
|
|||
Version writtenBy = null;
|
||||
if (in.getVersion().onOrAfter(org.elasticsearch.Version.V_1_3_0)) {
|
||||
String versionString = in.readOptionalString();
|
||||
writtenBy = versionString == null ? null : Version.parseLeniently(versionString);
|
||||
writtenBy = Lucene.parseVersionLenient(versionString, null);
|
||||
}
|
||||
metaData = new StoreFileMetaData(name, length, checksum, writtenBy);
|
||||
}
|
||||
|
|
|
@ -33,6 +33,7 @@ import org.elasticsearch.common.component.AbstractComponent;
|
|||
import org.elasticsearch.common.component.LifecycleComponent;
|
||||
import org.elasticsearch.common.inject.Module;
|
||||
import org.elasticsearch.common.logging.ESLogger;
|
||||
import org.elasticsearch.common.lucene.Lucene;
|
||||
import org.elasticsearch.common.settings.ImmutableSettings;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.common.unit.TimeValue;
|
||||
|
@ -571,7 +572,7 @@ public class PluginsService extends AbstractComponent {
|
|||
String parts[] = luceneVersion.split("\\.");
|
||||
|
||||
// Should fail if the running node is too old!
|
||||
org.apache.lucene.util.Version luceneExpectedVersion = org.apache.lucene.util.Version.parseLeniently(parts[0]+"."+parts[1]);
|
||||
org.apache.lucene.util.Version luceneExpectedVersion = Lucene.parseVersionLenient(parts[0] + "." + parts[1], null);
|
||||
|
||||
if (Version.CURRENT.luceneVersion.equals(luceneExpectedVersion)) {
|
||||
logger.debug("starting analysis plugin for Lucene [{}].", luceneExpectedVersion);
|
||||
|
|
|
@ -20,10 +20,14 @@
|
|||
package org.elasticsearch;
|
||||
|
||||
import org.elasticsearch.cluster.metadata.IndexMetaData;
|
||||
import org.elasticsearch.common.lucene.Lucene;
|
||||
import org.elasticsearch.common.settings.ImmutableSettings;
|
||||
import org.elasticsearch.test.ElasticsearchTestCase;
|
||||
import org.hamcrest.Matchers;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.Locale;
|
||||
|
||||
import static org.elasticsearch.Version.V_0_20_0;
|
||||
import static org.elasticsearch.Version.V_0_90_0;
|
||||
import static org.hamcrest.CoreMatchers.equalTo;
|
||||
|
@ -114,4 +118,19 @@ public class VersionTests extends ElasticsearchTestCase {
|
|||
assertThat(Version.V_1_0_0_RC2.minimumCompatibilityVersion(), equalTo(Version.V_1_0_0_RC2));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void parseLenient() {
|
||||
int numIters = randomIntBetween(10, 100);
|
||||
for (int i = 0; i < numIters; i++) {
|
||||
Version version = randomVersion(getRandom());
|
||||
org.apache.lucene.util.Version luceneVersion = version.luceneVersion;
|
||||
String string = luceneVersion.name().toUpperCase(Locale.ROOT)
|
||||
.replaceFirst("^LUCENE_(\\d+)_(\\d+)$", "$1.$2");
|
||||
if (randomBoolean()) {
|
||||
string = string + "." + randomIntBetween(0, 100);
|
||||
}
|
||||
assertThat(luceneVersion, Matchers.equalTo(Lucene.parseVersionLenient(string, null)));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue