X-Git-Url: https://git.gag.com/?a=blobdiff_plain;f=server-src%2Fplanner.c;h=f7a38be691eeedbdf900a7043fc8dc3e9fbde377;hb=HEAD;hp=fd18d8428c165ca3a1687b45490525d3534f21ec;hpb=b116e9366c7b2ea2c2eb53b0a13df4090e176235;p=debian%2Famanda diff --git a/server-src/planner.c b/server-src/planner.c index fd18d84..f7a38be 100644 --- a/server-src/planner.c +++ b/server-src/planner.c @@ -1,6 +1,7 @@ /* * Amanda, The Advanced Maryland Automatic Network Disk Archiver * Copyright (c) 1991-1999 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 @@ -108,6 +109,7 @@ typedef struct est_s { double fullcomp, incrcomp; char *errstr; char *degr_mesg; + info_t *info; } est_t; #define est(dp) ((est_t *)(dp)->up) @@ -191,6 +193,13 @@ main( int planner_setuid; int exit_status = EXIT_SUCCESS; gboolean no_taper = FALSE; + gboolean from_client = FALSE; + gboolean exact_match = FALSE; + + if (argc > 1 && argv && argv[1] && g_str_equal(argv[1], "--version")) { + printf("planner-%s\n", VERSION); + return (0); + } /* * Configure program for internationalization: @@ -265,7 +274,18 @@ main( no_taper = TRUE; diskarg_offset += 1; } + if (argc - diskarg_offset > 0 && strcmp(argv[diskarg_offset], "--from-client") == 0) { + from_client = TRUE; + diskarg_offset += 1; + } + if (argc - diskarg_offset > 0 && g_str_equal(argv[diskarg_offset], + "--exact_match")) { + exact_match = TRUE; + diskarg_offset += 1; + } + + run_server_global_scripts(EXECUTE_ON_PRE_ESTIMATE, get_config_name()); /* * 1. Networking Setup @@ -315,7 +335,7 @@ main( conf_tapecycle = getconf_int(CNF_TAPECYCLE); conf_etimeout = (time_t)getconf_int(CNF_ETIMEOUT); conf_reserve = getconf_int(CNF_RESERVE); - conf_autoflush = getconf_boolean(CNF_AUTOFLUSH); + conf_autoflush = getconf_no_yes_all(CNF_AUTOFLUSH); conf_usetimestamps = getconf_boolean(CNF_USETIMESTAMPS); today = time(0); @@ -335,12 +355,25 @@ main( g_fprintf(stderr, _("%s: timestamp %s\n"), get_pname(), planner_timestamp); - errstr = match_disklist(&origq, argc-diskarg_offset, + errstr = match_disklist(&origq, exact_match, argc-diskarg_offset, argv+diskarg_offset); if (errstr) { g_fprintf(stderr,"%s",errstr); exit_status = EXIT_FAILURE; } + + for (dp = origq.head; dp != NULL; dp = dp->next) { + if (dp->todo) { + if (from_client) { + if (!dp->dump_limit || !dp->dump_limit->same_host) + dp->todo = 0; + } else { + if (dp->dump_limit && !dp->dump_limit->server) + dp->todo = 0; + } + } + } + nb_disk = 0; for (dp = origq.head; dp != NULL; dp = dp->next) { if (dp->todo) { @@ -436,7 +469,8 @@ main( } /* see if this matches the command-line arguments */ - if (!match_dumpfile(&file, argc-diskarg_offset, + if (conf_autoflush == 1 && + !match_dumpfile(&file, exact_match, argc-diskarg_offset, argv+diskarg_offset)) { continue; } @@ -462,7 +496,7 @@ main( amfree(qhname); dumpfile_free_data(&file); } - g_slist_free_full(holding_list); + slist_free_full(holding_list, g_free); holding_list = NULL; } g_fprintf(stderr, _("ENDFLUSH\n")); @@ -552,6 +586,8 @@ main( while(!empty(estq)) analyze_estimate(dequeue_disk(&estq)); while(!empty(failq)) handle_failed(dequeue_disk(&failq)); + run_server_global_scripts(EXECUTE_ON_POST_ESTIMATE, get_config_name()); + /* * At this point, all the disks are on schedq sorted by priority. * The total estimated size of the backups is in total_size. @@ -728,7 +764,7 @@ setup_estimate( disk_t *dp) { est_t *ep; - info_t info; + info_t *info; int i; char *qname; int overwrite_runs; @@ -742,7 +778,8 @@ setup_estimate( /* get current information about disk */ - if(get_info(dp->host->hostname, dp->name, &info)) { + info = g_new0(info_t, 1); + if(get_info(dp->host->hostname, dp->name, info)) { /* no record for this disk, make a note of it */ log_add(L_INFO, _("Adding new disk %s:%s."), dp->host->hostname, qname); } @@ -782,6 +819,7 @@ setup_estimate( ep = alloc(SIZEOF(est_t)); dp->up = (void *) ep; + ep->info = info; ep->state = DISK_READY; ep->dump_priority = dp->priority; ep->errstr = 0; @@ -793,7 +831,7 @@ setup_estimate( /* calculated fields */ - if (ISSET(info.command, FORCE_FULL)) { + if (ISSET(info->command, FORCE_FULL)) { /* force a level 0, kind of like a new disk */ if(dp->strategy == DS_NOFULL) { /* @@ -812,18 +850,18 @@ setup_estimate( dp->host->hostname, qname); /* clear force command */ - CLR(info.command, FORCE_FULL); - ep->last_level = last_level(&info); - ep->next_level0 = next_level0(dp, &info); + CLR(info->command, FORCE_FULL); + ep->last_level = last_level(info); + ep->next_level0 = next_level0(dp, info); } else if (dp->strategy == DS_INCRONLY) { log_add(L_WARNING, _("Cannot force full dump of %s:%s with incronly option."), dp->host->hostname, qname); /* clear force command */ - CLR(info.command, FORCE_FULL); - ep->last_level = last_level(&info); - ep->next_level0 = next_level0(dp, &info); + CLR(info->command, FORCE_FULL); + ep->last_level = last_level(info); + ep->next_level0 = next_level0(dp, info); } else { ep->degr_mesg = _("Skipping: force-full disk can't be dumped in degraded mode"); ep->last_level = -1; @@ -835,44 +873,44 @@ setup_estimate( else if(dp->strategy == DS_NOFULL) { /* force estimate of level 1 */ ep->last_level = 1; - ep->next_level0 = next_level0(dp, &info); + ep->next_level0 = next_level0(dp, info); } else { - ep->last_level = last_level(&info); - ep->next_level0 = next_level0(dp, &info); + ep->last_level = last_level(info); + ep->next_level0 = next_level0(dp, info); } /* adjust priority levels */ /* warn if dump will be overwritten */ - if (ep->last_level > -1 && strlen(info.inf[0].label) > 0) { - overwrite_runs = when_overwrite(info.inf[0].label); + if (ep->last_level > -1 && strlen(info->inf[0].label) > 0) { + overwrite_runs = when_overwrite(info->inf[0].label); if(overwrite_runs == 0) { log_add(L_WARNING, _("Last full dump of %s:%s " "on tape %s overwritten on this run."), - dp->host->hostname, qname, info.inf[0].label); + dp->host->hostname, qname, info->inf[0].label); } else if(overwrite_runs <= RUNS_REDZONE) { log_add(L_WARNING, plural(_("Last full dump of %s:%s on tape %s overwritten in %d run."), _("Last full dump of %s:%s on tape %s overwritten in %d runs."), overwrite_runs), - dp->host->hostname, qname, info.inf[0].label, + dp->host->hostname, qname, info->inf[0].label, overwrite_runs); } } /* warn if last level 1 will be overwritten */ - if (ep->last_level > 1 && strlen(info.inf[1].label) > 0) { - overwrite_runs = when_overwrite(info.inf[1].label); + if (ep->last_level > 1 && strlen(info->inf[1].label) > 0) { + overwrite_runs = when_overwrite(info->inf[1].label); if(overwrite_runs == 0) { log_add(L_WARNING, _("Last level 1 dump of %s:%s " "on tape %s overwritten on this run, resetting to level 1"), - dp->host->hostname, qname, info.inf[1].label); + dp->host->hostname, qname, info->inf[1].label); ep->last_level = 0; } else if(overwrite_runs <= RUNS_REDZONE) { log_add(L_WARNING, plural(_("Last level 1 dump of %s:%s on tape %s overwritten in %d run."), _("Last level 1 dump of %s:%s on tape %s overwritten in %d runs."), overwrite_runs), - dp->host->hostname, qname, info.inf[1].label, + dp->host->hostname, qname, info->inf[1].label, overwrite_runs); } } @@ -884,7 +922,7 @@ setup_estimate( dp->host->hostname, qname, (-ep->next_level0)); ep->dump_priority -= ep->next_level0; } - else if (ISSET(info.command, FORCE_FULL)) + else if (ISSET(info->command, FORCE_FULL)) ep->dump_priority += 1; /* else XXX bump up the priority of incrementals that failed last night */ @@ -893,11 +931,11 @@ setup_estimate( if(dp->skip_full && dp->strategy != DS_NOINC) { if(ep->next_level0 <= 0) { /* update the date field */ - info.inf[0].date = today; - CLR(info.command, FORCE_FULL); + info->inf[0].date = today; + CLR(info->command, FORCE_FULL); ep->next_level0 += conf_dumpcycle; ep->last_level = 0; - if(put_info(dp->host->hostname, dp->name, &info)) { + if(put_info(dp->host->hostname, dp->name, info)) { error(_("could not put info record for %s:%s: %s"), dp->host->hostname, qname, strerror(errno)); /*NOTREACHED*/ @@ -907,9 +945,9 @@ setup_estimate( g_fprintf(stderr,_("%s:%s lev 0 skipped due to skip-full flag\n"), dp->host->hostname, qname); /* don't enqueue the disk */ - askfor(ep, 0, -1, &info); - askfor(ep, 1, -1, &info); - askfor(ep, 2, -1, &info); + askfor(ep, 0, -1, info); + askfor(ep, 1, -1, info); + askfor(ep, 2, -1, info); g_fprintf(stderr, _("%s: SKIPPED %s %s 0 [skip-full]\n"), get_pname(), dp->host->hostname, qname); log_add(L_SUCCESS, _("%s %s %s 0 [skipped: skip-full]"), @@ -929,11 +967,11 @@ setup_estimate( } } - if(dp->strategy == DS_INCRONLY && ep->last_level == -1 && !ISSET(info.command, FORCE_FULL)) { + if(dp->strategy == DS_INCRONLY && ep->last_level == -1 && !ISSET(info->command, FORCE_FULL)) { /* don't enqueue the disk */ - askfor(ep, 0, -1, &info); - askfor(ep, 1, -1, &info); - askfor(ep, 2, -1, &info); + askfor(ep, 0, -1, info); + askfor(ep, 1, -1, info); + askfor(ep, 2, -1, info); log_add(L_FAIL, _("%s %s 19000101 1 [Skipping incronly because no full dump were done]"), dp->host->hostname, qname); g_fprintf(stderr,_("%s:%s lev 1 skipped due to strategy incronly and no full dump were done\n"), @@ -948,9 +986,9 @@ setup_estimate( g_fprintf(stderr,_("%s:%s lev 1 skipped due to skip-incr flag\n"), dp->host->hostname, qname); /* don't enqueue the disk */ - askfor(ep, 0, -1, &info); - askfor(ep, 1, -1, &info); - askfor(ep, 2, -1, &info); + askfor(ep, 0, -1, info); + askfor(ep, 1, -1, info); + askfor(ep, 2, -1, info); g_fprintf(stderr, _("%s: SKIPPED %s %s 1 [skip-incr]\n"), get_pname(), dp->host->hostname, qname); @@ -970,15 +1008,16 @@ setup_estimate( ep->next_level0 = 0; } - if(ep->last_level == 0) ep->level_days = 0; - else ep->level_days = runs_at(&info, ep->last_level); - ep->last_lev0size = info.inf[0].csize; + //if(ep->last_level == 0) ep->level_days = 0; + //else ep->level_days = runs_at(info, ep->last_level); + ep->level_days = runs_at(info, ep->last_level); + ep->last_lev0size = info->inf[0].csize; - ep->fullrate = perf_average(info.full.rate, 0.0); - ep->incrrate = perf_average(info.incr.rate, 0.0); + ep->fullrate = perf_average(info->full.rate, 0.0); + ep->incrrate = perf_average(info->incr.rate, 0.0); - ep->fullcomp = perf_average(info.full.comp, dp->comprate[0]); - ep->incrcomp = perf_average(info.incr.comp, dp->comprate[1]); + ep->fullcomp = perf_average(info->full.comp, dp->comprate[0]); + ep->incrcomp = perf_average(info->incr.comp, dp->comprate[1]); /* determine which estimates to get */ @@ -986,10 +1025,10 @@ setup_estimate( if (dp->strategy == DS_NOINC || (!dp->skip_full && - (!ISSET(info.command, FORCE_BUMP) || + (!ISSET(info->command, FORCE_BUMP) || dp->skip_incr || ep->last_level == -1))) { - if(ISSET(info.command, FORCE_BUMP) && ep->last_level == -1) { + if(ISSET(info->command, FORCE_BUMP) && ep->last_level == -1) { log_add(L_INFO, _("Remove force-bump command of %s:%s because it's a new disk."), dp->host->hostname, qname); @@ -997,13 +1036,17 @@ setup_estimate( switch (dp->strategy) { case DS_STANDARD: case DS_NOINC: - askfor(ep, i++, 0, &info); + askfor(ep, i++, 0, info); + if (ep->last_level == -1) + ep->degr_mesg = _("Skipping: new disk can't be dumped in degraded mode"); + else + ep->degr_mesg = _("Skipping: strategy NOINC can't be dumped in degraded mode"); if(dp->skip_full) { log_add(L_INFO, _("Ignoring skip-full for %s:%s " "because the strategy is NOINC."), dp->host->hostname, qname); } - if(ISSET(info.command, FORCE_BUMP)) { + if(ISSET(info->command, FORCE_BUMP)) { log_add(L_INFO, _("Ignoring FORCE_BUMP for %s:%s because the strategy is NOINC."), dp->host->hostname, qname); @@ -1015,7 +1058,7 @@ setup_estimate( break; case DS_INCRONLY: - if (ISSET(info.command, FORCE_FULL)) + if (ISSET(info->command, FORCE_FULL)) ep->last_level = 0; break; } @@ -1026,7 +1069,7 @@ setup_estimate( if (ep->degr_mesg == NULL) ep->degr_mesg = _("Skipping: new disk can't be dumped in degraded mode"); if(dp->strategy == DS_NOFULL || dp->strategy == DS_INCRONLY) { - askfor(ep, i++, 1, &info); + askfor(ep, i++, 1, info); } else { assert(!dp->skip_full); /* should be handled above */ } @@ -1035,23 +1078,23 @@ setup_estimate( curr_level = ep->last_level; - if (ISSET(info.command, FORCE_NO_BUMP)) { + if (ISSET(info->command, FORCE_NO_BUMP)) { if(curr_level > 0) { /* level 0 already asked for */ - askfor(ep, i++, curr_level, &info); + askfor(ep, i++, curr_level, info); } log_add(L_INFO,_("Preventing bump of %s:%s as directed."), dp->host->hostname, qname); ep->degr_mesg = _("Skipping: force-no-bump disk can't be dumped in degraded mode"); - } else if (ISSET(info.command, FORCE_BUMP) + } else if (ISSET(info->command, FORCE_BUMP) && curr_level + 1 < DUMP_LEVELS) { - askfor(ep, i++, curr_level+1, &info); + askfor(ep, i++, curr_level+1, info); log_add(L_INFO,_("Bumping of %s:%s at level %d as directed."), dp->host->hostname, qname, curr_level+1); ep->degr_mesg = _("Skipping: force-bump disk can't be dumped in degraded mode"); } else if (curr_level == 0) { - askfor(ep, i++, 1, &info); + askfor(ep, i++, 1, info); } else { - askfor(ep, i++, curr_level, &info); + askfor(ep, i++, curr_level, info); /* * If last time we dumped less than the threshold, then this * time we will too, OR the extra size will be charged to both @@ -1059,25 +1102,25 @@ setup_estimate( * if we haven't been at this level 2 days, or the dump failed * last night, we can't bump. */ - if((info.inf[curr_level].size == (gint64)0 || /* no data, try it anyway */ - (((info.inf[curr_level].size > bump_thresh(curr_level, info.inf[0].size,dp->bumppercent, dp->bumpsize, dp->bumpmult))) + if((info->inf[curr_level].size == (gint64)0 || /* no data, try it anyway */ + (((info->inf[curr_level].size > bump_thresh(curr_level, info->inf[0].size,dp->bumppercent, dp->bumpsize, dp->bumpmult))) && ep->level_days >= dp->bumpdays)) && curr_level + 1 < DUMP_LEVELS) { - askfor(ep, i++, curr_level+1, &info); + askfor(ep, i++, curr_level+1, info); } - } + } } } - while(i < MAX_LEVELS) /* mark end of estimates */ - askfor(ep, i++, -1, &info); + while(i < MAX_LEVELS) /* mark end of estimates */ + askfor(ep, i++, -1, info); /* debug output */ g_fprintf(stderr, _("setup_estimate: %s:%s: command %u, options: %s " - "last_level %d next_level0 %d level_days %d getting estimates " + "last_level %d next_level0 %d level_days %d getting estimates " "%d (%lld) %d (%lld) %d (%lld)\n"), - dp->host->hostname, qname, info.command, + dp->host->hostname, qname, info->command, dp->strategy == DS_NOFULL ? "no-full" : dp->strategy == DS_INCRONLY ? "incr-only" : dp->skip_full ? "skip-full" : @@ -1255,10 +1298,9 @@ static int runs_at( last = last_level(info); if(lev != last) return 0; - if(lev == 0) return 1; - if(info->consecutive_runs != -1) return info->consecutive_runs; + if(lev == 0) return 1; /* to keep compatibility with old infofile */ cur_tape = lookup_tapelabel(info->inf[lev].label); @@ -1321,15 +1363,11 @@ static void get_estimates(void) hostp = dp->host; if(hostp->up == HOST_READY) { something_started = 1; + run_server_host_scripts(EXECUTE_ON_PRE_HOST_ESTIMATE, + get_config_name(), hostp); for(dp1 = hostp->disks; dp1 != NULL; dp1 = dp1->hostnext) { if (dp1->todo) - run_server_scripts(EXECUTE_ON_PRE_HOST_ESTIMATE, - get_config_name(), dp1, - est(dp1)->estimate[0].level); - } - for(dp1 = hostp->disks; dp1 != NULL; dp1 = dp1->hostnext) { - if (dp1->todo) - run_server_scripts(EXECUTE_ON_PRE_DLE_ESTIMATE, + run_server_dle_scripts(EXECUTE_ON_PRE_DLE_ESTIMATE, get_config_name(), dp1, est(dp1)->estimate[0].level); } @@ -1809,8 +1847,12 @@ static void handle_result( hostp->up = HOST_READY; if (pkt == NULL) { - errbuf = vstrallocf(_("Request to %s failed: %s"), + if (strcmp(security_geterror(sech), "timeout waiting for REP") == 0) { + errbuf = vstrallocf("Some estimate timeout on %s, using server estimate if possible", hostp->hostname); + } else { + errbuf = vstrallocf(_("Request to %s failed: %s"), hostp->hostname, security_geterror(sech)); + } goto error_return; } if (pkt->type == P_NAK) { @@ -1952,7 +1994,8 @@ static void handle_result( break; } } - if (i == MAX_LEVELS) { + if (i == MAX_LEVELS && level > 0) { + /* client always report level 0 for some error */ goto bad_msg; /* this est wasn't requested */ } est(dp)->got_estimate++; @@ -2064,7 +2107,7 @@ static void handle_result( est(dp)->estimate[1].nsize > (gint64)0) && (est(dp)->estimate[2].level == -1 || est(dp)->estimate[2].nsize > (gint64)0)))) { - run_server_scripts(EXECUTE_ON_POST_DLE_ESTIMATE, + run_server_dle_scripts(EXECUTE_ON_POST_DLE_ESTIMATE, get_config_name(), dp, est(dp)->estimate[0].level); est(dp)->post_dle = 1; @@ -2073,13 +2116,9 @@ static void handle_result( } if(hostp->up == HOST_DONE) { - for(dp = hostp->disks; dp != NULL; dp = dp->hostnext) { - if (dp->todo) - if (pkt->type == P_REP) { - run_server_scripts(EXECUTE_ON_POST_HOST_ESTIMATE, - get_config_name(), dp, - est(dp)->estimate[0].level); - } + if (pkt->type == P_REP) { + run_server_host_scripts(EXECUTE_ON_POST_HOST_ESTIMATE, + get_config_name(), hostp); } } @@ -2127,6 +2166,19 @@ static void handle_result( * reported. */ log_add(L_ERROR, "%s", errbuf); + for(dp = hostp->disks; dp != NULL; dp = dp->hostnext) { + if (dp->todo) { + qname = quote_string(dp->name); + est(dp)->state = DISK_DONE; + remove_disk(&waitq, dp); + enqueue_disk(&failq, dp); + + est(dp)->errstr = g_strdup(errbuf); + g_fprintf(stderr, _("error result for host %s disk %s: %s\n"), + dp->host->hostname, qname, errbuf); + amfree(qname); + } + } } hostp->up = HOST_DONE; amfree(errbuf); @@ -2197,7 +2249,8 @@ static void analyze_estimate( /* fill in degraded mode info */ g_fprintf(stderr,_("(picking inclevel for degraded mode)")); ep->degr_est = pick_inclevel(dp); - if (ep->degr_est->csize == (gint64)-1) { + if (ep->degr_est->level >= 0 && + ep->degr_est->csize == (gint64)-1) { ep->degr_est = est_for_level(dp, ep->degr_est->level + 1); } if (ep->degr_est->csize == (gint64)-1) { @@ -2263,7 +2316,15 @@ static void analyze_estimate( lev0size = est_tape_size(dp, 0); if(lev0size == (gint64)-1) lev0size = ep->last_lev0size; - balanced_size += (double)(lev0size / (gint64)runs_per_cycle); + if (dp->strategy == DS_NOINC) { + balanced_size += (double)lev0size; + } else if (dp->dumpcycle == 0) { + balanced_size += (double)(lev0size * conf_dumpcycle / (gint64)runs_per_cycle); + } else if (dp->dumpcycle != conf_dumpcycle) { + balanced_size += (double)(lev0size * (conf_dumpcycle / dp->dumpcycle) / (gint64)runs_per_cycle); + } else { + balanced_size += (double)(lev0size / (gint64)runs_per_cycle); + } } g_fprintf(stderr,_("total size %lld total_lev0 %1.0lf balanced-lev0size %1.0lf\n"), @@ -2439,6 +2500,7 @@ static void delay_dumps(void) disk_t * dp; disk_t * ndp; disk_t * preserve; + disk_t * delayed_dp; bi_t * bi; bi_t * nbi; gint64 new_total; /* New total_size */ @@ -2448,6 +2510,8 @@ static void delay_dumps(void) int delete; char * message; gint64 full_size; + time_t timestamps; + int priority; biq.head = biq.tail = NULL; @@ -2464,7 +2528,7 @@ static void delay_dumps(void) for(dp = schedq.head; dp != NULL; dp = ndp) { int avail_tapes = 1; - if (dp->splitsize > (gint64)0) + if (dp->splitsize > (gint64)0 || dp->allow_split) avail_tapes = conf_runtapes; ndp = dp->next; /* remove_disk zaps this */ @@ -2513,7 +2577,7 @@ static void delay_dumps(void) } else { delete = 0; - message = _("full dump delayed"); + message = _("full dump delayed, doing incremental"); } } else { @@ -2539,51 +2603,71 @@ static void delay_dumps(void) nb_forced_level_0 = 0; preserve = NULL; - for(dp = schedq.head; dp != NULL && preserve == NULL; dp = dp->next) - if(est(dp)->dump_est->level == 0) - preserve = dp; + timestamps = 2147483647; + priority = 0; + for(dp = schedq.head; dp != NULL; dp = dp->next) { + if (est(dp)->dump_est->level == 0) { + if (!preserve || + est(dp)->dump_priority > priority || + (est(dp)->dump_priority == priority && + est(dp)->info->inf[0].date < timestamps)) { + priority = est(dp)->dump_priority; + timestamps = est(dp)->info->inf[0].date; + preserve = dp; + } + } + } /* 2.a. Do not delay forced full */ - for(dp = schedq.tail; + delayed_dp = NULL; + do { + delayed_dp = 0; + timestamps = 0; + for(dp = schedq.tail; dp != NULL && total_size > tape_length; dp = ndp) { - ndp = dp->prev; - - if(est(dp)->dump_est->level != 0) continue; + ndp = dp->prev; - get_info(dp->host->hostname, dp->name, &info); - if(ISSET(info.command, FORCE_FULL)) { - nb_forced_level_0 += 1; - preserve = dp; - continue; - } + if(est(dp)->dump_est->level != 0) continue; - if(dp != preserve) { + get_info(dp->host->hostname, dp->name, &info); + if(ISSET(info.command, FORCE_FULL)) { + nb_forced_level_0 += 1; + preserve = dp; + continue; + } + if (dp != preserve && + est(dp)->info->inf[0].date > timestamps) { + delayed_dp = dp; + timestamps = est(dp)->info->inf[0].date; + } + } + if (delayed_dp) { /* Format dumpsize for messages */ g_snprintf(est_kb, 20, "%lld KB,", - (long long)est(dp)->dump_est->csize); + (long long)est(delayed_dp)->dump_est->csize); - if(dp->skip_incr) { + if(delayed_dp->skip_incr) { delete = 1; message = _("but cannot incremental dump skip-incr disk"); } - else if(est(dp)->last_level < 0) { + else if(est(delayed_dp)->last_level < 0) { delete = 1; message = _("but cannot incremental dump new disk"); } - else if(est(dp)->degr_est->level < 0) { + else if(est(delayed_dp)->degr_est->level < 0) { delete = 1; message = _("but no incremental estimate"); } else { delete = 0; - message = _("full dump delayed"); + message = _("full dump delayed, doing incremental"); } - delay_one_dump(dp, delete, _("dumps too big,"), est_kb, + delay_one_dump(delayed_dp, delete, _("dumps too big,"), est_kb, message, NULL); } - } + } while (delayed_dp); /* 2.b. Delay forced full if needed */ if(nb_forced_level_0 > 0 && total_size > tape_length) { @@ -2952,7 +3036,8 @@ static int promote_hills(void) } for(dp = schedq.head; dp != NULL; dp = dp->next) { - days = est(dp)->next_level0; /* This is > 0 by definition */ + days = est(dp)->next_level0; + if (days < 0) days = 0; if(daysskip_full && dp->strategy != DS_NOFULL && dp->strategy != DS_INCRONLY) { sp[days].disks++;