[svn.haxx.se] · SVN Dev · SVN Users · SVN Org · TSVN Dev · TSVN Users · Subclipse Dev · Subclipse Users · this month's index

Re: svn commit: r15948 - in trunk/subversion: libsvn_client libsvn_ra libsvn_ra_dav libsvn_ra_local libsvn_ra_svn

From: Stefan Küng <tortoisesvn_at_gmail.com>
Date: 2005-08-29 20:08:13 CEST

Patch with fixes for what Peter commented on is attached.

The patch also contains an implementation for progress notifications for
the ra_svn protocol. It doesn't provide a 'total' for now, but it
notifies about bytes sent/received. Maybe someone more familiar with
ra_svn can give me some pointers on where/how to set the total amount of
bytes to transfer? If there's no good way to do that, then this patch
should be enough for GUI clients to at least show the user information
like "YYY bytes transferred, currently with XXX bytes/s" (ok, lame
sentence, but you get the idea).

Stefan

-- 
        ___
   oo  // \\      "De Chelonian Mobile"
  (_,\/ \_/ \     TortoiseSVN
    \ \_/_\_/>    The coolest Interface to (Sub)Version Control
    /_/   \_\     http://tortoisesvn.tigris.org

[[[
Fix stack bug, improve the progress notification callback feature and
add progress notification for ra_svn. This is for issue #901.

Patch by: Stefan Küng <tortoisesvn@gmail.com>

* subversion/include/svn_ra.h
  (svn_ra_progress_notify_func_t): Callback function now takes an
  additional apr_pool_t.
  (svn_ra_create_callbacks): New function to create and initialize the
  svn_ra_callbacks2_t object for compatibility with future versions.
  (svn_ra_callbacks2_t): Add comment about svn_ra_create_callbacks.
  (svn_ra_callbacks_t): Change comment.
* subversion/libsvn_ra/ra_loader.c
  (svn_ra_create_callbacks): New function to create and initialize
  the svn_ra_callbacks2_t object.
  (svn_ra_open): Use the new svn_ra_create_callbacks().
* subversion/libsvn_ra/wrapper_template.h (compat_open):
  Use the new svn_ra_create_callbacks() function.
* subversion/libsvn_ra_dav/session.c
  (neon_progress_baton_t): New struct to pass to the neon callback.
  (ra_dav_neonprogress): Pass the new apr_pool_t param to the progress
  callback.
  (svn_ra_dav__open): Use the new neon_progress_baton_t struct to pass
  to the neon callback function.
* subversion/libsvn_ra_svn/client.c (ra_svn_open): Initialize the
  progress callback function for svn connections.
* subversion/libsvn_ra_svn/marshal.c
  (writebuf_output): call the progress notification callback.
  (readbuf_input): Take an additional pool param and call the progress
  notification callback.
  (readbuff_fill, readbuf_read, readbuf_skip_leading_garbage,
  svn_ra_svn_skip_leading_garbage):
  Pass an additional pool param to readbuf_input.
* subversion/libsvn_ra_svn/ra_svn.h: include svn_ra.h explicitely
  (svn_ra_svn_conn_st): Add params for the progress notifications to
  the struct.
]]]
Index: subversion/libsvn_ra/wrapper_template.h
===================================================================
--- subversion/libsvn_ra/wrapper_template.h (Revision 15964)
+++ subversion/libsvn_ra/wrapper_template.h (Arbeitskopie)
@@ -45,20 +45,21 @@
                                  apr_pool_t *pool)
 {
   svn_ra_session_t *sess = apr_pcalloc (pool, sizeof (svn_ra_session_t));
- svn_ra_callbacks2_t callbacks2;
   sess->vtable = &VTBL;
   sess->pool = pool;
+ svn_ra_callbacks2_t *callbacks2;
+ SVN_ERR (svn_ra_create_callbacks (callbacks2, pool));
 
- callbacks2.open_tmp_file = callbacks->open_tmp_file;
- callbacks2.auth_baton = callbacks->auth_baton;
- callbacks2.get_wc_prop = callbacks->get_wc_prop;
- callbacks2.set_wc_prop = callbacks->set_wc_prop;
- callbacks2.push_wc_prop = callbacks->push_wc_prop;
- callbacks2.invalidate_wc_props = callbacks->invalidate_wc_props;
- callbacks2.progress_func = NULL;
- callbacks2.progress_baton = NULL;
+ callbacks2->open_tmp_file = callbacks->open_tmp_file;
+ callbacks2->auth_baton = callbacks->auth_baton;
+ callbacks2->get_wc_prop = callbacks->get_wc_prop;
+ callbacks2->set_wc_prop = callbacks->set_wc_prop;
+ callbacks2->push_wc_prop = callbacks->push_wc_prop;
+ callbacks2->invalidate_wc_props = callbacks->invalidate_wc_props;
+ callbacks2->progress_func = NULL;
+ callbacks2->progress_baton = NULL;
 
- SVN_ERR (VTBL.open (sess, repos_URL, &callbacks2, callback_baton,
+ SVN_ERR (VTBL.open (sess, repos_URL, callbacks2, callback_baton,
                       config, pool));
   *session_baton = sess;
   return SVN_NO_ERROR;
Index: subversion/libsvn_ra/ra_loader.c
===================================================================
--- subversion/libsvn_ra/ra_loader.c (Revision 15964)
+++ subversion/libsvn_ra/ra_loader.c (Arbeitskopie)
@@ -230,6 +230,14 @@
   return SVN_NO_ERROR;
 }
 
+svn_error_t *
+svn_ra_create_callbacks (svn_ra_callbacks2_t **callbacks,
+ apr_pool_t *pool)
+{
+ *callbacks = apr_pcalloc (pool, sizeof (svn_ra_callbacks2_t));
+ return SVN_NO_ERROR;
+}
+
 svn_error_t *svn_ra_open2 (svn_ra_session_t **session_p,
                            const char *repos_URL,
                            const svn_ra_callbacks2_t *callbacks,
@@ -290,17 +298,18 @@
 {
   /* Deprecated function. Copy the contents of the svn_ra_callbacks_t
      to a new svn_ra_callbacks2_t and call svn_ra_open2(). */
- svn_ra_callbacks2_t callbacks2;
- callbacks2.open_tmp_file = callbacks->open_tmp_file;
- callbacks2.auth_baton = callbacks->auth_baton;
- callbacks2.get_wc_prop = callbacks->get_wc_prop;
- callbacks2.set_wc_prop = callbacks->set_wc_prop;
- callbacks2.push_wc_prop = callbacks->push_wc_prop;
- callbacks2.invalidate_wc_props = callbacks->invalidate_wc_props;
- callbacks2.progress_func = NULL;
- callbacks2.progress_baton = NULL;
+ svn_ra_callbacks2_t *callbacks2;
+ SVN_ERR (svn_ra_create_callbacks (callbacks2, pool));
+ callbacks2->open_tmp_file = callbacks->open_tmp_file;
+ callbacks2->auth_baton = callbacks->auth_baton;
+ callbacks2->get_wc_prop = callbacks->get_wc_prop;
+ callbacks2->set_wc_prop = callbacks->set_wc_prop;
+ callbacks2->push_wc_prop = callbacks->push_wc_prop;
+ callbacks2->invalidate_wc_props = callbacks->invalidate_wc_props;
+ callbacks2->progress_func = NULL;
+ callbacks2->progress_baton = NULL;
   return svn_ra_open2 (session_p, repos_URL,
- &callbacks2, callback_baton,
+ callbacks2, callback_baton,
                        config, pool);
 }
 
Index: subversion/include/svn_ra.h
===================================================================
--- subversion/include/svn_ra.h (Revision 15964)
+++ subversion/include/svn_ra.h (Arbeitskopie)
@@ -180,7 +180,8 @@
  */
 typedef void (*svn_ra_progress_notify_func_t) (apr_off_t progress,
                                                apr_off_t total,
- void * baton);
+ apr_pool_t *pool,
+ void *baton);
 
 
 /**
@@ -322,6 +323,10 @@
  * Each routine takes a @a callback_baton originally provided with the
  * vtable.
  *
+ * In order to avoid backward compatibility problems, clients should use
+ * svn_ra_create_callbacks() to allocate and initialize this structure
+ * instead of doing so themselves.
+ *
  * @since New in 1.3.
  */
 typedef struct svn_ra_callbacks2_t
@@ -371,52 +376,25 @@
   void *progress_baton;
 } svn_ra_callbacks2_t;
 
-/** A collection of callbacks implemented by libsvn_client which allows
- * an RA layer to "pull" information from the client application, or
- * possibly store information. libsvn_client passes this vtable to
- * @c RA->open().
+/** Similar to svn_ra_callbacks2_t, except that the progress
+ * notification function and baton is missing.
  *
- * Each routine takes a @a callback_baton originally provided with the
- * vtable.
- *
  * @deprecated Provided for backward compatibility with the 1.2 API.
  */
 typedef struct svn_ra_callbacks_t
 {
- /** Open a unique temporary file for writing in the working copy.
- * This file will be automatically deleted when @a fp is closed.
- */
   svn_error_t *(*open_tmp_file) (apr_file_t **fp,
                                  void *callback_baton,
                                  apr_pool_t *pool);
   
- /** An authentication baton, created by the application, which is
- * capable of retrieving all known types of credentials.
- */
   svn_auth_baton_t *auth_baton;
 
- /*** The following items may be set to NULL to disallow the RA layer
- to perform the respective operations of the vtable functions.
- Perhaps WC props are not defined or are in invalid for this
- session, or perhaps the commit operation this RA session will
- perform is a server-side only one that shouldn't do post-commit
- processing on a working copy path. ***/
-
- /** Fetch working copy properties.
- *
- *<pre> ### we might have a problem if the RA layer ever wants a property
- * ### that corresponds to a different revision of the file than
- * ### what is in the WC. we'll cross that bridge one day...</pre>
- */
   svn_ra_get_wc_prop_func_t get_wc_prop;
 
- /** Immediately set new values for working copy properties. */
   svn_ra_set_wc_prop_func_t set_wc_prop;
 
- /** Schedule new values for working copy properties. */
   svn_ra_push_wc_prop_func_t push_wc_prop;
 
- /** Invalidate working copy properties. */
   svn_ra_invalidate_wc_props_func_t invalidate_wc_props;
 
 } svn_ra_callbacks_t;
@@ -439,6 +417,23 @@
 svn_error_t *
 svn_ra_initialize (apr_pool_t *pool);
 
+/** Initialize a callback structure.
+* Set @a *callbacks to a ra callbacks object, allocated in @a pool.
+*
+* In order to avoid backwards compatibility problems, clients must
+* use this function to initialize and allocate the
+* @c svn_ra_callbacks2_t structure rather than doing so themselves, as
+* the size of this structure may change in the future.
+*
+* The current implementation never returns error, but callers should
+* still check for error, for compatibility with future versions.
+*
+* @since New in 1.3.
+*/
+svn_error_t *
+svn_ra_create_callbacks (svn_ra_callbacks2_t **callbacks,
+ apr_pool_t *pool);
+
 /**
  * A repository access session. This object is used to perform requests
  * to a repository, identified by an URL.
Index: subversion/libsvn_ra_svn/client.c
===================================================================
--- subversion/libsvn_ra_svn/client.c (Revision 15964)
+++ subversion/libsvn_ra_svn/client.c (Arbeitskopie)
@@ -644,6 +644,11 @@
       conn = svn_ra_svn_create_conn(sock, NULL, NULL, pool);
     }
 
+ conn->progress_func = callbacks->progress_func;
+ conn->progress_baton = callbacks->progress_baton;
+ conn->progress_progress = 0;
+ conn->progress_total = -1;
+
   /* Read server's greeting. */
   SVN_ERR(svn_ra_svn_read_cmd_response(conn, pool, "nnll", &minver, &maxver,
                                        &mechlist, &caplist));
Index: subversion/libsvn_ra_svn/marshal.c
===================================================================
--- subversion/libsvn_ra_svn/marshal.c (Revision 15964)
+++ subversion/libsvn_ra_svn/marshal.c (Arbeitskopie)
@@ -156,6 +156,12 @@
         status = apr_socket_send(conn->sock, data, &count);
       else
         status = apr_file_write(conn->out_file, data, &count);
+ conn->progress_progress += count;
+ if (conn->progress_func)
+ {
+ conn->progress_func(conn->progress_progress, conn->progress_total,
+ pool, conn->progress_baton);
+ }
       if (status)
         return svn_error_wrap_apr(status, _("Can't write to connection"));
       if (count == 0)
@@ -236,7 +242,7 @@
 
 /* Read data from socket or input file as appropriate. */
 static svn_error_t *readbuf_input(svn_ra_svn_conn_t *conn, char *data,
- apr_size_t *len)
+ apr_size_t *len, apr_pool_t *pool)
 {
   apr_status_t status;
 
@@ -247,6 +253,12 @@
     status = apr_socket_recv(conn->sock, data, len);
   else
     status = apr_file_read(conn->in_file, data, len);
+ conn->progress_progress += *len;
+ if (conn->progress_func)
+ {
+ conn->progress_func(conn->progress_progress, conn->progress_total,
+ pool, conn->progress_baton);
+ }
   if (conn->sock && conn->block_handler)
     apr_socket_timeout_set(conn->sock, 0);
   if (status && !APR_STATUS_IS_EOF(status))
@@ -265,7 +277,7 @@
   assert(conn->read_ptr == conn->read_end);
   SVN_ERR(writebuf_flush(conn, pool));
   len = sizeof(conn->read_buf);
- SVN_ERR(readbuf_input(conn, conn->read_buf, &len));
+ SVN_ERR(readbuf_input(conn, conn->read_buf, &len, pool));
   conn->read_ptr = conn->read_buf;
   conn->read_end = conn->read_buf + len;
   return SVN_NO_ERROR;
@@ -304,7 +316,7 @@
     {
       SVN_ERR(writebuf_flush(conn, pool));
       count = end - data;
- SVN_ERR(readbuf_input(conn, data, &count));
+ SVN_ERR(readbuf_input(conn, data, &count, pool));
       data += count;
     }
 
@@ -319,7 +331,8 @@
   return SVN_NO_ERROR;
 }
 
-static svn_error_t *readbuf_skip_leading_garbage(svn_ra_svn_conn_t *conn)
+static svn_error_t *readbuf_skip_leading_garbage(svn_ra_svn_conn_t *conn,
+ apr_pool_t *pool)
 {
   char buf[256]; /* Must be smaller than sizeof(conn->read_buf) - 1. */
   const char *p, *end;
@@ -331,7 +344,7 @@
     {
       /* Read some data directly from the connection input source. */
       len = sizeof(buf);
- SVN_ERR(readbuf_input(conn, buf, &len));
+ SVN_ERR(readbuf_input(conn, buf, &len, pool));
       end = buf + len;
 
       /* Scan the data for '(' WS with a very simple state machine. */
@@ -619,7 +632,7 @@
 svn_error_t *svn_ra_svn_skip_leading_garbage(svn_ra_svn_conn_t *conn,
                                              apr_pool_t *pool)
 {
- return readbuf_skip_leading_garbage(conn);
+ return readbuf_skip_leading_garbage(conn, pool);
 }
 
 /* --- READING AND PARSING TUPLES --- */
Index: subversion/libsvn_ra_svn/ra_svn.h
===================================================================
--- subversion/libsvn_ra_svn/ra_svn.h (Revision 15964)
+++ subversion/libsvn_ra_svn/ra_svn.h (Arbeitskopie)
@@ -29,6 +29,7 @@
 #include <apr_file_io.h>
 #include <apr_thread_proc.h>
 #include <svn_ra_svn.h>
+#include "svn_ra.h"
 
 /* Handler for blocked writes. */
 typedef svn_error_t *(*ra_svn_block_handler_t)(svn_ra_svn_conn_t *conn,
@@ -53,6 +54,10 @@
   ra_svn_block_handler_t block_handler;
   void *block_baton;
   apr_hash_t *capabilities;
+ svn_ra_progress_notify_func_t progress_func;
+ void *progress_baton;
+ apr_off_t progress_progress;
+ apr_off_t progress_total;
   apr_pool_t *pool;
 };
 
Index: subversion/libsvn_ra_dav/session.c
===================================================================
--- subversion/libsvn_ra_dav/session.c (Revision 15964)
+++ subversion/libsvn_ra_dav/session.c (Arbeitskopie)
@@ -561,14 +561,22 @@
 #endif /* if/else SVN_NEON_0_25 */
 }
 
+typedef struct neonprogress_baton_t
+{
+ void *progress_baton;
+ svn_ra_progress_notify_func_t progress_func;
+ apr_pool_t *pool;
+} neonprogress_baton_t;
+
 static void
 ra_dav_neonprogress(void * baton, off_t progress, off_t total)
 {
- /* Important: don't change the svn_ra_callbacks2_t struct here! */
- const svn_ra_callbacks2_t * callbacks = (svn_ra_callbacks2_t *)baton;
- if (callbacks->progress_func)
+ neonprogress_baton_t * neonprogress_baton = (neonprogress_baton_t *)baton;
+ if (neonprogress_baton->progress_func)
     {
- callbacks->progress_func(progress, total, callbacks->progress_baton);
+ neonprogress_baton->progress_func(progress, total,
+ neonprogress_baton->pool,
+ neonprogress_baton->progress_baton);
     }
 }
 
@@ -593,6 +601,8 @@
   svn_boolean_t compression;
   svn_config_t *cfg;
   const char *server_group;
+ neonprogress_baton_t * neonprogress_baton = apr_pcalloc (pool,
+ sizeof (neonprogress_baton_t));
 
   /* Sanity check the URI */
   if (ne_uri_parse(repos_URL, &uri)
@@ -802,13 +812,11 @@
           ne_ssl_trust_default_ca(sess2);
         }
     }
-
- /* Set the neon callback to make it call the svn_progress_notify_func_t
- * Note that ne_set_progress() takes a non-const baton as the third param.
- * Since we don't change the callback struct but only use the non-const
- * notification callback items of that struct, it's safe to cast */
- ne_set_progress(sess, ra_dav_neonprogress, (void*)callbacks);
- ne_set_progress(sess2, ra_dav_neonprogress, (void*)callbacks);
+ neonprogress_baton->pool = pool;
+ neonprogress_baton->progress_baton = callbacks->progress_baton;
+ neonprogress_baton->progress_func = callbacks->progress_func;
+ ne_set_progress(sess, ra_dav_neonprogress, (void*)neonprogress_baton);
+ ne_set_progress(sess2, ra_dav_neonprogress, (void*)neonprogress_baton);
   session->priv = ras;
 
   return SVN_NO_ERROR;

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@subversion.tigris.org
For additional commands, e-mail: dev-help@subversion.tigris.org
Received on Mon Aug 29 20:09:22 2005

This is an archived mail posted to the Subversion Dev mailing list.