You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by gs...@apache.org on 2012/05/12 09:51:53 UTC

svn commit: r1337467 - /subversion/trunk/subversion/libsvn_ra_serf/options.c

Author: gstein
Date: Sat May 12 07:51:53 2012
New Revision: 1337467

URL: http://svn.apache.org/viewvc?rev=1337467&view=rev
Log:
Use the v2 parsing system for the OPTIONS response. It was not even
using the v1 system, but some very early code that stylistically
resembles what became v1 (svn_ra_serf__xml_state_t).

This wipes out a bunch of code, along with making this more robust,
more pool-friendly, and easier to understand.

* subversion/libsvn_ra_serf/options.c:
  (options_state_e): add INITIAL to represent the context's initial state
  (options_state_list_t): removed. obsolete.
  (options_context_t): ACBUF, COLLECT_CDATA, STATE, FREE_STATE, DONE,
    PARSER_CTX are all removed as obsolete. added INNER_HANDLER and
    INNER_BATON to deal with our options response handler interposed
    before the expat handler.
  (D_, S_): helper namespace macros. S_ isn't actually used, but is
    there to match future precedent
  (options_ttable): new transition table for the OPTIONS body
  (push_state, pop_state, start_options, end_options, cdata_options):
    removed. obsolete.
  (options_closed): new v2 callback for capturing the activity
    collection set.
  (create_options_req): create a new xml context. stick that into an
    expat parsing handler. remove the v1-style xml parsing handler.
    interpose our custom handler in front of the expat handler.
  (svn_ra_serf__v2_get_youngest_revnum,
      svn_ra_serf__v1_get_activity_collection,
      svn_ra_serf__exchange_capabilities): wait on the handler's DONE
    field rather than the old-style DONE flag in the options context

Modified:
    subversion/trunk/subversion/libsvn_ra_serf/options.c

Modified: subversion/trunk/subversion/libsvn_ra_serf/options.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_ra_serf/options.c?rev=1337467&r1=1337466&r2=1337467&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_ra_serf/options.c (original)
+++ subversion/trunk/subversion/libsvn_ra_serf/options.c Sat May 12 07:51:53 2012
@@ -49,161 +49,67 @@
  * This enum represents the current state of our XML parsing for an OPTIONS.
  */
 typedef enum options_state_e {
+  INITIAL = 0,
   OPTIONS,
   ACTIVITY_COLLECTION,
   HREF
 } options_state_e;
 
-typedef struct options_state_list_t {
-  /* The current state that we are in now. */
-  options_state_e state;
-
-  /* The previous state we were in. */
-  struct options_state_list_t *prev;
-} options_state_list_t;
-
 typedef struct options_context_t {
   /* pool to allocate memory from */
   apr_pool_t *pool;
 
-  /* Buffer for the activity-collection  */
-  svn_stringbuf_t *acbuf;
-  svn_boolean_t collect_cdata;
-
-  /* Current state we're in */
-  options_state_list_t *state;
-  options_state_list_t *free_state;
-
   /* Have we extracted options values from the headers already?  */
   svn_boolean_t headers_processed;
 
-  /* are we done? */
-  svn_boolean_t done;
-
   svn_ra_serf__session_t *session;
   svn_ra_serf__connection_t *conn;
   svn_ra_serf__handler_t *handler;
-  svn_ra_serf__xml_parser_t *parser_ctx;
+
+  svn_ra_serf__response_handler_t inner_handler;
+  void *inner_baton;
 
   const char *activity_collection;
   svn_revnum_t youngest_rev;
 
 } options_context_t;
 
+#define D_ "DAV:"
+#define S_ SVN_XML_NAMESPACE
+static const svn_ra_serf__xml_transition_t options_ttable[] = {
+  { INITIAL, D_, "options-response", OPTIONS,
+    FALSE, { NULL }, FALSE, FALSE },
 
-static void
-push_state(options_context_t *options_ctx, options_state_e state)
-{
-  options_state_list_t *new_state;
+  { OPTIONS, D_, "activity-collection-set", ACTIVITY_COLLECTION,
+    FALSE, { NULL }, FALSE, FALSE },
 
-  if (!options_ctx->free_state)
-    {
-      new_state = apr_palloc(options_ctx->pool, sizeof(*options_ctx->state));
-    }
-  else
-    {
-      new_state = options_ctx->free_state;
-      options_ctx->free_state = options_ctx->free_state->prev;
-    }
-  new_state->state = state;
+  { ACTIVITY_COLLECTION, D_, "href", HREF,
+    TRUE, { NULL }, FALSE, TRUE },
 
-  /* Add it to the state chain. */
-  new_state->prev = options_ctx->state;
-  options_ctx->state = new_state;
-}
+  { 0 }
+};
 
