/** * Returns the next object from the log, or null if none available. * * @return The log record, or null if EOF * @throws IOException If there is a low-level I/O error. */ public Object next() throws IOException { if (prevPos <= 0) return null; long endOfThisRecord = prevPos; int thisLength = nextLength; long recordStart = prevPos - thisLength; // back up to the beginning of the next record prevPos = recordStart - 4; // back up 4 more to read the length of the next record if (prevPos <= 0) return null; // this record is the header long bufferPos = fis.getBufferPos(); if (prevPos >= bufferPos) { // nothing to do... we're within the current buffer } else { // Position buffer so that this record is at the end. // For small records, this will cause subsequent calls to next() to be within the buffer. long seekPos = endOfThisRecord - fis.getBufferSize(); seekPos = Math.min( seekPos, prevPos); // seek to the start of the record if it's larger then the block size. seekPos = Math.max(seekPos, 0); fis.seek(seekPos); fis.peek(); // cause buffer to be filled } fis.seek(prevPos); nextLength = fis.readInt(); // this is the length of the *next* record (i.e. closer to the beginning) // TODO: optionally skip document data Object o = codec.readVal(fis); // assert fis.position() == prevPos + 4 + thisLength; // this is only true if we read all the // data (and we currently skip reading SolrInputDocument return o; }
public FSReverseReader() throws IOException { incref(); long sz; synchronized (TransactionLog.this) { fos.flushBuffer(); sz = fos.size(); assert sz == channel.size(); } fis = new ChannelFastInputStream(channel, 0); if (sz >= 4) { // readHeader(fis); // should not be needed prevPos = sz - 4; fis.seek(prevPos); nextLength = fis.readInt(); } }