/*
 * 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 java.io.IOException;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

Embeds a [read-only] SegmentInfo and adds per-commit fields. @lucene.experimental
/** Embeds a [read-only] SegmentInfo and adds per-commit * fields. * * @lucene.experimental */
public class SegmentCommitInfo {
The SegmentInfo that we wrap.
/** The {@link SegmentInfo} that we wrap. */
public final SegmentInfo info; // How many deleted docs in the segment: private int delCount; // How many soft-deleted docs in the segment that are not also hard-deleted: private int softDelCount; // Generation number of the live docs file (-1 if there // are no deletes yet): private long delGen; // Normally 1+delGen, unless an exception was hit on last // attempt to write: private long nextWriteDelGen; // Generation number of the FieldInfos (-1 if there are no updates) private long fieldInfosGen; // Normally 1+fieldInfosGen, unless an exception was hit on last attempt to // write private long nextWriteFieldInfosGen; // Generation number of the DocValues (-1 if there are no updates) private long docValuesGen; // Normally 1+dvGen, unless an exception was hit on last attempt to // write private long nextWriteDocValuesGen; // Track the per-field DocValues update files private final Map<Integer,Set<String>> dvUpdatesFiles = new HashMap<>(); // TODO should we add .files() to FieldInfosFormat, like we have on // LiveDocsFormat? // track the fieldInfos update files private final Set<String> fieldInfosFiles = new HashSet<>(); private volatile long sizeInBytes = -1; // NOTE: only used in-RAM by IW to track buffered deletes; // this is never written to/read from the Directory private long bufferedDeletesGen = -1;
Sole constructor.
Params:
  • info – SegmentInfo that we wrap
  • delCount – number of deleted documents in this segment
  • delGen – deletion generation number (used to name deletion files)
  • fieldInfosGen – FieldInfos generation number (used to name field-infos files)
  • docValuesGen – DocValues generation number (used to name doc-values updates files)
/** * Sole constructor. * * @param info * {@link SegmentInfo} that we wrap * @param delCount * number of deleted documents in this segment * @param delGen * deletion generation number (used to name deletion files) * @param fieldInfosGen * FieldInfos generation number (used to name field-infos files) * @param docValuesGen * DocValues generation number (used to name doc-values updates files) */
public SegmentCommitInfo(SegmentInfo info, int delCount, int softDelCount, long delGen, long fieldInfosGen, long docValuesGen) { this.info = info; this.delCount = delCount; this.softDelCount = softDelCount; this.delGen = delGen; this.nextWriteDelGen = delGen == -1 ? 1 : delGen + 1; this.fieldInfosGen = fieldInfosGen; this.nextWriteFieldInfosGen = fieldInfosGen == -1 ? 1 : fieldInfosGen + 1; this.docValuesGen = docValuesGen; this.nextWriteDocValuesGen = docValuesGen == -1 ? 1 : docValuesGen + 1; }
Returns the per-field DocValues updates files.
/** Returns the per-field DocValues updates files. */
public Map<Integer,Set<String>> getDocValuesUpdatesFiles() { return Collections.unmodifiableMap(dvUpdatesFiles); }
Sets the DocValues updates file names, per field number. Does not deep clone the map.
/** Sets the DocValues updates file names, per field number. Does not deep clone the map. */
public void setDocValuesUpdatesFiles(Map<Integer,Set<String>> dvUpdatesFiles) { this.dvUpdatesFiles.clear(); for (Map.Entry<Integer,Set<String>> kv : dvUpdatesFiles.entrySet()) { // rename the set Set<String> set = new HashSet<>(); for (String file : kv.getValue()) { set.add(info.namedForThisSegment(file)); } this.dvUpdatesFiles.put(kv.getKey(), set); } }
Returns the FieldInfos file names.
/** Returns the FieldInfos file names. */
public Set<String> getFieldInfosFiles() { return Collections.unmodifiableSet(fieldInfosFiles); }
Sets the FieldInfos file names.
/** Sets the FieldInfos file names. */
public void setFieldInfosFiles(Set<String> fieldInfosFiles) { this.fieldInfosFiles.clear(); for (String file : fieldInfosFiles) { this.fieldInfosFiles.add(info.namedForThisSegment(file)); } }
Called when we succeed in writing deletes
/** Called when we succeed in writing deletes */
void advanceDelGen() { delGen = nextWriteDelGen; nextWriteDelGen = delGen+1; sizeInBytes = -1; }
Called if there was an exception while writing deletes, so that we don't try to write to the same file more than once.
/** Called if there was an exception while writing * deletes, so that we don't try to write to the same * file more than once. */
void advanceNextWriteDelGen() { nextWriteDelGen++; }
Gets the nextWriteDelGen.
/** Gets the nextWriteDelGen. */
long getNextWriteDelGen() { return nextWriteDelGen; }
Sets the nextWriteDelGen.
/** Sets the nextWriteDelGen. */
void setNextWriteDelGen(long v) { nextWriteDelGen = v; }
Called when we succeed in writing a new FieldInfos generation.
/** Called when we succeed in writing a new FieldInfos generation. */
void advanceFieldInfosGen() { fieldInfosGen = nextWriteFieldInfosGen; nextWriteFieldInfosGen = fieldInfosGen + 1; sizeInBytes = -1; }
Called if there was an exception while writing a new generation of FieldInfos, so that we don't try to write to the same file more than once.
/** * Called if there was an exception while writing a new generation of * FieldInfos, so that we don't try to write to the same file more than once. */
void advanceNextWriteFieldInfosGen() { nextWriteFieldInfosGen++; }
Gets the nextWriteFieldInfosGen.
/** Gets the nextWriteFieldInfosGen. */
long getNextWriteFieldInfosGen() { return nextWriteFieldInfosGen; }
Sets the nextWriteFieldInfosGen.
/** Sets the nextWriteFieldInfosGen. */
void setNextWriteFieldInfosGen(long v) { nextWriteFieldInfosGen = v; }
Called when we succeed in writing a new DocValues generation.
/** Called when we succeed in writing a new DocValues generation. */
void advanceDocValuesGen() { docValuesGen = nextWriteDocValuesGen; nextWriteDocValuesGen = docValuesGen + 1; sizeInBytes = -1; }
Called if there was an exception while writing a new generation of DocValues, so that we don't try to write to the same file more than once.
/** * Called if there was an exception while writing a new generation of * DocValues, so that we don't try to write to the same file more than once. */
void advanceNextWriteDocValuesGen() { nextWriteDocValuesGen++; }
Gets the nextWriteDocValuesGen.
/** Gets the nextWriteDocValuesGen. */
long getNextWriteDocValuesGen() { return nextWriteDocValuesGen; }
Sets the nextWriteDocValuesGen.
/** Sets the nextWriteDocValuesGen. */
void setNextWriteDocValuesGen(long v) { nextWriteDocValuesGen = v; }
Returns total size in bytes of all files for this segment.
/** Returns total size in bytes of all files for this * segment. */
public long sizeInBytes() throws IOException { if (sizeInBytes == -1) { long sum = 0; for (final String fileName : files()) { sum += info.dir.fileLength(fileName); } sizeInBytes = sum; } return sizeInBytes; }
Returns all files in use by this segment.
/** Returns all files in use by this segment. */
public Collection<String> files() throws IOException { // Start from the wrapped info's files: Collection<String> files = new HashSet<>(info.files()); // TODO we could rely on TrackingDir.getCreatedFiles() (like we do for // updates) and then maybe even be able to remove LiveDocsFormat.files(). // Must separately add any live docs files: info.getCodec().liveDocsFormat().files(this, files); // must separately add any field updates files for (Set<String> updatefiles : dvUpdatesFiles.values()) { files.addAll(updatefiles); } // must separately add fieldInfos files files.addAll(fieldInfosFiles); return files; } long getBufferedDeletesGen() { return bufferedDeletesGen; } void setBufferedDeletesGen(long v) { if (bufferedDeletesGen == -1) { bufferedDeletesGen = v; sizeInBytes = -1; } else { throw new IllegalStateException("buffered deletes gen should only be set once"); } }
Returns true if there are any deletions for the segment at this commit.
/** Returns true if there are any deletions for the * segment at this commit. */
public boolean hasDeletions() { return delGen != -1; }
Returns true if there are any field updates for the segment in this commit.
/** Returns true if there are any field updates for the segment in this commit. */
public boolean hasFieldUpdates() { return fieldInfosGen != -1; }
Returns the next available generation number of the FieldInfos files.
/** Returns the next available generation number of the FieldInfos files. */
public long getNextFieldInfosGen() { return nextWriteFieldInfosGen; }
Returns the generation number of the field infos file or -1 if there are no field updates yet.
/** * Returns the generation number of the field infos file or -1 if there are no * field updates yet. */
public long getFieldInfosGen() { return fieldInfosGen; }
Returns the next available generation number of the DocValues files.
/** Returns the next available generation number of the DocValues files. */
public long getNextDocValuesGen() { return nextWriteDocValuesGen; }
Returns the generation number of the DocValues file or -1 if there are no doc-values updates yet.
/** * Returns the generation number of the DocValues file or -1 if there are no * doc-values updates yet. */
public long getDocValuesGen() { return docValuesGen; }
Returns the next available generation number of the live docs file.
/** * Returns the next available generation number * of the live docs file. */
public long getNextDelGen() { return nextWriteDelGen; }
Returns generation number of the live docs file or -1 if there are no deletes yet.
/** * Returns generation number of the live docs file * or -1 if there are no deletes yet. */
public long getDelGen() { return delGen; }
Returns the number of deleted docs in the segment.
/** * Returns the number of deleted docs in the segment. */
public int getDelCount() { return delCount; }
Returns the number of only soft-deleted docs.
/** * Returns the number of only soft-deleted docs. */
public int getSoftDelCount() { return softDelCount; } void setDelCount(int delCount) { if (delCount < 0 || delCount > info.maxDoc()) { throw new IllegalArgumentException("invalid delCount=" + delCount + " (maxDoc=" + info.maxDoc() + ")"); } assert softDelCount + delCount <= info.maxDoc() : "maxDoc=" + info.maxDoc() + ",delCount=" + delCount + ",softDelCount=" + softDelCount; this.delCount = delCount; } void setSoftDelCount(int softDelCount) { if (softDelCount < 0 || softDelCount > info.maxDoc()) { throw new IllegalArgumentException("invalid softDelCount=" + softDelCount + " (maxDoc=" + info.maxDoc() + ")"); } assert softDelCount + delCount <= info.maxDoc() : "maxDoc=" + info.maxDoc() + ",delCount=" + delCount + ",softDelCount=" + softDelCount; this.softDelCount = softDelCount; }
Returns a description of this segment.
/** Returns a description of this segment. */
public String toString(int pendingDelCount) { String s = info.toString(delCount + pendingDelCount); if (delGen != -1) { s += ":delGen=" + delGen; } if (fieldInfosGen != -1) { s += ":fieldInfosGen=" + fieldInfosGen; } if (docValuesGen != -1) { s += ":dvGen=" + docValuesGen; } if (softDelCount > 0) { s += " :softDel=" + softDelCount; } return s; } @Override public String toString() { return toString(0); } @Override public SegmentCommitInfo clone() { SegmentCommitInfo other = new SegmentCommitInfo(info, delCount, softDelCount, delGen, fieldInfosGen, docValuesGen); // Not clear that we need to carry over nextWriteDelGen // (i.e. do we ever clone after a failed write and // before the next successful write?), but just do it to // be safe: other.nextWriteDelGen = nextWriteDelGen; other.nextWriteFieldInfosGen = nextWriteFieldInfosGen; other.nextWriteDocValuesGen = nextWriteDocValuesGen; // deep clone for (Entry<Integer,Set<String>> e : dvUpdatesFiles.entrySet()) { other.dvUpdatesFiles.put(e.getKey(), new HashSet<>(e.getValue())); } other.fieldInfosFiles.addAll(fieldInfosFiles); return other; } final int getDelCount(boolean includeSoftDeletes) { return includeSoftDeletes ? getDelCount() + getSoftDelCount() : getDelCount(); } }