⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 planner.c

📁 开源备份软件源码 AMANDA, the Advanced Maryland Automatic Network Disk Archiver, is a backup system that a
💻 C
📖 第 1 页 / 共 5 页
字号:
    estq.head = estq.tail = NULL;    pestq.head = pestq.tail = NULL;    waitq.head = waitq.tail = NULL;    failq.head = failq.tail = NULL;    get_estimates();    g_fprintf(stderr, _("%s: time %s: getting estimates took %s secs\n"),		    get_pname(),		    walltime_str(curclock()),		    walltime_str(timessub(curclock(), section_start)));    /*     * At this point, all disks with estimates are in estq, and     * all the disks on hosts that didn't respond to our inquiry     * are in failq.     */    dump_queue("FAILED", failq, 15, stderr);    dump_queue("DONE", estq, 15, stderr);    /*     * 6. Analyze Dump Estimates     *     * Each disk's estimates are looked at to determine what level it     * should dump at, and to calculate the expected size and time taking     * historical dump rates and compression ratios into account.  The     * total expected size is accumulated as well.     */    g_fprintf(stderr,_("\nANALYZING ESTIMATES...\n"));    section_start = curclock();			/* an empty tape still has a label and an endmark */    total_size = ((off_t)tt_blocksize_kb + (off_t)tape_mark) * (off_t)2;    total_lev0 = 0.0;    balanced_size = 0.0;    schedq.head = schedq.tail = NULL;    while(!empty(estq)) analyze_estimate(dequeue_disk(&estq));    while(!empty(failq)) handle_failed(dequeue_disk(&failq));    /*     * At this point, all the disks are on schedq sorted by priority.     * The total estimated size of the backups is in total_size.     */    {	disk_t *dp;	g_fprintf(stderr, _("INITIAL SCHEDULE (size %lld):\n"),		(long long)total_size);	for(dp = schedq.head; dp != NULL; dp = dp->next) {	    qname = quote_string(dp->name);	    g_fprintf(stderr, _("  %s %s pri %d lev %d nsize %lld csize %lld\n"),		    dp->host->hostname, qname, est(dp)->dump_priority,		    est(dp)->dump_level,		    (long long)est(dp)->dump_nsize,                    (long long)est(dp)->dump_csize);	    amfree(qname);	}    }    /*     * 7. Delay Dumps if Schedule Too Big     *     * If the generated schedule is too big to fit on the tape, we need to     * delay some full dumps to make room.  Incrementals will be done     * instead (except for new or forced disks).     *     * In extreme cases, delaying all the full dumps is not even enough.     * If so, some low-priority incrementals will be skipped completely     * until the dumps fit on the tape.     */    g_fprintf(stderr, _("\nDELAYING DUMPS IF NEEDED, total_size %lld, tape length %lld mark %zu\n"),	    (long long)total_size,	    (long long)tape_length,	    tape_mark);    initial_size = total_size;    delay_dumps();    /* XXX - why bother checking this? */    if(empty(schedq) && total_size < initial_size) {	error(_("cannot fit anything on tape, bailing out"));	/*NOTREACHED*/    }    /*     * 8. Promote Dumps if Schedule Too Small     *     * Amanda attempts to balance the full dumps over the length of the     * dump cycle.  If this night's full dumps are too small relative to     * the other nights, promote some high-priority full dumps that will be     * due for the next run, to full dumps for tonight, taking care not to     * overflow the tape size.     *     * This doesn't work too well for small sites.  For these we scan ahead     * looking for nights that have an excessive number of dumps and promote     * one of them.     *     * Amanda never delays full dumps just for the sake of balancing the     * schedule, so it can take a full cycle to balance the schedule after     * a big bump.     */    g_fprintf(stderr,     _("\nPROMOTING DUMPS IF NEEDED, total_lev0 %1.0lf, balanced_size %1.0lf...\n"),	    total_lev0, balanced_size);    balance_threshold = balanced_size * PROMOTE_THRESHOLD;    moved_one = 1;    while((balanced_size - total_lev0) > balance_threshold && moved_one)	moved_one = promote_highest_priority_incremental();    moved_one = promote_hills();    g_fprintf(stderr, _("%s: time %s: analysis took %s secs\n"),		    get_pname(),		    walltime_str(curclock()),		    walltime_str(timessub(curclock(), section_start)));    /*     * 9. Output Schedule     *     * The schedule goes to stdout, presumably to driver.  A copy is written     * on stderr for the debug file.     */    g_fprintf(stderr,_("\nGENERATING SCHEDULE:\n--------\n"));    while(!empty(schedq)) output_scheduleline(dequeue_disk(&schedq));    g_fprintf(stderr, _("--------\n"));    close_infofile();    log_add(L_FINISH, _("date %s time %s"), planner_timestamp, walltime_str(curclock()));    clear_tapelist();    amfree(planner_timestamp);    amfree(our_feature_string);    am_release_feature_set(our_features);    our_features = NULL;    dbclose();    return 0;}/* * ======================================================================== * SETUP FOR ESTIMATES * */static void askfor(est_t *, int, int, info_t *);static int last_level(info_t *info);		  /* subroutines */static off_t est_size(disk_t *dp, int level);static off_t est_tape_size(disk_t *dp, int level);static int next_level0(disk_t *dp, info_t *info);static int runs_at(info_t *info, int lev);static off_t bump_thresh(int level, off_t size_level_0, int bumppercent, off_t bumpsize, double bumpmult);static int when_overwrite(char *label);static void askfor(    est_t *ep,	/* esimate data block */    int seq,	/* sequence number of request */    int lev,	/* dump level being requested */    info_t *info)	/* info block for disk */{    if(seq < 0 || seq >= MAX_LEVELS) {	error(_("error [planner askfor: seq out of range 0..%d: %d]"),	      MAX_LEVELS, seq);	/*NOTREACHED*/    }    if(lev < -1 || lev >= DUMP_LEVELS) {	error(_("error [planner askfor: lev out of range -1..%d: %d]"),	      DUMP_LEVELS, lev);	/*NOTREACHED*/    }    if (lev == -1) {	ep->level[seq] = -1;	ep->dumpdate[seq] = (char *)0;	ep->est_size[seq] = (off_t)-2;	return;    }    ep->level[seq] = lev;    ep->dumpdate[seq] = stralloc(get_dumpdate(info,lev));    ep->est_size[seq] = (off_t)-2;    return;}static voidsetup_estimate(     disk_t *dp){    est_t *ep;    info_t info;    int i;    char *qname;    int overwrite_runs;    assert(dp && dp->host);    qname = quote_string(dp->name);    g_fprintf(stderr, _("%s: time %s: setting up estimates for %s:%s\n"),		    get_pname(), walltime_str(curclock()),		    dp->host->hostname, qname);    /* get current information about disk */    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, dp->name);    }    /* setup working data struct for disk */    ep = alloc(SIZEOF(est_t));    dp->up = (void *) ep;    ep->state = DISK_READY;    ep->dump_nsize = (off_t)-1;    ep->dump_csize = (off_t)-1;    ep->dump_priority = dp->priority;    ep->errstr = 0;    ep->promote = 0;    /* calculated fields */    if (ISSET(info.command, FORCE_FULL)) {	/* force a level 0, kind of like a new disk */	if(dp->strategy == DS_NOFULL) {	    /*	     * XXX - Not sure what it means to force a no-full disk.  The	     * purpose of no-full is to just dump changes relative to a	     * stable base, for example root partitions that vary only	     * slightly from a site-wide prototype.  Only the variations	     * are dumped.	     *	     * If we allow a level 0 onto the Amanda cycle, then we are	     * hosed when that tape gets re-used next.  Disallow this for	     * now.	     */	    log_add(L_ERROR,		    _("Cannot force full dump of %s:%s with no-full option."),		    dp->host->hostname, qname);	    /* clear force command */	    CLR(info.command, FORCE_FULL);	    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*/	    }	    ep->last_level = last_level(&info);	    ep->next_level0 = next_level0(dp, &info);	}	else {	    ep->last_level = -1;	    ep->next_level0 = -conf_dumpcycle;	    log_add(L_INFO, _("Forcing full dump of %s:%s as directed."),		    dp->host->hostname, qname);	}    }    else if(dp->strategy == DS_NOFULL) {	/* force estimate of level 1 */	ep->last_level = 1;	ep->next_level0 = next_level0(dp, &info);    }    else {	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(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);	} 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,		    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(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);	    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,		    overwrite_runs);	}    }    if(ep->next_level0 < 0) {	g_fprintf(stderr,plural(_("%s:%s overdue %d day for level 0\n"),			      _("%s:%s overdue %d days for level 0\n"),			      (-ep->next_level0)),		dp->host->hostname, qname, (-ep->next_level0));	ep->dump_priority -= ep->next_level0;    }    else if (ISSET(info.command, FORCE_FULL))	ep->dump_priority += 1;    /* else XXX bump up the priority of incrementals that failed last night */    /* handle external level 0 dumps */    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);	    ep->next_level0 += conf_dumpcycle;	    ep->last_level = 0;	    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*/	    }	    log_add(L_INFO, _("Skipping full dump of %s:%s today."),		    dp->host->hostname, qname);	    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);	    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]"),		    dp->host->hostname, qname, planner_timestamp);	    amfree(qname);	    return;	}	if(ep->last_level == -1) {	    /* probably a new disk, but skip-full means no full! */	    ep->last_level = 0;	}	if(ep->next_level0 == 1) {	    log_add(L_WARNING, _("Skipping full dump of %s:%s tomorrow."),		    dp->host->hostname, qname);	}    }    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);	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"),		dp->host->hostname, qname);	amfree(qname);	return;    }    /* handle "skip-incr" type archives */    if(dp->skip_incr && ep->next_level0 > 0) {	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);	g_fprintf(stderr, _("%s: SKIPPED %s %s 1 [skip-incr]\n"),		get_pname(), dp->host->hostname, qname);	log_add(L_SUCCESS, _("%s %s %s 1 [skipped: skip-incr]"),		dp->host->hostname, qname, planner_timestamp);	amfree(qname);	return;    }    if( ep->last_level == -1 && ep->next_level0 > 0 && 	dp->strategy != DS_NOFULL && dp->strategy != DS_INCRONLY &&	conf_reserve == 100) {	log_add(L_WARNING, _("%s:%s mismatch: no tapelist record, "		"but curinfo next_level0: %d."),		dp->host->hostname, qname, ep->next_level0);	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;    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]);    /* determine which estimates to get */    i = 0;    if (dp->strategy == DS_NOINC ||	(!dp->skip_full &&	 (!ISSET(info.command, FORCE_BUMP) ||	  dp->skip_incr ||	  ep->last_level == -1))) {	if(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);	}	switch (dp->strategy) {	case DS_STANDARD: 	case DS_NOINC:	    askfor(ep, i++, 0, &info);	    if(dp->skip_full) {		log_add(L_INFO, _("Ignoring skip_full for %s:%s "			"because the strategy is NOINC."),			dp->host->hostname, qname);	    }	    if(info.command & FORCE_BUMP) {		log_add(L_INFO,		 _("Ignoring FORCE_BUMP for %s:%s because the strategy is NOINC."),			dp->host->hostname, qname);	    }	    	    break;	case DS_NOFULL:	    break;	case DS_INCRONLY:	    if (ISSET(info.command, FORCE_FULL))		ep->last_level = 0;	    break;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -