mod_dav_fs: add DAVLockDBType directive.

* modules/dav/fs/dbm.c (dav_dbm_open_direct): Take a dbmtype argument
  and use it to select the apr_dbm driver type.
  (dav_dbm_open): Continue to use the "default" propdb type to open
  the property databases.

* modules/dav/fs/lock.c: Store and pass through the lockdb_type
  through.

* modules/dav/fs/mod_dav_fs.c (dav_get_lockdb_path): Return the dbm
  type via an output argument.
  (dav_fs_cmd_davlockdbtype): New config directive.
  (dav_fs_merge_server_config): Merge the dbm type.
  (dav_fs_post_config): Set the default lockdb type.

* modules/dav/fs/repos.h: Update prototypes as above; internal API
  only so no compat concerns.

Github: closes #386


git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1912718 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/changes-entries/davlockdbtype.txt b/changes-entries/davlockdbtype.txt
new file mode 100644
index 0000000..d83fd33
--- /dev/null
+++ b/changes-entries/davlockdbtype.txt
@@ -0,0 +1 @@
+  *) mod_dav_fs: Add DavLockDBType directive.  [Joe Orton]
diff --git a/docs/manual/mod/mod_dav_fs.xml b/docs/manual/mod/mod_dav_fs.xml
index 547461c..5c411b5 100644
--- a/docs/manual/mod/mod_dav_fs.xml
+++ b/docs/manual/mod/mod_dav_fs.xml
@@ -60,11 +60,12 @@
 
 <usage>
     <p>Use the <directive>DavLockDB</directive> directive to specify
-    the full path to the lock database, excluding an extension. If
-    the path is not absolute, it will be taken relative to <directive
+    the full path to the lock database, excluding an extension. If the
+    path is not absolute, it will be taken relative to <directive
     module="core">ServerRoot</directive>. The implementation of
-    <module>mod_dav_fs</module> uses a SDBM database to track user
-    locks.</p>
+    <module>mod_dav_fs</module> uses a database to track user
+    locks. The type of database file can be changed using
+    <directive module="mod_dav_fs">DavLockDBType</directive>.</p>
 
     <!-- XXX: someone should add that tool to the support directory...
     The utility <code>modules/dav/util/lockview</code> can be used from
@@ -96,6 +97,23 @@
 </directivesynopsis>
 
 <directivesynopsis>
+<name>DavLockDBType</name>
+<description>Database type of the DAV lock database</description>
+<syntax>DavLockDBType <var>dbm-type</var></syntax>
+<contextlist><context>server config</context><context>virtual host</context>
+</contextlist>
+<default>DavLockDBType default</default>
+<compatibility>Available in version 2.5.1 and later.</compatibility>
+<usage>
+    <p>Use the <directive>DavLockDBType</directive> directive to
+    specify the type of the database file. If the directive is not
+    used, the <code>apr_dbm</code> hard-coded default database type is
+    used, which is equivalent to using <code>DavLockDBType default</code>.</p>
+    
+</usage>
+</directivesynopsis>
+
+<directivesynopsis>
 <name>DavLockDiscovery</name>
 <description>Enable lock discovery</description>
 <syntax>DavLockDiscovery on|off</syntax>
diff --git a/modules/dav/fs/dbm.c b/modules/dav/fs/dbm.c
index 4753099..31635db 100644
--- a/modules/dav/fs/dbm.c
+++ b/modules/dav/fs/dbm.c
@@ -47,6 +47,10 @@
 #include "http_log.h"
 #include "http_main.h"      /* for ap_server_conf */
 
