You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@pdfbox.apache.org by le...@apache.org on 2022/12/03 16:11:55 UTC
svn commit: r1905718 - /pdfbox/trunk/io/src/main/java/org/apache/pdfbox/io/RandomAccessReadBufferedFile.java
Author: lehmi
Date: Sat Dec 3 16:11:55 2022
New Revision: 1905718
URL: http://svn.apache.org/viewvc?rev=1905718&view=rev
Log:
PDFBOX-5550: share RandomAccessReadBufferedFile when creating a new view within the same thread for the file
Modified:
pdfbox/trunk/io/src/main/java/org/apache/pdfbox/io/RandomAccessReadBufferedFile.java
Modified: pdfbox/trunk/io/src/main/java/org/apache/pdfbox/io/RandomAccessReadBufferedFile.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/io/src/main/java/org/apache/pdfbox/io/RandomAccessReadBufferedFile.java?rev=1905718&r1=1905717&r2=1905718&view=diff
==============================================================================
--- pdfbox/trunk/io/src/main/java/org/apache/pdfbox/io/RandomAccessReadBufferedFile.java (original)
+++ pdfbox/trunk/io/src/main/java/org/apache/pdfbox/io/RandomAccessReadBufferedFile.java Sat Dec 3 16:11:55 2022
@@ -21,8 +21,11 @@ import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.file.StandardOpenOption;
+import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.stream.Collectors;
/**
* Provides random access to portions of a file combined with buffered reading of content. Start of next bytes to read
@@ -39,6 +42,8 @@ public class RandomAccessReadBufferedFil
private static final long PAGE_OFFSET_MASK = -1L << PAGE_SIZE_SHIFT;
private static final int MAX_CACHED_PAGES = 1000;
+ private static ThreadLocal<Map<String, ThreadLocalRandomAccessRead>> randomAccessFiles = new ThreadLocal<Map<String, ThreadLocalRandomAccessRead>>();
+
private ByteBuffer lastRemovedCachePage = null;
/** Create a LRU page cache. */
@@ -92,6 +97,7 @@ public class RandomAccessReadBufferedFil
this.file = file;
fileChannel = FileChannel.open(file.toPath(), StandardOpenOption.READ);
fileLength = file.length();
+ randomAccessFiles.set(new ConcurrentHashMap<>(1));
seek(0);
}
@@ -225,9 +231,19 @@ public class RandomAccessReadBufferedFil
@Override
public void close() throws IOException
{
- fileChannel.close();
- pageCache.clear();
- isClosed = true;
+ Map<String, ThreadLocalRandomAccessRead> map = randomAccessFiles.get();
+ ThreadLocalRandomAccessRead tlRandomAccessRead = map.get(file.toString());
+ if (tlRandomAccessRead != null)
+ {
+ tlRandomAccessRead.removeClosedViews();
+ }
+ if (tlRandomAccessRead == null || tlRandomAccessRead.allViewsClosed())
+ {
+ map.remove(file.toString());
+ fileChannel.close();
+ pageCache.clear();
+ isClosed = true;
+ }
}
@Override
@@ -258,7 +274,53 @@ public class RandomAccessReadBufferedFil
public RandomAccessReadView createView(long startPosition, long streamLength) throws IOException
{
checkClosed();
- return new RandomAccessReadView(new RandomAccessReadBufferedFile(file), startPosition,
- streamLength, true);
+ Map<String, ThreadLocalRandomAccessRead> mapRandomAccessRead = randomAccessFiles.get();
+ ThreadLocalRandomAccessRead tlRandomAccessRead = mapRandomAccessRead.get(file.toString());
+ boolean newlyCreated = false;
+ if (tlRandomAccessRead == null || tlRandomAccessRead.getRandomAccessRead().isClosed())
+ {
+ tlRandomAccessRead = new ThreadLocalRandomAccessRead(
+ new RandomAccessReadBufferedFile(file));
+ mapRandomAccessRead.put(file.toString(), tlRandomAccessRead);
+ newlyCreated = true;
+ }
+ RandomAccessReadView view = new RandomAccessReadView(
+ tlRandomAccessRead.getRandomAccessRead(), startPosition, streamLength,
+ newlyCreated);
+ tlRandomAccessRead.addRandomAccessView(view);
+ return view;
+ }
+
+ private class ThreadLocalRandomAccessRead
+ {
+ private final RandomAccessReadBufferedFile randomAccessReadBufferedFile;
+ private final HashSet<RandomAccessReadView> randomAccessViews;
+
+ ThreadLocalRandomAccessRead(RandomAccessReadBufferedFile randomAccessRead)
+ {
+ randomAccessReadBufferedFile = randomAccessRead;
+ randomAccessViews = new HashSet<>();
+ }
+
+ public RandomAccessReadBufferedFile getRandomAccessRead()
+ {
+ return randomAccessReadBufferedFile;
+ }
+
+ public boolean addRandomAccessView(RandomAccessReadView randomAccessReadView)
+ {
+ return randomAccessViews.add(randomAccessReadView);
+ }
+
+ public void removeClosedViews()
+ {
+ randomAccessViews.removeAll(randomAccessViews.stream()
+ .filter(RandomAccessReadView::isClosed).collect(Collectors.toList()));
+ }
+
+ public boolean allViewsClosed()
+ {
+ return randomAccessViews.isEmpty();
+ }
}
-}
+}
\ No newline at end of file