📄 planner.c
字号:
} } if(!dp->skip_incr && !(dp->strategy == DS_NOINC)) { if(ep->last_level == -1) { /* a new disk */ if(dp->strategy == DS_NOFULL || dp->strategy == DS_INCRONLY) { askfor(ep, i++, 1, &info); } else { assert(!dp->skip_full); /* should be handled above */ } } else { /* not new, pick normally */ int curr_level; curr_level = ep->last_level; if (ISSET(info.command, FORCE_NO_BUMP)) { if(curr_level > 0) { /* level 0 already asked for */ askfor(ep, i++, curr_level, &info); } log_add(L_INFO,_("Preventing bump of %s:%s as directed."), dp->host->hostname, qname); } else if (ISSET(info.command, FORCE_BUMP) && curr_level + 1 < DUMP_LEVELS) { 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); } else if (curr_level == 0) { askfor(ep, i++, 1, &info); } else { 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 * cur_level and cur_level + 1, so we will never bump. Also, * 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 == (off_t)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); } } } } 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 " "%d (%lld) %d (%lld) %d (%lld)\n"), dp->host->hostname, qname, info.command, dp->strategy == DS_NOFULL ? "no-full" : dp->strategy == DS_INCRONLY ? "incr-only" : dp->skip_full ? "skip-full" : dp->skip_incr ? "skip-incr" : "none", ep->last_level, ep->next_level0, ep->level_days, ep->level[0], (long long)ep->est_size[0], ep->level[1], (long long)ep->est_size[1], ep->level[2], (long long)ep->est_size[2]); assert(ep->level[0] != -1); enqueue_disk(&startq, dp); amfree(qname);}static int when_overwrite( char *label){ tape_t *tp; int runtapes; runtapes = conf_runtapes; if(runtapes == 0) runtapes = 1; if((tp = lookup_tapelabel(label)) == NULL) return 1; /* "shouldn't happen", but trigger warning message */ else if(tp->reuse == 0) return 1024; else if(lookup_nb_tape() > conf_tapecycle) return (lookup_nb_tape() - tp->position) / runtapes; else return (conf_tapecycle - tp->position) / runtapes;}/* Return the estimated size for a particular dump */static off_t est_size( disk_t *dp, int level){ int i; for(i = 0; i < MAX_LEVELS; i++) { if(level == est(dp)->level[i]) return est(dp)->est_size[i]; } return (off_t)-1;}/* Return the estimated on-tape size of a particular dump */static off_t est_tape_size( disk_t *dp, int level){ off_t size; double ratio; size = est_size(dp, level); if(size == (off_t)-1) return size; if(dp->compress == COMP_NONE) return size; if(level == 0) ratio = est(dp)->fullcomp; else ratio = est(dp)->incrcomp; /* * make sure over-inflated compression ratios don't throw off the * estimates, this is mostly for when you have a small dump getting * compressed which takes up alot more disk/tape space relatively due * to the overhead of the compression. This is specifically for * Digital Unix vdump. This patch is courtesy of Rudolf Gabler * (RUG@USM.Uni-Muenchen.DE) */ if(ratio > 1.1) ratio = 1.1; size = (off_t)((double)size * ratio); /* * Ratio can be very small in some error situations, so make sure * size goes back greater than zero. It may not be right, but * indicates we did get an estimate. */ if(size <= (off_t)0) { size = (off_t)1; } return size;}/* what was the level of the last successful dump to tape? */static int last_level( info_t *info){ int min_pos, min_level, i; time_t lev0_date, last_date; tape_t *tp; if(info->last_level != -1) return info->last_level; /* to keep compatibility with old infofile */ min_pos = 1000000000; min_level = -1; lev0_date = EPOCH; last_date = EPOCH; for(i = 0; i < 9; i++) { if(conf_reserve < 100) { if(i == 0) lev0_date = info->inf[0].date; else if(info->inf[i].date < lev0_date) continue; if(info->inf[i].date > last_date) { last_date = info->inf[i].date; min_level = i; } } else { if((tp = lookup_tapelabel(info->inf[i].label)) == NULL) continue; /* cull any entries from previous cycles */ if(i == 0) lev0_date = info->inf[0].date; else if(info->inf[i].date < lev0_date) continue; if(tp->position < min_pos) { min_pos = tp->position; min_level = i; } } } info->last_level = i; return min_level;}/* when is next level 0 due? 0 = today, 1 = tomorrow, etc*/static intnext_level0( disk_t *dp, info_t *info){ if(dp->strategy == DS_NOFULL || dp->strategy == DS_INCRONLY) return 1; /* fake it */ else if (dp->strategy == DS_NOINC) return 0; else if(info->inf[0].date < (time_t)0) return -days_diff(EPOCH, today); /* new disk */ else return dp->dumpcycle - days_diff(info->inf[0].date, today);}/* how many runs at current level? */static int runs_at( info_t *info, int lev){ tape_t *cur_tape, *old_tape; int last, nb_runs; last = last_level(info); if(lev != last) return 0; if(lev == 0) return 1; if(info->consecutive_runs != -1) return info->consecutive_runs; /* to keep compatibility with old infofile */ cur_tape = lookup_tapelabel(info->inf[lev].label); old_tape = lookup_tapelabel(info->inf[lev-1].label); if(cur_tape == NULL || old_tape == NULL) return 0; if(conf_runtapes == 0) nb_runs = (old_tape->position - cur_tape->position) / 1; else nb_runs = (old_tape->position - cur_tape->position) / conf_runtapes; info->consecutive_runs = nb_runs; return nb_runs;}static off_t bump_thresh( int level, off_t size_level_0, int bumppercent, off_t bumpsize, double bumpmult){ double bump; if ((bumppercent != 0) && (size_level_0 > (off_t)1024)) { bump = ((double)size_level_0 * (double)bumppercent) / 100.0; } else { bump = (double)bumpsize; } while(--level) bump = bump * bumpmult; return (off_t)bump;}/* * ======================================================================== * GET REMOTE DUMP SIZE ESTIMATES * */static void getsize(am_host_t *hostp);static disk_t *lookup_hostdisk(am_host_t *hp, char *str);static void handle_result(void *datap, pkt_t *pkt, security_handle_t *sech);static void get_estimates(void){ am_host_t *hostp; disk_t *dp; int something_started; something_started = 1; while(something_started) { something_started = 0; for(dp = startq.head; dp != NULL; dp = dp->next) { hostp = dp->host; if(hostp->up == HOST_READY) { something_started = 1; getsize(hostp); protocol_check(); /* * dp is no longer on startq, so dp->next is not valid * and we have to start all over. */ break; } } } protocol_run(); while(!empty(waitq)) { disk_t *dp = dequeue_disk(&waitq); est(dp)->errstr = _("hmm, disk was stranded on waitq"); enqueue_disk(&failq, dp); } while(!empty(pestq)) { disk_t *dp = dequeue_disk(&pestq); char * qname = quote_string(dp->name); if(est(dp)->level[0] != -1 && est(dp)->est_size[0] < (off_t)0) { if(est(dp)->est_size[0] == (off_t)-1) { log_add(L_WARNING, _("disk %s:%s, estimate of level %d failed."), dp->host->hostname, qname, est(dp)->level[0]); } else { log_add(L_WARNING, _("disk %s:%s, estimate of level %d timed out."), dp->host->hostname, qname, est(dp)->level[0]); } est(dp)->level[0] = -1; } if(est(dp)->level[1] != -1 && est(dp)->est_size[1] < (off_t)0) { if(est(dp)->est_size[1] == (off_t)-1) { log_add(L_WARNING, _("disk %s:%s, estimate of level %d failed."), dp->host->hostname, qname, est(dp)->level[1]); } else { log_add(L_WARNING, _("disk %s:%s, estimate of level %d timed out."), dp->host->hostname, qname, est(dp)->level[1]); } est(dp)->level[1] = -1; } if(est(dp)->level[2] != -1 && est(dp)->est_size[2] < (off_t)0) { if(est(dp)->est_size[2] == (off_t)-1) { log_add(L_WARNING, _("disk %s:%s, estimate of level %d failed."), dp->host->hostname, qname, est(dp)->level[2]); } else { log_add(L_WARNING, _("disk %s:%s, estimate of level %d timed out."), dp->host->hostname, qname, est(dp)->level[2]); } est(dp)->level[2] = -1; } 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)) { enqueue_disk(&estq, dp); } else { est(dp)->errstr = vstralloc("disk ", qname, _(", all estimate timed out"), NULL); enqueue_disk(&failq, dp); } amfree(qname); }}static void getsize( am_host_t *hostp){ char number[NUM_STR_SIZE], *req; disk_t * dp; int i; time_t estimates, timeout; size_t req_len; const security_driver_t *secdrv; char * backup_api; char * calcsize; char * qname; char * qdevice; assert(hostp->disks != NULL); if(hostp->up != HOST_READY) { return; } /* * The first time through here we send a "noop" request. This will * return the feature list from the client if it supports that. * If it does not, handle_result() will set the feature list to an * empty structure. In either case, we do the disks on the second * (and subsequent) pass(es). */ if(hostp->features != NULL) { /* sendsize service */ int nb_client = 0; int nb_server = 0; int has_features = am_has_feature(hostp->features, fe_req_options_features); int has_hostname = am_has_feature(hostp->features, fe_req_options_hostname); int has_maxdumps = am_has_feature(hostp->features, fe_req_options_maxdumps); int has_config = am_has_feature(hostp->features, fe_req_options_config); g_snprintf(number, SIZEOF(number), "%d", hostp->maxdumps); req = vstralloc("SERVICE ", "sendsize", "\n", "OPTIONS ", has_features ? "features=" : "", has_features ? our_feature_string : "", has_features ? ";" : "", has_maxdumps ? "maxdumps=" : "", has_maxdumps ? number : "", has_maxdumps ? ";" : "", has_hostname ? "hostname=" : "", has_hostname ? hostp->hostname : "", has_hostname ? ";" : "", has_config ? "config=" : "", has_config ? config_name : "", has_config ? ";" : "", "\n", NULL); req_len = strlen(req); req_len += 128; /* room for SECURITY ... */ estimates = 0; for(dp = hostp->disks; dp != NULL; dp = dp->hostnext) { char *s = NULL; size_t s_len = 0; if(dp->todo == 0) continue; if(est(dp)->state != DISK_READY) continue; est(dp)->got_estimate = 0; if(est(dp)->level[0] == -1) { est(dp)->state = DISK_DONE; continue; } qname = quote_string(dp->name); qdevice = quote_string(dp->device); if(dp->estimate == ES_CLIENT || dp->estimate == ES_CALCSIZE) { nb_client++; for(i = 0; i < MAX_LEVELS; i++) { char *l; char *exclude1 = ""; char *exclude2 = ""; char *excludefree = NULL; char *include1 = ""; char *include2 = ""; char *includefree = NULL; char spindle[NUM_STR_SIZE]; char level[NUM_STR_SIZE]; int lev = est(dp)->level[i]; if(lev == -1) break; g_snprintf(level, SIZEOF(level), "%d", lev); g_snprintf(spindle, SIZEOF(spindle), "%d", dp->spindle); if(am_has_feature(hostp->features,fe_sendsize_req_options)){ exclude1 = " OPTIONS |"; exclude2 = optionstr(dp, hostp->features, NULL); if ( exclude2 == NULL ) { error(_("problem with option string, check the dumptype definition.\n")); } excludefree = exclude2; includefree = NULL; } else {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -