DataMuseum.dk

Presents historical artifacts from the history of:

Rational R1000/400 Tapes

This is an automatic "excavation" of a thematic subset of
artifacts from Datamuseum.dk's BitArchive.

See our Wiki for more about Rational R1000/400 Tapes

Excavated with: AutoArchaeologist - Free & Open Source Software.


top - metrics - download
Index: B T

⟦b9843e569⟧ TextFile

    Length: 21731 (0x54e3)
    Types: TextFile
    Names: »B«

Derivation

└─⟦180fe333a⟧ Bits:30000405 8mm tape, Rational 1000, SW CATALOG, 10_20_0
└─⟦180fe333a⟧ Bits:30000537 8mm tape, Rational 1000, SW Catalog 10_20_0
    └─⟦5cb1d1d7f⟧ »DATA« 
        └─⟦3b1ee7bd8⟧ 
            └─⟦this⟧ 

TextFile

with Bounded_String;  
with Calendar;  
with Daemon;  
with Debug_Tools;  
with Direct_Io;  
with Io;  
with Log;  
with Operator;  
with Pipe;  
with Profile;  
with Context;  
with Logfile_Library;  
with System_Utilities;  
with Time_Utilities;

package body Reboot_Server is

    Revision : constant String := "804-1";
    Username_Max_Length : constant := 20;  
    type Command is (Cancel_Next, Change_Day, Change_Time, Idle, Kill, Status);  
    type Weekday is (Mon, Tue, Wed, Thu, Fri, Sat, Sun);  
    type Boolean_Week is array (Weekday'First .. Weekday'Last) of Boolean;  
    type Message_Descriptor is  
        record  
            Command_Issued : Command := Idle;  
            For_Day : Weekday;  
            Username : Bounded_String.Variable_String  
                          (Maximum_Length => Username_Max_Length) :=  
               Bounded_String.Value ("startup", Username_Max_Length);  
            Target_Days : Boolean_Week := (others => False);  
            Shutdown : String (1 .. 5) := "03:00";  
            Deadline : String (1 .. 5) := "07:00";  
            Cancel_Next : Boolean := False;  
            Last_Reboot : Calendar.Time;  
        end record;

    package Tso is new Pipe.Type_Specific_Operations (Message_Descriptor);

    To_Server_Pipe_Name : constant String := ".input";  
    From_Server_Pipe_Name : constant String := ".output";  
    From_Server,  
    To_Server : Pipe.Handle;  
    Receive_Message,  
    Send_Message : Message_Descriptor;  
    Server_Not_Running : exception;

    procedure Display (Data : Message_Descriptor) is  
        function Get_Message_Kind (For_Command : Command; To_Display : Command)  
                                  return Profile.Msg_Kind is  
        begin  
            if For_Command = To_Display then  
                return Profile.Positive_Msg;  
            else  
                return Profile.Note_Msg;  
            end if;  
        end Get_Message_Kind;  
    begin  
        Log.Put_Line (Message => "[Reboot Server command " &  
                                    Command'Image (Data.Command_Issued) &  
                                    " issued by " &  
                                    Bounded_String.Image (Data.Username) & "]",  
                      Kind => Profile.Auxiliary_Msg);  
        Log.Put_Line (Message => "Shutdown => " & Data.Shutdown &  
                                    ", Deadline => " & Data.Deadline,  
                      Kind => Get_Message_Kind  
                                 (Data.Command_Issued, Change_Time));  
        Log.Put_Line (Message =>  
                         "Cancel_Next => " & Boolean'Image (Data.Cancel_Next),  
                      Kind => Get_Message_Kind  
                                 (Data.Command_Issued, Cancel_Next));  
        Log.Put_Line (Message =>  
                         "Target_Days (Mon => " &  
                            Boolean'Image (Data.Target_Days (Mon)) &  
                            ", Tue => " &  
                            Boolean'Image (Data.Target_Days (Tue)) &  
                            ", Wed => " &  
                            Boolean'Image (Data.Target_Days (Wed)) &  
                            ", Thu => " &  
                            Boolean'Image (Data.Target_Days (Thu)) &  
                            ", Fri => " &  
                            Boolean'Image (Data.Target_Days (Fri)) &  
                            ", Sat => " &  
                            Boolean'Image (Data.Target_Days (Sat)) &  
                            ", Sun => " &  
                            Boolean'Image (Data.Target_Days (Sun)) & ")",  
                      Kind => Get_Message_Kind (Data.Command_Issued,  
                                                Change_Day));  
        Log.Put_Line (Message =>  
                         "Last rebooted at " &  
                            Time_Utilities.Image (Time_Utilities.Convert_Time  
                                                     (Data.Last_Reboot)));  
        Log.Put_Line (Message => "[End of Reboot Server command " &  
                                    Command'Image (Data.Command_Issued) & "]",  
                      Kind => Profile.Auxiliary_Msg);
        Log.Save;
    end Display;

    procedure Server is  
        package Dio is new Direct_Io (Message_Descriptor);  
        Daemon_In_Progress_Counter : Natural := 0;  
        Daemon_In_Progress_Counter_Threshold : constant Natural := 10 * 60;  
        Data_File : Dio.File_Type;  
        Data_File_Name : constant String := ".data";  
        Hibernate_Interval : constant Duration := 4.0;  
        Logfile_Prefix : constant String := ".reboot_server_log_";  
        Permanent_Data,  
        Temporary_Data,  
        Volatile_Data : Message_Descriptor;  
        Shutdown_In_Progress : Boolean := False;  
        Terminate_Server : exception;

        procedure Read_Permanent_Data (Data : in out Message_Descriptor) is  
        begin  
            declare  
            begin  
                Dio.Open (File => Data_File,  
                          Mode => Dio.Inout_File,  
                          Name => Context & Data_File_Name);  
                Dio.Read (File => Data_File, Item => Data, From => 1);  
                Dio.Close (File => Data_File);  
            exception  
                when Dio.Name_Error =>  
                    Dio.Create (File => Data_File,  
                                Mode => Dio.Inout_File,  
                                Name => Context & Data_File_Name);  
                    Dio.Write (File => Data_File, Item => Data, To => 1);  
                    Dio.Close (File => Data_File);  
            end;  
        end Read_Permanent_Data;

        procedure Write_Permanent_Data (Data : Message_Descriptor) is  
        begin  
            Dio.Open (File => Data_File,  
                      Mode => Dio.Inout_File,  
                      Name => Context & Data_File_Name);  
            Dio.Write (File => Data_File, Item => Data, To => 1);  
            Dio.Close (File => Data_File);  
        end Write_Permanent_Data;

    begin  
        declare  
        begin  
            Pipe.Open (Pipe => From_Server,  
                       Mode => Pipe.Shared_Write,  
                       Name => Context & From_Server_Pipe_Name);  
        exception  
            when Pipe.Name_Error =>  
                Pipe.Create (Pipe => From_Server,  
                             Mode => Pipe.Exclusive,  
                             Name => Context & From_Server_Pipe_Name);  
                Pipe.Close (Pipe => From_Server);  
                Pipe.Open (Pipe => From_Server,  
                           Mode => Pipe.Shared_Write,  
                           Name => Context & From_Server_Pipe_Name);  
        end;  
        declare  
        begin  
            Pipe.Open (Pipe => To_Server,  
                       Mode => Pipe.Shared_Read,  
                       Name => Context & To_Server_Pipe_Name);  
        exception  
            when Pipe.Name_Error =>  
                Pipe.Create (Pipe => To_Server,  
                             Mode => Pipe.Exclusive,  
                             Name => Context & To_Server_Pipe_Name);  
                Pipe.Close (Pipe => To_Server);  
                Pipe.Open (Pipe => To_Server,  
                           Mode => Pipe.Shared_Read,  
                           Name => Context & To_Server_Pipe_Name);  
        end;  
        Operator.Enable_Privileges (Enable => True);  
        Read_Permanent_Data (Permanent_Data);  
        Volatile_Data := Permanent_Data;  
        Profile.Set_Response (Reaction => Profile.Persevere,  
                              Filter => Profile.Full,  
                              Prefixes => Profile.Default_Prefixes);  
        Io.Set_Output (Name => Logfile_Library & Logfile_Prefix &  
                                  Time_Utilities.Image  
                                     (Date => Time_Utilities.Convert_Time  
                                                 (Calendar.Clock),  
                                      Date_Style => Time_Utilities.Ada,  
                                      Time_Style => Time_Utilities.Ada));  
        Log.Put_Line (Message =>
                         "Reboot Server revision " & Revision & " started",  
                      Kind => Profile.Positive_Msg);  
        Display (Permanent_Data);  
        loop  
            declare  
            begin  
                Temporary_Data.Command_Issued := Idle;  
                Tso.Read (Pipe => To_Server,  
                          Message => Temporary_Data,  
                          Max_Wait => Pipe.Dont_Wait);  
                case Temporary_Data.Command_Issued is  
                    when Cancel_Next =>  
                        Volatile_Data.Command_Issued :=  
                           Temporary_Data.Command_Issued;  
                        Volatile_Data.Username := Temporary_Data.Username;  
                        Volatile_Data.Cancel_Next := Temporary_Data.Cancel_Next;  
                        Tso.Write (Pipe => From_Server,  
                                   Message => Volatile_Data);  
                        Display (Volatile_Data);  
                    when Change_Day =>  
                        Volatile_Data.Command_Issued :=  
                           Temporary_Data.Command_Issued;  
                        Volatile_Data.Username := Temporary_Data.Username;  
                        Volatile_Data.Target_Days (Temporary_Data.For_Day) :=  
                           Temporary_Data.Target_Days (Temporary_Data.For_Day);  
                        Permanent_Data.Target_Days (Temporary_Data.For_Day) :=  
                           Temporary_Data.Target_Days (Temporary_Data.For_Day);  
                        Tso.Write (Pipe => From_Server,  
                                   Message => Volatile_Data);  
                        Write_Permanent_Data (Permanent_Data);  
                        Display (Volatile_Data);  
                    when Change_Time =>  
                        Volatile_Data.Command_Issued :=  
                           Temporary_Data.Command_Issued;  
                        Volatile_Data.Username := Temporary_Data.Username;  
                        Volatile_Data.Shutdown := Temporary_Data.Shutdown;  
                        Volatile_Data.Deadline := Temporary_Data.Deadline;  
                        Permanent_Data.Shutdown := Temporary_Data.Shutdown;  
                        Permanent_Data.Deadline := Temporary_Data.Deadline;  
                        Tso.Write (Pipe => From_Server,  
                                   Message => Volatile_Data);  
                        Write_Permanent_Data (Permanent_Data);  
                        Display (Volatile_Data);  
                    when Idle =>  
                        null;  
                    when Kill =>  
                        Tso.Write (Pipe => From_Server,  
                                   Message => Volatile_Data);  
                        raise Terminate_Server;  
                    when Status =>  
                        Volatile_Data.Command_Issued :=  
                           Temporary_Data.Command_Issued;  
                        Volatile_Data.Username := Temporary_Data.Username;  
                        Tso.Write (Pipe => From_Server,  
                                   Message => Volatile_Data);  
                        Display (Volatile_Data);  
                end case;  
            exception  
                when Pipe.Use_Error | Pipe.End_Error =>  
                    null;  
            end;  
            declare  
                use Calendar;  
                use Time_Utilities;  
                Weekday_Today : constant String := Image (Day_Of_Week (Clock));  
                Shutdown : Calendar.Time := Convert_Time  
                                               (Value (Volatile_Data.Shutdown));  
                Deadline : Calendar.Time := Convert_Time  
                                               (Value (Volatile_Data.Deadline));  
            begin  
                if Volatile_Data.Target_Days (Weekday'Value  
                                                 (Weekday_Today (1 .. 3))) and  
                   Clock > Shutdown and Clock < Deadline and  
                   Permanent_Data.Last_Reboot < Shutdown then  
                    Shutdown_In_Progress := True;  
                    if not Volatile_Data.Cancel_Next then  
                        if not Daemon.In_Progress ("disk") then  
                            Log.Put_Line (Message =>  
                                             "Shutting down the environment",  
                                          Kind => Profile.Positive_Msg);  
                            Permanent_Data.Last_Reboot := Clock;  
                            Write_Permanent_Data (Permanent_Data);  
                            Volatile_Data := Permanent_Data;
                            Operator.Shutdown_Warning (Interval => 120.0);
                            Operator.Shutdown
                               (Reason => "COPS",
                                Explanation => "Shutdown by Reboot Server");
                            raise Terminate_Server;  
                        else  
                            Daemon_In_Progress_Counter :=  
                               Daemon_In_Progress_Counter +  
                                  Natural (Hibernate_Interval);  
                            if Daemon_In_Progress_Counter >=  
                               Daemon_In_Progress_Counter_Threshold then  
                                Log.Put_Line  
                                   (Message =>  
                                       "Waiting for the disk daemon to complete");  
                                Daemon_In_Progress_Counter := 0;  
                            end if;  
                        end if;  
                    end if;  
                else  
                    if Shutdown_In_Progress then  
                        Log.Put_Line (Message => "Cancel_Next set to FALSE",  
                                      Kind => Profile.Positive_Msg);  
                        Volatile_Data := Permanent_Data;  
                        Shutdown_In_Progress := False;  
                    end if;  
                end if;  
                delay Hibernate_Interval;  
            end;  
        end loop;  
    exception  
        when others =>  
            Pipe.Close (Pipe => From_Server);  
            Pipe.Close (Pipe => To_Server);  
            if Dio.Is_Open (File => Data_File) then  
                Dio.Close (File => Data_File);  
            end if;  
            Log.Put_Line (Message => "Reboot Server terminated with " &  
                                        Debug_Tools.Get_Exception_Name,  
                          Kind => Profile.Exception_Msg);  
            Io.Reset_Output;  
    end Server;

    function Exchange_Server_Messages  
                (Send_Message : Message_Descriptor) return Message_Descriptor is  
        Receive_Message : Message_Descriptor;  
    begin  
        Pipe.Open (Pipe => From_Server,  
                   Mode => Pipe.Shared_Read,  
                   Name => Context & From_Server_Pipe_Name);  
        Pipe.Open (Pipe => To_Server,  
                   Mode => Pipe.Shared_Write,  
                   Name => Context & To_Server_Pipe_Name);  
        Tso.Write (Pipe => To_Server, Message => Send_Message);  
        while Pipe.Current_Message_Count (Pipe => From_Server) /= 0 loop  
            declare  
            begin  
                Tso.Read (Pipe => From_Server,  
                          Message => Receive_Message,  
                          Max_Wait => Pipe.Dont_Wait);  
            exception  
                when Pipe.End_Error =>  
                    null;  
            end;  
        end loop;  
        return Tso.Read (Pipe => From_Server, Max_Wait => 5.0);  
        Pipe.Close (Pipe => From_Server);  
        Pipe.Close (Pipe => To_Server);  
    exception  
        when Pipe.Name_Error | Pipe.Use_Error =>  
            raise Server_Not_Running;  
    end Exchange_Server_Messages;

    procedure Cancel_Next (Reboot : Boolean := False;  
                           Response : String := "<PROFILE>") is  
    begin  
        Profile.Set (Profile.Value (Response));  
        Send_Message.Command_Issued := Cancel_Next;  
        Send_Message.Username :=  
           Bounded_String.Value (System_Utilities.User_Name,  
                                 Username_Max_Length);  
        Send_Message.Cancel_Next := Reboot;  
        Receive_Message := Exchange_Server_Messages (Send_Message);  
        Display (Receive_Message);  
    exception  
        when Server_Not_Running =>  
            Log.Put_Line (Message => "Unable to Cancel_Next",  
                          Kind => Profile.Error_Msg);  
            Log.Put_Line (Message => "Reboot Server not running",  
                          Kind => Profile.Negative_Msg);  
    end Cancel_Next;

    procedure Change_Day (Day : String := "ddd";  
                          Enable : Boolean := False;  
                          Response : String := "<PROFILE>") is  
    begin  
        Profile.Set (Profile.Value (Response));  
        Send_Message.Command_Issued := Change_Day;  
        Send_Message.For_Day := Weekday'Value (Day (1 .. 3));  
        Send_Message.Username :=  
           Bounded_String.Value (System_Utilities.User_Name,  
                                 Username_Max_Length);  
        Send_Message.Target_Days (Send_Message.For_Day) := Enable;  
        Receive_Message := Exchange_Server_Messages (Send_Message);  
        Display (Receive_Message);  
    exception  
        when Server_Not_Running =>  
            Log.Put_Line (Message => "Unable to Change_Day",  
                          Kind => Profile.Error_Msg);  
            Log.Put_Line (Message => "Reboot Server not running",  
                          Kind => Profile.Negative_Msg);  
    end Change_Day;

    procedure Change_Time (Shutdown : String := "hh:mm";  
                           Deadline : String := "hh:mm";  
                           Response : String := "<PROFILE>") is  
        Valid_Shutdown : String (1 .. 5);  
        Valid_Deadline : String (1 .. 5);  
        Time_Not_Valid : exception;  
        function Check_And_Convert_Time (T1 : String) return String is  
            T2 : String (1 .. 5);  
            T3 : Time_Utilities.Time;  
        begin  
            if T1 (T1'First .. T1'First + 1) = "24" then  
                T2 := "00" & T1 (T1'First + 2 .. T1'Last);  
            else  
                T2 := T1;  
            end if;  
            T3 := Time_Utilities.Value (T2);  
            return T2;  
        exception  
            when others =>  
                raise Time_Not_Valid;  
        end Check_And_Convert_Time;  
    begin  
        Profile.Set (Profile.Value (Response));  
        Valid_Shutdown := Check_And_Convert_Time (Shutdown);  
        Valid_Deadline := Check_And_Convert_Time (Deadline);  
        Send_Message.Command_Issued := Change_Time;  
        Send_Message.Username :=  
           Bounded_String.Value (System_Utilities.User_Name,  
                                 Username_Max_Length);  
        Send_Message.Shutdown := Valid_Shutdown;  
        Send_Message.Deadline := Valid_Deadline;  
        Receive_Message := Exchange_Server_Messages (Send_Message);  
        Display (Receive_Message);  
    exception  
        when Server_Not_Running =>  
            Log.Put_Line (Message => "Unable to Change_Time",  
                          Kind => Profile.Error_Msg);  
            Log.Put_Line (Message => "Reboot Server not running",  
                          Kind => Profile.Negative_Msg);  
        when Time_Not_Valid =>  
            Log.Put_Line (Message => "Unable to Change_time",  
                          Kind => Profile.Error_Msg);  
            Log.Put_Line (Message => "invalid time - Shutdown => " & Shutdown &  
                                        ", Deadline => " & Deadline,  
                          Kind => Profile.Negative_Msg);  
    end Change_Time;

    procedure Kill (Response : String := "<PROFILE>") is  
    begin  
        Send_Message.Command_Issued := Kill;  
        Send_Message.Username :=  
           Bounded_String.Value (System_Utilities.User_Name,  
                                 Username_Max_Length);  
        Receive_Message := Exchange_Server_Messages (Send_Message);  
        Log.Put_Line (Message => "Reboot Server killed",  
                      Kind => Profile.Positive_Msg);  
    exception  
        when Server_Not_Running =>  
            Log.Put_Line (Message => "Reboot Server already killed",  
                          Kind => Profile.Warning_Msg);  
    end Kill;

    procedure Status (Response : String := "<PROFILE>") is  
    begin  
        Profile.Set (Profile.Value (Response));  
        Send_Message.Command_Issued := Status;  
        Send_Message.Username :=  
           Bounded_String.Value (System_Utilities.User_Name,  
                                 Username_Max_Length);  
        Receive_Message := Exchange_Server_Messages (Send_Message);  
        Display (Receive_Message);  
    exception  
        when Server_Not_Running =>  
            Log.Put_Line (Message => "Unable to get Status",  
                          Kind => Profile.Error_Msg);  
            Log.Put_Line (Message => "Reboot Server not running",  
                          Kind => Profile.Negative_Msg);  
    end Status;

end Reboot_Server;