blob: 0863222f9bcfa06abec3a5035cc20920a4e72a45 [file] [log] [blame]
/*
* 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.
*/
package org.apache.lucene.index;
import org.apache.lucene.codecs.Codec;
import org.apache.lucene.codecs.CodecUtil;
import org.apache.lucene.mockfile.ExtrasFS;
import org.apache.lucene.search.Sort;
import org.apache.lucene.store.BaseDirectoryWrapper;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.IOContext;
import org.apache.lucene.store.IndexInput;
import org.apache.lucene.store.IndexOutput;
import org.apache.lucene.util.LuceneTestCase;
import org.apache.lucene.util.StringHelper;
import org.apache.lucene.util.TestUtil;
import org.apache.lucene.util.Version;
import java.io.IOException;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
public class TestSegmentInfos extends LuceneTestCase {
public void testIllegalCreatedVersion() {
IllegalArgumentException e = expectThrows(IllegalArgumentException.class, () -> new SegmentInfos(5));
assertEquals("indexCreatedVersionMajor must be >= 6, got: 5", e.getMessage());
e = expectThrows(IllegalArgumentException.class, () -> new SegmentInfos(Version.LATEST.major + 1));
assertEquals("indexCreatedVersionMajor is in the future: " + (Version.LATEST.major + 1), e.getMessage());
}
// LUCENE-5954
public void testVersionsNoSegments() throws IOException {
SegmentInfos sis = new SegmentInfos(Version.LATEST.major);
BaseDirectoryWrapper dir = newDirectory();
dir.setCheckIndexOnClose(false);
sis.commit(dir);
sis = SegmentInfos.readLatestCommit(dir);
assertNull(sis.getMinSegmentLuceneVersion());
assertEquals(Version.LATEST, sis.getCommitLuceneVersion());
dir.close();
}
// LUCENE-5954
public void testVersionsOneSegment() throws IOException {
BaseDirectoryWrapper dir = newDirectory();
dir.setCheckIndexOnClose(false);
byte id[] = StringHelper.randomId();
Codec codec = Codec.getDefault();
SegmentInfos sis = new SegmentInfos(Version.LATEST.major);
SegmentInfo info = new SegmentInfo(dir, Version.LUCENE_8_0_0, Version.LUCENE_8_0_0, "_0", 1, false, Codec.getDefault(),
Collections.<String,String>emptyMap(), id, Collections.<String,String>emptyMap(), null);
info.setFiles(Collections.<String>emptySet());
codec.segmentInfoFormat().write(dir, info, IOContext.DEFAULT);
SegmentCommitInfo commitInfo = new SegmentCommitInfo(info, 0, 0, -1, -1, -1, StringHelper.randomId());
sis.add(commitInfo);
sis.commit(dir);
sis = SegmentInfos.readLatestCommit(dir);
assertEquals(Version.LUCENE_8_0_0, sis.getMinSegmentLuceneVersion());
assertEquals(Version.LATEST, sis.getCommitLuceneVersion());
dir.close();
}
// LUCENE-5954
public void testVersionsTwoSegments() throws IOException {
BaseDirectoryWrapper dir = newDirectory();
dir.setCheckIndexOnClose(false);
byte id[] = StringHelper.randomId();
Codec codec = Codec.getDefault();
SegmentInfos sis = new SegmentInfos(Version.LATEST.major);
SegmentInfo info = new SegmentInfo(dir, Version.LUCENE_8_0_0, Version.LUCENE_8_0_0, "_0", 1, false, Codec.getDefault(),
Collections.<String,String>emptyMap(), id, Collections.<String,String>emptyMap(), null);
info.setFiles(Collections.<String>emptySet());
codec.segmentInfoFormat().write(dir, info, IOContext.DEFAULT);
SegmentCommitInfo commitInfo = new SegmentCommitInfo(info, 0, 0, -1, -1, -1, StringHelper.randomId());
sis.add(commitInfo);
info = new SegmentInfo(dir, Version.LUCENE_8_0_0, Version.LUCENE_8_0_0, "_1", 1, false, Codec.getDefault(),
Collections.<String,String>emptyMap(), id, Collections.<String,String>emptyMap(), null);
info.setFiles(Collections.<String>emptySet());
codec.segmentInfoFormat().write(dir, info, IOContext.DEFAULT);
commitInfo = new SegmentCommitInfo(info, 0, 0,-1, -1, -1, StringHelper.randomId());
sis.add(commitInfo);
sis.commit(dir);
byte[] commitInfoId0 = sis.info(0).getId();
byte[] commitInfoId1 = sis.info(1).getId();
sis = SegmentInfos.readLatestCommit(dir);
assertEquals(Version.LUCENE_8_0_0, sis.getMinSegmentLuceneVersion());
assertEquals(Version.LATEST, sis.getCommitLuceneVersion());
assertEquals(StringHelper.idToString(commitInfoId0), StringHelper.idToString(sis.info(0).getId()));
assertEquals(StringHelper.idToString(commitInfoId1), StringHelper.idToString(sis.info(1).getId()));
dir.close();
}
/** Test toString method */
public void testToString() throws Throwable{
SegmentInfo si;
final Directory dir = newDirectory();
Codec codec = Codec.getDefault();
// diagnostics map
Map<String, String> diagnostics = new LinkedHashMap<>();
diagnostics.put("key1", "value1");
diagnostics.put("key2", "value2");
// attributes map
Map<String,String> attributes = new LinkedHashMap<>();
attributes.put("key1", "value1");
attributes.put("key2", "value2");
// diagnostics X, attributes X
si = new SegmentInfo(dir, Version.LATEST, Version.LATEST, "TEST", 10000, false, codec, Collections.emptyMap(), StringHelper.randomId(), new HashMap<>(), Sort.INDEXORDER);
assertEquals("TEST(" + Version.LATEST.toString() + ")" +
":C10000" +
":[indexSort=<doc>]", si.toString());
// diagnostics O, attributes X
si = new SegmentInfo(dir, Version.LATEST, Version.LATEST, "TEST", 10000, false, codec, diagnostics, StringHelper.randomId(), new HashMap<>(), Sort.INDEXORDER);
assertEquals("TEST(" + Version.LATEST.toString() + ")" +
":C10000" +
":[indexSort=<doc>]" +
":[diagnostics={key1=value1, key2=value2}]", si.toString());
// diagnostics X, attributes O
si = new SegmentInfo(dir, Version.LATEST, Version.LATEST, "TEST", 10000, false, codec, Collections.emptyMap(), StringHelper.randomId(), attributes, Sort.INDEXORDER);
assertEquals("TEST(" + Version.LATEST.toString() + ")" +
":C10000" +
":[indexSort=<doc>]" +
":[attributes={key1=value1, key2=value2}]", si.toString());
// diagnostics O, attributes O
si = new SegmentInfo(dir, Version.LATEST, Version.LATEST, "TEST", 10000, false, codec, diagnostics, StringHelper.randomId(), attributes, Sort.INDEXORDER);
System.out.println(si.toString());
assertEquals("TEST(" + Version.LATEST.toString() + ")" +
":C10000" +
":[indexSort=<doc>]" +
":[diagnostics={key1=value1, key2=value2}]" +
":[attributes={key1=value1, key2=value2}]", si.toString());
dir.close();
}
public void testIDChangesOnAdvance() throws IOException {
try (BaseDirectoryWrapper dir = newDirectory()) {
dir.setCheckIndexOnClose(false);
byte id[] = StringHelper.randomId();
SegmentInfo info = new SegmentInfo(dir, Version.LUCENE_8_6_0, Version.LUCENE_8_6_0, "_0", 1, false, Codec.getDefault(),
Collections.<String, String>emptyMap(), StringHelper.randomId(), Collections.<String, String>emptyMap(), null);
SegmentCommitInfo commitInfo = new SegmentCommitInfo(info, 0, 0, -1, -1, -1, id);
assertEquals(StringHelper.idToString(id), StringHelper.idToString(commitInfo.getId()));
commitInfo.advanceDelGen();
assertNotEquals(StringHelper.idToString(id), StringHelper.idToString(commitInfo.getId()));
id = commitInfo.getId();
commitInfo.advanceDocValuesGen();
assertNotEquals(StringHelper.idToString(id), StringHelper.idToString(commitInfo.getId()));
id = commitInfo.getId();
commitInfo.advanceFieldInfosGen();
assertNotEquals(StringHelper.idToString(id), StringHelper.idToString(commitInfo.getId()));
SegmentCommitInfo clone = commitInfo.clone();
id = commitInfo.getId();
assertEquals(StringHelper.idToString(id), StringHelper.idToString(commitInfo.getId()));
assertEquals(StringHelper.idToString(id), StringHelper.idToString(clone.getId()));
commitInfo.advanceFieldInfosGen();
assertNotEquals(StringHelper.idToString(id), StringHelper.idToString(commitInfo.getId()));
assertEquals("clone changed but shouldn't", StringHelper.idToString(id), StringHelper.idToString(clone.getId()));
}
}
public void testBitFlippedTriggersCorruptIndexException() throws IOException {
BaseDirectoryWrapper dir = newDirectory();
dir.setCheckIndexOnClose(false);
byte id[] = StringHelper.randomId();
Codec codec = Codec.getDefault();
SegmentInfos sis = new SegmentInfos(Version.LATEST.major);
SegmentInfo info = new SegmentInfo(dir, Version.LATEST, Version.LATEST, "_0", 1, false, Codec.getDefault(),
Collections.<String,String>emptyMap(), id, Collections.<String,String>emptyMap(), null);
info.setFiles(Collections.<String>emptySet());
codec.segmentInfoFormat().write(dir, info, IOContext.DEFAULT);
SegmentCommitInfo commitInfo = new SegmentCommitInfo(info, 0, 0, -1, -1, -1, StringHelper.randomId());
sis.add(commitInfo);
info = new SegmentInfo(dir, Version.LATEST, Version.LATEST, "_1", 1, false, Codec.getDefault(),
Collections.<String,String>emptyMap(), id, Collections.<String,String>emptyMap(), null);
info.setFiles(Collections.<String>emptySet());
codec.segmentInfoFormat().write(dir, info, IOContext.DEFAULT);
commitInfo = new SegmentCommitInfo(info, 0, 0,-1, -1, -1, StringHelper.randomId());
sis.add(commitInfo);
sis.commit(dir);
BaseDirectoryWrapper corruptDir = newDirectory();
corruptDir.setCheckIndexOnClose(false);
boolean corrupt = false;
for (String file : dir.listAll()) {
if (file.startsWith(IndexFileNames.SEGMENTS)) {
try (IndexInput in = dir.openInput(file, IOContext.DEFAULT);
IndexOutput out = corruptDir.createOutput(file, IOContext.DEFAULT)) {
final long corruptIndex = TestUtil.nextLong(random(), 0, in.length() - 1);
out.copyBytes(in, corruptIndex);
final int b = Byte.toUnsignedInt(in.readByte()) + TestUtil.nextInt(random(), 0x01, 0xff);
out.writeByte((byte) b);
out.copyBytes(in, in.length() - in.getFilePointer());
}
try (IndexInput in = corruptDir.openInput(file, IOContext.DEFAULT)) {
CodecUtil.checksumEntireFile(in);
if (VERBOSE) {
System.out.println("TEST: Altering the file did not update the checksum, aborting...");
}
return;
} catch (CorruptIndexException e) {
// ok
}
corrupt = true;
} else if (ExtrasFS.isExtra(file) == false) {
corruptDir.copyFrom(dir, file, file, IOContext.DEFAULT);
}
}
assertTrue("No segments file found", corrupt);
expectThrowsAnyOf(
Arrays.asList(CorruptIndexException.class, IndexFormatTooOldException.class, IndexFormatTooNewException.class),
() -> SegmentInfos.readLatestCommit(corruptDir));
dir.close();
corruptDir.close();
}
}