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

📄 taper.c

📁 开源备份软件源码 AMANDA, the Advanced Maryland Automatic Network Disk Archiver, is a backup system that a
💻 C
📖 第 1 页 / 共 3 页
字号:
    /* If we got here, everything is cool. */    return FALSE;}/* Find and label a new tape, if one is not already open. Returns TRUE * if a tape could be written. */static gboolean find_and_label_new_tape(taper_state_t * state,                                        dump_info_t * dump_info) {    if (state->device != NULL) {        return TRUE;    }        if (!find_new_tape(state, dump_info)) {        return FALSE;    }    return label_new_tape(state, dump_info);}static gboolean label_new_tape(taper_state_t * state, dump_info_t * dump_info) {    char *tapelist_name;    char *tapelist_name_old;    char * old_volume_name;    char * old_volume_time;    /* If we got here, it means that we have found a tape to label and     * have gotten permission from the driver to write it. But we     * still can say NO-NEW-TAPE if a problem shows up, and must still     * say NEW-TAPE if one doesn't. */    state->device = device_open(state->next_tape_device);    amfree(state->next_tape_device);    if (state->device == NULL) {        amfree(state->next_tape_label);        return FALSE;    }        device_set_startup_properties_from_config(state->device);    device_read_label(state->device);    old_volume_name = g_strdup(state->device->volume_label);    old_volume_time = g_strdup(state->device->volume_time);        if (!device_start(state->device, ACCESS_WRITE, state->next_tape_label,                      state->driver_start_time)) {        gboolean tape_used;        /* Something broke, see if we can tell if the volume was erased or         * not. */        g_fprintf(stderr, "taper: Error writing label %s to device %s.\n",                state->next_tape_label, state->device->device_name);        device_finish(state->device);        device_read_label(state->device);        tape_used = check_volume_changed(state->device, old_volume_name,                                          old_volume_time);        g_object_unref(state->device);        state->device = NULL;        amfree(state->next_tape_label);        /* If the volume was written, we tell the driver and then immediately         * try again. */        if (tape_used) {            putresult(NEW_TAPE, "%s %s\n", dump_info->handle,		      state->device->volume_label);            if (old_volume_name) {                log_add(L_WARNING, "Problem writing label to volume %s, "                        "volume may be erased.\n", old_volume_name);            } else {                log_add(L_WARNING, "Problem writing label %s to new volume, "                        "volume may be erased.\n", state->next_tape_label);            }            amfree(old_volume_name);            amfree(old_volume_time);            return find_and_label_new_tape(state, dump_info);        } else {            /* Otherwise, we grab a new tape without talking to the driver             * again. */            tape_search_request_t request;            gboolean search_result;            if (old_volume_name) {                log_add(L_WARNING, "Problem writing label to volume %s, "                        "old volume data intact\n", old_volume_name);            } else {                log_add(L_WARNING, "Problem writing label %s to new volume, "                        "old volume data intact\n", state->next_tape_label);            }            amfree(old_volume_name);            amfree(old_volume_time);            request.state = state;            request.prolong = TRUE;            request.errmsg = NULL;            search_result = GPOINTER_TO_INT(tape_search_thread(&request));            if (search_result) {                amfree(request.errmsg);                return label_new_tape(state, dump_info);            } else {                /* Problem finding a new tape! */                log_taper_scan_errmsg(request.errmsg);                putresult(NO_NEW_TAPE, "%s\n", dump_info->handle);                return FALSE;            }        }    } else {	amfree(old_volume_name);	amfree(old_volume_time);    }    amfree(state->next_tape_label);    tapelist_name = config_dir_relative(getconf_str(CNF_TAPELIST));    if (state->cur_tape == 0) {	tapelist_name_old = stralloc2(tapelist_name, ".yesterday");    } else {	char cur_str[NUM_STR_SIZE];	g_snprintf(cur_str, SIZEOF(cur_str), "%d", state->cur_tape - 1);	tapelist_name_old = vstralloc(tapelist_name,				      ".today.", cur_str, NULL);    }    if (write_tapelist(tapelist_name_old)) {	error("could not write tapelist: %s", strerror(errno));	/*NOTREACHED*/    }    amfree(tapelist_name_old);    remove_tapelabel(state->device->volume_label);    add_tapelabel(state->driver_start_time,                  state->device->volume_label);    if (write_tapelist(tapelist_name)) {	error("could not write tapelist: %s", strerror(errno));	/*NOTREACHED*/    }    amfree(tapelist_name);    state->cur_tape++;    log_add(L_START, "datestamp %s label %s tape %d",            state->driver_start_time, state->device->volume_label,            state->cur_tape);    putresult(NEW_TAPE, "%s %s\n", dump_info->handle,	      state->device->volume_label);    return TRUE;}/* Find out if the dump is PARTIAL or not, and set the proper driver   and logfile tags for the dump. */static void find_completion_tags(dump_info_t * dump_info, /* IN */                                 cmd_t * result_cmd,      /* OUT */                                 logtype_t * result_log   /* OUT */) {    if (taper_source_is_partial(dump_info->source)) {        *result_cmd = PARTIAL;        *result_log = L_PARTIAL;    } else {        *result_cmd = DONE;        *result_log = L_DONE;    }}/* Put an L_PARTIAL message to the logfile. */static void put_partial_log(dump_info_t * dump_info, double dump_time,                            guint64 dump_kbytes) {    char * qdiskname = quote_string(dump_info->diskname);    log_add(L_PARTIAL, "%s %s %s %d %d [sec %f kb %ju kps %f] \"\"",            dump_info->hostname, qdiskname, dump_info->timestamp,            dump_info->current_part, dump_info->level, dump_time,            (uintmax_t)dump_kbytes, dump_kbytes / dump_time);    amfree(qdiskname);}/* Figure out what to do after a part attempt. Returns TRUE if another   attempt should proceed for this dump; FALSE if we are done. */static gboolean finish_part_attempt(taper_state_t * taper_state,                                    dump_info_t * dump_info,                                    queue_result_flags queue_result,                                    GTimeVal run_time, guint64 run_bytes) {    double part_time = g_timeval_to_double(run_time);    guint64 part_kbytes = run_bytes / 1024;    double part_kbps = run_bytes / (1024 * part_time);            char * qdiskname = quote_string(dump_info->diskname);    if (queue_result == QUEUE_SUCCESS) {        dump_info->total_time = timesadd(run_time, dump_info->total_time);        dump_info->total_bytes += run_bytes;        log_add(L_PART, "%s %d %s %s %s %d/%d %d [sec %f kb %ju kps %f]",                taper_state->device->volume_label,                taper_state->device->file, dump_info->hostname, qdiskname,                dump_info->timestamp, dump_info->current_part,                taper_source_predict_parts(dump_info->source),                dump_info->level, part_time, (uintmax_t)part_kbytes, part_kbps);        putresult(PARTDONE, "%s %s %d %ju \"[sec %f kb %ju kps %f]\"\n",                  dump_info->handle, taper_state->device->volume_label,                  taper_state->device->file, (uintmax_t)part_kbytes, part_time,		  (uintmax_t)part_kbytes, part_kbps);                if (taper_source_get_end_of_data(dump_info->source)) {            cmd_t result_cmd;            logtype_t result_log;            double dump_time = g_timeval_to_double(dump_info->total_time);            guint64 dump_kbytes = dump_info->total_bytes / 1024;            double dump_kbps = dump_info->total_bytes / (1024 * dump_time);            find_completion_tags(dump_info, &result_cmd, &result_log);            g_object_unref(dump_info->source);            dump_info->source = NULL;                    log_add(result_log, "%s %s %s %d %d [sec %f kb %ju kps %f]",                    dump_info->hostname, qdiskname, dump_info->timestamp,                    dump_info->current_part, dump_info->level, dump_time,		    (uintmax_t)dump_kbytes, dump_kbps);            putresult(result_cmd, "%s INPUT-GOOD TAPE-GOOD "                      "\"[sec %f kb %ju kps %f]\" \"\" \"\"\n",                      dump_info->handle, dump_time, (uintmax_t)dump_kbytes,                      dump_kbps);                        amfree(qdiskname);            return FALSE;        } else if (taper_source_get_end_of_part(dump_info->source)) {            taper_source_start_new_part(dump_info->source);            dump_info->current_part ++;            amfree(qdiskname);            return TRUE;        }        /* If we didn't read EOF or EOP, then an error           occured. But we read QUEUE_SUCCESS, so something is           b0rked. */        g_assert_not_reached();    } else {        char * volume_label = strdup(taper_state->device->volume_label);        int file_number = taper_state->device->file;        double dump_time, dump_kbps;        guint64 dump_kbytes;        /* A problem occured. */        if (queue_result & QUEUE_CONSUMER_ERROR) {            /* Close the device. */            device_finish(taper_state->device);            g_object_unref(taper_state->device);            taper_state->device = NULL;        }                log_add(L_PARTPARTIAL,                "%s %d %s %s %s %d/%d %d [sec %f kb %ju kps %f] \"\"",                volume_label, file_number, dump_info->hostname, qdiskname,                dump_info->timestamp, dump_info->current_part,                taper_source_predict_parts(dump_info->source),                dump_info->level, part_time, (uintmax_t)part_kbytes, part_kbps);        amfree(volume_label);                if ((queue_result & QUEUE_CONSUMER_ERROR) &&            (!(queue_result & QUEUE_PRODUCER_ERROR)) &&            taper_source_seek_to_part_start(dump_info->source)) {            /* It is recoverable. */            log_add(L_INFO, "Will request retry of failed split part.");            if (find_and_label_new_tape(taper_state, dump_info)) {                /* dump_info->current_part is unchanged. */                amfree(qdiskname);                return TRUE;            }        }        dump_info->total_time = timesadd(run_time, dump_info->total_time);        dump_info->total_bytes += run_bytes;        dump_time = g_timeval_to_double(dump_info->total_time);        dump_kbytes = dump_info->total_bytes / 1024;        dump_kbps = dump_info->total_bytes / (1024 * dump_time);                putresult(PARTIAL,                  "%s INPUT-%s TAPE-%s "                  "\"[sec %f kb %ju kps %f]\" \"\" \"\"\n",                  dump_info->handle,                  (queue_result & QUEUE_PRODUCER_ERROR) ? "ERROR" : "GOOD",                  (queue_result & QUEUE_CONSUMER_ERROR) ? "ERROR" : "GOOD",                  dump_time, (uintmax_t)dump_kbytes, dump_kbps);        put_partial_log(dump_info, dump_time, dump_kbytes);    }    amfree(qdiskname);    return FALSE;}/* Generate the actual header structure to write to tape. This means dropping * bits related to the holding disk, and adding bits for split dumps. */static dumpfile_t * munge_headers(dump_info_t * dump_info) {    dumpfile_t * rval;    int expected_splits;        rval = taper_source_get_first_header(dump_info->source);    if (rval == NULL) {        return NULL;    }    rval->cont_filename[0] = '\0';    expected_splits = taper_source_predict_parts(dump_info->source);    if (expected_splits != 1) {        rval->type = F_SPLIT_DUMPFILE;        rval->partnum = dump_info->current_part;        rval->totalparts = expected_splits;    }    return rval;}/* We call this when we can't find a tape to write data to. This could   happen with the first (or only) part of a file, but it could also   happen with an intermediate part of a split dump. dump_bytes   is 0 if this is the first part of a dump. */static void bail_no_volume(dump_info_t * dump_info) {    if (dump_info->total_bytes > 0) {        /* Second or later part of a split dump, so PARTIAL message. */        double dump_time = g_timeval_to_double(dump_info->total_time);        guint64 dump_kbytes = dump_info->total_bytes / 1024;        double dump_kbps = dump_kbytes / dump_time;        putresult(PARTIAL,                  "%s INPUT-GOOD TAPE-ERROR "                  "\"[sec %f kb %ju kps %f]\" \"\" \"no new tape\"\n",                  dump_info->handle,                   dump_time, (uintmax_t)dump_kbytes, dump_kbps);        put_partial_log(dump_info, dump_time, dump_kbytes);    } else {        char * qdiskname = quote_string(dump_info->diskname);        putresult(FAILED,                  "%s INPUT-GOOD TAPE-ERROR \"\" \"No new tape.\"\n",                  dump_info->handle);        log_add(L_FAIL, "%s %s %s %d \"No new tape.\"",                dump_info->hostname, qdiskname, dump_info->timestamp,                dump_info->level);	amfree(qdiskname);    }}/* Link up the TaperSource with the Device, including retries etc. */static void run_device_output(taper_state_t * taper_state,                              dump_info_t * dump_info) {    GValue val;    guint file_number;    dump_info->current_part = 1;    dump_info->total_time.tv_sec = 0;    dump_info->total_time.tv_usec = 0;    dump_info->total_bytes = 0;    for (;;) {        GTimeVal start_time, end_time, run_time;        StreamingRequirement streaming_mode;        queue_result_flags queue_result;        CountingConsumerData consumer_data;        dumpfile_t *this_header;        size_t max_memory;                this_header = munge_headers(dump_info);        if (this_header == NULL) {            char * qdiskname = quote_string(dump_info->diskname);            putresult(FAILED,             "%s INPUT-ERROR TAPE-GOOD \"Failed reading dump header.\" \"\"\n",                      dump_info->handle);            log_add(L_FAIL, "%s %s %s %d \"Failed reading dump header.\"",                    dump_info->hostname, qdiskname, dump_info->timestamp,                    dump_info->level);            amfree(qdiskname);            return;        }                    if (!find_and_label_new_tape(taper_state, dump_info)) {            bail_no_volume(dump_info);	    amfree(this_header);            return;        }        if (!device_start_file(taper_state->device, this_header)) {            bail_no_volume(dump_info);	    amfree(this_header);            return;        }	amfree(this_header);        bzero(&val, sizeof(val));        if (!device_property_get(taper_state->device, PROPERTY_STREAMING, &val)            || !G_VALUE_HOLDS(&val, STREAMING_REQUIREMENT_TYPE)) {            g_fprintf(stderr, "taper: Couldn't get streaming type!\n");            streaming_mode = STREAMING_REQUIREMENT_REQUIRED;        } else {            streaming_mode = g_value_get_enum(&val);        }            file_number = taper_state->device->file;        consumer_data.next_consumer = device_write_consumer;        consumer_data.next_consumer_data = taper_state->device;        consumer_data.bytes_written = 0;

⌨️ 快捷键说明

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