]> git.sur5r.net Git - openldap/blobdiff - servers/slapd/overlays/pcache.c
Merge branch 'mdb.master' of ssh://git-master.openldap.org/~git/git/openldap
[openldap] / servers / slapd / overlays / pcache.c
index fb5f8eebfc6eb4daca364dd8530da084931144ca..d27dcb7a0a7e176279f2e84aef65f980d8aec045 100644 (file)
@@ -922,38 +922,49 @@ static int pcache_filter_cmp( Filter *f1, Filter *f2 )
        int rc, weight1, weight2;
 
        switch( f1->f_choice ) {
-       case LDAP_FILTER_PRESENT:
+       case LDAP_FILTER_AND:
+       case LDAP_FILTER_OR:
                weight1 = 0;
                break;
+       case LDAP_FILTER_PRESENT:
+               weight1 = 1;
+               break;
        case LDAP_FILTER_EQUALITY:
        case LDAP_FILTER_GE:
        case LDAP_FILTER_LE:
-               weight1 = 1;
+               weight1 = 2;
                break;
        default:
-               weight1 = 2;
+               weight1 = 3;
        }
        switch( f2->f_choice ) {
-       case LDAP_FILTER_PRESENT:
+       case LDAP_FILTER_AND:
+       case LDAP_FILTER_OR:
                weight2 = 0;
                break;
+       case LDAP_FILTER_PRESENT:
+               weight2 = 1;
+               break;
        case LDAP_FILTER_EQUALITY:
        case LDAP_FILTER_GE:
        case LDAP_FILTER_LE:
-               weight2 = 1;
+               weight2 = 2;
                break;
        default:
-               weight2 = 2;
+               weight2 = 3;
        }
        rc = weight1 - weight2;
        if ( !rc ) {
                switch( weight1 ) {
                case 0:
+                       rc = pcache_filter_cmp( f1->f_and, f2->f_and );
                        break;
                case 1:
-                       rc = lex_bvcmp( &f1->f_av_value, &f2->f_av_value );
                        break;
                case 2:
+                       rc = lex_bvcmp( &f1->f_av_value, &f2->f_av_value );
+                       break;
+               case 3:
                        if ( f1->f_choice == LDAP_FILTER_SUBSTRINGS ) {
                                rc = 0;
                                if ( !BER_BVISNULL( &f1->f_sub_initial )) {
@@ -994,7 +1005,7 @@ static int pcache_filter_cmp( Filter *f1, Filter *f2 )
                        }
                        break;
                }
-               if ( !rc ) {
+               while ( !rc ) {
                        f1 = f1->f_next;
                        f2 = f2->f_next;
                        if ( f1 || f2 ) {
@@ -1003,12 +1014,10 @@ static int pcache_filter_cmp( Filter *f1, Filter *f2 )
                                else if ( !f2 )
                                        rc = 1;
                                else {
-                                       while ( f1->f_choice == LDAP_FILTER_AND || f1->f_choice == LDAP_FILTER_OR )
-                                               f1 = f1->f_and;
-                                       while ( f2->f_choice == LDAP_FILTER_AND || f2->f_choice == LDAP_FILTER_OR )
-                                               f2 = f2->f_and;
                                        rc = pcache_filter_cmp( f1, f2 );
                                }
+                       } else {
+                               break;
                        }
                }
        }
@@ -1019,7 +1028,7 @@ static int pcache_filter_cmp( Filter *f1, Filter *f2 )
 static int pcache_query_cmp( const void *v1, const void *v2 )
 {
        const CachedQuery *q1 = v1, *q2 =v2;
-       return pcache_filter_cmp( q1->first, q2->first );
+       return pcache_filter_cmp( q1->filter, q2->filter );
 }
 
 /* add query on top of LRU list */
@@ -1251,6 +1260,11 @@ filter_first( Filter *f )
        return f;
 }
 
+typedef struct fstack {
+       struct fstack *fs_next;
+       Filter *fs_fs;
+       Filter *fs_fi;
+} fstack;
 
 static CachedQuery *
 find_filter( Operation *op, Avlnode *root, Filter *inputf, Filter *first )
@@ -1262,6 +1276,7 @@ find_filter( Operation *op, Avlnode *root, Filter *inputf, Filter *first )
        int ret, rc, dir;
        Avlnode *ptr;
        CachedQuery cq, *qc;
+       fstack *stack = NULL, *fsp;
 
        cq.filter = inputf;
        cq.first = first;
@@ -1337,6 +1352,14 @@ nextpass:                        eqpass = 1;
                        switch (fs->f_choice) {
                        case LDAP_FILTER_OR:
                        case LDAP_FILTER_AND:
+                               if ( fs->f_next ) {
+                                       /* save our stack position */
+                                       fsp = op->o_tmpalloc(sizeof(fstack), op->o_tmpmemctx);
+                                       fsp->fs_next = stack;
+                                       fsp->fs_fs = fs->f_next;
+                                       fsp->fs_fi = fi->f_next;
+                                       stack = fsp;
+                               }
                                fs = fs->f_and;
                                fi = fi->f_and;
                                res=1;
@@ -1386,6 +1409,14 @@ nextpass:                        eqpass = 1;
                        default:
                                break;
                        }
+                       if (!fs && !fi && stack) {
+                               /* pop the stack */
+                               fsp = stack;
+                               stack = fsp->fs_next;
+                               fs = fsp->fs_fs;
+                               fi = fsp->fs_fi;
+                               op->o_tmpfree(fsp, op->o_tmpmemctx);
+                       }
                } while((res) && (fi != NULL) && (fs != NULL));
 
                if ( res )
@@ -2877,9 +2908,9 @@ pcache_op_bind(
 
        /* OK, just bind locally */
        if ( bi.bi_flags & BI_HASHED ) {
+               int delete = 0;
                BackendDB *be = op->o_bd;
                op->o_bd = &cm->db;
-               int delete = 0;
 
                Debug( pcache_debug, "pcache_op_bind: CACHED BIND for %s\n",
                        op->o_req_dn.bv_val, 0, 0 );