test: verfysup.c Source File

Main Page | Class Hierarchy | Class List | File List | Class Members | File Members

# verfysup.c

Go to the documentation of this file.

    00001 /*++
    00002
    00003 Copyright (c) 1990  Microsoft Corporation
    00004
    00005 Module Name:
    00006
    00007     VerfySup.c
    00008
    00009 Abstract:
    00010
    00011     This module implements consistency checking and structure comparisions
    00012     on Lfs structures.
    00013
    00014 Author:
    00015
    00016     Brian Andrew    [BrianAn]   20-June-1991
    00017
    00018 Revision History:
    00019
    00020 --*/
    00021
    00022 #include "lfsprocs.h"
    00023
    00024 #ifdef LFS_RAISE
    00025 BOOLEAN LfsRaiseFull = FALSE;
    00026 #endif
    00027
    00028 #ifdef ALLOC_PRAGMA
    00029 #pragma alloc_text(PAGE, LfsCurrentAvailSpace)
    00030 #pragma alloc_text(PAGE, LfsFindCurrentAvail)
    00031 #pragma alloc_text(PAGE, LfsVerifyLogSpaceAvail)
    00032 #endif
    00033
    00034
    00035 VOID
    00036 LfsCurrentAvailSpace (
    00037     IN PLFCB Lfcb,
    00038     OUT PLONGLONG CurrentAvailSpace,
    00039     OUT PULONG CurrentPageBytes
    00040     )
    00041
    00042 /*++
    00043
    00044 Routine Description:
    00045
    00046     This routine is called to determine the available log space in the log file.
    00047     It returns the total number of free bytes and the number available on the
    00048     active page if present.  The total free bytes will reflect all of the empty
    00049     pages as well as the number in the active page.
    00050
    00051 Arguments:
    00052
    00053     Lfcb - Lfcb for this log file.
    00054
    00055     CurrentAvailSpace - This is the number of bytes available for log
    00056                         records.
    00057
    00058     CurrentPageBytes - This is the number of bytes remaining on the
    00059                        current log page.
    00060
    00061 Return Value:
    00062
    00063     None.
    00064
    00065 --*/
    00066
    00067 {
    00068     *CurrentPageBytes = 0;
    00069
    00070     PAGED_CODE();
    00071
    00072     DebugTrace( +1, Dbg, "LfsCurrentAvailSpace:  Entered\n", 0 );
    00073
    00074     //
    00075     //  Get the total number from the Lfcb.
    00076     //
    00077
    00078     *CurrentAvailSpace = Lfcb->CurrentAvailable;
    00079
    00080     //
    00081     //  We now look to see if there are any bytes available on the Lbcb in
    00082     //  the active queue.  We can add this to the bytes available in the
    00083     //  log pages and also give this back to the caller.
    00084     //
    00085
    00086     if (!IsListEmpty( &Lfcb->LbcbActive )) {
    00087
    00088         PLBCB ThisLbcb;
    00089
    00090         ThisLbcb = CONTAINING_RECORD( Lfcb->LbcbActive.Flink,
    00091                                       LBCB,
    00092                                       ActiveLinks );
    00093
    00094         //
    00095         //  If the page is not empty or the page is empty but this is a
    00096         //  restart page then add the remaining bytes on this page.
    00097         //
    00098
    00099         if (FlagOn( ThisLbcb->LbcbFlags, LBCB_NOT_EMPTY | LBCB_FLUSH_COPY )) {
    00100
    00101             *CurrentPageBytes = (ULONG)Lfcb->LogPageSize - (ULONG)ThisLbcb->BufferOffset;
    00102
    00103             *CurrentAvailSpace = *CurrentAvailSpace + *CurrentPageBytes;                                               //**** xxAdd( *CurrentAvailSpace, xxFromUlong( *CurrentPageBytes ));
    00104         }
    00105     }
    00106
    00107     DebugTrace( +1, Dbg, "LfsCurrentAvailSpace:  Exit\n", 0 );
    00108
    00109     return;
    00110 }
    00111
    00112
    00113 BOOLEAN
    00114 LfsVerifyLogSpaceAvail (
    00115     IN PLFCB Lfcb,
    00116     IN PLCH Lch,
    00117     IN ULONG RemainingLogBytes,
    00118     IN LONG UndoRequirement,
    00119     IN BOOLEAN ForceToDisk
    00120     )
    00121
    00122 /*++
    00123
    00124 Routine Description:
    00125
    00126     This routine is called to verify that we may write this log record into the
    00127     log file.  We want to always leave room for each transaction to abort.
    00128
    00129     We determine how much space the current log record will take and the
    00130     worst case for its undo operation.  If this space is available we
    00131     update the corresponding values in the Lfcb and Lch for bookkeeping.
    00132     Otherwise we raise a status indicating that the log file is full.
    00133
    00134     The disk usage is different for the packed and unpacked cases.  Make the
    00135     following adjustments after finding the total available and amount still
    00136     remaining on the last active page,
    00137
    00138     Packed Case:
    00139
    00140         Size needed for log record is data size plus header size.
    00141
    00142         Undo requirement is the undo data size plus the header size.
    00143             We have already taken into account the end of the pages
    00144             except for the current page.
    00145
    00146         Add the log record size to the undo requirement to get the
    00147             log file usage.  Compare this number with the actual available
    00148             space (Available - CommittedUndo).  If the space is not
    00149             available, then raise LOG_FILE_FULL.  Must take into account
    00150             any unused bytes at the end of the current page.
    00151
    00152     Unpacked Case:
    00153
    00154         Size needed is initially header size plus data size.
    00155
    00156         If the log record can't begin on the current page then
    00157             add the bytes being thrown away to the log record size.
    00158
    00159         If the page is being forced to disk then add any remaining
    00160             bytes on the last page.  To the bytes being used.
    00161
    00162         Undo requirement is twice the sum of the header size and
    00163             undo size.  We double the requested size since the log
    00164             record will always fit on a page.  This can be a
    00165             positive or negative number.
    00166
    00167         Add the log record usage to the undo usage to get the log file
    00168             usage.  Compare this number with the actual available
    00169             space (Available - CommittedUndo).  If the space is not
    00170             available, then raise LOG_FILE_FULL.
    00171
    00172 Arguments:
    00173
    00174     Lfcb - Lfcb for this log file.
    00175
    00176     Lch - Client handle
    00177
    00178     RemainingLogBytes - Number of bytes for the current log record
    00179
    00180     UndoRequirement - User's requirement for the undo record.
    00181
    00182     ForceToDisk - Indicates if this log record will be flushed to disk.
    00183
    00184 Return Value:
    00185
    00186     BOOLEAN - Advisory, indicates that there is less than 1/4 of the log file available.
    00187
    00188 --*/
    00189
    00190 {
    00191     ULONG CurrentLogRecordSize;
    00192     ULONG LogRecordStart;
    00193     ULONG TailBytes;
    00194
    00195     LONGLONG CurrentAvailSpace;
    00196     ULONG CurrentPageBytes;
    00197
    00198     LONGLONG LogFileUsage;
    00199
    00200     PAGED_CODE();
    00201
    00202     DebugTrace( +1, Dbg, "LfsVerifyLogSpaceAvail:  Entered\n", 0 );
    00203     DebugTrace(  0, Dbg, "Lfcb              -> %08x\n", Lfcb );
    00204     DebugTrace(  0, Dbg, "Lch               -> %08lx\n", Lch );
    00205     DebugTrace(  0, Dbg, "RemainingLogBytes -> %08lx\n", RemainingLogBytes );
    00206     DebugTrace(  0, Dbg, "UndoRequirement   -> %08lx\n", UndoRequirement );
    00207     DebugTrace(  0, Dbg, "ForceToDisk       -> %04x\n", ForceToDisk );
    00208
    00209     //
    00210     //  Start by collecting the current data on the file.
    00211     //
    00212
    00213     LfsCurrentAvailSpace( Lfcb,
    00214                           &CurrentAvailSpace,
    00215                           &CurrentPageBytes );
    00216
    00217     //
    00218     //  We compute the amount of space needed for the current log record by
    00219     //  adding up the following:
    00220     //
    00221     //      Space at end of current log page which won't be used.
    00222     //      Size of header for log record.
    00223     //      Size of client data in log record.
    00224     //      Size of wasted portion of log page if this is forced to disk.
    00225     //
    00226
    00227     //
    00228     //  Start with the size of the header and the client data.
    00229     //
    00230
    00231     CurrentLogRecordSize = RemainingLogBytes + Lfcb->RecordHeaderLength;
    00232
    00233     //
    00234     //  If the log is packed and there are bytes on the current page we need
    00235     //  to take into account any bytes at the end of the page which won't
    00236     //  be used.  This will happen if the log record spills into the end of
    00237     //  the log page but doesn't use up the page.  If the remaining bytes are
    00238     //  less than a record header size we must throw them away.
    00239     //
    00240
    00241     if (FlagOn( Lfcb->Flags, LFCB_PACK_LOG )) {
    00242
    00243         if (CurrentPageBytes != 0
    00244             && CurrentLogRecordSize < CurrentPageBytes
    00245             && (CurrentPageBytes - CurrentLogRecordSize) < Lfcb->RecordHeaderLength) {
    00246
    00247             CurrentLogRecordSize += (CurrentPageBytes - CurrentLogRecordSize);
    00248         }
    00249
    00250     //
    00251     //  If this is the unpacked case we need to check for bytes being thrown away
    00252     //  on the current page or the last page.
    00253     //
    00254
    00255     } else {
    00256
    00257         //
    00258         //  If there is an active Lbcb, we need to add any bytes that
    00259         //  would be thrown away at the end.
    00260         //
    00261
    00262         if (CurrentPageBytes != 0) {
    00263
    00264             //
    00265             //  We won't use this log page unless the new log record will fit or
    00266             //  unless this is the first log record in the page.
    00267             //
    00268
    00269             if ((CurrentPageBytes != (ULONG)Lfcb->LogPageDataSize)
    00270                 && (CurrentLogRecordSize > CurrentPageBytes)) {
    00271
    00272                 CurrentLogRecordSize += CurrentPageBytes;
    00273
    00274                 //
    00275                 //  Remember that we will start this log record at the first
    00276                 //  byte in the data portion of a page.
    00277                 //
    00278
    00279                 LogRecordStart = 0;
    00280
    00281             //
    00282             //  Otherwise this will start at the current offset into the
    00283             //  data portion of the log page.
    00284             //
    00285
    00286             } else {
    00287
    00288                 LogRecordStart = (ULONG)Lfcb->LogPageDataSize - CurrentPageBytes;
    00289             }
    00290
    00291         //
    00292         //  If there was no Lbcb, then we know that we will start at the first
    00293         //  byte of the data portion.
    00294         //
    00295
    00296         } else {
    00297
    00298             LogRecordStart = 0;
    00299         }
    00300
    00301         //
    00302         //  We always assume that we will use up the rest of the bytes on the last page
    00303         //  in computing whether the log record will fit in the available space.  We
    00304         //  only subtract that space from the available space if this is a force write.
    00305         //
    00306
    00307         if (ForceToDisk) {
    00308
    00309             //
    00310             //  We take into account where we start on a log page and continue
    00311             //  to subtract log pages until we know the amount on the last
    00312             //  page.
    00313             //
    00314
    00315             TailBytes = RemainingLogBytes + Lfcb->RecordHeaderLength + LogRecordStart;
    00316
    00317             while (TailBytes > (ULONG)Lfcb->LogPageDataSize) {
    00318
    00319                 TailBytes -= (ULONG)Lfcb->LogPageDataSize;
    00320             }
    00321
    00322             TailBytes = (ULONG)Lfcb->LogPageDataSize - TailBytes;
    00323
    00324             CurrentLogRecordSize += TailBytes;
    00325         }
    00326     }
    00327
    00328     //
    00329     //  We now know the number of bytes needed for the current log page.
    00330     //  Next we compute the number of bytes being reserved by UndoRequirement.
    00331     //  If the UndoRequirement is positive, we will add to the amount reserved
    00332     //  in the log file.  If it is negative, we will subtract from the amount
    00333     //  reserved in the log file.
    00334     //
    00335
    00336     //
    00337     //  When we have an actual reserve amount, we convert it to positive
    00338     //  and then reserve twice the space required to hold the data and
    00339     //  its header (up to the maximum of a single page.
    00340     //
    00341
    00342     if (UndoRequirement != 0) {
    00343
    00344         if (!FlagOn( Lfcb->Flags, LFCB_PACK_LOG )) {
    00345
    00346             UndoRequirement *= 2;
    00347         }
    00348
    00349         if (UndoRequirement < 0) {
    00350
    00351             UndoRequirement -= (2 * Lfcb->RecordHeaderLength);
    00352         } else {
    00353
    00354             UndoRequirement += (2 * Lfcb->RecordHeaderLength);
    00355         }
    00356     }
    00357
    00358     //
    00359     //  Now compute the net log file usage.  The result may be positive or
    00360     //  negative.
    00361     //
    00362
    00363     LogFileUsage = ((LONG) CurrentLogRecordSize)  + UndoRequirement;                                                   //**** xxFromLong( ((LONG) CurrentLogRecordSize)  + UndoRequirement );
    00364
    00365     //
    00366     //  The actual available space is the CurrentAvail minus the reserved
    00367     //  undo value in the Lfcb.
    00368     //
    00369
    00370     CurrentAvailSpace = CurrentAvailSpace - Lfcb->TotalUndoCommitment;                                                 //**** xxSub( CurrentAvailSpace, Lfcb->TotalUndoCommitment );
    00371
    00372     //
    00373     //  If this log file usage is greater than the available log file space
    00374     //  then we raise a status code.
    00375     //
    00376
    00377 #ifdef LFS_RAISE
    00378     if (LfsRaiseFull) {
    00379
    00380         LfsRaiseFull = FALSE;
    00381         DebugTrace( -1, Dbg, "LfsVerifyLogSpaceAvail:  About to raise\n", 0 );
    00382         ExRaiseStatus( STATUS_LOG_FILE_FULL );
    00383     }
    00384 #endif
    00385
    00386     if (LogFileUsage > CurrentAvailSpace) {
    00387
    00388         DebugTrace( -1, Dbg, "LfsVerifyLogSpaceAvail:  About to raise\n", 0 );
    00389         ExRaiseStatus( STATUS_LOG_FILE_FULL );
    00390     }
    00391
    00392     Lfcb->TotalUndoCommitment = Lfcb->TotalUndoCommitment + UndoRequirement;                                           //**** xxAdd( Lfcb->TotalUndoCommitment, xxFromLong( UndoRequirement ));
    00393
    00394     Lch->ClientUndoCommitment = Lch->ClientUndoCommitment + UndoRequirement;                                           //**** xxAdd( Lch->ClientUndoCommitment, xxFromLong( UndoRequirement ));
    00395
    00396     DebugTrace( -1, Dbg, "LfsVerifyLogSpaceAvail:  Exit\n", 0 );
    00397
    00398     //
    00399     //  Now check if the log file is almost used up.
    00400     //
    00401
    00402     if ((CurrentAvailSpace - LogFileUsage) < (Lfcb->TotalAvailable >> 2)) {
    00403
    00404         return TRUE;
    00405     }
    00406
    00407     return FALSE;
    00408 }
    00409
    00410
    00411 VOID
    00412 LfsFindCurrentAvail (
    00413     IN PLFCB Lfcb
    00414     )
    00415
    00416 /*++
    00417
    00418 Routine Description:
    00419
    00420     This routine is called to calculate the number of bytes available for log
    00421     records which are in completely empty log record pages.  It ignores any
    00422     partial pages in the active work queue and ignores any page which is
    00423     going to be reused.
    00424
    00425 Arguments:
    00426
    00427     Lfcb - Lfcb for this log file.
    00428
    00429 Return Value:
    00430
    00431     None.
    00432
    00433 --*/
    00434
    00435 {
    00436     LONGLONG OldestPageOffset;
    00437     LONGLONG NextFreePageOffset;
    00438     LONGLONG FreeBytes;
    00439
    00440     PAGED_CODE();
    00441
    00442     DebugTrace( +1, Dbg, "LfsFindCurrentAvail:  Entered\n", 0 );
    00443     DebugTrace(  0, Dbg, "Lfcb              -> %08x\n", Lfcb );
    00444
    00445     //
    00446     //  If there is a last lsn in the restart area then we know
    00447     //  that we will have to compute the free range.
    00448     //
    00449
    00450     if (!FlagOn( Lfcb->Flags, LFCB_NO_LAST_LSN )) {
    00451
    00452         //
    00453         //  If there is no oldest Lsn then start at the
    00454         //  first page of the file.
    00455         //
    00456
    00457         if (FlagOn( Lfcb->Flags, LFCB_NO_OLDEST_LSN )) {
    00458
    00459             OldestPageOffset = Lfcb->FirstLogPage;
    00460
    00461         } else {
    00462
    00463             LfsTruncateOffsetToLogPage( Lfcb,
    00464                                         Lfcb->OldestLsnOffset,
    00465                                         &OldestPageOffset );
    00466         }
    00467
    00468         //
    00469         //  We will use the next log page offset to compute the
    00470         //  next free page.  If we are going to reuse this page
    00471         //  go to the next page,  if we are at the first page then
    00472         //  use the end of the file.
    00473         //
    00474
    00475         if (FlagOn( Lfcb->Flags, LFCB_REUSE_TAIL )) {
    00476
    00477             NextFreePageOffset = Lfcb->NextLogPage + Lfcb->LogPageSize;                                                //**** xxAdd( Lfcb->NextLogPage, Lfcb->LogPageSize );
    00478
    00479         } else if ( Lfcb->NextLogPage == Lfcb->FirstLogPage ) {                                                        //**** xxEql( Lfcb->NextLogPage, Lfcb->FirstLogPage )
    00480
    00481             NextFreePageOffset = Lfcb->FileSize;
    00482
    00483         } else {
    00484
    00485             NextFreePageOffset = Lfcb->NextLogPage;
    00486         }
    00487
    00488         //
    00489         //  If the two offsets are the same then there is no available space.
    00490         //
    00491
    00492         if ( OldestPageOffset == NextFreePageOffset ) {                                                                //**** xxEql( OldestPageOffset, NextFreePageOffset )
    00493
    00494             Lfcb->CurrentAvailable = 0;
    00495
    00496         } else {
    00497
    00498             //
    00499             //  If the free offset follows the oldest offset then subtract
    00500             //  this range from the total available pages.
    00501             //
    00502
    00503             if ( OldestPageOffset < NextFreePageOffset ) {                                                             //**** xxLtr( OldestPageOffset, NextFreePageOffset )
    00504
    00505                 FreeBytes = Lfcb->TotalAvailInPages - ( NextFreePageOffset - OldestPageOffset );                       //**** xxSub( Lfcb->TotalAvailInPages, xxSub( NextFreePageOffset, OldestPageOffset ));
    00506
    00507             } else {
    00508
    00509                 FreeBytes = OldestPageOffset - NextFreePageOffset;                                                     //**** xxSub( OldestPageOffset, NextFreePageOffset );
    00510             }
    00511
    00512             //
    00513             //  We now have the total bytes in the pages available.  We
    00514             //  now have to subtract the size of the page header to get
    00515             //  the total available bytes.
    00516             //
    00517             //  We will convert the bytes to pages and then multiple
    00518             //  by the data size of each page.
    00519             //
    00520
    00521             FreeBytes = Int64ShrlMod32(((ULONGLONG)(FreeBytes)), Lfcb->LogPageShift);
    00522
    00523             Lfcb->CurrentAvailable = FreeBytes * (ULONG)Lfcb->ReservedLogPageSize;                                     //**** xxXMul( FreeBytes, Lfcb->ReservedLogPageSize.LowPart );
    00524         }
    00525
    00526     //
    00527     //  Otherwise the entire file is available.
    00528     //
    00529
    00530     } else {
    00531
    00532         Lfcb->CurrentAvailable = Lfcb->MaxCurrentAvail;
    00533     }
    00534
    00535     DebugTrace( -1, Dbg, "LfsFindCurrentAvail:  Exit\n", 0 );
    00536
    00537     return;
    00538 }