Index: lucene/contrib/misc/src/java/org/apache/lucene/store/NRTCachingDirectory.java --- lucene/contrib/misc/src/java/org/apache/lucene/store/NRTCachingDirectory.java Sat May 28 08:38:45 2011 -0400 +++ lucene/contrib/misc/src/java/org/apache/lucene/store/NRTCachingDirectory.java Sat May 28 13:46:56 2011 -0400 @@ -269,7 +269,7 @@ in = cache.openInput(fileName); in.copyBytes(out, in.length()); } finally { - IOUtils.closeSafely(in, out); + IOUtils.closeSafely(false, in, out); } synchronized(this) { cache.deleteFile(fileName); Index: lucene/src/java/org/apache/lucene/index/CompoundFileWriter.java --- lucene/src/java/org/apache/lucene/index/CompoundFileWriter.java Sat May 28 08:38:45 2011 -0400 +++ lucene/src/java/org/apache/lucene/index/CompoundFileWriter.java Sat May 28 13:46:56 2011 -0400 @@ -219,7 +219,7 @@ } catch (IOException e) { priorException = e; } finally { - IOUtils.closeSafely(priorException, os); + IOUtils.closeSafelyPriorEx(priorException, os); } } Index: lucene/src/java/org/apache/lucene/index/DocFieldProcessor.java --- lucene/src/java/org/apache/lucene/index/DocFieldProcessor.java Sat May 28 08:38:45 2011 -0400 +++ lucene/src/java/org/apache/lucene/index/DocFieldProcessor.java Sat May 28 13:46:56 2011 -0400 @@ -71,7 +71,15 @@ childFields.put(f.getFieldInfo(), f); } - fieldsWriter.flush(state); + boolean success = false; + try { + fieldsWriter.flush(state); + success = true; + } finally { + if (!success) { + abort(); + } + } consumer.flush(childFields, state); // Important to save after asking consumer to flush so @@ -84,19 +92,44 @@ @Override public void abort() { - for(int i=0;i it = consumers.iterator(); - IOException err = null; + Throwable th = null; while (it.hasNext()) { try { it.next().close(); - } catch (IOException ioe) { - // keep first IOException we hit but keep - // closing the rest - if (err == null) { - err = ioe; + } catch (Throwable t) { + // keep first error we hit but keep closing the rest + if (th == null) { + th = t; } } } - if (err != null) { - throw err; + + if (th != null) { + if (th instanceof IOException) throw (IOException) th; + if (th instanceof RuntimeException) throw (RuntimeException) th; + if (th instanceof Error) throw (Error) th; + throw new RuntimeException(th); } } } @@ -177,21 +196,24 @@ @Override public void close() throws IOException { + // TODO: use IOUtils.closeSafely Iterator it = codecs.values().iterator(); - IOException err = null; + Throwable th = null; while (it.hasNext()) { try { it.next().close(); - } catch (IOException ioe) { - // keep first IOException we hit but keep - // closing the rest - if (err == null) { - err = ioe; + } catch (Throwable t) { + // keep first error we hit but keep closing the rest + if (th == null) { + th = t; } } } - if (err != null) { - throw err; + if (th != null) { + if (th instanceof IOException) throw (IOException) th; + if (th instanceof RuntimeException) throw (RuntimeException) th; + if (th instanceof Error) throw (Error) th; + throw new RuntimeException(th); } } Index: lucene/src/java/org/apache/lucene/index/SegmentInfos.java --- lucene/src/java/org/apache/lucene/index/SegmentInfos.java Sat May 28 08:38:45 2011 -0400 +++ lucene/src/java/org/apache/lucene/index/SegmentInfos.java Sat May 28 13:46:56 2011 -0400 @@ -40,6 +40,7 @@ import org.apache.lucene.store.IndexInput; import org.apache.lucene.store.IndexOutput; import org.apache.lucene.store.NoSuchDirectoryException; +import org.apache.lucene.util.IOUtils; import org.apache.lucene.util.ThreadInterruptedException; /** @@ -323,17 +324,13 @@ SegmentInfosWriter infosWriter = codecs.getSegmentInfosWriter(); segnOutput = infosWriter.writeInfos(directory, segmentFileName, this); infosWriter.prepareCommit(segnOutput); + pendingSegnOutput = segnOutput; success = true; - pendingSegnOutput = segnOutput; } finally { if (!success) { // We hit an exception above; try to close the file // but suppress any exception: - try { - segnOutput.close(); - } catch (Throwable t) { - // Suppress so we keep throwing the original exception - } + IOUtils.closeSafely(true, segnOutput); try { // Try not to leave a truncated segments_N file in // the index: @@ -945,9 +942,12 @@ } finally { genOutput.close(); } + } catch (ThreadInterruptedException t) { + throw t; } catch (Throwable t) { // It's OK if we fail to write this file since it's // used only as one of the retry fallbacks. + // nocommit if this is thread interrupted we should rethrow } } Index: lucene/src/java/org/apache/lucene/index/SegmentMerger.java --- lucene/src/java/org/apache/lucene/index/SegmentMerger.java Sat May 28 08:38:45 2011 -0400 +++ lucene/src/java/org/apache/lucene/index/SegmentMerger.java Sat May 28 13:46:56 2011 -0400 @@ -34,6 +34,7 @@ import org.apache.lucene.store.IndexInput; import org.apache.lucene.store.IndexOutput; import org.apache.lucene.util.Bits; +import org.apache.lucene.util.IOUtils; import org.apache.lucene.util.MultiBits; import org.apache.lucene.util.ReaderUtil; @@ -546,14 +547,13 @@ } codec = segmentWriteState.segmentCodecs.codec(); final FieldsConsumer consumer = codec.fieldsConsumer(segmentWriteState); - - // NOTE: this is silly, yet, necessary -- we create a - // MultiBits as our skip docs only to have it broken - // apart when we step through the docs enums in - // MultiDocsEnum. - mergeState.multiDeletedDocs = new MultiBits(bits, bitsStarts); - try { + // NOTE: this is silly, yet, necessary -- we create a + // MultiBits as our skip docs only to have it broken + // apart when we step through the docs enums in + // MultiDocsEnum. + mergeState.multiDeletedDocs = new MultiBits(bits, bitsStarts); + consumer.merge(mergeState, new MultiFields(fields.toArray(Fields.EMPTY_ARRAY), slices.toArray(ReaderUtil.Slice.EMPTY_ARRAY))); @@ -579,6 +579,7 @@ private void mergeNorms() throws IOException { IndexOutput output = null; + boolean success = false; try { for (FieldInfo fi : fieldInfos) { if (fi.isIndexed && !fi.omitNorms) { @@ -612,10 +613,9 @@ } } } + success = true; } finally { - if (output != null) { - output.close(); - } + IOUtils.closeSafely(!success, output); } } } Index: lucene/src/java/org/apache/lucene/index/TermVectorsTermsWriter.java --- lucene/src/java/org/apache/lucene/index/TermVectorsTermsWriter.java Sat May 28 08:38:45 2011 -0400 +++ lucene/src/java/org/apache/lucene/index/TermVectorsTermsWriter.java Sat May 28 13:46:56 2011 -0400 @@ -54,9 +54,7 @@ fill(state.numDocs); assert state.segmentName != null; String idxName = IndexFileNames.segmentFileName(state.segmentName, "", IndexFileNames.VECTORS_INDEX_EXTENSION); - tvx.close(); - tvf.close(); - tvd.close(); + IOUtils.closeSafely(false, tvx, tvf, tvd); tvx = tvd = tvf = null; if (4+((long) state.numDocs)*16 != state.directory.fileLength(idxName)) { throw new RuntimeException("after flush: tvx size mismatch: " + state.numDocs + " docs vs " + state.directory.fileLength(idxName) + " length in bytes of " + idxName + " file exists?=" + state.directory.fileExists(idxName)); @@ -89,18 +87,25 @@ private final void initTermVectorsWriter() throws IOException { if (tvx == null) { + boolean success = false; + try { + // If we hit an exception while init'ing the term + // vector output files, we must abort this segment + // because those files will be in an unknown + // state: + tvx = docWriter.directory.createOutput(IndexFileNames.segmentFileName(docWriter.getSegment(), "", IndexFileNames.VECTORS_INDEX_EXTENSION)); + tvd = docWriter.directory.createOutput(IndexFileNames.segmentFileName(docWriter.getSegment(), "", IndexFileNames.VECTORS_DOCUMENTS_EXTENSION)); + tvf = docWriter.directory.createOutput(IndexFileNames.segmentFileName(docWriter.getSegment(), "", IndexFileNames.VECTORS_FIELDS_EXTENSION)); - // If we hit an exception while init'ing the term - // vector output files, we must abort this segment - // because those files will be in an unknown - // state: - tvx = docWriter.directory.createOutput(IndexFileNames.segmentFileName(docWriter.getSegment(), "", IndexFileNames.VECTORS_INDEX_EXTENSION)); - tvd = docWriter.directory.createOutput(IndexFileNames.segmentFileName(docWriter.getSegment(), "", IndexFileNames.VECTORS_DOCUMENTS_EXTENSION)); - tvf = docWriter.directory.createOutput(IndexFileNames.segmentFileName(docWriter.getSegment(), "", IndexFileNames.VECTORS_FIELDS_EXTENSION)); - - tvx.writeInt(TermVectorsReader.FORMAT_CURRENT); - tvd.writeInt(TermVectorsReader.FORMAT_CURRENT); - tvf.writeInt(TermVectorsReader.FORMAT_CURRENT); + tvx.writeInt(TermVectorsReader.FORMAT_CURRENT); + tvd.writeInt(TermVectorsReader.FORMAT_CURRENT); + tvf.writeInt(TermVectorsReader.FORMAT_CURRENT); + success = true; + } finally { + if (!success) { + IOUtils.closeSafely(true, tvx, tvd, tvf); + } + } lastDocID = 0; } @@ -152,21 +157,26 @@ public void abort() { hasVectors = false; try { - IOUtils.closeSafely(tvx, tvd, tvf); - } catch (IOException ignored) { + IOUtils.closeSafely(true, tvx, tvd, tvf); + } catch (IOException e) { + // cannot happen since we suppress exceptions } + try { docWriter.directory.deleteFile(IndexFileNames.segmentFileName(docWriter.getSegment(), "", IndexFileNames.VECTORS_INDEX_EXTENSION)); } catch (IOException ignored) { } + try { docWriter.directory.deleteFile(IndexFileNames.segmentFileName(docWriter.getSegment(), "", IndexFileNames.VECTORS_DOCUMENTS_EXTENSION)); } catch (IOException ignored) { } + try { docWriter.directory.deleteFile(IndexFileNames.segmentFileName(docWriter.getSegment(), "", IndexFileNames.VECTORS_FIELDS_EXTENSION)); } catch (IOException ignored) { } + tvx = tvd = tvf = null; lastDocID = 0; Index: lucene/src/java/org/apache/lucene/index/TermVectorsWriter.java --- lucene/src/java/org/apache/lucene/index/TermVectorsWriter.java Sat May 28 08:38:45 2011 -0400 +++ lucene/src/java/org/apache/lucene/index/TermVectorsWriter.java Sat May 28 13:46:56 2011 -0400 @@ -31,15 +31,22 @@ private FieldInfos fieldInfos; public TermVectorsWriter(Directory directory, String segment, - FieldInfos fieldInfos) - throws IOException { - // Open files for TermVector storage - tvx = directory.createOutput(IndexFileNames.segmentFileName(segment, "", IndexFileNames.VECTORS_INDEX_EXTENSION)); - tvx.writeInt(TermVectorsReader.FORMAT_CURRENT); - tvd = directory.createOutput(IndexFileNames.segmentFileName(segment, "", IndexFileNames.VECTORS_DOCUMENTS_EXTENSION)); - tvd.writeInt(TermVectorsReader.FORMAT_CURRENT); - tvf = directory.createOutput(IndexFileNames.segmentFileName(segment, "", IndexFileNames.VECTORS_FIELDS_EXTENSION)); - tvf.writeInt(TermVectorsReader.FORMAT_CURRENT); + FieldInfos fieldInfos) throws IOException { + boolean success = false; + try { + // Open files for TermVector storage + tvx = directory.createOutput(IndexFileNames.segmentFileName(segment, "", IndexFileNames.VECTORS_INDEX_EXTENSION)); + tvx.writeInt(TermVectorsReader.FORMAT_CURRENT); + tvd = directory.createOutput(IndexFileNames.segmentFileName(segment, "", IndexFileNames.VECTORS_DOCUMENTS_EXTENSION)); + tvd.writeInt(TermVectorsReader.FORMAT_CURRENT); + tvf = directory.createOutput(IndexFileNames.segmentFileName(segment, "", IndexFileNames.VECTORS_FIELDS_EXTENSION)); + tvf.writeInt(TermVectorsReader.FORMAT_CURRENT); + success = true; + } finally { + if (!success) { + IOUtils.closeSafely(true, tvx, tvd, tvf); + } + } this.fieldInfos = fieldInfos; } @@ -51,8 +58,7 @@ * @param vectors * @throws IOException */ - public final void addAllDocVectors(TermFreqVector[] vectors) - throws IOException { + public final void addAllDocVectors(TermFreqVector[] vectors) throws IOException { tvx.writeLong(tvd.getFilePointer()); tvx.writeLong(tvf.getFilePointer()); @@ -187,6 +193,6 @@ final void close() throws IOException { // make an effort to close all streams we can but remember and re-throw // the first exception encountered in this process - IOUtils.closeSafely(tvx, tvd, tvf); + IOUtils.closeSafely(false, tvx, tvd, tvf); } } Index: lucene/src/java/org/apache/lucene/index/TermsHash.java --- lucene/src/java/org/apache/lucene/index/TermsHash.java Sat May 28 08:38:45 2011 -0400 +++ lucene/src/java/org/apache/lucene/index/TermsHash.java Sat May 28 13:46:56 2011 -0400 @@ -54,7 +54,6 @@ final boolean trackAllocations; - public TermsHash(final DocumentsWriterPerThread docWriter, final TermsHashConsumer consumer, boolean trackAllocations, final TermsHash nextTermsHash) { this.docState = docWriter.docState; this.docWriter = docWriter; @@ -108,11 +107,11 @@ } for (final Map.Entry entry : fieldsToFlush.entrySet()) { - TermsHashPerField perField = (TermsHashPerField) entry.getValue(); - childFields.put(entry.getKey(), perField.consumer); - if (nextTermsHash != null) { - nextChildFields.put(entry.getKey(), perField.nextPerField); - } + TermsHashPerField perField = (TermsHashPerField) entry.getValue(); + childFields.put(entry.getKey(), perField.consumer); + if (nextTermsHash != null) { + nextChildFields.put(entry.getKey(), perField.nextPerField); + } } consumer.flush(childFields, state); @@ -134,12 +133,9 @@ @Override void finishDocument() throws IOException { - try { - consumer.finishDocument(this); - } finally { - if (nextTermsHash != null) { - nextTermsHash.consumer.finishDocument(nextTermsHash); - } + consumer.finishDocument(this); + if (nextTermsHash != null) { + nextTermsHash.consumer.finishDocument(nextTermsHash); } } Index: lucene/src/java/org/apache/lucene/index/codecs/BlockTermsWriter.java --- lucene/src/java/org/apache/lucene/index/codecs/BlockTermsWriter.java Sat May 28 08:38:45 2011 -0400 +++ lucene/src/java/org/apache/lucene/index/codecs/BlockTermsWriter.java Sat May 28 13:46:56 2011 -0400 @@ -31,6 +31,7 @@ import org.apache.lucene.util.ArrayUtil; import org.apache.lucene.util.BytesRef; import org.apache.lucene.util.CodecUtil; +import org.apache.lucene.util.IOUtils; import org.apache.lucene.util.RamUsageEstimator; // TODO: currently we encode all terms between two indexed @@ -66,24 +67,29 @@ //private final String segment; - public BlockTermsWriter( - TermsIndexWriterBase termsIndexWriter, - SegmentWriteState state, - PostingsWriterBase postingsWriter) - throws IOException - { + public BlockTermsWriter(TermsIndexWriterBase termsIndexWriter, + SegmentWriteState state, PostingsWriterBase postingsWriter) + throws IOException { final String termsFileName = IndexFileNames.segmentFileName(state.segmentName, state.codecId, TERMS_EXTENSION); this.termsIndexWriter = termsIndexWriter; out = state.directory.createOutput(termsFileName); - fieldInfos = state.fieldInfos; - writeHeader(out); - currentField = null; - this.postingsWriter = postingsWriter; - //segment = state.segmentName; - - //System.out.println("BTW.init seg=" + state.segmentName); - - postingsWriter.start(out); // have consumer write its format/header + boolean success = false; + try { + fieldInfos = state.fieldInfos; + writeHeader(out); + currentField = null; + this.postingsWriter = postingsWriter; + //segment = state.segmentName; + + //System.out.println("BTW.init seg=" + state.segmentName); + + postingsWriter.start(out); // have consumer write its format/header + success = true; + } finally { + if (!success) { + IOUtils.closeSafely(true, out); + } + } } protected void writeHeader(IndexOutput out) throws IOException { @@ -130,20 +136,11 @@ } writeTrailer(dirStart); } finally { - try { - out.close(); - } finally { - try { - postingsWriter.close(); - } finally { - termsIndexWriter.close(); - } - } + IOUtils.closeSafely(false, out, postingsWriter, termsIndexWriter); } } protected void writeTrailer(long dirStart) throws IOException { - // TODO Auto-generated method stub out.seek(CodecUtil.headerLength(CODEC_NAME)); out.writeLong(dirStart); } Index: lucene/src/java/org/apache/lucene/index/codecs/DefaultSegmentInfosWriter.java --- lucene/src/java/org/apache/lucene/index/codecs/DefaultSegmentInfosWriter.java Sat May 28 08:38:45 2011 -0400 +++ lucene/src/java/org/apache/lucene/index/codecs/DefaultSegmentInfosWriter.java Sat May 28 13:46:56 2011 -0400 @@ -24,6 +24,7 @@ import org.apache.lucene.store.ChecksumIndexOutput; import org.apache.lucene.store.Directory; import org.apache.lucene.store.IndexOutput; +import org.apache.lucene.util.IOUtils; /** * Default implementation of {@link SegmentInfosWriter}. @@ -56,16 +57,24 @@ public IndexOutput writeInfos(Directory dir, String segmentFileName, SegmentInfos infos) throws IOException { IndexOutput out = createOutput(dir, segmentFileName); - out.writeInt(FORMAT_CURRENT); // write FORMAT - out.writeLong(infos.version); - out.writeInt(infos.counter); // write counter - out.writeLong(infos.getGlobalFieldMapVersion()); - out.writeInt(infos.size()); // write infos - for (SegmentInfo si : infos) { - si.write(out); + boolean success = false; + try { + out.writeInt(FORMAT_CURRENT); // write FORMAT + out.writeLong(infos.version); + out.writeInt(infos.counter); // write counter + out.writeLong(infos.getGlobalFieldMapVersion()); + out.writeInt(infos.size()); // write infos + for (SegmentInfo si : infos) { + si.write(out); + } + out.writeStringStringMap(infos.getUserData()); + success = true; + return out; + } finally { + if (!success) { + IOUtils.closeSafely(true, out); + } } - out.writeStringStringMap(infos.getUserData()); - return out; } protected IndexOutput createOutput(Directory dir, String segmentFileName) Index: lucene/src/java/org/apache/lucene/index/codecs/FixedGapTermsIndexReader.java --- lucene/src/java/org/apache/lucene/index/codecs/FixedGapTermsIndexReader.java Sat May 28 08:38:45 2011 -0400 +++ lucene/src/java/org/apache/lucene/index/codecs/FixedGapTermsIndexReader.java Sat May 28 13:46:56 2011 -0400 @@ -24,6 +24,7 @@ import org.apache.lucene.index.SegmentInfo; import org.apache.lucene.util.BytesRef; import org.apache.lucene.util.CodecUtil; +import org.apache.lucene.util.IOUtils; import org.apache.lucene.util.PagedBytes; import org.apache.lucene.util.packed.PackedInts; @@ -108,6 +109,7 @@ } success = true; } finally { + if (!success) IOUtils.closeSafely(true, in); if (indexDivisor > 0) { in.close(); in = null; Index: lucene/src/java/org/apache/lucene/index/codecs/FixedGapTermsIndexWriter.java --- lucene/src/java/org/apache/lucene/index/codecs/FixedGapTermsIndexWriter.java Sat May 28 08:38:45 2011 -0400 +++ lucene/src/java/org/apache/lucene/index/codecs/FixedGapTermsIndexWriter.java Sat May 28 13:46:56 2011 -0400 @@ -25,6 +25,7 @@ import org.apache.lucene.util.BytesRef; import org.apache.lucene.util.CodecUtil; import org.apache.lucene.util.ArrayUtil; +import org.apache.lucene.util.IOUtils; import org.apache.lucene.util.packed.PackedInts; import java.util.List; @@ -58,9 +59,17 @@ final String indexFileName = IndexFileNames.segmentFileName(state.segmentName, state.codecId, TERMS_INDEX_EXTENSION); termIndexInterval = state.termIndexInterval; out = state.directory.createOutput(indexFileName); - fieldInfos = state.fieldInfos; - writeHeader(out); - out.writeInt(termIndexInterval); + boolean success = false; + try { + fieldInfos = state.fieldInfos; + writeHeader(out); + out.writeInt(termIndexInterval); + success = true; + } finally { + if (!success) { + IOUtils.closeSafely(true, out); + } + } } protected void writeHeader(IndexOutput out) throws IOException { @@ -204,31 +213,36 @@ @Override public void close() throws IOException { - final long dirStart = out.getFilePointer(); - final int fieldCount = fields.size(); - - int nonNullFieldCount = 0; - for(int i=0;i 0) { - nonNullFieldCount++; + boolean success = false; + try { + final long dirStart = out.getFilePointer(); + final int fieldCount = fields.size(); + + int nonNullFieldCount = 0; + for(int i=0;i 0) { + nonNullFieldCount++; + } } + + out.writeVInt(nonNullFieldCount); + for(int i=0;i 0) { + out.writeVInt(field.fieldInfo.number); + out.writeVInt(field.numIndexTerms); + out.writeVLong(field.termsStart); + out.writeVLong(field.indexStart); + out.writeVLong(field.packedIndexStart); + out.writeVLong(field.packedOffsetsStart); + } + } + writeTrailer(dirStart); + success = true; + } finally { + IOUtils.closeSafely(!success, out); } - - out.writeVInt(nonNullFieldCount); - for(int i=0;i 0) { - out.writeVInt(field.fieldInfo.number); - out.writeVInt(field.numIndexTerms); - out.writeVLong(field.termsStart); - out.writeVLong(field.indexStart); - out.writeVLong(field.packedIndexStart); - out.writeVLong(field.packedOffsetsStart); - } - } - writeTrailer(dirStart); - out.close(); } protected void writeTrailer(long dirStart) throws IOException { Index: lucene/src/java/org/apache/lucene/index/codecs/TermsIndexWriterBase.java --- lucene/src/java/org/apache/lucene/index/codecs/TermsIndexWriterBase.java Sat May 28 08:38:45 2011 -0400 +++ lucene/src/java/org/apache/lucene/index/codecs/TermsIndexWriterBase.java Sat May 28 13:46:56 2011 -0400 @@ -19,10 +19,12 @@ import org.apache.lucene.index.FieldInfo; import org.apache.lucene.util.BytesRef; + +import java.io.Closeable; import java.io.IOException; /** @lucene.experimental */ -public abstract class TermsIndexWriterBase { +public abstract class TermsIndexWriterBase implements Closeable { public abstract class FieldWriter { public abstract boolean checkIndexTerm(BytesRef text, TermStats stats) throws IOException; @@ -31,6 +33,4 @@ } public abstract FieldWriter addField(FieldInfo fieldInfo, long termsFilePointer) throws IOException; - - public abstract void close() throws IOException; } Index: lucene/src/java/org/apache/lucene/index/codecs/VariableGapTermsIndexWriter.java --- lucene/src/java/org/apache/lucene/index/codecs/VariableGapTermsIndexWriter.java Sat May 28 08:38:45 2011 -0400 +++ lucene/src/java/org/apache/lucene/index/codecs/VariableGapTermsIndexWriter.java Sat May 28 13:46:56 2011 -0400 @@ -28,6 +28,7 @@ import org.apache.lucene.store.IndexOutput; import org.apache.lucene.util.BytesRef; import org.apache.lucene.util.CodecUtil; +import org.apache.lucene.util.IOUtils; import org.apache.lucene.util.automaton.fst.Builder; import org.apache.lucene.util.automaton.fst.FST; import org.apache.lucene.util.automaton.fst.PositiveIntOutputs; @@ -159,9 +160,17 @@ public VariableGapTermsIndexWriter(SegmentWriteState state, IndexTermSelector policy) throws IOException { final String indexFileName = IndexFileNames.segmentFileName(state.segmentName, state.codecId, TERMS_INDEX_EXTENSION); out = state.directory.createOutput(indexFileName); - fieldInfos = state.fieldInfos; - this.policy = policy; - writeHeader(out); + boolean success = false; + try { + fieldInfos = state.fieldInfos; + this.policy = policy; + writeHeader(out); + success = true; + } finally { + if (!success) { + IOUtils.closeSafely(true, out); + } + } } protected void writeHeader(IndexOutput out) throws IOException { @@ -267,6 +276,7 @@ @Override public void close() throws IOException { + try { final long dirStart = out.getFilePointer(); final int fieldCount = fields.size(); @@ -287,8 +297,10 @@ } } writeTrailer(dirStart); + } finally { out.close(); } + } protected void writeTrailer(long dirStart) throws IOException { out.seek(CodecUtil.headerLength(CODEC_NAME)); Index: lucene/src/java/org/apache/lucene/index/codecs/pulsing/PulsingCodec.java --- lucene/src/java/org/apache/lucene/index/codecs/pulsing/PulsingCodec.java Sat May 28 08:38:45 2011 -0400 +++ lucene/src/java/org/apache/lucene/index/codecs/pulsing/PulsingCodec.java Sat May 28 13:46:56 2011 -0400 @@ -38,6 +38,7 @@ import org.apache.lucene.index.codecs.TermsIndexWriterBase; import org.apache.lucene.index.codecs.standard.StandardCodec; import org.apache.lucene.store.Directory; +import org.apache.lucene.util.IOUtils; /** This codec "inlines" the postings for terms that have * low docFreq. It wraps another codec, which is used for @@ -81,7 +82,7 @@ success = true; } finally { if (!success) { - pulsingWriter.close(); + IOUtils.closeSafely(true, pulsingWriter); } } @@ -93,11 +94,7 @@ return ret; } finally { if (!success) { - try { - pulsingWriter.close(); - } finally { - indexWriter.close(); - } + IOUtils.closeSafely(true, pulsingWriter, indexWriter); } } } Index: lucene/src/java/org/apache/lucene/index/codecs/pulsing/PulsingPostingsWriterImpl.java --- lucene/src/java/org/apache/lucene/index/codecs/pulsing/PulsingPostingsWriterImpl.java Sat May 28 08:38:45 2011 -0400 +++ lucene/src/java/org/apache/lucene/index/codecs/pulsing/PulsingPostingsWriterImpl.java Sat May 28 13:46:56 2011 -0400 @@ -71,8 +71,6 @@ * for this term) is <= maxPositions, then the postings are * inlined into terms dict */ public PulsingPostingsWriterImpl(int maxPositions, PostingsWriterBase wrappedPostingsWriter) throws IOException { - super(); - pending = new Position[maxPositions]; for(int i=0;i extensions) { Index: lucene/src/java/org/apache/lucene/index/codecs/simpletext/SimpleTextFieldsWriter.java --- lucene/src/java/org/apache/lucene/index/codecs/simpletext/SimpleTextFieldsWriter.java Sat May 28 08:38:45 2011 -0400 +++ lucene/src/java/org/apache/lucene/index/codecs/simpletext/SimpleTextFieldsWriter.java Sat May 28 13:46:56 2011 -0400 @@ -143,8 +143,11 @@ @Override public void close() throws IOException { - write(END); - newline(); - out.close(); + try { + write(END); + newline(); + } finally { + out.close(); + } } } Index: lucene/src/java/org/apache/lucene/index/codecs/standard/StandardPostingsWriter.java --- lucene/src/java/org/apache/lucene/index/codecs/standard/StandardPostingsWriter.java Sat May 28 08:38:45 2011 -0400 +++ lucene/src/java/org/apache/lucene/index/codecs/standard/StandardPostingsWriter.java Sat May 28 13:46:56 2011 -0400 @@ -33,6 +33,7 @@ import org.apache.lucene.store.RAMOutputStream; import org.apache.lucene.util.BytesRef; import org.apache.lucene.util.CodecUtil; +import org.apache.lucene.util.IOUtils; /** @lucene.experimental */ public final class StandardPostingsWriter extends PostingsWriterBase { @@ -42,8 +43,8 @@ final static int VERSION_START = 0; final static int VERSION_CURRENT = VERSION_START; - final IndexOutput freqOut; - final IndexOutput proxOut; + IndexOutput freqOut; + IndexOutput proxOut; final DefaultSkipListWriter skipListWriter; /** Expert: The fraction of TermDocs entries stored in skip tables, * used to accelerate {@link DocsEnum#advance(int)}. Larger values result in @@ -85,31 +86,35 @@ public StandardPostingsWriter(SegmentWriteState state) throws IOException { this(state, DEFAULT_SKIP_INTERVAL); } + public StandardPostingsWriter(SegmentWriteState state, int skipInterval) throws IOException { - super(); this.skipInterval = skipInterval; this.skipMinimum = skipInterval; /* set to the same for now */ //this.segment = state.segmentName; String fileName = IndexFileNames.segmentFileName(state.segmentName, state.codecId, StandardCodec.FREQ_EXTENSION); freqOut = state.directory.createOutput(fileName); - - if (state.fieldInfos.hasProx()) { - // At least one field does not omit TF, so create the - // prox file - fileName = IndexFileNames.segmentFileName(state.segmentName, state.codecId, StandardCodec.PROX_EXTENSION); - proxOut = state.directory.createOutput(fileName); - } else { - // Every field omits TF so we will write no prox file - proxOut = null; + boolean success = false; + try { + if (state.fieldInfos.hasProx()) { + // At least one field does not omit TF, so create the + // prox file + fileName = IndexFileNames.segmentFileName(state.segmentName, state.codecId, StandardCodec.PROX_EXTENSION); + proxOut = state.directory.createOutput(fileName); + } else { + // Every field omits TF so we will write no prox file + proxOut = null; + } + + totalNumDocs = state.numDocs; + + skipListWriter = new DefaultSkipListWriter(skipInterval, maxSkipLevels, + state.numDocs, freqOut, proxOut); + success = true; + } finally { + if (!success) { + IOUtils.closeSafely(true, freqOut, proxOut); + } } - - totalNumDocs = state.numDocs; - - skipListWriter = new DefaultSkipListWriter(skipInterval, - maxSkipLevels, - state.numDocs, - freqOut, - proxOut); } @Override @@ -267,12 +272,6 @@ @Override public void close() throws IOException { - try { - freqOut.close(); - } finally { - if (proxOut != null) { - proxOut.close(); - } - } + IOUtils.closeSafely(false, freqOut, proxOut); } } Index: lucene/src/java/org/apache/lucene/store/Directory.java --- lucene/src/java/org/apache/lucene/store/Directory.java Sat May 28 08:38:45 2011 -0400 +++ lucene/src/java/org/apache/lucene/store/Directory.java Sat May 28 13:46:56 2011 -0400 @@ -208,7 +208,7 @@ } catch (IOException ioe) { priorException = ioe; } finally { - IOUtils.closeSafely(priorException, os, is); + IOUtils.closeSafelyPriorEx(priorException, os, is); } } Index: lucene/src/java/org/apache/lucene/util/IOUtils.java --- lucene/src/java/org/apache/lucene/util/IOUtils.java Sat May 28 08:38:45 2011 -0400 +++ lucene/src/java/org/apache/lucene/util/IOUtils.java Sat May 28 13:46:56 2011 -0400 @@ -19,6 +19,7 @@ import java.io.Closeable; import java.io.IOException; +import java.util.Iterator; /** @lucene.internal */ public final class IOUtils { @@ -46,45 +47,114 @@ * @param priorException null or an exception that will be rethrown after method completion * @param objects objects to call close() on */ - public static void closeSafely(E priorException, Closeable... objects) throws E, IOException { - IOException firstIOE = null; + public static void closeSafelyPriorEx(E priorException, Closeable... objects) throws E, IOException { + Throwable th = null; for (Closeable object : objects) { try { - if (object != null) + if (object != null) { object.close(); - } catch (IOException ioe) { - if (firstIOE == null) - firstIOE = ioe; + } + } catch (Throwable t) { + if (th == null) { + th = t; + } } } - if (priorException != null) + if (priorException != null) { throw priorException; - else if (firstIOE != null) - throw firstIOE; + } else if (th != null) { + if (th instanceof IOException) throw (IOException) th; + if (th instanceof RuntimeException) throw (RuntimeException) th; + if (th instanceof Error) throw (Error) th; + throw new RuntimeException(th); + } + } + + /** @see #closeSafelyPriorEx(Exception, Closeable...) */ + public static void closeSafelyPriorExIterable(E priorException, Iterable objects) throws E, IOException { + Throwable th = null; + + for (Closeable object : objects) { + try { + if (object != null) { + object.close(); + } + } catch (Throwable t) { + if (th == null) { + th = t; + } + } + } + + if (priorException != null) { + throw priorException; + } else if (th != null) { + if (th instanceof IOException) throw (IOException) th; + if (th instanceof RuntimeException) throw (RuntimeException) th; + if (th instanceof Error) throw (Error) th; + throw new RuntimeException(th); + } } /** - *

