project QadFinancials > class BBaseDaemonProcessor > method LoopForWorkAutoRecoverDaemons

Description

LoopForWorkLargeInterval: submethod of LoopForWork that will only be called after a certain longer time (eg every 20 minutes). This method
can optionally start some other daemons that should be running but that aren't or some other actions that can take up quite some time and that shouldn't be called very frequently (after viLargeIntervalInSeconds)


Parameters


oiReturnStatusoutputintegerReturn status of the method.


Internal usage


BLF
method BBaseDaemonProcessor.LoopForWork


program code (program/bbasedaemonprocessor.p)

    
<ANCESTOR-CODE>
    
    
    /* =================================================================================== */
    /* The start of other daemons will only be done by the History- and the Balance-daemon */
    /* =================================================================================== */
    if vcFcDaemonName <> {&BALANCEDAEMON} and 
       vcFcDaemonName <> {&HISTORYDAEMON}
    then return.
    
    /* ====================================================================== */
    /* Query through all daemons but not the current one                      */
    /* ====================================================================== */
    <Q-70 run DaemonByNameStatusNbrInst (all) (Read) (NoCache)
       (input ?, (DaemonName)
        input vcFcDaemonName, (DaemonNameDiffers)
        input ?, (DaemonStatus)
        input ?, (DaemonStatusDiffers)
        input ?, (MaxNbrOfInstances)
        input 1, (MaxNbrOfInstancesAtLeast)
        output dataset tqDaemonByNameStatusNbrInst) in BBaseDaemon>
        
    /* ========================================================== */
    /* Set indication that the TDaemonUitlity is not yet started  */
    /* ========================================================== */
    assign vlStartedTDaemonUtility = false.
    
    /* ======================================================================================= */
    /* Go through all running or inactive daemons that are configured but not the current one  */
    /* ======================================================================================= */
    for each tqDaemonByNameStatusNbrInst where
             tqDaemonByNameStatusNbrInst.tcDaemonName                 <> vcFcDaemonName and 
             tqDaemonByNameStatusNbrInst.tiDaemonMaxNumberOfInstances >= 1              and
             tqDaemonByNameStatusNbrInst.tcDaemonLogin                <> "":U           and
             tqDaemonByNameStatusNbrInst.tcDaemonLogin                <> ?              and  
             tqDaemonByNameStatusNbrInst.tcDaemonOsCommand            <> "":U           and 
             tqDaemonByNameStatusNbrInst.tcDaemonOsCommand            <> ?              and
             (tqDaemonByNameStatusNbrInst.tcDaemonStatus = {&DAEMONSTATUS-INACTIVE} or
              tqDaemonByNameStatusNbrInst.tcDaemonStatus = {&DAEMONSTATUS-RUNNING}) 
             no-lock : 
        
        /* ====================================================== */
        /* The default is that we do not need to start the daemon */
        /* ====================================================== */
        assign vlNeedToStartTheDaemon  = false.
        
        /* ============================================================= */
        /* The daemon needs to be started in case the daemon is inactive */
        /* ============================================================= */
        if tqDaemonByNameStatusNbrInst.tcDaemonStatus = {&DAEMONSTATUS-INACTIVE}
        then assign vlNeedToStartTheDaemon = true.
        
        /* ========================================================================================================================================================================= */ 
        /* Find out if the daemon needs to be started or not: this is needed in case the daemon is inactive and in case the daemon is running and the processes aren't valid anymore */
        /* ========================================================================================================================================================================= */
        if tqDaemonByNameStatusNbrInst.tcDaemonStatus = {&DAEMONSTATUS-RUNNING}
        then do :
            
            /* Cycle through the processes of the daemon */
            assign viNumberOfValidProcesses   = 0
                   viNumberOfInvalidProcesses = 0.
            do viProcessCounter = 1 to num-entries(tqDaemonByNameStatusNbrInst.tcDaemonProcessIDs):
                
                /* Get the Server-name and the Process ID */
                assign viProcessID = 0.
                if num-entries (entry(viProcessCounter,tqDaemonByNameStatusNbrInst.tcDaemonProcessIDs),":") = 2
                then assign vcProcessHostname = entry(1,entry(viProcessCounter,tqDaemonByNameStatusNbrInst.tcDaemonProcessIDs),":")
                            viProcessID       = integer(entry(2,entry(viProcessCounter,tqDaemonByNameStatusNbrInst.tcDaemonProcessIDs),":")) no-error.
                else assign viProcessID = integer(entry(viProcessCounter,tqDaemonByNameStatusNbrInst.tcDaemonProcessIDs)) no-error.
                
                /* Verify the correctness of the Process-db-field - if problems are spotted ignore this entry */ 
                if error-status:error or 
                   viProcessID = 0    or
                   viProcessID = ?
                then next.
                
                /* Start TDaemonUtility when this was not yet done and we need to start the daemon */
                if vlStartedTDaemonUtility = false
                then do :
                    <M-88 run Main  (input  viSessionID (iiSessionId)) in TDaemonUtility>
                    assign vhTDaemonUtility        = vhFcComponent
                           vlStartedTDaemonUtility = true.
                end. /* if vlStartedTDaemonUtility = false */
                else assign vhFcComponent = vhTDaemonUtility.
                
                /* Check if the process is still active - neglect ocMessage when calling ProcessIsValid as here we do not want this to interfer with the current running daemon */
                <M-64 run ProcessIsValid
                   (input  tqDaemonByNameStatusNbrInst.tcDaemonName (icDaemonName), 
                    input  vcProcessHostname (icProcessHostname), 
                    input  viProcessID (iiProcessNr), 
                    input  tqDaemonByNameStatusNbrInst.tcDaemonAppserver (icDaemonAppserverURL), 
                    output vlValidProcess (olValid), 
                    output vcDummy (ocMessage), 
                    output viFcReturnSuper (oiReturnStatus)) in TDaemonUtility>
                /* As we do not want this to interfer with the current running daemon: when this call has a negative return-status, we assume the process is still valid and we will not start another one */
                if viFcReturnSuper < 0 
                then assign vlValidProcess = true.
                
                /* Increase the process-counter data-items */
                if vlValidProcess = true
                then assign viNumberOfValidProcesses   = viNumberOfValidProcesses + 1.
                else assign viNumberOfInvalidProcesses = viNumberOfInvalidProcesses + 1.
            
            end. /* do viProcessCounter = 1 to num-entries(tqDaemonByNameStatusNbrInst.tcDaemonProcessIDs): */
            
            /* If there are only invalid processes then set the status of the daemon manually to inactive and mark the daemon to be started again */
            if viNumberOfValidProcesses   = 0 and 
               viNumberOfInvalidProcesses > 0
            then do :
                /* Set status in db to inactive */
                <M-71 run StartPersistence
                   (output vhFcComponent (ohPersistence), 
                    output viFcReturnSuper (oiReturnStatus)) in BBaseDaemonProcessor>
                <M-32 run InitTransaction  (output viFcReturnSuper (oiReturnStatus)) in persistence>
                <M-72 run WriteDirect
                   (input  'fcDaemon':U (icTableName), 
                    input  'for each fcDaemon where fcDaemon.DaemonId = ':U + string(tqDaemonByNameStatusNbrInst.tiDaemonID) (icPrepare), 
                    input  'DaemonStatus,DaemonProcessIDs,DaemonRunningProcesses':U (icFieldList), 
                    input  'c,c,i':U (icFieldListDataTypes), 
                    input  {&DAEMONSTATUS-INACTIVE} + chr(2) + '':U + chr(2) + string(0) (icAbsolute), 
                    input  '':U (icIncremental), 
                    input  {&TARGETPROCEDURE} (ihClass), 
                    input  vcUserLogin (icUserLogin), 
                    output viFcReturnSuper (oiReturnStatus)) in persistence>
                <M-91 run CommitTransaction  (output viFcReturnSuper (oiReturnStatus)) in persistence>
                /*  mark the daemon to be started again */
                assign vlNeedToStartTheDaemon = true.
            end. /* if viNumberOfValidProcesses   = 0 and  */ 
            
        end. /* if tqDaemonByNameStatusNbrInst.tcDaemonStatus = {&DAEMONSTATUS-RUNNING} */
             
        /* =========================== */
        /* Actions to start the daemon */
        /* =========================== */
        if vlNeedToStartTheDaemon = true
        then do :
            /* Start TDaemonUtility when this was not yet done and we need to start the daemon */
            if vlStartedTDaemonUtility = false
            then do :
                <M-41 run Main  (input  viSessionID (iiSessionId)) in TDaemonUtility>
                assign vhTDaemonUtility        = vhFcComponent
                       vlStartedTDaemonUtility = true.
            end. /* if vlStartedTDaemonUtility = false */
            else assign vhFcComponent = vhTDaemonUtility.
            /* Actualy start the daemon - neglect messages and errors as we do not want them to cause issues on the running daemon-process */
            <M-35 run StartDaemon
               (input  tqDaemonByNameStatusNbrInst.tcDaemonName (icDaemonName), 
                input  '' (icDaemonAppserverURL), 
                output vcDummy (ocMessage), 
                output viFcReturnSuper (oiReturnStatus)) in TDaemonUtility>
        end. /* if vlNeedToStartTheDaemon = true */
        
    end. /* for each tqDaemonLoginInfo */
    
    /* ========================================= */
    /* Stop TDaemonUtility when this was started */
    /* ========================================= */
    if vlStartedTDaemonUtility = true
    then do :
        run gipr_DeleteProcedure in vhTDaemonUtility.
        delete procedure vhTDaemonUtility.
    end. /* if vlStartedTDaemonUtility = true */