?? RIGHT := 110 ??
?? NEWTITLE := ' NOS/VE File Server: Client', EJECT ??
MODULE dfm$term_requests_to_server;

{ PURPOSE:
{   The purpose of this module is to terminate the outstanding requests
{         for a server mainframe being terminated.
{

?? NEWTITLE := '   Global Declarations Referenced by This Module', EJECT ??
?? PUSH (LISTEXT := ON) ??
*copyc dfc$poll_constants
*copyc dfd$driver_queue_types
*copyc dfd$request_package
*copyc dfe$error_condition_codes
*copyc dft$cpu_queue
*copyc dft$rb_file_server_request
*copyc iot$pp_interface_table
*copyc pmt$task_status
*copyc syt$monitor_status
?? POP ??
*copyc dfp$check_queue_entry_assigned
*copyc dfp$find_mainframe_id
*copyc dfp$free_entry_assignment
*copyc dfp$locate_server_translation
*copyc dfp$terminate_server_files
*copyc i#call_monitor
*copyc osp$set_status_abnormal
*copyc osp$system_error
*copyc pmp$exit
*copyc pmp$wait
?? TITLE := ' [XDCL] dfp$set_terminated_access_state', EJECT ??
  PROCEDURE [XDCL] dfp$set_terminated_access_state
    (    server_mainframe_id: pmt$binary_mainframe_id);

    VAR
      mainframe_found: boolean,
      mainframe_ordinal: 1 .. dfc$max_number_of_mainframes,
      request_block: dft$rb_file_server_request;

    dfp$locate_server_translation (server_mainframe_id, mainframe_ordinal, mainframe_found);
    request_block.reqcode := syc$rc_file_server_request;
    request_block.request := dfc$fsr_set_task_segment_state;
    request_block.status.normal := TRUE;
    request_block.terminate_access_work := $dft$mainframe_set [mainframe_ordinal];
    request_block.inhibit_access_work := $dft$mainframe_set [];
    i#call_monitor (#LOC (request_block), #SIZE (request_block));

  PROCEND dfp$set_terminated_access_state;

?? TITLE := '    [XDCL] dfp$term_requests_to_server', EJECT ??

  PROCEDURE [XDCL] dfp$term_requests_to_server
    (    mainframe_name: pmt$mainframe_id;
         p_idle_task_status: ^pmt$task_status;
     VAR status: ost$status);

    VAR
      host_is_server_to_client: boolean,
      ignore_status: ost$status,
      mainframe_found: boolean,
      p_cpu_queue: ^dft$cpu_queue,
      p_cpu_queue_entry: ^dft$cpu_queue_entry,
      p_driver_queue: ^dft$driver_queue,
      p_ost_status: ^ost$status,
      p_queue_interface_table: dft$p_queue_interface_table,
      p_q_interface_directory_entry: ^dft$q_interface_directory_entry,
      p_send_buffer_header: ^dft$buffer_header,
      p_status_response: ^dft$status_response,
      queue_entry_assigned: boolean,
      queue_index: dft$queue_index,
      q_d_index: dft$queue_directory_index,
      queue_entry_index: dft$queue_entry_index,
      request_block: dft$rb_file_server_request,
      response_buffer_entry: dft$fs_pp_response,
      total_queue_entries: dft$queue_entry_index;

    status.normal := TRUE;
    host_is_server_to_client := FALSE;
    dfp$find_mainframe_id (mainframe_name, host_is_server_to_client, mainframe_found,
          p_queue_interface_table, p_cpu_queue, queue_index, p_q_interface_directory_entry);
    IF NOT mainframe_found THEN
      osp$set_status_abnormal (dfc$file_server_id, dfe$mainframe_not_server, mainframe_name, status);
      RETURN;
    IFEND;

    IF p_q_interface_directory_entry^.connection_type <> dfc$esm_connection THEN
      osp$set_status_abnormal (dfc$file_server_id, dfe$not_stornet_connection, mainframe_name, status);
      osp$system_error ('NON-STORNET CONNECTION - DFP$TERM_REQUESTS_TO_SERVER', ^status);
    IFEND;

    p_driver_queue := p_queue_interface_table^.queue_directory.driver_queue_pva_directory [queue_index].
          p_driver_queue;
    p_driver_queue^.queue_header.flags.idle := TRUE;
    pmp$wait (2000, 2000);

    total_queue_entries := p_driver_queue^.queue_header.number_of_queue_entries;

{Search queues for active entry and set bad status
    request_block.reqcode := syc$rc_file_server_request;
    request_block.request := dfc$fsr_term_client_tasks;
    request_block.queue_interface_table_p := p_queue_interface_table;
    response_buffer_entry.response_flags.special_response  := TRUE;
    response_buffer_entry.response_flags.one_word_response := TRUE;
    response_buffer_entry.response_flags.error_response := FALSE;
    response_buffer_entry.response_flags.inquiry_response := FALSE;
    response_buffer_entry.response_flags.termination_pseudo_response := TRUE;
    response_buffer_entry.response_length := 8 {bytes = 1 word};
    response_buffer_entry.logical_unit := 0; {Not used by dfp$process_server_response_a
    response_buffer_entry.queue_index := queue_index;

  /search_for_incomplete_actions/
    FOR queue_entry_index := dfc$poll_queue_index + 1 TO total_queue_entries DO
      dfp$check_queue_entry_assigned (queue_entry_index, p_cpu_queue^.queue_header.
            queue_entry_assignment_table, queue_entry_assigned);
      IF NOT queue_entry_assigned THEN
        CYCLE /search_for_incomplete_actions/;
      IFEND;
      p_cpu_queue_entry := ^p_cpu_queue^.queue_entries [queue_entry_index];
      response_buffer_entry.queue_entry_index := queue_entry_index;
      request_block.one_word_response := response_buffer_entry;
      RESET p_cpu_queue_entry^.p_receive_buffer;
      NEXT p_status_response IN p_cpu_queue_entry^.p_receive_buffer;
      p_status_response^.buffer_header.transaction_count := p_cpu_queue_entry^.transaction_count;
      RESET p_cpu_queue_entry^.p_send_buffer;
      NEXT p_send_buffer_header IN p_cpu_queue_entry^.p_send_buffer;
      p_status_response^.buffer_header.version := dfc$status_buffer_version;
      p_status_response^.buffer_header.remote_processor := p_send_buffer_header^.remote_processor;
      {!! Assumming that the value returned is the same
      p_status_response^.status.normal := FALSE;
      p_status_response^.status.condition := dfe$server_has_terminated;
      IF p_cpu_queue_entry^.processor_type = dfc$task_services THEN
        NEXT p_ost_status IN p_cpu_queue_entry^.p_receive_buffer;
        osp$set_status_abnormal (dfc$file_server_id, dfe$server_has_terminated, mainframe_name,
              p_ost_status^);
      IFEND;
      request_block.cpu_queue_entry_p := p_cpu_queue_entry;
      request_block.status.normal := TRUE;
      p_driver_queue^.queue_entries [queue_entry_index].flags.active_entry := TRUE;
      p_driver_queue^.queue_entries [queue_entry_index].flags.driver_action := FALSE;
      p_driver_queue^.queue_entries [queue_entry_index].flags.subsystem_action := FALSE;
      p_driver_queue^.queue_entries [queue_entry_index].flags.buffer_received := TRUE;
      p_driver_queue^.queue_entries [queue_entry_index].flags.process_response := TRUE;

      i#call_monitor (#LOC (request_block), #SIZE (request_block));

      IF NOT request_block.status.normal THEN
        {  check if still assigned
        dfp$check_queue_entry_assigned (queue_entry_index, p_cpu_queue^.queue_header.
              queue_entry_assignment_table, queue_entry_assigned);
        IF queue_entry_assigned THEN
          dfp$free_entry_assignment (queue_entry_index,  p_cpu_queue^.queue_header.
                queue_entry_assignment_table);
        IFEND;
      IFEND;

    FOREND /search_for_incomplete_actions/;

{Wait for task performing idle processing - if any.
    IF p_idle_task_status <> NIL THEN
      REPEAT
        IF NOT p_idle_task_status^.complete THEN
          pmp$wait (2000, 2000);
        IFEND;
      UNTIL p_idle_task_status^.complete;
    IFEND;

    dfp$set_terminated_access_state (p_cpu_queue^.queue_header.destination_mainframe_id);

    dfp$terminate_server_files (p_cpu_queue^.queue_header.destination_mainframe_id, status);

  PROCEND dfp$term_requests_to_server;
MODEND dfm$term_requests_to_server;
