00156 :
00157
00158 This routine takes as a starting point
the log record header of an
00159 Lsn in
the log
file. It searches
for the next Lsn in
the file and
00160 returns that value in
the 'Lsn' argument. The
boolean return value
00161 indicates whether there
is another Lsn in
the file.
00162
00163 Arguments:
00164
00165 Lfcb - This
is the file control block
for the log
file.
00166
00167 RecordHeader - This
is the log record
for the Lsn starting point.
00168
00169 Lsn - This supplies
the address to store
the next Lsn,
if found.
00170
00171 Return Value:
00172
00173 BOOLEAN - Indicates whether
the next Lsn was found.
00174
00175 --*/
00176
00177 {
00178 BOOLEAN FoundNextLsn;
00179
00180 LONGLONG LsnOffset;
00181 LONGLONG EndOfLogRecord;
00182 LONGLONG LogHeaderOffset;
00183
00184 LONGLONG SequenceNumber;
00185
00186
PLFS_RECORD_PAGE_HEADER LogRecordPage;
00187
PBCB LogRecordPageBcb;
00188 BOOLEAN UsaError;
00189
00190
PAGED_CODE();
00191
00192
DebugTrace( +1, Dbg,
"LfsFindNextLsn: Entered\n", 0 );
00193
DebugTrace( 0, Dbg,
"Lfcb -> %08lx\n", Lfcb );
00194
DebugTrace( 0, Dbg,
"Record Header -> %08lx\n", RecordHeader );
00195
00196 LogRecordPageBcb =
NULL;
00197 FoundNextLsn =
FALSE;
00198
00199
00200
00201
00202
00203
try {
00204
00205
00206
00207
00208
00209
00210 LsnOffset =
LfsLsnToFileOffset( Lfcb, RecordHeader->ThisLsn );
00211
00212
LfsLsnFinalOffset( Lfcb,
00213 RecordHeader->ThisLsn,
00214 RecordHeader->ClientDataLength,
00215 &EndOfLogRecord );
00216
00217
LfsTruncateOffsetToLogPage( Lfcb, EndOfLogRecord, &LogHeaderOffset );
00218
00219
00220
00221
00222
00223 SequenceNumber =
LfsLsnToSeqNumber( Lfcb, RecordHeader->ThisLsn );
00224
00225
00226
00227
00228
00229
if ( EndOfLogRecord <= LsnOffset ) {
00230
00231 SequenceNumber = SequenceNumber + 1;
00232 }
00233
00234
00235
00236
00237
00238
LfsPinOrMapData( Lfcb,
00239 LogHeaderOffset,
00240 (ULONG)Lfcb->LogPageSize,
00241 FALSE,
00242 FALSE,
00243 FALSE,
00244 &UsaError,
00245 (PVOID *)&LogRecordPage,
00246 &LogRecordPageBcb );
00247
00248
00249
00250
00251
00252
00253
00254
00255
if ( RecordHeader->ThisLsn.QuadPart == LogRecordPage->
Copy.LastLsn.QuadPart ) {
00256
00257 BOOLEAN Wrapped;
00258
00259
LfsNextLogPageOffset( Lfcb,
00260 LogHeaderOffset,
00261 &LogHeaderOffset,
00262 &Wrapped );
00263
00264 LsnOffset = LogHeaderOffset + Lfcb->LogPageDataOffset;
00265
00266
00267
00268
00269
00270
if (Wrapped) {
00271
00272 SequenceNumber = SequenceNumber + 1;
00273 }
00274
00275 }
else {
00276
00277
LiQuadAlign( EndOfLogRecord, &LsnOffset );
00278 }
00279
00280
00281
00282
00283
00284 Lsn->QuadPart =
LfsFileOffsetToLsn( Lfcb, LsnOffset, SequenceNumber );
00285
00286
00287
00288
00289
00290
00291
if (
LfsIsLsnInFile( Lfcb, *Lsn )) {
00292
00293 FoundNextLsn =
TRUE;
00294 }
00295
00296 } finally {
00297
00298
DebugUnwind( LfsFindNextLsn );
00299
00300
00301
00302
00303
00304
if (LogRecordPageBcb !=
NULL) {
00305
00306
CcUnpinData( LogRecordPageBcb );
00307 }
00308
00309
DebugTrace( 0, Dbg,
"Lsn (Low) -> %08lx\n", Lsn->LowPart );
00310
DebugTrace( 0, Dbg,
"Lsn (High) -> %08lx\n", Lsn->HighPart );
00311
DebugTrace( -1, Dbg,
"LfsFindNextLsn: Exit -> %08x\n", FoundNextLsn );
00312 }
00313
00314
return FoundNextLsn;
00315 }