From: Thibault Godouet Date: Fri, 17 Oct 2008 14:15:31 +0000 (+0100) Subject: Added exe_list and lavg_list based on the new u_list (unordered lists) as a way to... X-Git-Tag: ver3_1_0~52 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=6dc8fff4c47bac2021fb437a41d0112d70489bb6;p=fcron Added exe_list and lavg_list based on the new u_list (unordered lists) as a way to clean-up the code and make it easier to maintain --- diff --git a/.gitignore b/.gitignore index 926ecf9..5db7943 100644 --- a/.gitignore +++ b/.gitignore @@ -13,3 +13,6 @@ fcronsighup files/fcron.conf convert-fcrontab doc/stylesheets/fcron-doc.dsl +PREVIOUS_VERSION +doc/fcron-doc.mod +exe_list_test diff --git a/Makefile.in b/Makefile.in index b9654b2..4099791 100644 --- a/Makefile.in +++ b/Makefile.in @@ -73,7 +73,7 @@ CFLAGS += $(OPTIM) $(OPTION) $(DEFS) $(CPPFLAGS) ifeq ($(FCRONDYN), 1) LIBOBJS := socket.o $(LIBOBJS) endif -OBJSD := fcron.o subs.o save.o temp_file.o log.o database.o job.o conf.o $(LIBOBJS) +OBJSD := fcron.o subs.o save.o temp_file.o log.o database.o job.o conf.o u_list.o exe_list.o lavg_list.o $(LIBOBJS) OBJSTAB := fcrontab.o subs.o save.o temp_file.o log.o fileconf.o allow.o read_string.o OBJSDYN := fcrondyn.o subs.o log.o allow.o read_string.o OBJCONV := convert-fcrontab.o subs.o save.o log.o @@ -114,6 +114,9 @@ fcronsighup: $(OBJSIG) convert-fcrontab: $(OBJCONV) $(CC) $(CFLAGS) -o $@ $(OBJCONV) $(LIBS) +exe_list_test: exe_list.o u_list.o exe_list_test.o log.o subs.o + $(CC) $(CFLAGS) -o $@ exe_list.o u_list.o exe_list_test.o log.o subs.o $(LIBS) + %.o: $(SRCDIR)/%.c $(HEADERSALL) $(SRCDIR)/%.h $(CC) $(CFLAGS) -DPIDFILE="\"${PIDFILE}\"" \ -DFIFOFILE="\"${FIFOFILE}\"" -DETC="\"${ETC}\"" \ diff --git a/conf.c b/conf.c index af05798..9e20d4b 100644 --- a/conf.c +++ b/conf.c @@ -904,6 +904,8 @@ delete_file(const char *user_name) struct job_t *prev_j; int i, k; struct cl_t **s_a = NULL; + exe_t *e = NULL; + lavg_t *l = NULL; file = file_base; while ( file != NULL) { @@ -913,39 +915,29 @@ delete_file(const char *user_name) continue; } - for ( i = 0; i < exe_num; i++) - if ( exe_array[i].e_line != NULL && - exe_array[i].e_line->cl_file == file ) { + for ( e = exe_list_first(exe_list) ; e != NULL ; e = exe_list_next(exe_list) ) + if ( e->e_line != NULL && + e->e_line->cl_file == file ) { /* we set the e_line to NULL, as so we know in wait_chld() * and wait_all() the corresponding file has been removed. * Plus, we decrement serial_running and lavg_serial_running * as we won't be able to do it at the end of the job */ - if ( ( is_serial(exe_array[i].e_line->cl_option) || - is_serial_once(exe_array[i].e_line->cl_option) ) && - ! is_lavg(exe_array[i].e_line->cl_option) ) + if ( ( is_serial(e->e_line->cl_option) || + is_serial_once(e->e_line->cl_option) ) && + ! is_lavg(e->e_line->cl_option) ) serial_running--; - else if ( is_serial(exe_array[i].e_line->cl_option) && - is_lavg(exe_array[i].e_line->cl_option) ) + else if ( is_serial(e->e_line->cl_option) && + is_lavg(e->e_line->cl_option) ) lavg_serial_running--; - exe_array[i].e_line = NULL; + e->e_line = NULL; } /* free lavg queue entries */ - i = 0; - while (i < lavg_num) - if ( lavg_array[i].l_line->cl_file == file ) { - debug("removing %s from lavg queue", - lavg_array[i].l_line->cl_shell); - lavg_array[i].l_line->cl_numexe--; - if (i < --lavg_num) { - lavg_array[i] = lavg_array[lavg_num]; - lavg_array[lavg_num].l_line = NULL; - } - else - lavg_array[i].l_line = NULL; + for (l = lavg_list_first(lavg_list) ; l != NULL ; l = lavg_list_next(lavg_list)) + if ( l->l_line->cl_file == file ) { + debug("removing %s from lavg queue", l->l_line->cl_shell); + lavg_list_remove_cur(lavg_list); } - else - i++; /* free serial queue entries */ for ( i = 0; i < serial_array_size; i++) diff --git a/configure b/configure index dd0b4b8..e874790 100755 --- a/configure +++ b/configure @@ -1748,7 +1748,7 @@ ac_config_headers="$ac_config_headers config.h" -vers="3.0.5" +vers="3.1.0" vers_quoted="\"$vers\"" cat >>confdefs.h <<_ACEOF #define VERSION $vers diff --git a/configure.in b/configure.in index 6e1e757..0a8b973 100644 --- a/configure.in +++ b/configure.in @@ -9,7 +9,7 @@ AC_INIT(allow.c) AC_CONFIG_HEADER(config.h) AC_PREREQ(2.57) -vers="3.0.5" +vers="3.1.0" vers_quoted="\"$vers\"" AC_DEFINE_UNQUOTED(VERSION, $vers) AC_DEFINE_UNQUOTED(VERSION_QUOTED, $vers_quoted) diff --git a/database.c b/database.c index a2b71b5..e869a2a 100644 --- a/database.c +++ b/database.c @@ -38,9 +38,8 @@ void move_time_to(int where, cl_t *line, struct tm *ftime); #define BEGIN_NEXT_PERIOD 11 /* move_time_to()'s where possible value */ #define END_OF_INTERVAL 12 /* move_time_to()'s where possible value */ void run_serial_job(void); -void run_lavg_job(int i); +void run_lavg_job(lavg_t *l); void run_queue_job(cl_t *line); -void resize_exe_array(void); #if ! defined(HAVE_SETENV) || ! defined(HAVE_UNSETENV) @@ -209,21 +208,14 @@ run_normal_job(cl_t *line, int info_fd) } void -run_lavg_job(int i) +run_lavg_job(lavg_t *l) { - run_queue_job(lavg_array[i].l_line); + run_queue_job(l->l_line); - if ( is_serial(lavg_array[i].l_line->cl_option) ) + if ( is_serial(l->l_line->cl_option) ) lavg_serial_running++; - if (i < --lavg_num) { - lavg_array[i] = lavg_array[lavg_num]; - lavg_array[lavg_num].l_line = NULL; - } - else - lavg_array[i].l_line = NULL; - } @@ -250,47 +242,24 @@ run_serial_job(void) } -void -resize_exe_array(void) - /* make exe_array bigger */ -{ - struct exe_t *ptr = NULL; - short int old_size = exe_array_size; - - debug("Resizing exe_array"); - exe_array_size = (exe_array_size + EXE_GROW_SIZE); - - if ( (ptr = calloc(exe_array_size, sizeof(struct exe_t))) == NULL ) - die_e("could not calloc exe_array"); - - memcpy(ptr, exe_array, (sizeof(struct exe_t) * old_size)); - free(exe_array); - exe_array = ptr; -} - - void run_queue_job(cl_t *line) /* run a job */ { + exe_t e = { NULL, 0, 0 }; + /* // */ /* debug("run_queue_job"); */ /* // */ - /* append job to the list of executed job */ - if ( exe_num >= exe_array_size ) - resize_exe_array(); - - exe_array[exe_num].e_line = line; - exe_num++; + e.e_line = line; /* run the job */ - if ( run_job(&exe_array[exe_num-1]) != OK ) { - /* The job could not be run: remove it from the exe_array */ - exe_array[exe_num-1].e_line->cl_numexe--; - exe_array[exe_num-1].e_line = NULL; - exe_num--; + if ( run_job(&e) == OK ) { + /* append job to the list of executed job */ + exe_list_add(exe_list, &e); + line->cl_file->cf_running += 1; } } @@ -428,6 +397,7 @@ add_lavg_job(cl_t *line, int info_fd) /* WARNING : must be run before a set_next_exe() to get the strict option * working correctly */ { + lavg_t *lavg_entry = NULL; /* check if the line is already in the lavg queue * (we consider serial jobs currently running as in the queue) */ @@ -441,32 +411,16 @@ add_lavg_job(cl_t *line, int info_fd) /* // */ /* append job to the list of lavg job */ - if ( lavg_num >= lavg_array_size ) { - if ( lavg_num >= lavg_queue_max ) { - error_fd(info_fd, "Could not add job : lavg queue is full (%d jobs)." - " Consider using options lavgonce, until, strict and/or " - "fcron's option -q.", lavg_queue_max, line->cl_shell); - if ( is_notice_notrun(line->cl_option) ) - mail_notrun(line, QUEUE_FULL, NULL); - return; - } - else { - struct lavg_t *ptr = NULL; - short int old_size = lavg_array_size; - - debug("Resizing lavg_array"); - lavg_array_size = (lavg_array_size + LAVG_GROW_SIZE); - - if ( (ptr = calloc(lavg_array_size, sizeof(lavg_t))) == NULL ) - die_e("could not calloc lavg_array"); - - memcpy(ptr, lavg_array, (sizeof(lavg_t) * old_size)); - free(lavg_array); - lavg_array = ptr; - } + lavg_entry = lavg_list_add_line(lavg_list, line); + if ( lavg_entry == NULL ) { + error_fd(info_fd, "Could not add job : lavg queue is full (%d jobs)." + " Consider using options lavgonce, until, strict and/or " + "fcron's option -q.", lavg_list->max_entries, line->cl_shell); + if ( is_notice_notrun(line->cl_option) ) + mail_notrun(line, QUEUE_FULL, NULL); + return; } - lavg_array[lavg_num].l_line = line; line->cl_numexe += 1; set_run_if_late(line->cl_option); if ( is_strict(line->cl_option) && line->cl_runfreq == 1) { @@ -498,9 +452,9 @@ add_lavg_job(cl_t *line, int info_fd) end_of_cur_int = mktime_no_dst(&ftime) + (line->cl_file->cf_tzdiff * 3600); if ((line->cl_until > 0) && (line->cl_until + now < end_of_cur_int)) - lavg_array[lavg_num].l_until = line->cl_until + now; + lavg_entry->l_until = line->cl_until + now; else { - lavg_array[lavg_num].l_until = end_of_cur_int; + lavg_entry->l_until = end_of_cur_int; clear_run_if_late(line->cl_option); } @@ -508,10 +462,9 @@ add_lavg_job(cl_t *line, int info_fd) switch_back_timezone(orig_tz_envvar); } else - lavg_array[lavg_num].l_until = + lavg_entry->l_until = (line->cl_until > 0) ? now + line->cl_until : 0; - lavg_num++; } @@ -519,10 +472,9 @@ void wait_chld(void) /* wait_chld() - check for job completion */ { - short int i = 0; int pid; cl_t *line = NULL; - + exe_t *e = NULL; /* // */ /* debug("wait_chld"); */ @@ -530,17 +482,16 @@ wait_chld(void) while ( (pid = wait3(NULL, WNOHANG, NULL)) > 0 ) { - i = 0; - while ( i < exe_num ) { + for ( e = exe_list_first(exe_list) ; e != NULL ; e = exe_list_next(exe_list) ) { - if (pid == exe_array[i].e_ctrl_pid) { - if ( exe_array[i].e_line == NULL ) { + if (pid == e->e_ctrl_pid) { + if ( e->e_line == NULL ) { /* the corresponding file has been removed from memory */ debug("job finished: pid %d", pid); } else { - line = exe_array[i].e_line; + line = e->e_line; /* debug("job finished: %s", line->cl_shell); */ line->cl_numexe -= 1; line->cl_file->cf_running -= 1; @@ -559,17 +510,10 @@ wait_chld(void) is_serial(line->cl_option) ) lavg_serial_running--; } - if (i < --exe_num) { - exe_array[i] = exe_array[exe_num]; - exe_array[exe_num].e_line = NULL; - } - else - exe_array[i].e_line = NULL; + exe_list_remove_cur(exe_list); break; } - - i++; } } @@ -581,39 +525,32 @@ void wait_all(int *counter) /* return after all jobs completion. */ { - short int i = 0; int pid; + exe_t *e = NULL; debug("Waiting for all jobs"); while ( (*counter > 0) && (pid = wait3(NULL, 0, NULL)) > 0 ) { - i = 0; - while ( i < exe_num ) { - if (pid == exe_array[i].e_ctrl_pid) { - if ( exe_array[i].e_line == NULL ) { + for ( e = exe_list_first(exe_list) ; e != NULL ; e = exe_list_next(exe_list) ) { + if (pid == e->e_ctrl_pid) { + if ( e->e_line == NULL ) { /* the corresponding file has been removed from memory */ debug("job finished: pid %d", pid); } else { - debug("job finished: %s", exe_array[i].e_line->cl_shell); - exe_array[i].e_line->cl_numexe -= 1; - exe_array[i].e_line->cl_file->cf_running -= 1; + debug("job finished: %s", e->e_line->cl_shell); + e->e_line->cl_numexe -= 1; + e->e_line->cl_file->cf_running -= 1; - if ( is_serial_once(exe_array[i].e_line->cl_option) ) - clear_serial_once(exe_array[i].e_line->cl_option); + if ( is_serial_once(e->e_line->cl_option) ) + clear_serial_once(e->e_line->cl_option); } - if (i < --exe_num) { - exe_array[i] = exe_array[exe_num]; - exe_array[exe_num].e_line = NULL; - } - else - exe_array[i].e_line = NULL; + exe_list_remove_cur(exe_list); break; } - i++; } } @@ -1355,13 +1292,9 @@ mail_notrun(cl_t *line, char context, struct tm *since) line->cl_shell, pid); /* // */ - /* create an entry in exe_array */ - if ( exe_num >= exe_array_size ) - resize_exe_array(); + /* create an entry in exe_list */ /* set line to NULL as this is not a line ... */ - exe_array[exe_num].e_line = NULL; - exe_array[exe_num].e_ctrl_pid = pid; - exe_num++; + exe_list_add_line(exe_list, NULL); return; } @@ -1437,10 +1370,14 @@ check_lavg(time_t lim) * and return the time to sleep */ { time_t tts = 0; + lavg_t *l = NULL; #ifdef NOLOADAVG - while ( lavg_num > 0 ) - run_lavg_job(0); + for ( l = lavg_list_first(lavg_list) ; l != NULL ; l = lavg_list_next(lavg_list) ) { + run_lavg_job(l); + lavg_list_remove_cur(lavg_list); + } + tts = time_to_sleep(lim); return tts; @@ -1450,44 +1387,37 @@ check_lavg(time_t lim) double l_avg[3]= {0, 0, 0}; /* first, check if some lines must be executed because of until */ - while ( i < lavg_num ) - if ( (lavg_array[i].l_line->cl_until > 0 - || lavg_array[i].l_line->cl_runfreq == 1) - && lavg_array[i].l_until < now){ - if ( ! is_run_if_late(lavg_array[i].l_line->cl_option) ) { - if ( ! is_nolog(lavg_array[i].l_line->cl_option) ) + for ( l = lavg_list_first(lavg_list) ; l != NULL ; l = lavg_list_next(lavg_list) ) + if ( (l->l_line->cl_until > 0 || l->l_line->cl_runfreq == 1) + && l->l_until < now) { + if ( ! is_run_if_late(l->l_line->cl_option) ) { + if ( ! is_nolog(l->l_line->cl_option) ) explain("Interval of execution exceeded : %s (not run)", - lavg_array[i].l_line->cl_shell); + l->l_line->cl_shell); /* set time of the next execution and send a mail if needed */ - if ( is_td(lavg_array[i].l_line->cl_option) && - is_notice_notrun(lavg_array[i].l_line->cl_option) ) - set_next_exe_notrun(lavg_array[i].l_line, LAVG); + if ( is_td(l->l_line->cl_option) && + is_notice_notrun(l->l_line->cl_option) ) + set_next_exe_notrun(l->l_line, LAVG); else - set_next_exe(lavg_array[i].l_line, NO_GOTO_LOG, -1); + set_next_exe(l->l_line, NO_GOTO_LOG, -1); /* remove this job from the lavg queue */ - lavg_array[i].l_line->cl_numexe -= 1; - if (i < --lavg_num) { - lavg_array[i] = lavg_array[lavg_num]; - lavg_array[lavg_num].l_line = NULL; - } - else - lavg_array[i].l_line = NULL; - + l->l_line->cl_numexe -= 1; + lavg_list_remove_cur(lavg_list); } else { - debug("until %s %d", lavg_array[i].l_line->cl_shell, - lavg_array[i].l_until); - run_lavg_job(i); + debug("until %s %d", l->l_line->cl_shell, + l->l_until); + run_lavg_job(l); + lavg_list_remove_cur(lavg_list); } - } else - i++; + } /* we do this set here as the nextexe of lavg line may change before */ tts = time_to_sleep(lim); - if ( lavg_num == 0 ) + if ( lavg_list->num_entries == 0 ) return tts; if ( (i = getloadavg(l_avg, 3)) != 3 ) @@ -1497,43 +1427,38 @@ check_lavg(time_t lim) l_avg[0] *= 10; l_avg[1] *= 10; l_avg[2] *= 10; - i = 0; - while ( i < lavg_num ) { + for ( l = lavg_list_first(lavg_list) ; l != NULL ; l = lavg_list_next(lavg_list) ) { /* check if the line should be executed */ if ( lavg_serial_running >= serial_max_running && - is_serial(lavg_array[i].l_line->cl_option) ) { - i++; + is_serial(l->l_line->cl_option) ) { continue; } - if ( ( is_land(lavg_array[i].l_line->cl_option) - && ( l_avg[0] < lavg_array[i].l_line->cl_lavg[0] - || lavg_array[i].l_line->cl_lavg[0] == 0 ) - && ( l_avg[1] < lavg_array[i].l_line->cl_lavg[1] - || lavg_array[i].l_line->cl_lavg[1] == 0 ) - && ( l_avg[2] < lavg_array[i].l_line->cl_lavg[2] - || lavg_array[i].l_line->cl_lavg[2] == 0 ) + if ( ( is_land(l->l_line->cl_option) + && ( l_avg[0] < l->l_line->cl_lavg[0] || l->l_line->cl_lavg[0] == 0 ) + && ( l_avg[1] < l->l_line->cl_lavg[1] || l->l_line->cl_lavg[1] == 0 ) + && ( l_avg[2] < l->l_line->cl_lavg[2] || l->l_line->cl_lavg[2] == 0 ) ) || - ( is_lor(lavg_array[i].l_line->cl_option) - && ( l_avg[0] < lavg_array[i].l_line->cl_lavg[0] - || l_avg[1] < lavg_array[i].l_line->cl_lavg[1] - || l_avg[2] < lavg_array[i].l_line->cl_lavg[2] ) + ( is_lor(l->l_line->cl_option) + && ( l_avg[0] < l->l_line->cl_lavg[0] + || l_avg[1] < l->l_line->cl_lavg[1] + || l_avg[2] < l->l_line->cl_lavg[2] ) ) ) { debug("lavg %s %s %.0f:%d %.0f:%d %.0f:%d", - lavg_array[i].l_line->cl_shell, - (is_lor(lavg_array[i].l_line->cl_option)) ? "or" : "and", - l_avg[0], lavg_array[i].l_line->cl_lavg[0], - l_avg[1], lavg_array[i].l_line->cl_lavg[1], - l_avg[2], lavg_array[i].l_line->cl_lavg[2]); - run_lavg_job(i); - - } else - i++; + l->l_line->cl_shell, + (is_lor(l->l_line->cl_option)) ? "or" : "and", + l_avg[0], l->l_line->cl_lavg[0], + l_avg[1], l->l_line->cl_lavg[1], + l_avg[2], l->l_line->cl_lavg[2]); + run_lavg_job(l); + lavg_list_remove_cur(lavg_list); + + } } - if ( lavg_num == 0 ) + if ( lavg_list->num_entries == 0 ) return tts; else return (LAVG_SLEEP < tts) ? LAVG_SLEEP : tts; diff --git a/doc/Makefile.in b/doc/Makefile.in index dc24d7c..09aab90 100644 --- a/doc/Makefile.in +++ b/doc/Makefile.in @@ -50,7 +50,27 @@ doc: # Build all the HTML, text and manual pages in all the languages @(for i in $(LANGUAGES); \ do \ - make $$i/HTML/index.html $$i/txt/readme.txt $$i/man/fcron.8 ; \ + test -d $(SRCDIR)/$$i/HTML || mkdir $(SRCDIR)/$$i/HTML ; \ + test -d $(SRCDIR)/$$i/txt || mkdir $(SRCDIR)/$$i/txt ; \ + test -d $(SRCDIR)/$$i/man || mkdir $(SRCDIR)/$$i/man ; \ + make $(SRCDIR)/$$i/HTML/index.html $(SRCDIR)/$$i/txt/readme.txt \ + $(SRCDIR)/$$i/man/fcron.8 ; \ + done) + +doc-if-none: +# Only generate the doc if there is none (e.g. if the sources came from git +# and not a tarball) +# The reason we don't try to generate the doc everytime is that we want the user +# to be able to compile and install fcron without needing all the tools required +# to generate the documentations. +# +# "make doc" will be called once at max, as all the tests will +# succeed after the first time "make doc" is called + @(for i in $(LANGUAGES); \ + do \ + test -f $(SRCDIR)/$$i/HTML/index.html || make doc ; \ + test -f $(SRCDIR)/$$i/txt/readme.txt || make doc ; \ + test -f $(SRCDIR)/$$i/man/fcron.8 || make doc ; \ done) # man/fcron.8 means in fact "build *all* the man pages" @@ -97,7 +117,7 @@ fcron-doc.mod: fcron-doc.mod.in ../configure.in install: install-staged perms -install-staged: clean +install-staged: doc-if-none clean @(echo "Installing man pages in $(DESTDIR)$(DESTMAN)...") @(for l in $(LANGUAGES); do \ if test "x$$l" = "xen"; then \ diff --git a/exe_list.c b/exe_list.c index f1427c4..6040cd0 100644 --- a/exe_list.c +++ b/exe_list.c @@ -38,7 +38,7 @@ exe_list_t *exe_list_init(void) } exe_t * -exe_list_add(exe_list_t *list, struct cl_t *line) +exe_list_add_line(exe_list_t *list, struct cl_t *line) { exe_t e = { NULL, 0, 0}; e.e_line = line; /* ANSI C does not allow us to directly replace NULL by line above*/ @@ -46,6 +46,12 @@ exe_list_add(exe_list_t *list, struct cl_t *line) return (exe_t *) u_list_add( (u_list_t *) list, (u_list_entry_t *) &e); } +exe_t * +exe_list_add(exe_list_t *list, exe_t *e) +{ + return (exe_t *) u_list_add( (u_list_t *) list, (u_list_entry_t *) e); +} + exe_t * exe_list_first(exe_list_t *list) { @@ -53,15 +59,21 @@ exe_list_first(exe_list_t *list) } exe_t * -exe_list_next(exe_list_t *list, exe_t *cur_entry) +exe_list_next(exe_list_t *list) +{ + return (exe_t *) u_list_next((u_list_t *) list); +} + +void +exe_list_end_iteration(exe_list_t *list) { - return (exe_t *) u_list_next((u_list_t *) list, (u_list_entry_t *) cur_entry); + u_list_end_iteration((u_list_t *) list); } void -exe_list_remove(exe_list_t *list, exe_t *entry) +exe_list_remove_cur(exe_list_t *list) { - u_list_remove((u_list_t *) list, (u_list_entry_t *) entry); + u_list_remove_cur((u_list_t *) list); } exe_list_t * diff --git a/exe_list.h b/exe_list.h index 50c0483..d80857d 100644 --- a/exe_list.h +++ b/exe_list.h @@ -44,12 +44,14 @@ typedef struct u_list_t exe_list_t; /* functions prototypes */ extern exe_list_t *exe_list_init(void); -/* WARNING: exe_t pointers returned by those functions are only - * valid for as long as the list is not modified (add/remove) */ -extern exe_t *exe_list_add(exe_list_t *list, struct cl_t *line); +extern exe_t *exe_list_add_line(exe_list_t *list, struct cl_t *line); +extern exe_t *exe_list_add(exe_list_t *list, exe_t *e); +/* WARNING: there should always be a unique iteration loop based on + * u_list_first()/u_list_next() running at any one time in the code */ extern exe_t *exe_list_first(exe_list_t *list); -extern exe_t *exe_list_next(exe_list_t *list, exe_t *cur_entry); -extern void exe_list_remove(exe_list_t *list, exe_t *entry); +extern exe_t *exe_list_next(exe_list_t *list); +extern void exe_list_end_iteration(exe_list_t *list); +extern void exe_list_remove_cur(exe_list_t *list); extern exe_list_t *exe_list_destroy(exe_list_t *list); diff --git a/fcron.c b/fcron.c index e77b56f..be63f5b 100644 --- a/fcron.c +++ b/fcron.c @@ -104,16 +104,12 @@ short int serial_running; /* number of running serial jobs */ /* do not run more than this number of serial job simultaneously */ short int serial_max_running = SERIAL_MAX_RUNNING; short int serial_queue_max = SERIAL_QUEUE_MAX; -short int lavg_queue_max = LAVG_QUEUE_MAX; -struct lavg_t *lavg_array; /* jobs waiting for a given system load value */ -short int lavg_array_size; /* size of lavg_array */ -short int lavg_num; /* number of job being queued */ +lavg_list_t *lavg_list; /* jobs waiting for a given system load value */ +short int lavg_queue_max = LAVG_QUEUE_MAX; short int lavg_serial_running;/* number of serialized lavg job being running */ -struct exe_t *exe_array; /* jobs which are executed */ -short int exe_array_size; /* size of exe_array */ -short int exe_num; /* number of job being executed */ +exe_list_t *exe_list; /* jobs which are executed */ time_t begin_sleep; /* the time at which sleep began */ time_t now; /* the current time */ @@ -610,10 +606,7 @@ main(int argc, char **argv) next_id = 0; /* initialize exe_array */ - exe_num = 0; - exe_array_size = EXE_INITIAL_SIZE; - if ( (exe_array = calloc(exe_array_size, sizeof(struct exe_t))) == NULL ) - die_e("could not calloc exe_array"); + exe_list = exe_list_init(); /* initialize serial_array */ serial_running = 0; @@ -624,11 +617,9 @@ main(int argc, char **argv) die_e("could not calloc serial_array"); /* initialize lavg_array */ - lavg_num = 0; + lavg_list = lavg_list_init(); + lavg_list->max_entries = lavg_queue_max; lavg_serial_running = 0; - lavg_array_size = LAVG_INITIAL_SIZE; - if ( (lavg_array = calloc(lavg_array_size, sizeof(lavg_t))) == NULL ) - die_e("could not calloc lavg_array"); #ifdef FCRONDYN /* initialize socket */ diff --git a/fcron.h b/fcron.h index f21b0df..e26d5a8 100644 --- a/fcron.h +++ b/fcron.h @@ -27,6 +27,8 @@ #define __FCRON_H__ #include "global.h" +#include "exe_list.h" +#include "lavg_list.h" #ifdef HAVE_CRYPT_H #include @@ -83,12 +85,8 @@ extern short int serial_running; extern short int serial_max_running; extern short int serial_queue_max; extern short int lavg_queue_max; -extern struct exe_t *exe_array; -extern short int exe_array_size; -extern short int exe_num; -extern struct lavg_t *lavg_array; -extern short int lavg_array_size; -extern short int lavg_num; +extern exe_list_t *exe_list; +extern lavg_list_t *lavg_list; extern short int lavg_serial_running; /* end of global variables */ diff --git a/global.h b/global.h index 6f746ce..14fcdfd 100644 --- a/global.h +++ b/global.h @@ -221,17 +221,6 @@ typedef struct job_t { struct job_t *j_next; } job_t; -typedef struct lavg_t { - struct cl_t *l_line; - time_t l_until; /* the timeout of the wait for load averages */ -} lavg_t; - -typedef struct exe_t { - struct cl_t *e_line; - pid_t e_ctrl_pid; /* pid of the fcron process controling the job */ - pid_t e_job_pid; /* pid of the job itself */ -} exe_t; - #if SIZEOF_TIME_T == SIZEOF_SHORT_INT #define ATTR_SIZE_TIMET "h" diff --git a/job.c b/job.c index 1610e5d..f4c7b54 100644 --- a/job.c +++ b/job.c @@ -661,7 +661,6 @@ run_job(struct exe_t *exeent) error_e("parent: could not close(pipe_pid_fd[1])"); exeent->e_ctrl_pid = pid; - line->cl_file->cf_running += 1; #ifdef CHECKRUNJOB debug("run_job(): about to read grand-child pid..."); diff --git a/lavg_list.c b/lavg_list.c index 8392dd4..416ebca 100644 --- a/lavg_list.c +++ b/lavg_list.c @@ -40,7 +40,7 @@ lavg_list_t *lavg_list_init(void) } lavg_t * -lavg_list_add(lavg_list_t *list, struct cl_t *line) +lavg_list_add_line(lavg_list_t *list, struct cl_t *line) { lavg_t e = { NULL, 0}; e.l_line = line; /* ANSI C does not allow us to directly replace NULL by line above*/ @@ -48,6 +48,12 @@ lavg_list_add(lavg_list_t *list, struct cl_t *line) return (lavg_t *) u_list_add( (u_list_t *) list, (u_list_entry_t *) &e); } +lavg_t * +lavg_list_add(lavg_list_t *list, lavg_t *entry) +{ + return (lavg_t *) u_list_add( (u_list_t *) list, (u_list_entry_t *) entry); +} + lavg_t * lavg_list_first(lavg_list_t *list) { @@ -55,15 +61,21 @@ lavg_list_first(lavg_list_t *list) } lavg_t * -lavg_list_next(lavg_list_t *list, lavg_t *cur_entry) +lavg_list_next(lavg_list_t *list) +{ + return (lavg_t *) u_list_next((u_list_t *) list); +} + +void +lavg_list_end_iteration(lavg_list_t *list) { - return (lavg_t *) u_list_next((u_list_t *) list, (u_list_entry_t *) cur_entry); + u_list_end_iteration((u_list_t *) list); } void -lavg_list_remove(lavg_list_t *list, lavg_t *entry) +lavg_list_remove_cur(lavg_list_t *list) { - u_list_remove((u_list_t *) list, (u_list_entry_t *) entry); + u_list_remove_cur((u_list_t *) list); } lavg_list_t * diff --git a/lavg_list.h b/lavg_list.h index 3c2af2e..0b7c0d7 100644 --- a/lavg_list.h +++ b/lavg_list.h @@ -43,12 +43,14 @@ typedef struct u_list_t lavg_list_t; /* functions prototypes */ extern lavg_list_t *lavg_list_init(void); -/* WARNING: lavg_t pointers returned by those functions are only - * valid for as long as the list is not modified (add/remove) */ -extern lavg_t *lavg_list_add(lavg_list_t *list, struct cl_t *line); +extern lavg_t *lavg_list_add_line(lavg_list_t *list, struct cl_t *line); +extern lavg_t *lavg_list_add(lavg_list_t *list, lavg_t *entry); +/* WARNING: there should always be a unique iteration loop based on + * u_list_first()/u_list_next() running at any one time in the code */ extern lavg_t *lavg_list_first(lavg_list_t *list); -extern lavg_t *lavg_list_next(lavg_list_t *list, lavg_t *cur_entry); -extern void lavg_list_remove(lavg_list_t *list, lavg_t *entry); +extern lavg_t *lavg_list_next(lavg_list_t *list); +extern void lavg_list_end_iteration(lavg_list_t *list); +extern void lavg_list_remove_cur(lavg_list_t *list); extern lavg_list_t *lavg_list_destroy(lavg_list_t *list); diff --git a/socket.c b/socket.c index 65adeb5..2248e73 100644 --- a/socket.c +++ b/socket.c @@ -40,9 +40,9 @@ void print_fields(int fd, unsigned char *details); void print_line(int fd, struct cl_t *line, unsigned char *details, pid_t pid, int index, time_t until); void cmd_on_exeq(struct fcrondyn_cl *client, long int *cmd, int fd, int is_root); -void cmd_renice(struct fcrondyn_cl *client, long int *cmd, int fd, int exe_index, +void cmd_renice(struct fcrondyn_cl *client, long int *cmd, int fd, exe_t *e, int is_root); -void cmd_send_signal(struct fcrondyn_cl *client, long int *cmd, int fd, int exe_index); +void cmd_send_signal(struct fcrondyn_cl *client, long int *cmd, int fd, exe_t *e); void cmd_run(struct fcrondyn_cl *client, long int *cmd, int fd, int is_root); void add_to_select_set(int fd, fd_set *set, int *max_fd); void remove_from_select_set(int fd, fd_set *set, int *max_fd); @@ -393,6 +393,8 @@ cmd_ls(struct fcrondyn_cl *client, long int *cmd, int fd, int is_root) struct job_t *j; int i; unsigned char fields[FIELD_NUM_SIZE]; + exe_t *e = NULL; + lavg_t *l = NULL; for (i = 0; i < FIELD_NUM_SIZE; i++) fields[i] = 0; @@ -482,23 +484,22 @@ cmd_ls(struct fcrondyn_cl *client, long int *cmd, int fd, int is_root) break; case CMD_LIST_EXEQ: - for ( i = 0; i < exe_num; i++) { - if ( exe_array[i].e_line == NULL ) { + for (e = exe_list_first(exe_list); e != NULL; e = exe_list_next(exe_list)) { + if ( e->e_line == NULL ) { if ( is_root ) { send_msg_fd(fd, "job no more in an fcrontab: pid %d", - exe_array[i].e_job_pid); + e->e_job_pid); found = 1; } } else - Test_line(exe_array[i].e_line, exe_array[i].e_job_pid, - 0, 0) + Test_line(e->e_line, e->e_job_pid, 0, 0) } break; case CMD_LIST_LAVGQ: - for ( i = 0; i < lavg_num; i++) - Test_line(lavg_array[i].l_line, 0, 0, lavg_array[i].l_until); + for (l=lavg_list_first(lavg_list); l!=NULL; l=lavg_list_next(lavg_list)) + Test_line(l->l_line, 0, 0, l->l_until); break; case CMD_LIST_SERIALQ: @@ -530,21 +531,20 @@ void cmd_on_exeq(struct fcrondyn_cl *client, long int *cmd, int fd, int is_root) /* common code to all cmds working on jobs in the exeq */ { - int exe_index; int found = 0; char *err_str = NULL; + exe_t *e = NULL; /* find the corresponding job */ - for ( exe_index = 0 ; exe_index < exe_num; exe_index++ ) { - if ( exe_array[exe_index].e_line != NULL - && cmd[2] == exe_array[exe_index].e_line->cl_id ) { + for (e = exe_list_first(exe_list); e != NULL; e = exe_list_next(exe_list)) { + if ( e->e_line != NULL + && cmd[2] == e->e_line->cl_id ) { found = 1; /* check if the request is valid */ if ( ! is_root && - strcmp(client->fcl_user, - exe_array[exe_index].e_line->cl_file->cf_user) != 0 ) { + strcmp(client->fcl_user, e->e_line->cl_file->cf_user) != 0 ) { if ( cmd[0] == CMD_RENICE ) err_str = "%s tried to renice to %ld job id %ld for %s : " @@ -564,9 +564,9 @@ cmd_on_exeq(struct fcrondyn_cl *client, long int *cmd, int fd, int is_root) /* request is valid : do it */ if ( cmd[0] == CMD_SEND_SIGNAL ) - cmd_send_signal(client, cmd, fd, exe_index); + cmd_send_signal(client, cmd, fd, e); else if ( cmd[0] == CMD_RENICE ) - cmd_renice(client, cmd, fd, exe_index, is_root); + cmd_renice(client, cmd, fd, e, is_root); else { Send_err_msg_end(fd, err_cmd_unknown_str); return; @@ -598,36 +598,36 @@ cmd_on_exeq(struct fcrondyn_cl *client, long int *cmd, int fd, int is_root) void -cmd_renice(struct fcrondyn_cl *client, long int *cmd, int fd, int exe_index, int is_root) +cmd_renice(struct fcrondyn_cl *client, long int *cmd, int fd, exe_t *e, int is_root) /* change nice value of a running job */ { #ifdef HAVE_SETPRIORITY /* check if arguments are valid */ - if ( exe_array[exe_index].e_job_pid <= 0 || ((int)cmd[1] < 0 && ! is_root) + if ( e->e_job_pid <= 0 || ((int)cmd[1] < 0 && ! is_root) || (int)cmd[1] > 20 || (int)cmd[1] < -20 ) { warn("renice: invalid args : pid: %d nice_value: %d user: %s.", - exe_array[exe_index].e_job_pid, (int)cmd[1], client->fcl_user); + e->e_job_pid, (int)cmd[1], client->fcl_user); Send_err_msg_end(fd, err_invalid_args_str); return; } /* ok, now setpriority() the job */ - if ( setpriority(PRIO_PROCESS, exe_array[exe_index].e_job_pid, (int)cmd[1]) != 0) { + if ( setpriority(PRIO_PROCESS, e->e_job_pid, (int)cmd[1]) != 0) { error_e("could not setpriority(PRIO_PROCESS, %d, %d)", - exe_array[exe_index].e_job_pid, (int)cmd[1]); + e->e_job_pid, (int)cmd[1]); Send_err_msg_end(fd, err_unknown_str); return; } else { send_msg_fd(fd, "Command successfully completed on process %d.", - exe_array[exe_index].e_job_pid); + e->e_job_pid); return; } #else /* HAVE_SETPRIORITY */ warn("System has no setpriority() : cannot renice. pid: %d nice_value: %d user: %s.", - exe_array[exe_index].e_job_pid, (int)cmd[1], client->fcl_user); + e->e_job_pid, (int)cmd[1], client->fcl_user); Send_err_msg_end(fd, err_cmd_unknown_str); #endif /* HAVE_SETPRIORITY */ @@ -635,25 +635,25 @@ cmd_renice(struct fcrondyn_cl *client, long int *cmd, int fd, int exe_index, int void -cmd_send_signal(struct fcrondyn_cl *client, long int *cmd, int fd, int exe_index) +cmd_send_signal(struct fcrondyn_cl *client, long int *cmd, int fd, exe_t *e) /* send a signal to a running job */ { - if ( exe_array[exe_index].e_job_pid <= 0 || (int)cmd[1] <= 0 ) { + if ( e->e_job_pid <= 0 || (int)cmd[1] <= 0 ) { warn("send_signal: invalid args : pid: %d signal: %d user: %s", - exe_array[exe_index].e_job_pid, (int)cmd[1], client->fcl_user); + e->e_job_pid, (int)cmd[1], client->fcl_user); Send_err_msg_end(fd, err_invalid_args_str); return; } /* ok, now kill() the job */ - if ( kill(exe_array[exe_index].e_job_pid, (int)cmd[1]) != 0) { - error_e("could not kill(%d, %d)", exe_array[exe_index].e_job_pid, (int)cmd[1]); + if ( kill(e->e_job_pid, (int)cmd[1]) != 0) { + error_e("could not kill(%d, %d)", e->e_job_pid, (int)cmd[1]); Send_err_msg_end(fd, err_unknown_str); return; } else { send_msg_fd(fd, "Command successfully completed on process %d.", - exe_array[exe_index].e_job_pid); + e->e_job_pid); return; } } diff --git a/subs.c b/subs.c index f49c1c5..cef1116 100644 --- a/subs.c +++ b/subs.c @@ -123,6 +123,13 @@ strdup2(const char *str) return(ptr); } +void +free_safe(void *ptr) + /* free() p and set it to NULL to prevent errors if it is free()ed again */ +{ + free(ptr); + ptr = NULL; +} int get_word(char **str) @@ -166,15 +173,15 @@ void free_conf(void) /* free() the memory allocated in init_conf() */ { - free(fcronconf); - free(fcrontabs); - free(pidfile); - free(fifofile); - free(fcronallow); - free(fcrondeny); - free(shell); - free(sendmail); - free(editor); + free_safe(fcronconf); + free_safe(fcrontabs); + free_safe(pidfile); + free_safe(fifofile); + free_safe(fcronallow); + free_safe(fcrondeny); + free_safe(shell); + free_safe(sendmail); + free_safe(editor); } diff --git a/subs.h b/subs.h index ab4a109..c04d622 100644 --- a/subs.h +++ b/subs.h @@ -46,6 +46,7 @@ extern uid_t get_user_uid_safe(char *username); extern gid_t get_group_gid_safe(char *groupname); extern int remove_blanks(char *str); extern char *strdup2(const char *); +extern void free_safe(void *ptr); extern int get_word(char **str); extern int temp_file(char **name); extern void read_conf(void); diff --git a/u_list.c b/u_list.c index 2d3f40a..25e6ed2 100644 --- a/u_list.c +++ b/u_list.c @@ -60,6 +60,8 @@ u_list_init(size_t entry_size, int init_size, int grow_size) l->array_size = init_size; l->entry_size = entry_size; l->grow_size = grow_size; + l->cur_entry = NULL; + l->cur_removed = 0; l->entries_array = calloc(init_size, entry_size); if ( l->entries_array == NULL ) die_e("Failed creating a new unordered list: could not calloc array" @@ -74,6 +76,7 @@ u_list_resize_array(u_list_t *l) * Returns OK on success, ERR if the array is already at maximum size */ { u_list_entry_t *e = NULL; + int offset = 0; int old_size = l->array_size; /* sanity check */ @@ -85,6 +88,11 @@ u_list_resize_array(u_list_t *l) return ERR; } + if ( l->cur_entry != NULL ) + /* Compute cur_entry's offset so as we can set cur_entry to the right place + * after we have allocated a new chunk of memory for the entries_array */ + offset = (char *) l->cur_entry - (char *) l->entries_array; + l->array_size = (l->array_size + l->grow_size); if ( l->max_entries > 0 && l->array_size > l->max_entries ) l->array_size = l->max_entries; @@ -99,6 +107,9 @@ u_list_resize_array(u_list_t *l) free_safe(l->entries_array); l->entries_array = e; + if ( l->cur_entry != NULL ) + l->cur_entry = (u_list_entry_t *) ( (char *) l->entries_array + offset ); + return OK; } @@ -145,54 +156,80 @@ u_list_first(u_list_t *l) /* sanity check */ if ( l == NULL ) die("Invalid argument for u_list_first(): list=%d", l); + if ( l->cur_entry != NULL ) + die("u_list_first() called but there is already an iteration"); - return (l->num_entries > 0) ? l->entries_array : NULL; + if (l->num_entries > 0) { + l->cur_entry = l->entries_array; + } + + return l->cur_entry; } u_list_entry_t * -u_list_next(u_list_t *l, u_list_entry_t *e) +u_list_next(u_list_t *l) /* Return the entry after e */ { + /* // WHAT IF I CALL _ADD() (+RESIZE?) OR _REMOVE() BETWEEN TWO _NEXT CALLS? */ + /* sanity checks */ - if (l==NULL||e==NULL) - die("Invalid arguments for u_list_next(): list=%d, entry=%d", l, e); - if (e < l->entries_array || e > u_list_last(l) ) - die("u_list_next(): entry out of list! (entries_array: %d, entry: %d," - "num_entries: %d)", l->entries_array, e, l->num_entries); - - /* // */ - /* Undefined? -- convert soustraction to float and check if result is an int ? */ -/* if ( ( (char *) e - (char *) l->entries_array ) % l->entry_size != 0 ) - die("u_list_next(): entry shifted! (entries_array: %d, entry_size: %d, " - "entry: %d", l->entries_array, l->entry_size, e); -*/ - if ( e < u_list_last(l) ) - return (u_list_entry_t *) ( (char *) e + l->entry_size); - else - return NULL; + if ( l == NULL ) + die("Invalid arguments for u_list_next(): list=%d", l); + if ( l->cur_entry == NULL ) + die("u_list_next() called outside an iteration: l->cur_entry=%d", l->cur_entry); + + if ( l->cur_removed > 0 ) { + l->cur_removed = 0; + /* the current entry has just been removed and replaced by another one: + * we can return the same pointer again. + * However if the removed entry was the last one then we reached the end + * of the list */ + if ( l->cur_entry > u_list_last(l) ) + l->cur_entry = NULL; + } + else { + /* cur_entry *not* removed (standard behavior) */ + + if ( l->cur_entry < u_list_last(l) ) + l->cur_entry = (u_list_entry_t *) ( (char *) l->cur_entry + l->entry_size); + else + /* reached the end of the list */ + l->cur_entry = NULL; + } + + return l->cur_entry; } void -u_list_remove(u_list_t *l, u_list_entry_t *e) +u_list_end_iteration(u_list_t *list) + /* Stop an iteration before _next() reached the end of the list by itself */ { + list->cur_entry = NULL; + list->cur_removed = 0; +} + + +void +u_list_remove_cur(u_list_t *l) +{ + /* // MANAGE L->NEXT_ENTRY (+ SPECIAL CASE FIRST/LAST ENTRY) */ u_list_entry_t *last = NULL; /* sanity checks */ - if ( l == NULL || e == NULL ) - die("Invalid arguments for u_list_remove(): list=%d, entry=%d", l, e); - if (e < l->entries_array || e > u_list_last(l) ) - die("u_list_next(): entry out of list! (entries_array: %d, entry: %d," - "num_entries: %d)", l->entries_array, e, l->num_entries); + if ( l == NULL ) + die("Invalid arguments for u_list_remove(): list=%d", l); + if ( l->cur_entry == NULL ) + die("u_list_remove_cur() called outside of an iteration"); last = u_list_last(l); - if ( e < last ) { + if ( l->cur_entry < last ) { /* Override e with the last entry */ - memcpy(e, last, l->entry_size); + memcpy(l->cur_entry, last, l->entry_size); } /* erase the last entry and update the number of entries */ memset(last, 0, l->entry_size); l->num_entries--; - + l->cur_removed = 1; } diff --git a/u_list.h b/u_list.h index 2152a3d..c6a2038 100644 --- a/u_list.h +++ b/u_list.h @@ -45,17 +45,24 @@ typedef struct u_list_t { int array_size; /* size of the array (in number of entries) */ size_t entry_size; /* number of element currently in the array */ int grow_size; /* grow array by grow_size entries at a time */ + u_list_entry_t *cur_entry; /* Current entry in iteration + * (null if not in iteration, i.e. X_first() has + * not been called or we reached the list end */ + char cur_removed; /* >0 if cur_entry has just been removed */ u_list_entry_t *entries_array; /* pointer to the actual array */ } u_list_t; /* functions prototypes */ extern u_list_t *u_list_init(size_t entry_size, int init_size, int grow_size); -/* WARNING: u_list_entry_t pointers returned by those functions are only - * valid for as long as the list is not modified (add/remove) */ extern u_list_entry_t *u_list_add(u_list_t *list, u_list_entry_t *entry); +/* WARNING: - there should always be a unique iteration loop based on + * u_list_first()/u_list_next() running at any one time in the code + * - the u_list_entry_t* returned by _first() and _next() should not + * be used anymore after a _add() or a _remove_cur() */ extern u_list_entry_t *u_list_first(u_list_t *list); -extern u_list_entry_t *u_list_next(u_list_t *list, u_list_entry_t *cur_entry); -extern void u_list_remove(u_list_t *list, u_list_entry_t *entry); +extern u_list_entry_t *u_list_next(u_list_t *list); +extern void u_list_end_iteration(u_list_t *list); +extern void u_list_remove_cur(u_list_t *list); extern u_list_t *u_list_destroy(u_list_t *list);