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