home *** CD-ROM | disk | FTP | other *** search
/ Chip 2000 October / Chip_2000-10_cd1.bin / zkuste / Delphi / navody / multithread / mchpipetransactions.pas < prev    next >
Pascal/Delphi Source File  |  1999-07-26  |  6KB  |  190 lines

  1. { 27-07-1999 12:46:19 AM > [martin on MARTIN] update: Bugfixing (0.5) /  }
  2. { 26-07-1999 12:05:12 AM > [martin on MARTIN] checked out /Bugfixing }
  3. { 10-05-1999 10:37:11 PM > [martin on MARTIN] checked out /Reformatting
  4.    according to Delphi guidelines. }
  5. { 10-05-1999 1:31:11 AM > [martin on MARTIN] update: Modifying to allow
  6.    for improved error mechanism (0.3) /  }
  7. { 08-05-1999 8:16:25 PM > [martin on MARTIN] checked out /Modifying to
  8.    allow for improved error mechanism }
  9. { 14-04-1999 11:59:15 PM > [martin on MARTIN] update: Changing dynamic
  10.    methods to virtual. (0.2) /  }
  11. { 14-04-1999 11:53:38 PM > [martin on MARTIN] checked out /Changing dynamic
  12.    methods to virtual. }
  13. { 06-04-1999 7:49:50 PM > [martin on MARTIN] checked out /Modifying Class
  14.    Names }
  15. { 06-04-1999 1:46:39 AM > [martin on MARTIN] check in: (0.0) Initial Version
  16.    / None }
  17. unit MCHPipeTransactions;
  18.  
  19. {Martin Harvey 2/12/98}
  20.  
  21. {A transaction manager suitable for the Pipe socket object.
  22.  
  23. I'm not toally happy with the original error handling architecture, and since
  24. I have to completely rewrite most of the ONCP stuff anyway, I might as well
  25. temporarily clear the situation up.
  26.  
  27. Reset will reset the transaction manager and DOPManager. It will not touch the
  28. underlying socket, which will be handled by the PipeONCPSession.
  29.  
  30. OnDisconnect will be handled by the ONCP and triggered when the socket indicates
  31. disconnection.
  32. OnFatalError will also be handled by the ONCP. However, it will trigger an automatic
  33. call to reset.
  34.  
  35. }
  36.  
  37. interface
  38.  
  39. uses MCHTransactions,Classes,MCHMemoryStream,MCHPipeSocket;
  40.  
  41. type
  42.   TMCHPipeTransactionManager = class(TMCHCustomTransactionManager)
  43.   private
  44.     FIncomingStream:TMCHMemoryStream;
  45.     FSocket:TMCHPipeSocket;
  46.     FTransactionStart,FTransactionEnd:integer;
  47.   protected
  48.     function GetActive:boolean;override;
  49.     procedure DoFatalError(Msg:string);override;
  50.   public
  51.     constructor Create;
  52.     destructor Destroy;override;
  53.     procedure WriteTransactionFromStream(ExternalIn:TStream);override;
  54.     procedure ReadTransactionToStream(ExternalOut:TStream);override;
  55.     procedure Reset;override;
  56.     {Socket handlers. Note that these are
  57.     automatically called by TMCHPipeSocket}
  58.     procedure HandleConnect;
  59.     procedure HandleDisconnect;
  60.     procedure HandleSockError;
  61.     procedure HandleSockRead;
  62.   published
  63.     property Socket:TMCHPipeSocket read FSocket write FSocket;
  64.     property OnFatalError;
  65.   end;
  66.  
  67. {NB: Events that I can trigger are:
  68.  
  69.      procedure DoTransactionRecieved;virtual;
  70.      procedure DoFatalError;virtual;
  71.      procedure DoDestroy;virtual;
  72. }
  73. implementation
  74.  
  75. constructor TMCHPipeTransactionManager.Create;
  76. begin
  77.   inherited Create; {TMCHCustomTransactionManager.Create creates DOPManager}
  78.   FIncomingStream := TMCHMemoryStream.Create;
  79. end;
  80.  
  81. function TMCHPipeTransactionManager.GetActive:boolean;
  82. begin
  83.   Result := FIncomingStream.Size > 0;
  84. end;
  85.  
  86. destructor TMCHPipeTransactionManager.Destroy;
  87. begin
  88.   FIncomingStream.Free;
  89.   inherited Destroy;
  90. end;
  91.  
  92. procedure TMCHPipeTransactionManager.DoFatalError(Msg:string);
  93. begin
  94.   Reset;
  95.   inherited DoFatalError(Msg);
  96. end;
  97.  
  98. procedure TMCHPipeTransactionManager.WriteTransactionFromStream(ExternalIn:TStream);
  99.  
  100. var
  101.   InStream:TMCHMemoryStream;
  102.   Size:integer;
  103.  
  104. begin
  105.   InStream := TMCHMemoryStream.Create;
  106.   try
  107.     Size := ExternalIn.Size;
  108.     InStream.WriteBuffer(Size,SizeOf(Size));
  109.     ExternalIn.Seek(0,soFromBeginning);
  110.     InStream.CopyFrom(ExternalIn,ExternalIn.Size);
  111.     Socket.WriteData(InStream);
  112.   finally
  113.     InStream.Free;
  114.   end;
  115. end;
  116.  
  117. procedure TMCHPipeTransactionManager.ReadTransactionToStream(ExternalOut:TStream);
  118.  
  119. begin
  120. {At this point, just copy the required amount of data}
  121.   FIncomingStream.Seek(FTransactionStart,soFromBeginning);
  122.   ExternalOut.CopyFrom(FIncomingStream,FTransactionEnd - FTransactionStart);
  123. end;
  124.  
  125. procedure TMCHPipeTransactionManager.Reset;
  126. begin
  127.   FIncomingStream.Clear;
  128.   inherited Reset;
  129. end;
  130.  
  131. procedure TMCHPipeTransactionManager.HandleConnect;
  132. begin
  133.   Reset;
  134. end;
  135.  
  136. procedure TMCHPipeTransactionManager.HandleDisconnect;
  137. begin
  138.   Reset;
  139. end;
  140.  
  141. procedure TMCHPipeTransactionManager.HandleSockError;
  142. begin
  143.   Reset;
  144. end;
  145.  
  146. procedure TMCHPipeTransactionManager.HandleSockRead;
  147.  
  148. var
  149.   TempStream:TMCHMemoryStream;
  150.   TrimFrom:integer;
  151.  
  152. begin
  153.   {Copy as much data as possible onto the end of our internal buffer}
  154.   FSocket.ReadData(FIncomingStream);
  155.   {Now see how many transactions we can extract}
  156.   TrimFrom := 0;
  157.   FTransactionStart := SizeOf(FTransactionEnd); {Start index at end of size field}
  158.   while FIncomingStream.Size >= (FTransactionStart) do
  159.   begin
  160.     FIncomingStream.Seek(FTransactionStart - SizeOf(FTransactionEnd),soFromBeginning);
  161.     FIncomingStream.ReadBuffer(FTransactionEnd,SizeOf(FTransactionEnd)); {read transaction size}
  162.     FTransactionEnd := FTransactionEnd + FTransactionStart; {Transaction end now at correct offset}
  163.     if FIncomingStream.Size >= FTransactionEnd then
  164.     begin
  165.       DoTransactionRecieved; {This will hopefully call ReadTransactionToStream}
  166.       TrimFrom := FTransactionEnd;
  167.     end;
  168.     {Now need to update readtransactionstart}
  169.     FTransactionStart := FTransactionEnd + SizeOf(FTransactionEnd);
  170.   end;
  171.   {At which point we have read all the data we can}
  172.   {Now need to remove all non required data}
  173.   {Now copy all data from TrimFrom onwards into new stream}
  174.   if TrimFrom > 0 then
  175.   begin
  176.     TempStream := TMCHMemoryStream.Create;
  177.     try
  178.       FIncomingStream.Seek(TrimFrom,soFromBeginning);
  179.       if TrimFrom < FIncomingStream.Size then
  180.         TempStream.CopyFrom(FIncomingStream,FIncomingStream.Size - TrimFrom);
  181.     finally
  182.       FIncomingStream.Free;
  183.       FIncomingStream := TempStream;
  184.     end;
  185.   end;
  186. end;
  187.  
  188. end.
  189.  
  190.