Commit 0e16f6ac authored by Howard Chu's avatar Howard Chu
Browse files

Moved AttributeDescription caching into main code:

   Changed AttributeDescription.{ad_cname,ad_lang} to struct berval everywhere
   Deleted ad_free() everywhere
   Added ad_mutex to init.c

The AttributeDescriptions are in a linked list hanging off of the
corresponding AttributeType.
parent 666f201c
......@@ -94,7 +94,7 @@ access_allowed(
assert( desc != NULL );
assert( access > ACL_NONE );
attr = desc->ad_cname->bv_val;
attr = desc->ad_cname.bv_val;
assert( attr != NULL );
......@@ -292,7 +292,7 @@ acl_get(
assert( count != NULL );
assert( desc != NULL );
attr = desc->ad_cname->bv_val;
attr = desc->ad_cname.bv_val;
assert( attr != NULL );
......@@ -463,7 +463,7 @@ acl_mask(
assert( mask != NULL );
assert( desc != NULL );
attr = desc->ad_cname->bv_val;
attr = desc->ad_cname.bv_val;
assert( attr != NULL );
......@@ -685,7 +685,7 @@ acl_mask(
struct berval bv;
int rc, match = 0;
const char *text;
const char *attr = b->a_dn_at->ad_cname->bv_val;
const char *attr = b->a_dn_at->ad_cname.bv_val;
assert( attr != NULL );
......@@ -1081,11 +1081,11 @@ acl_check_modlist(
#ifdef NEW_LOGGING
LDAP_LOG(( "aci", LDAP_LEVEL_DETAIL1,
"acl_check_modlist: conn %d no-user-mod %s: modify access granted\n",
conn->c_connid, mlist->sml_desc->ad_cname->bv_val ));
conn->c_connid, mlist->sml_desc->ad_cname.bv_val ));
#else
Debug( LDAP_DEBUG_ACL, "acl: no-user-mod %s:"
" modify access granted\n",
mlist->sml_desc->ad_cname->bv_val, 0, 0 );
mlist->sml_desc->ad_cname.bv_val, 0, 0 );
#endif
continue;
}
......@@ -1236,7 +1236,6 @@ aci_set_gather (void *cookie, char *name, char *attr)
}
ber_bvecfree(bvals);
}
ad_free(desc, 1);
}
}
ch_free(ndn);
......@@ -1294,7 +1293,6 @@ aci_match_set (
{
backend_attribute(be, NULL, NULL, e,
subjdn, desc, &bvals);
ad_free(desc, 1);
if ( bvals != NULL ) {
if ( bvals[0] != NULL )
set = ch_strdup(bvals[0]->bv_val);
......@@ -1533,7 +1531,6 @@ aci_group_member (
}
done:
if( grp_ad != NULL ) ad_free( grp_ad, 1 );
ch_free(grpdn);
ch_free(grpat);
ch_free(grpoc);
......@@ -1558,7 +1555,7 @@ aci_mask(
struct berval bv, perms, sdn;
char *subjdn;
int rc;
char *attr = desc->ad_cname->bv_val;
char *attr = desc->ad_cname.bv_val;
assert( attr != NULL );
......@@ -1645,7 +1642,6 @@ aci_mask(
}
}
ad_free( ad, 1 );
return rc;
......
......@@ -539,7 +539,7 @@ parse_acl(
fprintf( stderr,
"%s: line %d: group: \"%s\" not allowed by \"%s\"\n",
fname, lineno,
b->a_group_at->ad_cname->bv_val,
b->a_group_at->ad_cname.bv_val,
b->a_group_oc->soc_oid );
acl_usage();
}
......@@ -1200,7 +1200,7 @@ print_access( Access *b )
}
if ( b->a_dn_at != NULL ) {
fprintf( stderr, " dnattr=%s", b->a_dn_at->ad_cname->bv_val );
fprintf( stderr, " dnattr=%s", b->a_dn_at->ad_cname.bv_val );
}
if ( b->a_group_pat != NULL ) {
......@@ -1211,7 +1211,7 @@ print_access( Access *b )
b->a_group_oc->soc_oclass.oc_oid );
if ( b->a_group_at ) {
fprintf( stderr, " attributeType: %s", b->a_group_at->ad_cname->bv_val );
fprintf( stderr, " attributeType: %s", b->a_group_at->ad_cname.bv_val );
}
}
}
......@@ -1234,7 +1234,7 @@ print_access( Access *b )
#ifdef SLAPD_ACI_ENABLED
if ( b->a_aci_at != NULL ) {
fprintf( stderr, " aci=%s", b->a_aci_at->ad_cname->bv_val );
fprintf( stderr, " aci=%s", b->a_aci_at->ad_cname.bv_val );
}
#endif
......
......@@ -18,43 +18,7 @@
#include "ldap_pvt.h"
#include "slap.h"
AttributeDescription *ad_dup(
AttributeDescription *desc )
{
AttributeDescription *ad;
if( desc == NULL ) {
return NULL;
}
ad = (AttributeDescription *) ch_malloc( sizeof(AttributeDescription) );
*ad = *desc;
if( ad->ad_cname != NULL ) {
ad->ad_cname = ber_bvdup( ad->ad_cname );
}
if( ad->ad_lang != NULL ) {
ad->ad_lang = ch_strdup( ad->ad_lang );
}
return ad;
}
void
ad_free( AttributeDescription *ad, int freeit )
{
if( ad == NULL ) return;
if( ad->ad_cname != NULL ) {
ber_bvfree( ad->ad_cname );
}
free( ad->ad_lang );
if( freeit ) free( ad );
}
extern ldap_pvt_thread_mutex_t ad_mutex; /* init.c */
static int ad_keystring(
struct berval *bv )
......@@ -92,8 +56,8 @@ int slap_bv2ad(
{
int rtn = LDAP_UNDEFINED_TYPE;
int i;
AttributeDescription desc;
char **tokens;
AttributeDescription desc, *d2;
char *name, *options;
assert( ad != NULL );
assert( *ad == NULL ); /* temporary */
......@@ -109,25 +73,37 @@ int slap_bv2ad(
return rtn;
}
tokens = str2charray( bv->bv_val, ";");
if( tokens == NULL || *tokens == NULL ) {
*text = "no attribute type";
goto done;
}
desc.ad_type = at_find( *tokens );
/* find valid base attribute type; parse in place */
name = bv->bv_val;
options = strchr(name, ';');
if (options != NULL) *options = '\0';
desc.ad_type = at_find( name );
if (options != NULL) *options = ';';
if( desc.ad_type == NULL ) {
*text = "attribute type undefined";
goto done;
return rtn;
}
desc.ad_flags = SLAP_DESC_NONE;
desc.ad_lang = NULL;
if (options != NULL)
desc.ad_cname.bv_len = options - name;
else
desc.ad_cname.bv_len = strlen(name);
for( i=1; tokens[i] != NULL; i++ ) {
if( strcasecmp( tokens[i], "binary" ) == 0 ) {
desc.ad_flags = SLAP_DESC_NONE;
desc.ad_lang.bv_len = 0;
desc.ad_lang.bv_val = NULL;
/* parse options in place */
for( ; options != NULL; ) {
name = options+1;
options = strchr( name, ';' );
if ( options != NULL )
i = options - name;
else
i = strlen(name);
if( i == sizeof("binary")-1 && strncasecmp( name, "binary", i) == 0 ) {
if( slap_ad_is_binary( &desc ) ) {
*text = "option \"binary\" specified multiple times";
goto done;
......@@ -141,57 +117,126 @@ int slap_bv2ad(
desc.ad_flags |= SLAP_DESC_BINARY;
} else if ( strncasecmp( tokens[i], "lang-",
sizeof("lang-")-1 ) == 0 && tokens[i][sizeof("lang-")-1] )
} else if ( i >= sizeof("lang-") && strncasecmp( name, "lang-",
sizeof("lang-")-1 ) == 0)
{
if( desc.ad_lang != NULL ) {
if( desc.ad_lang.bv_len != 0 ) {
*text = "multiple language tag options specified";
goto done;
}
desc.ad_lang = ch_strdup( tokens[i] );
/* normalize to all lower case, it's easy */
ldap_pvt_str2lower( desc.ad_lang );
desc.ad_lang.bv_val = name;
desc.ad_lang.bv_len = i;
} else {
*text = "unrecognized option";
goto done;
}
}
desc.ad_cname = ch_malloc( sizeof( struct berval ) );
desc.ad_cname->bv_len = strlen( desc.ad_type->sat_cname );
if( slap_ad_is_binary( &desc ) ) {
desc.ad_cname->bv_len += sizeof("binary");
}
if( desc.ad_lang != NULL ) {
desc.ad_cname->bv_len += 1 + strlen( desc.ad_lang );
/* see if a matching description is already cached */
for (d2 = desc.ad_type->sat_ad; d2; d2=d2->ad_next) {
if (d2->ad_flags != desc.ad_flags)
continue;
if (d2->ad_lang.bv_len != desc.ad_lang.bv_len)
continue;
if (d2->ad_lang.bv_len == 0)
break;
if (strncasecmp(d2->ad_lang.bv_val, desc.ad_lang.bv_val,
desc.ad_lang.bv_len) == 0)
break;
}
desc.ad_cname->bv_val = ch_malloc( desc.ad_cname->bv_len + 1 );
/* Not found, add new one */
while (d2 == NULL) {
int dlen = 0;
/* uses a single mutex instead of one per attributetype.
* I don't believe this is a significant bottleneck. If
* necessary, could change to a per-AttrType rwlock.
*/
ldap_pvt_thread_mutex_lock( &ad_mutex );
/* Check again just in case another thread added it */
for (d2 = desc.ad_type->sat_ad; d2; d2=d2->ad_next) {
if (d2->ad_flags != desc.ad_flags)
continue;
if (d2->ad_lang.bv_len != desc.ad_lang.bv_len)
continue;
if (d2->ad_lang.bv_len == 0)
break;
if (strncasecmp(d2->ad_lang.bv_val,desc.ad_lang.bv_val,
desc.ad_lang.bv_len) == 0)
break;
}
/* Some other thread added it before we got the lock. */
if (d2 != NULL) {
ldap_pvt_thread_mutex_unlock( &ad_mutex );
break;
}
strcpy( desc.ad_cname->bv_val, desc.ad_type->sat_cname );
if( slap_ad_is_binary( &desc ) ) {
strcat( desc.ad_cname->bv_val, ";binary" );
}
/* Allocate a single contiguous block. If there are no
* options, we just need space for the AttrDesc structure.
* Otherwise, we need to tack on the full name length +
* options length.
*/
i = sizeof(AttributeDescription);
if (desc.ad_lang.bv_len || desc.ad_flags != SLAP_DESC_NONE) {
if (desc.ad_lang.bv_len)
dlen = desc.ad_lang.bv_len+1;
dlen += strlen(desc.ad_type->sat_cname)+1;
if( slap_ad_is_binary( &desc ) ) {
dlen += sizeof("binary");
}
}
if( desc.ad_lang != NULL ) {
strcat( desc.ad_cname->bv_val, ";" );
strcat( desc.ad_cname->bv_val, desc.ad_lang );
d2 = ch_malloc(i + dlen);
d2->ad_type = desc.ad_type;
d2->ad_flags = desc.ad_flags;
d2->ad_cname.bv_len = desc.ad_cname.bv_len;
d2->ad_lang.bv_len = desc.ad_lang.bv_len;
if (dlen == 0) {
d2->ad_cname.bv_val = d2->ad_type->sat_cname;
d2->ad_lang.bv_val = NULL;
} else {
d2->ad_cname.bv_val = (char *)(d2+1);
strcpy(d2->ad_cname.bv_val, d2->ad_type->sat_cname);
if( slap_ad_is_binary( &desc ) ) {
strcpy(d2->ad_cname.bv_val+d2->ad_cname.bv_len,
";binary");
d2->ad_cname.bv_len += sizeof("binary");
}
if( d2->ad_lang.bv_len ) {
d2->ad_cname.bv_val[d2->ad_cname.bv_len++]=';';
d2->ad_lang.bv_val = d2->ad_cname.bv_val+
d2->ad_cname.bv_len;
strncpy(d2->ad_lang.bv_val,desc.ad_lang.bv_val,
d2->ad_lang.bv_len);
d2->ad_lang.bv_val[d2->ad_lang.bv_len] = '\0';
ldap_pvt_str2lower(d2->ad_lang.bv_val);
d2->ad_cname.bv_len += d2->ad_lang.bv_len;
}
}
/* Add new desc to list. We always want the bare Desc with
* no options to stay at the head of the list, assuming
* that one will be used most frequently.
*/
if (desc.ad_type->sat_ad == NULL || dlen == 0) {
d2->ad_next = desc.ad_type->sat_ad;
desc.ad_type->sat_ad = d2;
} else {
d2->ad_next = desc.ad_type->sat_ad->ad_next;
desc.ad_type->sat_ad->ad_next = d2;
}
ldap_pvt_thread_mutex_unlock( &ad_mutex );
}
if( *ad == NULL ) {
*ad = ch_malloc( sizeof( AttributeDescription ) );
*ad = d2;
} else {
**ad = *d2;
}
**ad = desc;
rtn = LDAP_SUCCESS;
done:
charray_free( tokens );
return rtn;
}
......@@ -208,8 +253,9 @@ int is_ad_subtype(
return 0;
}
if( super->ad_lang != NULL && ( sub->ad_lang == NULL
|| strcasecmp( super->ad_lang, sub->ad_lang )))
if( super->ad_lang.bv_len && (sub->ad_lang.bv_len !=
super->ad_lang.bv_len || strcmp( super->ad_lang.bv_val,
sub->ad_lang.bv_val)))
{
return 0;
}
......@@ -234,8 +280,6 @@ int ad_inlist(
rc = is_ad_subtype( desc, ad );
ad_free( ad, 1 );
if( rc ) return 1;
}
......@@ -260,10 +304,9 @@ int slap_bv2undef_ad(
AttributeDescription **ad,
const char **text )
{
AttributeDescription desc;
AttributeDescription *desc;
assert( ad != NULL );
assert( *ad == NULL ); /* temporary */
if( bv == NULL || bv->bv_len == 0 ) {
*text = "empty attribute description";
......@@ -276,21 +319,36 @@ int slap_bv2undef_ad(
return LDAP_UNDEFINED_TYPE;
}
desc.ad_type = slap_schema.si_at_undefined;
desc.ad_flags = SLAP_DESC_NONE;
desc.ad_lang = NULL;
for (desc = slap_schema.si_at_undefined->sat_ad; desc;
desc=desc->ad_next)
if (desc->ad_cname.bv_len == bv->bv_len &&
!strcasecmp(desc->ad_cname.bv_val, bv->bv_val))
break;
if (!desc) {
desc = ch_malloc(sizeof(AttributeDescription) +
bv->bv_len + 1);
desc->ad_flags = SLAP_DESC_NONE;
desc->ad_lang.bv_val = NULL;
desc->ad_lang.bv_len = 0;
desc.ad_cname = ber_bvdup( bv );
desc->ad_cname.bv_len = bv->bv_len;
desc->ad_cname.bv_val = (char *)(desc+1);
strcpy(desc->ad_cname.bv_val, bv->bv_val);
/* canoncial to upper case */
ldap_pvt_str2upper( bv->bv_val );
/* canonical to upper case */
ldap_pvt_str2upper( desc->ad_cname.bv_val );
if( *ad == NULL ) {
*ad = ch_malloc( sizeof( AttributeDescription ) );
desc->ad_type = slap_schema.si_at_undefined;
desc->ad_next = desc->ad_type->sat_ad;
desc->ad_type->sat_ad = desc;
}
**ad = desc;
if (!*ad)
*ad = desc;
else
**ad = *desc;
return LDAP_SUCCESS;
}
......@@ -29,7 +29,6 @@ static void at_index_print( void );
void
attr_free( Attribute *a )
{
ad_free( a->a_desc, 1 );
ber_bvecfree( a->a_vals );
free( a );
}
......@@ -74,7 +73,7 @@ Attribute *attr_dup( Attribute *a )
tmp->a_vals = NULL;
}
tmp->a_desc = ad_dup( a->a_desc );
tmp->a_desc = a->a_desc;
tmp->a_next = NULL;
return tmp;
......@@ -124,7 +123,7 @@ attr_merge(
if ( *a == NULL ) {
*a = (Attribute *) ch_malloc( sizeof(Attribute) );
(*a)->a_desc = ad_dup( desc );
(*a)->a_desc = desc;
(*a)->a_vals = NULL;
(*a)->a_next = NULL;
}
......
......@@ -21,7 +21,6 @@ ava_free(
int freeit
)
{
ad_free( ava->aa_desc, 1 );
ber_bvfree( ava->aa_value );
if ( freeit ) {
ch_free( (char *) ava );
......@@ -70,7 +69,6 @@ get_ava(
ch_free( value.bv_val );
if( rc != LDAP_SUCCESS ) {
ad_free( aa->aa_desc, 1 );
ch_free( aa );
return rc;
}
......
......@@ -203,18 +203,17 @@ bdb_attr_index_config(
#ifdef NEW_LOGGING
LDAP_LOG(( "backend", LDAP_LEVEL_DETAIL1,
"attr_index_config: index %s 0x%04x\n",
ad->ad_cname->bv_val, mask ));
ad->ad_cname.bv_val, mask ));
#else
Debug( LDAP_DEBUG_CONFIG, "index %s 0x%04x\n",
ad->ad_cname->bv_val, mask, 0 );
ad->ad_cname.bv_val, mask, 0 );
#endif
#ifdef SLAPD_USE_AD
a->ai_desc = ad;
#else
a->ai_desc = ch_strdup( ad->ad_cname->bv_val );
ad_free( ad, 1 );
a->ai_desc = ch_strdup( ad->ad_cname.bv_val );
#endif
a->ai_indexmask = mask;
......@@ -242,9 +241,7 @@ static void
ainfo_free( void *attr )
{
AttrInfo *ai = attr;
#ifdef SLAPD_USE_AD
ad_free( ai->ai_desc, 1 );
#else
#ifndef SLAPD_USE_AD
free( ai->ai_desc );
#endif
free( ai );
......
......@@ -26,7 +26,7 @@ ad_type_cmp(
AttributeDescription *ad
)
{
return strcasecmp(desc, ad->ad_cname->bv_val);
return strcasecmp(desc, ad->ad_cname.bv_val);
}
static int
......@@ -35,7 +35,7 @@ ad_info_cmp(
AttributeDescription *a2
)
{
return strcasecmp(a1->ad_cname->bv_val, a2->ad_cname->bv_val);
return strcasecmp(a1->ad_cname.bv_val, a2->ad_cname.bv_val);
}
AttributeDescription *
......@@ -87,7 +87,7 @@ int bdb_encode(Entry *e, struct berval **bv)
for (a=e->e_attrs; a; a=a->a_next) {
/* For AttributeDesc, we only store the attr name */
siz += sizeof(Attribute);
len += a->a_desc->ad_cname->bv_len+1;
len += a->a_desc->ad_cname.bv_len+1;
for (i=0; a->a_vals[i]; i++) {
siz += sizeof(struct berval *);
siz += sizeof(struct berval);
......@@ -116,9 +116,9 @@ int bdb_encode(Entry *e, struct berval **bv)
b = (Attribute *)data;
data = (char *)(b+1);
b->a_desc = (AttributeDescription *)(ptr-base);
memcpy(ptr, a->a_desc->ad_cname->bv_val,
a->a_desc->ad_cname->bv_len);
ptr += a->a_desc->ad_cname->bv_len;
memcpy(ptr, a->a_desc->ad_cname.bv_val,
a->a_desc->ad_cname.bv_len);
ptr += a->a_desc->ad_cname.bv_len;
*ptr++ = '\0';
if (a->a_vals) {
bvl = (struct berval **)data;
......
......@@ -27,11 +27,11 @@ static slap_mask_t index_mask(
/* we do not support indexing of binary attributes */
if( slap_ad_is_binary( desc ) ) return 0;
bdb_attr_mask( be->be_private, desc->ad_cname->bv_val, &mask );
bdb_attr_mask( be->be_private, desc->ad_cname.bv_val, &mask );
if( mask ) {
*atname = desc->ad_cname->bv_val;
*dbname = desc->ad_cname->bv_val;
*atname = desc->ad_cname.bv_val;
*dbname = desc->ad_cname.bv_val;
return mask;
}
......@@ -40,7 +40,7 @@ static slap_mask_t index_mask(
bdb_attr_mask( be->be_private, desc->ad_type->sat_cname, &mask );
if( mask & SLAP_INDEX_AUTO_LANG ) {
*atname = desc->ad_cname->bv_val;
*atname = desc->ad_cname.bv_val;
*dbname = desc->ad_type->sat_cname;
return mask;
}
......@@ -248,7 +248,6 @@ static int indexer(
}
done:
ad_free( ad, 1 );
return rc;
}
......@@ -256,7 +255,7 @@ static int index_at_values(
Backend *be,
DB_TXN *txn,
AttributeType *type,
const char *lang,
struct berval *lang,
struct berval **vals,
ID id,
int op,
......@@ -295,13 +294,13