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 / regenLog.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-05-05  |  10.0 KB  |  420 lines

  1. /*
  2.  *   $RCSfile: regenLog.c,v $  
  3.  *   $Revision: 1.1.1.1 $  
  4.  *   $Date: 1996/05/04 21:55:49 $      
  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 "log_intfuncs.h"
  61. #include "log_extfuncs.h"
  62. #include "bf_extfuncs.h"
  63. #include "util_funcs.h"
  64. #include "thread_globals.h"
  65. #include "trans_globals.h"
  66. #include "log_globals.h"
  67. #include "io_globals.h"
  68.  
  69.  
  70.  int
  71. regenLog (
  72.  
  73.     register OPENLOG    *openLog 
  74. )
  75. {
  76.  
  77.     register PAGEHASH    *tailBuffer;
  78.     GROUPLINK            *tailLink;
  79.     LOGPAGEHDR            *pageHeader;
  80.     LOGPAGEHDR            *endHeader;
  81.     LOGRECORDHDR        *record;
  82.     CHECKPOINTMASTER    *checkMaster;
  83.     CHECKPOINTINFO        *checkInfo;
  84.     PID                    pid;
  85.     int                    i;
  86.     int                    initWrapCount;
  87.     PAGEHASH            *pageHashList[MAX_IO_LIST];
  88.     int                  numToForce;
  89.  
  90.     TRACE(TR_LOG, TR_LEVEL_1);
  91.  
  92.     /* get the latch on the log */
  93.     if (waitLatch( &(openLog->logLatch), EXCLUSIVE_LATCH) )    {
  94.  
  95.         SM_ERROR(TYPE_FATAL, Active->errno);
  96.     }
  97.  
  98.     /* get the semaphore on the log */
  99.     if (waitSemaphore( &(openLog->writeSemaphore) ))    {
  100.  
  101.         SM_ERROR(TYPE_FATAL, Active->errno);
  102.     }
  103.  
  104.     /*
  105.      *    Record the regen/recovery state of the log
  106.      *    so that other log writers will wait.
  107.      */
  108.     TransInfo.logState = L_RECOVER;
  109.  
  110.     /*
  111.      *    The initial value for the wrapCount is the wrapCount on
  112.      *    volume header +1
  113.      */
  114.     initWrapCount = (int) openLog->volRec->header->dismountEndOfLog.wrapCount + 1;
  115.  
  116.     /* zero out the control page which destroys the log */
  117.     bzero(openLog->controlBuffer->bufFrame, MIN_PAGESIZE);
  118.  
  119.     /*
  120.      *    dirty the page (get the semaphore to make the debugging
  121.      *    version of DIRTY_PAGE happy
  122.      */
  123. #ifdef DEBUG
  124.     waitSemaphore(&(openLog->controlBuffer->pageHash->semaphore));
  125. #endif
  126.     DIRTY_PAGE(openLog->controlBuffer->pageHash);
  127. #ifdef DEBUG
  128.     signalSemaphore(&(openLog->controlBuffer->pageHash->semaphore));
  129. #endif
  130.  
  131.     /* force it to disk */
  132.     bf_ForcePage(openLog->controlBuffer->pageHash, BF_SEM);
  133.  
  134.     /* contruct a pid nulling out the log */
  135.     pid.volid = openLog->volid;
  136.     pid.page  = openLog->logFileAddr;
  137.  
  138.     /* make sure I/O is asynchronous */
  139.     PREVENT_FAST_IO();
  140.  
  141.     /*
  142.      *    null out all pages of the log
  143.      */
  144.     numToForce = 0;
  145.     for (i = 0; i < openLog->filePages; i++, pid.page += openLog->blocksPerPage)    {
  146.  
  147.         register GROUPLINK        *tempLink;
  148.  
  149.         if (numToForce == MAX_IO_LIST) {
  150.             bf_ForcePageList(pageHashList, numToForce, BF_SEM);
  151.             numToForce = 0;
  152.         }
  153.  
  154.         /*
  155.          *    read the first log page into the cache
  156.          */
  157.         if ((tempLink = bf_ReadPage(openLog->writeGroup, &pid,
  158.                                     openLog->page2size, BF_SEM | BF_NOREAD)) == NULL)    {
  159.  
  160.             SM_ERROR(TYPE_FATAL, Active->errno);
  161.         }
  162.  
  163.         /*
  164.          *    zero the page
  165.          */
  166.         bzero(tempLink->bufFrame, (int) openLog->pageSize);
  167.  
  168.         /*
  169.          *    get a pointer to the header of the page
  170.          */
  171.         pageHeader = (LOGPAGEHDR *) tempLink->bufFrame;
  172.  
  173.         /*
  174.          *    initialize the page header
  175.          */
  176.         pageHeader->magic      = LOGPAGE_MAGIC;
  177.         pageHeader->pageNumber = i;
  178.         pageHeader->wrapCount  = NULL_LOG_WRAP_COUNT;
  179.         pageHeader->lastRecord = NULL_LAST_RECORD;
  180.  
  181.         /*
  182.          *    get a pointer to the end of the page
  183.          *    initialize the header on the page
  184.          */
  185.         endHeader = (LOGPAGEHDR *) (((char *) pageHeader) + openLog->lastUsableByte);
  186.         *endHeader = *pageHeader;
  187.  
  188.         /*
  189.          *    dirty the page
  190.          */
  191.         DIRTY_PAGE(tempLink->pageHash);
  192.  
  193.         /*
  194.          *    mark this as a log page
  195.          */
  196.         PSET_PAGE_TYPE(tempLink->pageHash, PAGE_LOG);
  197.  
  198.         /*
  199.          *    Give the tail of the log a dummy force mark so
  200.          *    that preflushLog() will flush it
  201.         OpenLog.tailBuffer = tempLink->pageHash;
  202.         OpenLog.tailBuffer->forceMark = i+1;
  203.         openLog->tailLink    = tempLink;
  204.          */
  205.  
  206.         /*
  207.          *    unfix the page
  208.          */
  209.         signalSemaphore(&(tempLink->pageHash->semaphore));
  210.         bf_UnfixPage(tempLink, BF_DEFAULT, FALSE);
  211.  
  212.         pageHashList[numToForce] = tempLink->pageHash;
  213.         numToForce++;
  214.     }
  215.  
  216.     /*
  217.      *    force rest of log to disk
  218.      */
  219.     if (numToForce > 0) {
  220.         bf_ForcePageList(pageHashList, numToForce, BF_SEM);
  221.         numToForce = 0;
  222.     }
  223.  
  224.     /* allow server to perform I/O itself (synchrounous) */
  225.     ALLOW_FAST_IO();
  226.  
  227.     /*
  228.      *    contruct a pid for reading the page
  229.      */
  230.     pid.volid = openLog->volid;
  231.     pid.page  = openLog->logFileAddr;
  232.  
  233.     /*
  234.      *    read the first log page into the cache
  235.      */
  236.     if ((tailLink = bf_ReadPage(openLog->writeGroup, &pid,
  237.                                 openLog->page2size, BF_SEM )) == NULL)    {
  238.  
  239.         SM_ERROR(TYPE_FATAL, Active->errno);
  240.     }
  241.  
  242.     /*
  243.      *    get a pointer to the page hash
  244.      */
  245.     tailBuffer = tailLink->pageHash;
  246.  
  247.     /*
  248.      *    mark the page as a log buffer
  249.      */
  250.     PSET_PAGE_TYPE(tailBuffer, PAGE_LOG);
  251.  
  252.     /*
  253.      *    get a pointer to the header of the page
  254.      */
  255.     pageHeader = (LOGPAGEHDR *) tailBuffer->bufFrame;
  256.  
  257.     /*
  258.      *    initialize the page header
  259.      */
  260.     pageHeader->magic      = LOGPAGE_MAGIC;
  261.     pageHeader->wrapCount  = initWrapCount;
  262.     pageHeader->lastRecord = NULL_LAST_RECORD;
  263.  
  264.     /*
  265.      *    get a pointer to the end of the page
  266.      */
  267.     endHeader = (LOGPAGEHDR *) (((char *) pageHeader) + openLog->lastUsableByte);
  268.  
  269.     /*
  270.      *    initialize the header on the page
  271.      */
  272.     endHeader->magic      = LOGPAGE_MAGIC;
  273.     endHeader->wrapCount  = initWrapCount;
  274.     endHeader->lastRecord = NULL_LAST_RECORD;
  275.  
  276.     /*
  277.      *    set the checkpoint information
  278.      */
  279.     openLog->checkPointPid = 0;
  280.     openLog->checkPointLSN.offset = FIRST_LSN;
  281.     openLog->checkPointLSN.wrapCount = 1;
  282.     TRPRINT(TR_LOG, TR_LEVEL_2, ("checkPointLSN:%d", openLog->checkPointLSN.offset));
  283.  
  284.     /*
  285.      *    get a pointer to where the checkpoint record resides
  286.      */
  287.     record = (LOGRECORDHDR *) (tailBuffer->bufFrame + FIRST_LSN);
  288.  
  289.     /*
  290.      *    record the initial checkpoint
  291.      */
  292.     record->magic           = LOGRECORD_MAGIC;
  293.     record->length         = sizeof(LOGRECORDHDR) + sizeof(CHECKPOINTINFO);
  294.     record->type            = LOG_REC_TYPE_CHECKPOINT;
  295.     record->recordLSN     = openLog->checkPointLSN;
  296.     record->tid             = NULL_TID;
  297.     record->previousLSN  = NULL_LSN;
  298.     record->imageCount     = 1;
  299.  
  300.     /*
  301.      *    setup the image
  302.      */
  303.     record->imageOffset[0] = 0;
  304.     record->imageSize[0]   = sizeof(CHECKPOINTINFO);
  305.  
  306.     /*
  307.      *    get a pointer to the checkpoint info record
  308.      */
  309.     checkInfo = (CHECKPOINTINFO *) (((char *) record) + sizeof(LOGRECORDHDR));
  310.     
  311.     /*
  312.      *    fill in the body field
  313.      */
  314.     checkInfo->numActiveTrans = 0;
  315.     checkInfo->numDirtyPages  = 0;
  316.     checkInfo->wrapCount      = initWrapCount;
  317.  
  318.     /*
  319.      *    set the openlog information
  320.      */
  321.     openLog->tailBuffer = tailBuffer;
  322.     openLog->tailLink    = tailLink;
  323.     openLog->wrapCount  = initWrapCount;
  324.     openLog->tailLSN    = FIRST_LSN + record->length;
  325.     openLog->tailPid    = 0;
  326.     openLog->activePid  = NULLPID;
  327.     openLog->nextValidLSN.wrapCount = initWrapCount;
  328.     openLog->nextValidLSN.offset = openLog->tailLSN;
  329.     TRPRINT(TR_LOG, TR_LEVEL_2, ("tailLSN:%d", openLog->tailLSN));
  330.  
  331.     /*
  332.      *    fill in the lastRecord field
  333.      */
  334.     pageHeader->lastRecord = FIRST_LSN;
  335.     endHeader->lastRecord = FIRST_LSN;
  336.  
  337.     /*
  338.      *    put non-zero first and force mark
  339.      */
  340.     tailBuffer->forceMark = tailBuffer->firstMark = 1;
  341.  
  342.     /*
  343.      *    dirty the page
  344.      */
  345.     DIRTY_PAGE(tailBuffer);
  346.  
  347.     /*
  348.      *    force it to disk
  349.      */
  350.     bf_ForcePage(tailBuffer, NOFLAGS);
  351.  
  352.     /*
  353.      *    unfix the page
  354.      */
  355.     signalSemaphore(&(tailLink->pageHash->semaphore));
  356.     bf_UnfixPage(tailLink, BF_DEFAULT, FALSE);
  357.  
  358.     /*
  359.      *    get a pointer to the checkpoint pointer page
  360.      */
  361.     checkMaster = (CHECKPOINTMASTER *) openLog->controlBuffer->bufFrame;
  362.  
  363.     /*
  364.      *    zero out the page
  365.      */
  366.     bzero(openLog->controlBuffer->bufFrame, MIN_PAGESIZE);
  367.  
  368.     /*
  369.      *    record the location of the initial checkpoint
  370.      */
  371.     checkMaster->magic                        = CHECKPOINTMASTER_MAGIC;
  372.     checkMaster->wrapCount                = initWrapCount;
  373.     checkMaster->oldestDirtyLSN           = FIRST_LSN;
  374.     checkMaster->checkRecordLSN.offset      = FIRST_LSN;
  375.     checkMaster->checkRecordLSN.wrapCount = initWrapCount;
  376.  
  377.     /*
  378.      *    dirty the page (get the semaphore to make the 
  379.      *    debugging version of DIRTY_PAGE happy)
  380.      */
  381. #ifdef DEBUG
  382.     waitSemaphore(&(openLog->controlBuffer->pageHash->semaphore));
  383. #endif
  384.     DIRTY_PAGE(openLog->controlBuffer->pageHash);
  385. #ifdef DEBUG
  386.     signalSemaphore(&(openLog->controlBuffer->pageHash->semaphore));
  387. #endif
  388.  
  389.     /*
  390.      *    force it to disk
  391.      */
  392.     bf_ForcePage(openLog->controlBuffer->pageHash, BF_SEM);
  393.  
  394.     /* mark the volume as regenerated */
  395.     openLog->volRec->header->dismountEndOfLog.wrapCount = 1;
  396.     openLog->volRec->dirty = TRUE;
  397.     DIRTY_PAGE(openLog->volRec->headerLink->pageHash);
  398.     bf_ForcePage(openLog->volRec->headerLink->pageHash, BF_SEM);
  399.  
  400.     /* remember this checkpoint */
  401.     LastFlushedCheckpoint = checkMaster->checkRecordLSN;
  402.     OldestDirtyPageLSN = LastFlushedCheckpoint;
  403.  
  404.     /*
  405.      *    set up a new transaction record
  406.      */
  407.     TransInfo.tidSequence = 1;
  408.  
  409.     /*
  410.      *    give back the latch and the semaphore
  411.      */
  412.     signalSemaphore( &(openLog->writeSemaphore) );
  413.     signalLatch( &(openLog->logLatch) );
  414.  
  415.     /*
  416.      *    return success
  417.      */
  418.     return(esmNOERROR);
  419. }
  420.