📄 taper.c
字号:
/* 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 + -