home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Chip 2000 October
/
Chip_2000-10_cd1.bin
/
zkuste
/
Delphi
/
navody
/
multithread
/
mchpipetransactions.pas
< prev
next >
Wrap
Pascal/Delphi Source File
|
1999-07-26
|
6KB
|
190 lines
{ 27-07-1999 12:46:19 AM > [martin on MARTIN] update: Bugfixing (0.5) / }
{ 26-07-1999 12:05:12 AM > [martin on MARTIN] checked out /Bugfixing }
{ 10-05-1999 10:37:11 PM > [martin on MARTIN] checked out /Reformatting
according to Delphi guidelines. }
{ 10-05-1999 1:31:11 AM > [martin on MARTIN] update: Modifying to allow
for improved error mechanism (0.3) / }
{ 08-05-1999 8:16:25 PM > [martin on MARTIN] checked out /Modifying to
allow for improved error mechanism }
{ 14-04-1999 11:59:15 PM > [martin on MARTIN] update: Changing dynamic
methods to virtual. (0.2) / }
{ 14-04-1999 11:53:38 PM > [martin on MARTIN] checked out /Changing dynamic
methods to virtual. }
{ 06-04-1999 7:49:50 PM > [martin on MARTIN] checked out /Modifying Class
Names }
{ 06-04-1999 1:46:39 AM > [martin on MARTIN] check in: (0.0) Initial Version
/ None }
unit MCHPipeTransactions;
{Martin Harvey 2/12/98}
{A transaction manager suitable for the Pipe socket object.
I'm not toally happy with the original error handling architecture, and since
I have to completely rewrite most of the ONCP stuff anyway, I might as well
temporarily clear the situation up.
Reset will reset the transaction manager and DOPManager. It will not touch the
underlying socket, which will be handled by the PipeONCPSession.
OnDisconnect will be handled by the ONCP and triggered when the socket indicates
disconnection.
OnFatalError will also be handled by the ONCP. However, it will trigger an automatic
call to reset.
}
interface
uses MCHTransactions,Classes,MCHMemoryStream,MCHPipeSocket;
type
TMCHPipeTransactionManager = class(TMCHCustomTransactionManager)
private
FIncomingStream:TMCHMemoryStream;
FSocket:TMCHPipeSocket;
FTransactionStart,FTransactionEnd:integer;
protected
function GetActive:boolean;override;
procedure DoFatalError(Msg:string);override;
public
constructor Create;
destructor Destroy;override;
procedure WriteTransactionFromStream(ExternalIn:TStream);override;
procedure ReadTransactionToStream(ExternalOut:TStream);override;
procedure Reset;override;
{Socket handlers. Note that these are
automatically called by TMCHPipeSocket}
procedure HandleConnect;
procedure HandleDisconnect;
procedure HandleSockError;
procedure HandleSockRead;
published
property Socket:TMCHPipeSocket read FSocket write FSocket;
property OnFatalError;
end;
{NB: Events that I can trigger are:
procedure DoTransactionRecieved;virtual;
procedure DoFatalError;virtual;
procedure DoDestroy;virtual;
}
implementation
constructor TMCHPipeTransactionManager.Create;
begin
inherited Create; {TMCHCustomTransactionManager.Create creates DOPManager}
FIncomingStream := TMCHMemoryStream.Create;
end;
function TMCHPipeTransactionManager.GetActive:boolean;
begin
Result := FIncomingStream.Size > 0;
end;
destructor TMCHPipeTransactionManager.Destroy;
begin
FIncomingStream.Free;
inherited Destroy;
end;
procedure TMCHPipeTransactionManager.DoFatalError(Msg:string);
begin
Reset;
inherited DoFatalError(Msg);
end;
procedure TMCHPipeTransactionManager.WriteTransactionFromStream(ExternalIn:TStream);
var
InStream:TMCHMemoryStream;
Size:integer;
begin
InStream := TMCHMemoryStream.Create;
try
Size := ExternalIn.Size;
InStream.WriteBuffer(Size,SizeOf(Size));
ExternalIn.Seek(0,soFromBeginning);
InStream.CopyFrom(ExternalIn,ExternalIn.Size);
Socket.WriteData(InStream);
finally
InStream.Free;
end;
end;
procedure TMCHPipeTransactionManager.ReadTransactionToStream(ExternalOut:TStream);
begin
{At this point, just copy the required amount of data}
FIncomingStream.Seek(FTransactionStart,soFromBeginning);
ExternalOut.CopyFrom(FIncomingStream,FTransactionEnd - FTransactionStart);
end;
procedure TMCHPipeTransactionManager.Reset;
begin
FIncomingStream.Clear;
inherited Reset;
end;
procedure TMCHPipeTransactionManager.HandleConnect;
begin
Reset;
end;
procedure TMCHPipeTransactionManager.HandleDisconnect;
begin
Reset;
end;
procedure TMCHPipeTransactionManager.HandleSockError;
begin
Reset;
end;
procedure TMCHPipeTransactionManager.HandleSockRead;
var
TempStream:TMCHMemoryStream;
TrimFrom:integer;
begin
{Copy as much data as possible onto the end of our internal buffer}
FSocket.ReadData(FIncomingStream);
{Now see how many transactions we can extract}
TrimFrom := 0;
FTransactionStart := SizeOf(FTransactionEnd); {Start index at end of size field}
while FIncomingStream.Size >= (FTransactionStart) do
begin
FIncomingStream.Seek(FTransactionStart - SizeOf(FTransactionEnd),soFromBeginning);
FIncomingStream.ReadBuffer(FTransactionEnd,SizeOf(FTransactionEnd)); {read transaction size}
FTransactionEnd := FTransactionEnd + FTransactionStart; {Transaction end now at correct offset}
if FIncomingStream.Size >= FTransactionEnd then
begin
DoTransactionRecieved; {This will hopefully call ReadTransactionToStream}
TrimFrom := FTransactionEnd;
end;
{Now need to update readtransactionstart}
FTransactionStart := FTransactionEnd + SizeOf(FTransactionEnd);
end;
{At which point we have read all the data we can}
{Now need to remove all non required data}
{Now copy all data from TrimFrom onwards into new stream}
if TrimFrom > 0 then
begin
TempStream := TMCHMemoryStream.Create;
try
FIncomingStream.Seek(TrimFrom,soFromBeginning);
if TrimFrom < FIncomingStream.Size then
TempStream.CopyFrom(FIncomingStream,FIncomingStream.Size - TrimFrom);
finally
FIncomingStream.Free;
FIncomingStream := TempStream;
end;
end;
end;
end.