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

📄 driver.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-1998 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: driver.c 6512 2007-05-24 17:00:24Z ian $ * * controlling process for the Amanda backup system *//* * XXX possibly modify tape queue to be cognizant of how much room is left on *     tape.  Probably not effective though, should do this in planner. */#include "amanda.h"#include "clock.h"#include "conffile.h"#include "diskfile.h"#include "event.h"#include "holding.h"#include "infofile.h"#include "logfile.h"#include "fsusage.h"#include "version.h"#include "driverio.h"#include "server_util.h"#include "timestamp.h"#define driver_debug(i, ...) do {	\	if ((i) <= debug_driver) {	\	    dbprintf(__VA_ARGS__);	\	}				\} while (0)#define hold_debug(i, ...) do {		\	if ((i) <= debug_holding) {	\	    dbprintf(__VA_ARGS__);	\	}				\} while (0)static disklist_t waitq;	// dle waiting estimate resultstatic disklist_t runq;		// dle waiting to be dumped to holding diskstatic disklist_t directq;	// dle waiting to be dumped directly to tapestatic disklist_t tapeq;	// dle on holding disk waiting to be written				//   to tapestatic disklist_t roomq;	// dle waiting for more space on holding diskstatic int pending_aborts;static disk_t *taper_disk;static int degraded_mode;static off_t reserved_space;static off_t total_disksize;static char *dumper_program;static char *chunker_program;static int  inparallel;static int nodump = 0;static off_t tape_length = (off_t)0;static off_t tape_left = (off_t)0;static int current_tape = 0;static int conf_taperalgo;static int conf_runtapes;static time_t sleep_time;static int idle_reason;static char *driver_timestamp;static char *hd_driver_timestamp;static am_host_t *flushhost = NULL;static int need_degraded=0;static holdalloc_t *holdalloc;static int num_holdalloc;static event_handle_t *dumpers_ev_time = NULL;static event_handle_t *schedule_ev_read = NULL;static int   conf_flush_threshold_dumped;static int   conf_flush_threshold_scheduled;static int   conf_taperflush;static off_t flush_threshold_dumped;static off_t flush_threshold_scheduled;static off_t taperflush;static int   schedule_done;			// 1 if we don't wait for a						//   schedule from the plannerstatic int   force_flush;			// All dump are terminated, we						// must now respect taper_flushstatic int wait_children(int count);static void wait_for_children(void);static void allocate_bandwidth(netif_t *ip, unsigned long kps);static int assign_holdingdisk(assignedhd_t **holdp, disk_t *diskp);static void adjust_diskspace(disk_t *diskp, cmd_t cmd);static void delete_diskspace(disk_t *diskp);static assignedhd_t **build_diskspace(char *destname);static int client_constrained(disk_t *dp);static void deallocate_bandwidth(netif_t *ip, unsigned long kps);static void dump_schedule(disklist_t *qp, char *str);static void dump_to_tape(disk_t *dp);static assignedhd_t **find_diskspace(off_t size, int *cur_idle,					assignedhd_t *preferred);static unsigned long free_kps(netif_t *ip);static off_t free_space(void);static void dumper_chunker_result(disk_t *dp);static void dumper_taper_result(disk_t *dp);static void file_taper_result(disk_t *dp);static void handle_dumper_result(void *);static void handle_chunker_result(void *);static void handle_dumpers_time(void *);static void handle_taper_result(void *);static void holdingdisk_state(char *time_str);static dumper_t *idle_dumper(void);static void interface_state(char *time_str);static int queue_length(disklist_t q);static disklist_t read_flush(void);static void read_schedule(void *cookie);static void short_dump_state(void);static void startaflush(void);static void start_degraded_mode(disklist_t *queuep);static void start_some_dumps(disklist_t *rq);static void continue_port_dumps(void);static void update_failed_dump_to_tape(disk_t *);typedef enum {    TAPE_ACTION_NO_ACTION     = 0,    TAPE_ACTION_NEW_TAPE      = (1 << 0),    TAPE_ACTION_NO_NEW_TAPE   = (1 << 1),    TAPE_ACTION_START_A_FLUSH = (1 << 2)} TapeAction;static TapeAction tape_action(void);static const char *idle_strings[] = {#define NOT_IDLE		0    T_("not-idle"),#define IDLE_NO_DUMPERS		1    T_("no-dumpers"),#define IDLE_START_WAIT		2    T_("start-wait"),#define IDLE_NO_HOLD		3    T_("no-hold"),#define IDLE_CLIENT_CONSTRAINED	4    T_("client-constrained"),#define IDLE_NO_BANDWIDTH	5    T_("no-bandwidth"),#define IDLE_NO_DISKSPACE	6    T_("no-diskspace")};intmain(    int		argc,    char **	argv){    disklist_t origq;    disk_t *diskp;    int dsk;    dumper_t *dumper;    char *newdir = NULL;    struct fs_usage fsusage;    holdingdisk_t *hdp;    unsigned long reserve = 100;    char *conf_diskfile;    cmd_t cmd;    int result_argc;    char *result_argv[MAX_ARGS+1];    char *taper_program;    char *conf_tapetype;    tapetype_t *tape;    char *line;    char hostname[1025];    intmax_t kb_avail;    config_overwrites_t *cfg_ovr = NULL;    char *cfg_opt = NULL;    holdalloc_t *ha, *ha_last;    /*     * 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");    safe_fd(-1, 0);    setvbuf(stdout, (char *)NULL, (int)_IOLBF, 0);    setvbuf(stderr, (char *)NULL, (int)_IOLBF, 0);    set_pname("driver");    dbopen(DBG_SUBDIR_SERVER);    atexit(wait_for_children);    /* Don't die when child closes pipe */    signal(SIGPIPE, SIG_IGN);    erroutput_type = (ERR_AMANDALOG|ERR_INTERACTIVE);    set_logerror(logerror);    startclock();    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);    g_printf(_("%s: pid %ld executable %s version %s\n"),	   get_pname(), (long) getpid(), argv[0], version());    if(argc > 2) {        if(strncmp(argv[2], "nodump", 6) == 0) {            nodump = 1;        }    }    safe_cd(); /* do this *after* config_init */    check_running_as(RUNNING_AS_DUMPUSER);    dbrename(config_name, DBG_SUBDIR_SERVER);    amfree(driver_timestamp);    /* read timestamp from stdin */    while ((line = agets(stdin)) != NULL) {	if (line[0] != '\0')	    break;	amfree(line);    }    if ( line == NULL ) {      error(_("Did not get DATE line from planner"));      /*NOTREACHED*/    }    driver_timestamp = alloc(15);    strncpy(driver_timestamp, &line[5], 14);    driver_timestamp[14] = '\0';    amfree(line);    log_add(L_START,_("date %s"), driver_timestamp);    gethostname(hostname, SIZEOF(hostname));    log_add(L_STATS,_("hostname %s"), hostname);    /* check that we don't do many dump in a day and usetimestamps is off */    if(strlen(driver_timestamp) == 8) {	if (!nodump) {	    char *conf_logdir = getconf_str(CNF_LOGDIR);	    char *logfile    = vstralloc(conf_logdir, "/log.",					 driver_timestamp, ".0", NULL);	    char *oldlogfile = vstralloc(conf_logdir, "/oldlog/log.",					 driver_timestamp, ".0", NULL);	    if(access(logfile, F_OK) == 0 || access(oldlogfile, F_OK) == 0) {		log_add(L_WARNING, _("WARNING: This is not the first amdump run today. Enable the usetimestamps option in the configuration file if you want to run amdump more than once per calendar day."));	    }	    amfree(oldlogfile);	    amfree(logfile);	}	hd_driver_timestamp = get_timestamp_from_time(0);    }    else {	hd_driver_timestamp = stralloc(driver_timestamp);    }    taper_program = vstralloc(amlibexecdir, "/", "taper", versionsuffix(), NULL);    dumper_program = vstralloc(amlibexecdir, "/", "dumper", versionsuffix(),			       NULL);    chunker_program = vstralloc(amlibexecdir, "/", "chunker", versionsuffix(),			       NULL);    conf_taperalgo = getconf_taperalgo(CNF_TAPERALGO);    conf_tapetype = getconf_str(CNF_TAPETYPE);    conf_runtapes = getconf_int(CNF_RUNTAPES);    tape = lookup_tapetype(conf_tapetype);    tape_length = tapetype_get_length(tape);    conf_flush_threshold_dumped = getconf_int(CNF_FLUSH_THRESHOLD_DUMPED);    conf_flush_threshold_scheduled = getconf_int(CNF_FLUSH_THRESHOLD_SCHEDULED);    conf_taperflush = getconf_int(CNF_TAPERFLUSH);    flush_threshold_dumped = (conf_flush_threshold_dumped * tape_length) / 100;    flush_threshold_scheduled = (conf_flush_threshold_scheduled * tape_length) / 100;    taperflush = (conf_taperflush *tape_length) / 100;    driver_debug(1, _("flush_threshold_dumped: %lld\n"), (long long)flush_threshold_dumped);    driver_debug(1, _("flush_threshold_scheduled: %lld\n"), (long long)flush_threshold_scheduled);    driver_debug(1, _("taperflush: %lld\n"), (long long)taperflush);    /* start initializing: read in databases */    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*/    }    amfree(conf_diskfile);    /* set up any configuration-dependent variables */    inparallel	= getconf_int(CNF_INPARALLEL);    reserve = (unsigned long)getconf_int(CNF_RESERVE);    total_disksize = (off_t)0;    ha_last = NULL;    num_holdalloc = 0;    for(hdp = getconf_holdingdisks(), dsk = 0; hdp != NULL; hdp = holdingdisk_next(hdp), dsk++) {	ha = alloc(SIZEOF(holdalloc_t));	num_holdalloc++;	/* link the list in the same order as getconf_holdingdisks's results */	ha->next = NULL;	if (ha_last == NULL)	    holdalloc = ha;	else	    ha_last->next = ha;	ha_last = ha;	ha->hdisk = hdp;	ha->allocated_dumpers = 0;	ha->allocated_space = (off_t)0;	ha->disksize = holdingdisk_get_disksize(hdp);	/* get disk size */	if(get_fs_usage(holdingdisk_get_diskdir(hdp), NULL, &fsusage) == -1	   || access(holdingdisk_get_diskdir(hdp), W_OK) == -1) {	    log_add(L_WARNING, _("WARNING: ignoring holding disk %s: %s\n"),		    holdingdisk_get_diskdir(hdp), strerror(errno));	    ha->disksize = 0L;	    continue;	}	/* do the division first to avoid potential integer overflow */	if (fsusage.fsu_bavail_top_bit_set)	    kb_avail = 0;	else	    kb_avail = fsusage.fsu_bavail / 1024 * fsusage.fsu_blocksize;	if(ha->disksize > (off_t)0) {	    if(ha->disksize > kb_avail) {		log_add(L_WARNING,			_("WARNING: %s: %lld KB requested, "			"but only %lld KB available."),			holdingdisk_get_diskdir(hdp),			(long long)ha->disksize,			(long long)kb_avail);			ha->disksize = kb_avail;	    }	}	/* ha->disksize is negative; use all but that amount */	else if(kb_avail < -ha->disksize) {	    log_add(L_WARNING,		    _("WARNING: %s: not %lld KB free."),		    holdingdisk_get_diskdir(hdp),		    (long long)-ha->disksize);	    ha->disksize = (off_t)0;	    continue;	}	else	    ha->disksize += kb_avail;	g_printf(_("driver: adding holding disk %d dir %s size %lld chunksize %lld\n"),	       dsk, holdingdisk_get_diskdir(hdp),	       (long long)ha->disksize,	       (long long)(holdingdisk_get_chunksize(hdp)));	newdir = newvstralloc(newdir,			      holdingdisk_get_diskdir(hdp), "/", hd_driver_timestamp,			      NULL);	if(!mkholdingdir(newdir)) {	    ha->disksize = (off_t)0;	}	total_disksize += ha->disksize;    }    reserved_space = total_disksize * (off_t)(reserve / 100);    g_printf(_("reserving %lld out of %lld for degraded-mode dumps\n"),	   (long long)reserved_space, (long long)free_space());    amfree(newdir);    if(inparallel > MAX_DUMPERS) inparallel = MAX_DUMPERS;    /* taper takes a while to get going, so start it up right away */    init_driverio();    if(conf_runtapes > 0) {        startup_tape_process(taper_program);        taper_cmd(START_TAPER, driver_timestamp, NULL, 0, NULL);    }    /* fire up the dumpers now while we are waiting */    if(!nodump) startup_dump_processes(dumper_program, inparallel, driver_timestamp);    /*     * Read schedule from stdin.  Usually, this is a pipe from planner,     * so the effect is that we wait here for the planner to     * finish, but meanwhile the taper is rewinding the tape, reading     * the label, checking it, writing a new label and all that jazz     * in parallel with the planner.     */    runq.head = NULL;    runq.tail = NULL;    directq.head = NULL;    directq.tail = NULL;    waitq = origq;    taper_state = TAPER_STATE_DEFAULT;    tapeq = read_flush();    roomq.head = roomq.tail = NULL;    log_add(L_STATS, _("startup time %s"), walltime_str(curclock()));    g_printf(_("driver: start time %s inparallel %d bandwidth %lu diskspace %lld "), walltime_str(curclock()), inparallel,	   free_kps(NULL), (long long)free_space());    g_printf(_(" dir %s datestamp %s driver: drain-ends tapeq %s big-dumpers %s\n"),	   "OBSOLETE", driver_timestamp, taperalgo2str(conf_taperalgo),	   getconf_str(CNF_DUMPORDER));    fflush(stdout);    /* ok, planner is done, now lets see if the tape is ready */    if (conf_runtapes > 0) {	cmd = getresult(taper, 1, &result_argc, result_argv, MAX_ARGS+1);	if (cmd != TAPER_OK) {	    /* no tape, go into degraded mode: dump to holding disk */	    need_degraded = 1;	}    } else {	need_degraded = 1;    }    tape_left = tape_length;    taper_busy = 0;    taper_input_error = NULL;

⌨️ 快捷键说明

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