?? RIGHT := 110 ??
?? NEWTITLE := 'NOS/VE Statistics Facility: Job Routing Control Manager' ??
MODULE sfm$job_routing_control_manager;

{ PURPOSE:
{   This module contains the procedures that are used to create and manage the job routing control table.
{
{ DESIGN:
{   The job routing control table controls the logging of statistics for the job.
{
{   The routing control for a given statistic is found by calculating an index into the table (statistic code
{   MOD size of the table) and chaining down the linked list of routing control entries.
{
{   Routing controls are added to the chain in last in first out order.
{
{   The size of the routing control table has been chosen to provide an average chain length of 1 when all
{   currently known statistics are activated.
{
{   Updates of the job routing control table are interlocked by using signature locks.
?? NEWTITLE := 'Global Declarations Referenced by This Module', EJECT ??
?? PUSH (LISTEXT := ON) ??
*copyc jml$user_id
*copyc sfe$condition_codes
*copyc sft$binary_logset
*copyc sft$limit_chain_entry
*copyc sft$routing_control
*copyc sft$routing_control_table
*copyc sft$statistic_code
?? POP ??
*copyc osp$append_status_parameter
*copyc osp$clear_job_signature_lock
*copyc osp$initialize_sig_lock
*copyc osp$set_job_signature_lock
*copyc osp$set_status_abnormal
*copyc osp$test_signature_lock
*copyc sfp$add_audit_control
*copyc sfp$add_routing_control
*copyc sfp$convert_stat_code_to_name
*copyc sfp$delete_audit_control
*copyc sfp$delete_routing_control
*copyc sfp$lock_routing_control
*copyc osv$job_pageable_heap
?? OLDTITLE ??
?? NEWTITLE := 'Global Declarations Declared by This Module', EJECT ??

{ The job routing control table controls which statistics are emitted to which logs for the job.

  VAR
    sfv$job_routing_control_table: [XDCL, #GATE, STATIC, oss$job_pageable] sft$routing_control_table := NIL;

{ The job routing control lock controls access to the job routing control table.

  VAR
    sfv$job_routing_control_lock: [XDCL, #GATE, STATIC, oss$job_pageable] ost$signature_lock;

{ This variable is used to store the number of limits active for the job.
{ NOTE: This variable must be initialized to 1 because 1 is reserved for the time limit condition identifier.

  VAR
    sfv$job_limit_count: [XDCL, #GATE, STATIC, oss$job_pageable] jmt$job_resource_condition := 1;

{ This variable is used to store a pointer to the first limit in the limit chain for the job.

  VAR
    sfv$first_job_limit_chain_entry: [XDCL, #GATE, STATIC, oss$job_pageable] ^sft$limit_chain_entry := NIL;

{ This variable indicates whether open_file statistics are activated for the job.

  VAR
    sfv$emit_job_open_statistics: [XDCL, #GATE, STATIC, oss$job_pageable] boolean := FALSE;

?? OLDTITLE ??
?? NEWTITLE := '[XDCL, #GATE] sfp$add_job_audit_control', EJECT ??
*copyc sfh$add_job_audit_control

  PROCEDURE [XDCL, #GATE] sfp$add_job_audit_control
    (    operation_set: sft$audited_operation_set;
         selection_criteria: sft$audit_selection_criteria;
         lock: boolean;
     VAR status: ost$status);

    status.normal := TRUE;

{ Make sure the job routing control table has been initialized.

    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$add_job_audit_control', status);
      RETURN;
    IFEND;

{ Interlock the job routing control table.

    osp$set_job_signature_lock (sfv$job_routing_control_lock);

{ Add the specified audit control information to the routing control table.

    sfp$add_audit_control (sfv$job_routing_control_table, operation_set, selection_criteria, lock,
          osv$job_pageable_heap);

{ Clear the interlock.

    osp$clear_job_signature_lock (sfv$job_routing_control_lock);

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

  PROCEDURE [XDCL, #GATE] sfp$add_job_routing_control
    (    statistic_code: sft$statistic_code;
         logs: sft$binary_logset;
         limit_name: ost$name;
     VAR status: ost$status);

    VAR
      statistic_name: ost$name,
      routing_control_p: ^sft$routing_control;

    status.normal := TRUE;

{ Make sure the job routing control table has been initialized.

    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$add_job_routing_control', status);
      RETURN;
    IFEND;

{ Interlock the job routing control table.

    osp$set_job_signature_lock (sfv$job_routing_control_lock);

{ Add the specified routing control information to the routing control table.

    sfp$add_routing_control (sfv$job_routing_control_table, statistic_code, logs, osv$job_pageable_heap,
          routing_control_p);

{ If a limit name was specified and no limit has already been associated with this statistic, set the limit
{ name in the routing control entry.

    IF limit_name <> osc$null_name THEN
      IF routing_control_p^.limit_name = osc$null_name THEN
          routing_control_p^.limit_name := limit_name;
      ELSE
        sfp$convert_stat_code_to_name (statistic_code, statistic_name, status);
        osp$set_status_abnormal ('SF', sfe$limit_already_active, statistic_name, status);
        osp$append_status_parameter (osc$status_parameter_delimiter, limit_name, status);
        osp$append_status_parameter (osc$status_parameter_delimiter,
              routing_control_p^.limit_name, status);
      IFEND;
    IFEND;

{ Clear the interlock.

    osp$clear_job_signature_lock (sfv$job_routing_control_lock);

    IF (statistic_code = jml$open_file_statistics) AND NOT sfv$emit_job_open_statistics THEN
      sfv$emit_job_open_statistics := TRUE;
    IFEND;

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

  PROCEDURE [XDCL, #GATE] sfp$clear_job_routing_ctl_lock;

    VAR
      lock_status: ost$signature_lock_status;

{ Check if the job routing control table is interlocked.
    osp$test_signature_lock (sfv$job_routing_control_lock, lock_status);

{ If this task has the job routing control table locked, release the lock.
    IF lock_status = osc$sls_locked_by_current_task THEN
      osp$clear_job_signature_lock (sfv$job_routing_control_lock);
    IFEND;

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

  PROCEDURE [XDCL, #GATE] sfp$delete_job_audit_control
    (    operation_set: sft$audited_operation_set;
     VAR status: ost$status);

    status.normal := TRUE;

{ Make sure the job routing control table has been initialized.

    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$delete_job_audit_control', status);
      RETURN;
    IFEND;

{ Interlock the job routing control table.

    osp$set_job_signature_lock (sfv$job_routing_control_lock);

{ Delete the specified audit control information from the routing control table.

    sfp$delete_audit_control (sfv$job_routing_control_table, operation_set, osv$job_pageable_heap,
          status);

{ Clear the interlock.

    osp$clear_job_signature_lock (sfv$job_routing_control_lock);

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

  PROCEDURE [XDCL, #GATE] sfp$delete_job_routing_control
    (    statistic_code: sft$statistic_code;
         logs: sft$binary_logset;
     VAR status: ost$status);

    status.normal := TRUE;

{ Make sure the job routing control table has been initialized.

    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$delete_job_routing_control', status);
      RETURN;
    IFEND;

{ Interlock the job routing control table.

    osp$set_job_signature_lock (sfv$job_routing_control_lock);

{ Delete the specified routing control information from the routing control table.

    sfp$delete_routing_control (sfv$job_routing_control_table, statistic_code, logs, status);

{ Clear the interlock.

    osp$clear_job_signature_lock (sfv$job_routing_control_lock);

    IF (statistic_code = jml$open_file_statistics) AND sfv$emit_job_open_statistics THEN
      sfv$emit_job_open_statistics := FALSE;
    IFEND;

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

  PROCEDURE [XDCL, #GATE] sfp$init_job_routing_control
    (VAR status: ost$status);

    VAR
      index: 0 .. sfc$routing_control_table_size;

    status.normal := TRUE;

{ Allocate the job routing control table and initialize each entry to NIL.

    ALLOCATE sfv$job_routing_control_table: [0 .. sfc$routing_control_table_size] IN osv$job_pageable_heap^;

    FOR index := 0 TO sfc$routing_control_table_size DO
      sfv$job_routing_control_table^ [index] := NIL;
    FOREND;

    osp$initialize_sig_lock (sfv$job_routing_control_lock);

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

  PROCEDURE [XDCL, #GATE] sfp$lock_job_routing_control
    (    statistic_code: sft$statistic_code;
         logs: sft$binary_logset;
     VAR status: ost$status);

    status.normal := TRUE;

{ Make sure the job routing control table has been initialized.

    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$lock_job_routing_control', status);
      RETURN;
    IFEND;

{ Interlock the job routing control table.

    osp$set_job_signature_lock (sfv$job_routing_control_lock);

{ Lock the specified routing control information.

    sfp$lock_routing_control (sfv$job_routing_control_table, statistic_code, logs,
          osv$job_pageable_heap);

{ Clear the interlock.

    osp$clear_job_signature_lock (sfv$job_routing_control_lock);

  PROCEND sfp$lock_job_routing_control;
?? OLDTITLE ??
MODEND sfm$job_routing_control_manager;
