You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by st...@apache.org on 2016/11/18 18:14:40 UTC

svn commit: r1770418 - in /subversion/branches/authzperf/subversion: include/svn_repos.h libsvn_repos/authz.c mod_dav_svn/mod_dav_svn.c svnserve/svnserve.c

Author: stefan2
Date: Fri Nov 18 18:14:40 2016
New Revision: 1770418

URL: http://svn.apache.org/viewvc?rev=1770418&view=rev
Log:
On the authzperf branch:
Add caching support to our authz parsers.

There is only one authz parser function anymore and we simply need to add
a global object cache to be used by that function.  However, the cache /
object pool needs to be created early on to guarantee pool lifetimes.  To
this end, the cache is optional and we add a public *_initialize function.

* subversion/include/svn_repos.h
  (svn_repos_authz_initialize): New API.

* subversion/libsvn_repos/authz.c
  (authz_pool,
   authz_pool_initialized,
   synchronized_authz_initialize,
   svn_repos_authz_initialize): Adds the authz object cache and the
                                initialization infrastructure.
  (construct_key): New utility function.
  (authz_read): Add cache lookup and insertion code.

* subversion/mod_dav_svn/mod_dav_svn.c
  (init): Initialize the authz caching.

* subversion/svnserve/svnserve.c
  (sub_main): Same.

Modified:
    subversion/branches/authzperf/subversion/include/svn_repos.h
    subversion/branches/authzperf/subversion/libsvn_repos/authz.c
    subversion/branches/authzperf/subversion/mod_dav_svn/mod_dav_svn.c
    subversion/branches/authzperf/subversion/svnserve/svnserve.c

