scheduler.xml revision d81978a0815d5b8a75633c35e3e1f8708d36f017
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE stax SYSTEM "/shared/stax.dtd">
<!--
! CDDL HEADER START
!
! The contents of this file are subject to the terms of the
! Common Development and Distribution License, Version 1.0 only
! (the "License"). You may not use this file except in compliance
! with the License.
!
! You can obtain a copy of the license at
! trunk/opends/resource/legal-notices/OpenDS.LICENSE
! or https://OpenDS.dev.java.net/OpenDS.LICENSE.
! See the License for the specific language governing permissions
! and limitations under the License.
!
! When distributing Covered Code, include this CDDL HEADER in each
! file and include the License file at
! trunk/opends/resource/legal-notices/OpenDS.LICENSE. If applicable,
! add the following below this CDDL HEADER, with the fields enclosed
! by brackets "[]" replaced with your own identifying information:
! Portions Copyright [yyyy] [name of copyright owner]
!
! CDDL HEADER END
!
! Copyright 2008 Sun Microsystems, Inc.
! -->
<stax>
<defaultcall function="scheduler"/>
<!-- ************************************************************ -->
<function name="scheduler" scope="local">
<function-map-args>
<function-arg-def name="phase" type="required">
<function-arg-description>
phase object
</function-arg-description>
</function-arg-def>
<function-arg-def name="instances" type="required">
<function-arg-description>
instance object
</function-arg-description>
</function-arg-def>
<function-arg-def name="suffix" type="required">
<function-arg-description>
suffix object
</function-arg-description>
</function-arg-def>
<function-arg-def name="scheduler" type="required">
<function-arg-description>
scheduler object
</function-arg-description>
</function-arg-def>
<function-arg-def name="scenario" type="required">
<function-arg-description>
scenario object
</function-arg-description>
</function-arg-def>
</function-map-args>
<sequence>
<!--========== Call preambule =========-->
<script>
tagAttr = []
durationValue = '%s%s' % \
(scenario.getDurationTime(),scenario.getDurationUnit())
tagAttr.append(['duration',durationValue])
</script>
<call function="'phasePreamble'">
{ 'phase' : phase,
'tagAttr' : tagAttr,
'fileFd' : LOG_MAIN_FD }
</call>
<!--==== Get the clients list from all modules ==============-->
<call function="'getEnabledClients'">{'scheduler':scheduler}</call>
<script>clients = STAXResult </script>
<!--==== Run clients only if no errors occured before ===========-->
<if expr="ERR_NUM[0] == 0">
<sequence>
<!--==== Start the system test and launch client's process ====-->
<call function="'runClients'">
{
'clients' : clients,
'instances' : instances,
'scenario' : scenario,
'suffix' : suffix
}
</call>
<!--============ Merge files ===========-->
<call function="'mergeClientsFiles'">
{
'scheduler' : scheduler,
'fileFd' : LOG_MAIN_FD
}
</call>
<!--==== Calculate phase percentage ==========-->
<script>
nbClients = len(clients)
nbClientSuccess = 0
percentageResult = 0
</script>
<iterate in="clients" var="client">
<script>
if client.getResult() == 'SUCCESS':
nbClientSuccess += 1
</script>
</iterate>
<script>
percentageResult = nbClientSuccess * 100
percentageResult = percentageResult / nbClients
phase.setPercentage(percentageResult)
</script>
</sequence>
</if>
<!--========== Call postphase =========-->
<call function="'phasePostamble'">
{
'phase' : phase,
'fileFd' : LOG_MAIN_FD
}
</call>
</sequence>
</function>
<!-- ************************************************************ -->
<function name="runClients" scope="local">
<function-map-args>
<function-arg-def name="clients" type="required"/>
<function-arg-def name="instances" type="required"/>
<function-arg-def name="scenario" type="required"/>
<function-arg-def name="suffix" type="required"/>
</function-map-args>
<sequence>
<!--========== Define variables =========-->
<script>
finishedClients = STAXGlobal([])
</script>
<!--========== Run clients in parallel =========-->
<paralleliterate in="clients" var="client">
<sequence>
<!--==== calculate start/stop time, open dedicated logfile ====-->
<script>
start = client.getStart()
stop = client.getStop()
dependency = client.getDependency()
if stop == NOT_DEFINED:
stop = 't100'
# convert durationTime in second
if scenario.getDurationUnit() == 's':
durationTime = int(scenario.getDurationTime())
elif scenario.getDurationUnit() == 'm':
durationTime = int(scenario.getDurationTime()) * 60
elif scenario.getDurationUnit() == 'h':
durationTime = int(scenario.getDurationTime()) * 3600
elif scenario.getDurationUnit() == 'd':
durationTime = int(scenario.getDurationTime()) * 24 * 3600
if (start != NOT_DEFINED and stop != NOT_DEFINED):
# remove t for t10, t20...
start = start.split('t')[1]
stop = stop.split('t')[1]
start = int(start) * int(durationTime) / 100
startms = int(start) * 1000
stop = int(stop) * int(durationTime) / 100
clientDuration = stop - start
</script>
<!--==== open logfile ====-->
<call function="'getLogFileName'">
{
'type' : 'client',
'object' : client,
'prefix' : 'client'
}
</call>
<script>
logFile = STAXResult[0]
fileFd = open(logFile,'w')
params = client.getParams()
paramsList = ''
for p in params:
paramsList = '%s%s:%s ' % (paramsList,p[0],p[1])
</script>
<!-- == Write tag for xml report -->
<call function="'writeStartTagClient'">
{
'client' : client,
'extraParameters' : 'params=\"%s\"' % paramsList,
'fileFd' : fileFd
}
</call>
<!--== Start is NOT defined in client attribute ==-->
<if expr="start == NOT_DEFINED">
<sequence>
<if expr="dependency == NOT_DEFINED">
<sequence>
<script>
str = 'ERROR: client %s should have' % client.getName()
str = '%s start or dependency attribute defined' % str
</script>
<message> str </message>
<call function="'writeMessage'">
{ 'fileFd' : fileFd,
'content' : str
}
</call>
<script>ERR_NUM[0] += 1</script>
</sequence>
<else>
<sequence>
<!--== Start is NOT defined, dependency is defined ==-->
<call function="'sleepForDependency'">
{
'client' : client,
'clients' : clients,
'durationTime' : durationTime,
'fileFd' : fileFd
}
</call>
</sequence>
</else>
</if>
</sequence>
<!--== Start is defined in client attribute ==-->
<else>
<sequence>
<!--=== Sleep and wait to start the client when specified ===-->
<call function="'sleep'">
{ 'location' : STAXServiceMachine,
'sleepForMilliSeconds' : startms,
'fileFd' : fileFd
}
</call>
<!--=== Wait if client depends on other clients ===-->
<if expr="dependency != NOT_DEFINED">
<sequence>
<call function="'sleepForDependency'">
{
'client' : client,
'clients' : clients,
'durationTime' : durationTime,
'fileFd' : fileFd
}
</call>
</sequence>
</if>
</sequence>
</else>
</if>
<!--== Run the client ==-->
<call function="'runClient'">
{
'client' : client,
'duration' : clientDuration,
'instances' : instances,
'suffix' : suffix,
'fileFd' : fileFd
}
</call>
<!-- == Write tag for xml report -->
<call function="'writeEndTagClient'">
{ 'fileFd' : fileFd }
</call>
<!--==== close logfile ====-->
<script>
fileFd.close()
fileFd = ''
</script>
</sequence>
</paralleliterate>
</sequence>
</function>
<!-- ************************************************************ -->
<function name="runClient" scope="local">
<function-map-args>
<function-arg-def name="client" type="required"/>
<function-arg-def name="duration" type="required"/>
<function-arg-def name="instances" type="required"/>
<function-arg-def name="suffix" type="required"/>
<function-arg-def name="fileFd" type="required"/>
</function-map-args>
<sequence>
<script>
startTime=strftime("%Y%m%d@%H:%M:%S",localtime())
client.setStartDate(startTime)
errNum = 0
</script>
<!--=============== Log info =======================================-->
<if expr="client.getHost() == NOT_DEFINED">
<sequence>
<script>
str = '++ START CLIENT %s' % (client.getName())
str = '%s (id=%s)' % (str, client.getId())
str = '%s at %s' % (str, startTime)
str = '%s, max duration is %s sec' % (str, duration)
</script>
<message> str </message>
<!--<call function="'writeMessage'">
{ 'fileFd' : fileFd,
'content' : 'Client id %s' % client.getId()
}
</call>-->
</sequence>
<else>
<sequence>
<script>
str = '++ START CLIENT %s' % (client.getName())
str = '%s (id=%s)' % (str, client.getId())
str = '%s running on %s' % (str, client.getHost())
str = '%s at %s' % (str, startTime)
str = '%s, max duration is %s sec' % (str, duration)
</script>
<message> str </message>
<!--<call function="'writeMessage'">
{ 'fileFd' : fileFd,
'content' : str
}
</call>-->
</sequence>
</else>
</if>
<!--=============== Run client phases ==============================-->
<call function="'runClientPreamble'">
{
'client' : client,
'instances' : instances,
'duration' : duration,
'suffix' : suffix,
'fileFd' : fileFd
}
</call>
<script> errNum += STAXResult </script>
<call function="'runClientMain'">
{
'client' : client,
'instances' : instances,
'duration' : duration,
'suffix' : suffix,
'fileFd' : fileFd
}
</call>
<script>
errNum += STAXResult[0]
outFileRun = STAXResult[1]
</script>
<call function="'runClientPostamble'">
{
'client' : client,
'instances' : instances,
'duration' : duration,
'suffix' : suffix,
'outFile' : outFileRun,
'fileFd' : fileFd
}
</call>
<script> errNum += STAXResult </script>
<!--=============== Log info =======================================-->
<script>
stopTime=strftime("%Y%m%d@%H:%M:%S",localtime())
client.setStopDate(stopTime)
</script>
<message>
'-- STOP CLIENT %s (id %s) running on %s at %s' %\
(client.getName(),client.getId(),client.getHost(),stopTime)
</message>
<!--=============== Set client result ==============================-->
<if expr="errNum == 0">
<script>
result = 'SUCCESS'
</script>
<else>
<script>
result = 'FAIL'
ERR_NUM[0] += 1
</script>
</else>
</if>
<script>
client.setResult(result)
attrs = 'status=\"%s\" startDate=\"%s\" stopDate=\"%s\"' % \
(result,client.getStartDate(),client.getStopDate())
fileFd.write('\n&lt;clientResult %s/&gt;\n' % attrs)
</script>
<!-- DO NOT record number of error(s) found by clients -->
<!-- each should use checkRC and ERR_NUM[0] is already updated -->
<!-- <script>
ERR_NUM[0] += errNum
</script> -->
</sequence>
</function>
<!-- ************************************************************ -->
<function name="runClientPreamble" scope="local">
<function-map-args>
<function-arg-def name="client" type="required"/>
<function-arg-def name="duration" type="required"/>
<function-arg-def name="instances" type="required"/>
<function-arg-def name="suffix" type="required"/>
<function-arg-def name="fileFd" type="required"/>
</function-map-args>
<sequence>
<call function="'isFile'">
{
'location' : client.getHost(),
'fileName' : '%s/%sPreamble.xml' % (client.getPath(),client.getName()),
}
</call>
<script>
fileExist = STAXResult
</script>
<if expr="fileExist == TRUE">
<sequence>
<call function="'writeStartTagOperation'">
{ 'tagName' : 'clientPreamble',
'fileFd' : fileFd }
</call>
<script>
errNum = 0
errMsg = ''
</script>
<!--============= Start the client under a timer =================-->
<!--== open logfile for details ==-->
<!-- All informations loged in this this function will -->
<!-- not be displayed in the main report, to avoid broken xml file-->
<call function="'getLogFileName'">
{
'type' : 'client',
'object' : client,
'prefix' : 'client_details_preamble'
}
</call>
<script>
logFileDetails = STAXResult[0]
logFileDetailsName = STAXResult[1]
logFileDetailsRelativePath = logFileDetails.replace(LOG_DIR,'.')
fileFdDetails = open(logFileDetails,'w')
outFile = '%s/%s.txt' % (client.getLogDir(),logFileDetailsName)
</script>
<message>
' Start preamble for %s (id=%s) running on %s' % \
(client.getName(),client.getId(), client.getHost())
</message>
<!-- ==== Log info ====================================-->
<!--== Write root tag for xml details file -->
<script>
str = '&lt;?xml version=\"1.0\" encoding=\"UTF-8\"'
str = '%s standalone=\"no\"?&gt;\n' % str
str = '%s &lt;?xml-stylesheet type="text/xsl"' % str
str = '%s href="clientDetails.xsl"?>\n' % str
fileFdDetails.write(str)
</script>
<call function="'writeStartTagClient'">
{
'client' : client,
'extraParameters' : 'xmlns:xlink="http://www.w3.org/1999/xlink"',
'fileFd' : fileFdDetails
}
</call>
<call function="'writeMessage'">
{
'content' : 'Client Preamble details',
'fileFd' : fileFdDetails,
}
</call>
<!--=============== run preamble =================================-->
<import machine="'%s' % (client.getHost())"
file="'%s/%sPreamble.xml' % (client.getPath(),client.getName())"/>
<call function="'%sPreamble' % client.getName()">
{
'client' : client,
'instances' : instances,
'duration' : duration,
'suffix' : suffix,
'outFile' : outFile,
'fileFd' : fileFdDetails
}
</call>
<script>
errNum = STAXResult
</script>
<!--=============== Log info =====================================-->
<call function="'writeMessage'">
{
'content' : 'Client preamble',
'xlink' : logFileDetailsRelativePath,
'fileFd' : fileFd
}
</call>
<!--== Close root tag for xml details file -->
<call function="'writeEndTagClient'">
{ 'fileFd' : fileFdDetails }
</call>
<script> fileFdDetails.close() </script>
<message>
' Stop pretamble for %s (id=%s) running on %s' % \
(client.getName(),client.getId(), client.getHost())
</message>
<call function="'checkRC'">
{
'returncode' : errNum,
'result' : errMsg,
'fileFd' : fileFd
}
</call>
<call function="'writeEndTagOperation'">{'fileFd' : fileFd}</call>
</sequence>
<else>
<message>
' File not found, skip preamble : %s/%sPreamble.xml' % \
(client.getPath(),client.getName())
</message>
</else>
</if>
<return>errNum</return>
</sequence>
</function>
<!-- ************************************************************ -->
<function name="runClientPostamble" scope="local">
<function-map-args>
<function-arg-def name="client" type="required"/>
<function-arg-def name="duration" type="required"/>
<function-arg-def name="instances" type="required"/>
<function-arg-def name="suffix" type="required"/>
<function-arg-def name="outFile" type="required"/>
<function-arg-def name="fileFd" type="required"/>
</function-map-args>
<sequence>
<call function="'isFile'">
{
'location' : client.getHost(),
'fileName' : '%s/%sPostamble.xml'%(client.getPath(),client.getName()),
}
</call>
<script>
fileExist = STAXResult
</script>
<if expr="fileExist == TRUE">
<sequence>
<call function="'writeStartTagOperation'">
{ 'tagName' : 'clientPostamble',
'fileFd' : fileFd }
</call>
<script>
errNum = 0
errMsg = ''
</script>
<!--============= Start the client under a timer =================-->
<!--== open logfile for details ==-->
<!-- All informations loged in this this function will -->
<!-- not be displayed in the main report, to avoid broken xml file-->
<call function="'getLogFileName'">
{
'type' : 'client',
'object' : client,
'prefix' : 'client_details_postamble'
}
</call>
<script>
logFileDetails = STAXResult[0]
logFileDetailsName = STAXResult[1]
logFileDetailsRelativePath = logFileDetails.replace(LOG_DIR,'.')
fileFdDetails = open(logFileDetails,'w')
</script>
<message>
' Start postamble for %s (id=%s) running on %s' % \
(client.getName(),client.getId(), client.getHost())
</message>
<!-- ==== Log info ====================================-->
<!--== Write root tag for xml details file -->
<script>
str = '&lt;?xml version=\"1.0\" encoding=\"UTF-8\"'
str = '%s standalone=\"no\"?&gt;\n' % str
str = '%s &lt;?xml-stylesheet type="text/xsl"' % str
str = '%s href="clientDetails.xsl"?>\n' % str
fileFdDetails.write(str)
</script>
<call function="'writeStartTagClient'">
{
'client' : client,
'extraParameters' : 'xmlns:xlink="http://www.w3.org/1999/xlink"',
'fileFd' : fileFdDetails
}
</call>
<call function="'writeMessage'">
{
'content' : 'Client Postamble details',
'fileFd' : fileFdDetails,
}
</call>
<!--=============== run postamble ================================-->
<import machine="'%s' % (client.getHost())"
file="'%s/%sPostamble.xml' % (client.getPath(),client.getName())"/>
<call function="'%sPostamble' % client.getName()">
{
'client' : client,
'instances' : instances,
'duration' : duration,
'suffix' : suffix,
'outFile' : outFile,
'fileFd' : fileFdDetails
}
</call>
<script>
errNum = STAXResult
</script>
<!--=============== Log info =====================================-->
<call function="'writeMessage'">
{
'content' : 'Client postamble',
'xlink' : logFileDetailsRelativePath,
'fileFd' : fileFd
}
</call>
<!--== Close root tag for xml details file -->
<call function="'writeEndTagClient'">
{ 'fileFd' : fileFdDetails }
</call>
<script> fileFdDetails.close() </script>
<message>
' Stop postamble for %s (id=%s) running on %s' % \
(client.getName(),client.getId(), client.getHost())
</message>
<call function="'checkRC'">
{
'returncode' : errNum,
'result' : errMsg,
'fileFd' : fileFd
}
</call>
<call function="'writeEndTagOperation'">{'fileFd' : fileFd}</call>
</sequence>
<else>
<message>
' File not found, skip postamble : %s/%sPostamble.xml' % \
(client.getPath(),client.getName())
</message>
</else>
</if>
<return>errNum</return>
</sequence>
</function>
<!-- ************************************************************ -->
<function name="runClientMain" scope="local">
<function-map-args>
<function-arg-def name="client" type="required"/>
<function-arg-def name="duration" type="required"/>
<function-arg-def name="instances" type="required"/>
<function-arg-def name="suffix" type="required"/>
<function-arg-def name="fileFd" type="required"/>
</function-map-args>
<sequence>
<call function="'writeStartTagOperation'">
{ 'tagName' : 'clientRun',
'fileFd' : fileFd }
</call>
<script>
errNum = 0
errMsg = ''
</script>
<!--=============== Start the client under a timer =================-->
<!--== open logfile for details ==-->
<!-- All informations loged in this this function will -->
<!-- not be displayed in the main report, to avoid broken xml file -->
<call function="'getLogFileName'">
{
'type' : 'client',
'object' : client,
'prefix' : 'client_details'
}
</call>
<script>
logFileDetails = STAXResult[0]
logFileDetailsName = STAXResult[1]
logFileDetailsRelativePath = logFileDetails.replace(LOG_DIR,'.')
fileFdDetails = open(logFileDetails,'w')
outFile = '%s/%s.txt' % (client.getLogDir(),logFileDetailsName)
outFileRelativePath = outFile.replace(LOG_DIR,'.')
</script>
<message>
' Start run for %s (id=%s) running on %s' % \
(client.getName(),client.getId(), client.getHost())
</message>
<call function="'startTimer'">
{
'client' : client,
'instances' : instances,
'duration' : duration,
'suffix' : suffix,
'outFile' : outFile,
'fileFd' : fileFdDetails
}
</call>
<script>
fileFdDetails.close()
errNum += STAXResult[0]
timerKilled = STAXResult[1]
</script>
<!--=============== Log info =======================================-->
<call function="'writeMessage'">
{
'content' : 'Details of the client',
'xlink' : logFileDetailsRelativePath,
'fileFd' : fileFd
}
</call>
<call function="'writeMessage'">
{
'content' : 'Client outPuts',
'xlink' : outFileRelativePath,
'fileFd' : fileFd
}
</call>
<!--=============== Analyze client run status ======================-->
<if expr="timerKilled == TRUE">
<sequence>
<script>
errMsg = 'ERROR: client %s has been killed,' % client.getName()
</script>
<message> errMsg </message>
<script>
errNum += 1
</script>
</sequence>
<else>
<message>
' Stop run for %s (id=%s) running on %s' % \
(client.getName(),client.getId(), client.getHost())
</message>
</else>
</if>
<script>
finishedClients.append(client.getId())
</script>
<call function="'checkRC'">
{
'returncode' : errNum,
'result' : errMsg,
'fileFd' : fileFd
}
</call>
<call function="'writeEndTagOperation'">{'fileFd' : fileFd}</call>
<return> [ errNum , outFile ]</return>
</sequence>
</function>
<!-- ************************************************************ -->
<function name="startTimer" scope="local">
<function-map-args>
<function-arg-def name="client" type="required"/>
<function-arg-def name="duration" type="required"/>
<function-arg-def name="instances" type="required"/>
<function-arg-def name="suffix" type="required"/>
<function-arg-def name="outFile" type="required"/>
<function-arg-def name="fileFd" type="required"/>
</function-map-args>
<sequence>
<!-- ==== Log info ====================================-->
<!--== Write root tag for xml details file -->
<script>
str = '&lt;?xml version=\"1.0\" encoding=\"UTF-8\"'
str = '%s standalone=\"no\"?&gt;\n' % str
str = '%s &lt;?xml-stylesheet type="text/xsl"' % str
str = '%s href="clientDetails.xsl"?>\n' % str
fileFd.write(str)
</script>
<call function="'writeStartTagClient'">
{
'client' : client,
'extraParameters' : 'xmlns:xlink="http://www.w3.org/1999/xlink"',
'fileFd' : fileFd
}
</call>
<!--=============== Select local/shared client file ================-->
<script>
timerKilled = TRUE
</script>
<!--================================================================-->
<!--====== run the client, exit if time exceed duration time ======-->
<timer duration="'%ss' % duration">
<sequence>
<!-- Check that staf is running on the client -->
<call function="'pingStaf'">
{ 'targetHost' : client.getHost(),
'fileFd' : fileFd}
</call>
<script>
pingRC = STAXResult[0]
</script>
<if expr="pingRC == 0">
<sequence>
<import machine="'%s' % (client.getHost())"
file="'%s/%s.xml' % (client.getPath(),client.getName())"/>
<call function="'%s' % client.getName()">
{
'client' : client,
'instances' : instances,
'duration' : duration,
'suffix' : suffix,
'outFile' : outFile,
'fileFd' : fileFd
}
</call>
<script>errNum = STAXResult</script>
</sequence>
<else>
<!-- staf does not answer ping on client host -->
<script> errNum = 1 </script>
</else>
</if>
<script>timerKilled = FALSE</script>
</sequence>
</timer>
<if expr="timerKilled == TRUE">
<!-- TBD try to finished xml client detail file -->
<call function="'writeEndTagOperation'">{'fileFd' : fileFd}</call>
</if>
<!--=============== Log info =======================================-->
<!--== Close root tag for xml details file -->
<call function="'writeEndTagClient'">
{ 'fileFd' : fileFd }
</call>
<return> [ errNum, timerKilled ] </return>
</sequence>
</function>
<!-- ************************************************************ -->
<function name="sleepForDependency" scope="local">
<function-map-args>
<function-arg-def name="location" type="optional"
default="'%s' % STAXServiceMachine"/>
<function-arg-def name="client" type="required"/>
<function-arg-def name="clients" type="required"/>
<function-arg-def name="durationTime" type="required"/>
<function-arg-def name="fileFd" type="required"/>
</function-map-args>
<sequence>
<!--== Convert dependencyId attribute value into a list ==-->
<script>
clientOfClientIds = []
clientOfClientIdsTmp = client.getDependency()
# if id separated by coma, make the list
if clientOfClientIdsTmp.count(',') > 0:
clientOfClientIds = clientOfClientIdsTmp.split(',')
# if id separated by whitespace, make the list
elif clientOfClientIdsTmp.count(' ') > 0:
clientOfClientIds = clientOfClientIdsTmp.split(' ')
# if id separated by ';', make the list
elif clientOfClientIdsTmp.count(';') > 0:
clientOfClientIds = clientOfClientIdsTmp.split(';')
# sounds like only one id
else:
clientOfClientIds.append(clientOfClientIdsTmp)
# remove whitespace characters
i=0
while i &lt; len(clientOfClientIds):
clientOfClientIds[i] = clientOfClientIds[i].replace(' ','')
i += 1
</script>
<!--== For each clientId, wait it has been completed ==-->
<iterate in="clientOfClientIds" var="clientOfClientId">
<sequence>
<!--== Wait until clientOfClient is finished ==-->
<!--== TBD : should not be durationTime but ==-->
<!--== "durationTime - time already runed" ==-->
<timer duration="'%ss' % durationTime">
<loop until="clientOfClientId in finishedClients">
<sequence>
<call function="'sleep'">
{
'location' : location,
'sleepForMilliSeconds' : '3000',
'silentMode' : FALSE ,
'fileFd' : fileFd
}
</call>
</sequence>
</loop>
</timer>
</sequence>
</iterate>
</sequence>
</function>
</stax>