windows-nt/Source/XPSP1/NT/sdktools/yapt/yapt.c
2020-09-26 16:20:57 +08:00

1300 lines
31 KiB
C

/*++
Copyright (c) 1994 Microsoft Corporation
Module Name:
yapt.c
Abstract:
This module contains the code for the Yet Another Performance Tool utility.
Author:
Chuck Park (chuckp) 07-Oct-1994
Revision History:
--*/
#include <nt.h>
#include <ntrtl.h>
#include <nturtl.h>
#include <windows.h>
#include <windowsx.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <time.h>
#include <assert.h>
#include "yapt.h"
//
// Test proc. declarations
//
BOOLEAN
ReadSequential(
ULONG Iterations
);
BOOLEAN
WriteSequential(
ULONG Iterations
);
BOOLEAN
ReadRandom(
ULONG Iterations
);
BOOLEAN
WriteRandom(
ULONG Iterations
);
//
// Common util. functions
//
BOOLEAN
CreateTestFile(
);
ULONG
GetRandomOffset(
ULONG min,
ULONG max
);
BOOL
GetSectorSize(
PDWORD SectorSize,
PCHAR DrvLetter
);
VOID
LogError(
PCHAR ErrString,
DWORD UniqueId,
DWORD ErrCode
);
BOOLEAN
ParseCmdLine(
INT Argc,
CHAR *Argv[]
);
BOOLEAN
ValidateOption(
CHAR Switch,
CHAR *Value
);
VOID
VerifyFileName(
IN CHAR *FileName
);
VOID
Usage(
VOID
);
VOID
__cdecl
Log(
ULONG LogLevel,
PCHAR String,
...
);
DWORD
YaptSetFileCompression(
IN HANDLE FileHandle,
IN USHORT CompressionFormat
);
//
// Default parameters
//
#define DEFAULT_BUFFER_SIZE 65536
#define DEFAULT_FILE_SIZE (20*1024*1024);
ULONG SectorSize = 512;
ULONG BufferSize = DEFAULT_BUFFER_SIZE;
ULONG FileSize = DEFAULT_FILE_SIZE;
UCHAR FileName[MAX_PATH] = "test.dat";
UCHAR Test = READ;
UCHAR Access = SEQ;
ULONG Verbose = 0;
ULONG Iterations = 10;
UCHAR ReuseFile = TRUE;
UCHAR Yes = FALSE;
BOOLEAN ReadOnly = FALSE;
INT
_cdecl main (
INT Argc,
CHAR *Argv[]
)
{
UCHAR testCase;
//
// Parse cmd line
//
if (!ParseCmdLine(Argc,Argv)) {
return 1;
}
//
// Create the test file
//
if (!CreateTestFile()) {
return 2;
}
//
// Call appropriate test routine.
//
testCase = (Test << 1) | Access;
switch (testCase) {
case 0:
if (!ReadSequential(Iterations)) {
return 3;
}
break;
case 1:
//
// Read random
//
if (!ReadRandom(Iterations)) {
return 3;
}
break;
case 2:
if (!WriteSequential(Iterations)) {
return 3;
}
break;
case 3:
//
// Write random
//
if (!WriteRandom(Iterations)) {
return 3;
}
break;
default:
printf("Invalid test case\n");
return 3;
}
return 0;
}
BOOLEAN
CreateTestFile(
VOID
)
{
PUCHAR buffer;
HANDLE port = INVALID_HANDLE_VALUE;
HANDLE fileHandle;
OVERLAPPED overlapped,*overlapped2;
DWORD bytesTransferred,bytesTransferred2;
DWORD_PTR key;
ULONG numberWrites;
BOOL status;
ULONG i;
DWORD currentSize;
buffer = VirtualAlloc(NULL,
DEFAULT_BUFFER_SIZE,
MEM_COMMIT,
PAGE_READWRITE);
if ( !buffer ) {
printf("Error allocating buffer %x\n",GetLastError());
return FALSE;
}
if(ReuseFile) {
fileHandle = CreateFile(FileName,
ReadOnly ? GENERIC_READ :
(GENERIC_READ | GENERIC_WRITE),
0,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED | FILE_FLAG_NO_BUFFERING,
NULL);
if(fileHandle != INVALID_HANDLE_VALUE) {
Log(1, "Using existing test file %s\n", FileName);
goto InitializeTestFile;
} else {
Log(1, "Error %d opening existing test file\n", GetLastError());
}
} else {
DeleteFile(FileName);
}
fileHandle = CreateFile(FileName,
GENERIC_READ | GENERIC_WRITE,
0,
NULL,
OPEN_ALWAYS,
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED | FILE_FLAG_NO_BUFFERING,
NULL);
InitializeTestFile:
if ( fileHandle == INVALID_HANDLE_VALUE ) {
printf("Error opening file %s %d\n",FileName,GetLastError());
return FALSE;
}
currentSize = GetFileSize(fileHandle, NULL);
if(currentSize >= FileSize) {
goto EndCreateTestFile;
} else if(ReadOnly) {
FileSize = currentSize;
goto EndCreateTestFile;
}
//
// Uncompress the file - compressed files will always do cached I/O even
// if you tell them not to. If this fails assume it's because the
// underlying file system doesn't handle compression.
//
Log(1, "Trying to decompress %s\n", FileName);
YaptSetFileCompression(fileHandle, COMPRESSION_FORMAT_NONE);
port = CreateIoCompletionPort(fileHandle,
NULL,
(DWORD_PTR)fileHandle,
0);
if ( !port ) {
printf("Error creating completion port %d\n",GetLastError());
return FALSE;
}
Log(1,"Creating test file %s",FileName);
memset(&overlapped, 0, sizeof(overlapped));
numberWrites = FileSize / BufferSize;
for (i = 0; i < numberWrites; i++) {
retryWrite:
status = WriteFile(fileHandle,
buffer,
BufferSize,
&bytesTransferred,
&overlapped);
if ( !status && GetLastError() != ERROR_IO_PENDING ) {
if (GetLastError() == ERROR_INVALID_USER_BUFFER ||
GetLastError() == ERROR_NOT_ENOUGH_QUOTA ||
GetLastError() == ERROR_WORKING_SET_QUOTA ||
GetLastError() == ERROR_NOT_ENOUGH_MEMORY) {
goto retryWrite;
}
printf("Error creating test file %x\n",GetLastError());
return FALSE;
}
Log(2,".");
overlapped.Offset += BufferSize;
}
for (i = 0; i < numberWrites; i++ ) {
status = GetQueuedCompletionStatus(port,
&bytesTransferred2,
&key,
&overlapped2,
(DWORD)-1);
if ( !status ) {
printf("Error on completion during test file create %x\n",GetLastError());
return FALSE;
}
}
Log(1,".. Complete.\n\n");
EndCreateTestFile:
if(port != INVALID_HANDLE_VALUE) CloseHandle(port);
if(fileHandle != INVALID_HANDLE_VALUE) CloseHandle(fileHandle);
VirtualFree(buffer,
DEFAULT_BUFFER_SIZE,
MEM_DECOMMIT);
return TRUE;
}
BOOLEAN
ReadSequential(
ULONG Iterations
)
{
ULONG j,
outstandingRequests,
remaining = Iterations;
ULONG start,end;
DOUBLE testTime,thruPut = 0.0,seconds = 0;
HANDLE file,
port;
OVERLAPPED overlapped,
*overlapped2;
DWORD bytesRead,
bytesRead2,
errCode,
version;
DWORD_PTR completionKey;
BOOL status;
PUCHAR buffer;
printf("Starting Sequential Reads of %d Meg file, using %d K I/O size\n", FileSize / 1024*1024, BufferSize / 1024);
version = GetVersion() >> 16;
buffer = VirtualAlloc(NULL,
BufferSize + SectorSize - 1,
MEM_COMMIT | MEM_RESERVE,
PAGE_READWRITE);
(ULONG_PTR)buffer &= ~((ULONG_PTR)SectorSize - 1);
if ( !buffer ) {
Log(0,"Error allocating buffer: %x\n",GetLastError());
return FALSE;
}
file = CreateFile(FileName,
ReadOnly ? GENERIC_READ : (GENERIC_READ | GENERIC_WRITE),
0,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED | FILE_FLAG_NO_BUFFERING,
NULL );
if ( file == INVALID_HANDLE_VALUE ) {
Log(0,"Error opening Target file: %x\n",GetLastError());
VirtualFree(buffer,
BufferSize + SectorSize - 1,
MEM_DECOMMIT);
return FALSE;
}
port = CreateIoCompletionPort(file,
NULL,
(DWORD_PTR)file,
0);
if ( !port ) {
Log(0,"Error creating completion port: %x\n",GetLastError());
VirtualFree(buffer,
BufferSize + SectorSize - 1,
MEM_DECOMMIT);
return FALSE;
}
while (remaining--) {
start = GetTickCount();
memset(&overlapped,0,sizeof(overlapped));
outstandingRequests = 0;
for (j = 0; j < FileSize / BufferSize; j++) {
do {
status = ReadFile(file,
buffer,
BufferSize,
&bytesRead,
&overlapped);
errCode = GetLastError();
if (!status) {
if (errCode == ERROR_IO_PENDING) {
break;
} else if (errCode == ERROR_NOT_ENOUGH_QUOTA ||
errCode == ERROR_INVALID_USER_BUFFER ||
errCode == ERROR_WORKING_SET_QUOTA ||
errCode == ERROR_NOT_ENOUGH_MEMORY) {
//
// Allow this to retry.
//
} else {
Log(0,"Error in ReadFile: %x\n",errCode);
VirtualFree(buffer,
BufferSize + SectorSize - 1,
MEM_DECOMMIT);
return FALSE;
}
}
} while (!status);
outstandingRequests++;
overlapped.Offset += BufferSize;
}
for (j = 0; j < outstandingRequests; j++) {
status = GetQueuedCompletionStatus(port,
&bytesRead2,
&completionKey,
&overlapped2,
(DWORD)-1);
if (!status) {
Log(0,"GetQueuedCompletionStatus error: %x\n",GetLastError());
VirtualFree(buffer,
BufferSize + SectorSize - 1,
MEM_DECOMMIT);
return FALSE;
}
}
end = GetTickCount();
testTime = end - start;
testTime /= 1000.0;
seconds += testTime;
Log(1,"Iteration %2d -> %4.3f MB/S\n",Iterations - remaining,(FileSize / testTime)/(1024*1024));
}
CloseHandle(port);
CloseHandle(file);
thruPut = FileSize * Iterations / seconds;
printf("\nAverage Throughput %4.3f MB/S\n",thruPut/(1024*1024));
VirtualFree(buffer,
BufferSize + SectorSize - 1,
MEM_DECOMMIT);
return TRUE;
}
BOOLEAN
ReadRandom(
ULONG Iterations
)
{
ULONG j,
outstandingRequests,
remaining = Iterations;
ULONG start,end;
DOUBLE testTime,thruPut = 0.0,seconds = 0;
HANDLE file,
port;
OVERLAPPED overlapped,
*overlapped2;
DWORD bytesRead,
bytesRead2,
errCode,
version;
DWORD_PTR completionKey;
BOOL status;
PUCHAR buffer;
ULONG min = FileSize,max = 0;
printf("Starting Random Reads of %d Meg file, using %d K I/O size\n", FileSize / 1024*1024, BufferSize / 1024);
version = GetVersion() >> 16;
srand((unsigned)time(NULL));
buffer = VirtualAlloc(NULL,
BufferSize + SectorSize - 1,
MEM_COMMIT | MEM_RESERVE,
PAGE_READWRITE);
(ULONG_PTR)buffer &= ~((ULONG_PTR)SectorSize - 1);
if ( !buffer ) {
Log(0,"Error allocating buffer: %x\n",GetLastError());
return FALSE;
}
file = CreateFile(FileName,
ReadOnly ? GENERIC_READ : (GENERIC_READ | GENERIC_WRITE),
0,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED | FILE_FLAG_NO_BUFFERING,
NULL );
if ( file == INVALID_HANDLE_VALUE ) {
Log(0,"Error opening Target file: %x\n",GetLastError());
VirtualFree(buffer,
BufferSize + SectorSize - 1,
MEM_DECOMMIT);
return FALSE;
}
port = CreateIoCompletionPort(file,
NULL,
(DWORD_PTR)file,
0);
if ( !port ) {
Log(0,"Error creating completion port: %x\n",GetLastError());
VirtualFree(buffer,
BufferSize + SectorSize - 1,
MEM_DECOMMIT);
return FALSE;
}
while (remaining--) {
start = GetTickCount();
memset(&overlapped,0,sizeof(overlapped));
outstandingRequests = 0;
for (j = 0; j < FileSize / BufferSize; j++) {
do {
status = ReadFile(file,
buffer,
BufferSize,
&bytesRead,
&overlapped);
errCode = GetLastError();
if (!status) {
if (errCode == ERROR_IO_PENDING) {
break;
} else if (errCode == ERROR_NOT_ENOUGH_QUOTA ||
errCode == ERROR_INVALID_USER_BUFFER ||
errCode == ERROR_WORKING_SET_QUOTA ||
errCode == ERROR_NOT_ENOUGH_MEMORY) {
//
// Allow this to retry.
//
} else {
Log(0,"Error in ReadFile: %x\n",errCode);
VirtualFree(buffer,
BufferSize + SectorSize - 1,
MEM_DECOMMIT);
return FALSE;
}
}
} while (!status);
outstandingRequests++;
overlapped.Offset = GetRandomOffset(0,FileSize - BufferSize);
if (overlapped.Offset > max) {
max = overlapped.Offset;
}
if (overlapped.Offset < min) {
min = overlapped.Offset;
}
}
for (j = 0; j < outstandingRequests; j++) {
status = GetQueuedCompletionStatus(port,
&bytesRead2,
&completionKey,
&overlapped2,
(DWORD)-1);
if (!status) {
Log(0,"GetQueuedCompletionStatus error: %x\n",GetLastError());
VirtualFree(buffer,
BufferSize + SectorSize - 1,
MEM_DECOMMIT);
return FALSE;
}
}
end = GetTickCount();
testTime = end - start;
testTime /= 1000.0;
seconds += testTime;
Log(1,"Iteration %2d -> %4.3f MB/S\n",Iterations - remaining,(FileSize / testTime)/(1024*1024));
}
CloseHandle(port);
CloseHandle(file);
thruPut = FileSize * Iterations / seconds;
printf("\nAverage Throughput %4.3f MB/S\n",thruPut/(1024*1024));
Log(2,"Min = %Lu, Max = %Lu, FileSize = %Lu\n",min,max,FileSize);
VirtualFree(buffer,
BufferSize + SectorSize - 1,
MEM_DECOMMIT);
return TRUE;
}
BOOLEAN
WriteSequential(
ULONG Iterations
)
{
ULONG j,
outstandingRequests,
remaining = Iterations;
ULONG start,end;
DOUBLE testTime,thruPut = 0.0,seconds = 0;
HANDLE file,
port;
OVERLAPPED overlapped,
*overlapped2;
DWORD bytesWritten,
bytesWritten2,
errCode,
version;
DWORD_PTR completionKey;
BOOL status;
PUCHAR buffer;
if(ReadOnly) {
printf("Can't run write tests on a read only file\n");
return FALSE;
}
printf("Starting Sequential Writes of %d Meg file, using %d K I/O size\n", FileSize / 1024*1024, BufferSize / 1024);
version = GetVersion() >> 16;
buffer = VirtualAlloc(NULL,
BufferSize + SectorSize - 1,
MEM_COMMIT | MEM_RESERVE,
PAGE_READWRITE);
(ULONG_PTR)buffer &= ~((ULONG_PTR)SectorSize - 1);
if ( !buffer ) {
Log(0,"Error allocating buffer: %x\n",GetLastError());
return FALSE;
}
file = CreateFile(FileName,
GENERIC_READ | GENERIC_WRITE,
0,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED | FILE_FLAG_NO_BUFFERING,
NULL );
if ( file == INVALID_HANDLE_VALUE ) {
Log(0,"Error opening Target file: %x\n",GetLastError());
VirtualFree(buffer,
BufferSize + SectorSize - 1,
MEM_DECOMMIT);
return FALSE;
}
port = CreateIoCompletionPort(file,
NULL,
(DWORD_PTR)file,
0);
if ( !port ) {
Log(0,"Error creating completion port: %x\n",GetLastError());
VirtualFree(buffer,
BufferSize + SectorSize - 1,
MEM_DECOMMIT);
return FALSE;
}
while (remaining--) {
start = GetTickCount();
memset(&overlapped,0,sizeof(overlapped));
outstandingRequests = 0;
for (j = 0; j < FileSize / BufferSize; j++) {
do {
status = WriteFile(file,
buffer,
BufferSize,
&bytesWritten,
&overlapped);
errCode = GetLastError();
if (!status) {
if (errCode == ERROR_IO_PENDING) {
break;
} else if (errCode == ERROR_NOT_ENOUGH_QUOTA ||
errCode == ERROR_INVALID_USER_BUFFER ||
errCode == ERROR_WORKING_SET_QUOTA ||
errCode == ERROR_NOT_ENOUGH_MEMORY) {
//
// Allow this to retry.
//
} else {
Log(0,"Error in WriteFile: %x\n",errCode);
VirtualFree(buffer,
BufferSize + SectorSize - 1,
MEM_DECOMMIT);
return FALSE;
}
}
} while (!status);
outstandingRequests++;
overlapped.Offset += BufferSize;
}
for (j = 0; j < outstandingRequests; j++) {
status = GetQueuedCompletionStatus(port,
&bytesWritten2,
&completionKey,
&overlapped2,
(DWORD)-1);
if (!status) {
Log(0,"GetQueuedCompletionStatus error: %x\n",GetLastError());
VirtualFree(buffer,
BufferSize + SectorSize - 1,
MEM_DECOMMIT);
return FALSE;
}
}
end = GetTickCount();
testTime = end - start;
testTime /= 1000.0;
seconds += testTime;
Log(1,"Iteration %2d -> %4.3f MB/S\n",Iterations - remaining,(FileSize / testTime)/(1024*1024));
}
CloseHandle(port);
CloseHandle(file);
thruPut = FileSize * Iterations / seconds;
printf("\nAverage Throughput %4.3f MB/S\n",thruPut/(1024*1024));
VirtualFree(buffer,
BufferSize + SectorSize - 1,
MEM_DECOMMIT);
return TRUE;
}
BOOLEAN
WriteRandom(
ULONG Iterations
)
{
ULONG j,
outstandingRequests,
remaining = Iterations;
ULONG start,end;
DOUBLE testTime,thruPut = 0.0,seconds = 0;
HANDLE file,
port;
OVERLAPPED overlapped,
*overlapped2;
DWORD bytesWritten,
bytesWritten2,
errCode,
version;
DWORD_PTR completionKey;
BOOL status;
PUCHAR buffer;
ULONG min = FileSize,max = 0;
if(ReadOnly) {
printf("Can't run write tests on a read only file\n");
return FALSE;
}
printf("Starting Random Writes of %d Meg file, using %d K I/O size\n", FileSize / 1024*1024, BufferSize / 1024);
version = GetVersion() >> 16;
buffer = VirtualAlloc(NULL,
BufferSize + SectorSize - 1,
MEM_COMMIT | MEM_RESERVE,
PAGE_READWRITE);
(ULONG_PTR)buffer &= ~((ULONG_PTR)SectorSize - 1);
if ( !buffer ) {
Log(0,"Error allocating buffer: %x\n",GetLastError());
return FALSE;
}
file = CreateFile(FileName,
GENERIC_READ | GENERIC_WRITE,
0,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED | FILE_FLAG_NO_BUFFERING,
NULL );
if ( file == INVALID_HANDLE_VALUE ) {
Log(0,"Error opening Target file: %x\n",GetLastError());
VirtualFree(buffer,
BufferSize + SectorSize - 1,
MEM_DECOMMIT);
return FALSE;
}
port = CreateIoCompletionPort(file,
NULL,
(DWORD_PTR)file,
0);
if ( !port ) {
Log(0,"Error creating completion port: %x\n",GetLastError());
VirtualFree(buffer,
BufferSize + SectorSize - 1,
MEM_DECOMMIT);
return FALSE;
}
while (remaining--) {
start = GetTickCount();
memset(&overlapped,0,sizeof(overlapped));
outstandingRequests = 0;
for (j = 0; j < FileSize / BufferSize; j++) {
do {
status = WriteFile(file,
buffer,
BufferSize,
&bytesWritten,
&overlapped);
errCode = GetLastError();
if (!status) {
if (errCode == ERROR_IO_PENDING) {
break;
} else if (errCode == ERROR_NOT_ENOUGH_QUOTA ||
errCode == ERROR_INVALID_USER_BUFFER ||
errCode == ERROR_WORKING_SET_QUOTA ||
errCode == ERROR_NOT_ENOUGH_MEMORY) {
//
// Allow this to retry.
//
} else {
Log(0,"Error in WriteFile: %x\n",errCode);
VirtualFree(buffer,
BufferSize + SectorSize - 1,
MEM_DECOMMIT);
return FALSE;
}
}
} while (!status);
outstandingRequests++;
overlapped.Offset = GetRandomOffset(0,FileSize - BufferSize);
if (overlapped.Offset > max) {
max = overlapped.Offset;
}
if (overlapped.Offset < min) {
min = overlapped.Offset;
}
}
for (j = 0; j < outstandingRequests; j++) {
status = GetQueuedCompletionStatus(port,
&bytesWritten2,
&completionKey,
&overlapped2,
(DWORD)-1);
if (!status) {
Log(0,"GetQueuedCompletionStatus error: %x\n",GetLastError());
VirtualFree(buffer,
BufferSize + SectorSize - 1,
MEM_DECOMMIT);
return FALSE;
}
}
end = GetTickCount();
testTime = end - start;
testTime /= 1000.0;
seconds += testTime;
Log(1,"Iteration %2d -> %4.3f MB/S\n",Iterations - remaining,(FileSize / testTime)/(1024*1024));
}
CloseHandle(port);
CloseHandle(file);
thruPut = FileSize * Iterations / seconds;
printf("\nAverage Throughput %4.3f MB/S\n",thruPut/(1024*1024));
Log(2,"Min = %Lu, Max = %Lu, FileSize = %Lu\n",min,max,FileSize);
VirtualFree(buffer,
BufferSize + SectorSize - 1,
MEM_DECOMMIT);
return TRUE;
}
ULONG
GetRandomOffset(
ULONG min,
ULONG max
)
{
INT base = rand();
ULONG retval = ((max - min) / RAND_MAX) * base;
retval += SectorSize - 1;
retval &= ~(SectorSize - 1);
if (retval < min) {
return min;
} else if (retval > max ){
return max & ~(SectorSize - 1);
} else{
return retval;
}
}
BOOLEAN
ParseCmdLine(
INT Argc,
CHAR *Argv[]
)
{
INT i;
CHAR *switches = " ,-";
CHAR swtch,*value,*str;
BOOLEAN gotSwitch = FALSE;
if (Argc <= 1) {
//
// Using defaults
//
return TRUE;
}
for (i = 1; i < Argc; i++) {
str = Argv[i];
value = strtok(str, switches);
if (gotSwitch) {
if (!ValidateOption(swtch,value)) {
Usage();
return FALSE;
} else {
gotSwitch = FALSE;
}
} else {
gotSwitch = TRUE;
swtch = value[0];
if (value[1] || swtch == '?') {
Usage();
return FALSE;
}
}
}
if (gotSwitch) {
Usage();
return FALSE;
} else {
return TRUE;
}
}
BOOLEAN
ValidateOption(
CHAR Switch,
CHAR *Value
)
{
Switch = (CHAR)toupper(Switch);
switch (Switch) {
case 'F':
VerifyFileName(Value);
strcpy(FileName,Value);
break;
case 'T':
if (_stricmp(Value,"READ")==0) {
Test = READ;
} else if (_stricmp(Value,"WRITE")==0) {
Test = WRITE;
} else {
return FALSE;
}
break;
case 'A':
if (_strnicmp(Value,"SEQ",3)==0) {
Access = SEQ;
} else if (_strnicmp(Value,"RAND",4)==0) {
Access = RAND;
} else {
return FALSE;
}
break;
case 'B':
BufferSize = atol(Value);
//
// TODO:Adjust buffersize to multiple of a sector and #of K.
//
BufferSize *= 1024;
break;
case 'S':
FileSize = atol(Value);
//
// TODO: Adjust filesize to multiple of buffersize and #of Meg.
//
FileSize *= 1024*1024;
break;
case 'V':
Verbose = atol(Value);
break;
case 'I':
Iterations = atol(Value);
break;
case 'R':
if(tolower(Value[0]) == 'y') {
ReuseFile = TRUE;
} else {
ReuseFile = FALSE;
}
break;
case 'O':
if(tolower(Value[0]) == 'y') {
ReadOnly = TRUE;
} else {
ReadOnly = FALSE;
}
break;
default:
return FALSE;
}
return TRUE;
}
VOID
Usage(
VOID
)
{
fprintf(stderr,"usage: YAPT (Yet another performance tool)\n"
" -f [filename]\n"
" -t [Test:Read,Write]\n"
" -a [Access Mode:Seq or Random]\n"
" -b [buffer size in KB]\n"
" -s [filesize]\n"
" -i [Iterations]\n"
" -v [Verbosity: 0-2]\n"
" -r [Reuse test file: yes, no]\n"
" -o [Read Only: yes, no]\n"
);
}
VOID
__cdecl
Log(
ULONG LogLevel,
PCHAR String,
...
)
{
CHAR Buffer[256];
va_list argp;
va_start(argp, String);
if (LogLevel <= Verbose) {
vsprintf(Buffer, String, argp);
printf("%s",Buffer);
}
va_end(argp);
}
DWORD
YaptSetFileCompression(
IN HANDLE FileHandle,
IN USHORT CompressionFormat
)
{
DWORD bytesReturned;
assert(FileHandle != INVALID_HANDLE_VALUE);
if(!DeviceIoControl(
FileHandle,
FSCTL_SET_COMPRESSION,
&CompressionFormat,
sizeof(CompressionFormat),
NULL,
0,
&bytesReturned,
NULL)) {
}
return GetLastError();
}
VOID
VerifyFileName(
IN CHAR *FileName
)
{
CHAR input[32];
if(Yes) return;
if(((FileName[0] == '\\') || (FileName[0] == '/')) &&
((FileName[1] == '\\') || (FileName[1] == '/')) &&
((FileName[2] == '.') || (FileName[2] == '?')) &&
((FileName[3] == '\\') || (FileName[3] == '/'))) {
printf("\n\t%s looks like a raw device\n"
"\tdo you want to continue? ", FileName);
fflush(stdout);
if(fgets(input, 32, stdin) == NULL) {
printf("\nQuitting\n");
exit(-1);
}
if(tolower(input[0]) != 'y') {
printf("\nNegative response - quitting\n");
exit(-1);
}
}
return;
}