/* * 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); }
/*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); }