Back to index

openldap  2.4.31
abandon.c
Go to the documentation of this file.
00001 /* abandon.c - decode and handle an ldap abandon operation */
00002 /* $OpenLDAP$ */
00003 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
00004  *
00005  * Copyright 1998-2012 The OpenLDAP Foundation.
00006  * All rights reserved.
00007  *
00008  * Redistribution and use in source and binary forms, with or without
00009  * modification, are permitted only as authorized by the OpenLDAP
00010  * Public License.
00011  *
00012  * A copy of this license is available in the file LICENSE in the
00013  * top-level directory of the distribution or, alternatively, at
00014  * <http://www.OpenLDAP.org/license.html>.
00015  */
00016 /* Portions Copyright (c) 1995 Regents of the University of Michigan.
00017  * All rights reserved.
00018  *
00019  * Redistribution and use in source and binary forms are permitted
00020  * provided that this notice is preserved and that due credit is given
00021  * to the University of Michigan at Ann Arbor. The name of the University
00022  * may not be used to endorse or promote products derived from this
00023  * software without specific prior written permission. This software
00024  * is provided ``as is'' without express or implied warranty.
00025  */
00026 
00027 #include "portable.h"
00028 
00029 #include <stdio.h>
00030 #include <ac/socket.h>
00031 
00032 #include "slap.h"
00033 
00034 int
00035 do_abandon( Operation *op, SlapReply *rs )
00036 {
00037        ber_int_t     id;
00038        Operation     *o;
00039        const char    *msg;
00040 
00041        Debug( LDAP_DEBUG_TRACE, "%s do_abandon\n",
00042               op->o_log_prefix, 0, 0 );
00043 
00044        /*
00045         * Parse the abandon request.  It looks like this:
00046         *
00047         *     AbandonRequest := MessageID
00048         */
00049 
00050        if ( ber_scanf( op->o_ber, "i", &id ) == LBER_ERROR ) {
00051               Debug( LDAP_DEBUG_ANY, "%s do_abandon: ber_scanf failed\n",
00052                      op->o_log_prefix, 0, 0 );
00053               send_ldap_discon( op, rs, LDAP_PROTOCOL_ERROR, "decoding error" );
00054               return SLAPD_DISCONNECT;
00055        }
00056 
00057        Statslog( LDAP_DEBUG_STATS, "%s ABANDON msg=%ld\n",
00058               op->o_log_prefix, (long) id, 0, 0, 0 );
00059 
00060        if( get_ctrls( op, rs, 0 ) != LDAP_SUCCESS ) {
00061               Debug( LDAP_DEBUG_ANY, "%s do_abandon: get_ctrls failed\n",
00062                      op->o_log_prefix, 0, 0 );
00063               return rs->sr_err;
00064        } 
00065 
00066        Debug( LDAP_DEBUG_ARGS, "%s do_abandon: id=%ld\n",
00067               op->o_log_prefix, (long) id, 0 );
00068 
00069        if( id <= 0 ) {
00070               Debug( LDAP_DEBUG_ANY, "%s do_abandon: bad msgid %ld\n",
00071                      op->o_log_prefix, (long) id, 0 );
00072               return LDAP_SUCCESS;
00073        }
00074 
00075        ldap_pvt_thread_mutex_lock( &op->o_conn->c_mutex );
00076 
00077        /* Find the operation being abandoned. */
00078        LDAP_STAILQ_FOREACH( o, &op->o_conn->c_ops, o_next ) {
00079               if ( o->o_msgid == id ) {
00080                      break;
00081               }
00082        }
00083 
00084        if ( o == NULL ) {
00085               msg = "not found";
00086               /* The operation is not active. Just discard it if found.  */
00087               LDAP_STAILQ_FOREACH( o, &op->o_conn->c_pending_ops, o_next ) {
00088                      if ( o->o_msgid == id ) {
00089                             msg = "discarded";
00090                             /* FIXME: This traverses c_pending_ops yet again. */
00091                             LDAP_STAILQ_REMOVE( &op->o_conn->c_pending_ops,
00092                                    o, Operation, o_next );
00093                             LDAP_STAILQ_NEXT(o, o_next) = NULL;
00094                             op->o_conn->c_n_ops_pending--;
00095                             slap_op_free( o, NULL );
00096                             break;
00097                      }
00098               }
00099 
00100        } else if ( o->o_tag == LDAP_REQ_BIND
00101                      || o->o_tag == LDAP_REQ_UNBIND
00102                      || o->o_tag == LDAP_REQ_ABANDON ) {
00103               msg = "cannot be abandoned";
00104 
00105 #if 0 /* Would break o_abandon used as "suppress response" flag, ITS#6138 */
00106        } else if ( o->o_abandon ) {
00107               msg = "already being abandoned";
00108 #endif
00109 
00110        } else {
00111               msg = "found";
00112               /* Set the o_abandon flag in the to-be-abandoned operation.
00113                * The backend can periodically check this flag and abort the
00114                * operation at a convenient time.  However it should "send"
00115                * the response anyway, with result code SLAPD_ABANDON.
00116                * The functions in result.c will intercept the message.
00117                */
00118               o->o_abandon = 1;
00119               op->orn_msgid = id;
00120               op->o_bd = frontendDB;
00121               rs->sr_err = frontendDB->be_abandon( op, rs );
00122        }
00123 
00124        ldap_pvt_thread_mutex_unlock( &op->o_conn->c_mutex );
00125 
00126        Debug( LDAP_DEBUG_TRACE, "%s do_abandon: op=%ld %s\n",
00127               op->o_log_prefix, (long) id, msg );
00128        return rs->sr_err;
00129 }
00130 
00131 int
00132 fe_op_abandon( Operation *op, SlapReply *rs )
00133 {
00134        LDAP_STAILQ_FOREACH( op->o_bd, &backendDB, be_next ) {
00135               if ( op->o_bd->be_abandon ) {
00136                      (void)op->o_bd->be_abandon( op, rs );
00137               }
00138        }
00139 
00140        return LDAP_SUCCESS;
00141 }