lazarus-ccr/components/flashfiler/sourcelaz/fffile.pas
2016-12-07 13:31:59 +00:00

416 lines
12 KiB
ObjectPascal

{*********************************************************}
{* FlashFiler: Low level file I/O routines *}
{*********************************************************}
(* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (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.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is TurboPower FlashFiler
*
* The Initial Developer of the Original Code is
* TurboPower Software
*
* Portions created by the Initial Developer are Copyright (C) 1996-2002
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* ***** END LICENSE BLOCK ***** *)
{$I ffdefine.inc}
{.$DEFINE Tracing}
unit fffile;
interface
uses
Windows,
SysUtils,
ffconst,
ffllbase,
ffsrmgr,
ffllexcp,
ffsrbase;
procedure FileProcsInitialize;
{$IFDEF Tracing}
{---File Access Tracing---}
type
TffTraceString = string[59];
procedure FFStartTracing(BufferSize : longint);
procedure FFDumpTrace(FileName : string);
procedure FFAddUserTrace(const ParamRec; PRSize : word);
procedure FFAddUserTraceStr(const S : TffTraceString);
{$ENDIF}
implementation
{$IFDEF Tracing}
type
TffFileOp = (foUnknown, foClose, foFlush, foLock, foOpen, foRead,
foSeek, foSetEOF, foUnlock, foWrite, foGeneral,
foUserTrace, foUserTraceStr);
procedure FFAddTrace(Op : TffFileOp; const ParamRec; PRSize : word); forward;
{$ENDIF}
{===File Access Primitives===========================================}
{$I FFFile.INC}
{====================================================================}
{$IFDEF Tracing}
{===File Access Tracing==============================================}
type
PTraceBuffer = ^TTraceBuffer;
TTraceBuffer = array [0..32767] of byte;
TTraceEntry = record
teWhat : word;
teSize : word;
teTime : TffWord32;
end;
var
TraceBuffer : PTraceBuffer;
TBSize : longint;
TBHead : longint;
TBTail : longint;
TracePadlock : TffPadlock;
{--------}
procedure FFStartTracing(BufferSize : longint);
const
MaxBufferSize = 64*1024;
begin
if (TraceBuffer = nil) then
begin
if (BufferSize <= 0) then
TBSize := 1024
else if (BufferSize > MaxBufferSize) then
TBSize := MaxBufferSize
else
TBSize := (BufferSize + 1023) and (not 1023);
GetMem(TraceBuffer, TBSize);
end;
TBHead := 0;
TBTail := 0;
TracePadLock := TffPadlock.Create;
end;
{--------}
procedure FFDumpTrace(FileName : string);
type
PHandyBuffer = ^THandyBuffer;
THandyBuffer = record
case byte of
0 : (L : array [0..127] of longint);
1 : (B : array [0..511] of byte);
2 : (C : array [0..511] of AnsiChar);
3 : (S : string[255]);
end;
{------}
procedure Read4Bytes(var B);
begin
Move(TraceBuffer^[TBTail], B, 4);
inc(TBTail, 4);
if (TBTail >= TBSize) then
dec(TBTail, TBSize);
end;
{------}
procedure GrowBuffer(var GB : PHandyBuffer; var CurSize : word; NewSize : word);
begin
if (NewSize > CurSize) then
begin
if (GB <> nil) then
FreeMem(GB, CurSize);
GetMem(GB, NewSize);
CurSize := NewSize;
end;
end;
{------}
procedure PrintEntry(var F : text; const TE : TTraceEntry; GB : PHandyBuffer);
var
FileName : TffMaxPathZ;
Offset : integer;
RemBytes : integer;
i, j : integer;
begin
{print the time in hex}
write(F, Format('%x8', [TE.teTime]));
{print the rest}
case TffFileOp(TE.teWhat) of
foUnknown :
begin
if (((TE.teSize+3) and $FFFC) = 4) then
writeln(F, Format(' ..(result): %d ($%0:x)', [GB^.L[0]]))
else
writeln(F, ' [unknown]');
end;
foGeneral :
begin
writeln(F, ' [general]');
end;
foOpen :
begin
writeln(F, ' [open file]');
StrCopy(FileName, @GB^.L[0]);
writeln(F, Format(' ..name: %s', [FileName]));
end;
foSeek :
begin
writeln(F, ' [position file]');
writeln(F, Format(' ..handle: %d ($%0:x)', [GB^.L[0]]));
if (GB^.L[1] = -1) then
writeln(F, ' ..position: End-Of-File')
else
writeln(F, Format(' ..position: %d ($%0:x)', [GB^.L[1]]));
end;
foSetEOF :
begin
writeln(F, ' [truncate file]');
writeln(F, Format(' ..handle: %d ($%0:x)', [GB^.L[0]]));
writeln(F, Format(' ..position: %d ($%0:x)', [GB^.L[1]]));
end;
foFlush :
begin
writeln(F, ' [flush file]');
writeln(F, Format(' ..handle: %d ($%0:x)', [GB^.L[0]]));
end;
foRead :
begin
writeln(F, ' [read file]');
writeln(F, Format(' ..handle: %d ($%0:x)', [GB^.L[0]]));
writeln(F, Format(' ..bytes to read: %d ($%0:x)', [GB^.L[1]]));
end;
foWrite :
begin
writeln(F, ' [write file]');
writeln(F, Format(' ..handle: %d ($%0:x)', [GB^.L[0]]));
writeln(F, Format(' ..bytes to write: %d ($%0:x)', [GB^.L[1]]));
end;
foLock :
begin
writeln(F, ' [lock file]');
writeln(F, Format(' ..handle: %d ($%0:x)', [GB^.L[0]]));
writeln(F, Format(' ..offset: %d ($%0:x)', [GB^.L[1]]));
writeln(F, Format(' ..bytes to lock: %d ($%0:x)', [GB^.L[2]]));
end;
foUnlock :
begin
writeln(F, ' [unlock file]');
writeln(F, Format(' ..handle: %d ($%0:x)', [GB^.L[0]]));
writeln(F, Format(' ..offset: %d ($%0:x)', [GB^.L[1]]));
writeln(F, Format(' ..bytes to unlock: %d ($%0:x)', [GB^.L[2]]));
end;
foClose :
begin
writeln(F, ' [close file]');
writeln(F, Format(' ..handle: %d ($%0:x)', [GB^.L[0]]));
end;
foUserTrace :
begin
writeln(F, Format(' [user trace entry], %d bytes', [TE.teSize]));
Offset := 0;
if (TE.teSize >= 8) then
for i := 0 to pred(TE.teSize div 8) do
begin
write(F, ' ');
for j := 0 to 7 do
write(F, Format('%.2x ', [GB^.B[Offset+j]]));
write(F, ' [');
for j := 0 to 7 do
write(F, Format('%s', [GB^.C[Offset+j]]));
writeln(F, ']');
inc(Offset, 8);
end;
RemBytes := TE.teSize mod 8;
if (RemBytes > 0) then
begin
write(F, ' ');
for j := 0 to pred(RemBytes) do
write(F, Format('%.2x ', [GB^.B[Offset+j]]));
for j := RemBytes to 7 do
write(F, ' ');
write(F, ' [');
for j := 0 to pred(RemBytes) do
write(F, Format('%s', [GB^.C[Offset+j]]));
for j := RemBytes to 7 do
write(F, ' ');
writeln(F, ']');
end;
end;
foUserTraceStr :
begin
writeln(F, Format(' [USER: %s]', [GB^.S]));
end;
end;{case}
end;
{------}
var
F : text;
GenBuf : PHandyBuffer;
GenBufSize : word;
TraceEntry : TTraceEntry;
AdjSize : word;
i : word;
begin
if (TraceBuffer <> nil) then
begin
{..write it to file..}
GenBuf := nil;
GenBufSize := 0;
System.Assign(F, FileName);
System.Rewrite(F);
if (TBTail = TBHead) then
writeln(F, '***no entries***')
else
repeat
Read4Bytes(TraceEntry);
Read4Bytes(TraceEntry.teTime);
AdjSize := (TraceEntry.teSize + 3) and $FFFC;
GrowBuffer(GenBuf, GenBufSize, AdjSize);
for i := 0 to pred(AdjSize div 4) do
Read4Bytes(GenBuf^.L[i]);
PrintEntry(F, TraceEntry, GenBuf);
until TBTail = TBHead;
System.Close(F);
FreeMem(GenBuf, GenBufSize);
FreeMem(TraceBuffer, TBSize);
TraceBuffer := nil;
TracePadLock.Free;
end;
end;
{--------}
procedure FFAddTrace(Op : TffFileOp; const ParamRec; PRSize : word);
{------}
procedure Write4Bytes(const B);
begin
Move(B, TraceBuffer^[TBHead], 4);
inc(TBHead, 4);
if (TBHead >= TBSize) then
dec(TBHead, TBSize);
end;
{------}
procedure WriteXBytes(const B; Size : word);
begin
FillChar(TraceBuffer^[TBHead], 4, 0);
Move(B, TraceBuffer^[TBHead], Size);
inc(TBHead, 4);
if (TBHead >= TBSize) then
dec(TBHead, TBSize);
end;
{------}
var
TraceEntry : TTraceEntry;
AdjSize : word;
i : word;
BytesFree : longint;
PRasLongints : array [1..128] of longint absolute ParamRec;
begin
if (TraceBuffer <> nil) then
begin
{calc the size rounded to nearest 4 bytes}
AdjSize := (PRSize + 3) and $FFFC;
{make sure that there's enough space in the trace buffer}
repeat
{calculate the number of bytes free in the trace buffer}
if (TBTail = TBHead) then
BytesFree := TBSize
else if (TBTail < TBHead) then
BytesFree := (TBSize - TBHead) + TBTail
else
BytesFree := TBTail - TBHead;
{if not enough room for this entry..}
if (BytesFree <= AdjSize + sizeof(TraceEntry)) then
begin
{..advance TBTail over oldest entry}
Move(TraceBuffer^[TBTail], TraceEntry, 4);
inc(TBTail, ((TraceEntry.teSize + 3) and $FFFC) + sizeof(TraceEntry));
if (TBTail >= TBSize) then
dec(TBTail, TBSize);
end;
until (BytesFree > AdjSize + sizeof(TraceEntry));
with TraceEntry do
begin
teWhat := ord(Op);
teSize := PRSize;
teTime := GetTickCount;
end;
Write4Bytes(TraceEntry);
Write4Bytes(TraceEntry.teTime);
for i := 1 to pred(AdjSize div 4) do
Write4Bytes(PRasLongints[i]);
if (AdjSize = PRSize) then
Write4Bytes(PRasLongints[AdjSize div 4])
else
WriteXBytes(PRasLongints[AdjSize div 4], 4 + PRSize - AdjSize);
end;
end;
{--------}
procedure FFGetTraceAccess;
begin
TracePadLock.Locked := true;
end;
{--------}
procedure FFFreeTraceAccess;
begin
TracePadLock.Locked := false;
end;
{--------}
procedure FFAddUserTrace(const ParamRec; PRSize : word);
begin
if (TraceBuffer <> nil) then
begin
FFGetTraceAccess;
if (PRSize > 128) then
PRSize := 128;
FFAddTrace(foUserTrace, ParamRec, PRSize);
FFFreeTraceAccess;
end;
end;
{--------}
procedure FFAddUserTraceStr(const S : TffTraceString);
begin
if (TraceBuffer <> nil) then
begin
FFGetTraceAccess;
FFAddTrace(foUserTraceStr, S, length(S)+1);
FFFreeTraceAccess;
end;
end;
{====================================================================}
{$ENDIF}
{===Unit initialization==============================================}
procedure FileProcsInitialize;
begin
FFCloseFilePrim := FFCloseFilePrim32;
FFFlushFilePrim := FFFlushFilePrim32;
FFGetPositionFilePrim := FFGetPositionFilePrim32;
// FFLockFilePrim := FFLockFilePrim32;
FFOpenFilePrim := FFOpenFilePrim32;
FFPositionFilePrim := FFPositionFilePrim32;
FFPositionFileEOFPrim := FFPositionFileEOFPrim32;
FFReadFilePrim := FFReadFilePrim32;
FFSetEOFPrim := FFSetEOFPrim32;
FFSleepPrim := FFSleepPrim32;
// FFUnlockFilePrim := FFUnlockFilePrim32;
FFWriteFilePrim := FFWriteFilePrim32;
{$IFDEF Tracing}
TraceBuffer := nil;
{$ENDIF}
end;
end.