]> git.sur5r.net Git - openldap/blob - servers/slapd/back-asyncmeta/delete.c
Happy New Year
[openldap] / servers / slapd / back-asyncmeta / delete.c
1 /* delete.c - delete request handler for back-asyncmeta */
2 /* $OpenLDAP$ */
3 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
4  *
5  * Copyright 2016-2018 The OpenLDAP Foundation.
6  * Portions Copyright 2016 Symas Corporation.
7  * All rights reserved.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted only as authorized by the OpenLDAP
11  * Public License.
12  *
13  * A copy of this license is available in the file LICENSE in the
14  * top-level directory of the distribution or, alternatively, at
15  * <http://www.OpenLDAP.org/license.html>.
16  */
17
18 /* ACKNOWLEDGEMENTS:
19 + * This work was developed by Symas Corporation
20 + * based on back-meta module for inclusion in OpenLDAP Software.
21 + * This work was sponsored by Ericsson. */
22
23 #include "portable.h"
24
25 #include <stdio.h>
26
27 #include <ac/string.h>
28 #include <ac/socket.h>
29
30 #include "slap.h"
31 #include "../back-ldap/back-ldap.h"
32 #include "back-asyncmeta.h"
33 #include "../../../libraries/liblber/lber-int.h"
34 #include "../../../libraries/libldap/ldap-int.h"
35
36 meta_search_candidate_t
37 asyncmeta_back_delete_start(Operation *op,
38                             SlapReply *rs,
39                             a_metaconn_t *mc,
40                             bm_context_t *bc,
41                             int candidate)
42 {
43         a_metainfo_t    *mi = mc->mc_info;
44         a_metatarget_t  *mt = mi->mi_targets[ candidate ];
45         struct berval   mdn = BER_BVNULL;
46         a_dncookie      dc;
47         int rc = 0, nretries = 1;
48         LDAPControl     **ctrls = NULL;
49         meta_search_candidate_t retcode = META_SEARCH_CANDIDATE;
50         BerElement *ber = NULL;
51         a_metasingleconn_t      *msc = &mc->mc_conns[ candidate ];
52         SlapReply               *candidates = bc->candidates;
53         ber_int_t       msgid;
54
55         dc.target = mt;
56         dc.conn = op->o_conn;
57         dc.rs = rs;
58         dc.ctx = "deleteDN";
59
60         if ( asyncmeta_dn_massage( &dc, &op->o_req_dn, &mdn ) ) {
61                 rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
62                 retcode = META_SEARCH_ERR;
63                 goto doreturn;
64         }
65
66 retry:;
67         ctrls = op->o_ctrls;
68         if ( asyncmeta_controls_add( op, rs, mc, candidate, &ctrls ) != LDAP_SUCCESS )
69         {
70                 candidates[ candidate ].sr_msgid = META_MSGID_IGNORE;
71                 retcode = META_SEARCH_ERR;
72                 goto done;
73         }
74
75         ber = ldap_build_delete_req( msc->msc_ld, mdn.bv_val, ctrls, NULL, &msgid);
76         if (ber) {
77                 candidates[ candidate ].sr_msgid = msgid;
78                 rc = ldap_send_initial_request( msc->msc_ld, LDAP_REQ_DELETE,
79                                                 mdn.bv_val, ber, msgid );
80                 if (rc == msgid)
81                         rc = LDAP_SUCCESS;
82                 else
83                         rc = LDAP_SERVER_DOWN;
84
85                 switch ( rc ) {
86                 case LDAP_SUCCESS:
87                         retcode = META_SEARCH_CANDIDATE;
88                         asyncmeta_set_msc_time(msc);
89                         break;
90
91                 case LDAP_SERVER_DOWN:
92                         ldap_pvt_thread_mutex_lock( &mc->mc_om_mutex);
93                         asyncmeta_clear_one_msc(NULL, mc, candidate);
94                         ldap_pvt_thread_mutex_unlock( &mc->mc_om_mutex);
95                         if ( nretries && asyncmeta_retry( op, rs, &mc, candidate, LDAP_BACK_DONTSEND ) ) {
96                                 nretries = 0;
97                                 /* if the identity changed, there might be need to re-authz */
98                                 (void)mi->mi_ldap_extra->controls_free( op, rs, &ctrls );
99                                 goto retry;
100                         }
101
102                 default:
103                         candidates[ candidate ].sr_msgid = META_MSGID_IGNORE;
104                         retcode = META_SEARCH_ERR;
105                 }
106         }
107 done:
108         (void)mi->mi_ldap_extra->controls_free( op, rs, &ctrls );
109
110         if ( mdn.bv_val != op->o_req_dn.bv_val ) {
111                 free( mdn.bv_val );
112                 BER_BVZERO( &mdn );
113         }
114
115 doreturn:;
116         Debug( LDAP_DEBUG_TRACE, "%s <<< asyncmeta_back_delete_start[%p]=%d\n", op->o_log_prefix, msc, candidates[candidate].sr_msgid );
117         return retcode;
118 }
119
120 int
121 asyncmeta_back_delete( Operation *op, SlapReply *rs )
122 {
123         a_metainfo_t    *mi = ( a_metainfo_t * )op->o_bd->be_private;
124         a_metatarget_t  *mt;
125         a_metaconn_t    *mc;
126         int             rc, candidate = -1;
127         OperationBuffer opbuf;
128         bm_context_t *bc;
129         SlapReply *candidates;
130         slap_callback *cb = op->o_callback;
131
132         Debug(LDAP_DEBUG_ARGS, "==> asyncmeta_back_delete: %s\n",
133               op->o_req_dn.bv_val, 0, 0 );
134
135         asyncmeta_new_bm_context(op, rs, &bc, mi->mi_ntargets );
136         if (bc == NULL) {
137                 rs->sr_err = LDAP_OTHER;
138                 asyncmeta_sender_error(op, rs, cb);
139                 return rs->sr_err;
140         }
141
142         candidates = bc->candidates;
143         mc = asyncmeta_getconn( op, rs, candidates, &candidate, LDAP_BACK_DONTSEND, 0);
144         if ( !mc || rs->sr_err != LDAP_SUCCESS) {
145                 asyncmeta_sender_error(op, rs, cb);
146                 asyncmeta_clear_bm_context(bc);
147                 return rs->sr_err;
148         }
149
150         mt = mi->mi_targets[ candidate ];
151         bc->timeout = mt->mt_timeout[ SLAP_OP_DELETE ];
152         bc->retrying = LDAP_BACK_RETRYING;
153         bc->sendok = ( LDAP_BACK_SENDRESULT | bc->retrying );
154         bc->stoptime = op->o_time + bc->timeout;
155
156         ldap_pvt_thread_mutex_lock( &mc->mc_om_mutex);
157         rc = asyncmeta_add_message_queue(mc, bc);
158         ldap_pvt_thread_mutex_unlock( &mc->mc_om_mutex);
159
160         if (rc != LDAP_SUCCESS) {
161                 rs->sr_err = LDAP_BUSY;
162                 rs->sr_text = "Maximum pending ops limit exceeded";
163                 asyncmeta_clear_bm_context(bc);
164                 asyncmeta_sender_error(op, rs, cb);
165                 goto finish;
166         }
167
168         rc = asyncmeta_dobind_init_with_retry(op, rs, bc, mc, candidate);
169         switch (rc)
170         {
171         case META_SEARCH_CANDIDATE:
172                 /* target is already bound, just send the request */
173                 Debug( LDAP_DEBUG_TRACE, "%s asyncmeta_back_delete:  "
174                        "cnd=\"%ld\"\n", op->o_log_prefix, candidate , 0);
175
176                 rc = asyncmeta_back_delete_start( op, rs, mc, bc, candidate);
177                 if (rc == META_SEARCH_ERR) {
178                         ldap_pvt_thread_mutex_lock( &mc->mc_om_mutex);
179                         asyncmeta_drop_bc(mc, bc);
180                         ldap_pvt_thread_mutex_unlock( &mc->mc_om_mutex);
181                         asyncmeta_sender_error(op, rs, cb);
182                         asyncmeta_clear_bm_context(bc);
183                         goto finish;
184
185                 }
186                         break;
187         case META_SEARCH_NOT_CANDIDATE:
188                 Debug( LDAP_DEBUG_TRACE, "%s asyncmeta_back_delete: NOT_CANDIDATE "
189                        "cnd=\"%ld\"\n", op->o_log_prefix, candidate , 0);
190                 candidates[ candidate ].sr_msgid = META_MSGID_IGNORE;
191                 ldap_pvt_thread_mutex_lock( &mc->mc_om_mutex);
192                 asyncmeta_drop_bc(mc, bc);
193                 ldap_pvt_thread_mutex_unlock( &mc->mc_om_mutex);
194                 asyncmeta_sender_error(op, rs, cb);
195                 asyncmeta_clear_bm_context(bc);
196                 goto finish;
197
198         case META_SEARCH_NEED_BIND:
199         case META_SEARCH_CONNECTING:
200                 Debug( LDAP_DEBUG_TRACE, "%s asyncmeta_back_delete: NEED_BIND "
201                        "cnd=\"%ld\" %p\n", op->o_log_prefix, candidate , &mc->mc_conns[candidate]);
202                 rc = asyncmeta_dobind_init(op, rs, bc, mc, candidate);
203                 if (rc == META_SEARCH_ERR) {
204                         ldap_pvt_thread_mutex_lock( &mc->mc_om_mutex);
205                         asyncmeta_drop_bc(mc, bc);
206                         ldap_pvt_thread_mutex_unlock( &mc->mc_om_mutex);
207                         asyncmeta_sender_error(op, rs, cb);
208                         asyncmeta_clear_bm_context(bc);
209                         goto finish;
210                 }
211                 break;
212         case META_SEARCH_BINDING:
213                         Debug( LDAP_DEBUG_TRACE, "%s asyncmeta_back_delete: BINDING "
214                                "cnd=\"%ld\" %p\n", op->o_log_prefix, candidate , &mc->mc_conns[candidate]);
215                         /* Todo add the context to the message queue but do not send the request
216                            the receiver must send this when we are done binding */
217                         /* question - how would do receiver know to which targets??? */
218                         break;
219
220         case META_SEARCH_ERR:
221                         Debug( LDAP_DEBUG_TRACE, "%s asyncmeta_back_delete: ERR "
222                                "cnd=\"%ldd\"\n", op->o_log_prefix, candidate , 0);
223                         candidates[ candidate ].sr_msgid = META_MSGID_IGNORE;
224                         candidates[ candidate ].sr_type = REP_RESULT;
225                         ldap_pvt_thread_mutex_lock( &mc->mc_om_mutex);
226                         asyncmeta_drop_bc(mc, bc);
227                         ldap_pvt_thread_mutex_unlock( &mc->mc_om_mutex);
228                         asyncmeta_sender_error(op, rs, cb);
229                         asyncmeta_clear_bm_context(bc);
230                         goto finish;
231                 default:
232                         assert( 0 );
233                         break;
234                 }
235         ldap_pvt_thread_mutex_lock( &mc->mc_om_mutex);
236         asyncmeta_start_one_listener(mc, candidates, bc, candidate);
237         ldap_pvt_thread_mutex_unlock( &mc->mc_om_mutex);
238 finish:
239         return rs->sr_err;
240 }