home *** CD-ROM | disk | FTP | other *** search
- /*
- * $RCSfile: calculateLogSpace.c,v $
- * $Revision: 1.1.1.1 $
- * $Date: 1996/05/04 21:55:49 $
- */
- /**********************************************************************
- * 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 "threadstate.h"
- #include "log.h"
- #include "log_intfuncs.h"
- #include "log_extfuncs.h"
- #include "log_globals.h"
- #include "thread_globals.h"
-
- int
- calculateLogSpace (
-
- OPENLOG *openLog,
- int length
- )
- {
- SHORTPID limitPid;
- LSNOFFSET limitLSN;
- BOOL checkLimit;
- SHORTPID tailPid;
- int freePages;
- TRANSREC *transRec;
-
- TRPRINT(TR_LOG, TR_LEVEL_1, ("length:%d", length));
-
- /*
- * check to make sure the the thing will fit in the undo buffer
- * and is less than the max log record length
- */
- if ( (length + sizeof(LOGRECORDHDR)) > MAX_LOGREC_LEN) {
- SM_ERROR(TYPE_LOG, esmLOGRECORDTOOBIG);
- return(esmFAILURE);
- }
-
- /*
- * Calculate how much space needs to be reserved in the log
- * This is dependent upon whether the log record is for an
- * aborting transaction or for a transaction performing
- * normal operations
- * PRAKASH: normal operations include those in T_PREPARED,
- * and T_COMMIT states
- */
- transRec = (TRANSREC *) Active->transRec;
- if ((transRec != NULL) &&
- ((transRec->transState == T_ACTIVE) ||
- (transRec->transState == T_PREPARED) ||
- (transRec->transState == T_COMMIT))) {
-
- /*
- * The transactions is performing normal operations, and
- * therefore the log must have enough space to
- * guarantee that all currently active transactions can
- * be undone. Space for two maximum size log records is
- * also required to be available as a precaution.
- */
- length += ActiveLogSpace + LOG_SLACK;
- TRPRINT(TR_LOG, TR_LEVEL_2, ("space needed:%d", length));
-
- } else {
-
- /*
- * The transaction is being undone, so only reserve two
- * extra pages.
- *
- */
- length += openLog->pageSize * 2;
- TRPRINT(TR_LOG, TR_LEVEL_2, ("space needed:%d", length));
- }
-
- /*
- * calculate the space left in the file between the last
- * active transaction and the last checkpoint
- */
- if (openLog->activePid < 0) {
-
- /*
- * there are no active transactions so the byte offset of
- * the checkpoint record is the limiting page
- */
- limitLSN = OldestDirtyPageLSN.offset;
- limitPid = LSN_TO_LOG_PAGE(limitLSN, openLog);
- checkLimit = TRUE;
- TRPRINT(TR_LOG, TR_LEVEL_2, ("no active transaction"));
-
- } else if (openLog->activeUnique < openLog->checkPointUnique) {
-
- /*
- * the active transaction is the limiting factor
- */
- limitPid = openLog->activePid;
- limitLSN = openLog->activeLSN;
- checkLimit = FALSE;
- TRPRINT(TR_LOG, TR_LEVEL_2, ("active limiting"));
-
- } else {
-
- /*
- * there are no transactions before the checkpoint
- * so the checkpoint record is the limit
- */
- limitLSN = OldestDirtyPageLSN.offset;
- limitPid = LSN_TO_LOG_PAGE(limitLSN, openLog);
- checkLimit = TRUE;
- TRPRINT(TR_LOG, TR_LEVEL_2, ("checkpoint limiting"));
- }
- TRPRINT(TR_LOG, TR_LEVEL_2, ("limitPid:%d limitLSN:%d", limitPid, limitLSN));
-
- /*
- * get the tail pid in a register
- */
- tailPid = openLog->tailPid;
-
- /*
- * calculate the space that can be used
- */
- if (tailPid < limitPid) {
-
- /*
- * calculate the space between
- */
- freePages = (((int)limitPid - (int) tailPid) - 1);
- TRPRINT(TR_LOG, TR_LEVEL_2, ("freePages:%d", freePages));
-
- } else if (tailPid > limitPid) {
-
- /*
- * calculate the space at the end and beginning of file
- */
- freePages = ((int)openLog->filePages - ((int)tailPid + 1)) + (int)limitPid;
- TRPRINT(TR_LOG, TR_LEVEL_2, ("freePages:%d", freePages));
-
- } else {
-
- /*
- * check to see which order the records appear on the page
- */
- if (limitLSN < openLog->tailLSN) {
-
- /*
- * set free pages to filesize minus one page
- */
- freePages = openLog->filePages - 1;
- TRPRINT(TR_LOG, TR_LEVEL_2, ("freePages:%d", freePages));
-
- } else {
-
- /*
- * there is no room
- */
- freePages = 0;
- TRPRINT(TR_LOG, TR_LEVEL_2, ("freePages:%d", freePages));
- }
- }
- TRPRINT(TR_LOG, TR_LEVEL_2, ("tailPid:%d limitPid:%d freePages:%d freeSpace:%d",
- tailPid, limitPid, freePages, freePages << openLog->page2size));
-
- /*
- * check to see if there is enough space to satisfy the request
- */
- if (length < (freePages << openLog->page2size)) {
-
- /*
- * return success
- */
- TRPRINT(TR_LOG, TR_LEVEL_2, ("enough space"));
- return(esmNOERROR);
-
- } else {
-
- /*
- * take action based on limiting factor
- */
- if (checkLimit) {
-
- /*
- * return an error code that will force a checkpoint
- */
- TRPRINT(TR_LOG, TR_LEVEL_2, ("need checkpoint"));
- return(LOG_DO_CHECKPOINT);
-
- } else {
-
- /*
- * abort the transactions that have not completed
- */
- abortLogSpace(openLog, length);
-
- /*
- * return the error to the caller
- */
- TRPRINT(TR_LOG, TR_LEVEL_2, ("abort transactions"));
- return(esmNOFREELOGSPACE);
- }
- }
- }
-
-