1*549b59edSchristos /* $NetBSD: message_queue.c,v 1.2 2021/08/14 16:14:59 christos Exp $ */
2e670fd5cSchristos
3e670fd5cSchristos /* message_queue.c - routines to maintain the per-connection lists
4e670fd5cSchristos * of pending operations */
5e670fd5cSchristos /* $OpenLDAP$ */
6e670fd5cSchristos /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
7e670fd5cSchristos *
8e670fd5cSchristos * Copyright 2016-2021 The OpenLDAP Foundation.
9e670fd5cSchristos * Portions Copyright 2016 Symas Corporation.
10e670fd5cSchristos * All rights reserved.
11e670fd5cSchristos *
12e670fd5cSchristos * Redistribution and use in source and binary forms, with or without
13e670fd5cSchristos * modification, are permitted only as authorized by the OpenLDAP
14e670fd5cSchristos * Public License.
15e670fd5cSchristos *
16e670fd5cSchristos * A copy of this license is available in the file LICENSE in the
17e670fd5cSchristos * top-level directory of the distribution or, alternatively, at
18e670fd5cSchristos * <http://www.OpenLDAP.org/license.html>.
19e670fd5cSchristos */
20e670fd5cSchristos
21e670fd5cSchristos /* ACKNOWLEDGEMENTS:
22e670fd5cSchristos * This work was developed by Symas Corporation
23e670fd5cSchristos * based on back-meta module for inclusion in OpenLDAP Software.
24e670fd5cSchristos * This work was sponsored by Ericsson. */
25e670fd5cSchristos
26e670fd5cSchristos #include <sys/cdefs.h>
27*549b59edSchristos __RCSID("$NetBSD: message_queue.c,v 1.2 2021/08/14 16:14:59 christos Exp $");
28e670fd5cSchristos
29e670fd5cSchristos #include "portable.h"
30e670fd5cSchristos
31e670fd5cSchristos #include <stdio.h>
32e670fd5cSchristos
33e670fd5cSchristos #include <ac/socket.h>
34e670fd5cSchristos #include <ac/string.h>
35e670fd5cSchristos #include <ac/time.h>
36e670fd5cSchristos
37e670fd5cSchristos #include "lutil.h"
38e670fd5cSchristos #include "slap.h"
39e670fd5cSchristos #include "../back-ldap/back-ldap.h"
40e670fd5cSchristos #include "back-asyncmeta.h"
41e670fd5cSchristos #include "../../../libraries/liblber/lber-int.h"
42e670fd5cSchristos #include "lutil.h"
43e670fd5cSchristos
44e670fd5cSchristos
45e670fd5cSchristos typedef struct listptr {
46e670fd5cSchristos void *reserved;
47e670fd5cSchristos struct listptr *next;
48e670fd5cSchristos } listptr;
49e670fd5cSchristos
50e670fd5cSchristos typedef struct listhead {
51e670fd5cSchristos struct listptr *list;
52e670fd5cSchristos int cnt;
53e670fd5cSchristos } listhead;
54e670fd5cSchristos
55e670fd5cSchristos #ifndef LH_MAX
56e670fd5cSchristos #define LH_MAX 16
57e670fd5cSchristos #endif
58e670fd5cSchristos
asyncmeta_memctx_put(void * threadctx,void * memctx)59e670fd5cSchristos static void asyncmeta_memctx_put(void *threadctx, void *memctx)
60e670fd5cSchristos {
61e670fd5cSchristos slap_sl_mem_setctx(threadctx, NULL);
62e670fd5cSchristos slap_sl_mem_destroy((void *)1, memctx);
63e670fd5cSchristos }
64e670fd5cSchristos
asyncmeta_new_bm_context(Operation * op,SlapReply * rs,bm_context_t ** new_bc,int ntargets,a_metainfo_t * mi)65e670fd5cSchristos int asyncmeta_new_bm_context(Operation *op,
66e670fd5cSchristos SlapReply *rs,
67e670fd5cSchristos bm_context_t **new_bc,
68e670fd5cSchristos int ntargets,
69e670fd5cSchristos a_metainfo_t *mi)
70e670fd5cSchristos {
71e670fd5cSchristos int i;
72e670fd5cSchristos *new_bc = op->o_tmpcalloc( 1, sizeof( bm_context_t ), op->o_tmpmemctx );
73e670fd5cSchristos
74e670fd5cSchristos (*new_bc)->op = op;
75e670fd5cSchristos (*new_bc)->copy_op = *op;
76e670fd5cSchristos (*new_bc)->candidates = op->o_tmpcalloc(ntargets, sizeof(SlapReply),op->o_tmpmemctx);
77e670fd5cSchristos (*new_bc)->msgids = op->o_tmpcalloc(ntargets, sizeof(int),op->o_tmpmemctx);
78e670fd5cSchristos (*new_bc)->nretries = op->o_tmpcalloc(ntargets, sizeof(int),op->o_tmpmemctx);
79e670fd5cSchristos (*new_bc)->c_peer_name = op->o_conn->c_peer_name;
80e670fd5cSchristos (*new_bc)->is_root = be_isroot( op );
81e670fd5cSchristos
82e670fd5cSchristos switch(op->o_tag) {
83e670fd5cSchristos case LDAP_REQ_COMPARE:
84e670fd5cSchristos {
85e670fd5cSchristos AttributeAssertion *ava = op->o_tmpcalloc( 1, sizeof(AttributeAssertion), op->o_tmpmemctx );
86e670fd5cSchristos *ava = *op->orc_ava;
87e670fd5cSchristos op->orc_ava = ava;
88e670fd5cSchristos }
89e670fd5cSchristos break;
90e670fd5cSchristos case LDAP_REQ_MODRDN:
91e670fd5cSchristos if (op->orr_newSup != NULL) {
92e670fd5cSchristos struct berval *bv = op->o_tmpalloc( sizeof( struct berval ), op->o_tmpmemctx );
93e670fd5cSchristos *bv = *op->orr_newSup;
94e670fd5cSchristos op->orr_newSup = bv;
95e670fd5cSchristos }
96e670fd5cSchristos
97e670fd5cSchristos if (op->orr_nnewSup != NULL) {
98e670fd5cSchristos struct berval *bv = op->o_tmpalloc( sizeof( struct berval ), op->o_tmpmemctx );
99e670fd5cSchristos *bv = *op->orr_nnewSup;
100e670fd5cSchristos op->orr_nnewSup = bv;
101e670fd5cSchristos }
102e670fd5cSchristos break;
103e670fd5cSchristos default:
104e670fd5cSchristos break;
105e670fd5cSchristos }
106e670fd5cSchristos for (i = 0; i < ntargets; i++) {
107e670fd5cSchristos (*new_bc)->msgids[i] = META_MSGID_UNDEFINED;
108e670fd5cSchristos }
109e670fd5cSchristos for (i = 0; i < ntargets; i++) {
110e670fd5cSchristos (*new_bc)->nretries[i] = mi->mi_targets[i]->mt_nretries;
111e670fd5cSchristos }
112e670fd5cSchristos return LDAP_SUCCESS;
113e670fd5cSchristos }
114e670fd5cSchristos
asyncmeta_free_op(Operation * op)115e670fd5cSchristos void asyncmeta_free_op(Operation *op)
116e670fd5cSchristos {
117e670fd5cSchristos assert (op != NULL);
118e670fd5cSchristos switch (op->o_tag) {
119e670fd5cSchristos case LDAP_REQ_SEARCH:
120e670fd5cSchristos break;
121e670fd5cSchristos case LDAP_REQ_ADD:
122e670fd5cSchristos if ( op->ora_modlist != NULL ) {
123e670fd5cSchristos slap_mods_free(op->ora_modlist, 0 );
124e670fd5cSchristos }
125e670fd5cSchristos
126e670fd5cSchristos if ( op->ora_e != NULL ) {
127e670fd5cSchristos entry_free( op->ora_e );
128e670fd5cSchristos }
129e670fd5cSchristos
130e670fd5cSchristos break;
131e670fd5cSchristos case LDAP_REQ_MODIFY:
132e670fd5cSchristos if ( op->orm_modlist != NULL ) {
133e670fd5cSchristos slap_mods_free(op->orm_modlist, 1 );
134e670fd5cSchristos }
135e670fd5cSchristos break;
136e670fd5cSchristos case LDAP_REQ_MODRDN:
137e670fd5cSchristos if ( op->orr_modlist != NULL ) {
138e670fd5cSchristos slap_mods_free(op->orr_modlist, 1 );
139e670fd5cSchristos }
140e670fd5cSchristos break;
141e670fd5cSchristos case LDAP_REQ_COMPARE:
142e670fd5cSchristos break;
143e670fd5cSchristos case LDAP_REQ_DELETE:
144e670fd5cSchristos break;
145e670fd5cSchristos default:
146e670fd5cSchristos Debug( LDAP_DEBUG_TRACE, "==> asyncmeta_free_op : other message type" );
147e670fd5cSchristos }
148e670fd5cSchristos
149e670fd5cSchristos connection_op_finish( op );
150e670fd5cSchristos slap_op_free( op, op->o_threadctx );
151e670fd5cSchristos }
152e670fd5cSchristos
153e670fd5cSchristos
154e670fd5cSchristos
155e670fd5cSchristos
asyncmeta_clear_bm_context(bm_context_t * bc)156e670fd5cSchristos void asyncmeta_clear_bm_context(bm_context_t *bc)
157e670fd5cSchristos {
158e670fd5cSchristos
159e670fd5cSchristos Operation *op = bc->op;
160e670fd5cSchristos void *thrctx, *memctx;
161e670fd5cSchristos int i;
162e670fd5cSchristos
163e670fd5cSchristos if ( bc->bc_mc && bc->bc_mc->mc_info ) {
164e670fd5cSchristos for (i = 0; i < bc->bc_mc->mc_info->mi_ntargets; i++) {
165e670fd5cSchristos if (bc->candidates[ i ].sr_text != NULL) {
166e670fd5cSchristos ch_free( (char *)bc->candidates[ i ].sr_text );
167e670fd5cSchristos bc->candidates[ i ].sr_text = NULL;
168e670fd5cSchristos }
169e670fd5cSchristos }
170e670fd5cSchristos }
171e670fd5cSchristos
172e670fd5cSchristos if (op->o_conn->c_conn_idx == -1)
173e670fd5cSchristos return;
174e670fd5cSchristos memctx = op->o_tmpmemctx;
175e670fd5cSchristos thrctx = op->o_threadctx;
176e670fd5cSchristos while (op->o_bd == bc->copy_op.o_bd)
177e670fd5cSchristos ldap_pvt_thread_yield();
178e670fd5cSchristos asyncmeta_free_op(op);
179e670fd5cSchristos asyncmeta_memctx_put(thrctx, memctx);
180e670fd5cSchristos }
181e670fd5cSchristos
asyncmeta_add_message_queue(a_metaconn_t * mc,bm_context_t * bc)182e670fd5cSchristos int asyncmeta_add_message_queue(a_metaconn_t *mc, bm_context_t *bc)
183e670fd5cSchristos {
184e670fd5cSchristos a_metainfo_t *mi = mc->mc_info;
185e670fd5cSchristos int max_pending_ops = (mi->mi_max_pending_ops == 0) ? META_BACK_CFG_MAX_PENDING_OPS : mi->mi_max_pending_ops;
186e670fd5cSchristos
187e670fd5cSchristos Debug( LDAP_DEBUG_TRACE, "add_message_queue: mc %p, pending_ops %d, max_pending %d\n",
188e670fd5cSchristos mc, mc->pending_ops, max_pending_ops );
189e670fd5cSchristos
190e670fd5cSchristos assert(bc->bc_mc == NULL);
191e670fd5cSchristos if (mc->pending_ops >= max_pending_ops) {
192e670fd5cSchristos return LDAP_BUSY;
193e670fd5cSchristos }
194e670fd5cSchristos bc->bc_mc = mc;
195e670fd5cSchristos
196e670fd5cSchristos slap_sl_mem_setctx(bc->op->o_threadctx, NULL);
197e670fd5cSchristos LDAP_STAILQ_INSERT_TAIL( &mc->mc_om_list, bc, bc_next);
198e670fd5cSchristos mc->pending_ops++;
199e670fd5cSchristos return LDAP_SUCCESS;
200e670fd5cSchristos }
201e670fd5cSchristos
202e670fd5cSchristos
203e670fd5cSchristos void
asyncmeta_drop_bc(a_metaconn_t * mc,bm_context_t * bc)204e670fd5cSchristos asyncmeta_drop_bc(a_metaconn_t *mc, bm_context_t *bc)
205e670fd5cSchristos {
206e670fd5cSchristos bm_context_t *om;
207e670fd5cSchristos LDAP_STAILQ_FOREACH( om, &mc->mc_om_list, bc_next ) {
208e670fd5cSchristos if (om == bc) {
209e670fd5cSchristos LDAP_STAILQ_REMOVE(&mc->mc_om_list, om, bm_context_t, bc_next);
210e670fd5cSchristos mc->pending_ops--;
211e670fd5cSchristos break;
212e670fd5cSchristos }
213e670fd5cSchristos }
214e670fd5cSchristos assert(om == bc);
215e670fd5cSchristos assert(bc->bc_mc == mc);
216e670fd5cSchristos }
217e670fd5cSchristos
218e670fd5cSchristos
219e670fd5cSchristos bm_context_t *
asyncmeta_find_message(ber_int_t msgid,a_metaconn_t * mc,int candidate)220e670fd5cSchristos asyncmeta_find_message(ber_int_t msgid, a_metaconn_t *mc, int candidate)
221e670fd5cSchristos {
222e670fd5cSchristos bm_context_t *om;
223e670fd5cSchristos LDAP_STAILQ_FOREACH( om, &mc->mc_om_list, bc_next ) {
224e670fd5cSchristos if (om->candidates[candidate].sr_msgid == msgid && !om->bc_invalid) {
225e670fd5cSchristos break;
226e670fd5cSchristos }
227e670fd5cSchristos }
228e670fd5cSchristos return om;
229e670fd5cSchristos }
230e670fd5cSchristos
231e670fd5cSchristos bm_context_t *
asyncmeta_bc_in_queue(a_metaconn_t * mc,bm_context_t * bc)232e670fd5cSchristos asyncmeta_bc_in_queue(a_metaconn_t *mc, bm_context_t *bc)
233e670fd5cSchristos {
234e670fd5cSchristos bm_context_t *om;
235e670fd5cSchristos LDAP_STAILQ_FOREACH( om, &mc->mc_om_list, bc_next ) {
236e670fd5cSchristos if (om == bc) {
237e670fd5cSchristos return bc;
238e670fd5cSchristos }
239e670fd5cSchristos }
240e670fd5cSchristos return NULL;
241e670fd5cSchristos }
242