⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pcache.c

📁 ldap服务器源码
💻 C
📖 第 1 页 / 共 4 页
字号:
	} else if ( rs->sr_type == REP_RESULT ) {		QueryTemplate* templ = (qm->templates)+si->template_id;		if (( si->count && cache_entries( op, rs, &uuid ) == 0 ) ||			( templ->negttl && !si->count && !si->over &&				rs->sr_err == LDAP_SUCCESS )) {			qm->addfunc(qm, &si->query, si->template_id,				si->count ? &uuid : NULL);			ldap_pvt_thread_mutex_lock(&cm->cache_mutex);			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);			/* If the consistency checker suspended itself,			 * wake it back up			 */			if ( cm->cc_paused ) {				ldap_pvt_thread_mutex_lock( &slapd_rq.rq_mutex );				if ( cm->cc_paused ) {					cm->cc_paused = 0;					ldap_pvt_runqueue_resched( &slapd_rq, cm->cc_arg, 0 );				}				ldap_pvt_thread_mutex_unlock( &slapd_rq.rq_mutex );			}		} else {			free( si->query.attrs );			filter_free( si->query.filter );		}		/* free self */		op->o_callback->sc_cleanup = slap_freeself_cb;	}	return SLAP_CB_CONTINUE;}static voidadd_filter_attrs(	Operation *op,	AttributeName** new_attrs,	struct attr_set *attrs,	AttributeName* filter_attrs,	int fattr_cnt,	int fattr_got_oc){	int alluser = 0;	int allop = 0;	int i, j;	int count;	int addoc = 0;	/* duplicate attrs */	count = attrs->count + fattr_cnt;	if ( !fattr_got_oc && !(attrs->flags & PC_GOT_OC)) {		addoc = 1;		count++;	}	*new_attrs = (AttributeName*)ch_malloc((count+1)*		sizeof(AttributeName));	for (i=0; i<attrs->count; i++) {		(*new_attrs)[i].an_name = attrs->attrs[i].an_name;		(*new_attrs)[i].an_desc = attrs->attrs[i].an_desc;	}	BER_BVZERO( &(*new_attrs)[i].an_name );	alluser = an_find(*new_attrs, &AllUser);	allop = an_find(*new_attrs, &AllOper);	j = i;	for ( i=0; i<fattr_cnt; i++ ) {		if ( an_find(*new_attrs, &filter_attrs[i].an_name ))			continue;		if ( is_at_operational(filter_attrs[i].an_desc->ad_type) ) {			if (allop)				continue;		} else if (alluser)			continue;		(*new_attrs)[j].an_name = filter_attrs[i].an_name;		(*new_attrs)[j].an_desc = filter_attrs[i].an_desc;		(*new_attrs)[j].an_oc = NULL;		(*new_attrs)[j].an_oc_exclude = 0;		j++;	}	if ( addoc ) {		(*new_attrs)[j].an_name = slap_schema.si_ad_objectClass->ad_cname;		(*new_attrs)[j].an_desc = slap_schema.si_ad_objectClass;		(*new_attrs)[j].an_oc = NULL;		(*new_attrs)[j].an_oc_exclude = 0;		j++;	}	BER_BVZERO( &(*new_attrs)[j].an_name );}/* NOTE: this is a quick workaround to let pcache minimally interact * with pagedResults.  A more articulated solutions would be to * perform the remote query without control and cache all results, * performing the pagedResults search only within the client * and the proxy.  This requires pcache to understand pagedResults. */static intpcache_chk_controls(	Operation	*op,	SlapReply	*rs ){	const char	*non = "";	const char	*stripped = "";	switch( op->o_pagedresults ) {	case SLAP_CONTROL_NONCRITICAL:		non = "non-";		stripped = "; stripped";		/* fallthru */	case SLAP_CONTROL_CRITICAL:		Debug( pcache_debug, "%s: "			"%scritical pagedResults control "			"disabled with proxy cache%s.\n",			op->o_log_prefix, non, stripped );				slap_remove_control( op, rs, slap_cids.sc_pagedResults, NULL );		break;	default:		rs->sr_err = SLAP_CB_CONTINUE;		break;	}	return rs->sr_err;}static intpcache_op_search(	Operation	*op,	SlapReply	*rs ){	slap_overinst *on = (slap_overinst *)op->o_bd->bd_info;	cache_manager *cm = on->on_bi.bi_private;	query_manager*		qm = cm->qm;	int count;	int i = -1;	AttributeName	*filter_attrs = NULL;	Query		query;	int 		attr_set = -1;	int 		template_id = -1;	CachedQuery 	*answerable = NULL;	int 		cacheable = 0;	int		fattr_cnt=0;	int		fattr_got_oc = 0;	int		oc_attr_absent = 1;	struct berval tempstr;	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,		&fattr_cnt, &fattr_got_oc )) {		op->o_tmpfree( tempstr.bv_val, op->o_tmpmemctx );		return SLAP_CB_CONTINUE;	}	Debug( pcache_debug, "query template of incoming query = %s\n",					tempstr.bv_val, 0, 0 );	/* FIXME: cannot cache/answer requests with pagedResults control */		/* find attr set */	attr_set = get_attr_set(op->ors_attrs, qm, cm->numattrsets);	query.filter = op->ors_filter;	query.attrs = op->ors_attrs;	query.save_attrs = NULL;	query.base = op->o_req_ndn;	query.scope = op->ors_scope;	/* check for query containment */	if (attr_set > -1) {		QueryTemplate *qt = qm->templates;		for (i=0; i<cm->numtemplates; i++, qt++) {			/* find if template i can potentially answer tempstr */			if ( qt->attr_set_index != attr_set ||				qt->querystr.bv_len != tempstr.bv_len ||				strcasecmp( qt->querystr.bv_val, tempstr.bv_val ))				continue;			cacheable = 1;			template_id = i;			Debug( LDAP_DEBUG_NONE, "Entering QC, querystr = %s\n",			 		op->ors_filterstr.bv_val, 0, 0 );			answerable = (*(qm->qcfunc))(op, qm, &query, i);			if (answerable)				break;		}	}	op->o_tmpfree( tempstr.bv_val, op->o_tmpmemctx );	query.save_attrs = op->ors_attrs;	query.attrs = NULL;	if (answerable) {		/* Need to clear the callbacks of the original operation,		 * in case there are other overlays */		BackendDB	*save_bd = op->o_bd;		slap_callback	*save_cb = op->o_callback;		Debug( pcache_debug, "QUERY ANSWERABLE\n", 0, 0, 0 );		op->o_tmpfree( filter_attrs, op->o_tmpmemctx );		ldap_pvt_thread_rdwr_runlock(&qm->templates[i].t_rwlock);		if ( BER_BVISNULL( &answerable->q_uuid )) {			/* No entries cached, just an empty result set */			i = rs->sr_err = 0;			send_ldap_result( op, rs );		} else {			op->o_bd = &cm->db;			op->o_callback = NULL;			i = cm->db.bd_info->bi_op_search( op, rs );		}		op->o_bd = save_bd;		op->o_callback = save_cb;		return i;	}	Debug( pcache_debug, "QUERY NOT ANSWERABLE\n", 0, 0, 0 );	ldap_pvt_thread_mutex_lock(&cm->cache_mutex);	if (cm->num_cached_queries >= cm->max_queries) {		cacheable = 0;	}	ldap_pvt_thread_mutex_unlock(&cm->cache_mutex);	if (op->ors_attrsonly)		cacheable = 0;	if (cacheable) {		slap_callback		*cb;		struct search_info	*si;		Debug( pcache_debug, "QUERY CACHEABLE\n", 0, 0, 0 );		query.filter = filter_dup(op->ors_filter, NULL);		add_filter_attrs(op, &query.attrs, &qm->attr_sets[attr_set],			filter_attrs, fattr_cnt, fattr_got_oc);		op->ors_attrs = query.attrs;		cb = op->o_tmpalloc( sizeof(*cb) + sizeof(*si), op->o_tmpmemctx);		cb->sc_response = pcache_response;		cb->sc_cleanup = NULL;		cb->sc_private = (cb+1);		si = cb->sc_private;		si->on = on;		si->query = query;		si->template_id = template_id;		si->max = cm->num_entries_limit ;		si->over = 0;		si->count = 0;		si->head = NULL;		si->tail = NULL;		if ( cm->response_cb == PCACHE_RESPONSE_CB_HEAD ) {			cb->sc_next = op->o_callback;			op->o_callback = cb;		} else {			slap_callback		**pcb;			/* need to move the callback at the end, in case other			 * overlays are present, so that the final entry is			 * actually cached */			cb->sc_next = NULL;			for ( pcb = &op->o_callback; *pcb; pcb = &(*pcb)->sc_next );			*pcb = cb;		}	} else {		Debug( pcache_debug, "QUERY NOT CACHEABLE\n",					0, 0, 0);	}	op->o_tmpfree( filter_attrs, op->o_tmpmemctx );	return SLAP_CB_CONTINUE;}static intget_attr_set(	AttributeName* attrs,	query_manager* qm,	int num ){	int i;	int count = 0;	if ( attrs ) {		for ( ; attrs[count].an_name.bv_val; count++ );	}	for (i=0; i<num; i++) {		AttributeName *a2;		int found = 1;		if ( count > qm->attr_sets[i].count )			continue;		if ( !count ) {			if ( !qm->attr_sets[i].count )				break;			continue;		}		for ( a2 = attrs; a2->an_name.bv_val; a2++ ) {			if ( !an_find( qm->attr_sets[i].attrs, &a2->an_name )) {				found = 0;				break;			}		}		if ( found )			break;	}	if ( i == num )		i = -1;	return i;}static void*consistency_check(	void *ctx,	void *arg ){	struct re_s *rtask = arg;	slap_overinst *on = rtask->arg;	cache_manager *cm = on->on_bi.bi_private;	query_manager *qm = cm->qm;	Connection conn = {0};	OperationBuffer opbuf;	Operation *op;	SlapReply rs = {REP_RESULT};	CachedQuery* query, *query_prev;	int i, return_val, pause = 1;	QueryTemplate* templ;	op = (Operation *) &opbuf;	connection_fake_init( &conn, op, ctx );	op->o_bd = &cm->db;	op->o_dn = cm->db.be_rootdn;	op->o_ndn = cm->db.be_rootndn;      	cm->cc_arg = arg;	for (i=0; qm->templates[i].querystr.bv_val; i++) {		templ = qm->templates + i;		query = templ->query_last;		if ( query ) pause = 0;		op->o_time = slap_get_time();		while (query && (query->expiry_time < op->o_time)) {			Debug( pcache_debug, "Lock CR index = %d\n",					i, 0, 0 );			ldap_pvt_thread_rdwr_wlock(&templ->t_rwlock);			remove_from_template(query, templ);			Debug( pcache_debug, "TEMPLATE %d QUERIES-- %d\n",					i, templ->no_of_queries, 0 );			Debug( pcache_debug, "Unlock CR index = %d\n",					i, 0, 0 );			ldap_pvt_thread_rdwr_wunlock(&templ->t_rwlock);			ldap_pvt_thread_mutex_lock(&qm->lru_mutex);			remove_query(qm, query);			ldap_pvt_thread_mutex_unlock(&qm->lru_mutex);			if ( BER_BVISNULL( &query->q_uuid ))				return_val = 0;			else				return_val = remove_query_data(op, &rs, &query->q_uuid);			Debug( pcache_debug, "STALE 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,				"STALE QUERY REMOVED, CACHE ="				"%d entries\n",				cm->cur_entries, 0, 0 );			query_prev = query;			query = query->prev;			free_query(query_prev);		}	}	ldap_pvt_thread_mutex_lock( &slapd_rq.rq_mutex );	if ( ldap_pvt_runqueue_isrunning( &slapd_rq, rtask )) {		ldap_pvt_runqueue_stoptask( &slapd_rq, rtask );	}	/* If there were no queries, defer processing for a while */	cm->cc_paused = pause;	ldap_pvt_runqueue_resched( &slapd_rq, rtask, pause );	ldap_pvt_thread_mutex_unlock( &slapd_rq.rq_mutex );	return NULL;}#define MAX_ATTR_SETS 500enum {	PC_MAIN = 1,	PC_ATTR,	PC_TEMP,	PC_RESP,	PC_QUERIES};static ConfigDriver pc_cf_gen;static ConfigLDAPadd pc_ldadd;static ConfigCfAdd pc_cfadd;static ConfigTable pccfg[] = {	{ "proxycache", "backend> <max_entries> <numattrsets> <entry limit> "				"<cycle_time",		6, 6, 0, ARG_MAGIC|ARG_NO_DELETE|PC_MAIN, pc_cf_gen,		"( OLcfgOvAt:2.1 NAME 'olcProxyCache' "			"DESC 'ProxyCache basic parameters' "			"SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL },	{ "proxyattrset", "index> <attributes...",		2, 0, 0, ARG_MAGIC|PC_ATTR, pc_cf_gen,		"( OLcfgOvAt:2.2 NAME 'olcProxyAttrset' "			"DESC 'A set of attributes to cache' "			"SYNTAX OMsDirectoryString )", NULL, NULL },	{ "proxytemplate", "filter> <attrset-index> <TTL> <negTTL",		4, 5, 0, ARG_MAGIC|PC_TEMP, pc_cf_gen,		"( OLcfgOvAt:2.3 NAME 'olcProxyTemplate' "			"DESC 'Filter template, attrset, cache TTL, optional negative TTL' "			"SYNTAX OMsDirectoryString )", NULL, NULL },	{ "response-callback", "head|tail(default)",		2, 2, 0, ARG_MAGIC|PC_RESP, pc_cf_gen,		"( OLcfgOvAt:2.4 NAME 'olcProxyResponseCB' "			"DESC 'Response callback position in overlay stack' "			"SYNTAX OMsDirectoryString )", NULL, NULL },	{ "proxyCacheQueries", "queries",		2, 2, 0, ARG_INT|ARG_MAGIC|PC_QUERIES, pc_cf_gen,		"( OLcfgOvAt:2.5 NAME 'olcProxyCacheQueries' "			"DESC 'Maximum number of queries to cache' "			"SYNTAX OMsInteger )", NULL, NULL },	{ NULL, NULL, 0, 0, 0, ARG_IGNORED }};static ConfigOCs pcocs[] = {	{ "( OLcfgOvOc:2.1 "		"NAME 'olcPcacheConfig' "		"DESC 'ProxyCache configuration' "		"SUP olcOverlayConfig "		"MUST ( olcProxyCache $ olcProxyAttrset $ olcProxyTemplate ) "		"MAY ( olcProxyResponseCB $ olcProxyCacheQueries ) )", Cft_Overlay, pccfg, NULL, pc_cfadd },	{ "( OLcfgOvOc:2.2 "		"NAME 'olcPcacheDatabase' "		"DESC 'Cache database configuration' "		"AUXILIARY )", Cft_Misc, pccfg, pc_ldadd },	{ NULL, 0, NULL }};static intpc_ldadd( CfEntryInfo *p, Entry *e, ConfigArgs *ca ){	slap_overinst *on;	cache_manager *cm;	if ( p->ce_type != Cft_Overlay || !p->ce_bi ||		p->ce_bi->bi_cf_ocs != pcocs )		return LDAP_CONSTRAINT_VIOLATION;	on = (slap_overinst *)p->ce_bi;	cm = on->on_bi.bi_private;	ca->be = &cm->db;	return LDAP_SUCCESS;}static intpc_cfadd( Operation *op, SlapReply *rs, Entry *p, ConfigArgs *ca ){	CfEntryInfo *pe = p->e_private;	slap_overinst *on = (slap_overinst *)pe->ce_bi;	cache_manager *cm = on->on_bi.bi_private;	struct berval bv;	/* FIXME: should not hardcode "olcDatabase" here */	bv.bv_len = sprintf( ca->msg, "olcDatabase=%s", cm->db.bd_info->bi_type );	bv.bv_val = ca->msg;	ca->be = &cm->db;	/* We can only create this entry if the database is table-driven	 */	if ( cm->db.bd_info->bi_cf_ocs )		config_build_entry( op, rs, pe, ca, &bv, cm->db.bd_info->bi_cf_ocs,			&pcocs[1] );	return 0;}static intpc_cf_gen( ConfigArgs *c ){	slap_overinst	*on = (slap_overinst *)c->bi;	cache_manager* 	cm = on->on_bi.bi_private;	query_manager*  qm = cm->qm;	QueryTemplate* 	temp;	AttributeName*  attr_name;	AttributeName* 	attrarray;	const char* 	text=NULL;	int		i, num, rc = 0;	char		*ptr;	unsigned long	t;	if ( c->op == SLAP_CONFIG_EMIT ) {		struct berval bv;		switch( c->type ) {		case PC_MAIN:			bv.bv_len = snprintf( c->msg, sizeof( c->msg ), "%s %d %d %d %ld",				cm->db.bd_info->bi_type, cm->max_entries, cm->numattrsets,				cm->num_entries_limit, cm->cc_period );			bv.bv_val = c->msg;			value_add_one( &c->rvalue_vals, &bv );			break;		case PC_ATTR:			for (i=0; i<cm->numattrsets; i++) {				if ( !qm->attr_sets[i].count ) continue;				bv.bv_len = snprintf( c->msg, sizeof( c->msg ), "%d", i );				/* count the attr length */				for ( attr_name = qm->attr_sets[i].attrs;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -