home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 3: Developer Tools / Linux Cubed Series 3 - Developer Tools.iso / devel / db / esm-3.1 / esm-3 / usr / local / sm / src / serverlib / log / convertClientLogPage.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-05-05  |  7.8 KB  |  301 lines

  1. /*
  2.  *   $RCSfile: convertClientLogPage.c,v $  
  3.  *   $Revision: 1.1.1.1 $  
  4.  *   $Date: 1996/05/04 21:55:50 $      
  5.  */ 
  6. /**********************************************************************
  7. * EXODUS Database Toolkit Software
  8. * Copyright (c) 1991 Computer Sciences Department, University of
  9. *                    Wisconsin -- Madison
  10. * All Rights Reserved.
  11. *
  12. * Permission to use, copy, modify and distribute this software and its
  13. * documentation is hereby granted, provided that both the copyright
  14. * notice and this permission notice appear in all copies of the
  15. * software, derivative works or modified versions, and any portions
  16. * thereof, and that both notices appear in supporting documentation.
  17. *
  18. * THE COMPUTER SCIENCES DEPARTMENT OF THE UNIVERSITY OF WISCONSIN --
  19. * MADISON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" CONDITION.  
  20. * THE DEPARTMENT DISCLAIMS ANY LIABILITY OF ANY KIND FOR ANY DAMAGES
  21. * WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
  22. *
  23. * The EXODUS Project Group requests users of this software to return 
  24. * any improvements or extensions that they make to:
  25. *
  26. *   EXODUS Project Group 
  27. *     c/o David J. DeWitt and Michael J. Carey
  28. *   Computer Sciences Department
  29. *   University of Wisconsin -- Madison
  30. *   Madison, WI 53706
  31. *
  32. *     or exodus@cs.wisc.edu
  33. *
  34. * In addition, the EXODUS Project Group requests that users grant the 
  35. * Computer Sciences Department rights to redistribute these changes.
  36. **********************************************************************/
  37.  
  38. #include "sysdefs.h"
  39. #include "ess.h"
  40. #include "checking.h"
  41. #include "trace.h"
  42. #include "error.h"
  43. #include "list.h"
  44. #include "pool.h"
  45. #include "tid.h"
  46. #include "io.h"
  47. #include "lock.h"
  48. #include "object.h"
  49. #include "msgdefs.h"
  50. #include "thread.h"
  51. #include "semaphore.h"
  52. #include "latch.h"
  53. #include "link.h"
  54. #include "lsn.h"
  55. #include "bf.h"
  56. #include "volume.h"
  57. #include "openlog.h"
  58. #include "trans.h"
  59. #include "logrecs.h"
  60. #include "util_funcs.h"
  61. #include "log_extfuncs.h"
  62. #include "log_globals.h"
  63.  
  64. /*
  65.  *    This function converts all the lsn's on in all the log records on 
  66.  *    the client log page.  Also, the wrapcounts in the log page 
  67.  *    headers are updated.  This functions enforces the assumption
  68.  *    the the log records all pertain to the same transaction.
  69.  */
  70.  
  71.  int
  72. convertClientLogPage (
  73.     GROUPLINK            *tailLink,     /* client log page, new log tail*/
  74.     SHORTPID            newTailPage,/* page # for tail of log        */
  75.     TRANSREC            *transRec,     /* transaction for all records    */
  76.     LSN                    *firstLSN,    /* lsn of first log record        */
  77.     LSN                    *lastLSN,    /* lsn of last log record        */
  78.     LSNOFFSET            *newTailLSN,/* lsn of new log tail            */
  79.     int                    *count         /* number of log records         */
  80. )
  81. {
  82.  
  83.     LSNOFFSET        tailLSN;
  84.     OPENLOG            *openLog;
  85.     LOGPAGEHDR        *pageHeader;
  86.     LOGPAGEHDR        *endHeader;
  87.     int                wrapCount;
  88.     LOGRECORDHDR    *current;
  89.     int                offset;
  90.     LSNOFFSET        previousLSN;
  91.     int                logCount;     
  92. #ifdef DEBUG
  93.     LSN                debugLSN;
  94. #endif
  95.  
  96.  
  97.     TRPRINT(TR_LOG, TR_LEVEL_1, ("new tailPid:%d", newTailPage));
  98.  
  99.     /*
  100.      *    Get the log information
  101.      */
  102.     openLog = &OpenLog;
  103.     tailLSN = LOG_PAGE_TO_LSN(newTailPage, openLog);
  104.  
  105.     /*
  106.      *    Determine what the wrap count will be assuming the page
  107.      *    is converted without error.  The wrap count does not
  108.      *    need to be incremented if the newTailPage is the current tail
  109.      *    page of the log.
  110.      */
  111.     if (newTailPage == 0 && newTailPage != openLog->tailPid) { 
  112.         openLog->wrapCount++;
  113.     }
  114.     wrapCount = openLog->wrapCount; 
  115.  
  116. #ifdef DEBUG
  117.     /* make sure we don't overwrite important log records */
  118.     debugLSN.offset = tailLSN;
  119.     debugLSN.wrapCount = openLog->wrapCount;
  120.     debugLSN.wrapCount--;
  121.     if(compareLSN(&debugLSN, &OldestDirtyPageLSN) >= 0) {
  122.         SM_ERROR(TYPE_FATAL, esmINTERNAL);
  123.     }
  124. #endif
  125.     /*
  126.      *    Find the headers on the log page and 
  127.      *    make sure client log page is valid
  128.      */
  129.     pageHeader = (LOGPAGEHDR*) tailLink->bufFrame;
  130.     endHeader = (LOGPAGEHDR *)(((char *) pageHeader) + openLog->lastUsableByte);
  131.     if (CHECK_LOGPAGE_MAGIC(pageHeader) || 
  132.         CHECK_LOGPAGE_MAGIC(endHeader) ) {
  133.  
  134.         SM_ERROR(TYPE_USER, esmBADLOGPAGEHEADER);
  135.         return(esmFAILURE);
  136.     }
  137.      pageHeader->pageNumber = newTailPage;
  138.      endHeader->pageNumber = newTailPage;
  139.  
  140.     /*
  141.      *     Convert the LSN and prevLSN fields on all the log records
  142.      *    on the page to be valid in the current log.  It is assumed
  143.      *    that the page begins with a log record header and
  144.      *    contains no partial log record at the end.
  145.      *    
  146.      *    It is also assumed that the LSN's on the page are relative
  147.      *    to the beginning of the page.
  148.      */
  149.     offset = FIRST_LSN; /*    offset of first record */
  150.     current = (LOGRECORDHDR*) (tailLink->bufFrame + offset);
  151.     tailLSN += offset;
  152.     firstLSN->offset = tailLSN;
  153.     firstLSN->wrapCount = wrapCount;
  154.     previousLSN = transRec->lastLSN;
  155.     *count = 0;
  156.     logCount = 0;
  157.     while (TRUE) {
  158.  
  159.         if (CHECK_LOGRECORD_MAGIC(current)) {
  160.         
  161.             /*
  162.              *    if the magic is zero, the we are at the end of
  163.              *    the page.  If not then there is an error.
  164.              */
  165.             if (current->magic == 0) {
  166.             
  167.                 /*
  168.                  *    done converting
  169.                  */
  170.                 break;
  171.  
  172.             } else {
  173.                 SM_ERROR(TYPE_USER, esmBADLOGRECORDHEADER);
  174.                 return(esmFAILURE);
  175.             }
  176.                 
  177.         }
  178.  
  179.         /*
  180.          *    Valid record, so update the count
  181.          */
  182.         logCount++;
  183.  
  184.         /*
  185.          *    For now make sure all the records correspond to the
  186.          *    same transaction and are the correct type. 
  187.          *
  188.          *    If compensation log records are allowed then the n
  189.          *    nextUndoLSN field for the record and for the transaction
  190.          *    will have to be updated.
  191.          */
  192.         SM_ASSERT(LEVEL_3, transRec->tid == current->tid);
  193.         SM_ASSERT(LEVEL_3, current->type == LOG_REC_TYPE_USER);
  194.  
  195.         /*
  196.          *    Convert the LSN field
  197.          */
  198.         SM_ASSERT(LEVEL_3, offset == current->recordLSN.offset);
  199.         current->recordLSN.offset = tailLSN;
  200.         current->recordLSN.wrapCount = wrapCount;
  201.  
  202.         /*
  203.          *    Convert the previous LSN field, check to see if
  204.          *    this is the first log record on the page
  205.          */
  206.         if (offset == FIRST_LSN) {
  207.  
  208.             /*
  209.              *    This is the first log record, so the prev LSN
  210.              *    should have been set to zero by the client.
  211.              */
  212.             SM_ASSERT(LEVEL_3, current->previousLSN == 0);
  213.  
  214.         } else {
  215.             
  216.             /*
  217.              *    The previous LSN is the lsn of the previous record
  218.              *    in the page.
  219.              */
  220.             SM_ASSERT(LEVEL_3, current->previousLSN == 
  221.                                LOG_PAGE_OFFSET(previousLSN, openLog));
  222.         }
  223.         current->previousLSN = previousLSN;
  224.  
  225.         /*
  226.          *    Remember the current lsn
  227.          */
  228.         previousLSN = current->recordLSN.offset;
  229.  
  230.         /*
  231.          *    Advance to the next log record
  232.          */
  233.         offset += current->length;
  234.         tailLSN += current->length;
  235.         current = (LOGRECORDHDR*) (tailLink->bufFrame + offset);
  236.  
  237.         /*
  238.          *    If a log record header can't fit on the rest of the page,
  239.          *    then we are at the end-of-page.  Otherwise, it is possible
  240.          *    that there is another log record.
  241.          */
  242.         if ((openLog->lastUsableByte - offset) < sizeof(LOGRECORDHDR))    {
  243.  
  244.             TRPRINT(TR_LOG, TR_LEVEL_2, ("header will not fit"));
  245.  
  246.             /*
  247.              *    At end-of-page, so exit the loop
  248.              */
  249.             break;
  250.         } 
  251.  
  252.     }
  253.  
  254.     /*
  255.      *    Make sure the log page header is correct
  256.      */
  257.     if (pageHeader->lastRecord != endHeader->lastRecord) {
  258.         SM_ERROR(TYPE_USER, esmBADLOGPAGEHEADER);
  259.         return(esmFAILURE);
  260.     }
  261.     if (endHeader->lastRecord != LOG_PAGE_OFFSET(previousLSN, openLog)) {
  262.         SM_ERROR(TYPE_USER, esmBADLOGPAGEHEADER);
  263.         return(esmFAILURE);
  264.     }
  265.  
  266.     /*
  267.      *    remember the last lsn for this transaction and the number
  268.      *    of log records.
  269.      *    make sure that the new previous lsn is greater that the old
  270.      *    previous lsn.  Also, return the new tail lsn
  271.      */
  272.     SM_ASSERT(LEVEL_3, logCount > 0);
  273.     lastLSN->offset = previousLSN;
  274.     lastLSN->wrapCount = wrapCount;
  275.     *count = logCount;
  276.     *newTailLSN = tailLSN;
  277.  
  278.     /*
  279.      *     Make sure the last log record didn't accidentally overlap
  280.      */
  281.     if (LOG_PAGE_OFFSET((*newTailLSN), openLog) > openLog->lastUsableByte) {
  282.         
  283.         /*
  284.          *    Bad log record
  285.          */
  286.         SM_ERROR(TYPE_USER, esmBADLOGRECORDHEADER);
  287.         return(esmFAILURE);
  288.     }
  289.  
  290.     /*
  291.      *    Update the wrapcounts in the page headers
  292.      */
  293.     pageHeader->wrapCount = wrapCount;
  294.     endHeader->wrapCount = wrapCount;
  295.  
  296.     /*
  297.      *    return success
  298.      */
  299.     return(esmNOERROR);
  300. }
  301.