]> git.sur5r.net Git - openldap/blobdiff - servers/slapd/back-ldbm/index.c
silence warning
[openldap] / servers / slapd / back-ldbm / index.c
index b16ddddd0ebcba61a9a387d41a7b418e4e568563..2680fb0abcaa26e2654d6c03f4fb34e76e1e8e14 100644 (file)
@@ -1,4 +1,9 @@
 /* index.c - routines for dealing with attribute indexes */
+/* $OpenLDAP$ */
+/*
+ * Copyright 1998-2003 The OpenLDAP Foundation, All Rights Reserved.
+ * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
+ */
 
 #include "portable.h"
 
 #include "slap.h"
 #include "back-ldbm.h"
 
-static int     add_value(Backend *be, struct dbcache *db, char *type, int indextype, char *val, ID id);
-static int     index2prefix(int indextype);
-
-int
-index_add_entry(
-    Backend    *be,
-    Entry      *e
-)
+static slap_mask_t index_mask(
+       Backend *be,
+       AttributeDescription *desc,
+       char **dbname,
+       struct berval *atname )
 {
-       Attribute       *ap;
-       struct berval   bv;
-       struct berval   *bvals[2];
-
-       Debug( LDAP_DEBUG_TRACE, "=> index_add( %ld, \"%s\" )\n", e->e_id,
-           e->e_dn, 0 );
-
-       /*
-        * dn index entry - make it look like an attribute so it works
-        * with index_add_values() call
-        */
+       AttributeType *at;
+       slap_mask_t mask = 0;
 
-       bv.bv_val = ch_strdup( e->e_dn );
-       bv.bv_len = strlen( bv.bv_val );
-       (void) dn_normalize_case( bv.bv_val );
-       bvals[0] = &bv;
-       bvals[1] = NULL;
+       attr_mask( be->be_private, desc, &mask );
 
-       /* add the dn to the indexes */
-       index_add_values( be, "dn", bvals, e->e_id );
+       if( mask ) {
+               *atname = desc->ad_cname;
+               *dbname = desc->ad_cname.bv_val;
+               return mask;
+       }
 
-       free( bv.bv_val );
+       /* If there is a tagging option, did we ever index the base
+        * type? If so, check for mask, otherwise it's not there.
+        */
+       if( slap_ad_is_tagged( desc ) && desc != desc->ad_type->sat_ad ) {
+               /* has tagging option */
+               attr_mask( be->be_private, desc->ad_type->sat_ad, &mask );
+
+               if( mask && ( mask ^ SLAP_INDEX_NOTAGS ) ) {
+                       *atname = desc->ad_type->sat_cname;
+                       *dbname = desc->ad_type->sat_cname.bv_val;
+                       return mask;
+               }
+       }
 
-       /* add each attribute to the indexes */
-       for ( ap = e->e_attrs; ap != NULL; ap = ap->a_next ) {
-               index_add_values( be, ap->a_type, ap->a_vals, e->e_id );
+       /* see if supertype defined mask for its subtypes */
+       for( at = desc->ad_type->sat_sup; at != NULL ; at = at->sat_sup ) {
+               /* If no AD, we've never indexed this type */
+               if (!at->sat_ad)
+                       continue;
+               
+               attr_mask( be->be_private, at->sat_ad, &mask );
+
+               if( mask && ( mask ^ SLAP_INDEX_NOSUBTYPES ) ) {
+                       *atname = at->sat_cname;
+                       *dbname = at->sat_cname.bv_val;
+                       return mask;
+               }
        }
 
-       Debug( LDAP_DEBUG_TRACE, "<= index_add( %ld, \"%s\" ) 0\n", e->e_id,
-           e->e_dn, 0 );
-       return( 0 );
+       return 0;
 }
 
-int
-index_add_mods(
-    Backend    *be,
-    LDAPModList        *ml,
-    ID         id
-)
+int index_is_indexed(
+       Backend *be,
+       AttributeDescription *desc )
 {
-       int     rc;
-
-       for ( ; ml != NULL; ml = ml->ml_next ) {
-               LDAPMod *mod = &ml->ml_mod;
+       slap_mask_t mask;
+       char *dbname;
+       struct berval prefix;
 
-               switch ( mod->mod_op & ~LDAP_MOD_BVALUES ) {
-               case LDAP_MOD_ADD:
-               case LDAP_MOD_REPLACE:
-                       rc = index_add_values( be, mod->mod_type,
-                           mod->mod_bvalues, id );
-                       break;
-
-               case LDAP_MOD_DELETE:
-                       rc = 0;
-                       break;
-               }
+       mask = index_mask( be, desc, &dbname, &prefix );
 
-               if ( rc != 0 ) {
-                       return( rc );
-               }
+       if( mask == 0 ) {
+               return LDAP_INAPPROPRIATE_MATCHING;
        }
 
-       return( 0 );
+       return LDAP_SUCCESS;
 }
 
-ID_BLOCK *
-index_read(
-    Backend    *be,
-    char       *type,
-    int                indextype,
-    char       *val
-)
+int index_param(
+       Backend *be,
+       AttributeDescription *desc,
+       int ftype,
+       char **dbnamep,
+       slap_mask_t *maskp,
+       struct berval *prefixp )
 {
-       struct dbcache  *db;
-       Datum           key;
-       ID_BLOCK                *idl;
-       int             indexmask, syntax;
-       char            prefix;
-       char            *realval, *tmpval;
-       char            buf[BUFSIZ];
-
-       ldbm_datum_init( key );
-
-       prefix = index2prefix( indextype );
-       Debug( LDAP_DEBUG_TRACE, "=> index_read( \"%s\" \"%c\" \"%s\" )\n",
-           type, prefix, val );
-
-       attr_masks( be->be_private, type, &indexmask, &syntax );
-       if ( ! (indextype & indexmask) ) {
-               idl =  idl_allids( be );
-               Debug( LDAP_DEBUG_TRACE,
-                   "<= index_read %ld candidates (allids - not indexed)\n",
-                   idl ? ID_BLOCK_NIDS(idl) : 0, 0, 0 );
-               return( idl );
-       }
+       slap_mask_t mask;
+       char *dbname;
 
-       attr_normalize( type );
-       if ( (db = ldbm_cache_open( be, type, LDBM_SUFFIX, LDBM_WRCREAT ))
-           == NULL ) {
-               Debug( LDAP_DEBUG_ANY,
-                   "<= index_read NULL (could not open %s%s)\n", type,
-                   LDBM_SUFFIX, 0 );
-               return( NULL );
+       mask = index_mask( be, desc, &dbname, prefixp );
+
+       if( mask == 0 ) {
+               return LDAP_INAPPROPRIATE_MATCHING;
        }
 
-       realval = val;
-       tmpval = NULL;
-       if ( prefix != UNKNOWN_PREFIX ) {
-              unsigned int     len = strlen( val );
-
-              if ( (len + 2) < sizeof(buf) ) {
-                       realval = buf;
-               } else {
-                       /* value + prefix + null */
-                       tmpval = (char *) ch_malloc( len + 2 );
-                       realval = tmpval;
+       switch( ftype ) {
+       case LDAP_FILTER_PRESENT:
+               if( IS_SLAP_INDEX( mask, SLAP_INDEX_PRESENT ) ) {
+                       goto done;
                }
-              realval[0] = prefix;
-              strcpy( &realval[1], val );
-       }
+               break;
 
-       key.dptr = realval;
-       key.dsize = strlen( realval ) + 1;
+       case LDAP_FILTER_APPROX:
+               if( IS_SLAP_INDEX( mask, SLAP_INDEX_APPROX ) ) {
+                       goto done;
+               }
+               /* fall thru */
 
-       idl = idl_fetch( be, db, key );
-      if ( tmpval != NULL ) {
-              free( tmpval );
-      }
+       case LDAP_FILTER_EQUALITY:
+               if( IS_SLAP_INDEX( mask, SLAP_INDEX_EQUALITY ) ) {
+                       goto done;
+               }
+               break;
 
-       ldbm_cache_close( be, db );
+       case LDAP_FILTER_SUBSTRINGS:
+               if( IS_SLAP_INDEX( mask, SLAP_INDEX_SUBSTR ) ) {
+                       goto done;
+               }
+               break;
+
+       default:
+               return LDAP_OTHER;
+       }
+
+       return LDAP_INAPPROPRIATE_MATCHING;
 
-       Debug( LDAP_DEBUG_TRACE, "<= index_read %ld candidates\n",
-           idl ? ID_BLOCK_NIDS(idl) : 0, 0, 0 );
-       return( idl );
+done:
+       *dbnamep = dbname;
+       *maskp = mask;
+       return LDAP_SUCCESS;
 }
 
-static int
-add_value(
-    Backend            *be,
-    struct dbcache     *db,
-    char               *type,
-    int                        indextype,
-    char               *val,
-    ID                 id
-)
+static int indexer(
+       Backend *be,
+       char *dbname,
+       struct berval *atname,
+       BerVarray vals,
+       ID id,
+       int op,
+       slap_mask_t mask )
 {
-       int     rc;
-       Datum   key;
-       /* XXX do we need idl ??? */
-       ID_BLOCK        *idl = NULL;
-       char    *tmpval = NULL;
-       char    *realval = val;
-       char    buf[BUFSIZ];
+       int rc, i;
+       const char *text;
+    DBCache    *db;
+       AttributeDescription *ad = NULL;
+       struct berval *keys;
 
-       char    prefix = index2prefix( indextype );
+       assert( mask );
 
-       ldbm_datum_init( key );
+       rc = slap_bv2ad( atname, &ad, &text );
 
-       Debug( LDAP_DEBUG_TRACE, "=> add_value( \"%c%s\" )\n", prefix, val, 0 );
+       if( rc != LDAP_SUCCESS ) return rc;
 
-       if ( prefix != UNKNOWN_PREFIX ) {
-              unsigned int     len = strlen( val );
+       db = ldbm_cache_open( be, dbname, LDBM_SUFFIX, LDBM_WRCREAT );
+       
+       if ( db == NULL ) {
+#ifdef NEW_LOGGING
+               LDAP_LOG( INDEX, ERR, 
+                          "index_read: Could not open db %s%s\n", dbname, LDBM_SUFFIX, 0 );
+#else
+               Debug( LDAP_DEBUG_ANY,
+                   "<= index_read NULL (could not open %s%s)\n",
+                       dbname, LDBM_SUFFIX, 0 );
+#endif
 
-              if ( (len + 2) < sizeof(buf) ) {
-                       realval = buf;
-               } else {
-                       /* value + prefix + null */
-                       tmpval = (char *) ch_malloc( len + 2 );
-                       realval = tmpval;
-               }
-              realval[0] = prefix;
-              strcpy( &realval[1], val );
+               return LDAP_OTHER;
        }
 
-       key.dptr = realval;
-       key.dsize = strlen( realval ) + 1;
-
-       rc = idl_insert_key( be, db, key, id );
+       if( IS_SLAP_INDEX( mask, SLAP_INDEX_PRESENT ) ) {
+               key_change( be, db, atname, id, op );
+       }
 
-       if ( tmpval != NULL ) {
-               free( tmpval );
+       if( IS_SLAP_INDEX( mask, SLAP_INDEX_EQUALITY ) ) {
+               rc = ad->ad_type->sat_equality->smr_indexer(
+                       LDAP_FILTER_EQUALITY,
+                       mask,
+                       ad->ad_type->sat_syntax,
+                       ad->ad_type->sat_equality,
+                       atname, vals, &keys );
+
+               if( rc == LDAP_SUCCESS && keys != NULL ) {
+                       for( i=0; keys[i].bv_val != NULL; i++ ) {
+                               key_change( be, db, &keys[i], id, op );
+                       }
+                       ber_bvarray_free( keys );
+               }
        }
 
-       if( idl != NULL ) {
-               idl_free( idl );
+       if( IS_SLAP_INDEX( mask, SLAP_INDEX_APPROX ) ) {
+               rc = ad->ad_type->sat_approx->smr_indexer(
+                       LDAP_FILTER_APPROX,
+                       mask,
+                       ad->ad_type->sat_syntax,
+                       ad->ad_type->sat_approx,
+                       atname, vals, &keys );
+
+               if( rc == LDAP_SUCCESS && keys != NULL ) {
+                       for( i=0; keys[i].bv_val != NULL; i++ ) {
+                               key_change( be, db, &keys[i], id, op );
+                       }
+                       ber_bvarray_free( keys );
+               }
        }
 
-       ldap_pvt_thread_yield();
+       if( IS_SLAP_INDEX( mask, SLAP_INDEX_SUBSTR ) ) {
+               rc = ad->ad_type->sat_substr->smr_indexer(
+                       LDAP_FILTER_SUBSTRINGS,
+                       mask,
+                       ad->ad_type->sat_syntax,
+                       ad->ad_type->sat_substr,
+                       atname, vals, &keys );
+
+               if( rc == LDAP_SUCCESS && keys != NULL ) {
+                       for( i=0; keys[i].bv_val != NULL; i++ ) {
+                               key_change( be, db, &keys[i], id, op );
+                       }
+                       ber_bvarray_free( keys );
+               }
+       }
 
-       /* Debug( LDAP_DEBUG_TRACE, "<= add_value %d\n", rc, 0, 0 ); */
-       return( rc );
+       ldbm_cache_close( be, db );
+       return LDAP_SUCCESS;
 }
 
-int
-index_add_values(
-    Backend            *be,
-    char               *type,
-    struct berval      **vals,
-    ID                 id
-)
+static int index_at_values(
+       Backend *be,
+       AttributeType *type,
+       struct berval *tags,
+       BerVarray vals,
+       ID id,
+       int op )
 {
-       char            *val, *p, *code, *w;
-       unsigned        i, j, len;
-       int             indexmask, syntax;
-       char            buf[SUBLEN + 1];
-       char            vbuf[BUFSIZ];
-       char            *bigbuf;
-       struct dbcache  *db;
-
-       Debug( LDAP_DEBUG_TRACE, "=> index_add_values( \"%s\", %ld )\n", type,
-           id, 0 );
-
-       attr_masks( be->be_private, type, &indexmask, &syntax );
-       if ( indexmask == 0 ) {
-               return( 0 );
-       }
+       slap_mask_t mask = 0;
 
-       if ( (db = ldbm_cache_open( be, type, LDBM_SUFFIX, LDBM_WRCREAT ))
-           == NULL ) {
-               Debug( LDAP_DEBUG_ANY,
-                   "<= index_add_values -1 (could not open/create %s%s)\n",
-                   type, LDBM_SUFFIX, 0 );
-               return( -1 );
+       if( type->sat_sup ) {
+               /* recurse */
+               (void) index_at_values( be,
+                       type->sat_sup, tags,
+                       vals, id, op );
        }
 
+       /* If this type has no AD, we've never used it before */
+       if( type->sat_ad ) {
+               attr_mask( be->be_private, type->sat_ad, &mask );
+       }
 
-       for ( i = 0; vals[i] != NULL; i++ ) {
-               /*
-                * presence index entry
-                */
-               if ( indexmask & INDEX_PRESENCE ) {
-                       add_value( be, db, type, INDEX_PRESENCE, "*", id );
-               }
-
-               Debug( LDAP_DEBUG_TRACE, "*** index_add_values syntax 0x%x syntax bin 0x%x\n",
-                   syntax, SYNTAX_BIN, 0 );
-               if ( syntax & SYNTAX_BIN ) {
-                       ldbm_cache_close( be, db );
-                       return( 0 );
-               }
+       if( mask ) {
+               indexer( be, type->sat_cname.bv_val,
+                       &type->sat_cname,
+                       vals, id, op,
+                       mask );
+       }
 
-               bigbuf = NULL;
-               len = vals[i]->bv_len;
+       if( tags->bv_len ) {
+               AttributeDescription *desc;
 
-               /* value + null */
-               if ( len + 2 > sizeof(vbuf) ) {
-                       bigbuf = (char *) ch_malloc( len + 1 );
-                       val = bigbuf;
-               } else {
-                       val = vbuf;
-               }
-               (void) memcpy( val, vals[i]->bv_val, len );
-               val[len] = '\0';
+               mask = 0;
 
-               value_normalize( val, syntax );
-
-               /*
-                * equality index entry
-                */
-               if ( indexmask & INDEX_EQUALITY ) {
-                       add_value( be, db, type, INDEX_EQUALITY, val, id );
+               desc = ad_find_tags(type, tags);
+               if( desc ) {
+                       attr_mask( be->be_private, desc, &mask );
                }
 
-               /*
-                * approximate index entry
-                */
-               if ( indexmask & INDEX_APPROX ) {
-                       for ( w = first_word( val ); w != NULL;
-                           w = next_word( w ) ) {
-                               if ( (code = phonetic( w )) != NULL ) {
-                                       add_value( be, db, type, INDEX_APPROX,
-                                           code, id );
-                                       free( code );
-                               }
-                       }
+               if( mask ) {
+                       indexer( be, desc->ad_cname.bv_val, &desc->ad_cname,
+                               vals, id, op,
+                               mask );
                }
+       }
 
-               /*
-                * substrings index entry
-                */
-               if ( indexmask & INDEX_SUB ) {
-                       /* leading and trailing */
-                       if ( len > SUBLEN - 2 ) {
-                               buf[0] = '^';
-                               for ( j = 0; j < SUBLEN - 1; j++ ) {
-                                       buf[j + 1] = val[j];
-                               }
-                               buf[SUBLEN] = '\0';
-
-                               add_value( be, db, type, INDEX_SUB, buf, id );
-
-                               p = val + len - SUBLEN + 1;
-                               for ( j = 0; j < SUBLEN - 1; j++ ) {
-                                       buf[j] = p[j];
-                               }
-                               buf[SUBLEN - 1] = '$';
-                               buf[SUBLEN] = '\0';
-
-                               add_value( be, db, type, INDEX_SUB, buf, id );
-                       }
-
-                       /* any */
-                       for ( p = val; p < (val + len - SUBLEN + 1); p++ ) {
-                               for ( j = 0; j < SUBLEN; j++ ) {
-                                       buf[j] = p[j];
-                               }
-                               buf[SUBLEN] = '\0';
-
-                               add_value( be, db, type, INDEX_SUB, buf, id );
-                       }
-               }
+       return LDAP_SUCCESS;
+}
 
-               if ( bigbuf != NULL ) {
-                       free( bigbuf );
-               }
-       }
-       ldbm_cache_close( be, db );
+int index_values(
+       Backend *be,
+       AttributeDescription *desc,
+       BerVarray vals,
+       ID id,
+       int op )
+{
+       (void) index_at_values( be,
+               desc->ad_type, &desc->ad_tags,
+               vals, id, op );
 
-       return( 0 );
+       return LDAP_SUCCESS;
 }
 
-static int
-index2prefix( int indextype )
+int
+index_entry(
+       Backend *be,
+       int op,
+       Entry *e )
 {
-       int     prefix;
+       Attribute *ap = e->e_attrs;
+#ifdef NEW_LOGGING
+       LDAP_LOG( INDEX, ENTRY, 
+               "index_entry: %s (%s)%ld\n", op == SLAP_INDEX_ADD_OP ? "add" : "del",
+               e->e_dn, e->e_id );
+#else
+       Debug( LDAP_DEBUG_TRACE, "=> index_entry_%s( %ld, \"%s\" )\n",
+               op == SLAP_INDEX_ADD_OP ? "add" : "del",
+               e->e_id, e->e_dn );
+#endif
 
-       switch ( indextype ) {
-       case INDEX_EQUALITY:
-               prefix = EQ_PREFIX;
-               break;
-       case INDEX_APPROX:
-               prefix = APPROX_PREFIX;
-               break;
-       case INDEX_SUB:
-               prefix = SUB_PREFIX;
-               break;
-       default:
-               prefix = UNKNOWN_PREFIX;
-               break;
+       /* add each attribute to the indexes */
+       for ( ; ap != NULL; ap = ap->a_next ) {
+               index_values( be, ap->a_desc,
+                       ap->a_nvals,
+                       e->e_id, op );
        }
 
-       return( prefix );
+#ifdef NEW_LOGGING
+       LDAP_LOG( INDEX, ENTRY, "index_entry: success\n", 0, 0, 0 );
+#else
+       Debug( LDAP_DEBUG_TRACE, "<= index_entry_%s( %ld, \"%s\" ) success\n",
+           op == SLAP_INDEX_ADD_OP ? "add" : "del",
+               e->e_id, e->e_dn );
+#endif
+
+       return LDAP_SUCCESS;
 }
+