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.
34 static char copyright
[] = "@(#) Copyright (c) 1990 Regents of the University of Michigan.\nAll rights reserved.\n";
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:
46 * msgid The message id of the operation to abandon
48 * ldap_abandon returns 0 if everything went ok, -1 otherwise.
51 * ldap_abandon( ld, msgid );
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
) {
68 * LDAPv3 extended abandon.
69 * Returns an LDAP error code.
73 ldap_abandon_ext( LDAP
*ld
, int msgid
, LDAPControl
**serverctrls
,
74 LDAPControl
**clientctrls
)
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
);
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
107 do_abandon( LDAP
*ld
, int origid
, int msgid
, LDAPControl
**serverctrls
,
108 LDAPControl
**clientctrls
)
111 int i
, bererr
, lderr
, sendabandon
;
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",
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. */
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
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... */
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 */
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... */
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 */
188 if ( ldap_msgdelete( ld
, msgid
) == 0 ) {
189 /* we had all the results and deleted them */
190 goto set_errorcode_and_return
;
194 /* create a message to send */
195 if (( lderr
= nsldapi_alloc_ber_with_options( ld
, &ber
)) ==
197 LDAP_MUTEX_LOCK( ld
, LDAP_MSGID_LOCK
);
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
);
205 bererr
= ber_printf( ber
, "{iti",
206 ++ld
->ld_msgid
, LDAP_REQ_ABANDON
, msgid
);
210 LDAP_MUTEX_UNLOCK( ld
, LDAP_MSGID_LOCK
);
213 ( lderr
= nsldapi_put_controls( ld
, serverctrls
,
214 1, ber
)) != LDAP_SUCCESS
) {
215 lderr
= LDAP_ENCODING_ERROR
;
218 /* send the message */
220 sb
= lr
->lr_conn
->lconn_sb
;
224 if ( nsldapi_ber_flush( ld
, sb
, ber
, 1, 0 )
226 lderr
= LDAP_SERVER_DOWN
;
234 nsldapi_free_connection( ld
, lr
->lr_conn
, NULL
, NULL
,
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
;
253 for ( i
= 0; ld
->ld_abandoned
[i
] != -1; i
++ )
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
);