From 95627d674ad2321a1c366cca9f9ce51a0bbc71c7 Mon Sep 17 00:00:00 2001 From: Kurt Zeilenga Date: Wed, 20 Sep 2000 07:21:09 +0000 Subject: [PATCH] Add dn2id code Add idl_insert --- servers/slapd/back-bdb/back-bdb.h | 13 +- servers/slapd/back-bdb/backbdb.dsp | 8 + servers/slapd/back-bdb/dn2id.c | 318 +++++++++++++++++++++++++++++ servers/slapd/back-bdb/idl.c | 117 +++++++++++ servers/slapd/back-bdb/init.c | 89 ++++++-- servers/slapd/back-bdb/proto-bdb.h | 22 +- 6 files changed, 547 insertions(+), 20 deletions(-) create mode 100644 servers/slapd/back-bdb/dn2id.c create mode 100644 servers/slapd/back-bdb/idl.c diff --git a/servers/slapd/back-bdb/back-bdb.h b/servers/slapd/back-bdb/back-bdb.h index 503e5de0a0..0cda387daf 100644 --- a/servers/slapd/back-bdb/back-bdb.h +++ b/servers/slapd/back-bdb/back-bdb.h @@ -15,6 +15,10 @@ LDAP_BEGIN_DECL +#define DN_BASE_PREFIX SLAP_INDEX_EQUALITY_PREFIX +#define DN_ONE_PREFIX '%' +#define DN_SUBTREE_PREFIX '@' + #define DBTzero(t) (memset((t), 0, sizeof(DBT))) #define DBT2bv(t,bv) ((bv)->bv_val = (t)->data, \ (bv)->bv_len = (t)->size) @@ -32,6 +36,7 @@ LDAP_BEGIN_DECL #define BDB_NEXTID 0 #define BDB_ENTRIES 1 #define BDB_DN2ID 2 +#define BDB_INDICES 3 struct bdb_db_info { DB *bdi_db; @@ -47,11 +52,11 @@ struct bdb_info { int bi_dbenv_mode; int bi_ndatabases; - struct bdb_db_info **bdi_databases; + struct bdb_db_info **bi_databases; }; -#define bi_nextid bdi_databases[BDB_NEXTID] -#define bi_entries bdi_databases[BDB_ENTRIES] -#define bi_dn2id bdi_databases[BDB_DN2ID] +#define bi_nextid bi_databases[BDB_NEXTID] +#define bi_entries bi_databases[BDB_ENTRIES] +#define bi_dn2id bi_databases[BDB_DN2ID] LDAP_END_DECL diff --git a/servers/slapd/back-bdb/backbdb.dsp b/servers/slapd/back-bdb/backbdb.dsp index 7d22533f37..ab0beaa5be 100644 --- a/servers/slapd/back-bdb/backbdb.dsp +++ b/servers/slapd/back-bdb/backbdb.dsp @@ -131,6 +131,10 @@ SOURCE=".\back-bdb.h" # End Source File # Begin Source File +SOURCE=.\dn2id.c +# End Source File +# Begin Source File + SOURCE=.\error.c # End Source File # Begin Source File @@ -139,6 +143,10 @@ SOURCE=.\external.h # End Source File # Begin Source File +SOURCE=.\idl.c +# End Source File +# Begin Source File + SOURCE=.\init.c # End Source File # Begin Source File diff --git a/servers/slapd/back-bdb/dn2id.c b/servers/slapd/back-bdb/dn2id.c new file mode 100644 index 0000000000..b008849573 --- /dev/null +++ b/servers/slapd/back-bdb/dn2id.c @@ -0,0 +1,318 @@ +/* dn2id.c - routines to deal with the dn2id index */ +/* $OpenLDAP$ */ +/* + * Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved. + * COPYING RESTRICTIONS APPLY, see COPYRIGHT file + */ + +#include "portable.h" + +#include + +#include +#include + +#include "back-bdb.h" + +int +bdb_index_dn_add( + Backend *be, + DB_TXN *txn, + const char *dn, + ID id +) +{ + int rc; + DBT key, data; + struct bdb_info *bdb = (struct bdb_info *) be->be_private; + DB *db = bdb->bi_dn2id->bdi_db; + + Debug( LDAP_DEBUG_TRACE, "=> bdb_index_dn_add( \"%s\", %ld )\n", dn, id, 0 ); + assert( id != NOID ); + + DBTzero( &key ); + key.size = strlen( dn ) + 2; + key.data = ch_malloc( key.size ); + ((char *)key.data)[0] = DN_BASE_PREFIX; + AC_MEMCPY( &((char *)key.data)[1], dn, key.size - 1 ); + + DBTzero( &data ); + data.data = (char *) &id; + data.size = sizeof( id ); + + /* store it -- don't override */ + rc = db->put( db, txn, &key, &data, DB_NOOVERWRITE ); + if( rc != 0 ) { + goto done; + } + + { + char *pdn = dn_parent( NULL, dn ); + ((char *)(key.data))[0] = DN_ONE_PREFIX; + + if( pdn != NULL ) { + key.size = strlen( pdn ) + 2; + AC_MEMCPY( &((char*)key.data)[1], + pdn, key.size - 1 ); + + rc = bdb_idl_insert_key( be, db, txn, &key, id ); + free( pdn ); + + if( rc != 0 ) { + goto done; + } + } + } + + if ( rc != -1 ) { + char **subtree = dn_subtree( NULL, dn ); + + if( subtree != NULL ) { + int i; + ((char *)key.data)[0] = DN_SUBTREE_PREFIX; + for( i=0; subtree[i] != NULL; i++ ) { + key.size = strlen( subtree[i] ) + 2; + AC_MEMCPY( &((char *)key.data)[1], + subtree[i], key.size - 1 ); + + rc = bdb_idl_insert_key( be, db, txn, &key, id ); + + if( rc != 0 ) { + goto done; + } + } + + charray_free( subtree ); + } + } + +done: + ch_free( key.data ); + Debug( LDAP_DEBUG_TRACE, "<= bdb_index_dn_add %d\n", rc, 0, 0 ); + return( rc ); +} + +#if 0 +ID +dn2id( + Backend *be, + const char *dn +) +{ + struct ldbminfo *li = (struct ldbminfo *) be->be_private; + DBCache *db; + ID id; + Datum key, data; + + Debug( LDAP_DEBUG_TRACE, "=> dn2id( \"%s\" )\n", dn, 0, 0 ); + + /* first check the cache */ + if ( (id = cache_find_entry_dn2id( be, &li->li_cache, dn )) != NOID ) { + Debug( LDAP_DEBUG_TRACE, "<= dn2id %ld (in cache)\n", id, + 0, 0 ); + return( id ); + } + + if ( (db = ldbm_cache_open( be, "dn2id", LDBM_SUFFIX, LDBM_WRCREAT )) + == NULL ) { + Debug( LDAP_DEBUG_ANY, "<= dn2id could not open dn2id%s\n", + LDBM_SUFFIX, 0, 0 ); + return( NOID ); + } + + ldbm_datum_init( key ); + + key.dsize = strlen( dn ) + 2; + key.dptr = ch_malloc( key.dsize ); + sprintf( key.dptr, "%c%s", DN_BASE_PREFIX, dn ); + + data = ldbm_cache_fetch( db, key ); + + ldbm_cache_close( be, db ); + + free( key.dptr ); + + if ( data.dptr == NULL ) { + Debug( LDAP_DEBUG_TRACE, "<= dn2id NOID\n", 0, 0, 0 ); + return( NOID ); + } + + AC_MEMCPY( (char *) &id, data.dptr, sizeof(ID) ); + + assert( id != NOID ); + + ldbm_datum_free( db->dbc_db, data ); + + Debug( LDAP_DEBUG_TRACE, "<= dn2id %ld\n", id, 0, 0 ); + return( id ); +} + +ID_BLOCK * +dn2idl( + Backend *be, + const char *dn, + int prefix +) +{ + DBCache *db; + Datum key; + ID_BLOCK *idl; + + Debug( LDAP_DEBUG_TRACE, "=> dn2idl( \"%c%s\" )\n", prefix, dn, 0 ); + + if ( (db = ldbm_cache_open( be, "dn2id", LDBM_SUFFIX, LDBM_WRCREAT )) + == NULL ) { + Debug( LDAP_DEBUG_ANY, "<= dn2idl could not open dn2id%s\n", + LDBM_SUFFIX, 0, 0 ); + return NULL; + } + + ldbm_datum_init( key ); + + key.dsize = strlen( dn ) + 2; + key.dptr = ch_malloc( key.dsize ); + sprintf( key.dptr, "%c%s", prefix, dn ); + + idl = idl_fetch( be, db, key ); + + ldbm_cache_close( be, db ); + + free( key.dptr ); + + return( idl ); +} + + +int +dn2id_delete( + Backend *be, + const char *dn, + ID id +) +{ + DBCache *db; + Datum key; + int rc; + + Debug( LDAP_DEBUG_TRACE, "=> dn2id_delete( \"%s\", %ld )\n", dn, id, 0 ); + + assert( id != NOID ); + + if ( (db = ldbm_cache_open( be, "dn2id", LDBM_SUFFIX, LDBM_WRCREAT )) + == NULL ) { + Debug( LDAP_DEBUG_ANY, + "<= dn2id_delete could not open dn2id%s\n", LDBM_SUFFIX, + 0, 0 ); + return( -1 ); + } + + + { + char *pdn = dn_parent( NULL, dn ); + + if( pdn != NULL ) { + ldbm_datum_init( key ); + key.dsize = strlen( pdn ) + 2; + key.dptr = ch_malloc( key.dsize ); + sprintf( key.dptr, "%c%s", DN_ONE_PREFIX, pdn ); + + (void) idl_delete_key( be, db, key, id ); + + free( key.dptr ); + free( pdn ); + } + } + + { + char **subtree = dn_subtree( NULL, dn ); + + if( subtree != NULL ) { + int i; + for( i=0; subtree[i] != NULL; i++ ) { + ldbm_datum_init( key ); + key.dsize = strlen( subtree[i] ) + 2; + key.dptr = ch_malloc( key.dsize ); + sprintf( key.dptr, "%c%s", + DN_SUBTREE_PREFIX, subtree[i] ); + + (void) idl_delete_key( be, db, key, id ); + + free( key.dptr ); + } + + charray_free( subtree ); + } + } + + ldbm_datum_init( key ); + + key.dsize = strlen( dn ) + 2; + key.dptr = ch_malloc( key.dsize ); + sprintf( key.dptr, "%c%s", DN_BASE_PREFIX, dn ); + + rc = ldbm_cache_delete( db, key ); + + free( key.dptr ); + + ldbm_cache_close( be, db ); + + Debug( LDAP_DEBUG_TRACE, "<= dn2id_delete %d\n", rc, 0, 0 ); + return( rc ); +} + +/* + * dn2entry - look up dn in the cache/indexes and return the corresponding + * entry. + */ + +Entry * +dn2entry_rw( + Backend *be, + const char *dn, + Entry **matched, + int rw +) +{ + ID id; + Entry *e = NULL; + char *pdn; + + Debug(LDAP_DEBUG_TRACE, "dn2entry_%s: dn: \"%s\"\n", + rw ? "w" : "r", dn, 0); + + if( matched != NULL ) { + /* caller cares about match */ + *matched = NULL; + } + + if ( (id = dn2id( be, dn )) != NOID && + (e = id2entry_rw( be, id, rw )) != NULL ) + { + return( e ); + } + + if ( id != NOID ) { + Debug(LDAP_DEBUG_ANY, + "dn2entry_%s: no entry for valid id (%ld), dn \"%s\"\n", + rw ? "w" : "r", id, dn); + /* must have been deleted from underneath us */ + /* treat as if NOID was found */ + } + + /* caller doesn't care about match */ + if( matched == NULL ) return NULL; + + /* entry does not exist - see how much of the dn does exist */ + /* dn_parent checks returns NULL if dn is suffix */ + if ( (pdn = dn_parent( be, dn )) != NULL ) { + /* get entry with reader lock */ + if ( (e = dn2entry_r( be, pdn, matched )) != NULL ) { + *matched = e; + } + free( pdn ); + } + + return NULL; +} + +#endif \ No newline at end of file diff --git a/servers/slapd/back-bdb/idl.c b/servers/slapd/back-bdb/idl.c new file mode 100644 index 0000000000..a105f29255 --- /dev/null +++ b/servers/slapd/back-bdb/idl.c @@ -0,0 +1,117 @@ +/* idl.c - ldap id list handling routines */ +/* $OpenLDAP$ */ +/* + * Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved. + * COPYING RESTRICTIONS APPLY, see COPYRIGHT file + */ + +#include "portable.h" + +#include + +#include +#include + +#include "back-bdb.h" + +#define BDB_IDL_SIZE (1<<16) +#define BDB_IDL_MAX (BDB_IDL_SIZE-16) +#define BDB_IDL_ALLOC (BDB_IDL_MAX * sizeof(ID)) + +#define BDB_IS_ALLIDS(ids) ((ids)[0] == NOID) + +static int idl_search( ID *ids, ID id ) +{ + /* we should replace this a binary search as ids is sorted */ + int i; + int n = (int) ids[0]; + + for( i = 1; i <= n; i++ ) { + if( id <= ids[i] ) { + return i; + } + } + + return 0; +} + +static int idl_insert( ID *ids, ID id ) +{ + int x = idl_search( ids, id ); + + if( ids[x] == id ) { + /* duplicate */ + return -1; + } + + if( x == 0 ) { + /* append the id */ + ids[0]++; + ids[ids[0]] = id; + + } else if ( ids[0]+1 >= BDB_IDL_MAX ) { + ids[0] = NOID; + + } else { + /* insert id */ + AC_MEMCPY( &ids[x+1], &ids[x], (1+ids[0]-x) * sizeof(ID) ); + ids[0]++; + ids[x] = id; + } + + return 0; +} + +int +bdb_idl_insert_key( + BackendDB *be, + DB *db, + DB_TXN *tid, + DBT *key, + ID id ) +{ + int rc; + ID ids[BDB_IDL_SIZE]; + DBT data; + + assert( id != NOID ); + + data.data = ids; + data.ulen = sizeof( ids ); + data.flags = DB_DBT_USERMEM; + + /* fetch the key and grab a write lock */ + rc = db->get( db, tid, key, &data, DB_RMW ); + + if( rc == DB_NOTFOUND ) { + ids[0] = 1; + ids[1] = id; + data.size = 2 * sizeof( ID ); + + } else if ( rc != 0 ) { + return rc; + + } else if ( data.size == 0 || data.size % sizeof( ID ) ) { + /* size not multiple of ID size */ + return -1; + + } else if ( BDB_IS_ALLIDS(ids) ) { + return 0; + + } else if ( data.size != (1 + ids[0]) * sizeof( ID ) ) { + /* size mismatch */ + return -1; + + } else { + rc = idl_insert( ids, id ); + + if( rc != 0 ) return rc; + + data.size = (ids[0]+1) * sizeof( ID ); + } + + /* store the key */ + rc = db->put( db, tid, key, &data, 0 ); + + return rc; +} diff --git a/servers/slapd/back-bdb/init.c b/servers/slapd/back-bdb/init.c index 0fbc7b882f..ea4021aef5 100644 --- a/servers/slapd/back-bdb/init.c +++ b/servers/slapd/back-bdb/init.c @@ -14,6 +14,10 @@ #include "back-bdb.h" +static char *bdbi_dbnames[BDB_INDICES] = { + "nextid", "id2entry", "dn2entry" +}; + static int bi_back_destroy( BackendInfo *bi ) { @@ -54,7 +58,7 @@ bi_back_db_init( Backend *be ) static int bi_back_db_open( BackendDB *be ) { - int rc; + int rc, i; struct bdb_info *bdb = (struct bdb_info *) be->be_private; u_int32_t flags; /* we should check existance of dbenv_home and db_directory */ @@ -121,18 +125,59 @@ bi_back_db_open( BackendDB *be ) bdb->bi_dbenv_mode ); if( rc != 0 ) { Debug( LDAP_DEBUG_ANY, - "bi_back_db_open: db_open(%s) failed: %s (%d)\n", + "bi_back_db_open: dbenv_open(%s) failed: %s (%d)\n", bdb->bi_dbenv_home, db_strerror(rc), rc ); return rc; } - /* we now need to open (and create) all database */ + flags = DB_THREAD; + +#if 0 + if( be->be_read_only ) { + flags |= DB_RDONLY; + } else +#endif + { + flags |= DB_CREATE; + } + + /* open (and create) main database */ + for( i = 0; i < BDB_INDICES; i++ ) { + struct bdb_db_info *db; + + db = (struct bdb_db_info *) ch_calloc(1, sizeof(struct bdb_db_info)); + + rc = db_create( &db->bdi_db, bdb->bi_dbenv, 0 ); + if( rc != 0 ) { + Debug( LDAP_DEBUG_ANY, + "bi_back_db_open: db_create(%s) failed: %s (%d)\n", + bdb->bi_dbenv_home, db_strerror(rc), rc ); + return rc; + } + + rc = db->bdi_db->open( db->bdi_db, + bdbi_dbnames[i], + bdbi_dbnames[i], + DB_BTREE, + flags, + bdb->bi_dbenv_mode ); + + if( rc != 0 ) { + Debug( LDAP_DEBUG_ANY, + "bi_back_db_open: db_open(%s) failed: %s (%d)\n", + bdb->bi_dbenv_home, db_strerror(rc), rc ); + return rc; + } + } + + /* open (and create) index databases */ + return 0; } static int -bi_back_db_destroy( BackendDB *be ) +bi_back_db_close( BackendDB *be ) { int rc; struct bdb_info *bdb = (struct bdb_info *) be->be_private; @@ -146,6 +191,20 @@ bi_back_db_destroy( BackendDB *be ) return rc; } + while( bdb->bi_ndatabases-- ) { + rc = bdb->bi_databases[bdb->bi_ndatabases]->bdi_db->close( + bdb->bi_databases[bdb->bi_ndatabases]->bdi_db, 0 ); + } + + return 0; +} + +static int +bi_back_db_destroy( BackendDB *be ) +{ + int rc; + struct bdb_info *bdb = (struct bdb_info *) be->be_private; + /* close db environment */ rc = bdb->bi_dbenv->close( bdb->bi_dbenv, 0 ); bdb->bi_dbenv = NULL; @@ -207,13 +266,13 @@ bdb_back_initialize( bi->bi_config = 0; bi->bi_destroy = bi_back_destroy; -#if 0 bi->bi_db_init = bi_back_db_init; - bi->bi_db_config = bi_back_db_config; + bi->bi_db_config = 0; bi->bi_db_open = bi_back_db_open; bi->bi_db_close = bi_back_db_close; bi->bi_db_destroy = bi_back_db_destroy; +#if 0 bi->bi_op_bind = bi_back_bind; bi->bi_op_unbind = bi_back_unbind; bi->bi_op_search = bi_back_search; @@ -230,22 +289,22 @@ bdb_back_initialize( bi->bi_acl_group = bi_back_group; bi->bi_acl_attribute = bi_back_attribute; bi->bi_chk_referrals = bi_back_referrals; +#endif /* * hooks for slap tools */ - bi->bi_tool_entry_open = bi_tool_entry_open; - bi->bi_tool_entry_close = bi_tool_entry_close; - bi->bi_tool_entry_first = bi_tool_entry_first; - bi->bi_tool_entry_next = bi_tool_entry_next; - bi->bi_tool_entry_get = bi_tool_entry_get; - bi->bi_tool_entry_put = bi_tool_entry_put; - bi->bi_tool_entry_reindex = bi_tool_entry_reindex; - bi->bi_tool_sync = bi_tool_sync; + bi->bi_tool_entry_open = bdb_tool_entry_open; + bi->bi_tool_entry_close = bdb_tool_entry_close; + bi->bi_tool_entry_first = bdb_tool_entry_next; + bi->bi_tool_entry_next = bdb_tool_entry_next; + bi->bi_tool_entry_get = bdb_tool_entry_get; + bi->bi_tool_entry_put = bdb_tool_entry_put; + bi->bi_tool_entry_reindex = 0; + bi->bi_tool_sync = 0; bi->bi_connection_init = 0; bi->bi_connection_destroy = 0; -#endif return 0; } diff --git a/servers/slapd/back-bdb/proto-bdb.h b/servers/slapd/back-bdb/proto-bdb.h index 1cad0d6cc6..5ab0c07f68 100644 --- a/servers/slapd/back-bdb/proto-bdb.h +++ b/servers/slapd/back-bdb/proto-bdb.h @@ -15,7 +15,7 @@ LDAP_BEGIN_DECL void bdb_errcall( const char *pfx, char * msg ); /* - * dn.c + * dn2id.c */ int bdb_index_dn_add( BackendDB *be, @@ -23,11 +23,31 @@ int bdb_index_dn_add( const char *dn, ID id ); +/* + * idl.c + */ +int bdb_idl_insert_key( + BackendDB *be, + DB *db, + DB_TXN *txn, + DBT *key, + ID id ); + /* * nextid.c */ int bdb_next_id( BackendDB *be, DB_TXN *tid, ID *id ); +/* + * tools.c + */ +int bdb_tool_entry_open( BackendDB *be, int mode ); +int bdb_tool_entry_close( BackendDB *be ); +ID bdb_tool_entry_next( BackendDB *be ); +Entry* bdb_tool_entry_get( BackendDB *be, ID id ); +ID bdb_tool_entry_put( BackendDB *be, Entry *e ); + + LDAP_END_DECL #endif /* _PROTO_BDB_H */ -- 2.39.5