📄 indexwriter.java
字号:
numSegments++; } } if (!exceedsUpperLimit) { // if none of the merged segments exceed upperBound, done break; } } lowerBound = upperBound; upperBound *= mergeFactor; } } /** * Merges the named range of segments, replacing them in the stack with a * single segment. */ private final int mergeSegments(SegmentInfos sourceSegments, int minSegment, int end) throws IOException { // We may be called solely because there are deletes // pending, in which case doMerge is false: boolean doMerge = end > 0; final String mergedName = newSegmentName(); SegmentMerger merger = null; final Vector segmentsToDelete = new Vector(); String segmentsInfosFileName = segmentInfos.getCurrentSegmentFileName(); String nextSegmentsFileName = segmentInfos.getNextSegmentFileName(); SegmentInfo newSegment = null; int mergedDocCount = 0; // This is try/finally to make sure merger's readers are closed: try { if (doMerge) { if (infoStream != null) infoStream.print("merging segments"); merger = new SegmentMerger(this, mergedName); for (int i = minSegment; i < end; i++) { SegmentInfo si = sourceSegments.info(i); if (infoStream != null) infoStream.print(" " + si.name + " (" + si.docCount + " docs)"); IndexReader reader = SegmentReader.get(si); // no need to set deleter (yet) merger.add(reader); if ((reader.directory() == this.directory) || // if we own the directory (reader.directory() == this.ramDirectory)) segmentsToDelete.addElement(reader); // queue segment for deletion } } SegmentInfos rollback = null; boolean success = false; // This is try/finally to rollback our internal state // if we hit exception when doing the merge: try { if (doMerge) { mergedDocCount = merger.merge(); if (infoStream != null) { infoStream.println(" into "+mergedName+" ("+mergedDocCount+" docs)"); } newSegment = new SegmentInfo(mergedName, mergedDocCount, directory, false, true); } if (!inTransaction && (sourceSegments != ramSegmentInfos || bufferedDeleteTerms.size() > 0)) { // Now save the SegmentInfo instances that // we are replacing: rollback = (SegmentInfos) segmentInfos.clone(); } if (doMerge) { if (sourceSegments == ramSegmentInfos) { segmentInfos.addElement(newSegment); } else { for (int i = end-1; i > minSegment; i--) // remove old infos & add new sourceSegments.remove(i); segmentInfos.set(minSegment, newSegment); } } if (sourceSegments == ramSegmentInfos) { // Should not be necessary: no prior commit should // have left pending files, so just defensive: deleter.clearPendingFiles(); maybeApplyDeletes(doMerge); doAfterFlush(); } if (!inTransaction) { segmentInfos.write(directory); // commit before deleting } else { commitPending = true; } success = true; } finally { if (success) { // The non-ram-segments case is already committed // (above), so all the remains for ram segments case // is to clear the ram segments: if (sourceSegments == ramSegmentInfos) { ramSegmentInfos.removeAllElements(); } } else if (!inTransaction) { // Must rollback so our state matches index: if (sourceSegments == ramSegmentInfos && 0 == bufferedDeleteTerms.size()) { // Simple case: newSegment may or may not have // been added to the end of our segment infos, // so just check & remove if so: if (newSegment != null && segmentInfos.size() > 0 && segmentInfos.info(segmentInfos.size()-1) == newSegment) { segmentInfos.remove(segmentInfos.size()-1); } } else if (rollback != null) { // Rollback the individual SegmentInfo // instances, but keep original SegmentInfos // instance (so we don't try to write again the // same segments_N file -- write once): segmentInfos.clear(); segmentInfos.addAll(rollback); } // Erase any pending files that we were going to delete: // i.e. old del files added by SegmentReader.doCommit() deleter.clearPendingFiles(); // Delete any partially created files: deleter.deleteFile(nextSegmentsFileName); deleter.findDeletableFiles(); deleter.deleteFiles(); } } } finally { // close readers before we attempt to delete now-obsolete segments if (doMerge) merger.closeReaders(); } if (!inTransaction) { // Attempt to delete all files we just obsoleted: deleter.deleteFile(segmentsInfosFileName); // delete old segments_N file deleter.deleteSegments(segmentsToDelete); // delete now-unused segments // Includes the old del files deleter.commitPendingFiles(); } else { deleter.addPendingFile(segmentsInfosFileName); // delete old segments_N file deleter.deleteSegments(segmentsToDelete, protectedSegments); // delete now-unused segments } if (useCompoundFile && doMerge) { segmentsInfosFileName = nextSegmentsFileName; nextSegmentsFileName = segmentInfos.getNextSegmentFileName(); Vector filesToDelete; boolean success = false; try { filesToDelete = merger.createCompoundFile(mergedName + ".cfs"); newSegment.setUseCompoundFile(true); if (!inTransaction) { segmentInfos.write(directory); // commit again so readers know we've switched this segment to a compound file } success = true; } finally { if (!success && !inTransaction) { // Must rollback: newSegment.setUseCompoundFile(false); deleter.deleteFile(mergedName + ".cfs"); deleter.deleteFile(nextSegmentsFileName); } } if (!inTransaction) { deleter.deleteFile(segmentsInfosFileName); // delete old segments_N file } // We can delete these segments whether or not we are // in a transaction because we had just written them // above so they can't need protection by the // transaction: deleter.deleteFiles(filesToDelete); // delete now-unused segments } return mergedDocCount; } // Called during flush to apply any buffered deletes. If // doMerge is true then a new segment was just created and // flushed from the ram segments. private final void maybeApplyDeletes(boolean doMerge) throws IOException { if (bufferedDeleteTerms.size() > 0) { if (infoStream != null) infoStream.println("flush " + numBufferedDeleteTerms + " buffered deleted terms on " + segmentInfos.size() + " segments."); if (doMerge) { IndexReader reader = null; try { reader = SegmentReader.get(segmentInfos.info(segmentInfos.size() - 1)); reader.setDeleter(deleter); // Apply delete terms to the segment just flushed from ram // apply appropriately so that a delete term is only applied to // the documents buffered before it, not those buffered after it. applyDeletesSelectively(bufferedDeleteTerms, reader); } finally { if (reader != null) reader.close(); } } int infosEnd = segmentInfos.size(); if (doMerge) { infosEnd--; } for (int i = 0; i < infosEnd; i++) { IndexReader reader = null; try { reader = SegmentReader.get(segmentInfos.info(i)); reader.setDeleter(deleter); // Apply delete terms to disk segments // except the one just flushed from ram. applyDeletes(bufferedDeleteTerms, reader); } finally { if (reader != null) reader.close(); } } // Clean up bufferedDeleteTerms. bufferedDeleteTerms.clear(); numBufferedDeleteTerms = 0; } } private final boolean checkNonDecreasingLevels(int start) { int lowerBound = -1; int upperBound = minMergeDocs; for (int i = segmentInfos.size() - 1; i >= start; i--) { int docCount = segmentInfos.info(i).docCount; if (docCount <= lowerBound) { return false; } while (docCount > upperBound) { lowerBound = upperBound; upperBound *= mergeFactor; } } return true; } // For test purposes. final synchronized int getBufferedDeleteTermsSize() { return bufferedDeleteTerms.size(); } // For test purposes. final synchronized int getNumBufferedDeleteTerms() { return numBufferedDeleteTerms; } // Number of ram segments a delete term applies to. private class Num { private int num; Num(int num) { this.num = num; } int getNum() { return num; } void setNum(int num) { this.num = num; } } // Buffer a term in bufferedDeleteTerms, which records the // current number of documents buffered in ram so that the // delete term will be applied to those ram segments as // well as the disk segments. private void bufferDeleteTerm(Term term) { Num num = (Num) bufferedDeleteTerms.get(term); if (num == null) { bufferedDeleteTerms.put(term, new Num(ramSegmentInfos.size())); } else { num.setNum(ramSegmentInfos.size()); } numBufferedDeleteTerms++; } // Apply buffered delete terms to the segment just flushed from ram // apply appropriately so that a delete term is only applied to // the documents buffered before it, not those buffered after it. private final void applyDeletesSelectively(HashMap deleteTerms, IndexReader reader) throws IOException { Iterator iter = deleteTerms.entrySet().iterator(); while (iter.hasNext()) { Entry entry = (Entry) iter.next(); Term term = (Term) entry.getKey(); TermDocs docs = reader.termDocs(term); if (docs != null) { int num = ((Num) entry.getValue()).getNum(); try { while (docs.next()) { int doc = docs.doc(); if (doc >= num) { break; } reader.deleteDocument(doc); } } finally { docs.close(); } } } } // Apply buffered delete terms to this reader. private final void applyDeletes(HashMap deleteTerms, IndexReader reader) throws IOException { Iterator iter = deleteTerms.entrySet().iterator(); while (iter.hasNext()) { Entry entry = (Entry) iter.next(); reader.deleteDocuments((Term) entry.getKey()); } }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -