?? RIGHT := 110 ??
?? NEWTITLE := 'NOS/VE Job Management: Generic Queue File Internal Interfaces' ??
MODULE qfm$generic_queue_file_manager;

{ PURPOSE:
{   This module contains the Queue File Management system core interfaces for managing files in the
{ generic queue and the Known Qfile List (KQL).
{
{ DESIGN:
{   These procedures execute in ring one and can be called from ring 3.  These procedures access
{ the ring one table: the Known Qfile List (KQL).  It is contained in mainframe pageable.  A signature
{ lock is used in order to ensure synchronous access to the KQL.
{
{ GLOSSARY:
{   AN             Application Name
{   NAN            Next Application Name

?? NEWTITLE := 'Global Declarations Referenced by This Module', EJECT ??
?? PUSH (LISTEXT := ON) ??
*copyc jmc$generic_queue_full_message
*copyc jmc$job_management_id
*copyc jmc$maximum_qfile_count
*copyc jme$application_name_in_use
*copyc jme$application_name_incorrect
*copyc jme$generic_queue_is_empty
*copyc jme$maximum_generic_qfiles
*copyc jme$qfile_already_terminated
*copyc jme$qfile_appl_not_permitted
*copyc jme$qfile_cannot_initiate
*copyc jme$queued_file_conditions
*copyc jmt$clock_time
*copyc jmt$job_attributes
*copyc jmt$known_qfile_list
*copyc jmt$known_qfile_list_entry
*copyc jmt$kql_entry_kind
*copyc jmt$kql_entry_kind_set
*copyc jmt$kql_index
*copyc jmt$name
*copyc jmt$qfile_application_attrs
*copyc jmt$qfile_attribute_options
*copyc jmt$qfile_counts
*copyc jmt$qfile_registration_options
*copyc jmt$qfile_state
*copyc jmt$qfile_state_set
*copyc jmt$qfile_status_count
*copyc jmt$qfile_status_options
*copyc jmt$qfile_status_results
*copyc jmt$qfile_system_label
*copyc jmt$queue_file_password
*copyc jmt$rerun_disposition
*copyc jmt$results_keys
*copyc jmt$system_supplied_name
*copyc jmt$system_supplied_name_list
*copyc jmt$work_area
*copyc oss$mainframe_pageable
*copyc oss$mainframe_paged_literal
*copyc ost$byte
*copyc ost$global_task_id
*copyc ost$halfword
*copyc ost$signature_lock
*copyc ost$status
*copyc ost$user_identification
?? POP ??
*copyc dpp$put_critical_message
*copyc osp$clear_mainframe_sig_lock
*copyc osp$monitor_fault_to_status
*copyc osp$set_mainframe_sig_lock
*copyc osp$set_status_abnormal
*copyc osp$set_status_condition
*copyc osp$test_sig_lock
*copyc pmp$get_executing_task_gtid
*copyc pmp$get_mainframe_id
*copyc pmp$ready_task
*copyc pmp$zero_out_table
*copyc syp$continue_to_cause
*copyc syp$disestablish_cond_handler
*copyc syp$establish_condition_handler
?? OLDTITLE ??
?? NEWTITLE := 'Global Declarations Declared by This Module', EJECT ??

  VAR
    jmv$qfile_recovery_option: [XDCL, #GATE, oss$mainframe_pageable] ost$byte := 0,
    jmv$purge_expired_qfile_time: [XDCL, #GATE, oss$mainframe_pageable] jmt$clock_time :=
          jmc$latest_clock_time,
    jmv$purge_processed_qfile_time: [XDCL, #GATE, oss$mainframe_pageable] jmt$clock_time :=
          jmc$latest_clock_time,
    jmv$ready_deferred_qfile_time: [XDCL, #GATE, oss$mainframe_pageable] jmt$clock_time :=
          jmc$latest_clock_time,
    jmv$known_qfile_list: [XDCL, #GATE, oss$mainframe_pageable] jmt$known_qfile_list,
    jmv$kql_p: [XDCL, #GATE, oss$mainframe_pageable] ^array [1 .. * ] of jmt$known_qfile_list_entry := NIL,
    qfv$current_kql_limit: [XDCL, #GATE, oss$mainframe_pageable] jmt$kql_index := 0,
    qfv$kql_lock: [XDCL, oss$mainframe_pageable] ost$signature_lock,
    convert_state_to_entry_kind: [STATIC, READ, oss$mainframe_paged_literal] array [jmt$qfile_state] of
          jmt$kql_entry_kind := [jmc$kql_deferred_entry, jmc$kql_queued_entry, jmc$kql_initiated_entry,
          jmc$kql_terminated_entry, jmc$kql_completed_entry],
    jmv$last_used_application_index: [XDCL, #GATE, oss$mainframe_pageable] jmt$qfile_application_index :=
          jmc$unassigned_qfile_index;

?? OLDTITLE ??
?? NEWTITLE := '[inline] F$DEFERRED', EJECT ??

  FUNCTION [INLINE] f$deferred
    (    known_qfile_list_entry: jmt$known_qfile_list_entry): boolean;

    f$deferred := known_qfile_list_entry.deferred_by_application OR
          known_qfile_list_entry.deferred_by_operator OR known_qfile_list_entry.deferred_by_user;

  FUNCEND f$deferred;
?? OLDTITLE ??
?? NEWTITLE := 'expand_kql', EJECT ??

{ PURPOSE:
{   The purpose of this request is to extend the initialized portion of the
{ Known Qfile List (KQL).  If the KQL is at its limit, this request does nothing.
{
{ CAUTION:  This request cannot be performed in a loop in ring one.  If
{           several entries must be added to the KQL this request must be
{           called from ring 3.  The reason for this is because pages
{           assigned in ring 1 do not get backing store until the ring is
{           exited.  So if too many new pages are added to the KQL, memory
{           may be exhausted and the system will crash or hang.

  PROCEDURE expand_kql;

    CONST
      expand_increment = 100;

    VAR
      kql_index: jmt$kql_index,
      new_kql_limit: jmt$kql_index;

    IF qfv$current_kql_limit < jmc$maximum_qfile_count THEN
      IF qfv$current_kql_limit + expand_increment > jmc$maximum_qfile_count THEN
        new_kql_limit := jmc$maximum_qfile_count;
      ELSE
        new_kql_limit := qfv$current_kql_limit + expand_increment;
      IFEND;
      FOR kql_index := qfv$current_kql_limit + 1 TO new_kql_limit - 1 DO
        jmv$kql_p^ [kql_index].forward_link := kql_index + 1;
        jmv$kql_p^ [kql_index].reverse_link := kql_index - 1;
        jmv$kql_p^ [kql_index].entry_kind := jmc$kql_unused_entry;
      FOREND;
      jmv$kql_p^ [new_kql_limit].forward_link := jmc$kql_undefined_index;
      jmv$kql_p^ [new_kql_limit].reverse_link := new_kql_limit - 1;
      jmv$kql_p^ [new_kql_limit].entry_kind := jmc$kql_unused_entry;

      jmv$known_qfile_list.state_data [jmc$kql_unused_entry].number_of_entries :=
            jmv$known_qfile_list.state_data [jmc$kql_unused_entry].number_of_entries + new_kql_limit -
            qfv$current_kql_limit;
      IF jmv$known_qfile_list.state_data [jmc$kql_unused_entry].first_entry = jmc$kql_undefined_index THEN
        jmv$known_qfile_list.state_data [jmc$kql_unused_entry].first_entry := qfv$current_kql_limit + 1;
        jmv$kql_p^ [qfv$current_kql_limit + 1].reverse_link := jmc$kql_undefined_index;
        jmv$known_qfile_list.state_data [jmc$kql_unused_entry].last_entry := new_kql_limit;

      ELSE
        jmv$kql_p^ [qfv$current_kql_limit + 1].reverse_link := jmv$known_qfile_list.
              state_data [jmc$kql_unused_entry].last_entry;
        jmv$kql_p^ [jmv$known_qfile_list.state_data [jmc$kql_unused_entry].last_entry].forward_link :=
              qfv$current_kql_limit + 1;
        jmv$known_qfile_list.state_data [jmc$kql_unused_entry].last_entry := new_kql_limit;
      IFEND;
      qfv$current_kql_limit := new_kql_limit;
    IFEND;

  PROCEND expand_kql;
?? OLDTITLE ??
?? NEWTITLE := 'find_application_name', EJECT ??

{ PURPOSE:
{   The purpose of this request is to find the specified application_name in the application table
{ and return with the application index.  If there is no application registered with this name
{ specified the value jmc$unassigned_qfile_index is returned.
{
{ DESIGN:
{   Starting with the index of the last application assigned, search backwards through the chain until
{ the application_name is found or there are no more applications to search.
{
{ NOTES:
{   The Known Qfile List (KQL) MUST be locked when this request is made.

  PROCEDURE find_application_name
    (    application_name: ost$name;
     VAR application_index: jmt$qfile_application_index);

    application_index := jmv$last_used_application_index;

    WHILE (jmv$known_qfile_list.application_table [application_index].application_name <>
          application_name) AND (application_index <> jmc$unassigned_qfile_index) DO
      application_index := application_index - 1;
    WHILEND;
  PROCEND find_application_name;
?? OLDTITLE ??
?? NEWTITLE := 'find_qfile_by_application', EJECT ??

{ PURPOSE:
{   The purpose of this request is to find a file assigned to a particular application by using its
{ system_file_name.
{
{ DESIGN:
{   Search the Known Qfile List (KQL) for the file that has been assigned to the application specified.
{ If the entry in the KQL is not found, return a kql_index of jmc$kql_undefined_index.
{
{ NOTES:
{   The KQL must be locked when this request is issued.

  PROCEDURE find_qfile_by_application
    (    system_file_name: jmt$system_supplied_name;
         application_index: jmt$qfile_application_index;
     VAR kql_index: jmt$kql_index);

    VAR
      application_state: jmt$kql_application_state;

  /search_for_the_specified_file/
    FOR application_state := SUCC (jmc$kql_application_unused) TO UPPERVALUE (application_state) DO
      kql_index := jmv$known_qfile_list.application_table [application_index].state_data [application_state].
            first_entry;
      WHILE kql_index <> jmc$kql_undefined_index DO
        IF jmv$kql_p^ [kql_index].system_file_name = system_file_name THEN
          EXIT /search_for_the_specified_file/; {----->
        ELSE
          kql_index := jmv$kql_p^ [kql_index].application_forward_link;
        IFEND;
      WHILEND;
    FOREND /search_for_the_specified_file/;
  PROCEND find_qfile_by_application;
?? OLDTITLE ??
?? NEWTITLE := 'kql_search', EJECT ??

{ PURPOSE:
{   The purpose of this request is to search the Known Qfile List (KQL) for the specified system_file_name
{ and returns the file's kql_index.  A kql_index of jmc$kql_undefined_index is returned if the queue file
{ is not found.
{
{ NOTES:
{   The KQL must be locked when this request is issued.

  PROCEDURE kql_search
    (    system_file_name: jmt$system_supplied_name;
         entry_kind_set: jmt$kql_entry_kind_set;
     VAR kql_index: jmt$kql_index);

    VAR
      kql_entry_kind: jmt$kql_entry_kind;

    kql_index := jmc$kql_undefined_index;

  /kql_search_each_entry_kind/
    FOR kql_entry_kind := SUCC (LOWERVALUE (kql_entry_kind)) TO UPPERVALUE (kql_entry_kind) DO
      IF kql_entry_kind IN entry_kind_set THEN
        kql_index := jmv$known_qfile_list.state_data [kql_entry_kind].first_entry;

        WHILE kql_index <> jmc$kql_undefined_index DO
          IF (jmv$kql_p^ [kql_index].system_file_name = system_file_name) THEN
            EXIT /kql_search_each_entry_kind/; {----->
          ELSE
            kql_index := jmv$kql_p^ [kql_index].forward_link;
          IFEND;
        WHILEND;
      IFEND;
    FOREND /kql_search_each_entry_kind/;

  PROCEND kql_search;
?? OLDTITLE ??
?? NEWTITLE := 'notify_qfile_application', EJECT ??

{ PURPOSE:
{   The purpose of this request is to ready a queue file application's control task.
{
{ NOTES:
{   The Known Qfile List (KQL) should be locked when this request is issued in order to ensure that
{ the global_task_id in the KQL's application table is valid.  If it isn't, the results will be to
{ cause a task to become ready before its scheduled time.  This is not generally a problem.
{ With this in mind, it is okay to make this request without the KQL locked, but it is preferred to
{ have the structure locked.

  PROCEDURE notify_qfile_application
    (    application_index: jmt$qfile_application_index);

    VAR
      ignore_status: ost$status;

    IF application_index <> jmc$unassigned_qfile_index THEN
      pmp$ready_task (jmv$known_qfile_list.application_table [application_index].global_task_id,
            ignore_status);
    IFEND;
  PROCEND notify_qfile_application;
?? OLDTITLE ??
?? NEWTITLE := 'relink_kql_application', EJECT ??

{ PURPOSE:
{   The purpose of this request is to relink a Known Qfile List (KQL) entry from one application state
{ thread to another.
{
{ DESIGN:
{   Upon entry to the procedure, the KQL entry contains the application_name and application_state that
{ defines the application thread that the entry belongs to.  The entry is removed from this thread and
{ added to the thread described by the application_name and destination_state supplied on the request.
{
{ NOTES:
{   The KQL must be locked when this request is issued.

  PROCEDURE relink_kql_application
    (    kql_index: jmt$kql_index;
         destination_application_index: jmt$qfile_application_index;
         destination_state: jmt$kql_application_state);

    VAR
      source_state: jmt$kql_application_state,
      source_application_index: jmt$qfile_application_index;

    find_application_name (jmv$kql_p^ [kql_index].application_name, source_application_index);
    source_state := jmv$kql_p^ [kql_index].application_state;

    CASE source_state OF
    = jmc$kql_application_unused =
      ;

    ELSE

{ Delete the entry from its application thread.

      IF jmv$kql_p^ [kql_index].application_reverse_link = jmc$kql_undefined_index THEN
        jmv$known_qfile_list.application_table [source_application_index].state_data [source_state].
              first_entry := jmv$kql_p^ [kql_index].application_forward_link;
      ELSE
        jmv$kql_p^ [jmv$kql_p^ [kql_index].application_reverse_link].
              application_forward_link := jmv$kql_p^ [kql_index].application_forward_link;
      IFEND;

      IF jmv$kql_p^ [kql_index].application_forward_link = jmc$kql_undefined_index THEN
        jmv$known_qfile_list.application_table [source_application_index].state_data [source_state].
              last_entry := jmv$kql_p^ [kql_index].application_reverse_link;
      ELSE
        jmv$kql_p^ [jmv$kql_p^ [kql_index].application_forward_link].
              application_reverse_link := jmv$kql_p^ [kql_index].application_reverse_link;
      IFEND;

{ Decrement the count for the application/state thread

      jmv$known_qfile_list.application_table [source_application_index].state_data [source_state].
            number_of_entries := jmv$known_qfile_list.application_table [source_application_index].
            state_data [source_state].number_of_entries - 1;
    CASEND;


    CASE destination_state OF

    = jmc$kql_application_unused =

{ Make the entry unused.

      jmv$kql_p^ [kql_index].application_reverse_link := jmc$kql_undefined_index;
      jmv$kql_p^ [kql_index].application_forward_link := jmc$kql_undefined_index;

    ELSE

{ Insert the entry at the end of the destination thread.

      IF jmv$known_qfile_list.application_table [destination_application_index].
            state_data [destination_state].last_entry = jmc$kql_undefined_index THEN
        jmv$kql_p^ [kql_index].application_reverse_link := jmc$kql_undefined_index;
        jmv$kql_p^ [kql_index].application_forward_link := jmc$kql_undefined_index;
        jmv$known_qfile_list.application_table [destination_application_index].state_data [destination_state].
              first_entry := kql_index;
        jmv$known_qfile_list.application_table [destination_application_index].state_data [destination_state].
              last_entry := kql_index;
      ELSE
        jmv$kql_p^ [kql_index].application_reverse_link := jmv$known_qfile_list.
              application_table [destination_application_index].state_data [destination_state].last_entry;
        jmv$kql_p^ [jmv$known_qfile_list.application_table [destination_application_index].
              state_data [destination_state].last_entry].application_forward_link := kql_index;
        jmv$kql_p^ [kql_index].application_forward_link := jmc$kql_undefined_index;
        jmv$known_qfile_list.application_table [destination_application_index].state_data [destination_state].
              last_entry := kql_index;
      IFEND;

{ Increment the count of the number of entries in the state

      jmv$known_qfile_list.application_table [destination_application_index].state_data [destination_state].
            number_of_entries := jmv$known_qfile_list.application_table [destination_application_index].
            state_data [destination_state].number_of_entries + 1;
    CASEND;

    jmv$kql_p^ [kql_index].application_state := destination_state;

  PROCEND relink_kql_application;
?? OLDTITLE ??
?? NEWTITLE := 'relink_kql_entry', EJECT ??

{ PURPOSE:
{   The purpose of this request is to relink a Known Qfile List (KQL) entry from one entry state chain to
{ another.
{
{ DESIGN:
{   The entry state in the KQL entry is used to determine the state thread that the entry is currently in.
{ The entry state chain is maintained as a doubly linked list so it can be searched backwards.
{
{ NOTES:
{   The KQL must be locked when this request is issued.

  PROCEDURE relink_kql_entry
    (    kql_index: jmt$kql_index;
         destination_entry_kind: jmt$kql_entry_kind);

    VAR
      source_entry_kind: jmt$kql_entry_kind,
      insertion_index: jmt$kql_index;

    source_entry_kind := jmv$kql_p^ [kql_index].entry_kind;

{ Delete the entry from its thread

    IF jmv$kql_p^ [kql_index].reverse_link = jmc$kql_undefined_index THEN
      jmv$known_qfile_list.state_data [source_entry_kind].first_entry := jmv$kql_p^ [kql_index].forward_link;
    ELSE
      jmv$kql_p^ [jmv$kql_p^ [kql_index].reverse_link].forward_link := jmv$kql_p^ [kql_index].forward_link;
    IFEND;

    IF jmv$kql_p^ [kql_index].forward_link = jmc$kql_undefined_index THEN
      jmv$known_qfile_list.state_data [source_entry_kind].last_entry := jmv$kql_p^ [kql_index].reverse_link;
    ELSE
      jmv$kql_p^ [jmv$kql_p^ [kql_index].forward_link].reverse_link := jmv$kql_p^ [kql_index].reverse_link;
    IFEND;

{ Decrement the count of the number of entries in the state

    jmv$known_qfile_list.state_data [source_entry_kind].number_of_entries := jmv$known_qfile_list.
          state_data [source_entry_kind].number_of_entries - 1;

{ Add the entry to the destination thread

    CASE destination_entry_kind OF

    = jmc$kql_unused_entry =

{ First, zero out the entry so "clag" doesn't show up

      pmp$zero_out_table (^jmv$kql_p^ [kql_index], #SIZE (jmv$kql_p^ [kql_index]));

{ Insert in the "unused" thread.  Trace backwards to find the next previous unused entry to insert after.

      insertion_index := kql_index - 1;
      WHILE (insertion_index <> jmc$kql_undefined_index) AND
            (jmv$kql_p^ [insertion_index].entry_kind <> jmc$kql_unused_entry) DO
        insertion_index := insertion_index - 1;
      WHILEND;
      IF insertion_index = jmc$kql_undefined_index THEN

{ Insert at the "head" of the unused thread

        jmv$kql_p^ [kql_index].reverse_link := jmc$kql_undefined_index;
        jmv$kql_p^ [kql_index].forward_link := jmv$known_qfile_list.state_data [jmc$kql_unused_entry].
              first_entry;
        jmv$known_qfile_list.state_data [jmc$kql_unused_entry].first_entry := kql_index;
        IF jmv$kql_p^ [kql_index].forward_link <> jmc$kql_undefined_index THEN
          jmv$kql_p^ [jmv$kql_p^ [kql_index].forward_link].reverse_link := kql_index;
        IFEND;
      ELSE

{ Insert in the unused thread.

        jmv$kql_p^ [kql_index].reverse_link := insertion_index;
        jmv$kql_p^ [kql_index].forward_link := jmv$kql_p^ [insertion_index].forward_link;
        jmv$kql_p^ [jmv$kql_p^ [kql_index].forward_link].reverse_link := kql_index;
        jmv$kql_p^ [insertion_index].forward_link := kql_index;
      IFEND;

    ELSE

{ Insert at the end of the destination thread.

      IF jmv$known_qfile_list.state_data [destination_entry_kind].last_entry = jmc$kql_undefined_index THEN
        jmv$kql_p^ [kql_index].reverse_link := jmc$kql_undefined_index;
        jmv$kql_p^ [kql_index].forward_link := jmc$kql_undefined_index;
        jmv$known_qfile_list.state_data [destination_entry_kind].first_entry := kql_index;
        jmv$known_qfile_list.state_data [destination_entry_kind].last_entry := kql_index;
      ELSE
        jmv$kql_p^ [kql_index].reverse_link := jmv$known_qfile_list.state_data [destination_entry_kind].
              last_entry;
        jmv$kql_p^ [jmv$known_qfile_list.state_data [destination_entry_kind].last_entry].forward_link :=
              kql_index;
        jmv$kql_p^ [kql_index].forward_link := jmc$kql_undefined_index;
        jmv$known_qfile_list.state_data [destination_entry_kind].last_entry := kql_index;
      IFEND;
    CASEND;

{ Increment the count for the destination thread.

    jmv$known_qfile_list.state_data [destination_entry_kind].number_of_entries :=
          jmv$known_qfile_list.state_data [destination_entry_kind].number_of_entries + 1;

    jmv$kql_p^ [kql_index].entry_kind := destination_entry_kind;

  PROCEND relink_kql_entry;
?? OLDTITLE ??
?? NEWTITLE := 'validate_application_access', EJECT ??

{ PURPOSE:
{    This request will validate that the executing task is the legitimate user of the application_name
{  specified.  The index into the application table for the specified application_name is returned.
{
{ NOTES:
{   The Known Qfile List (KQL) must be locked when this request is issued.

  PROCEDURE validate_application_access
    (    application_name: ost$name;
     VAR application_index: jmt$qfile_application_index;
     VAR status: ost$status);

    VAR
      global_task_id: ost$global_task_id;

    status.normal := TRUE;
    find_application_name (application_name, application_index);
    IF application_index = jmc$unassigned_qfile_index THEN
      osp$set_status_abnormal (jmc$job_management_id, jme$application_name_incorrect, application_name,
            status);
    ELSE
      pmp$get_executing_task_gtid (global_task_id);
      IF global_task_id <> jmv$known_qfile_list.application_table [application_index].global_task_id THEN
        osp$set_status_abnormal (jmc$job_management_id, jme$qfile_appl_not_permitted, application_name,
              status);
      IFEND;
    IFEND;
  PROCEND validate_application_access;
?? OLDTITLE ??
?? NEWTITLE := '[XDCL, #GATE] qfp$acquire_modified_qfile', EJECT ??
*copy qfh$acquire_modified_qfile

{ DESIGN:
{ Lock the KQL.
{ Determine if the application is valid.
{ IF valid THEN
{   IF a modified entry exists, THEN
{     Get the system_file_name of the entry.
{     Link application (AN) as ACQUIRED
{   ELSE return abnormal status jme$generic_queue_is_empty
{   IFEND
{ IFEND
{ Unlock the KQL.

  PROCEDURE [XDCL, #GATE] qfp$acquire_modified_qfile
    (    application_name: ost$name;
     VAR system_file_name: jmt$system_supplied_name;
     VAR status: ost$status);

    VAR
      application_index: jmt$qfile_application_index,
      kql_index: jmt$kql_index;

    status.normal := TRUE;
    osp$set_mainframe_sig_lock (qfv$kql_lock);

    validate_application_access (application_name, application_index, status);
    IF status.normal THEN
      kql_index := jmv$known_qfile_list.application_table [application_index].
            state_data [jmc$kql_application_modified].first_entry;
      IF kql_index <> jmc$kql_undefined_index THEN
        system_file_name := jmv$kql_p^ [kql_index].system_file_name;
        relink_kql_application (kql_index, application_index, jmc$kql_application_acquired);
      ELSE
        osp$set_status_condition (jme$generic_queue_is_empty, status);
      IFEND;
    IFEND;
    osp$clear_mainframe_sig_lock (qfv$kql_lock);

  PROCEND qfp$acquire_modified_qfile;
?? OLDTITLE ??
?? NEWTITLE := '[XDCL, #GATE] qfp$acquire_new_qfile', EJECT ??
*copyc qfh$acquire_new_qfile

{ DESIGN:
{ Lock the KQL.
{ Determine if the application is valid.
{ IF valid THEN
{   IF a new entry exists, THEN
{     Get the system_file_name of the entry.
{     Link application (AN) as ACQUIRED
{   ELSE return abnormal status jme$generic_queue_is_empty
{   IFEND
{ IFEND
{ Unlock the KQL.

  PROCEDURE [XDCL, #GATE] qfp$acquire_new_qfile
    (    application_name: ost$name;
     VAR system_file_name: jmt$system_supplied_name;
     VAR status: ost$status);


    VAR
      application_index: jmt$qfile_application_index,
      kql_index: jmt$kql_index;

    status.normal := TRUE;
    osp$set_mainframe_sig_lock (qfv$kql_lock);

    validate_application_access (application_name, application_index, status);
    IF status.normal THEN
      kql_index := jmv$known_qfile_list.application_table [application_index].
            state_data [jmc$kql_application_new].first_entry;
      IF kql_index <> jmc$kql_undefined_index THEN
        system_file_name := jmv$kql_p^ [kql_index].system_file_name;
        relink_kql_application (kql_index, application_index, jmc$kql_application_acquired);
      ELSE
        osp$set_status_condition (jme$generic_queue_is_empty, status);
      IFEND;
    IFEND;
    osp$clear_mainframe_sig_lock (qfv$kql_lock);

  PROCEND qfp$acquire_new_qfile;
?? OLDTITLE ??
?? NEWTITLE := '[XDCL, #GATE] qfp$change_qfile_attributes', EJECT ??
*copyc qfh$change_qfile_attributes

{ DESIGN:
{ Lock the KQL.
{ Find the requested entry in the KQL.
{ IF the entry exists, THEN
{   Reset application name.
{   IF KQL COMPLETED THEN
{     application_name := next_application_name
{     IF purge_delay < purge_processed_qfile_time THEN
{       purge_processed_qfile_time := purge_delay
{     IFEND
{   ELSE
{     IF deferred_file AND NOT (KQL application > NEW) THEN
{       IF earliest_run_time < ready_deferred_qfile_time THEN
{         ready_deferred_qfile_time := earliest_run_time
{       IFEND
{       Link application (NAN) as UNUSED
{       application_name := next_application_name
{       Link KQL as DEFERRED
{     ELSE
{       IF KQL application > NEW THEN
{         IF (application_name = next_application_name) AND NOT deferred_file THEN
{           Link application (AN) as MODIFIED
{         ELSE
{           Link application (AN) as TERMINATED
{         IFEND
{       ELSE
{         Link KQL as QUEUED
{         Link application (NAN) as NEW
{         application_name := next_application_name
{        IFEND
{        notify the correct application
{     IFEND
{     IF latest_run_time < purge_expired_qfile_time THEN
{       purge_expired_qfile_time := latest_run_time
{     IFEND
{   IFEND
{ ELSE return abnormal status  jme$name_not_found
{ Unlock the KQL.

{ NOTES:
{   Only deferred, queued or completed files can have their attributes changed.

  PROCEDURE [XDCL, #GATE] qfp$change_qfile_attributes
    (    system_label: jmt$qfile_system_label;
         earliest_clock_time_to_process: jmt$clock_time;
         latest_clock_time_to_process: jmt$clock_time;
         purge_delay_clock_time: jmt$clock_time;
         current_clock_time: jmt$clock_time;
         rerun_disposition: jmt$rerun_disposition;
     VAR delete_queue_file: boolean;
     VAR status: ost$status);


    VAR
      deferred_file: boolean,
      entry_kind: jmt$kql_entry_kind,
      kql_index: jmt$kql_index,
      qfile_application_index: jmt$qfile_application_index,
      time_deferred_file: boolean;

    status.normal := TRUE;
    delete_queue_file := FALSE;
    osp$set_mainframe_sig_lock (qfv$kql_lock);

  /find_entry_in_kql/
    FOR entry_kind := LOWERVALUE (entry_kind) TO UPPERVALUE (entry_kind) DO
      IF entry_kind IN $jmt$kql_entry_kind_set [jmc$kql_deferred_entry, jmc$kql_queued_entry,
            jmc$kql_completed_entry] THEN
        kql_index := jmv$known_qfile_list.state_data [entry_kind].first_entry;
        WHILE (kql_index <> jmc$kql_undefined_index) DO
          IF (jmv$kql_p^ [kql_index].system_file_name = system_label.system_file_name) THEN
            EXIT /find_entry_in_kql/; {----->
          ELSE
            kql_index := jmv$kql_p^ [kql_index].forward_link;
          IFEND;
        WHILEND;
      IFEND;
    FOREND /find_entry_in_kql/;

    IF kql_index <> jmc$kql_undefined_index THEN
      jmv$kql_p^ [kql_index].next_application_name := system_label.application_name;
      jmv$kql_p^ [kql_index].earliest_clock_time_to_process := earliest_clock_time_to_process;
      jmv$kql_p^ [kql_index].latest_clock_time_to_process := latest_clock_time_to_process;
      jmv$kql_p^ [kql_index].purge_delay := purge_delay_clock_time;
      jmv$kql_p^ [kql_index].deferred_by_application := system_label.deferred_by_application;
      jmv$kql_p^ [kql_index].deferred_by_operator := system_label.deferred_by_operator;
      jmv$kql_p^ [kql_index].deferred_by_user := system_label.deferred_by_user;

      time_deferred_file := current_clock_time < earliest_clock_time_to_process;
      deferred_file := time_deferred_file OR f$deferred (jmv$kql_p^ [kql_index]);

{ If the application state is not NEW, then the file has been acquired by the application
{ In this case, if the file is deferred or the application name has changed, mark
{ the file as terminated for the application.  When the application releases the file
{ it will be placed in the proper state.

      IF (jmv$kql_p^ [kql_index].entry_kind = jmc$kql_completed_entry) AND
            (rerun_disposition = jmc$rr_no_change) THEN
        jmv$kql_p^ [kql_index].application_name := jmv$kql_p^ [kql_index].next_application_name;
        IF purge_delay_clock_time < jmv$purge_processed_qfile_time THEN
          jmv$purge_processed_qfile_time := purge_delay_clock_time;
        IFEND;
      ELSEIF (jmv$kql_p^ [kql_index].entry_kind = jmc$kql_completed_entry) AND
            (rerun_disposition = jmc$rr_discard_file) THEN
        find_application_name (jmv$kql_p^ [kql_index].application_name, qfile_application_index);
        relink_kql_application (kql_index, qfile_application_index, jmc$kql_application_unused);
        relink_kql_entry (kql_index, jmc$kql_unused_entry);
        delete_queue_file := TRUE;
      ELSE

{ The file was not processed or it was processed and rerun was requested.

        IF deferred_file AND (jmv$kql_p^ [kql_index].application_state <= jmc$kql_application_new) THEN
          IF time_deferred_file AND (earliest_clock_time_to_process < jmv$ready_deferred_qfile_time) THEN
            jmv$ready_deferred_qfile_time := earliest_clock_time_to_process;
          IFEND;
          find_application_name (jmv$kql_p^ [kql_index].next_application_name, qfile_application_index);
          relink_kql_application (kql_index, qfile_application_index, jmc$kql_application_unused);
          jmv$kql_p^ [kql_index].application_name := jmv$kql_p^ [kql_index].next_application_name;
          relink_kql_entry (kql_index, jmc$kql_deferred_entry);
        ELSE
          IF jmv$kql_p^ [kql_index].application_state > jmc$kql_application_new THEN
            find_application_name (jmv$kql_p^ [kql_index].application_name, qfile_application_index);
            IF (NOT deferred_file) AND (jmv$kql_p^ [kql_index].application_name =
                  jmv$kql_p^ [kql_index].next_application_name) THEN
              relink_kql_application (kql_index, qfile_application_index, jmc$kql_application_modified);
            ELSE
              relink_kql_application (kql_index, qfile_application_index, jmc$kql_application_terminated);
            IFEND;
          ELSE
            find_application_name (jmv$kql_p^ [kql_index].next_application_name, qfile_application_index);
            relink_kql_application (kql_index, qfile_application_index, jmc$kql_application_new);
            jmv$kql_p^ [kql_index].application_name := jmv$kql_p^ [kql_index].next_application_name;
            relink_kql_entry (kql_index, jmc$kql_queued_entry);
          IFEND;
          notify_qfile_application (qfile_application_index);
        IFEND;
        IF latest_clock_time_to_process < jmv$purge_expired_qfile_time THEN
          jmv$purge_expired_qfile_time := latest_clock_time_to_process;
        IFEND;
      IFEND;
    ELSE
      osp$set_status_abnormal (jmc$job_management_id, jme$name_not_found, system_label.system_file_name,
            status);
    IFEND;

    osp$clear_mainframe_sig_lock (qfv$kql_lock);
  PROCEND qfp$change_qfile_attributes;
?? OLDTITLE ??
?? NEWTITLE := '[XDCL, #GATE] qfp$get_qfile_counts', EJECT ??

  PROCEDURE [XDCL, #GATE] qfp$get_qfile_counts
    (VAR qfile_counts: jmt$qfile_counts;
     VAR status: ost$status);

    status.normal := TRUE;

    osp$set_mainframe_sig_lock (qfv$kql_lock);

    qfile_counts.state_data [jmc$deferred_qfile] := jmv$known_qfile_list.state_data [jmc$kql_deferred_entry].
          number_of_entries;
    qfile_counts.state_data [jmc$queued_qfile] := jmv$known_qfile_list.state_data [jmc$kql_queued_entry].
          number_of_entries;
    qfile_counts.state_data [jmc$initiated_qfile] := jmv$known_qfile_list.
          state_data [jmc$kql_initiated_entry].number_of_entries;
    qfile_counts.state_data [jmc$terminated_qfile] := jmv$known_qfile_list.
          state_data [jmc$kql_terminated_entry].number_of_entries;
    qfile_counts.state_data [jmc$completed_qfile] := jmv$known_qfile_list.
          state_data [jmc$kql_completed_entry].number_of_entries;

    osp$clear_mainframe_sig_lock (qfv$kql_lock);

  PROCEND qfp$get_qfile_counts;
?? OLDTITLE ??
?? NEWTITLE := '[XDCL, #GATE] qfp$get_qfile_status', EJECT ??
*copy qfh$get_qfile_status

{ DESIGN:
{ Lock the KQL.
{ FOR each state DO
{   WHILE untested entries in the state exist DO
{     test entry against search criteria (options)
{     IF match THEN
{       add entry data to the result list (if it fits)
{     IFEND
{   WHILEND
{ FOREND
{ Unlock the KQL.

  PROCEDURE [XDCL, #GATE] qfp$get_qfile_status
    (    user_identification: ost$user_identification;
         privileged_job: boolean;
         status_options_p: ^jmt$qfile_status_options;
         status_results_keys_p: ^jmt$results_keys;
     VAR status_work_area_p: ^jmt$work_area;
     VAR status_results_p: ^jmt$qfile_status_results;
     VAR number_of_qfiles_found: jmt$qfile_status_count);

    VAR
      boolean_value_p: ^boolean,
      ignore_status: ost$status,
      kql_entry_kind: jmt$kql_entry_kind,
      kql_index: jmt$kql_index,
      mainframe_id_p: ^pmt$mainframe_id,
      name_value_p: ^ost$name,
      option_index: integer,
      qfile_index: integer,
      qfile_state: jmt$qfile_state,
      qfile_state_p: ^jmt$qfile_state,
      qfile_state_set: jmt$qfile_state_set,
      qualified_entry_found: boolean,
      result_index: integer,
      system_file_name_p: ^jmt$system_supplied_name;

?? NEWTITLE := 'handle_core_condition', EJECT ??

    PROCEDURE handle_core_condition
      (    monitor_fault: ost$monitor_fault;
           minimum_save_area_p: ^ost$minimum_save_area;
       VAR continue: syt$continue_option);

      VAR
        lock_status: ost$signature_lock_status;

      osp$test_sig_lock (qfv$kql_lock, lock_status);
      IF lock_status = osc$sls_locked_by_current_task THEN
        osp$clear_mainframe_sig_lock (qfv$kql_lock);
      IFEND;
      syp$continue_to_cause (monitor_fault, minimum_save_area_p, syc$condition_processed, continue);
      EXIT qfp$get_qfile_status; {----->
    PROCEND handle_core_condition;
?? OLDTITLE ??
?? EJECT ??
    syp$establish_condition_handler (^handle_core_condition);
    number_of_qfiles_found := 0;

    qfile_state_set := -$jmt$qfile_state_set [];
    IF status_options_p <> NIL THEN
      FOR option_index := 1 TO UPPERBOUND (status_options_p^) DO
        IF status_options_p^ [option_index].key = jmc$qfile_state_set THEN
          qfile_state_set := status_options_p^ [option_index].qfile_state_set;
        IFEND;
      FOREND;
    IFEND;

    osp$set_mainframe_sig_lock (qfv$kql_lock);

  /search_each_entry_kind/
    FOR qfile_state := LOWERVALUE (qfile_state) TO UPPERVALUE (qfile_state) DO
      IF qfile_state IN qfile_state_set THEN
        kql_entry_kind := convert_state_to_entry_kind [qfile_state];
        kql_index := jmv$known_qfile_list.state_data [kql_entry_kind].first_entry;

      /search_each_entry/
        WHILE kql_index <> jmc$kql_undefined_index DO
          IF (jmv$kql_p^ [kql_index].login_user_identification = user_identification) OR
                (jmv$kql_p^ [kql_index].qfile_controller = user_identification) OR privileged_job THEN

            qualified_entry_found := TRUE;
            IF status_options_p <> NIL THEN

            /status_option_check/
              FOR option_index := 1 TO UPPERBOUND (status_options_p^) DO
                CASE status_options_p^ [option_index].key OF
                = jmc$application_name =
                  IF status_options_p^ [option_index].application_name <>
                        jmv$kql_p^ [kql_index].application_name THEN
                    qualified_entry_found := FALSE;
                    EXIT /status_option_check/; {----->
                  IFEND;

                = jmc$control_family =
                  IF status_options_p^ [option_index].control_family <>
                        jmv$kql_p^ [kql_index].qfile_controller.family THEN
                    qualified_entry_found := FALSE;
                    EXIT /status_option_check/; {----->
                  IFEND;

                = jmc$control_user =
                  IF status_options_p^ [option_index].control_user <>
                        jmv$kql_p^ [kql_index].qfile_controller.user THEN
                    qualified_entry_found := FALSE;
                    EXIT /status_option_check/; {----->
                  IFEND;

                = jmc$login_family =
                  IF status_options_p^ [option_index].login_family <>
                        jmv$kql_p^ [kql_index].login_user_identification.family THEN
                    qualified_entry_found := FALSE;
                    EXIT /status_option_check/; {----->
                  IFEND;

                = jmc$login_user =
                  IF status_options_p^ [option_index].login_user <>
                        jmv$kql_p^ [kql_index].login_user_identification.user THEN
                    qualified_entry_found := FALSE;
                    EXIT /status_option_check/; {----->
                  IFEND;

                = jmc$null_attribute =
                  ;

                = jmc$qfile_state_set =
                  ;

                = jmc$system_supplied_name_list =
                  IF status_options_p^ [option_index].system_supplied_name_list <> NIL THEN
                    qualified_entry_found := FALSE;

                  /search_for_qfile_names/
                    FOR qfile_index := 1 TO UPPERBOUND (status_options_p^ [option_index].
                          system_supplied_name_list^) DO
                      IF status_options_p^ [option_index].system_supplied_name_list^ [qfile_index] =
                            jmv$kql_p^ [kql_index].system_file_name THEN
                        qualified_entry_found := TRUE;
                        EXIT /search_for_qfile_names/; {----->
                      IFEND;
                    FOREND /search_for_qfile_names/;
                    IF NOT qualified_entry_found THEN
                      EXIT /status_option_check/; {----->
                    IFEND;
                  IFEND;
                ELSE
                CASEND;
              FOREND /status_option_check/;
            IFEND;

            IF qualified_entry_found THEN
              number_of_qfiles_found := number_of_qfiles_found + 1;
              IF (status_work_area_p <> NIL) AND (status_results_keys_p <> NIL) THEN

              /fill_in_each_result_field/
                FOR result_index := 1 TO UPPERBOUND (status_results_keys_p^) DO
                  CASE status_results_keys_p^ [result_index] OF

                  = jmc$application_name =
                    NEXT name_value_p IN status_work_area_p;
                    IF name_value_p = NIL THEN
                      EXIT /fill_in_each_result_field/; {----->
                    IFEND;
                    name_value_p^ := jmv$kql_p^ [kql_index].application_name;

                  = jmc$client_mainframe_id =
                    NEXT mainframe_id_p IN status_work_area_p;
                    IF mainframe_id_p = NIL THEN
                      EXIT /fill_in_each_result_field/; {----->
                    IFEND;
                    pmp$get_mainframe_id (mainframe_id_p^, ignore_status);

                  = jmc$control_family =
                    NEXT name_value_p IN status_work_area_p;
                    IF name_value_p = NIL THEN
                      EXIT /fill_in_each_result_field/; {----->
                    IFEND;
                    name_value_p^ := jmv$kql_p^ [kql_index].qfile_controller.family;

                  = jmc$control_user =
                    NEXT name_value_p IN status_work_area_p;
                    IF name_value_p = NIL THEN
                      EXIT /fill_in_each_result_field/; {----->
                    IFEND;
                    name_value_p^ := jmv$kql_p^ [kql_index].qfile_controller.user;

                  = jmc$deferred_by_application =
                    NEXT boolean_value_p IN status_work_area_p;
                    IF boolean_value_p = NIL THEN
                      EXIT /fill_in_each_result_field/; {----->
                    IFEND;
                    boolean_value_p^ := jmv$kql_p^ [kql_index].deferred_by_application;

                  = jmc$deferred_by_operator =
                    NEXT boolean_value_p IN status_work_area_p;
                    IF boolean_value_p = NIL THEN
                      EXIT /fill_in_each_result_field/; {----->
                    IFEND;
                    boolean_value_p^ := jmv$kql_p^ [kql_index].deferred_by_operator;

                  = jmc$deferred_by_user =
                    NEXT boolean_value_p IN status_work_area_p;
                    IF boolean_value_p = NIL THEN
                      EXIT /fill_in_each_result_field/; {----->
                    IFEND;
                    boolean_value_p^ := jmv$kql_p^ [kql_index].deferred_by_user;

                  = jmc$login_family =
                    NEXT name_value_p IN status_work_area_p;
                    IF name_value_p = NIL THEN
                      EXIT /fill_in_each_result_field/; {----->
                    IFEND;
                    name_value_p^ := jmv$kql_p^ [kql_index].login_user_identification.family;

                  = jmc$login_user =
                    NEXT name_value_p IN status_work_area_p;
                    IF name_value_p = NIL THEN
                      EXIT /fill_in_each_result_field/; {----->
                    IFEND;
                    name_value_p^ := jmv$kql_p^ [kql_index].login_user_identification.user;

                  = jmc$null_attribute =
                    ;

                  = jmc$qfile_state =
                    NEXT qfile_state_p IN status_work_area_p;
                    IF qfile_state_p = NIL THEN
                      EXIT /fill_in_each_result_field/; {----->
                    IFEND;
                    qfile_state_p^ := qfile_state;

                  = jmc$system_file_name =
                    NEXT system_file_name_p IN status_work_area_p;
                    IF system_file_name_p = NIL THEN
                      EXIT /fill_in_each_result_field/; {----->
                    IFEND;
                    system_file_name_p^ := jmv$kql_p^ [kql_index].system_file_name;

                  ELSE
                  CASEND;
                FOREND /fill_in_each_result_field/;
              IFEND;
            IFEND;
          IFEND;

          kql_index := jmv$kql_p^ [kql_index].forward_link;
        WHILEND /search_each_entry/;
      IFEND;
    FOREND /search_each_entry_kind/;

    osp$clear_mainframe_sig_lock (qfv$kql_lock);
    syp$disestablish_cond_handler;

  PROCEND qfp$get_qfile_status;
?? OLDTITLE ??
?? NEWTITLE := '[XDCL, #GATE] qfp$purge_expired_queue_file', EJECT ??
*copy qfh$purge_expired_queue_file

{ DESIGN:
{ Lock the KQL.
{ purge_expired_qfile_time := latest clock time
{ file found := false
{ FOR the KQL states of DEFERRED, QUEUED, and INITIATED DO
{   WHILE untested files in the state remain DO
{     IF latest_run_time < current_microsecond_clock THEN
{       IF KQL application > NEW THEN
{         IF KQL < INITIATED THEN
{          Link application (AN) as TERMINATED
{          Notify the correct application
{         IFEND
{         Link KQL as TERMINATED
{       ELSE
{         IF NOT file found THEN
{           file found := true
{           file to delete := system_file_name
{           Link application (AN) as UNUSED
{           Link KQL as UNUSED
{         ELSE
{           purge_expired_qfile_time := latest_run_time
{         IFEND
{       IFEND
{     ELSE
{       IF latest_run_time < purge_expired_qfile_time THEN
{         purge_expired_qfile_time := latest_run_time
{       IFEND
{     IFEND
{   WHILEND
{ FOREND
{ Unlock the KQL.

  PROCEDURE [XDCL, #GATE] qfp$purge_expired_queue_file
    (VAR system_file_name_to_delete: jmt$system_supplied_name);

    VAR
      current_clock_value: jmt$clock_time,
      entry_kind: jmt$kql_entry_kind,
      kql_index: jmt$kql_index,
      next_kql_index: jmt$kql_index,
      qfile_application_index: jmt$qfile_application_index;

    system_file_name_to_delete := '';
    current_clock_value := #FREE_RUNNING_CLOCK (0);
    osp$set_mainframe_sig_lock (qfv$kql_lock);

    jmv$purge_expired_qfile_time := jmc$latest_clock_time;

  /search_for_expired_files/
    FOR entry_kind := LOWERVALUE (entry_kind) TO UPPERVALUE (entry_kind) DO
      IF entry_kind IN $jmt$kql_entry_kind_set [jmc$kql_deferred_entry, jmc$kql_queued_entry,
            jmc$kql_initiated_entry] THEN
        kql_index := jmv$known_qfile_list.state_data [entry_kind].first_entry;
        WHILE kql_index <> jmc$kql_undefined_index DO
          next_kql_index := jmv$kql_p^ [kql_index].forward_link;
          IF jmv$kql_p^ [kql_index].latest_clock_time_to_process < current_clock_value THEN
            IF jmv$kql_p^ [kql_index].application_state > jmc$kql_application_new THEN
              IF entry_kind < jmc$kql_initiated_entry THEN
                find_application_name (jmv$kql_p^ [kql_index].application_name, qfile_application_index);
                relink_kql_application (kql_index, qfile_application_index, jmc$kql_application_terminated);
                notify_qfile_application (qfile_application_index);
              IFEND;
              relink_kql_entry (kql_index, jmc$kql_terminated_entry);
            ELSE
              IF system_file_name_to_delete = '' THEN
                system_file_name_to_delete := jmv$kql_p^ [kql_index].system_file_name;
                find_application_name (jmv$kql_p^ [kql_index].application_name, qfile_application_index);
                relink_kql_application (kql_index, qfile_application_index, jmc$kql_application_unused);
                relink_kql_entry (kql_index, jmc$kql_unused_entry);
              ELSE
                jmv$purge_expired_qfile_time := jmv$kql_p^ [kql_index].latest_clock_time_to_process;
                EXIT /search_for_expired_files/; {----->
              IFEND;
            IFEND;
          ELSE
            IF jmv$kql_p^ [kql_index].latest_clock_time_to_process < jmv$purge_expired_qfile_time THEN
              jmv$purge_expired_qfile_time := jmv$kql_p^ [kql_index].latest_clock_time_to_process;
            IFEND;
          IFEND;
          kql_index := next_kql_index;
        WHILEND;
      IFEND;
    FOREND /search_for_expired_files/;
    osp$clear_mainframe_sig_lock (qfv$kql_lock);

  PROCEND qfp$purge_expired_queue_file;

?? OLDTITLE ??
?? NEWTITLE := '[XDCL, #GATE] qfp$purge_processed_queue_file', EJECT ??
*copy qfh$purge_processed_queue_file

{ DESIGN:
{ Lock the KQL.
{ purge_processed_qfile_time := latest clock time
{ file found := false
{ WHILE untested files in the COMPLETED state remain DO
{   IF purge_delay < current_microsecond_clock THEN
{     IF NOT file found THEN
{       Link KQL as UNUSED
{       file found := true
{       file_to_delete := system_file_name
{     ELSE
{       purge_processed_qfile_time := purge_delay
{     IFEND
{   ELSE
{     IF purge_delay < purge_processed_qfile_time THEN
{       purge_processed_qfile_time := purge_delay
{     IFEND
{   IFEND
{ WHILEND
{ Unlock the KQL.

  PROCEDURE [XDCL, #GATE] qfp$purge_processed_queue_file
    (VAR system_file_name_to_delete: jmt$system_supplied_name);

    VAR
      current_clock_value: jmt$clock_time,
      kql_index: jmt$kql_index,
      next_kql_index: jmt$kql_index,
      qfile_application_index: jmt$qfile_application_index;

    system_file_name_to_delete := '';
    current_clock_value := #FREE_RUNNING_CLOCK (0);
    osp$set_mainframe_sig_lock (qfv$kql_lock);

    jmv$purge_processed_qfile_time := jmc$latest_clock_time;

    kql_index := jmv$known_qfile_list.state_data [jmc$kql_completed_entry].first_entry;

  /search_for_processed_files/
    WHILE kql_index <> jmc$kql_undefined_index DO
      next_kql_index := jmv$kql_p^ [kql_index].forward_link;
      IF jmv$kql_p^ [kql_index].purge_delay < current_clock_value THEN
        IF system_file_name_to_delete = '' THEN
          system_file_name_to_delete := jmv$kql_p^ [kql_index].system_file_name;
          relink_kql_entry (kql_index, jmc$kql_unused_entry);
        ELSE
          jmv$purge_processed_qfile_time := jmv$kql_p^ [kql_index].purge_delay;
          EXIT /search_for_processed_files/; {----->
        IFEND;
      ELSE
        IF jmv$kql_p^ [kql_index].purge_delay < jmv$purge_processed_qfile_time THEN
          jmv$purge_processed_qfile_time := jmv$kql_p^ [kql_index].purge_delay;
        IFEND;
      IFEND;
      kql_index := next_kql_index;
    WHILEND /search_for_processed_files/;
    osp$clear_mainframe_sig_lock (qfv$kql_lock);

  PROCEND qfp$purge_processed_queue_file;

?? OLDTITLE ??
?? NEWTITLE := '[XDCL, #GATE] qfp$ready_deferred_queue_file', EJECT ??
*copy qfh$ready_deferred_queue_file

{ DESIGN:
{ Lock the KQL.
{ ready_deferred_qfile_time := latest_clock_time
{ WHILE untested files in the DEFERRED state remain DO
{   IF NOT deferred_by_application THEN
{     IF earliest_run_time < current_microsecond_clock THEN
{       Link KQL as QUEUED
{       Link application (AN) as NEW
{       notify the correct application
{     ELSE
{       IF earliest_run_time < ready_deferred_qfile_time THEN
{         ready_deferred_qfile_time := earliest_run_time
{       IFEND
{     IFEND
{   IFEND
{ WHILEND
{ Unlock the KQL.

  PROCEDURE [XDCL, #GATE] qfp$ready_deferred_queue_file;


    VAR
      current_clock_time: jmt$clock_time,
      kql_index: jmt$kql_index,
      next_kql_index: jmt$kql_index,
      qfile_application_index: jmt$qfile_application_index;

    current_clock_time := #FREE_RUNNING_CLOCK (0);
    osp$set_mainframe_sig_lock (qfv$kql_lock);

    jmv$ready_deferred_qfile_time := jmc$latest_clock_time;
    kql_index := jmv$known_qfile_list.state_data [jmc$kql_deferred_entry].first_entry;
    WHILE kql_index <> jmc$kql_undefined_index DO
      next_kql_index := jmv$kql_p^ [kql_index].forward_link;
      IF NOT f$deferred (jmv$kql_p^ [kql_index]) THEN
        IF (jmv$kql_p^ [kql_index].earliest_clock_time_to_process <= current_clock_time) THEN
          relink_kql_entry (kql_index, jmc$kql_queued_entry);
          find_application_name (jmv$kql_p^ [kql_index].application_name, qfile_application_index);
          relink_kql_application (kql_index, qfile_application_index, jmc$kql_application_new);
          notify_qfile_application (qfile_application_index);
        ELSE
          IF jmv$kql_p^ [kql_index].earliest_clock_time_to_process < jmv$ready_deferred_qfile_time THEN
            jmv$ready_deferred_qfile_time := jmv$kql_p^ [kql_index].earliest_clock_time_to_process;
          IFEND;
        IFEND;
      IFEND;
      kql_index := next_kql_index;
    WHILEND;
    osp$clear_mainframe_sig_lock (qfv$kql_lock);

  PROCEND qfp$ready_deferred_queue_file;

?? OLDTITLE ??
?? NEWTITLE := '[XDCL, #GATE] qfp$rebuild_generic_queue', EJECT ??
*copy qfh$rebuild_generic_queue

{ DESIGN:
{ Lock the KQL.
{ IF there is no room in the generic queue THEN
{   expand_kql
{ IFEND
{ IF there's still no room in the generic queue THEN
{   RETURN abnormal status
{ ELSE
{   find an available KQL entry and initialize it
{   IF the file has been processed THEN
{     IF purge_delay < purge_processed_qfile_time THEN
{       purge_processed_qfile_time := purge_delay
{     IFEND
{     Link KQL as COMPLETED
{   ELSE
{     IF deferred THEN
{       IF earliest_run_time < ready_deferred_qfile_time THEN
{         ready_deferred_qfile_time := earliest_run_time
{       IFEND
{       Link KQL as DEFERRED
{     ELSE
{       Link KQL as QUEUED
{       Link application (AN) as NEW
{     IFEND
{     IF latest_run_time < purge_expired_qfile_time THEN
{       purge_expired_qfile_time := latest_run_time
{     IFEND
{   IFEND
{ IFEND
{ Unlock the KQL.
{ NOTES:
{   This is only used during deadstart.  The queue recovery process knows how many files are
{ queued on a NOS/VE system and it will always make the KQL large enough to contain them.

  PROCEDURE [XDCL, #GATE] qfp$rebuild_generic_queue
    (    system_label: jmt$qfile_system_label;
         earliest_clock_time_to_process: jmt$clock_time;
         latest_clock_time_to_process: jmt$clock_time;
         purge_delay_clock_time: jmt$clock_time;
         current_clock_time: jmt$clock_time;
     VAR status: ost$status);


    VAR
      application_index: jmt$qfile_application_index,
      kql_index: jmt$kql_index,
      time_deferred_file: boolean;

    status.normal := TRUE;

    osp$set_mainframe_sig_lock (qfv$kql_lock);

{ Make sure that the name is not already in the KQL.

    kql_search (system_label.system_file_name, -$jmt$kql_entry_kind_set [], kql_index);
    IF kql_index <> jmc$kql_undefined_index THEN
      osp$clear_mainframe_sig_lock (qfv$kql_lock);
      osp$set_status_abnormal (jmc$job_management_id, jme$duplicate_name, system_label.system_file_name,
            status);
      RETURN; {----->
    IFEND;

{ Make sure that there is room in the KQL.

    IF jmv$known_qfile_list.state_data [jmc$kql_unused_entry].first_entry = jmc$kql_undefined_index THEN
      expand_kql;
    IFEND;

    IF jmv$known_qfile_list.state_data [jmc$kql_unused_entry].first_entry = jmc$kql_undefined_index THEN
      osp$set_status_condition (jme$maximum_generic_qfiles, status);
    ELSE
      kql_index := jmv$known_qfile_list.state_data [jmc$kql_unused_entry].first_entry;

      jmv$kql_p^ [kql_index].system_file_name := system_label.system_file_name;
      jmv$kql_p^ [kql_index].login_user_identification := system_label.login_user_identification;
      jmv$kql_p^ [kql_index].qfile_controller := system_label.qfile_controller;
      jmv$kql_p^ [kql_index].earliest_clock_time_to_process := earliest_clock_time_to_process;
      jmv$kql_p^ [kql_index].latest_clock_time_to_process := latest_clock_time_to_process;
      jmv$kql_p^ [kql_index].purge_delay := purge_delay_clock_time;
      jmv$kql_p^ [kql_index].application_name := system_label.application_name;
      jmv$kql_p^ [kql_index].next_application_name := system_label.application_name;
      jmv$kql_p^ [kql_index].deferred_by_application := system_label.deferred_by_application;
      jmv$kql_p^ [kql_index].deferred_by_operator := system_label.deferred_by_operator;
      jmv$kql_p^ [kql_index].deferred_by_user := system_label.deferred_by_user;
      jmv$kql_p^ [kql_index].application_state := jmc$kql_application_unused;

{ Has the file been processed??

      IF system_label.disposition_time.specified THEN
        IF jmv$kql_p^ [kql_index].purge_delay < jmv$purge_processed_qfile_time THEN
          jmv$purge_processed_qfile_time := jmv$kql_p^ [kql_index].purge_delay;
        IFEND;
        relink_kql_entry (kql_index, jmc$kql_completed_entry);
      ELSE
        time_deferred_file := jmv$kql_p^ [kql_index].earliest_clock_time_to_process > current_clock_time;
        IF time_deferred_file OR f$deferred (jmv$kql_p^ [kql_index]) THEN
          IF time_deferred_file AND (jmv$kql_p^ [kql_index].earliest_clock_time_to_process <
                jmv$ready_deferred_qfile_time) THEN
            jmv$ready_deferred_qfile_time := jmv$kql_p^ [kql_index].earliest_clock_time_to_process;
          IFEND;
          relink_kql_entry (kql_index, jmc$kql_deferred_entry);
        ELSE
          find_application_name (jmv$kql_p^ [kql_index].application_name, application_index);

          relink_kql_entry (kql_index, jmc$kql_queued_entry);
          relink_kql_application (kql_index, application_index, jmc$kql_application_new);
        IFEND;
        IF jmv$kql_p^ [kql_index].latest_clock_time_to_process < jmv$purge_expired_qfile_time THEN
          jmv$purge_expired_qfile_time := jmv$kql_p^ [kql_index].latest_clock_time_to_process;
        IFEND;
      IFEND;
    IFEND;
    osp$clear_mainframe_sig_lock (qfv$kql_lock);
  PROCEND qfp$rebuild_generic_queue;

?? OLDTITLE ??
?? NEWTITLE := '[XDCL, #GATE] qfp$register_qfile_application', EJECT ??
*copy qfh$register_qfile_application

{ DESIGN:
{ Lock the KQL.
{ Search the application table for the application name, saving the first available index
{ IF application name found THEN
{   RETURN abnormal status jme$application_name_in_use
{ IFEND
{ IF no room in the table THEN
{   RETURN abnormal status jme$application_table_is_full
{ ELSE
{   Update the last_used_application_index
{   WHILE untested entries exist in the unassigned application DO
{     IF the entry's application_name = application name THEN
{       Link application (AN) as NEW
{     IFEND
{   WHILEND
{   Initialize the entry in the KQL application table
{ IFEND
{ Unlock the KQL.

  PROCEDURE [XDCL, #GATE] qfp$register_qfile_application
    (    application_name: ost$name;
         registration_options_p: ^jmt$qfile_registration_options;
         password: ost$name;
     VAR status: ost$status);


    VAR
      application_index: jmt$qfile_application_index,
      first_available_index: jmt$qfile_application_index,
      kql_index: jmt$kql_index,
      next_forward_link: jmt$kql_index,
      option_index: integer;

    status.normal := TRUE;
    osp$set_mainframe_sig_lock (qfv$kql_lock);

    first_available_index := jmc$unassigned_qfile_index;

  /search_for_the_application/
    FOR application_index := 1 TO jmv$last_used_application_index DO
      IF jmv$known_qfile_list.application_table [application_index].application_name = osc$null_name THEN
        IF first_available_index = jmc$unassigned_qfile_index THEN
          first_available_index := application_index;
        IFEND;

      ELSE { does the application_name match ??
        IF jmv$known_qfile_list.application_table [application_index].application_name = application_name THEN
          osp$set_status_abnormal (jmc$job_management_id, jme$application_name_in_use, application_name,
                status);
          EXIT /search_for_the_application/; {----->
        IFEND;
      IFEND;
    FOREND /search_for_the_application/;

    IF status.normal THEN

{ The application_name is not already in the table.  Is there room in the table??

      IF first_available_index = jmc$unassigned_qfile_index THEN
        IF jmv$last_used_application_index = UPPERBOUND (jmv$known_qfile_list.application_table) THEN
          osp$set_status_condition (jme$application_table_is_full, status);
          osp$clear_mainframe_sig_lock (qfv$kql_lock);
          RETURN; {----->
        ELSE
          first_available_index := jmv$last_used_application_index + 1;
          jmv$last_used_application_index := jmv$last_used_application_index + 1;
        IFEND;
      IFEND;

{ Move all queue files with this application_name from the unassigned thread to this application thread.

      kql_index := jmv$known_qfile_list.application_table [jmc$unassigned_qfile_index].
            state_data [jmc$kql_application_new].first_entry;
      WHILE kql_index <> jmc$kql_undefined_index DO
        next_forward_link := jmv$kql_p^ [kql_index].application_forward_link;
        IF jmv$kql_p^ [kql_index].application_name = application_name THEN
          relink_kql_application (kql_index, first_available_index, jmc$kql_application_new);
        IFEND;
        kql_index := next_forward_link;
      WHILEND;

{ Initialize the entry in the table.  All files must be relinked before the table is initialized otherwise
{ the relink procedure will get confused with the application names.

      jmv$known_qfile_list.application_table [first_available_index].application_name := application_name;
      jmv$known_qfile_list.application_table [first_available_index].queue_file_password := password;
      pmp$get_executing_task_gtid (jmv$known_qfile_list.application_table [first_available_index].
            global_task_id);
      IF registration_options_p <> NIL THEN
        FOR option_index := 1 TO UPPERBOUND (registration_options_p^) DO
          CASE registration_options_p^ [option_index].key OF
          = jmc$notify_on_terminate =
            jmv$known_qfile_list.application_table [first_available_index].registration_options.
                  notify_on_terminate := registration_options_p^ [option_index].notify_on_terminate;
          = jmc$null_attribute =
            ;
          ELSE
          CASEND;
        FOREND;
      IFEND;
    IFEND; { status.normal
    osp$clear_mainframe_sig_lock (qfv$kql_lock);

  PROCEND qfp$register_qfile_application;
?? OLDTITLE ??
?? NEWTITLE := '[XDCL, #GATE] qfp$release_generic_queue_files', EJECT ??
*copy qfh$release_generic_queue_files

{ DESIGN:
{ Initialize release_file_count to 0.
{ Lock the KQL.
{ FOR each application in the application_table DO
{   IF executing GTID matches registered GTID THEN
{     FOR each application state DO
{       WHILE entries exist in state DO
{         IF KQL TERMINATED THEN
{           add to the release file list
{           Link application (AN) as UNUSED
{           Link KQL as UNUSED
{         ELSE
{           IF deferred THEN
{             IF earliest_run_time < ready_deferred_qfile_time THEN
{               ready_deferred_qfile_time := earliest_run_time
{             IFEND
{             Link application (NAN) as UNUSED
{             Link KQL as DEFERRED
{             application_name := next_application_name
{           ELSE
{             IF application_name has not changed THEN
{               target application is unassigned
{             ELSE
{               target application is next_application_name
{             IFEND
{             Link KQL as QUEUED
{             Link application (target) as NEW
{             application_name := next_application_name
{           IFEND
{         IFEND
{       WHILEND
{     FOREND
{     zero out the entry in the application table
{   IFEND
{ FOREND
{ Update the last_used_application_index
{ Unlock the KQL.

  PROCEDURE [XDCL, #GATE] qfp$release_generic_queue_files
    (    release_file_list: ^jmt$system_supplied_name_list;
     VAR release_file_count: jmt$qfile_count_range);


    VAR
      application_index: jmt$qfile_application_index,
      application_state: jmt$kql_application_state,
      current_clock_time: jmt$clock_time,
      global_task_id: ost$global_task_id,
      kql_index: jmt$kql_index,
      next_kql_index: jmt$kql_index,
      previously_terminated: boolean,
      relink_application_index: jmt$qfile_application_index,
      release_list_limit: jmt$qfile_count_range,
      time_deferred_file: boolean;

    pmp$get_executing_task_gtid (global_task_id);

    release_file_count := 0;
    IF release_file_list = NIL THEN
      release_list_limit := 0;
    ELSE
      release_list_limit := UPPERBOUND (release_file_list^);
    IFEND;

    osp$set_mainframe_sig_lock (qfv$kql_lock);

{ Check to see if this task has queue files registered.

  /search_all_applications/
    FOR application_index := 1 TO jmv$last_used_application_index DO
      IF jmv$known_qfile_list.application_table [application_index].global_task_id = global_task_id THEN

      /search_all_application_states/
        FOR application_state := SUCC (jmc$kql_application_unused) TO UPPERVALUE (application_state) DO
          kql_index := jmv$known_qfile_list.application_table [application_index].
                state_data [application_state].first_entry;

        /release_entries_in_state/
          WHILE kql_index <> jmc$kql_undefined_index DO

{ Save the index of the next KOL entry.  When the entry is relinked, the links on the current entry
{ will no longer link to the next entry that needs to be managed.

            next_kql_index := jmv$kql_p^ [kql_index].application_forward_link;
            previously_terminated := jmv$kql_p^ [kql_index].entry_kind = jmc$kql_terminated_entry;

{ If the file was terminated, add it to the release list so the caller knows to delete the file
{ and remove the file from the KQL.

            IF previously_terminated THEN
              release_file_count := release_file_count + 1;
              IF release_file_count <= release_list_limit THEN
                release_file_list^ [release_file_count] := jmv$kql_p^ [kql_index].system_file_name;
              IFEND;
              relink_kql_application (kql_index, application_index, jmc$kql_application_unused);
              relink_kql_entry (kql_index, jmc$kql_unused_entry);
            ELSE

              time_deferred_file := jmv$kql_p^ [kql_index].earliest_clock_time_to_process >
                    current_clock_time;
              IF time_deferred_file OR f$deferred (jmv$kql_p^ [kql_index]) THEN
                IF time_deferred_file AND (jmv$kql_p^ [kql_index].earliest_clock_time_to_process <
                      jmv$ready_deferred_qfile_time) THEN
                  jmv$ready_deferred_qfile_time := jmv$kql_p^ [kql_index].earliest_clock_time_to_process;
                IFEND;
                find_application_name (jmv$kql_p^ [kql_index].next_application_name,
                      relink_application_index);
                relink_kql_application (kql_index, relink_application_index, jmc$kql_application_unused);
                jmv$kql_p^ [kql_index].application_name := jmv$kql_p^ [kql_index].next_application_name;
                relink_kql_entry (kql_index, jmc$kql_deferred_entry);
              ELSE

{ If the file's application_name hasn't changed - relink it into the unassigned chain
{ If the application_name did change, then make it available to that application

                IF jmv$kql_p^ [kql_index].application_name = jmv$kql_p^ [kql_index].next_application_name THEN
                  relink_application_index := jmc$unassigned_qfile_index;
                ELSE
                  find_application_name (jmv$kql_p^ [kql_index].next_application_name,
                        relink_application_index);
                IFEND;
                relink_kql_entry (kql_index, jmc$kql_queued_entry);
                relink_kql_application (kql_index, relink_application_index, jmc$kql_application_new);
                jmv$kql_p^ [kql_index].application_name := jmv$kql_p^ [kql_index].next_application_name;
                notify_qfile_application (relink_application_index);
              IFEND;
            IFEND;

            kql_index := next_kql_index;
          WHILEND /release_entries_in_state/;
        FOREND /search_all_application_states/;

{ Zero out the entry in the application table.  The state_data has been zeroed by the relink procedures.

        jmv$known_qfile_list.application_table [application_index].application_name := osc$null_name;
        jmv$known_qfile_list.application_table [application_index].global_task_id.index := 0;
        jmv$known_qfile_list.application_table [application_index].global_task_id.seqno := 0;
        jmv$known_qfile_list.application_table [application_index].queue_file_password := osc$null_name;
        jmv$known_qfile_list.application_table [application_index].registration_options.notify_on_terminate :=
              FALSE;

{ Update the last_used_application_index.

        IF application_index = jmv$last_used_application_index THEN
          WHILE (jmv$known_qfile_list.application_table [jmv$last_used_application_index].application_name =
                osc$null_name) AND (jmv$last_used_application_index > jmc$unassigned_qfile_index) DO
            jmv$last_used_application_index := jmv$last_used_application_index - 1;
          WHILEND;
        IFEND;
      IFEND;
    FOREND /search_all_applications/;

    osp$clear_mainframe_sig_lock (qfv$kql_lock);

  PROCEND qfp$release_generic_queue_files;
?? OLDTITLE ??
?? NEWTITLE := '[XDCL, #GATE] qfp$set_qfile_completed', EJECT ??
*copy qfh$set_qfile_completed

{ DESIGN:
{ Lock the KQL.
{ Validate the application
{ IF valid THEN
{   find the file in the KQL
{   IF found THEN
{     IF completed successfully or KQL TERMINATED THEN
{       IF KQL TERMINATED or (purge_delay < current_clock_time) THEN
{         Link application (AN) as UNUSED
{         Link KQL as UNUSED
{       ELSE
{         IF purge_delay < purge_processed_qfile_time THEN
{           purge_processed_qfile_time := purge_delay
{         IFEND
{         Link application (NAN) as UNUSED
{         application_name := next_application_name
{         Link KQL as COMPLETED
{       IFEND
{     ELSE
{       IF deferred THEN
{         IF earliest_run_time < ready_deferred_qfile_time THEN
{           ready_deferred_qfile_time := earliest_run_time
{         IFEND
{         Link application (NAN) as UNUSED
{         application_name := next_application_name
{         Link KQL as DEFERRED
{       ELSE
{         Link KQL as QUEUED
{         Link application (NAN) as NEW
{         application_name := next_application_name
{         notify the correct application
{       IFEND
{     IFEND
{   ELSE
{     RETURN abnormal status jme$qfile_appl_not_permitted
{   IFEND
{ IFEND
{ Unlock the KQL.

  PROCEDURE [XDCL, #GATE] qfp$set_qfile_completed
    (    application_name: ost$name;
         system_file_name: jmt$system_supplied_name;
         completed_successfully: boolean;
         purge_delay_clock_time: jmt$clock_time;
         current_clock_time: jmt$clock_time;
     VAR delete_qfile: boolean;
     VAR status: ost$status);


    VAR
      application_index: jmt$qfile_application_index,
      kql_index: jmt$kql_index,
      previously_terminated: boolean,
      time_deferred_file: boolean;

    status.normal := TRUE;
    osp$set_mainframe_sig_lock (qfv$kql_lock);

    delete_qfile := FALSE;
    validate_application_access (application_name, application_index, status);
    IF status.normal THEN
      find_qfile_by_application (system_file_name, application_index, kql_index);

      IF kql_index <> jmc$kql_undefined_index THEN
        previously_terminated := jmv$kql_p^ [kql_index].entry_kind = jmc$kql_terminated_entry;
        IF completed_successfully OR previously_terminated THEN
          IF previously_terminated OR (purge_delay_clock_time < current_clock_time) THEN
            delete_qfile := TRUE;
            relink_kql_application (kql_index, application_index, jmc$kql_application_unused);
            relink_kql_entry (kql_index, jmc$kql_unused_entry);
          ELSE
            IF purge_delay_clock_time < jmv$purge_processed_qfile_time THEN
              jmv$purge_processed_qfile_time := purge_delay_clock_time;
            IFEND;
            jmv$kql_p^ [kql_index].purge_delay := purge_delay_clock_time;
            find_application_name (jmv$kql_p^ [kql_index].next_application_name, application_index);
            relink_kql_application (kql_index, application_index, jmc$kql_application_unused);
            jmv$kql_p^ [kql_index].application_name := jmv$kql_p^ [kql_index].next_application_name;
            relink_kql_entry (kql_index, jmc$kql_completed_entry);
          IFEND;
        ELSE
          find_application_name (jmv$kql_p^ [kql_index].next_application_name, application_index);
          time_deferred_file := jmv$kql_p^ [kql_index].earliest_clock_time_to_process > current_clock_time;
          IF time_deferred_file OR f$deferred (jmv$kql_p^ [kql_index]) THEN
            IF time_deferred_file AND (jmv$kql_p^ [kql_index].earliest_clock_time_to_process <
                  jmv$ready_deferred_qfile_time) THEN
              jmv$ready_deferred_qfile_time := jmv$kql_p^ [kql_index].earliest_clock_time_to_process;
            IFEND;
            relink_kql_application (kql_index, application_index, jmc$kql_application_unused);
            jmv$kql_p^ [kql_index].application_name := jmv$kql_p^ [kql_index].next_application_name;
            relink_kql_entry (kql_index, jmc$kql_deferred_entry);
          ELSE
            relink_kql_entry (kql_index, jmc$kql_queued_entry);
            relink_kql_application (kql_index, application_index, jmc$kql_application_new);
            jmv$kql_p^ [kql_index].application_name := jmv$kql_p^ [kql_index].next_application_name;
            notify_qfile_application (application_index);
          IFEND;
        IFEND;
      ELSE
        osp$set_status_abnormal (jmc$job_management_id, jme$name_not_found, system_file_name, status);
      IFEND;
    IFEND;
    osp$clear_mainframe_sig_lock (qfv$kql_lock);

  PROCEND qfp$set_qfile_completed;
?? OLDTITLE ??
?? NEWTITLE := '[XDCL, #GATE] qfp$set_qfile_initiated', EJECT ??
*copy qfh$set_qfile_initiated

{ DESIGN:
{ Lock the KQL.
{ Validate the application
{ IF valid THEN
{   find the file in the KQL
{   IF found THEN
{     IF application MODIFIED or TERMINATED THEN
{       Return abnormal status jme$qfile_cannot_initiate
{     ELSE
{       Link application (AN) as INITIATED
{       Link KQL as INITIATED
{     IFEND
{   ELSE
{     Return abnormal status jme$name_not_found
{   IFEND
{ IFEND
{ Unlock the KQL.

  PROCEDURE [XDCL, #GATE] qfp$set_qfile_initiated
    (    application_name: ost$name;
         system_file_name: jmt$system_supplied_name;
     VAR status: ost$status);


    VAR
      application_index: jmt$qfile_application_index,
      kql_index: jmt$kql_index;

    status.normal := TRUE;
    osp$set_mainframe_sig_lock (qfv$kql_lock);

    validate_application_access (application_name, application_index, status);
    IF status.normal THEN

      find_qfile_by_application (system_file_name, application_index, kql_index);
      IF kql_index <> jmc$kql_undefined_index THEN

        IF (jmv$kql_p^ [kql_index].application_state = jmc$kql_application_modified) OR
              (jmv$kql_p^ [kql_index].application_state = jmc$kql_application_terminated) OR
              (jmv$kql_p^ [kql_index].entry_kind = jmc$kql_terminated_entry) THEN
          osp$set_status_condition (jme$qfile_cannot_initiate, status);
        ELSE

          relink_kql_application (kql_index, application_index, jmc$kql_application_processing);
          relink_kql_entry (kql_index, jmc$kql_initiated_entry);
        IFEND;
      ELSE
        osp$set_status_abnormal (jmc$job_management_id, jme$name_not_found, system_file_name, status);
      IFEND;
    IFEND;
    osp$clear_mainframe_sig_lock (qfv$kql_lock);

  PROCEND qfp$set_qfile_initiated;
?? OLDTITLE ??
?? NEWTITLE := '[XDCL, #GATE] qfp$submit_qfile', EJECT ??
*copy qfh$submit_qfile

{ DESIGN:
{ Lock the KQL.
{ IF KQL full THEN
{   expand_kql
{ IFEND
{ IF KQL still full THEN
{   put message in critical window
{ ELSE
{   find an available KQL entry and initialize it
{   IF deferred THEN
{     IF earliest_run_time < ready_deferred_qfile_time THEN
{       ready_deferred_qfile_time := earliest_run_time
{     IFEND
{     Link KQL DEFERRED
{   ELSE
{     Link KQL QUEUED
{     Link application (AN) NEW
{     Notify the correct application
{   IFEND
{   IF latest_run_time < purge_expired_qfile_time THEN
{     purge_expired_qfile_time := latest_run_time
{   IFEND
{ IFEND
{ Unlock the KQL.

  PROCEDURE [XDCL, #GATE] qfp$submit_qfile
    (    system_label: jmt$qfile_system_label;
         earliest_clock_time_to_process: jmt$clock_time;
         latest_clock_time_to_process: jmt$clock_time;
         current_clock_time: jmt$clock_time;
     VAR status: ost$status);


    VAR
      application_index: jmt$qfile_application_index,
      ignore_status_p: ^ost$status,
      kql_index: jmt$kql_index,
      time_deferred_file: boolean;

    status.normal := TRUE;

    osp$set_mainframe_sig_lock (qfv$kql_lock);

{ Make sure that the name is not already in the KQL.

    kql_search (system_label.system_file_name, -$jmt$kql_entry_kind_set [], kql_index);
    IF kql_index <> jmc$kql_undefined_index THEN
      osp$clear_mainframe_sig_lock (qfv$kql_lock);
      osp$set_status_abnormal (jmc$job_management_id, jme$duplicate_name, system_label.system_file_name,
            status);
      RETURN; {----->
    IFEND;

    IF jmv$known_qfile_list.state_data [jmc$kql_unused_entry].first_entry = jmc$kql_undefined_index THEN
      expand_kql;
    IFEND;

{ Check for room in the Known Qfile List (KQL).  The distribution of entries in
{ the KQL is defined as follows:
{
{    #available = MAXIMUM - qfv$current_kql_limit + #initialized_unused_entries
{    #used_entries = MAXIMUM - #available = qfv$current_kql_limit - #initialized_unused_entries
{

    IF (qfv$current_kql_limit - jmv$known_qfile_list.state_data [jmc$kql_unused_entry].number_of_entries >=
          jmc$maximum_qfile_count) THEN
      osp$set_status_condition (jme$maximum_generic_qfiles, status);
      PUSH ignore_status_p;
      dpp$put_critical_message (jmc$generic_queue_full_message, ignore_status_p^);
    ELSE
      kql_index := jmv$known_qfile_list.state_data [jmc$kql_unused_entry].first_entry;

      jmv$kql_p^ [kql_index].system_file_name := system_label.system_file_name;
      jmv$kql_p^ [kql_index].login_user_identification := system_label.login_user_identification;
      jmv$kql_p^ [kql_index].qfile_controller := system_label.qfile_controller;
      jmv$kql_p^ [kql_index].earliest_clock_time_to_process := earliest_clock_time_to_process;
      jmv$kql_p^ [kql_index].latest_clock_time_to_process := latest_clock_time_to_process;
      jmv$kql_p^ [kql_index].purge_delay := jmc$earliest_clock_time;
      jmv$kql_p^ [kql_index].application_name := system_label.application_name;
      jmv$kql_p^ [kql_index].next_application_name := system_label.application_name;
      jmv$kql_p^ [kql_index].deferred_by_application := system_label.deferred_by_application;
      jmv$kql_p^ [kql_index].deferred_by_operator := system_label.deferred_by_operator;
      jmv$kql_p^ [kql_index].deferred_by_user := system_label.deferred_by_user;
      jmv$kql_p^ [kql_index].application_state := jmc$kql_application_unused;

      time_deferred_file := earliest_clock_time_to_process > current_clock_time;
      IF time_deferred_file OR f$deferred (jmv$kql_p^ [kql_index]) THEN
        IF time_deferred_file AND (earliest_clock_time_to_process < jmv$ready_deferred_qfile_time) THEN
          jmv$ready_deferred_qfile_time := earliest_clock_time_to_process;
        IFEND;
        relink_kql_entry (kql_index, jmc$kql_deferred_entry);
      ELSE
        find_application_name (jmv$kql_p^ [kql_index].application_name, application_index);
        relink_kql_entry (kql_index, jmc$kql_queued_entry);
        relink_kql_application (kql_index, application_index, jmc$kql_application_new);
        notify_qfile_application (application_index);
      IFEND;
      IF latest_clock_time_to_process < jmv$purge_expired_qfile_time THEN
        jmv$purge_expired_qfile_time := latest_clock_time_to_process;
      IFEND;
    IFEND;
    osp$clear_mainframe_sig_lock (qfv$kql_lock);

  PROCEND qfp$submit_qfile;
?? OLDTITLE ??
?? NEWTITLE := '[XDCL, #GATE] qfp$terminate_acquired_qfile', EJECT ??
*copy qfh$terminate_acquired_qfile

{ DESIGN:
{ Lock the KQL.
{ Validate the application
{ IF valid THEN
{   find the first terminated entry in the KQL
{   IF found THEN
{     IF KQL TERMINATED THEN
{       Link application (AN) as UNUSED
{       Link KQL as UNUSED
{     ELSE
{       IF deferred THEN
{         IF earliest_run_time < ready_deferred_qfile_time THEN
{           ready_deferred_qfile_time := earliest_run_time
{         IFEND
{         Link application (NAN) as UNUSED
{         application_name := next_application_name
{         Link KQL as DEFERRED
{       ELSE
{         Link application (NAN) as NEW
{         application_name := next_application_name
{         notify the correct application
{       IFEND
{     IFEND
{   ELSE
{     Return abnormal status jme$generic_queue_is_empty
{   IFEND
{ IFEND
{ Unlock the KQL.

  PROCEDURE [XDCL, #GATE] qfp$terminate_acquired_qfile
    (    application_name: ost$name;
     VAR system_file_name: jmt$system_supplied_name;
     VAR delete_qfile: boolean;
     VAR status: ost$status);


    VAR
      application_index: jmt$qfile_application_index,
      current_clock_time: jmt$clock_time,
      kql_index: jmt$kql_index,
      time_deferred_file: boolean;

    status.normal := TRUE;
    osp$set_mainframe_sig_lock (qfv$kql_lock);

    validate_application_access (application_name, application_index, status);
    IF status.normal THEN

      kql_index := jmv$known_qfile_list.application_table [application_index].
            state_data [jmc$kql_application_terminated].first_entry;
      IF kql_index <> jmc$kql_undefined_index THEN
        system_file_name := jmv$kql_p^ [kql_index].system_file_name;
        IF jmv$kql_p^ [kql_index].entry_kind = jmc$kql_terminated_entry THEN
          delete_qfile := TRUE;
          relink_kql_application (kql_index, application_index, jmc$kql_application_unused);
          relink_kql_entry (kql_index, jmc$kql_unused_entry);
        ELSE
          delete_qfile := FALSE;
          find_application_name (jmv$kql_p^ [kql_index].next_application_name, application_index);
          current_clock_time := #FREE_RUNNING_CLOCK (0);
          time_deferred_file := jmv$kql_p^ [kql_index].earliest_clock_time_to_process > current_clock_time;
          IF time_deferred_file OR f$deferred (jmv$kql_p^ [kql_index]) THEN
            IF time_deferred_file AND (jmv$kql_p^ [kql_index].earliest_clock_time_to_process <
                  jmv$ready_deferred_qfile_time) THEN
              jmv$ready_deferred_qfile_time := jmv$kql_p^ [kql_index].earliest_clock_time_to_process;
            IFEND;
            relink_kql_application (kql_index, application_index, jmc$kql_application_unused);
            jmv$kql_p^ [kql_index].application_name := jmv$kql_p^ [kql_index].next_application_name;
            relink_kql_entry (kql_index, jmc$kql_deferred_entry);
          ELSE
            relink_kql_application (kql_index, application_index, jmc$kql_application_new);
            jmv$kql_p^ [kql_index].application_name := jmv$kql_p^ [kql_index].next_application_name;
            notify_qfile_application (application_index);
          IFEND;
        IFEND;

      ELSE
        osp$set_status_condition (jme$generic_queue_is_empty, status);
      IFEND;

    IFEND;
    osp$clear_mainframe_sig_lock (qfv$kql_lock);

  PROCEND qfp$terminate_acquired_qfile;
?? OLDTITLE ??
?? NEWTITLE := '[XDCL, #GATE] qfp$terminate_qfile', EJECT ??
*copy qfh$terminate_qfile

{ DESIGN:
{ Lock the KQL.
{ Find the file to be terminated in the KQL
{ Link KQL as TERMINATED
{ IF KQL application > NEW THEN
{   IF notify_on_terminate (registration option) OR KQL was initiated THEN
{     Link application (AN) as TERMINATED
{     notify the correct application
{   IFEND
{ ELSE
{   Link application as UNUSED
{   Link KQL as UNUSED
{ IFEND
{ Unlock the KQL.

  PROCEDURE [XDCL, #GATE] qfp$terminate_qfile
    (    system_file_name: jmt$system_supplied_name;
         qfile_state_set: jmt$qfile_state_set;
     VAR delete_qfile: boolean;
     VAR status: ost$status);


    VAR
      application_index: jmt$qfile_application_index,
      kql_index: jmt$kql_index,
      kql_entry_kind_set: jmt$kql_entry_kind_set,
      kql_entry_kind: jmt$kql_entry_kind,
      qfile_state: jmt$qfile_state,
      qfile_was_initiated: boolean;

    status.normal := TRUE;
    delete_qfile := FALSE;
    qfile_was_initiated := TRUE;

    kql_entry_kind_set := $jmt$kql_entry_kind_set [];
    FOR qfile_state := LOWERVALUE (qfile_state) TO UPPERVALUE (qfile_state) DO
      IF qfile_state IN qfile_state_set THEN
        kql_entry_kind := convert_state_to_entry_kind [qfile_state];
        kql_entry_kind_set := kql_entry_kind_set + $jmt$kql_entry_kind_set [kql_entry_kind];
      IFEND;
    FOREND;

    osp$set_mainframe_sig_lock (qfv$kql_lock);

    kql_search (system_file_name, kql_entry_kind_set, kql_index);
    IF kql_index = jmc$kql_undefined_index THEN
      osp$clear_mainframe_sig_lock (qfv$kql_lock);
      osp$set_status_abnormal (jmc$job_management_id, jme$name_not_found, system_file_name, status);
      RETURN; {----->
    IFEND;

    IF jmv$kql_p^ [kql_index].entry_kind = jmc$kql_terminated_entry THEN
      osp$clear_mainframe_sig_lock (qfv$kql_lock);
      osp$set_status_abnormal (jmc$job_management_id, jme$qfile_already_terminated, system_file_name, status);
      RETURN; {----->
    IFEND;

    IF (jmv$kql_p^ [kql_index].entry_kind = jmc$kql_deferred_entry) OR
          (jmv$kql_p^ [kql_index].entry_kind = jmc$kql_queued_entry) THEN
      qfile_was_initiated := FALSE;
    IFEND;
    relink_kql_entry (kql_index, jmc$kql_terminated_entry);
    find_application_name (jmv$kql_p^ [kql_index].application_name, application_index);
    IF jmv$kql_p^ [kql_index].application_state > jmc$kql_application_new THEN
      IF qfile_was_initiated OR jmv$known_qfile_list.application_table [application_index].
            registration_options.notify_on_terminate THEN
        relink_kql_application (kql_index, application_index, jmc$kql_application_terminated);
        notify_qfile_application (application_index);
      IFEND;
    ELSE
      delete_qfile := TRUE;
      relink_kql_application (kql_index, application_index, jmc$kql_application_unused);
      relink_kql_entry (kql_index, jmc$kql_unused_entry);
    IFEND;

    osp$clear_mainframe_sig_lock (qfv$kql_lock);

  PROCEND qfp$terminate_qfile;
?? OLDTITLE ??
?? NEWTITLE := '[XDCL, #GATE] qfp$validate_qfile_access', EJECT ??
*copy qfh$validate_qfile_access

{ DESIGN:
{ Lock the KQL.
{ IF application_name is in application table THEN
{   IF passwords match THEN
{     find file in application's initiated thread
{       IF NOT found THEN
{         Return abnormal status jme$name_not_found
{       IFEND
{   ELSE
{     Return abnormal status jme$qfile_appl_not_permitted
{   IFEND
{ ELSE
{   Return abnormal status jme$application_name_incorrect
{ IFEND
{ Unlock the KQL.

  PROCEDURE [XDCL, #GATE] qfp$validate_qfile_access
    (    system_file_name: jmt$system_supplied_name;
         application_name: ost$name;
         queue_file_password: jmt$queue_file_password;
     VAR status: ost$status);


    VAR
      application_index: jmt$qfile_application_index,
      kql_index: jmt$kql_index;

    status.normal := TRUE;

    osp$set_mainframe_sig_lock (qfv$kql_lock);
    find_application_name (application_name, application_index);
    IF application_index = jmc$unassigned_qfile_index THEN
      osp$set_status_abnormal (jmc$job_management_id, jme$application_name_incorrect, application_name,
            status);
    ELSE

{ Do the passwords match??

      IF queue_file_password <> jmv$known_qfile_list.application_table [application_index].
            queue_file_password THEN
        osp$set_status_abnormal (jmc$job_management_id, jme$qfile_appl_not_permitted, application_name,
              status);
      ELSE

{ Search for the file in the applications initiated thread - If it isn't there, don't permit access
{ to the file.

        kql_index := jmv$known_qfile_list.application_table [application_index].
              state_data [jmc$kql_application_processing].first_entry;
        WHILE (kql_index <> jmc$kql_undefined_index) AND (jmv$kql_p^ [kql_index].system_file_name <>
              system_file_name) DO
          kql_index := jmv$kql_p^ [kql_index].application_forward_link;
        WHILEND;
        IF (kql_index = jmc$kql_undefined_index) THEN
          osp$set_status_abnormal (jmc$job_management_id, jme$name_not_found, system_file_name, status);
        IFEND;
      IFEND;
    IFEND;
    osp$clear_mainframe_sig_lock (qfv$kql_lock);

  PROCEND qfp$validate_qfile_access;
?? OLDTITLE ??
MODEND qfm$generic_queue_file_manager;
