X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=servers%2Fslapd%2Fentry.c;h=68f69a14186b3de4ef8024cc8ac066c9d7eadbb7;hb=450f352ec14a6c053b50cd2016c197d461990d8e;hp=823d3fbd177ee068e09c6d89a212a4900e73ca19;hpb=f63f46f0b1baf0e7f208b9181b8927f2b2ca5416;p=openldap diff --git a/servers/slapd/entry.c b/servers/slapd/entry.c index 823d3fbd17..68f69a1418 100644 --- a/servers/slapd/entry.c +++ b/servers/slapd/entry.c @@ -2,7 +2,7 @@ /* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * - * Copyright 1998-2006 The OpenLDAP Foundation. + * Copyright 1998-2009 The OpenLDAP Foundation. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -86,8 +86,8 @@ int entry_destroy(void) return attr_destroy(); } - -int entry_init(void) +int +entry_init(void) { ldap_pvt_thread_mutex_init( &entry2str_mutex ); ldap_pvt_thread_mutex_init( &entry_mutex ); @@ -100,6 +100,8 @@ str2entry( char *s ) return str2entry2( s, 1 ); } +#define bvcasematch(bv1, bv2) (ber_bvstrcasecmp(bv1, bv2) == 0) + Entry * str2entry2( char *s, int checkvals ) { @@ -166,6 +168,11 @@ str2entry2( char *s, int checkvals ) break; } i++; + if (i >= lines) { + Debug( LDAP_DEBUG_TRACE, + "<= str2entry ran past end of entry\n", 0, 0, 0 ); + goto fail; + } rc = ldif_parse_line2( s, type+i, vals+i, &freev ); freeval[i] = freev; @@ -175,9 +182,7 @@ str2entry2( char *s, int checkvals ) continue; } - if ( type[i].bv_len == dn_bv.bv_len && - strcasecmp( type[i].bv_val, dn_bv.bv_val ) == 0 ) { - + if ( bvcasematch( &type[i], &dn_bv ) ) { if ( e->e_dn != NULL ) { Debug( LDAP_DEBUG_ANY, "str2entry: " "entry %ld has multiple DNs \"%s\" and \"%s\"\n", @@ -215,7 +220,7 @@ str2entry2( char *s, int checkvals ) for (i=0; iad_cname ))) { - ad = NULL; - rc = slap_bv2ad( type+i, &ad, &text ); - - if( rc != LDAP_SUCCESS ) { - Debug( slapMode & SLAP_TOOL_MODE - ? LDAP_DEBUG_ANY : LDAP_DEBUG_TRACE, - "<= str2entry: str2ad(%s): %s\n", type[i].bv_val, text, 0 ); - if( slapMode & SLAP_TOOL_MODE ) { - goto fail; - } - - rc = slap_bv2undef_ad( type+i, &ad, &text, 0 ); + if ( lines > 0 ) { + for ( i=0; i<=lines; i++ ) { + ad_prev = ad; + if ( !ad || ( iad_cname ))) { + ad = NULL; + rc = slap_bv2ad( type+i, &ad, &text ); + if( rc != LDAP_SUCCESS ) { + Debug( slapMode & SLAP_TOOL_MODE + ? LDAP_DEBUG_ANY : LDAP_DEBUG_TRACE, + "<= str2entry: str2ad(%s): %s\n", type[i].bv_val, text, 0 ); + if( slapMode & SLAP_TOOL_MODE ) { + goto fail; + } + + rc = slap_bv2undef_ad( type+i, &ad, &text, 0 ); + if( rc != LDAP_SUCCESS ) { + Debug( LDAP_DEBUG_ANY, + "<= str2entry: slap_str2undef_ad(%s): %s\n", + type[i].bv_val, text, 0 ); + goto fail; + } + } + + /* require ';binary' when appropriate (ITS#5071) */ + if ( slap_syntax_is_binary( ad->ad_type->sat_syntax ) && !slap_ad_is_binary( ad ) ) { Debug( LDAP_DEBUG_ANY, - "<= str2entry: slap_str2undef_ad(%s): %s\n", - type[i].bv_val, text, 0 ); + "str2entry: attributeType %s #%d: " + "needs ';binary' transfer as per syntax %s\n", + ad->ad_cname.bv_val, 0, + ad->ad_type->sat_syntax->ssyn_oid ); goto fail; } } - } - - if (( ad_prev && ad != ad_prev ) || ( i == lines )) { - int j, k; - atail->a_next = attr_alloc( NULL ); - atail = atail->a_next; - atail->a_flags = 0; - atail->a_desc = ad_prev; - atail->a_vals = ch_malloc( (attr_cnt + 1) * sizeof(struct berval)); - if( ad_prev->ad_type->sat_equality && - ad_prev->ad_type->sat_equality->smr_normalize ) - atail->a_nvals = ch_malloc( (attr_cnt + 1) * sizeof(struct berval)); - else - atail->a_nvals = NULL; - k = i - attr_cnt; - for ( j=0; ja_vals[j] = vals[k]; + + if (( ad_prev && ad != ad_prev ) || ( i == lines )) { + int j, k; + /* FIXME: we only need this when migrating from an unsorted DB */ + if ( atail != &ahead && atail->a_desc->ad_type->sat_flags & SLAP_AT_SORTED_VAL ) { + rc = slap_sort_vals( (Modifications *)atail, &text, &j, NULL ); + if ( rc == LDAP_SUCCESS ) { + atail->a_flags |= SLAP_ATTR_SORTED_VALS; + } else if ( rc == LDAP_TYPE_OR_VALUE_EXISTS ) { + Debug( LDAP_DEBUG_ANY, + "str2entry: attributeType %s value #%d provided more than once\n", + atail->a_desc->ad_cname.bv_val, j, 0 ); + goto fail; + } + } + atail->a_next = attr_alloc( NULL ); + atail = atail->a_next; + atail->a_flags = 0; + atail->a_numvals = attr_cnt; + atail->a_desc = ad_prev; + atail->a_vals = ch_malloc( (attr_cnt + 1) * sizeof(struct berval)); + if( ad_prev->ad_type->sat_equality && + ad_prev->ad_type->sat_equality->smr_normalize ) + atail->a_nvals = ch_malloc( (attr_cnt + 1) * sizeof(struct berval)); else - ber_dupbv( atail->a_vals+j, &vals[k] ); - vals[k].bv_val = NULL; + atail->a_nvals = NULL; + k = i - attr_cnt; + for ( j=0; ja_vals[j] = vals[k]; + else + ber_dupbv( atail->a_vals+j, &vals[k] ); + vals[k].bv_val = NULL; + if ( atail->a_nvals ) { + atail->a_nvals[j] = nvals[k]; + nvals[k].bv_val = NULL; + } + k++; + } + BER_BVZERO( &atail->a_vals[j] ); if ( atail->a_nvals ) { - atail->a_nvals[j] = nvals[k]; - nvals[k].bv_val = NULL; + BER_BVZERO( &atail->a_nvals[j] ); + } else { + atail->a_nvals = atail->a_vals; } - k++; + attr_cnt = 0; + if ( i == lines ) break; } - BER_BVZERO( &atail->a_vals[j] ); - if ( atail->a_nvals ) { - BER_BVZERO( &atail->a_nvals[j] ); - } else { - atail->a_nvals = atail->a_vals; - } - attr_cnt = 0; - if ( i == lines ) break; - } - - if( slapMode & SLAP_TOOL_MODE ) { - struct berval pval; - slap_syntax_validate_func *validate = - ad->ad_type->sat_syntax->ssyn_validate; - slap_syntax_transform_func *pretty = - ad->ad_type->sat_syntax->ssyn_pretty; - - if ( pretty ) { - rc = ordered_value_pretty( ad, - &vals[i], &pval, NULL ); - - } else if ( validate ) { - /* - * validate value per syntax - */ - rc = ordered_value_validate( ad, &vals[i], LDAP_MOD_ADD ); - - } else { + + if ( BER_BVISNULL( &vals[i] ) ) { Debug( LDAP_DEBUG_ANY, "str2entry: attributeType %s #%d: " - "no validator for syntax %s\n", - ad->ad_cname.bv_val, attr_cnt, - ad->ad_type->sat_syntax->ssyn_oid ); - goto fail; - } - - if( rc != 0 ) { - Debug( LDAP_DEBUG_ANY, - "str2entry: invalid value " - "for attributeType %s #%d (syntax %s)\n", - ad->ad_cname.bv_val, attr_cnt, - ad->ad_type->sat_syntax->ssyn_oid ); + "no value\n", + ad->ad_cname.bv_val, attr_cnt, 0 ); goto fail; } - - if( pretty ) { - if ( freeval[i] ) free( vals[i].bv_val ); - vals[i] = pval; - freeval[i] = 1; + + if( slapMode & SLAP_TOOL_MODE ) { + struct berval pval; + slap_syntax_validate_func *validate = + ad->ad_type->sat_syntax->ssyn_validate; + slap_syntax_transform_func *pretty = + ad->ad_type->sat_syntax->ssyn_pretty; + + if ( pretty ) { + rc = ordered_value_pretty( ad, + &vals[i], &pval, NULL ); + + } else if ( validate ) { + /* + * validate value per syntax + */ + rc = ordered_value_validate( ad, &vals[i], LDAP_MOD_ADD ); + + } else { + Debug( LDAP_DEBUG_ANY, + "str2entry: attributeType %s #%d: " + "no validator for syntax %s\n", + ad->ad_cname.bv_val, attr_cnt, + ad->ad_type->sat_syntax->ssyn_oid ); + goto fail; + } + + if( rc != 0 ) { + Debug( LDAP_DEBUG_ANY, + "str2entry: invalid value " + "for attributeType %s #%d (syntax %s)\n", + ad->ad_cname.bv_val, attr_cnt, + ad->ad_type->sat_syntax->ssyn_oid ); + goto fail; + } + + if( pretty ) { + if ( freeval[i] ) free( vals[i].bv_val ); + vals[i] = pval; + freeval[i] = 1; + } } - } - - if ( ad->ad_type->sat_equality && - ad->ad_type->sat_equality->smr_normalize ) - { - rc = ordered_value_normalize( - SLAP_MR_VALUE_OF_ATTRIBUTE_SYNTAX, - ad, - ad->ad_type->sat_equality, - &vals[i], &nvals[i], NULL ); - - if ( rc ) { - Debug( LDAP_DEBUG_ANY, - "<= str2entry NULL (smr_normalize %d)\n", rc, 0, 0 ); - goto fail; + + if ( ad->ad_type->sat_equality && + ad->ad_type->sat_equality->smr_normalize ) + { + rc = ordered_value_normalize( + SLAP_MR_VALUE_OF_ATTRIBUTE_SYNTAX, + ad, + ad->ad_type->sat_equality, + &vals[i], &nvals[i], NULL ); + + if ( rc ) { + Debug( LDAP_DEBUG_ANY, + "<= str2entry NULL (smr_normalize %s %d)\n", ad->ad_cname.bv_val, rc, 0 ); + goto fail; + } } + + attr_cnt++; } - - attr_cnt++; } free( type ); @@ -444,22 +482,30 @@ entry_clean( Entry *e ) /* e_private must be freed by the caller */ assert( e->e_private == NULL ); + e->e_id = 0; + /* free DNs */ if ( !BER_BVISNULL( &e->e_name ) ) { free( e->e_name.bv_val ); + BER_BVZERO( &e->e_name ); } if ( !BER_BVISNULL( &e->e_nname ) ) { free( e->e_nname.bv_val ); + BER_BVZERO( &e->e_nname ); } if ( !BER_BVISNULL( &e->e_bv ) ) { free( e->e_bv.bv_val ); + BER_BVZERO( &e->e_bv ); } /* free attributes */ - attrs_free( e->e_attrs ); + if ( e->e_attrs ) { + attrs_free( e->e_attrs ); + e->e_attrs = NULL; + } - memset(e, 0, sizeof(Entry)); + e->e_ocflags = 0; } void @@ -473,24 +519,47 @@ entry_free( Entry *e ) ldap_pvt_thread_mutex_unlock( &entry_mutex ); } +/* These parameters work well on AMD64 */ +#if 0 +#define STRIDE 8 +#define STRIPE 5 +#else +#define STRIDE 1 +#define STRIPE 1 +#endif +#define STRIDE_FACTOR (STRIDE*STRIPE) + int entry_prealloc( int num ) { - Entry *e; + Entry *e, **prev, *tmp; slap_list *s; + int i, j; if (!num) return 0; +#if STRIDE_FACTOR > 1 + /* Round up to our stride factor */ + num += STRIDE_FACTOR-1; + num /= STRIDE_FACTOR; + num *= STRIDE_FACTOR; +#endif + s = ch_calloc( 1, sizeof(slap_list) + num * sizeof(Entry)); s->next = entry_chunks; entry_chunks = s; - e = (Entry *)(s+1); - for ( ;num>1; num--) { - e->e_private = e+1; - e++; + prev = &tmp; + for (i=0; ie_private; + e += STRIDE; + } } - e->e_private = entry_list; + *prev = entry_list; entry_list = (Entry *)(s+1); return 0; @@ -656,8 +725,8 @@ ber_len_t entry_flatsize(Entry *e, int norm) */ int entry_encode(Entry *e, struct berval *bv) { - ber_len_t len, dnlen, ndnlen; - int i, nattrs, nvals; + ber_len_t len, dnlen, ndnlen, i; + int nattrs, nvals; Attribute *a; unsigned char *ptr; @@ -690,6 +759,7 @@ int entry_encode(Entry *e, struct berval *bv) *ptr++ = '\0'; if (a->a_vals) { for (i=0; a->a_vals[i].bv_val; i++); + assert( i == a->a_numvals ); entry_putlen(&ptr, i); for (i=0; a->a_vals[i].bv_val; i++) { entry_putlen(&ptr, a->a_vals[i].bv_len); @@ -751,7 +821,7 @@ int entry_decode(EntryHeader *eh, Entry **e, void *ctx) int entry_decode(EntryHeader *eh, Entry **e) #endif { - int i, j, count, nattrs, nvals; + int i, j, nattrs, nvals; int rc; Attribute *a; Entry *x; @@ -803,7 +873,8 @@ int entry_decode(EntryHeader *eh, Entry **e) ptr += i + 1; a->a_desc = ad; a->a_flags = SLAP_ATTR_DONT_FREE_DATA | SLAP_ATTR_DONT_FREE_VALS; - count = j = entry_getlen(&ptr); + j = entry_getlen(&ptr); + a->a_numvals = j; a->a_vals = bptr; while (j) { @@ -835,6 +906,19 @@ int entry_decode(EntryHeader *eh, Entry **e) } else { a->a_nvals = a->a_vals; } + /* FIXME: This is redundant once a sorted entry is saved into the DB */ + if ( a->a_desc->ad_type->sat_flags & SLAP_AT_SORTED_VAL ) { + rc = slap_sort_vals( (Modifications *)a, &text, &j, NULL ); + if ( rc == LDAP_SUCCESS ) { + a->a_flags |= SLAP_ATTR_SORTED_VALS; + } else if ( rc == LDAP_TYPE_OR_VALUE_EXISTS ) { + /* should never happen */ + Debug( LDAP_DEBUG_ANY, + "entry_decode: attributeType %s value #%d provided more than once\n", + a->a_desc->ad_cname.bv_val, j, 0 ); + return rc; + } + } a = a->a_next; nattrs--; if ( !nattrs ) @@ -862,3 +946,77 @@ Entry *entry_dup( Entry *e ) return ret; } +#if 1 +/* Duplicates an entry using a single malloc. Saves CPU time, increases + * heap usage because a single large malloc is harder to satisfy than + * lots of small ones, and the freed space isn't as easily reusable. + * + * Probably not worth using this function. + */ +Entry *entry_dup_bv( Entry *e ) +{ + ber_len_t len; + int nattrs, nvals; + Entry *ret; + struct berval *bvl; + char *ptr; + Attribute *src, *dst; + + ret = entry_alloc(); + + entry_partsize(e, &len, &nattrs, &nvals, 1); + ret->e_id = e->e_id; + ret->e_attrs = attrs_alloc( nattrs ); + ret->e_ocflags = e->e_ocflags; + ret->e_bv.bv_len = len + nvals * sizeof(struct berval); + ret->e_bv.bv_val = ch_malloc( ret->e_bv.bv_len ); + + bvl = (struct berval *)ret->e_bv.bv_val; + ptr = (char *)(bvl + nvals); + + ret->e_name.bv_len = e->e_name.bv_len; + ret->e_name.bv_val = ptr; + AC_MEMCPY( ptr, e->e_name.bv_val, e->e_name.bv_len ); + ptr += e->e_name.bv_len; + *ptr++ = '\0'; + + ret->e_nname.bv_len = e->e_nname.bv_len; + ret->e_nname.bv_val = ptr; + AC_MEMCPY( ptr, e->e_nname.bv_val, e->e_nname.bv_len ); + ptr += e->e_name.bv_len; + *ptr++ = '\0'; + + dst = ret->e_attrs; + for (src = e->e_attrs; src; src=src->a_next,dst=dst->a_next ) { + int i; + dst->a_desc = src->a_desc; + dst->a_flags = SLAP_ATTR_DONT_FREE_DATA | SLAP_ATTR_DONT_FREE_VALS; + dst->a_vals = bvl; + dst->a_numvals = src->a_numvals; + for ( i=0; src->a_vals[i].bv_val; i++ ) { + bvl->bv_len = src->a_vals[i].bv_len; + bvl->bv_val = ptr; + AC_MEMCPY( ptr, src->a_vals[i].bv_val, bvl->bv_len ); + ptr += bvl->bv_len; + *ptr++ = '\0'; + bvl++; + } + BER_BVZERO(bvl); + bvl++; + if ( src->a_vals != src->a_nvals ) { + dst->a_nvals = bvl; + for ( i=0; src->a_nvals[i].bv_val; i++ ) { + bvl->bv_len = src->a_nvals[i].bv_len; + bvl->bv_val = ptr; + AC_MEMCPY( ptr, src->a_nvals[i].bv_val, bvl->bv_len ); + ptr += bvl->bv_len; + *ptr++ = '\0'; + bvl++; + } + BER_BVZERO(bvl); + bvl++; + } + } + return ret; +} +#endif