?? NEWTITLE := '  NOS/VE Set Management ' ??
MODULE stm$modify_job_set_table;
?? RIGHT := 110 ??

{ PURPOSE:
{   This module contains those routines that modify the job active set  table.
{
{ DESIGN:
{   A  pointer  to the job active set table is maintained as a static variable
{   in this ring 2 (223) module.  On creating a new entry, if the  pointer  is
{   NIL  a  new  job  active  set  table is allocated.  Locks to the table are
{   maintained as static variables in this module.

?? NEWTITLE := 'Global Declarations Referenced by This Module', EJECT ??
?? PUSH (LISTEXT := ON) ??
*copyc ose$heap_full_exceptions
*copyc ste$error_condition_codes
*copyc ost$signature_lock
*copyc ost$status
*copyc ost$user_identification
*copyc stt$jast_index
?? POP ??
*copyc osp$clear_job_signature_lock
*copyc osp$initialize_signature_lock
*copyc osp$set_job_signature_lock
*copyc osp$set_status_abnormal
*copyc pmp$wait
*copyc stp$search_jast_for_unused
*copyc osv$job_pageable_heap
?? OLDTITLE ??
?? NEWTITLE := 'Global Declarations Declared by This Module', EJECT ??

  VAR
    stv$jast_modify_lock: [XDCL] ost$signature_lock := [0],
    stv$jast_read_lock_set: [XDCL] boolean := FALSE,
    stv$jast_number_of_readers: [XDCL] integer := 0,
    stv$p_jast: [XDCL] ^stt$job_active_set_table := NIL;

?? OLDTITLE ??
?? NEWTITLE := 'p$set_exclusive_access_in_jas', EJECT ??

    PROCEDURE p$set_exclusive_access_in_jas
      (VAR need_to_wait: boolean);

      osp$set_job_signature_lock (stv$jast_modify_lock);
      need_to_wait := stv$jast_read_lock_set;
      IF need_to_wait THEN
        {dont wait with the lock set }
        osp$clear_job_signature_lock (stv$jast_modify_lock);
      IFEND;

    PROCEND p$set_exclusive_access_in_jas;
?? OLDTITLE ??
?? NEWTITLE := '  [XDCL] stp$clear_job_ast_exclusive', EJECT ??

  PROCEDURE [XDCL] stp$clear_job_ast_exclusive;

    osp$clear_job_signature_lock (stv$jast_modify_lock);

  PROCEND stp$clear_job_ast_exclusive;
?? OLDTITLE ??
?? NEWTITLE := '  [XDCL] stp$clear_job_ast_read', EJECT ??

  PROCEDURE [XDCL] stp$clear_job_ast_read;

    osp$set_job_signature_lock (stv$jast_modify_lock);
    stv$jast_number_of_readers := stv$jast_number_of_readers - 1;
    IF stv$jast_number_of_readers < 0 THEN
      stv$jast_number_of_readers := 0;
    IFEND;
    stv$jast_read_lock_set := stv$jast_number_of_readers > 0;
    osp$clear_job_signature_lock (stv$jast_modify_lock);

  PROCEND stp$clear_job_ast_read;
?? OLDTITLE ??
?? NEWTITLE := '  [XDCL] stp$create_jast_entry', EJECT ??

  PROCEDURE [XDCL] stp$create_jast_entry
    (    required_set: stt$set_name;
         unique_set: stt$unique_set_name;
         ast_index: stt$ast_index;
     VAR status: ost$status);

{  PURPOSE:
{    This procedure gets an unused entry in the job active set table, and
{    fills that entry with valid information.

    VAR
      entry_p: ^stt$job_active_set_entry,
      jast_index: integer;

    stp$get_unused_entry_in_jast (jast_index, status);
    IF status.normal THEN {space was found}
      entry_p := ^stv$p_jast^.table [jast_index];
      entry_p^.entry_type := stc$valid;
      entry_p^.set_name := required_set;
      entry_p^.unique_set_name := unique_set;
      entry_p^.ast_index := ast_index;
    IFEND;

  PROCEND stp$create_jast_entry;
?? OLDTITLE ??
?? NEWTITLE := '  [XDCL] stp$get_unused_entry_in_jast ', EJECT ??

  PROCEDURE [XDCL] stp$get_unused_entry_in_jast
    (VAR jast_index: integer;
     VAR status: ost$status);

{  PURPOSE:
{    This procedure does what is needed to get an unused entry in the
{    job active set table.  This could include searching for an unused entry,
{    creating a new table, or expanding an old table.

    CONST
      stc$initial_jast_size = 3,
      stc$expand_jast_amount = 3;

    VAR
      p_new_jast: ^stt$job_active_set_table,
      space_found: boolean;

    space_found := FALSE;
    IF stv$p_jast = NIL THEN
{     CREATE NEW TABLE
      ALLOCATE stv$p_jast: [1 .. stc$initial_jast_size] IN osv$job_pageable_heap^;
      IF stv$p_jast = NIL THEN
        osp$set_status_abnormal (stc$set_management_id, ose$job_pageable_full, stc$space_unavailable_jast,
              status);
      ELSE
        initialize_jast_to_unused (stv$p_jast);
        stp$search_jast_for_unused (stv$p_jast, jast_index, space_found);
      IFEND;
    ELSE
      stp$search_jast_for_unused (stv$p_jast, jast_index, space_found);
      IF NOT space_found THEN
{       EXPAND AN EXISTING TABLE
        ALLOCATE p_new_jast: [1 .. (UPPERBOUND (stv$p_jast^.table) + stc$expand_jast_amount)] IN
              osv$job_pageable_heap^;
        IF p_new_jast = NIL THEN
          osp$set_status_abnormal (stc$set_management_id, ose$job_pageable_full, stc$space_unavailable_jast,
                status);
        ELSE
          transfer_old_to_new_jast (stv$p_jast, p_new_jast, status);
          FREE stv$p_jast IN osv$job_pageable_heap^;
          {store the new pointer someplace}
          stv$p_jast := p_new_jast;
          stp$search_jast_for_unused (stv$p_jast, jast_index, space_found);
        IFEND;
      IFEND;
    IFEND;

  PROCEND stp$get_unused_entry_in_jast;
?? OLDTITLE ??
?? NEWTITLE := '  [XDCL] stp$recover_jobs_sets', EJECT ??

  PROCEDURE [XDCL] stp$recover_jobs_sets
    (VAR status: ost$status);

{   The purpose of this routine is to recover the job set table, following
{ a system recovery in which jobs are recovered.  Because of the current
{ use of the mainframe  lock to lock this table, no verification can be
{ made on the state of this table.
{   This table is currently only used for performance, and the next
{ permanent file access will re-built this table.  With only one set
{ the table could probably be used as is, since the active set table index
{ is always one.
{   If we ever have multiple sets or removable devices, this table could
{ be used to verify that all of the sets or devices that the job was using
{ are active.

    stv$p_jast := NIL;
    stv$jast_read_lock_set := FALSE;
    stv$jast_number_of_readers := 0;
    osp$initialize_signature_lock (stv$jast_modify_lock, status);

  PROCEND stp$recover_jobs_sets;
?? OLDTITLE ??
?? NEWTITLE := '  [XDCL] stp$remove_set_from_jast', EJECT ??

  PROCEDURE [XDCL] stp$remove_set_from_jast
    (    set_name: stt$set_name;
     VAR status: ost$status);

{  PURPOSE:
{    This procedure removes a given set from the jobs active set table.
{    This is done on a purge set.

    VAR
      jast_index: integer;

    status.normal := TRUE;
    IF stv$p_jast <> NIL THEN
      FOR jast_index := LOWERBOUND (stv$p_jast^.table) TO UPPERBOUND (stv$p_jast^.table) DO
        IF (stv$p_jast^.table [jast_index].entry_type = stc$valid) AND
              (stv$p_jast^.table [jast_index].set_name = set_name) THEN
          stv$p_jast^.table [jast_index].entry_type := stc$unused;
          RETURN; {----->
        IFEND;
      FOREND;
    IFEND;

  PROCEND stp$remove_set_from_jast;
?? OLDTITLE ??
?? NEWTITLE := '  [XDCL] stp$set_job_ast_exclusive', EJECT ??

  PROCEDURE [XDCL] stp$set_job_ast_exclusive;

    VAR
      need_to_wait: boolean;

    p$set_exclusive_access_in_jas (need_to_wait);
    WHILE need_to_wait DO
      pmp$wait (0ff(16), 0ff(16));
      p$set_exclusive_access_in_jas (need_to_wait);
    WHILEND;

  PROCEND stp$set_job_ast_exclusive;
?? OLDTITLE ??
?? NEWTITLE := '  [XDCL] stp$set_job_ast_read', EJECT ??

  PROCEDURE [XDCL] stp$set_job_ast_read;

    osp$set_job_signature_lock (stv$jast_modify_lock);
    stv$jast_read_lock_set := TRUE;
    stv$jast_number_of_readers := stv$jast_number_of_readers + 1;
    osp$clear_job_signature_lock (stv$jast_modify_lock);

  PROCEND stp$set_job_ast_read;
?? OLDTITLE ??
?? NEWTITLE := '  initialize_jast_to_unused', EJECT ??

  PROCEDURE initialize_jast_to_unused
    (    stv$p_jast: ^stt$job_active_set_table);

{  PURPOSE:
{    This procedure initialize the job active set table to indicate that all
{    entries are unused.

    VAR
      jast_index: integer;

    FOR jast_index := LOWERBOUND (stv$p_jast^.table) TO UPPERBOUND (stv$p_jast^.table) DO
      stv$p_jast^.table [jast_index].entry_type := stc$unused;
    FOREND;

  PROCEND initialize_jast_to_unused;
?? OLDTITLE ??
?? NEWTITLE := '  transfer_old_to_new_jast', EJECT ??

  PROCEDURE transfer_old_to_new_jast
    (    p_old_jast: ^stt$job_active_set_table;
         p_new_jast: ^stt$job_active_set_table;
     VAR status: ost$status);

{  PURPOSE:
{    This transfers an old job active set table to a new one, entry by entry.
{    The new table is assumed to be as big as, or bigger than, the old table.

    VAR
      jast_index: stt$jast_index;

    status.normal := TRUE;
    FOR jast_index := LOWERBOUND (p_old_jast^.table) TO UPPERBOUND (p_old_jast^.table) DO
      p_new_jast^.table [jast_index] := p_old_jast^.table [jast_index];
    FOREND;
    FOR jast_index := (UPPERBOUND (p_old_jast^.table) + 1) TO (UPPERBOUND (p_new_jast^.table)) DO
      p_new_jast^.table [jast_index].entry_type := stc$unused;
    FOREND;

  PROCEND transfer_old_to_new_jast;
?? OLDTITLE ??
MODEND stm$modify_job_set_table;
