示例#1
0
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);
}
示例#2
0
文件: taper.c 项目: regina/amanda
/* 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;
        }
    }
}