Hello, the attached patch adds a generic task execution implementation to the core. This is useful for monitoring purposes, e.g. in database modules to see if the db is still present.
You can register any function and an execution interval. This code (with a little bit different naming) has been in productions almost a year. Furthermore it can be deactivated with one simple #ifdef. I attached also a small demo module, that shows the usage of this facility. Its simple creates and register a task that output a log message every 10 seconds. I think this is a useful additions to OpenSER. Any comments? Cheers, Henning
Index: watchproc.h =================================================================== --- watchproc.h (Revision 0) +++ watchproc.h (Revision 0) @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2007 1und1 Internet AG + * + * This file is part of openser, a free SIP server. + * + * openser is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version + * + * openser is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef WATCHPROC_H +#define WATCHPROC_H + +#ifdef WATCHPROC + +#include <sys/types.h> +#include "str.h" + +typedef int (*watch_cmd_f) (void*, size_t); + +typedef struct watch_task { + watch_cmd_f cmd; + str name; + void * arg; + size_t argsize; + unsigned int interval; +} watch_task_t; + +int start_watch_proc(); + +int register_watch_task(watch_task_t * task); + +int unregister_watch_task(str * name); + +void destroy_watch_proc(); + +#endif +#endif Eigenschaftsänderungen: watchproc.h ___________________________________________________________________ Name: svn:eol-style + native Index: pt.h =================================================================== --- pt.h (Revision 2077) +++ pt.h (Arbeitskopie) @@ -71,6 +71,10 @@ #ifdef USE_TCP +((!tcp_disable)?( 1/* tcp main */ + tcp_children_no ):0) #endif +#ifdef WATCHPROC + /* watch process, it's always there */ + + 1 +#endif ; } Index: main.c =================================================================== --- main.c (Revision 2077) +++ main.c (Arbeitskopie) @@ -115,6 +115,10 @@ #include "script_cb.h" #include "blacklists.h" +#ifdef WATCHPROC +#include "watchproc.h" +#endif + #include "ut.h" #include "serialize.h" #include "statistics.h" @@ -798,6 +802,16 @@ goto error; } +#ifdef WATCHPROC + /* + * start the watch process + */ + if(start_watch_proc() < 0) { + LOG(L_ERR, "starting watch process failed\n"); + goto error; + } +#endif + /* udp processes */ for(si=udp_listen; si; si=si->next){ for(i=0;i<children_no;i++){ Index: sr_module.h =================================================================== --- sr_module.h (Revision 2077) +++ sr_module.h (Arbeitskopie) @@ -72,6 +72,10 @@ #define PROC_TCP_MAIN -4 /* TCP main process */ #define PROC_UNIXSOCK -5 /* Unix domain socket server processes */ +#ifdef WATCHPROC +#define PROC_WATCH -6 /* Watch process for e.g. database monitoring */ +#endif + #define DEFAULT_DLFLAGS 0 /* value that signals to module loader to use default dlopen flags in openser */ #ifndef RTLD_NOW Index: Makefile.defs =================================================================== --- Makefile.defs (Revision 2077) +++ Makefile.defs (Arbeitskopie) @@ -374,6 +374,9 @@ # -DSTATISTICS # enables statistics manager - support for collecting statistics # from core and all modules; all info may be fetch via FIFO/UNIX_SOCK +# +# -DWATCHPROC enables the watch process functionality +# @@ -390,6 +393,7 @@ -DHAVE_RESOLV_RES \ -DSTATISTICS \ -DF_MALLOC \ + -DWATCHPROC \ #-DDBG_QM_MALLOC \ #-DDBG_F_MALLOC \ #-DNO_DEBUG \ Index: watchproc.c =================================================================== --- watchproc.c (Revision 0) +++ watchproc.c (Revision 0) @@ -0,0 +1,213 @@ +/* + * Copyright (C) 2007 1und1 Internet AG + * + * This file is part of openser, a free SIP server. + * + * openser is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version + * + * openser is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifdef WATCHPROC + +#include "mem/shm_mem.h" +#include "watchproc.h" +#include "locking.h" +#include "pt.h" +#include "sr_module.h" +#include <time.h> +#include <unistd.h> + +typedef struct i_watch_task { + watch_task_t task; + time_t called; + gen_lock_t lock; +} +i_watch_task_t; + +typedef struct watch_task_list { +i_watch_task_t i_task; +struct watch_task_list * next; +} +watch_task_list_t; + +static watch_task_list_t * init_new_task(watch_task_t * task); +static void free_task(watch_task_list_t * t); +static void run_tasks(); + +static watch_task_list_t * tasks = NULL; + +pid_t watch_proc_pid; + +int start_watch_proc() { + process_no++; + watch_proc_pid = fork(); + if (watch_proc_pid<0) { + LOG(L_ERR, "ERROR: start_watch_proc: failure to fork: %s\n", + strerror(errno)); + return -1; + } + if (watch_proc_pid==0) { /* child == watch process */ + LOG(L_INFO, "INFO: watch process starting: %d\n", getpid()); + /* call per-child module initialization too -- some + tasks may need it + */ + if (init_child(PROC_WATCH) < 0 ) { + LOG(L_ERR, "ERROR: start_watch_proc: init_child failed\n"); + return -1; + } + run_tasks(); /* never returns */ + } + /* dad process */ + pt[process_no].pid=watch_proc_pid; + strncpy(pt[process_no].desc, "OpenSER watch process", MAX_PT_DESC ); +#ifdef USE_TCP + pt[process_no].idx=-1; /* this is not "tcp" process*/ +#endif + return 1; +} + +int register_watch_task(watch_task_t * task) { + watch_task_list_t * new_t; + watch_task_list_t * t; + if((new_t = init_new_task(task)) == NULL) { + return -1; + } + t = tasks; + if(t) { + lock_get(&t->i_task.lock); + } + new_t->next = tasks; + tasks = new_t; + if(t) { + lock_release(&t->i_task.lock); + } + return 1; +} + +int unregister_watch_task(str * name) { + watch_task_list_t * t, * prev = NULL; + if(!tasks) { + return -1; + } + lock_get(&tasks->i_task.lock); + t = tasks; + while(t) { + if(strncmp(t->i_task.task.name.s, name->s, name->len) == 0) { + if(prev == NULL) { + tasks = t->next; + lock_release(&t->i_task.lock); + free_task(t); + return 1; + } else { + prev->next = t->next; + free_task(t); + lock_release(&tasks->i_task.lock); + return 1; + } + } + prev = t; + t = t->next; + } + lock_release(&tasks->i_task.lock); + return -1; +} + +void destroy_watch_proc() { + watch_task_list_t * l , * n; + l = tasks; + while(l) { + n = l->next; + free_task(l); + l = n; + } + return; +} + +static void run_tasks() { + time_t start; + time_t sleep_time; + watch_task_list_t * t; + while(1) { + start = time(NULL); + if(tasks) { + lock_get(&tasks->i_task.lock); + t = tasks; + LOG(L_DBG, "watch_proc: run_tasks: now running tasks.\n"); + while(t) { + if((start - t->i_task.called) >= t->i_task.task.interval) { + LOG(L_INFO, "watch_proc: now running task %.*s\n", t->i_task.task.name.len, t->i_task.task.name.s); + if(t->i_task.task.cmd(t->i_task.task.arg, t->i_task.task.argsize) < 0) { + LOG(L_ERR, "watch_proc: task %.*s failed.\n", t->i_task.task.name.len, t->i_task.task.name.s); + } else { + t->i_task.called = start; + } + } + t = t->next; + } + lock_release(&tasks->i_task.lock); + } + sleep_time = 10 - (time(NULL) - start); + sleep_time = ((sleep_time > 0) ? sleep_time : 0); + LOG(L_INFO, "watch_proc: now going to sleep for %i seconds.\n", (int)sleep_time); + sleep(sleep_time); + } +} + +static watch_task_list_t * init_new_task(watch_task_t * task) { + watch_task_list_t * new_t; + if((new_t = shm_malloc(sizeof(watch_task_list_t))) == NULL) { + LOG(L_ERR, "watch_proc:new_task: no memory.\n"); + return NULL; + } + memset(new_t, 0, sizeof(watch_task_list_t)); + if(task->arg) { + if((new_t->i_task.task.arg = shm_malloc(task->argsize)) == NULL) { + LOG(L_ERR, "watch_proc:new_task: no memory.\n"); + shm_free(new_t); + return NULL; + } + } + if((new_t->i_task.task.name.s = shm_malloc(task->name.len + 1)) == NULL) { + LOG(L_ERR, "watch_proc:new_task: no memory.\n"); + shm_free(new_t->i_task.task.arg); + shm_free(new_t); + return NULL; + } + if(lock_init(&new_t->i_task.lock) == 0) { + LOG(L_ERR, "watch_proc:new_task: failed to init lock.\n"); + shm_free(new_t->i_task.task.arg); + shm_free(new_t->i_task.task.name.s); + shm_free(new_t); + return NULL; + } + strncpy(new_t->i_task.task.name.s, task->name.s, task->name.len); + memmove(&new_t->i_task.task, task, sizeof(watch_task_t)); + if(task->arg) { + memmove(&new_t->i_task.task.arg, task->arg, task->argsize); + } + return new_t; +} + +static void free_task(watch_task_list_t * t) { + lock_get(&t->i_task.lock); + if(t->i_task.task.arg) { + shm_free(t->i_task.task.arg); + } + shm_free(t->i_task.task.name.s); + lock_release(&t->i_task.lock); + shm_free(t); + return; +} + +#endif Eigenschaftsänderungen: watchproc.c ___________________________________________________________________ Name: svn:eol-style + native
diff -U 3 -dHrN openser-test/modules/watch_proc-test/Makefile openser/modules/watch_proc-test/Makefile --- openser-test/modules/watch_proc-test/Makefile 1970-01-01 01:00:00.000000000 +0100 +++ openser/modules/watch_proc-test/Makefile 2007-04-26 13:41:03.000000000 +0200 @@ -0,0 +1,14 @@ +# $Id: Makefile,v 1.1.1.1 2005/06/13 16:47:38 bogdan_iancu Exp $ +# +# cfgutils module makefile +# +# +# WARNING: do not run this directly, it should be run by the master Makefile + +include ../../Makefile.defs +auto_gen= +NAME=watch_proc-test.so +LIBS= + +include ../../Makefile.modules + diff -U 3 -dHrN openser-test/modules/watch_proc-test/watch_proc-test.c openser/modules/watch_proc-test/watch_proc-test.c --- openser-test/modules/watch_proc-test/watch_proc-test.c 1970-01-01 01:00:00.000000000 +0100 +++ openser/modules/watch_proc-test/watch_proc-test.c 2007-04-26 14:11:02.000000000 +0200 @@ -0,0 +1,42 @@ +#include "../../watchproc.h" +#include "../../sr_module.h" + +#include <stddef.h> // size_t + + +MODULE_VERSION + +static int mod_init(void); +static void mod_destroy(void); + +watch_task_t task; + +struct module_exports exports = {"watch_proc-test", DEFAULT_DLFLAGS, 0, 0, 0, 0, 0, mod_init, 0, mod_destroy, 0}; + +int my_task(void * arg, size_t argsize) +{ + LOG(L_INFO, "test: task called!"); + return 0; +} + +static int mod_init(void) +{ + // init watch task + task.cmd = my_task; + task.name.s = "just a test"; + task.name.len = strlen("just a test"); + task.arg = NULL; + task.argsize = 0; + task.interval = 10; // every 10 seconds + + if (register_watch_task(&task)) + return 0; + else + return -1; +} + +static void mod_destroy() +{ + // destroy watch task + destroy_watch_proc(); +}
_______________________________________________ Devel mailing list Devel@openser.org http://openser.org/cgi-bin/mailman/listinfo/devel