?? RIGHT := 110 ??
?? NEWTITLE := ' NOS/VE File Server: Server: Connection Manager', EJECT ??
MODULE dfm$manage_client_connection;

{================================================================================
{
{  This module is a Clone Master task managing the connection with the
{  DF Client mainframe. This includes reacting to the operator's commands:
{
{     Activate_Client
{     Deactivate_Client
{     Terminate_Client
{
{  as well as responding to the periodic polls that the Client sends to the
{  Server. This task also supervises and times out the requests to the Server
{  posted by the stable clones.
{
{  The operator requests come to this task indirectly: the various action
{  signals are set in the CPU_Queue header (Partner_Status record) by the
{  command processors and this task acts upon them.
{
{  Abnormal conditions will cause dfm$manage_client_connection to abort
{  the connection with the Client and to time itself out. Such conditions
{  include: garbled poll messages from the Server, time-out of the poll message,
{  and incorrect info contained in the request to verify Server Queue definition
{  on the Client. An incorrect family name in the Verify_Queue request or in
{  Verify_Family request, however, does not cause an abort. The family in question
{  will simply not be validated. Family will remain inaccessible to the users
{  on the Client in this case.
{
{===============================================================================

?? NEWTITLE := '    Global Declarations ', EJECT ??
?? PUSH (LISTEXT := ON) ??

*copyc clp$scan_parameter_list
*copyc dfc$test_jr_constants
*copyc dfc$loopback_server_mainframe
*copyc dfc$esm_allocation_constants
*copyc dfc$poll_constants
*copyc dfc$test_jr_constants
*copyc dfd$driver_queue_types
*copyc dfd$request_package
*copyc dfe$error_condition_codes
*copyc dfi$display
*copyc dfi$log_display
*copyc dft$application_support_limits
*copyc dfp$attach_application_library
*copyc dfp$build_client_mf_file_name
*copyc dfp$crack_mainframe_id
*copyc dfp$determine_action_for_server
*copyc dfp$establish_clone_task_stable
*copyc dfp$execute_state_change_task
*copyc dfp$fetch_queue_entry
*copyc dfp$find_mainframe_id
*copyc dfp$get_queue_directory_index
*copyc dfp$load_pp_if_first
*copyc dfp$queue_task_request
*copyc dfp$remove_client_jobs
*copyc dfp$reset_mainframe_tables
*copyc dfp$send_message_to_operator
*copyc dfp$set_client_mf_file_info
*copyc dfp$submit_client_mainframe_job
*copyc dfp$term_processing_on_server
*copyc dfp$timeout_requests_on_server
*copyc dfp$unload_pp_if_last
*copyc dfp$verify_system_administrator
*copyc dfp$word_boundary
*copyc dft$client_mainframe_file
*copyc dft$command_buffer
*copyc dft$cpu_queue
*copyc dft$display_identifier
*copyc dft$entry_type
*copyc dft$family_access
*copyc dft$family_list
*copyc dft$poll_family_list
*copyc dft$poll_header
*copyc dft$poll_message
*copyc dft$poll_queue_information
*copyc dft$procedure_address_ordinal
*copyc dft$queue_index
*copyc dfv$display_poll
*copyc dfv$file_server_debug_enabled
*copyc dfv$send_command_flags
*copyc dft$queue_interface_directory
*copyc dpp$put_next_line
*copyc i#current_sequence_position
*copyc ofd$type_definition
*copyc osc$server_state_change
*copyc osc$status_parameter_delimiter
*copyc osp$append_status_parameter
*copyc osp$establish_block_exit_hndlr
*copyc osp$format_message
*copyc osp$get_families_for_client
*copyc osp$set_status_abnormal
*copyc osp$set_status_from_condition
*copyc oss$task_private
*copyc oss$task_shared
*copyc osv$task_shared_heap
*copyc pfp$attach
*copyc pfp$validate_local_family
*copyc pmd$system_log_interface
*copyc pmp$cause_condition_in_tasks
*copyc pmp$exit
*copyc pmp$get_compact_date_time
*copyc pmp$get_executing_task_gtid
*copyc pmp$get_job_names
*copyc pmp$get_mainframe_id
*copyc pmp$log_ascii
*copyc pmp$wait
*copyc pmt$binary_mainframe_id
*copyc pmt$mainframe_id
*copyc qfp$discard_client_jobs
*copyc syp$hang_if_system_jrt_set
*copyc syp$invoke_system_debugger
*copyc syv$test_jr_job
?? POP ??
?? TITLE := '    Global Variables ', EJECT ??

  VAR
    dfv$normal_client_termination: [XDCL, oss$task_shared] boolean := FALSE;

  CONST
    client = 'Client ';

*copyc dfv$job_recovery_enabled
*copyc dfv$poll_type_string
*copyc dfv$p_clone_tasks_status
*copyc dpv$system_core_display
*copyc osv$os_defaults
*copyc osv$page_size

?? TITLE := '    dfp$manage_client_connection', EJECT ??

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

{       pdt manage_client_pdt (
{           mainframe_name: name pmc$mainframe_id_size = $required
{           status)

?? PUSH (LISTEXT := ON) ??

    VAR
      manage_client_pdt: [STATIC, READ, cls$pdt] clt$parameter_descriptor_table :=
            [^manage_client_pdt_names, ^manage_client_pdt_params];

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

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

{ MAINFRAME_NAME

      [[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 ??

    VAR
      mainframe_id: pmt$binary_mainframe_id,
      mainframe_name: pmt$mainframe_id;

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

    clp$scan_parameter_list (parameter_list, manage_client_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;

    get_client_mainframe_file (mainframe_name, status);
    IF NOT status.normal THEN
      display_error_status (status);
      RETURN;
    IFEND;
    dfp$determine_client_status (mainframe_name, status);

  PROCEND dfp$manage_client_connection;

?? TITLE := '    dfp$determine_client_status', EJECT ??

  PROCEDURE [XDCL] dfp$determine_client_status
    (    mainframe_name: pmt$mainframe_id;
     VAR status: ost$status);


?? NEWTITLE := '    handle_block_exit', EJECT ??

{ PURPOSE:
{   The purpose of this procedure is to deal with block exit conditions that
{   arise while system_authority is in effect.

  PROCEDURE handle_block_exit
    (    condition: pmt$condition;
         condition_information_p: ^pmt$condition_information;
         sfsa_p: ^ost$stack_frame_save_area;
     VAR handler_status: ost$status);

    VAR
      ignore_status: ost$status;

    IF NOT dfv$normal_client_termination THEN
       send_message_to_operator (' Abnormal client termination ', mainframe_name);
      { Catch aborts, or terminate_job
      CASE p_cpu_queue^.queue_header.partner_status.server_state OF
      = dfc$terminated, dfc$awaiting_recovery, dfc$inactive =
        p_cpu_queue^.queue_header.partner_status.verify_queue := FALSE;
      ELSE
        timeout_job (p_cpu_queue, queue_index, p_queue_interface_table, ' Client block exit', FALSE);
      CASEND;

      IF status.normal THEN
        osp$set_status_from_condition (dfc$file_server_id, condition, sfsa_p, status, ignore_status);
      IFEND;
    IFEND;
  PROCEND handle_block_exit;
?? OLDTITLE ??

    VAR
      ignore_status: ost$status,
      mainframe_found: boolean,
      operator_message: string (79),
      p_cpu_queue: ^dft$cpu_queue,
      p_poll_header: ^dft$poll_header,
      p_q_interface_directory_entry: ^dft$q_interface_directory_entry,
      p_queue_interface_table: ^dft$queue_interface_table,
      queue_index: dft$queue_index,
      reply_header: dft$poll_header,
      server_to_client: boolean,
      time_before_wait: integer,
      wait_time: integer;

{-------------------------------------
{   Set values for the life of the task.
{-------------------------------------

    status.normal := TRUE;
    dfp$verify_system_administrator ('ACTIVATE_CLIENT', status);
    IF NOT status.normal THEN
      display_error_status (status);
      RETURN;
    IFEND;
    server_to_client := TRUE;
    dfp$find_mainframe_id (mainframe_name, server_to_client, mainframe_found, p_queue_interface_table,
          p_cpu_queue, queue_index, p_q_interface_directory_entry);
    IF NOT mainframe_found THEN
      system_error ('INCORRECT SERVER MAINFRAME ID IN CLONE MASTER.');
    IFEND;
    osp$establish_block_exit_hndlr (^handle_block_exit);
    pmp$get_executing_task_gtid (p_cpu_queue^.queue_entries [dfc$poll_queue_index].global_task_id);
    pmp$get_mainframe_id (reply_header.mainframe_name, ignore_status);
    wait_time := p_cpu_queue^.queue_header.timeout_interval DIV 1000;

    dfp$attach_application_library (p_cpu_queue);

{   Check for "Loopback" mode and fudge in the mainframe_name.
{   NOTE: The invented Mainframe_Name must be passed in as the name of this SERVER.

    IF (reply_header.mainframe_name = mainframe_name) THEN
      reply_header.mainframe_name := dfc$loopback_server_mainframe;
    IFEND;

  /main_loop/
    WHILE TRUE DO
      #SPOIL (p_cpu_queue^.queue_header.partner_status);
      syp$hang_if_system_jrt_set (dfc$tjr_determine_client_status);

{ Termination conditions have priority over timeout.

      IF p_cpu_queue^.queue_header.partner_status.terminate_partner THEN
        operator_message := '  Operator terminated Client.';
        terminate_job (p_cpu_queue, queue_index, p_queue_interface_table, operator_message,
          { Restart}  FALSE);

      ELSEIF p_cpu_queue^.queue_header.partner_status.timeout_partner THEN
        operator_message := '  System timing out Client.';
        timeout_job (p_cpu_queue, queue_index, p_queue_interface_table, operator_message,
          { Restart}  FALSE);
      ELSE

{--------------------------
{       Check Server State.
{--------------------------

        CASE p_cpu_queue^.queue_header.partner_status.server_state OF

        = dfc$inactive =
          IF p_cpu_queue^.queue_header.partner_status.verify_queue THEN
            pmp$get_executing_task_gtid (p_cpu_queue^.queue_entries [dfc$poll_queue_index].
                  global_task_id);
            wait_for_verify_queue_message (p_cpu_queue, queue_index, p_queue_interface_table,
                  p_q_interface_directory_entry, reply_header);
          IFEND;

        = dfc$terminated, dfc$awaiting_recovery =
          IF p_cpu_queue^.queue_header.partner_status.verify_queue THEN
            wait_for_verify_queue_message (p_cpu_queue, queue_index, p_queue_interface_table,
                  p_q_interface_directory_entry, reply_header);
          ELSE
            system_error (' STATE=TERM/ AREC, NO VERIFY_QUEUE, AND POLL TASK RUNNING');
          IFEND;

        = dfc$active, dfc$deactivated, dfc$recovering =

{         Need not do anything here.

        ELSE
          system_error ('INCORRECT SERVER_STATE in Clone Master');
        CASEND;
      IFEND;

{-----------------------------------------
{     Process or time-out Poll message.
{-----------------------------------------

      time_before_wait := #FREE_RUNNING_CLOCK (0);

      pmp$wait (wait_time, wait_time);
      determine_wakeup_cause (p_cpu_queue, queue_index, p_queue_interface_table, time_before_wait,
            reply_header);
      time_out_poll (p_cpu_queue, queue_index, p_queue_interface_table);
      check_clones_status (p_cpu_queue, queue_index, p_queue_interface_table);

    WHILEND /main_loop/;

  PROCEND dfp$determine_client_status;

?? TITLE := '    call_state_change_procedures', EJECT ??

  PROCEDURE call_state_change_procedures
    (    old_state: dft$server_state;
         new_state: dft$server_state;
         p_cpu_queue: ^dft$cpu_queue);

    VAR
      local_status: ost$status,
      wait: ost$wait;

    local_status.normal := TRUE;
    IF old_state = new_state THEN
      RETURN;
    IFEND;

    IF p_cpu_queue^.queue_header.p_remote_application_info <> NIL THEN
      IF old_state IN $dft$server_states [dfc$deactivated, dfc$active, dfc$recovering] THEN
        { The application may be processing a remote procedure call
        log_display ($pmt$ascii_logset [pmc$job_log, pmc$system_log],
              ' Calling pmp$cause_condition_in_tasks for osc$server_state_change');
        pmp$cause_condition_in_tasks (osc$server_state_change);
      IFEND;
    IFEND;

    IF new_state IN $dft$server_states [dfc$deactivated, dfc$active, dfc$recovering] THEN
      {We must allow the poller task to continue so it can detect timeouts
      wait := osc$nowait;
    ELSE
      wait := osc$wait;
    IFEND;

    dfp$execute_state_change_task (p_cpu_queue^.queue_header.destination_mainframe_name,
          { Partner_is_server } FALSE, old_state, new_state, wait, local_status);

  PROCEND call_state_change_procedures;

?? TITLE := '    check_clones_status', EJECT ??

  PROCEDURE check_clones_status
    (    p_cpu_queue: ^dft$cpu_queue;
         queue_index: dft$queue_index;
         p_queue_interface_table: ^dft$queue_interface_table);

    VAR
      operator_message: string (79),
      queue_entry_index: dft$queue_entry_index,
      string_length: integer;

{   --------------------------------------------------------------------
{   This procedure checks the status of each clone task.
{   None of the clones should have completed. If any clone has completed
{   then the Client job will be terminated.
{   --------------------------------------------------------------------

    IF dfv$p_clone_tasks_status <> NIL THEN

    /check_each_clone_task/
      FOR queue_entry_index := LOWERBOUND (dfv$p_clone_tasks_status^)
            TO UPPERBOUND (dfv$p_clone_tasks_status^) DO

        IF dfv$p_clone_tasks_status^ [queue_entry_index].complete THEN
          IF NOT dfv$p_clone_tasks_status^ [queue_entry_index].status.normal THEN
            display_error_status (dfv$p_clone_tasks_status^ [queue_entry_index].status);
          IFEND;
          STRINGREP (operator_message, string_length, '  Clone number # ', queue_entry_index,
                ' completed prematurely - TIMING OUT CLIENT');
          timeout_job (p_cpu_queue, queue_index, p_queue_interface_table,
                operator_message (1, string_length), {restart } FALSE);
        IFEND;
      FOREND /check_each_clone_task/;
    IFEND;
  PROCEND check_clones_status;

?? TITLE := '    determine_wakeup_cause', EJECT ??

  PROCEDURE determine_wakeup_cause
    (    p_cpu_queue: ^dft$cpu_queue;
         queue_index: dft$queue_index;
         p_queue_interface_table: ^dft$queue_interface_table;
         time_before_wait: integer;
     VAR reply_header: dft$poll_header);

    VAR
      client_found: boolean,
      operator_message: string (79),
      p_driver_flags: ^dft$queue_entry_flags,
      remaining_wait_time: integer,
      status: ost$status,
      time_after_wait: integer,
      wait_time: integer;

    p_driver_flags := ^p_queue_interface_table^.queue_directory.driver_queue_pva_directory [queue_index].
          p_driver_queue^.queue_entries [dfc$poll_queue_index].flags;
    wait_time := p_cpu_queue^.queue_header.timeout_interval DIV 1000;

{---------------------------------------------------
{   Check if Poll arrived and process it immediately
{---------------------------------------------------

    REPEAT
      #SPOIL (p_cpu_queue^.queue_header.partner_status);
      #SPOIL (p_driver_flags);

      IF p_cpu_queue^.queue_header.partner_status.terminate_partner THEN
        operator_message := '  Operator terminated Client.';
        terminate_job (p_cpu_queue, queue_index, p_queue_interface_table, operator_message, FALSE);
      IFEND;

      IF p_cpu_queue^.queue_header.partner_status.timeout_partner THEN
        operator_message := '  System timed out Client.';
        timeout_job (p_cpu_queue, queue_index, p_queue_interface_table, operator_message, FALSE);
      IFEND;

      IF p_driver_flags^.subsystem_action THEN
        IF p_driver_flags^.driver_error_alert THEN
          dfp$set_client_mf_file_info (p_cpu_queue^.queue_header.destination_mainframe_id, dfc$terminated,
                p_cpu_queue^.queue_header.server_lifetime, p_cpu_queue^.queue_header.server_birthdate,
                client_found);
          p_cpu_queue^.queue_header.partner_status.server_state := dfc$terminated;
          system_error ('PP ERROR: DRIVER ERROR FLAG SET IN DETERMINE_WAKEUP_CAUSE');
        ELSE
          status.normal := TRUE;
          process_poll (p_cpu_queue, queue_index, p_queue_interface_table, reply_header, status);
          IF NOT status.normal THEN
            display_error_status (status);
            operator_message := ' TIMEOUT CLIENT.';
            timeout_job (p_cpu_queue, queue_index, p_queue_interface_table, operator_message, FALSE);
          IFEND;

        IFEND;
      IFEND;

{     ------------------------------------
{     Wait the balance of the wait period.
{     ------------------------------------

      time_after_wait := #FREE_RUNNING_CLOCK (0);
      remaining_wait_time := wait_time - ((time_after_wait - time_before_wait) DIV 1000);
      IF (remaining_wait_time > 0) THEN
        pmp$wait (remaining_wait_time, remaining_wait_time);
      IFEND;

    UNTIL NOT (remaining_wait_time > 0);

  PROCEND determine_wakeup_cause;

?? TITLE := '      display_error_status', EJECT ??

  PROCEDURE display_error_status
    (    status: ost$status);

    VAR
      destination_log: pmt$ascii_logset,
      ignore_status: ost$status,
      line_count: ost$status_message_line_count,
      message: ost$status_message,
      p_line_count: ^ost$status_message_line_count,
      p_line_size: ^ost$status_message_line_size,
      p_message: ^ost$status_message,
      p_message_line: ^string ( * ),
      window: dpt$window_id;

    window := dpv$system_core_display;
    destination_log := $pmt$ascii_logset [pmc$system_log, pmc$job_log];
    p_message := ^message;
    osp$format_message (status, osc$full_message_level, ofc$max_display_message, p_message^, ignore_status);
    RESET p_message;
    NEXT p_line_count IN p_message;
    IF p_line_count^ > 0 THEN

    /display_each_line/
      FOR line_count := 1 TO (p_line_count^) DO
        NEXT p_line_size IN p_message;
        NEXT p_message_line: [p_line_size^] IN p_message;
        dpp$put_next_line (window, p_message_line^ (1, p_line_size^), ignore_status);
        pmp$log_ascii (p_message_line^ (1, p_line_size^), destination_log, pmc$msg_origin_system,
              ignore_status);
      FOREND /display_each_line/;
    IFEND;
  PROCEND display_error_status;

?? TITLE := '    format_family_list', EJECT ??

  PROCEDURE format_family_list
    (    p_cpu_queue: ^dft$cpu_queue;
         queue_index: dft$queue_index;
         p_queue_interface_table: ^dft$queue_interface_table;
     VAR number_of_families: 0 .. dfc$max_family_parameters;
     VAR {input/output} p_receive_buffer: dft$p_command_buffer;
     VAR p_families: ^SEQ (REP dfc$max_family_parameters of dft$family_verification);
     VAR {input/output} p_family_list: ^dft$poll_family_list);

    VAR
      ignore_status: ost$status,
      operator_message: string (79),
      p_number_of_families: ^0 .. dfc$max_family_parameters,
      p_received_families: ^dft$poll_family_list;

    NEXT p_number_of_families IN p_receive_buffer;
    number_of_families := p_number_of_families^;
    IF (number_of_families = 0) THEN
      p_family_list := NIL;
    ELSE
      NEXT p_received_families: [1 .. number_of_families] IN p_receive_buffer;
      RESET p_families;
      NEXT p_family_list: [1 .. number_of_families] IN p_families;
      p_family_list^ := p_received_families^;
    IFEND;
    process_family_verification (p_cpu_queue^.queue_header.destination_mainframe_id, number_of_families,
          p_families^);
    IF number_of_families > 0 THEN
      RESET p_families;
      NEXT p_family_list: [1 .. number_of_families] IN p_families;
    IFEND;


  PROCEND format_family_list;

?? TITLE := '    get_client_mainframe_file', EJECT ??

  PROCEDURE get_client_mainframe_file
    (    client_mainframe: pmt$mainframe_id;
     VAR status: ost$status);

    VAR
      client_mainframe_file: ost$name,
      cycle_selector: pft$cycle_selector,
      error: string (60),
      p_mainframe_file_path: ^pft$path,
      string_length: integer;

    status.normal := TRUE;

    dfp$build_client_mf_file_name (client_mainframe, client_mainframe_file);
    PUSH p_mainframe_file_path: [1 .. 4];
    p_mainframe_file_path^ [1] := ' ';
    p_mainframe_file_path^ [2] := ' ';
    p_mainframe_file_path^ [3] := dfc$client_mainframe_catalog;
    p_mainframe_file_path^ [4] := client_mainframe_file;
    cycle_selector.cycle_option := pfc$specific_cycle;
    cycle_selector.cycle_number := 1;

    pfp$attach (client_mainframe_file, p_mainframe_file_path^, cycle_selector, osc$null_name,
          $pft$usage_selections [pfc$read, pfc$shorten, pfc$append, pfc$modify],
          $pft$share_selections [pfc$read, pfc$shorten, pfc$append, pfc$modify], pfc$no_wait, status);
    IF NOT status.normal THEN
      STRINGREP (error, string_length, client, '- error status from ATTACH ', client_mainframe_file);
      display (error (1, string_length));
    IFEND;

  PROCEND get_client_mainframe_file;

?? TITLE := '    issue_poll_reply', EJECT ??

  PROCEDURE issue_poll_reply
    (    p_cpu_queue: ^dft$cpu_queue;
         queue_index: dft$queue_index;
         p_queue_interface_table: ^dft$queue_interface_table;
         reply_header: dft$poll_header;
         p_family_list: ^dft$poll_family_list;
         p_queue_information: ^dft$poll_queue_information);

    VAR
      actual_length: integer,
      ignore_status:  ost$status,
      operator_message: string (79),
      p_driver_entry: ^dft$driver_queue_entry,
      p_number_of_families: ^0 .. dfc$max_family_parameters,
      p_poll_family_list: ^dft$poll_family_list,
      p_poll_queue_information: ^dft$poll_queue_information,
      p_send_buffer: dft$p_command_buffer,
      p_send_parameters: ^dft$poll_message;

    p_send_buffer := p_cpu_queue^.queue_entries [dfc$poll_queue_index].p_send_buffer;
    p_driver_entry := ^p_queue_interface_table^.queue_directory.driver_queue_pva_directory [queue_index].
          p_driver_queue^.queue_entries [dfc$poll_queue_index];

{-----------------------------------
{   Format Poll_Reply buffer header.
{-----------------------------------

    RESET p_send_buffer;
    NEXT p_send_parameters IN p_send_buffer;
    p_send_parameters^.buffer_header.version := dfc$poll_task_version;
    p_send_parameters^.buffer_header.transaction_count :=
          p_cpu_queue^.queue_entries [dfc$poll_queue_index].transaction_count;
    p_send_parameters^.buffer_header.retransmission_count := p_cpu_queue^.
          queue_entries [dfc$poll_queue_index].retransmission_count;
    p_send_parameters^.buffer_header.remote_processor := dfc$poll_task;
    p_send_parameters^.buffer_header.data_length_sent := 0;
    p_send_parameters^.poll_header := reply_header;

{---------------------------------
{   Format Poll_Reply message.
{---------------------------------

    CASE reply_header.poll_type OF
    = dfc$poll_reply, dfc$deactivate_reply, dfc$deactivate_server, dfc$recovery_complete_reply,
          dfc$req_verify_served_family =

{     These poll reply types only require poll_header.

    = dfc$verify_family_reply, dfc$verify_queue_reply =
      NEXT p_number_of_families IN p_send_buffer;
      IF (p_family_list = NIL) THEN
        p_number_of_families^ := 0;
      ELSE
        p_number_of_families^ := UPPERBOUND (p_family_list^.families);
        NEXT p_poll_family_list: [1 .. UPPERBOUND (p_family_list^.families)] IN p_send_buffer;
        p_poll_family_list^ := p_family_list^;
      IFEND;

      IF (reply_header.poll_type = dfc$verify_queue_reply) THEN
        IF (p_queue_information = NIL) THEN
          system_error (' NO QUEUE INFO LIST FOR POLL_REPLY IN ISSUE_POLL_REPLY');

        ELSE
          NEXT p_poll_queue_information IN p_send_buffer;
          p_poll_queue_information^ := p_queue_information^;
        IFEND;
      IFEND;

    ELSE
      system_error ('INCORRECT POLL REPLY IN ISSUE_POLL_REPLY.');
    CASEND;

    actual_length := dfp$word_boundary (i#current_sequence_position (p_send_buffer));
    p_send_parameters^.buffer_header.buffer_length_sent := actual_length;
    p_driver_entry^.flags := dfv$send_command_flags;
    p_driver_entry^.send_buffer_descriptor.actual_length := actual_length;
    IF reply_header.poll_type = dfc$verify_queue_reply THEN
      pmp$get_compact_date_time (p_poll_queue_information^.server_date_time, ignore_status);
    IFEND;
    IF dfv$display_poll THEN
      send_message_to_operator (dfv$poll_type_string [reply_header.poll_type],
      ' Issue Poll Reply');
    IFEND;
    dfp$queue_task_request (p_queue_interface_table, queue_index, dfc$poll_queue_index);

  PROCEND issue_poll_reply;

?? TITLE := '    process_family_verification', EJECT ??

  PROCEDURE process_family_verification
    (    client_binary_id: pmt$binary_mainframe_id;
     VAR number_of_families: 0 .. dfc$max_family_parameters;
     VAR family_container: SEQ (REP dfc$max_family_parameters of dft$family_verification));

    VAR
      access_list: array [1 .. dfc$max_family_ptr_array_size] of dft$family_access,
      family_index: 1 .. dfc$max_family_parameters,
      family_list: array [1 .. dfc$max_family_ptr_array_size] of ost$family_name,
      client_family_count: 0 .. dfc$max_family_ptr_array_size,
      out_index: 0 .. dfc$max_family_ptr_array_size,
      p_family_container: ^SEQ (REP dfc$max_family_parameters of dft$family_verification),
      p_family_verification: ^dft$family_verification;

    p_family_container := ^family_container;
    RESET p_family_container;

    osp$get_families_for_client (client_binary_id, ^family_list, ^access_list, client_family_count);

  /search_list/
    FOR out_index := 1 TO client_family_count DO

      IF access_list [out_index] = $dft$family_access [] THEN
        CYCLE /search_list/;
      IFEND;

      RESET p_family_container;

    /search_container/
      FOR family_index := 1 TO number_of_families DO
        NEXT p_family_verification IN p_family_container;
        IF p_family_verification^.family = family_list [out_index] THEN
          p_family_verification^.family_access := access_list [out_index];
          p_family_verification^.valid := TRUE;
          CYCLE /search_list/;
        IFEND;
      FOREND /search_container/;

{Family not found in family container - that is, not specified by client.
{  Add entry from family list on this (server) mainframe.

      NEXT p_family_verification IN p_family_container;
      p_family_verification^.family := family_list [out_index];
      p_family_verification^.family_access := access_list [out_index];
      p_family_verification^.valid := TRUE;
      number_of_families := number_of_families + 1;
    FOREND /search_list/;

  PROCEND process_family_verification;

?? TITLE := '    process_poll', EJECT ??

  PROCEDURE process_poll
    (    p_cpu_queue: ^dft$cpu_queue;
         queue_index: dft$queue_index;
         p_queue_interface_table: ^dft$queue_interface_table;
     VAR reply_header: dft$poll_header;
     VAR status: ost$status);

    VAR
      client_found: boolean,
      families: SEQ (REP dfc$max_family_parameters of dft$family_verification),
      ignore_status: ost$status,
      mainframe_name: pmt$mainframe_id,
      new_poll: boolean,
      number_of_families: 0 .. dfc$max_family_parameters,
      operator_message: string (79),
      operator_message_length: integer,
      p_buffer_parameters: ^dft$poll_message,
      p_families: ^SEQ (REP dfc$max_family_parameters of dft$family_verification),
      p_family_list: ^dft$poll_family_list,
      p_number_of_families: ^0 .. dfc$max_family_parameters,
      p_poll_header: ^dft$poll_header,
      p_queue_information: ^dft$poll_queue_information,
      p_queue_information_received: ^dft$poll_queue_information,
      p_receive_buffer: dft$p_command_buffer,
      queue_directory_index: dft$queue_directory_index,
      queue_information_received: dft$poll_queue_information,
      reactivating_partner: boolean,
      restart: boolean;

    mainframe_name := p_cpu_queue^.queue_header.destination_mainframe_name;
    restart := FALSE;
    reactivating_partner := FALSE;
    p_receive_buffer := p_cpu_queue^.queue_entries [dfc$poll_queue_index].p_receive_buffer;
    RESET p_receive_buffer;
    NEXT p_buffer_parameters IN p_receive_buffer;
    p_queue_information_received := NIL;
    p_family_list := NIL;

    validate_received_poll (p_cpu_queue, queue_index, p_queue_interface_table, new_poll);
    status.normal := TRUE;
    IF NOT new_poll THEN
      RETURN;
    IFEND;

{------------------------------------
{   Match Poll Type with Server State
{------------------------------------

    p_poll_header := ^p_buffer_parameters^.poll_header;
    CASE p_cpu_queue^.queue_header.partner_status.server_state OF
    = dfc$active, dfc$recovering =
      CASE p_poll_header^.poll_type OF
      = dfc$normal_poll =
        IF (p_cpu_queue^.queue_header.partner_status.server_state = dfc$active) AND
              p_cpu_queue^.queue_header.partner_status.send_deactivate_partner THEN
          reply_header.poll_type := dfc$deactivate_server;
          p_cpu_queue^.queue_header.partner_status.send_deactivate_partner := FALSE;
        ELSEIF p_cpu_queue^.queue_header.partner_status.verify_family THEN
          reply_header.poll_type := dfc$req_verify_served_family;
          p_cpu_queue^.queue_header.partner_status.verify_family := FALSE;
        ELSE
          reply_header.poll_type := dfc$poll_reply;
        IFEND;
      = dfc$recovery_complete =
        p_cpu_queue^.queue_header.partner_status.send_deactivate_partner :=  FALSE;
        p_cpu_queue^.queue_header.partner_status.server_state := dfc$active;
        dfp$set_client_mf_file_info (p_cpu_queue^.queue_header.destination_mainframe_id, dfc$active,
              p_cpu_queue^.queue_header.server_lifetime, p_cpu_queue^.queue_header.server_birthdate,
              client_found);
        reply_header.poll_type := dfc$recovery_complete_reply;
        operator_message := '  Recovery complete';
        send_message_to_operator (operator_message, mainframe_name);
        call_state_change_procedures (dfc$recovering, dfc$active, p_cpu_queue);

      = dfc$deactivate_server =
        p_cpu_queue^.queue_header.partner_status.server_state := dfc$deactivated;
        dfp$set_client_mf_file_info (p_cpu_queue^.queue_header.destination_mainframe_id, dfc$deactivated,
              p_cpu_queue^.queue_header.server_lifetime, p_cpu_queue^.queue_header.server_birthdate,
              client_found);
        p_cpu_queue^.queue_header.partner_status.send_deactivate_partner := FALSE;
        reply_header.poll_type := dfc$deactivate_reply;
        operator_message := '  Deactivating.';
        send_message_to_operator (operator_message, mainframe_name);
        call_state_change_procedures (dfc$active, dfc$deactivated, p_cpu_queue);

      = dfc$verify_served_family =
        IF p_cpu_queue^.queue_header.partner_status.send_deactivate_partner THEN
          reply_header.poll_type := dfc$deactivate_server;
          p_cpu_queue^.queue_header.partner_status.server_state := dfc$deactivated;
          dfp$set_client_mf_file_info (p_cpu_queue^.queue_header.destination_mainframe_id, dfc$deactivated,
                p_cpu_queue^.queue_header.server_lifetime, p_cpu_queue^.queue_header.server_birthdate,
                client_found);
          call_state_change_procedures (dfc$active, dfc$deactivated, p_cpu_queue);
          p_cpu_queue^.queue_header.partner_status.send_deactivate_partner := FALSE;
        ELSE
          p_families := ^families;
          format_family_list (p_cpu_queue, queue_index, p_queue_interface_table, number_of_families,
                p_receive_buffer, p_families, p_family_list);
          reply_header.poll_type := dfc$verify_family_reply;
        IFEND;
      = dfc$verify_queue =
        { Unexpected verify queue occurred.
        operator_message := '  Beginning CLIENT Re-activation.';
        restart := TRUE;
        timeout_job (p_cpu_queue, queue_index, p_queue_interface_table, operator_message, restart);

      ELSE
        operator_message := ' ';
        STRINGREP (operator_message, operator_message_length,
              ' TIMING CLIENT:incorrect POLL received - active', $integer (
               p_poll_header^.poll_type));
        timeout_job (p_cpu_queue, queue_index, p_queue_interface_table, operator_message, restart);
      CASEND;

    = dfc$deactivated =
      IF p_poll_header^.poll_type = dfc$deactivate_complete THEN
        p_cpu_queue^.queue_header.partner_status.server_state := dfc$inactive;
        dfp$set_client_mf_file_info (p_cpu_queue^.queue_header.destination_mainframe_id, dfc$inactive,
              p_cpu_queue^.queue_header.server_lifetime, p_cpu_queue^.queue_header.server_birthdate,
              client_found);
        call_state_change_procedures (dfc$deactivated, dfc$inactive, p_cpu_queue);
        operator_message := '  Turned inactive.';
        send_message_to_operator (operator_message, mainframe_name);

      ELSEIF p_poll_header^.poll_type = dfc$verify_queue THEN
        { Unexpected verify queue
        operator_message := '  Beginning CLIENT Re-activation.';
        restart := TRUE;
        timeout_job (p_cpu_queue, queue_index, p_queue_interface_table, operator_message, restart);

      ELSE
        operator_message := ' ';
        STRINGREP (operator_message, operator_message_length,
              ' TIMING CLIENT:incorrect POLL received - deact', $integer (
               p_poll_header^.poll_type));
        timeout_job (p_cpu_queue, queue_index, p_queue_interface_table, operator_message, restart);
      IFEND;

{   ----------------------------------------------
{   Validate contents of Verify_Queue Poll Type
{   ----------------------------------------------

    = dfc$inactive, dfc$terminated, dfc$awaiting_recovery =
      IF p_poll_header^.poll_type = dfc$verify_queue THEN
        operator_message := '  Queue verification message arrived.';
        send_message_to_operator (operator_message, mainframe_name);
        p_cpu_queue^.queue_header.partner_status.verify_queue := FALSE;
        p_families := ^families;
        format_family_list (p_cpu_queue, queue_index, p_queue_interface_table, number_of_families,
              p_receive_buffer, p_families, p_family_list);

        NEXT p_queue_information IN p_receive_buffer;
        queue_information_received := p_queue_information^;
        verify_queue_information (reply_header, p_cpu_queue, queue_index, p_queue_interface_table,
              queue_information_received, status);

        reply_header.poll_type := dfc$verify_queue_reply;
        p_queue_information_received := ^queue_information_received;
        queue_information_received.status := status;
        IF status.normal OR (status.condition = dfe$os_name_conflict) THEN
          status.normal := TRUE;
          p_cpu_queue^.queue_header.server_lifetime := queue_information_received.server_lifetime;
          p_cpu_queue^.queue_header.server_birthdate := queue_information_received.server_birthdate;
          p_cpu_queue^.queue_header.timeout_interval := queue_information_received.timeout_interval;
          p_cpu_queue^.queue_header.maximum_request_timeout_count :=
                queue_information_received.maximum_timeout_count;
          p_cpu_queue^.queue_header.maximum_retransmission_count :=
                queue_information_received.maximum_retransmission_count;


          CASE p_cpu_queue^.queue_header.partner_status.server_state OF
          = dfc$terminated, dfc$awaiting_recovery =
            IF (p_cpu_queue^.queue_header.partner_status.server_state = dfc$awaiting_recovery) THEN
              p_cpu_queue^.queue_header.partner_status.server_state := dfc$recovering;
              dfp$set_client_mf_file_info (p_cpu_queue^.queue_header.destination_mainframe_id, dfc$recovering,
                    p_cpu_queue^.queue_header.server_lifetime, p_cpu_queue^.queue_header.server_birthdate,
                    client_found);
              call_state_change_procedures (dfc$awaiting_recovery, dfc$recovering, p_cpu_queue);

            ELSE
              p_cpu_queue^.queue_header.partner_status.server_state := dfc$active;
              dfp$set_client_mf_file_info (p_cpu_queue^.queue_header.destination_mainframe_id, dfc$active,
                    p_cpu_queue^.queue_header.server_lifetime, p_cpu_queue^.queue_header.server_birthdate,
                    client_found);
              call_state_change_procedures (dfc$terminated, dfc$active, p_cpu_queue);
            IFEND;
            p_cpu_queue^.queue_header.partner_status.send_deactivate_partner := FALSE;
            dfp$establish_clone_task_stable (mainframe_name, p_cpu_queue^.queue_header.
                  number_of_monitor_queue_entries, p_cpu_queue^.queue_header.number_of_task_queue_entries,
                  status);
            IF NOT status.normal THEN
              display_error_status (status);
              operator_message := '  Clone Master cannot establish clone tasks - timing out client.';
              { Allow conditions to be cleaned up.
              timeout_job (p_cpu_queue, queue_index, p_queue_interface_table, operator_message, restart);
            IFEND;

          ELSE { Inactive
            p_cpu_queue^.queue_header.partner_status.server_state := dfc$active;
            p_cpu_queue^.queue_header.partner_status.send_deactivate_partner := FALSE;
            dfp$set_client_mf_file_info (p_cpu_queue^.queue_header.destination_mainframe_id, dfc$active,
                  p_cpu_queue^.queue_header.server_lifetime, p_cpu_queue^.queue_header.server_birthdate,
                  client_found);
            call_state_change_procedures (dfc$inactive, dfc$active, p_cpu_queue);
          CASEND;

        ELSEIF status.condition = dfe$force_client_recovery THEN
          { The client is inactive but the server is awaiting recovery.
          { Force the client to awaiting_recovery and re-activate.
          send_message_to_operator ('Forcing recovery of client ', mainframe_name);
          p_cpu_queue^.queue_header.partner_status.verify_queue := TRUE;
          reactivating_partner := TRUE;
          status.normal := TRUE;
        ELSEIF status.condition = dfe$force_client_termination THEN
          { The client is inactive or awaiting recovery, but the server is terminated.
          { Force the client to terminate and re-activate.
          send_message_to_operator ('Forcing termination of client ', mainframe_name);
          p_cpu_queue^.queue_header.partner_status.verify_queue := TRUE;
          reactivating_partner := TRUE;
          status.normal := TRUE;
        ELSEIF status.condition = dfe$force_server_recovery THEN
          { The client is awaiting_recovery, but the server is inactive.
          { Force the server to awaiting_recovery and re-activate.
          timeout_job (p_cpu_queue, queue_index, p_queue_interface_table,
                ' Forcing recovery of server ', TRUE);
        ELSEIF status.condition = dfe$force_server_termination THEN
          { The client is terminated, but the server is awaiting_recovery or inactive.
          { Force the server to terminate and re-activate.
          terminate_job (p_cpu_queue, queue_index, p_queue_interface_table,
              ' Forcing termination of server ', TRUE);
        ELSEIF status.condition = dfe$client_lifetime_error THEN
          { This is the most difficult case. Both mainframes have to be
          { terminated and restarted.
          { First terminate the server and on the
          { next re-activation the client will be forced to terminate and
          { re-activate.
          terminate_job (p_cpu_queue, queue_index, p_queue_interface_table,
              ' force termination of server - client next ', TRUE);
        ELSEIF status.condition = dfe$client_verification_error THEN
          p_cpu_queue^.queue_header.partner_status.verify_queue := TRUE;
        ELSE { Any other unexpected status?
        IFEND;

      ELSE
        operator_message := ' ';
        STRINGREP (operator_message, operator_message_length,
              ' TIMING CLIENT:incorrect POLL received - AwaitRec', $integer (
               p_poll_header^.poll_type));
        timeout_job (p_cpu_queue, queue_index, p_queue_interface_table, operator_message, restart);
      IFEND;

    ELSE
      system_error (' SERVER STATE INVALID IN PROCESS_POLL');
    CASEND;

    IF (p_poll_header^.poll_type = dfc$deactivate_complete) THEN

{     ------------------------------------------------------------
{     If the deactivation process is complete - do not reply to
{     the poll, just go INACTIVE after setting transaction_state to
{     follow standard file server protocol.
{     ------------------------------------------------------------

      p_queue_interface_table^.queue_directory.driver_queue_pva_directory [queue_index].p_driver_queue^.
            queue_entries [dfc$poll_queue_index].flags.subsystem_action := FALSE;
      p_queue_interface_table^.queue_directory.cpu_queue_pva_directory [queue_index].p_cpu_queue^.
            queue_entries [dfc$poll_queue_index].transaction_state := dfc$server_waiting_request;
      dfp$get_queue_directory_index (p_queue_interface_table, queue_directory_index);
      dfp$unload_pp_if_last (^dfv$p_queue_interface_directory^ [queue_directory_index], queue_index, status);
    ELSE
      issue_poll_reply (p_cpu_queue, queue_index, p_queue_interface_table, reply_header, p_family_list,
            p_queue_information_received);
      IF reactivating_partner THEN
        { Reset transaction count and retransmission count so the reactivation
        { request will occur.
         p_cpu_queue^.queue_entries [dfc$poll_queue_index].transaction_count := 0;
         p_cpu_queue^.queue_entries [dfc$poll_queue_index].retransmission_count := 0;
      IFEND;
    IFEND;

  PROCEND process_poll;

?? TITLE := '      restart_client_job ', EJECT ??
{ This procedure re-submits the client mainframe job.
{ No one gets out of here alive.

  PROCEDURE restart_client_job
    (    p_cpu_queue: ^dft$cpu_queue);

    VAR
      status: ost$status;

    dfp$reset_mainframe_tables (p_cpu_queue^.queue_header.destination_mainframe_name,
          {server_to_client=} TRUE, status);
    IF status.normal THEN
      p_cpu_queue^.queue_header.partner_status.verify_queue := TRUE;
      dfp$submit_client_mainframe_job (p_cpu_queue^.queue_header.destination_mainframe_name, status);
    IFEND;

    IF status.normal THEN
      send_message_to_operator (' Client Re-activation Started.',
            p_cpu_queue^.queue_header.destination_mainframe_name);
    ELSE
      p_cpu_queue^.queue_header.partner_status.verify_queue := FALSE;
      display_error_status (status);
      send_message_to_operator (' Client  Re-activation Aborted.',
            p_cpu_queue^.queue_header.destination_mainframe_name);
      status.normal := TRUE;
    IFEND;

    dfv$normal_client_termination := TRUE;
    pmp$exit (status);

  PROCEND restart_client_job;
?? TITLE := '      send_message_to_operator ', EJECT ??
  PROCEDURE send_message_to_operator
    (    message: string ( * <= 125);
         mainframe_name: pmt$mainframe_id);

    dfp$send_message_to_operator (message, { Server_to_client } TRUE, mainframe_name);
  PROCEND send_message_to_operator;

?? TITLE := '      set_verification_error ', EJECT ??

  PROCEDURE set_verification_error
    (    parameter_message: string ( * <= 79);
         mainframe_name: pmt$mainframe_id;
     VAR status: ost$status);

    osp$set_status_abnormal (dfc$file_server_id, dfe$client_verification_error, mainframe_name, status);
    osp$append_status_parameter (osc$status_parameter_delimiter, parameter_message, status);
    display_error_status (status);

  PROCEND set_verification_error;

?? TITLE := '    system_error  ', EJECT ??

  PROCEDURE system_error
    (    text: string ( * ));

    VAR
      user_supplied_name: jmt$user_supplied_name,
      system_supplied_name: jmt$system_supplied_name,
      local_status: ost$status;

    pmp$get_job_names (user_supplied_name, system_supplied_name, local_status);

    dpp$put_next_line (dpv$system_core_display, ' Client mainframe job - File server system error:',
          local_status);
    dpp$put_next_line (dpv$system_core_display, user_supplied_name, local_status);
    dpp$put_next_line (dpv$system_core_display, text, local_status);

    pmp$log_ascii (text, $pmt$ascii_logset [pmc$system_log, pmc$job_log], pmc$msg_origin_system,
          local_status);
    pmp$log_ascii (user_supplied_name, $pmt$ascii_logset [pmc$system_log, pmc$job_log], pmc$msg_origin_system,
          local_status);

    IF dfv$file_server_debug_enabled THEN
      syp$invoke_system_debugger (text, 0, local_status);
    IFEND;
    local_status.normal := TRUE;
    dfv$normal_client_termination := TRUE;
    pmp$exit (local_status);
  PROCEND system_error;
?? TITLE := '    terminate_job', EJECT ??
{
{   This procedure terminates the Client job. Depending on the value of the
{   RESTART parameter another Client job may be submitted here.
{
{   If any call out of this procedure returns an abnormal status, that status
{   is merely reported and the processing continues until the job termination
{   is completed.
{
{   The exception to the status handling occurs when another Client job is
{   to be submitted and a termination process of the current Client job produces
{   a bad status. In this case the new Client job is NOT started.
{
{   There is no return from this procedure.
{

  PROCEDURE terminate_job
    (    p_cpu_queue: ^dft$cpu_queue;
         queue_index: dft$queue_index;
         p_queue_interface_table: ^dft$queue_interface_table;
         operator_message: string ( * <= 79);
         restart: boolean);

    VAR
      client_found: boolean,
      local_status: ost$status,
      p_driver_flags: ^dft$queue_entry_flags,
      old_state: dft$server_state,
      queue_directory_index: dft$queue_directory_index,
      status: ost$status,
      submit: boolean;

    local_status.normal := TRUE;
    status.normal := TRUE;
    submit := restart;

    send_message_to_operator (operator_message, p_cpu_queue^.queue_header.destination_mainframe_name);
    p_driver_flags := ^p_queue_interface_table^.queue_directory.driver_queue_pva_directory [queue_index].
          p_driver_queue^.queue_entries [dfc$poll_queue_index].flags;

    p_driver_flags^.subsystem_action := FALSE;
    old_state :=  p_cpu_queue^.queue_header.partner_status.server_state;
    p_cpu_queue^.queue_header.partner_status.server_state := dfc$terminated;
    p_cpu_queue^.queue_header.partner_status.terminate_partner := FALSE;
    p_cpu_queue^.queue_header.partner_status.timeout_partner := FALSE;
    p_cpu_queue^.queue_header.partner_status.verify_queue := FALSE;
    p_cpu_queue^.queue_header.partner_status.deactivate_complete := FALSE;
    dfp$set_client_mf_file_info (p_cpu_queue^.queue_header.destination_mainframe_id, dfc$terminated,
          p_cpu_queue^.queue_header.server_lifetime, p_cpu_queue^.queue_header.server_birthdate,
          client_found);

    dfp$term_processing_on_server (p_cpu_queue^.queue_header.destination_mainframe_name, status);
    IF NOT status.normal THEN
      send_message_to_operator (' Client Termination Error - term processing.',
            p_cpu_queue^.queue_header.destination_mainframe_name);
      display_error_status (status);
      submit := FALSE;
    IFEND;

    dfp$remove_client_jobs (p_cpu_queue^.queue_header.destination_mainframe_name, status);
    IF NOT status.normal THEN
      send_message_to_operator (' Client Termination Error - remove client jobs   .',
            p_cpu_queue^.queue_header.destination_mainframe_name);
      display_error_status (status);
      submit := FALSE;
    IFEND;

    qfp$discard_client_jobs (p_cpu_queue^.queue_header.destination_mainframe_id);
    IF dfc$tjr_halt_terc IN syv$test_jr_job THEN
      { LRZ TEST CASE
      dfv$normal_client_termination := TRUE;
      p_driver_flags := NIL;
      p_driver_flags^.subsystem_action := FALSE;
    IFEND;

    dfp$get_queue_directory_index (p_queue_interface_table, queue_directory_index);
    dfp$unload_pp_if_last (^dfv$p_queue_interface_directory^ [queue_directory_index], queue_index, status);
    IF NOT status.normal THEN
      send_message_to_operator (' Client Termination Error - unload pp.',
            p_cpu_queue^.queue_header.destination_mainframe_name);
      submit := FALSE;
      display_error_status (status);
    IFEND;

    call_state_change_procedures (old_state, dfc$terminated, p_cpu_queue);

    IF submit THEN
      restart_client_job (p_cpu_queue);
    ELSE
      IF restart THEN
        send_message_to_operator (' Client Terminated, Re-activation Aborted.',
              p_cpu_queue^.queue_header.destination_mainframe_name);
      IFEND;
      send_message_to_operator (' Client Termination Complete.',
            p_cpu_queue^.queue_header.destination_mainframe_name);
      local_status.normal := TRUE;
      dfv$normal_client_termination := TRUE;
      pmp$exit (local_status);
    IFEND;

  PROCEND terminate_job;
?? TITLE := '    timeout_job', EJECT ??

{------------------------------------------------------------------------------------
{   This procedure terminates the Client job on a timeout situation.
{
{   If any call out of this procedure returns an abnormal status, that status
{   is merely reported and the processing continues until the job termination
{   is completed.
{
{   The exception to the status handling occurs when another Client job is
{   to be submitted and a termination process of the current Client job produces
{   a bad status. In this case the new Client job is NOT started.
{------------------------------------------------------------------------------------

  PROCEDURE timeout_job
    (    p_cpu_queue: ^dft$cpu_queue;
         queue_index: dft$queue_index;
         p_queue_interface_table: ^dft$queue_interface_table;
         operator_message: string ( * <= 79);
         restart: boolean);

    VAR
      client_found: boolean,
      local_status: ost$status,
      old_state: dft$server_state,
      p_driver_flags: ^dft$queue_entry_flags,
      queue_directory_index: dft$queue_directory_index,
      status: ost$status,
      submit_new_job: boolean;


    local_status.normal := TRUE;
    status.normal := TRUE;
    submit_new_job := restart;
    IF (NOT dfv$job_recovery_enabled) OR
          (p_cpu_queue^.queue_header.partner_status.server_state = dfc$terminated) THEN
      terminate_job (p_cpu_queue, queue_index, p_queue_interface_table, operator_message, restart);
      RETURN;
    IFEND;

    send_message_to_operator (operator_message, p_cpu_queue^.queue_header.destination_mainframe_name);
    p_driver_flags := ^p_queue_interface_table^.queue_directory.driver_queue_pva_directory [queue_index].
          p_driver_queue^.queue_entries [dfc$poll_queue_index].flags;

    old_state := p_cpu_queue^.queue_header.partner_status.server_state;
    p_driver_flags^.subsystem_action := FALSE;
    p_cpu_queue^.queue_header.partner_status.server_state := dfc$awaiting_recovery;
    p_cpu_queue^.queue_header.partner_status.timeout_partner := FALSE;
    p_cpu_queue^.queue_header.partner_status.terminate_partner := FALSE;
    p_cpu_queue^.queue_header.partner_status.verify_queue := FALSE;
    p_cpu_queue^.queue_header.partner_status.deactivate_complete := FALSE;
    dfp$set_client_mf_file_info (p_cpu_queue^.queue_header.destination_mainframe_id, dfc$awaiting_recovery,
          p_cpu_queue^.queue_header.server_lifetime, p_cpu_queue^.queue_header.server_birthdate,
          client_found);
    status.normal := TRUE;

    dfp$term_processing_on_server (p_cpu_queue^.queue_header.destination_mainframe_name, status);
    IF NOT status.normal THEN
      display_error_status (status);
      submit_new_job := FALSE;
    IFEND;
    dfp$get_queue_directory_index (p_queue_interface_table, queue_directory_index);
    dfp$unload_pp_if_last (^dfv$p_queue_interface_directory^ [queue_directory_index], queue_index, status);
    IF NOT status.normal THEN
      submit_new_job := FALSE;
      display_error_status (status);
    IFEND;

    call_state_change_procedures (old_state, dfc$awaiting_recovery, p_cpu_queue);

    IF submit_new_job THEN
      restart_client_job (p_cpu_queue);
    ELSE
      send_message_to_operator (' Client Timeout Complete.',
            p_cpu_queue^.queue_header.destination_mainframe_name);
      local_status.normal := TRUE;
      dfv$normal_client_termination := TRUE;
      pmp$exit (local_status);
    IFEND;

  PROCEND timeout_job;

?? TITLE := '    time_out_poll', EJECT ??

  PROCEDURE time_out_poll
    (    p_cpu_queue: ^dft$cpu_queue;
         queue_index: dft$queue_index;
         p_queue_interface_table: ^dft$queue_interface_table);

    VAR
      current_time: integer,
      elapsed_time: integer,
      operator_message: string (79),
      request_time: integer,
      restart: boolean,
      status: ost$status;

    IF NOT ((p_cpu_queue^.queue_header.partner_status.server_state = dfc$active) OR
          (p_cpu_queue^.queue_header.partner_status.server_state = dfc$deactivated) OR
          (p_cpu_queue^.queue_header.partner_status.server_state = dfc$recovering)) THEN
      RETURN;
    IFEND;

{   --------------------------------------------------------------------------
{   This procedure times out the Client mainframe by comparing the time
{   of the poll_reply request to the current time. If the time difference
{   is greater than the specified timeout value then the fresh poll message
{   has still not arrived from the Client mainframe. This means that either
{   the poll_reply has not reached the Client or the Client is unable to issue
{   a new poll. As a result the Client mainframe is going to be Terminated.
{
{   The specified timeout value is computed from the values obtained from the
{   Client during the queue verification processing.
{   --------------------------------------------------------------------------

    current_time := #FREE_RUNNING_CLOCK (0);
    request_time := p_cpu_queue^.queue_entries [dfc$poll_queue_index].request_start_time;
    elapsed_time := current_time - request_time;

    IF (elapsed_time >= (p_cpu_queue^.queue_header.timeout_interval *
          p_cpu_queue^.queue_header.maximum_request_timeout_count *
          p_cpu_queue^.queue_header.maximum_retransmission_count)) THEN
      restart := FALSE;
      IF dfv$job_recovery_enabled THEN
        operator_message := '  Client Poll Message TIMED OUT - TIMING OUT CLIENT.';
        timeout_job (p_cpu_queue, queue_index, p_queue_interface_table, operator_message, restart);
      ELSE
        operator_message := '  Client Poll Message TIMED OUT - TERMINATING CLIENT.';
        terminate_job (p_cpu_queue, queue_index, p_queue_interface_table, operator_message, restart);
      IFEND;
    IFEND;

  PROCEND time_out_poll;

?? TITLE := '    validate_received_poll', EJECT ??

  PROCEDURE validate_received_poll
    (    p_cpu_queue: ^dft$cpu_queue;
         queue_index: dft$queue_index;
         p_queue_interface_table: ^dft$queue_interface_table;
     VAR new_poll: boolean);

    VAR
      action_for_server: dft$action_for_server,
      p_cpu_queue_entry: ^dft$cpu_queue_entry,
      p_driver_queue_entry: ^dft$driver_queue_entry,
      mainframe_name: pmt$mainframe_id,
      operator_message: string (79),
      p_buffer_parameters: ^dft$poll_message,
      p_receive_buffer: dft$p_command_buffer,
      restart: boolean;


{---------------------------------------------------------------------------
{   This procedure will verify the content of the received Poll header.
{   If incorrect, it will terminate the Client job.
{   It will also check the transaction and the retransmission counts. Again,
{   an error will result in the Client job termination.
{---------------------------------------------------------------------------

    dfp$fetch_queue_entry (p_queue_interface_table, queue_index, dfc$poll_queue_index, p_driver_queue_entry,
          p_cpu_queue_entry);

    restart := FALSE;
    mainframe_name := p_cpu_queue^.queue_header.destination_mainframe_name;
    p_receive_buffer := p_cpu_queue_entry^.p_receive_buffer;
    RESET p_receive_buffer;
    NEXT p_buffer_parameters IN p_receive_buffer;
    new_poll := TRUE;

{-------------------------
{   Validate Poll Header.
{-------------------------

    IF NOT ((p_buffer_parameters^.buffer_header.version = dfc$poll_task_version) AND
          (p_buffer_parameters^.buffer_header.remote_processor = dfc$poll_task) AND
          (p_buffer_parameters^.buffer_header.data_length_sent = 0)) THEN
      operator_message := '  TIMEOUT CLIENT because incorrect BUFFER HEADER was received.';
      timeout_job (p_cpu_queue, queue_index, p_queue_interface_table, operator_message, restart);
    IFEND;

    IF NOT (p_buffer_parameters^.poll_header.mainframe_name = mainframe_name) THEN
      operator_message := '  TERMINATING CLIENT because incorrect MAINFRAME NAME was received.';
       { It wont get any better on second attempt.
      terminate_job (p_cpu_queue, queue_index, p_queue_interface_table, operator_message, restart);
    IFEND;

{----------------------------------------------------------------------------
{   Validate Transaction Count:
{     If the transaction count in the Poll message is 1 greater than the
{       transaction count in the CPU Queue then this is a new Poll message.
{     If the transaction counts in the Poll and in the CPU Queue are the same
{       but retransmission counts are not equal then the Poll_Reply will be
{       retransmitted out of here.
{     All other conditions result in Client job termination.
{----------------------------------------------------------------------------

    dfp$determine_action_for_server (p_cpu_queue_entry, p_driver_queue_entry, action_for_server);

    CASE action_for_server OF
    = dfc$new_request =
{     This is a new Poll - process it in Process_Poll.
      RETURN;

    = dfc$retransmitted_request =
{     This is a RETRANSMITTED Poll - retransmit Poll_Reply.
      p_driver_queue_entry^.flags := dfv$send_command_flags;
      dfp$queue_task_request (p_queue_interface_table, queue_index, dfc$poll_queue_index);
      new_poll := FALSE;

    = dfc$transaction_out_of_sequence =

{--------------------------------------------------------------------------
{     If poll_type = dfc$verify_queue disregard the transaction count error
{     because the Client job will have to be terminated and then restarted.
{--------------------------------------------------------------------------

      IF p_buffer_parameters^.poll_header.poll_type = dfc$verify_queue THEN
        send_message_to_operator (' Unexpected verify queue - out of seq', mainframe_name);
        { An unexpected verify queue came.  Perhaps the client mainframe
        { timed out and was re-activated.  process_poll will know what to
        { do with this unexpected poll so the transaction counts are set to
        { match.
        p_cpu_queue_entry^.transaction_count :=
            p_buffer_parameters^.buffer_header.transaction_count;
        p_cpu_queue_entry^.retransmission_count :=
            p_buffer_parameters^.buffer_header.retransmission_count;
        RETURN;
      ELSE

{ Despite this error a reactivation will cleanup everything.

        operator_message := '  TIMEOUT CLIENT because of TRANSACTION COUNT mismatch.';
        timeout_job (p_cpu_queue, queue_index, p_queue_interface_table, operator_message, restart);
      IFEND;

    = dfc$complete_request =
      IF p_buffer_parameters^.poll_header.poll_type = dfc$verify_queue THEN
        send_message_to_operator (' Unexpected verify_queue -complete req', mainframe_name);
        p_cpu_queue_entry^.transaction_count :=
            p_buffer_parameters^.buffer_header.transaction_count;
        p_cpu_queue_entry^.retransmission_count :=
            p_buffer_parameters^.buffer_header.retransmission_count;
        RETURN;
      ELSE
        system_error ('COMPLETE REQUEST INVALID FOR POLL PROCESS.');
      IFEND;
    = dfc$complete_request_on_error =
      system_error ('COMPLETE REQUEST ON ERROR INVALID FOR POLL PROCESS.');

    ELSE
      system_error ('ACTION_FOR_SERVER CASE NOT RECOGNIZED.');
    CASEND;

  PROCEND validate_received_poll;

?? TITLE := '      verify_queue_information', EJECT ??

  PROCEDURE verify_queue_information
    (    reply_header: dft$poll_header;
         p_cpu_queue: ^dft$cpu_queue;
         queue_index: dft$queue_index;
         p_queue_interface_table: ^dft$queue_interface_table;
         queue_information: dft$poll_queue_information;
     VAR status: ost$status);

    VAR
      destination_log: pmt$ascii_logset,
      error_message: string (125),
      ignore_boolean: boolean,
      ignore_character: char,
      ignore_status: ost$status,
      mainframe_name: pmt$mainframe_id,
      message_length: integer,
      p_driver_header: ^dft$driver_queue_header,
      window: dpt$window_id;

    status.normal := TRUE;
    mainframe_name := p_cpu_queue^.queue_header.destination_mainframe_name;
    destination_log := $pmt$ascii_logset [pmc$system_log, pmc$job_log];
    window := dpv$system_core_display;

{   -------------------------------------------------------------
{   Compare the content of the queue_information block with the
{   local tables. Set status to abnormal and exit verification
{   block when any mismatch is encountered.
{   ------------------------------------------------------------

  /verification/
    BEGIN
      IF (reply_header.mainframe_name <> queue_information.destination_mainframe_name) THEN
        STRINGREP (error_message, message_length, 'Server mainframe name mismatch, received: ',
              queue_information.destination_mainframe_name, ', expected: ', reply_header.mainframe_name);
        set_verification_error (error_message (1, message_length), mainframe_name, status);
        EXIT /verification/;
      IFEND;

{     ----------------------------
{     Match CPU_Queue information.
{     Chances are we won't actually be able to communicate if these disagree.

      IF (queue_information.number_of_monitor_queue_entries <>
            p_cpu_queue^.queue_header.number_of_monitor_queue_entries) THEN
        STRINGREP (error_message, message_length, 'Monitor queue entries mismatch, received: ',
              queue_information.number_of_monitor_queue_entries, ', expected: ',
              p_cpu_queue^.queue_header.number_of_monitor_queue_entries);
        set_verification_error (error_message (1, message_length), mainframe_name, status);
        EXIT /verification/;
      IFEND;
      IF (queue_information.number_of_task_queue_entries <>
            p_cpu_queue^.queue_header.number_of_task_queue_entries) THEN
        STRINGREP (error_message, message_length, 'Task queue entries mismatch, received: ',
              queue_information.number_of_task_queue_entries, ', expected: ',
              p_cpu_queue^.queue_header.number_of_task_queue_entries);
        set_verification_error (error_message (1, message_length), mainframe_name, status);
        EXIT /verification/;
      IFEND;

{     ----------------------------------------
{     Match Queue_Interface_Table information.
{     Chances are we won't actually be able to communicate if these disagree.
{     ----------------------------------------

      IF (queue_information.esm_base_addresses <> p_queue_interface_table^.esm_base_addresses) THEN
        error_message := 'ESM base addresses mismatch:';
        message_length := 28;
        dpp$put_next_line (window, error_message (1, message_length), ignore_status);
        pmp$log_ascii (error_message (1, message_length), destination_log, pmc$msg_origin_program,
              ignore_status);
        STRINGREP (error_message, message_length, 'Number of mainframes received =',
              queue_information.esm_base_addresses.number_of_mainframes);
        set_verification_error (error_message (1, message_length), mainframe_name, status);
        STRINGREP (error_message, message_length, 'Divisions_per_mainframe_received =',
              queue_information.esm_base_addresses.divisions_per_mainframe);
        set_verification_error (error_message (1, message_length), mainframe_name, status);
        STRINGREP (error_message, message_length, 'ESM flag base received =',
              queue_information.esm_base_addresses.esm_flag_base);
        set_verification_error (error_message (1, message_length), mainframe_name, status);
        STRINGREP (error_message, message_length, 'ESM memory base received =',
              queue_information.esm_base_addresses.esm_memory_base * dfc$esm_memory_base_shift);
        set_verification_error (error_message (1, message_length), mainframe_name, status);
        STRINGREP (error_message, message_length, 'ESM division size received =',
              queue_information.esm_base_addresses.esm_division_size * dfc$esm_memory_base_shift);
        set_verification_error (error_message (1, message_length), mainframe_name, status);
        STRINGREP (error_message, message_length, 'ESM divsiz 12bit cw received =',
              queue_information.esm_base_addresses.esm_divsiz_12bit_cw * dfc$esm_division_chwrds_shift);
        set_verification_error (error_message (1, message_length), mainframe_name, status);
        STRINGREP (error_message, message_length, 'ESM divsiz 16bit cw received =',
              queue_information.esm_base_addresses.esm_divsiz_16bit_cw * dfc$esm_division_chwrds_shift);
        set_verification_error (error_message (1, message_length), mainframe_name, status);
        EXIT /verification/;
      IFEND;

      p_driver_header := ^p_queue_interface_table^.queue_directory.driver_queue_pva_directory [queue_index].
            p_driver_queue^.queue_header;

{     -------------------------------
{     Match Driver_Queue information.
{     Chances are we won't actually be able to communicate if these disagree.
{     -------------------------------

      IF (queue_information.driver_number_of_queue_entries <> p_driver_header^.number_of_queue_entries) THEN
        STRINGREP (error_message, message_length, 'Driver queue entries mismatch, received: ',
              queue_information.driver_number_of_queue_entries, ', expected: ',
              p_driver_header^.number_of_queue_entries);
        set_verification_error (error_message (1, message_length), mainframe_name, status);
        EXIT /verification/;
      IFEND;
      IF (queue_information.driver_source_id_number <> p_driver_header^.connection_descriptor.destination.
            id_number) THEN
        STRINGREP (error_message, message_length, 'Driver destination ID mismatch, ID received: ',
              queue_information.driver_source_id_number, ', expected: ',
              p_driver_header^.connection_descriptor.destination.id_number);
        set_verification_error (error_message (1, message_length), mainframe_name, status);
        EXIT /verification/;
      IFEND;
      IF (queue_information.driver_source_queue_index <> p_driver_header^.connection_descriptor.destination.
            queue_index) THEN
        STRINGREP (error_message, message_length, 'Driver destination queue index mismatch: received: ',
              queue_information.driver_destination_queue_index, ', expected: ',
              p_driver_header^.connection_descriptor.destination.queue_index);
        set_verification_error (error_message (1, message_length), mainframe_name, status);
        EXIT /verification/;
      IFEND;
      IF (queue_information.driver_destination_id_number <>
            p_driver_header^.connection_descriptor.source.id_number) THEN
        STRINGREP (error_message, message_length, 'Driver source id mismatch, id received: ',
              queue_information.driver_destination_id_number, ', expected: ',
              p_driver_header^.connection_descriptor.source.id_number);
        set_verification_error (error_message (1, message_length), mainframe_name, status);
        EXIT /verification/;
      IFEND;
      IF (queue_information.driver_destination_queue_index <>
            p_driver_header^.connection_descriptor.source.queue_index) THEN
        STRINGREP (error_message, message_length, 'Driver source queue index mismatch: index received: ',
              queue_information.driver_destination_queue_index, ', expected: ',
              p_driver_header^.connection_descriptor.source.queue_index);
        set_verification_error (error_message (1, message_length), mainframe_name, status);
        EXIT /verification/;
      IFEND;

{     Match the system information.  These are all non-fatal errors, and the
{     verification should continue.

      IF queue_information.client_page_size < osv$page_size THEN
        STRINGREP (error_message, message_length, 'System page size incompatibility: Client page size: ',
              queue_information.client_page_size, ' < Server page size: ', osv$page_size);
        set_verification_error (error_message (1, message_length), mainframe_name, status);
        EXIT /verification/;
      IFEND;
      IF (queue_information.client_page_size <> 1000(16)) AND
            (queue_information.client_page_size <> 2000(16)) THEN
        STRINGREP (error_message, message_length, 'System page size incompatibility: Client page size: ',
              queue_information.client_page_size, ' <> 4k AND <> 8k');
        set_verification_error (error_message (1, message_length), mainframe_name, status);
        EXIT /verification/;
      IFEND;
      IF queue_information.client_os_name <> osv$os_defaults_os_name THEN
        osp$set_status_abnormal (dfc$file_server_id, dfe$os_name_conflict, mainframe_name, status);
        osp$append_status_parameter (osc$status_parameter_delimiter, osv$os_defaults_os_name, status);
        osp$append_status_parameter (osc$status_parameter_delimiter, queue_information.client_os_name,
              status);
        display_error_status (status);
      IFEND;

      verify_state_information (p_cpu_queue, mainframe_name, queue_information, status);
      IF NOT status.normal THEN
        display_error_status (status);
      IFEND;

    END /verification/;

  PROCEND verify_queue_information;
?? TITLE := ' verify_state_information ', EJECT ??
  PROCEDURE verify_state_information
    (    p_cpu_queue: ^dft$cpu_queue;
         mainframe_name: pmt$mainframe_id;
         queue_information: dft$poll_queue_information;
     VAR status: ost$status);

    VAR
      client_state: dft$server_state,
      error_message: string (125),
      message_length: integer,
      server_state: dft$server_state;

    client_state := queue_information.server_state;
    server_state := p_cpu_queue^.queue_header.partner_status.server_state;
    status.normal := TRUE;

    IF (client_state = dfc$terminated) OR (server_state = dfc$terminated) THEN
      IF (client_state = dfc$terminated) AND (server_state <> dfc$terminated) THEN
        osp$set_status_abnormal (dfc$file_server_id, dfe$force_server_termination, mainframe_name, status);
        RETURN;
      IFEND;

      IF (client_state <> dfc$terminated) AND (server_state = dfc$terminated) THEN
        osp$set_status_abnormal (dfc$file_server_id, dfe$force_client_termination, mainframe_name, status);
        RETURN;
      IFEND;

      { Both client and server are terminated all is ok.
      RETURN;
    IFEND;

    IF (queue_information.previous_server_lifetime <> p_cpu_queue^.queue_header.server_lifetime) OR
          (queue_information.previous_server_birthdate <> p_cpu_queue^.queue_header.server_birthdate) THEN
      STRINGREP (error_message, message_length, ' Lifetime/Birthdate  mismatch- Received: ',
            queue_information.previous_server_lifetime, '/', queue_information.previous_server_birthdate,
            ', expected: ', p_cpu_queue^.queue_header.server_lifetime, '/',
            p_cpu_queue^.queue_header.server_birthdate);
      osp$set_status_abnormal (dfc$file_server_id, dfe$client_lifetime_error, mainframe_name, status);
      osp$append_status_parameter (osc$status_parameter_delimiter, error_message (1, message_length), status);
      RETURN;
    IFEND;

{  If one of the mainframes is inactivate and the other awaiting_recovery, we
{ need to force the inactive mainframe to go through recovery.
    IF (client_state = dfc$inactive) AND (server_state = dfc$awaiting_recovery) THEN
      osp$set_status_abnormal (dfc$file_server_id, dfe$force_client_recovery, mainframe_name, status);
      RETURN;
    IFEND;

    IF (client_state = dfc$awaiting_recovery) AND (server_state = dfc$inactive) THEN
      osp$set_status_abnormal (dfc$file_server_id, dfe$force_server_recovery, mainframe_name, status);
      RETURN;
    IFEND;

  PROCEND verify_state_information;
?? TITLE := '      wait_for_verify_queue_message ', EJECT ??

  PROCEDURE wait_for_verify_queue_message
    (    p_cpu_queue: ^dft$cpu_queue;
         queue_index: dft$queue_index;
         p_queue_interface_table: ^dft$queue_interface_table;
         p_q_interface_directory_entry: ^dft$q_interface_directory_entry;
     VAR reply_header: dft$poll_header);

{------------------------------------------------------------------------
{   Arbitrary value of the wait time before the queue information is
{   received. The value is in milliseconds.
{------------------------------------------------------------------------

    CONST
      initial_wait_time = 10 * 1000;

    VAR
      operator_message: string (79),
      p_driver_flags: ^dft$queue_entry_flags,
      poll_received: boolean,
      restart: boolean,
      status: ost$status,
      time_before_wait: integer;

{--------------------------------------------------------------------------
{   This procedure is executed whenever Activate_Client subcommand has been
{   issued and Server_State = dfc$terminated dfc$inactive or dfc$awaiting_recovery
{   The procedure sets the Queue IDLE flag to FALSE and activates PP driver.
{   (Should Activate_PP return abnormal status, IDLE will be set again by
{   Unload_PP_If_Last called in Terminate_Task).
{   It then waits until Subsystem_Action is set in Driver_Queue_Entry.
{   Finally it calls Determine_Wakeup_Cause to process the (presumed) message
{   from the Client.
{--------------------------------------------------------------------------

    status.normal := TRUE;
    restart := FALSE;

    dfp$load_pp_if_first (p_q_interface_directory_entry, queue_index, status);
    IF NOT status.normal THEN
      display_error_status (status);
      p_cpu_queue^.queue_header.partner_status.verify_queue := FALSE;
      operator_message := '  TIMEOUT CLIENT.';
      timeout_job (p_cpu_queue, queue_index, p_queue_interface_table, operator_message, restart);
    IFEND;

    p_driver_flags := ^p_queue_interface_table^.queue_directory.driver_queue_pva_directory [queue_index].
          p_driver_queue^.queue_entries [dfc$poll_queue_index].flags;
    REPEAT
      #SPOIL (p_cpu_queue^.queue_header.partner_status);
      #SPOIL (p_driver_flags^.subsystem_action);
      IF p_cpu_queue^.queue_header.partner_status.terminate_partner THEN
        p_cpu_queue^.queue_header.partner_status.verify_queue := FALSE;
        operator_message := '  Operator terminated Client.';
        terminate_job (p_cpu_queue, queue_index, p_queue_interface_table, operator_message, restart);
      ELSEIF p_cpu_queue^.queue_header.partner_status.timeout_partner THEN
        p_cpu_queue^.queue_header.partner_status.verify_queue := FALSE;
        operator_message := '  Operator timeout Client.';
        timeout_job (p_cpu_queue, queue_index, p_queue_interface_table, operator_message, restart);
      IFEND;
      time_before_wait := #FREE_RUNNING_CLOCK (0);
      pmp$wait (initial_wait_time, initial_wait_time);
    UNTIL p_driver_flags^.subsystem_action;

    determine_wakeup_cause (p_cpu_queue, queue_index, p_queue_interface_table, time_before_wait,
          reply_header);

  PROCEND wait_for_verify_queue_message;

MODEND dfm$manage_client_connection;

