+ segmentTxId + ", first file found starts at txid: "
+ logFiles.get(0).getFirstTxId());
}
// the requested file is in the beginning of the list
EditLogFile elf = logFiles.get(0);
editFile = elf.getFile();
long lastValidTxId;
long maxValidLength;
if (segmentTxId == journal.getCurrentSegmentTxId()) {
if (!elf.isInProgress()) {
throw new IOException(
"Inconsistent state. Current segment must always be in progress.");
}
// this is the currently written segment, this will be the
// most common scenario, where we want to tail this segment
// we do not want to validate it at each request
maxValidLength = journal.getValidSizeOfCurrentSegment();
// we can safely read only up to this transaction
// max - secures a degenerate case when we have multiple empty segments
lastValidTxId = Math.max(segmentTxId - 1, journal.getCommittedTxnId());
} else if (elf.isInProgress()) {
// this is an in-progress segment, but there are newer segments already
// (possibly in progress). This happens when the journal failed and was
// restored at later time, we do not know what the last valid txid is.
// we can still serve the file, just in case there is logic on the
// reader side to handle this
lastValidTxId = HdfsConstants.INVALID_TXID;
maxValidLength = editFile.length();
} else {
// finalized segment has the last transaction id,
// ad this transaction has been committed in the quorum
// entire segment can be safely served
// (segment cannot be finalized if the last transaction
// was not synced to the quorum)
lastValidTxId = elf.getLastTxId();
maxValidLength = editFile.length();
}
if (position > maxValidLength) {
throw new IOException("Position: " + position
+ " is beyond valid length of the file. File size: " + maxValidLength);
}
lengthToSend = maxValidLength - position;
// we are sending lengthToSend bytes
response.setHeader(TransferFsImage.CONTENT_LENGTH,
String.valueOf(lengthToSend));
// indicate that this stream can only serve up to this transaction
response.setHeader(LAST_VALID_TXID, String.valueOf(lastValidTxId));
response.setHeader(IS_IN_PROGRESS, String.valueOf(elf.isInProgress()));
GetImageServlet.setFileNameHeaders(response, editFile);
// prepare input stream
RandomAccessFile rp = new RandomAccessFile(editFile, "r");