Back to index

openldap  2.4.31
Functions
abandon.c File Reference
#include "portable.h"
#include <stdio.h>
#include <ac/stdlib.h>
#include <ac/socket.h>
#include <ac/string.h>
#include <ac/time.h>
#include "ldap-int.h"
#include "lutil.h"

Go to the source code of this file.

Functions

static int do_abandon (LDAP *ld, ber_int_t origid, ber_int_t msgid, LDAPControl **sctrls, int sendabandon)
int ldap_abandon_ext (LDAP *ld, int msgid, LDAPControl **sctrls, LDAPControl **cctrls)
int ldap_abandon (LDAP *ld, int msgid)
int ldap_pvt_discard (LDAP *ld, ber_int_t msgid)
int ldap_int_bisect_find (ber_int_t *v, ber_len_t n, ber_int_t id, int *idxp)
int ldap_int_bisect_insert (ber_int_t **vp, ber_len_t *np, int id, int idx)
int ldap_int_bisect_delete (ber_int_t **vp, ber_len_t *np, int id, int idx)

Function Documentation

static int do_abandon ( LDAP *  ld,
ber_int_t  origid,
ber_int_t  msgid,
LDAPControl **  sctrls,
int  sendabandon 
) [static]

Definition at line 121 of file abandon.c.

{
       BerElement    *ber;
       int           i, err;
       Sockbuf              *sb;
       LDAPRequest   *lr;

       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 ) {
              /* this message */
              if ( lr->lr_msgid == msgid ) {
                     break;
              }

              /* child: abandon it */
              if ( lr->lr_origid == msgid && !lr->lr_abandoned ) {
                     (void)do_abandon( ld, lr->lr_origid, lr->lr_msgid,
                            sctrls, sendabandon );

                     /* restart, as lr may now be dangling... */
                     goto start_again;
              }

              lr = lr->lr_next;
       }

       if ( lr != NULL ) {
              if ( origid == msgid && lr->lr_parent != NULL ) {
                     /* don't let caller abandon child requests! */
                     ld->ld_errno = LDAP_PARAM_ERROR;
                     return( LDAP_PARAM_ERROR );
              }
              if ( lr->lr_status != LDAP_REQST_INPROGRESS ) {
                     /* no need to send abandon message */
                     sendabandon = 0;
              }
       }

       /* ldap_msgdelete locks the res_mutex. Give up the req_mutex
        * while we're in there.
        */
       LDAP_MUTEX_UNLOCK( &ld->ld_req_mutex );
       err = ldap_msgdelete( ld, msgid );
       LDAP_MUTEX_LOCK( &ld->ld_req_mutex );
       if ( err == 0 ) {
              ld->ld_errno = LDAP_SUCCESS;
              return LDAP_SUCCESS;
       }

       /* fetch again the request that we are abandoning */
       if ( lr != NULL ) {
              for ( lr = ld->ld_requests; lr != NULL; lr = lr->lr_next ) {
                     /* this message */
                     if ( lr->lr_msgid == msgid ) {
                            break;
                     }
              }
       }

       err = 0;
       if ( sendabandon ) {
              if ( ber_sockbuf_ctrl( ld->ld_sb, LBER_SB_OPT_GET_FD, NULL ) == -1 ) {
                     /* not connected */
                     err = -1;
                     ld->ld_errno = LDAP_SERVER_DOWN;

              } else if ( ( ber = ldap_alloc_ber_with_options( ld ) ) == NULL ) {
                     /* BER element allocation failed */
                     err = -1;
                     ld->ld_errno = LDAP_NO_MEMORY;

              } else {
                     /*
                      * We already have the mutex in LDAP_R_COMPILE, so
                      * don't try to get it again.
                      *            LDAP_NEXT_MSGID(ld, i);
                      */

                     LDAP_NEXT_MSGID(ld, i);
#ifdef LDAP_CONNECTIONLESS
                     if ( LDAP_IS_UDP(ld) ) {
                            struct sockaddr sa = {0};
                            /* dummy, filled with ldo_peer in request.c */
                            err = ber_write( ber, (char *) &sa, sizeof(sa), 0 );
                     }
                     if ( LDAP_IS_UDP(ld) && ld->ld_options.ldo_version ==
                            LDAP_VERSION2 )
                     {
                            char *dn;
                            LDAP_MUTEX_LOCK( &ld->ld_options.ldo_mutex );
                            dn = ld->ld_options.ldo_cldapdn;
                            if (!dn) dn = "";
                            err = ber_printf( ber, "{isti",  /* '}' */
                                   i, dn,
                                   LDAP_REQ_ABANDON, msgid );
                            LDAP_MUTEX_UNLOCK( &ld->ld_options.ldo_mutex );
                     } else
#endif
                     {
                            /* create a message to send */
                            err = ber_printf( ber, "{iti",  /* '}' */
                                   i,
                                   LDAP_REQ_ABANDON, msgid );
                     }

                     if ( err == -1 ) {
                            /* encoding error */
                            ld->ld_errno = LDAP_ENCODING_ERROR;

                     } else {
                            /* Put Server Controls */
                            if ( ldap_int_put_controls( ld, sctrls, ber )
                                   != LDAP_SUCCESS )
                            {
                                   err = -1;

                            } else {
                                   /* close '{' */
                                   err = ber_printf( ber, /*{*/ "N}" );

                                   if ( err == -1 ) {
                                          /* encoding error */
                                          ld->ld_errno = LDAP_ENCODING_ERROR;
                                   }
                            }
                     }

                     if ( err == -1 ) {
                            ber_free( ber, 1 );

                     } else {
                            /* send the message */
                            if ( lr != NULL ) {
                                   assert( lr->lr_conn != NULL );
                                   sb = lr->lr_conn->lconn_sb;
                            } else {
                                   sb = ld->ld_sb;
                            }

                            if ( ber_flush2( sb, ber, LBER_FLUSH_FREE_ALWAYS ) != 0 ) {
                                   ld->ld_errno = LDAP_SERVER_DOWN;
                                   err = -1;
                            } else {
                                   err = 0;
                            }
                     }
              }
       }

       if ( lr != NULL ) {
              if ( sendabandon || lr->lr_status == LDAP_REQST_WRITING ) {
                     LDAP_MUTEX_LOCK( &ld->ld_conn_mutex );
                     ldap_free_connection( ld, lr->lr_conn, 0, 1 );
                     LDAP_MUTEX_UNLOCK( &ld->ld_conn_mutex );
              }

              if ( origid == msgid ) {
                     ldap_free_request( ld, lr );

              } else {
                     lr->lr_abandoned = 1;
              }
       }

       LDAP_MUTEX_LOCK( &ld->ld_abandon_mutex );

       /* use bisection */
       i = 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 );
       }

       if ( err != -1 ) {
              ld->ld_errno = LDAP_SUCCESS;
       }

       LDAP_MUTEX_UNLOCK( &ld->ld_abandon_mutex );
       return( ld->ld_errno );
}

