home *** CD-ROM | disk | FTP | other *** search
- /*
- * $RCSfile: reserveClientLogPage.c,v $
- * $Revision: 1.1.1.1 $
- * $Date: 1996/05/04 21:55:50 $
- */
- /**********************************************************************
- * EXODUS Database Toolkit Software
- * Copyright (c) 1991 Computer Sciences Department, University of
- * Wisconsin -- Madison
- * All Rights Reserved.
- *
- * Permission to use, copy, modify and distribute this software and its
- * documentation is hereby granted, provided that both the copyright
- * notice and this permission notice appear in all copies of the
- * software, derivative works or modified versions, and any portions
- * thereof, and that both notices appear in supporting documentation.
- *
- * THE COMPUTER SCIENCES DEPARTMENT OF THE UNIVERSITY OF WISCONSIN --
- * MADISON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" CONDITION.
- * THE DEPARTMENT DISCLAIMS ANY LIABILITY OF ANY KIND FOR ANY DAMAGES
- * WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
- *
- * The EXODUS Project Group requests users of this software to return
- * any improvements or extensions that they make to:
- *
- * EXODUS Project Group
- * c/o David J. DeWitt and Michael J. Carey
- * Computer Sciences Department
- * University of Wisconsin -- Madison
- * Madison, WI 53706
- *
- * or exodus@cs.wisc.edu
- *
- * In addition, the EXODUS Project Group requests that users grant the
- * Computer Sciences Department rights to redistribute these changes.
- **********************************************************************/
-
- #include "sysdefs.h"
- #include "ess.h"
- #include "checking.h"
- #include "trace.h"
- #include "error.h"
- #include "list.h"
- #include "pool.h"
- #include "tid.h"
- #include "io.h"
- #include "lock.h"
- #include "object.h"
- #include "msgdefs.h"
- #include "thread.h"
- #include "semaphore.h"
- #include "latch.h"
- #include "link.h"
- #include "lsn.h"
- #include "bf.h"
- #include "volume.h"
- #include "openlog.h"
- #include "trans.h"
- #include "logrecs.h"
- #include "log.h"
- #include "threadstate.h"
- #include "util_funcs.h"
- #include "log_intfuncs.h"
- #include "log_extfuncs.h"
- #include "thread_funcs.h"
- #include "thread_globals.h"
- #include "log_globals.h"
- #include "trans_globals.h"
- #ifdef DEBUG
- # include "io_extfuncs.h"
- #endif
-
- int
- reserveClientLogPage (
-
- TRANSREC *transRec,
- SHORTPID *nextLogPage
- )
- {
-
- OPENLOG *openLog;
- BOOL takeCheckPoint;
-
- TRPRINT(TR_LOG, TR_LEVEL_1, ("reserve log page"));
-
- again:
-
- /*
- * get a register pointer to the openlog structure
- */
- openLog = &OpenLog;
-
- /*
- * check the open log magic number
- */
- CHECK_OPENLOG_MAGIC(openLog);
-
- /*
- * check the transaction magic number
- */
- CHECK_TRANSREC_MAGIC(transRec);
-
- /*
- * check the state of the logging
- */
- switch (TransInfo.logState) {
-
- case L_ACTIVE:
-
- /*
- * log is open and active
- */
- break;
-
- case L_RECOVER:
-
- /*
- * check to see if the transaction is in recovery
- */
- if (transRec->transState != T_RECOVER) {
-
- /*
- * queue the request pending recovery completion
- */
- if (waitList( &(openLog->recoverList) , THREAD_LOG_RECOVERY_WAIT)) {
-
- return(esmFAILURE);
- }
- }
- break;
-
- case L_QUIESCE:
-
- /*
- * check to see if the transaction is in abort
- */
- if (transRec->transState != T_ABORT) {
-
- SM_ERROR(TYPE_LOG, esmLOGDISABLED);
- return(esmFAILURE);
- }
- break;
-
- default:
-
- /*
- * reject the request
- */
- SM_ERROR(TYPE_LOG, esmLOGDISABLED);
- return esmFAILURE;
- }
-
- /*
- * If the transaction is not in the active state
- * it cannot write operation log records unless the transaction
- * is being committed.
- */
- if ((transRec->transState != T_ACTIVE) &&
- (transRec->intent != T_COMMIT) ) {
-
- SM_ERROR(TYPE_USER, esmBADTRANSID);
- return(esmFAILURE);
- }
-
- /*
- * get the latch on the log
- */
- if (waitLatch( &(openLog->logLatch), SHARE_LATCH )) {
-
- return(esmFAILURE);
- }
-
- /*
- * check to see if the log is in use
- */
- if (waitSemaphore( &(openLog->writeSemaphore) )) {
-
- signalLatch( &(openLog->logLatch) );
- return(esmFAILURE);
- }
-
-
- /*
- * calculate to see if there is enough space to hold the
- * log page. (sizeof(LOGRECORDHDR) is subtracted so
- * that calculateLogSpace won't complain when log pages
- * are the size of MAX_LOGREC_LEN).
- */
- switch ( calculateLogSpace(openLog, (openLog->usableBytes - sizeof(LOGRECORDHDR))) ) {
-
- case esmNOERROR:
-
- /* There is space */
- takeCheckPoint = FALSE;
- break;
-
- case esmFAILURE:
-
- /*
- * The log record is too big
- */
- signalSemaphore( &(openLog->writeSemaphore) );
- signalLatch( &(openLog->logLatch) );
- return(esmFAILURE);
-
- case esmNOFREELOGSPACE:
-
- /*
- * There is no log space and taking a checkpoint will not
- * help.
- */
- signalSemaphore( &(openLog->writeSemaphore) );
- signalLatch( &(openLog->logLatch) );
- SM_ERROR(TYPE_USER, esmNOFREELOGSPACE);
- return(esmFAILURE);
-
- case LOG_DO_CHECKPOINT:
-
- /*
- * A check point is required to free up space
- */
- takeCheckPoint = TRUE;
- break;
-
- default:
-
- SM_ERROR(TYPE_FATAL, esmINTERNAL);
- return(esmFAILURE);
- }
-
- /*
- * if a checkpoint is needed, perform it
- */
- if (takeCheckPoint) {
-
- /*
- * give back the log synchronization
- */
- signalSemaphore( &(openLog->writeSemaphore) );
- signalLatch( &(openLog->logLatch) );
-
- /* activate a checkpoint and wait for it to complete */
- activateCheckpoint(TRUE, FALSE, TRUE);
-
- /*
- * attempt to log the record again
- * Note, it cannot be assumed that there is enough
- * space after taking the checkpoint, since other
- * transactions may have used up the space.
- */
- TRPRINT(TR_LOG, TR_LEVEL_2, ("returned from checkPoint"));
- goto again;
- }
-
- /*
- * See if the page is already a new page (there are no log
- * records on it).
- */
- if (LOG_PAGE_OFFSET(openLog->tailLSN, openLog) == 0) {
- /*
- * Tail page is new, so use it.
- */
- *nextLogPage = openLog->tailPid;
- TRPRINT(TR_LOG, TR_LEVEL_1,
- ("Using tail page %d as client log page", openLog->tailPid));
- } else {
-
- /* record that the log has a another dirty page to preflush */
- preflushLog();
-
- /* potentially activate a checkpoint */
- activateCheckpoint(FALSE, FALSE, FALSE);
-
- /*
- * Get the next page in the log
- */
- *nextLogPage = (openLog->tailPid + 1) % openLog->filePages;
- }
-
- /*
- * Return success
- */
- return(esmNOERROR);
-
- }
-