Blob Blame Raw
From 59266365eda8130abf6901263efae4c87586376a Mon Sep 17 00:00:00 2001
From: Thierry Bordaz <tbordaz@redhat.com>
Date: Mon, 28 Jun 2021 16:40:15 +0200
Subject: [PATCH] Issue 4814 - _cl5_get_tod_expiration may crash at startup

Bug description:
	This bug exist only in 1.4.3 branch
	In 1.4.3, CL open as a separated database so
        compaction mechanism is started along a CL
        mechanism (CL trimming).
        The problem is that the configuration of the CL
        compaction is done after the compaction mechanism
        (is started). Depending on thread scheduling it
        crashes

Fix description:
        Make sure configuration of compaction thread is
        taken into account (cl5ConfigSetCompaction) before
	the compaction thread starts (cl5open)

relates: https://github.com/389ds/389-ds-base/issues/4814

Reviewed by: Mark Reynolds, Simon Pichugin (thanks !)

Platforms tested: 8.5
---
 ldap/servers/plugins/replication/cl5_api.c    | 24 ++++++++++++-------
 ldap/servers/plugins/replication/cl5_api.h    | 10 +++++++-
 ldap/servers/plugins/replication/cl5_config.c |  8 +++++--
 ldap/servers/plugins/replication/cl5_init.c   |  4 +++-
 ldap/servers/plugins/replication/cl5_test.c   |  2 +-
 .../servers/plugins/replication/repl_shared.h |  2 +-
 6 files changed, 35 insertions(+), 15 deletions(-)

diff --git a/ldap/servers/plugins/replication/cl5_api.c b/ldap/servers/plugins/replication/cl5_api.c
index 4c5077b48..954b6b9e3 100644
--- a/ldap/servers/plugins/replication/cl5_api.c
+++ b/ldap/servers/plugins/replication/cl5_api.c
@@ -1016,6 +1016,20 @@ cl5GetState()
     return s_cl5Desc.dbState;
 }
 
+void
+cl5ConfigSetCompaction(int compactInterval, char *compactTime)
+{
+
+    if (compactInterval != CL5_NUM_IGNORE) {
+        s_cl5Desc.dbTrim.compactInterval = compactInterval;
+    }
+
+    if (strcmp(compactTime, CL5_STR_IGNORE) != 0) {
+        s_cl5Desc.dbTrim.compactTime = slapi_ch_strdup(compactTime);
+    }
+
+}
+
 /* Name:        cl5ConfigTrimming
    Description:    sets changelog trimming parameters; changelog must be open.
    Parameters:  maxEntries - maximum number of entries in the chnagelog (in all files);
@@ -1026,7 +1040,7 @@ cl5GetState()
                 CL5_BAD_STATE if changelog is not open
  */
 int