Here is the call graph for this function:

Here is the caller graph for this function:

int ldap_abandon ( LDAP *  ld,
int  msgid 
)

Definition at line 99 of file abandon.c.

{
       Debug( LDAP_DEBUG_TRACE, "ldap_abandon %d\n", msgid, 0, 0 );
       return ldap_abandon_ext( ld, msgid, NULL, NULL ) == LDAP_SUCCESS
              ? 0 : -1;
}

Here is the call graph for this function:

Here is the caller graph for this function:

int ldap_abandon_ext ( LDAP *  ld,
int  msgid,
LDAPControl **  sctrls,
LDAPControl **  cctrls 
)

Definition at line 63 of file abandon.c.

{
       int    rc;

       Debug( LDAP_DEBUG_TRACE, "ldap_abandon_ext %d\n", msgid, 0, 0 );

       /* check client controls */
       LDAP_MUTEX_LOCK( &ld->ld_req_mutex );

       rc = ldap_int_client_controls( ld, cctrls );
       if ( rc == LDAP_SUCCESS ) {
              rc = do_abandon( ld, msgid, msgid, sctrls, 1 );
       }

       LDAP_MUTEX_UNLOCK( &ld->ld_req_mutex );

       return rc;
}

Here is the call graph for this function:

Here is the caller graph for this function:

int ldap_int_bisect_delete ( ber_int_t **  vp,
ber_len_t np,
int  id,
int  idx 
)

Definition at line 427 of file abandon.c.

{
       ber_int_t     *v;
       ber_len_t     i, n;

       assert( vp != NULL );
       assert( np != NULL );
       assert( idx >= 0 );
       assert( (unsigned) idx < *np );

       v = *vp;

       assert( v[ idx ] == id );

       --(*np);
       n = *np;

       for ( i = idx; i < n; i++ ) {
              v[ i ] = v[ i + 1 ];
       }

       return 0;
}

Here is the caller graph for this function:

int ldap_int_bisect_find ( ber_int_t *  v,
ber_len_t  n,
ber_int_t  id,
int idxp 
)

Definition at line 328 of file abandon.c.

{
       int           begin,
                     end,
                     rc = 0;

       assert( id >= 0 );

       begin = 0;
       end = n - 1;

              if ( n <= 0 || id < v[ begin ] ) {
                     *idxp = 0;

              } 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? */
                                   rc = 1;
                                   break;
                            }
                     } while ( end >= begin );
       
                     *idxp = pos;
              }

       return rc;
}

Here is the caller graph for this function:

int ldap_int_bisect_insert ( ber_int_t **  vp,
ber_len_t np,
int  id,
int  idx 
)

Definition at line 386 of file abandon.c.

{
       ber_int_t     *v;
       ber_len_t     n;
       int           i;

       assert( vp != NULL );
       assert( np != NULL );
       assert( idx >= 0 );
       assert( (unsigned) idx <= *np );

       n = *np;

       v = ber_memrealloc( *vp, sizeof( ber_int_t ) * ( n + 1 ) );
       if ( v == NULL ) {
              return -1;
       }
       *vp = v;

       for ( i = n; i > idx; i-- ) {
              v[ i ] = v[ i - 1 ];
       }
       v[ idx ] = id;
       ++(*np);

       return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

int ldap_pvt_discard ( LDAP *  ld,
ber_int_t  msgid 
)

Definition at line 108 of file abandon.c.

{
       int    rc;

       LDAP_MUTEX_LOCK( &ld->ld_req_mutex );
       rc = do_abandon( ld, msgid, msgid, NULL, 0 );
       LDAP_MUTEX_UNLOCK( &ld->ld_req_mutex );
       return rc;
}

Here is the call graph for this function:

Here is the caller graph for this function: