X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;ds=sidebyside;f=libraries%2Flibldap%2Fabandon.c;h=8f2fb3419499583f22babc83938cba956afc923e;hb=a5d0e36798978f9fdc9a15ab908fe0666dd5350f;hp=30742ea8258ae5fb495fde4457f20c768c2bed80;hpb=6416d83372aa272a72414cd985fab731cde556c7;p=openldap diff --git a/libraries/libldap/abandon.c b/libraries/libldap/abandon.c index 30742ea825..8f2fb34194 100644 --- a/libraries/libldap/abandon.c +++ b/libraries/libldap/abandon.c @@ -2,7 +2,7 @@ /* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * - * Copyright 1998-2006 The OpenLDAP Foundation. + * Copyright 1998-2008 The OpenLDAP Foundation. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -16,14 +16,6 @@ /* Portions Copyright (c) 1990 Regents of the University of Michigan. * All rights reserved. */ -/* Portions Copyright (C) The Internet Society (1997). - * ASN.1 fragments are from RFC 2251; see RFC for full legal notices. - */ - -/* - * An abandon request looks like this: - * AbandonRequest ::= MessageID - */ #include "portable.h" @@ -37,6 +29,13 @@ #include "ldap-int.h" +/* + * An abandon request looks like this: + * AbandonRequest ::= [APPLICATION 16] MessageID + * and has no response. (Source: RFC 4511) + */ +#include "lutil.h" + static int do_abandon( LDAP *ld, @@ -110,7 +109,7 @@ ldap_abandon( LDAP *ld, int msgid ) int -ldap_int_discard( +ldap_pvt_discard( LDAP *ld, ber_int_t msgid ) { @@ -139,22 +138,23 @@ do_abandon( { BerElement *ber; int i, err; - ber_int_t *old_abandon; Sockbuf *sb; LDAPRequest *lr; - Debug( LDAP_DEBUG_TRACE, "ldap_int_discard origid %d, msgid %d\n", + Debug( LDAP_DEBUG_TRACE, "do_abandon origid %d, msgid %d\n", origid, msgid, 0 ); /* find the request that we are abandoning */ start_again:; lr = ld->ld_requests; while ( lr != NULL ) { - if ( lr->lr_msgid == msgid ) { /* this message */ + /* this message */ + if ( lr->lr_msgid == msgid ) { break; } - if ( lr->lr_origid == msgid ) {/* child: abandon it */ + /* child: abandon it */ + if ( lr->lr_origid == msgid && !lr->lr_abandoned ) { (void)do_abandon( ld, lr->lr_origid, lr->lr_msgid, sctrls, sendabandon ); @@ -224,8 +224,9 @@ start_again:; i = ++(ld)->ld_msgid; #ifdef LDAP_CONNECTIONLESS if ( LDAP_IS_UDP(ld) ) { - err = ber_write( ber, ld->ld_options.ldo_peer, - sizeof(struct sockaddr), 0); + struct sockaddr sa = {0}; + /* dummy, filled with ldo_peer in request.c */ + err = ber_write( ber, &sa, sizeof(sa), 0 ); } if ( LDAP_IS_UDP(ld) && ld->ld_options.ldo_version == LDAP_VERSION2 ) @@ -295,6 +296,9 @@ start_again:; if ( origid == msgid ) { ldap_free_request( ld, lr ); + + } else { + lr->lr_abandoned = 1; } } @@ -307,76 +311,162 @@ start_again:; /* use bisection */ i = 0; - if ( ld->ld_abandoned != NULL ) { - int begin, - end; - - assert( ld->ld_nabandoned >= 0 ); + if ( ld->ld_nabandoned == 0 || + ldap_int_bisect_find( ld->ld_abandoned, ld->ld_nabandoned, msgid, &i ) == 0 ) + { + ldap_int_bisect_insert( &ld->ld_abandoned, &ld->ld_nabandoned, msgid, i ); + } - begin = 0; - end = ld->ld_nabandoned - 1; + if ( err != -1 ) { + ld->ld_errno = LDAP_SUCCESS; + } - if ( ld->ld_nabandoned == 0 || ld->ld_abandoned[ begin ] > msgid ) { - i = 0; +#ifdef LDAP_R_COMPILE + ldap_pvt_thread_mutex_unlock( &ld->ld_res_mutex ); + ldap_pvt_thread_mutex_lock( &ld->ld_req_mutex ); +#endif + return( ld->ld_errno ); +} - } else if ( ld->ld_abandoned[ end ] < msgid ) { - i = ld->ld_nabandoned; +/* + * ldap_int_bisect_find + * + * args: + * v: array of length n (in) + * n: length of array v (in) + * id: value to look for (in) + * idxp: pointer to location of value/insert point + * + * return: + * 0: not found + * 1: found + * -1: error + */ +int +ldap_int_bisect_find( ber_int_t *v, ber_len_t n, ber_int_t id, int *idxp ) +{ + int begin, + end, + rc = 0; - } else { - int pos, curid; + assert( n >= 0 ); + assert( id >= 0 ); - while ( end >= begin ) { - pos = (begin + end)/2; - curid = ld->ld_abandoned[ pos ]; + begin = 0; + end = n - 1; - if ( msgid < curid ) { - end = pos - 1; + if ( n <= 0 || id < v[ begin ] ) { + *idxp = 0; - } else if ( msgid > curid ) { - begin = pos + 1; + } else if ( id > v[ end ] ) { + *idxp = n; + } else { + int pos; + ber_int_t curid; + + do { + pos = (begin + end)/2; + curid = v[ pos ]; + + if ( id < curid ) { + end = pos - 1; + + } else if ( id > curid ) { + begin = ++pos; + } else { /* already abandoned? */ - i = -1; + rc = 1; break; } - } - - if ( i == 0 ) { - i = pos; - } + } while ( end >= begin ); + + *idxp = pos; } - } - if ( i != -1 ) { - int pos = i; + return rc; +} - old_abandon = ld->ld_abandoned; +/* + * ldap_int_bisect_insert + * + * args: + * vp: pointer to array of length *np (in/out) + * np: pointer to length of array *vp (in/out) + * id: value to insert (in) + * idx: location of insert point (as computed by ldap_int_bisect_find()) + * + * return: + * 0: inserted + * -1: error + */ +int +ldap_int_bisect_insert( ber_int_t **vp, ber_len_t *np, int id, int idx ) +{ + ber_int_t *v; + ber_len_t n; + int i; - ld->ld_abandoned = (ber_int_t *) LDAP_REALLOC( (char *)ld->ld_abandoned, - ( ld->ld_nabandoned + 1 ) * sizeof( ber_int_t ) ); + assert( vp != NULL ); + assert( np != NULL ); + assert( *np >= 0 ); + assert( idx >= 0 ); + assert( idx <= *np ); - if ( ld->ld_abandoned == NULL ) { - ld->ld_abandoned = old_abandon; - ld->ld_errno = LDAP_NO_MEMORY; - goto done; - } + n = *np; - for ( i = ld->ld_nabandoned; i > pos; i-- ) { - ld->ld_abandoned[ i ] = ld->ld_abandoned[ i - 1 ]; - } - ld->ld_abandoned[ pos ] = msgid; - ++ld->ld_nabandoned; + v = ber_memrealloc( *vp, sizeof( ber_int_t ) * ( n + 1 ) ); + if ( v == NULL ) { + return -1; } + *vp = v; - if ( err != -1 ) { - ld->ld_errno = LDAP_SUCCESS; + for ( i = n; i > idx; i-- ) { + v[ i ] = v[ i - 1 ]; } + v[ idx ] = id; + ++(*np); -done:; -#ifdef LDAP_R_COMPILE - ldap_pvt_thread_mutex_unlock( &ld->ld_res_mutex ); - ldap_pvt_thread_mutex_lock( &ld->ld_req_mutex ); -#endif - return( ld->ld_errno ); + return 0; +} + +/* + * ldap_int_bisect_delete + * + * args: + * vp: pointer to array of length *np (in/out) + * np: pointer to length of array *vp (in/out) + * id: value to delete (in) + * idx: location of value to delete (as computed by ldap_int_bisect_find()) + * + * return: + * 0: deleted + */ +int +ldap_int_bisect_delete( ber_int_t **vp, ber_len_t *np, int id, int idx ) +{ + ber_int_t *v; + ber_len_t n; + int i; + + assert( vp != NULL ); + assert( np != NULL ); + assert( *np >= 0 ); + assert( idx >= 0 ); + assert( idx < *np ); + + v = *vp; + + assert( v[ idx ] == id ); + + --(*np); + n = *np; + + for ( i = idx; i < n; i++ ) { + v[ i ] = v[ i + 1 ]; + } + + return 0; } +