New API calls burn_write_opts_set_dvd_obs(), burn_write_opts_set_stdio_fsync()

This commit is contained in:
Thomas Schmitt 2009-11-15 15:30:26 +00:00
parent 738b83ac03
commit 79a33ca2ac
5 changed files with 210 additions and 7 deletions

View File

@ -1 +1 @@
#define Cdrskin_timestamP "2009.11.15.152541"
#define Cdrskin_timestamP "2009.11.15.153140"

View File

@ -767,6 +767,9 @@ void burn_set_verbosity(int level);
This call can be made at any time - even before burn_initialize().
It is in effect for all active drives and currently not very thread
safe for multiple drives.
>>> ??? Shouldn't the file path with bit1 be adjustable ?
@param flag Bitfield for control purposes. The default is 0.
bit0= log to file /tmp/libburn_sg_command_log
bit1= log to stderr
@ -2119,6 +2122,32 @@ void burn_write_opts_set_force(struct burn_write_opts *opts, int use_force);
void burn_write_opts_set_stream_recording(struct burn_write_opts *opts,
int value);
/* ts A91115 */
/** Overrides the write chunk size for DVD and BD media which is normally
determined according to media type and setting of stream recording.
A chunk size of 64 KB may improve throughput with bus systems which show
latency problems.
@param opts The write opts to change
@param obs Number of bytes which shall be sent by a single write command.
0 means automatic size, 32768 and 65336 are the only other
accepted sizes for now.
@since 0.7.4
*/
void burn_write_opts_set_dvd_obs(struct burn_write_opts *opts, int obs);
/* ts A91115 */
/** Sets the rythm by which stdio pseudo drives force their output data to
be consumed by the receiving storage device. This forcing keeps the memory
from being clogged with lots of pending data for slow devices.
@param opts The write opts to change
@param rythm Number of 2KB output blocks after which fsync(2) is
performed. -1 means no fsync(), 0 means default,
elsewise the value must be >= 32.
Default is currently 8192 = 16 MB.
@since 0.7.4
*/
void burn_write_opts_set_stdio_fsync(struct burn_write_opts *opts, int rythm);
/** Sets whether to read in raw mode or not
@param opts The read opts to change

View File

@ -39,6 +39,8 @@ struct burn_write_opts *burn_write_opts_new(struct burn_drive *drive)
opts->fill_up_media = 0;
opts->force_is_set = 0;
opts->do_stream_recording = 0;
opts->dvd_obs_override = 0;
opts->stdio_fsync_size = Libburn_stdio_fsync_limiT;
opts->has_mediacatalog = 0;
opts->format = BURN_CDROM;
opts->multi = 0;
@ -389,6 +391,25 @@ void burn_write_opts_set_stream_recording(struct burn_write_opts *opts,
}
/* ts A91115: API */
void burn_write_opts_set_dvd_obs(struct burn_write_opts *opts, int obs)
{
if (obs != 0 && obs != 32 * 1024 && obs != 64 * 1024)
return;
opts->dvd_obs_override = obs;
}
/* ts A91115: API */
void burn_write_opts_set_stdio_fsync(struct burn_write_opts *opts, int rythm)
{
if (rythm == -1)
opts->stdio_fsync_size = 0;
else if (rythm == 0)
opts->stdio_fsync_size = Libburn_stdio_fsync_limiT;
else if (rythm >= 32)
opts->stdio_fsync_size = rythm;
}
/* ts A70901: API */

View File

@ -51,9 +51,19 @@ struct burn_write_opts
/* ts A80412 : whether to use WRITE12 with Streaming bit set
rather than WRITE10. Speeds up DVD-RAM. Might help with BD-RE.
This gets transferred to burn_drive.do_stream_recording */
This gets transferred to burn_drive.do_stream_recording
*/
int do_stream_recording;
/* ts A91115 : override value for .obs on DVD media.
Only values 0, 32K and 64K are allowed for now. */
int dvd_obs_override;
/* ts A91115 : size of the fsync() interval for stdio writing.
Values 0 or >= 32 counted in 2 KB blocks. */
int stdio_fsync_size;
/** A disc can have a media catalog number */
int has_mediacatalog;
unsigned char mediacatalog[13];
@ -64,6 +74,11 @@ struct burn_write_opts
unsigned char multi;
};
/* Default value for burn_write_opts.stdio_flush_size
*/
#define Libburn_stdio_fsync_limiT 8192
/** Options for disc reading operations. This should be created with
burn_read_opts_new() and freed with burn_read_opts_free(). */
struct burn_read_opts

View File

