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

Re: [PATCH] Support both BDB 4.0 and 4.1

From: Branko Čibej <brane_at_xbc.nu>
Date: 2002-10-22 01:26:49 CEST

Well, it turns out that BDB 4.1 _doesn't_ hang in
fs-test:undelrify_deltify, it's just incredibly slow. I suspect this is
because we're reading file contents 10 bytes at a time, but I have no
idea why it's so much slower than BDB 4.0.

Here's a second version of this patch, slightly cleaned up. I moved
svn_bdb__check_version into its own file, and I realised there's no need
to remember the compile-time DB version in static variables -- those
defines are constants, anyway. I also reverted the include of
bdb_compat.h from the headers that didn't use any of its features.

Added support for building with both Berkeley DB 4.0.14 and 4.1.24.
Based on this patch by Justin Erenkrantz <jerenkrantz@apache.org>:

    http://subversion.tigris.org/servlets/ReadMsg?list=dev&msgNo=22004

[ in subversion/libsvn_fs ]
* bdb/bdb_compat.h: New header. Definitions for BDB 4.0/4.1 compatibility.
* bdb/bdb_compat.c: New file. Implements svn_bdb__check_version.

* bdb/changes-table.c, bdb/copies-table.c, bdb/nodes-table.c, bdb/reps-table.c,
  bdb/rev-table.c, bdb/strings-table.c, bdb/txn-table.c:
Include "bdb_compat.h" instead of <db.h>. In calls to DB->open, wrap
the environment and transaction parameter in SVN_BDB_OPEN_PARAMS. Pass
the SVN_BDB_AUTO_COMMIT flag to DB->open and DB->put wherever the
transaction is NULL. Check the BDB version before each call to
db_create.

* bdb/changes-table.h: Include <db.h> instead of "db.h".

* fs.c: Include bdb/bdb_compat.h.
(check_db_version): New function.
(check_already_open): Extract version check into check_db_version.
(svn_fs_create_berkeley, svn_fs_open_berkeley): Call check_db_version.
(cleanup_fs_db, cleanup_fs): Make usage of DB_INCOMPLETE conditional.

* libsvn_fs.dsp: Add bdb/bdb_compat.c.

[top-level]
* subversion/mod_dav_svn/mod_dav_svn.dsp: Add bdb/bdb_compat.c.

-- 
Brane Čibej   <brane_at_xbc.nu>   http://www.xbc.nu/brane/

cd c:/Home/brane/src/svn/repo/
subversion/clients/cmdline/Debug/svn.exe diff subversion/libsvn_fs
Index: subversion/libsvn_fs/bdb/txn-table.c
===================================================================
--- subversion/libsvn_fs/bdb/txn-table.c (revision 3421)
+++ subversion/libsvn_fs/bdb/txn-table.c (working copy)
@@ -16,8 +16,8 @@
  */
 
 #include <string.h>
-#include <db.h>
 #include <assert.h>
+#include "bdb_compat.h"
 
 #include "svn_pools.h"
 #include "txn-table.h"
@@ -43,11 +43,14 @@
                                  DB_ENV *env,
                                  int create)
 {
+ int open_flags = (create ? (DB_CREATE | DB_EXCL) : 0);
   DB *txns;
 
+ DB_ERR (svn_bdb__check_version());
   DB_ERR (db_create (&txns, env, 0));
- DB_ERR (txns->open (txns, "transactions", 0, DB_BTREE,
- create ? (DB_CREATE | DB_EXCL) : 0,
+ DB_ERR (txns->open (SVN_BDB_OPEN_PARAMS(txns, NULL),
+ "transactions", 0, DB_BTREE,
+ open_flags | SVN_BDB_AUTO_COMMIT,
                       0666));
 
   /* Create the `next-id' table entry. */
@@ -59,7 +62,7 @@
                        svn_fs__str_to_dbt (&key,
                                            (char *) svn_fs__next_key_key),
                        svn_fs__str_to_dbt (&value, (char *) "0"),
- 0));
+ SVN_BDB_AUTO_COMMIT));
   }
 
   *transactions_p = txns;
