Reindented server/core/housekeeper.c

This commit is contained in:
Johan Wikman 2015-11-30 13:53:06 +02:00
parent 486f724dc1
commit 3189a47fc5
2 changed files with 215 additions and 198 deletions

View File

@ -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);
}

View File

@ -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