From 1782ca34c84f974342278bc8fdc30c7aab008e70 Mon Sep 17 00:00:00 2001
From: Noriko Hosoi <nhosoi@ponyo.sjc.redhat.com>
Date: Fri, 10 Feb 2012 10:41:41 -0800
Subject: [PATCH] Trac Ticket #169 - allow 389 to use db5

https://fedorahosted.org/389/ticket/169

Fix description:
1. DB suffix ".db4" is changed to ".db" if the server is linked
   with db5 (libdb); it remains ".db4" if linked with db4.
2. Fixed DB_VERSION macro to pick up the correct APIs for db5.
3. DB upgrade flag DBVERSION_UPGRADE_4_5 is introduced and set
   once it is found the db4 to db5 upgrade is necessary.
   Upgrade from db4 to 5 requires cleaning up the region files
   (__db.##) then update transaction log files.  The database
   files are compatible.
4. Added a code to db.m4 to check /usr/include/libdb/db.h.
   If /usr/include/db4/db.h does not exists AND libdb does,
   the db5 (libdb) header file is used.
   Note: package db4-devel and libdb-devel cannot coexist.
---
 ldap/servers/plugins/replication/cl5_api.c |    6 +-
 ldap/servers/slapd/back-ldbm/back-ldbm.h   |   12 +++++-
 ldap/servers/slapd/back-ldbm/dblayer.c     |   13 ++++--
 ldap/servers/slapd/back-ldbm/perfctrs.c    |    2 +-
 ldap/servers/slapd/back-ldbm/start.c       |    3 +-
 ldap/servers/slapd/back-ldbm/upgrade.c     |   56 ++++++++++++++--------------
 m4/db.m4                                   |    6 +++
 7 files changed, 59 insertions(+), 39 deletions(-)

diff --git a/ldap/servers/plugins/replication/cl5_api.c b/ldap/servers/plugins/replication/cl5_api.c
index 0ea90d1..3c02d41 100644
--- a/ldap/servers/plugins/replication/cl5_api.c
+++ b/ldap/servers/plugins/replication/cl5_api.c
@@ -121,13 +121,13 @@
 #define TXN_ABORT(txn) (txn)->abort(txn)
 #define MEMP_STAT(env, gsp, fsp, flags, malloc) \
 	(env)->memp_stat((env), (gsp), (fsp), (flags))
-#if DB_VERSION_MINOR >= 4 /* i.e. 4.4 or later */
+#if 1000*DB_VERSION_MAJOR + 100*DB_VERSION_MINOR >= 4400 /* db4.4 or later */
 #define DB_ENV_SET_TAS_SPINS(env, tas_spins) \
     (env)->mutex_set_tas_spins((env), (tas_spins))
-#else /* < 4.4 */
+#else
 #define DB_ENV_SET_TAS_SPINS(env, tas_spins) \
     (env)->set_tas_spins((env), (tas_spins))
-#endif /* 4.4 or later */
+#endif
 
 #else	/* older than db 4.0 */
 #define DB_ENV_SET_REGION_INIT(env) db_env_set_region_init(1)
diff --git a/ldap/servers/slapd/back-ldbm/back-ldbm.h b/ldap/servers/slapd/back-ldbm/back-ldbm.h
index f11ec82..fb45a9f 100644
--- a/ldap/servers/slapd/back-ldbm/back-ldbm.h
+++ b/ldap/servers/slapd/back-ldbm/back-ldbm.h
@@ -126,8 +126,16 @@ typedef unsigned short u_int16_t;
 
 #define ID2ENTRY "id2entry"	/* main db file name: ID2ENTRY+LDBM_SUFFIX */
 
+#if 1000*DB_VERSION_MAJOR + 100*DB_VERSION_MINOR >= 5000
+#define LDBM_SUFFIX_OLD	".db4"
+#define LDBM_SUFFIX	".db"
+#elif 1000*DB_VERSION_MAJOR + 100*DB_VERSION_MINOR >= 4000
 #define LDBM_SUFFIX_OLD	".db3"
 #define LDBM_SUFFIX	".db4"
+#else /* not supported anymore, though */
+#define LDBM_SUFFIX_OLD	".db2"
+#define LDBM_SUFFIX	".db3"
+#endif
 
 #define MEGABYTE (1024 * 1024)
 #define GIGABYTE (1024 * MEGABYTE)
@@ -193,7 +201,7 @@ typedef unsigned short u_int16_t;
 #define LDBM_VERSION_40          "Netscape-ldbm/4.0"
 #define LDBM_VERSION_30          "Netscape-ldbm/3.0"
 #define LDBM_VERSION_31          "Netscape-ldbm/3.1"
-#define LDBM_FILENAME_SUFFIX     ".db4"
+#define LDBM_FILENAME_SUFFIX     LDBM_SUFFIX
 #define    DBVERSION_FILENAME    "DBVERSION"
 #define DEFAULT_CACHE_SIZE       (size_t)10485760
 #define DEFAULT_CACHE_ENTRIES    -1        /* no limit */
@@ -520,6 +528,7 @@ struct _db_upgrade_info {
 	int old_dbversion_minor;
 	int type;
 	int action;
+	int is_dbd;
 };
 typedef struct _db_upgrade_info db_upgrade_info;
 /* Values for dbversion_stuff->type */
@@ -544,6 +553,7 @@ typedef struct _db_upgrade_info db_upgrade_info;
                                           * No database formats changed;
                                           * no db extention change
                                           */
+#define DBVERSION_UPGRADE_4_5      0x4000 /* bdb 4.X -> 5.X */
 #define DBVERSION_NEED_DN2RDN      0x1000/* DN to RDN (subtree-rename) format */
 #define DBVERSION_NEED_RDN2DN      0x2000/* RDN to DN (original) format */
 #define DBVERSION_NOT_SUPPORTED    0x10000000
diff --git a/ldap/servers/slapd/back-ldbm/dblayer.c b/ldap/servers/slapd/back-ldbm/dblayer.c
index 998beba..a763e05 100644
--- a/ldap/servers/slapd/back-ldbm/dblayer.c
+++ b/ldap/servers/slapd/back-ldbm/dblayer.c
@@ -136,7 +136,7 @@
 #define LOG_FLUSH(env, lsn) (env)->log_flush((env), (lsn))
 #define LOCK_DETECT(env, flags, atype, aborted) \
     (env)->lock_detect((env), (flags), (atype), (aborted))
-#if DB_VERSION_MINOR >= 4 /* i.e. 4.4 or later */
+#if 1000*DB_VERSION_MAJOR + 100*DB_VERSION_MINOR >= 4000 /* db4.4 or later */
 #define DB_ENV_SET_TAS_SPINS(env, tas_spins) \
     (env)->mutex_set_tas_spins((env), (tas_spins))
 #else /* < 4.4 */
@@ -1418,7 +1418,8 @@ no_diskspace(struct ldbminfo *li)
 #define DBCONFLEN    3
 #define CATASTROPHIC (struct dblayer_private_env *)-1
 
-int dblayer_start(struct ldbminfo *li, int dbmode)
+int
+dblayer_start(struct ldbminfo *li, int dbmode)
 {
     /* 
      * So, here we open our DB_ENV session. We store it away for future use.
@@ -5067,8 +5068,9 @@ dblayer_copy_directory(struct ldbminfo *li,
         }
         compare_piece = (char *)direntry->name + offset;
 
-        if (0 == strcmp(compare_piece, LDBM_FILENAME_SUFFIX) || /* .db4 */
-            0 == strcmp(compare_piece, LDBM_SUFFIX_OLD) || /* support .db3 */
+        /* rename .db3 -> .db4 or .db4 -> .db */
+        if (0 == strcmp(compare_piece, LDBM_FILENAME_SUFFIX) ||
+            0 == strcmp(compare_piece, LDBM_SUFFIX_OLD) ||
             0 == strcmp(direntry->name, DBVERSION_FILENAME)) {
             /* Found a database file.  Copy it. */
 
@@ -6158,7 +6160,8 @@ int dblayer_restore(struct ldbminfo *li, char *src_dir, Slapi_Task *task, char *
     }
 
     return_value = check_db_version(li, &action);
-    if (action & (DBVERSION_UPGRADE_3_4|DBVERSION_UPGRADE_4_4))
+    if (action &
+        (DBVERSION_UPGRADE_3_4|DBVERSION_UPGRADE_4_4|DBVERSION_UPGRADE_4_5))
     {
         dbmode = DBLAYER_CLEAN_RECOVER_MODE;/* upgrade: remove logs & recover */
     }
diff --git a/ldap/servers/slapd/back-ldbm/perfctrs.c b/ldap/servers/slapd/back-ldbm/perfctrs.c
index 27efb7d..a1957db 100644
--- a/ldap/servers/slapd/back-ldbm/perfctrs.c
+++ b/ldap/servers/slapd/back-ldbm/perfctrs.c
@@ -53,7 +53,7 @@
 #define LOG_STAT(env, spp, flags, malloc) (env)->log_stat((env), (spp), (flags))
 #define LOCK_STAT(env, statp, flags, malloc) \
 	(env)->lock_stat((env), (statp), (flags))
-#if DB_VERSION_MINOR >= 4 /* i.e. 4.4 or later */
+#if 1000*DB_VERSION_MAJOR + 100*DB_VERSION_MINOR >= 4400 /* db4.4 or later */
 #define GET_N_LOCK_WAITS(lockstat)   lockstat->st_lock_wait
 #else
 #define GET_N_LOCK_WAITS(lockstat)   lockstat->st_nconflicts
diff --git a/ldap/servers/slapd/back-ldbm/start.c b/ldap/servers/slapd/back-ldbm/start.c
index dabbca5..61146fe 100644
--- a/ldap/servers/slapd/back-ldbm/start.c
+++ b/ldap/servers/slapd/back-ldbm/start.c
@@ -205,7 +205,8 @@ ldbm_back_start( Slapi_PBlock *pb )
       return SLAPI_FAIL_GENERAL;
   }
 
-  if (action & (DBVERSION_UPGRADE_3_4|DBVERSION_UPGRADE_4_4))
+  if (action &
+      (DBVERSION_UPGRADE_3_4|DBVERSION_UPGRADE_4_4|DBVERSION_UPGRADE_4_5))
   {
       retval = dblayer_start(li,DBLAYER_CLEAN_RECOVER_MODE);
   }
diff --git a/ldap/servers/slapd/back-ldbm/upgrade.c b/ldap/servers/slapd/back-ldbm/upgrade.c
index a70cfd5..a10ee9b 100644
--- a/ldap/servers/slapd/back-ldbm/upgrade.c
+++ b/ldap/servers/slapd/back-ldbm/upgrade.c
@@ -62,13 +62,13 @@ db_upgrade_info ldbm_version_suss[] = {
      */
     /* for bdb/#.#/..., we don't have to put the version number in the 2nd col
        since DBVERSION keeps it */
-    {BDB_IMPL,         0, 0, DBVERSION_NEW_IDL, DBVERSION_NO_UPGRADE},
-    {LDBM_VERSION,     4, 2, DBVERSION_NEW_IDL, DBVERSION_NO_UPGRADE},
-    {LDBM_VERSION_OLD, 4, 2, DBVERSION_OLD_IDL, DBVERSION_NO_UPGRADE}, 
-    {LDBM_VERSION_62,  4, 2, DBVERSION_OLD_IDL, DBVERSION_NO_UPGRADE}, 
-    {LDBM_VERSION_61,  3, 3, DBVERSION_OLD_IDL, DBVERSION_UPGRADE_3_4}, 
-    {LDBM_VERSION_60,  3, 3, DBVERSION_OLD_IDL, DBVERSION_UPGRADE_3_4}, 
-    {NULL,             0, 0, 0,                 0                    }
+    {BDB_IMPL,         4, 0, DBVERSION_NEW_IDL, DBVERSION_UPGRADE_4_5, 1},
+    {LDBM_VERSION,     4, 2, DBVERSION_NEW_IDL, DBVERSION_NO_UPGRADE,  0},
+    {LDBM_VERSION_OLD, 4, 2, DBVERSION_OLD_IDL, DBVERSION_NO_UPGRADE,  0}, 
+    {LDBM_VERSION_62,  4, 2, DBVERSION_OLD_IDL, DBVERSION_NO_UPGRADE,  0}, 
+    {LDBM_VERSION_61,  3, 3, DBVERSION_OLD_IDL, DBVERSION_UPGRADE_3_4, 0}, 
+    {LDBM_VERSION_60,  3, 3, DBVERSION_OLD_IDL, DBVERSION_UPGRADE_3_4, 0}, 
+    {NULL,             0, 0, 0,                 0,                     0}
 };
 
 
@@ -105,7 +105,7 @@ lookup_dbversion(char *dbversion, int flag)
         if ( flag & DBVERSION_ACTION ) /* lookup request for action */
         {
             int dbmajor = 0, dbminor = 0;
-            if (0 == ldbm_version_suss[i].old_dbversion_major)
+            if (ldbm_version_suss[i].is_dbd)
             {
                 /* case of bdb/#.#/... */
                 char *p = strchr(dbversion, '/');
@@ -132,7 +132,7 @@ lookup_dbversion(char *dbversion, int flag)
             }
             if (dbmajor < DB_VERSION_MAJOR)
             {
-                /* 3.3 -> 4.x */
+                /* 3 -> 4 or 5 -> 6 */
                 rval |= ldbm_version_suss[i].action;
             }
             else if (dbminor < DB_VERSION_MINOR)
@@ -156,6 +156,7 @@ lookup_dbversion(char *dbversion, int flag)
  * action: 0: nothing is needed
  *         DBVERSION_UPGRADE_3_4: db3->db4 uprev is needed
  *         DBVERSION_UPGRADE_4_4: db4->db4 uprev is needed
+ *         DBVERSION_UPGRADE_4_5: db4->db  uprev is needed
  */
 int
 check_db_version( struct ldbminfo *li, int *action )
@@ -195,6 +196,11 @@ check_db_version( struct ldbminfo *li, int *action )
         dblayer_set_recovery_required(li);
         *action = DBVERSION_UPGRADE_4_4;
     }
+    else if ( value & DBVERSION_UPGRADE_4_5 )
+    {
+        dblayer_set_recovery_required(li);
+        *action = DBVERSION_UPGRADE_4_5;
+    }
     if (value & DBVERSION_RDN_FORMAT) {
         if (entryrdn_get_switch()) {
             /* nothing to do */
@@ -228,6 +234,7 @@ check_db_version( struct ldbminfo *li, int *action )
  *
  *         DBVERSION_UPGRADE_3_4: db3->db4 uprev is needed
  *         DBVERSION_UPGRADE_4_4: db4->db4 uprev is needed
+ *         DBVERSION_UPGRADE_4_5: db4->db  uprev is needed
  */
 int
 check_db_inst_version( ldbm_instance *inst )
@@ -280,6 +287,10 @@ check_db_inst_version( ldbm_instance *inst )
     {
         rval |= DBVERSION_UPGRADE_4_4;
     }
+    else if ( value & DBVERSION_UPGRADE_4_5 )
+    {
+        rval |= DBVERSION_UPGRADE_4_5;
+    }
     if (value & DBVERSION_RDN_FORMAT) {
         if (entryrdn_get_switch()) {
             /* nothing to do */
@@ -363,36 +374,25 @@ int ldbm_upgrade(ldbm_instance *inst, int action)
         return rval;
     }
 
-    if (action & DBVERSION_UPGRADE_3_4)    /* upgrade from db3 to db4 */
+    /* upgrade from db3 to db4 or db4 to db5 */
+    if (action & (DBVERSION_UPGRADE_3_4|DBVERSION_UPGRADE_4_5))
     {
-        /* basically, db4 supports db3.
-         * so, what we need to do is rename XXX.db3 to XXX.db4 */
-
-        int rval = dblayer_update_db_ext(inst, LDBM_SUFFIX_OLD, LDBM_SUFFIX);
+        rval = dblayer_update_db_ext(inst, LDBM_SUFFIX_OLD, LDBM_SUFFIX);
         if (0 == rval)
         {
-            if (idl_get_idl_new())
-            {
-                 LDAPDebug(LDAP_DEBUG_ANY, 
-                   "ldbm_upgrade: Upgrading instance %s to %s%s is successfully done.\n",
-                   inst->inst_name, LDBM_VERSION_BASE, DS_PACKAGE_VERSION);
-            }
-            else
-            {
-                 LDAPDebug(LDAP_DEBUG_ANY, 
-                   "ldbm_upgrade: Upgrading instance %s to %s%s is successfully done.\n",
-                   inst->inst_name, LDBM_VERSION_OLD, 0);
-            }
+            LDAPDebug(LDAP_DEBUG_ANY, "ldbm_upgrade: "
+                      "Upgrading instance %s supporting bdb %d.%d "
+                      "was successfully done.\n",
+                      inst->inst_name, DB_VERSION_MAJOR, DB_VERSION_MINOR);
         }
         else
         {
             /* recovery effort ... */
             dblayer_update_db_ext(inst, LDBM_SUFFIX, LDBM_SUFFIX_OLD);
-            return rval;
         }
     }
 
-    return 0; /* Means that the database is new */
+    return rval;
 }
 
 /* Here's the upgrade process : 
diff --git a/m4/db.m4 b/m4/db.m4
index 7b300f4..6a4a756 100644
--- a/m4/db.m4
+++ b/m4/db.m4
@@ -89,6 +89,12 @@ if test -z "$db_inc"; then
     db_inc="-I/usr/include/db4"
     db_lib='-L$(libdir)'
     db_libdir='$(libdir)'
+  elif test -f "/usr/include/libdb/db.h"; then
+    AC_MSG_RESULT([using /usr/include/libdb/db.h])
+    db_incdir="/usr/include/libdb"
+    db_inc="-I/usr/include/libdb"
+    db_lib='-L$(libdir)'
+    db_libdir='$(libdir)'
   elif test -f "/usr/include/db.h"; then
     AC_MSG_RESULT([using /usr/include/db.h])
     db_incdir="/usr/include"
-- 
1.7.7.6

