Fixes #2425 - Review BufferUtil.isMappedBuffer(). (#2432)

Now explicitly using a _mappedBuffer field in
CachedContentFactory.CachedHttpContent.
Deprecated BufferUtil.isMappedBuffer().

Signed-off-by: Simone Bordet <simone.bordet@gmail.com>
This commit is contained in:
Simone Bordet 2018-04-12 10:36:57 +02:00 committed by GitHub
parent b09760ca9a
commit 7629a8f98f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 50 additions and 80 deletions

View File

@ -397,6 +397,7 @@ public class CachedContentFactory implements HttpContent.ContentFactory
private final Map<CompressedContentFormat, CachedPrecompressedHttpContent> _precompressed;
private final AtomicReference<ByteBuffer> _indirectBuffer = new AtomicReference<>();
private final AtomicReference<ByteBuffer> _directBuffer = new AtomicReference<>();
private final AtomicReference<ByteBuffer> _mappedBuffer = new AtomicReference<>();
private volatile long _lastAccessed;
CachedHttpContent(String pathInContext, Resource resource, Map<CompressedContentFormat, CachedHttpContent> precompressedResources)
@ -481,15 +482,16 @@ public class CachedContentFactory implements HttpContent.ContentFactory
protected void invalidate()
{
ByteBuffer indirect = _indirectBuffer.get();
if (indirect != null && _indirectBuffer.compareAndSet(indirect, null))
ByteBuffer indirect = _indirectBuffer.getAndSet(null);
if (indirect != null)
_cachedSize.addAndGet(-BufferUtil.length(indirect));
ByteBuffer direct = _directBuffer.get();
if (direct != null && !BufferUtil.isMappedBuffer(direct) && _directBuffer.compareAndSet(direct, null))
ByteBuffer direct = _directBuffer.getAndSet(null);
if (direct != null)
_cachedSize.addAndGet(-BufferUtil.length(direct));
_mappedBuffer.getAndSet(null);
_cachedFiles.decrementAndGet();
_resource.close();
}
@ -574,26 +576,42 @@ public class CachedContentFactory implements HttpContent.ContentFactory
@Override
public ByteBuffer getDirectBuffer()
{
ByteBuffer buffer = _directBuffer.get();
ByteBuffer buffer = _mappedBuffer.get();
if (buffer == null)
buffer = _directBuffer.get();
if (buffer == null)
{
ByteBuffer mapped = CachedContentFactory.this.getMappedBuffer(_resource);
ByteBuffer direct = mapped == null ? CachedContentFactory.this.getDirectBuffer(_resource) : mapped;
if (direct == null)
LOG.warn("Could not load " + this);
else if (_directBuffer.compareAndSet(null, direct))
if (mapped != null)
{
buffer = direct;
if (mapped == null && _cachedSize.addAndGet(BufferUtil.length(buffer)) > _maxCacheSize)
shrinkCache();
if (_mappedBuffer.compareAndSet(null, mapped))
buffer = mapped;
else
buffer = _mappedBuffer.get();
}
else
buffer = _directBuffer.get();
{
ByteBuffer direct = CachedContentFactory.this.getDirectBuffer(_resource);
if (direct != null)
{
if (_directBuffer.compareAndSet(null, direct))
{
buffer = direct;
if (_cachedSize.addAndGet(BufferUtil.length(buffer)) > _maxCacheSize)
shrinkCache();
}
else
{
buffer = _directBuffer.get();
}
}
else
{
LOG.warn("Could not load " + this);
}
}
}
if (buffer == null)
return null;
return buffer.asReadOnlyBuffer();
return buffer == null ? null : buffer.asReadOnlyBuffer();
}
@Override

View File

@ -26,7 +26,6 @@ import java.io.RandomAccessFile;
import java.nio.Buffer;
import java.nio.BufferOverflowException;
import java.nio.ByteBuffer;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.channels.FileChannel.MapMode;
import java.nio.charset.Charset;
@ -922,25 +921,17 @@ public class BufferUtil
}
}
/**
* @param buffer the buffer to test
* @return {@code false}
* @deprecated don't use - there is no way to reliably tell if a ByteBuffer is mapped.
*/
@Deprecated
public static boolean isMappedBuffer(ByteBuffer buffer)
{
if (!(buffer instanceof MappedByteBuffer))
return false;
MappedByteBuffer mapped = (MappedByteBuffer) buffer;
try
{
// Check if it really is a mapped buffer
mapped.isLoaded();
return true;
}
catch(UnsupportedOperationException e)
{
return false;
}
return false;
}
public static ByteBuffer toBuffer(Resource resource,boolean direct) throws IOException
{
int len=(int)resource.length();

View File

@ -19,20 +19,10 @@
package org.eclipse.jetty.util;
import static org.hamcrest.CoreMatchers.containsString;
import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.nio.BufferOverflowException;
import java.nio.ByteBuffer;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.concurrent.ThreadLocalRandom;
@ -42,6 +32,12 @@ import org.junit.Assert;
import org.junit.Ignore;
import org.junit.Test;
import static org.hamcrest.CoreMatchers.containsString;
import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
public class BufferUtilTest
{
@Test
@ -352,39 +348,4 @@ public class BufferUtilTest
BufferUtil.writeTo(buffer.asReadOnlyBuffer(), out);
assertThat("Bytes in out equal bytes in buffer", Arrays.equals(bytes, out.toByteArray()), is(true));
}
@Test
public void testMappedFile() throws Exception
{
String data="Now is the time for all good men to come to the aid of the party";
File file = File.createTempFile("test",".txt");
file.deleteOnExit();
try(FileWriter out = new FileWriter(file))
{
out.write(data);
}
ByteBuffer mapped = BufferUtil.toMappedBuffer(file);
assertEquals(data,BufferUtil.toString(mapped));
assertTrue(BufferUtil.isMappedBuffer(mapped));
ByteBuffer direct = BufferUtil.allocateDirect(data.length());
BufferUtil.clearToFill(direct);
direct.put(data.getBytes(StandardCharsets.ISO_8859_1));
BufferUtil.flipToFlush(direct, 0);
assertEquals(data,BufferUtil.toString(direct));
assertFalse(BufferUtil.isMappedBuffer(direct));
ByteBuffer slice = direct.slice();
assertEquals(data,BufferUtil.toString(slice));
assertFalse(BufferUtil.isMappedBuffer(slice));
ByteBuffer duplicate = direct.duplicate();
assertEquals(data,BufferUtil.toString(duplicate));
assertFalse(BufferUtil.isMappedBuffer(duplicate));
ByteBuffer readonly = direct.asReadOnlyBuffer();
assertEquals(data,BufferUtil.toString(readonly));
assertFalse(BufferUtil.isMappedBuffer(readonly));
}
}