// Make sure we find the log, do not assume
// it is OK that the log is not there because
// it could be a user typo(like when users edit
// service.properties to change the log device
// while restoring from backups using OS copy.
StorageFile checklogDir =
logStorageFactory.newStorageFile(
LogFactory.LOG_DIRECTORY_NAME);
if (!privExists(checklogDir))
{
throw
StandardException.newException(
SQLState.LOG_FILE_NOT_FOUND, checklogDir.getPath());
}
}
}
}
//if user does not set the right value for the log buffer size,
//default value is used instead.
logBufferSize = PropertyUtil.getSystemInt(org.apache.derby.iapi.reference.Property.LOG_BUFFER_SIZE,
LOG_BUFFER_SIZE_MIN,
LOG_BUFFER_SIZE_MAX,
DEFAULT_LOG_BUFFER_SIZE);
jbmsVersion = Monitor.getMonitor().getEngineVersion();
String logArchiveMode =
startParams.getProperty(Property.LOG_ARCHIVE_MODE);
logArchived = Boolean.valueOf(logArchiveMode).booleanValue();
//get log factorty properties if any set in derby.properties
getLogFactoryProperties(null);
/* check if the storage factory supports write sync(rws). If so, use it unless
* derby.storage.fileSyncTransactionLog property is set true by user.
*/
if (logStorageFactory.supportsRws())
{
//write sync can be used in the jvm that database is running on.
//disable write sync if derby.storage.fileSyncTransactionLog is true
isWriteSynced =
!(PropertyUtil.getSystemBoolean(Property.FILESYNC_TRANSACTION_LOG));
}
else
{
isWriteSynced = false;
}
// If derby.system.durability=test is set,then set flag to
// disable sync of log records at commit and log file before
// data page makes it to disk
if (Property.DURABILITY_TESTMODE_NO_SYNC.equalsIgnoreCase(
PropertyUtil.getSystemProperty(Property.DURABILITY_PROPERTY)))
{
// disable syncing of log.
logNotSynced = true;
//if log not being synced;files shouldn't be open in write sync mode
isWriteSynced = false;
}
else if (Performance.MEASURE)
{
// development build only feature, must by hand set the
// Performance.MEASURE variable and rebuild. Useful during
// development to compare/contrast effect of syncing, release
// users can use the above relaxed durability option to disable
// all syncing.
logNotSynced =
PropertyUtil.getSystemBoolean(
Property.STORAGE_LOG_NOT_SYNCED);
if (logNotSynced)
{
isWriteSynced = false;
Monitor.logMessage("Performance.logNotSynced = true");
}
}
// try to access the log
// if it doesn't exist, create it.
// if it does exist, run recovery
boolean createNewLog = create;
if (SanityManager.DEBUG)
SanityManager.ASSERT(fid != -1, "invalid log format Id");
checkpointInstant = LogCounter.INVALID_LOG_INSTANT;
try
{
StorageFile logControlFileName = getControlFileName();
StorageFile logFile;
if (!createNewLog)
{
if (privExists(logControlFileName))
{
checkpointInstant =
readControlFile(logControlFileName, startParams);
// in case system was running previously with
// derby.system.durability=test then print a message
// to the derby log
if (wasDBInDurabilityTestModeNoSync)
{
// print message stating that the database was
// previously atleast at one time running with
// derby.system.durability=test mode
Monitor.logMessage(MessageService.getTextMessage(
MessageId.LOG_WAS_IN_DURABILITY_TESTMODE_NO_SYNC,
Property.DURABILITY_PROPERTY,
Property.DURABILITY_TESTMODE_NO_SYNC));
}
if (checkpointInstant == LogCounter.INVALID_LOG_INSTANT &&
privExists(getMirrorControlFileName()))
{
checkpointInstant =
readControlFile(
getMirrorControlFileName(), startParams);
}
}
else if (logDevice != null)
{
// Do not throw this error if logDevice is null because
// in a read only configuration, it is acceptable
// to not have a log directory. But clearly, if the
// logDevice property is set, then it should be there.
throw StandardException.newException(
SQLState.LOG_FILE_NOT_FOUND,
logControlFileName.getPath());
}
if (checkpointInstant != LogCounter.INVALID_LOG_INSTANT)
logFileNumber = LogCounter.getLogFileNumber(checkpointInstant);
else
logFileNumber = 1;
logFile = getLogFileName(logFileNumber);
// if log file is not there or if it is of the wrong format, create a
// brand new log file and do not attempt to recover the database
if (!privExists(logFile))
{
if (logDevice != null)
{
throw StandardException.newException(
SQLState.LOG_FILE_NOT_FOUND,
logControlFileName.getPath());
}
logErrMsg(MessageService.getTextMessage(
MessageId.LOG_MAYBE_INCONSISTENT,
logFile.getPath()));
createNewLog = true;
}
else if (!verifyLogFormat(logFile, logFileNumber))
{
Monitor.logTextMessage(MessageId.LOG_DELETE_INCOMPATIBLE_FILE, logFile);
// blow away the log file if possible
if (!privDelete(logFile) && logFileNumber == 1)
{
logErrMsgForDurabilityTestModeNoSync();
throw StandardException.newException(
SQLState.LOG_INCOMPATIBLE_FORMAT, dataDirectory);
}
// If logFileNumber > 1, we are not going to write that
// file just yet. Just leave it be and carry on. Maybe
// when we get there it can be deleted.
createNewLog = true;
}
}
if (createNewLog)
{
// brand new log. Start from log file number 1.
// create or overwrite the log control file with an invalid
// checkpoint instant since there is no checkpoint yet
if (writeControlFile(logControlFileName,
LogCounter.INVALID_LOG_INSTANT))
{
firstLogFileNumber = 1;
logFileNumber = 1;
if (SanityManager.DEBUG)
{
if (SanityManager.DEBUG_ON(TEST_MAX_LOGFILE_NUMBER))
{
// set the value to be two less than max possible
// log number, test case will perform some ops to
// hit the max number case.
firstLogFileNumber =
LogCounter.MAX_LOGFILE_NUMBER -2;
logFileNumber = LogCounter.MAX_LOGFILE_NUMBER -2;
}
}
logFile = getLogFileName(logFileNumber);
if (privExists(logFile))
{
// this log file maybe there because the system may have
// crashed right after a log switch but did not write
// out any log record
Monitor.logTextMessage(
MessageId.LOG_DELETE_OLD_FILE, logFile);
if (!privDelete(logFile))
{
logErrMsgForDurabilityTestModeNoSync();
throw StandardException.newException(
SQLState.LOG_INCOMPATIBLE_FORMAT,
dataDirectory);
}
}
// don't need to try to delete it, we know it isn't there
firstLog = privRandomAccessFile(logFile, "rw");
if (!initLogFile(firstLog, logFileNumber, LogCounter.INVALID_LOG_INSTANT))
{
throw StandardException.newException(
SQLState.LOG_SEGMENT_NOT_EXIST, logFile.getPath());
}
endPosition = firstLog.getFilePointer();
lastFlush = firstLog.getFilePointer();