Return-Path: Mailing-List: contact derby-commits-help@db.apache.org; run by ezmlm Delivered-To: mailing list derby-commits@db.apache.org Delivered-To: moderator for derby-commits@db.apache.org Received: (qmail 6603 invoked by uid 500); 5 Oct 2004 23:10:18 -0000 Delivered-To: apmail-incubator-derby-cvs@incubator.apache.org Received: (qmail 6600 invoked by uid 99); 5 Oct 2004 23:10:17 -0000 X-ASF-Spam-Status: No, hits=-10.0 required=10.0 tests=ALL_TRUSTED,NO_REAL_NAME X-Spam-Check-By: apache.org Received: from [209.237.227.194] (HELO minotaur.apache.org) (209.237.227.194) by apache.org (qpsmtpd/0.28) with SMTP; Tue, 05 Oct 2004 16:10:17 -0700 Received: (qmail 43456 invoked by uid 65534); 5 Oct 2004 23:10:16 -0000 Date: 5 Oct 2004 23:10:16 -0000 Message-ID: <20041005231016.43453.qmail@minotaur.apache.org> From: mikem@apache.org To: derby-cvs@incubator.apache.org Subject: svn commit: rev 53832 - incubator/derby/code/trunk/java/engine/org/apache/derby/impl/store/raw/log X-Virus-Checked: Checked Author: mikem Date: Tue Oct 5 16:10:15 2004 New Revision: 53832 Modified: incubator/derby/code/trunk/java/engine/org/apache/derby/impl/store/raw/log/LogToFile.java incubator/derby/code/trunk/java/engine/org/apache/derby/impl/store/raw/log/Scan.java Log: committed for tsuresh@Source-Zone.org problem : In multi-threaded application when lot of threads are executing commits in parallel, empty log files might be created. Recovery log scan does not expect empty log files while scanning log records to undo incomplete transactions.. Fix: a) prevent empty log switches by rechecking the conditions that triggers the log switches inside synchronized blocks. b) Make backward scans skip the empty log files. Modified: incubator/derby/code/trunk/java/engine/org/apache/derby/impl/store/raw/log/LogToFile.java ============================================================================== --- incubator/derby/code/trunk/java/engine/org/apache/derby/impl/store/raw/log/LogToFile.java (original) +++ incubator/derby/code/trunk/java/engine/org/apache/derby/impl/store/raw/log/LogToFile.java Tue Oct 5 16:10:15 2004 @@ -1819,24 +1819,12 @@ ///////////////////////////////////////////////////// synchronized (this) { - // we have an empty log file here, refuse to switch. - if (endPosition == LOG_FILE_HEADER_SIZE) - { - if (SanityManager.DEBUG) - { - Monitor.logMessage("not switching from an empty log file (" + - logFileNumber + ")"); - } - return; - } - // Make sure that this thread of control is guaranteed to complete // it's work of switching the log file without having to give up // the semaphore to a backup or another flusher. Do this by looping // until we have the semaphore, the log is not being flushed, and // the log is not frozen for backup. Track (2985). - boolean waited = false; while(logBeingFlushed | isFrozen) { try @@ -1849,6 +1837,17 @@ } } + // we have an empty log file here, refuse to switch. + if (endPosition == LOG_FILE_HEADER_SIZE) + { + if (SanityManager.DEBUG) + { + Monitor.logMessage("not switching from an empty log file (" + + logFileNumber + ")"); + } + return; + } + // log file isn't being flushed right now and logOut is not being // used. StorageFile newLogFile = getLogFileName(logFileNumber+1); @@ -3721,11 +3720,14 @@ if ((logWrittenFromLastCheckPoint + potentialLastFlush) > checkpointInterval && checkpointDaemon != null && !checkpointDaemonCalled && !inLogSwitch) { - //following synchronized block is required to make - //sure only one checkpoint request get scheduled. + // following synchronized block is required to make + // sure only one checkpoint request get scheduled. synchronized(this) { - if(!checkpointDaemonCalled) + // recheck if checkpoint is still required, it is possible some other + // thread might have already scheduled a checkpoint and completed it. + if ((logWrittenFromLastCheckPoint + potentialLastFlush) > checkpointInterval && + checkpointDaemon != null && !checkpointDaemonCalled && !inLogSwitch) { checkpointDaemonCalled = true; checkpointDaemon.serviceNow(myClientNumber); @@ -3741,11 +3743,14 @@ if (potentialLastFlush > logSwitchInterval && !checkpointDaemonCalled && !inLogSwitch) { - //following synchronized block is required - //to make sure only one thread switches the log file at a time. + // following synchronized block is required to make sure only + // one thread switches the log file at a time. synchronized(this) { - if(!inLogSwitch) + // recheck if log switch is still required, it is possible some other + // thread might have already switched the log file. + if (potentialLastFlush > logSwitchInterval && + !checkpointDaemonCalled && !inLogSwitch) { inLogSwitch = true; switchLogFile(); Modified: incubator/derby/code/trunk/java/engine/org/apache/derby/impl/store/raw/log/Scan.java ============================================================================== --- incubator/derby/code/trunk/java/engine/org/apache/derby/impl/store/raw/log/Scan.java (original) +++ incubator/derby/code/trunk/java/engine/org/apache/derby/impl/store/raw/log/Scan.java Tue Oct 5 16:10:15 2004 @@ -328,6 +328,14 @@ // end of the file header, in other words, there is at least // one log record in this log file. curpos = scan.getFilePointer(); + + // if the log file happens to be empty skip and proceed. + // ideally this case should never occur because log switch is + // not suppose to happen on an empty log file. + // But it is safer to put following check incase if it ever + // happens to avoid any recovery issues. + if (curpos == LogToFile.LOG_FILE_HEADER_SIZE) + continue; } scan.seek(curpos - 4);