test: logpgsup.c Source File

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

# logpgsup.c

Go to the documentation of this file.

    00001 /*++
    00002
    00003 Copyright (c) 1990  Microsoft Corporation
    00004
    00005 Module Name:
    00006
    00007     LogPgSup.c
    00008
    00009 Abstract:
    00010
    00011     This module implements support for manipulating log pages.
    00012
    00013 Author:
    00014
    00015     Brian Andrew    [BrianAn]   20-June-1991
    00016
    00017 Revision History:
    00018
    00019 --*/
    00020
    00021 #include "lfsprocs.h"
    00022
    00023 //
    00024 //  The debug trace level
    00025 //
    00026
    00027 #define Dbg                              (DEBUG_TRACE_LOG_PAGE_SUP)
    00028
    00029 #undef MODULE_POOL_TAG
    00030 #define MODULE_POOL_TAG                  ('PsfL')
    00031
    00032 #ifdef ALLOC_PRAGMA
    00033 #pragma alloc_text(PAGE, LfsAllocateSpanningBuffer)
    00034 #pragma alloc_text(PAGE, LfsFreeSpanningBuffer)
    00035 #pragma alloc_text(PAGE, LfsNextLogPageOffset)
    00036 #endif
    00037
    00038
    00039 VOID
    00040 LfsNextLogPageOffset (
    00041     IN PLFCB Lfcb,
    00042     IN LONGLONG CurrentLogPageOffset,
    00043     OUT PLONGLONG NextLogPageOffset,
    00044     OUT PBOOLEAN Wrapped
    00045     )
    00046
    00047 /*++
    00048
    00049 Routine Description:
    00050
    00051     This routine will compute the offset in the log file of the next log
    00052     page.
    00053
    00054 Arguments:
    00055
    00056     Lfcb - This is the file control block for the log file.
    00057
    00058     CurrentLogPageOffset - This is the file offset of the current log page.
    00059
    00060     NextLogPageOffset - Address to store the next log page to use.
    00061
    00062     Wrapped - This is a pointer to a boolean variable that, if present,
    00063               we use to indicate whether we wrapped in the log file.
    00064
    00065 Return Value:
    00066
    00067     None.
    00068
    00069 --*/
    00070
    00071 {
    00072     PAGED_CODE();
    00073
    00074     DebugTrace( +1, Dbg, "LfsNextLogPageOffset:  Entered\n", 0 );
    00075     DebugTrace(  0, Dbg, "Lfcb                          ->  %08lx\n", Lfcb );
    00076     DebugTrace(  0, Dbg, "CurrentLogPageOffset (Low)    ->  %08lx\n", CurrentLogPageOffset.LowPart );
    00077     DebugTrace(  0, Dbg, "CurrentLogPageOffset (High)   ->  %08lx\n", CurrentLogPageOffset.HighPart );
    00078     DebugTrace(  0, Dbg, "Wrapped                       ->  %08lx\n", Wrapped );
    00079
    00080     //
    00081     //  We add the log page size to the current log offset.
    00082     //
    00083
    00084     LfsTruncateOffsetToLogPage( Lfcb, CurrentLogPageOffset, &CurrentLogPageOffset );
    00085     *NextLogPageOffset = CurrentLogPageOffset + Lfcb->LogPageSize;                                                     //**** xxAdd( CurrentLogPageOffset, Lfcb->LogPageSize );
    00086
    00087     //
    00088     //  If the result is larger than the file, we use the first page offset
    00089     //  in the file.
    00090     //
    00091
    00092     if ( *NextLogPageOffset >= Lfcb->FileSize ) {                                                                      //**** xxGeq( *NextLogPageOffset, Lfcb->FileSize )
    00093
    00094         *NextLogPageOffset = Lfcb->FirstLogPage;
    00095
    00096         *Wrapped = TRUE;
    00097
    00098     } else {
    00099
    00100         *Wrapped = FALSE;
    00101     }
    00102
    00103     DebugTrace(  0, Dbg, "NextLogPageOffset (Low)    ->  %08lx\n", NextLogPageOffset->LowPart );
    00104     DebugTrace(  0, Dbg, "NextLogPageOffset (High)   ->  %08lx\n", NextLogPageOffset->HighPart );
    00105     DebugTrace(  0, Dbg, "Wrapped                    ->  %08x\n", *Wrapped );
    00106     DebugTrace( -1, Dbg, "LfsNextLogPageOffset:  Exit\n", 0 );
    00107
    00108     return;
    00109 }
    00110
    00111
    00112 PVOID
    00113 LfsAllocateSpanningBuffer (
    00114     IN PLFCB Lfcb,
    00115     IN ULONG Length
    00116     )
    00117
    00118 /*++
    00119
    00120 Routine Description:
    00121
    00122     This routine is called to allocate a spare buffer to read a file record
    00123     which spans a log page.  We will first try to allocate one.  If that
    00124     fails we will use one of the existing spare buffers.  If that fails then
    00125     we will raise.
    00126
    00127 Arguments:
    00128
    00129     Lfcb - This is the file control block for the log file.
    00130
    00131     Length - Length of the buffer required.
    00132
    00133 Return Value:
    00134
    00135     PVOID - Pointer to the buffer to use for reading the log record.
    00136         May be either from pool or from the auxilary buffer pool.
    00137
    00138 --*/
    00139
    00140 {
    00141     PVOID NewBuffer = NULL;
    00142     ERESOURCE_THREAD Thread;
    00143     BOOLEAN Wait = FALSE;
    00144
    00145     PAGED_CODE();
    00146
    00147     DebugTrace( +1, Dbg, "LfsAllocateSpanningBuffer:  Entered\n", 0 );
    00148
    00149     //
    00150     //  Loop while we don't have a buffer.  First try to get our reserved buffer
    00151     //  without waiting.  Then try to allocate a buffer.  Finally wait for the reserved
    00152     //  buffer as the final alternative.
    00153     //
    00154
    00155     do {
    00156
    00157         //
    00158         //  Skip the reserved buffer if the request is larger than we can read into it.
    00159         //
    00160
    00161         if (Length <= LFS_BUFFER_SIZE) {
    00162
    00163             //
    00164             //  If this thread already owns one buffer it can get the second directly.
    00165             //
    00166
    00167             Thread = ExGetCurrentResourceThread();
    00168
    00169             if (Thread == LfsData.BufferOwner) {
    00170
    00171                 if (!FlagOn( LfsData.BufferFlags, LFS_BUFFER1_OWNED )) {
    00172
    00173                     SetFlag( LfsData.BufferFlags, LFS_BUFFER1_OWNED );
    00174                     NewBuffer = LfsData.Buffer1;
    00175                     break;
    00176
    00177                 } else if (!FlagOn( LfsData.BufferFlags, LFS_BUFFER2_OWNED )) {
    00178
    00179                     SetFlag( LfsData.BufferFlags, LFS_BUFFER2_OWNED );
    00180                     NewBuffer = LfsData.Buffer2;
    00181                     break;
    00182
    00183                 } else if (Wait) {
    00184
    00185                     //
    00186                     //  This shouldn't happen but handle anyway.
    00187                     //
    00188
    00189                     DebugTrace( -1, Dbg, "LfsAllocateSpanningBuffer:  Exit\n", 0 );
    00190                     ExRaiseStatus( STATUS_INSUFFICIENT_RESOURCES );
    00191                 }
    00192
    00193             //
    00194             //  Otherwise acquire the buffer lock and check the state of the buffers.
    00195             //
    00196
    00197             } else {
    00198
    00199                 BOOLEAN LfcbOwned = TRUE;
    00200
    00201                 while (TRUE) {
    00202
    00203                     LfsAcquireBufferLock();
    00204
    00205                     //
    00206                     //  Check to see if the buffers are available.  No
    00207                     //  need to drop the Lfcb in the typical case.
    00208                     //
    00209
    00210                     if (LfsData.BufferOwner == (ERESOURCE_THREAD) NULL) {
    00211
    00212                         ASSERT( !FlagOn( LfsData.BufferFlags, LFS_BUFFER1_OWNED | LFS_BUFFER2_OWNED ));
    00213                         NewBuffer = LfsData.Buffer1;
    00214                         LfsData.BufferOwner = Thread;
    00215                         SetFlag( LfsData.BufferFlags, LFS_BUFFER1_OWNED );
    00216                         LfsBlockBufferWaiters();
    00217
    00218                         //
    00219                         //  Reacquire the Lfcb if needed.
    00220                         //
    00221
    00222                         if (!LfcbOwned) {
    00223
    00224                             LfsAcquireLfcb( Lfcb );
    00225                         }
    00226
    00227                         //
    00228                         //  Break out.
    00229                         //
    00230
    00231                         LfsReleaseBufferLock();
    00232                         break;
    00233                     }
    00234
    00235                     //
    00236                     //  Release the Lfcb and wait on the notification for the buffers.
    00237                     //
    00238
    00239                     if (Wait) {
    00240
    00241                         if (LfcbOwned) {
    00242                             LfsReleaseLfcb( Lfcb );
    00243                             LfcbOwned = FALSE;
    00244                         }
    00245
    00246                         LfsReleaseBufferLock();
    00247                         LfsWaitForBufferNotification();
    00248
    00249                     } else {
    00250
    00251                         //
    00252                         //  Go ahead and try to allocate a buffer from pool next.
    00253                         //
    00254
    00255                         LfsReleaseBufferLock();
    00256                         break;
    00257                     }
    00258                 }
    00259             }
    00260
    00261         //
    00262         //  Raise if we already tried the allocate path.
    00263         //
    00264
    00265         } else if (Wait) {
    00266
    00267             DebugTrace( -1, Dbg, "LfsAllocateSpanningBuffer:  Exit\n", 0 );
    00268             ExRaiseStatus( STATUS_INSUFFICIENT_RESOURCES );
    00269         }
    00270
    00271         //
    00272         //  Try pool if we didn't get a buffer above.
    00273         //
    00274
    00275         if (NewBuffer == NULL) {
    00276
    00277             //
    00278             //  Try pool next but don't let this fail on pool allocation.
    00279             //
    00280
    00281             NewBuffer = LfsAllocatePoolNoRaise( PagedPool, Length );
    00282         }
    00283
    00284         //
    00285         //  Wait on the next pass through the loop.
    00286         //
    00287
    00288         Wait = TRUE;
    00289
    00290     } while (NewBuffer == NULL);
    00291
    00292     DebugTrace( -1, Dbg, "LfsAllocateSpanningBuffer:  Exit\n", 0 );
    00293     return NewBuffer;
    00294 }
    00295
    00296 VOID
    00297 LfsFreeSpanningBuffer (
    00298     IN PVOID Buffer
    00299     )
    00300
    00301 /*++
    00302
    00303 Routine Description:
    00304
    00305     This routine is called to free a buffer used to read a log record
    00306     which spans pages.  We will check if it is one of our special buffers
    00307     and deal with synchronization in that case.
    00308
    00309 Arguments:
    00310
    00311     Buffer - Buffer to free.
    00312
    00313 Return Value:
    00314
    00315     None.
    00316
    00317 --*/
    00318
    00319 {
    00320     ERESOURCE_THREAD Thread;
    00321
    00322     PAGED_CODE();
    00323
    00324     DebugTrace( +1, Dbg, "LfsFreeSpanningBuffer:  Entered\n", 0 );
    00325
    00326     //
    00327     //  Do an unsafe test of the buffer flags.  If we own a buffer then they must be non-zero.
    00328     //  Otherwise do the correct check of the resource thread.
    00329     //
    00330
    00331     if (!FlagOn( LfsData.BufferFlags, LFS_BUFFER1_OWNED | LFS_BUFFER2_OWNED ) ||
    00332         (LfsData.BufferOwner != ExGetCurrentResourceThread())) {
    00333
    00334         LfsFreePool( Buffer );
    00335
    00336     } else {
    00337
    00338         //
    00339         //  Acquire the lock for synchronization.
    00340         //
    00341
    00342         LfsAcquireBufferLock();
    00343
    00344         //
    00345         //  Check which buffer it is.
    00346         //
    00347
    00348         if (Buffer == LfsData.Buffer1) {
    00349
    00350             ClearFlag( LfsData.BufferFlags, LFS_BUFFER1_OWNED );
    00351
    00352         } else {
    00353
    00354             //
    00355             //  It better be buffer2
    00356             //
    00357
    00358             ASSERT( FlagOn( LfsData.BufferFlags, LFS_BUFFER2_OWNED ));
    00359             ClearFlag( LfsData.BufferFlags, LFS_BUFFER2_OWNED );
    00360         }
    00361
    00362         //
    00363         //  If no buffers owned then signal the waiters.
    00364         //
    00365
    00366         if (!FlagOn( LfsData.BufferFlags, LFS_BUFFER1_OWNED | LFS_BUFFER2_OWNED )) {
    00367
    00368             LfsData.BufferOwner = (ERESOURCE_THREAD) NULL;
    00369             LfsNotifyBufferWaiters();
    00370         }
    00371
    00372         LfsReleaseBufferLock();
    00373     }
    00374
    00375     DebugTrace( -1, Dbg, "LfsFreeSpanningBuffer:  Exit\n", 0 );
    00376
    00377     return;
    00378 }
    00379