Class ScratchFile
- java.lang.Object
-
- org.apache.pdfbox.io.ScratchFile
-
- All Implemented Interfaces:
java.io.Closeable,java.lang.AutoCloseable,RandomAccessStreamCache
public class ScratchFile extends java.lang.Object implements RandomAccessStreamCache
Implements a memory page handling mechanism as base for creating (multiple)RandomAccessbuffers each having its set of pages (implemented byScratchFileBuffer). A buffer is created callingcreateBuffer().Pages can be stored in main memory or in a temporary file. A mixed mode is supported storing a certain amount of pages in memory and only the additional ones in temporary file (defined by maximum main memory to be used).
Pages can be marked as 'free' in order to re-use them. For in-memory pages this will release the used memory while for pages in temporary file this simply marks the area as free to re-use.
If a temporary file was created (done with the first page to be stored in temporary file) it is deleted when
close()is called.Using this class for
RandomAccessbuffers allows for a direct control on the maximum memory usage and allows processing large files for which we otherwise would get anOutOfMemoryErrorin case of usingRandomAccessReadBuffer.This base class for providing pages is thread safe (the buffer implementations are not).
-
-
Nested Class Summary
-
Nested classes/interfaces inherited from interface org.apache.pdfbox.io.RandomAccessStreamCache
RandomAccessStreamCache.StreamCacheCreateFunction
-
-
Field Summary
Fields Modifier and Type Field Description private java.util.List<ScratchFileBuffer>buffersprivate static intENLARGE_PAGE_COUNTnumber of pages by which we enlarge the scratch file (reduce I/O-operations)private java.io.Filefilescratch file; only to be accessed under synchronization ofioLockprivate java.util.BitSetfreePagesprivate static intINIT_UNRESTRICTED_MAINMEM_PAGECOUNTin case of unrestricted main memory usage this is the initial number of pagesinMemoryPagesis setup forprivate intinMemoryMaxPageCountprivate byte[][]inMemoryPagesholds pointers to in-memory page content; will be initialized once in case of restricted main memory, otherwise it is enlarged as needed and first initialized to a size ofINIT_UNRESTRICTED_MAINMEM_PAGECOUNTprivate java.lang.ObjectioLockprivate booleanisClosedprivate static org.apache.commons.logging.LogLOGprivate booleanmaxMainMemoryIsRestrictedprivate intmaxPageCountprivate static intPAGE_SIZEprivate intpageCountprivate java.io.RandomAccessFilerafrandom access to scratch file; only to be accessed under synchronization ofioLockprivate java.io.FilescratchFileDirectoryprivate booleanuseScratchFile
-
Constructor Summary
Constructors Constructor Description ScratchFile(java.io.File scratchFileDirectory)Initializes page handler.ScratchFile(MemoryUsageSetting memUsageSetting)Initializes page handler.
-
Method Summary
All Methods Static Methods Instance Methods Concrete Methods Modifier and Type Method Description (package private) voidcheckClosed()Checks if this page handler has already been closed.voidclose()Closes and deletes the temporary file.RandomAccesscreateBuffer()Creates a new buffer using this page handler.private voidenlarge()This will provide new free pages by either enlarging the scratch file by a number of pages defined byENLARGE_PAGE_COUNT- in case scratch file usage is allowed - or increase theinMemoryPagesarray in case main memory was not restricted.static ScratchFilegetMainMemoryOnlyInstance()Getter for an instance using only unrestricted main memory for buffering (same asnew ScratchFile(MemoryUsageSetting.setupMainMemoryOnly())).static ScratchFilegetMainMemoryOnlyInstance(long maxMainMemoryBytes)Getter for an instance to only use main-memory with the defined maximum.(package private) intgetNewPage()Returns a new free page, either from free page pool or by enlarging scratch file (may be created).(package private) intgetPageSize()Returns byte size of a page.private voidinitPages()(package private) voidmarkPagesAsFree(int[] pageIndexes, int off, int count)Allows a buffer which is cleared/closed to release its pages to be re-used.(package private) byte[]readPage(int pageIdx)Reads the page with specified index.(package private) voidremoveBuffer(ScratchFileBuffer buffer)(package private) voidwritePage(int pageIdx, byte[] page)Writes updated page.
-
-
-
Field Detail
-
LOG
private static final org.apache.commons.logging.Log LOG
-
ENLARGE_PAGE_COUNT
private static final int ENLARGE_PAGE_COUNT
number of pages by which we enlarge the scratch file (reduce I/O-operations)- See Also:
- Constant Field Values
-
INIT_UNRESTRICTED_MAINMEM_PAGECOUNT
private static final int INIT_UNRESTRICTED_MAINMEM_PAGECOUNT
in case of unrestricted main memory usage this is the initial number of pagesinMemoryPagesis setup for- See Also:
- Constant Field Values
-
PAGE_SIZE
private static final int PAGE_SIZE
- See Also:
- Constant Field Values
-
ioLock
private final java.lang.Object ioLock
-
scratchFileDirectory
private final java.io.File scratchFileDirectory
-
file
private java.io.File file
scratch file; only to be accessed under synchronization ofioLock
-
raf
private java.io.RandomAccessFile raf
random access to scratch file; only to be accessed under synchronization ofioLock
-
pageCount
private volatile int pageCount
-
freePages
private final java.util.BitSet freePages
-
inMemoryPages
private volatile byte[][] inMemoryPages
holds pointers to in-memory page content; will be initialized once in case of restricted main memory, otherwise it is enlarged as needed and first initialized to a size ofINIT_UNRESTRICTED_MAINMEM_PAGECOUNT
-
inMemoryMaxPageCount
private final int inMemoryMaxPageCount
-
maxPageCount
private final int maxPageCount
-
useScratchFile
private final boolean useScratchFile
-
maxMainMemoryIsRestricted
private final boolean maxMainMemoryIsRestricted
-
buffers
private final java.util.List<ScratchFileBuffer> buffers
-
isClosed
private volatile boolean isClosed
-
-
Constructor Detail
-
ScratchFile
public ScratchFile(java.io.File scratchFileDirectory) throws java.io.IOExceptionInitializes page handler. If ascratchFileDirectoryis supplied, then the scratch file will be created in that directory.All pages will be stored in the scratch file.
- Parameters:
scratchFileDirectory- The directory in which to create the scratch file ornullto created it in the default temporary directory.- Throws:
java.io.IOException- If scratch file directory was given but don't exist.
-
ScratchFile
public ScratchFile(MemoryUsageSetting memUsageSetting) throws java.io.IOException
Initializes page handler. If ascratchFileDirectoryis supplied, then the scratch file will be created in that directory.Depending on the size of allowed memory usage a number of pages (memorySize/
PAGE_SIZE) will be stored in-memory and only additional pages will be written to/read from scratch file.- Parameters:
memUsageSetting- set how memory/temporary files are used for buffering streams etc.- Throws:
java.io.IOException- If scratch file directory was given but don't exist.
-
-
Method Detail
-
initPages
private void initPages()
-
getMainMemoryOnlyInstance
public static ScratchFile getMainMemoryOnlyInstance()
Getter for an instance using only unrestricted main memory for buffering (same asnew ScratchFile(MemoryUsageSetting.setupMainMemoryOnly())).- Returns:
- instance configured to only use main memory with no size restriction
-
getMainMemoryOnlyInstance
public static ScratchFile getMainMemoryOnlyInstance(long maxMainMemoryBytes)
Getter for an instance to only use main-memory with the defined maximum.- Parameters:
maxMainMemoryBytes- maximum number of main-memory to be used;-1for no restriction;0will also be interpreted here as no restriction- Returns:
- instance configured to only use main memory with no size restriction or null if cannot create scratch file
-
getNewPage
int getNewPage() throws java.io.IOExceptionReturns a new free page, either from free page pool or by enlarging scratch file (may be created).- Returns:
- index of new page
- Throws:
java.io.IOException
-
enlarge
private void enlarge() throws java.io.IOExceptionThis will provide new free pages by either enlarging the scratch file by a number of pages defined byENLARGE_PAGE_COUNT- in case scratch file usage is allowed - or increase theinMemoryPagesarray in case main memory was not restricted. If neither of both is allowed/the case than free pages count won't be changed. The same is true if no new pages could be added because we reached the maximum ofInteger.MAX_VALUEpages.If scratch file usage is allowed and scratch file does not exist already it will be created.
Only to be called under synchronization on
freePages.- Throws:
java.io.IOException
-
getPageSize
int getPageSize()
Returns byte size of a page.- Returns:
- byte size of a page
-
readPage
byte[] readPage(int pageIdx) throws java.io.IOExceptionReads the page with specified index.- Parameters:
pageIdx- index of page to read- Returns:
- byte array of size
PAGE_SIZEfilled with page data read from file - Throws:
java.io.IOException
-
writePage
void writePage(int pageIdx, byte[] page) throws java.io.IOExceptionWrites updated page. Page is either kept in-memory if pageIdx <inMemoryMaxPageCountor is written to scratch file.Provided page byte array must not be re-used for other pages since we store it as is in case of in-memory handling.
- Parameters:
pageIdx- index of page to writepage- page to write (length has to be 4096)- Throws:
java.io.IOException- in case page index is out of range or page has wrong length or writing to file failed
-
checkClosed
void checkClosed() throws java.io.IOExceptionChecks if this page handler has already been closed. If so, anIOExceptionis thrown.- Throws:
java.io.IOException- Ifclose()has already been called.
-
createBuffer
public RandomAccess createBuffer() throws java.io.IOException
Creates a new buffer using this page handler.- Specified by:
createBufferin interfaceRandomAccessStreamCache- Returns:
- A new buffer.
- Throws:
java.io.IOException- If an error occurred.
-
removeBuffer
void removeBuffer(ScratchFileBuffer buffer)
-
markPagesAsFree
void markPagesAsFree(int[] pageIndexes, int off, int count)Allows a buffer which is cleared/closed to release its pages to be re-used.- Parameters:
pageIndexes- pages indexes of pages to releasecount- number of page indexes contained in provided array
-
close
public void close() throws java.io.IOExceptionCloses and deletes the temporary file. No further interaction with the scratch file or associated buffers can happen after this method is called. It also releases in-memory pages.- Specified by:
closein interfacejava.lang.AutoCloseable- Specified by:
closein interfacejava.io.Closeable- Throws:
java.io.IOException- If there was a problem closing or deleting the temporary file.
-
-