*copyc OSD$DEFAULT_PRAGMATS
MODULE icm$partner_job_exec_virtual;
?? TITLE := 'MODULE icm$partner_job_exec_virtual' ??

?? PUSH (LISTEXT := ON) ??
*copyc ICE$ERROR_CODES
*copyc ICF$OPEN_FILE_DESCRIPTOR
*copyc ICT$PARTNER_MESSAGES
*copyc ICP$PJ_ADD_SENDER
*copyc ICP$PJ_SIGN_OFF
*copyc ICP$PJ_SIGN_ON
*copyc ICP$RECEIVE_FROM_PJ_EXEC
*copyc ICP$REPORT_STATUS_ERROR
*copyc ICP$SEND_TO_PJ_EXEC
*copyc ICV$PJ_SIGNED_ON
*copyc IFE$ERROR_CODES
*copyc I#MOVE
*copyc OST$STATUS
*copyc OSP$APPEND_STATUS_INTEGER
*copyc OSP$DISESTABLISH_COND_HANDLER
*copyc OSP$ESTABLISH_CONDITION_HANDLER
*copyc OSP$SET_STATUS_ABNORMAL
*copyc PMP$CONTINUE_TO_CAUSE
*copyc PMP$LONG_TERM_WAIT
?? POP ??
?? TITLE := 'PROCEDURE icp$initiate_partner_job', EJECT ??

  PROCEDURE [XDCL] icp$initiate_partner_job
    (    commands_length: ict$partner_commands_length;
         commands_pointer: ^cell;
         data_length: ict$partner_data_length;
         data_pointer: ^cell;
         validation_length: integer;
         validation_pointer: ^cell;
     VAR partner_identification: ict$partner_identification;
     VAR status: ost$status);

    VAR
      initiate_partner_request: ict$initiate_partner_request,
      initiate_partner_response: ict$initiate_partner_response,
      message_length: mlt$message_length,
      arbitrary_info: mlt$arbitrary_info,
      partner_status_returned: boolean;

    PROCEDURE pj_break_handler
      (    cond: pmt$condition;
           condition_info: ^pmt$condition_information;
           stack_frame_save_area: ^ost$stack_frame_save_area;
       VAR break_status: ost$status);

      VAR
        local_status: ost$status;

      IF (cond.selector = ifc$interactive_condition) THEN
        IF partner_status_returned = TRUE THEN
          icp$receive_from_pj_exec (icv$pj_application_name,
                #LOC (initiate_partner_response),
                #SIZE (initiate_partner_response), message_length,
                arbitrary_info, status);
        IFEND;
        IF cond.interactive_condition = ifc$pause_break THEN
          osp$set_status_abnormal (ifc$interactive_facility_id,
                ife$pause_break_received, '', status);
        ELSEIF cond.interactive_condition = ifc$terminate_break THEN
          osp$set_status_abnormal (ifc$interactive_facility_id,
                ife$terminate_break_received, '', status);
        IFEND;
        pmp$continue_to_cause (pmc$execute_standard_procedure, local_status);
        EXIT icp$initiate_partner_job;
      IFEND;
      break_status.normal := TRUE;
      RETURN;
    PROCEND pj_break_handler;

{ Begin procedure ICP$INITIATE_PARTNER_JOB.

    status.normal := TRUE;
    osp$establish_condition_handler (^pj_break_handler, FALSE);
    IF NOT icv$pj_signed_on THEN
      icp$pj_sign_on (icv$pj_application_name, status);
      IF NOT status.normal THEN
        osp$disestablish_cond_handler;
        RETURN;
      IFEND;

{ Allow the partner-job-exec to send messages to us.

      icp$pj_add_sender (icv$pj_application_name, status);
      IF NOT status.normal THEN
        osp$disestablish_cond_handler;
        RETURN;
      IFEND;
    IFEND;

    icv$pj_signed_on := TRUE;

{ Build an initiate partner request message.

    initiate_partner_request.commands_length := commands_length;
    initiate_partner_request.data_length := data_length;
    i#move (commands_pointer, #LOC (initiate_partner_request.
          partner_image [1]), commands_length * 8);
    i#move (data_pointer, #LOC (initiate_partner_request.
          partner_image [commands_length + 1]), data_length * 8);
    i#move (validation_pointer, #LOC (initiate_partner_request.
          validation_image [1]), validation_length * 8);
    partner_status_returned := FALSE;

  /initiate_partner_job/
    WHILE TRUE DO

