| Method from org.apache.lucene.index.SegmentInfos Detail: |
public Object clone() {
SegmentInfos sis = (SegmentInfos) super.clone();
for(int i=0;i< sis.size();i++) {
sis.set(i, sis.info(i).clone());
}
return sis;
}
Returns a copy of this instance, also copying each
SegmentInfo. |
public final void commit(Directory dir) throws IOException {
prepareCommit(dir);
finishCommit(dir);
}
Writes & syncs to the Directory dir, taking care to
remove the segments file on exception |
public final void finishCommit(Directory dir) throws IOException {
if (pendingOutput == null)
throw new IllegalStateException("prepareCommit was not called");
boolean success = false;
try {
pendingOutput.finishCommit();
pendingOutput.close();
pendingOutput = null;
success = true;
} finally {
if (!success)
rollbackCommit(dir);
}
// NOTE: if we crash here, we have left a segments_N
// file in the directory in a possibly corrupt state (if
// some bytes made it to stable storage and others
// didn't). But, the segments_N file includes checksum
// at the end, which should catch this case. So when a
// reader tries to read it, it will throw a
// CorruptIndexException, which should cause the retry
// logic in SegmentInfos to kick in and load the last
// good (previous) segments_N-1 file.
final String fileName = IndexFileNames.fileNameFromGeneration(IndexFileNames.SEGMENTS,
"",
generation);
success = false;
try {
dir.sync(fileName);
success = true;
} finally {
if (!success) {
try {
dir.deleteFile(fileName);
} catch (Throwable t) {
// Suppress so we keep throwing the original exception
}
}
}
lastGeneration = generation;
try {
IndexOutput genOutput = dir.createOutput(IndexFileNames.SEGMENTS_GEN);
try {
genOutput.writeInt(FORMAT_LOCKLESS);
genOutput.writeLong(generation);
genOutput.writeLong(generation);
} finally {
genOutput.close();
}
} catch (Throwable t) {
// It's OK if we fail to write this file since it's
// used only as one of the retry fallbacks.
}
}
|
public static long generationFromSegmentsFileName(String fileName) {
if (fileName.equals(IndexFileNames.SEGMENTS)) {
return 0;
} else if (fileName.startsWith(IndexFileNames.SEGMENTS)) {
return Long.parseLong(fileName.substring(1+IndexFileNames.SEGMENTS.length()),
Character.MAX_RADIX);
} else {
throw new IllegalArgumentException("fileName \"" + fileName + "\" is not a segments file");
}
}
Parse the generation off the segments file name and
return it. |
public String getCurrentSegmentFileName() {
return IndexFileNames.fileNameFromGeneration(IndexFileNames.SEGMENTS,
"",
lastGeneration);
}
Get the segments_N filename in use by this segment infos. |
public static String getCurrentSegmentFileName(String[] files) throws IOException {
return IndexFileNames.fileNameFromGeneration(IndexFileNames.SEGMENTS,
"",
getCurrentSegmentGeneration(files));
}
Get the filename of the current segments_N file
from a list of files. |
public static String getCurrentSegmentFileName(Directory directory) throws IOException {
return IndexFileNames.fileNameFromGeneration(IndexFileNames.SEGMENTS,
"",
getCurrentSegmentGeneration(directory));
}
Get the filename of the current segments_N file
in the directory. |
public static long getCurrentSegmentGeneration(String[] files) {
if (files == null) {
return -1;
}
long max = -1;
for (int i = 0; i < files.length; i++) {
String file = files[i];
if (file.startsWith(IndexFileNames.SEGMENTS) && !file.equals(IndexFileNames.SEGMENTS_GEN)) {
long gen = generationFromSegmentsFileName(file);
if (gen > max) {
max = gen;
}
}
}
return max;
}
Get the generation (N) of the current segments_N file
from a list of files. |
public static long getCurrentSegmentGeneration(Directory directory) throws IOException {
String[] files = directory.list();
if (files == null)
throw new IOException("cannot read directory " + directory + ": list() returned null");
return getCurrentSegmentGeneration(files);
}
Get the generation (N) of the current segments_N file
in the directory. |
public static int getDefaultGenFileRetryCount() {
return defaultGenFileRetryCount;
}
|
public static int getDefaultGenFileRetryPauseMsec() {
return defaultGenFileRetryPauseMsec;
}
|
public static int getDefaultGenLookahedCount() {
return defaultGenLookaheadCount;
}
|
public long getGeneration() {
return generation;
}
|
public static PrintStream getInfoStream() {
return infoStream;
}
|
public long getLastGeneration() {
return lastGeneration;
}
|
public String getNextSegmentFileName() {
long nextGeneration;
if (generation == -1) {
nextGeneration = 1;
} else {
nextGeneration = generation+1;
}
return IndexFileNames.fileNameFromGeneration(IndexFileNames.SEGMENTS,
"",
nextGeneration);
}
Get the next segments_N filename that will be written. |
public long getVersion() {
return version;
}
version number when this SegmentInfos was generated. |
public final SegmentInfo info(int i) {
return (SegmentInfo) get(i);
}
|
public final void prepareCommit(Directory dir) throws IOException {
if (pendingOutput != null)
throw new IllegalStateException("prepareCommit was already called");
write(dir);
}
Call this to start a commit. This writes the new
segments file, but writes an invalid checksum at the
end, so that it is not visible to readers. Once this
is called you must call #finishCommit to complete
the commit or #rollbackCommit to abort it. |
public SegmentInfos range(int first,
int last) {
SegmentInfos infos = new SegmentInfos();
infos.addAll(super.subList(first, last));
return infos;
}
Returns a new SegmentInfos containg the SegmentInfo
instances in the specified range first (inclusive) to
last (exclusive), so total number of segments returned
is last-first. |
public final void read(Directory directory) throws IOException, CorruptIndexException {
generation = lastGeneration = -1;
new FindSegmentsFile(directory) {
protected Object doBody(String segmentFileName) throws CorruptIndexException, IOException {
read(directory, segmentFileName);
return null;
}
}.run();
}
This version of read uses the retry logic (for lock-less
commits) to find the right segments file to load. |
public final void read(Directory directory,
String segmentFileName) throws IOException, CorruptIndexException {
boolean success = false;
// Clear any previous segments:
clear();
ChecksumIndexInput input = new ChecksumIndexInput(directory.openInput(segmentFileName));
generation = generationFromSegmentsFileName(segmentFileName);
lastGeneration = generation;
try {
int format = input.readInt();
if(format < 0){ // file contains explicit format info
// check that it is a format we can understand
if (format < CURRENT_FORMAT)
throw new CorruptIndexException("Unknown format version: " + format);
version = input.readLong(); // read version
counter = input.readInt(); // read counter
}
else{ // file is in old format without explicit format info
counter = format;
}
for (int i = input.readInt(); i > 0; i--) { // read segmentInfos
add(new SegmentInfo(directory, format, input));
}
if(format >= 0){ // in old format the version number may be at the end of the file
if (input.getFilePointer() >= input.length())
version = System.currentTimeMillis(); // old file format without version number
else
version = input.readLong(); // read version
}
if (format < = FORMAT_CHECKSUM) {
final long checksumNow = input.getChecksum();
final long checksumThen = input.readLong();
if (checksumNow != checksumThen)
throw new CorruptIndexException("checksum mismatch in segments file");
}
success = true;
}
finally {
input.close();
if (!success) {
// Clear any segment infos we had loaded so we
// have a clean slate on retry:
clear();
}
}
}
Read a particular segmentFileName. Note that this may
throw an IOException if a commit is in process. |
public static long readCurrentVersion(Directory directory) throws IOException, CorruptIndexException {
return ((Long) new FindSegmentsFile(directory) {
protected Object doBody(String segmentFileName) throws CorruptIndexException, IOException {
IndexInput input = directory.openInput(segmentFileName);
int format = 0;
long version = 0;
try {
format = input.readInt();
if(format < 0){
if (format < CURRENT_FORMAT)
throw new CorruptIndexException("Unknown format version: " + format);
version = input.readLong(); // read version
}
}
finally {
input.close();
}
if(format < 0)
return new Long(version);
// We cannot be sure about the format of the file.
// Therefore we have to read the whole file and cannot simply seek to the version entry.
SegmentInfos sis = new SegmentInfos();
sis.read(directory, segmentFileName);
return new Long(sis.getVersion());
}
}.run()).longValue();
}
Current version number from segments file. |
public final void rollbackCommit(Directory dir) throws IOException {
if (pendingOutput != null) {
try {
pendingOutput.close();
} catch (Throwable t) {
// Suppress so we keep throwing the original exception
// in our caller
}
// Must carefully compute fileName from "generation"
// since lastGeneration isn't incremented:
try {
final String segmentFileName = IndexFileNames.fileNameFromGeneration(IndexFileNames.SEGMENTS,
"",
generation);
dir.deleteFile(segmentFileName);
} catch (Throwable t) {
// Suppress so we keep throwing the original exception
// in our caller
}
pendingOutput = null;
}
}
|
synchronized String segString(Directory directory) {
StringBuffer buffer = new StringBuffer();
final int count = size();
for(int i = 0; i < count; i++) {
if (i > 0) {
buffer.append(' ");
}
final SegmentInfo info = info(i);
buffer.append(info.segString(directory));
if (info.dir != directory)
buffer.append("**");
}
return buffer.toString();
}
|
public static void setDefaultGenFileRetryCount(int count) {
defaultGenFileRetryCount = count;
}
Advanced: set how many times to try loading the
segments.gen file contents to determine current segment
generation. This file is only referenced when the
primary method (listing the directory) fails. |
public static void setDefaultGenFileRetryPauseMsec(int msec) {
defaultGenFileRetryPauseMsec = msec;
}
Advanced: set how many milliseconds to pause in between
attempts to load the segments.gen file. |
public static void setDefaultGenLookaheadCount(int count) {
defaultGenLookaheadCount = count;
}
Advanced: set how many times to try incrementing the
gen when loading the segments file. This only runs if
the primary (listing directory) and secondary (opening
segments.gen file) methods fail to find the segments
file. |
public static void setInfoStream(PrintStream infoStream) {
SegmentInfos.infoStream = infoStream;
}
If non-null, information about retries when loading
the segments file will be printed to this. |
void updateGeneration(SegmentInfos other) {
lastGeneration = other.lastGeneration;
generation = other.generation;
version = other.version;
}
|