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

{ PURPOSE:
{   The purpose of this module is to idle all requests to the server
{   present on the client mainframe.  This occurs when the server is
{   being de-activated.
{
{ NOTES:
{   This procedure will execute as a separate system task
{   and the possibility exists that server termination may be started
{   while this task is executing .

?? NEWTITLE := '    Global Declarations Referenced by This Module', EJECT ??
?? PUSH (LISTEXT := ON) ??
*copyc dfc$poll_constants
*copyc dfe$error_condition_codes
*copyc dft$cpu_queue
*copyc dft$entry_type
*copyc dft$rb_file_server_request
*copyc ost$status
?? POP ??
*copyc clp$scan_parameter_list
*copyc dfi$log_display
*copyc dfi$display
*copyc dfp$crack_mainframe_id
*copyc dfp$deactivate_server_files
*copyc dfp$execute_state_change_task
*copyc dfp$find_mainframe_id
*copyc dfp$locate_server_translation
*copyc dfp$verify_system_administrator
*copyc dfp$wait_until_leveler_complete
*copyc dfv$file_server_debug_enabled
*copyc i#call_monitor
*copyc jmp$ready_job_leveler_task
*copyc osp$set_status_abnormal
*copyc pmp$long_term_wait

{ pdt idle_task_pdt (
{   mainframe_name, mn : name pmc$mainframe_id_size = $required
{   status)

?? PUSH (LISTEXT := ON) ??

  VAR
    idle_task_pdt: [STATIC, READ, cls$pdt] clt$parameter_descriptor_table := [^idle_task_pdt_names,
      ^idle_task_pdt_params];

  VAR
    idle_task_pdt_names: [STATIC, READ, cls$pdt_names_and_defaults] array [1 .. 3] of
      clt$parameter_name_descriptor := [['MAINFRAME_NAME', 1], ['MN', 1], ['STATUS', 2]];

  VAR
    idle_task_pdt_params: [STATIC, READ, cls$pdt_parameters] array [1 .. 2] of clt$parameter_descriptor := [

{ MAINFRAME_NAME MN }
    [[clc$required], 1, 1, 1, 1, clc$value_range_not_allowed, [NIL, clc$name_value, pmc$mainframe_id_size,
      pmc$mainframe_id_size]],

{ STATUS }
    [[clc$optional], 1, 1, 1, 1, clc$value_range_not_allowed, [NIL, clc$variable_reference,
      clc$array_not_allowed, clc$status_value]]];

?? POP ??

?? TITLE := '    [XDCL, #GATE] dfp$idle_requests_to_server', EJECT ??

  PROCEDURE [XDCL, #GATE] dfp$idle_requests_to_server
    (    parameter_list: clt$parameter_list;
     VAR status: ost$status);

    VAR
      all_queue_entries_free: boolean,
      host_is_server_to_client: boolean,
      leveler_complete: boolean,
      leveler_executing: boolean,
      mainframe_found: boolean,
      mainframe_id: pmt$binary_mainframe_id,
      mainframe_name: pmt$mainframe_id,
      mainframe_ordinal: 1 .. dfc$max_number_of_mainframes,
      p_cpu_queue: ^dft$cpu_queue,
      p_queue_interface_table: dft$p_queue_interface_table,
      p_q_interface_directory_entry: ^dft$q_interface_directory_entry,
      queue_index: dft$queue_index,
      request_block: dft$rb_file_server_request;

    status.normal := TRUE;

    clp$scan_parameter_list (parameter_list, idle_task_pdt, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;

    dfp$crack_mainframe_id ('MAINFRAME_NAME', mainframe_name, mainframe_id, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;

    dfp$verify_system_administrator ('IDLE_REQUESTS_TO_SERVER', status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;

    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;

    { Ready the leveler task early to let it get started.
    jmp$ready_job_leveler_task (leveler_executing);

    IF (p_cpu_queue^.queue_header.partner_status.server_state = dfc$terminated) OR
      (p_cpu_queue^.queue_header.partner_status.server_state = dfc$awaiting_recovery) THEN
      RETURN;
    IFEND;

    dfp$execute_state_change_task (mainframe_name,
        TRUE, dfc$active, dfc$deactivated, osc$wait, status);

    { Idle all server files.
    dfp$locate_server_translation (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.inhibit_access_work := $dft$mainframe_set [mainframe_ordinal];
    request_block.terminate_access_work := $dft$mainframe_set [];
    i#call_monitor (#LOC (request_block), #SIZE (request_block));


    dfp$deactivate_server_files (mainframe_id, status);
    IF NOT status.normal THEN
{     Possible abnormal status conditions are:
{     . dfe$server_file_not_deactivated        status.text = number of files not deactivated
{     . dfe$server_has_terminated              status.text = model and serial number of terminated server
      IF status.condition = dfe$server_file_not_deactivated THEN
        log_display ($pmt$ascii_logset[pmc$system_log], ' Some server files not deactivated' );
        status.normal := TRUE;
      ELSE
        RETURN;
      IFEND;
    IFEND;
    IF (p_cpu_queue^.queue_header.partner_status.server_state = dfc$terminated) OR
     (p_cpu_queue^.queue_header.partner_status.server_state = dfc$awaiting_recovery) THEN
      RETURN;
    IFEND;

    dfp$wait_until_leveler_complete (p_cpu_queue, leveler_complete);
    IF (p_cpu_queue^.queue_header.partner_status.server_state = dfc$terminated) OR
     (p_cpu_queue^.queue_header.partner_status.server_state = dfc$awaiting_recovery) THEN
      RETURN;
    IFEND;

    dfp$await_all_queue_entrys_free (p_cpu_queue, {2 mins} 120000, all_queue_entries_free);
    { Allow the poll task to reverify that all_queue_entries_free.
    { If the poller sees that they aren't it will force a timeout

    p_cpu_queue^.queue_header.partner_status.deactivate_complete := TRUE;

  PROCEND dfp$idle_requests_to_server;

?? TITLE := ' [XDCL] dfp$await_all_queue_entrys_free ', EJECT ??
  PROCEDURE [XDCL] dfp$await_all_queue_entrys_free
    (    p_cpu_queue: ^dft$cpu_queue;
         maximum_time_milliseconds: 0 .. 0ffffffffffff(16);
     VAR all_queue_entries_free: boolean);

    VAR
      assigned_entry_count: 0 .. dfc$max_queue_entries,
      current_elapsed_time: 0 .. 0ffffffffffff(16),
      queue_entry_index: dft$queue_entry_index;

    current_elapsed_time := 0;

  /await_all_entries_free/
    REPEAT
      assigned_entry_count := 0;
      all_queue_entries_free := TRUE;
      #SPOIL (p_cpu_queue^.queue_header);

    /check_all_queue_entries/
      FOR queue_entry_index := dfc$poll_queue_index + 1 TO
            (dfc$poll_queue_index + p_cpu_queue^.queue_header.number_of_monitor_queue_entries +
            p_cpu_queue^.queue_header.number_of_task_queue_entries) DO
        IF p_cpu_queue^.queue_header.queue_entry_assignment_table (queue_entry_index) =
              dfc$assigned_entry_char THEN
          assigned_entry_count := assigned_entry_count + 1;
        IFEND;
      FOREND /check_all_queue_entries/;

      IF (p_cpu_queue^.queue_header.partner_status.server_state = dfc$terminated) OR
       (p_cpu_queue^.queue_header.partner_status.server_state = dfc$awaiting_recovery) THEN
        all_queue_entries_free := TRUE;
        RETURN;
      IFEND;

      IF assigned_entry_count > 0 THEN
        all_queue_entries_free := FALSE;
        IF current_elapsed_time >= maximum_time_milliseconds THEN
          { Give up
          IF dfv$file_server_debug_enabled THEN
            display_integer (' Still some queue entries assigned', assigned_entry_count);
          IFEND;
          log_display_integer ($pmt$ascii_logset[pmc$system_log],
                ' Still some queue entries assigned', assigned_entry_count);
          RETURN;
        IFEND;
        current_elapsed_time := current_elapsed_time + 2000;
        pmp$long_term_wait (2000, 2000);
      IFEND;
    UNTIL assigned_entry_count = 0;
    all_queue_entries_free := TRUE;
  PROCEND dfp$await_all_queue_entrys_free;
MODEND dfm$idle_requests_to_server;
