Reindented server/core/housekeeper.c
This commit is contained in:
parent
486f724dc1
commit
3189a47fc5
@ -36,9 +36,9 @@
|
||||
* @verbatim
|
||||
* Revision History
|
||||
*
|
||||
* Date Who Description
|
||||
* 29/08/14 Mark Riddoch Initial implementation
|
||||
* 22/10/14 Mark Riddoch Addition of one-shot tasks
|
||||
* Date Who Description
|
||||
* 29/08/14 Mark Riddoch Initial implementation
|
||||
* 22/10/14 Mark Riddoch Addition of one-shot tasks
|
||||
*
|
||||
* @endverbatim
|
||||
*/
|
||||
@ -46,16 +46,16 @@
|
||||
/**
|
||||
* List of all tasks that need to be run
|
||||
*/
|
||||
static HKTASK *tasks = NULL;
|
||||
static HKTASK *tasks = NULL;
|
||||
/**
|
||||
* Spinlock to protect the tasks list
|
||||
*/
|
||||
static SPINLOCK tasklock = SPINLOCK_INIT;
|
||||
static SPINLOCK tasklock = SPINLOCK_INIT;
|
||||
|
||||
static int do_shutdown = 0;
|
||||
unsigned long hkheartbeat = 0;
|
||||
static int do_shutdown = 0;
|
||||
unsigned long hkheartbeat = 0;
|
||||
|
||||
static void hkthread(void *);
|
||||
static void hkthread(void *);
|
||||
|
||||
/**
|
||||
* Initialise the housekeeper thread
|
||||
@ -63,7 +63,7 @@ static void hkthread(void *);
|
||||
void
|
||||
hkinit()
|
||||
{
|
||||
thread_start(hkthread, NULL);
|
||||
thread_start(hkthread, NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -76,63 +76,64 @@ hkinit()
|
||||
*
|
||||
* Task names must be unique.
|
||||
*
|
||||
* @param name The unique name for this housekeeper task
|
||||
* @param taskfn The function to call for the task
|
||||
* @param data Data to pass to the task function
|
||||
* @param frequency How often to run the task, expressed in seconds
|
||||
* @return Return the time in seconds when the task will be first run if the task was added, otherwise 0
|
||||
* @param name The unique name for this housekeeper task
|
||||
* @param taskfn The function to call for the task
|
||||
* @param data Data to pass to the task function
|
||||
* @param frequency How often to run the task, expressed in seconds
|
||||
* @return Return the time in seconds when the task will be first run
|
||||
* if the task was added, otherwise 0
|
||||
*/
|
||||
int
|
||||
hktask_add(char *name, void (*taskfn)(void *), void *data, int frequency)
|
||||
{
|
||||
HKTASK *task, *ptr;
|
||||
HKTASK *task, *ptr;
|
||||
|
||||
if ((task = (HKTASK *)malloc(sizeof(HKTASK))) == NULL)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
if ((task->name = strdup(name)) == NULL)
|
||||
{
|
||||
free(task);
|
||||
return 0;
|
||||
}
|
||||
task->task = taskfn;
|
||||
task->data = data;
|
||||
task->frequency = frequency;
|
||||
task->type = HK_REPEATED;
|
||||
task->nextdue = time(0) + frequency;
|
||||
task->next = NULL;
|
||||
spinlock_acquire(&tasklock);
|
||||
ptr = tasks;
|
||||
while (ptr && ptr->next)
|
||||
{
|
||||
if (strcmp(ptr->name, name) == 0)
|
||||
{
|
||||
spinlock_release(&tasklock);
|
||||
free(task->name);
|
||||
free(task);
|
||||
return 0;
|
||||
}
|
||||
ptr = ptr->next;
|
||||
}
|
||||
if (ptr)
|
||||
{
|
||||
if (strcmp(ptr->name, name) == 0)
|
||||
{
|
||||
spinlock_release(&tasklock);
|
||||
free(task->name);
|
||||
free(task);
|
||||
return 0;
|
||||
}
|
||||
ptr->next = task;
|
||||
}
|
||||
else
|
||||
{
|
||||
tasks = task;
|
||||
}
|
||||
spinlock_release(&tasklock);
|
||||
if ((task = (HKTASK *)malloc(sizeof(HKTASK))) == NULL)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
if ((task->name = strdup(name)) == NULL)
|
||||
{
|
||||
free(task);
|
||||
return 0;
|
||||
}
|
||||
task->task = taskfn;
|
||||
task->data = data;
|
||||
task->frequency = frequency;
|
||||
task->type = HK_REPEATED;
|
||||
task->nextdue = time(0) + frequency;
|
||||
task->next = NULL;
|
||||
spinlock_acquire(&tasklock);
|
||||
ptr = tasks;
|
||||
while (ptr && ptr->next)
|
||||
{
|
||||
if (strcmp(ptr->name, name) == 0)
|
||||
{
|
||||
spinlock_release(&tasklock);
|
||||
free(task->name);
|
||||
free(task);
|
||||
return 0;
|
||||
}
|
||||
ptr = ptr->next;
|
||||
}
|
||||
if (ptr)
|
||||
{
|
||||
if (strcmp(ptr->name, name) == 0)
|
||||
{
|
||||
spinlock_release(&tasklock);
|
||||
free(task->name);
|
||||
free(task);
|
||||
return 0;
|
||||
}
|
||||
ptr->next = task;
|
||||
}
|
||||
else
|
||||
{
|
||||
tasks = task;
|
||||
}
|
||||
spinlock_release(&tasklock);
|
||||
|
||||
return task->nextdue;
|
||||
return task->nextdue;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -140,90 +141,99 @@ HKTASK *task, *ptr;
|
||||
*
|
||||
* Task names must be unique.
|
||||
*
|
||||
* @param name The unique name for this housekeeper task
|
||||
* @param taskfn The function to call for the task
|
||||
* @param data Data to pass to the task function
|
||||
* @param when How many second until the task is executed
|
||||
* @return Return the time in seconds when the task will be first run if the task was added, otherwise 0
|
||||
* @param name The unique name for this housekeeper task
|
||||
* @param taskfn The function to call for the task
|
||||
* @param data Data to pass to the task function
|
||||
* @param when How many second until the task is executed
|
||||
* @return Return the time in seconds when the task will be first run
|
||||
* if the task was added, otherwise 0
|
||||
*
|
||||
*/
|
||||
int
|
||||
hktask_oneshot(char *name, void (*taskfn)(void *), void *data, int when)
|
||||
{
|
||||
HKTASK *task, *ptr;
|
||||
HKTASK *task, *ptr;
|
||||
|
||||
if ((task = (HKTASK *)malloc(sizeof(HKTASK))) == NULL)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
if ((task->name = strdup(name)) == NULL)
|
||||
{
|
||||
free(task);
|
||||
return 0;
|
||||
}
|
||||
task->task = taskfn;
|
||||
task->data = data;
|
||||
task->frequency = 0;
|
||||
task->type = HK_ONESHOT;
|
||||
task->nextdue = time(0) + when;
|
||||
task->next = NULL;
|
||||
spinlock_acquire(&tasklock);
|
||||
ptr = tasks;
|
||||
while (ptr && ptr->next)
|
||||
{
|
||||
if (strcmp(ptr->name, name) == 0)
|
||||
{
|
||||
spinlock_release(&tasklock);
|
||||
free(task->name);
|
||||
free(task);
|
||||
return 0;
|
||||
}
|
||||
ptr = ptr->next;
|
||||
}
|
||||
if (ptr)
|
||||
ptr->next = task;
|
||||
else
|
||||
tasks = task;
|
||||
spinlock_release(&tasklock);
|
||||
if ((task = (HKTASK *)malloc(sizeof(HKTASK))) == NULL)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
if ((task->name = strdup(name)) == NULL)
|
||||
{
|
||||
free(task);
|
||||
return 0;
|
||||
}
|
||||
task->task = taskfn;
|
||||
task->data = data;
|
||||
task->frequency = 0;
|
||||
task->type = HK_ONESHOT;
|
||||
task->nextdue = time(0) + when;
|
||||
task->next = NULL;
|
||||
spinlock_acquire(&tasklock);
|
||||
ptr = tasks;
|
||||
while (ptr && ptr->next)
|
||||
{
|
||||
if (strcmp(ptr->name, name) == 0)
|
||||
{
|
||||
spinlock_release(&tasklock);
|
||||
free(task->name);
|
||||
free(task);
|
||||
return 0;
|
||||
}
|
||||
ptr = ptr->next;
|
||||
}
|
||||
if (ptr)
|
||||
{
|
||||
ptr->next = task;
|
||||
}
|
||||
else
|
||||
{
|
||||
tasks = task;
|
||||
}
|
||||
spinlock_release(&tasklock);
|
||||
|
||||
return task->nextdue;
|
||||
return task->nextdue;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Remove a named task from the housekeepers task list
|
||||
*
|
||||
* @param name The task name to remove
|
||||
* @return Returns 0 if the task could not be removed
|
||||
* @param name The task name to remove
|
||||
* @return Returns 0 if the task could not be removed
|
||||
*/
|
||||
int
|
||||
hktask_remove(char *name)
|
||||
{
|
||||
HKTASK *ptr, *lptr = NULL;
|
||||
HKTASK *ptr, *lptr = NULL;
|
||||
|
||||
spinlock_acquire(&tasklock);
|
||||
ptr = tasks;
|
||||
while (ptr && strcmp(ptr->name, name) != 0)
|
||||
{
|
||||
lptr = ptr;
|
||||
ptr = ptr->next;
|
||||
}
|
||||
if (ptr && lptr)
|
||||
lptr->next = ptr->next;
|
||||
else if (ptr)
|
||||
tasks = ptr->next;
|
||||
spinlock_release(&tasklock);
|
||||
spinlock_acquire(&tasklock);
|
||||
ptr = tasks;
|
||||
while (ptr && strcmp(ptr->name, name) != 0)
|
||||
{
|
||||
lptr = ptr;
|
||||
ptr = ptr->next;
|
||||
}
|
||||
if (ptr && lptr)
|
||||
{
|
||||
lptr->next = ptr->next;
|
||||
}
|
||||
else if (ptr)
|
||||
{
|
||||
tasks = ptr->next;
|
||||
}
|
||||
spinlock_release(&tasklock);
|
||||
|
||||
if (ptr)
|
||||
{
|
||||
free(ptr->name);
|
||||
free(ptr);
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
if (ptr)
|
||||
{
|
||||
free(ptr->name);
|
||||
free(ptr);
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -240,48 +250,54 @@ HKTASK *ptr, *lptr = NULL;
|
||||
* It is vital that the task->nextdue tiem is updated before the task
|
||||
* is run.
|
||||
*
|
||||
* @param data Unused, here to satisfy the thread system
|
||||
* @param data Unused, here to satisfy the thread system
|
||||
*/
|
||||
void
|
||||
hkthread(void *data)
|
||||
{
|
||||
HKTASK *ptr;
|
||||
time_t now;
|
||||
void (*taskfn)(void *);
|
||||
void *taskdata;
|
||||
int i;
|
||||
HKTASK *ptr;
|
||||
time_t now;
|
||||
void (*taskfn)(void *);
|
||||
void *taskdata;
|
||||
int i;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
for (i = 0; i < 10; i++)
|
||||
{
|
||||
if (do_shutdown)
|
||||
return;
|
||||
thread_millisleep(100);
|
||||
hkheartbeat++;
|
||||
}
|
||||
now = time(0);
|
||||
spinlock_acquire(&tasklock);
|
||||
ptr = tasks;
|
||||
while (ptr)
|
||||
{
|
||||
if (ptr->nextdue <= now)
|
||||
{
|
||||
ptr->nextdue = now + ptr->frequency;
|
||||
taskfn = ptr->task;
|
||||
taskdata = ptr->data;
|
||||
spinlock_release(&tasklock);
|
||||
(*taskfn)(taskdata);
|
||||
if (ptr->type == HK_ONESHOT)
|
||||
hktask_remove(ptr->name);
|
||||
spinlock_acquire(&tasklock);
|
||||
ptr = tasks;
|
||||
}
|
||||
else
|
||||
ptr = ptr->next;
|
||||
}
|
||||
spinlock_release(&tasklock);
|
||||
}
|
||||
for (;;)
|
||||
{
|
||||
for (i = 0; i < 10; i++)
|
||||
{
|
||||
if (do_shutdown)
|
||||
{
|
||||
return;
|
||||
}
|
||||
thread_millisleep(100);
|
||||
hkheartbeat++;
|
||||
}
|
||||
now = time(0);
|
||||
spinlock_acquire(&tasklock);
|
||||
ptr = tasks;
|
||||
while (ptr)
|
||||
{
|
||||
if (ptr->nextdue <= now)
|
||||
{
|
||||
ptr->nextdue = now + ptr->frequency;
|
||||
taskfn = ptr->task;
|
||||
taskdata = ptr->data;
|
||||
spinlock_release(&tasklock);
|
||||
(*taskfn)(taskdata);
|
||||
if (ptr->type == HK_ONESHOT)
|
||||
{
|
||||
hktask_remove(ptr->name);
|
||||
}
|
||||
spinlock_acquire(&tasklock);
|
||||
ptr = tasks;
|
||||
}
|
||||
else
|
||||
{
|
||||
ptr = ptr->next;
|
||||
}
|
||||
}
|
||||
spinlock_release(&tasklock);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -291,35 +307,35 @@ int i;
|
||||
void
|
||||
hkshutdown()
|
||||
{
|
||||
do_shutdown = 1;
|
||||
do_shutdown = 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the tasks that are scheduled for the house keeper
|
||||
*
|
||||
* @param pdcb The DCB to send to output
|
||||
* @param pdcb The DCB to send to output
|
||||
*/
|
||||
void
|
||||
hkshow_tasks(DCB *pdcb)
|
||||
{
|
||||
HKTASK *ptr;
|
||||
struct tm tm;
|
||||
char buf[40];
|
||||
HKTASK *ptr;
|
||||
struct tm tm;
|
||||
char buf[40];
|
||||
|
||||
dcb_printf(pdcb, "%-25s | Type | Frequency | Next Due\n", "Name");
|
||||
dcb_printf(pdcb, "--------------------------+----------+-----------+-------------------------\n");
|
||||
spinlock_acquire(&tasklock);
|
||||
ptr = tasks;
|
||||
while (ptr)
|
||||
{
|
||||
localtime_r(&ptr->nextdue, &tm);
|
||||
asctime_r(&tm, buf);
|
||||
dcb_printf(pdcb, "%-25s | %-8s | %-9d | %s",
|
||||
ptr->name,
|
||||
ptr->type == HK_REPEATED ? "Repeated" : "One-Shot",
|
||||
ptr->frequency,
|
||||
buf);
|
||||
ptr = ptr->next;
|
||||
}
|
||||
spinlock_release(&tasklock);
|
||||
dcb_printf(pdcb, "%-25s | Type | Frequency | Next Due\n", "Name");
|
||||
dcb_printf(pdcb, "--------------------------+----------+-----------+-------------------------\n");
|
||||
spinlock_acquire(&tasklock);
|
||||
ptr = tasks;
|
||||
while (ptr)
|
||||
{
|
||||
localtime_r(&ptr->nextdue, &tm);
|
||||
asctime_r(&tm, buf);
|
||||
dcb_printf(pdcb, "%-25s | %-8s | %-9d | %s",
|
||||
ptr->name,
|
||||
ptr->type == HK_REPEATED ? "Repeated" : "One-Shot",
|
||||
ptr->frequency,
|
||||
buf);
|
||||
ptr = ptr->next;
|
||||
}
|
||||
spinlock_release(&tasklock);
|
||||
}
|
||||
|
@ -26,30 +26,30 @@
|
||||
* @verbatim
|
||||
* Revision History
|
||||
*
|
||||
* Date Who Description
|
||||
* 29/08/14 Mark Riddoch Initial implementation
|
||||
* Date Who Description
|
||||
* 29/08/14 Mark Riddoch Initial implementation
|
||||
*
|
||||
* @endverbatim
|
||||
*/
|
||||
|
||||
typedef enum {
|
||||
HK_REPEATED = 1,
|
||||
HK_ONESHOT
|
||||
typedef enum
|
||||
{
|
||||
HK_REPEATED = 1,
|
||||
HK_ONESHOT
|
||||
} HKTASK_TYPE;
|
||||
|
||||
/**
|
||||
* The housekeeper task list
|
||||
*/
|
||||
typedef struct hktask {
|
||||
char *name; /*< A simple task name */
|
||||
void (*task)(void *data); /*< The task to call */
|
||||
void *data; /*< Data to pass the task */
|
||||
int frequency; /*< How often to call the tasks (seconds) */
|
||||
time_t nextdue; /*< When the task should be next run */
|
||||
HKTASK_TYPE
|
||||
type; /*< The task type */
|
||||
struct hktask
|
||||
*next; /*< Next task in the list */
|
||||
typedef struct hktask
|
||||
{
|
||||
char *name; /*< A simple task name */
|
||||
void (*task)(void *data); /*< The task to call */
|
||||
void *data; /*< Data to pass the task */
|
||||
int frequency; /*< How often to call the tasks (seconds) */
|
||||
time_t nextdue; /*< When the task should be next run */
|
||||
HKTASK_TYPE type; /*< The task type */
|
||||
struct hktask *next; /*< Next task in the list */
|
||||
} HKTASK;
|
||||
|
||||
extern void hkinit();
|
||||
@ -58,4 +58,5 @@ extern int hktask_oneshot(char *name, void (*task)(void *), void *data, int whe
|
||||
extern int hktask_remove(char *name);
|
||||
extern void hkshutdown();
|
||||
extern void hkshow_tasks(DCB *pdcb);
|
||||
|
||||
#endif
|
||||
|
Loading…
x
Reference in New Issue
Block a user