in src/prod/src/data/logicallog/LogTestBase.cpp [660:1163]
VOID LogTestBase::BasicIOTest(__in KtlLoggerMode, __in KGuid const & physicalLogId)
{
NTSTATUS status;
ILogManagerHandle::SPtr logManager;
status = CreateAndOpenLogManager(logManager);
VERIFY_STATUS_SUCCESS("CreateAndOpenLogManager", status);
LogManager* logManagerService = nullptr;
{
LogManagerHandle* logManagerServiceHandle = dynamic_cast<LogManagerHandle*>(logManager.RawPtr());
if (logManagerServiceHandle != nullptr)
{
logManagerService = logManagerServiceHandle->owner_.RawPtr();
}
}
VerifyState(
logManagerService,
1,
0,
TRUE);
KString::SPtr physicalLogName;
GenerateUniqueFilename(physicalLogName);
// Don't care if this fails
SyncAwait(logManager->DeletePhysicalLogAsync(*physicalLogName, physicalLogId, CancellationToken::None));
IPhysicalLogHandle::SPtr physicalLog;
status = CreatePhysicalLog(*logManager, physicalLogId, *physicalLogName, physicalLog);
VERIFY_STATUS_SUCCESS("CreatePhysicalLog", status);
VerifyState(
logManagerService,
1,
1,
TRUE,
dynamic_cast<PhysicalLogHandle*>(physicalLog.RawPtr()) != nullptr ? &(static_cast<PhysicalLogHandle&>(*physicalLog).Owner) : nullptr,
1,
0,
TRUE,
dynamic_cast<PhysicalLogHandle*>(physicalLog.RawPtr()),
TRUE);
KString::SPtr logicalLogName;
GenerateUniqueFilename(logicalLogName);
KGuid logicalLogId;
logicalLogId.CreateNew();
ILogicalLog::SPtr logicalLog;
status = CreateLogicalLog(*physicalLog, logicalLogId, *logicalLogName, logicalLog);
VERIFY_STATUS_SUCCESS("CreateLogicalLog", status);
VerifyState(
logManagerService,
1,
1,
TRUE,
dynamic_cast<PhysicalLogHandle*>(physicalLog.RawPtr()) != nullptr ? &(static_cast<PhysicalLogHandle&>(*physicalLog).Owner) : nullptr,
1,
1,
TRUE,
dynamic_cast<PhysicalLogHandle*>(physicalLog.RawPtr()),
TRUE,
nullptr,
-1,
-1,
FALSE,
nullptr,
FALSE,
FALSE,
dynamic_cast<LogicalLog*>(logicalLog.RawPtr()),
TRUE);
VERIFY_ARE_EQUAL(0, logicalLog->Length);
VERIFY_ARE_EQUAL(0, logicalLog->ReadPosition);
VERIFY_ARE_EQUAL(0, logicalLog->WritePosition);
VERIFY_ARE_EQUAL(-1, logicalLog->HeadTruncationPosition);
static const LONG MaxLogBlkSize = 128 * 1024;
// Prove simple recovery
status = SyncAwait(logicalLog->CloseAsync(CancellationToken::None));
VERIFY_STATUS_SUCCESS("LogicalLog::CloseAsync", status);
logicalLog = nullptr;
status = OpenLogicalLog(*physicalLog, logicalLogId, *logicalLogName, logicalLog);
VERIFY_STATUS_SUCCESS("OpenLogicalLog", status);
VERIFY_ARE_EQUAL(0, logicalLog->Length);
VERIFY_ARE_EQUAL(0, logicalLog->ReadPosition);
VERIFY_ARE_EQUAL(0, logicalLog->WritePosition);
VERIFY_ARE_EQUAL(-1, logicalLog->HeadTruncationPosition);
const int recordSize = 131;
// Prove we can write bytes
KBuffer::SPtr x;
PUCHAR xPtr;
AllocBuffer(recordSize, x, xPtr);
BuildDataBuffer(*x, 0, 0, recordSize);
ValidateDataBuffer(*x, x->QuerySize(), 0, 0, 0, recordSize);
VERIFY_ARE_EQUAL(0, logicalLog->WritePosition);
status = SyncAwait(logicalLog->AppendAsync(*x, 0, x->QuerySize(), CancellationToken::None));
VERIFY_STATUS_SUCCESS("LogicalLog::AppendAsync", status);
VERIFY_ARE_EQUAL(recordSize, logicalLog->WritePosition);
status = SyncAwait(logicalLog->FlushWithMarkerAsync(CancellationToken::None));
VERIFY_STATUS_SUCCESS("LogicalLog::FlushWithMarkerAsync", status);
status = SyncAwait(logicalLog->CloseAsync(CancellationToken::None));
VERIFY_STATUS_SUCCESS("LogicalLog::CloseAsync", status);
logicalLog = nullptr;
// Prove simple (non-null recovery - only one (asn 1) physical record in the log)
status = OpenLogicalLog(*physicalLog, logicalLogId, *logicalLogName, logicalLog);
VERIFY_STATUS_SUCCESS("OpenLogicalLog", status);
VERIFY_ARE_EQUAL(recordSize, logicalLog->Length);
VERIFY_ARE_EQUAL(0, logicalLog->ReadPosition);
VERIFY_ARE_EQUAL(recordSize, logicalLog->WritePosition);
VERIFY_ARE_EQUAL(-1, logicalLog->HeadTruncationPosition);
status = SyncAwait(logicalLog->AppendAsync(*x, 0, x->QuerySize(), CancellationToken::None));
VERIFY_STATUS_SUCCESS("LogicalLog::AppendAsync", status);
VERIFY_ARE_EQUAL(recordSize * 2, logicalLog->WritePosition);
status = SyncAwait(logicalLog->FlushWithMarkerAsync(CancellationToken::None));
VERIFY_STATUS_SUCCESS("LogicalLog::FlushWithMarkerAsync", status);
status = SyncAwait(logicalLog->CloseAsync(CancellationToken::None));
VERIFY_STATUS_SUCCESS("LogicalLog::CloseAsync", status);
logicalLog = nullptr;
// Prove simple (non-null recovery)
status = OpenLogicalLog(*physicalLog, logicalLogId, *logicalLogName, logicalLog);
VERIFY_STATUS_SUCCESS("OpenLogicalLog", status);
VERIFY_ARE_EQUAL(recordSize * 2, logicalLog->Length);
VERIFY_ARE_EQUAL(0, logicalLog->ReadPosition);
VERIFY_ARE_EQUAL(recordSize * 2, logicalLog->WritePosition);
VERIFY_ARE_EQUAL(-1, logicalLog->HeadTruncationPosition);
// Prove simple read and positioning works
AllocBuffer(recordSize, x, xPtr);
LONG bytesRead;
status = SyncAwait(logicalLog->ReadAsync(bytesRead, *x, 0, x->QuerySize(), 0, CancellationToken::None));
VERIFY_STATUS_SUCCESS("LogicalLog::ReadAsync", status);
VERIFY_ARE_EQUAL(recordSize, bytesRead);
ValidateDataBuffer(*x, x->QuerySize(), 0, 0, 0, recordSize);
VERIFY_ARE_EQUAL(recordSize, logicalLog->ReadPosition);
// Prove next sequential physical read works
AllocBuffer(recordSize, x, xPtr);
status = SyncAwait(logicalLog->ReadAsync(bytesRead, *x, 0, x->QuerySize(), 0, CancellationToken::None));
VERIFY_STATUS_SUCCESS("LogicalLog::ReadAsync", status);
VERIFY_ARE_EQUAL(recordSize, bytesRead);
ValidateDataBuffer(*x, x->QuerySize(), 0, 0, 0, recordSize);
VERIFY_ARE_EQUAL(recordSize * 2, logicalLog->ReadPosition);
// Positioning and reading partial and across physical records work
int offset = 1;
status = logicalLog->SeekForRead(offset, Common::SeekOrigin::Enum::Begin);
VERIFY_STATUS_SUCCESS("LogicalLog::SeekForRead", status);
AllocBuffer(recordSize, x, xPtr);
status = SyncAwait(logicalLog->ReadAsync(bytesRead, *x, 0, x->QuerySize(), 0, CancellationToken::None));
VERIFY_STATUS_SUCCESS("LogicalLog::ReadAsync", status);
VERIFY_ARE_EQUAL(recordSize, bytesRead);
ValidateDataBuffer(*x, x->QuerySize(), 0, offset, 0, recordSize);
VERIFY_ARE_EQUAL(recordSize + offset, logicalLog->ReadPosition);
// Prove reading a short record works
x->Zero();
status = SyncAwait(logicalLog->ReadAsync(bytesRead, *x, 0, x->QuerySize(), 0, CancellationToken::None));
VERIFY_STATUS_SUCCESS("LogicalLog::ReadAsync", status);
VERIFY_ARE_EQUAL(recordSize - 1, bytesRead);
ValidateDataBuffer(*x, recordSize - 1, 0, offset, 0, recordSize);
VERIFY_ARE_EQUAL(logicalLog->WritePosition, logicalLog->ReadPosition);
// Prove reading at EOS works
AllocBuffer(recordSize, x, xPtr);
status = SyncAwait(logicalLog->ReadAsync(bytesRead, *x, 0, x->QuerySize(), 0, CancellationToken::None));
VERIFY_STATUS_SUCCESS("LogicalLog::ReadAsync", status);
VERIFY_ARE_EQUAL(0, bytesRead);
VERIFY_ARE_EQUAL(logicalLog->WritePosition, logicalLog->ReadPosition);
// Prove position beyond and just EOS and reading works
LONGLONG currentPos;
status = logicalLog->SeekForRead(1, Common::SeekOrigin::Enum::End);
VERIFY_STATUS_SUCCESS("LogicalLog::SeekForRead", status);
currentPos = logicalLog->ReadPosition;
status = SyncAwait(logicalLog->ReadAsync(bytesRead, *x, 0, x->QuerySize(), 0, CancellationToken::None));
VERIFY_STATUS_SUCCESS("LogicalLog::ReadAsync", status);
VERIFY_ARE_EQUAL(0, bytesRead);
LONGLONG eos;
status = logicalLog->SeekForRead(0, Common::SeekOrigin::Enum::End);
VERIFY_STATUS_SUCCESS("LogicalLog::SeekForRead", status);
eos = logicalLog->ReadPosition;
status = SyncAwait(logicalLog->ReadAsync(bytesRead, *x, 0, x->QuerySize(), 0, CancellationToken::None));
VERIFY_STATUS_SUCCESS("LogicalLog::ReadAsync", status);
VERIFY_ARE_EQUAL(0, bytesRead);
VERIFY_ARE_EQUAL(logicalLog->WritePosition, eos);
status = logicalLog->SeekForRead(-1, Common::SeekOrigin::Enum::End);
VERIFY_STATUS_SUCCESS("LogicalLog::SeekForRead", status);
currentPos = logicalLog->ReadPosition;
status = SyncAwait(logicalLog->ReadAsync(bytesRead, *x, 0, 1, 0, CancellationToken::None));
VERIFY_STATUS_SUCCESS("LogicalLog::ReadAsync", status);
VERIFY_ARE_EQUAL(1, bytesRead);
ValidateDataBuffer(*x, 1, 0, currentPos, 0, recordSize);
status = logicalLog->SeekForRead(-1, Common::SeekOrigin::Enum::End);
VERIFY_STATUS_SUCCESS("LogicalLog::SeekForRead", status);
currentPos = logicalLog->ReadPosition;
status = SyncAwait(logicalLog->ReadAsync(bytesRead, *x, 0, 2, 0, CancellationToken::None));
VERIFY_STATUS_SUCCESS("LogicalLog::ReadAsync", status);
VERIFY_ARE_EQUAL(1, bytesRead);
ValidateDataBuffer(*x, 1, 0, currentPos, 0, recordSize);
status = logicalLog->SeekForRead(-2, Common::SeekOrigin::Enum::End);
VERIFY_STATUS_SUCCESS("LogicalLog::SeekForRead", status);
currentPos = logicalLog->ReadPosition;
status = SyncAwait(logicalLog->ReadAsync(bytesRead, *x, 0, 2, 0, CancellationToken::None));
VERIFY_STATUS_SUCCESS("LogicalLog::ReadAsync", status);
VERIFY_ARE_EQUAL(2, bytesRead);
ValidateDataBuffer(*x, 2, 0, currentPos, 0, recordSize);
// Prove we can position forward to every location
currentPos = eos - 1;
while (currentPos >= 0)
{
status = logicalLog->SeekForRead(currentPos, Common::SeekOrigin::Enum::Begin);
VERIFY_STATUS_SUCCESS("LogicalLog::SeekForRead", status);
VERIFY_ARE_EQUAL(currentPos, logicalLog->ReadPosition);
KBuffer::SPtr rBuff;
status = KBuffer::Create((ULONG)(eos - currentPos), rBuff, GetThisAllocator());
VERIFY_STATUS_SUCCESS("KBuffer::Create", status);
status = SyncAwait(logicalLog->ReadAsync(bytesRead, *rBuff, 0, rBuff->QuerySize(), 0, CancellationToken::None));
VERIFY_STATUS_SUCCESS("LogicalLog::ReadAsync", status);
VERIFY_ARE_EQUAL(rBuff->QuerySize(), (ULONG)bytesRead);
currentPos--;
}
// Prove Stream read abstraction works through a BufferedStream
// (since we don't have a BufferedStream, use KStream)
ILogicalLogReadStream::SPtr readStream;
status = logicalLog->CreateReadStream(readStream, 0);
VERIFY_STATUS_SUCCESS("LogicalLog::CreateReadStream", status);
ktl::io::KStream::SPtr bStream = readStream.RawPtr();
bStream->Position = bStream->Length + 1; // seek to end + 1
currentPos = bStream->Position;
ULONG uBytesRead;
status = SyncAwait(bStream->ReadAsync(*x, uBytesRead, 0, x->QuerySize()));
VERIFY_STATUS_SUCCESS("KStream::ReadAsync", status);
VERIFY_ARE_EQUAL(0, uBytesRead);
bStream->Position = bStream->Length; // seek to end
eos = bStream->Position;
VERIFY_ARE_EQUAL(logicalLog->WritePosition, eos);
bStream->Position = bStream->Length - 1; // seek to end - 1
currentPos = bStream->Position;
status = SyncAwait(bStream->ReadAsync(*x, uBytesRead, 0, 1));
VERIFY_STATUS_SUCCESS("KStream::ReadAsync", status);
VERIFY_ARE_EQUAL(1, uBytesRead);
ValidateDataBuffer(*x, 1, 0, currentPos, 0, recordSize);
bStream->Position = bStream->Length - 1; // seek to end - 1
currentPos = bStream->Position;
status = SyncAwait(bStream->ReadAsync(*x, uBytesRead, 0, 2));
VERIFY_STATUS_SUCCESS("KStream::ReadAsync", status);
VERIFY_ARE_EQUAL(1, uBytesRead);
ValidateDataBuffer(*x, 1, 0, currentPos, 0, recordSize);
bStream->Position = bStream->Length - 2; // seek to end - 2
currentPos = bStream->Position;
status = SyncAwait(bStream->ReadAsync(*x, uBytesRead, 0, 2));
VERIFY_STATUS_SUCCESS("KStream::ReadAsync", status);
VERIFY_ARE_EQUAL(2, uBytesRead);
ValidateDataBuffer(*x, 2, 0, currentPos, 0, recordSize);
currentPos = eos - 1;
while (currentPos >= 0)
{
bStream->Position = currentPos;
KBuffer::SPtr rBuff;
status = KBuffer::Create((ULONG)(eos - currentPos), rBuff, GetThisAllocator());
VERIFY_STATUS_SUCCESS("KBuffer::Create", status);
status = SyncAwait(bStream->ReadAsync(*rBuff, uBytesRead, 0, rBuff->QuerySize()));
VERIFY_STATUS_SUCCESS("KStream::ReadAsync", status);
VERIFY_ARE_EQUAL(rBuff->QuerySize(), uBytesRead);
currentPos--;
}
status = SyncAwait(bStream->CloseAsync());
VERIFY_STATUS_SUCCESS("KStream::CloseAsync", status);
bStream = nullptr;
readStream->Dispose(); // idempotent
readStream = nullptr;
status = SyncAwait(logicalLog->CloseAsync(CancellationToken::None));
VERIFY_STATUS_SUCCESS("LogicalLog::CloseAsync", status);
logicalLog = nullptr;
status = SyncAwait(physicalLog->DeleteLogicalLogOnlyAsync(logicalLogId, CancellationToken::None));
VERIFY_STATUS_SUCCESS("IPhysicalLogHandle::DeleteLogicalLogOnlyAsync", status);
// Prove some large I/O
status = CreateLogicalLog(*physicalLog, logicalLogId, *logicalLogName, logicalLog);
VERIFY_STATUS_SUCCESS("CreateLogicalLog", status);
VerifyState(
logManagerService,
1,
1,
TRUE,
dynamic_cast<PhysicalLogHandle*>(physicalLog.RawPtr()) != nullptr ? &(static_cast<PhysicalLogHandle&>(*physicalLog).Owner) : nullptr,
1,
1,
TRUE,
dynamic_cast<PhysicalLogHandle*>(physicalLog.RawPtr()),
TRUE,
nullptr,
-1,
-1,
FALSE,
nullptr,
FALSE,
FALSE,
dynamic_cast<LogicalLog*>(logicalLog.RawPtr()),
TRUE);
VERIFY_ARE_EQUAL(0, logicalLog->Length);
VERIFY_ARE_EQUAL(0, logicalLog->ReadPosition);
VERIFY_ARE_EQUAL(0, logicalLog->WritePosition);
VERIFY_ARE_EQUAL(-1, logicalLog->HeadTruncationPosition);
AllocBuffer(1024 * 1024, x, xPtr);
BuildDataBuffer(*x, 0, 0, recordSize);
status = SyncAwait(logicalLog->AppendAsync(*x, 0, x->QuerySize(), CancellationToken::None));
VERIFY_STATUS_SUCCESS("LogicalLog::AppendAsync", status);
VERIFY_ARE_EQUAL(1024 * 1024, logicalLog->WritePosition);
status = SyncAwait(logicalLog->FlushWithMarkerAsync(CancellationToken::None));
VERIFY_STATUS_SUCCESS("LogicalLog::FlushWithMarkerAsync", status);
AllocBuffer(1024 * 1024, x, xPtr);
status = SyncAwait(logicalLog->ReadAsync(bytesRead, *x, 0, x->QuerySize(), 0, CancellationToken::None));
VERIFY_STATUS_SUCCESS("LogicalLog::ReadAsync", status);
VERIFY_ARE_EQUAL(x->QuerySize(), (ULONG)bytesRead);
ValidateDataBuffer(*x, x->QuerySize(), 0, 0, 0, recordSize);
// Prove basic head truncation behavior
status = SyncAwait(logicalLog->TruncateHead(128 * 1024));
VERIFY_STATUS_SUCCESS("LogicalLog::TruncateHead", status);
VERIFY_ARE_EQUAL(128 * 1024, logicalLog->HeadTruncationPosition);
// Force a record out to make sure the head truncation point is captured
const KStringView testStr1(L"Test String Record");
AllocBuffer(testStr1.LengthInBytes(), x, xPtr);
LPCWSTR str = testStr1;
KMemCpySafe(xPtr, x->QuerySize(), str, testStr1.LengthInBytes());
status = SyncAwait(logicalLog->AppendAsync(*x, 0, x->QuerySize(), CancellationToken::None));
VERIFY_STATUS_SUCCESS("LogicalLog::AppendAsync", status);
status = SyncAwait(logicalLog->FlushWithMarkerAsync(CancellationToken::None));
VERIFY_STATUS_SUCCESS("LogicalLog::FlushAsync", status);
// Prove head truncation point is recovered
LONGLONG currentLength = logicalLog->WritePosition;
LONGLONG currentTrucPoint = logicalLog->HeadTruncationPosition;
status = SyncAwait(logicalLog->CloseAsync(CancellationToken::None));
VERIFY_STATUS_SUCCESS("LogicalLog::CloseAsync", status);
logicalLog = nullptr;
status = OpenLogicalLog(*physicalLog, logicalLogId, *logicalLogName, logicalLog);
VERIFY_STATUS_SUCCESS("OpenLogicalLog", status);
VERIFY_ARE_EQUAL(currentLength, logicalLog->WritePosition);
VERIFY_ARE_EQUAL(currentTrucPoint, logicalLog->HeadTruncationPosition);
// Prove basic tail truncation behavior
status = logicalLog->SeekForRead(currentLength - x->QuerySize(), Common::SeekOrigin::Enum::Begin);
VERIFY_STATUS_SUCCESS("LogicalLog::SeekForRead", status);
LONGLONG newEos = logicalLog->ReadPosition;
AllocBuffer(256, x, xPtr);
status = SyncAwait(logicalLog->ReadAsync(bytesRead, *x, 0, x->QuerySize(), 0, CancellationToken::None));
VERIFY_STATUS_SUCCESS("LogicalLog::ReadAsync", status);
KString::SPtr chars;
status = KString::Create(chars, GetThisAllocator(), bytesRead / sizeof(WCHAR));
VERIFY_STATUS_SUCCESS("KString::Create", status);
chars->SetLength(chars->BufferSizeInChars());
KMemCpySafe((PBYTE)(PVOID)*chars, chars->LengthInBytes(), xPtr, (ULONG)bytesRead);
VERIFY_ARE_EQUAL(testStr1, *chars);
// Chop off the last and part of the 2nd to last records
newEos = newEos - bytesRead - 1;
status = SyncAwait(logicalLog->TruncateTail(newEos, CancellationToken::None));
VERIFY_STATUS_SUCCESS("LogicalLog::TruncateTail", status);
VERIFY_ARE_EQUAL(newEos, logicalLog->WritePosition);
// Prove we can read valid up to the new EOS but not beyond
status = logicalLog->SeekForRead(newEos - 128, Common::SeekOrigin::Enum::Begin);
VERIFY_STATUS_SUCCESS("LogicalLog::SeekForRead", status);
AllocBuffer(256, x, xPtr);
status = SyncAwait(logicalLog->ReadAsync(bytesRead, *x, 0, x->QuerySize(), 0, CancellationToken::None));
VERIFY_STATUS_SUCCESS("LogicalLog::ReadAsync", status);
VERIFY_ARE_EQUAL(128, bytesRead);
ValidateDataBuffer(*x, bytesRead, 0, newEos - 128, 0, recordSize);
// Prove we recover the correct tail position (WritePosition)
status = SyncAwait(logicalLog->CloseAsync(CancellationToken::None));
VERIFY_STATUS_SUCCESS("LogicalLog::CloseAsync", status);
logicalLog = nullptr;
status = OpenLogicalLog(*physicalLog, logicalLogId, *logicalLogName, logicalLog);
VERIFY_STATUS_SUCCESS("OpenLogicalLog", status);
VERIFY_ARE_EQUAL(newEos, logicalLog->WritePosition);
VERIFY_ARE_EQUAL(currentTrucPoint, logicalLog->HeadTruncationPosition);
// Prove we can truncate all content via tail truncation
VERIFY_ARE_NOT_EQUAL(0, logicalLog->Length);
status = SyncAwait(logicalLog->TruncateTail(currentTrucPoint + 1, CancellationToken::None));
VERIFY_STATUS_SUCCESS("LogicalLog::TruncateTail", status);
VERIFY_ARE_EQUAL(0, logicalLog->Length);
VERIFY_ARE_EQUAL(currentTrucPoint + 1, logicalLog->WritePosition);
status = SyncAwait(logicalLog->CloseAsync(CancellationToken::None));
VERIFY_STATUS_SUCCESS("LogicalLog::CloseAsync", status);
logicalLog = nullptr;
status = OpenLogicalLog(*physicalLog, logicalLogId, *logicalLogName, logicalLog);
VERIFY_STATUS_SUCCESS("OpenLogicalLog", status);
VERIFY_ARE_EQUAL(currentTrucPoint + 1, logicalLog->WritePosition);
VERIFY_ARE_EQUAL(0, logicalLog->Length);
VERIFY_ARE_EQUAL(currentTrucPoint, logicalLog->HeadTruncationPosition);
// Add proof for truncating all but one byte - read it for the right value
LONGLONG currentWritePos = logicalLog->WritePosition;
AllocBuffer(1024 * 1024, x, xPtr);
BuildDataBuffer(*x, currentWritePos, 0, recordSize);
status = SyncAwait(logicalLog->AppendAsync(*x, 0, x->QuerySize(), CancellationToken::None));
VERIFY_STATUS_SUCCESS("LogicalLog::AppendAsync", status);
VERIFY_ARE_EQUAL(currentWritePos + (1024 * 1024), logicalLog->WritePosition);
status = SyncAwait(logicalLog->FlushWithMarkerAsync(CancellationToken::None));
VERIFY_STATUS_SUCCESS("LogicalLog::FlushWithMarkerAsync", status);
status = logicalLog->SeekForRead(currentWritePos, Common::SeekOrigin::Enum::Begin);
VERIFY_STATUS_SUCCESS("LogicalLog::SeekForRead", status);
VERIFY_ARE_EQUAL(currentWritePos, logicalLog->ReadPosition);
AllocBuffer(1024 * 1024, x, xPtr);
status = SyncAwait(logicalLog->ReadAsync(bytesRead, *x, 0, x->QuerySize(), 0, CancellationToken::None));
VERIFY_STATUS_SUCCESS("LogicalLog::ReadAsync", status);
VERIFY_ARE_EQUAL(x->QuerySize(), (ULONG)bytesRead);
ValidateDataBuffer(*x, x->QuerySize(), 0, currentWritePos, 0, recordSize);
status = SyncAwait(logicalLog->TruncateHead(currentWritePos + (1024 * 513)));
VERIFY_STATUS_SUCCESS("LogicalLog::TruncateHead", status);
VERIFY_ARE_EQUAL(currentWritePos + (1024 * 513), logicalLog->HeadTruncationPosition);
status = logicalLog->SeekForRead(currentWritePos + (1024 * 513) + 1, Common::SeekOrigin::Enum::Begin);
VERIFY_STATUS_SUCCESS("LogicalLog::SeekForRead", status);
VERIFY_ARE_EQUAL(currentWritePos + (1024 * 513) + 1, logicalLog->ReadPosition);
AllocBuffer((ULONG)logicalLog->Length, x, xPtr);
status = SyncAwait(logicalLog->ReadAsync(bytesRead, *x, 0, x->QuerySize(), 0, CancellationToken::None));
VERIFY_STATUS_SUCCESS("LogicalLog::ReadAsync", status);
VERIFY_ARE_EQUAL(x->QuerySize(), (ULONG)bytesRead);
ValidateDataBuffer(*x, x->QuerySize(), 0, currentWritePos + (1024 * 513) + 1, 0, recordSize);
status = SyncAwait(logicalLog->TruncateTail(currentWritePos + (1024 * 513) + 2, CancellationToken::None));
VERIFY_STATUS_SUCCESS("LogicalLog::TruncateTail", status);
VERIFY_ARE_EQUAL(1, logicalLog->Length);
status = logicalLog->SeekForRead(currentWritePos + (1024 * 513) + 1, Common::SeekOrigin::Enum::Begin);
VERIFY_STATUS_SUCCESS("LogicalLog::SeekForRead", status);
VERIFY_ARE_EQUAL(currentWritePos + (1024 * 513) + 1, logicalLog->ReadPosition);
((PBYTE)x->GetBuffer())[0] = ~(((PBYTE)x->GetBuffer())[0]);
status = SyncAwait(logicalLog->ReadAsync(bytesRead, *x, 0, 1, 0, CancellationToken::None));
VERIFY_STATUS_SUCCESS("LogicalLog::ReadAsync", status);
VERIFY_ARE_EQUAL(1, bytesRead);
ValidateDataBuffer(*x, 1, 0, currentWritePos + (1024 * 513) + 1, 0, recordSize);
// Prove close down
status = SyncAwait(logicalLog->CloseAsync(CancellationToken::None));
VERIFY_STATUS_SUCCESS("LogicalLog::CloseAsync", status);
logicalLog = nullptr;
status = SyncAwait(physicalLog->CloseAsync(CancellationToken::None));
VERIFY_STATUS_SUCCESS("PhysicalLog::CloseAsync", status);
physicalLog = nullptr;
status = SyncAwait(logManager->DeletePhysicalLogAsync(*physicalLogName, physicalLogId, CancellationToken::None));
VERIFY_STATUS_SUCCESS("LogManager::DeletePhysicalLogAsync", status);
status = SyncAwait(logManager->CloseAsync(CancellationToken::None));
VERIFY_STATUS_SUCCESS("LogManager::CloseAsync", status);
logManager = nullptr;
}