@ -1246,6 +1246,126 @@ int burn_disc_close_track_dvd_plus_r(struct burn_write_opts *o,
}
/* <<<
#define Libburn_simplified_dvd_chunk_transactioN 1
*/
#ifdef Libburn_simplified_dvd_chunk_transactioN
/* ts A91114 : EXPERIMENTAL, NOT COMPLETELY IMPLEMENTED
Simplified data transmission for DVD. libburn via Linux USB is 30 % slower
than growisofs or cdrecord when transmitting 32 KB chunks.
With 64 KB chunks it is 20% faster than the competitors.
No heavy CPU load is visible but there might be subtle race conditions in
the USB driver which work better with shorter time gaps between WRITE
commands.
Insight: It is actually about the interference of track source reading
with SCSI writing via USB. growisofs reads with O_DIRECT into a
mmap()ed buffer. When doing the same, libburn with 32 KB chunks
reaches similar write speed.
On the other hand, 64 KB chunks are 20% faster than that and
are not improved by reading O_DIRECT.
O_DIRECT is a property of the input fd of struct burn_source.
It can only be done with properly aligned memory and with aligned
read size. Alignment size is file system system specific.
System call
mmap(NULL, (size_t) buffer_size, PROT_READ | PROT_WRITE,
MAP_SHARED | MAP_ANONYMOUS, -1, (off_t) 0);
is supposed to allocate a properly aligned buffer.
64 KB is supposed to be a safe size.
@return 1= ok, go on , 2= no input with track->open_ended = nothing written
<= 0 = error
*/
static int transact_dvd_chunk(struct burn_write_opts *opts,
struct burn_track *track)
{
int curr = 0, valid, err;
struct burn_drive *d = opts->drive;
struct buffer *out = d->buffer;
unsigned char *data = out->data;
#ifdef Libburn_log_in_and_out_streaM
/* <<< ts A61031 */
static int tee_fd= -1;
if(tee_fd==-1)
tee_fd= open("/tmp/libburn_sg_readin",
O_WRONLY|O_CREAT|O_TRUNC,S_IRUSR|S_IWUSR);
#endif /* Libburn_log_in_and_out_streaM */
/* Read a chunk full of data */
/* ??? Do we have offset padding ? >>> First produce offset padding */;
/* <<<< */
if (0 && !track->eos) {
for (curr = 0; curr < opts->obs; curr += 2048) {
if (track->source->read != NULL)
valid = track->source->read(track->source,
data + curr, 2048);
else
valid = track->source->read_xt(track->source,
data + curr, 2048);
if (valid <= 0) {
track->eos = 1;
break;
}
track->sourcecount += valid;
#ifdef Libburn_log_in_and_out_streaM
if(tee_fd!=-1 && valid>0) {
write(tee_fd, data + curr, valid);
}
#endif /* Libburn_log_in_and_out_streaM */
}
} else if (!track->eos){
valid = track->source->read(track->source, data, opts->obs);
if (valid <= 0) {
track->eos = 1;
} else {
track->sourcecount += valid;
curr = valid;
#ifdef Libburn_log_in_and_out_streaM
if(tee_fd!=-1 && valid>0) {
write(tee_fd, data, valid);
}
#endif /* Libburn_log_in_and_out_streaM */
}
}
if (curr == 0 && track->open_ended) {
/* >>> allow tail padding */;
return 2;
}
if (curr < opts->obs)
memset(data + curr , 0, opts->obs - curr);
/* Write chunk */
out->bytes = opts->obs;
out->sectors = out->bytes / 2048;
err = d->write(d, d->nwa, out);
if (err == BE_CANCELLED)
return 0;
track->writecount += out->bytes;
track->written_sectors += out->sectors;
d->progress.buffered_bytes += out->bytes;
d->nwa += out->sectors;
out->bytes = 0;
out->sectors = 0;
return 1;
}
#endif /* Libburn_simplified_dvd_chunk_transactioN */
/* ts A61218 - A81208 */
int burn_dvd_write_track(struct burn_write_opts *o,
struct burn_session *s, int tnum, int is_last_track)
@ -1322,9 +1442,18 @@ int burn_dvd_write_track(struct burn_write_opts *o,
d->progress.buffer_capacity / 2048 + 128;
}
#ifdef Libburn_simplified_dvd_chunk_transactioN
ret = transact_dvd_chunk(o, t);
if (ret <= 0)
{ret = 0; goto ex;}
i += o->obs / 2048 - 1;
d->progress.sector += o->obs / 2048 - 1;
#else
/* transact a (CD sized) sector */
if (!sector_data(o, t, 0))
{ ret = 0; goto ex; }
#endif
if (open_ended) {
d->progress.sectors = sectors = i;
@ -1789,11 +1918,22 @@ int burn_dvd_write_sync(struct burn_write_opts *o,
/* <<< test only : Does this increase effective speed with USB ?
ts A90801 : 64kB: speed with 16x DVD-R is 12 rather than 8
128kB: glibc complains about double free
BURN_OS_TRANSPORT_BUFFER_SIZE would need to
be enlarged anyway.
With BURN_OS_TRANSPORT_BUFFER_SIZE
enlarged to 128 MB, the first WRITE fails
with an i/o error.
o->obs = 64 * 1024;
*/
if (o->dvd_obs_override >= 32 * 1024)
o->obs = o->dvd_obs_override;
if (o->obs > BUFFER_SIZE) {
sprintf(msg, "Chosen write chunk size %d exceeds system dependent buffer size", o->obs);
libdax_msgs_submit(libdax_messenger, d->global_index,
0x00000002, LIBDAX_MSGS_SEV_DEBUG,
LIBDAX_MSGS_PRIO_ZERO, msg, 0, 0);
o->obs = BUFFER_SIZE;
}
sprintf(msg, "dvd/bd Profile= %2.2Xh , obs= %d , obs_pad= %d",
d->current_profile, o->obs, o->obs_pad);
@ -2043,8 +2183,6 @@ int burn_stdio_slowdown(struct burn_drive *d, struct timeval *prev_time,
return 1;
}
/* Flush write buffer after each 16 MB */
#define Libburn_stdio_flush_limiT 8192
/* ts A70904 */
int burn_stdio_write_track(struct burn_write_opts *o, struct burn_session *s,
@ -2085,7 +2223,7 @@ int burn_stdio_write_track(struct burn_write_opts *o, struct burn_session *s,
d->progress.sector++;
/* Flush to disk from time to time */
if (d->progress.sector - prev_sync_sector >=
Libburn_stdio_flush_limiT) {
o->stdio_fsync_size && o->stdio_fsync_size > 0) {
prev_sync_sector = d->progress.sector;
if (!o->simulate)
burn_stdio_sync_cache(d->stdio_fd, d, 1);