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

📄 planner.c

📁 开源备份软件源码 AMANDA, the Advanced Maryland Automatic Network Disk Archiver, is a backup system that a
💻 C
📖 第 1 页 / 共 5 页
字号:
/* * Amanda, The Advanced Maryland Automatic Network Disk Archiver * Copyright (c) 1991-1999 University of Maryland at College Park * All Rights Reserved. * * Permission to use, copy, modify, distribute, and sell this software and its * documentation for any purpose is hereby granted without fee, provided that * the above copyright notice appear in all copies and that both that * copyright notice and this permission notice appear in supporting * documentation, and that the name of U.M. not be used in advertising or * publicity pertaining to distribution of the software without specific, * written prior permission.  U.M. makes no representations about the * suitability of this software for any purpose.  It is provided "as is" * without express or implied warranty. * * U.M. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL U.M. * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * * Authors: the Amanda Development Team.  Its members are listed in a * file named AUTHORS, in the root directory of this distribution. *//* * $Id: planner.c,v 1.206 2006/08/10 23:57:27 paddy_s Exp $ * * backup schedule planner for the Amanda backup system. */#include "amanda.h"#include "arglist.h"#include "conffile.h"#include "diskfile.h"#include "tapefile.h"#include "infofile.h"#include "logfile.h"#include "clock.h"#include "packet.h"#include "security.h"#include "protocol.h"#include "version.h"#include "amfeatures.h"#include "server_util.h"#include "holding.h"#include "timestamp.h"#define planner_debug(i,x) do {		\	if ((i) <= debug_planner) {	\	    dbprintf(x);		\	}				\} while (0)#define MAX_LEVELS		    3	/* max# of estimates per filesys */#define RUNS_REDZONE		    5	/* should be in conf file? */#define PROMOTE_THRESHOLD	 0.05	/* if <5% unbalanced, don't promote */#define DEFAULT_DUMPRATE	 1024.0	/* K/s *//* configuration file stuff */char *	conf_tapetype;off_t 	conf_maxdumpsize;int	conf_runtapes;int	conf_dumpcycle;int	conf_runspercycle;int	conf_tapecycle;time_t	conf_etimeout;int	conf_reserve;int	conf_autoflush;int	conf_usetimestamps;#define HOST_READY				((void *)0)	/* must be 0 */#define HOST_ACTIVE				((void *)1)#define HOST_DONE				((void *)2)#define DISK_READY				0		/* must be 0 */#define DISK_ACTIVE				1#define DISK_PARTIALY_DONE			2#define DISK_DONE				3typedef struct est_s {    int state;    int got_estimate;    int dump_priority;    int dump_level;    off_t dump_nsize;	/* native size */    off_t dump_csize;	/* compressed size */    int degr_level;	/* if dump_level == 0, what would be the inc level */    off_t degr_nsize;	/* native degraded size */    off_t degr_csize;	/* compressed degraded size */    int last_level;    off_t last_lev0size;    int next_level0;    int level_days;    int promote;    double fullrate, incrrate;    double fullcomp, incrcomp;    char *errstr;    int level[MAX_LEVELS];    char *dumpdate[MAX_LEVELS];    off_t est_size[MAX_LEVELS];} est_t;#define est(dp)	((est_t *)(dp)->up)/* pestq = partial estimate */disklist_t startq, waitq, pestq, estq, failq, schedq;off_t total_size;double total_lev0, balanced_size, balance_threshold;off_t tape_length;size_t tape_mark;tapetype_t *tape;size_t tt_blocksize;size_t tt_blocksize_kb;int runs_per_cycle = 0;time_t today;char *planner_timestamp = NULL;static am_feature_t *our_features = NULL;static char *our_feature_string = NULL;/* We keep a LIFO queue of before images for all modifications made * to schedq in our attempt to make the schedule fit on the tape. * Enough information is stored to reinstate a dump if it turns out * that it shouldn't have been touched after all. */typedef struct bi_s {    struct bi_s *next;    struct bi_s *prev;    int deleted;		/* 0=modified, 1=deleted */    disk_t *dp;			/* The disk that was changed */    int level;			/* The original level */    off_t nsize;		/* The original native size */    off_t csize;		/* The original compressed size */    char *errstr;		/* A message describing why this disk is here */} bi_t;typedef struct bilist_s {    bi_t *head, *tail;} bilist_t;bilist_t biq;			/* The BI queue itself *//* * ======================================================================== * MAIN PROGRAM * */static void setup_estimate(disk_t *dp);static void get_estimates(void);static void analyze_estimate(disk_t *dp);static void handle_failed(disk_t *dp);static void delay_dumps(void);static int promote_highest_priority_incremental(void);static int promote_hills(void);static void output_scheduleline(disk_t *dp);int main(int, char **);intmain(    int		argc,    char **	argv){    disklist_t origq;    disk_t *dp;    int moved_one;    int diskarg_offset;    off_t initial_size;    int i;    char *conf_diskfile;    char *conf_tapelist;    char *conf_infofile;    times_t section_start;    char *qname;    int    nb_disk;    char  *errstr = NULL;    config_overwrites_t *cfg_ovr = NULL;    char *cfg_opt = NULL;    /*     * Configure program for internationalization:     *   1) Only set the message locale for now.     *   2) Set textdomain for all amanda related programs to "amanda"     *      We don't want to be forced to support dozens of message catalogs.     */      setlocale(LC_MESSAGES, "C");    textdomain("amanda");     /* drop root privileges */    if (!set_root_privs(0)) {	error(_("planner must be run setuid root"));    }    safe_fd(-1, 0);    set_pname("planner");    dbopen(DBG_SUBDIR_SERVER);    cfg_ovr = extract_commandline_config_overwrites(&argc, &argv);    if (argc > 1) 	cfg_opt = argv[1];    config_init(CONFIG_INIT_EXPLICIT_NAME | CONFIG_INIT_USE_CWD | CONFIG_INIT_FATAL,		cfg_opt);    apply_config_overwrites(cfg_ovr);    safe_cd();    check_running_as(RUNNING_AS_DUMPUSER);    dbrename(config_name, DBG_SUBDIR_SERVER);    /* Don't die when child closes pipe */    signal(SIGPIPE, SIG_IGN);    setvbuf(stderr, (char *)NULL, (int)_IOLBF, 0);    erroutput_type = (ERR_AMANDALOG|ERR_INTERACTIVE);    set_logerror(logerror);    startclock();    section_start = curclock();    our_features = am_init_feature_set();    our_feature_string = am_feature_to_string(our_features);    g_fprintf(stderr, _("%s: pid %ld executable %s version %s\n"),	    get_pname(), (long) getpid(), argv[0], version());    for (i = 0; version_info[i] != NULL; i++)	g_fprintf(stderr, _("%s: %s"), get_pname(), version_info[i]);    diskarg_offset = 2;    if (argc > 3 && strcmp(argv[2], "--starttime") == 0) {	planner_timestamp = stralloc(argv[3]);	diskarg_offset += 2;    }    /*     * 1. Networking Setup     *     */    protocol_init();    /*     * 2. Read in Configuration Information     *     * All the Amanda configuration files are loaded before we begin.     */    g_fprintf(stderr,_("READING CONF INFO...\n"));    conf_diskfile = config_dir_relative(getconf_str(CNF_DISKFILE));    if (read_diskfile(conf_diskfile, &origq) < 0) {	error(_("could not load disklist \"%s\""), conf_diskfile);	/*NOTREACHED*/    }    if(origq.head == NULL) {	error(_("empty disklist \"%s\""), conf_diskfile);	/*NOTREACHED*/    }    errstr = match_disklist(&origq, argc-diskarg_offset,				    argv+diskarg_offset);    if (errstr) {	g_fprintf(stderr,"%s",errstr);	amfree(errstr);    }    nb_disk = 0;    for(dp = origq.head; dp != NULL; dp = dp->next) {	if(dp->todo) {	    qname = quote_string(dp->name);	    log_add(L_DISK, "%s %s", dp->host->hostname, qname);	    amfree(qname);	    nb_disk++;	}    }    if(nb_disk == 0) {	error(_("no DLE to backup"));	/*NOTREACHED*/    }    amfree(conf_diskfile);    conf_tapelist = config_dir_relative(getconf_str(CNF_TAPELIST));    if(read_tapelist(conf_tapelist)) {	error(_("could not load tapelist \"%s\""), conf_tapelist);	/*NOTREACHED*/    }    amfree(conf_tapelist);    conf_infofile = config_dir_relative(getconf_str(CNF_INFOFILE));    if(open_infofile(conf_infofile)) {	error(_("could not open info db \"%s\""), conf_infofile);	/*NOTREACHED*/    }    if (check_infofile(conf_infofile, &origq, &errstr) == -1) {	log_add(L_WARNING, "problem copying infofile: %s", errstr);	amfree(errstr);    }    amfree(conf_infofile);    conf_tapetype = getconf_str(CNF_TAPETYPE);    conf_maxdumpsize = getconf_am64(CNF_MAXDUMPSIZE);    conf_runtapes = getconf_int(CNF_RUNTAPES);    conf_dumpcycle = getconf_int(CNF_DUMPCYCLE);    conf_runspercycle = getconf_int(CNF_RUNSPERCYCLE);    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_usetimestamps = getconf_boolean(CNF_USETIMESTAMPS);    today = time(0);    if (planner_timestamp) {	if (conf_usetimestamps == 0) {	    planner_timestamp[8] = '\0';	}    } else if(conf_usetimestamps == 0) {	planner_timestamp = get_datestamp_from_time(0);    }    else {	planner_timestamp = get_timestamp_from_time(0);    }    log_add(L_START, _("date %s"), planner_timestamp);    g_printf("DATE %s\n", planner_timestamp);    fflush(stdout);    g_fprintf(stderr, _("%s: timestamp %s\n"),		    get_pname(), planner_timestamp);    /* some initializations */    if(conf_runspercycle == 0) {	runs_per_cycle = conf_dumpcycle;    } else if(conf_runspercycle == -1 ) {	runs_per_cycle = guess_runs_from_tapelist();    } else	runs_per_cycle = conf_runspercycle;    if (runs_per_cycle <= 0) {	runs_per_cycle = 1;    }    /*     * do some basic sanity checking     */     if(conf_tapecycle <= runs_per_cycle) {	log_add(L_WARNING, _("tapecycle (%d) <= runspercycle (%d)"),		conf_tapecycle, runs_per_cycle);     }        tape = lookup_tapetype(conf_tapetype);    if(conf_maxdumpsize > (off_t)0) {	tape_length = (off_t)conf_maxdumpsize;    }    else {	tape_length = tapetype_get_length(tape) * (off_t)conf_runtapes;    }    tape_mark = (size_t)tapetype_get_filemark(tape);    tt_blocksize_kb = (size_t)tapetype_get_blocksize(tape);    tt_blocksize = tt_blocksize_kb * 1024;    g_fprintf(stderr, _("%s: time %s: startup took %s secs\n"),		    get_pname(),		    walltime_str(curclock()),		    walltime_str(timessub(curclock(), section_start)));    /*     * 3. Send autoflush dumps left on the holding disks     *     * This should give us something to do while we generate the new     * dump schedule.     */    g_fprintf(stderr,_("\nSENDING FLUSHES...\n"));    if(conf_autoflush) {	dumpfile_t  file;	GSList *holding_list, *holding_file;	char *qdisk, *qhname;	/* get *all* flushable files in holding */	holding_list = holding_get_files_for_flush(NULL);	for(holding_file=holding_list; holding_file != NULL;				       holding_file = holding_file->next) {	    holding_file_get_dumpfile((char *)holding_file->data, &file);	    if (holding_file_size((char *)holding_file->data, 1) <= 0) {		log_add(L_INFO, "%s: removing file with no data.",			(char *)holding_file->data);		holding_file_unlink((char *)holding_file->data);		continue;	    }	    qdisk = quote_string(file.disk);	    qhname = quote_string((char *)holding_file->data);	    log_add(L_DISK, "%s %s", file.name, qdisk);	    g_fprintf(stderr,		    "FLUSH %s %s %s %d %s\n",		    file.name,		    qdisk,		    file.datestamp,		    file.dumplevel,		    qhname);	    g_fprintf(stdout,		    "FLUSH %s %s %s %d %s\n",		    file.name,		    qdisk,		    file.datestamp,		    file.dumplevel,		    qhname);	    amfree(qdisk);	    amfree(qhname);	}	g_slist_free_full(holding_list);	holding_list = NULL;    }    g_fprintf(stderr, _("ENDFLUSH\n"));    g_fprintf(stdout, _("ENDFLUSH\n"));    fflush(stdout);    /*     * 4. Calculate Preliminary Dump Levels     *     * Before we can get estimates from the remote slave hosts, we make a     * first attempt at guessing what dump levels we will be dumping at     * based on the curinfo database.     */    g_fprintf(stderr,_("\nSETTING UP FOR ESTIMATES...\n"));    section_start = curclock();    startq.head = startq.tail = NULL;    while(!empty(origq)) {	disk_t *dp = dequeue_disk(&origq);	if(dp->todo == 1) {	    setup_estimate(dp);	}    }    g_fprintf(stderr, _("%s: time %s: setting up estimates took %s secs\n"),		    get_pname(),		    walltime_str(curclock()),		    walltime_str(timessub(curclock(), section_start)));    /*     * 5. Get Dump Size Estimates from Remote Client Hosts     *     * Each host is queried (in parallel) for dump size information on all     * of its disks, and the results gathered as they come in.     */    /* go out and get the dump estimates */    g_fprintf(stderr,_("\nGETTING ESTIMATES...\n"));    section_start = curclock();

⌨️ 快捷键说明

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