Index: subversion/libsvn_fs/bdb/reps-table.c
===================================================================
--- subversion/libsvn_fs/bdb/reps-table.c (revision 3421)
+++ subversion/libsvn_fs/bdb/reps-table.c (working copy)
@@ -15,7 +15,7 @@
  * ====================================================================
  */
 
-#include <db.h>
+#include "bdb_compat.h"
 #include "svn_fs.h"
 #include "../fs.h"
 #include "../util/fs_skels.h"
@@ -35,11 +35,14 @@
                          DB_ENV *env,
                          int create)
 {
+ int open_flags = (create ? (DB_CREATE | DB_EXCL) : 0);
   DB *reps;
 
+ DB_ERR (svn_bdb__check_version());
   DB_ERR (db_create (&reps, env, 0));
- DB_ERR (reps->open (reps, "representations", 0, DB_BTREE,
- create ? (DB_CREATE | DB_EXCL) : 0,
+ DB_ERR (reps->open (SVN_BDB_OPEN_PARAMS(reps, NULL),
+ "representations", 0, DB_BTREE,
+ open_flags | SVN_BDB_AUTO_COMMIT,
                       0666));
 
   /* Create the `next-key' table entry. */
@@ -51,7 +54,7 @@
             (reps, 0,
              svn_fs__str_to_dbt (&key, (char *) svn_fs__next_key_key),
              svn_fs__str_to_dbt (&value, (char *) "0"),
- 0));
+ SVN_BDB_AUTO_COMMIT));
   }
 
   *reps_p = reps;
Index: subversion/libsvn_fs/bdb/bdb_compat.h
===================================================================
--- subversion/libsvn_fs/bdb/bdb_compat.h (working copy)
+++ subversion/libsvn_fs/bdb/bdb_compat.h (working copy)
@@ -0,0 +1,72 @@
+/* svn_bdb_compat.h --- Compatibility wrapper for different BDB versions.
+ *
+ * ====================================================================
+ * Copyright (c) 2000-2002 CollabNet. All rights reserved.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://subversion.tigris.org/license-1.html.
+ * If newer versions of this license are posted there, you may use a
+ * newer version instead, at your option.
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals. For exact contribution history, see the revision
+ * history and logs, available at http://subversion.tigris.org/.
+ * ====================================================================
+ */
+
+#ifndef SVN_LIBSVN_FS_BDB_COMPAT_H
+#define SVN_LIBSVN_FS_BDB_COMPAT_H
+
+#include <db.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+
+/* BDB 4.1 introduced the DB_AUTO_COMMIT flag. Older versions can just
+ use 0 instead. */
+#ifdef DB_AUTO_COMMIT
+#define SVN_BDB_AUTO_COMMIT (DB_AUTO_COMMIT)
+#else
+#define SVN_BDB_AUTO_COMMIT (0)
+#endif
+
+/* DB_INCOMPLETE is obsolete in BDB 4.1. */
+#ifdef DB_INCOMPLETE
+#define SVN_BDB_HAS_DB_INCOMPLETE 1
+#else
+#define SVN_BDB_HAS_DB_INCOMPLETE 0
+#endif
+
+/* In BDB 4.1, DB->open takes a transaction parameter. We'll ignore it
+ when building with 4.0. */
+#if (DB_VERSION_MAJOR > 4) \
+ || (DB_VERSION_MAJOR == 4) && (DB_VERSION_MINOR >= 1)
+#define SVN_BDB_OPEN_PARAMS(env,txn) (env), (txn)
+#else
+#define SVN_BDB_OPEN_PARAMS(env,txn) (env)
+#endif
+
+
+/* Before calling db_create, we must check that the version of the BDB
+ libraries we're linking with is the same as the one we compiled
+ against, because the DB->open call is not binary compatible between
+ BDB 4.0 and 4.1. This function returns DB_OLD_VERSION if the
+ compile-time and run-time versions of BDB don't match. */
+int svn_bdb__check_version (void);
+
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* SVN_LIBSVN_FS_BDB_COMPAT_H */
+
+
+/*
+ * local variables:
+ * eval: (load-file "../../../tools/dev/svn-dev.el")
+ * end:
+ */
Index: subversion/libsvn_fs/bdb/changes-table.h
===================================================================
--- subversion/libsvn_fs/bdb/changes-table.h (revision 3421)
+++ subversion/libsvn_fs/bdb/changes-table.h (working copy)
@@ -18,7 +18,7 @@
 #ifndef SVN_LIBSVN_FS_CHANGES_TABLE_H
 #define SVN_LIBSVN_FS_CHANGES_TABLE_H
 
