Did you run any tests to observe the alleged contention?

The dbm database is very fast. I'd be surprised that contention occurs in
any typical workload.

Cheers,
-g


On Mon, Oct 17, 2022 at 4:48 AM <yla...@apache.org> wrote:

> Author: ylavic
> Date: Mon Oct 17 09:48:11 2022
> New Revision: 1904638
>
> URL: http://svn.apache.org/viewvc?rev=1904638&view=rev
> Log:
> mod_dav: Allow to disable lock discovery via an DAVLockDiscovery
> expression.
>
> mod_dav-fs scales badly when a few clients run PROPFIND requests to
> discover
> directory content. Each PROPFIND involves lockdiscovery, which in turn
> waits
> for a locked access to the file containing the lock database. Performances
> quickly drop because of lock contention on this file.
>
> Add a DAVLockDiscovery configuration directive that allows lockdiscovery
> to be
> disabled. Its argument is an Apache expression so that flexible
> configuration
> are possible (per-request).
>
> When lock discovery is disabled, an empty lockdiscovery property is
> returned on
> POPRFIND methods, just like if no lock was set on the object. That should
> cause
> no regression, since a client cannot rely on lockdiscovery to decide when a
> file should be accessed, the LOCK methood must be used.
>
> If DAVLockDiscovery is not specified, the behavior is unchanged.
>
>
> PR 66313.
> Submitted by: Emmanuel Dreyfus <manu netbsd.org>
> Reviewed by: ylavic
>
>
> Added:
>     httpd/httpd/trunk/changes-entries/DAVLockDiscovery.txt
> Modified:
>     httpd/httpd/trunk/modules/dav/main/mod_dav.c
>     httpd/httpd/trunk/modules/dav/main/mod_dav.h
>     httpd/httpd/trunk/modules/dav/main/props.c
>
> Added: httpd/httpd/trunk/changes-entries/DAVLockDiscovery.txt
> URL:
> http://svn.apache.org/viewvc/httpd/httpd/trunk/changes-entries/DAVLockDiscovery.txt?rev=1904638&view=auto
>
> ==============================================================================
> --- httpd/httpd/trunk/changes-entries/DAVLockDiscovery.txt (added)
> +++ httpd/httpd/trunk/changes-entries/DAVLockDiscovery.txt Mon Oct 17
> 09:48:11 2022
> @@ -0,0 +1,2 @@
> +  *) mod_dav: Allow to disable lock discovery via an DAVLockDiscovery
> +     expression (per-request). PR 66313. [Emmanuel Dreyfus <manu
> netbsd.org>]
>
> Modified: httpd/httpd/trunk/modules/dav/main/mod_dav.c
> URL:
> http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/dav/main/mod_dav.c?rev=1904638&r1=1904637&r2=1904638&view=diff
>
> ==============================================================================
> --- httpd/httpd/trunk/modules/dav/main/mod_dav.c (original)
> +++ httpd/httpd/trunk/modules/dav/main/mod_dav.c Mon Oct 17 09:48:11 2022
> @@ -83,6 +83,7 @@ typedef struct {
>      const char *dir;
>      int locktimeout;
>      int allow_depthinfinity;
> +    ap_expr_info_t *allow_lockdiscovery;
>
>  } dav_dir_conf;
>
> @@ -203,6 +204,8 @@ static void *dav_merge_dir_config(apr_po
>      newconf->dir = DAV_INHERIT_VALUE(parent, child, dir);
>      newconf->allow_depthinfinity = DAV_INHERIT_VALUE(parent, child,
>                                                       allow_depthinfinity);
> +    newconf->allow_lockdiscovery = DAV_INHERIT_VALUE(parent, child,
> +                                                     allow_lockdiscovery);
>
>      return newconf;
>  }
> @@ -301,6 +304,30 @@ static const char *dav_cmd_davdepthinfin
>  }
>
>  /*
> + * Command handler for the DAVLockDiscovery directive, which is TAKE1.
> + */
> +static const char *dav_cmd_davlockdiscovery(cmd_parms *cmd, void *config,
> +                                            const char *arg)
> +{
> +    dav_dir_conf *conf = (dav_dir_conf *)config;
> +
> +    if (strncasecmp(arg, "expr=", 5) == 0) {
> +        const char *err;
> +        if ((arg[5] == '\0'))
> +            return "missing condition";
> +        conf->allow_lockdiscovery = ap_expr_parse_cmd(cmd, &arg[5],
> +
> AP_EXPR_FLAG_DONT_VARY,
> +                                                      &err, NULL);
> +        if (err)
> +            return err;
> +    } else {
> +        return "error in condition clause";
> +    }
> +
> +    return NULL;
> +}
> +
> +/*
>   * Command handler for DAVMinTimeout directive, which is TAKE1
>   */
>  static const char *dav_cmd_davmintimeout(cmd_parms *cmd, void *config,
> @@ -1450,7 +1477,7 @@ static dav_error *dav_gen_supported_live
>      }
>
>      /* open the property database (readonly) for the resource */
> -    if ((err = dav_open_propdb(r, lockdb, resource, 1, NULL,
> +    if ((err = dav_open_propdb(r, lockdb, resource, DAV_PROPDB_RO, NULL,
>                                 &propdb)) != NULL) {
>          if (lockdb != NULL)
>              (*lockdb->hooks->close_lockdb)(lockdb);
> @@ -2045,6 +2072,8 @@ static void dav_cache_badprops(dav_walke
>  static dav_error * dav_propfind_walker(dav_walk_resource *wres, int
> calltype)
>  {
>      dav_walker_ctx *ctx = wres->walk_ctx;
> +    dav_dir_conf *conf;
> +    int flags = DAV_PROPDB_RO;
>      dav_error *err;
>      dav_propdb *propdb;
>      dav_get_props_result propstats = { 0 };
> @@ -2068,6 +2097,20 @@ static dav_error * dav_propfind_walker(d
>          return NULL;
>      }
>
> +    conf = ap_get_module_config(ctx->r->per_dir_config, &dav_module);
> +    if (conf && conf->allow_lockdiscovery) {
> +            const char *errstr = NULL;
> +            int eval = ap_expr_exec(ctx->r, conf->allow_lockdiscovery,
> &errstr);
> +            if (errstr) {
> +                ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, ctx->r,
> APLOGNO(00623)
> +                              "Failed to evaluate expression (%s) -
> ignoring",
> +                              errstr);
> +            } else {
> +                if (!eval)
> +                    flags |= DAV_PROPDB_DISABLE_LOCKDISCOVERY;
> +            }
> +    }
> +
>      /*
>      ** Note: ctx->doc can only be NULL for DAV_PROPFIND_IS_ALLPROP. Since
>      ** dav_get_allprops() does not need to do namespace translation,
> @@ -2077,7 +2120,7 @@ static dav_error * dav_propfind_walker(d
>      ** the resource, however, since we are opening readonly.
>      */
>      err = dav_popen_propdb(ctx->scratchpool,
> -                           ctx->r, ctx->w.lockdb, wres->resource, 1,
> +                           ctx->r, ctx->w.lockdb, wres->resource, flags,
>                             ctx->doc ? ctx->doc->namespaces : NULL,
> &propdb);
>      if (err != NULL) {
>          /* ### do something with err! */
> @@ -2463,7 +2506,8 @@ static int dav_method_proppatch(request_
>          return dav_handle_err(r, err, NULL);
>      }
>
> -    if ((err = dav_open_propdb(r, NULL, resource, 0, doc->namespaces,
> +    if ((err = dav_open_propdb(r, NULL, resource,
> +                               DAV_PROPDB_NONE, doc->namespaces,
>                                 &propdb)) != NULL) {
>          /* undo any auto-checkout */
>          dav_auto_checkin(r, resource, 1 /*undo*/, 0 /*unlock*/, &av_info);
> @@ -5220,6 +5264,11 @@ static const command_rec dav_cmds[] =
>                   ACCESS_CONF|RSRC_CONF,
>                   "allow Depth infinity PROPFIND requests"),
>
> +    /* per directory/location, or per server */
> +    AP_INIT_TAKE1("DAVLockDiscovery", dav_cmd_davlockdiscovery, NULL,
> +                  ACCESS_CONF|RSRC_CONF,
> +                  "allow lock discovery by PROPFIND requests"),
> +
>      { NULL }
>  };
>
>
> Modified: httpd/httpd/trunk/modules/dav/main/mod_dav.h
> URL:
> http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/dav/main/mod_dav.h?rev=1904638&r1=1904637&r2=1904638&view=diff
>
> ==============================================================================
> --- httpd/httpd/trunk/modules/dav/main/mod_dav.h (original)
> +++ httpd/httpd/trunk/modules/dav/main/mod_dav.h Mon Oct 17 09:48:11 2022
> @@ -1691,12 +1691,15 @@ struct dav_hooks_locks
>
>  typedef struct dav_propdb dav_propdb;
>
> +#define DAV_PROPDB_NONE                  0
> +#define DAV_PROPDB_RO                    1
> +#define DAV_PROPDB_DISABLE_LOCKDISCOVERY 2
>
>  DAV_DECLARE(dav_error *) dav_open_propdb(
>      request_rec *r,
>      dav_lockdb *lockdb,
>      const dav_resource *resource,
> -    int ro,
> +    int flags,
>      apr_array_header_t *ns_xlate,
>      dav_propdb **propdb);
>
> @@ -1705,7 +1708,7 @@ DAV_DECLARE(dav_error *) dav_popen_propd
>      request_rec *r,
>      dav_lockdb *lockdb,
>      const dav_resource *resource,
> -    int ro,
> +    int flags,
>      apr_array_header_t *ns_xlate,
>      dav_propdb **propdb);
>
>
> Modified: httpd/httpd/trunk/modules/dav/main/props.c
> URL:
> http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/dav/main/props.c?rev=1904638&r1=1904637&r2=1904638&view=diff
>
> ==============================================================================
> --- httpd/httpd/trunk/modules/dav/main/props.c (original)
> +++ httpd/httpd/trunk/modules/dav/main/props.c Mon Oct 17 09:48:11 2022
> @@ -185,6 +185,8 @@ struct dav_propdb {
>
>      dav_buffer wb_lock;           /* work buffer for lockdiscovery
> property */
>
> +    int flags;                    /* ro, disable lock discovery */
> +
>      /* if we ever run a GET subreq, it will be stored here */
>      request_rec *subreq;
>
> @@ -351,6 +353,11 @@ static dav_error * dav_insert_coreprop(d
>      switch (propid) {
>
>      case DAV_PROPID_CORE_lockdiscovery:
> +        if (propdb->flags & DAV_PROPDB_DISABLE_LOCKDISCOVERY) {
> +            value = "";
> +            break;
> +        }
> +
>          if (propdb->lockdb != NULL) {
>              dav_lock *locks;
>
> @@ -522,17 +529,18 @@ static dav_error *dav_really_open_db(dav
>
>  DAV_DECLARE(dav_error *)dav_open_propdb(request_rec *r, dav_lockdb
> *lockdb,
>                                          const dav_resource *resource,
> -                                        int ro,
> +                                        int flags,
>                                          apr_array_header_t * ns_xlate,
>                                          dav_propdb **p_propdb)
>  {
> -    return dav_popen_propdb(r->pool, r, lockdb, resource, ro, ns_xlate,
> p_propdb);
> +    return dav_popen_propdb(r->pool, r, lockdb, resource,
> +                            flags, ns_xlate, p_propdb);
>  }
>
>  DAV_DECLARE(dav_error *)dav_popen_propdb(apr_pool_t *p,
>                                           request_rec *r, dav_lockdb
> *lockdb,
>                                           const dav_resource *resource,
> -                                         int ro,
> +                                         int flags,
>                                           apr_array_header_t * ns_xlate,
>                                           dav_propdb **p_propdb)
>  {
> @@ -559,6 +567,8 @@ DAV_DECLARE(dav_error *)dav_popen_propdb
>
>      propdb->lockdb = lockdb;
>
> +    propdb->flags = flags;
> +
>      /* always defer actual open, to avoid expense of accessing db
>       * when only live properties are involved
>       */
>
>
>

Reply via email to