diff --git a/libs/core/src/main/java/org/elasticsearch/core/internal/io/IOUtils.java b/libs/core/src/main/java/org/elasticsearch/core/internal/io/IOUtils.java index 970e891de55..022d8c90301 100644 --- a/libs/core/src/main/java/org/elasticsearch/core/internal/io/IOUtils.java +++ b/libs/core/src/main/java/org/elasticsearch/core/internal/io/IOUtils.java @@ -19,6 +19,8 @@ package org.elasticsearch.core.internal.io; +import org.elasticsearch.common.Nullable; + import java.io.Closeable; import java.io.IOException; import java.nio.channels.FileChannel; @@ -64,6 +66,15 @@ public final class IOUtils { close(null, Arrays.asList(objects)); } + /** + * @see #close(Closeable...) + */ + public static void close(@Nullable Closeable closeable) throws IOException { + if (closeable != null) { + closeable.close(); + } + } + /** * Closes all given {@link Closeable}s. Some of the {@linkplain Closeable}s may be null; they are * ignored. After everything is closed, the method adds any exceptions as suppressed to the @@ -102,9 +113,7 @@ public final class IOUtils { Exception firstException = ex; for (final Closeable object : objects) { try { - if (object != null) { - object.close(); - } + close(object); } catch (final IOException | RuntimeException e) { if (firstException == null) { firstException = e; @@ -142,14 +151,18 @@ public final class IOUtils { */ public static void closeWhileHandlingException(final Iterable objects) { for (final Closeable object : objects) { - // noinspection EmptyCatchBlock - try { - if (object != null) { - object.close(); - } - } catch (final IOException | RuntimeException e) { + closeWhileHandlingException(object); + } + } - } + /** + * @see #closeWhileHandlingException(Closeable...) + */ + public static void closeWhileHandlingException(final Closeable closeable) { + // noinspection EmptyCatchBlock + try { + close(closeable); + } catch (final IOException | RuntimeException e) { } } diff --git a/server/src/main/java/org/elasticsearch/common/io/stream/ReleasableBytesStreamOutput.java b/server/src/main/java/org/elasticsearch/common/io/stream/ReleasableBytesStreamOutput.java index 04b34783025..446a4103c16 100644 --- a/server/src/main/java/org/elasticsearch/common/io/stream/ReleasableBytesStreamOutput.java +++ b/server/src/main/java/org/elasticsearch/common/io/stream/ReleasableBytesStreamOutput.java @@ -21,9 +21,7 @@ package org.elasticsearch.common.io.stream; import org.elasticsearch.common.bytes.ReleasableBytesReference; import org.elasticsearch.common.lease.Releasable; -import org.elasticsearch.common.lease.Releasables; import org.elasticsearch.common.util.BigArrays; -import org.elasticsearch.common.util.ByteArray; import org.elasticsearch.common.util.PageCacheRecycler; /** @@ -35,10 +33,7 @@ import org.elasticsearch.common.util.PageCacheRecycler; * stream should only be closed after the bytes have been output or copied * elsewhere. */ -public class ReleasableBytesStreamOutput extends BytesStreamOutput - implements Releasable { - - private Releasable releasable; +public class ReleasableBytesStreamOutput extends BytesStreamOutput implements Releasable { public ReleasableBytesStreamOutput(BigArrays bigarrays) { this(PageCacheRecycler.PAGE_SIZE_IN_BYTES, bigarrays); @@ -46,31 +41,10 @@ public class ReleasableBytesStreamOutput extends BytesStreamOutput public ReleasableBytesStreamOutput(int expectedSize, BigArrays bigArrays) { super(expectedSize, bigArrays); - this.releasable = Releasables.releaseOnce(this.bytes); } @Override public void close() { - Releasables.close(releasable); - } - - @Override - void ensureCapacity(long offset) { - final ByteArray prevBytes = this.bytes; - super.ensureCapacity(offset); - if (prevBytes != this.bytes) { - // re-create the releasable with the new reference - releasable = Releasables.releaseOnce(this.bytes); - } - } - - @Override - public void reset() { - final ByteArray prevBytes = this.bytes; - super.reset(); - if (prevBytes != this.bytes) { - // re-create the releasable with the new reference - releasable = Releasables.releaseOnce(this.bytes); - } + bytes.close(); } } diff --git a/server/src/main/java/org/elasticsearch/common/lease/Releasables.java b/server/src/main/java/org/elasticsearch/common/lease/Releasables.java index 831c1254547..72fae5e2a34 100644 --- a/server/src/main/java/org/elasticsearch/common/lease/Releasables.java +++ b/server/src/main/java/org/elasticsearch/common/lease/Releasables.java @@ -96,13 +96,13 @@ public enum Releasables { } /** - * Equivalent to {@link #wrap(Releasable...)} but can be called multiple times without double releasing. + * Wraps a {@link Releasable} such that its {@link Releasable#close()} method can be called multiple times without double releasing. */ - public static Releasable releaseOnce(final Releasable... releasables) { + public static Releasable releaseOnce(final Releasable releasable) { final AtomicBoolean released = new AtomicBoolean(false); return () -> { if (released.compareAndSet(false, true)) { - close(releasables); + releasable.close(); } }; } diff --git a/server/src/test/java/org/elasticsearch/common/ReleasablesTests.java b/server/src/test/java/org/elasticsearch/common/ReleasablesTests.java index 62686354913..b7277d7c400 100644 --- a/server/src/test/java/org/elasticsearch/common/ReleasablesTests.java +++ b/server/src/test/java/org/elasticsearch/common/ReleasablesTests.java @@ -28,11 +28,11 @@ public class ReleasablesTests extends ESTestCase { public void testReleaseOnce() { AtomicInteger count = new AtomicInteger(0); - Releasable releasable = Releasables.releaseOnce(count::incrementAndGet, count::incrementAndGet); + Releasable releasable = Releasables.releaseOnce(count::incrementAndGet); assertEquals(0, count.get()); releasable.close(); - assertEquals(2, count.get()); + assertEquals(1, count.get()); releasable.close(); - assertEquals(2, count.get()); + assertEquals(1, count.get()); } }