dmake: do not set MAKEFLAGS=k
[unleashed/tickless.git] / usr / src / lib / libldap5 / sources / ldap / common / abandon.c
blobeeb3c0ac216713e4fffe83911f0db52da7efe681
1 #pragma ident "%Z%%M% %I% %E% SMI"
3 /*
4 * The contents of this file are subject to the Netscape Public
5 * License Version 1.1 (the "License"); you may not use this file
6 * except in compliance with the License. You may obtain a copy of
7 * the License at http://www.mozilla.org/NPL/
9 * Software distributed under the License is distributed on an "AS
10 * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
11 * implied. See the License for the specific language governing
12 * rights and limitations under the License.
14 * The Original Code is Mozilla Communicator client code, released
15 * March 31, 1998.
17 * The Initial Developer of the Original Code is Netscape
18 * Communications Corporation. Portions created by Netscape are
19 * Copyright (C) 1998-1999 Netscape Communications Corporation. All
20 * Rights Reserved.
22 * Contributor(s):
26 * Copyright (c) 1990 Regents of the University of Michigan.
27 * All rights reserved.
30 * abandon.c
33 #if 0
34 static char copyright[] = "@(#) Copyright (c) 1990 Regents of the University of Michigan.\nAll rights reserved.\n";
35 #endif
37 #include "ldap-int.h"
39 static int do_abandon( LDAP *ld, int origid, int msgid,
40 LDAPControl **serverctrls, LDAPControl **clientctrls );
43 * ldap_abandon - perform an ldap abandon operation. Parameters:
45 * ld LDAP descriptor
46 * msgid The message id of the operation to abandon
48 * ldap_abandon returns 0 if everything went ok, -1 otherwise.
50 * Example:
51 * ldap_abandon( ld, msgid );
53 int
54 LDAP_CALL
55 ldap_abandon( LDAP *ld, int msgid )
57 LDAPDebug( LDAP_DEBUG_TRACE, "ldap_abandon %d\n", msgid, 0, 0 );
59 if ( ldap_abandon_ext( ld, msgid, NULL, NULL ) == LDAP_SUCCESS ) {
60 return( 0 );
63 return( -1 );
68 * LDAPv3 extended abandon.
69 * Returns an LDAP error code.
71 int
72 LDAP_CALL
73 ldap_abandon_ext( LDAP *ld, int msgid, LDAPControl **serverctrls,
74 LDAPControl **clientctrls )
76 int rc;
78 LDAPDebug( LDAP_DEBUG_TRACE, "ldap_abandon_ext %d\n", msgid, 0, 0 );
80 if ( !NSLDAPI_VALID_LDAP_POINTER( ld )) {
81 return( LDAP_PARAM_ERROR );
84 LDAP_MUTEX_LOCK( ld, LDAP_CONN_LOCK );
85 LDAP_MUTEX_LOCK( ld, LDAP_REQ_LOCK );
86 rc = do_abandon( ld, msgid, msgid, serverctrls, clientctrls );
89 * XXXmcs should use cache function pointers to hook in memcache
91 ldap_memcache_abandon( ld, msgid );
93 LDAP_MUTEX_UNLOCK( ld, LDAP_REQ_LOCK );
94 LDAP_MUTEX_UNLOCK( ld, LDAP_CONN_LOCK );
96 return( rc );
101 * Abandon all outstanding requests for msgid (included child requests
102 * spawned when chasing referrals). This function calls itself recursively.
103 * No locking is done is this function so it must be done by the caller.
104 * Returns an LDAP error code and sets it in LDAP *ld as well
106 static int
107 do_abandon( LDAP *ld, int origid, int msgid, LDAPControl **serverctrls,
108 LDAPControl **clientctrls )
110 BerElement *ber;
111 int i, bererr, lderr, sendabandon;
112 Sockbuf *sb;
113 LDAPRequest *lr = NULL;
116 * An abandon request looks like this:
117 * AbandonRequest ::= MessageID
119 LDAPDebug( LDAP_DEBUG_TRACE, "do_abandon origid %d, msgid %d\n",
120 origid, msgid, 0 );
122 /* optimistic */
123 lderr = LDAP_SUCCESS;
126 * this is not the best implementation...
127 * the code special cases the when async io is enabled.
128 * The logic is clear this way, at the cost of code bloat.
129 * This logic should be cleaned up post nova 4.5 rtm
131 if (ld->ld_options & LDAP_BITOPT_ASYNC)
133 /* Don't send an abandon message unless there is something to abandon. */
134 sendabandon = 0;
136 /* Find the request that we are abandoning. */
137 if (ld->ld_requests != NULL) {
138 for ( lr = ld->ld_requests; lr != NULL; lr = lr->lr_next ) {
139 if ( lr->lr_msgid == msgid ) { /* this message */
140 if ( origid == msgid && lr->lr_parent != NULL ) {
141 /* don't let caller abandon child requests! */
142 lderr = LDAP_PARAM_ERROR;
143 goto set_errorcode_and_return;
145 if ( lr->lr_status == LDAP_REQST_INPROGRESS ) {
146 /* We only need to send an abandon message if the request
147 * is in progress.
149 sendabandon = 1;
151 break;
153 if ( lr->lr_origid == msgid ) { /* child: abandon it */
154 (void)do_abandon( ld, msgid, lr->lr_msgid,
155 serverctrls, clientctrls );
156 /* we ignore errors from child abandons... */
161 else
163 sendabandon = 1;
164 /* find the request that we are abandoning */
165 for ( lr = ld->ld_requests; lr != NULL; lr = lr->lr_next ) {
166 if ( lr->lr_msgid == msgid ) { /* this message */
167 break;
169 if ( lr->lr_origid == msgid ) { /* child: abandon it */
170 (void)do_abandon( ld, msgid, lr->lr_msgid,
171 serverctrls, clientctrls );
172 /* we ignore errors from child abandons... */
176 if ( lr != NULL ) {
177 if ( origid == msgid && lr->lr_parent != NULL ) {
178 /* don't let caller abandon child requests! */
179 lderr = LDAP_PARAM_ERROR;
180 goto set_errorcode_and_return;
182 if ( lr->lr_status != LDAP_REQST_INPROGRESS ) {
183 /* no need to send abandon message */
184 sendabandon = 0;
188 if ( ldap_msgdelete( ld, msgid ) == 0 ) {
189 /* we had all the results and deleted them */
190 goto set_errorcode_and_return;
193 if ( sendabandon ) {
194 /* create a message to send */
195 if (( lderr = nsldapi_alloc_ber_with_options( ld, &ber )) ==
196 LDAP_SUCCESS ) {
197 LDAP_MUTEX_LOCK( ld, LDAP_MSGID_LOCK );
198 #ifdef CLDAP
199 if ( ld->ld_dbp->sb_naddr > 0 ) {
200 bererr = ber_printf( ber, "{isti",
201 ++ld->ld_msgid, ld->ld_cldapdn,
202 LDAP_REQ_ABANDON, msgid );
203 } else {
204 #endif /* CLDAP */
205 bererr = ber_printf( ber, "{iti",
206 ++ld->ld_msgid, LDAP_REQ_ABANDON, msgid );
207 #ifdef CLDAP
209 #endif /* CLDAP */
210 LDAP_MUTEX_UNLOCK( ld, LDAP_MSGID_LOCK );
212 if ( bererr == -1 ||
213 ( lderr = nsldapi_put_controls( ld, serverctrls,
214 1, ber )) != LDAP_SUCCESS ) {
215 lderr = LDAP_ENCODING_ERROR;
216 ber_free( ber, 1 );
217 } else {
218 /* send the message */
219 if ( lr != NULL ) {
220 sb = lr->lr_conn->lconn_sb;
221 } else {
222 sb = ld->ld_sbp;
224 if ( nsldapi_ber_flush( ld, sb, ber, 1, 0 )
225 != 0 ) {
226 lderr = LDAP_SERVER_DOWN;
232 if ( lr != NULL ) {
233 if ( sendabandon ) {
234 nsldapi_free_connection( ld, lr->lr_conn, NULL, NULL,
235 0, 1 );
237 if ( origid == msgid ) {
238 nsldapi_free_request( ld, lr, 0 );
243 LDAP_MUTEX_LOCK( ld, LDAP_ABANDON_LOCK );
244 if ( ld->ld_abandoned == NULL ) {
245 if ( (ld->ld_abandoned = (int *)NSLDAPI_MALLOC( 2
246 * sizeof(int) )) == NULL ) {
247 lderr = LDAP_NO_MEMORY;
248 LDAP_MUTEX_UNLOCK( ld, LDAP_ABANDON_LOCK );
249 goto set_errorcode_and_return;
251 i = 0;
252 } else {
253 for ( i = 0; ld->ld_abandoned[i] != -1; i++ )
254 ; /* NULL */
255 if ( (ld->ld_abandoned = (int *)NSLDAPI_REALLOC( (char *)
256 ld->ld_abandoned, (i + 2) * sizeof(int) )) == NULL ) {
257 lderr = LDAP_NO_MEMORY;
258 LDAP_MUTEX_UNLOCK( ld, LDAP_ABANDON_LOCK );
259 goto set_errorcode_and_return;
262 ld->ld_abandoned[i] = msgid;
263 ld->ld_abandoned[i + 1] = -1;
264 LDAP_MUTEX_UNLOCK( ld, LDAP_ABANDON_LOCK );
266 set_errorcode_and_return:
267 LDAP_SET_LDERRNO( ld, lderr, NULL, NULL );
268 return( lderr );