DataMuseum.dkPresents historical artifacts from the history of: Rational R1000/400 Tapes |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about Rational R1000/400 Tapes Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - downloadIndex: ┃ B T ┃
Length: 15013 (0x3aa5) Types: TextFile Names: »B«
└─⟦bad92a95e⟧ Bits:30000535 8mm tape, Rational 1000, RPC 1_0_2 └─ ⟦bb34fe6e2⟧ »DATA« └─⟦15d8b76c6⟧ └─⟦this⟧
package body Transport_Stream is Buffer_Size : constant := 2 ** 10; Null_Socket_Id : constant Transport_Defs.Socket_Id := Transport_Defs.Null_Socket_Id; subtype Data_Count is Natural range 0 .. Buffer_Size; subtype Data_Index is Data_Count range 0 .. Data_Count'Last - 1; type Buffer_Type is record First : Data_Index; Count : Data_Count; Data : Byte_Defs.Byte_String (Data_Index'First .. Data_Index'Last); end record; type Pool_Type (Network_Length : Natural; Remote_Host_Length : Natural; Remote_Socket_Length : Natural; Local_Socket_Length : Natural) is record Next : Pool_List; Idle : Stream_List; Network : Transport_Defs.Network_Name (1 .. Network_Length); Remote_Host : Transport_Defs.Host_Id (1 .. Remote_Host_Length); Remote_Socket : Transport_Defs.Socket_Id (1 .. Remote_Socket_Length); Local_Socket : Transport_Defs.Socket_Id (1 .. Local_Socket_Length); end record; type Stream_Type is record Next : Stream_List := null; Pool : Pool_Id := null; Unique : Unique_Id := Null_Unique_Id; Referenced : Boolean := False; Connection : Transport.Connection_Id; Transmit, Receive : Buffer_Type; end record; function Is_Null (Stream : Stream_Id) return Boolean is begin return Stream.Stream = null or else Stream.Unique /= Stream.Stream.Unique; end Is_Null; procedure Check_Non_Null (Stream : Stream_Id) is begin if Is_Null (Stream) then raise Not_Connected; end if; end Check_Non_Null; procedure Initialize (Buffer : out Buffer_Type) is begin Buffer.First := Buffer.Data'First; Buffer.Count := 0; end Initialize; function Equals (X, Y : Transport_Defs.Network_Name) return Boolean is begin return Transport_Defs."=" (Transport_Defs.Normalize (X), Transport_Defs.Normalize (Y)); end Equals; function Equals (X, Y : Transport_Defs.Host_Id) return Boolean is begin return Transport_Defs."=" (Transport_Defs.Normalize (X), Transport_Defs.Normalize (Y)); end Equals; function Equals (X, Y : Transport_Defs.Socket_Id) return Boolean is begin return Transport_Defs."=" (Transport_Defs.Normalize (X), Transport_Defs.Normalize (Y)); end Equals; task Worker is entry Create (Pool : out Pool_Id; Network : Transport_Defs.Network_Name; Remote_Host : Transport_Defs.Host_Id; Remote_Socket : Transport_Defs.Socket_Id; Local_Socket : Transport_Defs.Socket_Id); entry Allocate (Stream : out Stream_Id); entry Allocate (Stream : out Stream_Id; Pool : Pool_Id); entry Allocate (Stream : out Stream_Id; Network : Transport_Defs.Network_Name; Remote_Host : Transport_Defs.Host_Id; Remote_Socket : Transport_Defs.Socket_Id); entry Deallocate (Stream : Stream_Id); entry Disconnect (Stream : Stream_Id); entry Scavenge (Pool : Pool_Id := null); entry Destroy (Pool : Pool_Id := null); entry Finalize; end Worker; function Create (Network : Transport_Defs.Network_Name; Remote_Host : Transport_Defs.Host_Id; Remote_Socket : Transport_Defs.Socket_Id; Local_Socket : Transport_Defs.Socket_Id := Transport_Defs.Null_Socket_Id) return Pool_Id is Pool : Pool_Id; begin Worker.Create (Pool, Network, Remote_Host, Remote_Socket, Local_Socket); return Pool; end Create; procedure Scavenge (Pool : Pool_Id) is begin Worker.Scavenge (Pool); end Scavenge; procedure Scavenge is begin Worker.Scavenge; end Scavenge; procedure Destroy (Pool : Pool_Id) is begin Worker.Destroy (Pool); end Destroy; task Scavenger is entry Finalize; end Scavenger; task body Scavenger is begin loop select accept Finalize; exit; or terminate; end select; Scavenge; end loop; end Scavenger; procedure Finalize is begin begin Worker.Finalize; exception when Tasking_Error => null; end; begin Scavenger.Finalize; exception when Tasking_Error => null; end; end Finalize; procedure Allocate (Stream : out Stream_Id; Connection : Transport.Connection_Id) is The_Stream : Stream_Id; begin Worker.Allocate (The_Stream); The_Stream.Stream.Connection := Connection; Stream := The_Stream; exception when Tasking_Error => raise Not_Connected; end Allocate; procedure Check_Ok (Status : Transport_Defs.Status_Code) is begin case Status is when Transport_Defs.Ok => null; when others => raise Not_Connected; end case; end Check_Ok; procedure Get_Connected (Stream : Stream_Id; Is_New : out Boolean; Network : Transport_Defs.Network_Name; Host : Transport_Defs.Host_Id; Socket : Transport_Defs.Socket_Id) is Connection : Transport.Connection_Id renames Stream.Stream.Connection; Status : Transport_Defs.Status_Code; begin Check_Non_Null (Stream); if Transport.Is_Connected (Connection) then Is_New := False; else Is_New := True; Initialize (Stream.Stream.Transmit); Initialize (Stream.Stream.Receive); if Transport.Is_Open (Connection) then Transport.Disconnect (Connection); else Transport.Close (Connection); Transport.Open (Connection, Status, Network); Check_Ok (Status); end if; Transport.Connect (Connection, Status, Host, Socket); Check_Ok (Status); end if; end Get_Connected; procedure Allocate (Stream : out Stream_Id; Pool : Pool_Id; Is_New : out Boolean) is The_Stream : Stream_Id; begin Worker.Allocate (The_Stream, Pool); Stream := The_Stream; Get_Connected (The_Stream, Is_New, Pool.Network, Pool.Remote_Host, Pool.Remote_Socket); exception when Not_Connected | Tasking_Error => Disconnect (The_Stream); raise Not_Connected; end Allocate; procedure Allocate (Stream : out Stream_Id; Is_New : out Boolean; Network : Transport_Defs.Network_Name; Host : Transport_Defs.Host_Id; Socket : Transport_Defs.Socket_Id) is The_Stream : Stream_Id; begin Worker.Allocate (The_Stream, Network, Host, Socket); Stream := The_Stream; Get_Connected (The_Stream, Is_New, Network, Host, Socket); exception when Not_Connected | Tasking_Error => Disconnect (The_Stream); raise Not_Connected; end Allocate; procedure Deallocate (Stream : Stream_Id) is begin if not Is_Null (Stream) then Worker.Deallocate (Stream); end if; exception when Tasking_Error => Disconnect (Stream); end Deallocate; function Connection (Stream : Stream_Id) return Transport.Connection_Id is begin Check_Non_Null (Stream); return Stream.Stream.Connection; end Connection; function Unique (Stream : Stream_Id) return Unique_Id is begin return Stream.Unique; end Unique; procedure Disconnect (Stream : Stream_Id) is begin if not Is_Null (Stream) then Worker.Disconnect (Stream); end if; exception when Tasking_Error => Stream.Stream.Unique := Null_Unique_Id; Transport.Close (Stream.Stream.Connection); end Disconnect; procedure Check (Status : Transport_Defs.Status_Code) is begin case Status is when Transport_Defs.Ok | Transport_Defs.Timed_Out => null; when others => raise Not_Connected; end case; end Check; procedure Transmit (Connection : Transport.Connection_Id; Data : Byte_Defs.Byte_String; More : Boolean := False) is Status : Transport_Defs.Status_Code; Count : Natural; Total : Natural := 0; begin loop Transport.Transmit (Connection, Status, Data (Data'First + Total .. Data'Last), Count, More => More); Total := Total + Count; exit when Total >= Data'Length; Check (Status); end loop; end Transmit; procedure Receive (Connection : Transport.Connection_Id; Data : out Byte_Defs.Byte_String) is Status : Transport_Defs.Status_Code; Count : Natural; Total : Natural := 0; begin loop Transport.Receive (Connection, Status, Data (Data'First + Total .. Data'Last), Count); Total := Total + Count; exit when Total >= Data'Length; Check (Status); end loop; end Receive; procedure Transmit (Into : Stream_Id; Data : Byte_Defs.Byte_String) is begin Check_Non_Null (Into); if Data'Length > 0 then declare Buf : Buffer_Type renames Into.Stream.Transmit; Connection : Transport.Connection_Id renames Into.Stream.Connection; begin pragma Assert (Buf.First = Data_Index'First); if Buf.Count + Data'Length < Data_Count'Last then Buf.Data (Buf.First + Buf.Count .. Buf.First + Buf.Count + Data'Length - 1) := Data; Buf.Count := Buf.Count + Data'Length; else Transmit (Connection, Buf.Data (Buf.First .. Buf.First + Buf.Count - 1)); Transmit (Connection, Data); Buf.Count := 0; end if; end; end if; exception when Not_Connected => Disconnect (Into); raise; end Transmit; procedure Receive (From : Stream_Id; Data : out Byte_Defs.Byte_String) is begin Check_Non_Null (From); if Data'Length > 0 then -- If its <= 0, then we're done. Receiving 0 bytes is easy. declare Buf : Buffer_Type renames From.Stream.Receive; Connection : Transport.Connection_Id renames From.Stream.Connection; Status : Transport_Defs.Status_Code; begin if Buf.Count = 0 then -- nothing at all in the buffer. pragma Assert (Buf.First = Buf.Data'First); if Data'Length >= Buf.Data'Length then -- bypass the buffer: receive right into Data. Receive (Connection, Data); return; else -- wait for some data (any data) to arrive. loop Transport.Receive (Connection, Status, Buf.Data, Buf.Count); exit when Buf.Count > 0; Check (Status); end loop; end if; end if; pragma Assert (Buf.First + Buf.Count - 1 <= Data_Index'Last); if Buf.Count >= Data'Length then -- All the data we need are in the buffer. Data := Buf.Data (Buf.First .. Buf.First + Data'Length - 1); Buf.Count := Buf.Count - Data'Length; if Buf.Count = 0 then Buf.First := Data_Index'First; else Buf.First := Buf.First + Data'Length; end if; else -- Clean out the buffer: Data (Data'First .. Data'First + Buf.Count - 1) := Buf.Data (Buf.First .. Buf.First + Buf.Count - 1); -- Receive the rest of the data straight into Data: Receive (Connection, Data (Data'First + Buf.Count .. Data'Last)); Buf.First := Buf.Data'First; Buf.Count := 0; end if; end; end if; exception when Not_Connected => Disconnect (From); raise; end Receive; procedure Flush_Transmit_Buffer (Stream : Stream_Id) is begin Check_Non_Null (Stream); declare Buf : Buffer_Type renames Stream.Stream.Transmit; begin Transmit (Stream.Stream.Connection, Buf.Data (Buf.Data'First .. Buf.Data'First + Buf.Count - 1), More => False); Buf.Count := 0; end; exception when Not_Connected => Disconnect (Stream); raise; end Flush_Transmit_Buffer; function Flush_Receive_Buffer (Stream : Stream_Id) return Byte_Defs.Byte_String is begin Check_Non_Null (Stream); declare Buf : Buffer_Type renames Stream.Stream.Receive; Answer : constant Byte_Defs.Byte_String := Buf.Data (Buf.First .. Buf.First + Buf.Count - 1); begin Buf.First := Buf.Data'First; Buf.Count := 0; return Answer; end; exception when Not_Connected => Disconnect (Stream); raise; end Flush_Receive_Buffer; task body Worker is separate; end Transport_Stream;