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

Generated on Sat May 15 19:40:39 2004 for test by doxygen 1.3.7