|
|||||||||
| PREV CLASS NEXT CLASS | FRAMES NO FRAMES | ||||||||
| SUMMARY: NESTED | FIELD | CONSTR | METHOD | DETAIL: FIELD | CONSTR | METHOD | ||||||||
java.lang.Objectorg.apache.derby.impl.store.raw.data.BaseContainer
org.apache.derby.impl.store.raw.data.FileContainer
org.apache.derby.impl.store.raw.data.RAFContainer
org.apache.derby.impl.store.raw.data.RAFContainer4
class RAFContainer4
RAFContainer4 overrides a few methods in FileContainer/RAFContainer in order to use FileChannel from Java 1.4's New IO framework to issue multiple IO operations to the same file concurrently instead of strictly serializing IO operations using a mutex on the container object. Since we compile with Java 1.4, the override "annotations" are inside the method javadoc headers.
Note that our requests for multiple concurrent IOs may be serialized further down in the IO stack - this is entirely up to the JVM and OS. However, at least in Linux on Sun's 1.4.2_09 JVM we see the desired behavior: The FileChannel.read/write(ByteBuffer buf, long position) calls map to pread/pwrite system calls, which enable efficient IO to the same file descriptor by multiple threads.
This whole class should be merged back into RAFContainer when Derby officially stops supporting Java 1.3.
Significant behavior changes from RAFContainer:
FileChannel| Field Summary | |
|---|---|
private java.lang.Object |
channelCleanupMonitor
|
private ContainerKey |
currentIdentity
|
private boolean |
giveUpIO
|
private java.lang.Object |
giveUpIOm
|
private int |
iosInProgress
For debugging - will be incremented when an IO is started, decremented when it is done. |
private java.nio.channels.FileChannel |
ourChannel
This channel will be retrieved from RAFContainer's fileData member when fileData is set. |
private boolean |
restoreChannelInProgress
|
private int |
threadsInPageIO
|
| Fields inherited from class org.apache.derby.impl.store.raw.data.RAFContainer |
|---|
fileData, needsSync |
| Fields inherited from class org.apache.derby.impl.store.raw.data.FileContainer |
|---|
allocCache, canUpdate, CHECKSUM_SIZE, CONTAINER_INFO_SIZE, containerCache, containerInfo, containerVersion, dataFactory, estimatedRowCount, FIRST_ALLOC_PAGE_NUMBER, FIRST_ALLOC_PAGE_OFFSET, firstAllocPageNumber, firstAllocPageOffset, formatIdInteger, initialPages, isDirty, lastLogInstant, minimumRecordSize, pageCache, pageSize, preDirty, SPACE_TRACE, spareSpace |
| Fields inherited from class org.apache.derby.impl.store.raw.data.BaseContainer |
|---|
identity, isCommittedDrop, isDropped, isReusableRecordId |
| Constructor Summary | |
|---|---|
RAFContainer4(BaseDataFileFactory factory)
|
|
| Method Summary | |
|---|---|
private void |
awaitRestoreChannel(java.lang.Exception e,
boolean stealthMode)
Use when seeing an exception during IO and when another thread is presumably doing the recovery. |
(package private) void |
closeContainer()
override of RAFContainer#closeContainer |
(package private) void |
createContainer(ContainerKey newIdentity)
override of RAFContainer#createContainer |
private static void |
debugTrace(java.lang.String msg)
|
private java.nio.channels.FileChannel |
getChannel()
Return the file channel for the current value of the fileData
field. |
private java.nio.channels.FileChannel |
getChannel(StorageRandomAccessFile file)
Return the FileChannel for the specified
StorageRandomAccessFile if it is a RandomAccessFile. |
(package private) byte[] |
getEmbryonicPage(StorageRandomAccessFile file,
long offset)
Read an embryonic page (that is, a section of the first alloc page that is so large that we know all the borrowed space is included in it) from the specified offset in a StorageRandomAccessFile. |
private void |
handleClosedChannel(java.nio.channels.ClosedChannelException e,
boolean stealthMode,
int retries)
This method handles what to do when, during a NIO operation we receive a ClosedChannelException. |
(package private) boolean |
openContainer(ContainerKey newIdentity)
Open a container. |
private void |
readFull(java.nio.ByteBuffer dstBuffer,
java.nio.channels.FileChannel srcChannel,
long position)
Attempts to fill buf completely from start until it's full. |
protected void |
readPage(long pageNumber,
byte[] pageData)
Read a page into the supplied array. |
private void |
readPage(long pageNumber,
byte[] pageData,
long offset)
Read a page into the supplied array. |
private void |
readPage0(long pageNumber,
byte[] pageData,
long offset)
|
private boolean |
recoverContainerAfterInterrupt(java.lang.String whence,
boolean stealthMode)
Use this when the thread has received a ClosedByInterruptException (or, prior to JDK 1.7 it may also be AsynchronousCloseException - a bug) exception during IO and its interruped flag is also set. |
private void |
reopen()
When the existing channel ( ourChannel) has been closed due to
interrupt, we need to reopen the underlying RAF to get a fresh channel
so we can resume IO. |
(package private) void |
writeAtOffset(StorageRandomAccessFile file,
byte[] bytes,
long offset)
Write a sequence of bytes at the given offset in a file. |
private void |
writeFull(java.nio.ByteBuffer srcBuffer,
java.nio.channels.FileChannel dstChannel,
long position)
Attempts to write buf completely from start until end, at the given position in the destination fileChannel. |
protected void |
writePage(long pageNumber,
byte[] pageData,
boolean syncPage)
Write a page from the supplied array. |
private void |
writePage0(long pageNumber,
byte[] pageData,
boolean syncPage)
|
| Methods inherited from class org.apache.derby.impl.store.raw.data.RAFContainer |
|---|
backupContainer, clean, encryptOrDecryptContainer, flushAll, getFileName, getRandomAccessFile, isDirty, preAllocate, privGetFileName, removeContainer, removeFile, reopenContainer, run, truncatePages, updatePageArray |
| Methods inherited from class org.apache.derby.impl.store.raw.data.BaseContainer |
|---|
addPage, compressContainer, fillInIdentity, getAllocPage, getAnyPage, getCommittedDropState, getContainerId, getContainerStatus, getDeallocLock, getDroppedState, getFirstPage, getIdentity, getNextPage, getSegmentId, isReusableRecordId, lockAttributes, lockerAlwaysCompatible, lockEvent, removePage, requestCompatible, setCommittedDropState, setDroppedState, setReusableRecordIdState, truncate, unlockEvent, use |
| Methods inherited from class java.lang.Object |
|---|
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait |
| Methods inherited from interface org.apache.derby.iapi.services.cache.Cacheable |
|---|
getIdentity |
| Field Detail |
|---|
private java.nio.channels.FileChannel ourChannel
private final java.lang.Object channelCleanupMonitor
private volatile int threadsInPageIO
private volatile boolean restoreChannelInProgress
private boolean giveUpIO
private final java.lang.Object giveUpIOm
private int iosInProgress
private ContainerKey currentIdentity
| Constructor Detail |
|---|
public RAFContainer4(BaseDataFileFactory factory)
| Method Detail |
|---|
private java.nio.channels.FileChannel getChannel(StorageRandomAccessFile file)
FileChannel for the specified
StorageRandomAccessFile if it is a RandomAccessFile.
Otherwise, return null.
file - the file to get the channel for
FileChannel if file is an instance of
RandomAccessFile, null otherwiseprivate java.nio.channels.FileChannel getChannel()
Return the file channel for the current value of the fileData
field. If fileData doesn't support file channels, return
null.
Callers of this method must synchronize on the container object since
two shared fields (fileData and ourChannel) are
accessed.
FileChannel object, if supported, or null
boolean openContainer(ContainerKey newIdentity)
throws StandardException
FileContainerLonger descrption of routine.
Open a container. Open the file that maps to this container, if the
file does not exist then we assume the container was never created.
If the file exists but we have trouble opening it then we throw some
exception.
MT - single thread required - Enforced by cache manager.
openContainer in class RAFContainerStandardException - Standard exception policy.
void createContainer(ContainerKey newIdentity)
throws StandardException
createContainer in class RAFContainerStandardException - Derby Standard error policy
private void reopen()
throws StandardException
ourChannel) has been closed due to
interrupt, we need to reopen the underlying RAF to get a fresh channel
so we can resume IO.
StandardExceptionvoid closeContainer()
closeContainer in class RAFContainer
protected void readPage(long pageNumber,
byte[] pageData)
throws java.io.IOException,
StandardException
readPage in class RAFContainerjava.io.IOException - exception reading page
StandardException - Standard Derby error policy
private void readPage(long pageNumber,
byte[] pageData,
long offset)
throws java.io.IOException,
StandardException
pageNumber - the page number to read data from, or -1 (called from
getEmbryonicPage)pageData - the buffer to read data intooffset - -1 normally (not used since offset is computed from
pageNumber), but used if pageNumber == -1
(getEmbryonicPage)
java.io.IOException - exception reading page
StandardException - Standard Derby error policy
private void readPage0(long pageNumber,
byte[] pageData,
long offset)
throws java.io.IOException,
StandardException
java.io.IOException
StandardException
protected void writePage(long pageNumber,
byte[] pageData,
boolean syncPage)
throws java.io.IOException,
StandardException
writePage in class RAFContainerStandardException - Standard Derby error policy
java.io.IOException - IO error accessing page
private void handleClosedChannel(java.nio.channels.ClosedChannelException e,
boolean stealthMode,
int retries)
throws StandardException
ClosedChannelException. Note the specialization hierarchy:
ClosedChannelException -> AsynchronousCloseException ->
ClosedByInterruptException
If e is a ClosedByInterruptException, we normally start
container recovery, i.e. we need to reopen the random access file so we
get get a new interruptible channel and continue IO.
If e is a AsynchronousCloseException or a plain ClosedChannelException, the behavior depends of stealthMode:
If stealthMode == false, the method will wait for
another thread tp finish recovering the IO channel before returning.
If stealthMode == true, the method throws InterruptDetectedException, allowing retry at a higher level in the
code. The reason for this is that we sometimes need to release monitors
on objects needed by the recovery thread.
e - Should be an instance of ClosedChannelException.stealthMode - If true, do retry at a higher levelretries - Give up waiting for another thread to reopen the channel
when retries reaches 0. Only applicable if stealthMode == false.
InterruptDetectedException - if retry at higher level is required
stealthMode == true.
StandardException - standard error policy, incl. when we give up
waiting for another thread to reopen channel
private void awaitRestoreChannel(java.lang.Exception e,
boolean stealthMode)
throws StandardException
stealthMode == false, wait for another thread to recover the
container after an interrupt. If stealthMode == true, throw
internal exception InterruptDetectedException to do retry from
higher in the stack.
If stealthMode == false, maximum wait time for the container to
become available again is determined by the product InterruptStatus.MAX_INTERRUPT_RETRIES *
InterruptStatus.INTERRUPT_RETRY_SLEEP.
There is a chance this thread will not see any recovery occuring (yet),
in which case it waits for a bit and just returns, so the caller must
retry IO until success.
If for some reason the recovering thread has given up on resurrecting
the container, cf #giveUpIO, the method throws FILE_IO_INTERRUPTED.
e - the exception we saw during IOstealthMode - true if the thread doing IO in stealth mode
StandardException - InterruptDetectedException and normal
error policy
private boolean recoverContainerAfterInterrupt(java.lang.String whence,
boolean stealthMode)
throws StandardException
whence - caller site (debug info)stealthMode - don't update threadsInPageIO if true
StandardException
private void writePage0(long pageNumber,
byte[] pageData,
boolean syncPage)
throws java.io.IOException,
StandardException
java.io.IOException
StandardException
void writeAtOffset(StorageRandomAccessFile file,
byte[] bytes,
long offset)
throws java.io.IOException,
StandardException
handleClosedChannel.
This presumes that IO retry happens at a higher level, i.e. the
caller(s) must be prepared to handle InterruptDetectedException.
This method overrides FileContainer#writeAtOffset.
writeAtOffset in class FileContainerfile - the file to write tobytes - the bytes to writeoffset - the offset to start writing at
java.io.IOException - if an I/O error occurs while writing
StandardException - Derby Standard error policy
byte[] getEmbryonicPage(StorageRandomAccessFile file,
long offset)
throws java.io.IOException,
StandardException
StorageRandomAccessFile.
override of FileContainer#getEmbryonicPage
getEmbryonicPage in class FileContainerfile - the file to read fromoffset - where to start reading (normally
FileContainer.FIRST_ALLOC_PAGE_OFFSET)
java.io.IOException - if an I/O error occurs while reading
StandardException - if thread is interrupted.
private void readFull(java.nio.ByteBuffer dstBuffer,
java.nio.channels.FileChannel srcChannel,
long position)
throws java.io.IOException,
StandardException
dstBuffer - buffer to read intosrcChannel - channel to read fromposition - file position from where to read
java.io.IOException - if an I/O error occurs while reading
StandardException - If thread is interrupted.
private void writeFull(java.nio.ByteBuffer srcBuffer,
java.nio.channels.FileChannel dstChannel,
long position)
throws java.io.IOException
srcBuffer - buffer to writedstChannel - channel to write toposition - file position to start writing at
java.io.IOException - if an I/O error occurs while writing
StandardException - If thread is interrupted.private static void debugTrace(java.lang.String msg)
|
Built on Wed 2013-06-12 15:21:56+0000, from revision ??? | ||||||||
| PREV CLASS NEXT CLASS | FRAMES NO FRAMES | ||||||||
| SUMMARY: NESTED | FIELD | CONSTR | METHOD | DETAIL: FIELD | CONSTR | METHOD | ||||||||