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

📄 idl.c

📁 开放源码的ldap系统
💻 C
📖 第 1 页 / 共 2 页
字号:
/* idl.c - ldap id list handling routines *//* $OpenLDAP: pkg/ldap/servers/slapd/back-ldbm/idl.c,v 1.29.2.8 2001/10/01 19:20:30 kurt Exp $ *//* * Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved. * COPYING RESTRICTIONS APPLY, see COPYRIGHT file */#include "portable.h"#include <stdio.h>#include <ac/string.h>#include <ac/socket.h>#include "slap.h"#include "back-ldbm.h"static ID_BLOCK* idl_dup( ID_BLOCK *idl );static void cont_alloc( Datum *cont, Datum *key ){	ldbm_datum_init( *cont );	cont->dsize = 1 + sizeof(ID) + key->dsize;	cont->dptr = ch_malloc( cont->dsize );	* (unsigned char *) cont->dptr = SLAP_INDEX_CONT_PREFIX;	AC_MEMCPY( &((unsigned char *)cont->dptr)[1 + sizeof(ID)],		key->dptr, key->dsize );}static void cont_id( Datum *cont, ID id ){	int i;	for( i=1; i <= sizeof(id); i++) {		((unsigned char *)cont->dptr)[i] = (unsigned char)(id & 0xFF);		id >>= 8;	}}static void cont_free( Datum *cont ){	ch_free( cont->dptr );}#ifdef LDBM_DEBUG_IDLstatic void idl_check(ID_BLOCK *idl){	int i;	ID_BLOCK last;	if( ID_BLOCK_INDIRECT(idl) || ID_BLOCK_ALLIDS(idl)		|| ID_BLOCK_NIDS(idl) <= 1 )	{		return;	}	for( last = ID_BLOCK_ID(idl, 0), i = 1;		i < ID_BLOCK_NIDS(idl);		last = ID_BLOCK_ID(idl, i), i++ )	{		assert (last < ID_BLOCK_ID(idl, i) );	}}#endif/* Allocate an ID_BLOCK with room for nids ids */ID_BLOCK *idl_alloc( unsigned int nids ){	ID_BLOCK	*new;	/* nmax + nids + space for the ids */	new = (ID_BLOCK *) ch_calloc( (ID_BLOCK_IDS_OFFSET + nids), sizeof(ID) );	ID_BLOCK_NMAX(new) = nids;	ID_BLOCK_NIDS(new) = 0;	return( new );}/* Allocate an empty ALLIDS ID_BLOCK */ID_BLOCK	*idl_allids( Backend *be ){	ID_BLOCK	*idl;	ID		id;	idl = idl_alloc( 0 );	ID_BLOCK_NMAX(idl) = ID_BLOCK_ALLIDS_VALUE;	if ( next_id_get( be, &id ) ) {		return NULL;	}	ID_BLOCK_NIDS(idl) = id;	return( idl );}/* Free an ID_BLOCK */voididl_free( ID_BLOCK *idl ){	if ( idl == NULL ) {		Debug( LDAP_DEBUG_TRACE,			"idl_free: called with NULL pointer\n",			0, 0, 0 );		return;	}	free( (char *) idl );}/* Fetch an single ID_BLOCK from the cache */static ID_BLOCK *idl_fetch_one(    Backend		*be,    DBCache	*db,    Datum		key){	Datum	data;	ID_BLOCK	*idl;	/* Debug( LDAP_DEBUG_TRACE, "=> idl_fetch_one\n", 0, 0, 0 ); */	data = ldbm_cache_fetch( db, key );	if( data.dptr == NULL ) {		return NULL;	}	idl = idl_dup((ID_BLOCK *) data.dptr);	ldbm_datum_free( db->dbc_db, data );	return idl;}/* Fetch a set of ID_BLOCKs from the cache *	if not INDIRECT * 		if block return is an ALLIDS block, *			return an new ALLIDS block * 		otherwise *			return block *	construct super block from all blocks referenced by INDIRECT block *	return super block */ID_BLOCK *idl_fetch(    Backend		*be,    DBCache	*db,    Datum		key){	Datum	data;	ID_BLOCK	*idl;	ID_BLOCK	**tmp;	int	i, nids;	idl = idl_fetch_one( be, db, key );	if ( idl == NULL ) {		return NULL;	}	if ( ID_BLOCK_ALLIDS(idl) ) {		/* all ids block */		/* make sure we have the current value of highest id */		idl_free( idl );		idl = idl_allids( be );		return( idl );	}	if ( ! ID_BLOCK_INDIRECT( idl ) ) {		/* regular block */		return( idl );	}	/*	 * this is an indirect block which points to other blocks.	 * we need to read in all the blocks it points to and construct	 * a big id list containing all the ids, which we will return.	 */	/* count the number of blocks & allocate space for pointers to them */	for ( i = 0; !ID_BLOCK_NOID(idl, i); i++ )		;	/* NULL */	tmp = (ID_BLOCK **) ch_malloc( (i + 1) * sizeof(ID_BLOCK *) );	/* read in all the blocks */	cont_alloc( &data, &key );	nids = 0;	for ( i = 0; !ID_BLOCK_NOID(idl, i); i++ ) {		cont_id( &data, ID_BLOCK_ID(idl, i) );		if ( (tmp[i] = idl_fetch_one( be, db, data )) == NULL ) {			Debug( LDAP_DEBUG_ANY,			    "idl_fetch: one returned NULL\n", 0, 0, 0 );			continue;		}		nids += ID_BLOCK_NIDS(tmp[i]);	}	tmp[i] = NULL;	cont_free( &data );	idl_free( idl );	/* allocate space for the big block */	idl = idl_alloc( nids );	ID_BLOCK_NIDS(idl) = nids;	nids = 0;	/* copy in all the ids from the component blocks */	for ( i = 0; tmp[i] != NULL; i++ ) {		if ( tmp[i] == NULL ) {			continue;		}		AC_MEMCPY(			(char *) &ID_BLOCK_ID(idl, nids),			(char *) &ID_BLOCK_ID(tmp[i], 0),			ID_BLOCK_NIDS(tmp[i]) * sizeof(ID) );		nids += ID_BLOCK_NIDS(tmp[i]);		idl_free( tmp[i] );	}	free( (char *) tmp );#ifdef LDBM_DEBUG_IDL	idl_check(idl);#endif	Debug( LDAP_DEBUG_TRACE, "<= idl_fetch %ld ids (%ld max)\n",	       ID_BLOCK_NIDS(idl), ID_BLOCK_NMAX(idl), 0 );	return( idl );}/* store a single block */static intidl_store(    Backend		*be,    DBCache	*db,    Datum		key,     ID_BLOCK		*idl){	int	rc, flags;	Datum	data;	struct ldbminfo *li = (struct ldbminfo *) be->be_private;#ifdef LDBM_DEBUG_IDL	idl_check(idl);#endif	ldbm_datum_init( data );	/* Debug( LDAP_DEBUG_TRACE, "=> idl_store\n", 0, 0, 0 ); */	data.dptr = (char *) idl;	data.dsize = (ID_BLOCK_IDS_OFFSET + ID_BLOCK_NMAX(idl)) * sizeof(ID);	#ifdef LDBM_DEBUG	Statslog( LDAP_DEBUG_STATS, "<= idl_store(): rc=%d\n",		rc, 0, 0, 0, 0 );#endif	flags = LDBM_REPLACE;	rc = ldbm_cache_store( db, key, data, flags );	/* Debug( LDAP_DEBUG_TRACE, "<= idl_store %d\n", rc, 0, 0 ); */	return( rc );}/* split the block at id  *	locate ID greater than or equal to id. */static voididl_split_block(    ID_BLOCK	*b,    ID		id,    ID_BLOCK	**right,    ID_BLOCK	**left){	unsigned int	nr, nl;	/* find where to split the block *//* XXX linear search XXX */	for ( nr = 0; nr < ID_BLOCK_NIDS(b) && id > ID_BLOCK_ID(b, nr); nr++ )		;	/* NULL */	nl = ID_BLOCK_NIDS(b) - nr;	*right = idl_alloc( nr == 0 ? 1 : nr );	*left = idl_alloc( nl + (nr == 0 ? 0 : 1));	/*	 * everything before the id being inserted in the first block	 * unless there is nothing, in which case the id being inserted	 * goes there.	 */	if ( nr == 0 ) {		ID_BLOCK_NIDS(*right) = 1;		ID_BLOCK_ID(*right, 0) = id;	} else {		AC_MEMCPY(			(char *) &ID_BLOCK_ID(*right, 0),			(char *) &ID_BLOCK_ID(b, 0),			nr * sizeof(ID) );		ID_BLOCK_NIDS(*right) = nr;		ID_BLOCK_ID(*left, 0) = id;	}	/* the id being inserted & everything after in the second block */	AC_MEMCPY(		(char *) &ID_BLOCK_ID(*left, (nr == 0 ? 0 : 1)),	    (char *) &ID_BLOCK_ID(b, nr),		nl * sizeof(ID) );	ID_BLOCK_NIDS(*left) = nl + (nr == 0 ? 0 : 1);#ifdef LDBM_DEBUG_IDL	idl_check(*right);	idl_check(*left);#endif}/* * idl_change_first - called when an indirect block's first key has * changed, meaning it needs to be stored under a new key, and the * header block pointing to it needs updating. */static intidl_change_first(    Backend		*be,    DBCache	*db,    Datum		hkey,		/* header block key	*/    ID_BLOCK		*h,		/* header block 	*/    int			pos,		/* pos in h to update	*/    Datum		bkey,		/* data block key	*/    ID_BLOCK		*b		/* data block 		*/){	int	rc;	/* Debug( LDAP_DEBUG_TRACE, "=> idl_change_first\n", 0, 0, 0 ); */	/* delete old key block */	if ( (rc = ldbm_cache_delete( db, bkey )) != 0 ) {		Debug( LDAP_DEBUG_ANY,		    "idl_change_first: ldbm_cache_delete returned %d\n",			rc, 0, 0 );		return( rc );	}	/* write block with new key */	cont_id( &bkey, ID_BLOCK_ID(b, 0) );	if ( (rc = idl_store( be, db, bkey, b )) != 0 ) {		Debug( LDAP_DEBUG_ANY,		    "idl_change_first: idl_store returned %d\n", rc, 0, 0 );		return( rc );	}	/* update + write indirect header block */	ID_BLOCK_ID(h, pos) = ID_BLOCK_ID(b, 0);	if ( (rc = idl_store( be, db, hkey, h )) != 0 ) {		Debug( LDAP_DEBUG_ANY,		    "idl_change_first: idl_store returned %d\n", rc, 0, 0 );		return( rc );	}	return( 0 );}intidl_insert_key(    Backend		*be,    DBCache	*db,    Datum		key,    ID			id){	int	i, j, first, rc;	ID_BLOCK	*idl, *tmp, *tmp2, *tmp3;	Datum	k2;	if ( (idl = idl_fetch_one( be, db, key )) == NULL ) {		idl = idl_alloc( 1 );		ID_BLOCK_ID(idl, ID_BLOCK_NIDS(idl)++) = id;		rc = idl_store( be, db, key, idl );		idl_free( idl );		return( rc );	}	if ( ID_BLOCK_ALLIDS( idl ) ) {		/* ALLIDS */		idl_free( idl );		return 0;	}	if ( ! ID_BLOCK_INDIRECT( idl ) ) {		/* regular block */		switch ( idl_insert( &idl, id, db->dbc_maxids ) ) {		case 0:		/* id inserted - store the updated block */		case 1:			rc = idl_store( be, db, key, idl );			break;		case 2:		/* id already there - nothing to do */			rc = 0;			break;		case 3:		/* id not inserted - block must be split */			/* check threshold for marking this an all-id block */			if ( db->dbc_maxindirect < 2 ) {				idl_free( idl );				idl = idl_allids( be );				rc = idl_store( be, db, key, idl );				break;			}			idl_split_block( idl, id, &tmp, &tmp2 );			idl_free( idl );			/* create the header indirect block */			idl = idl_alloc( 3 );			ID_BLOCK_NMAX(idl) = 3;			ID_BLOCK_NIDS(idl) = ID_BLOCK_INDIRECT_VALUE;			ID_BLOCK_ID(idl, 0) = ID_BLOCK_ID(tmp, 0);			ID_BLOCK_ID(idl, 1) = ID_BLOCK_ID(tmp2, 0);			ID_BLOCK_ID(idl, 2) = NOID;			/* store it */			rc = idl_store( be, db, key, idl );			cont_alloc( &k2, &key );			cont_id( &k2, ID_BLOCK_ID(tmp, 0) );			rc = idl_store( be, db, k2, tmp );			cont_id( &k2, ID_BLOCK_ID(tmp2, 0) );			rc = idl_store( be, db, k2, tmp2 );			cont_free( &k2 );			idl_free( tmp );			idl_free( tmp2 );			break;		}		idl_free( idl );		return( rc );	}	/*	 * this is an indirect block which points to other blocks.	 * we need to read in the block into which the id should be	 * inserted, then insert the id and store the block.  we might	 * have to split the block if it is full, which means we also	 * need to write a new "header" block.	 */	/* select the block to try inserting into *//* XXX linear search XXX */	for ( i = 0; !ID_BLOCK_NOID(idl, i) && id > ID_BLOCK_ID(idl, i); i++ )		;	/* NULL */	if ( i != 0 ) {		i--;		first = 0;	} else {		first = 1;	}	/* get the block */	cont_alloc( &k2, &key );	cont_id( &k2, ID_BLOCK_ID(idl, i) );	if ( (tmp = idl_fetch_one( be, db, k2 )) == NULL ) {		Debug( LDAP_DEBUG_ANY, "idl_insert_key: nonexistent continuation block\n",		    0, 0, 0 );		cont_free( &k2 );		idl_free( idl );		return( -1 );	}	/* insert the id */	switch ( idl_insert( &tmp, id, db->dbc_maxids ) ) {	case 0:		/* id inserted ok */		if ( (rc = idl_store( be, db, k2, tmp )) != 0 ) {			Debug( LDAP_DEBUG_ANY,			    "idl_insert_key: idl_store returned %d\n", rc, 0, 0 );		}		break;	case 1:		/* id inserted - first id in block has changed */		/*		 * key for this block has changed, so we have to		 * write the block under the new key, delete the		 * old key block + update and write the indirect		 * header block.		 */		rc = idl_change_first( be, db, key, idl, i, k2, tmp );		break;	case 2:		/* id not inserted - already there, do nothing */		rc = 0;		break;	case 3:		/* id not inserted - block is full */		/*		 * first, see if it will fit in the next block,		 * without splitting, unless we're trying to insert		 * into the beginning of the first block.		 */		/* is there a next block? */		if ( !first && !ID_BLOCK_NOID(idl, i + 1) ) {			/* read it in */			cont_alloc( &k2, &key );			cont_id( &k2, ID_BLOCK_ID(idl, i) );			if ( (tmp2 = idl_fetch_one( be, db, k2 )) == NULL ) {				Debug( LDAP_DEBUG_ANY,				    "idl_insert_key: idl_fetch_one returned NULL\n",				    0, 0, 0 );				/* split the original block */				cont_free( &k2 );				goto split;			}			/* If the new id is less than the last id in the			 * current block, it must not be put into the next			 * block. Push the last id of the current block			 * into the next block instead.			 */			if (id < ID_BLOCK_ID(tmp, ID_BLOCK_NIDS(tmp) - 1)) {			    ID id2 = ID_BLOCK_ID(tmp, ID_BLOCK_NIDS(tmp) - 1);			    Datum k3;			    ldbm_datum_init( k3 );			    --ID_BLOCK_NIDS(tmp);			    /* This must succeed since we just popped one			     * ID off the end of it.			     */			    rc = idl_insert( &tmp, id, db->dbc_maxids );				k3.dptr = ch_malloc(k2.dsize);				k3.dsize = k2.dsize;				AC_MEMCPY(k3.dptr, k2.dptr, k3.dsize);			    if ( (rc = idl_store( be, db, k3, tmp )) != 0 ) {				Debug( LDAP_DEBUG_ANY,			    "idl_insert_key: idl_store returned %d\n", rc, 0, 0 );			    }				free( k3.dptr );			    id = id2;			    /* This new id will necessarily be inserted			     * as the first id of the next block by the			     * following switch() statement.			     */			}			switch ( (rc = idl_insert( &tmp2, id,			    db->dbc_maxids )) ) {			case 1:		/* id inserted first in block */				rc = idl_change_first( be, db, key, idl,				    i + 1, k2, tmp2 );

⌨️ 快捷键说明

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