Index: IndexWriter.java =================================================================== RCS file: /home/cvspublic/jakarta-lucene/src/java/org/apache/lucene/index/IndexWriter.java,v retrieving revision 1.44 diff -u -r1.44 IndexWriter.java --- IndexWriter.java 12 Dec 2004 20:26:27 -0000 1.44 +++ IndexWriter.java 18 Dec 2004 01:50:20 -0000 @@ -657,6 +657,102 @@ } } } + + /** + * Expunges the deleted documents. + * Compacts and merges all segments containing deleted documents. + * @throws IOException + */ + public final void expungeDeleted() throws IOException { + final Vector segmentsToDelete = new Vector(); + final SegmentInfos newInfos = new SegmentInfos(); + + if (infoStream != null) { + infoStream.print("Expunging deleted documents."); + } + + class DeleteItem{ + SegmentMerger merger; + String segmentName; + } + + java.util.LinkedList delItemList=new java.util.LinkedList(); + + // iterate thru all the segment infos + for (int i = 0; i < segmentInfos.size(); i++) { + SegmentInfo si = segmentInfos.info(i); + + Directory directory = si.dir; + + if (SegmentReader.hasDeletions(si)) { // found a deletion + + // make a new segment and merge itself + String newSegment = newSegmentName(); + + SegmentReader reader = SegmentReader.get(si); + SegmentMerger merger = new SegmentMerger(directory, newSegment); + merger.add(reader); + int newDocCount = merger.merge(); + merger.closeReaders(); + + DeleteItem item=new DeleteItem(); + item.merger=merger; + item.segmentName=newSegment; + delItemList.add(item); + + if ((reader.directory() == this.directory) || // if we own the + // directory + (reader.directory() == this.ramDirectory)) { + segmentsToDelete.add(reader); + } + + newInfos + .add(new SegmentInfo(newSegment, newDocCount, directory)); + } else { + newInfos.add(si); + } + } + + // rewrite the segment info if there is something changed + if (segmentsToDelete.size() > 0) { + synchronized (directory) { // in- & inter-process sync + new Lock.With(directory.makeLock(COMMIT_LOCK_NAME), + COMMIT_LOCK_TIMEOUT) { + public Object doBody() throws IOException { + newInfos.write(directory); // commit before deleting + deleteSegments(segmentsToDelete); // delete now-unused + // segments + return null; + } + }.run(); + } + } + +// do the compound file thing + if (useCompoundFile && delItemList.size()>0) { + synchronized(directory){ + java.util.Iterator iter=delItemList.iterator(); + boolean locked = false; + Lock lock = directory.makeLock(COMMIT_LOCK_NAME); + try { + locked = lock.obtain(COMMIT_LOCK_TIMEOUT); + while(iter.hasNext()){ + DeleteItem item=(DeleteItem)iter.next(); + Vector filesToDelete = item.merger + .createCompoundFile(item.segmentName + ".tmp"); +// make compound file visible for SegmentReaders + directory.renameFile(item.segmentName+ ".tmp", + item.segmentName + ".cfs"); + // delete now unused files of segment + deleteFiles(filesToDelete); + } + } finally { + if (locked) + lock.release(); + } + } + } + } /* * Some operating systems (e.g. Windows) don't permit a file to be deleted