X-Git-Url: https://git.gag.com/?a=blobdiff_plain;f=server-src%2Fdriver.c;h=0a5c2c580377b7b9d0ac3b352dc185b8f110d245;hb=94a044f90357edefa6f4ae9f0b1d5885b0e34aee;hp=d5f265c0d664f084d16d3eccac23c29927acd6b6;hpb=d3b2175e084f88c8736ad7073eacbf4670147aec;p=debian%2Famanda diff --git a/server-src/driver.c b/server-src/driver.c index d5f265c..0a5c2c5 100644 --- a/server-src/driver.c +++ b/server-src/driver.c @@ -24,7 +24,7 @@ * file named AUTHORS, in the root directory of this distribution. */ /* - * $Id: driver.c,v 1.198 2006/08/24 01:57:16 paddy_s Exp $ + * $Id: driver.c 6512 2007-05-24 17:00:24Z ian $ * * controlling process for the Amanda backup system */ @@ -42,24 +42,30 @@ #include "holding.h" #include "infofile.h" #include "logfile.h" -#include "statfs.h" +#include "fsusage.h" #include "version.h" #include "driverio.h" #include "server_util.h" +#include "timestamp.h" -#define driver_debug(i,x) do { \ +#define driver_debug(i, ...) do { \ if ((i) <= debug_driver) { \ - dbprintf(x); \ + dbprintf(__VA_ARGS__); \ } \ } while (0) -#define hold_debug(i,x) do { \ +#define hold_debug(i, ...) do { \ if ((i) <= debug_holding) { \ - dbprintf(x); \ + dbprintf(__VA_ARGS__); \ } \ } while (0) -static disklist_t waitq, runq, tapeq, roomq; +static disklist_t waitq; // dle waiting estimate result +static disklist_t runq; // dle waiting to be dumped to holding disk +static disklist_t directq; // dle waiting to be dumped directly to tape +static disklist_t tapeq; // dle on holding disk waiting to be written + // to tape +static disklist_t roomq; // dle waiting for more space on holding disk static int pending_aborts; static disk_t *taper_disk; static int degraded_mode; @@ -71,7 +77,7 @@ static int inparallel; static int nodump = 0; static off_t tape_length = (off_t)0; static off_t tape_left = (off_t)0; -static int current_tape = 1; +static int current_tape = 0; static int conf_taperalgo; static int conf_runtapes; static time_t sleep_time; @@ -80,30 +86,44 @@ static char *driver_timestamp; static char *hd_driver_timestamp; static am_host_t *flushhost = NULL; static int need_degraded=0; - +static holdalloc_t *holdalloc; +static int num_holdalloc; static event_handle_t *dumpers_ev_time = NULL; static event_handle_t *schedule_ev_read = NULL; +static int conf_flush_threshold_dumped; +static int conf_flush_threshold_scheduled; +static int conf_taperflush; +static off_t flush_threshold_dumped; +static off_t flush_threshold_scheduled; +static off_t taperflush; +static int schedule_done; // 1 if we don't wait for a + // schedule from the planner +static int force_flush; // All dump are terminated, we + // must now respect taper_flush static int wait_children(int count); static void wait_for_children(void); -static void allocate_bandwidth(interface_t *ip, unsigned long kps); +static void allocate_bandwidth(netif_t *ip, unsigned long kps); static int assign_holdingdisk(assignedhd_t **holdp, disk_t *diskp); static void adjust_diskspace(disk_t *diskp, cmd_t cmd); static void delete_diskspace(disk_t *diskp); static assignedhd_t **build_diskspace(char *destname); static int client_constrained(disk_t *dp); -static void deallocate_bandwidth(interface_t *ip, unsigned long kps); +static void deallocate_bandwidth(netif_t *ip, unsigned long kps); static void dump_schedule(disklist_t *qp, char *str); -static int dump_to_tape(disk_t *dp); +static void dump_to_tape(disk_t *dp); static assignedhd_t **find_diskspace(off_t size, int *cur_idle, assignedhd_t *preferred); -static unsigned long free_kps(interface_t *ip); +static unsigned long free_kps(netif_t *ip); static off_t free_space(void); -static void dumper_result(disk_t *dp); +static void dumper_chunker_result(disk_t *dp); +static void dumper_taper_result(disk_t *dp); +static void file_taper_result(disk_t *dp); static void handle_dumper_result(void *); static void handle_chunker_result(void *); static void handle_dumpers_time(void *); static void handle_taper_result(void *); + static void holdingdisk_state(char *time_str); static dumper_t *idle_dumper(void); static void interface_state(char *time_str); @@ -116,48 +136,46 @@ static void start_degraded_mode(disklist_t *queuep); static void start_some_dumps(disklist_t *rq); static void continue_port_dumps(void); static void update_failed_dump_to_tape(disk_t *); -#if 0 -static void dump_state(const char *str); -#endif -int main(int main_argc, char **main_argv); + +typedef enum { + TAPE_ACTION_NO_ACTION = 0, + TAPE_ACTION_NEW_TAPE = (1 << 0), + TAPE_ACTION_NO_NEW_TAPE = (1 << 1), + TAPE_ACTION_START_A_FLUSH = (1 << 2) +} TapeAction; + +static TapeAction tape_action(void); static const char *idle_strings[] = { #define NOT_IDLE 0 - "not-idle", + T_("not-idle"), #define IDLE_NO_DUMPERS 1 - "no-dumpers", + T_("no-dumpers"), #define IDLE_START_WAIT 2 - "start-wait", + T_("start-wait"), #define IDLE_NO_HOLD 3 - "no-hold", + T_("no-hold"), #define IDLE_CLIENT_CONSTRAINED 4 - "client-constrained", -#define IDLE_NO_DISKSPACE 5 - "no-diskspace", -#define IDLE_TOO_LARGE 6 - "file-too-large", -#define IDLE_NO_BANDWIDTH 7 - "no-bandwidth", -#define IDLE_TAPER_WAIT 8 - "taper-wait", + T_("client-constrained"), +#define IDLE_NO_BANDWIDTH 5 + T_("no-bandwidth"), +#define IDLE_NO_DISKSPACE 6 + T_("no-diskspace") }; int main( - int main_argc, - char ** main_argv) + int argc, + char ** argv) { disklist_t origq; disk_t *diskp; int dsk; dumper_t *dumper; char *newdir = NULL; - generic_fs_stats_t fs; + struct fs_usage fsusage; holdingdisk_t *hdp; - unsigned long malloc_hist_1, malloc_size_1; - unsigned long malloc_hist_2, malloc_size_2; unsigned long reserve = 100; - char *conffile; char *conf_diskfile; cmd_t cmd; int result_argc; @@ -166,9 +184,20 @@ main( char *conf_tapetype; tapetype_t *tape; char *line; - int new_argc, my_argc; - char **new_argv, **my_argv; char hostname[1025]; + intmax_t kb_avail; + config_overwrites_t *cfg_ovr = NULL; + char *cfg_opt = NULL; + holdalloc_t *ha, *ha_last; + + /* + * Configure program for internationalization: + * 1) Only set the message locale for now. + * 2) Set textdomain for all amanda related programs to "amanda" + * We don't want to be forced to support dozens of message catalogs. + */ + setlocale(LC_MESSAGES, "C"); + textdomain("amanda"); safe_fd(-1, 0); @@ -184,56 +213,34 @@ main( /* Don't die when child closes pipe */ signal(SIGPIPE, SIG_IGN); - malloc_size_1 = malloc_inuse(&malloc_hist_1); - erroutput_type = (ERR_AMANDALOG|ERR_INTERACTIVE); set_logerror(logerror); startclock(); - parse_conf(main_argc, main_argv, &new_argc, &new_argv); - my_argc = new_argc; - my_argv = new_argv; - - printf("%s: pid %ld executable %s version %s\n", - get_pname(), (long) getpid(), my_argv[0], version()); + cfg_ovr = extract_commandline_config_overwrites(&argc, &argv); - if (my_argc > 1) { - config_name = stralloc(my_argv[1]); - config_dir = vstralloc(CONFIG_DIR, "/", config_name, "/", NULL); - if(my_argc > 2) { - if(strncmp(my_argv[2], "nodump", 6) == 0) { - nodump = 1; - } - } + if (argc > 1) + cfg_opt = argv[1]; + config_init(CONFIG_INIT_EXPLICIT_NAME | CONFIG_INIT_USE_CWD | CONFIG_INIT_FATAL, + cfg_opt); + apply_config_overwrites(cfg_ovr); - } else { + g_printf(_("%s: pid %ld executable %s version %s\n"), + get_pname(), (long) getpid(), argv[0], version()); - char my_cwd[STR_SIZE]; - - if (getcwd(my_cwd, SIZEOF(my_cwd)) == NULL) { - error("cannot determine current working directory"); - /*NOTREACHED*/ - } - config_dir = stralloc2(my_cwd, "/"); - if ((config_name = strrchr(my_cwd, '/')) != NULL) { - config_name = stralloc(config_name + 1); - } + if(argc > 2) { + if(strncmp(argv[2], "nodump", 6) == 0) { + nodump = 1; + } } - safe_cd(); + safe_cd(); /* do this *after* config_init */ - conffile = stralloc2(config_dir, CONFFILE_NAME); - if(read_conffile(conffile)) { - error("errors processing config file \"%s\"", conffile); - /*NOTREACHED*/ - } - amfree(conffile); + check_running_as(RUNNING_AS_DUMPUSER); dbrename(config_name, DBG_SUBDIR_SERVER); - report_bad_conf_arg(); - amfree(driver_timestamp); /* read timestamp from stdin */ while ((line = agets(stdin)) != NULL) { @@ -242,17 +249,17 @@ main( amfree(line); } if ( line == NULL ) { - error("Did not get DATE line from planner"); + error(_("Did not get DATE line from planner")); /*NOTREACHED*/ } driver_timestamp = alloc(15); strncpy(driver_timestamp, &line[5], 14); driver_timestamp[14] = '\0'; amfree(line); - log_add(L_START,"date %s", driver_timestamp); + log_add(L_START,_("date %s"), driver_timestamp); gethostname(hostname, SIZEOF(hostname)); - log_add(L_STATS,"hostname %s", hostname); + log_add(L_STATS,_("hostname %s"), hostname); /* check that we don't do many dump in a day and usetimestamps is off */ if(strlen(driver_timestamp) == 8) { @@ -263,21 +270,21 @@ main( char *oldlogfile = vstralloc(conf_logdir, "/oldlog/log.", driver_timestamp, ".0", NULL); if(access(logfile, F_OK) == 0 || access(oldlogfile, F_OK) == 0) { - log_add(L_WARNING, "WARNING: This is not the first amdump run today. Enable the usetimestamps option in the configuration file if you want to run amdump more than once per calendar day."); + log_add(L_WARNING, _("WARNING: This is not the first amdump run today. Enable the usetimestamps option in the configuration file if you want to run amdump more than once per calendar day.")); } amfree(oldlogfile); amfree(logfile); } - hd_driver_timestamp = construct_timestamp(NULL); + hd_driver_timestamp = get_timestamp_from_time(0); } else { hd_driver_timestamp = stralloc(driver_timestamp); } - taper_program = vstralloc(libexecdir, "/", "taper", versionsuffix(), NULL); - dumper_program = vstralloc(libexecdir, "/", "dumper", versionsuffix(), + taper_program = vstralloc(amlibexecdir, "/", "taper", versionsuffix(), NULL); + dumper_program = vstralloc(amlibexecdir, "/", "dumper", versionsuffix(), NULL); - chunker_program = vstralloc(libexecdir, "/", "chunker", versionsuffix(), + chunker_program = vstralloc(amlibexecdir, "/", "chunker", versionsuffix(), NULL); conf_taperalgo = getconf_taperalgo(CNF_TAPERALGO); @@ -285,18 +292,23 @@ main( conf_runtapes = getconf_int(CNF_RUNTAPES); tape = lookup_tapetype(conf_tapetype); tape_length = tapetype_get_length(tape); - printf("driver: tape size " OFF_T_FMT "\n", (OFF_T_FMT_TYPE)tape_length); + conf_flush_threshold_dumped = getconf_int(CNF_FLUSH_THRESHOLD_DUMPED); + conf_flush_threshold_scheduled = getconf_int(CNF_FLUSH_THRESHOLD_SCHEDULED); + conf_taperflush = getconf_int(CNF_TAPERFLUSH); + + flush_threshold_dumped = (conf_flush_threshold_dumped * tape_length) / 100; + flush_threshold_scheduled = (conf_flush_threshold_scheduled * tape_length) / 100; + taperflush = (conf_taperflush *tape_length) / 100; + + driver_debug(1, _("flush_threshold_dumped: %lld\n"), (long long)flush_threshold_dumped); + driver_debug(1, _("flush_threshold_scheduled: %lld\n"), (long long)flush_threshold_scheduled); + driver_debug(1, _("taperflush: %lld\n"), (long long)taperflush); /* start initializing: read in databases */ - conf_diskfile = getconf_str(CNF_DISKFILE); - if (*conf_diskfile == '/') { - conf_diskfile = stralloc(conf_diskfile); - } else { - conf_diskfile = stralloc2(config_dir, conf_diskfile); - } + conf_diskfile = config_dir_relative(getconf_str(CNF_DISKFILE)); if (read_diskfile(conf_diskfile, &origq) < 0) { - error("could not load disklist \"%s\"", conf_diskfile); + error(_("could not load disklist \"%s\""), conf_diskfile); /*NOTREACHED*/ } amfree(conf_diskfile); @@ -308,62 +320,81 @@ main( reserve = (unsigned long)getconf_int(CNF_RESERVE); total_disksize = (off_t)0; - for(hdp = getconf_holdingdisks(), dsk = 0; hdp != NULL; hdp = hdp->next, dsk++) { - hdp->up = (void *)alloc(SIZEOF(holdalloc_t)); - holdalloc(hdp)->allocated_dumpers = 0; - holdalloc(hdp)->allocated_space = (off_t)0; + ha_last = NULL; + num_holdalloc = 0; + for(hdp = getconf_holdingdisks(), dsk = 0; hdp != NULL; hdp = holdingdisk_next(hdp), dsk++) { + ha = alloc(SIZEOF(holdalloc_t)); + num_holdalloc++; + + /* link the list in the same order as getconf_holdingdisks's results */ + ha->next = NULL; + if (ha_last == NULL) + holdalloc = ha; + else + ha_last->next = ha; + ha_last = ha; + + ha->hdisk = hdp; + ha->allocated_dumpers = 0; + ha->allocated_space = (off_t)0; + ha->disksize = holdingdisk_get_disksize(hdp); - if(get_fs_stats(holdingdisk_get_diskdir(hdp), &fs) == -1 + /* get disk size */ + if(get_fs_usage(holdingdisk_get_diskdir(hdp), NULL, &fsusage) == -1 || access(holdingdisk_get_diskdir(hdp), W_OK) == -1) { - log_add(L_WARNING, "WARNING: ignoring holding disk %s: %s\n", + log_add(L_WARNING, _("WARNING: ignoring holding disk %s: %s\n"), holdingdisk_get_diskdir(hdp), strerror(errno)); - hdp->disksize = 0L; + ha->disksize = 0L; continue; } - if(fs.avail != (off_t)-1) { - if(hdp->disksize > (off_t)0) { - if(hdp->disksize > fs.avail) { - log_add(L_WARNING, - "WARNING: %s: " OFF_T_FMT " KB requested, " - "but only " OFF_T_FMT " KB available.", - holdingdisk_get_diskdir(hdp), - (OFF_T_FMT_TYPE)hdp->disksize, - (OFF_T_FMT_TYPE)fs.avail); - hdp->disksize = fs.avail; - } - } - else if((fs.avail + hdp->disksize) < (off_t)0) { + /* do the division first to avoid potential integer overflow */ + if (fsusage.fsu_bavail_top_bit_set) + kb_avail = 0; + else + kb_avail = fsusage.fsu_bavail / 1024 * fsusage.fsu_blocksize; + + if(ha->disksize > (off_t)0) { + if(ha->disksize > kb_avail) { log_add(L_WARNING, - "WARNING: %s: not " OFF_T_FMT " KB free.", - holdingdisk_get_diskdir(hdp), -hdp->disksize); - hdp->disksize = (off_t)0; - continue; + _("WARNING: %s: %lld KB requested, " + "but only %lld KB available."), + holdingdisk_get_diskdir(hdp), + (long long)ha->disksize, + (long long)kb_avail); + ha->disksize = kb_avail; } - else - hdp->disksize += fs.avail; } + /* ha->disksize is negative; use all but that amount */ + else if(kb_avail < -ha->disksize) { + log_add(L_WARNING, + _("WARNING: %s: not %lld KB free."), + holdingdisk_get_diskdir(hdp), + (long long)-ha->disksize); + ha->disksize = (off_t)0; + continue; + } + else + ha->disksize += kb_avail; - printf("driver: adding holding disk %d dir %s size " - OFF_T_FMT " chunksize " OFF_T_FMT "\n", + g_printf(_("driver: adding holding disk %d dir %s size %lld chunksize %lld\n"), dsk, holdingdisk_get_diskdir(hdp), - (OFF_T_FMT_TYPE)hdp->disksize, - (OFF_T_FMT_TYPE)(holdingdisk_get_chunksize(hdp))); + (long long)ha->disksize, + (long long)(holdingdisk_get_chunksize(hdp))); newdir = newvstralloc(newdir, holdingdisk_get_diskdir(hdp), "/", hd_driver_timestamp, NULL); if(!mkholdingdir(newdir)) { - hdp->disksize = (off_t)0; + ha->disksize = (off_t)0; } - total_disksize += hdp->disksize; + total_disksize += ha->disksize; } reserved_space = total_disksize * (off_t)(reserve / 100); - printf("reserving " OFF_T_FMT " out of " OFF_T_FMT - " for degraded-mode dumps\n", - (OFF_T_FMT_TYPE)reserved_space, (OFF_T_FMT_TYPE)free_space()); + g_printf(_("reserving %lld out of %lld for degraded-mode dumps\n"), + (long long)reserved_space, (long long)free_space()); amfree(newdir); @@ -390,39 +421,45 @@ main( runq.head = NULL; runq.tail = NULL; + directq.head = NULL; + directq.tail = NULL; waitq = origq; + taper_state = TAPER_STATE_DEFAULT; tapeq = read_flush(); roomq.head = roomq.tail = NULL; - log_add(L_STATS, "startup time %s", walltime_str(curclock())); + log_add(L_STATS, _("startup time %s"), walltime_str(curclock())); - printf("driver: start time %s inparallel %d bandwidth %lu diskspace " - OFF_T_FMT " ", walltime_str(curclock()), inparallel, - free_kps((interface_t *)0), (OFF_T_FMT_TYPE)free_space()); - printf(" dir %s datestamp %s driver: drain-ends tapeq %s big-dumpers %s\n", + g_printf(_("driver: start time %s inparallel %d bandwidth %lu diskspace %lld "), walltime_str(curclock()), inparallel, + free_kps(NULL), (long long)free_space()); + g_printf(_(" dir %s datestamp %s driver: drain-ends tapeq %s big-dumpers %s\n"), "OBSOLETE", driver_timestamp, taperalgo2str(conf_taperalgo), getconf_str(CNF_DUMPORDER)); fflush(stdout); /* ok, planner is done, now lets see if the tape is ready */ - if(conf_runtapes > 0) { + if (conf_runtapes > 0) { cmd = getresult(taper, 1, &result_argc, result_argv, MAX_ARGS+1); - - if(cmd != TAPER_OK) { + if (cmd != TAPER_OK) { /* no tape, go into degraded mode: dump to holding disk */ - need_degraded=1; + need_degraded = 1; } - } - else { - need_degraded=1; + } else { + need_degraded = 1; } tape_left = tape_length; taper_busy = 0; + taper_input_error = NULL; + taper_tape_error = NULL; taper_disk = NULL; taper_ev_read = NULL; + + schedule_done = nodump; + force_flush = 0; + if(!need_degraded) startaflush(); if(!nodump) @@ -431,43 +468,45 @@ main( short_dump_state(); event_loop(0); - /* handle any remaining dumps by dumping directly to tape, if possible */ + force_flush = 1; - while(!empty(runq) && taper > 0) { + /* mv runq to directq */ + while (!empty(runq)) { diskp = dequeue_disk(&runq); + headqueue_disk(&directq, diskp); + } + + /* handle any remaining dumps by dumping directly to tape, if possible */ + while(!empty(directq) && taper > 0) { + diskp = dequeue_disk(&directq); if (diskp->to_holdingdisk == HOLD_REQUIRED) { - log_add(L_FAIL, "%s %s %s %d [%s]", + log_add(L_FAIL, _("%s %s %s %d [%s]"), diskp->host->hostname, diskp->name, sched(diskp)->datestamp, sched(diskp)->level, - "can't dump required holdingdisk"); + _("can't dump required holdingdisk")); } else if (!degraded_mode) { - int rc = dump_to_tape(diskp); - if(rc == 1) - log_add(L_INFO, - "%s %s %d [dump to tape failed, will try again]", - diskp->host->hostname, - diskp->name, - sched(diskp)->level); - else if(rc == 2) - log_add(L_FAIL, "%s %s %s %d [dump to tape failed]", - diskp->host->hostname, - diskp->name, - sched(diskp)->datestamp, - sched(diskp)->level); + taper_state |= TAPER_STATE_DUMP_TO_TAPE; + dump_to_tape(diskp); + event_loop(0); + taper_state &= !TAPER_STATE_DUMP_TO_TAPE; } else - log_add(L_FAIL, "%s %s %s %d [%s]", + log_add(L_FAIL, _("%s %s %s %d [%s]"), diskp->host->hostname, diskp->name, sched(diskp)->datestamp, sched(diskp)->level, diskp->to_holdingdisk == HOLD_AUTO ? - "no more holding disk space" : - "can't dump no-hold disk in degraded mode"); + _("no more holding disk space") : + _("can't dump no-hold disk in degraded mode")); } + /* fill up the tape or start new one for taperflush */ + startaflush(); + event_loop(0); + short_dump_state(); /* for amstatus */ - printf("driver: QUITTING time %s telling children to quit\n", + g_printf(_("driver: QUITTING time %s telling children to quit\n"), walltime_str(curclock())); fflush(stdout); @@ -485,29 +524,19 @@ main( /* wait for all to die */ wait_children(600); - for(hdp = getconf_holdingdisks(); hdp != NULL; hdp = hdp->next) { - cleanup_holdingdisk(holdingdisk_get_diskdir(hdp), 0); - amfree(hdp->up); - } + /* cleanup */ + holding_cleanup(NULL, NULL); + amfree(newdir); check_unfree_serial(); - printf("driver: FINISHED time %s\n", walltime_str(curclock())); + g_printf(_("driver: FINISHED time %s\n"), walltime_str(curclock())); fflush(stdout); - log_add(L_FINISH,"date %s time %s", driver_timestamp, walltime_str(curclock())); + log_add(L_FINISH,_("date %s time %s"), driver_timestamp, walltime_str(curclock())); amfree(driver_timestamp); - free_new_argv(new_argc, new_argv); amfree(dumper_program); amfree(taper_program); - amfree(config_dir); - amfree(config_name); - - malloc_size_2 = malloc_inuse(&malloc_hist_2); - - if(malloc_size_1 != malloc_size_2) { - malloc_list(fileno(stderr), malloc_hist_1, malloc_hist_2); - } dbclose(); @@ -537,10 +566,10 @@ wait_children(int count) if (pid > 0) { what = NULL; if (! WIFEXITED(retstat)) { - what = "signal"; + what = _("signal"); code = WTERMSIG(retstat); } else if (WEXITSTATUS(retstat) != 0) { - what = "code"; + what = _("code"); code = WEXITSTATUS(retstat); } who = NULL; @@ -565,9 +594,9 @@ wait_children(int count) who = stralloc("unknown"); } if(who && what) { - log_add(L_WARNING, "%s pid %u exited with %s %d\n", who, + log_add(L_WARNING, _("%s pid %u exited with %s %d\n"), who, (unsigned)pid, what, code); - printf("driver: %s pid %u exited with %s %d\n", who, + g_printf(_("driver: %s pid %u exited with %s %d\n"), who, (unsigned)pid, what, code); } amfree(who); @@ -589,14 +618,14 @@ kill_children(int signal) if(!nodump) { for(dumper = dmptable; dumper < dmptable + inparallel; dumper++) { if (!dumper->down && dumper->pid > 1) { - printf("driver: sending signal %d to %s pid %u\n", signal, + g_printf(_("driver: sending signal %d to %s pid %u\n"), signal, dumper->name, (unsigned)dumper->pid); if (kill(dumper->pid, signal) == -1 && errno == ESRCH) { if (dumper->chunker) dumper->chunker->pid = 0; } if (dumper->chunker && dumper->chunker->pid > 1) { - printf("driver: sending signal %d to %s pid %u\n", signal, + g_printf(_("driver: sending signal %d to %s pid %u\n"), signal, dumper->chunker->name, (unsigned)dumper->chunker->pid); if (kill(dumper->chunker->pid, signal) == -1 && @@ -608,7 +637,7 @@ kill_children(int signal) } if(taper_pid > 1) - printf("driver: sending signal %d to %s pid %u\n", signal, + g_printf(_("driver: sending signal %d to %s pid %u\n"), signal, "taper", (unsigned)taper_pid); if (kill(taper_pid, signal) == -1 && errno == ESRCH) taper_pid = 0; @@ -655,8 +684,20 @@ startaflush(void) char *datestamp; int extra_tapes = 0; char *qname; + TapeAction result_tape_action; + + result_tape_action = tape_action(); - if(!degraded_mode && !taper_busy && !empty(tapeq)) { + if (result_tape_action & TAPE_ACTION_NEW_TAPE) { + taper_state &= !TAPER_STATE_WAIT_FOR_TAPE; + taper_cmd(NEW_TAPE, NULL, NULL, 0, NULL); + } else if (result_tape_action & TAPE_ACTION_NO_NEW_TAPE) { + taper_state &= !TAPER_STATE_WAIT_FOR_TAPE; + taper_cmd(NO_NEW_TAPE, NULL, NULL, 0, NULL); + } + + if (!degraded_mode && !taper_busy && !empty(tapeq) && + (result_tape_action & TAPE_ACTION_START_A_FLUSH)) { datestamp = sched(tapeq.head)->datestamp; switch(conf_taperalgo) { @@ -715,8 +756,8 @@ startaflush(void) } if(!dp) { /* ALGO_SMALLEST, or default if nothing fit. */ if(conf_taperalgo != ALGO_SMALLEST) { - fprintf(stderr, - "driver: startaflush: Using SMALLEST because nothing fit\n"); + g_fprintf(stderr, + _("driver: startaflush: Using SMALLEST because nothing fit\n")); } fit = dp = tapeq.head; while (fit != NULL) { @@ -735,21 +776,28 @@ startaflush(void) if (dp) { taper_disk = dp; taper_busy = 1; + taper_input_error = NULL; + taper_tape_error = NULL; + taper_result = LAST_TOK; + taper_sendresult = 0; + taper_first_label = NULL; + taper_written = 0; + taper_state &= !TAPER_STATE_DUMP_TO_TAPE; + taper_dumper = NULL; qname = quote_string(dp->name); taper_cmd(FILE_WRITE, dp, sched(dp)->destname, sched(dp)->level, sched(dp)->datestamp); - fprintf(stderr,"driver: startaflush: %s %s %s " - OFF_T_FMT " " OFF_T_FMT "\n", + g_fprintf(stderr,_("driver: startaflush: %s %s %s %lld %lld\n"), taperalgo2str(conf_taperalgo), dp->host->hostname, qname, - (OFF_T_FMT_TYPE)sched(taper_disk)->act_size, - (OFF_T_FMT_TYPE)tape_left); + (long long)sched(taper_disk)->act_size, + (long long)tape_left); if(sched(dp)->act_size <= tape_left) tape_left -= sched(dp)->act_size; else tape_left = (off_t)0; amfree(qname); } else { - error("FATAL: Taper marked busy and no work found."); + error(_("FATAL: Taper marked busy and no work found.")); /*NOTREACHED*/ } } else if(!taper_busy && taper_ev_read != NULL) { @@ -758,7 +806,6 @@ startaflush(void) } } - static int client_constrained( disk_t * dp) @@ -800,6 +847,7 @@ start_some_dumps( dumper_t *dumper; char dumptype; char *dumporder; + int busy_dumpers = 0; idle_reason = IDLE_NO_DUMPERS; sleep_time = 0; @@ -809,6 +857,12 @@ start_some_dumps( dumpers_ev_time = NULL; } + for(dumper = dmptable; dumper < (dmptable+inparallel); dumper++) { + if( dumper->busy ) { + busy_dumpers++; + } + } + for (dumper = dmptable; dumper < dmptable+inparallel; dumper++) { if( dumper->busy || dumper->down) { @@ -881,6 +935,10 @@ start_some_dumps( } else if ((holdp = find_diskspace(sched(diskp)->est_size, &cur_idle, NULL)) == NULL) { cur_idle = max(cur_idle, IDLE_NO_DISKSPACE); + if (empty(tapeq) && busy_dumpers == 0) { + remove_disk(rq, diskp); + enqueue_disk(&directq, diskp); + } } else if (client_constrained(diskp)) { free_assignedhd(holdp); cur_idle = max(cur_idle, IDLE_CLIENT_CONSTRAINED); @@ -902,7 +960,7 @@ start_some_dumps( break; case 'B': accept = (sched(diskp)->est_kps > sched(diskp_accept)->est_kps); break; - default: log_add(L_WARNING, "Unknown dumporder character \'%c\', using 's'.\n", + default: log_add(L_WARNING, _("Unknown dumporder character \'%c\', using 's'.\n"), dumptype); accept = (sched(diskp)->est_size < sched(diskp_accept)->est_size); break; @@ -972,7 +1030,7 @@ start_some_dumps( assignedhd_t **h=NULL; int activehd; - printf("driver: did not get PORT from %s for %s:%s\n", + g_printf(_("driver: did not get PORT from %s for %s:%s\n"), chunker->name, diskp->host->hostname, diskp->name); fflush(stdout); @@ -980,7 +1038,7 @@ start_some_dumps( h = sched(diskp)->holdp; activehd = sched(diskp)->activehd; h[activehd]->used = 0; - holdalloc(h[activehd]->disk)->allocated_dumpers--; + h[activehd]->disk->allocated_dumpers--; adjust_diskspace(diskp, DONE); delete_diskspace(diskp); diskp->host->inprogress--; @@ -988,9 +1046,9 @@ start_some_dumps( sched(diskp)->dumper = NULL; dumper->busy = 0; dumper->dp = NULL; - sched(diskp)->attempted++; + sched(diskp)->dump_attempted++; free_serial_dp(diskp); - if(sched(diskp)->attempted < 2) + if(sched(diskp)->dump_attempted < 2) enqueue_disk(rq, diskp); } else { @@ -1031,17 +1089,17 @@ dump_schedule( disk_t *dp; char *qname; - printf("dump of driver schedule %s:\n--------\n", str); + g_printf(_("dump of driver schedule %s:\n--------\n"), str); for(dp = qp->head; dp != NULL; dp = dp->next) { qname = quote_string(dp->name); - printf(" %-20s %-25s lv %d t %5lu s " OFF_T_FMT " p %d\n", + g_printf(" %-20s %-25s lv %d t %5lu s %lld p %d\n", dp->host->hostname, qname, sched(dp)->level, sched(dp)->est_time, - (OFF_T_FMT_TYPE)sched(dp)->est_size, sched(dp)->priority); + (long long)sched(dp)->est_size, sched(dp)->priority); amfree(qname); } - printf("--------\n"); + g_printf("--------\n"); } static void @@ -1053,14 +1111,9 @@ start_degraded_mode( off_t est_full_size; char *qname; - if (taper_ev_read != NULL) { - event_release(taper_ev_read); - taper_ev_read = NULL; - } - newq.head = newq.tail = 0; - dump_schedule(queuep, "before start degraded mode"); + dump_schedule(queuep, _("before start degraded mode")); est_full_size = (off_t)0; while(!empty(*queuep)) { @@ -1086,7 +1139,7 @@ start_degraded_mode( enqueue_disk(&newq, dp); } else { - log_add(L_FAIL,"%s %s %s %d [can't switch to incremental dump]", + log_add(L_FAIL,_("%s %s %s %d [can't switch to incremental dump]"), dp->host->hostname, qname, sched(dp)->datestamp, sched(dp)->level); } @@ -1097,7 +1150,7 @@ start_degraded_mode( /*@i@*/ *queuep = newq; degraded_mode = 1; - dump_schedule(queuep, "after start degraded mode"); + dump_schedule(queuep, _("after start degraded mode")); } @@ -1178,15 +1231,14 @@ continue_port_dumps(void) static void handle_taper_result( - void * cookie) + void *cookie) { disk_t *dp; - off_t filenum; cmd_t cmd; int result_argc; char *result_argv[MAX_ARGS+1]; - int avail_tapes = 0; - + char *qname; + (void)cookie; /* Quiet unused parameter warning */ assert(cookie == NULL); @@ -1199,127 +1251,156 @@ handle_taper_result( switch(cmd) { - case PARTIAL: - case DONE: /* DONE