ProFTPD Developer's Guide: Schedules

ProFTPD Version 1.2

Table of Contents

The core engine provides a mechanism for setting schedules, which can be used to perform actions on a recurring basis. The triggering of schedules is based on "loops", the number of times the daemon loops around while waiting for incoming connections. This means that schedules, rather than being based on a clock, are based on server activity: a busy server loops more quickly than a quiescent one. The main functions to use when dealing with schedules are defined in support.h:

  void schedule(void (*cb)(void *, void *, void *, void *), int nloops, void *a1, void *a2,
    void *a3, void *a4)
  void run_schedule()

The schedule() function (which would ideally be named add_schedule()) registers a schedule callback function cb, which handles four void * arguments, to be run every nloops. When called, cb will be passed the registered pointers a1 through a4, which correspond to the four void * arguments expected by the cb function.

The run_schedule() function (which would ideally be named run_schedules()) is called by the internal engine, and should not be invoked anywhere else in the code without a very good reason.

Example Schedule Callback
An excerpt from main.c, this defines the schedule callback for rehashing -- the registration of this schedule occurs in the SIGHUP signal handler, sig_rehash():

static RETSIGTYPE sig_rehash(int signo) {
  schedule(main_rehash, 0, NULL, NULL, NULL, NULL);

  signal(SIGHUP, sig_rehash);
Here one sees how the rehashing of the configuration file, signalled via SIGHUP, is scheduled:
void main_rehash(void *d1, void *d2, void *d3, void *d4) {
  /* rehashing code here */


In this example, the nloops value given, 0, means that that schedule will be run the next time run_schedule() is called. The nloops value is used to determine the frequency with which a schedule fires, assuming it is meant to be a recurring schedule. Which brings up a good point: schedules inherently are one-time triggers. They fire, then are removed from the list of impending schedules. Unlike timers, schedules cannot re-register themselves simply by returning a certain value. Instead, if a recurring schedule is desired, simply have the callback function call schedule() again to add that callback back to the schedule list.

How Schedules Work
The schedule mechanism is based on counters associated with each schedule object, the nloops member. At certain points in the code, those counters are decremented. Once the counter reaches zero, the callback function for that schedule object is triggered. Schedule objects are registered and added to an internally maintained list, and removed from that list once the callback has triggered.

The nloops counter is decremented by run_schedule(), which is invoked at four points in the core:

Similar to timers, schedules do not provide fine-grained time resolution, and are not meant for precise work. In fact, the nature of the loops means the time at which a schedule is triggered is very coarse. Schedules are a mechanism for scheduling something to happen at some point in the future, when that activity is not time-critical. Periodically checking state, performing scrubbing or cleanup activities, these are activities suited for scheduling.

Table of Contents

Author: $Author: castaglia $
Last Updated: $Date: 2003/01/24 06:59:48 $

© Copyright 2000-2003 TJ Saunders
All Rights Reserved