Return-Path: Delivered-To: apmail-jakarta-lucene-dev-archive@www.apache.org Received: (qmail 65891 invoked from network); 20 Nov 2003 19:10:47 -0000 Received: from daedalus.apache.org (HELO mail.apache.org) (208.185.179.12) by minotaur-2.apache.org with SMTP; 20 Nov 2003 19:10:47 -0000 Received: (qmail 16457 invoked by uid 500); 20 Nov 2003 19:10:34 -0000 Delivered-To: apmail-jakarta-lucene-dev-archive@jakarta.apache.org Received: (qmail 16422 invoked by uid 500); 20 Nov 2003 19:10:33 -0000 Mailing-List: contact lucene-dev-help@jakarta.apache.org; run by ezmlm Precedence: bulk List-Unsubscribe: List-Subscribe: List-Help: List-Post: List-Id: "Lucene Developers List" Reply-To: "Lucene Developers List" Delivered-To: mailing list lucene-dev@jakarta.apache.org Received: (qmail 16384 invoked by uid 500); 20 Nov 2003 19:10:33 -0000 Received: (qmail 16367 invoked from network); 20 Nov 2003 19:10:33 -0000 Received: from unknown (HELO minotaur.apache.org) (209.237.227.194) by daedalus.apache.org with SMTP; 20 Nov 2003 19:10:33 -0000 Received: (qmail 65834 invoked by uid 1754); 20 Nov 2003 19:10:41 -0000 Date: 20 Nov 2003 19:10:41 -0000 Message-ID: <20031120191041.65833.qmail@minotaur.apache.org> From: goller@apache.org To: jakarta-lucene-cvs@apache.org Subject: cvs commit: jakarta-lucene/src/java/org/apache/lucene/index SegmentsReader.java FilterIndexReader.java IndexReader.java SegmentReader.java SegmentInfos.java X-Spam-Rating: daedalus.apache.org 1.6.2 0/1000/N X-Spam-Rating: minotaur-2.apache.org 1.6.2 0/1000/N goller 2003/11/20 11:10:41 Modified: src/java/org/apache/lucene/index SegmentsReader.java FilterIndexReader.java IndexReader.java SegmentReader.java SegmentInfos.java Log: file timestamp of segments file substituted by version number in segments file Revision Changes Path 1.16 +4 -3 jakarta-lucene/src/java/org/apache/lucene/index/SegmentsReader.java Index: SegmentsReader.java =================================================================== RCS file: /home/cvs/jakarta-lucene/src/java/org/apache/lucene/index/SegmentsReader.java,v retrieving revision 1.15 retrieving revision 1.16 diff -u -r1.15 -r1.16 --- SegmentsReader.java 31 Oct 2003 09:46:54 -0000 1.15 +++ SegmentsReader.java 20 Nov 2003 19:10:41 -0000 1.16 @@ -77,9 +77,10 @@ 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++) { 1.4 +1 -0 jakarta-lucene/src/java/org/apache/lucene/index/FilterIndexReader.java Index: FilterIndexReader.java =================================================================== RCS file: /home/cvs/jakarta-lucene/src/java/org/apache/lucene/index/FilterIndexReader.java,v retrieving revision 1.3 retrieving revision 1.4 diff -u -r1.3 -r1.4 --- FilterIndexReader.java 6 Nov 2003 15:30:57 -0000 1.3 +++ FilterIndexReader.java 20 Nov 2003 19:10:41 -0000 1.4 @@ -114,6 +114,7 @@ public FilterIndexReader(IndexReader in) { super(in.directory()); + segmentInfos = in.segmentInfos; this.in = in; } 1.23 +86 -19 jakarta-lucene/src/java/org/apache/lucene/index/IndexReader.java Index: IndexReader.java =================================================================== RCS file: /home/cvs/jakarta-lucene/src/java/org/apache/lucene/index/IndexReader.java,v retrieving revision 1.22 retrieving revision 1.23 diff -u -r1.22 -r1.23 --- IndexReader.java 21 Oct 2003 18:24:23 -0000 1.22 +++ IndexReader.java 20 Nov 2003 19:10:41 -0000 1.23 @@ -83,14 +83,14 @@ 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 @@ 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 @@ /** 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. + * + *

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.

+ * + * @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. + * + *

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.

+ * + * @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. + * + *

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.

+ * + * @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 true if an index exists at the specified directory. @@ -274,6 +338,9 @@ 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 @@ // 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); 1.16 +7 -3 jakarta-lucene/src/java/org/apache/lucene/index/SegmentReader.java Index: SegmentReader.java =================================================================== RCS file: /home/cvs/jakarta-lucene/src/java/org/apache/lucene/index/SegmentReader.java,v retrieving revision 1.15 retrieving revision 1.16 diff -u -r1.15 -r1.16 --- SegmentReader.java 21 Oct 2003 18:24:23 -0000 1.15 +++ SegmentReader.java 20 Nov 2003 19:10:41 -0000 1.16 @@ -98,10 +98,11 @@ } 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 @@ 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(); 1.3 +38 -9 jakarta-lucene/src/java/org/apache/lucene/index/SegmentInfos.java Index: SegmentInfos.java =================================================================== RCS file: /home/cvs/jakarta-lucene/src/java/org/apache/lucene/index/SegmentInfos.java,v retrieving revision 1.2 retrieving revision 1.3 diff -u -r1.2 -r1.3 --- SegmentInfos.java 18 Nov 2003 11:35:57 -0000 1.2 +++ SegmentInfos.java 20 Nov 2003 19:10:41 -0000 1.3 @@ -61,22 +61,28 @@ 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 @@ 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(); } } --------------------------------------------------------------------- To unsubscribe, e-mail: lucene-dev-unsubscribe@jakarta.apache.org For additional commands, e-mail: lucene-dev-help@jakarta.apache.org