-static void pop_state(options_context_t *options_ctx)
-{
-  options_state_list_t *free_state;
-  free_state = options_ctx->state;
-  /* advance the current state */
-  options_ctx->state = options_ctx->state->prev;
-  free_state->prev = options_ctx->free_state;
-  options_ctx->free_state = free_state;
-}
 
+/* Conforms to svn_ra_serf__xml_closed_t  */
 static svn_error_t *
-start_options(svn_ra_serf__xml_parser_t *parser,
-              svn_ra_serf__dav_props_t name,
-              const char **attrs,
-              apr_pool_t *scratch_pool)
+options_closed(svn_ra_serf__xml_estate_t *xes,
+               void *baton,
+               int leaving_state,
+               const svn_string_t *cdata,
+               apr_hash_t *attrs,
+               apr_pool_t *scratch_pool)
 {
-  options_context_t *options_ctx = parser->user_data;
-
-  if (!options_ctx->state && strcmp(name.name, "options-response") == 0)
-    {
-      push_state(options_ctx, OPTIONS);
-    }
-  else if (!options_ctx->state)
-    {
-      /* Nothing to do. */
-      return SVN_NO_ERROR;
-    }
-  else if (options_ctx->state->state == OPTIONS &&
-           strcmp(name.name, "activity-collection-set") == 0)
-    {
-      push_state(options_ctx, ACTIVITY_COLLECTION);
-    }
-  else if (options_ctx->state->state == ACTIVITY_COLLECTION &&
-           strcmp(name.name, "href") == 0)
-    {
-      options_ctx->collect_cdata = TRUE;
-      push_state(options_ctx, HREF);
-    }
-
-  return SVN_NO_ERROR;
-}
-
-static svn_error_t *
-end_options(svn_ra_serf__xml_parser_t *parser,
-            svn_ra_serf__dav_props_t name,
-            apr_pool_t *scratch_pool)
-{
-  options_context_t *options_ctx = parser->user_data;
-  options_state_list_t *cur_state;
+  options_context_t *opt_ctx = baton;
 
-  if (!options_ctx->state)
-    {
-      return SVN_NO_ERROR;
-    }
+  SVN_ERR_ASSERT(leaving_state == HREF);
+  SVN_ERR_ASSERT(cdata != NULL);
 
-  cur_state = options_ctx->state;
-
-  if (cur_state->state == OPTIONS &&
-      strcmp(name.name, "options-response") == 0)
-    {
-      pop_state(options_ctx);
-    }
-  else if (cur_state->state == ACTIVITY_COLLECTION &&
-           strcmp(name.name, "activity-collection-set") == 0)
-    {
-      pop_state(options_ctx);
-    }
-  else if (cur_state->state == HREF &&
-           strcmp(name.name, "href") == 0)
-    {
-      options_ctx->collect_cdata = FALSE;
-      options_ctx->activity_collection =
-        svn_urlpath__canonicalize(options_ctx->acbuf->data, options_ctx->pool);
-      pop_state(options_ctx);
-    }
+  opt_ctx->activity_collection = svn_urlpath__canonicalize(cdata->data,
+                                                           opt_ctx->pool);
 
   return SVN_NO_ERROR;
 }
 
-static svn_error_t *
-cdata_options(svn_ra_serf__xml_parser_t *parser,
-              const char *data,
-              apr_size_t len,
-              apr_pool_t *scratch_pool)
-{
-  options_context_t *ctx = parser->user_data;
-
-  if (ctx->collect_cdata)
-    svn_stringbuf_appendbytes(ctx->acbuf, data, len);
-
-  return SVN_NO_ERROR;
-}
 
 static svn_error_t *
 create_options_body(serf_bucket_t **body_bkt,
@@ -394,8 +300,7 @@ options_response_handler(serf_request_t 
     }
 
   /* Execute the 'real' response handler to XML-parse the repsonse body. */
-  return svn_ra_serf__handle_xml_parser(request, response,
-                                        opt_ctx->parser_ctx, pool);
+  return opt_ctx->inner_handler(request, response, opt_ctx->inner_baton, pool);
 }
 
 