-cl5ConfigTrimming(int maxEntries, const char *maxAge, int compactInterval, char *compactTime, int trimInterval)
+cl5ConfigTrimming(int maxEntries, const char *maxAge, int trimInterval)
 {
     if (s_cl5Desc.dbState == CL5_STATE_NONE) {
         slapi_log_err(SLAPI_LOG_ERR, repl_plugin_name_cl,
@@ -1058,14 +1072,6 @@ cl5ConfigTrimming(int maxEntries, const char *maxAge, int compactInterval, char
         s_cl5Desc.dbTrim.maxEntries = maxEntries;
     }
 
-    if (compactInterval != CL5_NUM_IGNORE) {
-        s_cl5Desc.dbTrim.compactInterval = compactInterval;
-    }
-
-    if (strcmp(compactTime, CL5_STR_IGNORE) != 0) {
-        s_cl5Desc.dbTrim.compactTime = slapi_ch_strdup(compactTime);
-    }
-
     if (trimInterval != CL5_NUM_IGNORE) {
         s_cl5Desc.dbTrim.trimInterval = trimInterval;
     }
diff --git a/ldap/servers/plugins/replication/cl5_api.h b/ldap/servers/plugins/replication/cl5_api.h
index 11db771f2..6aa48aec4 100644
--- a/ldap/servers/plugins/replication/cl5_api.h
+++ b/ldap/servers/plugins/replication/cl5_api.h
@@ -227,6 +227,14 @@ int cl5ImportLDIF(const char *clDir, const char *ldifFile, Replica **replicas);
 
 int cl5GetState(void);
 
+/* Name:        cl5ConfigSetCompaction
+ * Description: sets the database compaction parameters
+ * Parameters:  compactInterval - Interval for compaction default is 30days
+ *              compactTime - Compact time default is 23:59
+ * Return:      void
+ */
+void cl5ConfigSetCompaction(int compactInterval, char *compactTime);
+
 /* Name:        cl5ConfigTrimming
    Description:    sets changelog trimming parameters
    Parameters:  maxEntries - maximum number of entries in the log;
@@ -236,7 +244,7 @@ int cl5GetState(void);
    Return:        CL5_SUCCESS if successful;
                 CL5_BAD_STATE if changelog has not been open
  */
-int cl5ConfigTrimming(int maxEntries, const char *maxAge, int compactInterval, char *compactTime, int trimInterval);
+int cl5ConfigTrimming(int maxEntries, const char *maxAge, int trimInterval);
 
 void cl5DestroyIterator(void *iterator);
 
diff --git a/ldap/servers/plugins/replication/cl5_config.c b/ldap/servers/plugins/replication/cl5_config.c
index b32686788..a43534c9b 100644
--- a/ldap/servers/plugins/replication/cl5_config.c
+++ b/ldap/servers/plugins/replication/cl5_config.c
@@ -197,6 +197,8 @@ changelog5_config_add(Slapi_PBlock *pb __attribute__((unused)),
 
         goto done;
     }
+    /* Set compaction parameters */
+    cl5ConfigSetCompaction(config.compactInterval, config.compactTime);
 
     /* start the changelog */
     rc = cl5Open(config.dir, &config.dbconfig);
@@ -212,7 +214,7 @@ changelog5_config_add(Slapi_PBlock *pb __attribute__((unused)),
     }
 
     /* set trimming parameters */
-    rc = cl5ConfigTrimming(config.maxEntries, config.maxAge, config.compactInterval, config.compactTime, config.trimInterval);
+    rc = cl5ConfigTrimming(config.maxEntries, config.maxAge, config.trimInterval);
     if (rc != CL5_SUCCESS) {
         *returncode = 1;
         if (returntext) {
@@ -548,6 +550,8 @@ changelog5_config_modify(Slapi_PBlock *pb,
                 slapi_log_err(SLAPI_LOG_REPL, repl_plugin_name_cl,
                               "changelog5_config_modify - Deleted the changelog at %s\n", currentDir);
             }
+            /* Set compaction parameters */
+            cl5ConfigSetCompaction(config.compactInterval, config.compactTime);
 
             rc = cl5Open(config.dir, &config.dbconfig);
             if (rc != CL5_SUCCESS) {
@@ -575,7 +579,7 @@ changelog5_config_modify(Slapi_PBlock *pb,
     if (config.maxEntries != CL5_NUM_IGNORE ||
         config.trimInterval != CL5_NUM_IGNORE ||
         strcmp(config.maxAge, CL5_STR_IGNORE) != 0) {
-        rc = cl5ConfigTrimming(config.maxEntries, config.maxAge, config.compactInterval, config.compactTime, config.trimInterval);
+        rc = cl5ConfigTrimming(config.maxEntries, config.maxAge, config.trimInterval);
         if (rc != CL5_SUCCESS) {
             *returncode = 1;
             if (returntext) {
diff --git a/ldap/servers/plugins/replication/cl5_init.c b/ldap/servers/plugins/replication/cl5_init.c
index 251859714..567e0274c 100644
--- a/ldap/servers/plugins/replication/cl5_init.c
+++ b/ldap/servers/plugins/replication/cl5_init.c
@@ -45,6 +45,8 @@ changelog5_init()
         rc = 0; /* OK */
         goto done;
     }
+    /* Set compaction parameters */
+    cl5ConfigSetCompaction(config.compactInterval, config.compactTime);
 
     /* start changelog */
     rc = cl5Open(config.dir, &config.dbconfig);
@@ -57,7 +59,7 @@ changelog5_init()
     }
 
     /* set trimming parameters */
-    rc = cl5ConfigTrimming(config.maxEntries, config.maxAge, config.compactInterval, config.compactTime, config.trimInterval);
+    rc = cl5ConfigTrimming(config.maxEntries, config.maxAge, config.trimInterval);
     if (rc != CL5_SUCCESS) {
         slapi_log_err(SLAPI_LOG_ERR, repl_plugin_name_cl,
                       "changelog5_init: failed to configure changelog trimming\n");
diff --git a/ldap/servers/plugins/replication/cl5_test.c b/ldap/servers/plugins/replication/cl5_test.c
index d6656653c..efb8c543a 100644
--- a/ldap/servers/plugins/replication/cl5_test.c
+++ b/ldap/servers/plugins/replication/cl5_test.c
@@ -281,7 +281,7 @@ testTrimming()
         rc = populateChangelog(300, NULL);
 
         if (rc == 0)
-            rc = cl5ConfigTrimming(300, "1d", CHANGELOGDB_COMPACT_INTERVAL, CHANGELOGDB_TRIM_INTERVAL);
+            rc = cl5ConfigTrimming(300, "1d", CHANGELOGDB_TRIM_INTERVAL);
 
         interval = PR_SecondsToInterval(300); /* 5 min is default trimming interval */
         slapi_log_err(SLAPI_LOG_ERR, repl_plugin_name_cl,
diff --git a/ldap/servers/plugins/replication/repl_shared.h b/ldap/servers/plugins/replication/repl_shared.h
index 6708e12f7..b59b2bd27 100644
--- a/ldap/servers/plugins/replication/repl_shared.h
+++ b/ldap/servers/plugins/replication/repl_shared.h
@@ -26,7 +26,7 @@
 
 #define CHANGELOGDB_TRIM_INTERVAL 300        /* 5 minutes */
 #define CHANGELOGDB_COMPACT_INTERVAL 2592000 /* 30 days */
-#define CHANGELOGDB_COMPACT_TIME "23:55" /* 30 days */
+#define CHANGELOGDB_COMPACT_TIME "23:59"     /* around midnight */
 
 #define CONFIG_CHANGELOG_DIR_ATTRIBUTE "nsslapd-changelogdir"
 #define CONFIG_CHANGELOG_MAXENTRIES_ATTRIBUTE "nsslapd-changelogmaxentries"
-- 
2.31.1