On Sat, Jun 18, 2011 at 07:37, <gst...@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