Closes all given Closeables, suppressing all thrown exceptions. Some of the Closeables - * may be null, they are ignored. After everything is closed, method either throws the first of suppressed exceptions, - * or completes normally.

- * @param objects objects to call close() on + * Closes all given Closeables, suppressing all thrown exceptions. + * Some of the Closeables may be null, they are ignored. After + * everything is closed, and if {@code suppressExceptions} is {@code false}, + * method either throws the first of suppressed exceptions, or completes + * normally. + * + * @param suppressExceptions + * if true then exceptions that occur during close() are suppressed + * @param objects + * objects to call close() on */ - public static void closeSafely(Closeable... objects) throws IOException { - IOException firstIOE = null; + public static void closeSafely(boolean suppressExceptions, Closeable... objects) throws IOException { + Throwable th = null; for (Closeable object : objects) { try { - if (object != null) + if (object != null) { object.close(); - } catch (IOException ioe) { - if (firstIOE == null) - firstIOE = ioe; + } + } catch (Throwable t) { + if (th == null) + th = t; } } - if (firstIOE != null) - throw firstIOE; + if (th != null && !suppressExceptions) { + if (th instanceof IOException) throw (IOException) th; + if (th instanceof RuntimeException) throw (RuntimeException) th; + if (th instanceof Error) throw (Error) th; + throw new RuntimeException(th); + } } + + /** + * @see #closeSafely(boolean, Closeable...) + */ + public static void closeSafelyIterable(boolean suppressExceptions, Iterable objects) throws IOException { + Throwable th = null; + + for (Closeable object : objects) { + try { + if (object != null) { + object.close(); + } + } catch (Throwable t) { + if (th == null) + th = t; + } + } + + if (th != null && !suppressExceptions) { + if (th instanceof IOException) throw (IOException) th; + if (th instanceof RuntimeException) throw (RuntimeException) th; + if (th instanceof Error) throw (Error) th; + throw new RuntimeException(th); + } + } + } Index: lucene/src/test-framework/org/apache/lucene/index/codecs/mockintblock/MockFixedIntBlockCodec.java --- lucene/src/test-framework/org/apache/lucene/index/codecs/mockintblock/MockFixedIntBlockCodec.java Sat May 28 08:38:45 2011 -0400 +++ lucene/src/test-framework/org/apache/lucene/index/codecs/mockintblock/MockFixedIntBlockCodec.java Sat May 28 13:46:56 2011 -0400 @@ -44,6 +44,7 @@ import org.apache.lucene.index.codecs.standard.StandardCodec; import org.apache.lucene.store.*; import org.apache.lucene.util.BytesRef; +import org.apache.lucene.util.IOUtils; /** * A silly test codec to verify core support for fixed @@ -97,15 +98,25 @@ @Override public IntIndexOutput createOutput(Directory dir, String fileName) throws IOException { - return new FixedIntBlockIndexOutput(dir.createOutput(fileName), blockSize) { - @Override - protected void flushBlock() throws IOException { - for(int i=0;i= 0; - out.writeVInt(buffer[i]); + IndexOutput out = dir.createOutput(fileName); + boolean success = false; + try { + FixedIntBlockIndexOutput ret = new FixedIntBlockIndexOutput(out, blockSize) { + @Override + protected void flushBlock() throws IOException { + for(int i=0;i= 0; + out.writeVInt(buffer[i]); + } } + }; + success = true; + return ret; + } finally { + if (!success) { + IOUtils.closeSafely(true, out); } - }; + } } } Index: lucene/src/test-framework/org/apache/lucene/index/codecs/mockintblock/MockVariableIntBlockCodec.java --- lucene/src/test-framework/org/apache/lucene/index/codecs/mockintblock/MockVariableIntBlockCodec.java Sat May 28 08:38:45 2011 -0400 +++ lucene/src/test-framework/org/apache/lucene/index/codecs/mockintblock/MockVariableIntBlockCodec.java Sat May 28 13:46:56 2011 -0400 @@ -46,6 +46,7 @@ import org.apache.lucene.store.IndexInput; import org.apache.lucene.store.IndexOutput; import org.apache.lucene.util.BytesRef; +import org.apache.lucene.util.IOUtils; /** * A silly test codec to verify core support for variable @@ -102,34 +103,42 @@ @Override public IntIndexOutput createOutput(Directory dir, String fileName) throws IOException { final IndexOutput out = dir.createOutput(fileName); - out.writeInt(baseBlockSize); - return new VariableIntBlockIndexOutput(out, 2*baseBlockSize) { - - int pendingCount; - final int[] buffer = new int[2+2*baseBlockSize]; - - @Override - protected int add(int value) throws IOException { - assert value >= 0; - buffer[pendingCount++] = value; - // silly variable block length int encoder: if - // first value <= 3, we write N vints at once; - // else, 2*N - final int flushAt = buffer[0] <= 3 ? baseBlockSize : 2*baseBlockSize; - - // intentionally be non-causal here: - if (pendingCount == flushAt+1) { - for(int i=0;i= 0; + buffer[pendingCount++] = value; + // silly variable block length int encoder: if + // first value <= 3, we write N vints at once; + // else, 2*N + final int flushAt = buffer[0] <= 3 ? baseBlockSize : 2*baseBlockSize; + + // intentionally be non-causal here: + if (pendingCount == flushAt+1) { + for(int i=0;i pairs in a Directory. A TermInfos can be written once, in order. */ -final class TermInfosWriter { +final class TermInfosWriter implements Closeable { /** The file format version, a negative number. */ public static final int FORMAT = -3; @@ -216,13 +219,18 @@ } /** Called to complete TermInfos creation. */ - void close() throws IOException { - output.seek(4); // write size after format - output.writeLong(size); - output.close(); - - if (!isIndex) - other.close(); + public void close() throws IOException { + try { + output.seek(4); // write size after format + output.writeLong(size); + } finally { + try { + output.close(); + } finally { + if (!isIndex) { + other.close(); + } + } + } } - } Index: lucene/src/test-framework/org/apache/lucene/store/MockDirectoryWrapper.java --- lucene/src/test-framework/org/apache/lucene/store/MockDirectoryWrapper.java Sat May 28 08:38:45 2011 -0400 +++ lucene/src/test-framework/org/apache/lucene/store/MockDirectoryWrapper.java Sat May 28 13:46:56 2011 -0400 @@ -68,24 +68,24 @@ boolean trackDiskUsage = false; private Set unSyncedFiles; private Set createdFiles; - Set openFilesForWrite = new HashSet(); + private Set openFilesForWrite = new HashSet(); volatile boolean crashed; private ThrottledIndexOutput throttledOutput; private Throttling throttling = Throttling.SOMETIMES; // use this for tracking files for crash. // additionally: provides debugging information in case you leave one open - Map openFileHandles = Collections.synchronizedMap(new IdentityHashMap()); + private Map openFileHandles = Collections.synchronizedMap(new IdentityHashMap()); // NOTE: we cannot initialize the Map here due to the // order in which our constructor actually does this // member initialization vs when it calls super. It seems // like super is called, then our members are initialized: - Map openFiles; + private Map openFiles; // Only tracked if noDeleteOpenFile is true: if an attempt // is made to delete an open file, we enroll it here. - Set openFilesDeleted; + private Set openFilesDeleted; private synchronized void init() { if (openFiles == null) { @@ -127,7 +127,7 @@ SOMETIMES, /** never throttle output */ NEVER - }; + } public void setThrottling(Throttling throttling) { this.throttling = throttling; @@ -362,9 +362,10 @@ ramdir.fileMap.put(name, file); } } + //System.out.println(Thread.currentThread().getName() + ": MDW: create " + name); IndexOutput io = new MockIndexOutputWrapper(this, delegate.createOutput(name), name); - openFileHandles.put(io, new RuntimeException("unclosed IndexOutput")); + addFileHandle(io, name, false); openFilesForWrite.add(name); // throttling REALLY slows down tests, so don't do it very often for SOMETIMES. @@ -379,6 +380,18 @@ } } + private void addFileHandle(Closeable c, String name, boolean input) { + Integer v = openFiles.get(name); + if (v != null) { + v = Integer.valueOf(v.intValue()+1); + openFiles.put(name, v); + } else { + openFiles.put(name, Integer.valueOf(1)); + } + + openFileHandles.put(c, new RuntimeException("unclosed Index" + (input ? "Input" : "Output") + ": " + name)); + } + @Override public synchronized IndexInput openInput(String name) throws IOException { maybeYield(); @@ -391,16 +404,8 @@ throw fillOpenTrace(new IOException("MockDirectoryWrapper: file \"" + name + "\" is still open for writing"), name, false); } - if (openFiles.containsKey(name)) { - Integer v = openFiles.get(name); - v = Integer.valueOf(v.intValue()+1); - openFiles.put(name, v); - } else { - openFiles.put(name, Integer.valueOf(1)); - } - IndexInput ii = new MockIndexInputWrapper(this, name, delegate.openInput(name)); - openFileHandles.put(ii, new RuntimeException("unclosed IndexInput")); + addFileHandle(ii, name, true); return ii; } @@ -465,6 +470,31 @@ delegate.close(); } + private synchronized void removeOpenFile(Closeable c, String name) { + Integer v = openFiles.get(name); + // Could be null when crash() was called + if (v != null) { + if (v.intValue() == 1) { + openFiles.remove(name); + openFilesDeleted.remove(name); + } else { + v = Integer.valueOf(v.intValue()-1); + openFiles.put(name, v); + } + } + + openFileHandles.remove(c); + } + + public synchronized void removeIndexOutput(IndexOutput out, String name) { + openFilesForWrite.remove(name); + removeOpenFile(out, name); + } + + public synchronized void removeIndexInput(IndexInput in, String name) { + removeOpenFile(in, name); + } + private CodecProvider codecProvider; // We pass this CodecProvider to checkIndex when dir is closed... Index: lucene/src/test-framework/org/apache/lucene/store/MockIndexInputWrapper.java --- lucene/src/test-framework/org/apache/lucene/store/MockIndexInputWrapper.java Sat May 28 08:38:45 2011 -0400 +++ lucene/src/test-framework/org/apache/lucene/store/MockIndexInputWrapper.java Sat May 28 13:46:56 2011 -0400 @@ -31,8 +31,7 @@ private IndexInput delegate; private boolean isClone; - /** Construct an empty output buffer. - * @throws IOException */ + /** Construct an empty output buffer. */ public MockIndexInputWrapper(MockDirectoryWrapper dir, String name, IndexInput delegate) { this.name = name; this.dir = dir; @@ -46,20 +45,7 @@ // remove the conditional check so we also track that // all clones get closed: if (!isClone) { - synchronized(dir) { - Integer v = dir.openFiles.get(name); - // Could be null when MockRAMDirectory.crash() was called - if (v != null) { - if (v.intValue() == 1) { - dir.openFiles.remove(name); - dir.openFilesDeleted.remove(name); - } else { - v = Integer.valueOf(v.intValue()-1); - dir.openFiles.put(name, v); - } - } - dir.openFileHandles.remove(this); - } + dir.removeIndexInput(this, name); } } Index: lucene/src/test-framework/org/apache/lucene/store/MockIndexOutputWrapper.java --- lucene/src/test-framework/org/apache/lucene/store/MockIndexOutputWrapper.java Sat May 28 08:38:45 2011 -0400 +++ lucene/src/test-framework/org/apache/lucene/store/MockIndexOutputWrapper.java Sat May 28 13:46:56 2011 -0400 @@ -57,10 +57,7 @@ dir.maxUsedSize = size; } } - synchronized(dir) { - dir.openFileHandles.remove(this); - dir.openFilesForWrite.remove(name); - } + dir.removeIndexOutput(this, name); } } Index: lucene/src/test-framework/org/apache/lucene/util/ThrottledIndexOutput.java --- lucene/src/test-framework/org/apache/lucene/util/ThrottledIndexOutput.java Sat May 28 08:38:45 2011 -0400 +++ lucene/src/test-framework/org/apache/lucene/util/ThrottledIndexOutput.java Sat May 28 13:46:56 2011 -0400 @@ -73,9 +73,11 @@ @Override public void close() throws IOException { + try { sleep(closeDelayMillis + getDelay(true)); + } finally { delegate.close(); - + } } @Override Index: lucene/src/test/org/apache/lucene/index/TestIndexWriter.java --- lucene/src/test/org/apache/lucene/index/TestIndexWriter.java Sat May 28 08:38:45 2011 -0400 +++ lucene/src/test/org/apache/lucene/index/TestIndexWriter.java Sat May 28 13:46:56 2011 -0400 @@ -2123,6 +2123,10 @@ allowInterrupt = true; } } catch (ThreadInterruptedException re) { + if (VERBOSE) { + System.out.println("TEST: got interrupt"); + re.printStackTrace(System.out); + } Throwable e = re.getCause(); assertTrue(e instanceof InterruptedException); if (finish) { Index: lucene/src/test/org/apache/lucene/index/TestIndexWriterDelete.java --- lucene/src/test/org/apache/lucene/index/TestIndexWriterDelete.java Sat May 28 08:38:45 2011 -0400 +++ lucene/src/test/org/apache/lucene/index/TestIndexWriterDelete.java Sat May 28 13:46:56 2011 -0400 @@ -833,6 +833,10 @@ try { modifier.addDocument(doc); } catch (IOException io) { + if (VERBOSE) { + System.out.println("TEST: got expected exc:"); + io.printStackTrace(System.out); + } break; } } Index: lucene/src/test/org/apache/lucene/index/TestIndexWriterExceptions.java --- lucene/src/test/org/apache/lucene/index/TestIndexWriterExceptions.java Sat May 28 08:38:45 2011 -0400 +++ lucene/src/test/org/apache/lucene/index/TestIndexWriterExceptions.java Sat May 28 13:46:56 2011 -0400 @@ -919,7 +919,7 @@ assertTrue(failure.failOnCommit && failure.failOnDeleteFile); w.rollback(); assertFalse(dir.fileExists("1.fnx")); - // FIXME: on windows, this often fails! assertEquals(0, dir.listAll().length); + assertEquals(0, dir.listAll().length); dir.close(); } } Index: lucene/src/test/org/apache/lucene/index/TestIndexWriterWithThreads.java --- lucene/src/test/org/apache/lucene/index/TestIndexWriterWithThreads.java Sat May 28 08:38:45 2011 -0400 +++ lucene/src/test/org/apache/lucene/index/TestIndexWriterWithThreads.java Sat May 28 13:46:56 2011 -0400 @@ -65,6 +65,10 @@ writer.updateDocument(new Term("id", ""+(idUpto++)), doc); addCount++; } catch (IOException ioe) { + if (VERBOSE) { + System.out.println("TEST: expected exc:"); + ioe.printStackTrace(System.out); + } //System.out.println(Thread.currentThread().getName() + ": hit exc"); //ioe.printStackTrace(System.out); if (ioe.getMessage().startsWith("fake disk full at") || @@ -218,6 +222,9 @@ int NUM_THREADS = 3; for(int iter=0;iter<2;iter++) { + if (VERBOSE) { + System.out.println("TEST: iter=" + iter); + } MockDirectoryWrapper dir = newDirectory(); IndexWriter writer = new IndexWriter( @@ -228,6 +235,7 @@ setMergePolicy(newLogMergePolicy(4)) ); ((ConcurrentMergeScheduler) writer.getConfig().getMergeScheduler()).setSuppressExceptions(); + writer.setInfoStream(VERBOSE ? System.out : null); IndexerThread[] threads = new IndexerThread[NUM_THREADS]; Index: modules/suggest/src/java/org/apache/lucene/search/suggest/fst/FSTLookup.java --- modules/suggest/src/java/org/apache/lucene/search/suggest/fst/FSTLookup.java Sat May 28 08:38:45 2011 -0400 +++ modules/suggest/src/java/org/apache/lucene/search/suggest/fst/FSTLookup.java Sat May 28 13:46:56 2011 -0400 @@ -510,7 +510,7 @@ this.automaton = new FST(new InputStreamDataInput(is), NoOutputs.getSingleton()); cacheRootArcs(); } finally { - IOUtils.closeSafely(is); + IOUtils.closeSafely(false, is); } return true; } @@ -532,7 +532,7 @@ try { this.automaton.save(new OutputStreamDataOutput(os)); } finally { - IOUtils.closeSafely(os); + IOUtils.closeSafely(false, os); } return true;