Rocket U2 | UniVerse & UniData

 View Only
  • 1.  Controlling PHANTOM tasks using process locks

    ROCKETEER
    Posted 10-05-2020 13:51
    Edited by System 11-19-2020 15:02
      |   view attached
    If you have become used to stopping PHANTOM processes by killing them or editing a controlling record in a file, there is a much more elegant method available using the often under-recognised method of process locks.

    For example, if we choose lock 1 to signify that a job is already running and lock 2 to instruct a job to terminate, then the code below can be used to ensure that one - and only one - instance of the PHANTOM is permitted to run at any one time:

    * Sample code snippet:- PHANTOM job start
    *
    * Set the PHANTOM job name
    *
    PHANTOM_JOB='WEEKLY_INVOICES_EMEA'
    *
    * Designate the locks to be used for this handshake
    * RUNNING_LOCK=1 ;
    * the lock number used by the PHANTOM when it is running
    *
    * check if the PHANTOM is running by attempting to set the process lock
    * that it would own if it were already running.
    *
    LOCK RUNNING_LOCK THEN
    *
    * The controlled job is not running - OK to start it
    * first release the lock we just set to check if it was already running.
    *
    UNLOCK RUNNING_LOCK
    *
    * now launch the PHANTOM
    *
    EXECUTE 'PHANTOM ':PHANTOM_JOB
    PRINT 'PHANTOM ':PHANTOM_JOB:' launched @ ':TIMEDATE()
    END ELSE
    *
    * already running - do not allow a second copy to run
    *
    PRINT PHANTOM_JOB:' is already started @ ':TIMEDATE()
    END​


    As can be seen,  if Process Lock 1 is set then the PHANTOM is already running, and we only permit one instance of the PHANTOM to run. If however the PHANTOM is not already running then once launched it would set Process Lock 1 to indicate that it is now running.


    Similar code using process lock 2 can now be used to request that the PHANTOM terminate in a controlled fashion. As the PHANTOM job being used as an example may be either busy performing its designated task or sleeping waiting for a set time to elapse, we have added a loop/retry with a brief pause between each attempt.

    <------------------------------------------------------------------------------------------------------------->

    * Sample code snippet:- PHANTOM job termination
    *
    * Set the PHANTOM job name
    *
    PHANTOM_JOB='WEEKLY_INVOICES_EMEA'
    *
    * Designate the locks to be used for this handshake
    *
    RUNNING_LOCK=1;
    * the lock number used by the job being controlled when it is running
    STOPPING_LOCK=2;
    * the lock number used to signal the job to stop
    *
    ALL_DONE=0
    *
    * check if the job is running
    *
    LOCK RUNNING_LOCK THEN
    *
    * The running lock could be obtained, so the job is not running and
    * there is nothing to do.
    *
    UNLOCK RUNNING_LOCK
    PRINT PHANTOM_JOB:' not running @ ':TIMEDATE()
    *
    END ELSE
    *
    * The job is running, so signal it to stop
    *
    LOCK STOPPING_LOCK THEN
    *
    * iterate - looking for the RUNNING_LOCK to be released when
    * the job terminates.
    *
    MONITOR_STOPPED=0 CHECK_INTERVAL=2;
    * interval between checks of the process status
    CHECK_ITERATIONS=30; * number of times to check at the selected interval
    ITERATION_PASS=0
    LOOP
    *
    * Is the job still running?
    *
    LOCK RUNNING_LOCK THEN
    *
    * No - it is not running
    * unlock the two locks we are using and exit gracefully.
    *
    UNLOCK RUNNING_LOCK
    UNLOCK STOPPING_LOCK
    ALL_DONE=1
    IF ITERATION_PASS #0 THEN
    PRINT
    PRINT PHANTOM_JOB:' stopped @ ':TIMEDATE()
    END ELSE
    *
    * Still running - wait a little longer *
    ITERATION_PASS +=1
    *
    * Prettification - give a ticking row of dots as we wait
    *
    IF ITERATION_PASS=1 THEN
    PRINT 'Waiting .':
    END ELSE
    PRINT '.':
    END
    IF ITERATION_PASS > CHECK_ITERATIONS THEN
    *
    * Number of attempts to stop the job exceeded - abandon the attempt.
    *
    ALL_DONE=2
    PRINT; PRINT 'Stop of ':PHANTOM_JOB:' failed @ ':TIMEDATE()
    END
    END
    UNTIL ALL_DONE#0 DO
    *
    * sleep until the next iteration
    *
    SLEEP CHECK_INTERVAL
    REPEAT
    PRINT
    END ELSE
    *
    * STOPPING_LOCK already set - can't be used by two processes at the same time
     PRINT 'Unable to set lock ':STOPPING_LOCK:' already set/in use @ ':TIMEDATE()
    END
    END


    <------------------------------------------------------------------------------------------------------------->

    Following on from the two controlling programs illustrated above, it now follows that the job being controlled will use the same locks in its overall control structures. Lock 1 indicating that the job is already running, and lock 2 indicating that the job has been requested to stop:

    <------------------------------------------------------------------------------------------------------------->

    * Sample code snippet: job being controlled
    *
    PHANTOM_JOB='WEEKLY_INVOICES_EMEA'
    *
    * Designate the locks to be used for this handshake
    *
    RUNNING_LOCK=1; * the lock number used by the job when it is running
    STOPPING_LOCK=2; * the lock number used to signal the job to stop
    *
    * Is the job already running?
    *
    LOCK RUNNING_LOCK THEN
    *
    * Not already running - so OK to run as long as it has not
    * already been asked to stop. So is STOPPING_LOCK set?
    *
    LOCK STOPPING_LOCK THEN
    *
    * No - so still OK to run.
    *
    UNLOCK STOPPING_LOCK
    END ELSE
    UNLOCK RUNNING_LOCK
    PRINT PHANTOM_JOB:' under orders to stop - exiting @ ':TIMEDATE()
    STOP
    END
    END ELSE
    *
    * already running - exit
    *
    PRINT PHANTOM_JOB:' already running, stopping @ ':TIMEDATE()
    STOP
    END
    *
    *
    * <<< MAIN PROCESSING LOGIC>>>
    *
    *
    * Has the job been ordered to stop?
    *
    LOCK STOPPING_LOCK THEN
    *
    * no - unlock and carry on
    *
    UNLOCK STOPPING_LOCK
    EOF=0
    END ELSE
    *
    * ordered to stop - release the running lock after tidying up
    *
    *<<< Place any closing logic here - for example: >>>
    ** Closing sequential files
    ** Updating control records
    ** etc.
    *
    UNLOCK RUNNING_LOCK; * release the lock that showed the job was running
    *
    * exit gracefully *

    <------------------------------------------------------------------------------------------------------------->

    A fully-worked example has been attached as three BASIC programs in source code form:

    • START_LICENSE_MONITOR - a program to launch the PHANTOM program LICENSE_MONITOR
    • LICENSE_MONITOR - a program to monitor and record U2 database license usage to a CSV file suitable for import into a spreadsheet.
    • STOP_LICENSE_MONITOR - a program to stop the PHANTOM program LICENSE_MONITOR

    The programs are fully self-documenting and  should be compiled and catalogued in an account of your choice.  To launch the monitoring program the syntax is:

    • START_LICENSE_MONITOR n
      • Where 'n' is the number of seconds between sample intervals. The default value is 5 (seconds).
    • STOP_LICENSE_MONITOR
    If wished the program can also be run directly on a terminal:

    • LICENSE_MONITOR n
      • Where 'n' is the number of seconds between sample intervals. The default value is 5 (seconds).

      Some will be well familiar with this technique, but hopefully others will find it useful as an overall control methodology. For more widespread Job Control usage it may be necessary to dynamically allocate and return pairs of available free locks from the Process Lock table, though I will leave this as an exercise for the Developer if needed.

      ------------------------------
      John Jenkins
      Principal Technical Support Engineer
      Rocket Software Limited
      U.K.
      ------------------------------

      Attachment(s)

      zip
      LICENSE_MONITOR.zip   3 KB 1 version


    • 2.  RE: Controlling PHANTOM tasks using process locks

      Posted 01-27-2021 08:55
      Thank you John! This will come in handy and I'll give it a shot. We currently use the "edit control" record" to stop a PHANTOM.


      -Peter G

      ------------------------------
      Peter Gonzalez
      programmer
      Allied Healthcare Products, Inc.
      ------------------------------



    • 3.  RE: Controlling PHANTOM tasks using process locks

      ROCKETEER
      Posted 01-27-2021 10:12
      For UniData here is some example code I use to see if a couple of my phantom monitor processes are running without using process locks.
      The phantoms are starting via PHANTOM MONITOR.REPLOG and PHANTON MONITOR.REPSTATUS.

      EXECUTE 'PORT.STATUS' CAPTURING POUT
      NO.OF.LINES = DCOUNT(POUT,@AM)
      FOR LINE.NXT = 7 TO NO.OF.LINES
       LINE = TRIM(POUT<LINE.NXT>)
       CHECK.USER.TYPE = FIELD(LINE," ",4)
       IF CHECK.USER.TYPE = "phantom" THEN
       CHECK.PID = FIELD(LINE," ",2)
       CMD = 'PORT.STATUS PID ' : CHECK.PID : ' CALL.STACK'
       EXECUTE CMD CAPTURING CMD.POUT
       IF NOT(MON1.RUNNING) THEN
         IF INDEX(CMD.POUT,"MONITOR.REPLOG",1) THEN
          MON1.RUNNING = 1
         END
       END
      IF NOT(MON2.RUNNING) THEN
      IF INDEX(CMD.POUT,"MONITOR.REPSTATUS",1) THEN
       MON2.RUNNING = 1
      END
      END
      IF MON1.RUNNING AND MON2.RUNNING THEN EXIT
      END
      NEXT LINE.NXT

      ------------------------------
      Jonathan Smith
      UniData ATS and Principal Engineer
      Rocket Software
      ------------------------------



    • 4.  RE: Controlling PHANTOM tasks using process locks

      Posted 01-28-2021 10:33
      Thank you Jonathan.


      ------------------------------
      Peter Gonzalez
      programmer
      Allied Healthcare Products, Inc.
      ------------------------------