?? RIGHT := 110 ??
?? NEWTITLE := 'NOS/VE Statistics Facility: Limit Interfaces' ??
MODULE sfm$limit_interfaces;

{ PURPOSE:
{   This module contains the external interfaces used to manipulate and retrieve
{   information from the job limit chain.
{
{ DESIGN:
{   The interfaces that update the job limit chain call internal interfaces in
{   the statistics facility that execute in lower rings and are capable of locking
{   the job routing control table which indirectly locks the job limit chain.
{   Interfaces that retrieve information from the job routing control table do not
{   call internal interfaces in the statistics facility and do not indirectly
{   interlock the job limit chain.

?? NEWTITLE := 'Global Declarations referenced by this module', EJECT ??
?? PUSH (LISTEXT := ON) ??
*copyc avc$system_defined_limit_names
*copyc cle$ecc_lexical
*copyc cle$ecc_miscellaneous
*copyc jmd$sru_count
*copyc sfc$unlimited
*copyc sfe$condition_codes
?? POP ??
*copyc avp$monitor_statistics_handler
*copyc avv$accumulated_srus
*copyc clp$get_processing_phase
*copyc clp$validate_name
*copyc jmp$system_job
*copyc osp$append_status_integer
*copyc osp$append_status_parameter
*copyc osp$set_status_abnormal
*copyc sfp$get_file_space_limit
*copyc sfp$job_limit_chain_entry
*copyc sfp$update_job_warning_limit
*copyc sfv$job_routing_control_table
?? OLDTITLE ??
?? NEWTITLE := '[XDCL, #GATE] sfp$change_job_resource_limit', EJECT ??

{ PURPOSE:
{   Change the job warning value for a specified limit.
{
{ NOTES:
{   This interface has been replaced by SFP$CHANGE_JOB_WARNING_LIMIT.  It has been retained to provide
{   compatibility with previos systems.

  PROCEDURE [XDCL, #GATE] sfp$change_job_resource_limit
    (    limit_name: ost$name;
         resource_limit: sft$counter;
     VAR status: ost$status);

    status.normal := TRUE;

    sfp$change_job_warning_limit (limit_name, resource_limit, status);

  PROCEND sfp$change_job_resource_limit;
?? OLDTITLE ??
?? NEWTITLE := '[XDCL, #GATE] sfp$change_job_warning_limit', EJECT ??
*copyc sfh$change_job_warning_limit

  PROCEDURE [XDCL, #GATE] sfp$change_job_warning_limit
    (    limit_name: ost$name;
         warning_limit: sft$counter;
     VAR status: ost$status);

    VAR
      valid_name: boolean,
      validated_name: ost$name;

    status.normal := TRUE;

    clp$validate_name (limit_name, validated_name, valid_name);
    IF NOT valid_name THEN
      osp$set_status_abnormal ('CL', cle$improper_name, limit_name, status);
      RETURN;
    IFEND;

    sfp$update_job_warning_limit (limit_name, warning_limit, status);

  PROCEND sfp$change_job_warning_limit;
?? OLDTITLE ??
?? NEWTITLE := '[XDCL, #GATE] sfp$get_all_job_limits', EJECT ??
*copyc sfh$get_all_job_limits

  PROCEDURE [XDCL, #GATE] sfp$get_all_job_limits
    (    limits: sft$limits;
     VAR count: jmt$job_resource_condition;
     VAR status: ost$status);

    VAR
      current_limit_chain_entry: ^sft$limit_chain_entry,
      index: jmt$job_resource_condition;

    status.normal := TRUE;

    IF jmp$system_job () THEN
      osp$set_status_abnormal ('SF', sfe$no_active_limits, '', status);
      RETURN;
    IFEND;

    IF sfv$job_routing_control_table = NIL THEN
      osp$set_status_abnormal ('SF', sfe$statistics_not_available, 'Job', status);
      osp$append_status_parameter (osc$status_parameter_delimiter, 'sfp$get_all_job_limits', status);
      RETURN;
    IFEND;

    IF limits = NIL THEN
      osp$set_status_abnormal ('SF', sfe$limit_array_pointer_nil, '', status);
      RETURN;
    IFEND;

    count := sfv$job_limit_count;

{ The specified array must be big enough to accept the limits.

    IF UPPERBOUND (limits^) >= count THEN

{ Update the CPU time and SRU limit accumulators.

      avp$monitor_statistics_handler (avc$monitor_statistics_flag);
      current_limit_chain_entry := sfv$first_job_limit_chain_entry;

    /copy_limits/
      FOR index := 1 TO count DO
        IF current_limit_chain_entry = NIL THEN

{ The end of the chain should never occur before the count is exhausted.

          osp$set_status_abnormal ('SF', sfe$corrupted_limit_chain, 'sfp$get_all_job_limits', status);
          RETURN;
        IFEND;
        limits^ [index] := current_limit_chain_entry^.limit;
        IF limits^ [index].name = avc$pfs_limit_name THEN
          sfp$get_file_space_limit (sfc$perm_file_space_limit, limits^ [index].
                job_resource_limit, limits^ [index].job_abort_limit, limits^ [index].accumulator);
        ELSEIF limits^ [index].name = avc$tfs_limit_name THEN
          sfp$get_file_space_limit (sfc$temp_file_space_limit, limits^ [index].
                job_resource_limit, limits^ [index].job_abort_limit, limits^ [index].accumulator);
        IFEND;
        current_limit_chain_entry := current_limit_chain_entry^.forward;
      FOREND /copy_limits/;
    ELSE
      osp$set_status_abnormal ('SF', sfe$limit_array_too_small, '', status);
      osp$append_status_integer (osc$status_parameter_delimiter, UPPERBOUND (limits^), 10, FALSE, status);
      osp$append_status_integer (osc$status_parameter_delimiter, sfv$job_limit_count, 10, FALSE, status);
    IFEND;

  PROCEND sfp$get_all_job_limits;
?? OLDTITLE ??
?? NEWTITLE := '[XDCL, #GATE] sfp$get_job_limit', EJECT ??
*copyc sfh$get_job_limit

  PROCEDURE [XDCL, #GATE] sfp$get_job_limit
    (    limit_name: ost$name;
     VAR limit: sft$limit;
     VAR status: ost$status);

    VAR
      job_limit_chain_entry: ^sft$limit_chain_entry,
      valid_name: boolean,
      validated_name: ost$name;

    status.normal := TRUE;

    clp$validate_name (limit_name, validated_name, valid_name);
    IF NOT valid_name THEN
      osp$set_status_abnormal ('CL', cle$improper_name, limit_name, status);
      RETURN;
    IFEND;

    IF sfv$job_routing_control_table = NIL THEN
      osp$set_status_abnormal ('SF', sfe$statistics_not_available, 'Job', status);
      osp$append_status_parameter (osc$status_parameter_delimiter, 'sfp$get_job_limit', status);
      RETURN;
    IFEND;

{ Make sure the limit has been updated if CPU time or SRU limit is requested.

    IF (limit_name = avc$cpu_time_limit_name) OR (limit_name = avc$sru_limit_name) THEN
      avp$monitor_statistics_handler (avc$monitor_statistics_flag);
    IFEND;

{ Get the limit chain entry for the specified limit name if one exists.

    job_limit_chain_entry := sfp$job_limit_chain_entry (limit_name);
    IF job_limit_chain_entry <> NIL THEN
      limit := job_limit_chain_entry^.limit;
      IF limit.name = avc$pfs_limit_name THEN
        sfp$get_file_space_limit (sfc$perm_file_space_limit, limit.job_resource_limit, limit.job_abort_limit,
              limit.accumulator);
      ELSEIF limit.name = avc$tfs_limit_name THEN
        sfp$get_file_space_limit (sfc$temp_file_space_limit, limit.job_resource_limit, limit.job_abort_limit,
              limit.accumulator);
      IFEND;
    ELSE
      osp$set_status_abnormal ('SF', sfe$limit_not_activated, limit_name, status);
    IFEND;

  PROCEND sfp$get_job_limit;
?? OLDTITLE ??
?? NEWTITLE := '[XDCL, #GATE] sfp$get_job_limit_count', EJECT ??
*copyc sfh$get_job_limit_count

  PROCEDURE [XDCL, #GATE] sfp$get_job_limit_count
    (VAR count: jmt$job_resource_condition;
     VAR status: ost$status);

    status.normal := TRUE;

    IF sfv$job_routing_control_table = NIL THEN
      osp$set_status_abnormal ('SF', sfe$statistics_not_available, 'Job', status);
      osp$append_status_parameter (osc$status_parameter_delimiter, 'sfp$get_job_limit_count', status);
      RETURN;
    IFEND;

    count := sfv$job_limit_count;

  PROCEND sfp$get_job_limit_count;
?? OLDTITLE ??
?? NEWTITLE := '[XDCL, #GATE] sfp$get_job_limit_name', EJECT ??
*copyc sfh$get_job_limit_name

  PROCEDURE [XDCL, #GATE] sfp$get_job_limit_name
    (    condition_id: jmt$job_resource_condition;
     VAR limit_name: ost$name;
     VAR status: ost$status);

    VAR
      current_limit_chain_entry: ^sft$limit_chain_entry;

    status.normal := TRUE;

    IF sfv$job_routing_control_table = NIL THEN
      osp$set_status_abnormal ('SF', sfe$statistics_not_available, 'Job', status);
      osp$append_status_parameter (osc$status_parameter_delimiter, 'sfp$get_job_limit_name', status);
      RETURN;
    IFEND;

    current_limit_chain_entry := sfv$first_job_limit_chain_entry;

  /search_for_limit_chain_entry/
    WHILE (current_limit_chain_entry <> NIL) AND (current_limit_chain_entry^.limit.condition_identifier <>
          condition_id) DO
      current_limit_chain_entry := current_limit_chain_entry^.forward;
    WHILEND /search_for_limit_chain_entry/;

    IF current_limit_chain_entry <> NIL THEN
      limit_name := current_limit_chain_entry^.limit.name;
    ELSE
      osp$set_status_abnormal ('SF', sfe$unknown_condition_id, '', status);
      osp$append_status_integer (osc$status_parameter_delimiter, condition_id, 10, FALSE, status);
    IFEND;

  PROCEND sfp$get_job_limit_name;
?? OLDTITLE ??
?? NEWTITLE := '[XDCL, #GATE] pmp$get_srus', EJECT ??
*copyc pmh$get_srus

  PROCEDURE [XDCL, #GATE] pmp$get_srus
    (VAR srus: jmt$sru_count;
     VAR status: ost$status);

    VAR
      limit_information: sft$limit;

    status.normal := TRUE;

    avp$monitor_statistics_handler (avc$monitor_statistics_flag);
    srus := avv$accumulated_srus;

  PROCEND pmp$get_srus;
?? OLDTITLE ??
MODEND sfm$limit_interfaces;
