00071 :
00072
00073 This routine
is called to write a log record into
the log
file
00074
using the cache manager. If there
is room in
the current log
00075 page
it is added to that. Otherwise we allocate a
new log page
00076 and write
the log record header
for this log page. We then
00077 write
the log record into
the remaining bytes of
this page and
00078 into any subsequent pages
if needed.
00079
00080 Arguments:
00081
00082 Lfcb -
File control block
for this log
file.
00083
00084 Lch - This
is the client handle, we may update
the undo space
for this
00085 client.
00086
00087 NumberOfWriteEntries - Number of components of
the log record.
00088
00089 WriteEntries - Pointer to an array of write entries.
00090
00091 UndoRequirement - Signed value indicating
the requirement to write
00092 an abort log record
for this log record.
A negative
00093 value indicates that
this is the abort record.
00094
00095 RecordType - The Lfs-defined
type of
this log record.
00096
00097 TransactionId - Pointer to
the transaction structure containing
the
00098 Id
for transaction containing
this operation.
00099
00100 ClientUndoNextLsn - This
is the Lsn provided by
the client
for use
00101 in his restart. Will be
the zero Lsn
for
00102 a restart log record.
00103
00104 ClientPreviousLsn - This
is the Lsn provided by
the client
for use
00105 in his restart. Will
the the zero Lsn
for a
00106 restart log record.
00107
00108 UndoRequirement - This
is the data size
for the undo record
for
00109
this log record.
00110
00111 ForceToDisk - Indicates
if this log record will be flushed immediately
00112 to disk.
00113
00114 Lsn -
A pointer to store
the Lsn
for this log record.
00115
00116 Return Value:
00117
00118 BOOLEAN - Advisory,
TRUE indicates that less than 1/4 of
the log
file is
00119 available.
00120
00121 --*/
00122
00123 {
00124
PLFS_WRITE_ENTRY ThisWriteEntry;
00125
00126 ULONG RemainingLogBytes;
00127 ULONG OriginalLogBytes;
00128
00129 ULONG RemainingPageBytes;
00130 ULONG HeaderAdjust;
00131
00132
PLBCB ThisLbcb;
00133
00134
LSN NextLsn;
00135
00136
PLFS_RECORD_HEADER RecordHeader;
00137
00138 PCHAR CurrentBuffer;
00139 ULONG CurrentByteCount;
00140 ULONG PadBytes;
00141
00142 BOOLEAN LogFileFull =
FALSE;
00143
00144
PAGED_CODE();
00145
00146
DebugTrace( +1, Dbg,
"LfsWriteLogRecordIntoLogPage: Entered\n", 0 );
00147
DebugTrace( 0, Dbg,
"Lfcb -> %08lx\n", Lfcb );
00148
DebugTrace( 0, Dbg,
"Lch -> %08lx\n", Lch );
00149
DebugTrace( 0, Dbg,
"Number of Write Entries -> %08lx\n", NumberOfWriteEntries );
00150
DebugTrace( 0, Dbg,
"Write Entries -> %08lx\n", WriteEntries );
00151
DebugTrace( 0, Dbg,
"Record Type -> %08lx\n", RecordType );
00152
DebugTrace( 0, Dbg,
"Transaction Id -> %08lx\n", TransactionId );
00153
DebugTrace( 0, Dbg,
"ClientUndoNextLsn (Low) -> %08lx\n", ClientUndoNextLsn.LowPart );
00154
DebugTrace( 0, Dbg,
"ClientUndoNextLsn (High) -> %08lx\n", ClientUndoNextLsn.HighPart );
00155
DebugTrace( 0, Dbg,
"ClientPreviousLsn (Low) -> %08lx\n", ClientPreviousLsn.LowPart );
00156
DebugTrace( 0, Dbg,
"ClientPreviousLsn (High) -> %08lx\n", ClientPreviousLsn.HighPart );
00157
DebugTrace( 0, Dbg,
"UndoRequirement -> %08lx\n", UndoRequirement );
00158
DebugTrace( 0, Dbg,
"ForceToDisk -> %04x\n", ForceToDisk );
00159
00160
00161
00162
00163
00164 ThisWriteEntry = WriteEntries;
00165
00166 RemainingLogBytes = 0;
00167
00168
while (NumberOfWriteEntries--) {
00169
00170 RemainingLogBytes +=
QuadAlign( ThisWriteEntry->
ByteLength );
00171
00172 ThisWriteEntry++;
00173 }
00174
00175 OriginalLogBytes = RemainingLogBytes;
00176
00177 ThisWriteEntry = WriteEntries;
00178
00179
00180
00181
00182
00183
00184
00185
while (
TRUE) {
00186
00187 LogFileFull =
LfsVerifyLogSpaceAvail( Lfcb,
00188 Lch,
00189 RemainingLogBytes,
00190 UndoRequirement,
00191 ForceToDisk );
00192
00193
00194
00195
00196
00197
00198
LfsPrepareLfcbForLogRecord( Lfcb,
00199 RemainingLogBytes + Lfcb->RecordHeaderLength );
00200
00201 ThisLbcb = CONTAINING_RECORD( Lfcb->LbcbActive.Flink,
00202
LBCB,
00203 ActiveLinks );
00204
00205
00206
00207
00208
00209
if (ThisLbcb->
LogPageBcb !=
NULL) {
break; }
00210
00211
00212
00213
00214
00215 Lfcb->Waiters += 1;
00216
00217
LfsReleaseLfcb( Lfcb );
00218
00219
KeWaitForSingleObject( &Lfcb->Sync->Event,
00220 Executive,
00221 KernelMode,
00222 FALSE,
00223 NULL );
00224
00225
LfsAcquireLfcb( Lfcb );
00226 Lfcb->Waiters -= 1;
00227 }
00228
00229 RemainingPageBytes = (ULONG)Lfcb->LogPageSize - (ULONG)ThisLbcb->
BufferOffset;
00230
00231
00232
00233
00234
00235 NextLsn.QuadPart =
LfsComputeLsnFromLbcb( Lfcb, ThisLbcb );
00236
00237
00238
00239
00240
00241
00242 RecordHeader =
Add2Ptr( ThisLbcb->
PageHeader,
00243 (ULONG)ThisLbcb->
BufferOffset,
00244
PLFS_RECORD_HEADER );
00245
00246
00247
00248
00249
00250
00251
00252
00253
00254 RtlZeroMemory( RecordHeader, Lfcb->RecordHeaderLength );
00255
00256
00257
00258
00259
00260 RecordHeader->
ThisLsn = NextLsn;
00261 RecordHeader->
ClientPreviousLsn = ClientPreviousLsn;
00262 RecordHeader->
ClientUndoNextLsn = ClientUndoNextLsn;
00263
00264
if (TransactionId !=
NULL) {
00265 RecordHeader->
TransactionId = *TransactionId;
00266 }
00267
00268 RecordHeader->
ClientDataLength = RemainingLogBytes;
00269 RecordHeader->
ClientId = Lch->ClientId;
00270 RecordHeader->
RecordType = RecordType;
00271
00272
00273
00274
00275
00276
if (RemainingLogBytes + Lfcb->RecordHeaderLength > RemainingPageBytes) {
00277
00278
SetFlag( RecordHeader->
Flags, LOG_RECORD_MULTI_PAGE );
00279 }
00280
00281 RemainingPageBytes -= Lfcb->RecordHeaderLength;
00282
00283
00284
00285
00286
00287 (ULONG)ThisLbcb->
BufferOffset += Lfcb->RecordHeaderLength;
00288 HeaderAdjust = Lfcb->RecordHeaderLength;
00289
00290
00291
00292
00293
00294 CurrentBuffer = ThisWriteEntry->
Buffer;
00295 CurrentByteCount = ThisWriteEntry->
ByteLength;
00296
00297 PadBytes = (8 - (CurrentByteCount & ~(0xfffffff8))) & ~(0xfffffff8);
00298
00299
00300
00301
00302
00303
00304
while (RemainingLogBytes != 0) {
00305
00306
PLFS_RECORD_PAGE_HEADER PageHeader;
00307
00308 PageHeader = (
PLFS_RECORD_PAGE_HEADER) ThisLbcb->
PageHeader;
00309
00310
00311
00312
00313
00314
00315
00316
if (!
FlagOn( ThisLbcb->
LbcbFlags, LBCB_NOT_EMPTY )) {
00317
00318
00319
00320
00321
00322
00323
00324
00325
if ((ULONG)ThisLbcb->
BufferOffset - HeaderAdjust == (ULONG)Lfcb->LogPageDataOffset) {
00326
00327
00328 Lfcb->CurrentAvailable = Lfcb->CurrentAvailable - Lfcb->ReservedLogPageSize;
00329 }
00330
00331 InsertTailList( &Lfcb->LbcbWorkque, &ThisLbcb->
WorkqueLinks );
00332
SetFlag( ThisLbcb->
LbcbFlags, LBCB_NOT_EMPTY );
00333 }
00334
00335 HeaderAdjust = 0;
00336
00337
00338
00339
00340
00341
00342
00343
LfsTransferLogBytes( ThisLbcb,
00344 &ThisWriteEntry,
00345 &CurrentBuffer,
00346 &CurrentByteCount,
00347 &PadBytes,
00348 &RemainingPageBytes,
00349 &RemainingLogBytes );
00350
00351
00352
00353
00354
00355
00356
if (RemainingLogBytes == 0) {
00357
00358
SetFlag( ThisLbcb->
Flags, LOG_PAGE_LOG_RECORD_END );
00359 ThisLbcb->
LastEndLsn = NextLsn;
00360
00361
if (
FlagOn( Lfcb->Flags, LFCB_PACK_LOG )) {
00362
00363 PageHeader->
Header.Packed.LastEndLsn = NextLsn;
00364 PageHeader->
Header.Packed.NextRecordOffset = (
USHORT)ThisLbcb->
BufferOffset;
00365 }
00366 }
00367
00368
00369
00370
00371
00372
if (RemainingPageBytes == 0
00373 || RemainingLogBytes == 0) {
00374
00375
00376
00377
00378
00379 ThisLbcb->
LastLsn = NextLsn;
00380 PageHeader->
Copy.LastLsn = NextLsn;
00381 PageHeader->
Flags = ThisLbcb->
Flags;
00382
00383
00384
00385
00386
00387
00388
if (RemainingPageBytes < Lfcb->RecordHeaderLength) {
00389
00390 RemoveHeadList( &Lfcb->LbcbActive );
00391
ClearFlag( ThisLbcb->
LbcbFlags, LBCB_ON_ACTIVE_QUEUE );
00392
00393
00394
00395
00396
00397
if (RemainingLogBytes != 0) {
00398
00399 ThisLbcb = CONTAINING_RECORD( Lfcb->LbcbActive.Flink,
00400
LBCB,
00401 ActiveLinks );
00402
00403 RemainingPageBytes = (ULONG)Lfcb->LogPageSize
00404 - (ULONG)ThisLbcb->
BufferOffset;
00405 }
00406 }
00407 }
00408 }
00409
00410 *Lsn = NextLsn;
00411
00412 Lfcb->RestartArea->CurrentLsn = NextLsn;
00413
00414 Lfcb->RestartArea->LastLsnDataLength = OriginalLogBytes;
00415
00416
ClearFlag( Lfcb->Flags, LFCB_NO_LAST_LSN );
00417
00418
DebugTrace( 0, Dbg,
"Lsn (Low) -> %08lx\n", Lsn->LowPart );
00419
DebugTrace( 0, Dbg,
"Lsn (High) -> %08lx\n", Lsn->HighPart );
00420
DebugTrace( -1, Dbg,
"LfsWriteLogRecordIntoLogPage: Exit\n", 0 );
00421
00422
return LogFileFull;
00423 }