ldbm.c
来自「ldap服务器源码」· C语言 代码 · 共 1,212 行 · 第 1/2 页
C
1,212 行
/* ldbm.c - ldap dbm compatibility routines *//* $OpenLDAP: pkg/ldap/servers/slapd/back-ldbm/ldbm.c,v 1.4.2.4 2007/01/02 21:44:03 kurt Exp $ *//* This work is part of OpenLDAP Software <http://www.openldap.org/>. * * Copyright 1998-2007 The OpenLDAP Foundation. * Portions Copyright 1998-2003 Kurt D. Zeilenga. * Portions Copyright 1998-2001 Net Boolean Incorporated. * 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 originally developed by the University of Michigan * (as part of U-MICH LDAP). Additional significant contributors * include: * Gary Williams * Howard Chu * Juan Gomez * Kurt D. Zeilenga * Kurt Spanier * Mark Whitehouse * Randy Kundee */#include "portable.h"#ifdef SLAPD_LDBM#include <stdio.h>#include <ac/stdlib.h>#include <ac/string.h>#include <ac/errno.h>#include "ldbm.h"#include "ldap_pvt_thread.h"voidldbm_datum_free( LDBM ldbm, Datum data ){ if ( data.dptr ) { free( data.dptr ); memset( &data, '\0', sizeof( Datum )); data.dptr = NULL; }}Datumldbm_datum_dup( LDBM ldbm, Datum data ){ Datum dup; ldbm_datum_init( dup ); if ( data.dsize == 0 ) { dup.dsize = 0; dup.dptr = NULL; return( dup ); } dup.dsize = data.dsize; if ( (dup.dptr = (char *) malloc( data.dsize )) != NULL ) { AC_MEMCPY( dup.dptr, data.dptr, data.dsize ); } return( dup );}static int ldbm_initialized = 0;#if defined( USE_BERKELEY_CDB ) /* not currently supported */#define LDBM_RWLOCK_INIT ((void) 0)#define LDBM_RWLOCK_DESTROY ((void) 0)#define LDBM_WLOCK ((void) 0)#define LDBM_WUNLOCK ((void) 0)#define LDBM_RLOCK ((void) 0)#define LDBM_RUNLOCK ((void) 0)#elif defined( HAVE_BERKELEY_DB_THREAD )static ldap_pvt_thread_rdwr_t ldbm_big_rdwr;#define LDBM_RWLOCK_INIT (ldap_pvt_thread_rdwr_init( &ldbm_big_rdwr ))#define LDBM_RWLOCK_DESTROY (ldap_pvt_thread_rdwr_destroy( &ldbm_big_rdwr ))#define LDBM_WLOCK (ldap_pvt_thread_rdwr_wlock(&ldbm_big_rdwr))#define LDBM_WUNLOCK (ldap_pvt_thread_rdwr_wunlock(&ldbm_big_rdwr))#define LDBM_RLOCK (ldap_pvt_thread_rdwr_rlock(&ldbm_big_rdwr))#define LDBM_RUNLOCK (ldap_pvt_thread_rdwr_runlock(&ldbm_big_rdwr))#elsestatic ldap_pvt_thread_mutex_t ldbm_big_mutex;#define LDBM_RWLOCK_INIT (ldap_pvt_thread_mutex_init( &ldbm_big_mutex ))#define LDBM_RWLOCK_DESTROY (ldap_pvt_thread_mutex_destroy( &ldbm_big_mutex ))#define LDBM_WLOCK (ldap_pvt_thread_mutex_lock(&ldbm_big_mutex))#define LDBM_WUNLOCK (ldap_pvt_thread_mutex_unlock(&ldbm_big_mutex))#define LDBM_RLOCK LDBM_WLOCK#define LDBM_RUNLOCK LDBM_WUNLOCK#endif#if !defined( HAVE_BERKELEY_DB ) || (DB_VERSION_MAJOR < 3) /* a dbEnv for BERKELEYv2 */DB_ENV *ldbm_Env = NULL; /* real or fake, depending on db and version */#endif/* Let's make the version comparisons a little easier... */#undef DB_VERSION_X#ifdef HAVE_BERKELEY_DB#define DB_VERSION_X ((DB_VERSION_MAJOR<<16)|(DB_VERSION_MINOR<<8)|DB_VERSION_PATCH)#endif/******************************************************************* * * * Create some special functions to initialize Berkeley DB for * * versions greater than 2. * * * *******************************************************************/#if defined( HAVE_BERKELEY_DB ) && (DB_VERSION_MAJOR >= 2)void *ldbm_malloc( size_t size ){ /* likely should use ber_mem* routines */ return( calloc( 1, size ) );}#ifdef LDAP_SYSLOG#include <ac/syslog.h>#endifstatic void#if DB_VERSION_X < 0x040300ldbm_db_errcall( const char *prefix, char *message )#elseldbm_db_errcall( const DB_ENV *env, const char *prefix, char *message )#endif{#ifdef LDAP_SYSLOG syslog( LOG_INFO, "ldbm: %s %s", prefix, message );#endif}int ldbm_initialize( const char* home ){#if DB_VERSION_MAJOR < 3 int err; u_int32_t envFlags;#endif if(ldbm_initialized++) return 1; { char *version;#ifdef HAVE_EBCDIC char v2[1024];#endif int major, minor, patch; version = db_version( &major, &minor, &patch );#ifdef HAVE_EBCDIC strcpy( v2, version ); __etoa( v2 ); version = v2;#endif if( major != DB_VERSION_MAJOR || minor < DB_VERSION_MINOR ) {#ifdef LDAP_SYSLOG syslog( LOG_INFO, "ldbm_initialize(): version mismatch\nexpected: %s\ngot: %s\n", DB_VERSION_STRING, version );#endif return 1; } }#if DB_VERSION_MAJOR < 3 ldbm_Env = calloc( 1, sizeof( DB_ENV )); if( ldbm_Env == NULL ) return 1; ldbm_Env->db_errcall = ldbm_db_errcall; ldbm_Env->db_errpfx = "==>"; envFlags = DB_CREATE | DB_USE_ENVIRON; /* add optional flags */#ifdef DB_PRIVATE envFlags |= DB_PRIVATE;#endif#ifdef HAVE_BERKELEY_DB_THREAD envFlags |= DB_THREAD; #endif err = db_appinit( home, NULL, ldbm_Env, envFlags ); if ( err ) {#ifdef LDAP_SYSLOG syslog( LOG_INFO, "ldbm_initialize(): " "FATAL error (%d) in db_appinit()\n", err );#endif return( 1 ); }#endif LDBM_RWLOCK_INIT; return 0;}int ldbm_shutdown( void ){ if( !ldbm_initialized ) return 1;#if DB_VERSION_MAJOR < 3 db_appexit( ldbm_Env );#endif LDBM_RWLOCK_DESTROY; return 0;}#else /* some DB other than Berkeley V2 or greater */int ldbm_initialize( const char * home ){ if(ldbm_initialized++) return 1; LDBM_RWLOCK_INIT; return 0;}int ldbm_shutdown( void ){ if( !ldbm_initialized ) return 1; LDBM_RWLOCK_DESTROY; return 0;}#endif /* HAVE_BERKELEY_DB */#if defined( HAVE_BERKELEY_DB ) && (DB_VERSION_MAJOR >= 3)DB_ENV *ldbm_initialize_env(const char *home, int dbcachesize, int *envdirok){ DB_ENV *env = NULL; int err; u_int32_t envFlags;#ifdef HAVE_EBCDIC char n2[2048];#endif err = db_env_create( &env, 0 ); if ( err ) {#ifdef LDAP_SYSLOG syslog( LOG_INFO, "ldbm_initialize_env(): " "FATAL error in db_env_create() : %s (%d)\n", db_strerror( err ), err );#endif return NULL; }#if DB_VERSION_X >= 0x030300 /* This interface appeared in 3.3 */ env->set_alloc( env, ldbm_malloc, NULL, NULL );#endif env->set_errcall( env, ldbm_db_errcall ); env->set_errpfx( env, "==>" ); if (dbcachesize) { env->set_cachesize( env, 0, dbcachesize, 0 ); } envFlags = DB_CREATE | DB_INIT_MPOOL | DB_USE_ENVIRON;#ifdef DB_PRIVATE envFlags |= DB_PRIVATE;#endif#ifdef DB_MPOOL_PRIVATE envFlags |= DB_MPOOL_PRIVATE;#endif#ifdef HAVE_BERKELEY_DB_THREAD envFlags |= DB_THREAD;#endif#ifdef HAVE_EBCDIC strncpy(n2, home, sizeof(n2)-1); n2[sizeof(n2)-1] = '\0'; __atoe(n2); home = n2;#endif#if DB_VERSION_X >= 0x030100 err = env->open( env, home, envFlags, 0 );#else /* 3.0.x requires an extra argument */ err = env->open( env, home, NULL, envFlags, 0 );#endif if ( err != 0 ) {#ifdef LDAP_SYSLOG syslog( LOG_INFO, "ldbm_initialize_env(): " "FATAL error in dbEnv->open() : %s (%d)\n", db_strerror( err ), err );#endif env->close( env, 0 ); return NULL; } *envdirok = 1; return env;}void ldbm_shutdown_env(DB_ENV *env){ env->close( env, 0 );}#elseDB_ENV *ldbm_initialize_env(const char *home, int dbcachesize, int *envdirok){ return ldbm_Env;}void ldbm_shutdown_env(DB_ENV *env){}#endif#if defined( LDBM_USE_DBHASH ) || defined( LDBM_USE_DBBTREE )/***************************************************************** * * * use berkeley db hash or btree package * * * *****************************************************************/LDBMldbm_open( DB_ENV *env, char *name, int rw, int mode, int dbcachesize ){ LDBM ret = NULL;#ifdef HAVE_EBCDIC char n2[2048];#endif#if DB_VERSION_MAJOR >= 3 int err; LDBM_WLOCK; err = db_create( &ret, env, 0 ); if ( err != 0 ) { (void)ret->close(ret, 0); LDBM_WUNLOCK; return NULL; }#if DB_VERSION_X < 0x030300 ret->set_malloc( ret, ldbm_malloc );#endif ret->set_pagesize( ret, DEFAULT_DB_PAGE_SIZE ); /* likely should use ber_mem* routines */#ifdef HAVE_EBCDIC strncpy(n2, name, sizeof(n2)-1); n2[sizeof(n2)-1] = '\0'; __atoe(n2); name = n2;#endif#if DB_VERSION_X >= 0x040111 err = ret->open( ret, NULL, name, NULL, DB_TYPE, rw, mode);#else err = ret->open( ret, name, NULL, DB_TYPE, rw, mode);#endif if ( err != 0 ) { int tmp = errno; (void)ret->close(ret, 0); errno = tmp; LDBM_WUNLOCK; return NULL; } LDBM_WUNLOCK; #elif DB_VERSION_MAJOR >= 2 DB_INFO dbinfo; memset( &dbinfo, '\0', sizeof( dbinfo ));#if DB_VERSION_MAJOR == 2 && DB_VERSION_MINOR == 4 /* * BerkeleyDB 2.4 do not allow db_cachesize * to be specified if an DB_ENV is. */#else /* set db_cachesize of MPOOL is NOT being used. */ if (( ldbm_Env == NULL ) || ( ldbm_Env->mp_info == NULL )) { dbinfo.db_cachesize = dbcachesize; }#endif dbinfo.db_pagesize = DEFAULT_DB_PAGE_SIZE; dbinfo.db_malloc = ldbm_malloc; LDBM_WLOCK; (void) db_open( name, DB_TYPE, rw, mode, ldbm_Env, &dbinfo, &ret ); LDBM_WUNLOCK;#else void *info; BTREEINFO binfo; HASHINFO hinfo; if ( DB_TYPE == DB_HASH ) { memset( (char *) &hinfo, '\0', sizeof(hinfo) ); hinfo.cachesize = dbcachesize; info = &hinfo; } else if ( DB_TYPE == DB_BTREE ) { memset( (char *) &binfo, '\0', sizeof(binfo) ); binfo.cachesize = dbcachesize; info = &binfo; } else { info = NULL; } LDBM_WLOCK; ret = dbopen( name, rw, mode, DB_TYPE, info ); LDBM_WUNLOCK;#endif return ret;}voidldbm_close( LDBM ldbm ){ LDBM_WLOCK;#if DB_VERSION_MAJOR >= 2 ldbm->close( ldbm, 0 );#else ldbm->close( ldbm );#endif LDBM_WUNLOCK;}voidldbm_sync( LDBM ldbm ){ LDBM_WLOCK; (*ldbm->sync)( ldbm, 0 ); LDBM_WUNLOCK;}Datumldbm_fetch( LDBM ldbm, Datum key ){ Datum data; int rc; LDBM_RLOCK;#if DB_VERSION_MAJOR >= 2 ldbm_datum_init( data ); data.flags = DB_DBT_MALLOC; if ( (rc = ldbm->get( ldbm, NULL, &key, &data, 0 )) != 0 ) { ldbm_datum_free( ldbm, data ); data.dptr = NULL; data.dsize = 0; }#else if ( (rc = ldbm->get( ldbm, &key, &data, 0 )) == 0 ) { /* Berkeley DB 1.85 don't malloc the data for us */ /* duplicate it for to ensure reentrancy */ data = ldbm_datum_dup( ldbm, data ); } else { data.dptr = NULL; data.dsize = 0; }#endif LDBM_RUNLOCK; return( data );}intldbm_store( LDBM ldbm, Datum key, Datum data, int flags ){ int rc; LDBM_WLOCK;#if DB_VERSION_MAJOR >= 2 rc = ldbm->put( ldbm, NULL, &key, &data, flags & ~LDBM_SYNC ); rc = (-1) * rc;#else rc = ldbm->put( ldbm, &key, &data, flags & ~LDBM_SYNC );#endif if ( flags & LDBM_SYNC ) ldbm->sync( ldbm, 0 ); LDBM_WUNLOCK; return( rc );}intldbm_delete( LDBM ldbm, Datum key ){ int rc; LDBM_WLOCK;#if DB_VERSION_MAJOR >= 2 rc = ldbm->del( ldbm, NULL, &key, 0 ); rc = (-1) * rc;#else rc = ldbm->del( ldbm, &key, 0 );#endif ldbm->sync( ldbm, 0 ); LDBM_WUNLOCK; return( rc );}Datumldbm_firstkey( LDBM ldbm, LDBMCursor **dbch ){ Datum key, data; int rc;#if DB_VERSION_MAJOR >= 2 LDBMCursor *dbci; ldbm_datum_init( key ); ldbm_datum_init( data ); key.flags = data.flags = DB_DBT_MALLOC; LDBM_RLOCK; /* acquire a cursor for the DB */# if DB_VERSION_X >= 0x020600 rc = ldbm->cursor( ldbm, NULL, &dbci, 0 );# else rc = ldbm->cursor( ldbm, NULL, &dbci );# endif if( rc ) { key.dptr = NULL; } else { *dbch = dbci; if ( dbci->c_get( dbci, &key, &data, DB_NEXT ) == 0 ) { ldbm_datum_free( ldbm, data ); } else { key.dptr = NULL; key.dsize = 0; } } LDBM_RUNLOCK;#else LDBM_RLOCK; rc = ldbm->seq( ldbm, &key, &data, R_FIRST ); if ( rc == 0 ) { key = ldbm_datum_dup( ldbm, key ); } else { key.dptr = NULL; key.dsize = 0; } LDBM_RUNLOCK;#endif return( key );}Datumldbm_nextkey( LDBM ldbm, Datum key, LDBMCursor *dbcp ){ int rc; Datum data; LDBM_RLOCK;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?