From 0473fa4313b6096a3f258c582d5d927a34171b67 Mon Sep 17 00:00:00 2001 From: Andrea Cavalli Date: Mon, 26 Nov 2018 14:50:44 +0100 Subject: [PATCH] Fixed memory leak --- .../java/org/warp/jcwdb/FileIndexManager.java | 64 +++++++++++-------- 1 file changed, 37 insertions(+), 27 deletions(-) diff --git a/src/main/java/org/warp/jcwdb/FileIndexManager.java b/src/main/java/org/warp/jcwdb/FileIndexManager.java index 8b98e00..af9bd9d 100644 --- a/src/main/java/org/warp/jcwdb/FileIndexManager.java +++ b/src/main/java/org/warp/jcwdb/FileIndexManager.java @@ -20,8 +20,12 @@ public class FileIndexManager implements IndexManager { private final TypesManager typesManager; private final SeekableByteChannel dataFileChannel, metadataFileChannel; private final FileAllocator fileAllocator; + private final ByteBuffer metadataByteBuffer = ByteBuffer.allocateDirect(IndexDetails.TOTAL_BYTES); + private final ByteBuffer maskByteBuffer = ByteBuffer.allocateDirect(Integer.BYTES); private volatile boolean closed; private final Object closeLock = new Object(); + private final Object metadataByteBufferLock = new Object(); + private final Object maskByteBufferBufferLock = new Object(); /** * Edit this using editIndex() @@ -104,12 +108,13 @@ public class FileIndexManager implements IndexManager { * @throws IOException */ private void writeExact(final IndexDetails indexDetails, DBDataOutput data) throws IOException { - if (indexDetails.getSize() != data.getSize()) { - throw new IOException("Unable to write " + data.getSize() + " in a space of " + indexDetails.getSize()); + final int dataSize = data.getSize(); + if (indexDetails.getSize() != dataSize) { + throw new IOException("Unable to write " + dataSize + " in a space of " + indexDetails.getSize()); } final long offset = indexDetails.getOffset(); - final Output o = new Output(Channels.newOutputStream(dataFileChannel.position(offset))); + final Output o = new Output(Channels.newOutputStream(dataFileChannel.position(offset)), dataSize); data.getWriter().write(o); o.flush(); } @@ -157,7 +162,7 @@ public class FileIndexManager implements IndexManager { } private long createIndexMetadata(IndexDetails indexDetails) { - long newIndex = firstAllocableIndex++; + Long newIndex = firstAllocableIndex++; loadedIndices.put(newIndex, indexDetails); dirtyLoadedIndices.add(newIndex); removedIndices.remove(newIndex); @@ -176,17 +181,19 @@ public class FileIndexManager implements IndexManager { return null; } SeekableByteChannel currentMetadataFileChannel = metadataFileChannel.position(metadataPosition); - ByteBuffer currentMetadataByteBuffer = ByteBuffer.allocateDirect(IndexDetails.TOTAL_BYTES); - currentMetadataFileChannel.read(currentMetadataByteBuffer); - currentMetadataByteBuffer.flip(); - // If it's not deleted continue - if ((currentMetadataByteBuffer.getInt() & IndexDetails.MASK_DELETED) == 0) { - final long offset = currentMetadataByteBuffer.getLong(); - final int size = currentMetadataByteBuffer.getInt(); - final int type = currentMetadataByteBuffer.getInt(); - final IndexDetails indexDetails = new IndexDetails(offset, size, type); - editIndex(index, indexDetails); - return indexDetails; + synchronized (metadataByteBufferLock) { + metadataByteBuffer.rewind(); + currentMetadataFileChannel.read(metadataByteBuffer); + metadataByteBuffer.rewind(); + // If it's not deleted continue + if ((metadataByteBuffer.getInt() & IndexDetails.MASK_DELETED) == 0) { + final long offset = metadataByteBuffer.getLong(); + final int size = metadataByteBuffer.getInt(); + final int type = metadataByteBuffer.getInt(); + final IndexDetails indexDetails = new IndexDetails(offset, size, type); + editIndex(index, indexDetails); + return indexDetails; + } } // No results found. Returning null @@ -215,30 +222,33 @@ public class FileIndexManager implements IndexManager { // Update indices metadata SeekableByteChannel metadata = metadataFileChannel; - ByteBuffer metadataEntryBuffer = ByteBuffer.allocateDirect(IndexDetails.TOTAL_BYTES); long lastIndex = -2; for (Long index : dirtyLoadedIndices) { IndexDetails indexDetails = loadedIndices.get(index); if (index - lastIndex != 1) { metadata = metadata.position(index * IndexDetails.TOTAL_BYTES); } - metadataEntryBuffer.clear(); - metadataEntryBuffer.putInt(0); - metadataEntryBuffer.putLong(indexDetails.getOffset()); - metadataEntryBuffer.putInt(indexDetails.getSize()); - metadataEntryBuffer.putInt(indexDetails.getType()); - metadataEntryBuffer.flip(); - metadata.write(metadataEntryBuffer); + synchronized (metadataByteBufferLock) { + metadataByteBuffer.rewind(); + metadataByteBuffer.putInt(0); + metadataByteBuffer.putLong(indexDetails.getOffset()); + metadataByteBuffer.putInt(indexDetails.getSize()); + metadataByteBuffer.putInt(indexDetails.getType()); + metadataByteBuffer.rewind(); + metadata.write(metadataByteBuffer); + } lastIndex = index; } // Remove removed indices - ByteBuffer updatedMaskBuffer = ByteBuffer.allocateDirect(1); for (Long index : removedIndices) { metadata = metadata.position(index * IndexDetails.TOTAL_BYTES); - updatedMaskBuffer.putInt(IndexDetails.MASK_DELETED); - updatedMaskBuffer.flip(); - metadata.write(updatedMaskBuffer); + synchronized (maskByteBufferBufferLock) { + maskByteBuffer.rewind(); + maskByteBuffer.putInt(IndexDetails.MASK_DELETED); + maskByteBuffer.rewind(); + metadata.write(maskByteBuffer); + } } fileAllocator.close(); }