?? RIGHT := 110 ??
?? NEWTITLE := 'NOS/VE Resource Management : Robotic Server Interfaces' ??
*copyc osd$default_pragmats
MODULE rmm$robotic_interfaces_23d;

{ Purpose: This module contains the interfaces used by a NOS/VE
{ server to intercept mount requests for removable media and
{ to automate the mount/dismount process.
{

?? TITLE := 'Global Declarations Declared by This Module', EJECT ??

  CONST
    one_second = 1000 {milliseconds};

?? NEWTITLE := 'Global Declarations Referenced by this Module', EJECT ??
?? PUSH (LISTEXT := ON) ??
*copyc cmt$element_name
*copyc jmc$system_family
*copyc mmp$verify_access
*copyc osd$integer_limits
*copyc osd$virtual_address
*copyc oss$job_paged_literal
*copyc ost$caller_identifier
*copyc iot$logical_unit
*copyc ost$status
*copyc rmc$unspecified_vsn
*copyc rme$condition_codes
*copyc rme$robotic_interface_errors
*copyc rmt$external_vsn
*copyc rmt$rbt_request
*copyc rmt$rbt_unformatted_response
*copyc rmt$rbt_server_attribute
?? POP ??
*copyc clp$trimmed_string_size
*copyc clp$validate_name
*copyc iop$define_robotic_server
*copyc iop$get_server_entry
*copyc iop$remove_robotic_server
*copyc iop$server_get_request
*copyc iop$server_put_response
*copyc osp$append_status_integer
*copyc osp$append_status_parameter
*copyc osp$get_parameter_prompt
*copyc osp$set_status_abnormal
*copyc osp$set_status_condition
*copyc osv$lower_to_upper
*copyc pmp$get_user_identification
*copyc pmp$wait
*copyc rmp$log_debug_integer
*copyc rmp$log_debug_message
*copyc rmp$log_debug_status
*copyc rmp$validate_ansi_string

?? OLDTITLE ??
?? NEWTITLE := 'Global Variables Declared by this Module', EJECT ??


  VAR
    valid_requests: [STATIC, READ, oss$job_paged_literal] rmt$rbt_supported_requests :=
          [rmc$rbt_query, rmc$rbt_mount, rmc$rbt_dismount, rmc$rbt_force_dismount],

    rmv$default_server_attributes: [STATIC, READ, oss$job_paged_literal] iot$robotic_server_attributes :=
          [[rmc$rbt_query, rmc$rbt_mount, rmc$rbt_dismount, rmc$rbt_force_dismount], 300000 {5 minutes} ];

?? OLDTITLE ??
?? NEWTITLE := 'rmp$define_robotic_server', EJECT ??

  PROCEDURE [XDCL, #GATE] rmp$define_robotic_server
    (    server_name: ost$name;
         managed_elements: array [1 .. * ] of cmt$element_name;
         server_attributes: array [1 .. * ] of rmt$rbt_server_attribute;
     VAR status: ost$status);

    CONST
      procedure_name = 'RMP$DEFINE_ROBOTIC_SERVER';

    VAR
      caller_id: ost$caller_identifier,
      debug_message_logged: boolean,
      server_entry: iot$robotic_server_entry,
      validated_attributes: iot$robotic_server_attributes,
      validated_elements_p: ^array [1 .. * ] of cmt$element_name,
      validated_server_name: ost$name;

    #CALLER_ID (caller_id);

    status.normal := TRUE;

    validate_caller (caller_id, status);
    IF status.normal THEN
      validate_server_name (server_name, procedure_name, FALSE {require_server_preexist} , server_entry,
            validated_server_name, status);
      IF status.normal THEN
        PUSH validated_elements_p: [LOWERBOUND (managed_elements) .. UPPERBOUND (managed_elements)];
        validate_element_list (managed_elements, 'MANAGED_ELEMENTS parameter', procedure_name, NIL
              {no server entry} , validated_elements_p^, status);
        IF status.normal THEN
          validate_server_attributes (server_attributes, procedure_name, validated_attributes, status);
          IF status.normal THEN
            debug_message_logged := FALSE;
            REPEAT
              IF NOT debug_message_logged THEN
                rmp$log_debug_message (' Calling iop$define_robotic_server');
              IFEND;
              iop$define_robotic_server (validated_server_name, validated_elements_p^, validated_attributes,
                    status);
              IF NOT status.normal AND (status.condition = dme$unable_to_lock_tape_table) THEN
                IF NOT debug_message_logged THEN
                  rmp$log_debug_message (' Waiting for tape table lock');
                  debug_message_logged := TRUE;
                IFEND;
                pmp$wait (one_second, one_second);
              IFEND;
            UNTIL status.normal OR (status.condition <> dme$unable_to_lock_tape_table);
          IFEND;
        IFEND;
      IFEND;
    IFEND;

  PROCEND rmp$define_robotic_server;

?? OLDTITLE ??
?? NEWTITLE := 'rmp$remove_robotic_server', EJECT ??

  PROCEDURE [XDCL, #GATE] rmp$remove_robotic_server
    (    server_name: ost$name;
     VAR status: ost$status);

    CONST
      procedure_name = 'RMP$REMOVE_ROBOTIC_SERVER';

    VAR
      debug_message_logged: boolean,
      caller_id: ost$caller_identifier,
      server_entry: iot$robotic_server_entry,
      validated_server_name: ost$name;

    #CALLER_ID (caller_id);

    status.normal := TRUE;

    validate_caller (caller_id, status);
    IF status.normal THEN
      validate_server_name (server_name, procedure_name, TRUE {require__server_preexist} , server_entry,
            validated_server_name, status);
      IF status.normal THEN
        debug_message_logged := FALSE;
        REPEAT
          IF NOT debug_message_logged THEN
            rmp$log_debug_message (' Calling iop$remove_robotic_server');
          IFEND;
          iop$remove_robotic_server (validated_server_name, status);
          IF NOT status.normal AND (status.condition = dme$unable_to_lock_tape_table) THEN
            IF NOT debug_message_logged THEN
              rmp$log_debug_message (' Waiting for tape table lock');
              debug_message_logged := TRUE;
            IFEND;
            pmp$wait (one_second, one_second);
          IFEND;
        UNTIL status.normal OR (status.condition <> dme$unable_to_lock_tape_table);
      IFEND;
    IFEND;

  PROCEND rmp$remove_robotic_server;

?? NEWTITLE := 'rmp$server_get_request_23d', EJECT ??

  PROCEDURE [XDCL, #GATE] rmp$server_get_request_23d
    (    server_name: ost$name;
         wait: boolean;
     VAR client_request: rmt$rbt_request;
     VAR status: ost$status);

    CONST
      procedure_name = 'RMP$SERVER_GET_REQUEST';

    VAR
      caller_id: ost$caller_identifier,
      debug_message_logged: boolean,
      server_entry: iot$robotic_server_entry,
      validated_server_name: ost$name;

    #CALLER_ID (caller_id);

    status.normal := TRUE;

    validate_caller (caller_id, status);
    IF status.normal THEN
      validate_server_name (server_name, procedure_name, TRUE {validate_server_preexist} , server_entry,
            validated_server_name, status);
      IF status.normal THEN
        IF (wait < LOWERVALUE (boolean)) OR (wait > UPPERVALUE (boolean)) THEN
          osp$set_status_abnormal (rmc$resource_management_id, rme$invalid_wait_specified, procedure_name,
                status);
        ELSE
          debug_message_logged := FALSE;
          REPEAT
            IF NOT debug_message_logged THEN
              rmp$log_debug_message (' Calling iop$server_get_request');
            IFEND;
            iop$server_get_request (validated_server_name, wait, client_request, status);
            IF NOT status.normal AND (status.condition = dme$unable_to_lock_tape_table) THEN
              IF NOT debug_message_logged THEN
                rmp$log_debug_message (' Waiting for tape table lock');
                debug_message_logged := TRUE;
              IFEND;
              pmp$wait (one_second, one_second);
            IFEND;
          UNTIL status.normal OR (status.condition <> dme$unable_to_lock_tape_table);
          IF status.normal THEN
            rmp$log_debug_integer (' Exiting rmp$server_get_request_23d: REQUEST_ID=',
                client_request.request_id);
          ELSE
            rmp$log_debug_message (' Exiting rmp$server_get_request_23d');
            rmp$log_debug_status (status);
          IFEND;
        IFEND;
      IFEND;
    IFEND;
  PROCEND rmp$server_get_request_23d;

?? OLDTITLE ??
?? NEWTITLE := 'rmp$server_put_response', EJECT ??

  PROCEDURE [XDCL, #GATE] rmp$server_put_response
    (    server_name: ost$name;
         server_response: rmt$rbt_unformatted_response;
     VAR status: ost$status);

    CONST
      procedure_name = 'RMP$SERVER_PUT_RESPONSE';

    VAR
      debug_message_logged: boolean,
      caller_id: ost$caller_identifier,
      local_response: iot$formatted_server_response,
      server_entry: iot$robotic_server_entry,
      validated_server_name: ost$name;

    #CALLER_ID (caller_id);

    status.normal := TRUE;

    validate_caller (caller_id, status);
    IF status.normal THEN
      validate_server_name (server_name, procedure_name, TRUE {validate_server_defined} , server_entry,
            validated_server_name, status);
      IF status.normal THEN
        validate_request_id (server_response.request_id, 'REQUEST_ID', local_response.request_id, status);
        IF status.normal THEN
          validate_boolean (server_response.request_processed, 'REQUEST_PROCESSED',
                local_response.request_processed, status);
          IF status.normal THEN
            IF local_response.request_processed THEN
              validate_request_type (server_response.processed_request, 'PROCESSED_REQUEST',
                    local_response.processed_request, status);
              IF status.normal THEN
                CASE local_response.processed_request OF
                = rmc$rbt_query =
                  validate_response_query (server_response.query, local_response.query, status);
                  IF status.normal AND server_response.query.volume_located THEN
                    IF server_response.query.already_mounted THEN
                      validate_element_name (server_response.query.element, 'QUERY.ELEMENT', ^server_entry,
                            local_response.query.element, status);
                    ELSE
                      IF server_response.query.preferred_candidates <> NIL THEN
                        PUSH local_response.query.preferred_candidates:
                              [LOWERBOUND (server_response.query.preferred_candidates^) .. UPPERBOUND (
                              server_response.query.preferred_candidates^)];
                        validate_element_list (server_response.query.preferred_candidates^,
                              'QUERY.PREFERRED_CANDIDATES field', procedure_name, ^server_entry,
                              local_response.query.preferred_candidates^, status);
                      ELSE
                        local_response.query.preferred_candidates := NIL;
                      IFEND;
                      IF status.normal AND (server_response.query.remaining_candidates <> NIL) THEN
                        PUSH local_response.query.remaining_candidates:
                              [LOWERBOUND (server_response.query.remaining_candidates^) .. UPPERBOUND (
                              server_response.query.remaining_candidates^)];
                        validate_element_list (server_response.query.remaining_candidates^,
                              'QUERY.REMAINING_CANDIDATES field', procedure_name, ^server_entry,
                              local_response.query.remaining_candidates^, status);
                      ELSE
                        local_response.query.remaining_candidates := NIL;
                      IFEND;
                    IFEND;
                  IFEND;
                = rmc$rbt_mount =
                  validate_response_mount (server_response.mount, server_entry, local_response.mount, status);
                = rmc$rbt_dismount =
                  validate_response_dismount (server_response.dismount, server_entry, local_response.dismount,
                        status);
                = rmc$rbt_force_dismount =
                  validate_response_force_dismnt (server_response.force_dismount, server_entry,
                        local_response.force_dismount, status);
                CASEND;
              IFEND;
            ELSE
              process_response_retry (server_response, local_response, status);
            IFEND;
            IF status.normal THEN
              debug_message_logged := FALSE;
              REPEAT
                IF NOT debug_message_logged THEN
                  rmp$log_debug_message (' Calling iop$server_put_response');
                IFEND;
                iop$server_put_response (validated_server_name, local_response, status);
                IF NOT status.normal AND (status.condition = dme$unable_to_lock_tape_table) THEN
                  IF NOT debug_message_logged THEN
                    rmp$log_debug_message (' Waiting for tape table lock');
                    debug_message_logged := TRUE;
                  IFEND;
                  pmp$wait (one_second, one_second);
                IFEND;
              UNTIL status.normal OR (status.condition <> dme$unable_to_lock_tape_table);
              rmp$log_debug_integer (' Exiting rmp$server_put_response:    REQUEST_ID=',
                  server_response.request_id);
              rmp$log_debug_status (status);
            IFEND;
          IFEND;
        IFEND;
      IFEND;
    IFEND;

  PROCEND rmp$server_put_response;

?? OLDTITLE ??
?? NEWTITLE := 'format_conditional_message', EJECT ??

  PROCEDURE format_conditional_message
    (    conditional_message: rmt$rbt_conditional_message;
     VAR formatted_conditional_message: iot$conditional_server_message;
     VAR status: ost$status);

    VAR
      formatted_message: ost$status_message;

    osp$get_parameter_prompt (conditional_message.message_module, conditional_message.message_name,
          conditional_message.message_parameters, rmc$rbt_status_message_width, formatted_message, status);

    IF status.normal THEN
      formatted_conditional_message.issue_prior_to_retry_attempt :=
            conditional_message.issue_prior_to_retry_attempt;
      formatted_conditional_message.message := formatted_message;
    IFEND;
  PROCEND format_conditional_message;
?? OLDTITLE ??
?? NEWTITLE := 'process_messages', EJECT ??

  PROCEDURE process_messages
    (    response: rmt$rbt_unformatted_response;
     VAR server_messages: iot$robotic_server_messages;
     VAR status: ost$status);

    VAR
      local_messages_requested: iot$requested_server_messages,
      job_log_conditional_message: iot$conditional_server_message,
      job_status_conditional_message: iot$conditional_server_message,
      operator_conditional_message: iot$conditional_server_message,
      system_log_conditional_message: iot$conditional_server_message;

    local_messages_requested := $iot$requested_server_messages [];
    IF response.job_log <> NIL THEN
      validate_pva (response.job_log, 'RESPONSE.JOB_LOG - invalid PVA', status);
      IF status.normal THEN
        validate_conditional_message (response.job_log^, 'RESPONSE.JOB_LOG',
              status);
        IF status.normal THEN
          format_conditional_message (response.job_log^,
                job_log_conditional_message, status);
          IF status.normal THEN
            local_messages_requested := local_messages_requested +
                  $iot$requested_server_messages [ioc$job_log_message];
          IFEND;
        IFEND;
      IFEND;
    IFEND;

    IF response.job_status_display <> NIL THEN
      validate_pva (response.job_status_display,
            'RESPONSE.JOB_STATUS_DISPLAY - invalid PVA', status);
      IF status.normal THEN
        validate_conditional_message (response.job_status_display^,
              'RESPONSE.JOB_STATUS_DISPLAY', status);
        IF status.normal THEN
          format_conditional_message (response.job_status_display^,
                job_status_conditional_message, status);
          IF status.normal THEN
            local_messages_requested := local_messages_requested +
                  $iot$requested_server_messages [ioc$job_status_message];
          IFEND;
        IFEND;
      IFEND;
    IFEND;

    IF response.operator_action <> NIL THEN
      validate_pva (response.operator_action,
            'RESPONSE.OPERATOR_ACTION - invalid PVA', status);
      validate_conditional_message (response.operator_action^,
            'RESPONSE.OPERATOR_ACTION', status);
      IF status.normal THEN
        format_conditional_message (response.operator_action^,
              operator_conditional_message, status);
        IF status.normal THEN
          local_messages_requested := local_messages_requested +
                $iot$requested_server_messages [ioc$operator_action_message];
        IFEND;
      IFEND;
    IFEND;

    IF response.system_log <> NIL THEN
      validate_pva (response.system_log, 'RESPONSE.SYSTEM_LOG - invalid PVA',
            status);
      validate_conditional_message (response.system_log^, 'RESPONSE.SYSTEM_LOG',
            status);
      IF status.normal THEN
        format_conditional_message (response.system_log^,
              system_log_conditional_message, status);
        IF status.normal THEN
          local_messages_requested := local_messages_requested +
                $iot$requested_server_messages [ioc$system_log_message];
        IFEND;
      IFEND;
    IFEND;

    IF status.normal THEN
      server_messages.requested_messages := local_messages_requested;
      IF ioc$job_log_message IN local_messages_requested THEN
        server_messages.job_log := job_log_conditional_message;
      IFEND;
      IF ioc$job_status_message IN local_messages_requested THEN
        server_messages.job_status_display := job_status_conditional_message;
      IFEND;
      IF ioc$operator_action_message IN local_messages_requested THEN
        server_messages.operator_action := operator_conditional_message;
      IFEND;
      IF ioc$system_log_message IN local_messages_requested THEN
        server_messages.system_log := system_log_conditional_message;
      IFEND;
    IFEND;

  PROCEND process_messages;

?? OLDTITLE ??
?? NEWTITLE := 'process_response_retry', EJECT ??

  PROCEDURE process_response_retry
    (    response: rmt$rbt_unformatted_response;
     VAR server_response: iot$formatted_server_response;
     VAR status: ost$status);

    VAR
      server_messages: ^iot$robotic_server_messages;

    validate_request_type (response.current_request, 'RESPONSE.CURRENT_REQUEST',
          server_response.current_request, status);
    IF status.normal THEN
      PUSH server_messages;
      server_response.server_messages := server_messages;
      process_messages (response, server_response.server_messages^, status);
      IF status.normal THEN
        validate_request_type (response.next_request, 'RESPONSE.NEXT_REQUEST', server_response.next_request,
              status);
        IF status.normal THEN
          validate_request_type (response.next_request, 'RESPONSE.NEXT_REQUEST', server_response.next_request,
                status);
          IF status.normal THEN
            IF (response.server_event_code < 0) OR (response.server_event_code > osc$max_integer) THEN
              report_invalid_response_field ('SERVER_EVENT_CODE', status);
            ELSEIF (response.retry_delay_interval < 0) OR (response.retry_delay_interval > osc$max_integer)
                  THEN
              report_invalid_response_field ('RETRY_DELAY_INTERVAL', status);
            ELSEIF (response.retry_limit < 1) OR (response.retry_limit > osc$max_integer) THEN
              report_invalid_response_field ('RETRY_LIMIT', status);
            ELSE
              server_response.server_event_code := response.server_event_code;
              server_response.retry_delay_interval := response.retry_delay_interval;
              server_response.retry_limit := response.retry_limit;
            IFEND;
          IFEND;
        IFEND;
      IFEND;
    IFEND;

  PROCEND process_response_retry;

?? OLDTITLE ??
?? NEWTITLE := 'report_invalid_response_field', EJECT ??

  PROCEDURE [INLINE] report_invalid_response_field
    (    field: string ( * );
     VAR status: ost$status);

    osp$set_status_abnormal (rmc$resource_management_id, rme$invalid_server_response, field, status);

  PROCEND report_invalid_response_field;
?? OLDTITLE ??
?? NEWTITLE := 'validate_boolean', EJECT ??

  PROCEDURE validate_boolean
    (    boolean_value: boolean;
         field: string ( * );
     VAR validated_boolean: boolean;
     VAR status: ost$status);

    IF (boolean_value < LOWERVALUE (boolean)) OR (boolean_value > UPPERVALUE (boolean)) THEN
      report_invalid_response_field (field, status);
    ELSE
      status.normal := TRUE;
      validated_boolean := boolean_value;
    IFEND;

  PROCEND validate_boolean;

?? OLDTITLE ??
?? NEWTITLE := 'validate_caller', EJECT ??

  PROCEDURE validate_caller
    (    caller_id: ost$caller_identifier;

     VAR status: ost$status);

    VAR
      user_id: ost$user_identification;

    status.normal := TRUE;

    IF (caller_id.ring > osc$sj_ring_3 {ring 6} ) THEN
      osp$set_status_condition (rme$robotic_validation_error, status);
    ELSE
      pmp$get_user_identification (user_id, status);
      IF status.normal THEN
        IF (user_id.family = jmc$system_family) AND (user_id.user = jmc$system_user) THEN
          RETURN;
        ELSE
          osp$set_status_condition (rme$robotic_validation_error, status);
        IFEND;
      IFEND;
    IFEND;

  PROCEND validate_caller;

?? OLDTITLE ??
?? NEWTITLE := 'validate_conditional_message', EJECT ??

  PROCEDURE validate_conditional_message
    (    conditional_message: rmt$rbt_conditional_message;
         record_name: string ( * );
     VAR status: ost$status);

    CONST
      max_seed_name = 21; {Allows for natural language suffix of 10 characters}

    VAR
      field: string (osc$max_string_size),
      i: integer,
      ignore_name: ost$name,
      ignore_size: integer,
      name_is_valid: boolean;

    IF (conditional_message.issue_prior_to_retry_attempt < 1) OR
          (conditional_message.issue_prior_to_retry_attempt > osc$max_integer) THEN
      STRINGREP (field, ignore_size, record_name, '.ISSUE_PRIOR_TO_RETRY_ATTEMPT');
      report_invalid_response_field (field, status);
    ELSE
      clp$validate_name (conditional_message.message_module, ignore_name, name_is_valid);
      IF name_is_valid AND (clp$trimmed_string_size (conditional_message.message_module) <=
            max_seed_name) THEN
        clp$validate_name (conditional_message.message_name, ignore_name, name_is_valid);
        IF name_is_valid THEN
          IF conditional_message.message_parameters <> NIL THEN
            FOR i := LOWERBOUND (conditional_message.message_parameters^)
                  TO UPPERBOUND (conditional_message.message_parameters^) DO
              IF conditional_message.message_parameters^ [i] <> NIL THEN
                IF STRLENGTH (conditional_message.message_parameters^ [i]^) >
                      rmc$rbt_status_message_width THEN
                  STRINGREP (field, ignore_size, record_name, '.MESSAGE_PARAMETERS exceeds ',
                        rmc$rbt_status_message_width, ' characters in length');
                  report_invalid_response_field (field, status);
                  RETURN;
                IFEND;
              IFEND;
            FOREND;
          IFEND;
        ELSE
          STRINGREP (field, ignore_size, record_name, '.MESSAGE_NAME');
          report_invalid_response_field (field, status);
        IFEND;
      ELSE
        STRINGREP (field, ignore_size, record_name, '.MODULE_NAME is either not a valid name or it exceeds ',
              max_seed_name, ' characters in length');
        report_invalid_response_field (field, status);
      IFEND;
    IFEND;

  PROCEND validate_conditional_message;

?? OLDTITLE ??
?? NEWTITLE := 'validate_element_list', EJECT ??

  PROCEDURE validate_element_list
    (    element_list: array [1 .. * ] of cmt$element_name;
         field: string ( * );
         procedure_name: string ( * );
         server_entry: ^iot$robotic_server_entry;
     VAR validated_list: array [1 .. * ] of cmt$element_name;
     VAR status: ost$status);

    VAR
      i: 0 .. ioc$max_unit_number,
      j: 0 .. ioc$max_unit_number,
      name_is_valid: boolean,
      validated_name: ost$name;

    status.normal := TRUE;

    IF (UPPERBOUND (element_list) - LOWERBOUND (element_list) + 1) > ioc$max_unit_number THEN
      osp$set_status_abnormal (rmc$resource_management_id, rme$too_many_elements, procedure_name, status);
      osp$append_status_parameter (osc$status_parameter_delimiter, field, status);
      osp$append_status_integer (osc$status_parameter_delimiter, ioc$max_unit_number, 16, TRUE, status);
    ELSE
      FOR i := LOWERBOUND (element_list) TO UPPERBOUND (element_list) DO
        validate_element_name (element_list [i], field, server_entry, validated_list [i], status);
        IF status.normal THEN
          { Validate that there are no duplicate elements in the array.}
          FOR j := i + 1 TO UPPERBOUND (element_list) DO
            IF element_list [i] = element_list [j] THEN
              osp$set_status_abnormal (rmc$resource_management_id, rme$duplicate_element_name, procedure_name,
                    status);
              osp$append_status_parameter (osc$status_parameter_delimiter, element_list [i], status);
              osp$append_status_parameter (osc$status_parameter_delimiter, field, status);
              RETURN;
            IFEND;
          FOREND;
        ELSE
          osp$set_status_abnormal (rmc$resource_management_id, rme$invalid_element_name, procedure_name,
                status);
          osp$append_status_parameter (osc$status_parameter_delimiter, element_list [i], status);
          RETURN;
        IFEND;
      FOREND;
    IFEND;

  PROCEND validate_element_list;
?? OLDTITLE ??
?? NEWTITLE := 'validate_element_name', EJECT ??

  PROCEDURE validate_element_name
    (    element_name: cmt$element_name;
         field: string ( * );
         server_entry: ^iot$robotic_server_entry;
     VAR validated_element_name: cmt$element_name;
     VAR status: ost$status);

    VAR
      i: integer,
      name_is_valid: boolean;

    status.normal := TRUE;

    clp$validate_name (element_name, validated_element_name, name_is_valid);
    IF name_is_valid THEN
      IF (server_entry <> NIL) AND (server_entry^.managed_elements_p <> NIL) THEN
        FOR i := LOWERBOUND (server_entry^.managed_elements_p^)
              TO UPPERBOUND (server_entry^.managed_elements_p^) DO
          IF server_entry^.managed_elements_p^ [i] = validated_element_name THEN
            RETURN;
          IFEND
        FOREND;
        report_invalid_response_field (field, status);
      IFEND;
    ELSE
      report_invalid_response_field (field, status);
    IFEND;

  PROCEND validate_element_name;
?? OLDTITLE ??
?? NEWTITLE := 'validate_external_vsn', EJECT ??

  PROCEDURE validate_external_vsn
    (    external_vsn: rmt$external_vsn;
         field: string ( * );
     VAR validated_external_vsn: rmt$external_vsn;
     VAR status: ost$status);

    IF STRLENGTH (external_vsn) = rmc$external_vsn_size THEN
      rmp$validate_ansi_string (external_vsn, validated_external_vsn, status);
      IF NOT status.normal THEN
        report_invalid_response_field (field, status);
      IFEND;
    ELSE
      report_invalid_response_field (field, status);
    IFEND;

  PROCEND validate_external_vsn;
?? OLDTITLE ??
?? NEWTITLE := 'validate_pva', EJECT ??

  PROCEDURE validate_pva
    (    pva: ^cell;
         field: string ( * );
     VAR status: ost$status);

    IF (NOT mmp$verify_access (^pva, mmc$va_read)) THEN
      report_invalid_response_field (field, status);
    IFEND;

  PROCEND validate_pva;
?? OLDTITLE ??

?? NEWTITLE := 'validate_request_id', EJECT ??

  PROCEDURE validate_request_id
    (    request_id: rmt$rbt_request_id;
         field: string ( * );
     VAR validated_request_id: rmt$rbt_request_id;
     VAR status: ost$status);

    IF (request_id < LOWERVALUE (rmt$rbt_request_id)) OR {}
          (request_id > UPPERVALUE (rmt$rbt_request_id)) THEN
      report_invalid_response_field (field, status);
    ELSE
      status.normal := TRUE;
      validated_request_id := request_id;
    IFEND;
  PROCEND validate_request_id;
?? OLDTITLE ??
?? NEWTITLE := 'validate_request_type', EJECT ??

  PROCEDURE validate_request_type
    (    request_type: rmt$rbt_request_type;
         field: string ( * );
     VAR validated_request_type: rmt$rbt_request_type;
     VAR status: ost$status);

    IF (request_type < LOWERVALUE (rmt$rbt_request_type)) OR
          (request_type > UPPERVALUE (rmt$rbt_request_type)) THEN
      report_invalid_response_field (field, status);
    ELSE
      status.normal := TRUE;
      validated_request_type := request_type;
    IFEND;
  PROCEND validate_request_type;
?? OLDTITLE ??
?? NEWTITLE := 'validate_response_dismount', EJECT ??

  PROCEDURE validate_response_dismount
    (    dismount_response: rmt$rbt_dismount_response;
         server_entry: iot$robotic_server_entry;
     VAR validated_response: rmt$rbt_dismount_response;
     VAR status: ost$status);

    validate_element_name (dismount_response.element, 'DISMOUNT.ELEMENT', ^server_entry,
          validated_response.element, status);
    IF status.normal THEN
      validate_external_vsn (dismount_response.external_vsn, 'DISMOUNT.EXTERNAL_VSN',
            validated_response.external_vsn, status);
      IF status.normal THEN
        validated_response := dismount_response;
      IFEND;
    IFEND;

  PROCEND validate_response_dismount;
?? OLDTITLE ??
?? NEWTITLE := 'validate_response_force_dismnt', EJECT ??

  PROCEDURE validate_response_force_dismnt
    (    force_dismount_response: rmt$rbt_force_dismount_response;
         server_entry: iot$robotic_server_entry;
     VAR validated_response: rmt$rbt_force_dismount_response;
     VAR status: ost$status);

    validate_element_name (force_dismount_response.element, 'FORCE_DISMOUNT.ELEMENT', ^server_entry,
          validated_response.element, status);

  PROCEND validate_response_force_dismnt;

?? OLDTITLE ??
?? NEWTITLE := 'validate_response_mount', EJECT ??

  PROCEDURE validate_response_mount
    (    mount_response: rmt$rbt_mount_response;
         server_entry: iot$robotic_server_entry;
     VAR validated_response: rmt$rbt_mount_response;
     VAR status: ost$status);

    validate_element_name (mount_response.element, 'MOUNT.ELEMENT', ^server_entry, validated_response.element,
          status);
    IF status.normal THEN
      validate_external_vsn (mount_response.external_vsn, 'MOUNT.EXTERNAL_VSN',
            validated_response.external_vsn, status);
    IFEND;

  PROCEND validate_response_mount;
?? OLDTITLE ??
?? NEWTITLE := 'validate_response_query', EJECT ??

  PROCEDURE validate_response_query
    (    query_response: rmt$rbt_query_response;
     VAR validated_response: rmt$rbt_query_response;
     VAR status: ost$status);

    validate_external_vsn (query_response.external_vsn, 'QUERY.EXTERNAL_VSN', validated_response.external_vsn,
          status);
    IF status.normal THEN
      validate_boolean (query_response.volume_located, 'QUERY.VOLUME_LOCATED',
            validated_response.volume_located, status);
      IF status.normal AND query_response.volume_located THEN
        validate_boolean (query_response.already_mounted, 'QUERY.ALREADY_MOUNTED',
              validated_response.already_mounted, status);
        IF status.normal AND (NOT query_response.already_mounted) THEN
          IF query_response.preferred_candidates <> NIL THEN
            validate_pva (query_response.preferred_candidates, 'QUERY.PREFERRED_CANDIDATES - invalid PVA',
                status);
          IFEND;
          IF status.normal AND (query_response.remaining_candidates <> NIL) THEN
            validate_pva (query_response.remaining_candidates, 'QUERY.REMAINING_CANDIDATES - invalid PVA',
                status);
          IFEND;
          IF status.normal AND (query_response.preferred_candidates = NIL) AND
              (query_response.remaining_candidates = NIL) THEN
            osp$set_status_condition (rme$no_candidate_elements, status);
          IFEND;
        IFEND;
      IFEND;
    IFEND;

  PROCEND validate_response_query;

?? OLDTITLE ??
?? NEWTITLE := 'validate_server_attributes', EJECT ??

  PROCEDURE validate_server_attributes
    (    server_attributes: array [1 .. * ] of rmt$rbt_server_attribute;
         procedure_name: string ( * );
     VAR validated_attributes: iot$robotic_server_attributes;
     VAR status: ost$status);

    CONST
      maximum_timeout = 60 {minutes} * 60 {seconds} * 1000 {milliseconds} ;

    VAR
      i: integer,
      local_attributes: iot$robotic_server_attributes;

    status.normal := TRUE;

    local_attributes := rmv$default_server_attributes;

  /loop/
    FOR i := LOWERBOUND (server_attributes) TO UPPERBOUND (server_attributes) DO
      CASE server_attributes [i].selector OF
      = rmc$rbt_null_attribute =
        ;
      = rmc$rbt_server_timeout =
        IF (server_attributes [i].server_timeout < 0) OR
              (server_attributes [i].server_timeout > maximum_timeout) THEN
          osp$set_status_abnormal (rmc$resource_management_id,
                rme$invalid_server_timeout, procedure_name, status);
          osp$append_status_integer (osc$status_parameter_delimiter,
                maximum_timeout, 10, FALSE {include radix} , status);
          EXIT /loop/;
        ELSE
          local_attributes.timeout := server_attributes [i].server_timeout;
        IFEND;
      = rmc$rbt_supported_requests =
        IF NOT (server_attributes [i].supported_requests <= valid_requests) THEN
          osp$set_status_abnormal (rmc$resource_management_id,
                rme$invalid_supported_requests, procedure_name, status);
          EXIT /loop/;
        ELSE
          local_attributes.supported_requests :=
                server_attributes [i].supported_requests;
        IFEND;
      ELSE
        osp$set_status_abnormal (rmc$resource_management_id,
              rme$invalid_server_attribute, procedure_name, status);
        osp$append_status_integer (osc$status_parameter_delimiter, i, 10, FALSE
              {include radix} , status);
        EXIT /loop/;
      CASEND;
    FOREND /loop/;
    IF status.normal THEN
      validated_attributes := local_attributes;
    IFEND;

  PROCEND validate_server_attributes;

?? OLDTITLE ??
?? NEWTITLE := 'validate_server_name', EJECT ??

  PROCEDURE validate_server_name
    (    server_name: ost$name;
         procedure_name: string ( * );
         validate_server_defined: boolean;
     VAR server_entry: iot$robotic_server_entry;
     VAR validated_server_name: ost$name;
     VAR status: ost$status);

    VAR
      debug_message_logged: boolean,
      i: integer,
      name_is_valid: boolean;

    status.normal := TRUE;

    clp$validate_name (server_name, validated_server_name, name_is_valid);
    IF name_is_valid THEN

    /locate_server/
      FOR i := LOWERVALUE (iot$robotic_server_index) TO UPPERVALUE (iot$robotic_server_index) DO
        debug_message_logged := FALSE;
        REPEAT
          IF NOT debug_message_logged THEN
            rmp$log_debug_message (' Calling iop$get_server_entry');
          IFEND;
          iop$get_server_entry (i, server_entry, status);
          IF NOT status.normal AND (status.condition = dme$unable_to_lock_tape_table) THEN
            IF NOT debug_message_logged THEN
              rmp$log_debug_message (' Waiting for tape table lock');
              debug_message_logged := TRUE;
            IFEND;
            pmp$wait (one_second, one_second);
          IFEND;
        UNTIL status.normal OR (status.condition <> dme$unable_to_lock_tape_table);
        IF status.normal THEN
          IF server_entry.server_name = validated_server_name THEN
            IF validate_server_defined THEN
              RETURN;
            ELSE
              osp$set_status_abnormal (rmc$resource_management_id, rme$duplicate_server, procedure_name,
                    status);
              osp$append_status_parameter (osc$status_parameter_delimiter, server_name, status);
            IFEND;
          IFEND;
        ELSEIF status.condition = rme$invalid_server_index THEN
          EXIT /locate_server/;
        IFEND;
      FOREND /locate_server/;

      IF validate_server_defined THEN
        osp$set_status_abnormal (rmc$resource_management_id, rme$server_not_defined, procedure_name, status);
        osp$append_status_parameter (osc$status_parameter_delimiter, server_name, status);
      ELSE
        status.normal := TRUE;
      IFEND;
    ELSE
      osp$set_status_abnormal (rmc$resource_management_id, rme$invalid_server_name, procedure_name, status);
      osp$append_status_parameter (osc$status_parameter_delimiter, server_name, status);
    IFEND;

  PROCEND validate_server_name;
?? OLDTITLE ??
MODEND rmm$robotic_interfaces_23d;
