using System;
using System.Runtime.InteropServices;
using Vanara.InteropServices;
using LSN = System.Int64;
namespace Vanara.PInvoke;
public static partial class Ole32
{
/// Specifies a hint about the order in which records are to be read from a log.
// https://docs.microsoft.com/en-us/windows/win32/api/txlogpub/ne-txlogpub-record_reading_policy typedef enum RECORD_READING_POLICY {
// RECORD_READING_POLICY_FORWARD = 1, RECORD_READING_POLICY_BACKWARD = 2, RECORD_READING_POLICY_RANDOM = 3 } ;
[PInvokeData("txlogpub.h", MSDNShortId = "NE:txlogpub.RECORD_READING_POLICY")]
public enum RECORD_READING_POLICY
{
///
/// Value:
/// 1
/// Indicates that records will be read in order of increasing LSN (from least recent to most recent).
///
RECORD_READING_POLICY_FORWARD = 1,
///
/// Value:
/// 2
/// Indicates that records will be read in order of decreasing LSN (from most recent to least recent).
///
RECORD_READING_POLICY_BACKWARD,
///
/// Value:
/// 3
/// Indicates that records may be read in any order.
///
RECORD_READING_POLICY_RANDOM,
}
/// Initializes an instance of a file based implementation of ILog.
// https://docs.microsoft.com/en-us/windows/win32/api/txlogpub/nn-txlogpub-ifilebasedloginit
[PInvokeData("txlogpub.h", MSDNShortId = "NN:txlogpub.IFileBasedLogInit")]
[ComImport, Guid("00951E8C-1294-11d1-97E4-00C04FB9618A"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown), CoClass(typeof(SimpleFileBasedLog))]
public interface IFileBasedLogInit
{
/// Create a new log instance on the specified file. If a file with that name already exists, it is overwritten.
/// The absolute path of the file to be created.
/// A hint to the implementation about the total capacity that will be needed.
// https://docs.microsoft.com/en-us/windows/win32/api/txlogpub/nf-txlogpub-ifilebasedloginit-initnew HRESULT InitNew( [in] LPCWSTR
// filename, [in] ULONG cbCapacityHint );
void InitNew([MarshalAs(UnmanagedType.LPWStr)] string filename, uint cbCapacityHint);
}
///
/// Provides generic low-level logging functionality.
/// The Common Log File System (CLFS), provides functionality that is a superset of that provided by ILog.
///
///
///
/// WAL is a technique used by certain applications, such as database management systems, to implement atomic and isolated transactions.
/// This technique involves writing records of changes to the application's resources to a log before you make these changes. This way
/// the changes can be reverted if they are required, for example if the transaction fails or is interrupted. In order for applications
/// to provide transactions that are robust against interruptions such as system crash or power failure, the logging implementation must
/// provide a method for forcing the log; that is, to make sure that previously written records are on disk before continuing.
///
///
/// Writing records that use ILog is a sequential operation; that is, new records are always appended to the end of the log. Each
/// record appended to the log is assigned a log sequence number (LSN), a numeric identifier which may be used to retrieve the record
/// later. The data type LSN is a typedef for LARGE_INTEGER, a signed 64-bit value; however, ILog uses only LSNs with nonnegative
/// values. In addition, LSNs must satisfy the following conditions:
///
///
/// -
///
/// LSNs are monotonically increasing; if record B is written to the log after record A, the LSN of record B must be larger than the LSN
/// of record A.
///
///
/// -
///
/// Values of zero and MAXLSN (0x7FFFFFFFFFFFFFFF) must never be used as the LSN of a record, as they have special meaning to some of the
/// methods of ILog.
///
///
///
///
/// Other than the conditions here, no assumptions should be made about how LSNs are assigned by an implementation of ILog. In
/// particular, it is not safe to assume that records will be assigned sequential values for LSNs.
///
///
/// After a record is appended to the log, it may not be modified. However, when previously written records are no longer needed, for
/// example records of changes in a transaction that has already been committed, ILog supports truncating the log. This way, disk
/// space that was used for nonessential records may be reused. Truncating the log consists of deleting all records with an LSN less than
/// a specified value.
///
///
/// As a performance optimization, some implementations of ILog may buffer records in memory until the log is forced. If this is
/// the case, special you must consider error control and recovery. Consider the following situation:
///
///
/// -
///
/// Record A is appended to the log, but the log is not forced. The ILog implementation copies the record to a buffer in memory
/// and returns a success code.
///
///
/// -
///
/// Record B is appended to the log, and the ILog implementation decides to force the log to disk. This is either because the
/// caller asked the log to be forced or because the memory buffer is full. However, the write operation fails, for example because of
/// low disk space.
///
///
///
///
/// In this situation, it would be inappropriate for the ILog implementation to enable additional records to be appended to the
/// log, unless it can guarantee that all records for which it returned a success code are first written to disk. One possible method of
/// error control would be to pin the log in an error state when this situation occurs, permanently disallowing additional writes to the
/// log instance. Callers that do not force the log to disk for each appended record should realize that this situation may occur and be
/// able to handle it appropriately.
///
/// ILog File-based Implementation
///
/// The Windows operating system provides a file-based implementation of ILog, which enables you to create a log suited for
/// write-ahead logging on a file. The log uses a file as a circular buffer, which enables unused space to be reused. This may also
/// increase the size of the file that may be needed to fit additional records when the log is full. Changes to the log are made
/// atomically, so that the contents of the log may be recovered after a crash. This implementation uses a buffer in memory for appending
/// log records. As a result, records are not guaranteed to be written to disk when the ILog::AppendRecord method returns, unless the
/// caller requests that the log be forced.
///
/// Use the following CLSID to create an instance of a file based log (see CoCreateInstance):
/// CLSID_SimpleFileBasedLog ({E16C0593-128F-11D1-97E4-00C04FB9618A} ).
///
/// The file based implementation of ILog additionally supports the IFileBasedLogInit and IPersistFile interfaces. Use
/// IFileBasedLogInit::InitNew to create a new log file. Use IPersistFile::Load to open an existing log file.
///
///
/// This implementation uses a simple error control policy. If any one of the methods fails because of an error on the file-system level,
/// which includes a disk full error, the log is pinned in an error state. This prevents clients from appending additional records to the
/// file or reading potentially bad records. To continue to use the log file, you must create a new instance of the log.
///
///
// https://docs.microsoft.com/en-us/windows/win32/api/txlogpub/nn-txlogpub-ilog
[PInvokeData("txlogpub.h", MSDNShortId = "NN:txlogpub.ILog")]
[ComImport, Guid("FF222117-0C6C-11d2-B89A-00C04FB9618A"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface ILog
{
/// Forces the contents of the log to disk, at least up through the specified LSN.
///
/// At the very least, all records that have not yet been written to disk with an LSN less than or equal to lsnMinToForce must
/// be written to disk now. An implementation may, however, choose to write more records than what is strictly required. For example,
/// an implementation is allowed to force all records to disk, regardless of the value of lsnMinToForce. Passing 0 as
/// lsnMinToForce indicates that the entire log is to be forced to disk.
///
///
/// The log may also be forced to disk after appending individual records. See ILog::AppendRecord.
/// Notes to Callers
///
/// A failure return value indicates that any records appended to the log since the last time it was successfully forced are not
/// guaranteed to be on disk. The ILog interface does not provide a method to determine which records have been successfully written
/// to disk. If you need to know which records were successfully written to disk, you must force the log for each record. See ILog::AppendRecord.
///
/// Notes to Implementers
///
/// It is recommended that you flush file buffers (for example, using the FlushFileBuffers function) before returning from this method.
///
///
// https://docs.microsoft.com/en-us/windows/win32/api/txlogpub/nf-txlogpub-ilog-force HRESULT Force( [in] LSN lsnMinToForce );
void Force(LSN lsnMinToForce);
/// Write a new record to the end of the log.
/// A pointer to an array of BLOBs of data to be written.
/// The size of the rgBlob array, in elements.
///
/// Indicates whether to force the data to disk. If TRUE, the contents of the log up to this record must be forced to disk
/// before the call returns. If FALSE, this record may be buffered in memory to be written after the call returns successfully.
///
///
/// A pointer to the LSN of the newly appended record. If the LSN of the newly appended record is not needed, this parameter can be NULL.
///
///
///
/// Each log record written or read by ILog is an opaque BLOB of data. As a convenience to callers, AppendRecord allows
/// multiple BLOBs to be concatenated into a single record; because many implementations of ILog will copy records to a buffer
/// in memory, it may be inefficient for the caller to allocate memory for concatenating the parts of a record. However, once a
/// record is appended to the log, ILog provides no method to extract individual BLOBs from the record. It is the
/// responsibility of the caller to parse the data in records read from the log. See ILog::ReadRecord.
///
/// Notes to Callers
///
/// A failure return value indicates that any records appended to the log since the last time it was successfully forced are not
/// guaranteed to be on disk. The ILog interface does not provide a method to determine which records have been successfully written
/// to disk. If you need to know which records were successfully written to disk, you must force the log for each record.
///
/// Notes to Implementers
///
/// If fForceNow is TRUE, it is recommended that you flush file buffers (for example, using the FlushFileBuffers
/// function) before returning from this method.
///
///
// https://docs.microsoft.com/en-us/windows/win32/api/txlogpub/nf-txlogpub-ilog-appendrecord HRESULT AppendRecord( [in] BLOB *rgBlob,
// [in] ULONG cBlob, [in] BOOL fForceNow, [in, out] LSN *plsn );
void AppendRecord([In, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] BLOB[] rgBlob, uint cBlob, [MarshalAs(UnmanagedType.Bool)] bool fForceNow, out LSN plsn);
/// Read a record from the log.
/// The LSN of the record to be read.
///
/// A pointer to the LSN of the previous record (the record immediately preceding the record to be read). This parameter can be
/// NULL if the LSN of the previous record is not needed. This parameter is 0 if there is no previous record in the log, or if
/// an error occurs.
///
///
/// A pointer to the LSN of the next record (the record immediately following the record to read). This parameter can be NULL
/// if the LSN of the next record is not needed. This parameter is MAXLSN (0x7FFFFFFFFFFFFFFF) if there is no next record in the log.
/// This parameter is 0 if an error occurs.
///
///
/// A pointer to a variable that will contain a pointer to the record data on return. The memory for this data is allocated by
/// ReadRecord and freed by the caller (see CoTaskMemFree). This parameter is NULL if an error occurs.
///
/// A pointer to a variable that receives the size of the record data, in bytes, on return.
///
///
/// Although records appended to the log using ILog::AppendRecord may be concatenated from multiple BLOBs, ReadRecord returns
/// the record as a single opaque blob of data. ILog provides no method to extract individual BLOBs from the record. It is the
/// responsibility of the caller to parse the data in records returned by ReadRecord.
///
/// Notes to Callers
///
/// If the log contains very large records, this method may fail because ReadRecord was unable to allocate sufficient memory
/// for the record data. If the size of records is bounded or if you only need an initial part of the record, it may be more
/// efficient to call ILog::ReadRecordPrefix.
///
///
// https://docs.microsoft.com/en-us/windows/win32/api/txlogpub/nf-txlogpub-ilog-readrecord HRESULT ReadRecord( [in] LSN lsnToRead,
// [in, out] LSN *plsnPrev, [in, out] LSN *plsnNext, [out] BYTE **ppbData, [out] ULONG *pcbData );
unsafe void ReadRecord(LSN lsnToRead, [In, Out, Optional] LSN* plsnPrev, [In, Out, Optional] LSN* plsnNext, out SafeCoTaskMemHandle ppbData, out uint pcbData);
/// Reads an initial part of a record from the log.
/// The LSN of the record to be read.
///
/// A pointer to the LSN of the previous record (the record immediately preceding the record to read). You may pass NULL if
/// the LSN of the previous record is not needed. This parameter is 0 if there is no previous record in the log or if an error occurs.
///
///
/// A pointer to the LSN of the next record (the record immediately following the record to read). You may pass NULL if the
/// LSN of the next record is not needed. This parameter is MAXLSN (0x7FFFFFFFFFFFFFFF) if there is no next record in the log. This
/// parameter is 0 if an error occurs.
///
/// A pointer to a buffer into which the record data is to be read.
///
/// A pointer to a variable that contains the size in bytes of the buffer on input, and will contain the size in bytes of the record
/// data read on return.
///
///
/// A pointer to a variable that will contain the size in bytes of the entire record on return. You may pass NULL if the size
/// of the entire record is not needed.
///
///
/// Although records appended to the log using ILog::AppendRecord may be concatenated from multiple BLOBs, ReadRecordPrefix
/// returns the record as a single opaque blob of data. ILog provides no method to extract individual BLOBs from the record. It is
/// the responsibility of the caller to parse the data in records returned by ReadRecordPrefix.
///
// https://docs.microsoft.com/en-us/windows/win32/api/txlogpub/nf-txlogpub-ilog-readrecordprefix HRESULT ReadRecordPrefix( [in] LSN
// lsnToRead, [in, out] LSN *plsnPrev, [in, out] LSN *plsnNext, [out] BYTE *pbData, [in, out] ULONG *pcbData, [out] ULONG *pcbRecord );
unsafe void ReadRecordPrefix(LSN lsnToRead, [In, Out, Optional] LSN* plsnPrev, [In, Out, Optional] LSN* plsnNext, [Out] IntPtr pbData, ref uint pcbData, out uint pcbRecord);
/// Retrieves information about the current bounds of the log.
///
/// A pointer to the LSN of the first record in the log. This parameter can be NULL if the LSN of the first record is not needed.
///
///
/// A pointer to the LSN of the last record in the log. This parameter can be NULL if the LSN of the last record is not needed.
///
/// The limits returned by this method may include records that have not yet been written to disk.
// https://docs.microsoft.com/en-us/windows/win32/api/txlogpub/nf-txlogpub-ilog-getloglimits HRESULT GetLogLimits( [in, out] LSN
// *plsnFirst, [in, out] LSN *plsnLast );
unsafe void GetLogLimits([In, Out, Optional] LSN* plsnFirst, [In, Out, Optional] LSN* plsnLast);
/// Throws away the specified prefix of the log, making it no longer retrievable.
/// The LSN of the first record not to be thrown away. If this parameter is 0, the entire log is emptied.
///
/// This request is only a hint to the log implementation. The log is free to ignore the request, or to retain more than was strictly
/// requested. Many ILog implementations will follow this latter option.
///
// https://docs.microsoft.com/en-us/windows/win32/api/txlogpub/nf-txlogpub-ilog-truncateprefix HRESULT TruncatePrefix( [in] LSN
// lsnFirstToKeep );
void TruncatePrefix(LSN lsnFirstToKeep);
/// Provides a hint to the implementation about the pattern in which records will be read.
///
/// The pattern in which records will most often be read. For more information, see the RECORD_READING_POLICY enumeration.
///
///
/// Not all implementations of ILog will be optimized for reading records in a particular pattern. An implementation may choose to
/// ignore this request and return S_OK.
///
// https://docs.microsoft.com/en-us/windows/win32/api/txlogpub/nf-txlogpub-ilog-setaccesspolicyhint HRESULT SetAccessPolicyHint( [in]
// RECORD_READING_POLICY policy );
void SetAccessPolicyHint(RECORD_READING_POLICY policy);
}
/// CLSID_SimpleFileBasedLog
[ComImport, Guid("e16c0593-128f-11d1-97e4-00c04fb9618a"), ClassInterface(ClassInterfaceType.None)]
public class SimpleFileBasedLog { }
}