Select one of the following sections
The Scheduler program is responsible for monitoring task records in the Todolist table, which contains the current day's task schedule, and starting the tasks according to the their status, type, and scheduled start time. It also updates the status in the database following task execution, which is reflected on the processing status (PROSTAT) display.
The Scheduler program is invoked and controlled by using the vdcs_s utility program as follows:
To start: vdcs_s -s To pause: vdcs_s -p To exit: vdcs_s -q
The Scheduler program interfaces with the following database tables:
Processing Database
The following pseudo code illustrates the logic flow of the Scheduler program:
connect to database
WHILE the scheduler flag is not "N" LOOP
get the run flag value for next loop iteration
IF the scheduler flag is not "P" then
get the current time
read Todolist table into memory
FOR all enabled tasks in the Todolist LOOP
IF task is TIMED and it is time to do it then
set the task status to READY
End if
IF task is MONITOR then
IF it is time to do it then
set the task status to READY
ELSE
IF the task is hung then
kill jobs and restart task
End if
End if
End if
IF task status is READY then
start the task
End if
IF task status is OK and a trigger is specified then
set task status to OK!
set triggered task to READY
End if
IF task status is ERROR and a trigger is specified then
set task status to ERROR!
set triggered task to READY
End if
End loop
End if
smartsleep
End loop
disconnect from database
Connecting to the database
The Scheduler program uses the services-layer function, accessdb(), to connect to the database server.
Control status checking
Upon startup, the Scheduler program enters the control loop regardless of the status of the "scheduler" field. For each iteration thereafter, the Scheduler program calls the services layer function get_control_scheduler(). This function invokes an SQL procedure that queries the Control table for the value of the "scheduler" field and returns the value to the Scheduler program, which then sets the pause and looping variables accordingly. The scheduler flag can have the following values:
| Scheduler Flag | Scheduler action |
Y |
runs normally |
P |
pauses |
N |
exits |
Reading the Todolist table
To promote quicker data-access times, the records in the Todolist are read into direct-access memory at the start of each loop iteration. The Scheduler program uses this "copy" to access information only. All modifications are made directly to the database. So, even though the task status may be updated numerous times in the Todolist table during the course of one iteration of the Scheduler program, only the value in the "copy" is visible. Any new values will be copied, and therefore visible, on the successive iteration.
To read the Todolist table, the Scheduler program makes a call to the services layer function gettodolink(). This function builds a list of the records in the Todolist table and returns a pointer to the first element.
Identifying tasks that are ready to run
Once the task records have been copied to memory, the Scheduler program examines the type of each task. If a task is timed, the Scheduler program compares the "TaskWhenToDo" field, which contains the task's scheduled start time, and the current time. If the current time is greater than or equal to the scheduled start time, the Scheduler program makes a call to the services layer function modtaskstatus() to update the "TaskStatus" field to READY. \
For monitor tasks, the Scheduler program computes the scheduled start time by adding the "TaskLastRunTime" and "TaskFrequency" fields. If the resulting time is greater than or equal to the current time, the scheduler program uses the modtaskstatus() function to update the "TaskStatus" field to READY. As mentioned in the previous section, the updates to the "TaskStatus" field are made directly to the Todolist table and, therefore, are not visible until the next iteration of the Scheduler program.
Starting the task
When the Scheduler program identifies a task whose status is READY, it calls the internal function starttask(). This function updates the task's status to BUSY and, invokes the task job shell via the system() function using the resources specified in the "TaskHost", "TaskCPU", and "TaskJobDir" fields. It also updates the "TaskStartTime" and "TaskLastRunTime" fields with the current time. The task job shell is specified in the "TaskJobShell" field on the Todolist record.
Identifying completed tasks
When the task job shell finishes, it updates the "TaskStatus" field in the Todolist table to OK or ERROR depending on the success of the job shell.
When the Scheduler program identifies a task with an OK or ERROR status, it examines the link fields on the Todolist record to see if a subsequent task should be triggered. The link fields, which are the "LinkIfSuccessDo" and "LinkIfErrorDo" fields, may specify tasks that are to be triggered based on the condition of the "TaskStatus" value of the current task. If the current task's status is OK and there is a task specified in the "LinkIfSuccessDo" field, the Scheduler program updates the current task's status to OK! and the status of the task to be triggered to READY.
Similarly, if the current task's status is ERROR and there is a task specified in the "LinkIfErrorDo" field, the Scheduler program will update the current task's status to ERROR! and the status of the task to be triggered to READY. In both cases, the "!" indicates another task was triggered.
Identifying and restarting hung monitor tasks
The concept of a monitor task is that it runs on a user-defined frequency. If a monitor task becomes hung or its status remains BUSY, the Scheduler program will detect the condition, and it will kill all of the jobs associated with the task and restart it.
The task is identified by comparing the "TaskWarnSecs" field and the difference of the current time and the "TaskStartTime" field. If the latter is greater than the amount of time specified in the "TaskWarnSecs" field, the Scheduler program calls the internal function, kill_and_reset(). This function uses the system function, kill(), and the "TaskPid" field to determine whether the task job shell is still running. If it is, a kill signal is sent to the process. The status for the task is then set to READY.
Smart Sleep?
The final step for each iteration of the Scheduler program is to make a call to the internal function smartsleep(). This function determines whether any changes have been made to the Todolist table and adjusts the period between loop iterations accordingly. For each successive iteration of the Scheduler program for which there are no changes to the Todolist table, the period is increased by one second until it reaches the maximum period, 60 seconds. When the Todolist is modified, the period is reset to the minimum, 1 second.
Changes to the Todolist are detected by comparing the old Todolist copy with the new list copy. The smartsleep() function makes a call to the internal function compare_lists(). This function traverses both lists and compares the corresponding fields in each record until a discrepancy is found or it reaches the end of the list.
Disconnecting from the database
The Scheduler program uses the services-layer function, exitdb(), to disconnect from the database server.