home *** CD-ROM | disk | FTP | other *** search
- /*
- * $RCSfile: writeImage.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 "util_funcs.h"
- #include "log_intfuncs.h"
- #include "log_extfuncs.h"
- #include "log_globals.h"
- #include "thread_globals.h"
-
-
- void
- writeImage (
-
- OPENLOG *openLog,
- LOGRECORDINFO *logRecInfo,
- int index,
- LSNOFFSET *recordLSN
- )
- {
- LSNOFFSET tailLSN;
- SHORTPID tailPid;
- int total;
- LSNOFFSET offset;
- int size;
- char *image;
- PAGEHASH *tailBuffer;
- int count;
- #ifdef DEBUG
- LSN debugLSN;
- #endif
-
- /*
- * put pointers in registers
- */
- size = logRecInfo->imageSize[index];
- image = (char *) logRecInfo->imageData[index];
- tailLSN = openLog->tailLSN;
- tailPid = openLog->tailPid;
-
- TRPRINT(TR_LOG, TR_LEVEL_1,
- ("size:%d tailLSN %d", logRecInfo->imageSize[index], tailLSN));
-
- /*
- * place the image on successive pages
- */
- for (total = 0, count=0; total < size; total += count, image += count) {
-
- /*
- * check to see if the offset is zero
- * we can come in with a zero offset or we can
- * generate a zero offset at the bottom of this loop
- */
- TRPRINT(TR_LOG, TR_LEVEL_2, ("total:%d count %d tailLSN %d, offset %d",
- total, count, tailLSN, LOG_PAGE_OFFSET(tailLSN, openLog)));
-
- if ((offset = LOG_PAGE_OFFSET(tailLSN, openLog)) == 0) {
-
- /*
- * write the page header
- */
- writeLogPageHeader(openLog, tailPid);
-
- /*
- * increment the tail pointer
- */
- tailLSN += FIRST_LSN;
- offset = FIRST_LSN;
- }
-
- TRPRINT(TR_LOG, TR_LEVEL_2, ("offset:%d", offset));
-
- /*
- * save the buffer
- */
- tailBuffer = openLog->tailBuffer;
-
- /*
- * get the count of data to move
- */
- count = MIN((openLog->lastUsableByte - offset), (size - total));
- TRPRINT(TR_LOG, TR_LEVEL_2, ("moving %d bytes", count));
-
- /*
- * copy the data
- */
- bcopy(image, tailBuffer->bufFrame + offset, count);
-
- /*
- * dirty the page
- */
- DIRTY_PAGE(tailBuffer);
-
- /*
- * check to see if the force mark is the first one
- */
- if (tailBuffer->firstMark == 0) {
-
- /*
- * mark the first lsn
- */
- tailBuffer->firstMark = openLog->logRecordCount;
- TRPRINT(TR_LOG, TR_LEVEL_2, ("firstMark:%d", tailBuffer->firstMark));
- }
-
- /*
- * save the record number
- */
- tailBuffer->forceMark = openLog->logRecordCount;
- TRPRINT(TR_LOG, TR_LEVEL_2, ("forceMark:%d", tailBuffer->forceMark));
-
- /*
- * increment the tail pointer
- * round up the pointer
- */
-
- tailLSN += count;
- tailLSN = ALIGN(tailLSN, 4);
- TRPRINT(TR_LOG, TR_LEVEL_2, ("tailLSN:%d", tailLSN));
-
- /*
- * check to see if we advance to the next page
- */
- if (LOG_PAGE_OFFSET(tailLSN, openLog) == openLog->lastUsableByte) {
-
- TRPRINT(TR_LOG, TR_LEVEL_2, ("advance to next page"));
-
- /*
- * check to see if the record offset is not null,
- * indicating that the record header is on this page
- */
- if (*recordLSN != NULL_LSN) {
-
- /*
- * update the header with the address of the
- * log record header
- */
- updateLogPageHeader(openLog, LOG_PAGE_OFFSET(*recordLSN, openLog));
-
- /*
- * null out the recordLSN
- */
- *recordLSN = NULL_LSN;
- } else {
-
- /*
- * There is no log record header on this page, so
- * just record the first usable byte on the page
- */
- updateLogPageHeader(openLog, FIRST_LSN);
- }
-
- /*
- * increment the tail page
- */
- tailPid = ((tailPid + 1) % openLog->filePages);
- TRPRINT(TR_LOG, TR_LEVEL_2, ("tailPid:%d", tailPid));
-
- /*
- * check to see if the tail page is zero
- */
- if (tailPid == 0) {
-
- /*
- * increment the wrap counter
- */
- openLog->wrapCount++;
- /* this confuses too many users:
- SM_ERROR(TYPE_LOG, esmLOGWRAPPED);
- */
- }
-
- /*
- * recalculate the tail pointer
- */
- tailLSN = LOG_PAGE_TO_LSN(tailPid, openLog);
- }
- }
-
- #ifdef DEBUG
- /* make sure we don't overwrite important log records */
- debugLSN.offset = tailLSN;
- debugLSN.wrapCount = openLog->wrapCount-1;
- SM_ASSERT(LEVEL_3, compareLSN(&debugLSN, &OldestDirtyPageLSN) < 0);
- #endif
-
- /*
- * See if this is the last image for the record and the
- * image does not completely fill page (ie. the log tail is not
- * on a new page).
- */
- if ( (index+1 == logRecInfo->imageCount) && !(LOG_PAGE_OFFSET(tailLSN, openLog) == 0) ) {
-
- /*
- * See if the record header is on this page.
- */
- if (*recordLSN != NULL_LSN) {
-
- /*
- * update the header with the address of the
- * log record header
- */
- updateLogPageHeader(openLog, LOG_PAGE_OFFSET(*recordLSN, openLog));
- } else {
-
- /*
- * There is no log record header on this page, so
- * just record the first usable byte on the page
- */
- updateLogPageHeader(openLog, FIRST_LSN);
- }
- }
- /*
- * record the pointers
- */
- openLog->tailPid = tailPid;
- openLog->tailLSN = tailLSN;
- TRPRINT(TR_LOG, TR_LEVEL_2, ("tailPid:%d tailLSN:%d", tailPid, tailLSN));
- }
-