logicalOut.writeInt(optionalDataLength);
completeLength = logOutputBuffer.getPosition() + optionalDataLength;
LogInstant logInstant = null;
int encryptedLength = 0; // in case of encryption, we need to pad
try
{
if (logFactory.databaseEncrypted())
{
// we must pad the encryption data to be multiple of block
// size, which is logFactory.getEncryptionBlockSize()
encryptedLength = completeLength;
if ((encryptedLength % logFactory.getEncryptionBlockSize()) != 0)
encryptedLength = encryptedLength + logFactory.getEncryptionBlockSize() - (encryptedLength % logFactory.getEncryptionBlockSize());
if (encryptionBuffer == null ||
encryptionBuffer.length < encryptedLength)
encryptionBuffer = new byte[encryptedLength];
System.arraycopy(logOutputBuffer.getByteArray(), 0,
encryptionBuffer, 0, completeLength-optionalDataLength);
if (optionalDataLength > 0)
System.arraycopy(preparedLog, optionalDataOffset,
encryptionBuffer,
completeLength-optionalDataLength, optionalDataLength);
// do not bother to clear out the padding area
int len =
logFactory.encrypt(encryptionBuffer, 0, encryptedLength,
encryptionBuffer, 0);
if (SanityManager.DEBUG)
SanityManager.ASSERT(len == encryptedLength,
"encrypted log buffer length != log buffer len");
}
if ((operation.group() & (Loggable.FIRST | Loggable.LAST)) != 0)
{
synchronized (logFactory)
{
long instant = 0;
if (logFactory.databaseEncrypted())
{
// encryption has completely drained both the the
// logOuputBuffer array and the preparedLog array
instant = logFactory.
appendLogRecord(encryptionBuffer, 0,
encryptedLength, null,
-1, 0);
}
else
{
instant = logFactory.
appendLogRecord(logOutputBuffer.getByteArray(),
0, completeLength, preparedLog,
optionalDataOffset,
optionalDataLength);
}
logInstant = new LogCounter(instant);
operation.doMe(xact, logInstant, logIn);
}
}
else
{
long instant = 0;
if (logFactory.databaseEncrypted())
{
// encryption has completely drained both the the
// logOuputBuffer array and the preparedLog array
instant = logFactory.
appendLogRecord(encryptionBuffer, 0,
encryptedLength, null, -1, 0);
}
else
{
instant = logFactory.
appendLogRecord(logOutputBuffer.getByteArray(), 0,
completeLength, preparedLog,
optionalDataOffset,
optionalDataLength);
}
logInstant = new LogCounter(instant);
operation.doMe(xact, logInstant, logIn);
}
}
catch (StandardException se)
{
throw logFactory.markCorrupt(
StandardException.newException(
SQLState.LOG_DO_ME_FAIL, se, operation));
}
catch (IOException ioe)
{
throw logFactory.markCorrupt(
StandardException.newException(
SQLState.LOG_DO_ME_FAIL, ioe, operation));
}
finally
{
logIn.clearLimit();
}
if (SanityManager.DEBUG)
{
if (SanityManager.DEBUG_ON(LogToFile.DBG_FLAG))
{
SanityManager.DEBUG(
LogToFile.DBG_FLAG,
"Write log record: tranId=" + transactionId.toString() +
" instant: " + logInstant.toString() + " length: " +
completeLength + "\n" + operation + "\n");
}
}
return logInstant;
}