/*------------------------------------------------------------------------ File : PABLManager.p Purpose : DataPA Business Logic manager. Contains the procedures and functions required to dynamically manage business logic on an AppServer without having to restart the Broker or Agents. Syntax : DEFINE VARIABLE hProc AS HANDLE. RUN PABLManager.p PERSISTENT SET hProc. SESSION:ADD-SUPER-PROCEDURE(hProc). Description : Call RefreshBL procedure to ensure any changes to the business logic are reflected in the super-procedure stack. The variable cBLPath should contain the path where all business logic procedures are stored. Author(s) : DataPA Limited Created : 14/07/09 Notes : FOR DETAILED INSTRUCTIONS ON HOW TO USE THIS PROCEDURE SEE http://support.datapa.com/ics/support/default.asp?deptID=5554&task=knowledge&questionID=73 ---------------------------------------------------------------------- Copyright © 2021 DataPA Limited, All Rights Reserved. ------------------------------------------------------------------------ Amendments ========== Date Author Description ======== ============== ============================================== ------------------------------------------------------------------------ */ /* *************************** Definitions ************************** */ /* Set this variable to an initial value of a directory path where you will save your */ /* Business logic routines */ DEFINE VARIABLE cBLPath AS CHARACTER NO-UNDO INITIAL "<>". /* If you want to load only source code (.p's) in the cBLPath, set this vaiable to an */ /* initial value of TRUE. Otherwise, set to FALSE if you want to load any r-code (.r's) */ /* that are found in the cBLPath directory */ DEFINE VARIABLE lRunSource AS LOGICAL NO-UNDO INITIAL TRUE. /* If you would like the procedure to add debug messages to the AppServer log file each */ /* time a procedure is deleted or loaded to the super procedure stack, set this variable */ /* to an initial value of TRUE. Otherwise, set to FALSE to turn off debug messages */ DEFINE VARIABLE lDebugMessages AS LOGICAL NO-UNDO INITIAL TRUE. /* This temp table will details of all the business logic procedures that have been */ /* loaded into the super procedure stack */ DEFINE TEMP-TABLE BusinessLogicProcedure FIELD ProcedureName AS CHARACTER FIELD CreateDate AS DATE FIELD CreateTime AS INTEGER FIELD ModifiedDate AS DATE FIELD ModifiedTime AS INTEGER FIELD RunningInstance AS HANDLE INDEX idx1 IS UNIQUE IS PRIMARY ProcedureName. /* ************************ Function Prototypes ********************** */ FUNCTION BLPathExists RETURNS LOGICAL ( /* parameter-definitions */ ) FORWARD. FUNCTION IsProcedureCurrent RETURNS LOGICAL ( INPUT ipcProcedureName AS CHARACTER ) FORWARD. /* *************************** Main Block *************************** */ IF NOT BLPAthExists() THEN MESSAGE "WARNING: " + cBLPATH + " does not exist. Business logic will not be loaded". /* ********************** Internal Procedures *********************** */ PROCEDURE LoadProcedure : /*------------------------------------------------------------------------------ Purpose: Loads the procedure recieved as an input parameter into the super procedure stack, and stores the last update information and handle in the BusinessLogicProcedure temp table. Parameters: Notes: ------------------------------------------------------------------------------*/ DEFINE INPUT PARAMETER ipcProcedureName AS CHARACTER NO-UNDO. /* Run the procedure persistently, add it to the super-procedure stack */ /* and store it's details */ DO TRANSACTION ON ERROR UNDO, LEAVE: FILE-INFO:FILE-NAME = cBLPath + ipcProcedureName. CREATE BusinessLogicProcedure. ASSIGN BusinessLogicProcedure.ProcedureName = ipcProcedureName BusinessLogicProcedure.CreateDate = FILE-INFO:FILE-CREATE-DATE BusinessLogicProcedure.CreateTime = FILE-INFO:FILE-CREATE-TIME BusinessLogicProcedure.ModifiedDate = FILE-INFO:FILE-MOD-DATE BusinessLogicProcedure.ModifiedTime = FILE-INFO:FILE-MOD-TIME. RUN VALUE(FILE-INFO:FULL-PATHNAME) PERSISTENT SET BusinessLogicProcedure.RunningInstance. SESSION:ADD-SUPER-PROCEDURE(BusinessLogicProcedure.RunningInstance). IF lDebugMessages THEN MESSAGE ipcProcedureName + " started and added to super procedure stack". END. END PROCEDURE. PROCEDURE RefreshBL : /*------------------------------------------------------------------------------ Purpose: Ensures the current version of any business logic in the directory referenced by the variable cBLPath is loaded in the super procedure stack. Parameters: Notes: ------------------------------------------------------------------------------*/ DEFINE VARIABLE cFile AS CHARACTER NO-UNDO. DEFINE VARIABLE cSearchExpression AS CHARACTER NO-UNDO. /* If BL does not exist, do nothing */ IF NOT BLPAthExists() THEN RETURN. /* Determine whether we are looking for .p's or .r's */ IF lRunSource THEN cSearchExpression = "*.p". ELSE cSearchExpression = "*.r". /* Now list the contents of the BL path directory */ INPUT FROM OS-DIR(cBLPath). REPEAT: IMPORT cFile. IF TRIM(cFile) MATCHES cSearchExpression THEN DO: /* Now check it's running and current, if not, run it */ IF NOT IsProcedureCurrent(cFile) THEN DO: RUN LoadProcedure (INPUT cFile). END. /* IF NOT IsProcedureCurrent(cFile) THEN DO */ END. /* IF TRIM(cFile) MATCHES cSearchExpression THEN DO */ END. /* REPEAT: */ END PROCEDURE. /* ************************ Function Implementations ***************** */ FUNCTION BLPathExists RETURNS LOGICAL ( /* parameter-definitions */ ) : /*------------------------------------------------------------------------------ Purpose: Returns a logical value indicating if the path recieved exists Notes: ------------------------------------------------------------------------------*/ FILE-INFO:FILE-NAME = cBLPath. RETURN FILE-INFO:FULL-PATHNAME <> ?. /* Function return value. */ END FUNCTION. FUNCTION IsProcedureCurrent RETURNS LOGICAL ( INPUT ipcProcedureName AS CHARACTER ) : /*------------------------------------------------------------------------------ Purpose: Checks whether the procedure passed in is current, if not deletes any reference to it so it can be added Notes: ------------------------------------------------------------------------------*/ /* First check whether we have a BusinessLogicProcedure Record */ FIND BusinessLogicProcedure WHERE BusinessLogicProcedure.ProcedureName = ipcProcedureName NO-ERROR. /* There is no record, so it's not running, return false */ IF NOT AVAILABLE BusinessLogicProcedure THEN RETURN FALSE. /* Check the handle is still valid, if not, we've lost the procedure so */ /* delete the record and return false */ IF NOT VALID-HANDLE(BusinessLogicProcedure.RunningInstance) THEN DO: IF lDebugMessages THEN MESSAGE ipcProcedureName + " has invalid handle, deleting". DELETE BusinessLogicProcedure. RETURN FALSE. END. /* Check the modified and created time and dates. If they differ the */ /* version of the procedure is out of date, so delete it, delete the */ /* record and return false */ FILE-INFO:FILE-NAME = cBLPath + ipcProcedureName. IF FILE-INFO:FILE-MOD-DATE <> BusinessLogicProcedure.ModifiedDate OR FILE-INFO:FILE-MOD-TIME <> BusinessLogicProcedure.ModifiedTime OR FILE-INFO:FILE-CREATE-DATE <> BusinessLogicProcedure.CreateDate OR FILE-INFO:FILE-CREATE-TIME <> BusinessLogicProcedure.CreateTime THEN DO: IF lDebugMessages THEN MESSAGE ipcProcedureName + " out of date, deleting". DELETE PROCEDURE BusinessLogicProcedure.runningInstance. DELETE BusinessLogicProcedure. RETURN FALSE. END. /* The file is running, and up to date, so return true */ RETURN TRUE. END FUNCTION.