📄 pcache.c
字号:
case LDAP_FILTER_OR: case LDAP_FILTER_AND: fs = fs->f_and; fi = fi->f_and; res=1; break; case LDAP_FILTER_SUBSTRINGS: /* check if the equality query can be * answered with cached substring query */ if ((fi->f_choice == LDAP_FILTER_EQUALITY) && substr_containment_equality( op, fs, fi)) res=1; /* check if the substring query can be * answered with cached substring query */ if ((fi->f_choice ==LDAP_FILTER_SUBSTRINGS ) && substr_containment_substr( op, fs, fi)) res= 1; fs=fs->f_next; fi=fi->f_next; break; case LDAP_FILTER_PRESENT: res=1; fs=fs->f_next; fi=fi->f_next; break; case LDAP_FILTER_EQUALITY: if (ret == 0) res = 1; fs=fs->f_next; fi=fi->f_next; break; case LDAP_FILTER_GE: if (ret >= 0) res = 1; fs=fs->f_next; fi=fi->f_next; break; case LDAP_FILTER_LE: if (ret <= 0) res = 1; fs=fs->f_next; fi=fi->f_next; break; case LDAP_FILTER_NOT: res=0; break; default: break; } } while((res) && (fi != NULL) && (fs != NULL)); if(res) { ldap_pvt_thread_mutex_lock(&qm->lru_mutex); if (qm->lru_top != qc) { remove_query(qm, qc); add_query_on_top(qm, qc); } ldap_pvt_thread_mutex_unlock(&qm->lru_mutex); return qc; } } } Debug( pcache_debug, "Not answerable: Unlock QC index=%d\n", template_index, 0, 0 ); ldap_pvt_thread_rdwr_runlock(&(templa[template_index].t_rwlock)); } return NULL;}static voidfree_query (CachedQuery* qc){ Query* q = (Query*)qc; int i; free(qc->q_uuid.bv_val); filter_free(q->filter); free (q->base.bv_val); free(q->attrs); free(qc);}/* Add query to query cache */static void add_query( query_manager* qm, Query* query, int template_index, struct berval* uuid){ CachedQuery* new_cached_query = (CachedQuery*) ch_malloc(sizeof(CachedQuery)); QueryTemplate* templ = (qm->templates)+template_index; Query* new_query; new_cached_query->template_id = template_index; if ( uuid ) { new_cached_query->q_uuid = *uuid; new_cached_query->expiry_time = slap_get_time() + templ->ttl; } else { BER_BVZERO( &new_cached_query->q_uuid ); new_cached_query->expiry_time = slap_get_time() + templ->negttl; } new_cached_query->lru_up = NULL; new_cached_query->lru_down = NULL; Debug( pcache_debug, "Added query expires at %ld\n", (long) new_cached_query->expiry_time, 0, 0 ); new_query = (Query*)new_cached_query; ber_dupbv(&new_query->base, &query->base); new_query->scope = query->scope; new_query->filter = query->filter; new_query->attrs = query->attrs; /* Adding a query */ Debug( pcache_debug, "Lock AQ index = %d\n", template_index, 0, 0 ); ldap_pvt_thread_rdwr_wlock(&templ->t_rwlock); if (templ->query == NULL) templ->query_last = new_cached_query; else templ->query->prev = new_cached_query; new_cached_query->next = templ->query; new_cached_query->prev = NULL; templ->query = new_cached_query; templ->no_of_queries++; Debug( pcache_debug, "TEMPLATE %d QUERIES++ %d\n", template_index, templ->no_of_queries, 0 ); Debug( pcache_debug, "Unlock AQ index = %d \n", template_index, 0, 0 ); ldap_pvt_thread_rdwr_wunlock(&templ->t_rwlock); /* Adding on top of LRU list */ ldap_pvt_thread_mutex_lock(&qm->lru_mutex); add_query_on_top(qm, new_cached_query); ldap_pvt_thread_mutex_unlock(&qm->lru_mutex);}static voidremove_from_template (CachedQuery* qc, QueryTemplate* template){ if (!qc->prev && !qc->next) { template->query_last = template->query = NULL; } else if (qc->prev == NULL) { qc->next->prev = NULL; template->query = qc->next; } else if (qc->next == NULL) { qc->prev->next = NULL; template->query_last = qc->prev; } else { qc->next->prev = qc->prev; qc->prev->next = qc->next; } template->no_of_queries--;}/* remove bottom query of LRU list from the query cache */static void cache_replacement(query_manager* qm, struct berval *result){ CachedQuery* bottom; int temp_id; ldap_pvt_thread_mutex_lock(&qm->lru_mutex); bottom = qm->lru_bottom; result->bv_val = NULL; result->bv_len = 0; if (!bottom) { Debug ( pcache_debug, "Cache replacement invoked without " "any query in LRU list\n", 0, 0, 0 ); ldap_pvt_thread_mutex_unlock(&qm->lru_mutex); return; } temp_id = bottom->template_id; remove_query(qm, bottom); ldap_pvt_thread_mutex_unlock(&qm->lru_mutex); *result = bottom->q_uuid; bottom->q_uuid.bv_val = NULL; Debug( pcache_debug, "Lock CR index = %d\n", temp_id, 0, 0 ); ldap_pvt_thread_rdwr_wlock(&(qm->templates[temp_id].t_rwlock)); remove_from_template(bottom, (qm->templates+temp_id)); Debug( pcache_debug, "TEMPLATE %d QUERIES-- %d\n", temp_id, qm->templates[temp_id].no_of_queries, 0 ); Debug( pcache_debug, "Unlock CR index = %d\n", temp_id, 0, 0 ); ldap_pvt_thread_rdwr_wunlock(&(qm->templates[temp_id].t_rwlock)); free_query(bottom);}struct query_info { struct query_info *next; struct berval xdn; int del;};static intremove_func ( Operation *op, SlapReply *rs){ Attribute *attr; struct query_info *qi; int count = 0; if ( rs->sr_type != REP_SEARCH ) return 0; for (attr = rs->sr_entry->e_attrs; attr!= NULL; attr = attr->a_next) { if (attr->a_desc == ad_queryid) { for (count=0; attr->a_vals[count].bv_val; count++) ; break; } } if ( count == 0 ) return 0; qi = op->o_tmpalloc( sizeof( struct query_info ), op->o_tmpmemctx ); qi->next = op->o_callback->sc_private; op->o_callback->sc_private = qi; ber_dupbv_x( &qi->xdn, &rs->sr_entry->e_nname, op->o_tmpmemctx ); qi->del = ( count == 1 ); return 0;}static intremove_query_data ( Operation *op, SlapReply *rs, struct berval* query_uuid){ struct query_info *qi, *qnext; char filter_str[64];#ifdef LDAP_COMP_MATCH AttributeAssertion ava = { NULL, BER_BVNULL, NULL };#else AttributeAssertion ava = { NULL, BER_BVNULL };#endif Filter filter = {LDAP_FILTER_EQUALITY}; SlapReply sreply = {REP_RESULT}; slap_callback cb = { NULL, remove_func, NULL, NULL }; int deleted = 0; sreply.sr_entry = NULL; sreply.sr_nentries = 0; op->ors_filterstr.bv_len = snprintf(filter_str, sizeof(filter_str), "(%s=%s)", ad_queryid->ad_cname.bv_val, query_uuid->bv_val); filter.f_ava = &ava; filter.f_av_desc = ad_queryid; filter.f_av_value = *query_uuid; op->o_tag = LDAP_REQ_SEARCH; op->o_protocol = LDAP_VERSION3; op->o_callback = &cb; op->o_time = slap_get_time(); op->o_do_not_cache = 1; op->o_req_dn = op->o_bd->be_suffix[0]; op->o_req_ndn = op->o_bd->be_nsuffix[0]; op->ors_scope = LDAP_SCOPE_SUBTREE; op->ors_deref = LDAP_DEREF_NEVER; op->ors_slimit = SLAP_NO_LIMIT; op->ors_tlimit = SLAP_NO_LIMIT; op->ors_filter = &filter; op->ors_filterstr.bv_val = filter_str; op->ors_filterstr.bv_len = strlen(filter_str); op->ors_attrs = NULL; op->ors_attrsonly = 0; op->o_bd->be_search( op, &sreply ); for ( qi=cb.sc_private; qi; qi=qnext ) { qnext = qi->next; op->o_req_dn = qi->xdn; op->o_req_ndn = qi->xdn; if ( qi->del) { Debug( pcache_debug, "DELETING ENTRY TEMPLATE=%s\n", query_uuid->bv_val, 0, 0 ); op->o_tag = LDAP_REQ_DELETE; if (op->o_bd->be_delete(op, &sreply) == LDAP_SUCCESS) { deleted++; } } else { Modifications mod; struct berval vals[2]; vals[0] = *query_uuid; vals[1].bv_val = NULL; vals[1].bv_len = 0; mod.sml_op = LDAP_MOD_DELETE; mod.sml_flags = 0; mod.sml_desc = ad_queryid; mod.sml_type = ad_queryid->ad_cname; mod.sml_values = vals; mod.sml_nvalues = NULL; mod.sml_next = NULL; Debug( pcache_debug, "REMOVING TEMP ATTR : TEMPLATE=%s\n", query_uuid->bv_val, 0, 0 ); op->orm_modlist = &mod; op->o_bd->be_modify( op, &sreply ); } op->o_tmpfree( qi->xdn.bv_val, op->o_tmpmemctx ); op->o_tmpfree( qi, op->o_tmpmemctx ); } return deleted;}static intget_attr_set( AttributeName* attrs, query_manager* qm, int num);static intfilter2template( Operation *op, Filter *f, struct berval *fstr, AttributeName** filter_attrs, int* filter_cnt, int* filter_got_oc ){ AttributeDescription *ad; 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 ); 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 ); 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 ); 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 ); 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 ); 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 ); 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; 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; return rc; } default: strcpy( fstr->bv_val, "(?=?)" ); fstr->bv_len += sizeof("(?=?)")-1; return -1; } *filter_attrs = (AttributeName *)op->o_tmprealloc(*filter_attrs, (*filter_cnt + 2)*sizeof(AttributeName), op->o_tmpmemctx); (*filter_attrs)[*filter_cnt].an_desc = ad; (*filter_attrs)[*filter_cnt].an_name = ad->ad_cname; (*filter_attrs)[*filter_cnt].an_oc = NULL; (*filter_attrs)[*filter_cnt].an_oc_exclude = 0; BER_BVZERO( &(*filter_attrs)[*filter_cnt+1].an_name ); (*filter_cnt)++; if ( ad == slap_schema.si_ad_objectClass ) *filter_got_oc = 1; return 0;}struct search_info { slap_overinst *on; Query query; int template_id; int max; int over; int count; Entry *head, *tail;};static intcache_entries( Operation *op, SlapReply *rs, struct berval *query_uuid){ struct search_info *si = op->o_callback->sc_private; slap_overinst *on = si->on; cache_manager *cm = on->on_bi.bi_private; query_manager* qm = cm->qm; int return_val = 0; Entry *e; struct berval crp_uuid; char uuidbuf[ LDAP_LUTIL_UUIDSTR_BUFSIZE ]; Operation op_tmp = *op; 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; Debug( pcache_debug, "UUID for query being added = %s\n", uuidbuf, 0, 0 ); for ( e=si->head; e; e=si->head ) { si->head = e->e_private; e->e_private = NULL; while ( cm->cur_entries > (cm->max_entries) ) { qm->crfunc(qm, &crp_uuid); if (crp_uuid.bv_val) { Debug( pcache_debug, "Removing query UUID %s\n", crp_uuid.bv_val, 0, 0 ); return_val = remove_query_data(&op_tmp, rs, &crp_uuid); Debug( pcache_debug, "QUERY REMOVED, SIZE=%d\n", return_val, 0, 0); ldap_pvt_thread_mutex_lock( &cm->cache_mutex ); cm->cur_entries -= return_val; cm->num_cached_queries--; Debug( pcache_debug, "STORED QUERIES = %lu\n", cm->num_cached_queries, 0, 0 ); ldap_pvt_thread_mutex_unlock( &cm->cache_mutex ); Debug( pcache_debug, "QUERY REMOVED, CACHE =" "%d entries\n", cm->cur_entries, 0, 0 ); } } 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, "ENTRY ADDED/MERGED, CACHED ENTRIES=%d\n", cm->cur_entries, 0, 0 ); return_val = 0; ldap_pvt_thread_mutex_unlock(&cm->cache_mutex); } return return_val;}static intpcache_response( Operation *op, SlapReply *rs ){ struct search_info *si = op->o_callback->sc_private; slap_overinst *on = si->on; cache_manager *cm = on->on_bi.bi_private; query_manager* qm = cm->qm; struct berval uuid; if ( si->query.save_attrs != NULL ) { rs->sr_attrs = si->query.save_attrs; op->ors_attrs = si->query.save_attrs; si->query.save_attrs = NULL; } if ( rs->sr_type == REP_SEARCH ) { Entry *e; /* If we haven't exceeded the limit for this query, * build a chain of answers to store. If we hit the * limit, empty the chain and ignore the rest. */ if ( !si->over ) { if ( si->count < si->max ) { si->count++; e = entry_dup( rs->sr_entry ); if ( !si->head ) si->head = e; if ( si->tail ) si->tail->e_private = e; si->tail = e; } else { si->over = 1; si->count = 0; for (;si->head; si->head=e) { e = si->head->e_private; si->head->e_private = NULL; entry_free(si->head); } si->tail = NULL; } }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -