📄 planner.c
字号:
est(dp)->level[2], (long long)est(dp)->est_size[2]); if((est(dp)->level[0] != -1 && est(dp)->est_size[0] > (off_t)0) || (est(dp)->level[1] != -1 && est(dp)->est_size[1] > (off_t)0) || (est(dp)->level[2] != -1 && est(dp)->est_size[2] > (off_t)0)) { if(est(dp)->level[2] != -1 && est(dp)->est_size[2] < (off_t)0) { log_add(L_WARNING, _("disk %s:%s, estimate of level %d failed."), dp->host->hostname, qname, est(dp)->level[2]); est(dp)->level[2] = -1; } if(est(dp)->level[1] != -1 && est(dp)->est_size[1] < (off_t)0) { log_add(L_WARNING, _("disk %s:%s, estimate of level %d failed."), dp->host->hostname, qname, est(dp)->level[1]); est(dp)->level[1] = -1; } if(est(dp)->level[0] != -1 && est(dp)->est_size[0] < (off_t)0) { log_add(L_WARNING, _("disk %s:%s, estimate of level %d failed."), dp->host->hostname, qname, est(dp)->level[0]); est(dp)->level[0] = -1; } enqueue_disk(&estq, dp); } else { enqueue_disk(&failq, dp); if(est(dp)->got_estimate) { est(dp)->errstr = vstrallocf("disk %s, all estimate failed", qname); } else { g_fprintf(stderr, _("error result for host %s disk %s: missing estimate\n"), dp->host->hostname, qname); if (est(dp)->errstr == NULL) { est(dp)->errstr = vstrallocf(_("missing result for %s in %s response"), qname, dp->host->hostname); } } } } amfree(qname); } getsize(hostp); /* try to clean up any defunct processes, since Amanda doesn't wait() for them explicitly */ while(waitpid(-1, NULL, WNOHANG)> 0); return; NAK_parse_failed: errbuf = vstrallocf(_("%s NAK: [NAK parse failed]"), hostp->hostname); g_fprintf(stderr, _("got strange nak from %s:\n----\n%s----\n\n"), hostp->hostname, pkt->body); goto error_return; bad_msg: g_fprintf(stderr,_("got a bad message, stopped at:\n")); /*@ignore@*/ g_fprintf(stderr,_("----\n%s----\n\n"), line); errbuf = stralloc2(_("badly formatted response from "), hostp->hostname); /*@end@*/ error_return: i = 0; for(dp = hostp->disks; dp != NULL; dp = dp->hostnext) { if (dp->todo) { if(est(dp)->state == DISK_ACTIVE) { qname = quote_string(dp->name); est(dp)->state = DISK_DONE; remove_disk(&waitq, dp); enqueue_disk(&failq, dp); i++; est(dp)->errstr = stralloc(errbuf); g_fprintf(stderr, _("error result for host %s disk %s: %s\n"), dp->host->hostname, qname, errbuf); amfree(qname); } } } if(i == 0) { /* * If there were no disks involved, make sure the error gets * reported. */ log_add(L_ERROR, "%s", errbuf); } hostp->up = HOST_DONE; amfree(errbuf); /* try to clean up any defunct processes, since Amanda doesn't wait() for them explicitly */ while(waitpid(-1, NULL, WNOHANG)> 0);}/* * ======================================================================== * ANALYSE ESTIMATES * */static int schedule_order(disk_t *a, disk_t *b); /* subroutines */static int pick_inclevel(disk_t *dp);static void analyze_estimate( disk_t *dp){ est_t *ep; info_t info; int have_info = 0; char *qname = quote_string(dp->name); ep = est(dp); g_fprintf(stderr, _("pondering %s:%s... "), dp->host->hostname, qname); g_fprintf(stderr, _("next_level0 %d last_level %d "), ep->next_level0, ep->last_level); if(get_info(dp->host->hostname, dp->name, &info) == 0) { have_info = 1; } ep->degr_level = -1; ep->degr_nsize = (off_t)-1; ep->degr_csize = (off_t)-1; if(ep->next_level0 <= 0 || (have_info && ep->last_level == 0 && (info.command & FORCE_NO_BUMP))) { if(ep->next_level0 <= 0) { g_fprintf(stderr,_("(due for level 0) ")); } ep->dump_level = 0; ep->dump_nsize = est_size(dp, 0); ep->dump_csize = est_tape_size(dp, 0); if(ep->dump_csize <= (off_t)0) { g_fprintf(stderr, _("(no estimate for level 0, picking an incr level)\n")); ep->dump_level = pick_inclevel(dp); ep->dump_nsize = est_size(dp, ep->dump_level); ep->dump_csize = est_tape_size(dp, ep->dump_level); if(ep->dump_nsize == (off_t)-1) { ep->dump_level = ep->dump_level + 1; ep->dump_nsize = est_size(dp, ep->dump_level); ep->dump_csize = est_tape_size(dp, ep->dump_level); } } else { total_lev0 += (double) ep->dump_csize; if(ep->last_level == -1 || dp->skip_incr) { g_fprintf(stderr,_("(%s disk, can't switch to degraded mode)\n"), dp->skip_incr? "skip-incr":_("new")); ep->degr_level = -1; ep->degr_nsize = (off_t)-1; ep->degr_csize = (off_t)-1; } else { /* fill in degraded mode info */ g_fprintf(stderr,_("(picking inclevel for degraded mode)")); ep->degr_level = pick_inclevel(dp); ep->degr_nsize = est_size(dp, ep->degr_level); ep->degr_csize = est_tape_size(dp, ep->degr_level); if(ep->degr_csize == (off_t)-1) { ep->degr_level = ep->degr_level + 1; ep->degr_nsize = est_size(dp, ep->degr_level); ep->degr_csize = est_tape_size(dp, ep->degr_level); } if(ep->degr_csize == (off_t)-1) { g_fprintf(stderr,_("(no inc estimate)")); ep->degr_level = -1; } g_fprintf(stderr,"\n"); } } } else { g_fprintf(stderr,_("(not due for a full dump, picking an incr level)\n")); /* XXX - if this returns -1 may be we should force a total? */ ep->dump_level = pick_inclevel(dp); ep->dump_nsize = est_size(dp, ep->dump_level); ep->dump_csize = est_tape_size(dp, ep->dump_level); if(ep->dump_csize == (off_t)-1) { ep->dump_level = ep->last_level; ep->dump_nsize = est_size(dp, ep->dump_level); ep->dump_csize = est_tape_size(dp, ep->dump_level); } if(ep->dump_csize == (off_t)-1) { ep->dump_level = ep->last_level + 1; ep->dump_nsize = est_size(dp, ep->dump_level); ep->dump_csize = est_tape_size(dp, ep->dump_level); } if(ep->dump_csize == (off_t)-1) { ep->dump_level = 0; ep->dump_nsize = est_size(dp, ep->dump_level); ep->dump_csize = est_tape_size(dp, ep->dump_level); } } g_fprintf(stderr,_(" curr level %d nsize %lld csize %lld "), ep->dump_level, (long long)ep->dump_nsize, (long long)ep->dump_csize); insert_disk(&schedq, dp, schedule_order); total_size += (off_t)tt_blocksize_kb + ep->dump_csize + tape_mark; /* update the balanced size */ if(!(dp->skip_full || dp->strategy == DS_NOFULL || dp->strategy == DS_INCRONLY)) { off_t lev0size; lev0size = est_tape_size(dp, 0); if(lev0size == (off_t)-1) lev0size = ep->last_lev0size; balanced_size += (double)(lev0size / (off_t)runs_per_cycle); } g_fprintf(stderr,_("total size %lld total_lev0 %1.0lf balanced-lev0size %1.0lf\n"), (long long)total_size, total_lev0, balanced_size); amfree(qname);}static void handle_failed( disk_t *dp){ char *errstr, *errstr1, *qerrstr; char *qname = quote_string(dp->name); errstr = est(dp)->errstr? est(dp)->errstr : _("hmm, no error indicator!"); errstr1 = vstralloc("[",errstr,"]", NULL); qerrstr = quote_string(errstr1); amfree(errstr1); g_fprintf(stderr, _("%s: FAILED %s %s %s 0 %s\n"), get_pname(), dp->host->hostname, qname, planner_timestamp, qerrstr); log_add(L_FAIL, _("%s %s %s 0 %s"), dp->host->hostname, qname, planner_timestamp, qerrstr); amfree(qerrstr); amfree(qname); /* XXX - memory leak with *dp */}/* * insert-sort by decreasing priority, then * by decreasing size within priority levels. */static int schedule_order( disk_t *a, disk_t *b){ int diff; off_t ldiff; diff = est(b)->dump_priority - est(a)->dump_priority; if(diff != 0) return diff; ldiff = est(b)->dump_csize - est(a)->dump_csize; if(ldiff < (off_t)0) return -1; /* XXX - there has to be a better way to dothis */ if(ldiff > (off_t)0) return 1; return 0;}static int pick_inclevel( disk_t *dp){ int base_level, bump_level; off_t base_size, bump_size; off_t thresh; char *qname; base_level = est(dp)->last_level; /* if last night was level 0, do level 1 tonight, no ifs or buts */ if(base_level == 0) { g_fprintf(stderr,_(" picklev: last night 0, so tonight level 1\n")); return 1; } /* if no-full option set, always do level 1 */ if(dp->strategy == DS_NOFULL) { g_fprintf(stderr,_(" picklev: no-full set, so always level 1\n")); return 1; } base_size = est_size(dp, base_level); /* if we didn't get an estimate, we can't do an inc */ if(base_size == (off_t)-1) { base_size = est_size(dp, base_level+1); if(base_size > (off_t)0) /* FORCE_BUMP */ return base_level+1; g_fprintf(stderr,_(" picklev: no estimate for level %d, so no incs\n"), base_level); return base_level; } thresh = bump_thresh(base_level, est_size(dp, 0), dp->bumppercent, dp->bumpsize, dp->bumpmult); g_fprintf(stderr, _(" pick: size %lld level %d days %d (thresh %lldK, %d days)\n"), (long long)base_size, base_level, est(dp)->level_days, (long long)thresh, dp->bumpdays); if(base_level == 9 || est(dp)->level_days < dp->bumpdays || base_size <= thresh) return base_level; bump_level = base_level + 1; bump_size = est_size(dp, bump_level); if(bump_size == (off_t)-1) return base_level; g_fprintf(stderr, _(" pick: next size %lld... "), (long long)bump_size); if(base_size - bump_size < thresh) { g_fprintf(stderr, _("not bumped\n")); return base_level; } qname = quote_string(dp->name); g_fprintf(stderr, _("BUMPED\n")); log_add(L_INFO, _("Incremental of %s:%s bumped to level %d."), dp->host->hostname, qname, bump_level); amfree(qname); return bump_level;}/*** ========================================================================** ADJUST SCHEDULE**** We have two strategies here:**** 1. Delay dumps**** If we are trying to fit too much on the tape something has to go. We** try to delay totals until tomorrow by converting them into incrementals** and, if that is not effective enough, dropping incrementals altogether.** While we are searching for the guilty dump (the one that is really** causing the schedule to be oversize) we have probably trampled on a lot of** innocent dumps, so we maintain a "before image" list and use this to** put back what we can.**** 2. Promote dumps.**** We try to keep the amount of tape used by total dumps the same each night.** If there is some spare tape in this run we have a look to see if any of** tonights incrementals could be promoted to totals and leave us with a** more balanced cycle.*/static void delay_one_dump(disk_t *dp, int delete, ...);static int promote_highest_priority_incremental(void);static int promote_hills(void);/* delay any dumps that will not fit */static void delay_dumps(void){ disk_t * dp; disk_t * ndp; disk_t * preserve; bi_t * bi; bi_t * nbi; off_t new_total; /* New total_size */ char est_kb[20]; /* Text formatted dump size */ int nb_forced_level_0; info_t info; int delete; char * message; off_t full_size; biq.head = biq.tail = NULL; /* ** 1. Delay dumps that are way oversize. ** ** Dumps larger that the size of the tapes we are using are just plain ** not going to fit no matter how many other dumps we drop. Delay ** oversize totals until tomorrow (by which time my owner will have ** resolved the problem!) and drop incrementals altogether. Naturally ** a large total might be delayed into a large incremental so these ** need to be checked for separately. */ for(dp = schedq.head; dp != NULL; dp = ndp) { int avail_tapes = 1; if (dp->tape_splitsize > (off_t)0) avail_tapes = conf_runtapes; ndp = dp->next; /* remove_disk zaps this */ full_size = est_tape_size(dp, 0); if (full_size > tapetype_get_length(tape) * (off_t)avail_tapes) { char *qname = quote_string(dp->name); if (conf_runtapes > 1 && dp->tape_splitsize == (off_t)0) { log_add(L_WARNING, _("disk %s:%s, full dump (%lldKB) will be larger than available tape space" ", you could define a splitsize"), dp->host->hostname, qname, (long long)full_size); } else { log_add(L_WARNING, _("disk %s:%s, full dump (%lldKB) will be larger than available tape space"), dp->host->hostname, qname, (long long)full_size); } amfree(qname); } if (est(dp)->dump_csize == (off_t)-1 || est(dp)->dump_csize <= tapetype_get_length(tape) * (off_t)avail_tapes) { continue; } /* Format dumpsize for messages */ g_snprintf(est_kb, 20, "%lld KB,", (long long)est(dp)->dump_csize); if(est(dp)->dump_level == 0) { if(dp->skip_incr) { delete = 1; message = _("but cannot incremental dump skip-incr disk"); } else if(est(dp)->last_level < 0) { delete = 1; message = _("but cannot incremental dump new disk"); } else if(est(dp)->degr_level < 0) { delete = 1; message = _("but no incremental estimate"); } else if (est(dp)->degr_csize > tapetype_get_length(tape)) { delete = 1; message = _("incremental dump also larger than tape"); } else { delete = 0; message = _("full dump delayed"); } } else { delete = 1; message = _("skipping incremental"); } delay_one_dump(dp, delete, _("dump larger than available tape space,"), est_kb, message, NULL);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -