Author: philip Date: Tue Apr 23 13:04:42 2013 New Revision: 1470936 URL: http://svn.apache.org/r1470936 Log: Significantly reduce the number of open files during a typical update over ra_serf by using lazy-opening streams to delay opening until the HTTP response is received. This changes the new-in-1.8 lazy-open API.
* subversion/include/svn_io.h (svn_stream_lazyopen_create): Add open_on_close boolean parameter. * subversion/libsvn_subr/stream.c (struct lazyopen_baton_t): Add open_on_close boolean member. (close_handler_lazyopen): Open if required. (svn_stream_lazyopen_create): Add open_on_close boolean parameter. * subversion/libsvn_wc/update_editor.c (lazy_open_source, lazy_open_target, struct lazy_target_baton): New. (apply_textdelta): Use lazy-open streams for source and target. * subversion/libsvn_wc/adm_ops.c (svn_wc__get_pristine_contents_by_checksum): Adjust call. Modified: subversion/trunk/subversion/include/svn_io.h subversion/trunk/subversion/libsvn_subr/stream.c subversion/trunk/subversion/libsvn_wc/adm_ops.c subversion/trunk/subversion/libsvn_wc/update_editor.c Modified: subversion/trunk/subversion/include/svn_io.h URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/include/svn_io.h?rev=1470936&r1=1470935&r2=1470936&view=diff ============================================================================== --- subversion/trunk/subversion/include/svn_io.h (original) +++ subversion/trunk/subversion/include/svn_io.h Tue Apr 23 13:04:42 2013 @@ -1387,14 +1387,15 @@ typedef svn_error_t * * invoked upon the first read of @a *stream which are used to open the * "real" source stream. * - * @note If the only "access" the returned stream gets is to close it, - * @a open_func will not be called. + * @note If the only "access" the returned stream gets is to close it + * then @a open_func will only be called if @a open_on_close is TRUE. * * @since New in 1.8. */ svn_stream_t * svn_stream_lazyopen_create(svn_stream_lazyopen_func_t open_func, void *open_baton, + svn_boolean_t open_on_close, apr_pool_t *result_pool); /** @} */ Modified: subversion/trunk/subversion/libsvn_subr/stream.c URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_subr/stream.c?rev=1470936&r1=1470935&r2=1470936&view=diff ============================================================================== --- subversion/trunk/subversion/libsvn_subr/stream.c (original) +++ subversion/trunk/subversion/libsvn_subr/stream.c Tue Apr 23 13:04:42 2013 @@ -1676,6 +1676,9 @@ typedef struct lazyopen_baton_t { svn_stream_t *real_stream; apr_pool_t *pool; + /* Whether to open the wrapped stream on a close call. */ + svn_boolean_t open_on_close; + } lazyopen_baton_t; @@ -1747,7 +1750,9 @@ close_handler_lazyopen(void *baton) { lazyopen_baton_t *b = baton; - if (b->real_stream != NULL) + if (b->open_on_close) + SVN_ERR(lazyopen_if_unopened(b)); + if (b->real_stream) SVN_ERR(svn_stream_close(b->real_stream)); return SVN_NO_ERROR; @@ -1796,6 +1801,7 @@ is_buffered_lazyopen(void *baton) svn_stream_t * svn_stream_lazyopen_create(svn_stream_lazyopen_func_t open_func, void *open_baton, + svn_boolean_t open_on_close, apr_pool_t *result_pool) { lazyopen_baton_t *lob = apr_pcalloc(result_pool, sizeof(*lob)); @@ -1805,6 +1811,7 @@ svn_stream_lazyopen_create(svn_stream_la lob->open_baton = open_baton; lob->real_stream = NULL; lob->pool = result_pool; + lob->open_on_close = open_on_close; stream = svn_stream_create(lob, result_pool); svn_stream_set_read(stream, read_handler_lazyopen); Modified: subversion/trunk/subversion/libsvn_wc/adm_ops.c URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_wc/adm_ops.c?rev=1470936&r1=1470935&r2=1470936&view=diff ============================================================================== --- subversion/trunk/subversion/libsvn_wc/adm_ops.c (original) +++ subversion/trunk/subversion/libsvn_wc/adm_ops.c Tue Apr 23 13:04:42 2013 @@ -1155,7 +1155,7 @@ svn_wc__get_pristine_contents_by_checksu gpl_baton->checksum = checksum; *contents = svn_stream_lazyopen_create(get_pristine_lazyopen_func, - gpl_baton, result_pool); + gpl_baton, FALSE, result_pool); } return SVN_NO_ERROR; Modified: subversion/trunk/subversion/libsvn_wc/update_editor.c URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_wc/update_editor.c?rev=1470936&r1=1470935&r2=1470936&view=diff ============================================================================== --- subversion/trunk/subversion/libsvn_wc/update_editor.c (original) +++ subversion/trunk/subversion/libsvn_wc/update_editor.c Tue Apr 23 13:04:42 2013 @@ -3525,6 +3525,46 @@ open_file(const char *path, return SVN_NO_ERROR; } +static svn_error_t * +lazy_open_source(svn_stream_t **stream, + void *baton, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool) +{ + struct file_baton *fb = baton; + + SVN_ERR(svn_wc__db_pristine_read(stream, NULL, fb->edit_baton->db, + fb->local_abspath, + fb->original_checksum, + result_pool, scratch_pool)); + + + return SVN_NO_ERROR; +} + +struct lazy_target_baton { + struct file_baton *fb; + struct handler_baton *hb; + struct edit_baton *eb; +}; + +static svn_error_t * +lazy_open_target(svn_stream_t **stream, + void *baton, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool) +{ + struct lazy_target_baton *tb = baton; + + SVN_ERR(svn_wc__open_writable_base(stream, &tb->hb->new_text_base_tmp_abspath, + NULL, &tb->hb->new_text_base_sha1_checksum, + tb->fb->edit_baton->db, + tb->eb->wcroot_abspath, + result_pool, scratch_pool)); + + return SVN_NO_ERROR; +} + /* An svn_delta_editor_t function. */ static svn_error_t * apply_textdelta(void *file_baton, @@ -3537,10 +3577,10 @@ apply_textdelta(void *file_baton, apr_pool_t *handler_pool = svn_pool_create(fb->pool); struct handler_baton *hb = apr_pcalloc(handler_pool, sizeof(*hb)); struct edit_baton *eb = fb->edit_baton; - svn_error_t *err; const svn_checksum_t *recorded_base_checksum; svn_checksum_t *expected_base_checksum; svn_stream_t *source; + struct lazy_target_baton *tb; svn_stream_t *target; if (fb->skip_this) @@ -3607,10 +3647,8 @@ apply_textdelta(void *file_baton, SVN_ERR_ASSERT(!fb->original_checksum || fb->original_checksum->kind == svn_checksum_sha1); - SVN_ERR(svn_wc__db_pristine_read(&source, NULL, fb->edit_baton->db, - fb->local_abspath, - fb->original_checksum, - handler_pool, handler_pool)); + source = svn_stream_lazyopen_create(lazy_open_source, fb, FALSE, + handler_pool); } else { @@ -3636,16 +3674,11 @@ apply_textdelta(void *file_baton, hb->source_checksum_stream = source; } - /* Open the text base for writing (this will get us a temporary file). */ - err = svn_wc__open_writable_base(&target, &hb->new_text_base_tmp_abspath, - NULL, &hb->new_text_base_sha1_checksum, - fb->edit_baton->db, eb->wcroot_abspath, - handler_pool, pool); - if (err) - { - svn_pool_destroy(handler_pool); - return svn_error_trace(err); - } + tb = apr_palloc(handler_pool, sizeof(struct lazy_target_baton)); + tb->hb = hb; + tb->fb = fb; + tb->eb = eb; + target = svn_stream_lazyopen_create(lazy_open_target, tb, TRUE, handler_pool); /* Prepare to apply the delta. */ svn_txdelta_apply(source, target,