]> git.sur5r.net Git - openldap/blobdiff - servers/slapd/overlays/accesslog.c
More #5728 fallout
[openldap] / servers / slapd / overlays / accesslog.c
index 2a04e84c3978efd1ec0d28d9da05674751fefafc..866afd7937763176ed0d5a3e81b3294c979df05a 100644 (file)
@@ -2,7 +2,7 @@
 /* $OpenLDAP$ */
 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
  *
- * Copyright 2005-2007 The OpenLDAP Foundation.
+ * Copyright 2005-2008 The OpenLDAP Foundation.
  * Portions copyright 2004-2005 Symas Corporation.
  * All rights reserved.
  *
@@ -67,7 +67,6 @@ typedef struct log_info {
        Entry *li_old;
        log_attr *li_oldattrs;
        int li_success;
-       int li_unlock;
        ldap_pvt_thread_rmutex_t li_op_rmutex;
        ldap_pvt_thread_mutex_t li_log_mutex;
 } log_info;
@@ -569,19 +568,22 @@ static int
 log_old_lookup( Operation *op, SlapReply *rs )
 {
        purge_data *pd = op->o_callback->sc_private;
+       Attribute *a;
 
        if ( rs->sr_type != REP_SEARCH) return 0;
 
        if ( slapd_shutdown ) return 0;
 
-       /* Remember old CSN */
-       if ( pd->csn.bv_val[0] == '\0' ) {
-               Attribute *a = attr_find( rs->sr_entry->e_attrs,
-                       slap_schema.si_ad_entryCSN );
-               if ( a ) {
-                       int len = a->a_vals[0].bv_len;
-                       if ( len > pd->csn.bv_len )
-                               len = pd->csn.bv_len;
+       /* Remember max CSN: should always be the last entry
+        * seen, since log entries are ordered chronologically...
+        */
+       a = attr_find( rs->sr_entry->e_attrs,
+               slap_schema.si_ad_entryCSN );
+       if ( a ) {
+               int len = a->a_vals[0].bv_len;
+               if ( len > pd->csn.bv_len )
+                       len = pd->csn.bv_len;
+               if ( memcmp( a->a_vals[0].bv_val, pd->csn.bv_val, len ) > 0 ) {
                        AC_MEMCPY( pd->csn.bv_val, a->a_vals[0].bv_val, len );
                        pd->csn.bv_len = len;
                }
@@ -657,6 +659,7 @@ accesslog_purge( void *ctx, void *arg )
        if ( pd.used ) {
                int i;
 
+               /* delete the expired entries */
                op->o_tag = LDAP_REQ_DELETE;
                op->o_callback = &nullsc;
                op->o_csn = pd.csn;
@@ -671,6 +674,33 @@ accesslog_purge( void *ctx, void *arg )
                }
                ch_free( pd.ndn );
                ch_free( pd.dn );
+
+               {
+                       Modifications mod;
+                       struct berval bv[2];
+                       /* update context's entryCSN to reflect oldest CSN */
+                       mod.sml_numvals = 1;
+                       mod.sml_values = bv;
+                       bv[0] = pd.csn;
+                       BER_BVZERO(&bv[1]);
+                       mod.sml_nvalues = NULL;
+                       mod.sml_desc = slap_schema.si_ad_entryCSN;
+                       mod.sml_op = LDAP_MOD_REPLACE;
+                       mod.sml_flags = SLAP_MOD_INTERNAL;
+                       mod.sml_next = NULL;
+
+                       op->o_tag = LDAP_REQ_MODIFY;
+                       op->orm_modlist = &mod;
+                       op->orm_no_opattrs = 1;
+                       op->o_req_dn = li->li_db->be_suffix[0];
+                       op->o_req_ndn = li->li_db->be_nsuffix[0];
+                       op->o_no_schema_check = 1;
+                       op->o_managedsait = SLAP_CONTROL_NONCRITICAL;
+                       op->o_bd->be_modify( op, &rs );
+                       if ( mod.sml_next ) {
+                               slap_mods_free( mod.sml_next, 1 );
+                       }
+               }
        }
 
        ldap_pvt_thread_mutex_lock( &slapd_rq.rq_mutex );
@@ -770,9 +800,11 @@ log_cf_gen(ConfigArgs *c)
                        if ( li->li_task ) {
                                struct re_s *re = li->li_task;
                                li->li_task = NULL;
+                               ldap_pvt_thread_mutex_lock( &slapd_rq.rq_mutex );
                                if ( ldap_pvt_runqueue_isrunning( &slapd_rq, re ))
                                        ldap_pvt_runqueue_stoptask( &slapd_rq, re );
                                ldap_pvt_runqueue_remove( &slapd_rq, re );
+                               ldap_pvt_thread_mutex_unlock( &slapd_rq.rq_mutex );
                        }
                        li->li_age = 0;
                        li->li_cycle = 0;
@@ -844,12 +876,15 @@ log_cf_gen(ConfigArgs *c)
                                        struct re_s *re = li->li_task;
                                        if ( re )
                                                re->interval.tv_sec = li->li_cycle;
-                                       else
+                                       else {
+                                               ldap_pvt_thread_mutex_lock( &slapd_rq.rq_mutex );
                                                li->li_task = ldap_pvt_runqueue_insert( &slapd_rq,
                                                        li->li_cycle, accesslog_purge, li,
                                                        "accesslog_purge", li->li_db ?
                                                                li->li_db->be_suffix[0].bv_val :
                                                                c->be->be_suffix[0].bv_val );
+                                               ldap_pvt_thread_mutex_unlock( &slapd_rq.rq_mutex );
+                                       }
                                }
                        }
                        break;
@@ -1339,10 +1374,17 @@ static int accesslog_response(Operation *op, SlapReply *rs) {
                return SLAP_CB_CONTINUE;
 
        if ( lo->mask & LOG_OP_WRITES ) {
+               slap_callback *cb;
                ldap_pvt_thread_mutex_lock( &li->li_log_mutex );
                old = li->li_old;
                li->li_old = NULL;
-               li->li_unlock = 0;
+               /* Disarm mod_cleanup */
+               for ( cb = op->o_callback; cb; cb = cb->sc_next ) {
+                       if ( cb->sc_private == (void *)on ) {
+                               cb->sc_private = NULL;
+                               break;
+                       }
+               }
                ldap_pvt_thread_rmutex_unlock( &li->li_op_rmutex, op->o_tid );
        }
 
@@ -1693,12 +1735,11 @@ accesslog_mod_cleanup( Operation *op, SlapReply *rs )
 {
        slap_callback *sc = op->o_callback;
        slap_overinst *on = sc->sc_private;
-       log_info *li = on->on_bi.bi_private;
        op->o_callback = sc->sc_next;
 
        op->o_tmpfree( sc, op->o_tmpmemctx );
 
-       if ( li->li_unlock ) {
+       if ( on ) {
                BackendInfo *bi = op->o_bd->bd_info;
                op->o_bd->bd_info = (BackendInfo *)on;
                accesslog_response( op, rs );
@@ -1714,15 +1755,15 @@ accesslog_op_mod( Operation *op, SlapReply *rs )
        log_info *li = on->on_bi.bi_private;
 
        if ( li->li_ops & LOG_OP_WRITES ) {
-               slap_callback *cb = op->o_tmpalloc( sizeof( slap_callback ), op->o_tmpmemctx );
+               slap_callback *cb = op->o_tmpalloc( sizeof( slap_callback ), op->o_tmpmemctx ), *cb2;
                cb->sc_cleanup = accesslog_mod_cleanup;
                cb->sc_response = NULL;
                cb->sc_private = on;
-               cb->sc_next = op->o_callback;
-               op->o_callback = cb;
+               cb->sc_next = NULL;
+               for ( cb2 = op->o_callback; cb2->sc_next; cb2 = cb2->sc_next );
+               cb2->sc_next = cb;
 
                ldap_pvt_thread_rmutex_lock( &li->li_op_rmutex, op->o_tid );
-               li->li_unlock = 1;
                if ( li->li_oldf && ( op->o_tag == LDAP_REQ_DELETE ||
                        op->o_tag == LDAP_REQ_MODIFY ||
                        ( op->o_tag == LDAP_REQ_MODRDN && li->li_oldattrs ))) {
@@ -2017,8 +2058,10 @@ accesslog_db_open(
                ber_dupbv( &li->li_db->be_rootndn, li->li_db->be_nsuffix );
        }
 
+       ldap_pvt_thread_mutex_lock( &slapd_rq.rq_mutex );
        ldap_pvt_runqueue_insert( &slapd_rq, 3600, accesslog_db_root, on,
                "accesslog_db_root", li->li_db->be_suffix[0].bv_val );
+       ldap_pvt_thread_mutex_unlock( &slapd_rq.rq_mutex );
 
        return 0;
 }