X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=servers%2Fslapd%2Foverlays%2Fpcache.c;h=450706c12751e13454798016afecc6057b54fb95;hb=2c3aaca62f060cd276cdeb6ad7da617962234aa3;hp=71e04db825d56d34303df1d6b5aaf11bc6d9d9eb;hpb=1e35a2f9d7dd8c5346b16a51e0c4aa9a5fb7984a;p=openldap diff --git a/servers/slapd/overlays/pcache.c b/servers/slapd/overlays/pcache.c index 71e04db825..450706c127 100644 --- a/servers/slapd/overlays/pcache.c +++ b/servers/slapd/overlays/pcache.c @@ -1,7 +1,7 @@ /* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * - * Copyright 2003-2007 The OpenLDAP Foundation. + * Copyright 2003-2008 The OpenLDAP Foundation. * Portions Copyright 2003 IBM Corporation. * Portions Copyright 2003 Symas Corporation. * All rights reserved. @@ -185,15 +185,16 @@ typedef struct cache_manager_s { int numattrsets; /* number of attribute sets */ int cur_entries; /* current number of entries cached */ int max_entries; /* max number of entries cached */ - int num_entries_limit; /* max # of entries in a cacheable query */ + int num_entries_limit; /* max # of entries in a cacheable query */ char response_cb; /* install the response callback * at the tail of the callback list */ #define PCACHE_RESPONSE_CB_HEAD 0 #define PCACHE_RESPONSE_CB_TAIL 1 + char defer_db_open; /* defer open for online add */ time_t cc_period; /* interval between successive consistency checks (sec) */ - int cc_paused; + int cc_paused; void *cc_arg; ldap_pvt_thread_mutex_t cache_mutex; @@ -1367,8 +1368,7 @@ remove_func ( attr = attr_find( rs->sr_entry->e_attrs, ad_queryId ); if ( attr == NULL ) return 0; - for ( count = 0; !BER_BVISNULL( &attr->a_vals[count] ); count++ ) - ; + count = attr->a_numvals; assert( count > 0 ); qi = op->o_tmpalloc( sizeof( struct query_info ), op->o_tmpmemctx ); qi->next = op->o_callback->sc_private; @@ -1450,6 +1450,7 @@ remove_query_data( mod.sml_type = ad_queryId->ad_cname; mod.sml_values = vals; mod.sml_nvalues = NULL; + mod.sml_numvals = 1; mod.sml_next = NULL; Debug( pcache_debug, "REMOVING TEMP ATTR : TEMPLATE=%s\n", @@ -1482,67 +1483,91 @@ filter2template( int* filter_got_oc ) { AttributeDescription *ad; + int len, ret; switch ( f->f_choice ) { case LDAP_FILTER_EQUALITY: ad = f->f_av_desc; - sprintf( fstr->bv_val+fstr->bv_len, "(%s=)", ad->ad_cname.bv_val ); - fstr->bv_len += ad->ad_cname.bv_len + ( sizeof("(=)") - 1 ); + len = STRLENOF( "(=)" ) + ad->ad_cname.bv_len; + ret = snprintf( fstr->bv_val+fstr->bv_len, len + 1, "(%s=)", ad->ad_cname.bv_val ); + assert( ret == len ); + fstr->bv_len += len; break; case LDAP_FILTER_GE: ad = f->f_av_desc; - sprintf( fstr->bv_val+fstr->bv_len, "(%s>=)", ad->ad_cname.bv_val); - fstr->bv_len += ad->ad_cname.bv_len + ( sizeof("(>=)") - 1 ); + len = STRLENOF( "(>=)" ) + ad->ad_cname.bv_len; + ret = snprintf( fstr->bv_val+fstr->bv_len, len + 1, "(%s>=)", ad->ad_cname.bv_val); + assert( ret == len ); + fstr->bv_len += len; break; case LDAP_FILTER_LE: ad = f->f_av_desc; - sprintf( fstr->bv_val+fstr->bv_len, "(%s<=)", ad->ad_cname.bv_val); - fstr->bv_len += ad->ad_cname.bv_len + ( sizeof("(<=)") - 1 ); + len = STRLENOF( "(<=)" ) + ad->ad_cname.bv_len; + ret = snprintf( fstr->bv_val+fstr->bv_len, len + 1, "(%s<=)", ad->ad_cname.bv_val); + assert( ret == len ); + fstr->bv_len += len; break; case LDAP_FILTER_APPROX: ad = f->f_av_desc; - sprintf( fstr->bv_val+fstr->bv_len, "(%s~=)", ad->ad_cname.bv_val); - fstr->bv_len += ad->ad_cname.bv_len + ( sizeof("(~=)") - 1 ); + len = STRLENOF( "(~=)" ) + ad->ad_cname.bv_len; + ret = snprintf( fstr->bv_val+fstr->bv_len, len + 1, "(%s~=)", ad->ad_cname.bv_val); + assert( ret == len ); + fstr->bv_len += len; break; case LDAP_FILTER_SUBSTRINGS: ad = f->f_sub_desc; - sprintf( fstr->bv_val+fstr->bv_len, "(%s=)", ad->ad_cname.bv_val ); - fstr->bv_len += ad->ad_cname.bv_len + ( sizeof("(=)") - 1 ); + len = STRLENOF( "(=)" ) + ad->ad_cname.bv_len; + ret = snprintf( fstr->bv_val+fstr->bv_len, len + 1, "(%s=)", ad->ad_cname.bv_val ); + assert( ret == len ); + fstr->bv_len += len; break; case LDAP_FILTER_PRESENT: ad = f->f_desc; - sprintf( fstr->bv_val+fstr->bv_len, "(%s=*)", ad->ad_cname.bv_val ); - fstr->bv_len += ad->ad_cname.bv_len + ( sizeof("(=*)") - 1 ); + len = STRLENOF( "(=*)" ) + ad->ad_cname.bv_len; + ret = snprintf( fstr->bv_val+fstr->bv_len, len + 1, "(%s=*)", ad->ad_cname.bv_val ); + assert( ret == len ); + fstr->bv_len += len; break; case LDAP_FILTER_AND: case LDAP_FILTER_OR: case LDAP_FILTER_NOT: { int rc = 0; - sprintf( fstr->bv_val+fstr->bv_len, "(%c", - f->f_choice == LDAP_FILTER_AND ? '&' : - f->f_choice == LDAP_FILTER_OR ? '|' : '!' ); - fstr->bv_len += sizeof("(%") - 1; + fstr->bv_val[fstr->bv_len++] = '('; + switch ( f->f_choice ) { + case LDAP_FILTER_AND: + fstr->bv_val[fstr->bv_len] = '&'; + break; + case LDAP_FILTER_OR: + fstr->bv_val[fstr->bv_len] = '|'; + break; + case LDAP_FILTER_NOT: + fstr->bv_val[fstr->bv_len] = '!'; + break; + } + fstr->bv_len++; for ( f = f->f_list; f != NULL; f = f->f_next ) { rc = filter2template( op, f, fstr, filter_attrs, filter_cnt, filter_got_oc ); if ( rc ) break; } - sprintf( fstr->bv_val+fstr->bv_len, ")" ); - fstr->bv_len += sizeof(")") - 1; + fstr->bv_val[fstr->bv_len++] = ')'; + fstr->bv_val[fstr->bv_len] = '\0'; return rc; } default: - strcpy( fstr->bv_val, "(?=?)" ); - fstr->bv_len += sizeof("(?=?)")-1; + /* a filter should at least have room for "()", + * an "=" and for a 1-char attr */ + strcpy( fstr->bv_val, "(?=)" ); + fstr->bv_len += STRLENOF("(?=)"); return -1; } @@ -1876,14 +1901,19 @@ cache_entries( Entry *e; struct berval crp_uuid; char uuidbuf[ LDAP_LUTIL_UUIDSTR_BUFSIZE ]; - Operation op_tmp = *op; + Operation *op_tmp; + Connection conn = {0}; + OperationBuffer opbuf; + void *thrctx = ldap_pvt_thread_pool_context(); query_uuid->bv_len = lutil_uuidstr(uuidbuf, sizeof(uuidbuf)); ber_str2bv(uuidbuf, query_uuid->bv_len, 1, query_uuid); - op_tmp.o_bd = &cm->db; - op_tmp.o_dn = cm->db.be_rootdn; - op_tmp.o_ndn = cm->db.be_rootndn; + connection_fake_init2( &conn, &opbuf, thrctx, 0 ); + op_tmp = &opbuf.ob_op; + op_tmp->o_bd = &cm->db; + op_tmp->o_dn = cm->db.be_rootdn; + op_tmp->o_ndn = cm->db.be_rootndn; Debug( pcache_debug, "UUID for query being added = %s\n", uuidbuf, 0, 0 ); @@ -1893,10 +1923,10 @@ cache_entries( e->e_private = NULL; while ( cm->cur_entries > (cm->max_entries) ) { BER_BVZERO( &crp_uuid ); - remove_query_and_data( &op_tmp, rs, cm, &crp_uuid ); + remove_query_and_data( op_tmp, rs, cm, &crp_uuid ); } - return_val = merge_entry(&op_tmp, e, query_uuid); + return_val = merge_entry(op_tmp, e, query_uuid); ldap_pvt_thread_mutex_lock(&cm->cache_mutex); cm->cur_entries += return_val; Debug( pcache_debug, @@ -1958,7 +1988,8 @@ pcache_op_cleanup( Operation *op, SlapReply *rs ) { rs->sr_attrs = si->save_attrs; op->ors_attrs = si->save_attrs; } - if ( op->o_abandon || rs->sr_err == SLAPD_ABANDON ) { + if ( (op->o_abandon || rs->sr_err == SLAPD_ABANDON) && + si->caching_reason == PC_IGNORE ) { filter_free( si->query.filter ); if ( si->count ) { /* duplicate query, free it */ @@ -1984,6 +2015,9 @@ pcache_op_cleanup( Operation *op, SlapReply *rs ) { case PC_SIZELIMIT: qc->q_sizelimit = rs->sr_nentries; break; + default: + assert( 0 ); + break; } ldap_pvt_thread_rdwr_wunlock(&qc->rwlock); ldap_pvt_thread_mutex_lock(&cm->cache_mutex); @@ -2181,6 +2215,13 @@ pcache_op_privdb( return SLAP_CB_CONTINUE; } + /* The cache DB isn't open yet */ + if ( cm->defer_db_open ) { + send_ldap_error( op, rs, LDAP_UNAVAILABLE, + "pcachePrivDB: cacheDB not available" ); + return rs->sr_err; + } + /* FIXME: might be a little bit exaggerated... */ if ( !be_isroot( op ) ) { save_cb = op->o_callback; @@ -2253,6 +2294,13 @@ pcache_op_search( } #endif /* PCACHE_CONTROL_PRIVDB */ + /* The cache DB isn't open yet */ + if ( cm->defer_db_open ) { + send_ldap_error( op, rs, LDAP_UNAVAILABLE, + "pcachePrivDB: cacheDB not available" ); + return rs->sr_err; + } + tempstr.bv_val = op->o_tmpalloc( op->ors_filterstr.bv_len+1, op->o_tmpmemctx ); tempstr.bv_len = 0; if ( filter2template( op, op->ors_filter, &tempstr, &filter_attrs, @@ -2475,7 +2523,7 @@ consistency_check( op->o_dn = cm->db.be_rootdn; op->o_ndn = cm->db.be_rootndn; - cm->cc_arg = arg; + cm->cc_arg = arg; for (templ = qm->templates; templ; templ=templ->qmnext) { query = templ->query_last; @@ -2586,6 +2634,15 @@ static ConfigTable pccfg[] = { { NULL, NULL, 0, 0, 0, ARG_IGNORED } }; +/* Need to no-op this keyword for dynamic config */ +static ConfigTable pcdummy[] = { + { "", "", 0, 0, 0, ARG_IGNORED, + NULL, "( OLcfgGlAt:13 NAME 'olcDatabase' " + "DESC 'The backend type for a database instance' " + "SUP olcBackend SINGLE-VALUE X-ORDERED 'SIBLINGS' )", NULL, NULL }, + { NULL, NULL, 0, 0, 0, ARG_IGNORED } +}; + static ConfigOCs pcocs[] = { { "( OLcfgOvOc:2.1 " "NAME 'olcPcacheConfig' " @@ -2597,10 +2654,19 @@ static ConfigOCs pcocs[] = { { "( OLcfgOvOc:2.2 " "NAME 'olcPcacheDatabase' " "DESC 'Cache database configuration' " - "AUXILIARY )", Cft_Misc, pccfg, pc_ldadd }, + "AUXILIARY )", Cft_Misc, pcdummy, pc_ldadd }, { NULL, 0, NULL } }; +static int pcache_db_open2( slap_overinst *on, ConfigReply *cr ); + +static int +pc_ldadd_cleanup( ConfigArgs *c ) +{ + slap_overinst *on = c->ca_private; + return pcache_db_open2( on, &c->reply ); +} + static int pc_ldadd( CfEntryInfo *p, Entry *e, ConfigArgs *ca ) { @@ -2614,6 +2680,12 @@ pc_ldadd( CfEntryInfo *p, Entry *e, ConfigArgs *ca ) on = (slap_overinst *)p->ce_bi; cm = on->on_bi.bi_private; ca->be = &cm->db; + /* Defer open if this is an LDAPadd */ + if ( CONFIG_ONLINE_ADD( ca )) + ca->cleanup = pc_ldadd_cleanup; + else + cm->defer_db_open = 0; + ca->ca_private = on; return LDAP_SUCCESS; } @@ -2626,9 +2698,14 @@ pc_cfadd( Operation *op, SlapReply *rs, Entry *p, ConfigArgs *ca ) struct berval bv; /* FIXME: should not hardcode "olcDatabase" here */ - bv.bv_len = sprintf( ca->cr_msg, "olcDatabase=%s", cm->db.bd_info->bi_type ); + bv.bv_len = snprintf( ca->cr_msg, sizeof( ca->cr_msg ), + "olcDatabase=%s", cm->db.bd_info->bi_type ); + if ( bv.bv_len < 0 || bv.bv_len >= sizeof( ca->cr_msg ) ) { + return -1; + } bv.bv_val = ca->cr_msg; ca->be = &cm->db; + cm->defer_db_open = 0; /* We can only create this entry if the database is table-driven */ @@ -2798,6 +2875,7 @@ pc_cf_gen( ConfigArgs *c ) Debug( LDAP_DEBUG_CONFIG, "%s: %s.\n", c->log, c->cr_msg, 0 ); return( 1 ); } + cm->cc_period = (time_t)t; Debug( pcache_debug, "Total # of attribute sets to be cached = %d.\n", @@ -3065,8 +3143,10 @@ pcache_db_init( cm->max_queries = 10000; cm->save_queries = 0; cm->response_cb = PCACHE_RESPONSE_CB_TAIL; + cm->defer_db_open = 1; cm->cc_period = 1000; cm->cc_paused = 0; + cm->cc_arg = NULL; qm->attr_sets = NULL; qm->templates = NULL; @@ -3121,64 +3201,25 @@ pcache_cachedquery_count_cb( Operation *op, SlapReply *rs ) } static int -pcache_db_open( - BackendDB *be, +pcache_db_open2( + slap_overinst *on, ConfigReply *cr ) { - slap_overinst *on = (slap_overinst *)be->bd_info; cache_manager *cm = on->on_bi.bi_private; query_manager* qm = cm->qm; - int i, ncf = 0, rf = 0, nrf = 0, rc = 0; - - /* check attr sets */ - for ( i = 0; i < cm->numattrsets; i++) { - if ( !( qm->attr_sets[i].flags & PC_CONFIGURED ) ) { - if ( qm->attr_sets[i].flags & PC_REFERENCED ) { - Debug( LDAP_DEBUG_CONFIG, "pcache: attr set #%d not configured but referenced.\n", i, 0, 0 ); - rf++; - - } else { - Debug( LDAP_DEBUG_CONFIG, "pcache: warning, attr set #%d not configured.\n", i, 0, 0 ); - } - ncf++; - - } else if ( !( qm->attr_sets[i].flags & PC_REFERENCED ) ) { - Debug( LDAP_DEBUG_CONFIG, "pcache: attr set #%d configured but not referenced.\n", i, 0, 0 ); - nrf++; - } - } - - if ( ncf || rf || nrf ) { - Debug( LDAP_DEBUG_CONFIG, "pcache: warning, %d attr sets configured but not referenced.\n", nrf, 0, 0 ); - Debug( LDAP_DEBUG_CONFIG, "pcache: warning, %d attr sets not configured.\n", ncf, 0, 0 ); - Debug( LDAP_DEBUG_CONFIG, "pcache: %d attr sets not configured but referenced.\n", rf, 0, 0 ); - - if ( rf > 0 ) { - return 1; - } - } - - /* need to inherit something from the original database... */ - cm->db.be_def_limit = be->be_def_limit; - cm->db.be_limits = be->be_limits; - cm->db.be_acl = be->be_acl; - cm->db.be_dfltaccess = be->be_dfltaccess; - - if ( SLAP_DBMONITORING( be ) ) { - SLAP_DBFLAGS( &cm->db ) |= SLAP_DBFLAG_MONITORING; - - } else { - SLAP_DBFLAGS( &cm->db ) &= ~SLAP_DBFLAG_MONITORING; - } + int rc; rc = backend_startup_one( &cm->db, NULL ); + if ( rc == 0 ) { + cm->defer_db_open = 0; + } /* There is no runqueue in TOOL mode */ - if ( slapMode & SLAP_SERVER_MODE ) { + if (( slapMode & SLAP_SERVER_MODE ) && rc == 0 ) { ldap_pvt_thread_mutex_lock( &slapd_rq.rq_mutex ); ldap_pvt_runqueue_insert( &slapd_rq, cm->cc_period, consistency_check, on, - "pcache_consistency", be->be_suffix[0].bv_val ); + "pcache_consistency", cm->db.be_suffix[0].bv_val ); ldap_pvt_thread_mutex_unlock( &slapd_rq.rq_mutex ); /* Cached database must have the rootdn */ @@ -3276,6 +3317,62 @@ pcache_db_open( rc = 0; } } + return rc; +} + +static int +pcache_db_open( + BackendDB *be, + ConfigReply *cr ) +{ + slap_overinst *on = (slap_overinst *)be->bd_info; + cache_manager *cm = on->on_bi.bi_private; + query_manager* qm = cm->qm; + int i, ncf = 0, rf = 0, nrf = 0, rc = 0; + + /* check attr sets */ + for ( i = 0; i < cm->numattrsets; i++) { + if ( !( qm->attr_sets[i].flags & PC_CONFIGURED ) ) { + if ( qm->attr_sets[i].flags & PC_REFERENCED ) { + Debug( LDAP_DEBUG_CONFIG, "pcache: attr set #%d not configured but referenced.\n", i, 0, 0 ); + rf++; + + } else { + Debug( LDAP_DEBUG_CONFIG, "pcache: warning, attr set #%d not configured.\n", i, 0, 0 ); + } + ncf++; + + } else if ( !( qm->attr_sets[i].flags & PC_REFERENCED ) ) { + Debug( LDAP_DEBUG_CONFIG, "pcache: attr set #%d configured but not referenced.\n", i, 0, 0 ); + nrf++; + } + } + + if ( ncf || rf || nrf ) { + Debug( LDAP_DEBUG_CONFIG, "pcache: warning, %d attr sets configured but not referenced.\n", nrf, 0, 0 ); + Debug( LDAP_DEBUG_CONFIG, "pcache: warning, %d attr sets not configured.\n", ncf, 0, 0 ); + Debug( LDAP_DEBUG_CONFIG, "pcache: %d attr sets not configured but referenced.\n", rf, 0, 0 ); + + if ( rf > 0 ) { + return 1; + } + } + + /* need to inherit something from the original database... */ + cm->db.be_def_limit = be->be_def_limit; + cm->db.be_limits = be->be_limits; + cm->db.be_acl = be->be_acl; + cm->db.be_dfltaccess = be->be_dfltaccess; + + if ( SLAP_DBMONITORING( be ) ) { + SLAP_DBFLAGS( &cm->db ) |= SLAP_DBFLAG_MONITORING; + + } else { + SLAP_DBFLAGS( &cm->db ) &= ~SLAP_DBFLAG_MONITORING; + } + + if ( !cm->defer_db_open ) + rc = pcache_db_open2( on, cr ); return rc; } @@ -3354,6 +3451,7 @@ pcache_db_close( mod.sml_type = ad_cachedQueryURL->ad_cname; mod.sml_values = vals; mod.sml_nvalues = NULL; + mod.sml_numvals = 1; mod.sml_next = NULL; Debug( pcache_debug, "%sSETTING CACHED QUERY URLS\n", @@ -3875,6 +3973,11 @@ pcache_initialize() code = config_register_schema( pccfg, pcocs ); if ( code ) return code; + { + const char *text; + code = slap_str2ad( "olcDatabase", &pcdummy[0].ad, &text ); + if ( code ) return code; + } return overlay_register( &pcache ); }