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

{ PURPOSE:
{    The purpose of this module is to provide the procedures involved with
{    the verifying client jobs during file server job recovery. This module
{    includes a command processor and an "internal" procedure.

?? NEWTITLE := ' Global Declarations Referenced by This Module', EJECT ??
?? PUSH (LISTEXT := ON) ??
*copyc dfc$loopback_server_mainframe
*copyc dfe$error_condition_codes
*copyc dft$procedure_address_ordinal
*copyc dft$rpc_served_job_list
?? POP ??
*copyc clp$scan_parameter_list
*copyc dfi$display
*copyc dfi$log_display
*copyc dfp$crack_mainframe_id
*copyc dfp$find_mainframe_id
*copyc dfp$send_remote_procedure_call
*copyc dfp$verify_system_administrator
*copyc dfv$file_server_debug_enabled
*copyc i#current_sequence_position
*copyc jmp$job_exists
*copyc jmp$reconcile_leveled_jobs
*copyc osp$set_status_abnormal
*copyc osp$set_status_from_condition
*copyc pmp$convert_mainframe_to_binary
?? OLDTITLE ??
?? TITLE := '    [XDCL, #GATE] dfp$verify_client_jobs', EJECT ??

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

{  pdt verify_jobs_pdt     (
{   mainframe_id, mi: name pmc$mainframe_id_size = $required
{   status)

?? PUSH (LISTEXT := ON) ??
?? FMT (FORMAT := OFF) ??

  VAR
    verify_jobs_pdt: [STATIC, READ, cls$pdt] clt$parameter_descriptor_table := [^verify_jobs_pdt_names,
  ^verify_jobs_pdt_params];

  VAR
    verify_jobs_pdt_names: [STATIC, READ, cls$pdt_names_and_defaults] array [1 .. 3] of
  clt$parameter_name_descriptor := [['MAINFRAME_ID', 1], ['MI', 1], ['STATUS', 2]];

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

{ MAINFRAME_ID MI }
    [[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]]];

?? FMT (FORMAT := ON) ??
?? POP ??


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

    status.normal := TRUE;

    dfp$verify_system_administrator (' DFP$VERIFY_CLIENT_JOBS', status);
    IF status.normal THEN

      clp$scan_parameter_list (parameter_list, verify_jobs_pdt, status);
      IF status.normal THEN
        dfp$crack_mainframe_id ('MAINFRAME_ID', mainframe_id, binary_mainframe_id, status);
        IF status.normal THEN
          dfp$verify_client_jobs_request (mainframe_id, status);
        IFEND;
      IFEND;
    IFEND;

  PROCEND dfp$verify_client_jobs;

?? TITLE := '    [XDCL] dfp$verify_client_jobs_request', EJECT ??
*copyc dfh$verify_client_jobs_request

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

    VAR
      binary_mainframe_id: pmt$binary_mainframe_id,
      display_string: string (80),
      display_length: integer,
      mainframe_found: boolean,
      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_entry_index: dft$queue_entry_index,
      queue_index: dft$queue_index;

    status.normal := TRUE;

    dfp$find_mainframe_id (mainframe_id, {server_to_client } FALSE, 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_id, status);
      RETURN;
    IFEND;

    IF (p_cpu_queue^.queue_header.partner_status.server_state = dfc$recovering) OR
          ((p_cpu_queue^.queue_header.partner_status.server_state = dfc$active) AND
          (NOT p_cpu_queue^.queue_header.partner_status.job_reconcilliation_completed)) THEN
      IF mainframe_id <> dfc$loopback_server_mainframe THEN
        STRINGREP (display_string, display_length, ' ', mainframe_id, ' Reconcile leveled jobs ');
        display (display_string (1, display_length));
        pmp$convert_mainframe_to_binary (mainframe_id, binary_mainframe_id, status);
        jmp$reconcile_leveled_jobs (binary_mainframe_id, status);
        IF NOT status.normal THEN
          display_status (status);
        IFEND;
      IFEND;
    IFEND;

    verify_client_jobs (mainframe_id, status);

    IF ((p_cpu_queue^.queue_header.partner_status.server_state = dfc$active) AND
          (NOT p_cpu_queue^.queue_header.partner_status.job_reconcilliation_completed)) THEN
      p_cpu_queue^.queue_header.partner_status.job_reconcilliation_completed := TRUE;
    IFEND;

  PROCEND dfp$verify_client_jobs_request;
?? TITLE := ' verify_client_jobs ', EJECT ??
  PROCEDURE verify_client_jobs
    (    mainframe_name: pmt$mainframe_id;
     VAR status: ost$status);

?? NEWTITLE := 'dfp$remote_procedure_call_ch', EJECT ??

{ PURPOSE:
{   This procedure is a condition handler established to call a routine to clear the assignment of a task
{   services queue_entry if a task aborts with a queue_entry assigned to it.  The queue_entry must be clear
{   before the task can safely exit.

    PROCEDURE dfp$remote_procedure_call_ch
      (    condition: pmt$condition;
           cond_desc: ^pmt$condition_information;
           save: ^ost$stack_frame_save_area;
       VAR handler_status: ost$status);

      dfp$ch_cleanup;
      osp$set_status_from_condition (dfc$file_server_id, condition, save, status, handler_status);
      EXIT verify_client_jobs;

    PROCEND dfp$remote_procedure_call_ch;
*block
*copyc dfp$begin_ch_remote_proc_call
*copyc dfp$end_ch_remote_proc_call
*blockend
?? OLDTITLE, EJECT ??
    VAR
      allowed_when_server_deactivated: boolean,
      job: ost$non_negative_integers,
      job_exists: boolean,
      local_status: ost$status,
      log_message: string (100),
      log_message_size: integer,
      number_of_jobs_awaiting_rec: ost$non_negative_integers,
      number_of_jobs_on_server: ost$non_negative_integers,
      number_of_jobs_to_remove: ost$non_negative_integers,
      p_served_job_list_header: ^dft$rpc_served_job_list_header,
      p_served_job_list_data_out: ^dft$rpc_served_job_list_data,
      p_served_job_list_data: ^dft$rpc_served_job_list_data,
      p_receive_buffer: dft$p_receive_parameters,
      p_receive_data: dft$p_receive_data,
      p_send_buffer: dft$p_send_parameters,
      p_send_data: dft$p_send_data,
      procedure_ordinal: dft$procedure_address_ordinal,
      queue_entry_location: dft$rpc_queue_entry_location,
      send_buffer_size: dft$send_parameter_size,
      send_data_size: dft$send_data_size,
      server_location: dft$server_location;

    status.normal := TRUE;
    local_status.normal := TRUE;
    number_of_jobs_on_server := 0;
    number_of_jobs_awaiting_rec := 0;
    number_of_jobs_to_remove := 0;

    server_location.server_location_selector := dfc$mainframe_id;
    server_location.server_mainframe := mainframe_name;
    allowed_when_server_deactivated := FALSE;

    dfp$begin_ch_remote_proc_call (server_location, allowed_when_server_deactivated, queue_entry_location,
          p_send_buffer, p_send_data, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;

  /doit/
    BEGIN

      procedure_ordinal := dfc$get_client_job_list;
      send_buffer_size := 0;
      send_data_size := 0;

      dfp$send_remote_procedure_call (queue_entry_location, procedure_ordinal, send_buffer_size,
            send_data_size, p_receive_buffer, p_receive_data, status);
      IF NOT status.normal THEN
        IF ((status.condition <> dfe$server_request_terminated) AND
              (status.condition <> dfe$server_not_active) AND (status.condition <> dfe$server_has_terminated))
              THEN
          display (' ABNORMAL STATUS FROM dfp$get_client_job_list');
          display_status (status);
        IFEND;
        EXIT /doit/;
      IFEND;

      { Process receive data
      NEXT p_served_job_list_header IN p_receive_data;
      number_of_jobs_on_server := p_served_job_list_header^.number_of_jobs;
      number_of_jobs_awaiting_rec := p_served_job_list_header^.number_of_jobs_awaiting_rec;
      number_of_jobs_to_remove := 0;
      IF number_of_jobs_on_server = 0 THEN
        EXIT /doit/;
      IFEND;

      NEXT p_served_job_list_header IN p_send_data;
      p_served_job_list_header^.number_of_jobs := 0;
      p_served_job_list_header^.number_of_jobs_awaiting_rec := 0;

    /check_jobs/
      FOR job := 1 TO number_of_jobs_on_server DO
        NEXT p_served_job_list_data IN p_receive_data;
        jmp$job_exists (p_served_job_list_data^.system_supplied_job_name,
              $jmt$job_state_set [jmc$initiated_job, jmc$terminating_job], job_exists, status);
        IF NOT status.normal THEN
          display_status (status);
          EXIT /doit/;
        IFEND;

        IF NOT job_exists THEN
          IF dfv$file_server_debug_enabled THEN
            display (p_served_job_list_data^.system_supplied_job_name);
          IFEND;
          NEXT p_served_job_list_data_out IN p_send_data;
          p_served_job_list_data_out^.system_supplied_job_name :=
                p_served_job_list_data^.system_supplied_job_name;
          p_served_job_list_data_out^.client_job_id := p_served_job_list_data^.client_job_id;
          p_served_job_list_header^.number_of_jobs := p_served_job_list_header^.number_of_jobs + 1;
        IFEND;
      FOREND /check_jobs/;

      IF p_served_job_list_header^.number_of_jobs > 0 THEN
        number_of_jobs_to_remove := p_served_job_list_header^.number_of_jobs;
        procedure_ordinal := dfc$remove_unknown_jobs;
        send_data_size := i#current_sequence_position (p_send_data);
        send_buffer_size := 0;
        dfp$send_remote_procedure_call (queue_entry_location, procedure_ordinal, send_buffer_size,
              send_data_size, p_receive_buffer, p_receive_data, status);
        IF NOT status.normal THEN
          IF ((status.condition <> dfe$server_request_terminated) AND
                (status.condition <> dfe$server_not_active) AND
                (status.condition <> dfe$server_has_terminated)) THEN
            display (' ABNORMAL STATUS FROM dfp$verify_client_jobs_request');
            display_status (status);
          IFEND;
          EXIT /doit/;
        IFEND;
        IF dfv$file_server_debug_enabled THEN
          display_integer (' No. of client jobs to be removed from server: ',
                p_served_job_list_header^.number_of_jobs);
        IFEND;
      IFEND;

    END /doit/;

    dfp$end_ch_remote_proc_call (queue_entry_location, local_status);
    IF status.normal AND NOT local_status.normal THEN
      status := local_status;
    IFEND;

   STRINGREP (log_message, log_message_size, ' Server ', mainframe_name,
     ' Total_jobs:',  number_of_jobs_on_server,
     '   Awaiting_recovery:', number_of_jobs_awaiting_rec,
     '   Remove:', number_of_jobs_to_remove);
   log_display ($pmt$ascii_logset[pmc$system_log], log_message (1, log_message_size));
   IF dfv$file_server_debug_enabled THEN
     display (log_message (1, log_message_size));
   IFEND;
  PROCEND verify_client_jobs;
MODEND dfm$verify_client_jobs;