@@ -406,22 +311,21 @@ create_options_req(options_context_t **o
                    apr_pool_t *pool)
 {
   options_context_t *new_ctx;
+  svn_ra_serf__xml_context_t *xmlctx;
   svn_ra_serf__handler_t *handler;
-  svn_ra_serf__xml_parser_t *parser_ctx;
 
   new_ctx = apr_pcalloc(pool, sizeof(*new_ctx));
-
   new_ctx->pool = pool;
-
-  new_ctx->acbuf = svn_stringbuf_create_empty(pool);
-  new_ctx->youngest_rev = SVN_INVALID_REVNUM;
-
   new_ctx->session = session;
   new_ctx->conn = conn;
 
-  handler = apr_pcalloc(pool, sizeof(*handler));
+  new_ctx->youngest_rev = SVN_INVALID_REVNUM;
+
+  xmlctx = svn_ra_serf__xml_context_create(options_ttable,
+                                           NULL, options_closed, new_ctx,
+                                           pool);
+  handler = svn_ra_serf__create_expat_handler(xmlctx, pool);
 
-  handler->handler_pool = pool;
   handler->method = "OPTIONS";
   handler->path = session->session_url.path;
   handler->body_delegate = create_options_body;
@@ -429,18 +333,10 @@ create_options_req(options_context_t **o
   handler->conn = conn;
   handler->session = session;
 
-  parser_ctx = apr_pcalloc(pool, sizeof(*parser_ctx));
-
-  parser_ctx->pool = pool;
-  parser_ctx->user_data = new_ctx;
-  parser_ctx->start = start_options;
-  parser_ctx->end = end_options;
-  parser_ctx->cdata = cdata_options;
-  parser_ctx->done = &new_ctx->done;
-
   new_ctx->handler = handler;
-  new_ctx->parser_ctx = parser_ctx;
 
+  new_ctx->inner_handler = handler->response_handler;
+  new_ctx->inner_baton = handler->response_baton;
   handler->response_handler = options_response_handler;
   handler->response_baton = new_ctx;
 
@@ -463,7 +359,7 @@ svn_ra_serf__v2_get_youngest_revnum(svn_
   SVN_ERR_ASSERT(SVN_RA_SERF__HAVE_HTTPV2_SUPPORT(session));
 
   SVN_ERR(create_options_req(&opt_ctx, session, conn, scratch_pool));
-  SVN_ERR(svn_ra_serf__context_run_wait(&opt_ctx->done, session,
+  SVN_ERR(svn_ra_serf__context_run_wait(&opt_ctx->handler->done, session,
                                         scratch_pool));
 
   *youngest = opt_ctx->youngest_rev;
@@ -484,7 +380,7 @@ svn_ra_serf__v1_get_activity_collection(
   SVN_ERR_ASSERT(!SVN_RA_SERF__HAVE_HTTPV2_SUPPORT(session));
 
   SVN_ERR(create_options_req(&opt_ctx, session, conn, scratch_pool));
-  SVN_ERR(svn_ra_serf__context_run_wait(&opt_ctx->done, session,
+  SVN_ERR(svn_ra_serf__context_run_wait(&opt_ctx->handler->done, session,
                                         scratch_pool));
 
   *activity_url = apr_pstrdup(result_pool, opt_ctx->activity_collection);
@@ -508,7 +404,8 @@ svn_ra_serf__exchange_capabilities(svn_r
   /* This routine automatically fills in serf_sess->capabilities */
   SVN_ERR(create_options_req(&opt_ctx, serf_sess, serf_sess->conns[0], pool));
 
-  err = svn_ra_serf__context_run_wait(&opt_ctx->done, serf_sess, pool);
+  err = svn_ra_serf__context_run_wait(&opt_ctx->handler->done, serf_sess,
+                                      pool);
 
   /* If our caller cares about server redirections, and our response
      carries such a thing, report as much.  We'll disregard ERR --