/* * Assume that the window is properly positioned. Try to fill the read * buffer with data from this file handle, starting at the location * indicated by the starting offset field. If this file contains more * data, return true. If this file doesn't contain more data, return * false. * * In all cases, leave the the read buffer pointing at the target * offset and in a state that's ready to support reads, even if there * is nothing in the buffer. Note that the target offset, which may not * be the same as starting offset. * @return true if more data was read, false if not. */ protected boolean fillFromFile(FileHandle fileHandle, long targetOffset) throws DatabaseException { boolean foundData = false; readBuffer.clear(); if (fileManager.readFromFile( fileHandle.getFile(), readBuffer, startOffset, fileHandle.getFileNum(), false /* dataKnownToBeInFile */)) { foundData = true; nReadOperations += 1; /* * Ensure that fileNum and logVersion are in sync. setFileNum * handles changes in the file number. But we must also update * the logVersion here to handle the first read after we * initialize fileNum and logVersion is unknown. */ logVersion = fileHandle.getLogVersion(); } /* * In all cases, setup read buffer for valid reading. If the buffer * has no data, it will be positioned at the beginning, and will be * able to correctly return the fact that there is no data present. */ endOffset = startOffset + threadSafeBufferPosition(readBuffer); threadSafeBufferFlip(readBuffer); threadSafeBufferPosition(readBuffer, (int) (targetOffset - startOffset)); return foundData; }
/* * Reposition to the specified file, and fill starting at * startOffset. Position the window's buffer to point at the log entry * indicated by targetOffset */ public void slideAndFill( long windowfileNum, long windowStartOffset, long targetOffset, boolean forward) throws ChecksumException, FileNotFoundException, DatabaseException { FileHandle fileHandle = fileManager.getFileHandle(windowfileNum); try { startOffset = windowStartOffset; setFileNum(windowfileNum, fileHandle.getLogVersion()); boolean foundData = fillFromFile(fileHandle, targetOffset); /* * When reading backwards, we need to guarantee there is no log * gap, throws out an EnvironmentFailreException if it exists. */ if (!foundData && !forward) { throw EnvironmentFailureException.unexpectedState( "Detected a log file gap when reading backwards. " + "Target position = " + DbLsn.getNoFormatString(DbLsn.makeLsn(windowfileNum, targetOffset)) + " starting position = " + DbLsn.getNoFormatString(DbLsn.makeLsn(windowfileNum, windowStartOffset)) + " end position = " + DbLsn.getNoFormatString(DbLsn.makeLsn(windowfileNum, endOffset))); } } finally { fileHandle.release(); } }
/** * Fill up the read buffer with more data, moving along to the following file (next largest * number) if needed. * * @return true if the fill moved us to a new file. */ protected boolean fillNext(boolean singleFile, int bytesNeeded) throws ChecksumException, FileNotFoundException, EOFException, DatabaseException { adjustReadBufferSize(bytesNeeded); FileHandle fileHandle = null; try { /* Get a file handle to read in more log. */ fileHandle = fileManager.getFileHandle(fileNum); /* * Check to see if we've come to the end of the file. If so, * get the next file. */ startOffset = endOffset; if (fillFromFile(fileHandle, startOffset)) { /* * Successfully filled the read buffer, but didn't move to * a new file. */ return false; } /* This file is done -- can we read in the next file? */ if (singleFile) { throw new EOFException("Single file only"); } Long nextFile = fileManager.getFollowingFileNum(fileNum, true /* forward */); if (nextFile == null) { throw new EOFException(); } fileHandle.release(); fileHandle = null; fileHandle = fileManager.getFileHandle(nextFile); setFileNum(nextFile, fileHandle.getLogVersion()); startOffset = 0; fillFromFile(fileHandle, 0); return true; } finally { if (fileHandle != null) { fileHandle.release(); } } }