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

📄 pcache.c

📁 ldap服务器源码
💻 C
📖 第 1 页 / 共 4 页
字号:
/* $OpenLDAP: pkg/ldap/servers/slapd/overlays/pcache.c,v 1.41.2.17 2007/01/02 21:44:08 kurt Exp $ *//* This work is part of OpenLDAP Software <http://www.openldap.org/>. * * Copyright 2003-2007 The OpenLDAP Foundation. * Portions Copyright 2003 IBM Corporation. * Portions Copyright 2003 Symas Corporation. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted only as authorized by the OpenLDAP * Public License. * * A copy of this license is available in the file LICENSE in the * top-level directory of the distribution or, alternatively, at * <http://www.OpenLDAP.org/license.html>. *//* ACKNOWLEDGEMENTS: * This work was initially developed by Apurva Kumar for inclusion * in OpenLDAP Software and subsequently rewritten by Howard Chu. */#include "portable.h"#ifdef SLAPD_OVER_PROXYCACHE#include <stdio.h>#include <ac/string.h>#include <ac/time.h>#include "slap.h"#include "lutil.h"#include "ldap_rq.h"#include "config.h"/* query cache structs *//* query */typedef struct Query_s {	Filter* 	filter; 	/* Search Filter */	AttributeName* 	attrs;		/* Projected attributes */	AttributeName*  save_attrs;	/* original attributes, saved for response */	struct berval 	base; 		/* Search Base */	int 		scope;		/* Search scope */} Query;/* struct representing a cached query */typedef struct cached_query_s {	Query 				query;		/* LDAP query */	struct berval			q_uuid;		/* query identifier */	int 				template_id;	/* template of the query */	time_t 				expiry_time;	/* time till the query is considered valid */	struct cached_query_s  		*next;  	/* next query in the template */	struct cached_query_s  		*prev;  	/* previous query in the template */	struct cached_query_s           *lru_up;	/* previous query in the LRU list */	struct cached_query_s           *lru_down;	/* next query in the LRU list */} CachedQuery;/* struct representing a query template * e.g. template string = &(cn=)(mail=) */typedef struct query_template_s {	struct berval	querystr;	/* Filter string corresponding to the QT */	int 		attr_set_index; /* determines the projected attributes */	CachedQuery* 	query;	        /* most recent query cached for the template */	CachedQuery* 	query_last;     /* oldest query cached for the template */	int 		no_of_queries;  /* Total number of queries in the template */	time_t		ttl;		/* TTL for the queries of this template */	time_t		negttl;		/* TTL for negative results */        ldap_pvt_thread_rdwr_t t_rwlock; /* Rd/wr lock for accessing queries in the template */} QueryTemplate;/* * Represents a set of projected attributes. */struct attr_set {	unsigned	flags;#define	PC_CONFIGURED	(0x1)#define	PC_REFERENCED	(0x2)#define	PC_GOT_OC		(0x4)	AttributeName*	attrs; 		/* specifies the set */	int 		count;		/* number of attributes */};struct query_manager_s;/* prototypes for functions for 1) query containment * 2) query addition, 3) cache replacement */typedef CachedQuery * 	(QCfunc)(Operation *op, struct query_manager_s*, Query*, int );typedef void  	(AddQueryfunc)(struct query_manager_s*, Query*, int, struct berval*);typedef void	(CRfunc)(struct query_manager_s*, struct berval * );/* LDAP query cache */typedef struct query_manager_s {	struct attr_set* 	attr_sets;		/* possible sets of projected attributes */	QueryTemplate*	  	templates;		/* cacheable templates */	CachedQuery*		lru_top;		/* top and bottom of LRU list */	CachedQuery*		lru_bottom;	ldap_pvt_thread_mutex_t		lru_mutex;	/* mutex for accessing LRU list */	/* Query cache methods */	QCfunc			*qcfunc;			/* Query containment*/	CRfunc 			*crfunc;			/* cache replacement */	AddQueryfunc	*addfunc;			/* add query */} query_manager;/* LDAP query cache manager */typedef struct cache_manager_s {	BackendDB	db;	/* underlying database */	unsigned long	num_cached_queries; 		/* total number of cached queries */	unsigned long   max_queries;			/* upper bound on # of cached queries */	int 	numattrsets;			/* number of attribute sets */	int 	numtemplates;			/* number of cacheable templates */	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 */	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	time_t	cc_period;		/* interval between successive consistency checks (sec) */	int	cc_paused;	void	*cc_arg;	ldap_pvt_thread_mutex_t		cache_mutex;	query_manager*   qm;	/* query cache managed by the cache manager */} cache_manager;static int pcache_debug;static AttributeDescription *ad_queryid;static char *queryid_schema = "( 1.3.6.1.4.1.4203.666.1.12 NAME 'queryid' "			"DESC 'list of queries the entry belongs to' "			"EQUALITY octetStringMatch "			"SYNTAX 1.3.6.1.4.1.1466.115.121.1.40{64} "			"NO-USER-MODIFICATION USAGE directoryOperation )";/* Return 1 for an added entry, else 0 */static intmerge_entry(	Operation		*op,	Entry			*e,	struct berval*		query_uuid ){	int		rc;	Modifications* modlist = NULL;	const char* 	text = NULL;	Attribute		*attr;	char			textbuf[SLAP_TEXT_BUFLEN];	size_t			textlen = sizeof(textbuf);	SlapReply sreply = {REP_RESULT};	slap_callback cb = { NULL, slap_null_cb, NULL, NULL };	attr = e->e_attrs;	e->e_attrs = NULL;	/* add queryid attribute */	attr_merge_one( e, ad_queryid, query_uuid, NULL );	/* append the attribute list from the fetched entry */	e->e_attrs->a_next = attr;	op->o_tag = LDAP_REQ_ADD;	op->o_protocol = LDAP_VERSION3;	op->o_callback = &cb;	op->o_time = slap_get_time();	op->o_do_not_cache = 1;	op->ora_e = e;	op->o_req_dn = e->e_name;	op->o_req_ndn = e->e_nname;	rc = op->o_bd->be_add( op, &sreply );	if ( rc != LDAP_SUCCESS ) {		if ( rc == LDAP_ALREADY_EXISTS ) {			slap_entry2mods( e, &modlist, &text, textbuf, textlen );			modlist->sml_op = LDAP_MOD_ADD;			op->o_tag = LDAP_REQ_MODIFY;			op->orm_modlist = modlist;			op->o_bd->be_modify( op, &sreply );			slap_mods_free( modlist, 1 );		} else if ( rc == LDAP_REFERRAL ||					rc == LDAP_NO_SUCH_OBJECT ) {			syncrepl_add_glue( op, e );			e = NULL;			rc = 1;		}		if ( e ) {			entry_free( e );			rc = 0;		}	} else {		be_entry_release_w( op, e );		rc = 1;	}	return rc;}/* compare base and scope of incoming and cached queries */static int base_scope_compare(	struct berval* ndn_stored,	struct berval* ndn_incoming,	int scope_stored,	int scope_incoming	){	struct berval pdn_incoming = BER_BVNULL;	if (scope_stored < scope_incoming)		return 0;	if ( !dnIsSuffix(ndn_incoming, ndn_stored))		return 0;	switch(scope_stored) {	case LDAP_SCOPE_BASE:		return (ndn_incoming->bv_len == ndn_stored->bv_len);	case LDAP_SCOPE_ONELEVEL:		switch(scope_incoming){		case LDAP_SCOPE_BASE:			dnParent(ndn_incoming, &pdn_incoming);			return (pdn_incoming.bv_len == ndn_stored->bv_len);		case LDAP_SCOPE_ONELEVEL:			return (ndn_incoming->bv_len == ndn_stored->bv_len);		default:			return 0;		}	case LDAP_SCOPE_SUBTREE:		return 1;		break;	default:		return 0;		break;    }}/* add query on top of LRU list */static voidadd_query_on_top (query_manager* qm, CachedQuery* qc){	CachedQuery* top = qm->lru_top;	Query* q = (Query*)qc;	qm->lru_top = qc;	if (top)		top->lru_up = qc;	else		qm->lru_bottom = qc;	qc->lru_down = top;	qc->lru_up = NULL;	Debug( pcache_debug, "Base of added query = %s\n",			q->base.bv_val, 0, 0 );}/* remove_query from LRU list */static voidremove_query (query_manager* qm, CachedQuery* qc){	CachedQuery* up;	CachedQuery* down;	if (!qc)		return;	up = qc->lru_up;	down = qc->lru_down;	if (!up)		qm->lru_top = down;	if (!down)		qm->lru_bottom = up;	if (down)		down->lru_up = up;	if (up)		up->lru_down = down;	qc->lru_up = qc->lru_down = NULL;}/* find and remove string2 from string1 * from start if position = 1, * from end if position = 3, * from anywhere if position = 2 * string1 is overwritten if position = 2. */static intfind_and_remove(struct berval* ber1, struct berval* ber2, int position){	int ret=0;	if ( !ber2->bv_val )		return 1;	if ( !ber1->bv_val )		return 0;	switch( position ) {	case 1:		if ( ber1->bv_len >= ber2->bv_len && !memcmp( ber1->bv_val,			ber2->bv_val, ber2->bv_len )) {			ret = 1;			ber1->bv_val += ber2->bv_len;			ber1->bv_len -= ber2->bv_len;		}		break;	case 2: {		char *temp;		ber1->bv_val[ber1->bv_len] = '\0';		temp = strstr( ber1->bv_val, ber2->bv_val );		if ( temp ) {			strcpy( temp, temp+ber2->bv_len );			ber1->bv_len -= ber2->bv_len;			ret = 1;		}		break;		}	case 3:		if ( ber1->bv_len >= ber2->bv_len &&			!memcmp( ber1->bv_val+ber1->bv_len-ber2->bv_len, ber2->bv_val,				ber2->bv_len )) {			ret = 1;			ber1->bv_len -= ber2->bv_len;		}		break;	}	return ret;}static struct berval*merge_init_final(Operation *op, struct berval* init, struct berval* any,	struct berval* final){	struct berval* merged, *temp;	int i, any_count, count;	for (any_count=0; any && any[any_count].bv_val; any_count++)		;	count = any_count;	if (init->bv_val)		count++;	if (final->bv_val)		count++;	merged = (struct berval*)op->o_tmpalloc( (count+1)*sizeof(struct berval),		op->o_tmpmemctx );	temp = merged;	if (init->bv_val) {		ber_dupbv_x( temp, init, op->o_tmpmemctx );		temp++;	}	for (i=0; i<any_count; i++) {		ber_dupbv_x( temp, any, op->o_tmpmemctx );		temp++; any++;	}	if (final->bv_val){		ber_dupbv_x( temp, final, op->o_tmpmemctx );		temp++;	}	BER_BVZERO( temp );	return merged;}/* Each element in stored must be found in incoming. Incoming is overwritten. */static intstrings_containment(struct berval* stored, struct berval* incoming){	struct berval* element;	int k=0;	int j, rc = 0;	for ( element=stored; element->bv_val != NULL; element++ ) {		for (j = k; incoming[j].bv_val != NULL; j++) {			if (find_and_remove(&(incoming[j]), element, 2)) {				k = j;				rc = 1;				break;			}			rc = 0;		}		if ( rc ) {			continue;		} else {			return 0;		}	}	return 1;}static intsubstr_containment_substr(Operation *op, Filter* stored, Filter* incoming){	int i;	int rc = 0;	struct berval init_incoming;	struct berval final_incoming;	struct berval *remaining_incoming = NULL;	if ((!(incoming->f_sub_initial.bv_val) && (stored->f_sub_initial.bv_val))	   || (!(incoming->f_sub_final.bv_val) && (stored->f_sub_final.bv_val)))		return 0;	init_incoming = incoming->f_sub_initial;	final_incoming =  incoming->f_sub_final;	if (find_and_remove(&init_incoming,			&(stored->f_sub_initial), 1) && find_and_remove(&final_incoming,			&(stored->f_sub_final), 3))	{		if (stored->f_sub_any == NULL) {			rc = 1;			goto final;		}		remaining_incoming = merge_init_final(op, &init_incoming,						incoming->f_sub_any, &final_incoming);		rc = strings_containment(stored->f_sub_any, remaining_incoming);		ber_bvarray_free_x( remaining_incoming, op->o_tmpmemctx );	}final:	return rc;}static intsubstr_containment_equality(Operation *op, Filter* stored, Filter* incoming){	struct berval incoming_val[2];	int rc = 0;	incoming_val[1] = incoming->f_av_value;	if (find_and_remove(incoming_val+1,			&(stored->f_sub_initial), 1) && find_and_remove(incoming_val+1,			&(stored->f_sub_final), 3)) {		if (stored->f_sub_any == NULL){			rc = 1;			goto final;		}		ber_dupbv_x( incoming_val, incoming_val+1, op->o_tmpmemctx );		BER_BVZERO( incoming_val+1 );		rc = strings_containment(stored->f_sub_any, incoming_val);		op->o_tmpfree( incoming_val[0].bv_val, op->o_tmpmemctx );	}final:	return rc;}/* check whether query is contained in any of * the cached queries in template template_index */static CachedQuery *query_containment(Operation *op, query_manager *qm,		  Query *query,		  int template_index){	QueryTemplate* templa= qm->templates;	CachedQuery* qc;	Query* q;	Filter* inputf = query->filter;	struct berval* base = &(query->base);	int scope = query->scope;	int res=0;	Filter* fs;	Filter* fi;	int ret, rc;	const char* text;	MatchingRule* mrule = NULL;	if (inputf != NULL) {		Debug( pcache_debug, "Lock QC index = %d\n",				template_index, 0, 0 );		ldap_pvt_thread_rdwr_rlock(&(templa[template_index].t_rwlock));		for(qc=templa[template_index].query; qc != NULL; qc= qc->next) {			q = (Query*)qc;			if(base_scope_compare(&(q->base), base, q->scope, scope)) {				fi = inputf;				fs = q->filter;				do {					res=0;					switch (fs->f_choice) {					case LDAP_FILTER_EQUALITY:						if (fi->f_choice == LDAP_FILTER_EQUALITY)							mrule = fs->f_ava->aa_desc->ad_type->sat_equality;						else							ret = 1;						break;					case LDAP_FILTER_GE:					case LDAP_FILTER_LE:						mrule = fs->f_ava->aa_desc->ad_type->sat_ordering;						break;					default:						mrule = NULL; 					}					if (mrule) {						rc = value_match(&ret, fs->f_ava->aa_desc, mrule,						 	SLAP_MR_VALUE_OF_ASSERTION_SYNTAX,							&(fi->f_ava->aa_value),							&(fs->f_ava->aa_value), &text);						if (rc != LDAP_SUCCESS) {							ldap_pvt_thread_rdwr_runlock(&(templa[template_index].t_rwlock));							Debug( pcache_debug,							"Unlock: Exiting QC index=%d\n",							template_index, 0, 0 );							return NULL;						}					}					switch (fs->f_choice) {

⌨️ 快捷键说明

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