static void push_buffer_impl( XferElement *elt, gpointer buf, size_t len) { XferDestDevice *self = XFER_DEST_DEVICE(elt); gpointer to_free = buf; /* Handle EOF */ if (!buf) { /* write out the partial buffer, if there's anything in it */ if (self->partial_length) { if (!do_block(self, self->block_size, self->partial)) { return; } self->partial_length = 0; } device_finish_file(self->device); return; } /* set up the block buffer, now that we can depend on having a blocksize * from the device */ if (!self->partial) { self->partial = g_try_malloc(self->device->block_size); if (self->partial == NULL) { xfer_cancel_with_error(elt, "%s: Cannot allocate memory", self->device->device_name); wait_until_xfer_cancelled(elt->xfer); return; } self->block_size = self->device->block_size; self->partial_length = 0; } /* if we already have data in the buffer, add the new data to it */ if (self->partial_length != 0) { gsize to_copy = min(self->block_size - self->partial_length, len); memmove((char *)self->partial + self->partial_length, buf, to_copy); buf = (gpointer)(to_copy + (char *)buf); len -= to_copy; self->partial_length += to_copy; } /* and if the buffer is now full, write the block */ if (self->partial_length == self->block_size) { if (!do_block(self, self->block_size, self->partial)) { g_free(to_free); return; } self->partial_length = 0; } /* write any whole blocks directly from the push buffer */ while (len >= self->block_size) { if (!do_block(self, self->block_size, buf)) { g_free(to_free); return; } buf = (gpointer)(self->block_size + (char *)buf); len -= self->block_size; } /* and finally store any leftover data in the partial buffer */ if (len) { memmove(self->partial, buf, len); self->partial_length = len; } g_free(to_free); }
/* 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); char * errstr = taper_source_get_errmsg(dump_info->source); if (!errstr) errstr = "Failed reading dump header."; errstr = quote_string(errstr); putresult(FAILED, "%s INPUT-ERROR TAPE-GOOD %s \"\"\n", dump_info->handle, errstr); log_add(L_FAIL, "%s %s %s %d %s", dump_info->hostname, qdiskname, dump_info->timestamp, dump_info->level, errstr); amfree(qdiskname); amfree(errstr); return; } if (!find_and_label_new_tape(taper_state, dump_info)) { bail_no_volume(dump_info, taper_state->last_errmsg); dumpfile_free(this_header); return; } while (!device_start_file(taper_state->device, this_header)) { /* Close the device. */ device_finish(taper_state->device); g_object_unref(taper_state->device); taper_state->device = NULL; if (!find_and_label_new_tape(taper_state, dump_info)) { bail_no_volume(dump_info, taper_state->last_errmsg); dumpfile_free(this_header); return; } } dumpfile_free(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; g_get_current_time(&start_time); if (getconf_seen(CNF_DEVICE_OUTPUT_BUFFER_SIZE)) { max_memory = getconf_size(CNF_DEVICE_OUTPUT_BUFFER_SIZE); if (getconf_seen(CNF_TAPEBUFS)) { g_fprintf(stderr, "Configuration directives 'device_output_buffer_size' " "and \n" "'tapebufs' are incompatible; using former.\n"); } } else if (getconf_seen(CNF_TAPEBUFS)) { max_memory = getconf_int(CNF_TAPEBUFS) * taper_state->device->block_size; } else { /* Use default. */ max_memory = getconf_size(CNF_DEVICE_OUTPUT_BUFFER_SIZE); } queue_result = do_consumer_producer_queue_full (taper_source_producer, dump_info->source, counting_consumer, &consumer_data, taper_state->device->block_size, max_memory, streaming_mode); g_get_current_time(&end_time); run_time = timesub(end_time, start_time); /* The device_write_consumer leaves the file open, so close it now. */ if (!device_finish_file(taper_state->device)) { queue_result = queue_result | QUEUE_CONSUMER_ERROR; } if (!finish_part_attempt(taper_state, dump_info, queue_result, run_time, consumer_data.bytes_written)) { break; } } }