+#ifndef DEFAULT_PROPDB_DBM_TYPE
+#define DEFAULT_PROPDB_DBM_TYPE "default"
+#endif
+
 APLOG_USE_MODULE(dav_fs);
 
 struct dav_db {
@@ -129,8 +133,8 @@
 /* dav_dbm_open_direct:  Opens a *dbm database specified by path.
  *    ro = boolean read-only flag.
  */
-dav_error * dav_dbm_open_direct(apr_pool_t *p, const char *pathname, int ro,
-                                dav_db **pdb)
+dav_error * dav_dbm_open_direct(apr_pool_t *p, const char *pathname,
+                                const char *dbmtype, int ro, dav_db **pdb)
 {
 #if APR_MAJOR_VERSION > 1 || (APU_MAJOR_VERSION == 1 && APU_MINOR_VERSION >= 7)
     const apr_dbm_driver_t *driver;
@@ -142,10 +146,10 @@
     *pdb = NULL;
 
 #if APR_MAJOR_VERSION > 1 || (APU_MAJOR_VERSION == 1 && APU_MINOR_VERSION >= 7)
-    if ((status = apr_dbm_get_driver(&driver, NULL, &err, p)) != APR_SUCCESS) {
+    if ((status = apr_dbm_get_driver(&driver, dbmtype, &err, p)) != APR_SUCCESS) {
         ap_log_error(APLOG_MARK, APLOG_ERR, status, ap_server_conf, APLOGNO(10289)
-                     "mod_dav_fs: The DBM library '%s' could not be loaded: %s",
-                             err->reason, err->msg);
+                     "mod_dav_fs: The DBM library '%s' for '%s' could not be loaded: %s",
+                     err->reason, dbmtype, err->msg);
         return dav_new_error(p, HTTP_INTERNAL_SERVER_ERROR, 1, status,
                 "Could not load library for database.");
     }
@@ -156,9 +160,9 @@
         return dav_fs_dbm_error(NULL, p, status);
     }
 #else
-    if ((status = apr_dbm_open(&file, pathname,
-                               ro ? APR_DBM_READONLY : APR_DBM_RWCREATE,
-                               APR_OS_DEFAULT, p))
+    if ((status = apr_dbm_open_ex(&file, dbmtype, pathname,
+                                  ro ? APR_DBM_READONLY : APR_DBM_RWCREATE,
+                                  APR_OS_DEFAULT, p))
                 != APR_SUCCESS
         && !ro) {
         /* ### do something with 'status' */
@@ -206,7 +210,7 @@
 
     /* ### do we need to deal with the umask? */
 
-    return dav_dbm_open_direct(p, pathname, ro, pdb);
+    return dav_dbm_open_direct(p, pathname, DEFAULT_PROPDB_DBM_TYPE, ro, pdb);
 }
 
 void dav_dbm_close(dav_db *db)
diff --git a/modules/dav/fs/lock.c b/modules/dav/fs/lock.c
index 2126b31..c477302 100644
--- a/modules/dav/fs/lock.c
+++ b/modules/dav/fs/lock.c
@@ -182,6 +182,7 @@
     request_rec *r;                  /* for accessing the uuid state */
     apr_pool_t *pool;                /* a pool to use */
     const char *lockdb_path;         /* where is the lock database? */
+    const char *lockdb_type;         /* where is the lock database? */
 
     int opened;                      /* we opened the database */
     dav_db *db;                      /* if non-NULL, the lock database */
@@ -306,6 +307,7 @@
 
     err = dav_dbm_open_direct(lockdb->info->pool,
                               lockdb->info->lockdb_path,
+                              lockdb->info->lockdb_type,
                               lockdb->ro,
                               &lockdb->info->db);
     if (err != NULL) {
@@ -342,7 +344,7 @@
     comb->priv.r = r;
     comb->priv.pool = r->pool;
 
-    comb->priv.lockdb_path = dav_get_lockdb_path(r);
+    comb->priv.lockdb_path = dav_get_lockdb_path(r, &comb->priv.lockdb_type);
     if (comb->priv.lockdb_path == NULL) {
         return dav_new_error(r->pool, HTTP_INTERNAL_SERVER_ERROR,
                              DAV_ERR_LOCK_NO_DB, 0,
diff --git a/modules/dav/fs/mod_dav_fs.c b/modules/dav/fs/mod_dav_fs.c
index 6845d90..f76d21c 100644
--- a/modules/dav/fs/mod_dav_fs.c
+++ b/modules/dav/fs/mod_dav_fs.c
@@ -34,7 +34,7 @@
 /* per-server configuration */
 typedef struct {
     const char *lockdb_path;
-
+    const char *lockdb_type;
 } dav_fs_server_conf;
 
 extern module AP_MODULE_DECLARE_DATA dav_fs_module;
@@ -42,12 +42,19 @@
 #ifndef DEFAULT_DAV_LOCKDB
 #define DEFAULT_DAV_LOCKDB "davlockdb"
 #endif
+#ifndef DEFAULT_DAV_LOCKDB_TYPE
+#define DEFAULT_DAV_LOCKDB_TYPE "default"
+#endif
 
-const char *dav_get_lockdb_path(const request_rec *r)
+
+const char *dav_get_lockdb_path(const request_rec *r, const char **dbmtype)
 {
     dav_fs_server_conf *conf;
 
     conf = ap_get_module_config(r->server->module_config, &dav_fs_module);
+
+    *dbmtype = conf->lockdb_type;
+
     return conf->lockdb_path;
 }
 
@@ -119,6 +126,8 @@
 
     newconf->lockdb_path =
         child->lockdb_path ? child->lockdb_path : parent->lockdb_path;
+    newconf->lockdb_type =
+        child->lockdb_type ? child->lockdb_type : parent->lockdb_type;
 
     return newconf;
 }
@@ -167,6 +176,9 @@
         if (!conf->lockdb_path) {
             conf->lockdb_path = ap_state_dir_relative(p, DEFAULT_DAV_LOCKDB);
         }
+        if (!conf->lockdb_type) {
+            conf->lockdb_type = DEFAULT_DAV_LOCKDB_TYPE;
+        }
     }
 
     return OK;
@@ -192,6 +204,19 @@
 }
 
 /*
+ * Command handler for the DAVLockDBType directive, which is TAKE1
+ */
+static const char *dav_fs_cmd_davlockdbtype(cmd_parms *cmd, void *config,
+                                        const char *arg1)
+{
+    dav_fs_server_conf *conf = ap_get_module_config(cmd->server->module_config,
+                                                    &dav_fs_module);
+    conf->lockdb_type = arg1;
+
+    return NULL;
+}
+
+/*
  * Command handler for the DAVquota directive, which is TAKE1
  */
 static const char *dav_fs_cmd_quota(cmd_parms *cmd, void *config,
@@ -215,6 +240,8 @@
     /* per server */
     AP_INIT_TAKE1("DAVLockDB", dav_fs_cmd_davlockdb, NULL, RSRC_CONF,
                   "specify a lock database"),
+    AP_INIT_TAKE1("DAVLockDBType", dav_fs_cmd_davlockdbtype, NULL, RSRC_CONF,
+                  "specify a lock database DBM type"),
 
     /* per directory */
     AP_INIT_TAKE1("DAVquota", dav_fs_cmd_quota, NULL, ACCESS_CONF|RSRC_CONF,
diff --git a/modules/dav/fs/repos.h b/modules/dav/fs/repos.h
index fa3b138..849ba5f 100644
--- a/modules/dav/fs/repos.h
+++ b/modules/dav/fs/repos.h
@@ -66,8 +66,8 @@
 /* DBM functions used by the repository and locking providers */
 extern const dav_hooks_db dav_hooks_db_dbm;
 
-dav_error * dav_dbm_open_direct(apr_pool_t *p, const char *pathname, int ro,
-                                dav_db **pdb);
+dav_error * dav_dbm_open_direct(apr_pool_t *p, const char *pathname,
+                                const char *dbmtype, int ro, dav_db **pdb);
 void dav_dbm_get_statefiles(apr_pool_t *p, const char *fname,
                             const char **state1, const char **state2);
 dav_error * dav_dbm_delete(dav_db *db, apr_datum_t key);
@@ -77,8 +77,9 @@
 int dav_dbm_exists(dav_db *db, apr_datum_t key);
 void dav_dbm_close(dav_db *db);
 
-/* where is the lock database located? */
-const char *dav_get_lockdb_path(const request_rec *r);
+/* Returns path to lock database and configured dbm type as
+ * *dbmtype. */
+const char *dav_get_lockdb_path(const request_rec *r, const char **dbmtype);
 
 dav_error *dav_fs_get_quota(const request_rec *r, const char *path,
                             apr_off_t *quota_bytes);