Implemented burn_source.cancel() in a binary backwards compatible way

This commit is contained in:
Thomas Schmitt 2007-12-24 14:21:23 +00:00
parent 32a6bd1f82
commit d9e056c3ac
7 changed files with 88 additions and 237 deletions

View File

@ -1 +1 @@
#define Cdrskin_timestamP "2007.12.07.185206"
#define Cdrskin_timestamP "2007.12.24.141959"

View File

@ -188,115 +188,8 @@ struct burn_source *burn_fd_source_new(int datafd, int subfd, off_t size)
}
/* ts A70930 */
/* ----------------------------- fifo ---------------------------- */
/* The fifo mechanism consists of a burn_source proxy which is here,
a thread management team which is located in async.c,
and a synchronous shoveller which is here.
*/
/* fifo_ng has a ringbuffer and runs in a thread. og is on its way out. */
#define Libburn_fifo_nG 1
#ifndef Libburn_fifo_nG
static int fifo_read(struct burn_source *source,
unsigned char *buffer,
int size)
{
struct burn_source_fifo *fs = source->data;
int ret;
if (fs->is_started == 0) {
ret = burn_fifo_start(source, 0);
if (ret <= 0) {
libdax_msgs_submit(libdax_messenger, -1, 0x00020152,
LIBDAX_MSGS_SEV_FATAL, LIBDAX_MSGS_PRIO_HIGH,
"Cannot start fifo thread", 0, 0);
return -1;
}
fs->is_started = 1;
}
if (size == 0)
return 0;
ret = read_full_buffer(fs->outlet[0], buffer, size);
if (ret > 0)
fs->out_counter += ret;
return ret;
}
static off_t fifo_get_size(struct burn_source *source)
{
struct burn_source_fifo *fs = source->data;
return fs->inp->get_size(fs->inp);
}
static int fifo_set_size(struct burn_source *source, off_t size)
{
struct burn_source_fifo *fs = source->data;
return fs->inp->set_size(fs->inp, size);
}
static void fifo_free(struct burn_source *source)
{
struct burn_source_fifo *fs = source->data;
if (fs->outlet[1] >= 0)
close(fs->outlet[1]);
free(fs);
}
int burn_fifo_source_shoveller_og(struct burn_source *source, int flag)
{
struct burn_source_fifo *fs = source->data;
int ret;
fs->thread_pid = getpid();
fs->thread_pid_valid = 1;
while (1) {
ret = fs->inp->read(fs->inp, (unsigned char *) fs->buf,
fs->chunksize);
if (ret > 0)
fs->in_counter += ret;
else if (ret == 0)
break; /* EOF */
else {
libdax_msgs_submit(libdax_messenger, -1, 0x00020153,
LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH,
"Read error on fifo input", errno, 0);
break;
}
ret = write(fs->outlet[1], fs->buf, ret);
if (ret == -1) {
/* >>> write error */;
break;
}
}
/* >>> check and destroy ring buffer */;
free(fs->buf);
fs->buf = NULL;
if (fs->outlet[1] >= 0)
close(fs->outlet[1]);
fs->outlet[1] = -1;
return (ret >= 0);
}
#endif /* Libburn_fifo_nG */
/* ts A71003 */
/* ----------------------------- fifo ng ------------------------- */
/* ------------------------------ fifo --------------------------- */
/* The fifo mechanism consists of a burn_source proxy which is here,
a thread management team which is located in async.c,
@ -311,7 +204,7 @@ static int fifo_sleep(int flag)
}
static int fifo_read_ng(struct burn_source *source,
static int fifo_read(struct burn_source *source,
unsigned char *buffer,
int size)
{
@ -341,7 +234,7 @@ static int fifo_read_ng(struct burn_source *source,
/* This needs no mutex because each volatile variable has one thread
which may write and the other which only reads and is aware of
volatility.
The feeder of the ringbuffer is in burn_fifo_source_shoveller_ng().
The feeder of the ringbuffer is in burn_fifo_source_shoveller().
*/
todo = size;
bufsize = fs->chunksize * fs->chunks;
@ -394,7 +287,7 @@ static int fifo_read_ng(struct burn_source *source,
}
static off_t fifo_get_size_ng(struct burn_source *source)
static off_t fifo_get_size(struct burn_source *source)
{
struct burn_source_fifo *fs = source->data;
@ -402,7 +295,7 @@ static off_t fifo_get_size_ng(struct burn_source *source)
}
static int fifo_set_size_ng(struct burn_source *source, off_t size)
static int fifo_set_size(struct burn_source *source, off_t size)
{
struct burn_source_fifo *fs = source->data;
@ -410,7 +303,7 @@ static int fifo_set_size_ng(struct burn_source *source, off_t size)
}
static void fifo_free_ng(struct burn_source *source)
static void fifo_free(struct burn_source *source)
{
struct burn_source_fifo *fs = source->data;
@ -422,7 +315,7 @@ static void fifo_free_ng(struct burn_source *source)
}
int burn_fifo_source_shoveller_ng(struct burn_source *source, int flag)
int burn_fifo_source_shoveller(struct burn_source *source, int flag)
{
struct burn_source_fifo *fs = source->data;
int ret, bufsize, diff, wpos, rpos, trans_end, free_bytes;
@ -469,8 +362,12 @@ int burn_fifo_source_shoveller_ng(struct burn_source *source, int flag)
}
/* Obtain next chunk */
ret = fs->inp->read(fs->inp, (unsigned char *) bufpt,
fs->chunksize);
if (fs->inp->read != NULL)
ret = fs->inp->read(fs->inp,
(unsigned char *) bufpt, fs->chunksize);
else
ret = fs->inp->read_xt( fs->inp,
(unsigned char *) bufpt, fs->chunksize);
if (ret > 0)
fs->in_counter += ret;
else if (ret == 0)
@ -537,15 +434,12 @@ int burn_fifo_source_shoveller_ng(struct burn_source *source, int flag)
}
#define Libburn_fifo_nG 1
int burn_fifo_source_shoveller(struct burn_source *source, int flag)
int burn_fifo_cancel(struct burn_source *source)
{
#ifndef Libburn_fifo_nG
return burn_fifo_source_shoveller_og(source, flag);
#else
return burn_fifo_source_shoveller_ng(source, flag);
#endif
struct burn_source_fifo *fs = source->data;
burn_source_cancel(fs->inp);
return(1);
}
@ -554,9 +448,6 @@ struct burn_source *burn_fifo_source_new(struct burn_source *inp,
{
struct burn_source_fifo *fs;
struct burn_source *src;
#ifndef Libburn_fifo_nG
int ret, outlet[2];
#endif
if (((double) chunksize) * ((double) chunks) > 1024.0*1024.0*1024.0) {
libdax_msgs_submit(libdax_messenger, -1, 0x00020155,
@ -570,16 +461,6 @@ struct burn_source *burn_fifo_source_new(struct burn_source *inp,
"Desired fifo buffer too small", 0, 0);
return NULL;
}
#ifndef Libburn_fifo_nG
outlet[0] = outlet[1] = -1;
ret = pipe(outlet);
if (ret == -1) {
/* >>> error on pipe creation */;
return NULL;
}
#endif /* ! Libburn_fifo_nG */
fs = malloc(sizeof(struct burn_source_fifo));
if (fs == NULL)
return NULL;
@ -587,12 +468,6 @@ struct burn_source *burn_fifo_source_new(struct burn_source *inp,
fs->thread_pid = 0;
fs->thread_pid_valid = 0;
fs->inp = NULL; /* set later */
#ifndef Libburn_fifo_nG
fs->outlet[0] = outlet[0];
fs->outlet[1] = outlet[1];
#endif
fs->chunksize = chunksize;
fs->chunks = chunks;
fs->buf = NULL;
@ -607,23 +482,15 @@ struct burn_source *burn_fifo_source_new(struct burn_source *inp,
free((char *) fs);
return NULL;
}
#ifndef Libburn_fifo_nG
src->read = fifo_read;
src->read = NULL;
src->read_sub = NULL;
src->get_size = fifo_get_size;
src->set_size = fifo_set_size;
src->free_data = fifo_free;
#else /* Libburn_fifo_nG */
src->read = fifo_read_ng;
src->read_sub = NULL;
src->get_size = fifo_get_size_ng;
src->set_size = fifo_set_size_ng;
src->free_data = fifo_free_ng;
#endif /* ! Libburn_fifo_nG */
src->data = fs;
src->version= 1;
src->read_xt = fifo_read;
src->cancel= burn_fifo_cancel;
fs->inp = inp;
inp->refcount++; /* make sure inp lives longer than src */
@ -644,7 +511,7 @@ int burn_fifo_inquire_status(struct burn_source *source,
*status_text = NULL;
*size = 0;
if (source->free_data != fifo_free_ng) {
if (source->free_data != fifo_free) {
libdax_msgs_submit(libdax_messenger, -1, 0x00020157,
LIBDAX_MSGS_SEV_FATAL, LIBDAX_MSGS_PRIO_HIGH,
"burn_source is not a fifo object", 0, 0);
@ -673,4 +540,3 @@ int burn_fifo_inquire_status(struct burn_source *source,
return ret;
}

View File

@ -376,6 +376,11 @@ struct burn_source {
libburn will read a single sector by each call to (*read).
The size of a sector depends on BURN_MODE_*. The known range is
2048 to 2352.
IMPORTANT:
If this function pointer is NULL, then the struct burn_source is of
version >= 1 and the job of .(*read)() is done by .(*read_xt)().
See below, member .version.
*/
int (*read)(struct burn_source *, unsigned char *buffer, int size);
@ -442,6 +447,29 @@ struct burn_source {
*/
void *data;
/* ts A71222 : Supposed to be binary backwards compatible extension. */
/** Valid only if above member .(*read)() is NULL. This indicates a
version of struct burn_source younger than 0.
From then on, member .version tells which further members exist
in the memory layout of struct burn_source. libburn will only touch
those announced extensions.
Versions:
0 has .(*read)() != NULL, not even .version is present.
1 has .version, .(*read_xt)(), .(*cancel)()
*/
int version;
/** This substitutes for (*read)() in versions above 0. */
int (*read_xt)(struct burn_source *, unsigned char *buffer, int size);
/** Informs the burn_source that the consumer of data prematurely
ended reading. This call may or may not be issued by libburn
before (*free_data)() is called.
*/
int (*cancel)(struct burn_source *source);
};

View File

@ -123,7 +123,12 @@ static void get_bytes(struct burn_track *track, int count, unsigned char *data)
/* Next we use source data */
curr = valid;
if (!track->eos) {
valid = track->source->read(track->source, data + curr, count - curr);
if (track->source->read != NULL)
valid = track->source->read(track->source,
data + curr, count - curr);
else
valid = track->source->read_xt(track->source,
data + curr, count - curr);
} else valid = 0;
if (valid <= 0) { /* ts A61031 : extended from (valid == -1) */

View File

@ -18,8 +18,6 @@ void burn_source_free(struct burn_source *src)
enum burn_source_status burn_track_set_source(struct burn_track *t,
struct burn_source *s)
{
if (!s->read)
return BURN_SOURCE_FAILED;
s->refcount++;
t->source = s;
@ -43,3 +41,15 @@ struct burn_source *burn_source_new(void)
out->refcount = 1;
return out;
}
/* ts A71223 */
int burn_source_cancel(struct burn_source *src)
{
if(src->read == NULL)
if(src->version > 0)
if(src->cancel != NULL)
src->cancel(src);
return 1;
}

View File

@ -5,4 +5,6 @@
struct burn_source *burn_source_new(void);
int burn_source_cancel(struct burn_source *src);
#endif /*__SOURCE*/

View File

@ -43,6 +43,7 @@
#include "write.h"
#include "options.h"
#include "structure.h"
#include "source.h"
#include "libdax_msgs.h"
extern struct libdax_msgs *libdax_messenger;
@ -836,6 +837,8 @@ int burn_write_track(struct burn_write_opts *o, struct burn_session *s,
/* ts A61103 */
ret = 1;
ex:;
if (d->cancel)
burn_source_cancel(t->source);
if (o->write_type == BURN_WRITE_TAO) {
/* ts A71002 */
@ -1273,6 +1276,8 @@ int burn_dvd_write_track(struct burn_write_opts *o,
}
ret = 1;
ex:;
if (d->cancel)
burn_source_cancel(t->source);
if (!is_flushed)
d->sync_cache(d); /* burn_write_flush() was not called */
return ret;
@ -1693,7 +1698,11 @@ int burn_stdio_read_source(struct burn_source *source, char *buf, int bufsize,
int count= 0, todo;
for(todo = bufsize; todo > 0; todo -= count) {
count = source->read(source,
if(source->read!=NULL)
count = source->read(source,
(unsigned char *) (buf + (bufsize - todo)), todo);
else
count = source->read_xt(source,
(unsigned char *) (buf + (bufsize - todo)), todo);
if (count <= 0)
break;
@ -1718,16 +1727,6 @@ int burn_stdio_write(int fd, char *buf, int count, struct burn_drive *d,
}
/* ts A70911
If defined this makes stdio run on top of sector_data() rather than
own stdio read and write functions. The MMC function pointers d->write()
and d->sync_cache() get replaced by stdio substitutes.
*/
#define Libburn_stdio_track_by_sector_datA 1
#ifdef Libburn_stdio_track_by_sector_datA
/* ts A70910 : to be used as burn_drive.write(), emulating mmc_write() */
int burn_stdio_mmc_write(struct burn_drive *d, int start, struct buffer *buf)
{
@ -1849,9 +1848,6 @@ int burn_stdio_slowdown(struct burn_drive *d, struct timeval *prev_time,
}
#endif /* Libburn_stdio_track_by_sector_datA */
/* ts A70904 */
int burn_stdio_write_track(struct burn_write_opts *o, struct burn_session *s,
int tnum, int flag)
@ -1860,14 +1856,9 @@ int burn_stdio_write_track(struct burn_write_opts *o, struct burn_session *s,
struct burn_track *t = s->track[tnum];
struct burn_drive *d = o->drive;
char buf[16*2048];
#ifdef Libburn_stdio_track_by_sector_datA
int i, prev_sync_sector = 0;
struct buffer *out = d->buffer;
struct timeval prev_time;
#else
int eof_seen = 0;
off_t t_size, w_count;
#endif
bufsize = sizeof(buf);
fd = d->stdio_fd;
@ -1876,8 +1867,6 @@ int burn_stdio_write_track(struct burn_write_opts *o, struct burn_session *s,
burn_disc_init_track_status(o, s, tnum, sectors);
open_ended = burn_track_is_open_ended(t);
#ifdef Libburn_stdio_track_by_sector_datA
/* attach stdio emulators for mmc_*() functions */
if (o->simulate)
d->write = burn_stdio_mmc_dummy_write;
@ -1889,7 +1878,7 @@ int burn_stdio_write_track(struct burn_write_opts *o, struct burn_session *s,
for (i = 0; open_ended || i < sectors; i++) {
/* transact a (CD sized) sector */
if (!sector_data(o, t, 0))
return 0;
{ret= 0; goto ex;}
if (open_ended) {
d->progress.sectors = sectors = d->progress.sector;
if (burn_track_is_data_done(t))
@ -1912,60 +1901,11 @@ int burn_stdio_write_track(struct burn_write_opts *o, struct burn_session *s,
out->bytes = o->obs;
}
ret = burn_write_flush(o, t);
#else /* Libburn_stdio_track_by_sector_datA */
t_size = t->source->get_size(t->source);
/* >>> write t->offset zeros */;
for(w_count = 0; w_count < t_size || open_ended; w_count += ret) {
if (t_size - w_count < bufsize && ! open_ended)
/* >>> what about final sector padding ? */
bufsize = t_size - w_count;
if (eof_seen)
ret = 0;
else
ret = burn_stdio_read_source(t->source, buf,
bufsize, o, 0);
if (ret < 0)
return ret;
if (ret == 0 && open_ended)
break;
if (ret < bufsize && !open_ended) {
memset(buf + ret, 0, bufsize - ret);
eof_seen = 1;
ret = bufsize;
}
t->sourcecount += ret;
if (!o->simulate)
ret = burn_stdio_write(fd, buf, ret, d, 0);
if (ret <= 0)
return ret;
d->progress.sector = (w_count + (off_t) ret) / (off_t) 2048;
if (open_ended)
d->progress.sectors = d->progress.sector;
t->writecount += ret;
t->written_sectors = t->writecount / 2048;
/* Flush to physical device after each full MB */
if (d->progress.sector - prev_sync_sector >= 512) {
prev_sync_sector = d->progress.sector;
if (!o->simulate)
burn_stdio_sync_cache(fd, d, 1);
}
}
/* >>> write t->tail zeros */;
#endif
return 1;
ret= 1;
ex:;
if (d->cancel)
burn_source_cancel(t->source);
return ret;
}