From ecafe729920ea0a539a8f47711c3cd06407b87a7 Mon Sep 17 00:00:00 2001 From: Kern Sibbald Date: Sat, 3 May 2003 16:11:58 +0000 Subject: [PATCH] Misc see kes-1.30a git-svn-id: https://bacula.svn.sourceforge.net/svnroot/bacula/trunk@483 91ce42f0-d328-0410-95d8-f526ca767f89 --- bacula/kernstodo | 3 ++ bacula/scripts/btraceback.in | 4 +-- bacula/src/console.glade | 66 +++++++++++++++++++++++++++++++++--- bacula/src/dird/job.c | 4 +++ bacula/src/dird/protos.h | 3 ++ bacula/src/dird/ua.h | 2 ++ bacula/src/dird/ua_cmds.c | 19 ++++------- bacula/src/dird/ua_dotcmds.c | 2 ++ bacula/src/dird/ua_input.c | 66 +++++++++++++++++++++++++++++++++--- bacula/src/dird/ua_label.c | 16 +++++++-- bacula/src/dird/ua_select.c | 39 ++++++++++++++------- bacula/src/filed/backup.c | 16 ++++++--- bacula/src/jcr.h | 1 + bacula/src/lib/bnet.c | 31 ++++++++++++++++- bacula/src/lib/protos.h | 2 +- bacula/src/lib/signal.c | 15 ++++++-- bacula/src/version.h | 2 +- 17 files changed, 242 insertions(+), 49 deletions(-) diff --git a/bacula/kernstodo b/bacula/kernstodo index 40ec0450ac..e9224e573a 100644 --- a/bacula/kernstodo +++ b/bacula/kernstodo @@ -20,6 +20,9 @@ For 1.30a release: - Test multiple simultaneous Volumes - Document FInclude ... +- Test and implement get_pint and get_yesno. +- Implement timeout in response() when it should come quickly. + - Figure out how to use ssh or stunnel to protect Bacula communications. After 1.30: diff --git a/bacula/scripts/btraceback.in b/bacula/scripts/btraceback.in index 8d29d9469e..bc9d87c67b 100755 --- a/bacula/scripts/btraceback.in +++ b/bacula/scripts/btraceback.in @@ -8,8 +8,8 @@ # $1 = path to executable # $2 = main pid of running program to be traced back. # - -gdb -quiet -batch -x @sbindir@/btraceback.gdb $1 $2 2>&1 | mail -s "Bacula traceback" @dump_email@ +gdb -quiet -batch -x @sbindir@/btraceback.gdb $1 $2 2>&1 \ + | @sbindir@/smtp -h @smtp_host@ -s "Bacula traceback" @dump_email@ # Below is some old code that did the traceback from a core # dump. However, for some odd reason, core dumps are not diff --git a/bacula/src/console.glade b/bacula/src/console.glade index 71a9eab4dc..84b6eec753 100644 --- a/bacula/src/console.glade +++ b/bacula/src/console.glade @@ -2344,7 +2344,7 @@ GtkLabel label107 - 70 + 78 GTK_JUSTIFY_CENTER False @@ -2407,7 +2407,7 @@ GtkLabel label109 - 70 + 78 GTK_JUSTIFY_LEFT False @@ -2470,11 +2470,11 @@ GtkLabel label111 - 70 + 78 GTK_JUSTIFY_LEFT False - 0.18 + 0.17 0.5 0 0 @@ -2505,6 +2505,64 @@ + + GtkHBox + hbox48 + 5 + False + 0 + + 0 + True + True + + + + GtkLabel + slot1 + 93 + + GTK_JUSTIFY_LEFT + False + 0.09 + 0.5 + 0 + 0 + + 0 + False + True + + + + + GtkSpinButton + label_slot + True + 1 + 0 + True + GTK_UPDATE_ALWAYS + False + False + 0 + 0 + 10000 + 1 + 10 + 10 + + 0 + True + True + + + + + Placeholder + + + GtkLabel label113 diff --git a/bacula/src/dird/job.c b/bacula/src/dird/job.c index 4a73ac3895..5da55395ea 100644 --- a/bacula/src/dird/job.c +++ b/bacula/src/dird/job.c @@ -359,6 +359,7 @@ wait: V(mutex); /* Try again */ } + jcr->acquired_resource_locks = 1; #endif return 1; } @@ -403,6 +404,9 @@ static void backoff_resource_locks(JCR *jcr, int count) */ static void release_resource_locks(JCR *jcr) { + if (!jcr->acquired_resource_locks) { + return; /* Job canceled, no locks acquired */ + } #ifdef USE_SEMAPHORE P(mutex); sem_unlock(&jcr->store->sem); diff --git a/bacula/src/dird/protos.h b/bacula/src/dird/protos.h index 05ebb1d88f..5f808e4bf6 100644 --- a/bacula/src/dird/protos.h +++ b/bacula/src/dird/protos.h @@ -88,6 +88,8 @@ void set_pool_dbr_defaults_in_media_dbr(MEDIA_DBR *mr, POOL_DBR *pr); /* ua_input.c */ int get_cmd(UAContext *ua, char *prompt); +int get_pint(UAContext *ua, char *prompt); +int get_yesno(UAContext *ua, char *prompt); void parse_ua_args(UAContext *ua); /* ua_output.c */ @@ -122,6 +124,7 @@ int get_job_dbr(UAContext *ua, JOB_DBR *jr); int find_arg_keyword(UAContext *ua, char **list); int find_arg(UAContext *ua, char *keyword); +int find_arg_with_value(UAContext *ua, char *keyword); int do_keyword_prompt(UAContext *ua, char *msg, char **list); int confirm_retention(UAContext *ua, utime_t *ret, char *msg); diff --git a/bacula/src/dird/ua.h b/bacula/src/dird/ua.h index b7d33892f5..73aa81f9ff 100644 --- a/bacula/src/dird/ua.h +++ b/bacula/src/dird/ua.h @@ -48,6 +48,8 @@ typedef struct s_ua_context { int automount; /* if set, mount after label */ int quit; /* if set, quit */ int verbose; /* set for normal UA verbosity */ + uint32_t pint32_val; /* positive integer */ + int32_t int32_val; /* positive/negative */ } UAContext; #endif diff --git a/bacula/src/dird/ua_cmds.c b/bacula/src/dird/ua_cmds.c index 3381a6063e..11dc32e92b 100644 --- a/bacula/src/dird/ua_cmds.c +++ b/bacula/src/dird/ua_cmds.c @@ -241,11 +241,11 @@ static int addcmd(UAContext *ua, char *cmd) } getVolName: if (num == 0) { - if (!get_cmd(ua, _("Enter Volume name: ")) || ua->cmd[0] == '.') { + if (!get_cmd(ua, _("Enter Volume name: "))) { return 1; } } else { - if (!get_cmd(ua, _("Enter base volume name: ")) || ua->cmd[0] == '.') { + if (!get_cmd(ua, _("Enter base volume name: "))) { return 1; } } @@ -284,7 +284,7 @@ getVolName: } if (store && store->autochanger) { - if (!get_cmd(ua, _("Enter slot (0 for none): ")) || ua->cmd[0] == '.') { + if (!get_cmd(ua, _("Enter slot (0 for none): "))) { return 1; } slot = atoi(ua->cmd); @@ -410,10 +410,7 @@ static int cancelcmd(UAContext *ua, char *cmd) return 1; } if (njobs == 1) { - if (!get_cmd(ua, _("Confirm cancel (yes/no): "))) { - return 1; - } - if (strcasecmp(ua->cmd, _("yes")) != 0) { + if (!get_yesno(ua, _("Confirm cancel (yes/no): ")) || ua->pint32_val == 0) { return 1; } } @@ -1101,11 +1098,9 @@ static int setdebugcmd(UAContext *ua, char *cmd) Dmsg1(120, "setdebug:%s:\n", cmd); level = -1; - for (i=1; iargc; i++) { - if (strcasecmp(ua->argk[i], _("level")) == 0 && ua->argv[i]) { - level = atoi(ua->argv[i]); - break; - } + i = find_arg_with_value(ua, _("level")); + if (i >= 0) { + level = atoi(ua->argv[i]); } if (level < 0) { if (!get_cmd(ua, _("Enter new debug level: "))) { diff --git a/bacula/src/dird/ua_dotcmds.c b/bacula/src/dird/ua_dotcmds.c index 605def60f6..4f85e6e2ef 100644 --- a/bacula/src/dird/ua_dotcmds.c +++ b/bacula/src/dird/ua_dotcmds.c @@ -118,7 +118,9 @@ static int diecmd(UAContext *ua, char *cmd) JCR *jcr = NULL; int a; + bsendmsg(ua, "The Director will segment fault.\n"); a = jcr->JobId; /* ref NULL pointer */ + jcr->JobId = 1000; /* another ref NULL pointer */ return 0; } diff --git a/bacula/src/dird/ua_input.c b/bacula/src/dird/ua_input.c index 13d7d3f6fd..646d349195 100644 --- a/bacula/src/dird/ua_input.c +++ b/bacula/src/dird/ua_input.c @@ -61,16 +61,74 @@ int get_cmd(UAContext *ua, char *prompt) if (strcmp(ua->cmd, ".messages") == 0) { qmessagescmd(ua, ua->cmd); } - /* ****FIXME**** if .command, go off and do it. For now ignore it. */ - if (ua->cmd[0] == '.' && ua->cmd[1] != 0) { - continue; /* dot command */ + /* Lone dot => break */ + if (ua->cmd[0] == '.' && ua->cmd[1] == 0) { + return 0; } - /* Lone dot => break or actual response */ break; } return 1; } +/* + * Get a positive integer + * Returns: 0 if failure + * 1 if success => value in ua->pint32_val + */ +int get_pint(UAContext *ua, char *prompt) +{ + double dval; + ua->pint32_val = 0; + for (;;) { + if (!get_cmd(ua, prompt)) { + return 0; + } + if (!is_a_number(ua->cmd)) { + bsendmsg(ua, "Expected a positive integer, got: %s\n", ua->cmd); + continue; + } + errno = 0; + dval = strtod(ua->cmd, NULL); + if (errno != 0 || dval < 0) { + bsendmsg(ua, "Expected a positive integer, got: %s\n", ua->cmd); + continue; + } + ua->pint32_val = (uint32_t)dval; + return 1; + } +} + +/* + * Gets a yes or no response + * Returns: 0 if failure + * 1 if success => ua->pint32_val == 1 for yes + * ua->pint32_val == 0 for no + */ +int get_yesno(UAContext *ua, char *prompt) +{ + int len; + + ua->pint32_val = 0; + for (;;) { + if (!get_cmd(ua, prompt)) { + return 0; + } + len = strlen(ua->cmd); + if (len < 1 || len > 3) { + continue; + } + if (strncasecmp(ua->cmd, _("yes"), len) == 0) { + ua->pint32_val = 1; + return 1; + } + if (strncasecmp(ua->cmd, _("no"), len) == 0) { + return 1; + } + bsendmsg(ua, _("Invalid response. You must answer yes or no.\n")); + } +} + + void parse_ua_args(UAContext *ua) { return parse_command_args(ua->cmd, ua->args, &ua->argc, ua->argk, ua->argv); diff --git a/bacula/src/dird/ua_label.c b/bacula/src/dird/ua_label.c index 554dc7cc33..9020445e4f 100644 --- a/bacula/src/dird/ua_label.c +++ b/bacula/src/dird/ua_label.c @@ -225,17 +225,27 @@ checkName: /* If autochanger, request slot */ if (store->autochanger) { + int first = 1; for ( ;; ) { - if (!get_cmd(ua, _("Enter slot (0 for none): ")) || ua->cmd[0] == '.') { - return 1; + if (first) { + i = find_arg(ua, "slot"); + if (i >= 0 && ua->argv[i]) { + mr.Slot = atoi(ua->argv[i]); + } + first = 0; + } else { + if (!get_cmd(ua, _("Enter slot (0 for none): ")) || ua->cmd[0] == '.') { + return 1; + } + mr.Slot = atoi(ua->cmd); } - mr.Slot = atoi(ua->cmd); if (mr.Slot >= 0) { /* OK */ break; } bsendmsg(ua, _("Slot numbers must be positive.\n")); } } + bstrncpy(mr.MediaType, store->media_type, sizeof(mr.MediaType)); /* Must select Pool if not already done */ diff --git a/bacula/src/dird/ua_select.c b/bacula/src/dird/ua_select.c index c34ccc4657..bc3eb0038d 100644 --- a/bacula/src/dird/ua_select.c +++ b/bacula/src/dird/ua_select.c @@ -97,6 +97,21 @@ int find_arg(UAContext *ua, char *keyword) return -1; } +int find_arg_with_value(UAContext *ua, char *keyword) +{ + for (int i=1; iargc; i++) { + if (strcasecmp(keyword, ua->argk[i]) == 0) { + if (ua->argv[i]) { + return i; + } else { + return -1; + } + } + } + return -1; +} + + /* * Given a list of keywords, prompt the user @@ -459,8 +474,8 @@ int select_media_dbr(UAContext *ua, MEDIA_DBR *mr) memset(mr, 0, sizeof(MEDIA_DBR)); - i = find_arg(ua, "volume"); - if (i >= 0 && ua->argv[i]) { + i = find_arg_with_value(ua, "volume"); + if (i >= 0) { bstrncpy(mr->VolumeName, ua->argv[i], sizeof(mr->VolumeName)); } if (mr->VolumeName[0] == 0) { @@ -520,15 +535,13 @@ POOL *get_pool_resource(UAContext *ua) POOL *pool = NULL; int i; - for (i=1; iargc; i++) { - if (strcasecmp(ua->argk[i], _("pool")) == 0 && ua->argv[i]) { - pool = (POOL *)GetResWithName(R_POOL, ua->argv[i]); - if (pool) { - return pool; - } - bsendmsg(ua, _("Error: Pool resource %s does not exist.\n"), ua->argv[i]); - break; + i = find_arg_with_value(ua, "pool"); + if (i >= 0) { + pool = (POOL *)GetResWithName(R_POOL, ua->argv[i]); + if (pool) { + return pool; } + bsendmsg(ua, _("Error: Pool resource %s does not exist.\n"), ua->argv[i]); } return select_pool_resource(ua); } @@ -661,7 +674,7 @@ int do_prompt(UAContext *ua, char *msg, char *prompt, int max_prompt) sprintf(pmsg, "%s (1-%d): ", msg, ua->num_prompts-1); } /* Either a . or an @ will get you out of the loop */ - if (!get_cmd(ua, pmsg) || *ua->cmd == '.' || *ua->cmd == '@') { + if (!get_cmd(ua, pmsg) || *ua->cmd == '@') { item = -1; /* error */ bsendmsg(ua, _("Selection aborted, nothing done.\n")); break; @@ -779,8 +792,8 @@ int get_media_type(UAContext *ua, char *MediaType, int max_media) STORE *store; int i; - i = find_arg(ua, "mediatype"); - if (i >= 0 && ua->argv[i]) { + i = find_arg_with_value(ua, "mediatype"); + if (i >= 0) { bstrncpy(MediaType, ua->argv[i], max_media); return 1; } diff --git a/bacula/src/filed/backup.c b/bacula/src/filed/backup.c index a127b0da61..49f47a708b 100644 --- a/bacula/src/filed/backup.c +++ b/bacula/src/filed/backup.c @@ -50,17 +50,19 @@ static void *heartbeat_thread(void *arg) * a heartbeat, we simply send it on to the Director to * keep him alive. */ - for ( ;; ) { - n = bnet_recv(sd); - if (is_bnet_stop(sd)) { - break; + for ( ; !is_bnet_stop(sd); ) { + n = bnet_wait_data_intr(sd, 60); + if (n != 1) { + continue; } + n = bnet_recv(sd); if (n == BNET_SIGNAL && sd->msglen == BNET_HEARTBEAT) { bnet_sig(dir, BNET_HEARTBEAT); } } bnet_close(sd); bnet_close(dir); + jcr->duped_sd = NULL; return NULL; } @@ -81,8 +83,12 @@ static void stop_heartbeat_monitor(JCR *jcr) bmicrosleep(0, 500); /* avoid race */ } jcr->duped_sd->timed_out = 1; /* set timed_out to terminate read */ + jcr->duped_sd->terminated = 1; /* set to terminate read */ - pthread_kill(hbtid, TIMEOUT_SIGNAL); /* make heartbeat thread go away */ + while (jcr->duped_sd) { + pthread_kill(hbtid, TIMEOUT_SIGNAL); /* make heartbeat thread go away */ + bmicrosleep(0, 20); + } pthread_join(hbtid, NULL); /* wait for him to clean up */ } diff --git a/bacula/src/jcr.h b/bacula/src/jcr.h index ed4d390a5a..dfd9db3d87 100644 --- a/bacula/src/jcr.h +++ b/bacula/src/jcr.h @@ -149,6 +149,7 @@ struct s_jcr { char *RestoreWhere; /* Where to restore the files */ POOLMEM *client_uname; /* client uname */ int replace; /* Replace option */ + int acquired_resource_locks; /* set if resource locks acquired */ #endif /* DIRECTOR_DAEMON */ diff --git a/bacula/src/lib/bnet.c b/bacula/src/lib/bnet.c index 66aa09add0..73d1ab3a19 100644 --- a/bacula/src/lib/bnet.c +++ b/bacula/src/lib/bnet.c @@ -382,7 +382,7 @@ int bnet_ssl_client(BSOCK *bsock, char *password, int ssl_need) * -1 if error */ int -bnet_wait_data(BSOCK *bsock, int sec) +bnet_wait_data(BSOCK *bsock, int sec) { fd_set fdset; struct timeval tv; @@ -409,6 +409,35 @@ bnet_wait_data(BSOCK *bsock, int sec) } } +/* + * As above, but returns on interrupt + */ +int +bnet_wait_data_intr(BSOCK *bsock, int sec) +{ + fd_set fdset; + struct timeval tv; + + FD_ZERO(&fdset); + FD_SET(bsock->fd, &fdset); + tv.tv_sec = sec; + tv.tv_usec = 0; + for ( ;; ) { + switch(select(bsock->fd + 1, &fdset, NULL, NULL, &tv)) { + case 0: /* timeout */ + bsock->b_errno = 0; + return 0; + case -1: + bsock->b_errno = errno; + return -1; /* error return */ + default: + bsock->b_errno = 0; + return 1; + } + } +} + + static pthread_mutex_t ip_mutex = PTHREAD_MUTEX_INITIALIZER; /* diff --git a/bacula/src/lib/protos.h b/bacula/src/lib/protos.h index aad26b6f87..93f4801715 100644 --- a/bacula/src/lib/protos.h +++ b/bacula/src/lib/protos.h @@ -58,7 +58,6 @@ int bnet_ssl_client (BSOCK *bsock, char *password, int ssl_need); BSOCK * bnet_connect (void *jcr, int retry_interval, int max_retry_time, char *name, char *host, char *service, int port, int verbose); -int bnet_wait_data (BSOCK *bsock, int sec); void bnet_close (BSOCK *bsock); BSOCK * init_bsock (void *jcr, int sockfd, char *who, char *ip, int port); BSOCK * dup_bsock (BSOCK *bsock); @@ -66,6 +65,7 @@ void term_bsock (BSOCK *bsock); char * bnet_strerror (BSOCK *bsock); char * bnet_sig_to_ascii (BSOCK *bsock); int bnet_wait_data (BSOCK *bsock, int sec); +int bnet_wait_data_intr (BSOCK *bsock, int sec); int bnet_despool (BSOCK *bsock); int is_bnet_stop (BSOCK *bsock); int is_bnet_error (BSOCK *bsock); diff --git a/bacula/src/lib/signal.c b/bacula/src/lib/signal.c index 0bbd312391..aea28d9453 100644 --- a/bacula/src/lib/signal.c +++ b/bacula/src/lib/signal.c @@ -83,17 +83,24 @@ static void signal_handler(int sig) static char pid_buf[20]; static char btpath[400]; pid_t pid; + int exelen = strlen(exepath); fprintf(stderr, "Kaboom! %s, %s got signal %d. Attempting traceback.\n", exename, my_name, sig); - if (strlen(exepath) + 12 > (int)sizeof(btpath)) { + if (exelen + 12 > (int)sizeof(btpath)) { strcpy(btpath, "btraceback"); } else { strcpy(btpath, exepath); - strcat(btpath, "/btraceback"); + if (btpath[exelen-1] != '/') { + strcat(btpath, "/btraceback"); + } else { + strcat(btpath, "btraceback"); + } + } + if (btpath[exelen-1] != '/') { + strcat(exepath, "/"); } - strcat(exepath, "/"); strcat(exepath, exename); if (chdir(working_directory) !=0) { /* dump in working directory */ Pmsg2(000, "chdir to %s failed. ERR=%s\n", working_directory, strerror(errno)); @@ -112,6 +119,7 @@ static void signal_handler(int sig) argv[1] = exepath; /* path to exe */ argv[2] = pid_buf; argv[3] = (char *)NULL; + fprintf(stderr, "Calling: %s %s %s\n", btpath, exepath, pid_buf); if (execv(btpath, argv) != 0) { printf("execv: %s failed: ERR=%s\n", btpath, strerror(errno)); } @@ -119,6 +127,7 @@ static void signal_handler(int sig) default: /* parent */ break; } + /* Parent continue here, waiting for child */ sigdefault.sa_flags = 0; sigdefault.sa_handler = SIG_DFL; sigfillset(&sigdefault.sa_mask); diff --git a/bacula/src/version.h b/bacula/src/version.h index 843cd4e467..dd31484f94 100644 --- a/bacula/src/version.h +++ b/bacula/src/version.h @@ -11,7 +11,7 @@ #define TRACE_FILE 1 /* Turn this on if you want to try the new Job semaphore code */ -/* #define USE_SEMAPHORE */ +#define USE_SEMAPHORE /* IF you undefine this, Bacula will run 10X slower */ #define NO_POLL_TEST 1 -- 2.39.5