TOP

{--------------------------------------------------------------------

Author: J.M.Wehlou

Description:

    Data definitions for performance monitoring. Used both by
    the client application monitoring class as by the performance
    monitoring DLL.

--------------------------------------------------------------------}


unit PerfMonClientDef;

interface

uses
  PerfMonClientDefIf;

type
  { Ordinal values must start at zero. All counters in the entire
    application must be enumerated here. }

  pmcCounter = (
    pmcRawCounter,
    pmcDeltaCounter
  );

function getPerfMonClientDef(): IPerfMonClientDef;

// ==================================================================

implementation

uses
  SysUtils,
  Windows,
  WinPerf;

type
  TPerfMonClientDef = class(TInterfacedObject, IPerfMonClientDef)
  private
    function FileNameInModPath(const sFileName: string): string;
  public
    function DLLPath: String;
    function DriverName: String;
    function FuncName_Close: String;
    function FuncName_Collect: String;
    function FuncName_Open: String;
    function MainHelp: String;
    function MainName: String;
    function MemMappedFileName: String;
    function NbOfObjects: Integer;
    function ObjectHelp(iNb: Integer): String;
    function ObjectName(iNb: Integer): String;
    function ObjectScale(iNb: integer): integer;
    function ObjectCounterType(iNb: integer): cardinal;

    function TotalSize: Cardinal;
    function ServiceKey(): string;
    function _AddRef(): integer; stdcall;
    function _Release(): integer; stdcall;
  end;

const
{ the drivername should be equal to the apps filename, since
  it will correspond to the registry key for performance counting
  Note that it should not change dynamically in runtime, since if the
  user changes the apps name, it wouldn't find the perfmon registry entries
  anymore. }
  cDRIVERNAME = 'PerfMonClient';
  cFUNCNAMEOPEN = 'PerfData_Open';
  cFUNCNAMECLOSE = 'PerfData_Close';
  cFUNCNAMECOLLECT = 'PerfData_Collect';
  cDLLNAME = 'PerfMonDLL.dll';
  cMAINNAME = 'PerfMonTest Performance Counters';
  cMAINHELP = 'A demo application for your unbridled pleasure';
  cMEMMAPPEDFILENAME = 'PerfMon_PerfMonTest';

type
  // this implementation assumes nothing but cardinals as counters
  PerfMonDefRec = record
    title   : string;
    help    : string;
    scale   : integer;
    cnttype : cardinal;
  end;

var
  PerfMonDef : array[Low(pmcCounter)..High(pmcCounter)] of PerfMonDefRec = (
    (
      Title   : 'RawCount';
      Help    : 'A count of something that goes up and down';
      Scale   : 0; // scale to 1
      CntType : PERF_COUNTER_RAWCOUNT;
    ),(
      Title   : 'DeltaCount';
      Help    : 'Something going up all the time, Windows shows difference per time unit';
      Scale   : -1; // scale to 0.1
      CntType : PERF_COUNTER_COUNTER;
    )
  );

var
  gPMCD : TPerfMonClientDef = nil;

// ==================================================================

function getPerfMonClientDef(): IPerfMonClientDef;
begin
  if not assigned(gPMCD) then
    gPMCD := TPerfMonClientDef.Create();
  Result := gPMCD;
end;

// ==================================================================
{ TPerfMonClientDef }


function TPerfMonClientDef._AddRef: integer;
begin
  Result := -1;
end;

// ------------------------------------------------------------------

function TPerfMonClientDef._Release: integer;
begin
  Result := -1;
end;

// ------------------------------------------------------------------

function TPerfMonClientDef.DLLPath: String;
begin
  Result := FileNameInModPath(cDLLNAME);
end;

// ------------------------------------------------------------------

function TPerfMonClientDef.DriverName: String;
begin
  Result := cDRIVERNAME;
end;

// ------------------------------------------------------------------

function TPerfMonClientDef.FuncName_Close: String;
begin
  Result := cFUNCNAMECLOSE;
end;

// ------------------------------------------------------------------

function TPerfMonClientDef.FuncName_Collect: String;
begin
  Result := cFUNCNAMECOLLECT;
end;

// ------------------------------------------------------------------

function TPerfMonClientDef.FuncName_Open: String;
begin
  Result := cFUNCNAMEOPEN;
end;

// ------------------------------------------------------------------

function TPerfMonClientDef.MainHelp: String;
begin
  Result := cMAINHELP;
end;

// ------------------------------------------------------------------

function TPerfMonClientDef.MainName: String;
begin
  Result := cMAINNAME;
end;

// ------------------------------------------------------------------

function TPerfMonClientDef.MemMappedFileName: String;
begin
  Result := cMEMMAPPEDFILENAME;
end;

// ------------------------------------------------------------------

function TPerfMonClientDef.NbOfObjects: Integer;
begin
  Result := Ord(High(pmcCounter)) - Ord(Low(pmcCounter)) + 1;
end;

// ------------------------------------------------------------------

function TPerfMonClientDef.ObjectHelp(iNb: Integer): String;
begin
  Result := PerfMonDef[pmcCounter(iNb)].help;
end;

// ------------------------------------------------------------------

function TPerfMonClientDef.ObjectName(iNb: Integer): String;
begin
  Result := PerfMonDef[pmcCounter(iNb)].title;
end;

// ------------------------------------------------------------------

function TPerfMonClientDef.ObjectScale(iNb: integer): integer;
begin
  Result := PerfMonDef[pmcCounter(iNb)].scale;
end;

// ------------------------------------------------------------------

function TPerfMonClientDef.ObjectCounterType(iNb: integer): cardinal;
begin
  Result := PerfMonDef[pmcCounter(iNb)].cnttype;
end;

// ------------------------------------------------------------------

function TPerfMonClientDef.TotalSize: Cardinal;
begin
  Result := NbOfObjects * sizeof(cardinal);
end;

// ------------------------------------------------------------------

function TPerfMonClientDef.ServiceKey: string;
begin
  Result := '\SYSTEM\CurrentControlSet\Services\' + cDRIVERNAME;
end;

// ------------------------------------------------------------------

{ Constructs a fully qualified path consisting of the path to the
  executable with the filename as given in the parameter. This function
  should be part of your libraries, but since I didn't want to complicate
  this demo project with a lot of library units, this function is repeated
  in this unit and in PerfMonLib.pas. }

function TPerfMonClientDef.FileNameInModPath(const sFileName: string): string;
begin
  SetLength(Result , MAX_PATH);
  SetLength(Result, GetModuleFileName(0, PChar(Result), MAX_PATH));
  Result := ExtractFileDir(Result);
  Result := IncludeTrailingPathDelimiter(Result) + sFileName;
end;



// ==================================================================

initialization

finalization
  gPMCD.Free;

end.