use of org.apache.asterix.common.transactions.ILogRecord.RecordReadStatus in project asterixdb by apache.
the class LogReader method read.
//for random reading
@Override
public ILogRecord read(long LSN) throws ACIDException {
readLSN = LSN;
//wait for the log to be flushed if needed before trying to read it.
synchronized (flushLSN) {
while (readLSN >= flushLSN.get()) {
try {
flushLSN.wait();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
}
try {
if (logFile == null) {
//get the log file which contains readLSN
getLogFile();
fillLogReadBuffer();
} else if (readLSN < fileBeginLSN || readLSN >= fileBeginLSN + logFile.size()) {
//log is not in the current log file
logFile.close();
getLogFile();
fillLogReadBuffer();
} else if (readLSN < bufferBeginLSN || readLSN >= bufferBeginLSN + readBuffer.limit()) {
//log is not in the current read buffer
fillLogReadBuffer();
} else {
//log is either completely in the current read buffer or truncated
readBuffer.position((int) (readLSN - bufferBeginLSN));
}
} catch (IOException e) {
throw new ACIDException(e);
}
ByteBuffer readBuffer = this.readBuffer;
while (true) {
RecordReadStatus status = logRecord.readLogRecord(readBuffer);
switch(status) {
case LARGE_RECORD:
{
readBuffer = ByteBuffer.allocate(logRecord.getLogSize());
fillLogReadBuffer(logRecord.getLogSize(), readBuffer);
//now see what we have in the refilled buffer
continue;
}
case TRUNCATED:
{
if (!fillLogReadBuffer()) {
throw new IllegalStateException("Could not read LSN(" + LSN + ") from log file id " + logFile.getLogFileId());
}
//now read the complete log record
continue;
}
case BAD_CHKSUM:
{
throw new ACIDException("Log record has incorrect checksum");
}
case OK:
break;
default:
throw new IllegalStateException("Unexpected log read status: " + status);
}
break;
}
logRecord.setLSN(readLSN);
readLSN += logRecord.getLogSize();
return logRecord;
}
use of org.apache.asterix.common.transactions.ILogRecord.RecordReadStatus in project asterixdb by apache.
the class LogReader method next.
/**
* Get the next log record from the log file.
*
* @return A deserialized log record, or null if we have reached the end of the file.
* @throws ACIDException
*/
@Override
public ILogRecord next() throws ACIDException {
if (waitForFlushOrReturnIfEOF() == ReturnState.EOF) {
return null;
}
if (readBuffer.position() == readBuffer.limit()) {
boolean hasRemaining = refillLogReadBuffer();
if (!hasRemaining && isRecoveryMode && readLSN < flushLSN.get()) {
LOGGER.severe("Transaction log ends before expected. Log files may be missing.");
return null;
}
}
ByteBuffer readBuffer = this.readBuffer;
boolean refilled = false;
while (true) {
RecordReadStatus status = logRecord.readLogRecord(readBuffer);
switch(status) {
case TRUNCATED:
{
if (!refilled) {
//we may have just read off the end of the buffer, so try refiling it
if (!refillLogReadBuffer()) {
return null;
}
refilled = true;
//now see what we have in the refilled buffer
continue;
} else {
LOGGER.info("Log file has truncated log records.");
return null;
}
}
case LARGE_RECORD:
{
readBuffer = ByteBuffer.allocate(logRecord.getLogSize());
fillLogReadBuffer(logRecord.getLogSize(), readBuffer);
//now see what we have in the expanded buffer
continue;
}
case BAD_CHKSUM:
{
LOGGER.severe("Transaction log contains corrupt log records (perhaps due to medium error). Stopping recovery early.");
return null;
}
case OK:
break;
default:
throw new IllegalStateException("Unexpected log read status: " + status);
}
// break the loop by default
break;
}
logRecord.setLSN(readLSN);
readLSN += logRecord.getLogSize();
return logRecord;
}
Aggregations