project BLF > class BBaseDaemon > method ControlDaemon

Description

This method should be called whenever a daemon-process is started (run of a daemon), stopped or a request to stop has been received.
This method should only be called from the daemon processor components and has a transaction on its own.


Parameters


iiDaemonIdinputintegerDaemon Id of the daemon that needs to be "controlled".
icStatusinputcharacterThe status to which the daemon should be switched.
ocErrorMessageoutputcharacterThe error message that is produced in case of an error.
iiProcessIdinputinteger
icDaemonHostnameinputcharacter
oiReturnStatusoutputintegerReturn status of the method.


Internal usage


BLF
method BBaseDaemon.APIStop
method BBaseDaemonProcessor.MarkDaemonRunning
method BBaseDaemonProcessor.SetDaemonStopping
method BBaseDaemonProcessor.StopDaemon


program code (program1/bbasedaemon.p)

OLCloop: repeat:

/* ================== */
/* Validate daemon id */
/* ================== */
if iiDaemonID = 0 or
   iiDaemonID = ?
then do :
    assign oiReturnStatus = -3.
    <M-1 run SetMessage
       (input  #T-82'Update the daemon. The daemon ID is mandatory.':255(60)T-82# (icMessage), 
        input  '' (icArguments), 
        input  '' (icFieldName), 
        input  '' (icFieldValue), 
        input  'E':U (icType), 
        input  3 (iiSeverity), 
        input  '' (icRowid), 
        input  'BLF-17':U (icFcMsgNumber), 
        input  '' (icFcExplanation), 
        input  '' (icFcIdentification), 
        input  '' (icFcContext), 
        output viFcReturnSuper (oiReturnStatus)) in BBaseDaemon>
    Return.
end. /* if iiDaemonID = 0 or */

