THRIFT-1872 issues with TBufferedTransport buffer
authorJens Geyer <jensg@apache.org>
Thu, 7 Mar 2013 19:40:59 +0000 (20:40 +0100)
committerJens Geyer <jensg@apache.org>
Thu, 7 Mar 2013 19:40:59 +0000 (20:40 +0100)
Patch: Jens Geyer

lib/delphi/src/Thrift.Transport.pas

index 0664772..8668e5a 100644 (file)
@@ -26,6 +26,7 @@ interface
 uses\r
   Classes,\r
   SysUtils,\r
+  Math,\r
   Sockets,\r
   Generics.Collections,\r
   Thrift.Collections,\r
@@ -202,7 +203,8 @@ type
   private\r
     FStream : IThriftStream;\r
     FBufSize : Integer;\r
-    FBuffer : TMemoryStream;\r
+    FReadBuffer : TMemoryStream;\r
+    FWriteBuffer : TMemoryStream;\r
   protected\r
     procedure Write( const buffer: TBytes; offset: Integer; count: Integer); override;\r
     function Read( var buffer: TBytes; offset: Integer; count: Integer): Integer; override;\r
@@ -769,15 +771,20 @@ procedure TBufferedStreamImpl.Close;
 begin\r
   Flush;\r
   FStream := nil;\r
-  FBuffer.Free;\r
-  FBuffer := nil;\r
+\r
+  FReadBuffer.Free;\r
+  FReadBuffer := nil;\r
+\r
+  FWriteBuffer.Free;\r
+  FWriteBuffer := nil;\r
 end;\r
 \r
 constructor TBufferedStreamImpl.Create( const AStream: IThriftStream; ABufSize: Integer);\r
 begin\r
   FStream := AStream;\r
   FBufSize := ABufSize;\r
-  FBuffer := TMemoryStream.Create;\r
+  FReadBuffer := TMemoryStream.Create;\r
+  FWriteBuffer := TMemoryStream.Create;\r
 end;\r
 \r
 destructor TBufferedStreamImpl.Destroy;\r
@@ -793,21 +800,23 @@ var
 begin\r
   if IsOpen then\r
   begin\r
-    len := FBuffer.Size;\r
+    len := FWriteBuffer.Size;\r
     if len > 0 then\r
     begin\r
       SetLength( buf, len );\r
-      FBuffer.Position := 0;\r
-      FBuffer.Read( Pointer(@buf[0])^, len );\r
+      FWriteBuffer.Position := 0;\r
+      FWriteBuffer.Read( Pointer(@buf[0])^, len );\r
       FStream.Write( buf, 0, len );\r
     end;\r
-    FBuffer.Clear;\r
+    FWriteBuffer.Clear;\r
   end;\r
 end;\r
 \r
 function TBufferedStreamImpl.IsOpen: Boolean;\r
 begin\r
-  Result := (FBuffer <> nil) and ( FStream <> nil);\r
+  Result := (FWriteBuffer <> nil)\r
+        and (FReadBuffer <> nil)\r
+        and (FStream <> nil);\r
 end;\r
 \r
 procedure TBufferedStreamImpl.Open;\r
@@ -822,25 +831,27 @@ var
 begin\r
   inherited;\r
   Result := 0;\r
-  if count > 0 then\r
+  if IsOpen then\r
   begin\r
-    if IsOpen then\r
-    begin\r
-      if FBuffer.Position >= FBuffer.Size then\r
+    while count > 0 do begin\r
+\r
+      if FReadBuffer.Position >= FReadBuffer.Size then\r
       begin\r
-        FBuffer.Clear;\r
+        FReadBuffer.Clear;\r
         SetLength( tempbuf, FBufSize);\r
         nRead := FStream.Read( tempbuf, 0, FBufSize );\r
-        if nRead > 0 then\r
-        begin\r
-          FBuffer.WriteBuffer( Pointer(@tempbuf[0])^, nRead );\r
-          FBuffer.Position := 0;\r
-        end;\r
+        if nRead = 0 then Break; // avoid infinite loop\r
+\r
+        FReadBuffer.WriteBuffer( Pointer(@tempbuf[0])^, nRead );\r
+        FReadBuffer.Position := 0;\r
       end;\r
 \r
-      if FBuffer.Position < FBuffer.Size then\r
+      if FReadBuffer.Position < FReadBuffer.Size then\r
       begin\r
-        Result := FBuffer.Read( Pointer(@buffer[offset])^, count );\r
+        nRead  := Min( FReadBuffer.Size - FReadBuffer.Position, count);\r
+        Inc( Result, FReadBuffer.Read( Pointer(@buffer[offset])^, nRead));\r
+        Dec( count, nRead);\r
+        Inc( offset, nRead);\r
       end;\r
     end;\r
   end;\r
@@ -854,15 +865,15 @@ begin
 \r
   if IsOpen then\r
   begin\r
-    len := FBuffer.Size;\r
+    len := FReadBuffer.Size;\r
   end;\r
 \r
   SetLength( Result, len);\r
 \r
   if len > 0 then\r
   begin\r
-    FBuffer.Position := 0;\r
-    FBuffer.Read( Pointer(@Result[0])^, len );\r
+    FReadBuffer.Position := 0;\r
+    FReadBuffer.Read( Pointer(@Result[0])^, len );\r
   end;\r
 end;\r
 \r
@@ -873,8 +884,8 @@ begin
   begin\r
     if IsOpen then\r
     begin\r
-      FBuffer.Write( Pointer(@buffer[offset])^, count );\r
-      if FBuffer.Size > FBufSize then\r
+      FWriteBuffer.Write( Pointer(@buffer[offset])^, count );\r
+      if FWriteBuffer.Size > FBufSize then\r
       begin\r
         Flush;\r
       end;\r