project BLF > class TDaemonUtility > method StartDaemonInternal
Description
Internal method that physically starts the new daemon process. It is only called by the wrapper method "tDaemonUtility.StartDaemon".
Parameters
| icDaemonName | input | character | |
| ocMessage | output | character | |
| oiReturnStatus | output | integer | Return status of the method. |
Internal usage
BLF
program code (program1/tdaemonutility.p)
/* ================================================================= */
/* First do some validations. */
/* ================================================================= */
<Q-1 run DaemonLoginInfo (all) (Read) (NoCache)
(input icDaemonName, (DaemonName)
output dataset tqDaemonLoginInfo) in BBaseDaemon >
find first tqDaemonLoginInfo no-error.
if not available tqDaemonLoginInfo
then do :
assign ocMessage = trim(substitute(#T-10'The daemon (&1) cannot be started since it has not yet been configured.':255(4381)T-10#,icDaemonName))
oiReturnStatus = -3.
return.
end.
if tqDaemonLoginInfo.tiDaemonMaxNumberOfInstances = 0
then do :
assign ocMessage = #T-58'A disabled daemon (# instances is zero) cannot be started.':255(323576663)T-58#
oiReturnStatus = -3.
return.
end.
if tqDaemonLoginInfo.tcDaemonStatus = {&DAEMONSTATUS-RUNNING}
then assign viDaemonsStarted = tqDaemonLoginInfo.tiDaemonRunningProcesses
viDaemonsToStart = tqDaemonLoginInfo.tiDaemonMaxNumberOfInstances - tqDaemonLoginInfo.tiDaemonRunningProcesses.
else assign viDaemonsStarted = 0
viDaemonsToStart = tqDaemonLoginInfo.tiDaemonMaxNumberOfInstances.
if viDaemonsToStart <= 0
then do:
assign ocMessage = substitute(#T-93'The daemon (&1) is already running.':255(925698927)T-93#,icDaemonName).
oiReturnStatus = -3.
return.
end.
if tqDaemonLoginInfo.tcDaemonLogin = "":U or
tqDaemonLoginInfo.tcDaemonLogin = ?
then assign ocMessage = ocMessage + chr(10) + trim(substitute(#T-11'The daemon (&1) cannot be started because the &2 is not specified. Please use the maintenance function on this daemon to correct this.':255(5184)T-11#,icDaemonName,trim(#T-12'Login':35(5183)T-12#))).
if tqDaemonLoginInfo.tcDaemonStartDirectory = "":U or
tqDaemonLoginInfo.tcDaemonStartDirectory = ?
then assign ocMessage = ocMessage + chr(10) + trim(substitute(#T-13'The daemon (&1) cannot be started because the &2 is not specified. Please use the maintenance function on this daemon to correct this.':255(5184)T-13#,icDaemonName,trim(#T-14'Start-directory':35(5185)T-14#))).
else do:
file-info:file-name = tqDaemonLoginInfo.tcDaemonStartDirectory.
if file-info:file-type <> "DRW"
then ocMessage = ocMessage + chr(10) + #T-175'The specified directory does not exist or is not writable.':100(9034)T-175#
+ " ("
+ (if file-info:full-pathname = ? then tqDaemonLoginInfo.tcDaemonStartDirectory else file-info:full-pathname)
+ ")".
end.
if tqDaemonLoginInfo.tcDaemonLogFile = "":U or
tqDaemonLoginInfo.tcDaemonLogFile = ?
then assign ocMessage = ocMessage + chr(10) + trim(substitute(#T-15'The daemon (&1) cannot be started because the &2 is not specified. Please use the maintenance function on this daemon to correct this.':255(5184)T-15#,icDaemonName,trim(#T-16'Log-file':35(5187)T-16#))).
else do:
file-info:file-name = tqDaemonLoginInfo.tcDaemonLogFile.
if file-info:full-pathname = ?
then do:
vcTemp = tqDaemonLoginInfo.tcDaemonLogFile.
if num-entries(vcTemp,"/") > num-entries(vcTemp,"~\")
then entry (num-entries(vcTemp,"/"),vcTemp,"/") = "".
else entry (num-entries(vcTemp,"~\"),vcTemp,"~\") = "".
file-info:file-name = vcTemp.
if file-info:file-type <> "DRW"
then ocMessage = ocMessage + chr(10) + #T-44'The directory for the log file is not valid.':255(5199)T-44#
+ " (" + vcTemp + ")".
end.
else do:
if file-info:file-type <> "FRW"
then ocMessage = ocMessage + chr(10) + #T-50'You do not have write permissions for this log file.':100(5198)T-50#
+ " ("
+ (if file-info:full-pathname = ? then tqDaemonLoginInfo.tcDaemonLogFile else file-info:full-pathname)
+ ")".
end.
end.
if tqDaemonLoginInfo.tcDaemonOsCommand = "":U or
tqDaemonLoginInfo.tcDaemonOsCommand = ?
then assign ocMessage = ocMessage + chr(10) + trim(substitute(#T-17'The daemon (&1) cannot be started because the &2 is not specified. Please use the maintenance function on this daemon to correct this.':255(5184)T-17#,icDaemonName,trim(#T-18'OS-Command':35(5188)T-18#))).
if ocMessage <> ? and
length(ocMessage,"character":U) > 1
then do :
assign ocMessage = substring(ocMessage,2,-1,"character":U) + chr(10) +
trim(substitute(#T-19'This daemon cannot be started because not all required properties are available.':255(5189)T-19#))
oiReturnStatus = -3.
return.
end. /* if ocMessage <> ? and */
/* ================================================================= */
/* Start the daemon. */
/* ================================================================= */
if tqDaemonLoginInfo.tcDaemonStatus <> {&DAEMONSTATUS-RUNNING}
then do:
vcArguments = "for each fcDaemon where fcDaemon.DaemonName = '" + icDaemonName + "'".
run StartPersistenceInPool (input ?, output vhFcComponent, output viFcReturnSuper).
<M-83 run WriteDirect
(input 'fcDaemon' (icTableName),
input vcArguments (icPrepare),
input 'DaemonStatus' (icFieldList),
input 'c' (icFieldListDataTypes),
input {&DAEMONSTATUS-STARTING} (icAbsolute),
input '' (icIncremental),
input ? (ihClass),
input '' (icUserLogin),
output viFcReturnSuper (oiReturnStatus)) in persistence>
end.
file-info:file-name = tqDaemonLoginInfo.tcDaemonStartDirectory.
vcStartDirectory = file-info:full-pathname.
/* =========================================================== *
* Convert relative paths to full pathnames
* ========================================================== */
assign vcArguments = ""
vcPropath = "":U.
assign vcConfigFile = search(Icdaemonname + ".config":U)
vcTemp = ''.
if vcConfigFile <> ?
then do :
input from value(vcConfigFile).
repeat on error undo, leave: /* cannot use throw */
import unformatted vcTemp.
if vcTemp begins 'EXTRAPAR='
then assign vcArguments = vcArguments + ' ' + substring (vcTemp,10,-1,'CHARACTER').
if vcTemp begins "PROPATH=":U
then do:
assign vcTemp = substring (vcTemp,9,-1,'CHARACTER').
do viIdx = 1 to num-entries (vcTemp,',') :
assign vcPathEntry = entry (viIdx,vcTemp,',').
file-info:file-name = vcPathEntry.
if file-info:full-pathname <> ?
then vcPropath = vcPropath + ",":U + file-info:full-pathname.
end.
end.
end. /* repeat */
input close.
end. /* if vcConfigFile <> ? */
do viIdx = 1 to num-entries(PROPATH):
vcPathEntry = entry(viIdx, PROPATH).
if vcPathEntry = "":U
then vcPathEntry = ".":U.
file-info:file-name = vcPathEntry.
if file-info:full-pathname <> ?
then vcPropath = vcPropath + ",":U + file-info:full-pathname.
end.
vcPropath = trim(vcPropath, ",":U).
/* ================================================================= *
* Prepare the arguments
* ================================================================= */
assign vlPF = no
viCountStartupParams = num-entries(session:startup-parameters).
do viCount = 1 to viCountStartupParams:
vcParameter = entry(viCount, session:startup-parameters).
if vlPF
then do:
if vcParameter = "(end .pf)":U
then vlPF = no.
next.
end.
if not vcParameter begins "-":U or
vcParameter begins "-logginglevel ":U or
vcParameter begins "-logentrytypes ":U or
vcParameter begins "-logfile ":U or
vcParameter begins "-ubpid ":U or
vcParameter begins "-logname ":U or
vcParameter begins "-logthreshold ":U or
vcParameter begins "-numlogfiles ":U or
vcParameter begins "-ASID ":U or
vcParameter begins "-ubpropfile ":U or
vcParameter begins "-p ":U or
vcParameter begins "-param ":U or
vcParameter begins "-ininame ":U
then next.
if vcParameter begins "-pf "
then do:
vlPF = yes.
if length(vcParameter, "CHARACTER") > 14 and
replace(substr(vcParameter, length(vcParameter, "CHARACTER":U) - 10, 11, "CHARACTER":U), "~\":U, "/":U) <> "/startup.pf":U
then vcArguments = vcArguments + " ":U + vcParameter.
next.
end.
assign vcArguments = vcArguments + " ":U + vcParameter.
end. /* do viCount = 1 to viCountStartupParams: */
assign vcArguments = vcArguments + " -param ":U + icDaemonName + " -b -p program/tdaemon.p ":U.
vcDLC = os-getenv("DLC").
file-info:file-name = vcDLC.
if file-info:file-type = ?
then do:
vcpromsgs = search("promsgs":U).
if opsys = "UNIX":U
then vcDLC = replace(vcpromsgs,"/promsgs":U,"").
else vcDLC = replace(vcpromsgs,"~\promsgs":U,"").
end.
else do:
file-info:file-name = vcDLC + (if opsys = "UNIX":U
then "/promsgs":U
else "~\promsgs":U).
if file-info:file-type = ?
then vcpromsgs = search("promsgs":U).
else vcpromsgs = file-info:full-pathname.
end.
/* ================================================================= */
/* Starting the daemon is done by spawning a new progress session */
/* on the server in which the specific daemon process is started. */
/* The mark in the database that the daemon is active, is done by */
/* the daemonprocessor itself. */
/* ================================================================= */
do viA = 1 to viDaemonsToStart:
assign viDaemonsStarted = viDaemonsStarted + 1.
case OPSYS:
when "UNIX":U
then do:
if viA = 1
then assign vcStartDirectory = vcStartDirectory + "/":U
vcDaemonExec = replace (tqDaemonLoginInfo.tcDaemonOsCommand, {&DAEMONOSCOMMAND-CONSTANT}, " ":U + <M-31 GetDaemonExecutable
(input icDaemonName (icDaemonName),
input vcDLC (icDLC)) in TDaemonUtility>
+ vcArguments).
assign vcProgress = "cd ":U + vcStartDirectory + " ; ":U +
"DLC=":U + vcDLC + " ; ":U +
"PROMSGS=":U + vcpromsgs + " ; ":U +
"PROPATH=":U + vcPropath + " ; ":U +
"export DLC PROMSGS PROPATH ; nohup ":U +
vcDaemonExec +
" > ":U + vcStartDirectory + icDaemonName + "StdOut" + string(viA) + ".log":U +
" 2> ":U + vcStartDirectory + icDaemonName + "StdErr" + string(viA) + ".log&":U.
os-command no-wait value(vcProgress).
<M-39 run CheckDaemonStatusInternal
(input icDaemonName (icDaemonName),
input viDaemonsStarted (iiStarted),
output viFcReturnSuper (oiReturnStatus)) in TDaemonUtility>
/* We do not really need the process ID, but this process will avoid the previous nohup process from hanging around and becoming a zombie process. */
/* (see BLF-3319) */
input stream sProcessRead through "echo $PPID":U.
import stream sProcessRead vcTemp.
input stream sProcessRead close.
if viFcReturnSuper <> 0
then oiReturnStatus = viFcReturnSuper.
if viFcReturnSuper < 0
then do:
assign ocMessage =
trim(substitute(#T-85'The daemon cannot be started: (&1)':120(4766)T-85#,icDaemonName)) + chr (10) +
trim(substitute(#T-78'See daemon log file for detailed information: (&1)':120(4767)T-78#,tqDaemonLoginInfo.tcDaemonLogFile)).
return.
end.
end. /* when "UNIX":U */
when "WIN32":U
then do:
if viA = 1
then assign vcStartDirectory = vcStartDirectory + "~\":U
vcDaemonExec = "~"":U + <M-30 GetDaemonExecutable
(input icDaemonName (icDaemonName),
input vcDLC (icDLC)) in TDaemonUtility> + "~"":U.
assign vcIni = vcStartDirectory + "s":U + string(viA) + string(TIME) + ".ini":U.
OUTPUT TO value(vcIni).
PUT UNFORMATTED "[WinChar Startup]":U SKIP
"DLC=":U + vcDLC SKIP
"PROPATH=":U + replace(REPLACE(vcPropath,"~\":U,"/":U),"/gui":U,"/tty":U) SKIP.
OUTPUT CLOSE.
ASSIGN vcQuotedIni = (IF vcIni MATCHES "* *":U THEN "~"":U + vcIni + "~"":U ELSE vcIni)
vcProgress = vcDaemonExec + " -ininame ":U + vcQuotedIni + vcArguments
vcProgress = Trim(Replace (tqDaemonLoginInfo.tcDaemonOsCommand, {&DAEMONOSCOMMAND-CONSTANT}, " ":U + vcProgress + " ":U))
vhFcComponent = ?.
<M-4 run Main () in Win32Lib>
/*redirect output*/
assign vcProgress = vcProgress + " >>" + vcStartDirectory + "TDaemonUtility":U + string(time) + ".log":U.
/*this will start 2 processes, 1 cmd and 1 daemon*/
assign viReturn = <M-5 ShellExecuteExtended
(input 'cmd':U (icFile),
input '/c ' + vcProgress (icParameters),
input vcStartDirectory (icDir),
input 'open':U (icVerb),
output viProcess (oiProcessHandle),
output viProcessId (oiProcessId)) in Win32Lib>.
if viReturn = 0
then do:
/* BLF-4204
* If shellexecute fails try a simple os-command.
* You cannot check the result of the os-command so do not try.
* os-command should use silent in stead of no-wait but that does not work.
*/
os-command no-wait value (vcProgress).
end.
else
if viReturn < 0
then do:
output to value(tqDaemonLoginInfo.tcDaemonLogFile) append.
put unformatted
"TDaemonUtility : ":U + string(now) #T-20'The daemon did not start properly.':255(5130)T-20# skip.
if viReturn eq -1 /* wrong parameters */
then do:
<M-6 run GetCBFError
(output tErrorFromWin32 (tCBFError),
output viFcReturnSuper (oiReturnStatus)) in Win32Lib>
for each tErrorFromWin32 by tErrorFromWin32.tiCBFSequence:
put unformatted tErrorFromWin32.tcCBFMessage skip.
end.
end.
output close.
assign ocMessage =
trim(substitute(#T-23'The daemon cannot be started: (&1)':120(4766)T-23#,icDaemonName)) + chr (10) +
trim(substitute(#T-24'See daemon log file for detailed information: (&1)':120(4767)T-24#,tqDaemonLoginInfo.tcDaemonLogFile)).
oiReturnStatus = -3.
OS-DELETE VALUE(vcIni).
run gipr_DeleteProcedure in vhFcComponent.
delete procedure vhFcComponent.
return.
end. /* if viReturn le 0 */
<M-496 run CheckDaemonStatusInternal
(input icDaemonName (icDaemonName),
input viDaemonsStarted (iiStarted),
output viFcReturnSuper (oiReturnStatus)) in TDaemonUtility>
if viFcReturnSuper <> 0
then oiReturnStatus = viFcReturnSuper.
if viFcReturnSuper < 0
then ocMessage =
trim(substitute(#T-51'The daemon cannot be started: (&1)':120(4766)T-51#,icDaemonName)) + chr (10) +
trim(substitute(#T-77'See daemon log file for detailed information: (&1)':120(4767)T-77#,tqDaemonLoginInfo.tcDaemonLogFile)).
OS-DELETE VALUE(vcIni).
/*terminate the cmd process*/
if viProcessid > 0
then do:
assign viReturn = <M-8 EndProcessNoOpen
(input viProcess (iiProcessHandle)) in Win32Lib>.
if viReturn = 0 and viFcReturnSuper >= 0
then do:
assign vcErrorMessage = <M-9 GetLastErrorStr () in Win32Lib>.
if vcErrorMessage = ?
then vcErrorMessage = "".
assign ocMessage = trim(substitute(#T-25'The daemon cmd process could not be terminated: (&1)':255(5109)T-25#,icDaemonName)) + chr (10) +
trim(#T-26'It is possible that the cmd process was already gone because the daemon did not start correctlty.':255(5131)T-26#) + chr (10) +
trim(substitute(#T-27'Check the daemon log files for errors: (&1)':255(5129)T-27#,tqDaemonLoginInfo.tcDaemonLogFile)).
oiReturnStatus = -3.
/* write error to daemon log file */
output to value(tqDaemonLoginInfo.tcDaemonLogFile) append.
put unformatted
"TDaemonUtility : ":U + string(now) " : The daemon cmd process could not be stopped" skip
trim(substitute(#T-28'Operating system message: (&1)':120(4768)T-28#,vcerrorMessage)) skip.
output close.
end.
end.
run gipr_DeleteProcedure in vhFcComponent.
delete procedure vhFcComponent.
if viFcReturnSuper < 0
or viReturn = 0
then return.
end. /* when "WIN32":U */
otherwise do:
assign ocMessage = trim(substitute(#T-29'The daemon (&1) cannot be started since the operating system is not supported.':120(4388)T-29#,icDaemonName))
oiReturnStatus = -3.
return.
end. /* otherwise */
end case.
/* Pause before starting next daemon instance to avoid optimistic lock problems */
Pause 10.
end. /* do viA = 1 to viDaemonsToStart */