X-Git-Url: https://git.gag.com/?p=debian%2Famanda;a=blobdiff_plain;f=server-src%2Fdriver.c;h=38ebb331538a02842760ae6ae9a7016d3d695767;hp=af5095ab93a8715c3a50fee552bcb1c1aca19b89;hb=d28952249e392eb31bc8eecc53f6c477f30c617b;hpb=949b8910a5e23c4285d0b1aedacfc82a14dc97a5 diff --git a/server-src/driver.c b/server-src/driver.c index af5095a..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 @@ -142,6 +143,7 @@ static void start_some_dumps(disklist_t *rq); static void continue_port_dumps(void); static void update_failed_dump(disk_t *); static int no_taper_flushing(void); +static int active_dumper(void); typedef enum { TAPE_ACTION_NO_ACTION = 0, @@ -187,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; @@ -585,8 +586,6 @@ main( amfree(dumper_program); amfree(taper_program); - if (result_argv) - g_strfreev(result_argv); dbclose(); @@ -1063,7 +1062,7 @@ allow_dump_dle( enqueue_disk(&directq, diskp); diskp->to_holdingdisk = HOLD_NEVER; } - if (empty(*rq)) force_flush = 1; + if (empty(*rq) && active_dumper() == 0) { force_flush = 1;} } } else if (client_constrained(diskp)) { free_assignedhd(holdp); @@ -1346,8 +1345,8 @@ start_some_dumps( sched(diskp)->level); dumper_cmd(dumper, PORT_DUMP, diskp, NULL); } - diskp->host->start_t = now + 15; - if (empty(*rq)) force_flush = 1; + diskp->host->start_t = now + 5; + if (empty(*rq) && active_dumper() == 0) { force_flush = 1;} if (result_argv) g_strfreev(result_argv); @@ -1390,7 +1389,7 @@ 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; state_changed = TRUE; } @@ -1445,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; @@ -1649,7 +1673,8 @@ 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; @@ -1705,7 +1730,8 @@ 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; @@ -1726,12 +1752,12 @@ 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 = atol(s)/1024; + sched(dp)->dumpsize = OFF_T_ATOI(s)/1024; } } @@ -1762,12 +1788,12 @@ 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 = atol(s)/1024; + partsize = OFF_T_ATOI(s)/1024; } } taper->left -= partsize; @@ -1871,6 +1897,7 @@ handle_taper_result( if (strcmp(result_argv[1], "SETUP") == 0) { taper_nb_wait_reply = 0; taper_nb_scan_volume = 0; + need_degraded = 1; } else { taper = taper_from_name(result_argv[1]); taper->state = TAPER_STATE_DONE; @@ -1887,13 +1914,11 @@ handle_taper_result( taper_nb_scan_volume--; } if (taper_nb_wait_reply == 0) { + need_degraded = 1; event_release(taper_ev_read); taper_ev_read = NULL; } - need_degraded = 1; - if (schedule_done && !degraded_mode) { - start_degraded_mode(&runq); - } + start_degraded_mode(&runq); start_some_dumps(&runq); break; @@ -1921,7 +1946,7 @@ handle_taper_result( sched(dp)->level); /* tell the dumper to dump to a port */ dumper_cmd(dumper, PORT_DUMP, dp, NULL); - dp->host->start_t = time(NULL) + 15; + dp->host->start_t = time(NULL) + 5; amfree(dp->dataport_list); taper->state |= TAPER_STATE_DUMP_TO_TAPE; @@ -1961,7 +1986,6 @@ handle_taper_result( file_taper_result(taper->disk); } } - } taper = NULL; @@ -1970,6 +1994,7 @@ handle_taper_result( taper_ev_read = NULL; taper_nb_wait_reply = 0; } + need_degraded = 1; start_degraded_mode(&runq); tapeq.head = tapeq.tail = NULL; aclose(taper_fd); @@ -3192,8 +3217,8 @@ read_schedule( amfree(inpline); if(line == 0) log_add(L_WARNING, _("WARNING: got empty schedule from planner")); - if(need_degraded==1) start_degraded_mode(&runq); schedule_done = 1; + start_degraded_mode(&runq); run_server_global_scripts(EXECUTE_ON_PRE_BACKUP, get_config_name()); if (empty(runq)) force_flush = 1; start_some_dumps(&runq); @@ -3742,13 +3767,17 @@ tape_action( int dump_to_disk_terminated; int nb_taper_active = nb_sent_new_tape; int nb_taper_flushing = 0; - int dle_free = 0; + int dle_free = 0; /* number of dle that fit on started tape */ + int new_dle = 0; /* number of dle that doesn't fit on started tape */ + off_t new_data = 0; /* size of dle that doesn't fit on started tape */ off_t data_next_tape = 0; off_t data_free = 0; off_t data_lost = 0; off_t data_lost_next_tape = 0; - gboolean allow_size_or_number; + gboolean taperflush_criteria; + gboolean flush_criteria; + driver_debug(2, "tape_action: ENTER %p\n", taper); dumpers_size = 0; for(dumper = dmptable; dumper < (dmptable+inparallel); dumper++) { if (dumper->busy && !sched(dumper->dp)->taper) @@ -3782,35 +3811,68 @@ tape_action( } /* Add what is currently written to tape and in the go. */ + new_data = 0; for (taper1 = tapetable; taper1 < tapetable+conf_taper_parallel_write; taper1++) { if (taper1->state & TAPER_STATE_TAPE_STARTED) { - tapeq_size -= taper1->left; + if (taper1->nb_dle < conf_max_dle_by_volume) { + tapeq_size -= taper1->left; + } dle_free += (conf_max_dle_by_volume - taper1->nb_dle); } if (taper1->disk) { off_t data_to_go; + off_t t_size; if (taper1->dumper) { - data_to_go = sched(taper1->disk)->est_size - taper1->written; + t_size = sched(taper1->disk)->est_size; } else { - data_to_go = sched(taper1->disk)->act_size - taper1->written; + t_size = sched(taper1->disk)->act_size; } + data_to_go = t_size - taper1->written; if (data_to_go > taper1->left) { data_next_tape += data_to_go - taper1->left; data_lost += taper1->written + taper1->left; if (taper1->state & TAPER_STATE_TAPE_STARTED) { - dle_free--; + dle_free -= (conf_max_dle_by_volume - taper1->nb_dle) + 1; } else { - dle_free += conf_max_dle_by_volume - 2; + dle_free -= 2; + new_data += t_size; } } else { + if (!(taper1->state & TAPER_STATE_TAPE_STARTED)) { + dle_free--; + new_data += t_size; + } data_free += taper1->left - data_to_go; } tapeq_size += data_to_go; } } - data_lost_next_tape = tape_length + data_free - data_next_tape - runq_size - directq_size - tapeq_size; + + new_dle = queue_length(tapeq) - dle_free; driver_debug(2, _("dle_free: %d\n"), dle_free); + driver_debug(2, _("new_dle: %d\n"), new_dle); + if (new_dle > 0) { + if (taperflush == 0 && + flush_threshold_dumped == 0 && + flush_threshold_scheduled == 0) { + /* shortcut, will trigger taperflush_criteria and/or flush_criteria */ + new_data += 1; + } else { + /* sum the size of the first new-dle in tapeq */ + /* they should be the reverse taperalgo */ + for (dp = tapeq.head; + dp != NULL && new_dle > 0; + dp = dp->next, new_dle--) { + new_data += sched(dp)->act_size; + } + } + if (tapeq_size < new_data) { + tapeq_size = new_data; + } + } + driver_debug(2, _("new_data: %lld\n"), (long long)new_data); + data_lost_next_tape = tape_length + data_free - data_next_tape - runq_size - directq_size - tapeq_size; driver_debug(2, _("data_lost: %lld\n"), (long long)data_lost); driver_debug(2, _("data_free: %lld\n"), (long long)data_free); driver_debug(2, _("data_next_tape: %lld\n"), (long long)data_next_tape); @@ -3833,18 +3895,25 @@ tape_action( } } - allow_size_or_number = (flush_threshold_dumped < tapeq_size && - flush_threshold_scheduled < sched_size) || - (dle_free < (queue_length(runq) + - queue_length(directq) + - queue_length(tapeq))); + taperflush_criteria = (taperflush < tapeq_size && + (force_flush == 1 || dump_to_disk_terminated)); + flush_criteria = (flush_threshold_dumped < tapeq_size && + flush_threshold_scheduled < sched_size) || + taperflush_criteria; + + driver_debug(2, "taperflush %lld\n", (long long)taperflush); + driver_debug(2, "flush_threshold_dumped %lld\n", (long long)flush_threshold_dumped); + driver_debug(2, "flush_threshold_scheduled %lld\n", (long long)flush_threshold_scheduled); + driver_debug(2, "force_flush %d\n", force_flush); + driver_debug(2, "dump_to_disk_terminated %d\n", dump_to_disk_terminated); driver_debug(2, "queue_length(runq) %d\n", queue_length(runq)); driver_debug(2, "queue_length(directq) %d\n", queue_length(directq)); driver_debug(2, "queue_length(tapeq) %d\n", queue_length(tapeq)); - driver_debug(2, "allow_size_or_number %d\n", allow_size_or_number); + driver_debug(2, "taperflush_criteria %d\n", taperflush_criteria); + driver_debug(2, "flush_criteria %d\n", flush_criteria); // Changing conditionals can produce a driver hang, take care. - // + // // when to start writting to a new tape if (taper->state & TAPER_STATE_TAPE_REQUESTED) { driver_debug(2, "tape_action: TAPER_STATE_TAPE_REQUESTED\n"); @@ -3852,16 +3921,19 @@ tape_action( nb_taper_active == 0) { *why_no_new_tape = g_strdup_printf(_("%d tapes filled; runtapes=%d " "does not allow additional tapes"), current_tape, conf_runtapes); + driver_debug(2, "tape_action: TAPER_STATE_TAPE_REQUESTED return TAPE_ACTION_NO_NEW_TAPE\n"); result |= TAPE_ACTION_NO_NEW_TAPE; } else if (current_tape < conf_runtapes && taper_nb_scan_volume == 0 && - (allow_size_or_number || + (flush_criteria || (data_lost > data_lost_next_tape) || nb_taper_active == 0) && (last_started_taper == NULL || last_started_taper == taper)) { + driver_debug(2, "tape_action: TAPER_STATE_TAPE_REQUESTED return TAPE_ACTION_SCAN\n"); result |= TAPE_ACTION_SCAN; } else { + driver_debug(2, "tape_action: TAPER_STATE_TAPE_REQUESTED return TAPE_ACTION_MOVE\n"); result |= TAPE_ACTION_MOVE; } } else if ((taper->state & TAPER_STATE_WAIT_FOR_TAPE) && @@ -3869,11 +3941,8 @@ tape_action( !empty(directq) || // if a dle is waiting for a dump to tape !empty(roomq) || // holding disk constraint idle_reason == IDLE_NO_DISKSPACE || // holding disk constraint - allow_size_or_number || - (data_lost > data_lost_next_tape) || - (taperflush < tapeq_size && // taperflush - (force_flush == 1 || // if force_flush - dump_to_disk_terminated)) // or all dump to disk terminated + flush_criteria || // flush criteria + data_lost > data_lost_next_tape )) { driver_debug(2, "tape_action: TAPER_STATE_WAIT_FOR_TAPE return TAPE_ACTION_NEW_TAPE\n"); result |= TAPE_ACTION_NEW_TAPE; @@ -3905,14 +3974,17 @@ tape_action( (taper->state & TAPER_STATE_TAPE_STARTED || // tape already started !empty(roomq) || // holding disk constraint idle_reason == IDLE_NO_DISKSPACE || // holding disk constraint - allow_size_or_number || - (force_flush == 1 && taperflush < tapeq_size))) { // taperflush if force_flush + flush_criteria)) { // flush if (nb_taper_flushing == 0) { + driver_debug(2, "tape_action: TAPER_STATE_IDLE return TAPE_ACTION_START_A_FLUSH\n"); result |= TAPE_ACTION_START_A_FLUSH; } else { + driver_debug(2, "tape_action: TAPER_STATE_IDLE return TAPE_ACTION_START_A_FLUSH_FIT\n"); result |= TAPE_ACTION_START_A_FLUSH_FIT; } + } else { + driver_debug(2, "tape_action: TAPER_STATE_IDLE return TAPE_ACTION_NO_ACTION\n"); } } return result; @@ -3931,6 +4003,14 @@ no_taper_flushing(void) return 1; } +static int +active_dumper(void) +{ + int i, nidle=0; + + for(i = 0; i < inparallel; i++) if(!dmptable[i].busy) nidle++; + return inparallel - nidle; +} #if 0 static void dump_state(