From: Kurt Zeilenga Date: Thu, 12 Nov 1998 18:39:33 +0000 (+0000) Subject: remove an entry from its parent's children ID list when it's deleted. X-Git-Tag: OPENLDAP_SLAPD_BACK_LDAP~1129 X-Git-Url: https://git.sur5r.net/?a=commitdiff_plain;h=f1fde41ff87e0be6798f80b8f4f29ce859bcdc0e;p=openldap remove an entry from its parent's children ID list when it's deleted. Provided by "Gary D. Williams" --- diff --git a/servers/slapd/back-ldbm/delete.c b/servers/slapd/back-ldbm/delete.c index a7997e0f3f..412566d809 100644 --- a/servers/slapd/back-ldbm/delete.c +++ b/servers/slapd/back-ldbm/delete.c @@ -23,7 +23,8 @@ ldbm_back_delete( { struct ldbminfo *li = (struct ldbminfo *) be->be_private; char *matched = NULL; - Entry *e; + char *pdn = NULL; + Entry *e, *p; Debug(LDAP_DEBUG_ARGS, "==> ldbm_back_delete: %s\n", dn, 0, 0); @@ -66,6 +67,13 @@ ldbm_back_delete( e->e_rdwr.readers_reading, e->e_rdwr.writer_writing, 0); /* XXX delete from parent's id2children entry XXX */ + pdn = dn_parent( be, dn ); + matched = NULL; + p = dn2entry_r( be, pdn, &matched ); + if ( id2children_remove( be, p, e ) != 0 ) { + send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, "","" ); + goto error_return; + } /* delete from dn2id mapping */ if ( dn2id_delete( be, e->e_dn ) != 0 ) { @@ -96,5 +104,8 @@ error_return:; /* free entry and writer lock */ cache_return_entry_w( &li->li_cache, e ); + if( p ) + cache_return_entry_r( &li->li_cache, p ); + return( -1 ); } diff --git a/servers/slapd/back-ldbm/id2children.c b/servers/slapd/back-ldbm/id2children.c index 522e3d2733..7c555bfecb 100644 --- a/servers/slapd/back-ldbm/id2children.c +++ b/servers/slapd/back-ldbm/id2children.c @@ -61,6 +61,49 @@ id2children_add( return( 0 ); } + +int +id2children_remove( + Backend *be, + Entry *p, + Entry *e +) +{ + struct dbcache *db; + Datum key; + int len, rc; + IDList *idl; + char buf[20]; + + Debug( LDAP_DEBUG_TRACE, "=> id2children_remove( %d, %d )\n", p ? p->e_id + : 0, e->e_id, 0 ); + + if ( (db = ldbm_cache_open( be, "id2children", LDBM_SUFFIX, + LDBM_WRCREAT )) == NULL ) { + Debug( LDAP_DEBUG_ANY, + "<= id2children_add -1 could not open \"id2children%s\"\n", + LDBM_SUFFIX, 0, 0 ); + return( -1 ); + } + + memset( &key, 0, sizeof(key) ); + sprintf( buf, "%c%d", EQ_PREFIX, p ? p->e_id : 0 ); + key.dptr = buf; + key.dsize = strlen( buf ) + 1; + + if ( idl_delete_key( be, db, key, e->e_id ) != 0 ) { + Debug( LDAP_DEBUG_TRACE, "<= id2children_add -1 (idl_insert)\n", + 0, 0, 0 ); + ldbm_cache_close( be, db ); + return( -1 ); + } + + ldbm_cache_close( be, db ); + + Debug( LDAP_DEBUG_TRACE, "<= id2children_add 0\n", 0, 0, 0 ); + return( 0 ); +} + int has_children( Backend *be, diff --git a/servers/slapd/back-ldbm/idl.c b/servers/slapd/back-ldbm/idl.c index 7244c6ae39..d1e38aa197 100644 --- a/servers/slapd/back-ldbm/idl.c +++ b/servers/slapd/back-ldbm/idl.c @@ -618,6 +618,93 @@ idl_insert( IDList **idl, ID id, int maxids ) return( i == 0 ? 1 : 0 ); /* inserted - first id changed or not */ } +int +idl_delete_key ( + Backend *be, + struct dbcache *db, + Datum key, + ID id +) +{ + Datum k2; + IDList *idl, *tmp; + int i, j, nids; + char *kstr; + + if ( (idl = idl_fetch_one( be, db, key ) ) == NULL ) + { + /* It wasn't found. Hmm... */ + return -1; + } + + if ( ! INDIRECT_BLOCK( idl ) ) + { + for ( i=0; i < idl->b_nids; i++ ) + { + if ( idl->b_ids[i] == id ) + { + memcpy ( &idl->b_ids[i], &idl->b_ids[i+1], sizeof(ID)*(idl->b_nids-(i+1))); + idl->b_ids[idl->b_nids-1] = NOID; + idl->b_nids--; + if ( idl->b_nids ) + idl_store( be, db, key, idl ); + else + ldbm_cache_delete( db, key ); + return 0; + } + /* We didn't find the ID. Hmmm... */ + } + return -1; + } + + /* We have to go through an indirect block and find the ID + in the list of IDL's + */ + for ( nids = 0; idl->b_ids[nids] != NOID; nids++ ) + ; /* NULL */ + kstr = (char *) ch_malloc( key.dsize + 20 ); + for ( j = 0; idl->b_ids[j] != NOID; j++ ) + { + memset( &k2, 0, sizeof(k2) ); + sprintf( kstr, "%c%s%d", CONT_PREFIX, key.dptr, idl->b_ids[j] ); + k2.dptr = kstr; + k2.dsize = strlen( kstr ) + 1; + + if ( (tmp = idl_fetch_one( be, db, k2 )) == NULL ) { + Debug( LDAP_DEBUG_ANY, + "idl_fetch of (%s) returns NULL\n", k2.dptr, 0, 0 ); + continue; + } + /* + Now try to find the ID in tmp + */ + for ( i=0; i < tmp->b_nids; i++ ) + { + if ( tmp->b_ids[i] == id ) + { + memcpy ( &tmp->b_ids[i], &tmp->b_ids[i+1], sizeof(ID)*(tmp->b_nids-(i+1))); + tmp->b_ids[tmp->b_nids-1] = NOID; + tmp->b_nids--; + if ( tmp->b_nids ) + idl_store ( be, db, k2, tmp ); + else + { + ldbm_cache_delete( db, k2 ); + memcpy ( &idl->b_ids[j], &idl->b_ids[j+1], sizeof(ID)*(nids-(j+1))); + idl->b_ids[nids-1] = NOID; + nids--; + if ( ! nids ) + ldbm_cache_delete( db, key ); + else + idl_store( be, db, key, idl ); + } + return 0; + } + } + } + return -1; +} + static IDList * idl_dup( IDList *idl ) {