Beispiel #1
0
/*
 * ndmp_tar_reader
 *
 * NDMP Tar reader thread. This threads keep reading the tar
 * file from the tape and wakes up the consumer thread to extract
 * it on the disk
 */
int
ndmp_tar_reader(ndmp_tar_reader_arg_t *argp)
{
	int bidx;
	int err;
	tlm_buffer_t *buf;
	tlm_buffers_t *bufs;
	tlm_cmd_t *lcmd;	/* Local command */
	ndmpd_session_t *session;
	ndmpd_module_params_t *mod_params;
	tlm_commands_t *cmds;

	if (!argp)
		return (-1);

	session = argp->tr_session;
	mod_params = argp->tr_mod_params;
	cmds = argp->tr_cmds;

	err = 0;
	if (session == NULL) {
		NDMP_LOG(LOG_DEBUG, "session == NULL");
		err = -1;
	} else if (cmds == NULL) {
		NDMP_LOG(LOG_DEBUG, "cmds == NULL");
		err = -1;
	}

	if (err != 0) {
		tlm_cmd_signal(cmds->tcs_command, TLM_TAR_READER);
		return (err);
	}

	lcmd = cmds->tcs_command;
	bufs = lcmd->tc_buffers;

	lcmd->tc_ref++;
	cmds->tcs_reader_count++;

	/*
	 * Synchronize with our parent thread.
	 */
	tlm_cmd_signal(cmds->tcs_command, TLM_TAR_READER);

	buf = tlm_buffer_in_buf(bufs, &bidx);
	while (cmds->tcs_reader == TLM_RESTORE_RUN &&
	    lcmd->tc_reader == TLM_RESTORE_RUN) {

		if (buf->tb_full) {
			NDMP_LOG(LOG_DEBUG, "R%d", bidx);
			/*
			 * The buffer is still full, wait for the consumer
			 * thread to use it.
			 */
			tlm_buffer_out_buf_timed_wait(bufs, 100);
			buf = tlm_buffer_in_buf(bufs, NULL);
		} else {
			NDMP_LOG(LOG_DEBUG, "r%d", bidx);

			err = read_one_buf(mod_params, bufs, buf);
			if (err < 0) {
				NDMP_LOG(LOG_DEBUG,
				    "Reading buffer %d, pos: %lld",
				    bidx, session->ns_mover.md_position);

				/* Force the writer to stop. */
				buf->tb_eot = buf->tb_eof = TRUE;
				break;
			} else if (err == 1) {
				NDMP_LOG(LOG_DEBUG,
				    "operation aborted or session terminated");
				err = 0;
				break;
			}

			buf = tlm_buffer_in_buf(bufs, &bidx);
			tlm_buffer_release_in_buf(bufs);
		}
	}

	/*
	 * If the consumer is waiting for us, wake it up so that it detects
	 * we're quiting.
	 */
	lcmd->tc_writer = TLM_STOP;
	tlm_buffer_release_in_buf(bufs);
	(void) usleep(1000);

	/*
	 * Clean up.
	 */
	cmds->tcs_reader_count--;
	lcmd->tc_ref--;
	return (err);
}
Beispiel #2
0
/*ARGSUSED*/
char *
tlm_get_write_buffer(long want, long *actual_size,
                     tlm_buffers_t *buffers, int zero)
{
    int	buf = buffers->tbs_buffer_in;
    tlm_buffer_t *buffer = &buffers->tbs_buffer[buf];
    int	align_size = RECORDSIZE - 1;
    char	*rec;

    /*
     * make sure the allocation is in chunks of 512 bytes
     */
    want += align_size;
    want &= ~align_size;

    *actual_size = buffer->tb_buffer_size - buffer->tb_buffer_spot;
    if (*actual_size <= 0) {
        /*
         * no room, send this one
         * and wait for a free one
         */
        if (!buffer->tb_full) {
            /*
             * we are now ready to send a full buffer
             * instead of trying to get a new buffer
             *
             * do not send if we failed to get a buffer
             * on the previous call
             */
            buffer->tb_full = TRUE;

            /*
             * tell the writer that a buffer is available
             */
            tlm_buffer_release_in_buf(buffers);

            buffer = tlm_buffer_advance_in_idx(buffers);
        }

        buffer = tlm_buffer_in_buf(buffers, NULL);

        if (buffer->tb_full) {
            /*
             * wait for the writer to free up a buffer
             */
            tlm_buffer_out_buf_timed_wait(buffers, 500);
        }

        buffer = tlm_buffer_in_buf(buffers, NULL);
        if (buffer->tb_full) {
            /*
             * the next buffer is still full
             * of data from previous activity
             *
             * nothing has changed.
             */
            return (0);
        }

        buffer->tb_buffer_spot = 0;
        *actual_size = buffer->tb_buffer_size - buffer->tb_buffer_spot;
    }

    *actual_size = min(want, *actual_size);
    rec = &buffer->tb_buffer_data[buffer->tb_buffer_spot];
    buffer->tb_buffer_spot += *actual_size;
    buffers->tbs_offset += *actual_size;
    if (zero) {
        (void) memset(rec, 0, *actual_size);
    }
    return (rec);
}