X-Git-Url: https://git.gag.com/?a=blobdiff_plain;f=server-src%2Fdriver.c;h=38ebb331538a02842760ae6ae9a7016d3d695767;hb=HEAD;hp=9a0bb27bceba68fa9c80773cb6c6e0cbf4587458;hpb=b116e9366c7b2ea2c2eb53b0a13df4090e176235;p=debian%2Famanda diff --git a/server-src/driver.c b/server-src/driver.c index 9a0bb27..38ebb33 100644 --- a/server-src/driver.c +++ b/server-src/driver.c @@ -1,6 +1,7 @@ /* * Amanda, The Advanced Maryland Automatic Network Disk Archiver * Copyright (c) 1991-1998 University of Maryland at College Park + * Copyright (c) 2007-2012 Zmanda, Inc. All Rights Reserved. * All Rights Reserved. * * Permission to use, copy, modify, distribute, and sell this software and its @@ -76,6 +77,7 @@ static int inparallel; static int nodump = 0; static off_t tape_length = (off_t)0; static int current_tape = 0; +static int conf_max_dle_by_volume; static int conf_taperalgo; static int conf_taper_parallel_write; static int conf_runtapes; @@ -140,7 +142,8 @@ 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(disk_t *); -static int all_taper_idle(void); +static int no_taper_flushing(void); +static int active_dumper(void); typedef enum { TAPE_ACTION_NO_ACTION = 0, @@ -186,7 +189,6 @@ main( identlist_t il; unsigned long reserve = 100; char *conf_diskfile; - char **result_argv = NULL; char *taper_program; char *conf_tapetype; tapetype_t *tape; @@ -199,6 +201,12 @@ main( find_result_t *holding_files; disklist_t holding_disklist = { NULL, NULL }; int no_taper = FALSE; + int from_client = FALSE; + + if (argc > 1 && argv && argv[1] && g_str_equal(argv[1], "--version")) { + printf("driver-%s\n", VERSION); + return (0); + } /* * Configure program for internationalization: @@ -267,6 +275,15 @@ main( } } + if (argc > 2) { + if (strcmp(argv[2], "--from-client") == 0) { + from_client = TRUE; + from_client = from_client; + argv++; + argc--; + } + } + safe_cd(); /* do this *after* config_init */ check_running_as(RUNNING_AS_DUMPUSER); @@ -326,6 +343,7 @@ main( conf_taper_parallel_write = getconf_int(CNF_TAPER_PARALLEL_WRITE); conf_tapetype = getconf_str(CNF_TAPETYPE); conf_runtapes = getconf_int(CNF_RUNTAPES); + conf_max_dle_by_volume = getconf_int(CNF_MAX_DLE_BY_VOLUME); if (conf_taper_parallel_write > conf_runtapes) { conf_taper_parallel_write = conf_runtapes; } @@ -335,7 +353,6 @@ main( 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; @@ -499,31 +516,11 @@ main( headqueue_disk(&directq, diskp); } - /* handle any remaining dumps by dumping directly to tape, if possible */ - while(!empty(directq) && taper_fd > 0) { - time_t sleep_time = 100000000; - disk_t *sleep_diskp = NULL; - time_t now = time(0); - - /* Find one we can do immediately or the sonner */ - for (diskp = directq.head; diskp != NULL; diskp = diskp->next) { - if (diskp->to_holdingdisk == HOLD_REQUIRED || - degraded_mode) { - sleep_time = 0; - sleep_diskp = diskp; - } else if (diskp->host->start_t - now < sleep_time && - diskp->start_t -now < sleep_time) { - if (diskp->host->start_t > diskp->start_t) - sleep_time = diskp->host->start_t - now; - else - sleep_time = diskp->start_t - now; - sleep_diskp = diskp; - } - } - diskp = sleep_diskp; - if (sleep_time > 0) - sleep(sleep_time); - remove_disk(&directq, diskp); + run_server_global_scripts(EXECUTE_ON_POST_BACKUP, get_config_name()); + + /* log error for any remaining dumps */ + while(!empty(directq)) { + diskp = dequeue_disk(&directq); if (diskp->to_holdingdisk == HOLD_REQUIRED) { char *qname = quote_string(diskp->name); @@ -538,7 +535,7 @@ main( log_add(L_FAIL, "%s %s %s %d [%s]", diskp->host->hostname, qname, sched(diskp)->datestamp, sched(diskp)->level, - _("can't dump in degraded mode")); + _("can't dump in non degraded mode")); amfree(qname); } else { @@ -555,10 +552,6 @@ main( } } - /* fill up the tape or start new one for taperflush */ - startaflush(); - event_loop(0); - short_dump_state(); /* for amstatus */ g_printf(_("driver: QUITTING time %s telling children to quit\n"), @@ -593,8 +586,6 @@ main( amfree(dumper_program); amfree(taper_program); - if (result_argv) - g_strfreev(result_argv); dbclose(); @@ -735,46 +726,51 @@ wait_for_children(void) } -static void startaflush_tape(taper_t *taper); +static void startaflush_tape(taper_t *taper, gboolean *state_changed); static void startaflush(void) { taper_t *taper; + gboolean state_changed = FALSE; for(taper = tapetable; taper <= tapetable+conf_taper_parallel_write; taper++) { if (!(taper->state & TAPER_STATE_DONE) && taper->state & TAPER_STATE_WAIT_FOR_TAPE) { - startaflush_tape(taper); + startaflush_tape(taper, &state_changed); } } for(taper = tapetable; taper <= tapetable+conf_taper_parallel_write; taper++) { if (!(taper->state & TAPER_STATE_DONE) && taper->state & TAPER_STATE_TAPE_REQUESTED) { - startaflush_tape(taper); + startaflush_tape(taper, &state_changed); } } for(taper = tapetable; taper <= tapetable+conf_taper_parallel_write; taper++) { if (!(taper->state & TAPER_STATE_DONE) && taper->state & TAPER_STATE_INIT) { - startaflush_tape(taper); + startaflush_tape(taper, &state_changed); } } for(taper = tapetable; taper <= tapetable+conf_taper_parallel_write; taper++) { if (!(taper->state & TAPER_STATE_DONE) && taper->state & TAPER_STATE_IDLE) { - startaflush_tape(taper); + startaflush_tape(taper, &state_changed); } } + if (state_changed) { + short_dump_state(); + } } static void startaflush_tape( - taper_t *taper) + taper_t *taper, + gboolean *state_changed) { disk_t *dp = NULL; disk_t *fit = NULL; @@ -803,6 +799,7 @@ startaflush_tape( taper_cmd(NO_NEW_TAPE, taper->disk, why_no_new_tape, 0, NULL); taper->state |= TAPER_STATE_DONE; start_degraded_mode(&runq); + *state_changed = TRUE; } else if (result_tape_action & TAPE_ACTION_MOVE) { taper_t *taper1 = idle_taper(); if (taper1) { @@ -812,9 +809,11 @@ startaflush_tape( taper1->state = TAPER_STATE_DEFAULT; taper->state |= TAPER_STATE_TAPE_STARTED; taper->left = taper1->left; + taper->nb_dle++; if (last_started_taper == taper1) { last_started_taper = taper; } + *state_changed = TRUE; } } @@ -940,6 +939,24 @@ startaflush_tape( if(dp) remove_disk(&tapeq, dp); break; } + if (!dp) { + if (!(result_tape_action & TAPE_ACTION_START_A_FLUSH_FIT)) { + if(conf_taperalgo != ALGO_SMALLEST) { + g_fprintf(stderr, + _("driver: startaflush: Using SMALLEST because nothing fit\n")); + } + + fit = dp = tapeq.head; + while (fit != NULL) { + if (sched(fit)->act_size < sched(dp)->act_size && + strcmp(sched(fit)->datestamp, datestamp) <= 0) { + dp = fit; + } + fit = fit->next; + } + if(dp) remove_disk(&tapeq, dp); + } + } if (dp) { taper->disk = dp; taper->dumper = NULL; @@ -958,6 +975,7 @@ startaflush_tape( handle_taper_result, NULL); } taper_nb_wait_reply++; + taper->nb_dle++; sched(dp)->taper = taper; taper_cmd(FILE_WRITE, dp, sched(dp)->destname, sched(dp)->level, sched(dp)->datestamp); @@ -966,8 +984,8 @@ startaflush_tape( (long long)sched(taper->disk)->act_size, (long long)taper->left); amfree(qname); + *state_changed = TRUE; } - short_dump_state(); } } @@ -1038,12 +1056,13 @@ allow_dump_dle( } else if (!taper && (holdp = find_diskspace(sched(diskp)->est_size, cur_idle, NULL)) == NULL) { *cur_idle = max(*cur_idle, IDLE_NO_DISKSPACE); - if (empty(tapeq) && dumper_to_holding == 0 && rq != &directq) { + if (empty(tapeq) && dumper_to_holding == 0 && rq != &directq && no_taper_flushing()) { remove_disk(rq, diskp); if (diskp->to_holdingdisk != HOLD_REQUIRED) { enqueue_disk(&directq, diskp); diskp->to_holdingdisk = HOLD_NEVER; } + if (empty(*rq) && active_dumper() == 0) { force_flush = 1;} } } else if (client_constrained(diskp)) { free_assignedhd(holdp); @@ -1094,7 +1113,7 @@ start_some_dumps( { const time_t now = time(NULL); int cur_idle; - disk_t *diskp, *delayed_diskp, *diskp_accept; + disk_t *diskp, *delayed_diskp, *diskp_accept, *diskp_next; disk_t *dp; assignedhd_t **holdp=NULL, **holdp_accept; cmd_t cmd; @@ -1106,6 +1125,7 @@ start_some_dumps( char dumptype; char *dumporder; int dumper_to_holding = 0; + gboolean state_changed = FALSE; /* don't start any actual dumps until the taper is started */ if (!taper_started) return; @@ -1201,7 +1221,8 @@ start_some_dumps( } for (diskp = directq.head; diskp != NULL; - diskp = diskp->next) { + diskp = diskp_next) { + diskp_next = diskp->next; allow_dump_dle(diskp, taper, dumptype, &directq, now, dumper_to_holding, &cur_idle, &delayed_diskp, &diskp_accept, @@ -1220,7 +1241,8 @@ start_some_dumps( } if (diskp == NULL) { - for(diskp = rq->head; diskp != NULL; diskp = diskp->next) { + for(diskp = rq->head; diskp != NULL; diskp = diskp_next) { + diskp_next = diskp->next; assert(diskp->host != NULL && sched(diskp) != NULL); allow_dump_dle(diskp, NULL, dumptype, rq, now, @@ -1314,18 +1336,17 @@ start_some_dumps( diskp->dataport_list = stralloc(result_argv[2]); if (diskp->host->pre_script == 0) { - for (dp=diskp->host->disks; dp != NULL; dp = dp->hostnext) { - run_server_scripts(EXECUTE_ON_PRE_HOST_BACKUP, - get_config_name(), dp, -1); - } + run_server_host_scripts(EXECUTE_ON_PRE_HOST_BACKUP, + get_config_name(), diskp->host); diskp->host->pre_script = 1; } - run_server_scripts(EXECUTE_ON_PRE_DLE_BACKUP, + run_server_dle_scripts(EXECUTE_ON_PRE_DLE_BACKUP, get_config_name(), diskp, sched(diskp)->level); dumper_cmd(dumper, PORT_DUMP, diskp, NULL); } - diskp->host->start_t = now + 15; + diskp->host->start_t = now + 5; + if (empty(*rq) && active_dumper() == 0) { force_flush = 1;} if (result_argv) g_strfreev(result_argv); @@ -1359,6 +1380,7 @@ start_some_dumps( taper->dumper = dumper; taper->state |= TAPER_STATE_DUMP_TO_TAPE; taper->state &= ~TAPER_STATE_IDLE; + taper->nb_dle++; if (taper_nb_wait_reply == 0) { taper_ev_read = event_register(taper_fd, EV_READFD, handle_taper_result, NULL); @@ -1367,11 +1389,14 @@ start_some_dumps( taper_nb_wait_reply++; taper_cmd(PORT_WRITE, diskp, NULL, sched(diskp)->level, sched(diskp)->datestamp); - diskp->host->start_t = now + 15; + diskp->host->start_t = now + 5; - short_dump_state(); + state_changed = TRUE; } } + if (state_changed) { + short_dump_state(); + } } /* @@ -1419,6 +1444,31 @@ start_degraded_mode( disklist_t newq; off_t est_full_size; char *qname; + taper_t *taper; + + if (need_degraded == 0) { + for(taper = tapetable; + taper < tapetable+conf_taper_parallel_write; + taper++) { + if (!(taper->state & TAPER_STATE_DONE)) + return; + } + need_degraded = 1; + } + + if (!schedule_done || degraded_mode) { + return; + } + + if (need_degraded == 0) { + for(taper = tapetable; + taper < tapetable+conf_taper_parallel_write; + taper++) { + if (!(taper->state & TAPER_STATE_DONE)) + return; + } + need_degraded = 1; + } newq.head = newq.tail = 0; @@ -1509,15 +1559,17 @@ continue_port_dumps(void) if( dumper->busy ) { busy_dumpers++; if( !find_disk(&roomq, dumper->dp) ) { - active_dumpers++; - } else if( !dp || + if (dumper->chunker) { + active_dumpers++; + } + } else if( !dp || sched(dp)->est_size > sched(dumper->dp)->est_size ) { dp = dumper->dp; } } } - if((dp != NULL) && (active_dumpers == 0) && (busy_dumpers > 0) && - ((all_taper_idle() && empty(tapeq)) || degraded_mode) && + if((dp != NULL) && (active_dumpers == 0) && (busy_dumpers > 0) && + ((no_taper_flushing() && empty(tapeq)) || degraded_mode) && pending_aborts == 0 ) { /* case b */ sched(dp)->no_space = 1; /* At this time, dp points to the dump with the smallest est_size. @@ -1535,7 +1587,7 @@ static void handle_taper_result( void *cookie G_GNUC_UNUSED) { - disk_t *dp = NULL, *dp1; + disk_t *dp = NULL; dumper_t *dumper; cmd_t cmd; int result_argc; @@ -1573,6 +1625,7 @@ handle_taper_result( } assert(taper != NULL); taper->left = 0; + taper->nb_dle = 0; taper->state &= ~TAPER_STATE_INIT; taper->state |= TAPER_STATE_RESERVATION; taper->state |= TAPER_STATE_IDLE; @@ -1607,6 +1660,9 @@ handle_taper_result( if (strcmp(result_argv[2], "INPUT-ERROR") == 0) { taper->input_error = newstralloc(taper->input_error, result_argv[4]); + taper->result = FAILED; + amfree(qname); + break; } else if (strcmp(result_argv[2], "INPUT-GOOD") != 0) { taper->tape_error = newstralloc(taper->tape_error, _("Taper protocol error")); @@ -1617,9 +1673,13 @@ handle_taper_result( amfree(qname); break; } - if (strcmp(result_argv[3], "TAPE-ERROR") == 0) { + if (strcmp(result_argv[3], "TAPE-ERROR") == 0 || + strcmp(result_argv[3], "TAPE-CONFIG") == 0) { taper->state &= ~TAPER_STATE_TAPE_STARTED; taper->tape_error = newstralloc(taper->tape_error, result_argv[5]); + taper->result = FAILED; + amfree(qname); + break; } else if (strcmp(result_argv[3], "TAPE-GOOD") != 0) { taper->state &= ~TAPER_STATE_TAPE_STARTED; taper->tape_error = newstralloc(taper->tape_error, @@ -1657,6 +1717,9 @@ handle_taper_result( if (strcmp(result_argv[2], "INPUT-ERROR") == 0) { taper->input_error = newstralloc(taper->input_error, result_argv[5]); + taper->result = FAILED; + amfree(qname); + break; } else if (strcmp(result_argv[2], "INPUT-GOOD") != 0) { taper->tape_error = newstralloc(taper->tape_error, _("Taper protocol error")); @@ -1667,9 +1730,13 @@ handle_taper_result( amfree(qname); break; } - if (strcmp(result_argv[3], "TAPE-ERROR") == 0) { + if (strcmp(result_argv[3], "TAPE-ERROR") == 0 || + strcmp(result_argv[3], "TAPE-CONFIG") == 0) { taper->state &= ~TAPER_STATE_TAPE_STARTED; taper->tape_error = newstralloc(taper->tape_error, result_argv[6]); + taper->result = FAILED; + amfree(qname); + break; } else if (strcmp(result_argv[3], "TAPE-GOOD") != 0) { taper->state &= ~TAPER_STATE_TAPE_STARTED; taper->tape_error = newstralloc(taper->tape_error, @@ -1685,7 +1752,13 @@ handle_taper_result( s = strstr(result_argv[4], " kb "); if (s) { s += 4; - sched(dp)->dumpsize = atol(s); + sched(dp)->dumpsize = OFF_T_ATOI(s); + } else { + s = strstr(result_argv[4], " bytes "); + if (s) { + s += 7; + sched(dp)->dumpsize = OFF_T_ATOI(s)/1024; + } } taper->result = cmd; @@ -1715,7 +1788,13 @@ handle_taper_result( s = strstr(result_argv[5], " kb "); if (s) { s += 4; - partsize = atol(s); + partsize = OFF_T_ATOI(s); + } else { + s = strstr(result_argv[5], " bytes "); + if (s) { + s += 7; + partsize = OFF_T_ATOI(s)/1024; + } } taper->left -= partsize; @@ -1730,11 +1809,15 @@ handle_taper_result( dp = serial2disk(result_argv[1]); taper = sched(dp)->taper; - taper->state &= ~TAPER_STATE_TAPE_STARTED; - taper->state |= TAPER_STATE_TAPE_REQUESTED; + if (taper->state & TAPER_STATE_DONE) { + taper_cmd(NO_NEW_TAPE, taper->disk, "taper found no tape", 0, NULL); + } else { + taper->state &= ~TAPER_STATE_TAPE_STARTED; + taper->state |= TAPER_STATE_TAPE_REQUESTED; - start_some_dumps(&runq); - startaflush(); + start_some_dumps(&runq); + startaflush(); + } break; case NEW_TAPE: /* NEW-TAPE