{ Send the initiate partner job request message to the partner-job-exec.

      icp$send_to_pj_exec (icv$pj_application_name,
            #LOC (initiate_partner_request), #SIZE (initiate_partner_request),
            $INTEGER (icc$initiate_partner_request), status);
      IF NOT status.normal THEN
        EXIT /initiate_partner_job/;
      IFEND;
      partner_status_returned := TRUE;

{ Get the initiate partner response from the partner-job-exec.

      icp$receive_from_pj_exec (icv$pj_application_name,
            #LOC (initiate_partner_response),
            #SIZE (initiate_partner_response), message_length, arbitrary_info,
            status);
      IF NOT status.normal THEN
        EXIT /initiate_partner_job/;
      IFEND;
      partner_status_returned := FALSE;

      IF arbitrary_info <> $INTEGER (icc$initiate_partner_response) THEN
        osp$set_status_abnormal (icc$interstate_communication_id,
              ice$partner_cannot_be_started, '', status);
        icp$report_status_error (status, ' garbage initiate response');
        EXIT /initiate_partner_job/;
      IFEND;

      CASE initiate_partner_response.initiate_status OF

      = $INTEGER (icc$partner_started_ok) =
        partner_identification := initiate_partner_response.
              partner_identification;
        EXIT /initiate_partner_job/;

      = $INTEGER (icc$partner_job_limit_exceeded) =
        pmp$long_term_wait (icf_interval, icf_interval);
        CYCLE /initiate_partner_job/;

      = $INTEGER (icc$partner_start_failed) =
        osp$set_status_abnormal (icc$interstate_communication_id,
              ice$partner_cannot_be_started, '', status);
        icp$report_status_error (status, ' initiate partner failed');
        EXIT /initiate_partner_job/;

      ELSE
        osp$set_status_abnormal (icc$interstate_communication_id,
              ice$partner_cannot_be_started, '', status);
        icp$report_status_error (status, ' initiate partner failed');
        EXIT /initiate_partner_job/;

      CASEND;
    WHILEND /initiate_partner_job/;
    osp$disestablish_cond_handler;

  PROCEND icp$initiate_partner_job;

?? TITLE := 'PROCEDURE icp$status_partner_job', EJECT ??

  PROCEDURE [XDCL] icp$status_partner_job
    (    partner_identification: ict$partner_identification;
     VAR status_partner_status: ict$status_partner_status;
     VAR status: ost$status);

    VAR
      status_partner_request: ict$status_partner_request,
      status_partner_response: ict$status_partner_response,
      partner_status_returned: boolean,
      message_length: mlt$message_length,
      arbitrary_info: mlt$arbitrary_info;

    PROCEDURE pj_break_handler
      (    cond: pmt$condition;
           condition_info: ^pmt$condition_information;
           stack_frame_save_area: ^ost$stack_frame_save_area;
       VAR break_status: ost$status);

      VAR
        local_status: ost$status;

      IF (cond.selector = ifc$interactive_condition) THEN
        IF partner_status_returned = TRUE THEN
          icp$receive_from_pj_exec (icv$pj_application_name,
                #LOC (status_partner_response),
                #SIZE (status_partner_response), message_length,
                arbitrary_info, status);
        IFEND;
        IF cond.interactive_condition = ifc$pause_break THEN
          osp$set_status_abnormal (ifc$interactive_facility_id,
                ife$pause_break_received, '', status);
        ELSEIF cond.interactive_condition = ifc$terminate_break THEN
          osp$set_status_abnormal (ifc$interactive_facility_id,
                ife$terminate_break_received, '', status);
        IFEND;
        pmp$continue_to_cause (pmc$execute_standard_procedure, local_status);
        EXIT icp$status_partner_job;
      IFEND;
      break_status.normal := TRUE;
      RETURN;
    PROCEND pj_break_handler;

{ Begin procedure ICP$STATUS_PARTNER_JOB.

    status.normal := TRUE;
    osp$establish_condition_handler (^pj_break_handler, FALSE);
    partner_status_returned := FALSE;
    status_partner_request.partner_identification := partner_identification;
    icp$send_to_pj_exec (icv$pj_application_name,
          #LOC (status_partner_request), #SIZE (status_partner_request),
          $INTEGER (icc$status_partner_request), status);
    IF NOT status.normal THEN
      osp$disestablish_cond_handler;
      RETURN;
    IFEND;
    partner_status_returned := TRUE;

{ Get the status partner response from the partner-job-exec.

    icp$receive_from_pj_exec (icv$pj_application_name,
          #LOC (status_partner_response), #SIZE (status_partner_response),
          message_length, arbitrary_info, status);
    IF NOT status.normal THEN
      osp$disestablish_cond_handler;
      RETURN;
    IFEND;
    partner_status_returned := FALSE;

    IF arbitrary_info <> $INTEGER (icc$status_partner_response) THEN
      osp$set_status_abnormal (icc$interstate_communication_id,
            ice$partner_ended, '', status);
      icp$report_status_error (status, ' garbage status response');
      osp$disestablish_cond_handler;
      RETURN;
    ELSE
      CASE status_partner_response.partner_status OF

      = $INTEGER (icc$partner_not_found) =
        status_partner_status := icc$partner_not_found;

      = $INTEGER (icc$partner_in_input_queue) =
        status_partner_status := icc$partner_in_input_queue;

      = $INTEGER (icc$partner_not_signed_on) =
        status_partner_status := icc$partner_not_signed_on;

      = $INTEGER (icc$partner_signed_on) =
        status_partner_status := icc$partner_signed_on;

      ELSE
        status_partner_status := icc$partner_not_found;

      CASEND;
    IFEND;
    osp$disestablish_cond_handler;

  PROCEND icp$status_partner_job;
?? TITLE := 'PROCEDURE icp$delete_partner_job', EJECT ??

  PROCEDURE [XDCL] icp$delete_partner_job
    (    partner_identification: ict$partner_identification;
     VAR status: ost$status);

    VAR
      delete_partner_request: ict$delete_partner_request,
      delete_partner_response: ict$delete_partner_response,
      partner_status_returned: boolean,
      message_length: mlt$message_length,
      arbitrary_info: mlt$arbitrary_info,
      local_status: ost$status;

    PROCEDURE pj_break_handler
      (    cond: pmt$condition;
           condition_info: ^pmt$condition_information;
           stack_frame_save_area: ^ost$stack_frame_save_area;
       VAR break_status: ost$status);

      VAR
        local_status: ost$status;

      IF (cond.selector = ifc$interactive_condition) THEN
        IF partner_status_returned = TRUE THEN
          icp$receive_from_pj_exec (icv$pj_application_name,
                #LOC (delete_partner_response),
                #SIZE (delete_partner_response), message_length,
                arbitrary_info, status);
        IFEND;
        IF cond.interactive_condition = ifc$pause_break THEN
          osp$set_status_abnormal (ifc$interactive_facility_id,
                ife$pause_break_received, '', status);
        ELSEIF cond.interactive_condition = ifc$terminate_break THEN
          osp$set_status_abnormal (ifc$interactive_facility_id,
                ife$terminate_break_received, '', status);
        IFEND;
        pmp$continue_to_cause (pmc$execute_standard_procedure, local_status);
        EXIT icp$delete_partner_job;
      IFEND;
      break_status.normal := TRUE;
      RETURN;
    PROCEND pj_break_handler;

  /delete_partner/
    BEGIN
      status.normal := TRUE;
      osp$establish_condition_handler (^pj_break_handler, FALSE);

{ Send a delete partner job request message to the partner-job-exec.

      delete_partner_request.partner_identification := partner_identification;
      partner_status_returned := FALSE;
      icp$send_to_pj_exec (icv$pj_application_name,
            #LOC (delete_partner_request), #SIZE (delete_partner_request),
            $INTEGER (icc$delete_partner_request), status);
      IF NOT status.normal THEN
        EXIT /delete_partner/;
      IFEND;
      partner_status_returned := TRUE;

{ Get the delete partner response from the partner-job-exec.

      icp$receive_from_pj_exec (icv$pj_application_name,
            #LOC (delete_partner_response), #SIZE (delete_partner_response),
            message_length, arbitrary_info, status);
      IF NOT status.normal THEN
        EXIT /delete_partner/;
      IFEND;
      partner_status_returned := FALSE;

      IF arbitrary_info <> $INTEGER (icc$delete_partner_response) THEN
        osp$set_status_abnormal (icc$interstate_communication_id,
              ice$partner_ended, '', status);
        icp$report_status_error (status, ' garbage delete response');
        EXIT /delete_partner/;
      IFEND;

    END /delete_partner/;

{ Sign off of the Memory Link.

    icp$pj_sign_off (icv$pj_application_name, local_status);
    icv$pj_signed_on := FALSE;
    osp$disestablish_cond_handler;

  PROCEND icp$delete_partner_job;

MODEND icm$partner_job_exec_virtual;
