/*++ BUILD Version: 0000 // Increment this if a change has global effects Copyright (c) 1989 Microsoft Corporation Module Name: Lfs.h Abstract: This module contains the public data structures and procedure prototypes for the Log File Service. Author: Brian Andrew [BrianAn] 20-June-1991 Revision History: --*/ #ifndef _LFS_ #define _LFS_ // // The Multi-Sector Header and Update Sequence Array provide detection of // incomplete multi-sector transfers for devices which either have a // physical sector size equal to the Sequence Number Stride or greater, or // which do not transfer sectors out of order. If a device exists which has // a sector size smaller than the Sequence Number Stride *and* it sometimes // transfers sectors out of order, then the Update Sequence Array will not // provide absolute detection of incomplete transfers. The Sequence Number // Stride is set to a small enough number to provide absolute protection for // all known hard disks. It is not set any smaller, in order to avoid // excessive run time and space overhead. // // The Multi-Sector Header contains space for a four-byte signature for the // convenience of its user. It then provides the offset to and length of the // the Update Sequence Array. The Update Sequence Array consists of an array // of n saved USHORTs, where n is the size of the structure being protected // divided by the sequence number stride. (The size of structure being // protected must be a nonzero power of 2 times the Sequence Number Stride, // and less than or equal to the physical page size of the machine.) The // first word of the Update Sequence Array contains the Update Sequence Number, // which is a cyclical counter (however 0 is not used) of the number of times // the containing structure has been written to disk. Following the Update // Sequence Number are the n saved USHORTs which were overwritten by the // Update Sequence Number the last time the containing structure was // written to disk. // // In detail, just prior to each time the protected structure is written to // disk, the last word in each Sequence Number Stride is saved to its // respective position in the Sequence Number Array, and then it is overwritten // with the next Update Sequence Number. Just after this write, or whenever // reading the structure, the saved word from the Sequence Number Array is // restored to its actual position in the structure. Before restoring the // saved words on reads, all of the sequence numbers at the end of each // stride are compared with the actual sequence number at the start of the // array. If any of these compares come up not equal, then a failed // multi-sector transfer has been detected. // // The size of the array is determined by the size of the containing structure. // As a C detail, the array is declared here with a size of 1, since its // actual size can only be determined at runtime. // // The Update Sequence Array should be included at the end of the header of // the structure it is protecting, since it is variable size. Its user must // insure that the correct size is reserved for it, namely: // // (sizeof-structure / SEQUENCE_NUMBER_STRIDE + 1) * sizeof(USHORT) // #define SEQUENCE_NUMBER_STRIDE (512) typedef USHORT UPDATE_SEQUENCE_NUMBER, *PUPDATE_SEQUENCE_NUMBER; // // This array must be present at the offset described above. // typedef UPDATE_SEQUENCE_NUMBER UPDATE_SEQUENCE_ARRAY[1]; typedef UPDATE_SEQUENCE_ARRAY *PUPDATE_SEQUENCE_ARRAY; // // The following structure is used to identify a log record by a log // sequence number. // typedef LARGE_INTEGER LSN, *PLSN; // // The following Lsn will never occur in a file, it is used to indicate // a non-lsn. // extern LSN LfsZeroLsn; // // The following type defines the different log record types. // typedef enum _LFS_RECORD_TYPE { LfsClientRecord = 1, LfsClientRestart } LFS_RECORD_TYPE, *PLFS_RECORD_TYPE; // // The following search modes are supported. // typedef enum _LFS_CONTEXT_MODE { LfsContextUndoNext = 1, LfsContextPrevious, LfsContextForward } LFS_CONTEXT_MODE, *PLFS_CONTEXT_MODE; typedef ULONG TRANSACTION_ID, *PTRANSACTION_ID; typedef enum _TRANSACTION_STATE { TransactionUninitialized = 0, TransactionActive, TransactionPrepared, TransactionCommitted } TRANSACTION_STATE, *PTRANSACTION_STATE; typedef enum _LFS_INFO { LfsUseUsa = 1, LfsPackLog } LFS_INFO, *PLFS_INFO; typedef PVOID LFS_LOG_HANDLE, *PLFS_LOG_HANDLE; typedef PVOID LFS_LOG_CONTEXT, *PLFS_LOG_CONTEXT; // // Write Entry for LfsWrite and LfsForceWrite. The interface to these // routines takes a pointer to a Write Entry along with a count of how // many Write Entries to expect to describe pieces of the caller's buffer // which are supposed to be copied in sequence to the log file. // typedef struct _LFS_WRITE_ENTRY { PVOID Buffer; ULONG ByteLength; } LFS_WRITE_ENTRY, *PLFS_WRITE_ENTRY; // // Global Maintenance routines // BOOLEAN LfsInitializeLogFileService ( ); // // Log File Registration routines // typedef struct _LOG_FILE_INFORMATION { // // This is the total useable space in the log file after space for // headers and Lfs Restart Areas. // LONGLONG TotalAvailable; // // This is the useable space in the log file from the current position // in the log file to the lowest BaseLsn. This total as returned is not // yet reduced for undo commitments, returned separately below. // LONGLONG CurrentAvailable; // // This is the total undo commitment for all clients of the log file. // LfsWrite requests are refused when the sum of the write size of the // request plus the UndoRequirement for the request plus the TotalUndoCommitment // are greater than the CurrentAvailable. // LONGLONG TotalUndoCommitment; // // This is the total undo commitment for this client. // LONGLONG ClientUndoCommitment; // // Current system Lsn's. Includes the Oldest, LastFlushed and current // Lsn. // LSN OldestLsn; LSN LastFlushedLsn; LSN LastLsn; } LOG_FILE_INFORMATION, *PLOG_FILE_INFORMATION; #define LOG_FILE_DATA_BITS(D) ((sizeof(LSN) * 8) - GetSeqNumberBits(D)) #define LOG_PAGE_MASK(D) (GetLogPageSize(D) - 1) #define LOG_PAGE_INVERSE_MASK(D) (~LOG_PAGE_MASK(D)) #define LfsLogPageOffset(D, i) ((i) & LOG_PAGE_MASK(D)) #define LfsLsnToPageOffset(D, lsn) (LfsLogPageOffset(D, (lsn).LowPart << three)) extern const int three; #define LfsLsnToFileOffset(D, LSN) \ /*xxShr*/(((ULONGLONG)/*xxShl*/((LSN).QuadPart << GetSeqNumberBits(D))) >> (GetSeqNumberBits(D) - three)) #define LfsTruncateLsnToLogPage(D, lsn, FO) { \ *(FO) = LfsLsnToFileOffset((D), (lsn)); \ *((PULONG)(FO)) &= LOG_PAGE_INVERSE_MASK(D); \ } #define LfsLsnToSeqNumber(D, LSN) \ /*xxShr*/((ULONGLONG)/*xxShl*/((LSN).QuadPart) >> LOG_FILE_DATA_BITS(D)) #define LfsFileOffsetToLsn(D, FO, SN) \ ((((ULONGLONG)(FO)) >> three) + ((SN) << LOG_FILE_DATA_BITS(D))) extern ULONG GetLogPageSize(PLOG_IO_DP_DRIVE); extern ULONG GetSeqNumberBits(PLOG_IO_DP_DRIVE); #endif // LFS