|
|
/*++
Copyright (c) 1995 Microsoft Corporation
Module Name:
cpdata.h
Abstract:
cp data internal data structures
Author:
08-Apr-1998 mraghu
Revision History:
--*/
#ifndef __CPDATA__
#define __CPDATA__
#include <stdlib.h>
#include <stdio.h>
#include <nt.h>
#pragma warning (disable:4306)
#include <ntrtl.h>
#include <nturtl.h>
#pragma warning (default:4306)
#include <windows.h>
#include <shellapi.h>
#include <tchar.h>
#include <wmistr.h>
#include <wtypes.h>
#pragma warning (disable:4201)
#include <wmistr.h>
#include <tchar.h>
#include <objbase.h>
#include <initguid.h>
#include <wmium.h>
#include <ntwmi.h>
#include <wmiumkm.h>
#include <wmiguid.h>
#include <evntrace.h>
#pragma warning (default:4201)
#include "list.h"
#include "workload.h"
#define MAX_FILE_TABLE_SIZE 64 // Must match ntos\wmi\callout.c
#define MAX_TRANS_LEVEL 32
#ifndef IsEqualGUID
#define IsEqualGUID(guid1, guid2) \
(!memcmp((guid1), (guid2), sizeof(GUID))) #endif
#define THREAD_HASH_TABLESIZE 29
#define MAXSTR 1024
#define CHECK_HR(hr) if( ERROR_SUCCESS != hr ){ goto cleanup; }
typedef struct _TRACE_CONTEXT_BLOCK { PEVENT_TRACE_PROPERTIES LoggerInfo; ULONG LogFileCount; ULONG LoggerCount; LPWSTR LogFileName[MAXLOGGERS]; LPWSTR LoggerName[MAXLOGGERS]; LPCSTR PdhFileName; // ANSI ??
LPWSTR ProcFileName; LPWSTR DumpFileName; LPWSTR MofFileName; LPWSTR MergeFileName; LPWSTR SummaryFileName; LPWSTR CompFileName; HANDLE hEvent; FILE* hDumpFile; ULONGLONG StartTime; // If Sequential, start, End Times to window.
ULONGLONG EndTime; //
ULONG Flags; BOOLEAN LoggerStartedHere; HANDLE hThreadVector; TRACEHANDLE HandleArray[MAXLOGGERS]; PVOID pUserContext; } TRACE_CONTEXT_BLOCK, *PTRACE_CONTEXT_BLOCK;
typedef struct _HPF_FILE_RECORD { LIST_ENTRY Entry; ULONG RecordID; ULONG IrpFlags; ULONG DiskNumber; ULONG BytesCount; ULONGLONG ByteOffset; PVOID fDO; } HPF_FILE_RECORD, *PHPF_FILE_RECORD;
typedef struct _HPF_RECORD { LIST_ENTRY Entry; ULONG RecordID; ULONG lProgramCounter; ULONG lFaultAddress; PVOID fDO; LONG lByteCount; LONGLONG lByteOffset; LIST_ENTRY HPFReadListHead; } HPF_RECORD, *PHPF_RECORD;
typedef struct _TDISK_RECORD { LIST_ENTRY Entry; ULONG DiskNumber; LPWSTR DiskName; ULONG ReadCount; ULONG WriteCount; ULONG ReadSize; ULONG WriteSize; ULONG HPF; ULONG HPFSize; LIST_ENTRY FileListHead; LIST_ENTRY ProcessListHead; } TDISK_RECORD, *PTDISK_RECORD;
typedef struct _FILE_RECORD { LIST_ENTRY Entry; LIST_ENTRY ProtoProcessListHead; // List of Processes touching this file.
PWCHAR FileName; ULONG DiskNumber; ULONG ReadCount; ULONG HPF; ULONG WriteCount; ULONG ReadSize; ULONG WriteSize; ULONG HPFSize; } FILE_RECORD, *PFILE_RECORD;
typedef struct _FILE_OBJECT { PVOID fDO; PFILE_RECORD fileRec; LIST_ENTRY ProtoFileRecordListHead; }FILE_OBJECT, *PFILE_OBJECT;
typedef struct _PROTO_FILE_RECORD { LIST_ENTRY Entry; BOOLEAN ReadFlag; ULONG DiskNumber; ULONG IoSize; } PROTO_FILE_RECORD, *PPROTO_FILE_RECORD;
typedef struct _TRANS_RECORD { LIST_ENTRY Entry; LIST_ENTRY SubTransListHead; LPGUID pGuid; BOOL bStarted; ULONG UCpu; ULONG KCpu; ULONG DeltaReadIO; ULONG DeltaWriteIO; ULONG RefCount; ULONG RefCount1; } TRANS_RECORD, *PTRANS_RECORD;
typedef struct _PROCESS_RECORD { LIST_ENTRY Entry; LIST_ENTRY ThreadListHead; LIST_ENTRY DiskListHead; LIST_ENTRY FileListHead; // All the Files this process touched.
LIST_ENTRY ModuleListHead; // All the modules this process loaded.
LIST_ENTRY HPFListHead; PWCHAR UserName; PWCHAR ImageName; ULONG PID; ULONG DeadFlag; ULONG ReadIO; ULONG WriteIO; ULONG SendCount; ULONG RecvCount; ULONG SendSize; ULONG RecvSize; ULONG HPF; ULONG HPFSize; ULONG SPF; ULONG PrivateWSet; ULONG GlobalWSet; ULONG ReadIOSize; ULONG WriteIOSize; ULONG lDataFaultHF; ULONG lDataFaultTF; ULONG lDataFaultDZF; ULONG lDataFaultCOW; ULONG lCodeFaultHF; ULONG lCodeFaultTF; ULONG lCodeFaultDZF; ULONG lCodeFaultCOW; ULONGLONG ResponseTime; ULONGLONG TxnStartTime; ULONGLONG TxnEndTime; } PROCESS_RECORD, *PPROCESS_RECORD;
typedef struct _THREAD_RECORD { LIST_ENTRY Entry; LIST_ENTRY DiskListHead; LIST_ENTRY TransListHead; // transactions list
LIST_ENTRY HPFReadListHead; LIST_ENTRY HPFWriteListHead; WCHAR strSortKey[MAXSTR]; ULONG TID; PPROCESS_RECORD pProcess; BOOLEAN fOrphan; ULONG DeadFlag; ULONG ProcessorID; ULONG ClassNumber; // Class to which this thread is assigned.
ULONG ReadIO; ULONG WriteIO; ULONG SendCount; ULONG RecvCount; ULONG SendSize; ULONG RecvSize; ULONG HPF; ULONG SPF; ULONG ReadIOSize; ULONG WriteIOSize; ULONG HPFSize;
ULONGLONG TimeStart; ULONGLONG TimeEnd; ULONG KCPUStart; ULONG KCPUEnd; ULONG UCPUStart; ULONG UCPUEnd;
// The Following fields are used in getting the Delta
// CPU, I/O to charge on a transaction basis.
// The Current Transaction being executed by this thread is
// given by pMofInfo and when the trans is completed the Delta CPU, I/O
// are charged to that transaction.
ULONG DeltaReadIO; ULONG DeltaWriteIO; ULONG DeltaSend; ULONG DeltaRecv; ULONG RefCount; ULONG JobId; // Keeps track of the Current Job this thread is working on
PVOID pMofData; // Keep Track of the Current transaction Guid
ULONG KCPU_Trans; ULONG UCPU_Trans; ULONG KCPU_NoTrans; ULONG UCPU_NoTrans; ULONG KCPU_PrevTrans; ULONG UCPU_PrevTrans; LONG TransLevel;
ULONG KCPU_PrevEvent; ULONG UCPU_PrevEvent; ULONGLONG Time_PrevEvent;
PTRANS_RECORD TransStack[MAX_TRANS_LEVEL];
}THREAD_RECORD, *PTHREAD_RECORD;
typedef struct _MODULE_RECORD MODULE_RECORD, *PMODULE_RECORD; struct _MODULE_RECORD { LIST_ENTRY Entry; PPROCESS_RECORD pProcess; ULONG lBaseAddress; ULONG lModuleSize; ULONG lDataFaultHF; ULONG lDataFaultTF; ULONG lDataFaultDZF; ULONG lDataFaultCOW; ULONG lCodeFaultHF; ULONG lCodeFaultTF; ULONG lCodeFaultDZF; ULONG lCodeFaultCOW; WCHAR * strModuleName; PMODULE_RECORD pGlobalPtr; };
typedef struct _SYSTEM_RECORD { ULONGLONG StartTime; ULONGLONG EndTime; FILE* TempFile; BOOLEAN fNoEndTime; ULONG CurrentThread0; ULONG ElapseTime; ULONG TimerResolution; ULONG NumberOfEvents; ULONG NumberOfProcessors; ULONG NumberOfWorkloads; ULONG BuildNumber; PFILE_OBJECT *FileTable; PLIST_ENTRY ThreadHashList; LIST_ENTRY ProcessListHead; LIST_ENTRY GlobalThreadListHead; LIST_ENTRY GlobalDiskListHead; LIST_ENTRY HotFileListHead; LIST_ENTRY WorkloadListHead; LIST_ENTRY InstanceListHead; LIST_ENTRY EventListHead; LIST_ENTRY GlobalModuleListHead; // Global module list.
LIST_ENTRY ProcessFileListHead; LIST_ENTRY JobListHead; HANDLE hLoggerUpEvent; } SYSTEM_RECORD, *PSYSTEM_RECORD;
typedef struct _PROCESS_FILE_RECORD { LIST_ENTRY Entry; ULONGLONG StartTime; ULONGLONG EndTime; LPWSTR FileName; LPWSTR TraceName; } PROCESS_FILE_RECORD, *PPROCESS_FILE_RECORD;
typedef struct _PROTO_PROCESS_RECORD { LIST_ENTRY Entry; PPROCESS_RECORD ProcessRecord; ULONG ReadCount; ULONG WriteCount; ULONG HPF; ULONG ReadSize; ULONG WriteSize; ULONG HPFSize; }PROTO_PROCESS_RECORD, *PPROTO_PROCESS_RECORD;
//
// MOF_INFO structure maintains the global information for the GUID.
// For each GUID, the event layouts are maintained by Version, Level and Type.
//
typedef struct _MOF_INFO { LIST_ENTRY Entry; LIST_ENTRY DataListHead; LPWSTR strDescription; // Class Name
LPWSTR strSortField; ULONG EventCount; GUID Guid; LIST_ENTRY VersionHeader; BOOL bKernelEvent; } MOF_INFO, *PMOF_INFO;
//
// MOF_VERSION structure ic created one per Version, Level Type combination.
//
typedef struct _MOF_VERSION { LIST_ENTRY Entry; LIST_ENTRY ItemHeader; // Maintains the list of ITEM_DESC for this type.
LPWSTR strType; SHORT Version; SHORT TypeIndex; CHAR Level; ULONG EventCountByType; // Count of Events by this type for this Guid
} MOF_VERSION, *PMOF_VERSION;
typedef struct _MOF_DATA { LIST_ENTRY Entry; PWCHAR strSortKey; ULONG CompleteCount; LONG InProgressCount; LONGLONG AverageResponseTime; LONGLONG TotalResponseTime; ULONGLONG PrevClockTime; ULONG MmTf; ULONG MmDzf; ULONG MmCow; ULONG MmGpf; ULONG UserCPU; ULONG KernelCPU; ULONG EventCount; ULONG ReadCount; ULONG WriteCount; ULONG SendCount; ULONG RecvCount; LONG MinKCpu; LONG MaxKCpu; LONG MinUCpu; LONG MaxUCpu; } MOF_DATA, *PMOF_DATA;
// A Job record is one that passses through several threads to complete.
// Jobs are identified by a Job Id, usually created during the Start
// event and recorded as an additional field in the mof data.
// Since there can be any number of jobs in the system over the data
// collection interval, we will flush the completed jobs to a temp file
// and reread it back at the end to print a report.
// Note: Job_record needs to be Guid based. (ie., per type of transaction).
// Currently it is not.
//
#define MAX_THREADS 10 // Upto threads can be working on a Job.
typedef struct _THREAD_DATA { ULONG ThreadId; ULONG PrevKCPUTime; ULONG PrevUCPUTime; ULONG PrevReadIO; ULONG PrevWriteIO; ULONG KCPUTime; ULONG UCPUTime; ULONG ReadIO; ULONG WriteIO; ULONG Reserved; } THREAD_DATA, *PTHREAD_DATA;
typedef struct _JOB_RECORD { LIST_ENTRY Entry; ULONG JobId; ULONG KCPUTime; ULONG UCPUTime; ULONG ReadIO; ULONG WriteIO; ULONG DataType; ULONG JobSize; ULONG Pages; ULONG PagesPerSide; ULONG ICMMethod; ULONG GdiJobSize; ULONGLONG StartTime; ULONGLONG EndTime; ULONGLONG ResponseTime; ULONGLONG PauseTime; ULONGLONG PauseStartTime; ULONGLONG PrintJobTime; SHORT FilesOpened; SHORT Color; SHORT XRes; SHORT YRes; SHORT Quality; SHORT Copies; SHORT TTOption; ULONG NumberOfThreads; // Total Number of Threads worked on this Job
THREAD_DATA ThreadData[MAX_THREADS]; } JOB_RECORD, *PJOB_RECORD;
//
// Global that holds everything about the current session
//
extern SYSTEM_RECORD CurrentSystem; extern BOOLEAN fDSOnly; extern ULONGLONG DSStartTime; extern ULONGLONG DSEndTime;
extern RTL_CRITICAL_SECTION TLCritSect; #define EnterTracelibCritSection() RtlEnterCriticalSection(&TLCritSect)
#define LeaveTracelibCritSection() RtlLeaveCriticalSection(&TLCritSect)
//
// Initialization Routines.
//
VOID InitDiskRecord( PTDISK_RECORD pDisk, ULONG DiskNumber );
VOID InitMofData( PMOF_DATA pMofData );
VOID InitThreadRecord( PTHREAD_RECORD pThread );
VOID InitTransRecord( PTRANS_RECORD pThread );
VOID InitProcessRecord( PPROCESS_RECORD pProcess );
VOID InitFileRecord( PFILE_RECORD pFile );
//
// Add, Delete and Find routines
BOOLEAN AddModuleRecord( PMODULE_RECORD * pModule, ULONG lBaseAddress, ULONG lModuleSize, WCHAR * strModuleName );
BOOLEAN AddHPFFileRecord( PHPF_FILE_RECORD * ppHPFFileRecord, ULONG RecordID, ULONG IrpFlags, ULONG DiskNumber, ULONGLONG ByteOffset, ULONG BytesCount, PVOID fDO );
BOOLEAN AddHPFRecord( PHPF_RECORD * ppHPFRRecord, ULONG lFaultAddress, PVOID fDO, LONG ByteCount, LONGLONG ByteOffset );
void DeleteHPFRecord( PHPF_RECORD pHPFRecord );
BOOLEAN AddProcess( ULONG ProcessId, PPROCESS_RECORD *Process );
BOOLEAN DeleteTrans( PTRANS_RECORD Trans );
BOOLEAN DeleteTransList( PLIST_ENTRY Head, ULONG level );
PTRANS_RECORD FindTransByList( PLIST_ENTRY Head, LPGUID pGuid, ULONG level );
PMOF_DATA FindMofData( PMOF_INFO pMofInfo, PWCHAR strSortKey );
BOOLEAN DeleteProcess( PPROCESS_RECORD Process );
BOOLEAN AddThread( ULONG ThreadId, PEVENT_TRACE pEvent, PTHREAD_RECORD * Thread );
BOOLEAN DeleteThread( PTHREAD_RECORD Thread );
BOOLEAN AddFile( WCHAR* fileName, PFILE_RECORD *ReturnedFile );
BOOLEAN DeleteFileRecord( PFILE_RECORD fileRec );
BOOLEAN DeleteFileObject( PFILE_OBJECT fileObj );
PPROCESS_RECORD FindProcessById( ULONG Id, BOOLEAN CheckAlive );
PTDISK_RECORD FindLocalDiskById( PLIST_ENTRY Head, ULONG DiskNumber ); PTDISK_RECORD FindProcessDiskById( PPROCESS_RECORD pProcess, ULONG DiskNumber );
PFILE_RECORD FindFileInProcess( PPROCESS_RECORD pProcess, WCHAR* Name ); PPROTO_PROCESS_RECORD FindProtoProcessRecord( PFILE_RECORD pFile, PPROCESS_RECORD pProcess );
PFILE_RECORD FindFileRecordByName( WCHAR* Name );
PTHREAD_RECORD FindGlobalThreadById( ULONG ThreadId, PEVENT_TRACE pEvent );
PTDISK_RECORD FindGlobalDiskById( ULONG Id );
PPROCESS_RECORD FindDiskProcessById( PTDISK_RECORD Disk, ULONG Id );
ULONGLONG CalculateProcessLifeTime(PPROCESS_RECORD pProcess); ULONG CalculateProcessKCPU(PPROCESS_RECORD pProcess); ULONG CalculateProcessUCPU(PPROCESS_RECORD pProcess);
VOID Cleanup();
BOOLEAN AddDisk( ULONG DiskNumber, PTDISK_RECORD *ReturnedDisk );
BOOLEAN DeleteDisk( PTDISK_RECORD Disk );
ULONG DeleteJobRecord( PJOB_RECORD pJob, ULONG bSave ); PJOB_RECORD AddJobRecord( ULONG JobId ); PJOB_RECORD FindJobRecord( ULONG JobId );
int EtwRelogEtl( PTRACE_CONTEXT_BLOCK TraceContext );
//
// Trace Event Callbacks
//
VOID ShutdownThreads(); // Shuts down the running threads before finishing
VOID ShutdownProcesses(); // Shuts down the running processes before finishing
ULONG GetMofData( PEVENT_TRACE pEvent, WCHAR *strName, PVOID ReturnValue, ULONG ReturnLength );
VOID GeneralEventCallback(PEVENT_TRACE pEvent); VOID DeclareKernelEvents();
VOID ProcessCallback( PEVENT_TRACE pEvent ); VOID PsStartCallback( PEVENT_TRACE pEvent ); VOID PsEndCallback( PEVENT_TRACE pEvent ); VOID ThreadCallback( PEVENT_TRACE pEvent ); VOID ThStartCallback( PEVENT_TRACE pEvent ); VOID ThEndCallback( PEVENT_TRACE pEvent ); VOID DiskIoCallback( PEVENT_TRACE pEvent, PTHREAD_RECORD pThread ); VOID IoReadCallback( PEVENT_TRACE pEvent, PTHREAD_RECORD pThread ); VOID IoWriteCallback( PEVENT_TRACE pEvent, PTHREAD_RECORD pThread ); VOID HotFileCallback( PEVENT_TRACE pEvent ); VOID LogHeaderCallback( PEVENT_TRACE pEvent ); VOID EventCallback( PEVENT_TRACE pEvent, PTHREAD_RECORD pThread );
VOID AddEvent( IN PFILE_OBJECT fileObject, IN ULONG DiskNumber, IN ULONG IoSize, IN BOOLEAN ReadFlag);
PFILE_OBJECT FindFileInTable ( IN PVOID fDO );
//VOID
//ProcessPdh(
// IN LPCSTR LogFileName,
// IN ULONGLONG StartTime,
// IN ULONGLONG EndTime
// );
//
// Workload Classification Routines
//
VOID Classify();
VOID Aggregate();
VOID InitClass();
VOID AssignClass( IN PPROCESS_RECORD pProcess, IN PTHREAD_RECORD pThread );
ULONG ProcessRunDown();
PMOF_INFO GetMofInfoHead( LPCGUID pGuid );
void WriteSummary();
#define IsEmpty( string ) ((BOOL)( (NULL != string) && ( L'\0' != string[0]) ))
#define ASSIGN_STRING( dest, src ) \
if( NULL != src ){ \ dest = (LPWSTR)malloc( (wcslen(src)+1)*sizeof(WCHAR) ); \ if( NULL != dest ){ \ wcscpy( dest, src ); \ } \ } \
#endif // __CPDATA__
|