1 /* abandon.c - decode and handle an ldap abandon operation */ 2 /* $OpenLDAP: pkg/ldap/servers/slapd/abandon.c,v 1.52.2.4 2008/02/11 23:26:43 kurt Exp $ */ 3 /* This work is part of OpenLDAP Software <http://www.openldap.org/>. 4 * 5 * Copyright 1998-2008 The OpenLDAP Foundation. 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted only as authorized by the OpenLDAP 10 * Public License. 11 * 12 * A copy of this license is available in the file LICENSE in the 13 * top-level directory of the distribution or, alternatively, at 14 * <http://www.OpenLDAP.org/license.html>. 15 */ 16 /* Portions Copyright (c) 1995 Regents of the University of Michigan. 17 * All rights reserved. 18 * 19 * Redistribution and use in source and binary forms are permitted 20 * provided that this notice is preserved and that due credit is given 21 * to the University of Michigan at Ann Arbor. The name of the University 22 * may not be used to endorse or promote products derived from this 23 * software without specific prior written permission. This software 24 * is provided ``as is'' without express or implied warranty. 25 */ 26 27 #include "portable.h" 28 29 #include <stdio.h> 30 #include <ac/socket.h> 31 32 #include "slap.h" 33 34 int 35 do_abandon( Operation *op, SlapReply *rs ) 36 { 37 ber_int_t id; 38 Operation *o; 39 40 Debug( LDAP_DEBUG_TRACE, "%s do_abandon\n", 41 op->o_log_prefix, 0, 0 ); 42 43 /* 44 * Parse the abandon request. It looks like this: 45 * 46 * AbandonRequest := MessageID 47 */ 48 49 if ( ber_scanf( op->o_ber, "i", &id ) == LBER_ERROR ) { 50 Debug( LDAP_DEBUG_ANY, "%s do_abandon: ber_scanf failed\n", 51 op->o_log_prefix, 0, 0 ); 52 send_ldap_discon( op, rs, LDAP_PROTOCOL_ERROR, "decoding error" ); 53 return SLAPD_DISCONNECT; 54 } 55 56 Statslog( LDAP_DEBUG_STATS, "%s ABANDON msg=%ld\n", 57 op->o_log_prefix, (long) id, 0, 0, 0 ); 58 59 if( get_ctrls( op, rs, 0 ) != LDAP_SUCCESS ) { 60 Debug( LDAP_DEBUG_ANY, "%s do_abandon: get_ctrls failed\n", 61 op->o_log_prefix, 0, 0 ); 62 return rs->sr_err; 63 } 64 65 Debug( LDAP_DEBUG_ARGS, "%s do_abandon: id=%ld\n", 66 op->o_log_prefix, (long) id, 0 ); 67 68 if( id <= 0 ) { 69 Debug( LDAP_DEBUG_ANY, "%s do_abandon: bad msgid %ld\n", 70 op->o_log_prefix, (long) id, 0 ); 71 return LDAP_SUCCESS; 72 } 73 74 ldap_pvt_thread_mutex_lock( &op->o_conn->c_mutex ); 75 /* 76 * find the operation being abandoned and set the o_abandon 77 * flag. It's up to the backend to periodically check this 78 * flag and abort the operation at a convenient time. 79 */ 80 81 LDAP_STAILQ_FOREACH( o, &op->o_conn->c_ops, o_next ) { 82 if ( o->o_msgid == id ) { 83 o->o_abandon = 1; 84 break; 85 } 86 } 87 88 if ( o ) { 89 op->orn_msgid = id; 90 91 op->o_bd = frontendDB; 92 rs->sr_err = frontendDB->be_abandon( op, rs ); 93 94 } else { 95 LDAP_STAILQ_FOREACH( o, &op->o_conn->c_pending_ops, o_next ) { 96 if ( o->o_msgid == id ) { 97 LDAP_STAILQ_REMOVE( &op->o_conn->c_pending_ops, 98 o, Operation, o_next ); 99 LDAP_STAILQ_NEXT(o, o_next) = NULL; 100 op->o_conn->c_n_ops_pending--; 101 slap_op_free( o, NULL ); 102 break; 103 } 104 } 105 } 106 107 ldap_pvt_thread_mutex_unlock( &op->o_conn->c_mutex ); 108 109 Debug( LDAP_DEBUG_TRACE, "%s do_abandon: op=%ld %sfound\n", 110 op->o_log_prefix, 111 (long) id, o ? "" : "not " ); 112 return rs->sr_err; 113 } 114 115 int 116 fe_op_abandon( Operation *op, SlapReply *rs ) 117 { 118 LDAP_STAILQ_FOREACH( op->o_bd, &backendDB, be_next ) { 119 if ( op->o_bd->be_abandon ) { 120 (void)op->o_bd->be_abandon( op, rs ); 121 } 122 } 123 124 return LDAP_SUCCESS; 125 } 126