2015-12-29 17:57:04 +01:00
|
|
|
|
{
|
|
|
|
|
THIS UNIT IS A MODIFIED VERSION OF delphi-iocp-framework PROJECT
|
|
|
|
|
You can find the original version here
|
|
|
|
|
https://code.google.com/p/delphi-iocp-framework/
|
|
|
|
|
}
|
|
|
|
|
|
2016-06-22 17:49:16 +02:00
|
|
|
|
// ***************************************************************************
|
|
|
|
|
//
|
|
|
|
|
// Delphi MVC Framework
|
|
|
|
|
//
|
|
|
|
|
// Copyright (c) 2010-2016 Daniele Teti and the DMVCFramework Team
|
|
|
|
|
//
|
|
|
|
|
// https://github.com/danieleteti/delphimvcframework
|
|
|
|
|
//
|
|
|
|
|
// ***************************************************************************
|
|
|
|
|
//
|
|
|
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
|
// you may not use this file except in compliance with the License.
|
|
|
|
|
// You may obtain a copy of the License at
|
|
|
|
|
//
|
|
|
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
|
//
|
|
|
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
|
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
|
// See the License for the specific language governing permissions and
|
|
|
|
|
// limitations under the License.
|
|
|
|
|
//
|
|
|
|
|
// ***************************************************************************
|
2015-12-22 12:38:17 +01:00
|
|
|
|
|
2013-10-30 00:48:23 +01:00
|
|
|
|
unit Iocp.Logger;
|
|
|
|
|
|
|
|
|
|
interface
|
|
|
|
|
|
|
|
|
|
uses
|
|
|
|
|
Windows,
|
|
|
|
|
Classes,
|
|
|
|
|
SysUtils,
|
|
|
|
|
SyncObjs,
|
|
|
|
|
uGlobalVars,
|
|
|
|
|
Iocp.Utils;
|
|
|
|
|
|
|
|
|
|
type
|
|
|
|
|
TLogType = (ltNormal, ltWarning, ltError, ltException);
|
|
|
|
|
TLogTypeSets = set of TLogType;
|
|
|
|
|
|
|
|
|
|
const
|
|
|
|
|
LogTypeStr: array [TLogType] of string = ('ALL', 'WAR', 'ERR', 'EXP');
|
|
|
|
|
|
|
|
|
|
type
|
|
|
|
|
TCacheFileStream = class(TThread)
|
|
|
|
|
private
|
2013-11-08 23:10:25 +01:00
|
|
|
|
FFileStream: TFileStream;
|
|
|
|
|
FFileTime: TDateTime;
|
|
|
|
|
FLocker: TCriticalSection;
|
2013-10-30 00:48:23 +01:00
|
|
|
|
FCacheBuffer, FCacheBufferA, FCacheBufferB: TMemoryStream;
|
2013-11-08 23:10:25 +01:00
|
|
|
|
FFlushInterval: DWORD;
|
2013-10-30 00:48:23 +01:00
|
|
|
|
|
|
|
|
|
protected
|
|
|
|
|
procedure Lock;
|
|
|
|
|
procedure Unlock;
|
|
|
|
|
|
|
|
|
|
procedure Execute; override;
|
|
|
|
|
|
|
|
|
|
public
|
|
|
|
|
constructor Create(const AFileName: string); reintroduce;
|
|
|
|
|
destructor Destroy; override;
|
|
|
|
|
|
|
|
|
|
function Write(const Buffer; Count: Longint): Longint;
|
|
|
|
|
procedure AppendStr(const S: RawByteString); overload;
|
|
|
|
|
procedure AppendStr(const S: UTF8String); overload;
|
|
|
|
|
procedure AppendStr(const S: UnicodeString); overload;
|
|
|
|
|
procedure Flush;
|
|
|
|
|
|
|
|
|
|
property FileTime: TDateTime read FFileTime;
|
|
|
|
|
property FlushInterval: DWORD read FFlushInterval write FFlushInterval;
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
TIocpLogger = class
|
|
|
|
|
private
|
2013-11-08 23:10:25 +01:00
|
|
|
|
FRefCount: Integer;
|
|
|
|
|
FFileWriters: array [TLogType] of TCacheFileStream;
|
|
|
|
|
FFileLocker: array [TLogType] of TCriticalSection;
|
|
|
|
|
FLogColor: array [TLogType] of Integer;
|
2013-10-30 00:48:23 +01:00
|
|
|
|
FConsoleHandle: THandle;
|
2013-11-08 23:10:25 +01:00
|
|
|
|
FShowConsole: Boolean;
|
2013-10-30 00:48:23 +01:00
|
|
|
|
FConsoleLocker: TCriticalSection;
|
|
|
|
|
procedure SetShowConsole(const Value: Boolean);
|
|
|
|
|
|
|
|
|
|
protected
|
|
|
|
|
function GetLogFileName(LogType: TLogType; Date: TDateTime): string;
|
|
|
|
|
procedure AppendStrToLogFile(const S: UnicodeString; LogType: TLogType);
|
|
|
|
|
|
|
|
|
|
function AddRef: Integer;
|
|
|
|
|
function Release: Boolean;
|
|
|
|
|
|
|
|
|
|
public
|
|
|
|
|
constructor Create; virtual;
|
|
|
|
|
destructor Destroy; override;
|
|
|
|
|
|
|
|
|
|
procedure AppendLog(const Log: UnicodeString; const TimeFormat: string;
|
|
|
|
|
LogType: TLogType = ltNormal; CRLF: string = ';'); overload;
|
|
|
|
|
procedure AppendLog(const Log: UnicodeString; LogType: TLogType = ltNormal;
|
|
|
|
|
CRLF: string = ';'); overload;
|
|
|
|
|
procedure AppendLog(const Fmt: UnicodeString; const Args: array of const;
|
2016-03-14 23:56:41 +01:00
|
|
|
|
const TimeFormat: string; LogType: TLogType = ltNormal;
|
|
|
|
|
CRLF: string = ';'); overload;
|
2013-10-30 00:48:23 +01:00
|
|
|
|
procedure AppendLog(const Fmt: UnicodeString; const Args: array of const;
|
|
|
|
|
LogType: TLogType = ltNormal; CRLF: string = ';'); overload;
|
|
|
|
|
|
|
|
|
|
property ShowConsole: Boolean read FShowConsole write SetShowConsole;
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
procedure ShowConsoleLog(OnOff: Boolean);
|
|
|
|
|
procedure AppendLog(const Log: UnicodeString; const TimeFormat: string;
|
|
|
|
|
LogType: TLogType = ltNormal; CRLF: string = ';'); overload;
|
|
|
|
|
procedure AppendLog(const Log: UnicodeString; LogType: TLogType = ltNormal;
|
|
|
|
|
CRLF: string = ';'); overload;
|
2016-03-14 23:56:41 +01:00
|
|
|
|
procedure AppendLog(const Fmt: UnicodeString; const Args: array of const;
|
|
|
|
|
const TimeFormat: string; LogType: TLogType = ltNormal;
|
|
|
|
|
CRLF: string = ';'); overload;
|
2013-10-30 00:48:23 +01:00
|
|
|
|
procedure AppendLog(const Fmt: UnicodeString; const Args: array of const;
|
|
|
|
|
LogType: TLogType = ltNormal; CRLF: string = ';'); overload;
|
|
|
|
|
|
|
|
|
|
function gIocpLogger: TIocpLogger;
|
|
|
|
|
|
|
|
|
|
implementation
|
|
|
|
|
|
|
|
|
|
constructor TIocpLogger.Create;
|
|
|
|
|
var
|
|
|
|
|
i: TLogType;
|
|
|
|
|
begin
|
|
|
|
|
FRefCount := 1;
|
|
|
|
|
|
|
|
|
|
for i := low(TLogType) to high(TLogType) do
|
|
|
|
|
begin
|
|
|
|
|
FFileLocker[i] := TCriticalSection.Create;
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
FShowConsole := False;
|
|
|
|
|
FConsoleHandle := INVALID_HANDLE_VALUE;
|
|
|
|
|
FConsoleLocker := TCriticalSection.Create;
|
|
|
|
|
|
|
|
|
|
{ <EFBFBD><EFBFBD><EFBFBD><EFBFBD>̨<EFBFBD><EFBFBD>ɫ<EFBFBD><EFBFBD>
|
|
|
|
|
|
|
|
|
|
FOREGROUND_INTENSITY - ǰ<EFBFBD><EFBFBD>ɫ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|
|
|
|
FOREGROUND_BLUE - ǰ<EFBFBD><EFBFBD>ɫ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɫ
|
|
|
|
|
FOREGROUND_GREEN - ǰ<EFBFBD><EFBFBD>ɫ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɫ
|
|
|
|
|
FOREGROUND_RED - ǰ<EFBFBD><EFBFBD>ɫ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɫ
|
|
|
|
|
|
|
|
|
|
BACKGROUND_INTENSITY - <EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɫ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|
|
|
|
BACKGROUND_BLUE - <EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɫ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɫ
|
|
|
|
|
BACKGROUND_GREEN - <EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɫ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɫ
|
|
|
|
|
BACKGROUND_RED - <EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɫ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɫ
|
|
|
|
|
|
|
|
|
|
<EFBFBD><EFBFBD>ɫ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ԭɫ<EFBFBD><EFBFBD><EFBFBD>϶<EFBFBD><EFBFBD><EFBFBD>
|
|
|
|
|
}
|
|
|
|
|
FLogColor[ltNormal] := FOREGROUND_RED or FOREGROUND_GREEN or FOREGROUND_BLUE;
|
2016-03-14 23:56:41 +01:00
|
|
|
|
FLogColor[ltWarning] := FOREGROUND_INTENSITY or FOREGROUND_RED or
|
|
|
|
|
FOREGROUND_GREEN;
|
2013-10-30 00:48:23 +01:00
|
|
|
|
FLogColor[ltError] := FOREGROUND_INTENSITY or FOREGROUND_RED;
|
2016-03-14 23:56:41 +01:00
|
|
|
|
FLogColor[ltException] := FOREGROUND_INTENSITY or FOREGROUND_RED or
|
|
|
|
|
FOREGROUND_BLUE;
|
2013-10-30 00:48:23 +01:00
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
destructor TIocpLogger.Destroy;
|
|
|
|
|
var
|
|
|
|
|
i: TLogType;
|
2016-03-14 23:56:41 +01:00
|
|
|
|
LHandle: Cardinal;
|
2013-10-30 00:48:23 +01:00
|
|
|
|
begin
|
|
|
|
|
for i := low(TLogType) to high(TLogType) do
|
|
|
|
|
begin
|
|
|
|
|
if Assigned(FFileWriters[i]) then
|
|
|
|
|
begin
|
|
|
|
|
FFileWriters[i].Flush;
|
2016-03-14 23:56:41 +01:00
|
|
|
|
LHandle := FFileWriters[i].Handle;
|
2013-10-30 00:48:23 +01:00
|
|
|
|
FFileWriters[i].Terminate;
|
2016-03-14 23:56:41 +01:00
|
|
|
|
WaitForSingleObject(LHandle, INFINITE);
|
2016-06-22 17:49:16 +02:00
|
|
|
|
// FFileWriters[i].Free;
|
2013-10-30 00:48:23 +01:00
|
|
|
|
FFileWriters[i] := nil;
|
|
|
|
|
end;
|
|
|
|
|
FFileLocker[i].Free;
|
|
|
|
|
end;
|
|
|
|
|
FConsoleLocker.Free;
|
|
|
|
|
|
|
|
|
|
inherited Destroy;
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
function TIocpLogger.GetLogFileName(LogType: TLogType; Date: TDateTime): string;
|
|
|
|
|
begin
|
|
|
|
|
Result := LogTypeStr[LogType];
|
|
|
|
|
if (Result <> '') then
|
|
|
|
|
Result := Result + '-';
|
|
|
|
|
|
2013-11-08 23:10:25 +01:00
|
|
|
|
{$IFDEF USEPIDFORLOGFILE}
|
2013-10-30 00:48:23 +01:00
|
|
|
|
Result := Result + ThreadFormatDateTime('YYYY-MM-DD', Date) + '_PID' +
|
|
|
|
|
IntToStr(GetCurrentProcessID) + '.log';
|
|
|
|
|
|
2013-11-08 23:10:25 +01:00
|
|
|
|
{$ELSE}
|
2013-10-30 00:48:23 +01:00
|
|
|
|
Result := Result + ThreadFormatDateTime('YYYY-MM-DD', Date) + '.log';
|
|
|
|
|
|
2013-11-08 23:10:25 +01:00
|
|
|
|
{$ENDIF}
|
2013-10-30 00:48:23 +01:00
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
function TIocpLogger.Release: Boolean;
|
|
|
|
|
begin
|
|
|
|
|
Result := (InterlockedDecrement(FRefCount) = 0);
|
|
|
|
|
|
|
|
|
|
if Result then
|
|
|
|
|
Free;
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
procedure TIocpLogger.SetShowConsole(const Value: Boolean);
|
|
|
|
|
var
|
|
|
|
|
ConSize: TCoord;
|
2013-11-08 23:10:25 +01:00
|
|
|
|
ConRec: TSmallRect;
|
2013-10-30 00:48:23 +01:00
|
|
|
|
begin
|
|
|
|
|
if (FShowConsole = Value) then
|
|
|
|
|
Exit;
|
|
|
|
|
|
|
|
|
|
FShowConsole := Value;
|
|
|
|
|
|
|
|
|
|
if FShowConsole then
|
|
|
|
|
begin
|
|
|
|
|
if (FConsoleHandle = INVALID_HANDLE_VALUE) then
|
|
|
|
|
begin
|
|
|
|
|
AllocConsole;
|
|
|
|
|
FConsoleHandle := GetStdHandle(STD_OUTPUT_HANDLE);
|
|
|
|
|
|
|
|
|
|
// <20><><EFBFBD>ÿ<EFBFBD><C3BF><EFBFBD>̨<EFBFBD><CCA8>Ļ<EFBFBD><C4BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>С<EFBFBD><D0A1>X=<3D><>(<28>ֽ<EFBFBD><D6BD><EFBFBD>), Y=<3D><>
|
|
|
|
|
ConSize.X := 80;
|
|
|
|
|
ConSize.Y := 8192;
|
|
|
|
|
SetConsoleScreenBufferSize(FConsoleHandle, ConSize);
|
|
|
|
|
|
|
|
|
|
// <20><><EFBFBD>ÿ<EFBFBD><C3BF><EFBFBD>̨λ<CCA8>ô<EFBFBD>С(<28><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊ<EFBFBD><CEAA>λ)
|
|
|
|
|
ConRec.Left := 0;
|
|
|
|
|
ConRec.Top := 0;
|
|
|
|
|
ConRec.Right := 80 - 1;
|
|
|
|
|
ConRec.Bottom := 25 - 1;
|
|
|
|
|
SetConsoleWindowInfo(FConsoleHandle, True, ConRec);
|
|
|
|
|
end;
|
|
|
|
|
end
|
|
|
|
|
else
|
|
|
|
|
begin
|
|
|
|
|
if (FConsoleHandle <> INVALID_HANDLE_VALUE) then
|
|
|
|
|
begin
|
|
|
|
|
FreeConsole;
|
|
|
|
|
FConsoleHandle := INVALID_HANDLE_VALUE;
|
|
|
|
|
end;
|
|
|
|
|
end;
|
|
|
|
|
end;
|
|
|
|
|
|
2016-03-14 23:56:41 +01:00
|
|
|
|
procedure TIocpLogger.AppendLog(const Log: UnicodeString;
|
|
|
|
|
const TimeFormat: string; LogType: TLogType; CRLF: string);
|
2013-10-30 00:48:23 +01:00
|
|
|
|
var
|
|
|
|
|
LogText: UnicodeString;
|
|
|
|
|
begin
|
|
|
|
|
if (AddRef = 1) then
|
|
|
|
|
Exit;
|
|
|
|
|
|
|
|
|
|
try
|
|
|
|
|
if (CRLF <> '') then
|
2016-03-14 23:56:41 +01:00
|
|
|
|
LogText := StringReplace(StringReplace(Log, #13#10, CRLF, [rfReplaceAll]),
|
|
|
|
|
#10, CRLF, [rfReplaceAll])
|
2013-10-30 00:48:23 +01:00
|
|
|
|
else
|
|
|
|
|
LogText := Log;
|
|
|
|
|
LogText := ThreadFormatDateTime(TimeFormat, Now) + ' ' + LogText + #13#10;
|
|
|
|
|
|
|
|
|
|
if FShowConsole then
|
|
|
|
|
try
|
|
|
|
|
FConsoleLocker.Enter;
|
|
|
|
|
SetConsoleTextAttribute(FConsoleHandle, FLogColor[LogType]);
|
|
|
|
|
System.Write(LogText);
|
|
|
|
|
SetConsoleTextAttribute(FConsoleHandle, FLogColor[ltNormal]);
|
|
|
|
|
finally
|
|
|
|
|
FConsoleLocker.Leave;
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
AppendStrToLogFile(LogText, LogType);
|
|
|
|
|
finally
|
|
|
|
|
Release;
|
|
|
|
|
end;
|
|
|
|
|
end;
|
|
|
|
|
|
2016-03-14 23:56:41 +01:00
|
|
|
|
procedure TIocpLogger.AppendLog(const Log: UnicodeString; LogType: TLogType;
|
|
|
|
|
CRLF: string);
|
2013-10-30 00:48:23 +01:00
|
|
|
|
begin
|
|
|
|
|
if (AddRef = 1) then
|
|
|
|
|
Exit;
|
|
|
|
|
try
|
|
|
|
|
AppendLog(Log, 'HH:NN:SS:ZZZ', LogType, CRLF);
|
|
|
|
|
finally
|
|
|
|
|
Release;
|
|
|
|
|
end;
|
|
|
|
|
end;
|
|
|
|
|
|
2016-03-14 23:56:41 +01:00
|
|
|
|
procedure TIocpLogger.AppendLog(const Fmt: UnicodeString;
|
|
|
|
|
const Args: array of const; const TimeFormat: string; LogType: TLogType;
|
|
|
|
|
CRLF: string);
|
2013-10-30 00:48:23 +01:00
|
|
|
|
begin
|
|
|
|
|
if (AddRef = 1) then
|
|
|
|
|
Exit;
|
|
|
|
|
try
|
|
|
|
|
AppendLog(ThreadFormat(Fmt, Args), TimeFormat, LogType, CRLF);
|
|
|
|
|
finally
|
|
|
|
|
Release;
|
|
|
|
|
end;
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
function TIocpLogger.AddRef: Integer;
|
|
|
|
|
begin
|
|
|
|
|
Result := InterlockedIncrement(FRefCount);
|
|
|
|
|
end;
|
|
|
|
|
|
2016-03-14 23:56:41 +01:00
|
|
|
|
procedure TIocpLogger.AppendLog(const Fmt: UnicodeString;
|
|
|
|
|
const Args: array of const; LogType: TLogType; CRLF: string);
|
2013-10-30 00:48:23 +01:00
|
|
|
|
begin
|
|
|
|
|
if (AddRef = 1) then
|
|
|
|
|
Exit;
|
|
|
|
|
try
|
|
|
|
|
AppendLog(ThreadFormat(Fmt, Args), LogType, CRLF);
|
|
|
|
|
finally
|
|
|
|
|
Release;
|
|
|
|
|
end;
|
|
|
|
|
end;
|
|
|
|
|
|
2016-03-14 23:56:41 +01:00
|
|
|
|
procedure TIocpLogger.AppendStrToLogFile(const S: UnicodeString;
|
|
|
|
|
LogType: TLogType);
|
2013-10-30 00:48:23 +01:00
|
|
|
|
var
|
|
|
|
|
LogDir, LogFile: string;
|
|
|
|
|
begin
|
|
|
|
|
if (AddRef = 1) then
|
|
|
|
|
Exit;
|
|
|
|
|
try
|
2016-03-14 23:56:41 +01:00
|
|
|
|
if (FFileWriters[LogType] = nil) or
|
|
|
|
|
(Trunc(FFileWriters[LogType].FileTime) <> Trunc(Now)) then
|
|
|
|
|
begin
|
|
|
|
|
FFileLocker[LogType].Enter;
|
|
|
|
|
try
|
|
|
|
|
// CREATE OR ROTATE //daniele
|
|
|
|
|
if (FFileWriters[LogType] = nil) or
|
|
|
|
|
(Trunc(FFileWriters[LogType].FileTime) <> Trunc(Now)) then
|
2013-10-30 00:48:23 +01:00
|
|
|
|
begin
|
2016-03-14 23:56:41 +01:00
|
|
|
|
if Assigned(FFileWriters[LogType]) then
|
|
|
|
|
begin
|
|
|
|
|
FFileWriters[LogType].Flush;
|
|
|
|
|
FFileWriters[LogType].Terminate; // freeonterminate = true
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
LogDir := gAppPath + gAppName + '.Log\';
|
|
|
|
|
LogFile := LogDir + GetLogFileName(LogType, Now);
|
|
|
|
|
ForceDirectories(LogDir);
|
|
|
|
|
FFileWriters[LogType] := TCacheFileStream.Create(LogFile);
|
2013-10-30 00:48:23 +01:00
|
|
|
|
end;
|
2016-03-14 23:56:41 +01:00
|
|
|
|
finally
|
|
|
|
|
FFileLocker[LogType].Leave;
|
2013-10-30 00:48:23 +01:00
|
|
|
|
end;
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
FFileWriters[LogType].AppendStr(S);
|
|
|
|
|
finally
|
|
|
|
|
Release;
|
|
|
|
|
end;
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
{ TCacheFileStream }
|
|
|
|
|
|
|
|
|
|
procedure TCacheFileStream.AppendStr(const S: RawByteString);
|
|
|
|
|
begin
|
|
|
|
|
write(S[1], Length(S));
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
procedure TCacheFileStream.AppendStr(const S: UTF8String);
|
|
|
|
|
begin
|
|
|
|
|
AppendStr(RawByteString(S));
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
procedure TCacheFileStream.AppendStr(const S: UnicodeString);
|
|
|
|
|
begin
|
|
|
|
|
AppendStr(UTF8Encode(S));
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
constructor TCacheFileStream.Create(const AFileName: string);
|
|
|
|
|
var
|
|
|
|
|
UTF8Header: RawByteString;
|
|
|
|
|
begin
|
|
|
|
|
if FileExists(AFileName) then
|
|
|
|
|
begin
|
2016-03-14 23:56:41 +01:00
|
|
|
|
FFileStream := TFileStream.Create(AFileName, fmOpenReadWrite or
|
|
|
|
|
fmShareDenyWrite);
|
2013-10-30 00:48:23 +01:00
|
|
|
|
UTF8Header := '';
|
|
|
|
|
end
|
|
|
|
|
else
|
|
|
|
|
begin
|
|
|
|
|
FFileStream := TFileStream.Create(AFileName, fmCreate);
|
|
|
|
|
FFileStream.Free;
|
2016-03-14 23:56:41 +01:00
|
|
|
|
FFileStream := TFileStream.Create(AFileName, fmOpenReadWrite or
|
|
|
|
|
fmShareDenyWrite);
|
2013-10-30 00:48:23 +01:00
|
|
|
|
// дUTF8<46>ļ<EFBFBD>ͷ
|
|
|
|
|
UTF8Header := RawByteString(#$EF#$BB#$BF);
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
inherited Create(True);
|
|
|
|
|
|
2016-03-14 23:56:41 +01:00
|
|
|
|
FreeOnTerminate := True;
|
2013-10-30 00:48:23 +01:00
|
|
|
|
|
|
|
|
|
FLocker := TCriticalSection.Create;
|
|
|
|
|
FCacheBufferA := TMemoryStream.Create;
|
|
|
|
|
FCacheBufferB := TMemoryStream.Create;
|
|
|
|
|
FCacheBuffer := FCacheBufferA;
|
|
|
|
|
FFileTime := Now;
|
|
|
|
|
FFlushInterval := 1000;
|
|
|
|
|
|
|
|
|
|
if (UTF8Header <> '') then
|
|
|
|
|
AppendStr(UTF8Header);
|
|
|
|
|
|
|
|
|
|
Suspended := False;
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
destructor TCacheFileStream.Destroy;
|
|
|
|
|
begin
|
|
|
|
|
Lock;
|
|
|
|
|
Flush; // daniele
|
|
|
|
|
try
|
|
|
|
|
if Assigned(FCacheBufferA) then
|
|
|
|
|
FreeAndNil(FCacheBufferA);
|
|
|
|
|
if Assigned(FCacheBufferB) then
|
|
|
|
|
FreeAndNil(FCacheBufferB);
|
|
|
|
|
if Assigned(FFileStream) then
|
|
|
|
|
FreeAndNil(FFileStream);
|
|
|
|
|
finally
|
|
|
|
|
Unlock;
|
|
|
|
|
end;
|
|
|
|
|
if Assigned(FLocker) then
|
|
|
|
|
FreeAndNil(FLocker);
|
|
|
|
|
|
|
|
|
|
inherited Destroy;
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
procedure TCacheFileStream.Execute;
|
|
|
|
|
begin
|
|
|
|
|
// while not Terminated do
|
|
|
|
|
// begin
|
|
|
|
|
// if (CalcTickDiff(t, GetTickCount) >= FFlushInterval) then
|
|
|
|
|
// begin
|
|
|
|
|
// Flush;
|
|
|
|
|
// t := GetTickCount;
|
|
|
|
|
// end
|
|
|
|
|
// else
|
|
|
|
|
// SleepEx(100, True);
|
|
|
|
|
// end;
|
|
|
|
|
|
|
|
|
|
while not Terminated do
|
|
|
|
|
begin
|
|
|
|
|
Flush;
|
2016-03-14 23:56:41 +01:00
|
|
|
|
TThread.Sleep(500);
|
2013-10-30 00:48:23 +01:00
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
// Flush;
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
procedure TCacheFileStream.Flush;
|
|
|
|
|
var
|
|
|
|
|
Buffer: TMemoryStream;
|
|
|
|
|
begin
|
|
|
|
|
if (FCacheBuffer.Position <= 0) then
|
|
|
|
|
Exit;
|
|
|
|
|
|
|
|
|
|
Buffer := FCacheBuffer;
|
|
|
|
|
Lock;
|
|
|
|
|
if (FCacheBuffer = FCacheBufferA) then
|
|
|
|
|
FCacheBuffer := FCacheBufferB
|
|
|
|
|
else
|
|
|
|
|
FCacheBuffer := FCacheBufferA;
|
|
|
|
|
FCacheBuffer.Position := 0;
|
|
|
|
|
Unlock;
|
|
|
|
|
try
|
|
|
|
|
FFileStream.Seek(0, soEnd);
|
|
|
|
|
FFileStream.Write(Buffer.Memory^, Buffer.Position);
|
|
|
|
|
FlushFileBuffers(FFileStream.Handle);
|
|
|
|
|
finally
|
|
|
|
|
Buffer.Position := 0;
|
|
|
|
|
end;
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
procedure TCacheFileStream.Lock;
|
|
|
|
|
begin
|
|
|
|
|
FLocker.Enter;
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
procedure TCacheFileStream.Unlock;
|
|
|
|
|
begin
|
|
|
|
|
FLocker.Leave;
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
function TCacheFileStream.Write(const Buffer; Count: Integer): Longint;
|
|
|
|
|
begin
|
|
|
|
|
Lock;
|
|
|
|
|
try
|
|
|
|
|
Result := FCacheBuffer.Write(Buffer, Count);
|
|
|
|
|
finally
|
|
|
|
|
Unlock;
|
|
|
|
|
end;
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
procedure ShowConsoleLog(OnOff: Boolean);
|
|
|
|
|
begin
|
|
|
|
|
gIocpLogger.ShowConsole := OnOff;
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
procedure AppendLog(const Log: UnicodeString; const TimeFormat: string;
|
|
|
|
|
LogType: TLogType = ltNormal; CRLF: string = ';');
|
|
|
|
|
begin
|
|
|
|
|
gIocpLogger.AppendLog(Log, TimeFormat, LogType, CRLF);
|
|
|
|
|
end;
|
|
|
|
|
|
2016-03-14 23:56:41 +01:00
|
|
|
|
procedure AppendLog(const Log: UnicodeString; LogType: TLogType = ltNormal;
|
|
|
|
|
CRLF: string = ';');
|
2013-10-30 00:48:23 +01:00
|
|
|
|
begin
|
|
|
|
|
gIocpLogger.AppendLog(Log, LogType, CRLF);
|
|
|
|
|
end;
|
|
|
|
|
|
2016-03-14 23:56:41 +01:00
|
|
|
|
procedure AppendLog(const Fmt: UnicodeString; const Args: array of const;
|
|
|
|
|
const TimeFormat: string; LogType: TLogType = ltNormal; CRLF: string = ';');
|
2013-10-30 00:48:23 +01:00
|
|
|
|
begin
|
|
|
|
|
gIocpLogger.AppendLog(Fmt, Args, TimeFormat, LogType, CRLF);
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
procedure AppendLog(const Fmt: UnicodeString; const Args: array of const;
|
|
|
|
|
LogType: TLogType = ltNormal; CRLF: string = ';');
|
|
|
|
|
begin
|
|
|
|
|
gIocpLogger.AppendLog(Fmt, Args, LogType, CRLF);
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
var
|
|
|
|
|
_gIocpLogger: TIocpLogger;
|
|
|
|
|
|
|
|
|
|
function gIocpLogger: TIocpLogger;
|
|
|
|
|
begin
|
|
|
|
|
{ if (TInterlocked.CompareExchange<TIocpLogger>(_gIocpLogger, nil, nil) <> nil) then Exit(_gIocpLogger);
|
|
|
|
|
|
|
|
|
|
Result := TIocpLogger.Create;
|
|
|
|
|
TInterlocked.Exchange<TIocpLogger>(_gIocpLogger, Result); }
|
|
|
|
|
|
|
|
|
|
Result := _gIocpLogger;
|
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
initialization
|
|
|
|
|
|
|
|
|
|
_gIocpLogger := TIocpLogger.Create;
|
|
|
|
|
|
|
|
|
|
finalization
|
|
|
|
|
|
|
|
|
|
if Assigned(_gIocpLogger) then
|
|
|
|
|
_gIocpLogger.Release;
|
|
|
|
|
|
|
|
|
|
end.
|