]> git.ipfire.org Git - thirdparty/openldap.git/commitdiff
ITS#10465 Suspend purge task sometimes to improve fairness
authorOndřej Kuzník <ondra@mistotebe.net>
Thu, 19 Mar 2026 12:35:43 +0000 (12:35 +0000)
committerQuanah Gibson-Mount <quanah@openldap.org>
Mon, 23 Mar 2026 19:34:31 +0000 (19:34 +0000)
servers/slapd/overlays/accesslog.c

index c43c0e113033001770d322f694d695b813328278..210cc51033a92c337c6c97ed6aa41d00426b1abc 100644 (file)
@@ -82,6 +82,7 @@ typedef struct log_info {
        log_base *li_bases;
        BerVarray li_mincsn;
        int *li_sids, li_numcsns;
+       int li_yield_factor;
 
        /*
         * Allow partial concurrency, main operation processing serialised with
@@ -106,7 +107,8 @@ enum {
        LOG_SUCCESS,
        LOG_OLD,
        LOG_OLDATTR,
-       LOG_BASE
+       LOG_BASE,
+       LOG_YIELD_FACTOR
 };
 
 static ConfigTable log_cfats[] = {
@@ -147,6 +149,11 @@ static ConfigTable log_cfats[] = {
                        "DESC 'Operation types to log under a specific branch' "
                        "EQUALITY caseIgnoreMatch "
                        "SYNTAX OMsDirectoryString )", NULL, NULL },
+       { "logpurgebatch", NULL, 2, 2, 0, ARG_MAGIC|ARG_UINT|LOG_YIELD_FACTOR,
+               log_cf_gen, "( OLcfgOvAt:4.8 NAME 'olcAccessLogPurgeBatch' "
+                       "DESC 'Pause purge task after every N entries have been purged' "
+                       "EQUALITY integerMatch "
+                       "SYNTAX OMsInteger SINGLE-VALUE )", NULL, NULL },
        { NULL }
 };
 
@@ -157,7 +164,8 @@ static ConfigOCs log_cfocs[] = {
                "SUP olcOverlayConfig "
                "MUST olcAccessLogDB "
                "MAY ( olcAccessLogOps $ olcAccessLogPurge $ olcAccessLogSuccess $ "
-                       "olcAccessLogOld $ olcAccessLogOldAttr $ olcAccessLogBase ) )",
+                       "olcAccessLogOld $ olcAccessLogOldAttr $ olcAccessLogBase $ "
+                       "olcAccessLogPurgeBatch ) )",
                        Cft_Overlay, log_cfats },
        { NULL }
 };
@@ -743,6 +751,7 @@ accesslog_purge( void *ctx, void *arg )
 
        if ( pd.used ) {
                int i;
+               struct timeval start = { .tv_sec = 0 };
 
                op->o_callback = &nullsc;
                op->o_dont_replicate = 1;
@@ -779,6 +788,8 @@ accesslog_purge( void *ctx, void *arg )
                /* delete the expired entries */
                op->o_tag = LDAP_REQ_DELETE;
                for (i=0; i<pd.used; i++) {
+                       unsigned int factor = li->li_yield_factor;
+
                        op->o_req_dn = pd.dn[i];
                        op->o_req_ndn = pd.ndn[i];
                        if ( !slapd_shutdown ) {
@@ -788,6 +799,31 @@ accesslog_purge( void *ctx, void *arg )
                        ch_free( pd.ndn[i].bv_val );
                        ch_free( pd.dn[i].bv_val );
                        ldap_pvt_thread_pool_pausewait( &connection_pool );
+                       if ( factor && ( i % factor == 0 ) ) {
+                               if ( start.tv_sec || start.tv_usec ) {
+                                       struct timeval diff;
+
+                                       gettimeofday( &diff, NULL );
+                                       diff.tv_sec -= start.tv_sec;
+                                       diff.tv_usec -= start.tv_usec;
+                                       if ( diff.tv_usec < 0 ) {
+                                               diff.tv_sec -= 1;
+                                               diff.tv_usec += 1000000;
+                                       }
+
+                                       diff.tv_usec /= factor;
+                                       diff.tv_usec += (1000000 * (diff.tv_sec % factor)) / factor;
+                                       diff.tv_sec /= factor;
+
+                                       Debug( LDAP_DEBUG_TRACE, "accesslog_purge: "
+                                                       "giving other threads a chance for %ld.%06lds\n",
+                                                       diff.tv_sec, diff.tv_usec );
+                                       select( 0, NULL, NULL, NULL, &diff );
+                               }
+                               gettimeofday( &start, NULL );
+                       } else {
+                               ldap_pvt_thread_yield();
+                       }
                }
                ch_free( pd.ndn );
                ch_free( pd.dn );
@@ -896,6 +932,12 @@ log_cf_gen(ConfigArgs *c)
                        break;
                }
                break;
+               case LOG_YIELD_FACTOR:
+                       if ( li->li_yield_factor )
+                               c->value_int = li->li_yield_factor;
+                       else
+                               rc = 1;
+                       break;
        case LDAP_MOD_DELETE:
                switch( c->type ) {
                case LOG_DB:
@@ -972,6 +1014,9 @@ log_cf_gen(ConfigArgs *c)
                                ch_free( lb );
                        }
                        break;
+               case LOG_YIELD_FACTOR:
+                       li->li_yield_factor = 0;
+                       break;
                }
                break;
        default:
@@ -1146,6 +1191,9 @@ log_cf_gen(ConfigArgs *c)
                        }
                        }
                        break;
+               case LOG_YIELD_FACTOR:
+                       li->li_yield_factor = c->value_int;
+                       break;
                }
                break;
        }