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

querylog.c

Go to the documentation of this file.
00001 /*++ 00002 00003 Copyright (c) 1990 Microsoft Corporation 00004 00005 Module Name: 00006 00007 QueryLog.c 00008 00009 Abstract: 00010 00011 This module implements the user routines which query for log records 00012 in a log file. 00013 00014 Author: 00015 00016 Brian Andrew [BrianAn] 20-June-1991 00017 00018 Revision History: 00019 00020 --*/ 00021 00022 #include "lfsprocs.h" 00023 00024 // 00025 // The debug trace level 00026 // 00027 00028 #define Dbg (DEBUG_TRACE_QUERY) 00029 00030 #undef MODULE_POOL_TAG 00031 #define MODULE_POOL_TAG ('QsfL') 00032 00033 VOID 00034 LfsFindLogRecord ( 00035 IN PLFCB Lfcb, 00036 IN OUT PLCB Lcb, 00037 IN LSN Lsn, 00038 OUT PLFS_RECORD_TYPE RecordType, 00039 OUT TRANSACTION_ID *TransactionId, 00040 OUT PLSN UndoNextLsn, 00041 OUT PLSN PreviousLsn, 00042 OUT PULONG BufferLength, 00043 OUT PVOID *Buffer 00044 ); 00045 00046 BOOLEAN 00047 LfsFindClientNextLsn ( 00048 IN PLFCB Lfcb, 00049 IN PLCB Lcb, 00050 OUT PLSN Lsn 00051 ); 00052 00053 BOOLEAN 00054 LfsSearchForwardByClient ( 00055 IN PLFCB Lfcb, 00056 IN OUT PLCB Lcb, 00057 OUT PLSN Lsn 00058 ); 00059 00060 #ifdef ALLOC_PRAGMA 00061 #pragma alloc_text(PAGE, LfsFindClientNextLsn) 00062 #pragma alloc_text(PAGE, LfsFindLogRecord) 00063 #pragma alloc_text(PAGE, LfsQueryLastLsn) 00064 #pragma alloc_text(PAGE, LfsReadLogRecord) 00065 #pragma alloc_text(PAGE, LfsReadNextLogRecord) 00066 #pragma alloc_text(PAGE, LfsSearchForwardByClient) 00067 #pragma alloc_text(PAGE, LfsTerminateLogQuery) 00068 #endif 00069 00070 00071 VOID 00072 LfsReadLogRecord ( 00073 IN LFS_LOG_HANDLE LogHandle, 00074 IN LSN FirstLsn, 00075 IN LFS_CONTEXT_MODE ContextMode, 00076 OUT PLFS_LOG_CONTEXT Context, 00077 OUT PLFS_RECORD_TYPE RecordType, 00078 OUT TRANSACTION_ID *TransactionId, 00079 OUT PLSN UndoNextLsn, 00080 OUT PLSN PreviousLsn, 00081 OUT PULONG BufferLength, 00082 OUT PVOID *Buffer 00083 ) 00084 00085 /*++ 00086 00087 Routine Description: 00088 00089 This routine initiates the query operation. It returns the log record 00090 in question and a context structure used by the Lfs to return related 00091 log records. The caller specifies what mode of query to use. He may 00092 walk backwards through the file by Undo records or all records for 00093 this client linked through the previous Lsn fields. He may also look 00094 forwards through the file for all records for the issuing client. 00095 00096 Arguments: 00097 00098 LogHandle - Pointer to private Lfs structure used to identify this 00099 client. 00100 00101 FirstLsn - Starting record for this query operation. 00102 00103 ContextMode - Method of query. 00104 00105 Context - Supplies the address to store a pointer to the Lfs created 00106 context structure. 00107 00108 RecordType - Supplies the address to store the record type of this 00109 log record. 00110 00111 TransactionId - Supplies the address to store the transaction Id of 00112 this log record. 00113 00114 UndoNextLsn - Supplies the address to store the Undo Next Lsn for this 00115 log record. 00116 00117 PreviousLsn - Supplies the address to store the Previous Lsn for this 00118 log record. 00119 00120 BufferLength - This is the length of the log data. 00121 00122 Buffer - This is a pointer to the start of the log data. 00123 00124 Return Value: 00125 00126 None 00127 00128 --*/ 00129 00130 { 00131 volatile NTSTATUS Status = STATUS_SUCCESS; 00132 00133 PLFS_CLIENT_RECORD ClientRecord; 00134 00135 PLCH Lch; 00136 00137 PLFCB Lfcb; 00138 00139 PLCB Lcb = NULL; 00140 00141 PAGED_CODE(); 00142 00143 DebugTrace( +1, Dbg, "LfsReadLogRecord: Entered\n", 0 ); 00144 DebugTrace( 0, Dbg, "Log Handle -> %08lx\n", LogHandle ); 00145 DebugTrace( 0, Dbg, "First Lsn (Low) -> %08lx\n", FirstLsn.LowPart ); 00146 DebugTrace( 0, Dbg, "First Lsn (High) -> %08lx\n", FirstLsn.HighPart ); 00147 DebugTrace( 0, Dbg, "Context Mode -> %08lx\n", ContextMode ); 00148 00149 Lch = (PLCH) LogHandle; 00150 00151 // 00152 // Check that the context mode is valid. 00153 // 00154 00155 switch (ContextMode) { 00156 00157 case LfsContextUndoNext : 00158 case LfsContextPrevious : 00159 case LfsContextForward : 00160 00161 break; 00162 00163 default: 00164 00165 DebugTrace( 0, Dbg, "Invalid context mode -> %08x\n", ContextMode ); 00166 ExRaiseStatus( STATUS_INVALID_PARAMETER ); 00167 } 00168 00169 // 00170 // Check that the structure is a valid log handle structure. 00171 // 00172 00173 LfsValidateLch( Lch ); 00174 00175 // 00176 // Use a try-except to catch errors. 00177 // 00178 00179 try { 00180 00181 // 00182 // Use a try-finally to facilitate cleanup. 00183 // 00184 00185 try { 00186 00187 // 00188 // Acquire the log file control block for this log file. 00189 // 00190 00191 LfsAcquireLch( Lch ); 00192 Lfcb = Lch->Lfcb; 00193 00194 // 00195 // If the Log file has been closed then refuse access. 00196 // 00197 00198 if (Lfcb == NULL) { 00199 00200 ExRaiseStatus( STATUS_ACCESS_DENIED ); 00201 } 00202 00203 // 00204 // Check that the client Id is valid. 00205 // 00206 00207 LfsValidateClientId( Lfcb, Lch ); 00208 00209 // 00210 // Check that the given Lsn is in the legal range for this client. 00211 // 00212 00213 ClientRecord = Add2Ptr( Lfcb->ClientArray, 00214 Lch->ClientArrayByteOffset, 00215 PLFS_CLIENT_RECORD ); 00216 00217 if (!LfsVerifyClientLsnInRange( Lfcb, ClientRecord, FirstLsn )) { 00218 00219 ExRaiseStatus( STATUS_DISK_CORRUPT_ERROR ); 00220 } 00221 00222 // 00223 // We can give up the Lfcb as we know the Lsn is within the file. 00224 // 00225 00226 LfsReleaseLch( Lch ); 00227 00228 // 00229 // Allocate and initialize a context structure. 00230 // 00231 00232 LfsAllocateLcb( Lfcb, &Lcb ); 00233 00234 LfsInitializeLcb( Lcb, 00235 Lch->ClientId, 00236 ContextMode ); 00237 00238 // 00239 // Find the log record indicated by the given Lsn. 00240 // 00241 00242 LfsFindLogRecord( Lfcb, 00243 Lcb, 00244 FirstLsn, 00245 RecordType, 00246 TransactionId, 00247 UndoNextLsn, 00248 PreviousLsn, 00249 BufferLength, 00250 Buffer ); 00251 00252 // 00253 // Update the client's arguments. 00254 // 00255 00256 *Context = Lcb; 00257 Lcb = NULL; 00258 00259 } finally { 00260 00261 DebugUnwind( LfsReadLogRecord ); 00262 00263 // 00264 // Release the log file control block if held. 00265 // 00266 00267 LfsReleaseLch( Lch ); 00268 00269 // 00270 // Deallocate the context block if an error occurred. 00271 // 00272 00273 if (Lcb != NULL) { 00274 00275 LfsDeallocateLcb( Lfcb, Lcb ); 00276 } 00277 00278 DebugTrace( 0, Dbg, "Context -> %08lx\n", *Context ); 00279 DebugTrace( 0, Dbg, "Buffer Length -> %08lx\n", *BufferLength ); 00280 DebugTrace( 0, Dbg, "Buffer -> %08lx\n", *Buffer ); 00281 DebugTrace( -1, Dbg, "LfsReadLogRecord: Exit\n", 0 ); 00282 } 00283 00284 } except (LfsExceptionFilter( GetExceptionInformation() )) { 00285 00286 Status = GetExceptionCode(); 00287 } 00288 00289 if (Status != STATUS_SUCCESS) { 00290 00291 ExRaiseStatus( Status ); 00292 } 00293 00294 return; 00295 } 00296 00297 00298 BOOLEAN 00299 LfsReadNextLogRecord ( 00300 IN LFS_LOG_HANDLE LogHandle, 00301 IN OUT LFS_LOG_CONTEXT Context, 00302 OUT PLFS_RECORD_TYPE RecordType, 00303 OUT TRANSACTION_ID *TransactionId, 00304 OUT PLSN UndoNextLsn, 00305 OUT PLSN PreviousLsn, 00306 OUT PLSN Lsn, 00307 OUT PULONG BufferLength, 00308 OUT PVOID *Buffer 00309 ) 00310 00311 /*++ 00312 00313 Routine Description: 00314 00315 This routine is called to continue a query operation. The Lfs uses 00316 private information stored in the context structure to determine the 00317 next log record to return to the caller. 00318 00319 Arguments: 00320 00321 LogHandle - Pointer to private Lfs structure used to identify this 00322 client. 00323 00324 Context - Supplies the address to store a pointer to the Lfs created 00325 context structure. 00326 00327 Lsn - Lsn for this log record. 00328 00329 RecordType - Supplies the address to store the record type of this 00330 log record. 00331 00332 TransactionId - Supplies the address to store the transaction Id of 00333 this log record. 00334 00335 UndoNextLsn - Supplies the address to store the Undo Next Lsn for this 00336 log record. 00337 00338 PreviousLsn - Supplies the address to store the Previous Lsn for this 00339 log record. 00340 00341 BufferLength - This is the length of the log data. 00342 00343 Buffer - This is a pointer to the start of the log data. 00344 00345 Return Value: 00346 00347 None 00348 00349 --*/ 00350 00351 { 00352 volatile NTSTATUS Status = STATUS_SUCCESS; 00353 00354 PLCH Lch; 00355 00356 PLFCB Lfcb; 00357 00358 PLCB Lcb; 00359 00360 BOOLEAN FoundNextLsn; 00361 00362 BOOLEAN UnwindRememberLcbFields; 00363 PBCB UnwindRecordHeaderBcb; 00364 PLFS_RECORD_HEADER UnwindRecordHeader; 00365 PVOID UnwindCurrentLogRecord; 00366 BOOLEAN UnwindAuxilaryBuffer; 00367 00368 PAGED_CODE(); 00369 00370 DebugTrace( +1, Dbg, "LfsReadNextLogRecord: Entered\n", 0 ); 00371 DebugTrace( 0, Dbg, "Log Handle -> %08lx\n", LogHandle ); 00372 DebugTrace( 0, Dbg, "Context -> %08lx\n", Context ); 00373 00374 FoundNextLsn = FALSE; 00375 00376 UnwindRememberLcbFields = FALSE; 00377 00378 Lch = (PLCH) LogHandle; 00379 Lcb = (PLCB) Context; 00380 00381 // 00382 // Check that the structure is a valid log handle structure. 00383 // 00384 00385 LfsValidateLch( Lch ); 00386 00387 // 00388 // Use a try-except to catch errors. 00389 // 00390 00391 try { 00392 00393 // 00394 // Use a try-finally to facilitate cleanup. 00395 // 00396 00397 try { 00398 00399 // 00400 // Acquire the log file control block for this log file. 00401 // 00402 00403 LfsAcquireLch( Lch ); 00404 Lfcb = Lch->Lfcb; 00405 00406 // 00407 // If the Log file has been closed then refuse access. 00408 // 00409 00410 if (Lfcb == NULL) { 00411 00412 ExRaiseStatus( STATUS_ACCESS_DENIED ); 00413 } 00414 00415 // 00416 // Check that the client Id is valid. 00417 // 00418 00419 LfsValidateClientId( Lfcb, Lch ); 00420 00421 // 00422 // Check that the context structure is valid. 00423 // 00424 00425 LfsValidateLcb( Lcb, Lch ); 00426 00427 // 00428 // Remember any context fields to be overwritten. 00429 // 00430 00431 UnwindRememberLcbFields = TRUE; 00432 00433 UnwindRecordHeaderBcb = Lcb->RecordHeaderBcb; 00434 Lcb->RecordHeaderBcb = NULL; 00435 00436 UnwindRecordHeader = Lcb->RecordHeader; 00437 UnwindCurrentLogRecord = Lcb->CurrentLogRecord; 00438 00439 UnwindAuxilaryBuffer = Lcb->AuxilaryBuffer; 00440 Lcb->AuxilaryBuffer = FALSE; 00441 00442 // 00443 // Find the next Lsn number based on the current Lsn number in 00444 // the context block. 00445 // 00446 00447 if (LfsFindClientNextLsn( Lfcb, Lcb, Lsn )) { 00448 00449 // 00450 // We can give up the Lfcb as we know the Lsn is within the file. 00451 // 00452 00453 LfsReleaseLfcb( Lfcb ); 00454 00455 // 00456 // Cleanup the context block so we can do the next search. 00457 // 00458 00459 Lcb->CurrentLogRecord = NULL; 00460 Lcb->AuxilaryBuffer = FALSE; 00461 00462 // 00463 // Perform the work of getting the log record. 00464 // 00465 00466 LfsFindLogRecord( Lfcb, 00467 Lcb, 00468 *Lsn, 00469 RecordType, 00470 TransactionId, 00471 UndoNextLsn, 00472 PreviousLsn, 00473 BufferLength, 00474 Buffer ); 00475 00476 FoundNextLsn = TRUE; 00477 } 00478 00479 } finally { 00480 00481 DebugUnwind( LfsReadNextLogRecord ); 00482 00483 // 00484 // If we exited due to an error, we have to restore the context 00485 // block. 00486 // 00487 00488 if (UnwindRememberLcbFields) { 00489 00490 if (AbnormalTermination()) { 00491 00492 // 00493 // If the record header in the context block is not 00494 // the same as we started with. Then we unpin that 00495 // data. 00496 // 00497 00498 if (Lcb->RecordHeaderBcb != NULL) { 00499 00500 CcUnpinData( Lcb->RecordHeaderBcb ); 00501 00502 } 00503 00504 if (Lcb->CurrentLogRecord != NULL 00505 && Lcb->AuxilaryBuffer == TRUE) { 00506 00507 LfsFreeSpanningBuffer( Lcb->CurrentLogRecord ); 00508 } 00509 00510 Lcb->RecordHeaderBcb = UnwindRecordHeaderBcb; 00511 Lcb->RecordHeader = UnwindRecordHeader; 00512 Lcb->CurrentLogRecord = UnwindCurrentLogRecord; 00513 Lcb->AuxilaryBuffer = UnwindAuxilaryBuffer; 00514 00515 // 00516 // Otherwise, if we have successfully found the next Lsn, 00517 // we free up any resources being held from the previous search. 00518 // 00519 00520 } else if (FoundNextLsn ) { 00521 00522 if (UnwindRecordHeaderBcb != NULL) { 00523 00524 CcUnpinData( UnwindRecordHeaderBcb ); 00525 } 00526 00527 if (UnwindCurrentLogRecord != NULL 00528 && UnwindAuxilaryBuffer == TRUE) { 00529 00530 LfsFreeSpanningBuffer( UnwindCurrentLogRecord ); 00531 } 00532 00533 // 00534 // Restore the Bcb and auxilary buffer field for the final 00535 // cleanup. 00536 // 00537 00538 } else { 00539 00540 if (UnwindRecordHeaderBcb != NULL) { 00541 00542 if (Lcb->RecordHeaderBcb != NULL) { 00543 00544 CcUnpinData( UnwindRecordHeaderBcb ); 00545 00546 } else { 00547 00548 Lcb->RecordHeaderBcb = UnwindRecordHeaderBcb; 00549 } 00550 } 00551 00552 if (UnwindAuxilaryBuffer) { 00553 00554 if (Lcb->CurrentLogRecord == UnwindCurrentLogRecord) { 00555 00556 Lcb->AuxilaryBuffer = TRUE; 00557 00558 } else { 00559 00560 LfsFreeSpanningBuffer( UnwindCurrentLogRecord ); 00561 } 00562 } 00563 } 00564 } 00565 00566 // 00567 // Release the log file control block if held. 00568 // 00569 00570 LfsReleaseLch( Lch ); 00571 00572 DebugTrace( 0, Dbg, "Lsn (Low) -> %08lx\n", Lsn->LowPart ); 00573 DebugTrace( 0, Dbg, "Lsn (High) -> %08lx\n", Lsn->HighPart ); 00574 DebugTrace( 0, Dbg, "Buffer Length -> %08lx\n", *BufferLength ); 00575 DebugTrace( 0, Dbg, "Buffer -> %08lx\n", *Buffer ); 00576 DebugTrace( -1, Dbg, "LfsReadNextLogRecord: Exit\n", 0 ); 00577 } 00578 00579 } except (LfsExceptionFilter( GetExceptionInformation() )) { 00580 00581 Status = GetExceptionCode(); 00582 } 00583 00584 if (Status != STATUS_SUCCESS) { 00585 00586 ExRaiseStatus( Status ); 00587 } 00588 00589 return FoundNextLsn; 00590 } 00591 00592 00593 VOID 00594 LfsTerminateLogQuery ( 00595 IN LFS_LOG_HANDLE LogHandle, 00596 IN LFS_LOG_CONTEXT Context 00597 ) 00598 00599 /*++ 00600 00601 Routine Description: 00602 00603 This routine is called when a client has completed his query operation 00604 and wishes to deallocate any resources acquired by the Lfs to 00605 perform the log file query. 00606 00607 Arguments: 00608 00609 LogHandle - Pointer to private Lfs structure used to identify this 00610 client. 00611 00612 Context - Supplies the address to store a pointer to the Lfs created 00613 context structure. 00614 00615 Return Value: 00616 00617 None 00618 00619 --*/ 00620 00621 { 00622 PLCH Lch; 00623 PLCB Lcb; 00624 00625 PLFCB Lfcb; 00626 00627 PAGED_CODE(); 00628 00629 DebugTrace( +1, Dbg, "LfsTerminateLogQuery: Entered\n", 0 ); 00630 DebugTrace( 0, Dbg, "Log Handle -> %08lx\n", LogHandle ); 00631 DebugTrace( 0, Dbg, "Context -> %08lx\n", Context ); 00632 00633 Lch = (PLCH) LogHandle; 00634 Lcb = (PLCB) Context; 00635 00636 // 00637 // Check that the structure is a valid log handle structure. 00638 // 00639 00640 LfsValidateLch( Lch ); 00641 00642 // 00643 // Use a try-finally to facilitate cleanup. 00644 // 00645 00646 try { 00647 00648 // 00649 // Acquire the log file control block for this log file. 00650 // 00651 00652 LfsAcquireLch( Lch ); 00653 Lfcb = Lch->Lfcb; 00654 00655 // 00656 // If the Log file has been closed then refuse access. 00657 // 00658 00659 if (Lfcb == NULL) { 00660 00661 try_return( NOTHING ); 00662 } 00663 00664 // 00665 // Check that the client Id is valid. 00666 // 00667 00668 LfsValidateClientId( Lfcb, Lch ); 00669 00670 // 00671 // Check that the context structure is valid. 00672 // 00673 00674 LfsValidateLcb( Lcb, Lch ); 00675 00676 // 00677 // Deallocate the context block. 00678 // 00679 00680 LfsDeallocateLcb( Lfcb, Lcb ); 00681 00682 try_exit: NOTHING; 00683 } finally { 00684 00685 DebugUnwind( LfsTerminateLogQuery ); 00686 00687 // 00688 // Release the Lfcb if acquired. 00689 // 00690 00691 LfsReleaseLch( Lch ); 00692 00693 DebugTrace( -1, Dbg, "LfsTerminateLogQuery: Exit\n", 0 ); 00694 } 00695 00696 return; 00697 } 00698 00699 00700 LSN 00701 LfsQueryLastLsn ( 00702 IN LFS_LOG_HANDLE LogHandle 00703 ) 00704 00705 /*++ 00706 00707 Routine Description: 00708 00709 This routine will return the most recent Lsn for this log record. 00710 00711 Arguments: 00712 00713 LogHandle - Pointer to private Lfs structure used to identify this 00714 client. 00715 00716 Return Value: 00717 00718 LSN - This is the last Lsn assigned in this log file. 00719 00720 --*/ 00721 00722 { 00723 PLCH Lch; 00724 00725 PLFCB Lfcb; 00726 00727 LSN LastLsn; 00728 00729 PAGED_CODE(); 00730 00731 DebugTrace( +1, Dbg, "LfsQueryLastLsn: Entered\n", 0 ); 00732 DebugTrace( 0, Dbg, "Log Handle -> %08lx\n", LogHandle ); 00733 00734 Lch = (PLCH) LogHandle; 00735 00736 // 00737 // Check that the structure is a valid log handle structure. 00738 // 00739 00740 LfsValidateLch( Lch ); 00741 00742 // 00743 // Use a try-finally to facilitate cleanup. 00744 // 00745 00746 try { 00747 00748 // 00749 // Acquire the log file control block for this log file. 00750 // 00751 00752 LfsAcquireLch( Lch ); 00753 Lfcb = Lch->Lfcb; 00754 00755 // 00756 // If the Log file has been closed then refuse access. 00757 // 00758 00759 if (Lfcb == NULL) { 00760 00761 ExRaiseStatus( STATUS_ACCESS_DENIED ); 00762 } 00763 00764 // 00765 // Check that the client Id is valid. 00766 // 00767 00768 LfsValidateClientId( Lfcb, Lch ); 00769 00770 // 00771 // Copy the last Lsn out of the Lfcb. If the last Lsn is 00772 // does not correspond to a log record, we will return the 00773 // zero Lsn. 00774 // 00775 00776 if (FlagOn( Lfcb->Flags, LFCB_NO_LAST_LSN )) { 00777 00778 LastLsn = LfsZeroLsn; 00779 00780 } else { 00781 00782 LastLsn = Lfcb->RestartArea->CurrentLsn; 00783 } 00784 00785 } finally { 00786 00787 DebugUnwind( LfsQueryLastLsn ); 00788 00789 // 00790 // Release the Lfcb if acquired. 00791 // 00792 00793 LfsReleaseLch( Lch ); 00794 00795 DebugTrace( 0, Dbg, "Last Lsn (Low) -> %08lx\n", LastLsn.LowPart ); 00796 DebugTrace( 0, Dbg, "Last Lsn (High) -> %08lx\n", LastLsn.HighPart ); 00797 DebugTrace( -1, Dbg, "LfsQueryLastLsn: Exit\n", 0 ); 00798 } 00799 00800 return LastLsn; 00801 } 00802 00803 00804 // 00805 // Local support routine. 00806 // 00807 00808 VOID 00809 LfsFindLogRecord ( 00810 IN PLFCB Lfcb, 00811 IN OUT PLCB Lcb, 00812 IN LSN Lsn, 00813 OUT PLFS_RECORD_TYPE RecordType, 00814 OUT TRANSACTION_ID *TransactionId, 00815 OUT PLSN UndoNextLsn, 00816 OUT PLSN PreviousLsn, 00817 OUT PULONG BufferLength, 00818 OUT PVOID *Buffer 00819 ) 00820 00821 /*++ 00822 00823 Routine Description: 00824 00825 This routine is called recover a log record for a client. 00826 00827 Arguments: 00828 00829 Lfcb - Log file control block for this file. 00830 00831 Lcb - Pointer to the context block to update. 00832 00833 Lsn - This is the Lsn for the log record. 00834 00835 RecordType - Supplies the address to store the record type of this 00836 log record. 00837 00838 TransactionId - Supplies the address to store the transaction Id of 00839 this log record. 00840 00841 UndoNextLsn - Supplies the address to store the Undo Next Lsn for this 00842 log record. 00843 00844 PreviousLsn - Supplies the address to store the Previous Lsn for this 00845 log record. 00846 00847 BufferLength - Pointer to address to store the length in bytes of the 00848 log record. 00849 00850 Buffer - Pointer to store the address where the log record data begins. 00851 00852 Return Value: 00853 00854 None 00855 00856 --*/ 00857 00858 { 00859 PCHAR NewBuffer; 00860 BOOLEAN UsaError; 00861 LONGLONG LogRecordLength; 00862 ULONG PageOffset; 00863 00864 PAGED_CODE(); 00865 00866 DebugTrace( +1, Dbg, "LfsFindLogRecord: Entered\n", 0 ); 00867 DebugTrace( 0, Dbg, "Lfcb -> %08lx\n", Lfcb ); 00868 DebugTrace( 0, Dbg, "Context Block -> %08lx\n", Lcb ); 00869 DebugTrace( 0, Dbg, "Lsn (Low) -> %08lx\n", Lsn.LowPart ); 00870 00871 NewBuffer = NULL; 00872 00873 // 00874 // Use a try-finally to facilitate cleanup. 00875 // 00876 00877 try { 00878 00879 // 00880 // Map the record header for this Lsn if we haven't already. 00881 // 00882 00883 if (Lcb->RecordHeader == NULL) { 00884 00885 LfsPinOrMapLogRecordHeader( Lfcb, 00886 Lsn, 00887 FALSE, 00888 FALSE, 00889 &UsaError, 00890 &Lcb->RecordHeader, 00891 &Lcb->RecordHeaderBcb ); 00892 } 00893 00894 // 00895 // We now have the log record desired. If the Lsn in the 00896 // log record doesn't match the desired Lsn then the disk is 00897 // corrupt. 00898 // 00899 00900 if ( Lsn.QuadPart != Lcb->RecordHeader->ThisLsn.QuadPart ) { //**** xxNeq( Lsn, Lcb->RecordHeader->ThisLsn ) 00901 00902 ExRaiseStatus( STATUS_DISK_CORRUPT_ERROR ); 00903 } 00904 00905 // 00906 // Check that the length field isn't greater than the total available space 00907 // in the log file. 00908 // 00909 00910 LogRecordLength = Lcb->RecordHeader->ClientDataLength + Lfcb->RecordHeaderLength; //**** xxFromUlong( Lcb->RecordHeader->ClientDataLength + Lfcb->RecordHeaderLength ); 00911 00912 if ( LogRecordLength >= Lfcb->TotalAvailable ) { //**** xxGeq( LogRecordLength, Lfcb->TotalAvailable ) 00913 00914 ExRaiseStatus( STATUS_DISK_CORRUPT_ERROR ); 00915 } 00916 00917 // 00918 // If the entire log record is on this log page, put a pointer to 00919 // the log record in the context block. 00920 // 00921 00922 if (!FlagOn( Lcb->RecordHeader->Flags, LOG_RECORD_MULTI_PAGE )) { 00923 00924 // 00925 // If client size indicates that we have to go beyond the end of the current 00926 // page, we raise an error. 00927 // 00928 00929 PageOffset = LfsLsnToPageOffset( Lfcb, Lsn ); 00930 00931 if ((PageOffset + Lcb->RecordHeader->ClientDataLength + Lfcb->RecordHeaderLength) 00932 > (ULONG)Lfcb->LogPageSize) { 00933 00934 ExRaiseStatus( STATUS_DISK_CORRUPT_ERROR ); 00935 } 00936 00937 Lcb->CurrentLogRecord = Add2Ptr( Lcb->RecordHeader, LFS_RECORD_HEADER_SIZE, PVOID ); 00938 Lcb->AuxilaryBuffer = FALSE; 00939 00940 // 00941 // Else we copy the data and remember that we allocated a buffer. 00942 // 00943 00944 } else { 00945 00946 NewBuffer = LfsAllocateSpanningBuffer( Lfcb, Lcb->RecordHeader->ClientDataLength ); 00947 00948 // 00949 // Copy the data into the buffer returned. 00950 // 00951 00952 LfsCopyReadLogRecord( Lfcb, 00953 Lcb->RecordHeader, 00954 NewBuffer ); 00955 00956 Lcb->CurrentLogRecord = NewBuffer; 00957 00958 Lcb->AuxilaryBuffer = TRUE; 00959 00960 NewBuffer = NULL; 00961 } 00962 00963 // 00964 // We need to update the caller's parameters and the context block. 00965 // 00966 00967 *RecordType = Lcb->RecordHeader->RecordType; 00968 *TransactionId = Lcb->RecordHeader->TransactionId; 00969 00970 *UndoNextLsn = Lcb->RecordHeader->ClientUndoNextLsn; 00971 *PreviousLsn = Lcb->RecordHeader->ClientPreviousLsn; 00972 00973 *Buffer = Lcb->CurrentLogRecord; 00974 *BufferLength = Lcb->RecordHeader->ClientDataLength; 00975 00976 } finally { 00977 00978 DebugUnwind( LfsFindLogRecord ); 00979 00980 // 00981 // If an error occurred we unpin the record header and the log 00982 // We also free the buffer if allocated by us. 00983 // 00984 00985 if (NewBuffer != NULL) { 00986 00987 LfsFreeSpanningBuffer( NewBuffer ); 00988 } 00989 00990 DebugTrace( 0, Dbg, "Buffer Length -> %08lx\n", *BufferLength ); 00991 DebugTrace( 0, Dbg, "Buffer -> %08lx\n", *Buffer ); 00992 DebugTrace( -1, Dbg, "LfsFindLogRecord: Exit\n", 0 ); 00993 } 00994 00995 return; 00996 } 00997 00998 00999 // 01000 // Local support routine. 01001 // 01002 01003 BOOLEAN 01004 LfsFindClientNextLsn ( 01005 IN PLFCB Lfcb, 01006 IN PLCB Lcb, 01007 OUT PLSN Lsn 01008 ) 01009 01010 /*++ 01011 01012 Routine Description: 01013 01014 This routine will attempt to find the next Lsn to return to a client 01015 based on the context mode. 01016 01017 Arguments: 01018 01019 Lfcb - File control block for this log file. 01020 01021 Lcb - Pointer to the context block for this query operation. 01022 01023 Lsn - Pointer to store the Lsn found (if any) 01024 01025 Return Value: 01026 01027 BOOLEAN - TRUE if an Lsn is found, FALSE otherwise. 01028 01029 --*/ 01030 01031 { 01032 LSN NextLsn; 01033 BOOLEAN NextLsnFound; 01034 01035 PLFS_CLIENT_RECORD ClientRecord; 01036 01037 PAGED_CODE(); 01038 01039 DebugTrace( +1, Dbg, "LfsFindClientNextLsn: Entered\n", 0 ); 01040 DebugTrace( 0, Dbg, "Lcb -> %08lx\n", Lcb ); 01041 01042 ClientRecord = Lfcb->ClientArray + Lcb->ClientId.ClientIndex; 01043 01044 // 01045 // The context block has the last Lsn returned. If the user wanted 01046 // one of the Lsn's in that log header then our job is simple. 01047 // 01048 01049 switch (Lcb->ContextMode) { 01050 01051 case LfsContextUndoNext: 01052 case LfsContextPrevious: 01053 01054 NextLsn = (Lcb->ContextMode == LfsContextUndoNext 01055 ? Lcb->RecordHeader->ClientUndoNextLsn 01056 : Lcb->RecordHeader->ClientPreviousLsn); 01057 01058 if ( NextLsn.QuadPart == 0 ) { //**** xxEqlZero( NextLsn ) 01059 01060 NextLsnFound = FALSE; 01061 01062 } else if (LfsVerifyClientLsnInRange( Lfcb, ClientRecord, NextLsn )) { 01063 01064 BOOLEAN UsaError; 01065 01066 LfsPinOrMapLogRecordHeader( Lfcb, 01067 NextLsn, 01068 FALSE, 01069 FALSE, 01070 &UsaError, 01071 &Lcb->RecordHeader, 01072 &Lcb->RecordHeaderBcb ); 01073 01074 NextLsnFound = TRUE; 01075 01076 } else { 01077 01078 NextLsnFound = FALSE; 01079 } 01080 01081 break; 01082 01083 case LfsContextForward: 01084 01085 // 01086 // We search forward for the next log record for this client. 01087 // 01088 01089 NextLsnFound = LfsSearchForwardByClient( Lfcb, Lcb, &NextLsn ); 01090 break; 01091 01092 default: 01093 01094 NextLsnFound = FALSE; 01095 break; 01096 } 01097 01098 if (NextLsnFound) { 01099 01100 *Lsn = NextLsn; 01101 } 01102 01103 DebugTrace( 0, Dbg, "NextLsn (Low) -> %08lx\n", NextLsn.LowPart ); 01104 DebugTrace( 0, Dbg, "NextLsn (High) -> %08lx\n", NextLsn.HighPart ); 01105 DebugTrace( -1, Dbg, "LfsFindClientNextLsn: Exit -> %08x\n", NextLsnFound ); 01106 01107 return NextLsnFound; 01108 } 01109 01110 01111 // 01112 // Local support routine. 01113 // 01114 01115 BOOLEAN 01116 LfsSearchForwardByClient ( 01117 IN PLFCB Lfcb, 01118 IN OUT PLCB Lcb, 01119 OUT PLSN Lsn 01120 ) 01121 01122 /*++ 01123 01124 Routine Description: 01125 01126 This routine will attempt to find the next Lsn for this client by searching 01127 forward in the file, looking for a match. 01128 01129 Arguments: 01130 01131 Lfcb - Pointer to the file control block for this log file. 01132 01133 Lcb - Pointer to the context block for this query operation. 01134 01135 Lsn - Points to the location to store the next Lsn if found. 01136 01137 Return Value: 01138 01139 BOOLEAN - TRUE if another Lsn for this client is found. FALSE otherwise. 01140 01141 --*/ 01142 01143 { 01144 PLFS_RECORD_HEADER CurrentRecordHeader; 01145 PBCB CurrentBcb; 01146 01147 BOOLEAN FoundNextLsn; 01148 01149 LSN CurrentLsn; 01150 01151 PAGED_CODE(); 01152 01153 DebugTrace( +1, Dbg, "LfsSearchForwardByClient: Entered\n", 0 ); 01154 DebugTrace( 0, Dbg, "Lcb -> %08lx\n", Lcb ); 01155 01156 // 01157 // The log record header is in the log context 01158 // block. We set the current Bcb to NULL so that we don't 01159 // unpin the log record in the context block until we're sure 01160 // of success. 01161 // 01162 01163 CurrentRecordHeader = Lcb->RecordHeader; 01164 01165 CurrentBcb = NULL; 01166 01167 // 01168 // We use a try-finally to facilitate cleanup. 01169 // 01170 01171 try { 01172 01173 // 01174 // We assume we won't find another Lsn. 01175 // 01176 01177 FoundNextLsn = FALSE; 01178 01179 // 01180 // Loop as long as another Lsn can be found. 01181 // 01182 01183 while (LfsFindNextLsn( Lfcb, CurrentRecordHeader, &CurrentLsn )) { 01184 01185 BOOLEAN UsaError; 01186 01187 // 01188 // Unpin the previous log record header. 01189 // 01190 01191 if (CurrentBcb != NULL) { 01192 01193 CcUnpinData( CurrentBcb ); 01194 CurrentBcb = NULL; 01195 } 01196 01197 // 01198 // Pin the log record header for this Lsn. 01199 // 01200 01201 LfsPinOrMapLogRecordHeader( Lfcb, 01202 CurrentLsn, 01203 FALSE, 01204 FALSE, 01205 &UsaError, 01206 &CurrentRecordHeader, 01207 &CurrentBcb ); 01208 01209 // 01210 // If the client values match, then we update the 01211 // context block and exit. 01212 // 01213 01214 if (LfsClientIdMatch( &CurrentRecordHeader->ClientId, 01215 &Lcb->ClientId ) 01216 && CurrentRecordHeader->RecordType == LfsClientRecord) { 01217 01218 // 01219 // We remember this one. 01220 // 01221 01222 Lcb->RecordHeader = CurrentRecordHeader; 01223 Lcb->RecordHeaderBcb = CurrentBcb; 01224 01225 CurrentBcb = NULL; 01226 FoundNextLsn = TRUE; 01227 01228 *Lsn = CurrentLsn; 01229 break; 01230 } 01231 } 01232 01233 } finally { 01234 01235 DebugUnwind( LfsSearchForwardByClient ); 01236 01237 // 01238 // Unpin any log record headers still pinned for no reason. 01239 // 01240 01241 if (CurrentBcb != NULL) { 01242 01243 CcUnpinData( CurrentBcb ); 01244 } 01245 01246 DebugTrace( 0, Dbg, "NextLsn (Low) -> %08lx\n", Lsn->LowPart ); 01247 DebugTrace( 0, Dbg, "NextLsn (High) -> %08lx\n", Lsn->HighPart ); 01248 DebugTrace( -1, Dbg, "LfsSearchForwardByClient: Exit -> %08x\n", FoundNextLsn ); 01249 } 01250 01251 return FoundNextLsn; 01252 }

Generated on Sat May 15 19:41:34 2004 for test by doxygen 1.3.7