?? NEWTITLE := '  NOS/VE Set Management ' ??
MODULE stm$initialize_sets;
?? RIGHT := 110 ??

{ PURPOSE:
{   This module contains those routines used during the deadstart sequence.

?? NEWTITLE := 'Global Declarations Referenced by This Module', EJECT ??
?? PUSH (LISTEXT := ON) ??
*copyc jmc$system_family
*copyc osc$nosve_system_set
*copyc ste$error_condition_codes
*copyc ost$status
*copyc stt$inactive_members_to_remove
?? POP ??
*copyc fip#addl_initialize
*copyc fip#addl_string

*copyc clp$trimmed_string_size
*copyc clp$validate_name
*copyc osp$append_status_parameter
*copyc osp$set_status_abnormal
*copyc osp$set_status_condition
*copyc pmp$get_mainframe_id
*copyc pmp$get_user_identification
*copyc stp$create_set
*copyc stp$get_volumes_by_ast_index
*copyc stp$get_volumes_in_set
*copyc stp$r2_remove_inactive_member
*copyc stp$search_ast_by_set
*copyc stp$update_system_set_name
*copyc stp$validate_owner
*copyc dmv$system_device_information
*copyc osv$lower_to_upper
*copyc osv$recover_system_set_phase
*copyc osv$system_family_name
*copyc stv$system_set_name
?? TITLE := '  [XDCL, #GATE] stp$initialize_sets ', EJECT ??
*copyc sth$initialize_sets

  PROCEDURE [XDCL, #GATE] stp$initialize_sets
    (VAR status: ost$status);

    VAR
      master_vol: rmt$recorded_vsn,
      set_name: stt$set_name,
      mainframe_id: pmt$mainframe_id,
      set_owner: ost$user_identification;

    set_owner.family := osv$system_family_name;
    set_owner.user := jmc$system_user;
    master_vol := dmv$system_device_recorded_vsn;

    IF stv$system_set_name = osc$null_name THEN
      {!pmp$get_mainframe_id (mainframe_id, status);
      {!set_name := mainframe_id;
      { Force default system set name to be the old NVESET
      set_name := osc$nosve_system_set;
    ELSE
      #TRANSLATE (osv$lower_to_upper, stv$system_set_name, set_name);
    IFEND;
    stp$update_system_set_name (set_name);

    stp$create_set (stv$system_set_name, master_vol, set_owner, stc$allow_access,
          osv$recover_system_set_phase = osc$reinitialize_system_device, status);
    IF (NOT status.normal) AND (status.condition = ste$set_already_active) THEN
      status.normal := TRUE;
    IFEND;

  PROCEND stp$initialize_sets;
?? TITLE := ' [XDCL, #GATE] stp$remove_inactive_members ', EJECT ??
*copyc sth$remove_inactive_members

  PROCEDURE [XDCL, #GATE] stp$remove_inactive_members
    (    members_to_remove: stt$inactive_members_to_remove;
         set_name: stt$set_name;
     VAR status: ost$status);

    VAR
      active_member_str_p: ^ost$string,
      ast_index: stt$ast_index,
      current_number_of_members_guess: stt$number_of_members,
      i: integer,
      master_volume_info: stt$volume_info,
      member_entry_p: ^stt$volume_info,
      member_volume_list_p: ^stt$volume_list,
      number_of_members: stt$number_of_members,
      unavailable_member_str_p: ^ost$string;

?? NEWTITLE := ' [INLINE] P$APPEND_STATUS_PARAMETER', EJECT ??

    PROCEDURE [INLINE] p$append_status_parameter
      (    text_p: ^ost$string;
       VAR status: ost$status);

      IF (text_p <> NIL) AND (text_p^.size > 2) THEN
        text_p^.size := text_p^.size - 1;
        text_p^.value (text_p^.size) := ')';
        osp$append_status_parameter (osc$status_parameter_delimiter, text_p^.value (1, text_p^.size), status);
      ELSE
        osp$append_status_parameter (osc$status_parameter_delimiter, '', status);
      IFEND;

    PROCEND p$append_status_parameter;
?? OLDTITLE ??
?? NEWTITLE := ' [INLINE] P$GET_MEMBER_ENTRY', EJECT ??

    PROCEDURE [INLINE] p$get_member_entry
      (    recorded_vsn: rmt$recorded_vsn;
       VAR member_entry_p: ^stt$volume_info);

      VAR
        j: integer;

      member_entry_p := NIL;
      FOR j := 1 TO number_of_members DO
        IF member_volume_list_p^ [j].recorded_vsn = recorded_vsn THEN
          member_entry_p := ^member_volume_list_p^ [j];
          RETURN; {----->
        IFEND;
      FOREND;

    PROCEND p$get_member_entry;
?? OLDTITLE ??
?? EJECT ??
    verify_remove_inactive (set_name, ast_index, status);
    IF NOT status.normal THEN
      RETURN; {----->
    IFEND;

    number_of_members := 1;

    REPEAT
      current_number_of_members_guess := number_of_members;
      PUSH member_volume_list_p: [1 .. current_number_of_members_guess];
      stp$get_volumes_by_ast_index (ast_index, 1, master_volume_info, member_volume_list_p^,
            number_of_members);
    UNTIL (current_number_of_members_guess >= number_of_members);

    CASE members_to_remove.kind OF
    = stc$imtr_remove_none =
      ;
    = stc$imtr_remove_all_inactive =

      FOR i := 1 TO number_of_members DO
        IF member_volume_list_p^ [i].volume_activity.volume_activity_status = stc$inactive THEN
          stp$r2_remove_inactive_member (ast_index, member_volume_list_p^ [i].recorded_vsn,
                master_volume_info.recorded_vsn, status);
          IF NOT status.normal THEN
            RETURN; {----->
          IFEND;
        IFEND;
      FOREND;

    = stc$imtr_remove_vsn_list =
      IF members_to_remove.vsn_list_p = NIL THEN
        RETURN; {----->
      IFEND;

{Verify, all specified members exist and are inactive
      unavailable_member_str_p := NIL;
      active_member_str_p := NIL;
      FOR i := 1 TO UPPERBOUND (members_to_remove.vsn_list_p^) DO
        p$get_member_entry (members_to_remove.vsn_list_p^ [i], member_entry_p);
        IF member_entry_p = NIL THEN
          IF unavailable_member_str_p = NIL THEN
            PUSH unavailable_member_str_p;
            fip#addl_initialize (unavailable_member_str_p^, '(');
          ELSE
            fip#addl_string (unavailable_member_str_p^, ', ');
          IFEND;
          fip#addl_string (unavailable_member_str_p^, members_to_remove.vsn_list_p^ [i]);

        ELSEIF member_entry_p^.volume_activity.volume_activity_status <> stc$inactive THEN
          IF active_member_str_p = NIL THEN
            PUSH active_member_str_p;
            fip#addl_initialize (active_member_str_p^, '(');
          ELSE
            fip#addl_string (active_member_str_p^, ', ');
          IFEND;
          fip#addl_string (active_member_str_p^, members_to_remove.vsn_list_p^ [i]);
        IFEND;
      FOREND;

      IF (unavailable_member_str_p = NIL) AND (active_member_str_p = NIL) THEN
        FOR i := 1 TO UPPERBOUND (members_to_remove.vsn_list_p^) DO
          stp$r2_remove_inactive_member (ast_index, members_to_remove.vsn_list_p^ [i],
                master_volume_info.recorded_vsn, status);
          IF NOT status.normal THEN
            RETURN; {----->
          IFEND;
        FOREND;
      ELSE
        osp$set_status_condition (ste$member_active_or_unavail, status);
        p$append_status_parameter (active_member_str_p, status);
        p$append_status_parameter (unavailable_member_str_p, status);
        RETURN; {----->
      IFEND;
    ELSE
      ;
    CASEND;

  PROCEND stp$remove_inactive_members;
?? TITLE := ' [XDCL, #GATE]  stp$verify_all_volumes_active', EJECT ??
*copyc sth$verify_all_volumes_active

  PROCEDURE [XDCL, #GATE] stp$verify_all_volumes_active
    (    set_name: stt$set_name;
     VAR status: ost$status);

    VAR
      all_volumes_active: boolean,
      current_number_of_members_guess: stt$number_of_members,
      i: integer,
      master_volume_info: stt$volume_info,
      number_of_members: stt$number_of_members,
      outputline: string (256),
      outputline_index: integer,
      p_member_volume_list: ^stt$volume_list,
      vsn_length: integer;

{ get a list of all volumes in the set
    number_of_members := 1;
    REPEAT
      current_number_of_members_guess := number_of_members;
      PUSH p_member_volume_list: [1 .. current_number_of_members_guess];
      stp$get_volumes_in_set (set_name, master_volume_info, p_member_volume_list^, number_of_members, status);
      IF NOT status.normal THEN
        RETURN; {----->
      IFEND;
    UNTIL current_number_of_members_guess >= number_of_members;

{ verify all volumes active
    all_volumes_active := TRUE;
    IF master_volume_info.volume_activity.volume_activity_status = stc$inactive THEN
      all_volumes_active := FALSE;
      STRINGREP (outputline, outputline_index, 'MASTER VOLUME: ', master_volume_info.recorded_vsn);
    ELSE
      { verify all members active
      FOR i := 1 TO number_of_members DO
        IF p_member_volume_list^ [i].volume_activity.volume_activity_status = stc$inactive THEN
          IF all_volumes_active THEN
            all_volumes_active := FALSE;
            STRINGREP (outputline, outputline_index, 'MEMBER VOLUME: ');
          ELSE
            STRINGREP (outputline, outputline_index, outputline (1, outputline_index), ', ');
          IFEND;

          vsn_length := clp$trimmed_string_size (p_member_volume_list^ [i].recorded_vsn);
          STRINGREP (outputline, outputline_index, outputline (1, outputline_index),
                p_member_volume_list^ [i].recorded_vsn (1, vsn_length));
        IFEND;
      FOREND;
    IFEND;

    IF NOT all_volumes_active THEN
      vsn_length := clp$trimmed_string_size (set_name);
      STRINGREP (outputline, outputline_index, outputline (1, outputline_index), ' -- NOT ACTIVE ON SET: ',
            set_name (1, vsn_length));
      osp$set_status_abnormal (stc$set_management_id, ste$all_volumes_not_active,
            outputline (1, outputline_index), status);
    IFEND;

  PROCEND stp$verify_all_volumes_active;
?? TITLE := ' verify_remove_inactive ', EJECT ??

  PROCEDURE verify_remove_inactive
    (    set_name: stt$set_name;
     VAR ast_index: stt$ast_index;
     VAR status: ost$status);

    VAR
      ast_entry: stt$active_set_entry,
      job_owner: ost$user_identification,
      local_set_name: ost$name,
      set_found: boolean,
      valid_name: boolean,
      valid_owner: boolean;

    status.normal := TRUE;
    clp$validate_name (set_name, local_set_name, valid_name);
    IF NOT valid_name THEN
      osp$set_status_abnormal (stc$set_management_id, ste$bad_set_name, set_name, status);
      RETURN; {----->
    IFEND;

    stp$search_ast_by_set (local_set_name, ast_entry, ast_index, set_found);
    IF NOT set_found THEN
      osp$set_status_abnormal (stc$set_management_id, ste$set_not_active, stc$null_parameter, status);
      RETURN; {----->
    IFEND;

    IF (NOT ast_entry.master_ever_up) OR (ast_entry.master_volume_activity.volume_activity_status <>
          stc$active) THEN
      osp$set_status_abnormal (stc$set_management_id, ste$master_not_active, ast_entry.master_vsn, status);
      osp$append_status_parameter (osc$status_parameter_delimiter, ast_entry.set_name, status);
      RETURN; {----->
    IFEND;

    stp$validate_owner (ast_entry.set_owner, valid_owner);
    IF NOT valid_owner THEN
      pmp$get_user_identification (job_owner, status);
      osp$set_status_abnormal (stc$set_management_id, ste$set_not_job_owner, job_owner.user, status);
      osp$append_status_parameter (osc$status_parameter_delimiter, job_owner.family, status);
      osp$append_status_parameter (osc$status_parameter_delimiter, set_name, status);
      RETURN; {----->
    IFEND;

  PROCEND verify_remove_inactive;
?? OLDTITLE ??
MODEND stm$initialize_sets;
