|
|
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 - metrics - downloadIndex: B T
Length: 21731 (0x54e3)
Types: TextFile
Names: »B«
└─⟦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⟧
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;