-#include "db.h"
+#include <db.h>
 #include "svn_io.h"
 #include "svn_fs.h"
 #include "../trail.h"
Index: subversion/libsvn_fs/bdb/copies-table.c
===================================================================
--- subversion/libsvn_fs/bdb/copies-table.c (revision 3421)
+++ subversion/libsvn_fs/bdb/copies-table.c (working copy)
@@ -17,7 +17,7 @@
 
 #include <string.h>
 
-#include <db.h>
+#include "bdb_compat.h"
 #include "../fs.h"
 #include "../err.h"
 #include "../key-gen.h"
@@ -35,11 +35,14 @@
                            DB_ENV *env,
                            int create)
 {
+ int open_flags = (create ? (DB_CREATE | DB_EXCL) : 0);
   DB *copies;
 
+ DB_ERR (svn_bdb__check_version());
   DB_ERR (db_create (&copies, env, 0));
- DB_ERR (copies->open (copies, "copies", 0, DB_BTREE,
- create ? (DB_CREATE | DB_EXCL) : 0,
+ DB_ERR (copies->open (SVN_BDB_OPEN_PARAMS(copies, NULL),
+ "copies", 0, DB_BTREE,
+ open_flags | SVN_BDB_AUTO_COMMIT,
                         0666));
 
   /* Create the initial `next-id' table entry. */
@@ -50,7 +53,7 @@
                          svn_fs__str_to_dbt (&key,
                                              (char *) svn_fs__next_key_key),
                          svn_fs__str_to_dbt (&value, (char *) "0"),
- 0));
+ SVN_BDB_AUTO_COMMIT));
   }
 
   *copies_p = copies;
Index: subversion/libsvn_fs/bdb/strings-table.c
===================================================================
--- subversion/libsvn_fs/bdb/strings-table.c (revision 3421)
+++ subversion/libsvn_fs/bdb/strings-table.c (working copy)
@@ -15,7 +15,7 @@
  * ====================================================================
  */
 
-#include <db.h>
+#include "bdb_compat.h"
 #include "svn_fs.h"
 #include "svn_pools.h"
 #include "../fs.h"
@@ -33,17 +33,20 @@
                             DB_ENV *env,
                             int create)
 {
+ int open_flags = (create ? (DB_CREATE | DB_EXCL) : 0);
   DB *strings;
 
+ DB_ERR (svn_bdb__check_version());
   DB_ERR (db_create (&strings, env, 0));
 
   /* Enable duplicate keys. This allows the data to be spread out across
      multiple records. Note: this must occur before ->open(). */
   DB_ERR (strings->set_flags (strings, DB_DUP));
 
- DB_ERR (strings->open (strings, "strings", 0, DB_BTREE,
- create ? (DB_CREATE | DB_EXCL) : 0,
- 0666));
+ DB_ERR (strings->open (SVN_BDB_OPEN_PARAMS(strings, NULL),
+ "strings", 0, DB_BTREE,
+ open_flags | SVN_BDB_AUTO_COMMIT,
+ 0666));
 
   if (create)
   {
@@ -54,7 +57,7 @@
             (strings, 0,
              svn_fs__str_to_dbt (&key, (char *) svn_fs__next_key_key),
              svn_fs__str_to_dbt (&value, (char *) "0"),
- 0));
+ SVN_BDB_AUTO_COMMIT));
   }
   
   *strings_p = strings;
