1 #pragma ident "%Z%%M% %I% %E% SMI"
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
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
26 * Copyright (c) 1990 Regents of the University of Michigan.
27 * All rights reserved.
35 static char copyright
[] = "@(#) Copyright (c) 1990 Regents of the University of Michigan.\nAll rights reserved.\n";
41 static int do_abandon( LDAP
*ld
, int origid
, int msgid
,
42 LDAPControl
**serverctrls
, LDAPControl
**clientctrls
);
45 * ldap_abandon - perform an ldap abandon operation. Parameters:
48 * msgid The message id of the operation to abandon
50 * ldap_abandon returns 0 if everything went ok, -1 otherwise.
53 * ldap_abandon( ld, msgid );
57 ldap_abandon( LDAP
*ld
, int msgid
)
59 LDAPDebug( LDAP_DEBUG_TRACE
, "ldap_abandon %d\n", msgid
, 0, 0 );
61 if ( ldap_abandon_ext( ld
, msgid
, NULL
, NULL
) == LDAP_SUCCESS
) {
70 * LDAPv3 extended abandon.
71 * Returns an LDAP error code.
75 ldap_abandon_ext( LDAP
*ld
, int msgid
, LDAPControl
**serverctrls
,
76 LDAPControl
**clientctrls
)
80 LDAPDebug( LDAP_DEBUG_TRACE
, "ldap_abandon_ext %d\n", msgid
, 0, 0 );
82 if ( !NSLDAPI_VALID_LDAP_POINTER( ld
)) {
83 return( LDAP_PARAM_ERROR
);
86 LDAP_MUTEX_LOCK( ld
, LDAP_CONN_LOCK
);
87 LDAP_MUTEX_LOCK( ld
, LDAP_REQ_LOCK
);
88 rc
= do_abandon( ld
, msgid
, msgid
, serverctrls
, clientctrls
);
91 * XXXmcs should use cache function pointers to hook in memcache
93 ldap_memcache_abandon( ld
, msgid
);
95 LDAP_MUTEX_UNLOCK( ld
, LDAP_REQ_LOCK
);
96 LDAP_MUTEX_UNLOCK( ld
, LDAP_CONN_LOCK
);
103 * Abandon all outstanding requests for msgid (included child requests
104 * spawned when chasing referrals). This function calls itself recursively.
105 * No locking is done is this function so it must be done by the caller.
106 * Returns an LDAP error code and sets it in LDAP *ld as well
109 do_abandon( LDAP
*ld
, int origid
, int msgid
, LDAPControl
**serverctrls
,
110 LDAPControl
**clientctrls
)
113 int i
, bererr
, lderr
, sendabandon
;
115 LDAPRequest
*lr
= NULL
;
118 * An abandon request looks like this:
119 * AbandonRequest ::= MessageID
121 LDAPDebug( LDAP_DEBUG_TRACE
, "do_abandon origid %d, msgid %d\n",
125 lderr
= LDAP_SUCCESS
;
128 * this is not the best implementation...
129 * the code special cases the when async io is enabled.
130 * The logic is clear this way, at the cost of code bloat.
131 * This logic should be cleaned up post nova 4.5 rtm
133 if (ld
->ld_options
& LDAP_BITOPT_ASYNC
)
135 /* Don't send an abandon message unless there is something to abandon. */
138 /* Find the request that we are abandoning. */
139 if (ld
->ld_requests
!= NULL
) {
140 for ( lr
= ld
->ld_requests
; lr
!= NULL
; lr
= lr
->lr_next
) {
141 if ( lr
->lr_msgid
== msgid
) { /* this message */
142 if ( origid
== msgid
&& lr
->lr_parent
!= NULL
) {
143 /* don't let caller abandon child requests! */
144 lderr
= LDAP_PARAM_ERROR
;
145 goto set_errorcode_and_return
;
147 if ( lr
->lr_status
== LDAP_REQST_INPROGRESS
) {
148 /* We only need to send an abandon message if the request
155 if ( lr
->lr_origid
== msgid
) { /* child: abandon it */
156 (void)do_abandon( ld
, msgid
, lr
->lr_msgid
,
157 serverctrls
, clientctrls
);
158 /* we ignore errors from child abandons... */
166 /* find the request that we are abandoning */
167 for ( lr
= ld
->ld_requests
; lr
!= NULL
; lr
= lr
->lr_next
) {
168 if ( lr
->lr_msgid
== msgid
) { /* this message */
171 if ( lr
->lr_origid
== msgid
) { /* child: abandon it */
172 (void)do_abandon( ld
, msgid
, lr
->lr_msgid
,
173 serverctrls
, clientctrls
);
174 /* we ignore errors from child abandons... */
179 if ( origid
== msgid
&& lr
->lr_parent
!= NULL
) {
180 /* don't let caller abandon child requests! */
181 lderr
= LDAP_PARAM_ERROR
;
182 goto set_errorcode_and_return
;
184 if ( lr
->lr_status
!= LDAP_REQST_INPROGRESS
) {
185 /* no need to send abandon message */
190 if ( ldap_msgdelete( ld
, msgid
) == 0 ) {
191 /* we had all the results and deleted them */
192 goto set_errorcode_and_return
;
196 /* create a message to send */
197 if (( lderr
= nsldapi_alloc_ber_with_options( ld
, &ber
)) ==
199 LDAP_MUTEX_LOCK( ld
, LDAP_MSGID_LOCK
);
201 if ( ld
->ld_dbp
->sb_naddr
> 0 ) {
202 bererr
= ber_printf( ber
, "{isti",
203 ++ld
->ld_msgid
, ld
->ld_cldapdn
,
204 LDAP_REQ_ABANDON
, msgid
);
207 bererr
= ber_printf( ber
, "{iti",
208 ++ld
->ld_msgid
, LDAP_REQ_ABANDON
, msgid
);
212 LDAP_MUTEX_UNLOCK( ld
, LDAP_MSGID_LOCK
);
215 ( lderr
= nsldapi_put_controls( ld
, serverctrls
,
216 1, ber
)) != LDAP_SUCCESS
) {
217 lderr
= LDAP_ENCODING_ERROR
;
220 /* send the message */
222 sb
= lr
->lr_conn
->lconn_sb
;
226 if ( nsldapi_ber_flush( ld
, sb
, ber
, 1, 0 )
228 lderr
= LDAP_SERVER_DOWN
;
236 nsldapi_free_connection( ld
, lr
->lr_conn
, NULL
, NULL
,
239 if ( origid
== msgid
) {
240 nsldapi_free_request( ld
, lr
, 0 );
245 LDAP_MUTEX_LOCK( ld
, LDAP_ABANDON_LOCK
);
246 if ( ld
->ld_abandoned
== NULL
) {
247 if ( (ld
->ld_abandoned
= (int *)NSLDAPI_MALLOC( 2
248 * sizeof(int) )) == NULL
) {
249 lderr
= LDAP_NO_MEMORY
;
250 LDAP_MUTEX_UNLOCK( ld
, LDAP_ABANDON_LOCK
);
251 goto set_errorcode_and_return
;
255 for ( i
= 0; ld
->ld_abandoned
[i
] != -1; i
++ )
257 if ( (ld
->ld_abandoned
= (int *)NSLDAPI_REALLOC( (char *)
258 ld
->ld_abandoned
, (i
+ 2) * sizeof(int) )) == NULL
) {
259 lderr
= LDAP_NO_MEMORY
;
260 LDAP_MUTEX_UNLOCK( ld
, LDAP_ABANDON_LOCK
);
261 goto set_errorcode_and_return
;
264 ld
->ld_abandoned
[i
] = msgid
;
265 ld
->ld_abandoned
[i
+ 1] = -1;
266 LDAP_MUTEX_UNLOCK( ld
, LDAP_ABANDON_LOCK
);
268 set_errorcode_and_return
:
269 LDAP_SET_LDERRNO( ld
, lderr
, NULL
, NULL
);