diff --git a/src/core/downloader.c b/src/core/downloader.c index 2f28bc95..15ef962d 100644 --- a/src/core/downloader.c +++ b/src/core/downloader.c @@ -114,19 +114,6 @@ static int downloader_ensure_size ( struct downloader *downloader, * */ -/** - * Handle start() event received via job control interface - * - * @v job Downloader job control interface - */ -static void downloader_job_start ( struct job_interface *job ) { - struct downloader *downloader = - container_of ( job, struct downloader, job ); - - /* Start data transfer */ - xfer_request_all ( &downloader->xfer ); -} - /** * Handle kill() event received via job control interface * @@ -142,7 +129,7 @@ static void downloader_job_kill ( struct job_interface *job ) { /** Downloader job control interface operations */ static struct job_interface_operations downloader_job_operations = { - .start = downloader_job_start, + .start = ignore_job_start, .done = ignore_job_done, .kill = downloader_job_kill, .progress = ignore_job_progress, diff --git a/src/core/hw.c b/src/core/hw.c index 77b39ba1..a3eb8500 100644 --- a/src/core/hw.c +++ b/src/core/hw.c @@ -3,6 +3,7 @@ #include #include #include +#include #include #include @@ -15,6 +16,7 @@ struct hw { struct refcnt refcnt; struct xfer_interface xfer; + struct process process; }; static const char hw_msg[] = "Hello world!\n"; @@ -22,6 +24,7 @@ static const char hw_msg[] = "Hello world!\n"; static void hw_finished ( struct hw *hw, int rc ) { xfer_nullify ( &hw->xfer ); xfer_close ( &hw->xfer, rc ); + process_del ( &hw->process ); } static void hw_xfer_close ( struct xfer_interface *xfer, int rc ) { @@ -30,26 +33,25 @@ static void hw_xfer_close ( struct xfer_interface *xfer, int rc ) { hw_finished ( hw, rc ); } -static int hw_xfer_request ( struct xfer_interface *xfer, - off_t start __unused, int whence __unused, - size_t len __unused ) { - struct hw *hw = container_of ( xfer, struct hw, xfer ); - int rc; - - rc = xfer_deliver_raw ( xfer, hw_msg, sizeof ( hw_msg ) ); - hw_finished ( hw, rc ); - return 0; -} - static struct xfer_interface_operations hw_xfer_operations = { .close = hw_xfer_close, .vredirect = ignore_xfer_vredirect, - .request = hw_xfer_request, + .request = ignore_xfer_request, .seek = ignore_xfer_seek, .deliver_iob = xfer_deliver_as_raw, .deliver_raw = ignore_xfer_deliver_raw, }; +static void hw_step ( struct process *process ) { + struct hw *hw = container_of ( process, struct hw, process ); + int rc; + + if ( xfer_ready ( &hw->xfer ) == 0 ) { + rc = xfer_deliver_raw ( &hw->xfer, hw_msg, sizeof ( hw_msg ) ); + hw_finished ( hw, rc ); + } +} + static int hw_open ( struct xfer_interface *xfer, struct uri *uri __unused ) { struct hw *hw; @@ -59,6 +61,7 @@ static int hw_open ( struct xfer_interface *xfer, struct uri *uri __unused ) { return -ENOMEM; memset ( hw, 0, sizeof ( *hw ) ); xfer_init ( &hw->xfer, &hw_xfer_operations, &hw->refcnt ); + process_init ( &hw->process, hw_step, &hw->refcnt ); /* Attach parent interface, mortalise self, and return */ xfer_plug_plug ( &hw->xfer, xfer ); diff --git a/src/core/posix_io.c b/src/core/posix_io.c index 6cefbf7b..3b5660e4 100644 --- a/src/core/posix_io.c +++ b/src/core/posix_io.c @@ -191,6 +191,7 @@ static int posix_find_free_fd ( void ) { if ( ! posix_fd_to_file ( fd ) ) return fd; } + DBG ( "POSIX could not find free file descriptor\n" ); return -ENFILE; } @@ -226,13 +227,11 @@ int open ( const char *uri_string ) { if ( ( rc = xfer_open_uri ( &file->xfer, uri_string ) ) != 0 ) goto err; - /* Request data */ - if ( ( rc = xfer_request_all ( &file->xfer ) ) != 0 ) - goto err; - /* Wait for open to succeed or fail */ while ( list_empty ( &file->data ) ) { step(); + if ( file->rc == 0 ) + break; if ( file->rc != -EINPROGRESS ) { rc = file->rc; goto err; @@ -241,6 +240,7 @@ int open ( const char *uri_string ) { /* Add to list of open files. List takes reference ownership. */ list_add ( &file->list, &posix_files ); + DBG ( "POSIX opened %s as file %d\n", uri_string, fd ); return fd; err: diff --git a/src/core/xfer.c b/src/core/xfer.c index f2783f5b..54377c70 100644 --- a/src/core/xfer.c +++ b/src/core/xfer.c @@ -35,6 +35,8 @@ void xfer_close ( struct xfer_interface *xfer, int rc ) { struct xfer_interface *dest = xfer_get_dest ( xfer ); + DBGC ( xfer, "XFER %p->%p close\n", xfer, dest ); + dest->op->close ( dest, rc ); xfer_unplug ( xfer ); xfer_put ( dest ); @@ -52,7 +54,14 @@ int xfer_vredirect ( struct xfer_interface *xfer, int type, va_list args ) { struct xfer_interface *dest = xfer_get_dest ( xfer ); int rc; + DBGC ( xfer, "XFER %p->%p redirect\n", xfer, dest ); + rc = dest->op->vredirect ( dest, type, args ); + + if ( rc != 0 ) { + DBGC ( xfer, "XFER %p<-%p redirect: %s\n", xfer, dest, + strerror ( rc ) ); + } xfer_put ( dest ); return rc; } @@ -89,21 +98,19 @@ int xfer_request ( struct xfer_interface *xfer, off_t offset, int whence, struct xfer_interface *dest = xfer_get_dest ( xfer ); int rc; + DBGC ( xfer, "XFER %p->%p request %s+%ld %zd\n", xfer, dest, + whence_text ( whence ), offset, len ); + rc = dest->op->request ( dest, offset, whence, len ); + + if ( rc != 0 ) { + DBGC ( xfer, "XFER %p<-%p request: %s\n", xfer, dest, + strerror ( rc ) ); + } xfer_put ( dest ); return rc; } -/** - * Request all data - * - * @v xfer Data transfer interface - * @ret rc Return status code - */ -int xfer_request_all ( struct xfer_interface *xfer ) { - return xfer_request ( xfer, 0, SEEK_SET, ~( ( size_t ) 0 ) ); -} - /** * Seek to position * @@ -116,11 +123,33 @@ int xfer_seek ( struct xfer_interface *xfer, off_t offset, int whence ) { struct xfer_interface *dest = xfer_get_dest ( xfer ); int rc; + DBGC ( xfer, "XFER %p->%p seek %s+%ld\n", xfer, dest, + whence_text ( whence ), offset ); + rc = dest->op->seek ( dest, offset, whence ); + + if ( rc != 0 ) { + DBGC ( xfer, "XFER %p<-%p seek: %s\n", xfer, dest, + strerror ( rc ) ); + } xfer_put ( dest ); return rc; } +/** + * Test to see if interface is ready to accept data + * + * @v xfer Data transfer interface + * @ret rc Return status code + * + * This test is optional; the data transfer interface may wish that it + * does not yet wish to accept data, but cannot prevent attempts to + * deliver data to it. + */ +int xfer_ready ( struct xfer_interface *xfer ) { + return xfer_seek ( xfer, 0, SEEK_CUR ); +} + /** * Allocate I/O buffer * @@ -132,7 +161,13 @@ struct io_buffer * xfer_alloc_iob ( struct xfer_interface *xfer, size_t len ) { struct xfer_interface *dest = xfer_get_dest ( xfer ); struct io_buffer *iobuf; + DBGC ( xfer, "XFER %p->%p alloc_iob %zd\n", xfer, dest, len ); + iobuf = dest->op->alloc_iob ( dest, len ); + + if ( ! iobuf ) { + DBGC ( xfer, "XFER %p<-%p alloc_iob failed\n", xfer, dest ); + } xfer_put ( dest ); return iobuf; } @@ -148,7 +183,15 @@ int xfer_deliver_iob ( struct xfer_interface *xfer, struct io_buffer *iobuf ) { struct xfer_interface *dest = xfer_get_dest ( xfer ); int rc; + DBGC ( xfer, "XFER %p->%p deliver_iob %zd\n", xfer, dest, + iob_len ( iobuf ) ); + rc = dest->op->deliver_iob ( dest, iobuf ); + + if ( rc != 0 ) { + DBGC ( xfer, "XFER %p<-%p deliver_iob: %s\n", xfer, dest, + strerror ( rc ) ); + } xfer_put ( dest ); return rc; } @@ -165,7 +208,15 @@ int xfer_deliver_raw ( struct xfer_interface *xfer, struct xfer_interface *dest = xfer_get_dest ( xfer ); int rc; + DBGC ( xfer, "XFER %p->%p deliver_raw %p+%zd\n", xfer, dest, + data, len ); + rc = dest->op->deliver_raw ( dest, data, len ); + + if ( rc != 0 ) { + DBGC ( xfer, "XFER %p<-%p deliver_raw: %s\n", xfer, dest, + strerror ( rc ) ); + } xfer_put ( dest ); return rc; } diff --git a/src/include/gpxe/xfer.h b/src/include/gpxe/xfer.h index 71b69dc5..e6c896c3 100644 --- a/src/include/gpxe/xfer.h +++ b/src/include/gpxe/xfer.h @@ -112,6 +112,20 @@ enum seek_whence { SEEK_CUR, }; +/** + * Describe seek basis + * + * @v whence Basis for new position + */ +static inline __attribute__ (( always_inline )) const char * +whence_text ( int whence ) { + switch ( whence ) { + case SEEK_SET: return "SET"; + case SEEK_CUR: return "CUR"; + default: return "INVALID"; + } +} + extern struct xfer_interface null_xfer; extern struct xfer_interface_operations null_xfer_ops; @@ -121,8 +135,8 @@ extern int xfer_vredirect ( struct xfer_interface *xfer, int type, extern int xfer_redirect ( struct xfer_interface *xfer, int type, ... ); extern int xfer_request ( struct xfer_interface *xfer, off_t offset, int whence, size_t len ); -extern int xfer_request_all ( struct xfer_interface *xfer ); extern int xfer_seek ( struct xfer_interface *xfer, off_t offset, int whence ); +extern int xfer_ready ( struct xfer_interface *xfer ); extern struct io_buffer * xfer_alloc_iob ( struct xfer_interface *xfer, size_t len ); extern int xfer_deliver_iob ( struct xfer_interface *xfer,