/* ====================================================================================================== */
/* Start from an emtpy instance to make sure we are not working with old information// then Load the data */
/* ====================================================================================================== */
<M-2 run ClearData  (output viFcReturnSuper (oiReturnStatus)) in BBaseDaemon>
if viFcReturnSuper <> 0
then oiReturnStatus = viFcReturnSuper.
if viFcReturnSuper < 0
then do:
    assign ocErrorMessage = trim(substitute(#T-12'Update the daemon; unable clear the current instance information. Daemon ID; &1':255(61)T-12#,string(iiDaemonID))).
    return.
end.

<M-3 run DataLoad
   (input  ? (icRowids), 
    input  iiDaemonId (icPkeys), 
    input  ? (icObjectIds), 
    input  '' (icFreeform), 
    input  false (ilKeepPrevious), 
    output viFcReturnSuper (oiReturnStatus)) in BBaseDaemon>
if viFcReturnSuper <> 0
then oiReturnStatus = viFcReturnSuper.
if viFcReturnSuper < 0
then do:
    assign ocErrorMessage = trim(substitute(#T-17'Update the daemon; unable to load it based on its ID (&1).':255(62)T-17#,string(iiDaemonID))).
    return.
end.

find first tfcDaemon where tfcDaemon.DaemonID = iiDaemonID.

/* ============================================================= */
/* Skip if the status = Inactive and the new status is stopping  */
/* ============================================================= */
if icStatus               = {&DAEMONSTATUS-STOPPING} and 
   tfcDaemon.DaemonStatus = {&DAEMONSTATUS-INACTIVE}
then return.

/* =============== */
/* Update the data */
/* =============== */
case icStatus  :
    when {&DAEMONSTATUS-RUNNING}
    then do:
        /* Save date and time in UTC */
        session:timezone = 0.
        assign  tfcDaemon.DaemonRunningProcesses  = (if tfcDaemon.DaemonStatus = {&DAEMONSTATUS-RUNNING}
                                                     then tfcDaemon.DaemonRunningProcesses + 1
                                                     else 1)
                tfcDaemon.DaemonStatus            = icStatus
                tfcDaemon.DaemonLastStartDate     = today
                tfcDaemon.DaemonLastStartTime     = time
                tfcDaemon.tc_Status               = "C":U.
        session:timezone = viTimeOffset.
        if tfcDaemon.DaemonRunningProcesses = 1
        then tfcDaemon.DaemonProcessIDs = (if icDaemonHostname = "" then "" else icDaemonHostname + ":") + string(iiProcessId).
        else if icDaemonHostname = ""
        then tfcDaemon.DaemonProcessIDs = trim(tfcDaemon.DaemonProcessIDs + "," + string(iiProcessId),",").
        else ADDPID: do:
            do viFcCount3 = 1 to num-entries(tfcDaemon.DaemonProcessIDs):
                if entry (1,entry(viFcCount3,tfcDaemon.DaemonProcessIDs),":") = icDaemonHostname
                then do:
                    entry(viFcCount3,tfcDaemon.DaemonProcessIDs) = entry(viFcCount3,tfcDaemon.DaemonProcessIDs) + "," + string(iiProcessId).
                    leave ADDPID.
                end.
            end.
            tfcDaemon.DaemonProcessIDs = trim(tfcDaemon.DaemonProcessIDs + "," + icDaemonHostname + ":" + string(iiProcessId),",").
        end.
    end.
    when {&DAEMONSTATUS-STOPPING}
    then do :
        assign tfcDaemon.DaemonStatus = icStatus
               tfcDaemon.tc_Status    = "C":U.
        /* ============================================================================================== */
        /* Set the LastUser on the daemon - this has to be done here and not in the actual daemon-process */
        /* as the current user there is the user that is specified in the daemon-configuration while here */
        /* we need to know the user who started/stopped the daemon.                                       */
        /* Here we set the user who last stopped the daemon but do note that the user who last started    */
        /* the daemon is set in TDaemonUtility:StartDaemon()                                              */
        /* ============================================================================================== */
        assign tfcDaemon.LastStoppedUsr_ID  = viUsrId. /* Set the user who stopped the daemon here when marking the status as 'Stopping' as when marking it as 'Inactive' is done by the daemon-itself. And here we want to track the person who requested the dmn to go down */
    end.
    when {&DAEMONSTATUS-INACTIVE}    then do:
        /* Save date and time in UTC */
        session:timezone = 0.    
        assign  tfcDaemon.DaemonStatus            = (if tfcDaemon.DaemonRunningProcesses > 1 and iiProcessId <> 0
                                                     then tfcDaemon.DaemonStatus
                                                     else icStatus)
                tfcDaemon.DaemonRunningProcesses  = (if tfcDaemon.DaemonRunningProcesses > 1 and iiProcessId <> 0
                                                     then tfcDaemon.DaemonRunningProcesses - 1
                                                     else 0)
                tfcDaemon.DaemonLastEndDate       = today
                tfcDaemon.DaemonLastEndTime       = time
                tfcDaemon.tc_Status               = "C":U.
        session:timezone = viTimeOffset.        
        if tfcDaemon.DaemonRunningProcesses = 0
        then tfcDaemon.DaemonProcessIDs = "".
        else do:
            vcProcessHostname = icDaemonHostname.
            do viFcCount3 = 1 to num-entries(tfcDaemon.DaemonProcessIDs):
                if num-entries (entry(viFcCount3,tfcDaemon.DaemonProcessIDs),":") = 2
                then do:
                    vcProcessHostname = entry (1,entry(viFcCount3,tfcDaemon.DaemonProcessIDs),":").
                    if (icDaemonHostname = vcProcessHostname or icDaemonHostname = "")
                    and entry (2,entry(viFcCount3,tfcDaemon.DaemonProcessIDs),":") = string(iiProcessId)
                    then do:
                        entry(viFcCount3,tfcDaemon.DaemonProcessIDs) = "".
                        leave.
                    end.
                end.
                else if (icDaemonHostname = vcProcessHostname or icDaemonHostname = "")
                     and entry(viFcCount3,tfcDaemon.DaemonProcessIDs) = string(iiProcessId)
                then do:
                    entry(viFcCount3,tfcDaemon.DaemonProcessIDs) = "".
                    leave.
                end.
            end.
            tfcDaemon.DaemonProcessIDs  = trim(replace(tfcDaemon.DaemonProcessIDs,",,",","),",").
        end.
    end.
end case.

/* ================================================================= */
/* Setting the daemon status does not require validation.            */
/* ================================================================= */
vlFcDataValidated = yes.

<M-7 run AdditionalUpdates  (output viFcReturnSuper (oiReturnStatus)) in BBaseDaemon>
if viFcReturnSuper <> 0
then oiReturnStatus = viFcReturnSuper.
if viFcReturnSuper < 0
then do:
    assign ocErrorMessage = trim(substitute(#T-28'An error has occurred on &1 (daemon ID = &3), error number = &2.':255(64)T-28#,"AdditionalUpdates":U,string(oiReturnStatus),string(iiDaemonID))).
    return.
end.

<M-9 run DataSave  (output viFcReturnSuper (oiReturnStatus)) in BBaseDaemon>
/* Repeat everything in case an optimistic lock error occured. */
if viFcReturnSuper = -2
then do:
    viOLCount = viOLCount + 1.
    if viOLCount < 6
    then do:
        oiReturnStatus = 0.
        <M-38 run ClearMessages  (output viFcReturnSuper (oiReturnStatus)) in BBaseDaemon>
        next OLCloop.
    end.
end.
if viFcReturnSuper <> 0
then oiReturnStatus = viFcReturnSuper.
if viFcReturnSuper < 0
then do:
    assign ocErrorMessage = trim(substitute(#T-33'An error has occurred on &1 (daemon ID = &3), error number = &2.':255(64)T-33#,"DataSave":U,string(oiReturnStatus),string(iiDaemonID))).
    return.
end.

leave OLCloop.
end.

finally:
    for each tFcMessages:
        assign ocErrorMessage = ocErrorMessage + chr(10) + 
                                (if tFcMessages.tcFcType = "W":U then trim(#T-34'Warning':100(38)t-34#) + "; ":U else trim(#T-35'Error':100(39)t-35#) + "; ":U) +
                                (if tFcMessages.tcFcMessage = ? then "?":U else tFcMessages.tcFcMessage) + 
                                (if tFcMessages.tcFcFieldName = ? then "":U else " ":U + trim(#T-36'Field Name':100(40)T-36#) + "; ":U + tFcMessages.tcFcFieldName) + 
                                (if tFcMessages.tcFcFieldValue = ? then "":U else " ":U + trim(#T-37'Field Value':100(41)T-37#) + "; ":U + tFcMessages.tcFcFieldValue).
    end.
end finally.