Free disk buffers 78/111678/2
authorRobert Varga <robert.varga@pantheon.tech>
Sun, 12 May 2024 10:14:33 +0000 (12:14 +0200)
committerRobert Varga <robert.varga@pantheon.tech>
Mon, 13 May 2024 10:29:39 +0000 (12:29 +0200)
We are allocating the buffer via a ByteBufAllocator, which may lead to
leaks is we do not release() the buffer.

JIRA: CONTROLLER-2115
Change-Id: I8a1aff9cd7ef1a3cd5937a5ac481a3c188a6c13f
Signed-off-by: Robert Varga <robert.varga@pantheon.tech>
atomix-storage/src/main/java/io/atomix/storage/journal/DiskFileReader.java
atomix-storage/src/main/java/io/atomix/storage/journal/DiskFileWriter.java
atomix-storage/src/main/java/io/atomix/storage/journal/FileReader.java
atomix-storage/src/main/java/io/atomix/storage/journal/FileWriter.java
atomix-storage/src/main/java/io/atomix/storage/journal/JournalSegmentReader.java
atomix-storage/src/main/java/io/atomix/storage/journal/MappedFileReader.java
atomix-storage/src/main/java/io/atomix/storage/journal/MappedFileWriter.java

index 197a16dc65193224a1cb253c64fadff71dd18fbf..961ba3ba43e3459a6f3f529607d142392444a1fd 100644 (file)
@@ -28,8 +28,8 @@ import org.eclipse.jdt.annotation.NonNull;
  */
 final class DiskFileReader extends FileReader {
     private final FileChannel channel;
-    private final ByteBuf buffer;
 
+    private ByteBuf buffer;
     // tracks where memory's first available byte maps to in terms of FileChannel.position()
     private int bufferPosition;
 
@@ -55,6 +55,15 @@ final class DiskFileReader extends FileReader {
         return seek >= 0 ? forwardAndRead(seek, position, size) : rewindAndRead(-seek, position, size);
     }
 
+    @Override
+    void release() {
+        final var local = buffer;
+        if (local != null) {
+            buffer = null;
+            local.release();
+        }
+    }
+
     private @NonNull ByteBuf forwardAndRead(final int seek, final int position, final int size) {
         final int remaining = buffer.writerIndex() - seek;
         final int missing = remaining - size;
index 7ca43c8fea15b202cc41fc9573c5bcd80e55e74e..dc98419482d15c8540ab0d2955d86a19f82ffbc5 100644 (file)
@@ -78,4 +78,9 @@ final class DiskFileWriter extends FileWriter {
             }
         }
     }
+
+    @Override
+    void release() {
+        reader.release();
+    }
 }
index dc44cca34a4010a858772fedf95585293dae84f9..da040371f15db89e8d6b88ca6a3fea65fb7c3de4 100644 (file)
@@ -46,6 +46,11 @@ abstract sealed class FileReader permits DiskFileReader, MappedFileReader {
      */
     abstract @NonNull ByteBuf read(int position, int size);
 
+    /**
+     * Releases resources associated with this writer.
+     */
+    abstract void release();
+
     @Override
     public final String toString() {
         return MoreObjects.toStringHelper(this).add("path", file.path()).toString();
index e2cda5274cf0d0fd2390e5f572aba47c5099cd38..da0f9bb73cfb791d4e7d99e0bd99b77ec35783a2 100644 (file)
@@ -72,6 +72,11 @@ abstract sealed class FileWriter permits DiskFileWriter, MappedFileWriter {
      */
     abstract void flush() throws IOException;
 
+    /**
+     * Releases resources associated with this writer.
+     */
+    abstract void release();
+
     @Override
     public final String toString() {
         return MoreObjects.toStringHelper(this).add("path", file.path()).toString();
index 15accd3d620b725514d3f00e71a212c6713268fe..58536b83b0bb30094f5ee7f2d7ff7ab7861a54c4 100644 (file)
@@ -27,10 +27,10 @@ final class JournalSegmentReader {
     private static final Logger LOG = LoggerFactory.getLogger(JournalSegmentReader.class);
 
     private final JournalSegment segment;
-    private final FileReader fileReader;
     private final int maxSegmentSize;
     private final int maxEntrySize;
 
+    private FileReader fileReader;
     private int position;
 
     JournalSegmentReader(final JournalSegment segment, final FileReader fileReader, final int maxEntrySize) {
@@ -115,6 +115,11 @@ final class JournalSegmentReader {
      * Close this reader.
      */
     void close() {
-        segment.closeReader(this);
+        final var local = fileReader;
+        if (local != null) {
+            fileReader = null;
+            local.release();
+            segment.closeReader(this);
+        }
     }
 }
index 2ec2e4ccc875ca18131497b4ca1d1bd9e4c130df..876b602b95e7dafa5a3e650d8dab2a07dd7a07c8 100644 (file)
@@ -37,4 +37,9 @@ final class MappedFileReader extends FileReader {
     ByteBuf read(final int position, final int size) {
         return buffer.slice(position, size);
     }
+
+    @Override
+    void release() {
+        // No-op
+    }
 }
index 3a73a98cc20f55343c2e55d5fa3a5fc06fb5be10..711d8d9480592c7fad40968e8593f5c3d77cf142 100644 (file)
@@ -62,4 +62,9 @@ final class MappedFileWriter extends FileWriter {
     void flush() throws IOException {
         flush.flush();
     }
+
+    @Override
+    void release() {
+        // No-op
+    }
 }