X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=servers%2Fslapd%2Fbackover.c;h=8ec4b6bc560d986f55da910bf946593e48a0ba80;hb=6556561626b32ab751e111add34f56e0c0bcf07b;hp=f332b335f206088f85ca6b024284e65fe08012a3;hpb=c2a07f49c577b0a8d4c3b57094361c4c2a20e6b4;p=openldap diff --git a/servers/slapd/backover.c b/servers/slapd/backover.c index f332b335f2..8ec4b6bc56 100644 --- a/servers/slapd/backover.c +++ b/servers/slapd/backover.c @@ -2,7 +2,7 @@ /* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * - * Copyright 2003-2011 The OpenLDAP Foundation. + * Copyright 2003-2014 The OpenLDAP Foundation. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -1076,14 +1076,22 @@ overlay_register_control( BackendDB *be, const char *oid ) gotit = 1; } - bd->be_ctrls[ cid ] = 1; + /* overlays can be instanciated multiple times, use + * be_ctrls[ cid ] as an instance counter, so that the + * overlay's controls are only really disabled after the + * last instance called overlay_register_control() */ + bd->be_ctrls[ cid ]++; bd->be_ctrls[ SLAP_MAX_CIDS ] = 1; } } if ( !gotit ) { - be->bd_self->be_ctrls[ cid ] = 1; + /* overlays can be instanciated multiple times, use + * be_ctrls[ cid ] as an instance counter, so that the + * overlay's controls are only really unregistered after the + * last instance called overlay_register_control() */ + be->bd_self->be_ctrls[ cid ]++; be->bd_self->be_ctrls[ SLAP_MAX_CIDS ] = 1; } @@ -1110,12 +1118,12 @@ overlay_unregister_control( BackendDB *be, const char *oid ) gotit = 1; } - bd->be_ctrls[ cid ] = 0; + bd->be_ctrls[ cid ]--; } } if ( !gotit ) { - be->bd_self->be_ctrls[ cid ] = 0; + be->bd_self->be_ctrls[ cid ]--; } } #endif /* SLAP_CONFIG_DELETE */ @@ -1142,38 +1150,75 @@ overlay_destroy_one( BackendDB *be, slap_overinst *on ) } #ifdef SLAP_CONFIG_DELETE +typedef struct ov_remove_ctx { + BackendDB *be; + slap_overinst *on; +} ov_remove_ctx; + +int +overlay_remove_cb( Operation *op, SlapReply *rs ) +{ + ov_remove_ctx *rm_ctx = (ov_remove_ctx*) op->o_callback->sc_private; + BackendInfo *bi_orig = rm_ctx->be->bd_info; + + rm_ctx->be->bd_info = (BackendInfo*) rm_ctx->on; + + if ( rm_ctx->on->on_bi.bi_db_close ) { + rm_ctx->on->on_bi.bi_db_close( rm_ctx->be, NULL ); + } + if ( rm_ctx->on->on_bi.bi_db_destroy ) { + rm_ctx->on->on_bi.bi_db_destroy( rm_ctx->be, NULL ); + } + + /* clean up after removing last overlay */ + if ( ! rm_ctx->on->on_info->oi_list ) { + /* reset db flags and bd_info to orig */ + SLAP_DBFLAGS( rm_ctx->be ) &= ~SLAP_DBFLAG_GLOBAL_OVERLAY; + rm_ctx->be->bd_info = rm_ctx->on->on_info->oi_orig; + ch_free(rm_ctx->on->on_info); + } else { + rm_ctx->be->bd_info = bi_orig; + } + free( rm_ctx->on ); + op->o_tmpfree(rm_ctx, op->o_tmpmemctx); + return SLAP_CB_CONTINUE; +} + void -overlay_remove( BackendDB *be, slap_overinst *on ) +overlay_remove( BackendDB *be, slap_overinst *on, Operation *op ) { slap_overinfo *oi = on->on_info; slap_overinst **oidx; - BackendInfo *bi_orig; + ov_remove_ctx *rm_ctx; + slap_callback *rm_cb, *cb; - /* remove overlay from oi_list an call db_close and db_destroy - * handlers */ + /* remove overlay from oi_list */ for ( oidx = &oi->oi_list; *oidx; oidx = &(*oidx)->on_next ) { if ( *oidx == on ) { *oidx = on->on_next; - bi_orig = be->bd_info; - be->bd_info = (BackendInfo *)on; - if ( on->on_bi.bi_db_close ) { - on->on_bi.bi_db_close( be, NULL ); - } - if ( on->on_bi.bi_db_destroy ) { - on->on_bi.bi_db_destroy( be, NULL ); - } - be->bd_info = bi_orig; - free( on ); break; } } - - /* clean up after removing last overlay */ - if ( ! oi->oi_list ) - { - /* reset db flags and bd_info to orig */ - be->bd_info = oi->oi_orig; - ch_free(oi); + + /* The db_close and db_destroy handlers to cleanup a release + * the overlay's resources are called from the cleanup callback + */ + rm_ctx = op->o_tmpalloc( sizeof( ov_remove_ctx ), op->o_tmpmemctx ); + rm_ctx->be = be; + rm_ctx->on = on; + + rm_cb = op->o_tmpalloc( sizeof( slap_callback ), op->o_tmpmemctx ); + rm_cb->sc_next = NULL; + rm_cb->sc_cleanup = overlay_remove_cb; + rm_cb->sc_response = NULL; + rm_cb->sc_private = (void*) rm_ctx; + + /* Append callback to the end of the list */ + if ( !op->o_callback ) { + op->o_callback = rm_cb; + } else { + for ( cb = op->o_callback; cb->sc_next; cb = cb->sc_next ); + cb->sc_next = rm_cb; } } #endif /* SLAP_CONFIG_DELETE */