]> git.sur5r.net Git - openldap/blob - servers/slapd/back-asyncmeta/message_queue.c
Do not require ac/string.h for lber_pvt.h
[openldap] / servers / slapd / back-asyncmeta / message_queue.c
1 /* message_queue.c - routines to maintain the per-connection lists
2  * of pending operations */
3 /* $OpenLDAP$ */
4 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
5  *
6  * Copyright 2016-2018 The OpenLDAP Foundation.
7  * Portions Copyright 2016 Symas Corporation.
8  * All rights reserved.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted only as authorized by the OpenLDAP
12  * Public License.
13  *
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>.
17  */
18
19 /* ACKNOWLEDGEMENTS:
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. */
23
24 #include "portable.h"
25
26 #include <stdio.h>
27
28 #include <ac/socket.h>
29 #include <ac/string.h>
30 #include <ac/time.h>
31
32 #include "lutil.h"
33 #include "slap.h"
34 #include "../back-ldap/back-ldap.h"
35 #include "back-asyncmeta.h"
36 #include "../../../libraries/liblber/lber-int.h"
37 #include "lutil.h"
38
39
40 LDAPControl **asyncmeta_copy_controls(Operation *op)
41 {
42         LDAPControl **new_controls = NULL;
43         LDAPControl **c;
44         LDAPControl  *tmp_ctl = NULL;
45         int i, length = 1;
46
47
48         if (op->o_ctrls == NULL) {
49                 return NULL;
50         }
51         for (c = op->o_ctrls; *c != NULL; c++) {
52                 length++;
53         }
54
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);
60                 }
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);
63                 }
64                 new_controls[i]->ldctl_iscritical = op->o_ctrls[i]->ldctl_iscritical;
65         }
66         new_controls[length-1] = NULL;
67         return new_controls;
68 }
69
70 static
71 void asyncmeta_free_op_controls(Operation *op)
72 {
73         LDAPControl **c;
74         for (c = op->o_ctrls; *c != NULL; c++) {
75                 if ((*c)->ldctl_value.bv_len > 0) {
76                         free((*c)->ldctl_value.bv_val);
77                 }
78                 if ((*c)->ldctl_oid) {
79                         free((*c)->ldctl_oid);
80                 }
81                 free(*c);
82         }
83         free(op->o_ctrls);
84 }
85
86
87 static
88 Modifications* asyncmeta_copy_modlist(Operation *op, Modifications *modlist)
89 {
90         Modifications *ml;
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 );
94                 *mod = *ml;
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 );
99                                 }
100                         }
101                 mod->sml_next = NULL;
102                 if (new_mods == NULL) {
103                         new_mods = mod;
104                 } else {
105                         new_mods->sml_next = mod;
106                 }
107         }
108         return new_mods;
109 }
110
111 Operation *asyncmeta_copy_op(Operation *op)
112 {
113         const char      *text;
114         int rc;
115         char txtbuf[SLAP_TEXT_BUFLEN];
116         size_t textlen = sizeof txtbuf;
117         Entry *e;
118         Operation *new_op = op->o_tmpcalloc( 1, sizeof(OperationBuffer), op->o_tmpmemctx );
119         *new_op = *op;
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;
126
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;
130
131         if (op->o_ndn.bv_len > 0) {
132                 ber_dupbv_x( &new_op->o_ndn, &op->o_ndn, op->o_tmpmemctx );
133         }
134         if (op->o_dn.bv_len > 0) {
135                 ber_dupbv_x( &new_op->o_dn, &op->o_dn, op->o_tmpmemctx );
136         }
137
138         new_op->o_ctrls = asyncmeta_copy_controls(op);
139         switch (op->o_tag) {
140         case LDAP_REQ_SEARCH:
141         {
142                 AttributeName *at_names;
143                 int i;
144                 for (i=0; op->ors_attrs && !BER_BVISNULL( &op->ors_attrs[i].an_name ); i++);
145                 if (i > 0) {
146                         at_names = op->o_tmpcalloc( i+1, sizeof( AttributeName ), op->o_tmpmemctx );
147                         at_names[i].an_name.bv_len = 0;
148                         i--;
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 );
152                         }
153                 } else {
154                         at_names = NULL;
155                 }
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;
159         }
160         break;
161         case LDAP_REQ_ADD:
162         {
163                 slap_entry2mods(op->ora_e, &new_op->ora_modlist, &text, txtbuf, textlen);
164                 e = entry_alloc();
165                 new_op->ora_e = e;
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);
169         }
170         break;
171         case LDAP_REQ_MODIFY:
172         {
173                 new_op->orm_modlist = asyncmeta_copy_modlist(op, op->orm_modlist);
174         }
175         break;
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);
181                 }
182                 break;
183         case LDAP_REQ_MODRDN:
184
185                 if (op->orr_newrdn.bv_len > 0) {
186                         ber_dupbv_x( &new_op->orr_newrdn, &op->orr_newrdn, op->o_tmpmemctx );
187                 }
188                 if (op->orr_nnewrdn.bv_len > 0) {
189                         ber_dupbv_x( &new_op->orr_nnewrdn, &op->orr_nnewrdn, op->o_tmpmemctx );
190                 }
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 );
196                         }
197                 }
198
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 );
204                         }
205                 }
206                 new_op->orr_modlist = asyncmeta_copy_modlist(op, op->orr_modlist);
207                 break;
208         case LDAP_REQ_DELETE:
209         default:
210                 break;
211         }
212         return new_op;
213 }
214
215
216 typedef struct listptr {
217         void *reserved;
218         struct listptr *next;
219 } listptr;
220
221 typedef struct listhead {
222         struct listptr *list;
223         int cnt;
224 } listhead;
225
226 static void *asyncmeta_memctx_destroy(void *key, void *data)
227 {
228         listhead *lh = data;
229         listptr *lp;
230         while (lp = lh->list) {
231                 lh->list = lp->next;
232                 slap_sl_mem_destroy((void *)1, lp);
233         }
234         ch_free(lh);
235 }
236
237 #ifndef LH_MAX
238 #define LH_MAX  16
239 #endif
240
241 static void *asyncmeta_memctx_get(void *threadctx)
242 {
243         listhead *lh = NULL;
244         listptr *lp = NULL;
245         ldap_pvt_thread_pool_getkey(threadctx, asyncmeta_memctx_get, &lh, NULL);
246         if (!lh) {
247                 lh = ch_malloc(sizeof(listhead));
248                 lh->cnt = 0;
249                 lh->list = NULL;
250                 ldap_pvt_thread_pool_setkey(threadctx, asyncmeta_memctx_get, lh, asyncmeta_memctx_destroy, NULL, NULL);
251         }
252         if (lh->list) {
253                 lp = lh->list;
254                 lh->list = lp->next;
255                 lh->cnt--;
256                 slap_sl_mem_setctx(threadctx, lp);
257         }
258         return slap_sl_mem_create(SLAP_SLAB_SIZE, SLAP_SLAB_STACK, threadctx, 1);
259 }
260
261 static void asyncmeta_memctx_put(void *threadctx, void *memctx)
262 {
263         listhead *lh = NULL;
264         ldap_pvt_thread_pool_getkey(threadctx, asyncmeta_memctx_get, &lh, NULL);
265         if (!lh) {
266                 lh = ch_malloc(sizeof(listhead));
267                 lh->cnt = 0;
268                 lh->list = NULL;
269                 ldap_pvt_thread_pool_setkey(threadctx, asyncmeta_memctx_get, lh, asyncmeta_memctx_destroy, NULL, NULL);
270         }
271         if (lh->cnt < LH_MAX) {
272                 listptr *lp = memctx;
273                 lp->next = lh->list;
274                 lh->list = lp;
275                 lh->cnt++;
276         } else {
277                 slap_sl_mem_destroy((void *)1, memctx);
278         }
279 }
280
281 int asyncmeta_new_bm_context(Operation *op, SlapReply *rs, bm_context_t **new_bc, int ntargets)
282 {
283         void *oldctx = op->o_tmpmemctx;
284         int i;
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 );
290
291         (*new_bc)->op = asyncmeta_copy_op(op);
292         (*new_bc)->candidates = op->o_tmpcalloc(ntargets, sizeof(SlapReply),op->o_tmpmemctx);
293         (*new_bc)->msgids = op->o_tmpcalloc(ntargets, sizeof(int),op->o_tmpmemctx);
294         for (i = 0; i < ntargets; i++) {
295                 (*new_bc)->msgids[i] = META_MSGID_UNDEFINED;
296         }
297         /* restore original memctx */
298         slap_sl_mem_setctx(op->o_threadctx, oldctx);
299         op->o_tmpmemctx = oldctx;
300         return LDAP_SUCCESS;
301 }
302
303 void asyncmeta_free_op(Operation *op)
304 {
305         assert (op != NULL);
306         switch (op->o_tag) {
307         case LDAP_REQ_SEARCH:
308                 if (op->ors_filterstr.bv_len != 0) {
309                         free(op->ors_filterstr.bv_val);
310                 }
311                 if (op->ors_filter) {
312                         filter_free(op->ors_filter);
313                 }
314                 if (op->ors_attrs) {
315                         free(op->ors_attrs);
316                 }
317                 break;
318         case LDAP_REQ_ADD:
319                 if ( op->ora_modlist != NULL ) {
320                         slap_mods_free(op->ora_modlist, 0 );
321                 }
322
323                 if ( op->ora_e != NULL ) {
324                         entry_free( op->ora_e );
325                 }
326
327                 break;
328         case LDAP_REQ_MODIFY:
329                 if ( op->orm_modlist != NULL ) {
330                         slap_mods_free(op->orm_modlist, 1 );
331                 }
332                 break;
333         case LDAP_REQ_MODRDN:
334                 if (op->orr_newrdn.bv_len > 0) {
335                         free(op->orr_newrdn.bv_val);
336                 }
337                 if (op->orr_nnewrdn.bv_len > 0) {
338                         free(op->orr_nnewrdn.bv_val);
339                 }
340
341                 if (op->orr_nnewSup != NULL ) {
342                         if (op->orr_nnewSup->bv_len > 0) {
343                                 free(op->orr_nnewSup->bv_val);
344                         }
345                         free (op->orr_nnewSup);
346                 }
347
348                 if (op->orr_newSup != NULL ) {
349                         if (op->orr_newSup->bv_len > 0) {
350                                 free(op->orr_newSup->bv_val);
351                         }
352                         free (op->orr_newSup);
353                 }
354
355                 if ( op->orr_modlist != NULL ) {
356                         slap_mods_free(op->orr_modlist, 1 );
357                 }
358                 break;
359         case LDAP_REQ_COMPARE:
360                 if ( !BER_BVISNULL( &op->orc_ava->aa_value ) ) {
361                         free(op->orc_ava->aa_value.bv_val);
362                 }
363                 free(op->orc_ava);
364                 break;
365         case LDAP_REQ_DELETE:
366                 break;
367         default:
368                 Debug( LDAP_DEBUG_TRACE, "==> asyncmeta_free_op : other message type",
369                0, 0, 0 );
370         }
371
372         if (op->o_ctrls != NULL) {
373                 asyncmeta_free_op_controls(op);
374         }
375         if (op->o_ndn.bv_len > 0) {
376                 free(op->o_ndn.bv_val);
377         }
378         if (op->o_dn.bv_len > 0) {
379                 free( op->o_dn.bv_val );
380         }
381         if (op->o_req_dn.bv_len > 0) {
382                 free(op->o_req_dn.bv_val);
383         }
384         if (op->o_req_dn.bv_len > 0) {
385                 free(op->o_req_ndn.bv_val);
386         }
387         free(op);
388 }
389
390
391
392
393 void asyncmeta_clear_bm_context(bm_context_t *bc)
394 {
395
396         Operation *op = bc->op;
397 #if 0
398         bm_candidates_t  *cl;
399         a_metainfo_t    *mi;
400         int i = 0;
401         if (bmc == NULL) {
402                 return;
403         } else if (bmc->cl == NULL) {
404                 free(bmc);
405                 return;
406         }
407         cl = bmc->cl;
408         op = cl->op;
409         switch (op->o_tag) {
410         case LDAP_REQ_SEARCH:
411                 break;
412         case LDAP_REQ_ADD:
413                 if ( (bmc->mdn.bv_len != 0) &&
414                      (bmc->mdn.bv_val != op->o_req_dn.bv_val) ) {
415                         free( bmc->mdn.bv_val );
416                 }
417
418                 if (bmc->data.add_d.attrs != NULL )  {
419                         while (bmc->data.add_d.attrs[i] != NULL) {
420                                 free( bmc->data.add_d.attrs[i]->mod_bvalues );
421                                 free( bmc->data.add_d.attrs[i] );
422                                 i++;
423                         }
424                         free( bmc->data.add_d.attrs );
425                         }
426                 break;
427         case LDAP_REQ_MODIFY:
428                 if ( bmc->mdn.bv_val != op->o_req_dn.bv_val ) {
429                         free( bmc->mdn.bv_val );
430                 }
431                 if ( bmc->data.mod_d.modv != NULL ) {
432                         for ( i = 0; bmc->data.mod_d.modv[ i ]; i++ ) {
433                                 free( bmc->data.mod_d.modv[ i ]->mod_bvalues );
434                         }
435                 }
436                 free( bmc->data.mod_d.mods );
437                 free( bmc->data.mod_d.modv );
438
439                 break;
440         case LDAP_REQ_MODRDN:
441                 if ( bmc->mdn.bv_val != op->o_req_dn.bv_val ) {
442                         free( bmc->mdn.bv_val );
443                 }
444
445                 if ( bmc->data.modrdn_d.newSuperior.bv_len != 0 &&
446                      bmc->data.modrdn_d.newSuperior.bv_val != op->orr_newSup->bv_val )
447                 {
448                         free( bmc->data.modrdn_d.newSuperior.bv_val );
449
450                 }
451
452                 if ( bmc->data.modrdn_d.newrdn.bv_len != 0 &&
453                      bmc->data.modrdn_d.newrdn.bv_val != op->orr_newrdn.bv_val )
454                 {
455                         free( bmc->data.modrdn_d.newrdn.bv_val );
456
457                 }
458                 break;
459         case LDAP_REQ_COMPARE:
460                 if ( bmc->mdn.bv_val != op->o_req_dn.bv_val ) {
461                         free( bmc->mdn.bv_val );
462                 }
463                 if ( op->orc_ava->aa_value.bv_val != bmc->data.comp_d.mapped_value.bv_val ) {
464                         free( bmc->data.comp_d.mapped_value.bv_val );
465                         }
466                 break;
467         case LDAP_REQ_DELETE:
468                 if ( bmc->mdn.bv_val != op->o_req_dn.bv_val ) {
469                         free( bmc->mdn.bv_val );
470                 }
471                 break;
472         default:
473                 Debug( LDAP_DEBUG_TRACE, "==> asyncmeta_clear_bm_context: other message type",
474                0, 0, 0 );
475         }
476         if (bmc->dc != NULL) {
477                 free (bmc->dc);
478         }
479         free(bmc);
480
481         if (clear_cl > 0) {
482                 asyncmeta_free_candidate_list(cl, lock);
483                 Debug( LDAP_DEBUG_TRACE, "==> asyncmeta_clear_bm_context: free_cl_list\n",
484                0, 0, 0 );
485         }
486 #else
487         asyncmeta_memctx_put(op->o_threadctx, op->o_tmpmemctx);
488 #endif
489 }
490
491 int asyncmeta_add_message_queue(a_metaconn_t *mc, bm_context_t *bc)
492 {
493         a_metainfo_t *mi = mc->mc_info;
494         int max_pending_ops = (mi->mi_max_pending_ops == 0) ? META_BACK_CFG_MAX_PENDING_OPS : mi->mi_max_pending_ops;
495
496         Debug( LDAP_DEBUG_TRACE, "add_message_queue: mc %p, pending_ops %d, max_pending %d\n",
497                 mc, mc->pending_ops, max_pending_ops );
498
499         if (mc->pending_ops >= max_pending_ops) {
500                 return LDAP_BUSY;
501         }
502
503         LDAP_SLIST_INSERT_HEAD( &mc->mc_om_list, bc, bc_next);
504         mc->pending_ops++;
505         return LDAP_SUCCESS;
506 }
507
508 void
509 asyncmeta_drop_bc(a_metaconn_t *mc, bm_context_t *bc)
510 {
511         bm_context_t *om;
512         int i;
513         LDAP_SLIST_FOREACH( om, &mc->mc_om_list, bc_next ) {
514                 if (om == bc) {
515                         for (i = 0; i < mc->mc_info->mi_ntargets; i++)
516                         {
517                                 if (bc->msgids[i] >= 0) {
518                                         mc->mc_conns[i].msc_pending_ops--;
519                                 }
520                         }
521                         LDAP_SLIST_REMOVE(&mc->mc_om_list, om, bm_context_t, bc_next);
522                         mc->pending_ops--;
523                         break;
524                 }
525         }
526 }
527
528 bm_context_t *
529 asyncmeta_find_message(ber_int_t msgid, a_metaconn_t *mc, int candidate)
530 {
531         bm_context_t *om;
532         LDAP_SLIST_FOREACH( om, &mc->mc_om_list, bc_next ) {
533                 if (om->candidates[candidate].sr_msgid == msgid) {
534                         break;
535                 }
536         }
537         return om;
538 }
539
540
541
542 bm_context_t *
543 asyncmeta_find_message_by_opmsguid (ber_int_t msgid, a_metaconn_t *mc, int remove)
544 {
545         bm_context_t *om;
546         LDAP_SLIST_FOREACH( om, &mc->mc_om_list, bc_next ) {
547                 if (om->op->o_msgid == msgid) {
548                         break;
549                 }
550         }
551         if (remove && om) {
552                 LDAP_SLIST_REMOVE(&mc->mc_om_list, om, bm_context_t, bc_next);
553                 mc->pending_ops--;
554         }
555         return om;
556 }