From c1a76d9dbef7a0de7ada2452172fa1935037f513 Mon Sep 17 00:00:00 2001 From: Michael McCandless Date: Sat, 18 Aug 2007 09:42:21 +0000 Subject: [PATCH] LUCENE-978: ensure all streams are closed when we hit exception in constructor git-svn-id: https://svn.apache.org/repos/asf/lucene/java/trunk@567253 13f79535-47bb-0310-9956-ffa450edef68 --- CHANGES.txt | 4 ++ .../org/apache/lucene/index/FieldsReader.java | 55 +++++++++++++------ .../apache/lucene/index/TermInfosReader.java | 32 ++++++++--- .../lucene/index/TermVectorsReader.java | 50 +++++++++++------ 4 files changed, 97 insertions(+), 44 deletions(-) diff --git a/CHANGES.txt b/CHANGES.txt index 6e883e72cb0..131e43bcbf5 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -72,6 +72,10 @@ Bug fixes sharing an index over NFS and using a custom deletion policy (Mike McCandless) +11. LUCENE-978: Ensure TermInfosReader, FieldsReader, and FieldsReader + close any streams they had opened if an exception is hit in the + constructor. (Ning Li via Mike McCandless) + New features 1. LUCENE-906: Elision filter for French. diff --git a/src/java/org/apache/lucene/index/FieldsReader.java b/src/java/org/apache/lucene/index/FieldsReader.java index cd0c7e1c34f..eef6d75b823 100644 --- a/src/java/org/apache/lucene/index/FieldsReader.java +++ b/src/java/org/apache/lucene/index/FieldsReader.java @@ -66,23 +66,38 @@ final class FieldsReader { } FieldsReader(Directory d, String segment, FieldInfos fn, int readBufferSize, int docStoreOffset, int size) throws IOException { - fieldInfos = fn; + boolean success = false; - cloneableFieldsStream = d.openInput(segment + ".fdt", readBufferSize); - fieldsStream = (IndexInput)cloneableFieldsStream.clone(); - indexStream = d.openInput(segment + ".fdx", readBufferSize); + try { + fieldInfos = fn; - if (docStoreOffset != -1) { - // We read only a slice out of this shared fields file - this.docStoreOffset = docStoreOffset; - this.size = size; + cloneableFieldsStream = d.openInput(segment + ".fdt", readBufferSize); + fieldsStream = (IndexInput) cloneableFieldsStream.clone(); + indexStream = d.openInput(segment + ".fdx", readBufferSize); - // Verify the file is long enough to hold all of our - // docs - assert ((int) (indexStream.length()/8)) >= size + this.docStoreOffset; - } else { - this.docStoreOffset = 0; - this.size = (int) (indexStream.length() >> 3); + if (docStoreOffset != -1) { + // We read only a slice out of this shared fields file + this.docStoreOffset = docStoreOffset; + this.size = size; + + // Verify the file is long enough to hold all of our + // docs + assert ((int) (indexStream.length() / 8)) >= size + this.docStoreOffset; + } else { + this.docStoreOffset = 0; + this.size = (int) (indexStream.length() >> 3); + } + + success = true; + } finally { + // With lock-less commits, it's entirely possible (and + // fine) to hit a FileNotFound exception above. In + // this case, we want to explicitly close any subset + // of things that were opened so that we don't have to + // wait for a GC to do so. + if (!success) { + close(); + } } } @@ -103,9 +118,15 @@ final class FieldsReader { */ final void close() throws IOException { if (!closed) { - fieldsStream.close(); - cloneableFieldsStream.close(); - indexStream.close(); + if (fieldsStream != null) { + fieldsStream.close(); + } + if (cloneableFieldsStream != null) { + cloneableFieldsStream.close(); + } + if (indexStream != null) { + indexStream.close(); + } IndexInput localFieldsStream = (IndexInput) fieldsStreamTL.get(); if (localFieldsStream != null) { localFieldsStream.close(); diff --git a/src/java/org/apache/lucene/index/TermInfosReader.java b/src/java/org/apache/lucene/index/TermInfosReader.java index 89e2d2ef914..40283efd94d 100644 --- a/src/java/org/apache/lucene/index/TermInfosReader.java +++ b/src/java/org/apache/lucene/index/TermInfosReader.java @@ -48,17 +48,31 @@ final class TermInfosReader { TermInfosReader(Directory dir, String seg, FieldInfos fis, int readBufferSize) throws CorruptIndexException, IOException { - directory = dir; - segment = seg; - fieldInfos = fis; + boolean success = false; - origEnum = new SegmentTermEnum(directory.openInput(segment + ".tis", readBufferSize), - fieldInfos, false); - size = origEnum.size; + try { + directory = dir; + segment = seg; + fieldInfos = fis; - indexEnum = - new SegmentTermEnum(directory.openInput(segment + ".tii", readBufferSize), - fieldInfos, true); + origEnum = new SegmentTermEnum(directory.openInput(segment + ".tis", + readBufferSize), fieldInfos, false); + size = origEnum.size; + + indexEnum = new SegmentTermEnum(directory.openInput(segment + ".tii", + readBufferSize), fieldInfos, true); + + success = true; + } finally { + // With lock-less commits, it's entirely possible (and + // fine) to hit a FileNotFound exception above. In + // this case, we want to explicitly close any subset + // of things that were opened so that we don't have to + // wait for a GC to do so. + if (!success) { + close(); + } + } } public int getSkipInterval() { diff --git a/src/java/org/apache/lucene/index/TermVectorsReader.java b/src/java/org/apache/lucene/index/TermVectorsReader.java index 70a220fa27b..19f0cb64afc 100644 --- a/src/java/org/apache/lucene/index/TermVectorsReader.java +++ b/src/java/org/apache/lucene/index/TermVectorsReader.java @@ -53,26 +53,40 @@ class TermVectorsReader implements Cloneable { TermVectorsReader(Directory d, String segment, FieldInfos fieldInfos, int readBufferSize, int docStoreOffset, int size) throws CorruptIndexException, IOException { - if (d.fileExists(segment + TermVectorsWriter.TVX_EXTENSION)) { - tvx = d.openInput(segment + TermVectorsWriter.TVX_EXTENSION, readBufferSize); - checkValidFormat(tvx); - tvd = d.openInput(segment + TermVectorsWriter.TVD_EXTENSION, readBufferSize); - tvdFormat = checkValidFormat(tvd); - tvf = d.openInput(segment + TermVectorsWriter.TVF_EXTENSION, readBufferSize); - tvfFormat = checkValidFormat(tvf); - if (-1 == docStoreOffset) { - this.docStoreOffset = 0; - this.size = (int) (tvx.length() >> 3); - } else { - this.docStoreOffset = docStoreOffset; - this.size = size; - // Verify the file is long enough to hold all of our - // docs - assert ((int) (tvx.length()/8)) >= size + docStoreOffset; + boolean success = false; + + try { + if (d.fileExists(segment + TermVectorsWriter.TVX_EXTENSION)) { + tvx = d.openInput(segment + TermVectorsWriter.TVX_EXTENSION, readBufferSize); + checkValidFormat(tvx); + tvd = d.openInput(segment + TermVectorsWriter.TVD_EXTENSION, readBufferSize); + tvdFormat = checkValidFormat(tvd); + tvf = d.openInput(segment + TermVectorsWriter.TVF_EXTENSION, readBufferSize); + tvfFormat = checkValidFormat(tvf); + if (-1 == docStoreOffset) { + this.docStoreOffset = 0; + this.size = (int) (tvx.length() >> 3); + } else { + this.docStoreOffset = docStoreOffset; + this.size = size; + // Verify the file is long enough to hold all of our + // docs + assert ((int) (tvx.length() / 8)) >= size + docStoreOffset; + } + } + + this.fieldInfos = fieldInfos; + success = true; + } finally { + // With lock-less commits, it's entirely possible (and + // fine) to hit a FileNotFound exception above. In + // this case, we want to explicitly close any subset + // of things that were opened so that we don't have to + // wait for a GC to do so. + if (!success) { + close(); } } - - this.fieldInfos = fieldInfos; } private int checkValidFormat(IndexInput in) throws CorruptIndexException, IOException