]> git.sur5r.net Git - openldap/commitdiff
Fixed memory leak in pcache. Cache is now populated in cleanup handler.
authorRalf Haferkamp <ralf@openldap.org>
Thu, 20 Sep 2007 16:15:23 +0000 (16:15 +0000)
committerRalf Haferkamp <ralf@openldap.org>
Thu, 20 Sep 2007 16:15:23 +0000 (16:15 +0000)
ITS#5112

servers/slapd/overlays/pcache.c

index b6057d7aaaf62020030f3d78a78705a4d2b9e63f..38a213e2f03ec3a17075950fc2472b35148a2e76 100644 (file)
@@ -1566,6 +1566,7 @@ struct search_info {
        int count;
        int slimit;
        int slimit_exceeded;
+       pc_caching_reason_t caching_reason;
        Entry *head, *tail;
 };
 
@@ -1905,46 +1906,18 @@ static int
 pcache_op_cleanup( Operation *op, SlapReply *rs ) {
        slap_callback   *cb = op->o_callback;
        struct search_info *si = cb->sc_private;
+       slap_overinst *on = si->on;
+       cache_manager *cm = on->on_bi.bi_private;
+       query_manager*          qm = cm->qm;
 
        if ( rs->sr_type == REP_SEARCH ) {
+               Entry *e;
+
                /* don't return more entries than requested by the client */
                if ( si->slimit && rs->sr_nentries >= si->slimit ) {
                        si->slimit_exceeded = 1;
                }
-       }
-
-       if ( rs->sr_type == REP_RESULT || 
-               op->o_abandon || 
-               rs->sr_err == SLAPD_ABANDON )
-       {
-               if ( si->save_attrs != NULL ) {
-                       rs->sr_attrs = si->save_attrs;
-                       op->ors_attrs = si->save_attrs;
-               }
-               op->o_callback = op->o_callback->sc_next;
-               op->o_tmpfree( cb, op->o_tmpmemctx );
-       }
-
-       return SLAP_CB_CONTINUE;
-}
-
-static int
-pcache_response(
-       Operation       *op,
-       SlapReply       *rs )
-{
-       struct search_info *si = op->o_callback->sc_private;
-       slap_overinst *on = si->on;
-       cache_manager *cm = on->on_bi.bi_private;
-       query_manager*          qm = cm->qm;
 
-       if ( si->save_attrs != NULL ) {
-               rs->sr_attrs = si->save_attrs;
-               op->ors_attrs = si->save_attrs;
-       }
-
-       if ( rs->sr_type == REP_SEARCH ) {
-               Entry *e;
                /* If we haven't exceeded the limit for this query,
                 * build a chain of answers to store. If we hit the
                 * limit, empty the chain and ignore the rest.
@@ -1969,36 +1942,34 @@ pcache_response(
                        }
                }
 
-               /* don't return more entries than requested by the client */
-               if ( si->slimit_exceeded ) {
-                       return 0;
-               }
-
-       } else if ( rs->sr_type == REP_RESULT ) {
-               pc_caching_reason_t why = PC_IGNORE;
-
-               if ( si->count ) {
-                       if ( rs->sr_err == LDAP_SUCCESS ) {
-                               why = PC_POSITIVE;
-
-                       } else if ( rs->sr_err == LDAP_SIZELIMIT_EXCEEDED
-                               && si->qtemp->limitttl )
-                       {
-                               why = PC_SIZELIMIT;
-                       }
+       }
 
-               } else if ( si->qtemp->negttl && !si->count && !si->over &&
-                               rs->sr_err == LDAP_SUCCESS )
-               {
-                       why = PC_NEGATIVE;
+       if ( rs->sr_type == REP_RESULT || 
+               op->o_abandon || rs->sr_err == SLAPD_ABANDON )
+       {
+               if ( si->save_attrs != NULL ) {
+                       rs->sr_attrs = si->save_attrs;
+                       op->ors_attrs = si->save_attrs;
                }
-
-               if ( why != PC_IGNORE ) {
+               if ( op->o_abandon || rs->sr_err == SLAPD_ABANDON ) {
+                       filter_free( si->query.filter );
+                       if ( si->count ) {
+                               /* duplicate query, free it */
+                               Entry *e;
+                               for (;si->head; si->head=e) {
+                                       e = si->head->e_private;
+                                       si->head->e_private = NULL;
+                                       entry_free(si->head);
+                               }
+                       }
+                       op->o_callback = op->o_callback->sc_next;
+                       op->o_tmpfree( cb, op->o_tmpmemctx );
+               } else if ( si->caching_reason != PC_IGNORE ) {
                        CachedQuery *qc = qm->addfunc(op, qm, &si->query,
-                               si->qtemp, why );
+                               si->qtemp, si->caching_reason );
 
                        if ( qc != NULL ) {
-                               switch ( why ) {
+                               switch ( si->caching_reason ) {
                                case PC_POSITIVE:
                                        cache_entries( op, rs, &qc->q_uuid );
                                        break;
@@ -2038,6 +2009,47 @@ pcache_response(
                } else {
                        filter_free( si->query.filter );
                }
+       }
+
+       return SLAP_CB_CONTINUE;
+}
+
+static int
+pcache_response(
+       Operation       *op,
+       SlapReply       *rs )
+{
+       struct search_info *si = op->o_callback->sc_private;
+
+       if ( si->save_attrs != NULL ) {
+               rs->sr_attrs = si->save_attrs;
+               op->ors_attrs = si->save_attrs;
+       }
+
+       if ( rs->sr_type == REP_SEARCH ) {
+               /* don't return more entries than requested by the client */
+               if ( si->slimit_exceeded ) {
+                       return 0;
+               }
+
+       } else if ( rs->sr_type == REP_RESULT ) {
+
+               if ( si->count ) {
+                       if ( rs->sr_err == LDAP_SUCCESS ) {
+                               si->caching_reason = PC_POSITIVE;
+
+                       } else if ( rs->sr_err == LDAP_SIZELIMIT_EXCEEDED
+                               && si->qtemp->limitttl )
+                       {
+                               si->caching_reason = PC_SIZELIMIT;
+                       }
+
+               } else if ( si->qtemp->negttl && !si->count && !si->over &&
+                               rs->sr_err == LDAP_SUCCESS )
+               {
+                       si->caching_reason = PC_NEGATIVE;
+               }
+
 
                if ( si->slimit_exceeded ) {
                        rs->sr_err = LDAP_SIZELIMIT_EXCEEDED;
@@ -2335,6 +2347,7 @@ pcache_op_search(
                si->count = 0;
                si->slimit = 0;
                si->slimit_exceeded = 0;
+               si->caching_reason = PC_IGNORE;
                if ( op->ors_slimit && op->ors_slimit < cm->num_entries_limit ) {
                        si->slimit = op->ors_slimit;
                        op->ors_slimit = cm->num_entries_limit;