?? RIGHT := 110 ??
?? TITLE := ' NOS/VE File Server: Client: Manage segment state' ??
MODULE dfm$manage_segment_state;

{
{  This module contains code used by the monitor.
{  This contains the processes involoved with setting the access state for
{  a server file.   This code is executing during initial detection of the
{  server that timed out, and also as a result of delayed swap in work.

?? NEWTITLE := '   Global Declarations', EJECT ??
?? PUSH (LISTEXT := ON) ??
*copyc dft$mainframe_set
*copyc dft$server_descriptor
*copyc gft$system_file_identifier
*copyc ost$execution_control_block
*copyc tmt$fnx_search_type
?? POP ??
*copyc dfi$monitor_display
*copyc dfp$locate_server_translation
*copyc dfp$get_served_file_desc_p
*copyc gfp$mtr_get_fde_p
*copyc jsp$set_delayed_swapin_work_mtr
*copyc mmp$purge_all_page_seg_map
*copyc mmp$get_max_sdt_sdtx_pointer
*copyc tmp$find_next_xcb

*copyc dfv$file_server_debug_enabled
*copyc jmv$null_ijl_ordinal

{ dfv$gary is used as a test vehicle to control
{ whether the ASID in the SDTX should be cleared when the
{ inhibit_access is set.
{ For as yet unknown reason NOT clearing this causes a different
{ path to be executed.
{ The default value is to NOT clear this since comvert_pva will
{ stick a value back in.

 VAR
  dfv$gary : [XDCL, #GATE] boolean := TRUE;

?? TITLE := '  [XDCL] dfp$clear_task_inhibit_access ', EJECT ??
{
{   This procedure clearing the inhibit_access in the
{ access_state of the sdtx for all tasks in the job.
{

  PROCEDURE [XDCL] dfp$clear_task_inhibit_access
    (    search: tmt$fnx_search_type;
         ijle_p: ^jmt$initiated_job_list_entry;
         ijlo: jmt$ijl_ordinal;
         clear_inhibit_access_work: dft$mainframe_set);

    VAR
      fde_p: gft$file_desc_entry_p,
      sdt_p: mmt$max_sdt_p,
      sdtx_p: mmt$max_sdtx_p,
      segment_number: ost$segment,
      server_mainframe: boolean,
      server_translation_ordinal: 1 .. dfc$max_number_of_mainframes,
      terminated_file: boolean,
      xcb_p: ^ost$execution_control_block,
      xcb_state: tmt$find_next_xcb_state;

    tmp$find_next_xcb (search, ijle_p, ijlo, xcb_state, xcb_p);

  /for_all_tasks/
    WHILE xcb_p <> NIL DO

      mmp$get_max_sdt_sdtx_pointer (xcb_p, sdt_p, sdtx_p);

    /for_all_segments/
      FOR segment_number := 0 TO xcb_p^.xp.segment_table_length DO
        IF (sdt_p^.st [segment_number].ste.vl = osc$vl_invalid_entry) OR
              (sdtx_p^.sdtx_table [segment_number].sfid.residence <> gfc$tr_system) THEN
          CYCLE /for_all_segments/;
        IFEND;

        gfp$mtr_get_fde_p (sdtx_p^.sdtx_table [segment_number].sfid, NIL, fde_p);
        IF fde_p^.media <> gfc$fm_served_file THEN
          CYCLE /for_all_segments/;
        IFEND;

        IF sdtx_p^.sdtx_table [segment_number].access_state <> mmc$sas_inhibit_access THEN
          CYCLE /for_all_segments/;
        IFEND;

        get_file_location (fde_p, server_mainframe, server_translation_ordinal, terminated_file);
        IF server_mainframe THEN
          IF terminated_file THEN

{ This should not happen, but just in case clean up the SDTX.

            sdtx_p^.sdtx_table [segment_number].access_state := mmc$sas_terminate_access;
          ELSEIF (server_translation_ordinal IN clear_inhibit_access_work) THEN
            sdtx_p^.sdtx_table [segment_number].access_state := mmc$sas_allow_access;
          IFEND;
        IFEND;
      FOREND /for_all_segments/;
      tmp$find_next_xcb (tmc$fnx_continue, NIL, jmv$null_ijl_ordinal, xcb_state, xcb_p);
    WHILEND /for_all_tasks/;

  PROCEND dfp$clear_task_inhibit_access;
?? TITLE := '  [XDCL] dfp$set_task_segment_state ', EJECT ??
*copyc dfh$set_task_segment_state
{ NOTE: It is not of any use to clear the asid in the sdtx here.
{       convert_pva will store the asid back in.
{
  PROCEDURE [XDCL] dfp$set_task_segment_state
    (    search: tmt$fnx_search_type;
         ijle_p: ^jmt$initiated_job_list_entry;
         ijlo: jmt$ijl_ordinal;
         inhibit_access_work: dft$mainframe_set;
         terminate_access_work: dft$mainframe_set);

    VAR
      delayed_swapin_work_record: jmt$delayed_swapin_work_record,
      fde_p: gft$file_desc_entry_p,
      sdt_p: mmt$max_sdt_p,
      sdtx_p: mmt$max_sdtx_p,
      segment_number: ost$segment,
      server_mainframe: boolean,
      server_translation_ordinal: 1 .. dfc$max_number_of_mainframes,
      terminated_file: boolean,
      xcb_p: ^ost$execution_control_block,
      xcb_state: tmt$find_next_xcb_state;

    tmp$find_next_xcb (search, ijle_p, ijlo, xcb_state, xcb_p);

  /for_all_tasks/
    WHILE xcb_p <> NIL DO

      mmp$get_max_sdt_sdtx_pointer (xcb_p, sdt_p, sdtx_p);

    /for_all_segments/
      FOR segment_number := 0 TO xcb_p^.xp.segment_table_length DO
        IF (sdt_p^.st [segment_number].ste.vl = osc$vl_invalid_entry) OR
              (sdtx_p^.sdtx_table [segment_number].access_state = mmc$sas_terminate_access) OR
              (sdtx_p^.sdtx_table [segment_number].sfid.residence <> gfc$tr_system) THEN
          CYCLE /for_all_segments/;
        IFEND;

        gfp$mtr_get_fde_p (sdtx_p^.sdtx_table [segment_number].sfid, NIL, fde_p);
        IF fde_p^.media <> gfc$fm_served_file THEN
          CYCLE /for_all_segments/;
        IFEND;

        get_file_location (fde_p, server_mainframe, server_translation_ordinal, terminated_file);
        IF server_mainframe THEN
          IF server_translation_ordinal IN inhibit_access_work THEN
            IF NOT dfv$gary THEN
              sdt_p^.st [segment_number].ste.asid := 0;
            IFEND;
            sdtx_p^.sdtx_table [segment_number].access_state := mmc$sas_inhibit_access;
          IFEND;
          IF (server_translation_ordinal IN terminate_access_work) OR terminated_file THEN
            IF NOT dfv$gary THEN
              sdt_p^.st [segment_number].ste.asid := 0;
            IFEND;
            sdtx_p^.sdtx_table [segment_number].access_state := mmc$sas_terminate_access;
          IFEND;
        IFEND;
      FOREND /for_all_segments/;
      tmp$find_next_xcb (tmc$fnx_continue, NIL, jmv$null_ijl_ordinal, xcb_state, xcb_p);
    WHILEND /for_all_tasks/;

    IF search = tmc$fnx_system THEN
      delayed_swapin_work_record.delayed_swapin_work :=
            $jmt$delayed_swapin_work [jmc$dsw_update_server_files];
      delayed_swapin_work_record.terminate_access_work := terminate_access_work;
      delayed_swapin_work_record.inhibit_access_work := inhibit_access_work;
      jsp$set_delayed_swapin_work_mtr (delayed_swapin_work_record);
    IFEND;

   IF NOT dfv$gary THEN
     { Only if the asid is cleared is this required.
     mmp$purge_all_page_seg_map;
   IFEND;

  PROCEND dfp$set_task_segment_state;
?? TITLE := '  [XDCL] dfp$verify_segments_recovered ', EJECT ??
{
{   This procedure is run at the end of server job recovery to verify that all
{ files were recovered.  Any file not recovered will be marked as terminated.
{
  PROCEDURE [XDCL] dfp$verify_segments_recovered
    (    search: tmt$fnx_search_type;
         ijle_p: ^jmt$initiated_job_list_entry;
         ijlo: jmt$ijl_ordinal;
         recovered_work: dft$mainframe_set);

    VAR
      fde_p: gft$file_desc_entry_p,
      sdt_p: mmt$max_sdt_p,
      sdtx_p: mmt$max_sdtx_p,
      segment_number: ost$segment,
      server_mainframe: boolean,
      server_translation_ordinal: 1 .. dfc$max_number_of_mainframes,
      terminated_file: boolean,
      xcb_p: ^ost$execution_control_block,
      xcb_state: tmt$find_next_xcb_state;

    tmp$find_next_xcb (search, ijle_p, ijlo, xcb_state, xcb_p);

  /for_all_tasks/
    WHILE xcb_p <> NIL DO

      mmp$get_max_sdt_sdtx_pointer (xcb_p, sdt_p, sdtx_p);

    /for_all_segments/
      FOR segment_number := 0 TO xcb_p^.xp.segment_table_length DO
        IF (sdt_p^.st [segment_number].ste.vl = osc$vl_invalid_entry) OR
              (sdtx_p^.sdtx_table [segment_number].access_state <> mmc$sas_inhibit_access) OR
              (sdtx_p^.sdtx_table [segment_number].sfid.residence <> gfc$tr_system) THEN
          CYCLE /for_all_segments/;
        IFEND;

        gfp$mtr_get_fde_p (sdtx_p^.sdtx_table [segment_number].sfid, NIL, fde_p);
        IF fde_p^.media <> gfc$fm_served_file THEN
          CYCLE /for_all_segments/;
        IFEND;

        get_file_location (fde_p, server_mainframe, server_translation_ordinal, terminated_file);
        IF server_mainframe AND ((server_translation_ordinal IN recovered_work) OR terminated_file) THEN
          IF dfv$file_server_debug_enabled THEN
            display_integer_monitor (' Terminated unrecovered segment ', segment_number);
          IFEND;
          sdtx_p^.sdtx_table [segment_number].access_state := mmc$sas_terminate_access;
        IFEND;
      FOREND /for_all_segments/;
      tmp$find_next_xcb (tmc$fnx_continue, NIL, ijlo, xcb_state, xcb_p);
    WHILEND /for_all_tasks/;

  PROCEND dfp$verify_segments_recovered;
?? TITLE := '  [INLINE] get_file_location ', EJECT ??

  PROCEDURE [INLINE] get_file_location
    (    fde_p: gft$file_desc_entry_p;
     VAR server_mainframe: boolean;
     VAR server_translation_ordinal: 1 .. dfc$max_number_of_mainframes;
     VAR terminated_file: boolean);

    VAR
      server_descriptor_p: dft$server_descriptor_p;

    dfp$get_served_file_desc_p (fde_p, server_descriptor_p);
    dfp$locate_server_translation (server_descriptor_p^.header.server_mainframe_id,
          server_translation_ordinal, server_mainframe);
    terminated_file := server_descriptor_p^.header.file_state = dfc$terminated;

  PROCEND get_file_location;
?? OLDTITLE, OLDTITLE ??
MODEND dfm$manage_segment_state;