Index: subversion/libsvn_fs/bdb/rev-table.c
===================================================================
--- subversion/libsvn_fs/bdb/rev-table.c (revision 3421)
+++ subversion/libsvn_fs/bdb/rev-table.c (working copy)
@@ -15,7 +15,7 @@
  * ====================================================================
  */
 
-#include <db.h>
+#include "bdb_compat.h"
 #include "svn_fs.h"
 #include "../fs.h"
 #include "../err.h"
@@ -31,11 +31,14 @@
                                   DB_ENV *env,
                                   int create)
 {
+ int open_flags = (create ? (DB_CREATE | DB_EXCL) : 0);
   DB *revisions;
 
+ DB_ERR (svn_bdb__check_version());
   DB_ERR (db_create (&revisions, env, 0));
- DB_ERR (revisions->open (revisions, "revisions", 0, DB_RECNO,
- create ? (DB_CREATE | DB_EXCL) : 0,
+ DB_ERR (revisions->open (SVN_BDB_OPEN_PARAMS(revisions, NULL),
+ "revisions", 0, DB_RECNO,
+ open_flags | SVN_BDB_AUTO_COMMIT,
                            0666));
 
   *revisions_p = revisions;
Index: subversion/libsvn_fs/bdb/bdb_compat.c
===================================================================
--- subversion/libsvn_fs/bdb/bdb_compat.c (working copy)
+++ subversion/libsvn_fs/bdb/bdb_compat.c (working copy)
@@ -0,0 +1,37 @@
+/* bdb_compat.c --- Compatibility wrapper for different BDB versions.
+ *
+ * ====================================================================
+ * Copyright (c) 2000-2002 CollabNet. All rights reserved.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://subversion.tigris.org/license-1.html.
+ * If newer versions of this license are posted there, you may use a
+ * newer version instead, at your option.
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals. For exact contribution history, see the revision
+ * history and logs, available at http://subversion.tigris.org/.
+ * ====================================================================
+ */
+
+#include "bdb_compat.h"
+
+int
+svn_bdb__check_version (void)
+{
+ int major, minor;
+
+ db_version(&major, &minor, NULL);
+ if (major != DB_VERSION_MAJOR || minor != DB_VERSION_MINOR)
+ return DB_OLD_VERSION;
+ return 0;
+}
+
+
+
+/*
+ * local variables:
+ * eval: (load-file "../../../tools/dev/svn-dev.el")
+ * end:
+ */
Index: subversion/libsvn_fs/bdb/changes-table.c
===================================================================
--- subversion/libsvn_fs/bdb/changes-table.c (revision 3421)
+++ subversion/libsvn_fs/bdb/changes-table.c (working copy)
@@ -15,7 +15,7 @@
  * ====================================================================
  */
 
-#include <db.h>
+#include "bdb_compat.h"
 
 #include <apr_hash.h>
 #include <apr_tables.h>
@@ -39,16 +39,19 @@
                             DB_ENV *env,
                             int create)
 {
+ int open_flags = (create ? (DB_CREATE | DB_EXCL) : 0);
   DB *changes;
 
+ DB_ERR (svn_bdb__check_version());
   DB_ERR (db_create (&changes, env, 0));
 
   /* Enable duplicate keys. This allows us to store the changes
      one-per-row. Note: this must occur before ->open(). */
   DB_ERR (changes->set_flags (changes, DB_DUP));
 
- DB_ERR (changes->open (changes, "changes", 0, DB_BTREE,
- create ? (DB_CREATE | DB_EXCL) : 0,
+ DB_ERR (changes->open (SVN_BDB_OPEN_PARAMS(changes, NULL),
+ "changes", 0, DB_BTREE,
+ open_flags | SVN_BDB_AUTO_COMMIT,
                          0666));
 
   *changes_p = changes;
Index: subversion/libsvn_fs/bdb/nodes-table.c
===================================================================
--- subversion/libsvn_fs/bdb/nodes-table.c (revision 3421)
+++ subversion/libsvn_fs/bdb/nodes-table.c (working copy)
@@ -17,7 +17,7 @@
 
 #include <string.h>
 #include <assert.h>
-#include <db.h>
+#include "bdb_compat.h"
 
 #include "svn_fs.h"
 
@@ -41,11 +41,14 @@
                           DB_ENV *env,
                           int create)
 {
+ int open_flags = (create ? (DB_CREATE | DB_EXCL) : 0);
   DB *nodes;
 
+ DB_ERR (svn_bdb__check_version());
   DB_ERR (db_create (&nodes, env, 0));
- DB_ERR (nodes->open (nodes, "nodes", 0, DB_BTREE,
- create ? (DB_CREATE | DB_EXCL) : 0,
+ DB_ERR (nodes->open (SVN_BDB_OPEN_PARAMS(nodes, NULL),
+ "nodes", 0, DB_BTREE,
+ open_flags | SVN_BDB_AUTO_COMMIT,
                        0666));
 
   /* Create the `next-id' table entry (use '1' because '0' is
@@ -58,7 +61,7 @@
                         svn_fs__str_to_dbt (&key,
                                             (char *) svn_fs__next_key_key),
                         svn_fs__str_to_dbt (&value, (char *) "1"),
- 0));
+ SVN_BDB_AUTO_COMMIT));
   }
 
   *nodes_p = nodes;
Index: subversion/libsvn_fs/fs.c
===================================================================
--- subversion/libsvn_fs/fs.c (revision 3421)
+++ subversion/libsvn_fs/fs.c (working copy)
@@ -34,6 +34,7 @@
 #include "dag.h"
 #include "svn_private_config.h"
 
+#include "bdb/bdb_compat.h"
 #include "bdb/nodes-table.h"
 #include "bdb/rev-table.h"
 #include "bdb/txn-table.h"
@@ -45,28 +46,48 @@
 
 /* Checking for return values, and reporting errors. */
 
-
-/* If FS is already open, then return an SVN_ERR_FS_ALREADY_OPEN
- error. Otherwise, return zero. */
+/* Check that we're using the right Berkeley DB version. */
+/* FIXME: This check should be abstracted into the DB back-end layer. */
 static svn_error_t *
-check_already_open (svn_fs_t *fs)
+check_bdb_version (apr_pool_t *pool)
 {
   int major, minor, patch;
 
- /* ### check_already_open() doesn't truly have the right semantic for
- ### this, but it is called by both create_berkeley and open_berkeley,
- ### so it happens to be a low-cost point. probably should be
- ### refactored to go elsewhere. note that svn_fs_new() doesn't return
- ### an error, so it isn't quite suitable. */
   db_version (&major, &minor, &patch);
+
+ /* First, check that we're using a reasonably correct of Berkeley DB. */
   if ((major < SVN_FS_WANT_DB_MAJOR)
       || (major == SVN_FS_WANT_DB_MAJOR && minor < SVN_FS_WANT_DB_MINOR)
       || (major == SVN_FS_WANT_DB_MAJOR && minor == SVN_FS_WANT_DB_MINOR
           && patch < SVN_FS_WANT_DB_PATCH))
- return svn_error_createf (SVN_ERR_FS_GENERAL, 0, 0, fs->pool,
- "bad database version: %d.%d.%d",
+ return svn_error_createf (SVN_ERR_FS_GENERAL, 0, 0, pool,
+ "bad database version: got %d.%d.%d,"
+ " should be at least %d.%d.%d",
+ major, minor, patch,
+ SVN_FS_WANT_DB_MAJOR,
+ SVN_FS_WANT_DB_MINOR,
+ SVN_FS_WANT_DB_PATCH);
+
+ /* Now, check that the version we're running against is the same as
+ the one we compiled with. */
+ if (major != DB_VERSION_MAJOR || minor != DB_VERSION_MINOR)
+ return svn_error_createf (SVN_ERR_FS_GENERAL, 0, 0, pool,
+ "bad database version:"
+ " compiled with %d.%d.%d,"
+ " running against %d.%d.%d",
+ DB_VERSION_MAJOR,
+ DB_VERSION_MINOR,
+ DB_VERSION_PATCH,
                               major, minor, patch);
+ return SVN_NO_ERROR;
+}
 
+
+/* If FS is already open, then return an SVN_ERR_FS_ALREADY_OPEN
+ error. Otherwise, return zero. */
+static svn_error_t *
+check_already_open (svn_fs_t *fs)
+{
   if (fs->env)
     return svn_error_create (SVN_ERR_FS_ALREADY_OPEN, 0, 0, fs->pool,
                              "filesystem object already open");
@@ -104,6 +125,7 @@
       *db_ptr = 0;
       db_err = db->close (db, 0);
 
+#if SVN_BDB_HAS_DB_INCOMPLETE
       /* We can ignore DB_INCOMPLETE on db->close and db->sync; it
        * just means someone else was using the db at the same time
        * we were. See the Berkeley documentation at:
@@ -112,6 +134,7 @@
        */
       if (db_err == DB_INCOMPLETE)
         db_err = 0;
+#endif /* SVN_BDB_HAS_DB_INCOMPLETE */
 
       SVN_ERR (DB_WRAP (fs, msg, db_err));
     }
@@ -141,11 +164,13 @@
   {
     int db_err = env->txn_checkpoint (env, 0, 0, 0);
 
+#if SVN_BDB_HAS_DB_INCOMPLETE
     while (db_err == DB_INCOMPLETE)
       {
         apr_sleep (APR_USEC_PER_SEC * 1);
         db_err = env->txn_checkpoint (env, 0, 0, 0);
       }
+#endif /* SVN_BDB_HAS_DB_INCOMPLETE */
 
     /* If the environment was not (properly) opened, then txn_checkpoint
        will typically return EINVAL. Ignore this case.
@@ -383,6 +408,7 @@
   svn_error_t *svn_err;
   const char *path_native;
 
+ SVN_ERR (check_bdb_version (fs->pool));
   SVN_ERR (check_already_open (fs));
 
   /* Initialize the fs's path. */
@@ -519,6 +545,7 @@
   svn_error_t *svn_err;
   const char *path_native;
 
+ SVN_ERR (check_bdb_version (fs->pool));
   SVN_ERR (check_already_open (fs));
 
   /* Initialize paths. */
Index: subversion/libsvn_fs/libsvn_fs.dsp
===================================================================
--- subversion/libsvn_fs/libsvn_fs.dsp (revision 3421)
+++ subversion/libsvn_fs/libsvn_fs.dsp (working copy)
@@ -139,6 +139,21 @@
 # End Source File
 # Begin Source File
 
+SOURCE=".\bdb\bdb_compat.c"
+
+!IF "$(CFG)" == "libsvn_fs - Win32 Release"
+
+# PROP Intermediate_Dir "Release\obj\bdb"
+
+!ELSEIF "$(CFG)" == "libsvn_fs - Win32 Debug"
+
+# PROP Intermediate_Dir "Debug\obj\bdb"
+
+!ENDIF
+
+# End Source File
+# Begin Source File
+
 SOURCE=".\bdb\copies-table.c"
 
 !IF "$(CFG)" == "libsvn_fs - Win32 Release"

Compilation finished at Tue Oct 22 01:21:39

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@subversion.tigris.org
For additional commands, e-mail: dev-help@subversion.tigris.org
Received on Tue Oct 22 01:27:36 2002

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

This site is subject to the Apache Privacy Policy and the Apache Public Forum Archive Policy.