file timestamp of segments file substituted by version

number in segments file


git-svn-id: https://svn.apache.org/repos/asf/lucene/java/trunk@150135 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Christoph Goller 2003-11-20 19:10:41 +00:00
parent dfaa46dd93
commit e535a52af6
5 changed files with 133 additions and 31 deletions

View File

@ -114,6 +114,7 @@ public class FilterIndexReader extends IndexReader {
public FilterIndexReader(IndexReader in) {
super(in.directory());
segmentInfos = in.segmentInfos;
this.in = in;
}

View File

@ -83,14 +83,14 @@ import org.apache.lucene.document.Field; // for javadoc
public abstract class IndexReader {
protected IndexReader(Directory directory) {
this.directory = directory;
segmentInfosAge = Long.MAX_VALUE;
stale = false;
segmentInfos = null;
}
private Directory directory;
private Lock writeLock;
//used to determine whether index has chaged since reader was opened
private long segmentInfosAge;
SegmentInfos segmentInfos = null;
private boolean stale = false;
/** Returns an IndexReader reading the index in an FSDirectory in the named
path. */
@ -111,21 +111,16 @@ public abstract class IndexReader {
directory.makeLock(IndexWriter.COMMIT_LOCK_NAME),
IndexWriter.COMMIT_LOCK_TIMEOUT) {
public Object doBody() throws IOException {
IndexReader result = null;
SegmentInfos infos = new SegmentInfos();
infos.read(directory);
if (infos.size() == 1) { // index is optimized
result = new SegmentReader(infos.info(0), true);
return new SegmentReader(infos, infos.info(0), true);
} else {
SegmentReader[] readers = new SegmentReader[infos.size()];
for (int i = 0; i < infos.size(); i++)
readers[i] = new SegmentReader(infos.info(i), i==infos.size()-1);
result = new SegmentsReader(directory, readers);
readers[i] = new SegmentReader(infos, infos.info(i), i==infos.size()-1);
return new SegmentsReader(infos, directory, readers);
}
result.segmentInfosAge = lastModified(directory);
return result;
}
}.run();
}
@ -134,20 +129,89 @@ public abstract class IndexReader {
/** Returns the directory this index resides in. */
public Directory directory() { return directory; }
/** Returns the time the index in the named directory was last modified. */
/**
* Returns the time the index in the named directory was last modified.
*
* <p>Synchronization of IndexReader and IndexWriter instances is
* no longer done via time stamps of the segments file since the time resolution
* depends on the hardware platform. Instead, a version number is maintained
* within the segments file, which is incremented everytime when the index is
* changed.</p>
*
* @deprecated Replaced by {@link #getCurrentVersion(String)}
* */
public static long lastModified(String directory) throws IOException {
return lastModified(new File(directory));
}
/** Returns the time the index in the named directory was last modified. */
/**
* Returns the time the index in the named directory was last modified.
*
* <p>Synchronization of IndexReader and IndexWriter instances is
* no longer done via time stamps of the segments file since the time resolution
* depends on the hardware platform. Instead, a version number is maintained
* within the segments file, which is incremented everytime when the index is
* changed.</p>
*
* @deprecated Replaced by {@link #getCurrentVersion(File)}
* */
public static long lastModified(File directory) throws IOException {
return FSDirectory.fileModified(directory, "segments");
}
/** Returns the time the index in this directory was last modified. */
/**
* Returns the time the index in the named directory was last modified.
*
* <p>Synchronization of IndexReader and IndexWriter instances is
* no longer done via time stamps of the segments file since the time resolution
* depends on the hardware platform. Instead, a version number is maintained
* within the segments file, which is incremented everytime when the index is
* changed.</p>
*
* @deprecated Replaced by {@link #getCurrentVersion(Directory)}
* */
public static long lastModified(Directory directory) throws IOException {
return directory.fileModified("segments");
}
/**
* Reads version number from segments files. The version number counts the
* number of changes of the index.
*
* @param directory where the index resides.
* @return version number.
* @throws IOException if segments file cannot be read
*/
public static long getCurrentVersion(String directory) throws IOException {
return getCurrentVersion(new File(directory));
}
/**
* Reads version number from segments files. The version number counts the
* number of changes of the index.
*
* @param directory where the index resides.
* @return version number.
* @throws IOException if segments file cannot be read
*/
public static long getCurrentVersion(File directory) throws IOException {
Directory dir = FSDirectory.getDirectory(directory, false);
long version = getCurrentVersion(dir);
dir.close();
return version;
}
/**
* Reads version number from segments files. The version number counts the
* number of changes of the index.
*
* @param directory where the index resides.
* @return version number.
* @throws IOException if segments file cannot be read.
*/
public static long getCurrentVersion(Directory directory) throws IOException {
return SegmentInfos.readCurrentVersion(directory);
}
/**
* Returns <code>true</code> if an index exists at the specified directory.
@ -274,6 +338,9 @@ public abstract class IndexReader {
this will be corrected eventually as the index is further modified.
*/
public final synchronized void delete(int docNum) throws IOException {
if(stale)
throw new IOException("IndexReader out of date and no longer valid for deletion");
if (writeLock == null) {
Lock writeLock = directory.makeLock(IndexWriter.WRITE_LOCK_NAME);
if (!writeLock.obtain(IndexWriter.WRITE_LOCK_TIMEOUT)) // obtain write lock
@ -282,11 +349,11 @@ public abstract class IndexReader {
// we have to check whether index has changed since this reader was opened.
// if so, this reader is no longer valid for deletion
if(lastModified(directory) > segmentInfosAge){
if(segmentInfos != null && SegmentInfos.readCurrentVersion(directory) > segmentInfos.getVersion()){
stale = true;
this.writeLock.release();
this.writeLock = null;
throw new IOException(
"IndexReader out of date and no longer valid for deletion");
throw new IOException("IndexReader out of date and no longer valid for deletion");
}
}
doDelete(docNum);

View File

@ -61,22 +61,28 @@ import org.apache.lucene.store.InputStream;
import org.apache.lucene.store.OutputStream;
final class SegmentInfos extends Vector {
public int counter = 0; // used to name new segments
public int counter = 0; // used to name new segments
private long version = 0; //counts how often the index has been changed by adding or deleting docs
public final SegmentInfo info(int i) {
return (SegmentInfo)elementAt(i);
return (SegmentInfo) elementAt(i);
}
public final void read(Directory directory) throws IOException {
InputStream input = directory.openFile("segments");
try {
counter = input.readInt(); // read counter
counter = input.readInt(); // read counter
for (int i = input.readInt(); i > 0; i--) { // read segmentInfos
SegmentInfo si = new SegmentInfo(input.readString(), input.readInt(),
directory);
SegmentInfo si =
new SegmentInfo(input.readString(), input.readInt(), directory);
addElement(si);
}
} finally {
if (input.getFilePointer() >= input.length())
version = 0; // old file format without version number
else
version = input.readLong(); // read version
}
finally {
input.close();
}
}
@ -84,18 +90,41 @@ final class SegmentInfos extends Vector {
public final void write(Directory directory) throws IOException {
OutputStream output = directory.createFile("segments.new");
try {
output.writeInt(counter); // write counter
output.writeInt(size()); // write infos
output.writeInt(counter); // write counter
output.writeInt(size()); // write infos
for (int i = 0; i < size(); i++) {
SegmentInfo si = info(i);
output.writeString(si.name);
output.writeInt(si.docCount);
}
} finally {
output.writeLong(++version); // every write changes the index
}
finally {
output.close();
}
// install new segment info
directory.renameFile("segments.new", "segments");
}
/**
* version number when this SegmentInfos was generated.
*/
public long getVersion() {
return version;
}
/**
* Current version number from segments file.
*/
public static long readCurrentVersion(Directory directory)
throws IOException {
// We cannot be sure whether the segments file is in the old format or the new one.
// Therefore we have to read the whole file and cannot simple seek to the version entry.
SegmentInfos sis = new SegmentInfos();
sis.read(directory);
return sis.getVersion();
}
}

View File

@ -98,10 +98,11 @@ final class SegmentReader extends IndexReader {
}
private Hashtable norms = new Hashtable();
SegmentReader(SegmentInfo si, boolean closeDir)
SegmentReader(SegmentInfos sis, SegmentInfo si, boolean closeDir)
throws IOException {
this(si);
closeDirectory = closeDir;
segmentInfos = sis;
}
SegmentReader(SegmentInfo si)
@ -141,7 +142,10 @@ final class SegmentReader extends IndexReader {
public Object doBody() throws IOException {
deletedDocs.write(directory(), segment + ".tmp");
directory().renameFile(segment + ".tmp", segment + ".del");
directory().touchFile("segments");
if(segmentInfos != null)
segmentInfos.write(directory());
else
directory().touchFile("segments");
return null;
}
}.run();

View File

@ -77,9 +77,10 @@ final class SegmentsReader extends IndexReader
private int maxDoc = 0;
private int numDocs = -1;
private boolean hasDeletions = false;
SegmentsReader(Directory directory, SegmentReader[] r) throws IOException {
SegmentsReader(SegmentInfos sis, Directory directory, SegmentReader[] r) throws IOException {
super(directory);
segmentInfos = sis;
readers = r;
starts = new int[readers.length + 1]; // build starts array
for (int i = 0; i < readers.length; i++) {