Modified: subversion/branches/authzperf/subversion/include/svn_repos.h
URL: http://svn.apache.org/viewvc/subversion/branches/authzperf/subversion/include/svn_repos.h?rev=1770418&r1=1770417&r2=1770418&view=diff
==============================================================================
--- subversion/branches/authzperf/subversion/include/svn_repos.h (original)
+++ subversion/branches/authzperf/subversion/include/svn_repos.h Fri Nov 18 18:14:40 2016
@@ -3889,6 +3889,17 @@ svn_repos_get_fs_build_parser(const svn_
 typedef struct svn_authz_t svn_authz_t;
 
 /**
+ * This should be called before any other authz function.
+ *
+ * @a pool must support multi-threaded access if the application will use
+ * authz from multiple threads.
+ *
+ * @since New in 1.10.
+ */
+svn_error_t *
+svn_repos_authz_initialize(apr_pool_t *pool);
+
+/**
  * Read authz configuration data from @a path (a dirent, an absolute file url
  * or a registry path) into @a *authz_p, allocated in @a pool.
  *

Modified: subversion/branches/authzperf/subversion/libsvn_repos/authz.c
URL: http://svn.apache.org/viewvc/subversion/branches/authzperf/subversion/libsvn_repos/authz.c?rev=1770418&r1=1770417&r2=1770418&view=diff
==============================================================================
--- subversion/branches/authzperf/subversion/libsvn_repos/authz.c (original)
+++ subversion/branches/authzperf/subversion/libsvn_repos/authz.c Fri Nov 18 18:14:40 2016
@@ -35,6 +35,7 @@
 #include "svn_repos.h"
 #include "svn_config.h"
 #include "svn_ctype.h"
+#include "private/svn_atomic.h"
 #include "private/svn_fspath.h"
 #include "private/svn_repos_private.h"
 #include "private/svn_sorts_private.h"
@@ -1353,6 +1354,67 @@ get_filtered_tree(svn_authz_t *authz,
   return authz->user_rules[i];
 }
 
+
+
+/*** Authz cache access. ***/
+
+/* All authz instances currently in use will be cached here.
+ * Will be instantiated at most once. */
+svn_object_pool__t *authz_pool = NULL;
+static svn_atomic_t authz_pool_initialized = FALSE;
+
+/* Implements svn_atomic__err_init_func_t. */
+static svn_error_t *
+synchronized_authz_initialize(void *baton, apr_pool_t *pool)
+{
+  svn_boolean_t multi_threaded
+    = apr_allocator_mutex_get(apr_pool_allocator_get(pool)) != NULL;
+
+  return svn_error_trace(svn_object_pool__create(&authz_pool, multi_threaded,
+                                                 pool));
+}
+
+svn_error_t *
+svn_repos_authz_initialize(apr_pool_t *pool)
+{
+  /* Protect against multiple calls. */
+  return svn_error_trace(svn_atomic__init_once(&authz_pool_initialized,
+                                               synchronized_authz_initialize,
+                                               NULL, pool));
+}
+
+/* Return a combination of AUTHZ_KEY and GROUPS_KEY, allocated in RESULT_POOL.
+ * GROUPS_KEY may be NULL.
+ */
+static svn_membuf_t *
+construct_key(const svn_checksum_t *authz_key,
+              const svn_checksum_t *groups_key,
+              apr_pool_t *result_pool)
+{
+  svn_membuf_t *result = apr_pcalloc(result_pool, sizeof(*result));
+  if (groups_key)
+    {
+      apr_size_t authz_size = svn_checksum_size(authz_key);
+      apr_size_t groups_size = svn_checksum_size(groups_key);
+
+      svn_membuf__create(result, authz_size + groups_size, result_pool);
+      result->size = authz_size + groups_size; /* exact length is required! */
+
+      memcpy(result->data, authz_key->digest, authz_size);
+      memcpy((char *)result->data + authz_size,
+             groups_key->digest, groups_size);
+    }
+  else
+    {
+      apr_size_t size = svn_checksum_size(authz_key);
+      svn_membuf__create(result, size, result_pool);
+      result->size = size; /* exact length is required! */
+      memcpy(result->data, authz_key->digest, size);
+    }
+
+  return result;
+}
+
 
 /* Read authz configuration data from PATH into *AUTHZ_P, allocated in
    RESULT_POOL.  If GROUPS_PATH is set, use the global groups parsed from it.
@@ -1379,6 +1441,7 @@ authz_read(authz_full_t **authz_p,
   svn_stream_t *groups_stream = NULL;
   svn_checksum_t *rules_checksum = NULL;
   svn_checksum_t *groups_checksum = NULL;
+  svn_membuf_t *key;
 
   config_access_t *access = svn_repos__create_config_access(repos_hint,
                                                             scratch_pool);
@@ -1392,12 +1455,52 @@ authz_read(authz_full_t **authz_p,
     SVN_ERR(svn_repos__get_config(&groups_stream, &groups_checksum, access,
                                   groups_path, must_exist, scratch_pool));
 
-  /* Parse the configuration(s) and construct the full authz model from it. */
-  err = svn_error_quick_wrapf(svn_authz__parse(authz_p, rules_stream,
-                                               groups_stream,
-                                               result_pool, scratch_pool),
-                              "Error while parsing authz file: '%s':",
-                              path);
+  /* The authz cache is optional. */
+  if (authz_pool)
+    {
+      /* Cache lookup. */
+      key = construct_key(rules_checksum, groups_checksum, scratch_pool);
+      SVN_ERR(svn_object_pool__lookup((void **)authz_p, authz_pool, key,
+                                      result_pool));
+
+      /* If not found, parse and add to cache. */
+      if (!*authz_p)
+        {
+          apr_pool_t *item_pool = svn_object_pool__new_item_pool(authz_pool);
+
+          /* Parse the configuration(s) and construct the full authz model
+           * from it. */
+          err = svn_authz__parse(authz_p, rules_stream, groups_stream,
+                                item_pool, scratch_pool);
+          if (err != SVN_NO_ERROR)
+            {
+              /* That pool would otherwise never get destroyed. */
+              svn_pool_destroy(item_pool);
+
+              /* Add the URL / file name to the error stack since the parser
+               * doesn't have it. */
+              err = svn_error_quick_wrapf(err,
+                                   "Error while parsing config file: '%s':",
+                                   path);
+            }
+          else
+            {
+              SVN_ERR(svn_object_pool__insert((void **)authz_p, authz_pool,
+                                              key, *authz_p,
+                                              item_pool, result_pool));
+            }
+        }
+    }
+  else
+    {
+      /* Parse the configuration(s) and construct the full authz model from
+       * it. */
+      err = svn_error_quick_wrapf(svn_authz__parse(authz_p, rules_stream,
+                                                   groups_stream,
+                                                   result_pool, scratch_pool),
+                                  "Error while parsing authz file: '%s':",
+                                  path);
+    }
 
   svn_repos__destroy_config_access(access);
 

Modified: subversion/branches/authzperf/subversion/mod_dav_svn/mod_dav_svn.c
URL: http://svn.apache.org/viewvc/subversion/branches/authzperf/subversion/mod_dav_svn/mod_dav_svn.c?rev=1770418&r1=1770417&r2=1770418&view=diff
==============================================================================
--- subversion/branches/authzperf/subversion/mod_dav_svn/mod_dav_svn.c (original)
+++ subversion/branches/authzperf/subversion/mod_dav_svn/mod_dav_svn.c Fri Nov 18 18:14:40 2016
@@ -137,6 +137,15 @@ init(apr_pool_t *p, apr_pool_t *plog, ap
       return HTTP_INTERNAL_SERVER_ERROR;
     }
 
+  serr = svn_repos_authz_initialize(p);
+  if (serr)
+    {
+      ap_log_perror(APLOG_MARK, APLOG_ERR, serr->apr_err, p,
+               "mod_dav_svn: error calling svn_repos_authz_initialize: '%s'",
+                    serr->message ? serr->message : "(no more info)");
+      return HTTP_INTERNAL_SERVER_ERROR;
+    }
+
   /* This returns void, so we can't check for error. */
   conf = ap_get_module_config(s->module_config, &dav_svn_module);
   svn_utf_initialize2(conf->use_utf8, p);

Modified: subversion/branches/authzperf/subversion/svnserve/svnserve.c
URL: http://svn.apache.org/viewvc/subversion/branches/authzperf/subversion/svnserve/svnserve.c?rev=1770418&r1=1770417&r2=1770418&view=diff
==============================================================================
--- subversion/branches/authzperf/subversion/svnserve/svnserve.c (original)
+++ subversion/branches/authzperf/subversion/svnserve/svnserve.c Fri Nov 18 18:14:40 2016
@@ -752,6 +752,9 @@ sub_main(int *exit_code, int argc, const
   /* Initialize the FS library. */
   SVN_ERR(svn_fs_initialize(pool));
 
+  /* Initialize the efficient Authz support. */
+  SVN_ERR(svn_repos_authz_initialize(pool));
+
   SVN_ERR(svn_cmdline__getopt_init(&os, argc, argv, pool));
 
   params.root = "/";