diff --git a/lucene/src/java/org/apache/lucene/codecs/DocValuesConsumer.java b/lucene/src/java/org/apache/lucene/codecs/DocValuesConsumer.java
index cf69388..ef6e40c 100644
--- a/lucene/src/java/org/apache/lucene/codecs/DocValuesConsumer.java
+++ b/lucene/src/java/org/apache/lucene/codecs/DocValuesConsumer.java
@@ -16,6 +16,7 @@ package org.apache.lucene.codecs;
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+import java.io.Closeable;
 import java.io.IOException;
 
 import org.apache.lucene.codecs.lucene40.values.Writer;
@@ -36,7 +37,7 @@ import org.apache.lucene.util.BytesRef;
  * 
  * @lucene.experimental
  */
-public abstract class DocValuesConsumer {
+public abstract class DocValuesConsumer implements Closeable {
 
   protected Source currentMergeSource;
   protected final BytesRef spare = new BytesRef();
@@ -66,7 +67,7 @@ public abstract class DocValuesConsumer {
    *          {@link #add(int, DocValue)}.
    * @throws IOException
    */
-  public abstract void finish(int docCount) throws IOException;
+  public abstract void flush(int docCount) throws IOException;
 
   /**
    * Merges the given {@link org.apache.lucene.index.MergeState} into
@@ -92,9 +93,9 @@ public abstract class DocValuesConsumer {
         mergeState.checkAbort.work(reader.reader.maxDoc());
       }
     }
-    // only finish if no exception is thrown!
+    // only flush if we really merged any docs
     if (hasMerged) {
-      finish(mergeState.mergedDocCount);
+      flush(mergeState.mergedDocCount);
     }
   }
 
@@ -161,7 +162,7 @@ public abstract class DocValuesConsumer {
   protected void add(int docID, BytesRef value) throws IOException {
     throw new UnsupportedOperationException("override this method to support byte types");
   }
-
+  
   /**
    * Merges a document with the given <code>docID</code>. The methods
    * implementation obtains the value for the <i>sourceDoc</i> id from the
diff --git a/lucene/src/java/org/apache/lucene/codecs/PerDocConsumer.java b/lucene/src/java/org/apache/lucene/codecs/PerDocConsumer.java
index 4228cc7..5a4502f 100644
--- a/lucene/src/java/org/apache/lucene/codecs/PerDocConsumer.java
+++ b/lucene/src/java/org/apache/lucene/codecs/PerDocConsumer.java
@@ -23,6 +23,7 @@ import org.apache.lucene.index.DocValues;
 import org.apache.lucene.index.IndexReader;
 import org.apache.lucene.index.MergeState;
 import org.apache.lucene.index.DocValues.Type;
+import org.apache.lucene.util.IOUtils;
 
 /**
  * Abstract API that consumes per document values. Concrete implementations of
@@ -53,8 +54,19 @@ public abstract class PerDocConsumer implements Closeable {
           docValues[i] = getDocValuesForMerge(mergeState.readers.get(i).reader, fieldInfo);
         }
         final DocValuesConsumer docValuesConsumer = addValuesField(getDocValuesType(fieldInfo), fieldInfo);
-        assert docValuesConsumer != null;
-        docValuesConsumer.merge(mergeState, docValues);
+        boolean success = false;
+        try {
+          assert docValuesConsumer != null;
+          docValuesConsumer.merge(mergeState, docValues);
+          success = true;
+        } finally {
+          if (success) {
+            IOUtils.close(docValuesConsumer);
+          } else {
+            IOUtils.closeWhileHandlingException(docValuesConsumer);
+          }
+        }
+        
       }
     }
   }
diff --git a/lucene/src/java/org/apache/lucene/codecs/lucene40/values/Bytes.java b/lucene/src/java/org/apache/lucene/codecs/lucene40/values/Bytes.java
index 5a3fcad..08bdfd0 100644
--- a/lucene/src/java/org/apache/lucene/codecs/lucene40/values/Bytes.java
+++ b/lucene/src/java/org/apache/lucene/codecs/lucene40/values/Bytes.java
@@ -112,7 +112,7 @@ public final class Bytes {
    *        is used instead
    * @param bytesUsed
    *          an {@link AtomicLong} instance to track the used bytes within the
-   *          {@link Writer}. A call to {@link Writer#finish(int)} will release
+   *          {@link Writer}. A call to {@link Writer#flush(int)} will release
    *          all internally used resources and frees the memory tracking
    *          reference.
    * @param fasterButMoreRam whether packed ints for docvalues should be optimized for speed by rounding up the bytes
@@ -300,7 +300,7 @@ public final class Bytes {
     abstract void add(int docID, BytesRef bytes) throws IOException;
 
     @Override
-    public abstract void finish(int docCount) throws IOException;
+    public abstract void flush(int docCount) throws IOException;
 
     @Override
     protected void mergeDoc(int docID, int sourceDoc) throws IOException {
@@ -314,6 +314,11 @@ public final class Bytes {
         add(docID, ref);
       }
     }
+    
+    @Override
+    public void close() throws IOException {
+      IOUtils.close(idxOut, datOut);
+    }
   }
 
   /**
@@ -479,32 +484,18 @@ public final class Bytes {
       }
     }
     
-    // Important that we get docCount, in case there were
-    // some last docs that we didn't see
+    
     @Override
-    public void finish(int docCount) throws IOException {
-      boolean success = false;
+    public void close() throws IOException {
       try {
-        finishInternal(docCount);
-        success = true;
+        hash.close();
+        bytesUsed.addAndGet((-docToEntry.length) * RamUsageEstimator.NUM_BYTES_INT);
+        docToEntry = null;
       } finally {
-        releaseResources();
-        if (success) {
-          IOUtils.close(getIndexOut(), getDataOut());
-        } else {
-          IOUtils.closeWhileHandlingException(getIndexOut(), getDataOut());
-        }
-        
+        super.close();
       }
     }
     
-    protected abstract void finishInternal(int docCount) throws IOException;
-    
-    protected void releaseResources() {
-      hash.close();
-      bytesUsed.addAndGet((-docToEntry.length) * RamUsageEstimator.NUM_BYTES_INT);
-      docToEntry = null;
-    }
     
     protected void writeIndex(IndexOutput idxOut, int docCount,
         long maxValue, int[] toEntry) throws IOException {
diff --git a/lucene/src/java/org/apache/lucene/codecs/lucene40/values/FixedDerefBytesImpl.java b/lucene/src/java/org/apache/lucene/codecs/lucene40/values/FixedDerefBytesImpl.java
index 72efc15..4afe3f9 100644
--- a/lucene/src/java/org/apache/lucene/codecs/lucene40/values/FixedDerefBytesImpl.java
+++ b/lucene/src/java/org/apache/lucene/codecs/lucene40/values/FixedDerefBytesImpl.java
@@ -50,7 +50,7 @@ class FixedDerefBytesImpl {
     }
 
     @Override
-    protected void finishInternal(int docCount) throws IOException {
+    public void flush(int docCount) throws IOException {
       final int numValues = hash.size();
       final IndexOutput datOut = getOrCreateDataOut();
       datOut.writeInt(size);
diff --git a/lucene/src/java/org/apache/lucene/codecs/lucene40/values/FixedSortedBytesImpl.java b/lucene/src/java/org/apache/lucene/codecs/lucene40/values/FixedSortedBytesImpl.java
index 28006d6..040ffed 100644
--- a/lucene/src/java/org/apache/lucene/codecs/lucene40/values/FixedSortedBytesImpl.java
+++ b/lucene/src/java/org/apache/lucene/codecs/lucene40/values/FixedSortedBytesImpl.java
@@ -37,7 +37,6 @@ import org.apache.lucene.store.IndexInput;
 import org.apache.lucene.store.IndexOutput;
 import org.apache.lucene.util.BytesRef;
 import org.apache.lucene.util.Counter;
-import org.apache.lucene.util.IOUtils;
 import org.apache.lucene.util.packed.PackedInts;
 
 // Stores fixed-length byte[] by deref, ie when two docs
@@ -64,38 +63,24 @@ class FixedSortedBytesImpl {
     @Override
     public void merge(MergeState mergeState, DocValues[] docValues)
         throws IOException {
-      boolean success = false;
-      try {
-        final MergeContext ctx = SortedBytesMergeUtils.init(Type.BYTES_FIXED_SORTED, docValues, comp, mergeState);
-        List<SortedSourceSlice> slices = SortedBytesMergeUtils.buildSlices(mergeState, docValues, ctx);
-        final IndexOutput datOut = getOrCreateDataOut();
-        datOut.writeInt(ctx.sizePerValues);
-        final int maxOrd = SortedBytesMergeUtils.mergeRecords(ctx, datOut, slices);
-        
-        final IndexOutput idxOut = getOrCreateIndexOut();
-        idxOut.writeInt(maxOrd);
-        final PackedInts.Writer ordsWriter = PackedInts.getWriter(idxOut, ctx.docToEntry.length,
-            PackedInts.bitsRequired(maxOrd));
-        for (SortedSourceSlice slice : slices) {
-          slice.writeOrds(ordsWriter);
-        }
-        ordsWriter.finish();
-        success = true;
-      } finally {
-        releaseResources();
-        if (success) {
-          IOUtils.close(getIndexOut(), getDataOut());
-        } else {
-          IOUtils.closeWhileHandlingException(getIndexOut(), getDataOut());
-        }
-
+      final MergeContext ctx = SortedBytesMergeUtils.init(Type.BYTES_FIXED_SORTED, docValues, comp, mergeState);
+      List<SortedSourceSlice> slices = SortedBytesMergeUtils.buildSlices(mergeState, docValues, ctx);
+      final IndexOutput datOut = getOrCreateDataOut();
+      datOut.writeInt(ctx.sizePerValues);
+      final int maxOrd = SortedBytesMergeUtils.mergeRecords(ctx, datOut, slices);
+      
+      final IndexOutput idxOut = getOrCreateIndexOut();
+      idxOut.writeInt(maxOrd);
+      final PackedInts.Writer ordsWriter = PackedInts.getWriter(idxOut, ctx.docToEntry.length,
+          PackedInts.bitsRequired(maxOrd));
+      for (SortedSourceSlice slice : slices) {
+        slice.writeOrds(ordsWriter);
       }
+      ordsWriter.finish();
     }
 
-    // Important that we get docCount, in case there were
-    // some last docs that we didn't see
     @Override
-    public void finishInternal(int docCount) throws IOException {
+    public void flush(int docCount) throws IOException {
       fillDefault(docCount);
       final IndexOutput datOut = getOrCreateDataOut();
       final int count = hash.size();
diff --git a/lucene/src/java/org/apache/lucene/codecs/lucene40/values/FixedStraightBytesImpl.java b/lucene/src/java/org/apache/lucene/codecs/lucene40/values/FixedStraightBytesImpl.java
index 042250d..a2f548b 100644
--- a/lucene/src/java/org/apache/lucene/codecs/lucene40/values/FixedStraightBytesImpl.java
+++ b/lucene/src/java/org/apache/lucene/codecs/lucene40/values/FixedStraightBytesImpl.java
@@ -136,48 +136,40 @@ class FixedStraightBytesImpl {
     @Override
     protected void merge(SingleSubMergeState state) throws IOException {
       datOut = getOrCreateDataOut();
-      boolean success = false;
-      try {
-        if (!hasMerged && size != -1) {
-          datOut.writeInt(size);
-        }
+      if (!hasMerged && size != -1) {
+        datOut.writeInt(size);
+      }
 
-        if (state.liveDocs == null && tryBulkMerge(state.reader)) {
-          FixedStraightReader reader = (FixedStraightReader) state.reader;
-          final int maxDocs = reader.maxDoc;
-          if (maxDocs == 0) {
-            return;
-          }
-          if (size == -1) {
-            size = reader.size;
-            datOut.writeInt(size);
-          } else if (size != reader.size) {
-            throw new IllegalArgumentException("expected bytes size=" + size
-                + " but got " + reader.size);
-           }
-          if (lastDocID+1 < state.docBase) {
-            fill(datOut, state.docBase);
-            lastDocID = state.docBase-1;
-          }
-          // TODO should we add a transfer to API to each reader?
-          final IndexInput cloneData = reader.cloneData();
-          try {
-            datOut.copyBytes(cloneData, size * maxDocs);
-          } finally {
-            IOUtils.close(cloneData);  
-          }
-        
-          lastDocID += maxDocs;
-        } else {
-          super.merge(state);
+      if (state.liveDocs == null && tryBulkMerge(state.reader)) {
+        FixedStraightReader reader = (FixedStraightReader) state.reader;
+        final int maxDocs = reader.maxDoc;
+        if (maxDocs == 0) {
+          return;
         }
-        success = true;
-      } finally {
-        if (!success) {
-          IOUtils.closeWhileHandlingException(datOut);
+        if (size == -1) {
+          size = reader.size;
+          datOut.writeInt(size);
+        } else if (size != reader.size) {
+          throw new IllegalArgumentException("expected bytes size=" + size
+              + " but got " + reader.size);
+         }
+        if (lastDocID+1 < state.docBase) {
+          fill(datOut, state.docBase);
+          lastDocID = state.docBase-1;
         }
-        hasMerged = true;
+        // TODO should we add a transfer to API to each reader?
+        final IndexInput cloneData = reader.cloneData();
+        try {
+          datOut.copyBytes(cloneData, size * maxDocs);
+        } finally {
+          IOUtils.close(cloneData);  
+        }
+      
+        lastDocID += maxDocs;
+      } else {
+        super.merge(state);
       }
+      hasMerged = true;
     }
     
     protected boolean tryBulkMerge(DocValues docValues) {
@@ -213,41 +205,39 @@ class FixedStraightBytesImpl {
     }
 
     @Override
-    public void finish(int docCount) throws IOException {
-      boolean success = false;
-      try {
-        if (!hasMerged) {
-          // indexing path - no disk IO until here
-          assert datOut == null;
-          datOut = getOrCreateDataOut();
-          if (size == -1) {
-            datOut.writeInt(0);
-          } else {
-            datOut.writeInt(size);
-            writeData(datOut);
-          }
-          if (lastDocID + 1 < docCount) {
-            fill(datOut, docCount);
-          }
+    public void flush(int docCount) throws IOException {
+      if (!hasMerged) {
+        // indexing path - no disk IO until here
+        assert datOut == null;
+        datOut = getOrCreateDataOut();
+        if (size == -1) {
+          datOut.writeInt(0);
         } else {
-          // merge path - datOut should be initialized
-          assert datOut != null;
-          if (size == -1) {// no data added
-            datOut.writeInt(0);
-          } else {
-            fill(datOut, docCount);
-          }
+          datOut.writeInt(size);
+          writeData(datOut);
         }
-        success = true;
-      } finally {
-        resetPool();
-        if (success) {
-          IOUtils.close(datOut);
+        if (lastDocID + 1 < docCount) {
+          fill(datOut, docCount);
+        }
+      } else {
+        // merge path - datOut should be initialized
+        assert datOut != null;
+        if (size == -1) {// no data added
+          datOut.writeInt(0);
         } else {
-          IOUtils.closeWhileHandlingException(datOut);
+          fill(datOut, docCount);
         }
       }
     }
+    
+    @Override
+    public void close() throws IOException {
+      try {
+      resetPool();
+      } finally {
+        super.close();
+      }
+    }
   
   }
   
diff --git a/lucene/src/java/org/apache/lucene/codecs/lucene40/values/PackedIntValues.java b/lucene/src/java/org/apache/lucene/codecs/lucene40/values/PackedIntValues.java
index e6a1c6a..11bd857 100644
--- a/lucene/src/java/org/apache/lucene/codecs/lucene40/values/PackedIntValues.java
+++ b/lucene/src/java/org/apache/lucene/codecs/lucene40/values/PackedIntValues.java
@@ -81,7 +81,7 @@ class PackedIntValues {
     }
 
     @Override
-    public void finish(int docCount) throws IOException {
+    public void flush(int docCount) throws IOException {
       boolean success = false;
       final IndexOutput dataOut = getOrCreateDataOut();
       try {
diff --git a/lucene/src/java/org/apache/lucene/codecs/lucene40/values/VarDerefBytesImpl.java b/lucene/src/java/org/apache/lucene/codecs/lucene40/values/VarDerefBytesImpl.java
index 19a7bd7..3faf8ee 100644
--- a/lucene/src/java/org/apache/lucene/codecs/lucene40/values/VarDerefBytesImpl.java
+++ b/lucene/src/java/org/apache/lucene/codecs/lucene40/values/VarDerefBytesImpl.java
@@ -66,10 +66,8 @@ class VarDerefBytesImpl {
       // allow var bytes sizes
     }
 
-    // Important that we get docCount, in case there were
-    // some last docs that we didn't see
     @Override
-    public void finishInternal(int docCount) throws IOException {
+    public void flush(int docCount) throws IOException {
       fillDefault(docCount);
       final int size = hash.size();
       final long[] addresses = new long[size];
diff --git a/lucene/src/java/org/apache/lucene/codecs/lucene40/values/VarSortedBytesImpl.java b/lucene/src/java/org/apache/lucene/codecs/lucene40/values/VarSortedBytesImpl.java
index d1e8c2a..b6b42fe 100644
--- a/lucene/src/java/org/apache/lucene/codecs/lucene40/values/VarSortedBytesImpl.java
+++ b/lucene/src/java/org/apache/lucene/codecs/lucene40/values/VarSortedBytesImpl.java
@@ -65,43 +65,31 @@ final class VarSortedBytesImpl {
     @Override
     public void merge(MergeState mergeState, DocValues[] docValues)
         throws IOException {
-      boolean success = false;
-      try {
-        MergeContext ctx = SortedBytesMergeUtils.init(Type.BYTES_VAR_SORTED, docValues, comp, mergeState);
-        final List<SortedSourceSlice> slices = SortedBytesMergeUtils.buildSlices(mergeState, docValues, ctx);
-        IndexOutput datOut = getOrCreateDataOut();
-        
-        ctx.offsets = new long[1];
-        final int maxOrd = SortedBytesMergeUtils.mergeRecords(ctx, datOut, slices);
-        final long[] offsets = ctx.offsets;
-        maxBytes = offsets[maxOrd-1];
-        final IndexOutput idxOut = getOrCreateIndexOut();
-        
-        idxOut.writeLong(maxBytes);
-        final PackedInts.Writer offsetWriter = PackedInts.getWriter(idxOut, maxOrd+1,
-            PackedInts.bitsRequired(maxBytes));
-        offsetWriter.add(0);
-        for (int i = 0; i < maxOrd; i++) {
-          offsetWriter.add(offsets[i]);
-        }
-        offsetWriter.finish();
-        
-        final PackedInts.Writer ordsWriter = PackedInts.getWriter(idxOut, ctx.docToEntry.length,
-            PackedInts.bitsRequired(maxOrd-1));
-        for (SortedSourceSlice slice : slices) {
-          slice.writeOrds(ordsWriter);
-        }
-        ordsWriter.finish();
-        success = true;
-      } finally {
-        releaseResources();
-        if (success) {
-          IOUtils.close(getIndexOut(), getDataOut());
-        } else {
-          IOUtils.closeWhileHandlingException(getIndexOut(), getDataOut());
-        }
-
+      MergeContext ctx = SortedBytesMergeUtils.init(Type.BYTES_VAR_SORTED, docValues, comp, mergeState);
+      final List<SortedSourceSlice> slices = SortedBytesMergeUtils.buildSlices(mergeState, docValues, ctx);
+      IndexOutput datOut = getOrCreateDataOut();
+      
+      ctx.offsets = new long[1];
+      final int maxOrd = SortedBytesMergeUtils.mergeRecords(ctx, datOut, slices);
+      final long[] offsets = ctx.offsets;
+      maxBytes = offsets[maxOrd-1];
+      final IndexOutput idxOut = getOrCreateIndexOut();
+      
+      idxOut.writeLong(maxBytes);
+      final PackedInts.Writer offsetWriter = PackedInts.getWriter(idxOut, maxOrd+1,
+          PackedInts.bitsRequired(maxBytes));
+      offsetWriter.add(0);
+      for (int i = 0; i < maxOrd; i++) {
+        offsetWriter.add(offsets[i]);
+      }
+      offsetWriter.finish();
+      
+      final PackedInts.Writer ordsWriter = PackedInts.getWriter(idxOut, ctx.docToEntry.length,
+          PackedInts.bitsRequired(maxOrd-1));
+      for (SortedSourceSlice slice : slices) {
+        slice.writeOrds(ordsWriter);
       }
+      ordsWriter.finish();
     }
 
     @Override
@@ -109,10 +97,8 @@ final class VarSortedBytesImpl {
       // allow var bytes sizes
     }
 
-    // Important that we get docCount, in case there were
-    // some last docs that we didn't see
     @Override
-    public void finishInternal(int docCount) throws IOException {
+    public void flush(int docCount) throws IOException {
       fillDefault(docCount);
       final int count = hash.size();
       final IndexOutput datOut = getOrCreateDataOut();
diff --git a/lucene/src/java/org/apache/lucene/codecs/lucene40/values/VarStraightBytesImpl.java b/lucene/src/java/org/apache/lucene/codecs/lucene40/values/VarStraightBytesImpl.java
index 80924f2..940a0a6 100644
--- a/lucene/src/java/org/apache/lucene/codecs/lucene40/values/VarStraightBytesImpl.java
+++ b/lucene/src/java/org/apache/lucene/codecs/lucene40/values/VarStraightBytesImpl.java
@@ -96,54 +96,46 @@ class VarStraightBytesImpl {
     protected void merge(SingleSubMergeState state) throws IOException {
       merge = true;
       datOut = getOrCreateDataOut();
-      boolean success = false;
-      try {
-        if (state.liveDocs == null && state.reader instanceof VarStraightReader) {
-          // bulk merge since we don't have any deletes
-          VarStraightReader reader = (VarStraightReader) state.reader;
-          final int maxDocs = reader.maxDoc;
-          if (maxDocs == 0) {
-            return;
-          }
-          if (lastDocID+1 < state.docBase) {
-            fill(state.docBase, address);
-            lastDocID = state.docBase-1;
-          }
-          final long numDataBytes;
-          final IndexInput cloneIdx = reader.cloneIndex();
-          try {
-            numDataBytes = cloneIdx.readVLong();
-            final ReaderIterator iter = PackedInts.getReaderIterator(cloneIdx);
-            for (int i = 0; i < maxDocs; i++) {
-              long offset = iter.next();
-              ++lastDocID;
-              if (lastDocID >= docToAddress.length) {
-                int oldSize = docToAddress.length;
-                docToAddress = ArrayUtil.grow(docToAddress, 1 + lastDocID);
-                bytesUsed.addAndGet((docToAddress.length - oldSize)
-                    * RamUsageEstimator.NUM_BYTES_INT);
-              }
-              docToAddress[lastDocID] = address + offset;
+      if (state.liveDocs == null && state.reader instanceof VarStraightReader) {
+        // bulk merge since we don't have any deletes
+        VarStraightReader reader = (VarStraightReader) state.reader;
+        final int maxDocs = reader.maxDoc;
+        if (maxDocs == 0) {
+          return;
+        }
+        if (lastDocID+1 < state.docBase) {
+          fill(state.docBase, address);
+          lastDocID = state.docBase-1;
+        }
+        final long numDataBytes;
+        final IndexInput cloneIdx = reader.cloneIndex();
+        try {
+          numDataBytes = cloneIdx.readVLong();
+          final ReaderIterator iter = PackedInts.getReaderIterator(cloneIdx);
+          for (int i = 0; i < maxDocs; i++) {
+            long offset = iter.next();
+            ++lastDocID;
+            if (lastDocID >= docToAddress.length) {
+              int oldSize = docToAddress.length;
+              docToAddress = ArrayUtil.grow(docToAddress, 1 + lastDocID);
+              bytesUsed.addAndGet((docToAddress.length - oldSize)
+                  * RamUsageEstimator.NUM_BYTES_INT);
             }
-            address += numDataBytes; // this is the address after all addr pointers are updated
-            iter.close();
-          } finally {
-            IOUtils.close(cloneIdx);
-          }
-          final IndexInput cloneData = reader.cloneData();
-          try {
-            datOut.copyBytes(cloneData, numDataBytes);
-          } finally {
-            IOUtils.close(cloneData);  
+            docToAddress[lastDocID] = address + offset;
           }
-        } else {
-          super.merge(state);
+          address += numDataBytes; // this is the address after all addr pointers are updated
+          iter.close();
+        } finally {
+          IOUtils.close(cloneIdx);
         }
-        success = true;
-      } finally {
-        if (!success) {
-          IOUtils.closeWhileHandlingException(datOut);
+        final IndexInput cloneData = reader.cloneData();
+        try {
+          datOut.copyBytes(cloneData, numDataBytes);
+        } finally {
+          IOUtils.close(cloneData);  
         }
+      } else {
+        super.merge(state);
       }
     }
     
@@ -164,59 +156,46 @@ class VarStraightBytesImpl {
     
 
     @Override
-    public void finish(int docCount) throws IOException {
-      boolean success = false;
+    public void flush(int docCount) throws IOException {
       assert (!merge && datOut == null) || (merge && datOut != null); 
       final IndexOutput datOut = getOrCreateDataOut();
-      try {
-        if (!merge) {
-          // header is already written in getDataOut()
-          pool.writePool(datOut);
+      if (!merge) {
+        // header is already written in getDataOut()
+        pool.writePool(datOut);
+      }
+      final IndexOutput idxOut = getOrCreateIndexOut();
+      if (lastDocID == -1) {
+        idxOut.writeVLong(0);
+        final PackedInts.Writer w = PackedInts.getWriter(idxOut, docCount+1,
+            PackedInts.bitsRequired(0));
+        // docCount+1 so we write sentinel
+        for (int i = 0; i < docCount+1; i++) {
+          w.add(0);
         }
-        success = true;
-      } finally {
-        if (success) {
-          IOUtils.close(datOut);
-        } else {
-          IOUtils.closeWhileHandlingException(datOut);
+        w.finish();
+      } else {
+        fill(docCount, address);
+        idxOut.writeVLong(address);
+        final PackedInts.Writer w = PackedInts.getWriter(idxOut, docCount+1,
+            PackedInts.bitsRequired(address));
+        for (int i = 0; i < docCount; i++) {
+          w.add(docToAddress[i]);
         }
-        pool.dropBuffersAndReset();
+        // write sentinel
+        w.add(address);
+        w.finish();
       }
-
-      success = false;
-      final IndexOutput idxOut = getOrCreateIndexOut();
+    }
+    
+    @Override
+    public void close() throws IOException {
       try {
-        if (lastDocID == -1) {
-          idxOut.writeVLong(0);
-          final PackedInts.Writer w = PackedInts.getWriter(idxOut, docCount+1,
-              PackedInts.bitsRequired(0));
-          // docCount+1 so we write sentinel
-          for (int i = 0; i < docCount+1; i++) {
-            w.add(0);
-          }
-          w.finish();
-        } else {
-          fill(docCount, address);
-          idxOut.writeVLong(address);
-          final PackedInts.Writer w = PackedInts.getWriter(idxOut, docCount+1,
-              PackedInts.bitsRequired(address));
-          for (int i = 0; i < docCount; i++) {
-            w.add(docToAddress[i]);
-          }
-          // write sentinel
-          w.add(address);
-          w.finish();
-        }
-        success = true;
-      } finally {
         bytesUsed.addAndGet(-(docToAddress.length)
             * RamUsageEstimator.NUM_BYTES_INT);
         docToAddress = null;
-        if (success) {
-          IOUtils.close(idxOut);
-        } else {
-          IOUtils.closeWhileHandlingException(idxOut);
-        }
+        pool.dropBuffersAndReset();
+      } finally {
+        super.close();
       }
     }
 
diff --git a/lucene/src/java/org/apache/lucene/codecs/lucene40/values/Writer.java b/lucene/src/java/org/apache/lucene/codecs/lucene40/values/Writer.java
index a7f621b..238019c 100644
--- a/lucene/src/java/org/apache/lucene/codecs/lucene40/values/Writer.java
+++ b/lucene/src/java/org/apache/lucene/codecs/lucene40/values/Writer.java
@@ -47,7 +47,7 @@ public abstract class Writer extends DocValuesConsumer {
    * @param bytesUsed
    *          bytes-usage tracking reference used by implementation to track
    *          internally allocated memory. All tracked bytes must be released
-   *          once {@link #finish(int)} has been called.
+   *          once {@link #flush(int)} has been called.
    */
   protected Writer(Counter bytesUsed) {
     this.bytesUsed = bytesUsed;
diff --git a/lucene/src/java/org/apache/lucene/codecs/simpletext/SimpleTextNormsConsumer.java b/lucene/src/java/org/apache/lucene/codecs/simpletext/SimpleTextNormsConsumer.java
index 65e77dc..1bc3b60 100644
--- a/lucene/src/java/org/apache/lucene/codecs/simpletext/SimpleTextNormsConsumer.java
+++ b/lucene/src/java/org/apache/lucene/codecs/simpletext/SimpleTextNormsConsumer.java
@@ -139,7 +139,7 @@ public class SimpleTextNormsConsumer extends PerDocConsumer {
     }
 
     @Override
-    public void finish(int docCount) throws IOException {
+    public void flush(int docCount) throws IOException {
       final NormsWriter normsWriter = getNormsWriter();
       boolean success = false;
       try {
@@ -172,6 +172,11 @@ public class SimpleTextNormsConsumer extends PerDocConsumer {
         }
       }
     }
+
+    @Override
+    public void close() throws IOException {
+      // nothing to close
+    }
   }
 
   public NormsWriter getNormsWriter() throws IOException {
diff --git a/lucene/src/java/org/apache/lucene/index/DocFieldProcessor.java b/lucene/src/java/org/apache/lucene/index/DocFieldProcessor.java
index 50b4808..341b511 100644
--- a/lucene/src/java/org/apache/lucene/index/DocFieldProcessor.java
+++ b/lucene/src/java/org/apache/lucene/index/DocFieldProcessor.java
@@ -89,7 +89,12 @@ final class DocFieldProcessor extends DocConsumer {
     FieldInfosWriter infosWriter = codec.fieldInfosFormat().getFieldInfosWriter();
     infosWriter.write(state.directory, state.segmentName, state.fieldInfos, IOContext.DEFAULT);
     for (DocValuesConsumerAndDocID consumers : docValues.values()) {
-      consumers.docValuesConsumer.finish(state.numDocs);
+      try {
+        consumers.docValuesConsumer.flush(state.numDocs);
+      } finally {
+        // if we fail this seg is aborted and consumers are closed
+        IOUtils.close(consumers.docValuesConsumer);
+      }
     }
     // close perDocConsumer during flush to ensure all files are flushed due to PerCodec CFS
     IOUtils.close(perDocConsumers.values());
@@ -142,6 +147,10 @@ final class DocFieldProcessor extends DocConsumer {
       }
     }
     
+    for (DocValuesConsumerAndDocID consumer : docValues.values()) {
+      IOUtils.closeWhileHandlingException(consumer.docValuesConsumer);
+    }
+    
     // If any errors occured, throw it.
     if (th != null) {
       if (th instanceof RuntimeException) throw (RuntimeException) th;
@@ -341,11 +350,19 @@ final class DocFieldProcessor extends DocConsumer {
       perDocConsumers.put(0, perDocConsumer);
     }
     DocValuesConsumer docValuesConsumer = perDocConsumer.addValuesField(valueType, fieldInfo);
-    fieldInfo.setDocValuesType(valueType);
-
-    docValuesConsumerAndDocID = new DocValuesConsumerAndDocID(docValuesConsumer);
-    docValuesConsumerAndDocID.docID = docState.docID;
-    docValues.put(fieldInfo.name, docValuesConsumerAndDocID);
-    return docValuesConsumer;
+    boolean succcess = false;
+    try {
+      fieldInfo.setDocValuesType(valueType);
+  
+      docValuesConsumerAndDocID = new DocValuesConsumerAndDocID(docValuesConsumer);
+      docValuesConsumerAndDocID.docID = docState.docID;
+      docValues.put(fieldInfo.name, docValuesConsumerAndDocID);
+      succcess = true;
+      return docValuesConsumer;
+    } finally {
+      if (!succcess) {
+        IOUtils.closeWhileHandlingException(docValuesConsumer);
+      }
+    }
   }
 }
diff --git a/lucene/src/java/org/apache/lucene/index/NormsConsumer.java b/lucene/src/java/org/apache/lucene/index/NormsConsumer.java
index 3e68e04..a51e576 100644
--- a/lucene/src/java/org/apache/lucene/index/NormsConsumer.java
+++ b/lucene/src/java/org/apache/lucene/index/NormsConsumer.java
@@ -75,10 +75,20 @@ final class NormsConsumer extends InvertedDocEndConsumer {
               // we must check the final value of omitNorms for the fieldinfo, it could have 
               // changed for this field since the first time we added it.
               final DocValuesConsumer valuesConsumer = newConsumer(new PerDocWriteState(state), fi);
-              final DocValuesField value = new DocValuesField("");
-              value.setBytes(new BytesRef(new byte[] {0x00}), Type.BYTES_FIXED_STRAIGHT);
-              valuesConsumer.add(state.numDocs-1, value);
-              valuesConsumer.finish(state.numDocs);
+              boolean innnerSuccess = false;
+              try {
+                final DocValuesField value = new DocValuesField("");
+                value.setBytes(new BytesRef(new byte[] {0x00}), Type.BYTES_FIXED_STRAIGHT);
+                valuesConsumer.add(state.numDocs-1, value);
+                valuesConsumer.flush(state.numDocs);
+                innnerSuccess = true;
+              } finally {
+                if (innnerSuccess) {
+                  IOUtils.close(valuesConsumer);
+                } else {
+                  IOUtils.closeWhileHandlingException(valuesConsumer);
+                }
+              }
             }
           }
         }
diff --git a/lucene/src/java/org/apache/lucene/index/NormsConsumerPerField.java b/lucene/src/java/org/apache/lucene/index/NormsConsumerPerField.java
index ef9d1e7..b8ccadd 100644
--- a/lucene/src/java/org/apache/lucene/index/NormsConsumerPerField.java
+++ b/lucene/src/java/org/apache/lucene/index/NormsConsumerPerField.java
@@ -22,6 +22,7 @@ import org.apache.lucene.document.DocValuesField;
 import org.apache.lucene.index.DocValues.Type;
 import org.apache.lucene.search.similarities.Similarity;
 import org.apache.lucene.util.BytesRef;
+import org.apache.lucene.util.IOUtils;
 
 public class NormsConsumerPerField extends InvertedDocEndConsumerPerField implements Comparable<NormsConsumerPerField> {
   private final FieldInfo fieldInfo;
@@ -55,20 +56,29 @@ public class NormsConsumerPerField extends InvertedDocEndConsumerPerField implem
       spare.bytes[0] = similarity.computeNorm(fieldState);
       value.setBytes(spare, Type.BYTES_FIXED_STRAIGHT);
       consumer.add(docState.docID, value);
-      
     }    
   }
   
   void flush(int docCount) throws IOException {
     DocValuesConsumer consumer = this.consumer;
-    if (consumer == null && fieldInfo.isIndexed) {
-       consumer = getConsumer();
-      spare.bytes[0] = 0x00;
-      value.setBytes(spare, Type.BYTES_FIXED_STRAIGHT);
-      consumer.add(docCount-1, value);
-    } 
-    if (consumer != null) {
-      consumer.finish(docCount);
+    boolean success = false;
+    try {
+      if (consumer == null && fieldInfo.isIndexed) {
+         consumer = getConsumer();
+        spare.bytes[0] = 0x00;
+        value.setBytes(spare, Type.BYTES_FIXED_STRAIGHT);
+        consumer.add(docCount-1, value);
+      } 
+      if (consumer != null) {
+        consumer.flush(docCount);
+      }
+      success = true;
+    } finally {
+      if (success) {
+        IOUtils.close(consumer);
+      } else {
+        IOUtils.closeWhileHandlingException(consumer);
+      }
     }
   }
   
@@ -82,7 +92,7 @@ public class NormsConsumerPerField extends InvertedDocEndConsumerPerField implem
 
   @Override
   void abort() {
-    //
+    IOUtils.closeWhileHandlingException(consumer);
   }
 
 }
diff --git a/lucene/src/test-framework/java/org/apache/lucene/codecs/preflexrw/PreFlexNormsConsumer.java b/lucene/src/test-framework/java/org/apache/lucene/codecs/preflexrw/PreFlexNormsConsumer.java
index 0ec0cde..9434bc4 100644
--- a/lucene/src/test-framework/java/org/apache/lucene/codecs/preflexrw/PreFlexNormsConsumer.java
+++ b/lucene/src/test-framework/java/org/apache/lucene/codecs/preflexrw/PreFlexNormsConsumer.java
@@ -98,7 +98,7 @@ class PreFlexNormsConsumer extends PerDocConsumer {
     }
 
     @Override
-    public void finish(int docCount) throws IOException {
+    public void flush(int docCount) throws IOException {
       final NormsWriter normsWriter = getNormsWriter();
       boolean success = false;
       try {
@@ -152,8 +152,11 @@ class PreFlexNormsConsumer extends PerDocConsumer {
       docIDs[upto] = docID;
       upto++;
     }
-    
-    
+
+    @Override
+    public void close() throws IOException {
+      // nothing to close here
+    }
   }
   
   public NormsWriter getNormsWriter() throws IOException {
diff --git a/lucene/src/test/org/apache/lucene/codecs/lucene40/TestDocValues.java b/lucene/src/test/org/apache/lucene/codecs/lucene40/TestDocValues.java
index 1d2f97c..c98ab97 100644
--- a/lucene/src/test/org/apache/lucene/codecs/lucene40/TestDocValues.java
+++ b/lucene/src/test/org/apache/lucene/codecs/lucene40/TestDocValues.java
@@ -84,7 +84,8 @@ public class TestDocValues extends LuceneTestCase {
       valueHolder.bytes = bytesRef;
       w.add(2 * i, valueHolder);
     }
-    w.finish(maxDoc);
+    w.flush(maxDoc);
+    w.close();
     assertEquals(0, trackBytes.get());
 
     DocValues r = Bytes.getValues(dir, "test", mode, fixedSize, maxDoc, COMP, newIOContext(random));
@@ -179,7 +180,8 @@ public class TestDocValues extends LuceneTestCase {
       w.add(0, valueHolder);
       valueHolder.intValue = minMax[i][1];
       w.add(1, valueHolder);
-      w.finish(2);
+      w.flush(2);
+      w.close();
       assertEquals(0, trackBytes.get());
       DocValues r = Ints.getValues(dir, "test", 2,  Type.VAR_INTS, newIOContext(random));
       Source source = getSource(r);
@@ -215,7 +217,8 @@ public class TestDocValues extends LuceneTestCase {
       valueHolder.intValue = (long) sourceArray[i];
       w.add(i, valueHolder);
     }
-    w.finish(sourceArray.length);
+    w.flush(sourceArray.length);
+    w.close();
     DocValues r = Ints.getValues(dir, "test", sourceArray.length, Type.FIXED_INTS_8, newIOContext(random));
     Source source = r.getSource();
     assertTrue(source.hasArray());
@@ -238,7 +241,8 @@ public class TestDocValues extends LuceneTestCase {
       valueHolder.intValue = (long) sourceArray[i];
       w.add(i, valueHolder);
     }
-    w.finish(sourceArray.length);
+    w.flush(sourceArray.length);
+    w.close();
     DocValues r = Ints.getValues(dir, "test", sourceArray.length, Type.FIXED_INTS_16, newIOContext(random));
     Source source = r.getSource();
     assertTrue(source.hasArray());
@@ -261,7 +265,8 @@ public class TestDocValues extends LuceneTestCase {
       valueHolder.intValue = sourceArray[i];
       w.add(i, valueHolder);
     }
-    w.finish(sourceArray.length);
+    w.flush(sourceArray.length);
+    w.close();
     DocValues r = Ints.getValues(dir, "test", sourceArray.length, Type.FIXED_INTS_64, newIOContext(random));
     Source source = r.getSource();
     assertTrue(source.hasArray());
@@ -284,7 +289,8 @@ public class TestDocValues extends LuceneTestCase {
       valueHolder.intValue = (long) sourceArray[i];
       w.add(i, valueHolder);
     }
-    w.finish(sourceArray.length);
+    w.flush(sourceArray.length);
+    w.close();
     DocValues r = Ints.getValues(dir, "test", sourceArray.length, Type.FIXED_INTS_32, newIOContext(random));
     Source source = r.getSource();
     assertTrue(source.hasArray());
@@ -307,7 +313,8 @@ public class TestDocValues extends LuceneTestCase {
       valueHolder.floatValue = sourceArray[i];
       w.add(i, valueHolder);
     }
-    w.finish(sourceArray.length);
+    w.flush(sourceArray.length);
+    w.close();
     DocValues r = Floats.getValues(dir, "test", 3, newIOContext(random), Type.FLOAT_32);
     Source source = r.getSource();
     assertTrue(source.hasArray());
@@ -330,7 +337,8 @@ public class TestDocValues extends LuceneTestCase {
       valueHolder.floatValue = sourceArray[i];
       w.add(i, valueHolder);
     }
-    w.finish(sourceArray.length);
+    w.flush(sourceArray.length);
+    w.close();
     DocValues r = Floats.getValues(dir, "test", 3, newIOContext(random), Type.FLOAT_64);
     Source source = r.getSource();
     assertTrue(source.hasArray());
@@ -358,7 +366,8 @@ public class TestDocValues extends LuceneTestCase {
         w.add(i, valueHolder);
       }
       final int additionalDocs = 1 + random.nextInt(9);
-      w.finish(NUM_VALUES + additionalDocs);
+      w.flush(NUM_VALUES + additionalDocs);
+      w.close();
       assertEquals(0, trackBytes.get());
 
       DocValues r = Ints.getValues(dir, "test", NUM_VALUES + additionalDocs, type, newIOContext(random));
@@ -394,7 +403,8 @@ public class TestDocValues extends LuceneTestCase {
       w.add(i, valueHolder);
     }
     final int additionalValues = 1 + random.nextInt(10);
-    w.finish(NUM_VALUES + additionalValues);
+    w.flush(NUM_VALUES + additionalValues);
+    w.close();
     assertEquals(0, trackBytes.get());
 
     DocValues r = Floats.getValues(dir, "test", NUM_VALUES + additionalValues, newIOContext(random), type);
