dxcachedlogging.pas
来自「Well known and usefull component for del」· PAS 代码 · 共 249 行
PAS
249 行
unit DXCachedLogging;
interface
///////////////////////////////////////////////////////////////////////////////
// Component: TDXCachedLogging
// Author: G.E. Ozz Nixon Jr. (onixon@dxsock.com)
// ========================================================================
// Source Owner: DX, Inc. 1995-2002
// Copyright: All code is the property of DX, Inc. Licensed for
// resell by Brain Patchwork DX (tm) and part of the
// DX (r) product lines, which are (c) 1999-2002
// DX, Inc. Source may not be distributed without
// written permission from both Brain Patchwork DX,
// and DX, Inc.
// License: (Reminder), None of this code can be added to other
// developer products without permission. This includes
// but not limited to DCU's, DCP's, DLL's, OCX's, or
// any other form of merging our technologies. All of
// your products released to a public consumer be it
// shareware, freeware, commercial, etc. must contain a
// license notification somewhere visible in the
// application.
// Example is Internet Explorer - Help->About screen
// shows the licensed code contained in the application.
// Code Version: (3rd Generation Code)
// ========================================================================
// Description:
// ========================================================================
///////////////////////////////////////////////////////////////////////////////
uses
DXBasicTimer,
DXString,
Classes;
{$I DXAddons.def}
{$WARNINGS OFF}
type
TDX_WriteRedirect=procedure(WriteData:TStream) of object;
// TDXCachedLogging is the ancestor to all of our logging
// components. It incorporates two types of caching techniques.
//
//
// 1. Based upon the amount of data stored in memory,
// flushing at this threshhold reduces the amount of
// disk operations.
// 2. Based upon the age of the data stored in memory,
// flushing after a given period of time also reduces
// the amount of disk operations.
// These two technoqies are used jointly, producing the ultimate
// style of buffered logging. No matter how busy or inactive a
// server is - this design improves the overall performance of
// the server and hosting PC. While incorporating the ability to
// manually flush the content, the ability to redirect the
// \output to another resource (like a database), and the
// ability to rename the log file for a new day.
//
//
//
// Summary
// Ancestor Logging Component.
TDXCachedLogging=class(TDXComponent)
private
// Private declarations
fCacheArray:TList;
FFilename:string;
FInterval:Cardinal;
FMaxSize:Integer;
MyTimer:TDXBasicTimer;
fLastRun:TDateTime;
feOnDayRollover:TNotifyEvent;
feWriteRedirect:TDX_WriteRedirect;
fIsFlushing:Boolean;
fMemInUse:Cardinal;
procedure FlushLog(Sender:TObject);
protected
// Protected declarations
function GetMemInUse:Cardinal;
function GetEntries:Integer;
public
// Public declarations
constructor Create(AOwner:TComponent); {$IFNDEF OBJECTS_ONLY}override;
{$ENDIF}
destructor Destroy; override;
procedure Writeln(Value:string); virtual;
procedure FlushNow;
published
property FileName:string read FFileName
write FFileName;
property CacheInterval:Cardinal read FInterval
write FInterval;
property CacheMaxSize:Integer read FMaxSize
write FMaxSize;
property OnDayRollover:TNotifyEvent read feOnDayRollover
write feOnDayRollover;
property OnWriteRedirect:TDX_WriteRedirect read feWriteRedirect
write feWriteRedirect;
property MemInUse:Cardinal read GetMemInUse;
property Entries:Integer read GetEntries;
end;
implementation
uses
SysUtils;
type
PListString=^TListString;
TListString=record
Str:string;
Len:Integer;
end;
constructor TDXCachedLogging.Create(AOwner:TComponent);
begin
inherited Create(AOwner);
{$IFDEF OBJECTS_ONLY}
MyTimer:=TDXBasicTimer.Create;
{$ELSE}
MyTimer:=TDXBasicTimer.Create(nil);
{$ENDIF}
fCacheArray:=TList.Create;
FInterval:=6000;
FMaxSize:=2048;
fIsFlushing:=False;
MyTimer.Enabled:=False;
MyTimer.Interval:=FInterval;
MyTimer.OnTimer:=FlushLog;
fLastRun:=Trunc(Date);
feWriteRedirect:=nil;
fMemInUse:=0;
end;
destructor TDXCachedLogging.Destroy;
begin
if Assigned(MyTimer) then begin
MyTimer.Enabled:=False;
MyTimer.Free;
MyTimer:=nil;
end;
if Assigned(fCacheArray) then begin
if fCacheArray.Count>0 then FlushLog(nil);
fCacheArray.Free;
fCacheArray:=nil;
end;
inherited Destroy;
end;
procedure TDXCachedLogging.Writeln(Value:string);
var
ListString:PListString;
VLen:Integer;
begin
if (Trunc(Date)<>fLastRun) then begin
FlushLog(nil);
if Assigned(feOnDayRollover) then feOnDayRollover(Self);
fLastRun:=Trunc(Date);
end;
New(ListString);
{$IFDEF LINUX}
Value:=Value+#13;
{$ELSE}
Value:=Value+#13#10;
{$ENDIF}
VLen:=Length(Value);
ListString^.Str:=Value;
ListString^.Len:=VLen;
{ SetLength(ListString^.Str, VLen);
FastMove(Value[1], ListString^.Str[1], VLen);}
Inc(fMemInUse, VLen);
MyCriticalSection.StartingWrite;
fCacheArray.Add(ListString);
MyCriticalSection.FinishedWrite;
with MyTimer do begin
if FInterval<>Interval then Interval:=FInterval;
if not Enabled then Enabled:=True;
end;
if fMemInUse>FMaxSize then FlushLog(nil);
end;
procedure TDXCachedLogging.FlushLog;
var
TFH:Integer;
MemoryStream:TMemoryStream;
ListString:PListString;
begin
fMemInUse:=0;
MyCriticalSection.StartingWrite;
if (FFileName='')or
(not Assigned(fCacheArray))or
fIsFlushing or
(fCacheArray.Count<1) then begin
if (fCacheArray.Count<1) then MyTimer.Enabled:=False;
MyCriticalSection.FinishedWrite;
Exit;
end
else
fIsFlushing:=True;
try
if Assigned(feWriteRedirect) then begin
MemoryStream:=TMemoryStream.Create;
while fCacheArray.Count>0 do begin
MemoryStream.Write(PListString(fCacheArray[0])^.Str[1],
PListString(fCacheArray[0])^.Len);
fCacheArray.Delete(0);
end;
MemoryStream.Position:=0;
feWriteRedirect(MemoryStream);
MemoryStream.Free;
end
else begin
TFH:=FileOpen(FFileName, fmOpenWrite or fmShareDenyNone);
if TFH<0 then TFH:=FileCreate(FFileName)
else FileSeek(TFH, 0, 2);
while fCacheArray.Count>0 do begin
ListString:=PListString(fCacheArray[0]);
FileWrite(TFH, ListString^.Str[1], ListString^.Len);
Dispose(ListString);
fCacheArray.Delete(0);
end;
FileClose(TFH);
end;
finally
fIsFlushing:=False;
end;
MyCriticalSection.FinishedWrite;
end;
procedure TDXCachedLogging.FlushNow;
begin
FlushLog(nil);
end;
function TDXCachedLogging.GetMemInUse:Cardinal;
begin
Result:=fMemInUse;
end;
function TDXCachedLogging.GetEntries:Integer;
begin
Result:=fCacheArray.Count;
end;
end.
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?