From 8ec251cb550cd63e006e4cf338432bbce154cb18 Mon Sep 17 00:00:00 2001 From: Kern Sibbald Date: Mon, 28 Jul 2003 20:14:58 +0000 Subject: [PATCH] Fix SIGTSTP loop in Console, complete hash code git-svn-id: https://bacula.svn.sourceforge.net/svnroot/bacula/trunk@649 91ce42f0-d328-0410-95d8-f526ca767f89 --- bacula/ChangeLog | 8 ++++ bacula/kernstodo | 28 +++++++++++- bacula/src/console/console.c | 49 ++++++++++---------- bacula/src/dird/jobq.c | 22 ++++++--- bacula/src/findlib/attribs.c | 8 +++- bacula/src/lib/htable.c | 87 +++++++++++++++++++++++++++++------- bacula/src/lib/htable.h | 42 ++++++++--------- bacula/src/version.h | 4 +- 8 files changed, 174 insertions(+), 74 deletions(-) diff --git a/bacula/ChangeLog b/bacula/ChangeLog index a1fb5767e2..bec153b2e2 100644 --- a/bacula/ChangeLog +++ b/bacula/ChangeLog @@ -1,4 +1,12 @@ +2003-07-xx Version 1.31 Beta 28Jul03 +- Add sleep(1) to console when it gets a SIGTSTP signal + to prevent it from using 100% of the CPU. +- Improve description of Priorities. +- Add a bit more documentation to jobq.c +- Complete hash table routine htable.c htable.h +- Change M_INFO to M_ERROR in attribs.c for Windows errors. + 2003-07-23 Version 1.31 Beta 22Jul03 - Apply a patch from Nic Bellamy that clarifies the error messages during recycling volumes. diff --git a/bacula/kernstodo b/bacula/kernstodo index 0a111a1cdc..f950c6b98a 100644 --- a/bacula/kernstodo +++ b/bacula/kernstodo @@ -1,5 +1,5 @@ Kern's ToDo List - 14 July 2003 + 28 July 2003 Documentation to do: (any release a little bit at a time) - Document running a test version. @@ -18,6 +18,30 @@ Documentation to do: (any release a little bit at a time) (./create_mys... ./make_my...). - Document all the status codes JobLevel, JobType, JobStatus. - Document dynamic DNS +- On Fri, 2003-07-25 at 22:39, Thiago Lima wrote: + I've just noticed that bacula uses the server time to scan the + > clients for new files since the last backup in incremental backup. + > So if server and client clocks aren't synced you may not backup all + > files. + > + > Example : + > + > Server time : 16:05 + > Client time : 16:00 + > runs full backup + > + > Server time : 16:15 + > Client time : 16:10 + > runs incremental backup + > + > If there's any file created/changed between 16:00 and 16:05 (client + > clock) they will never be backuped. + > The solution is keep all your machines clocks synced. + > + > Is that right? Does anybody have any comments on that? Maybe this + > could go to the FAQ? + > + > Testing to do: (painful) - that ALL console command line options work and are always implemented @@ -32,6 +56,7 @@ Testing to do: (painful) For 1.31 release: + For 1.32: - Maybe remove multiple simultaneous devices code in SD. - On Windows with very long path names, it may be impossible to create @@ -1032,4 +1057,3 @@ Done: (see kernsdone for more) (Phil's problem). - Increment DB version prior to releasing. - Turn off FULL_DEBUG prior to releasing. - diff --git a/bacula/src/console/console.c b/bacula/src/console/console.c index b036edc30d..769ae122a5 100644 --- a/bacula/src/console/console.c +++ b/bacula/src/console/console.c @@ -442,21 +442,21 @@ wait_for_data(int fd, int sec) fd_set fdset; struct timeval tv; - FD_ZERO(&fdset); - FD_SET(fd, &fdset); tv.tv_sec = sec; tv.tv_usec = 0; for ( ;; ) { + FD_ZERO(&fdset); + FD_SET(fd, &fdset); switch(select(fd + 1, &fdset, NULL, NULL, &tv)) { - case 0: /* timeout */ - return 0; - case -1: - if (errno == EINTR || errno == EAGAIN) { - continue; - } - return -1; /* error return */ - default: - return 1; + case 0: /* timeout */ + return 0; + case -1: + if (errno == EINTR || errno == EAGAIN) { + continue; + } + return -1; /* error return */ + default: + return 1; } } } @@ -480,19 +480,20 @@ get_cmd(FILE *input, char *prompt, BSOCK *sock, int sec) } again: switch (wait_for_data(fileno(input), sec)) { - case 0: - return 0; /* timeout */ - case -1: - return -1; /* error */ - default: - len = sizeof_pool_memory(sock->msg) - 1; - if (stop) { - goto again; - } - if (fgets(sock->msg, len, input) == NULL) { - return -1; - } - break; + case 0: + return 0; /* timeout */ + case -1: + return -1; /* error */ + default: + len = sizeof_pool_memory(sock->msg) - 1; + if (stop) { + sleep(1); + goto again; + } + if (fgets(sock->msg, len, input) == NULL) { + return -1; + } + break; } strip_trailing_junk(sock->msg); sock->msglen = strlen(sock->msg); diff --git a/bacula/src/dird/jobq.c b/bacula/src/dird/jobq.c index 1768939118..c416ee7e2b 100755 --- a/bacula/src/dird/jobq.c +++ b/bacula/src/dird/jobq.c @@ -140,7 +140,11 @@ struct wait_pkt { }; /* - * Wait until schedule time arrives before starting + * Wait until schedule time arrives before starting. Normally + * this routine is only used for jobs started from the console + * for which the user explicitly specified a start time. Otherwise + * most jobs are put into the job queue only when their + * scheduled time arives. */ static void *sched_wait(void *arg) { @@ -236,6 +240,7 @@ int jobq_add(jobq_t *jq, JCR *jcr) } } + /* Ensure that at least one server looks at the queue. */ stat = start_server(jq); if (stat == 0) { @@ -246,7 +251,7 @@ int jobq_add(jobq_t *jq, JCR *jcr) } /* - * Remove a job from the job queue + * Remove a job from the job queue. Used only by cancel Console command. * jq is a queue that was created with jobq_init * work_item is an element of work * @@ -294,7 +299,7 @@ int jobq_remove(jobq_t *jq, JCR *jcr) /* - * Start the server thread + * Start the server thread if it isn't already running */ static int start_server(jobq_t *jq) { @@ -433,7 +438,7 @@ static void *jobq_server(void *arg) jobq_add(jq, jcr); /* queue the job to run again */ P(jq->mutex); free(je); /* free the job entry */ - continue; + continue; /* look for another job to run */ } /* * Something was actually backed up, so we cannot reuse @@ -451,7 +456,7 @@ static void *jobq_server(void *arg) njcr->messages = jcr->messages; Dmsg0(100, "Call to run new job\n"); V(jq->mutex); - run_job(njcr); + run_job(njcr); /* This creates a "new" job */ P(jq->mutex); Dmsg0(100, "Back from running new job.\n"); } @@ -482,9 +487,11 @@ static void *jobq_server(void *arg) Dmsg1(100, "Set Job pri=%d\n", Priority); } /* - * Acquire locks + * Walk down the list of waiting jobs and attempt + * to acquire the resources it needs. */ for ( ; je; ) { + /* je is current job item on the queue, jn is the next one */ JCR *jcr = je->jcr; jobq_item_t *jn = (jobq_item_t *)jq->waiting_jobs->next(je); Dmsg3(100, "Examining Job=%d JobPri=%d want Pri=%d\n", @@ -518,6 +525,9 @@ static void *jobq_server(void *arg) je = jn; continue; } + /* Got all locks, now remove it from wait queue and append it + * to the ready queue + */ jcr->acquired_resource_locks = true; jq->waiting_jobs->remove(je); jq->ready_jobs->append(je); diff --git a/bacula/src/findlib/attribs.c b/bacula/src/findlib/attribs.c index 9e192c0d01..27d9254262 100755 --- a/bacula/src/findlib/attribs.c +++ b/bacula/src/findlib/attribs.c @@ -416,6 +416,10 @@ static int set_win32_attributes(JCR *jcr, ATTR *attr, BFILE *ofd) ULARGE_INTEGER li; POOLMEM *win32_ofile; + if (!p_GetFileAttributesEx) { + return 0; + } + if (!p || !*p) { /* we should have attributes */ Dmsg2(100, "Attributes missing. of=%s ofd=%d\n", attr->ofname, ofd->fid); if (is_bopen(ofd)) { @@ -498,7 +502,7 @@ void win_error(JCR *jcr, char *prefix, POOLMEM *win32_ofile) NULL); Dmsg3(100, "Error in %s on file %s: ERR=%s\n", prefix, win32_ofile, msg); strip_trailing_junk(msg); - Jmsg(jcr, M_INFO, 0, _("Error in %s file %s: ERR=%s\n"), prefix, win32_ofile, msg); + Jmsg(jcr, M_ERROR, 0, _("Error in %s file %s: ERR=%s\n"), prefix, win32_ofile, msg); LocalFree(msg); } @@ -515,7 +519,7 @@ void win_error(JCR *jcr, char *prefix, DWORD lerror) NULL); strip_trailing_junk(msg); if (jcr) { - Jmsg2(jcr, M_INFO, 0, _("Error in %s: ERR=%s\n"), prefix, msg); + Jmsg2(jcr, M_ERROR, 0, _("Error in %s: ERR=%s\n"), prefix, msg); } else { MessageBox(NULL, msg, prefix, MB_OK); } diff --git a/bacula/src/lib/htable.c b/bacula/src/lib/htable.c index 790578fa7d..1c4c4bf639 100644 --- a/bacula/src/lib/htable.c +++ b/bacula/src/lib/htable.c @@ -4,16 +4,17 @@ * htable is a hash table of items (pointers). This code is * adapted and enhanced from code I wrote in 1982 for a * relocatable linker. At that time, the hash table size - * was fixed and a primary number, which essentially providing - * the hashing. In this program, the hash table can grow when - * it gets too full, so the table is a binary number. The + * was fixed and a primary number, which essentially provides + * the randomness. In this program, the hash table can grow when + * it gets too full, so the table size here is a binary number. The * hashing is provided using an idea from Tcl where the initial - * hash code is then "randomized" a simple calculation from + * hash code is then "randomized" using a simple calculation from * a random number generator that multiplies by a big number + * (I multiply by a prime number, while Tcl did not) * then shifts the results down and does the binary division - * by masking. Increasing the size of the hash table is simple - * simply create a new larger table, walk the old table and - * insert each entry into the new table. + * by masking. Increasing the size of the hash table is simple. + * Just create a new larger table, walk the old table and + * re-hash insert each entry into the new table. * * * Kern Sibbald, July MMIII @@ -65,18 +66,23 @@ void htable::hash_index(char *key) return; } -htable::htable(void *item, void *link) +htable::htable(void *item, void *link, int tsize) { - init(item, link); + init(item, link, tsize); } -void htable::init(void *item, void *link) +void htable::init(void *item, void *link, int tsize) { + int pwr; + tsize >>= 2; + for (pwr=0; tsize; pwr++) { + tsize >>= 1; + } loffset = (char *)link - (char *)item; - mask = 7; /* 3 bits => table size = 8 */ - rshift = 27; /* start using bits 28, 29, 30 */ + mask = ~((~0)< table size = 8 */ + rshift = 30 - pwr; /* start using bits 28, 29, 30 */ num_items = 0; /* number of entries in table */ - buckets = 8; /* hash table size -- power of two */ + buckets = 1<destroy(); + free(tbl); +} + +uint32_t htable::size() +{ + return num_items; +} + +void htable::stats() +{ + int count[10]; + int max = 0; + int i, j; + hlink *p; + printf("\n\nNumItems=%d\nBuckets=%d\n", num_items, buckets); + for (i=0; i<10; i++) { + count[i] = 0; + } + for (i=0; i<(int)buckets; i++) { + p = table[i]; + j = 0; + while (p) { + p = (hlink *)(p->next); + j++; + } + if (j > max) { + max = j; + } + if (j < 10) { + count[j]++; + } + } + for (i=0; i<10; i++) { + printf("%2d: %d\n",i, count[i]); + } + printf("max = %d\n", max); +} + void htable::grow_table() { Dmsg1(000, "Grow called old size = %d\n", buckets); @@ -246,11 +298,11 @@ int main() MYJCR *save_jcr = NULL, *item; MYJCR *jcr = NULL; int count = 0; - + jcrtbl = (htable *)malloc(sizeof(htable)); - jcrtbl->init(jcr, &jcr->link); + jcrtbl->init(jcr, &jcr->link, NITEMS); - Dmsg0(000, "Insert NITEMS items 0-19\n"); + Dmsg1(000, "Inserting %d items\n", NITEMS); for (int i=0; ikey); } + jcrtbl->stats(); printf("Walk the hash table:\n"); for (MYJCR *jcr=(MYJCR *)jcrtbl->first(); jcr; jcr=(MYJCR *)jcrtbl->next() ) { - printf("htable item = %s\n", jcr->key); +// printf("htable item = %s\n", jcr->key); free(jcr->key); count++; } diff --git a/bacula/src/lib/htable.h b/bacula/src/lib/htable.h index d1bd82301b..e2cb3c3a73 100644 --- a/bacula/src/lib/htable.h +++ b/bacula/src/lib/htable.h @@ -28,36 +28,36 @@ * */ -#define OFFSET(item,link) ((char *)link - (char *)item) - struct hlink { - void *next; /* next hash item */ - char *key; /* key this item */ - uint32_t hash; /* hash for this key */ + void *next; /* next hash item */ + char *key; /* key this item */ + uint32_t hash; /* hash for this key */ }; class htable { - hlink **table; /* hash table */ - int loffset; /* link offset in item */ - uint32_t num_items; /* current number of items */ - uint32_t max_items; /* maximum items before growing */ - uint32_t buckets; /* size of hash table */ - uint32_t hash; /* temp storage */ - uint32_t index; /* temp storage */ + hlink **table; /* hash table */ + int loffset; /* link offset in item */ + uint32_t num_items; /* current number of items */ + uint32_t max_items; /* maximum items before growing */ + uint32_t buckets; /* size of hash table */ + uint32_t hash; /* temp storage */ + uint32_t index; /* temp storage */ uint32_t mask; /* "remainder" mask */ - uint32_t rshift; /* amount to shift down */ - hlink *walkptr; /* table walk pointer */ - uint32_t walk_index; /* table walk index */ - void hash_index(char *key); /* produce hash key,index */ - void grow_table(); /* grow the table */ + uint32_t rshift; /* amount to shift down */ + hlink *walkptr; /* table walk pointer */ + uint32_t walk_index; /* table walk index */ + void hash_index(char *key); /* produce hash key,index */ + void grow_table(); /* grow the table */ public: - htable(void *item, void *link); - void init(void *item, void *link); + htable(void *item, void *link, int tsize = 31); + void init(void *item, void *link, int tsize = 31); bool insert(char *key, void *item); void *lookup(char *key); - void *first(); /* get first item in table */ - void *next(); /* get next item in table */ + void *first(); /* get first item in table */ + void *next(); /* get next item in table */ void destroy(); + void stats(); /* print stats about the table */ + uint32_t size(); /* return size of table */ void * operator new(size_t); void operator delete(void *); }; diff --git a/bacula/src/version.h b/bacula/src/version.h index 33f1fd21a3..02135eb270 100644 --- a/bacula/src/version.h +++ b/bacula/src/version.h @@ -1,8 +1,8 @@ /* */ #define VERSION "1.31" #define VSTRING "1" -#define BDATE "22 Jul 2003" -#define LSMDATE "22Jul03" +#define BDATE "28 Jul 2003" +#define LSMDATE "28Jul03" /* Debug flags */ #define DEBUG 1 -- 2.39.5