1 /* message_queue.c - routines to maintain the per-connection lists
2 * of pending operations */
4 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
6 * Copyright 2016 The OpenLDAP Foundation.
7 * Portions Copyright 2016 Symas Corporation.
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted only as authorized by the OpenLDAP
14 * A copy of this license is available in the file LICENSE in the
15 * top-level directory of the distribution or, alternatively, at
16 * <http://www.OpenLDAP.org/license.html>.
20 * This work was developed by Symas Corporation
21 * based on back-meta module for inclusion in OpenLDAP Software.
22 * This work was sponsored by Ericsson. */
28 #include <ac/socket.h>
29 #include <ac/string.h>
34 #include "../back-ldap/back-ldap.h"
35 #include "back-asyncmeta.h"
36 #include "../../../libraries/liblber/lber-int.h"
40 LDAPControl **asyncmeta_copy_controls(Operation *op)
42 LDAPControl **new_controls = NULL;
44 LDAPControl *tmp_ctl = NULL;
48 if (op->o_ctrls == NULL) {
51 for (c = op->o_ctrls; *c != NULL; c++) {
55 new_controls = op->o_tmpalloc( sizeof(LDAPControl*)*length, op->o_tmpmemctx );
56 for (i = 0; i < length-1; i ++) {
57 new_controls[i] = op->o_tmpalloc( sizeof(LDAPControl), op->o_tmpmemctx );
58 if (op->o_ctrls[i]->ldctl_value.bv_len > 0) {
59 ber_dupbv_x( &new_controls[i]->ldctl_value, &op->o_ctrls[i]->ldctl_value, op->o_tmpmemctx);
61 if (op->o_ctrls[i]->ldctl_oid) {
62 new_controls[i]->ldctl_oid = ber_strdup_x(op->o_ctrls[i]->ldctl_oid, op->o_tmpmemctx);
64 new_controls[i]->ldctl_iscritical = op->o_ctrls[i]->ldctl_iscritical;
66 new_controls[length-1] = NULL;
71 void asyncmeta_free_op_controls(Operation *op)
74 for (c = op->o_ctrls; *c != NULL; c++) {
75 if ((*c)->ldctl_value.bv_len > 0) {
76 free((*c)->ldctl_value.bv_val);
78 if ((*c)->ldctl_oid) {
79 free((*c)->ldctl_oid);
88 Modifications* asyncmeta_copy_modlist(Operation *op, Modifications *modlist)
91 Modifications *new_mods = NULL;
92 for ( ml = modlist; ml != NULL; ml = ml->sml_next ) {
93 Modifications *mod = op->o_tmpalloc( sizeof( Modifications ), op->o_tmpmemctx );
95 if ( ml->sml_values ) {
96 ber_bvarray_dup_x( &mod->sml_values, ml->sml_values, op->o_tmpmemctx );
97 if ( ml->sml_nvalues ) {
98 ber_bvarray_dup_x( &mod->sml_nvalues, ml->sml_nvalues, op->o_tmpmemctx );
101 mod->sml_next = NULL;
102 if (new_mods == NULL) {
105 new_mods->sml_next = mod;
111 Operation *asyncmeta_copy_op(Operation *op)
115 char txtbuf[SLAP_TEXT_BUFLEN];
116 size_t textlen = sizeof txtbuf;
118 Operation *new_op = op->o_tmpcalloc( 1, sizeof(OperationBuffer), op->o_tmpmemctx );
120 new_op->o_hdr = &((OperationBuffer *) new_op)->ob_hdr;
121 *(new_op->o_hdr) = *(op->o_hdr);
122 new_op->o_controls = ((OperationBuffer *) new_op)->ob_controls;
123 new_op->o_callback = op->o_callback;
124 new_op->o_ber = NULL;
125 new_op->o_bd = op->o_bd->bd_self;
127 ber_dupbv_x( &new_op->o_req_dn, &op->o_req_dn, op->o_tmpmemctx );
128 ber_dupbv_x( &new_op->o_req_ndn, &op->o_req_ndn, op->o_tmpmemctx );
129 op->o_callback = NULL;
131 if (op->o_ndn.bv_len > 0) {
132 ber_dupbv_x( &new_op->o_ndn, &op->o_ndn, op->o_tmpmemctx );
134 if (op->o_dn.bv_len > 0) {
135 ber_dupbv_x( &new_op->o_dn, &op->o_dn, op->o_tmpmemctx );
138 new_op->o_ctrls = asyncmeta_copy_controls(op);
140 case LDAP_REQ_SEARCH:
142 AttributeName *at_names;
144 for (i=0; op->ors_attrs && !BER_BVISNULL( &op->ors_attrs[i].an_name ); i++);
146 at_names = op->o_tmpcalloc( i+1, sizeof( AttributeName ), op->o_tmpmemctx );
147 at_names[i].an_name.bv_len = 0;
149 for (i; i >= 0; i--) {
150 at_names[i] = op->ors_attrs[i];
151 ber_dupbv_x( &at_names[i].an_name, &op->ors_attrs[i].an_name, op->o_tmpmemctx );
156 ber_dupbv_x( &new_op->ors_filterstr, &op->ors_filterstr, op->o_tmpmemctx );
157 new_op->ors_filter = filter_dup( op->ors_filter, op->o_tmpmemctx );
158 new_op->ors_attrs = at_names;
163 slap_entry2mods(op->ora_e, &new_op->ora_modlist, &text, txtbuf, textlen);
166 ber_dupbv_x( &e->e_name, &op->o_req_dn, op->o_tmpmemctx );
167 ber_dupbv_x( &e->e_nname, &op->o_req_ndn, op->o_tmpmemctx );
168 rc = slap_mods2entry( new_op->ora_modlist, &new_op->ora_e, 1, 0, &text, txtbuf, textlen);
171 case LDAP_REQ_MODIFY:
173 new_op->orm_modlist = asyncmeta_copy_modlist(op, op->orm_modlist);
176 case LDAP_REQ_COMPARE:
177 new_op->orc_ava = (AttributeAssertion *)ch_calloc( 1, sizeof( AttributeAssertion ));
178 *new_op->orc_ava = *op->orc_ava;
179 if ( !BER_BVISNULL( &op->orc_ava->aa_value ) ) {
180 ber_dupbv_x( &new_op->orc_ava->aa_value, &op->orc_ava->aa_value, op->o_tmpmemctx);
183 case LDAP_REQ_MODRDN:
185 if (op->orr_newrdn.bv_len > 0) {
186 ber_dupbv_x( &new_op->orr_newrdn, &op->orr_newrdn, op->o_tmpmemctx );
188 if (op->orr_nnewrdn.bv_len > 0) {
189 ber_dupbv_x( &new_op->orr_nnewrdn, &op->orr_nnewrdn, op->o_tmpmemctx );
191 if (op->orr_newSup != NULL) {
192 new_op->orr_newSup = op->o_tmpalloc( sizeof( struct berval ), op->o_tmpmemctx );
193 new_op->orr_newSup->bv_len = 0;
194 if (op->orr_newSup->bv_len > 0) {
195 ber_dupbv_x( new_op->orr_newSup, op->orr_newSup, op->o_tmpmemctx );
199 if (op->orr_nnewSup != NULL) {
200 new_op->orr_nnewSup = op->o_tmpalloc( sizeof( struct berval ), op->o_tmpmemctx );
201 new_op->orr_nnewSup->bv_len = 0;
202 if (op->orr_nnewSup->bv_len > 0) {
203 ber_dupbv_x( new_op->orr_nnewSup, op->orr_nnewSup, op->o_tmpmemctx );
206 new_op->orr_modlist = asyncmeta_copy_modlist(op, op->orr_modlist);
208 case LDAP_REQ_DELETE:
216 typedef struct listptr {
218 struct listptr *next;
221 typedef struct listhead {
222 struct listptr *list;
226 static void *asyncmeta_memctx_destroy(void *key, void *data)
230 while (lp = lh->list) {
232 slap_sl_mem_destroy((void *)1, lp);
241 static void *asyncmeta_memctx_get(void *threadctx)
245 ldap_pvt_thread_pool_getkey(threadctx, asyncmeta_memctx_get, &lh, NULL);
247 lh = ch_malloc(sizeof(listhead));
250 ldap_pvt_thread_pool_setkey(threadctx, asyncmeta_memctx_get, lh, asyncmeta_memctx_destroy, NULL, NULL);
256 slap_sl_mem_setctx(threadctx, lp);
258 return slap_sl_mem_create(SLAP_SLAB_SIZE, SLAP_SLAB_STACK, threadctx, 1);
261 static void asyncmeta_memctx_put(void *threadctx, void *memctx)
264 ldap_pvt_thread_pool_getkey(threadctx, asyncmeta_memctx_get, &lh, NULL);
266 lh = ch_malloc(sizeof(listhead));
269 ldap_pvt_thread_pool_setkey(threadctx, asyncmeta_memctx_get, lh, asyncmeta_memctx_destroy, NULL, NULL);
271 if (lh->cnt < LH_MAX) {
272 listptr *lp = memctx;
277 slap_sl_mem_destroy((void *)1, memctx);
281 int asyncmeta_new_bm_context(Operation *op, SlapReply *rs, bm_context_t **new_bc, int ntargets)
283 void *oldctx = op->o_tmpmemctx;
285 /* prevent old memctx from being destroyed */
286 slap_sl_mem_setctx(op->o_threadctx, NULL);
287 /* create new memctx */
288 op->o_tmpmemctx = asyncmeta_memctx_get( op->o_threadctx );
289 *new_bc = op->o_tmpcalloc( 1, sizeof( bm_context_t ), op->o_tmpmemctx );
291 (*new_bc)->op = asyncmeta_copy_op(op);
292 (*new_bc)->candidates = op->o_tmpcalloc(ntargets, sizeof(SlapReply),op->o_tmpmemctx);
293 /* restore original memctx */
294 slap_sl_mem_setctx(op->o_threadctx, oldctx);
295 op->o_tmpmemctx = oldctx;
299 void asyncmeta_free_op(Operation *op)
303 case LDAP_REQ_SEARCH:
304 if (op->ors_filterstr.bv_len != 0) {
305 free(op->ors_filterstr.bv_val);
307 if (op->ors_filter) {
308 filter_free(op->ors_filter);
315 if ( op->ora_modlist != NULL ) {
316 slap_mods_free(op->ora_modlist, 0 );
319 if ( op->ora_e != NULL ) {
320 entry_free( op->ora_e );
324 case LDAP_REQ_MODIFY:
325 if ( op->orm_modlist != NULL ) {
326 slap_mods_free(op->orm_modlist, 1 );
329 case LDAP_REQ_MODRDN:
330 if (op->orr_newrdn.bv_len > 0) {
331 free(op->orr_newrdn.bv_val);
333 if (op->orr_nnewrdn.bv_len > 0) {
334 free(op->orr_nnewrdn.bv_val);
337 if (op->orr_nnewSup != NULL ) {
338 if (op->orr_nnewSup->bv_len > 0) {
339 free(op->orr_nnewSup->bv_val);
341 free (op->orr_nnewSup);
344 if (op->orr_newSup != NULL ) {
345 if (op->orr_newSup->bv_len > 0) {
346 free(op->orr_newSup->bv_val);
348 free (op->orr_newSup);
351 if ( op->orr_modlist != NULL ) {
352 slap_mods_free(op->orr_modlist, 1 );
355 case LDAP_REQ_COMPARE:
356 if ( !BER_BVISNULL( &op->orc_ava->aa_value ) ) {
357 free(op->orc_ava->aa_value.bv_val);
361 case LDAP_REQ_DELETE:
364 Debug( LDAP_DEBUG_TRACE, "==> asyncmeta_free_op : other message type",
368 if (op->o_ctrls != NULL) {
369 asyncmeta_free_op_controls(op);
371 if (op->o_ndn.bv_len > 0) {
372 free(op->o_ndn.bv_val);
374 if (op->o_dn.bv_len > 0) {
375 free( op->o_dn.bv_val );
377 if (op->o_req_dn.bv_len > 0) {
378 free(op->o_req_dn.bv_val);
380 if (op->o_req_dn.bv_len > 0) {
381 free(op->o_req_ndn.bv_val);
389 void asyncmeta_clear_bm_context(bm_context_t *bc)
392 Operation *op = bc->op;
399 } else if (bmc->cl == NULL) {
406 case LDAP_REQ_SEARCH:
409 if ( (bmc->mdn.bv_len != 0) &&
410 (bmc->mdn.bv_val != op->o_req_dn.bv_val) ) {
411 free( bmc->mdn.bv_val );
414 if (bmc->data.add_d.attrs != NULL ) {
415 while (bmc->data.add_d.attrs[i] != NULL) {
416 free( bmc->data.add_d.attrs[i]->mod_bvalues );
417 free( bmc->data.add_d.attrs[i] );
420 free( bmc->data.add_d.attrs );
423 case LDAP_REQ_MODIFY:
424 if ( bmc->mdn.bv_val != op->o_req_dn.bv_val ) {
425 free( bmc->mdn.bv_val );
427 if ( bmc->data.mod_d.modv != NULL ) {
428 for ( i = 0; bmc->data.mod_d.modv[ i ]; i++ ) {
429 free( bmc->data.mod_d.modv[ i ]->mod_bvalues );
432 free( bmc->data.mod_d.mods );
433 free( bmc->data.mod_d.modv );
436 case LDAP_REQ_MODRDN:
437 if ( bmc->mdn.bv_val != op->o_req_dn.bv_val ) {
438 free( bmc->mdn.bv_val );
441 if ( bmc->data.modrdn_d.newSuperior.bv_len != 0 &&
442 bmc->data.modrdn_d.newSuperior.bv_val != op->orr_newSup->bv_val )
444 free( bmc->data.modrdn_d.newSuperior.bv_val );
448 if ( bmc->data.modrdn_d.newrdn.bv_len != 0 &&
449 bmc->data.modrdn_d.newrdn.bv_val != op->orr_newrdn.bv_val )
451 free( bmc->data.modrdn_d.newrdn.bv_val );
455 case LDAP_REQ_COMPARE:
456 if ( bmc->mdn.bv_val != op->o_req_dn.bv_val ) {
457 free( bmc->mdn.bv_val );
459 if ( op->orc_ava->aa_value.bv_val != bmc->data.comp_d.mapped_value.bv_val ) {
460 free( bmc->data.comp_d.mapped_value.bv_val );
463 case LDAP_REQ_DELETE:
464 if ( bmc->mdn.bv_val != op->o_req_dn.bv_val ) {
465 free( bmc->mdn.bv_val );
469 Debug( LDAP_DEBUG_TRACE, "==> asyncmeta_clear_bm_context: other message type",
472 if (bmc->dc != NULL) {
478 asyncmeta_free_candidate_list(cl, lock);
479 Debug( LDAP_DEBUG_TRACE, "==> asyncmeta_clear_bm_context: free_cl_list\n",
483 asyncmeta_memctx_put(op->o_threadctx, op->o_tmpmemctx);
487 int asyncmeta_add_message_queue(a_metaconn_t *mc, bm_context_t *bc)
489 a_metainfo_t *mi = mc->mc_info;
490 int max_pending_ops = (mi->mi_max_pending_ops == 0) ? META_BACK_CFG_MAX_PENDING_OPS : mi->mi_max_pending_ops;
492 Debug( LDAP_DEBUG_TRACE, "add_message_queue: mc %p, pending_ops %d, max_pending %d\n",
493 mc, mc->pending_ops, max_pending_ops );
495 if (mc->pending_ops >= max_pending_ops) {
499 LDAP_SLIST_INSERT_HEAD( &mc->mc_om_list, bc, bc_next);
505 asyncmeta_drop_bc(a_metaconn_t *mc, bm_context_t *bc)
508 LDAP_SLIST_FOREACH( om, &mc->mc_om_list, bc_next ) {
510 LDAP_SLIST_REMOVE(&mc->mc_om_list, om, bm_context_t, bc_next);
518 asyncmeta_find_message(ber_int_t msgid, a_metaconn_t *mc, int candidate)
521 LDAP_SLIST_FOREACH( om, &mc->mc_om_list, bc_next ) {
522 if (om->candidates[candidate].sr_msgid == msgid) {
532 asyncmeta_find_message_by_opmsguid (ber_int_t msgid, a_metaconn_t *mc, int remove)
535 LDAP_SLIST_FOREACH( om, &mc->mc_om_list, bc_next ) {
536 if (om->op->o_msgid == msgid) {
541 LDAP_SLIST_REMOVE(&mc->mc_om_list, om, bm_context_t, bc_next);