From dfafda4128daec86e30b57624877a044917faff0 Mon Sep 17 00:00:00 2001 From: Howard Chu Date: Fri, 17 Nov 2006 22:52:20 +0000 Subject: [PATCH] Better tracking of system schema, refresh cn=schema after moduleloads --- servers/slapd/at.c | 10 ++-- servers/slapd/bconfig.c | 123 +++++++++++++++++++++++++++++++++++++--- servers/slapd/oc.c | 7 ++- servers/slapd/oidm.c | 7 ++- 4 files changed, 127 insertions(+), 20 deletions(-) diff --git a/servers/slapd/at.c b/servers/slapd/at.c index e02acf90a0..acdeff290b 100644 --- a/servers/slapd/at.c +++ b/servers/slapd/at.c @@ -62,7 +62,7 @@ static LDAP_STAILQ_HEAD(ATList, slap_attribute_type) attr_list = LDAP_STAILQ_HEAD_INITIALIZER(attr_list); /* Last hardcoded attribute registered */ -static AttributeType *attr_sys_tail; +AttributeType *at_sys_tail; int at_oc_cache; @@ -529,8 +529,8 @@ at_insert( } if ( sat->sat_flags & SLAP_AT_HARDCODE ) { - prev = attr_sys_tail; - attr_sys_tail = sat; + prev = at_sys_tail; + at_sys_tail = sat; } if ( prev ) { LDAP_STAILQ_INSERT_AFTER( &attr_list, prev, sat, sat_next ); @@ -924,7 +924,7 @@ at_unparse( BerVarray *res, AttributeType *start, AttributeType *end, int sys ) /* count the result size */ i = 0; for ( at=start; at; at=LDAP_STAILQ_NEXT(at, sat_next)) { - if ( sys && !(at->sat_flags & SLAP_AT_HARDCODE)) continue; + if ( sys && !(at->sat_flags & SLAP_AT_HARDCODE)) break; i++; if ( at == end ) break; } @@ -941,7 +941,7 @@ at_unparse( BerVarray *res, AttributeType *start, AttributeType *end, int sys ) i = 0; for ( at=start; at; at=LDAP_STAILQ_NEXT(at, sat_next)) { LDAPAttributeType lat, *latp; - if ( sys && !(at->sat_flags & SLAP_AT_HARDCODE)) continue; + if ( sys && !(at->sat_flags & SLAP_AT_HARDCODE)) break; if ( at->sat_oidmacro ) { lat = at->sat_atype; lat.at_oid = at->sat_oidmacro; diff --git a/servers/slapd/bconfig.c b/servers/slapd/bconfig.c index 89b59891ab..e8fa653bfd 100644 --- a/servers/slapd/bconfig.c +++ b/servers/slapd/bconfig.c @@ -37,8 +37,11 @@ #include "config.h" -static struct berval config_rdn = BER_BVC("cn=config"); -static struct berval schema_rdn = BER_BVC("cn=schema"); +#define CONFIG_RDN "cn=config" +#define SCHEMA_RDN "cn=schema" + +static struct berval config_rdn = BER_BVC(CONFIG_RDN); +static struct berval schema_rdn = BER_BVC(SCHEMA_RDN); extern int slap_DN_strict; /* dn.c */ @@ -71,6 +74,8 @@ typedef struct { int cb_use_ldif; } CfBackInfo; +static CfBackInfo cfBackInfo; + static char *passwd_salt; static char *logfileName; #ifdef SLAP_AUTH_REWRITE @@ -81,15 +86,25 @@ static struct berval cfdir; /* Private state */ static AttributeDescription *cfAd_backend, *cfAd_database, *cfAd_overlay, - *cfAd_include; + *cfAd_include, *cfAd_attr, *cfAd_oc, *cfAd_om; static ConfigFile *cfn; static Avlnode *CfOcTree; +/* System schema state */ +extern AttributeType *at_sys_tail; /* at.c */ +extern ObjectClass *oc_sys_tail; /* oc.c */ +extern OidMacro *om_sys_tail; /* oidm.c */ +static AttributeType *cf_at_tail; +static ObjectClass *cf_oc_tail; +static OidMacro *cf_om_tail; + static int config_add_internal( CfBackInfo *cfb, Entry *e, ConfigArgs *ca, SlapReply *rs, int *renumber, Operation *op ); +static int config_check_schema( CfBackInfo *cfb ); + static ConfigDriver config_fname; static ConfigDriver config_cfdir; static ConfigDriver config_generic; @@ -1611,6 +1626,10 @@ config_generic(ConfigArgs *c) { ber_str2bv(ptr, 0, 1, &bv); ber_bvarray_add( &modcur->mp_loads, &bv ); } + /* Check for any new hardcoded schema */ + if ( c->op == LDAP_MOD_ADD && CONFIG_ONLINE_ADD( c )) { + config_check_schema( &cfBackInfo ); + } break; case CFG_MODPATH: @@ -4746,6 +4765,87 @@ config_build_modules( ConfigArgs *c, CfEntryInfo *ceparent, } #endif +static int +config_check_schema(CfBackInfo *cfb) +{ + struct berval schema_dn = BER_BVC(SCHEMA_RDN "," CONFIG_RDN); + ConfigArgs c = {0}; + ConfigFile *cf = cfb->cb_config; + CfEntryInfo *ce, *last; + Entry *e; + + /* If there's no root entry, we must be in the midst of converting */ + if ( !cfb->cb_root ) + return 0; + + /* Make sure the main schema entry exists */ + ce = config_find_base( cfb->cb_root, &schema_dn, &last ); + if ( ce ) { + Attribute *a; + struct berval *bv; + + e = ce->ce_entry; + + /* Make sure it's up to date */ + if ( cf_om_tail != om_sys_tail ) { + a = attr_find( e->e_attrs, cfAd_om ); + if ( a ) { + if ( a->a_nvals != a->a_vals ) + ber_bvarray_free( a->a_nvals ); + ber_bvarray_free( a->a_vals ); + a->a_vals = NULL; + a->a_nvals = NULL; + } + oidm_unparse( &bv, NULL, NULL, 1 ); + attr_merge_normalize( e, cfAd_om, bv, NULL ); + ber_bvarray_free( bv ); + cf_om_tail = om_sys_tail; + } + if ( cf_at_tail != at_sys_tail ) { + a = attr_find( e->e_attrs, cfAd_attr ); + if ( a ) { + if ( a->a_nvals != a->a_vals ) + ber_bvarray_free( a->a_nvals ); + ber_bvarray_free( a->a_vals ); + a->a_vals = NULL; + a->a_nvals = NULL; + } + at_unparse( &bv, NULL, NULL, 1 ); + attr_merge_normalize( e, cfAd_attr, bv, NULL ); + ber_bvarray_free( bv ); + cf_at_tail = at_sys_tail; + } + if ( cf_oc_tail != oc_sys_tail ) { + a = attr_find( e->e_attrs, cfAd_oc ); + if ( a ) { + if ( a->a_nvals != a->a_vals ) + ber_bvarray_free( a->a_nvals ); + ber_bvarray_free( a->a_vals ); + a->a_vals = NULL; + a->a_nvals = NULL; + } + oc_unparse( &bv, NULL, NULL, 1 ); + attr_merge_normalize( e, cfAd_oc, bv, NULL ); + ber_bvarray_free( bv ); + cf_oc_tail = oc_sys_tail; + } + } else { + SlapReply rs = {REP_RESULT}; + c.private = NULL; + e = config_build_entry( NULL, &rs, cfb->cb_root, &c, &schema_rdn, + &CFOC_SCHEMA, NULL ); + if ( !e ) { + return -1; + } + ce = e->e_private; + ce->ce_private = cfb->cb_config; + cf_at_tail = at_sys_tail; + cf_oc_tail = oc_sys_tail; + cf_om_tail = om_sys_tail; + } + return 0; +} + static const char *defacl[] = { NULL, "to", "*", "by", "*", "none", NULL }; @@ -4776,9 +4876,10 @@ config_back_db_open( BackendDB *be ) parse_acl(be, "config_back_db_open", 0, 6, (char **)defacl, 0 ); } - /* If we read the config from back-ldif, nothing to do here */ - if ( cfb->cb_got_ldif ) - return 0; + /* If we read the config from back-ldif, do some quick sanity checks */ + if ( cfb->cb_got_ldif ) { + return config_check_schema( cfb ); + } if ( cfb->cb_use_ldif ) { thrctx = ldap_pvt_thread_pool_context(); @@ -4838,6 +4939,9 @@ config_back_db_open( BackendDB *be ) } ce = e->e_private; ce->ce_private = cfb->cb_config; + cf_at_tail = at_sys_tail; + cf_oc_tail = oc_sys_tail; + cf_om_tail = om_sys_tail; /* Create schema nodes for included schema... */ if ( cfb->cb_config->c_kids ) { @@ -5028,8 +5132,6 @@ config_back_db_destroy( BackendDB *be ) backend_destroy_one( &cfb->cb_db, 0 ); } - free( be->be_private ); - loglevel_destroy(); return 0; @@ -5041,7 +5143,7 @@ config_back_db_init( BackendDB *be ) struct berval dn; CfBackInfo *cfb; - cfb = ch_calloc( 1, sizeof(CfBackInfo)); + cfb = &cfBackInfo; cfb->cb_config = ch_calloc( 1, sizeof(ConfigFile)); cfn = cfb->cb_config; be->be_private = cfb; @@ -5145,9 +5247,12 @@ static struct { char *name; AttributeDescription **desc; } ads[] = { + { "attribute", &cfAd_attr }, { "backend", &cfAd_backend }, { "database", &cfAd_database }, { "include", &cfAd_include }, + { "objectclass", &cfAd_oc }, + { "objectidentifier", &cfAd_om }, { "overlay", &cfAd_overlay }, { NULL, NULL } }; diff --git a/servers/slapd/oc.c b/servers/slapd/oc.c index 87ced2d7cb..c6b50fde48 100644 --- a/servers/slapd/oc.c +++ b/servers/slapd/oc.c @@ -134,7 +134,8 @@ static Avlnode *oc_index = NULL; static Avlnode *oc_cache = NULL; static LDAP_STAILQ_HEAD(OCList, slap_object_class) oc_list = LDAP_STAILQ_HEAD_INITIALIZER(oc_list); -static ObjectClass *oc_sys_tail; + +ObjectClass *oc_sys_tail; static int oc_index_cmp( @@ -805,7 +806,7 @@ oc_unparse( BerVarray *res, ObjectClass *start, ObjectClass *end, int sys ) /* count the result size */ i = 0; for ( oc=start; oc; oc=LDAP_STAILQ_NEXT(oc, soc_next)) { - if ( sys && !(oc->soc_flags & SLAP_OC_HARDCODE)) continue; + if ( sys && !(oc->soc_flags & SLAP_OC_HARDCODE)) break; i++; if ( oc == end ) break; } @@ -822,7 +823,7 @@ oc_unparse( BerVarray *res, ObjectClass *start, ObjectClass *end, int sys ) i = 0; for ( oc=start; oc; oc=LDAP_STAILQ_NEXT(oc, soc_next)) { LDAPObjectClass loc, *locp; - if ( sys && !(oc->soc_flags & SLAP_OC_HARDCODE)) continue; + if ( sys && !(oc->soc_flags & SLAP_OC_HARDCODE)) break; if ( oc->soc_oidmacro ) { loc = oc->soc_oclass; loc.oc_oid = oc->soc_oidmacro; diff --git a/servers/slapd/oidm.c b/servers/slapd/oidm.c index 2fe6cc552c..3279336e8f 100644 --- a/servers/slapd/oidm.c +++ b/servers/slapd/oidm.c @@ -29,7 +29,7 @@ static LDAP_STAILQ_HEAD(OidMacroList, slap_oid_macro) om_list = LDAP_STAILQ_HEAD_INITIALIZER(om_list); -static OidMacro *om_sys_tail; +OidMacro *om_sys_tail; /* Replace an OID Macro invocation with its full numeric OID. * If the macro is used with "macroname:suffix" append ".suffix" @@ -149,6 +149,7 @@ parse_oidm( if ( !user ) { om->som_flags |= SLAP_OM_HARDCODE; prev = om_sys_tail; + om_sys_tail = om; } if ( prev ) { @@ -173,7 +174,7 @@ void oidm_unparse( BerVarray *res, OidMacro *start, OidMacro *end, int sys ) /* count the result size */ i = 0; for ( om=start; om; om=LDAP_STAILQ_NEXT(om, som_next)) { - if ( sys && !(om->som_flags & SLAP_OM_HARDCODE)) continue; + if ( sys && !(om->som_flags & SLAP_OM_HARDCODE)) break; for ( j=0; !BER_BVISNULL(&om->som_names[j]); j++ ); i += j; if ( om == end ) break; @@ -189,7 +190,7 @@ void oidm_unparse( BerVarray *res, OidMacro *start, OidMacro *end, int sys ) ibuf[0] = '\0'; } for ( i=0,om=start; om; om=LDAP_STAILQ_NEXT(om, som_next)) { - if ( sys && !(om->som_flags & SLAP_OM_HARDCODE)) continue; + if ( sys && !(om->som_flags & SLAP_OM_HARDCODE)) break; for ( j=0; !BER_BVISNULL(&om->som_names[j]); i++,j++ ) { if ( !sys ) { idx.bv_len = sprintf(idx.bv_val, "{%d}", i ); -- 2.39.5