On Sat, Jun 18, 2011 at 07:37, <gstein_at_apache.org> wrote:
> Author: gstein
> Date: Sat Jun 18 03:37:34 2011
> New Revision: 1137120
>
> URL: http://svn.apache.org/viewvc?rev=1137120&view=rev
> Log:
> Continued work on the XML parser pausing and processing. In particular,
> this revision enables reading from the "spill" file, and injects that
> content into the XML parser.
>
[...]
> ==============================================================================
> --- subversion/trunk/subversion/libsvn_ra_serf/util.c (original)
> +++ subversion/trunk/subversion/libsvn_ra_serf/util.c Sat Jun 18 03:37:34 2011
> @@ -1215,6 +1215,32 @@ add_done_item(svn_ra_serf__xml_parser_t
> }
>
>
[...]
> @@ -1325,27 +1343,38 @@ svn_error_t *
> svn_ra_serf__process_pending(svn_ra_serf__xml_parser_t *parser,
> apr_pool_t *scratch_pool)
> {
> + struct pending_buffer_t *pb;
> + svn_error_t *err;
> + apr_off_t output_unused;
> +
> /* Fast path exit: already paused, or nothing to do. */
> if (parser->paused || parser->pending == NULL)
> return SVN_NO_ERROR;
>
> + /* ### it is possible that the XML parsing of the pending content is
> + ### so slow, and that we don't return to reading the connection
> + ### fast enough... that the server will disconnect us. right now,
> + ### that is highly improbably, but is noted for future's sake.
> + ### should that ever happen, the loops in this function can simply
> + ### terminate after N seconds. */
> +
> /* Empty out memory buffers until we run out, or we get paused again. */
> while (parser->pending->head != NULL)
> {
> - struct pending_buffer_t *pb = parser->pending->head;
> - svn_error_t *err;
> -
> + /* Pull the HEAD buffer out of the list. */
> + pb = parser->pending->head;
> if (parser->pending->tail == pb)
> parser->pending->head = parser->pending->tail = NULL;
> else
> parser->pending->head = pb->next;
> +
> + /* We're using less memory now. If we haven't hit the spill file,
> + then we may be able to keep using memory. */
> parser->pending->memory_size -= pb->size;
>
> err = inject_to_parser(parser, pb->data, pb->size, NULL);
>
> - /* Return the block to the "available" list. */
> - pb->next = parser->pending->avail;
> - parser->pending->avail = pb;
> + return_buffer(parser, pb);
>
> if (err)
> return svn_error_return(err);
> @@ -1360,9 +1389,43 @@ svn_ra_serf__process_pending(svn_ra_serf
> if (parser->pending->spill == NULL)
> return SVN_NO_ERROR;
>
> - /* ### read the spill file... */
> + /* Seek once to where we left off reading. */
> + output_unused = parser->pending->spill_start; /* ### stupid API */
> + SVN_ERR(svn_io_file_seek(parser->pending->spill,
> + APR_SET, &output_unused,
> + scratch_pool));
> +
> + /* We need a buffer for reading out of the file. One of these will always
> + exist by the time we start reading from the spill file. */
> + pb = get_buffer(parser);
> +
> + /* Keep reading until we hit EOF, or get paused again. */
> + while (TRUE)
> + {
> + apr_size_t len = sizeof(pb->data);
> + apr_status_t status;
> +
> + /* Read some data and remember where we left off. */
> + status = apr_file_read(parser->pending->spill, pb->data, &len);
> + if (status && !APR_STATUS_IS_EOF(status))
> + {
> + err = svn_error_wrap_apr(status, NULL);
> + break;
> + }
> + parser->pending->spill_start += len;
>
> - return SVN_NO_ERROR;
> + err = inject_to_parser(parser, pb->data, len, NULL);
> + if (err)
> + break;
> +
> + /* If there is no more content (for now), or the callbacks paused
> + the parsing, then we're done. */
> + if (APR_STATUS_IS_EOF(status) || parser->paused)
> + break;
> + }
> +
You have to seek to the end after injecting parser in you paused (or
on error) since write_pending assumes that file position is at the end
of file.
--
Ivan Zhakov
Received on 2011-06-21 00:50:39 CEST