X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=bacula%2Fsrc%2Fstored%2Fstored.c;h=957738336fb02483cd4b80d8cb9a2031098582fb;hb=b9265a6898ae36e450755721acfbf4a52342bc2f;hp=1a32be9ac1c9571d44ce3f4ffa66a55b4674250a;hpb=fab3c713ba8e7384fe1fa404d2e93e50cf161ab1;p=bacula%2Fbacula diff --git a/bacula/src/stored/stored.c b/bacula/src/stored/stored.c index 1a32be9ac1..957738336f 100644 --- a/bacula/src/stored/stored.c +++ b/bacula/src/stored/stored.c @@ -10,7 +10,7 @@ * */ /* - Copyright (C) 2000-2003 Kern Sibbald and John Walker + Copyright (C) 2000-2004 Kern Sibbald and John Walker This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as @@ -38,24 +38,25 @@ /* Forward referenced functions */ void terminate_stored(int sig); static void check_config(); -static void *device_allocation(void *arg); + +extern "C" void *device_allocation(void *arg); #define CONFIG_FILE "bacula-sd.conf" /* Default config file */ /* Global variables exported */ +char OK_msg[] = "3000 OK\n"; +char TERM_msg[] = "3999 Terminate\n"; +STORES *me = NULL; /* our Global resource */ +bool forge_on = false; /* proceed inspite of I/O errors */ - -/* This is our own global resource */ -STORES *me; - -static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; static uint32_t VolSessionId = 0; uint32_t VolSessionTime; - char *configfile; -static int foreground = 0; +/* Global static variables */ +static int foreground = 0; +static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; static workq_t dird_workq; /* queue for processing connections */ @@ -63,14 +64,15 @@ static void usage() { fprintf(stderr, _( "\nVersion: " VERSION " (" BDATE ")\n\n" -"Usage: stored [-s -f ] [-c config_file] [-d debug_level] [config_file]\n" +"Usage: stored [options] [-c config_file] [config_file]\n" " -c use as configuration file\n" " -dnn set debug level to nn\n" " -f run in foreground (for debugging)\n" -" -g groupid\n" +" -g set groupid to group\n" +" -p proceed despite I/O errors\n" " -s no signals (for debugging)\n" " -t test - read config and exit\n" -" -u userid\n" +" -u userid to \n" " -v verbose user messages\n" " -? print this message.\n" "\n")); @@ -92,10 +94,10 @@ int main (int argc, char *argv[]) char *gid = NULL; init_stack_dump(); - my_name_is(argc, argv, "stored"); + my_name_is(argc, argv, "bacula-sd"); + textdomain("bacula"); init_msg(NULL, NULL); daemon_start_time = time(NULL); - memset(&last_job, 0, sizeof(last_job)); /* Sanity checks */ if (TAPE_BSIZE % DEV_BSIZE != 0 || TAPE_BSIZE / DEV_BSIZE == 0) { @@ -106,50 +108,54 @@ int main (int argc, char *argv[]) Emsg1(M_ABORT, 0, "Tape block size (%d) is not a power of 2\n", TAPE_BSIZE); } - while ((ch = getopt(argc, argv, "c:d:fg:stu:v?")) != -1) { + while ((ch = getopt(argc, argv, "c:d:fg:pstu:v?")) != -1) { switch (ch) { - case 'c': /* configuration file */ - if (configfile != NULL) { - free(configfile); - } - configfile = bstrdup(optarg); - break; + case 'c': /* configuration file */ + if (configfile != NULL) { + free(configfile); + } + configfile = bstrdup(optarg); + break; - case 'd': /* debug level */ - debug_level = atoi(optarg); - if (debug_level <= 0) { - debug_level = 1; - } - break; + case 'd': /* debug level */ + debug_level = atoi(optarg); + if (debug_level <= 0) { + debug_level = 1; + } + break; - case 'f': /* run in foreground */ - foreground = TRUE; - break; + case 'f': /* run in foreground */ + foreground = TRUE; + break; - case 'g': /* set group id */ - gid = optarg; - break; + case 'g': /* set group id */ + gid = optarg; + break; - case 's': /* no signals */ - no_signals = TRUE; - break; + case 'p': /* proceed in spite of I/O errors */ + forge_on = true; + break; - case 't': - test_config = TRUE; - break; + case 's': /* no signals */ + no_signals = TRUE; + break; - case 'u': /* set uid */ - uid = optarg; - break; + case 't': + test_config = TRUE; + break; - case 'v': /* verbose */ - verbose++; - break; + case 'u': /* set uid */ + uid = optarg; + break; - case '?': - default: - usage(); + case 'v': /* verbose */ + verbose++; + break; + case '?': + default: + usage(); + break; } } argc -= optind; @@ -187,9 +193,10 @@ int main (int argc, char *argv[]) init_stack_dump(); /* pick up new pid */ } - drop(uid, gid); - create_pid_file(me->pid_directory, "bacula-sd", me->SDport); + read_state_file(me->working_directory, "bacula-sd", me->SDport); + + drop(uid, gid); /* Ensure that Volume Session Time and Id are both * set and are both non-zero. @@ -211,6 +218,8 @@ int main (int argc, char *argv[]) start_watchdog(); /* start watchdog thread */ + init_jcr_subsystem(); /* start JCR watchdogs etc. */ + /* * Sleep a bit to give device thread a chance to lock the resource * chain before we start the server. @@ -219,7 +228,7 @@ int main (int argc, char *argv[]) /* Single server used for Director and File daemon */ bnet_thread_server(me->SDaddr, me->SDport, me->max_concurrent_jobs * 2 + 1, - &dird_workq, connection_request); + &dird_workq, handle_connection_request); exit(1); /* to keep compiler quiet */ } @@ -238,8 +247,6 @@ uint32_t newVolSessionId() /* Check Configuration file for necessary info */ static void check_config() { - struct stat stat_buf; - LockRes(); me = (STORES *)GetNextRes(R_STORAGE, NULL); if (!me) { @@ -281,30 +288,23 @@ static void check_config() Emsg1(M_ERROR_TERM, 0, _("No Working Directory defined in %s. Cannot continue.\n"), configfile); } - if (stat(me->working_directory, &stat_buf) != 0) { - Emsg1(M_ERROR_TERM, 0, _("Working Directory: %s not found. Cannot continue.\n"), - me->working_directory); - } - if (!S_ISDIR(stat_buf.st_mode)) { - Emsg1(M_ERROR_TERM, 0, _("Working Directory: %s is not a directory. Cannot continue.\n"), - me->working_directory); - } - working_directory = me->working_directory; + + set_working_directory(me->working_directory); } /* * We are started as a separate thread. The * resources are alread locked. */ -static void *device_allocation(void *arg) +extern "C" +void *device_allocation(void *arg) { - int i; DEVRES *device; LockRes(); pthread_detach(pthread_self()); - for (device=NULL,i=0; (device=(DEVRES *)GetNextRes(R_DEVICE, (RES *)device)); i++) { + foreach_res(device, R_DEVICE) { Dmsg1(90, "calling init_dev %s\n", device->device_name); device->dev = init_dev(NULL, device); Dmsg1(10, "SD init done %s\n", device->device_name); @@ -312,19 +312,27 @@ static void *device_allocation(void *arg) Emsg1(M_ERROR, 0, _("Could not initialize %s\n"), device->device_name); continue; } + if (device->cap_bits & CAP_ALWAYSOPEN) { - Dmsg1(20, "calling open_device %s\n", device->device_name); - if (!open_device(device->dev)) { + Dmsg1(20, "calling first_open_device %s\n", device->device_name); + if (!first_open_device(device->dev)) { Emsg1(M_ERROR, 0, _("Could not open device %s\n"), device->device_name); } } if (device->cap_bits & CAP_AUTOMOUNT && device->dev && device->dev->state & ST_OPENED) { - DEV_BLOCK *block; JCR *jcr; - block = new_block(device->dev); + DCR *dcr; jcr = new_jcr(sizeof(JCR), stored_free_jcr); - switch (read_dev_volume_label(jcr, device->dev, block)) { + jcr->JobType = JT_SYSTEM; + /* Initialize FD start condition variable */ + int errstat = pthread_cond_init(&jcr->job_start_wait, NULL); + if (errstat != 0) { + Jmsg1(jcr, M_ABORT, 0, _("Unable to init job cond variable: ERR=%s\n"), strerror(errstat)); + } + jcr->device = device; + dcr = new_dcr(jcr, device->dev); + switch (read_dev_volume_label(dcr, dcr->block)) { case VOL_OK: break; default: @@ -332,7 +340,6 @@ static void *device_allocation(void *arg) break; } free_jcr(jcr); - free_block(block); } } UnlockRes(); @@ -345,19 +352,50 @@ void terminate_stored(int sig) { static int in_here = FALSE; DEVRES *device; + JCR *jcr; if (in_here) { /* prevent loops */ exit(1); } in_here = TRUE; + if (sig == SIGTERM) { /* normal shutdown request? */ + /* + * This is a normal shutdown request. We wiffle through + * all open jobs canceling them and trying to wake + * them up so that they will report back the correct + * volume status. + */ + lock_jcr_chain(); + foreach_jcr(jcr) { + BSOCK *fd; + free_locked_jcr(jcr); + if (jcr->JobId == 0) { + continue; /* ignore console */ + } + set_jcr_job_status(jcr, JS_Canceled); + fd = jcr->file_bsock; + if (fd) { + fd->timed_out = TRUE; + Dmsg1(100, "killing JobId=%d\n", jcr->JobId); + pthread_kill(jcr->my_thread_id, TIMEOUT_SIGNAL); + if (jcr->device && jcr->device->dev && jcr->device->dev->dev_blocked) { + pthread_cond_signal(&jcr->device->dev->wait_next_vol); + } + bmicrosleep(0, 50000); + } + } + unlock_jcr_chain(); + bmicrosleep(0, 500000); /* give them 1/2 sec to clean up */ + } + + write_state_file(me->working_directory, "bacula-sd", me->SDport); delete_pid_file(me->pid_directory, "bacula-sd", me->SDport); - stop_watchdog(); - Dmsg0(200, "In terminate_stored()\n"); + Dmsg1(200, "In terminate_stored() sig=%d\n", sig); LockRes(); - for (device=NULL; (device=(DEVRES *)GetNextRes(R_DEVICE, (RES *)device)); ) { + foreach_res(device, R_DEVICE) { if (device->dev) { term_dev(device->dev); } @@ -372,8 +410,9 @@ void terminate_stored(int sig) print_memory_pool_stats(); } term_msg(); + stop_watchdog(); close_memory_pool(); - sm_dump(False); /* dump orphaned buffers */ - exit(1); + sm_dump(false); /* dump orphaned buffers */ + exit(sig); }