1/* operation.c - routines to deal with pending ldap operations */ 2/* $OpenLDAP$ */ 3/* This work is part of OpenLDAP Software <http://www.openldap.org/>. 4 * 5 * Copyright 1998-2011 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 31#include <ac/string.h> 32#include <ac/socket.h> 33 34#include "slap.h" 35 36#ifdef LDAP_SLAPI 37#include "slapi/slapi.h" 38#endif 39 40static ldap_pvt_thread_mutex_t slap_op_mutex; 41static time_t last_time; 42static int last_incr; 43 44void slap_op_init(void) 45{ 46 ldap_pvt_thread_mutex_init( &slap_op_mutex ); 47} 48 49void slap_op_destroy(void) 50{ 51 ldap_pvt_thread_mutex_destroy( &slap_op_mutex ); 52} 53 54static void 55slap_op_q_destroy( void *key, void *data ) 56{ 57 Operation *op, *op2; 58 for ( op = data; op; op = op2 ) { 59 op2 = LDAP_STAILQ_NEXT( op, o_next ); 60 ber_memfree_x( op, NULL ); 61 } 62} 63 64void 65slap_op_groups_free( Operation *op ) 66{ 67 GroupAssertion *g, *n; 68 for ( g = op->o_groups; g; g = n ) { 69 n = g->ga_next; 70 slap_sl_free( g, op->o_tmpmemctx ); 71 } 72 op->o_groups = NULL; 73} 74 75void 76slap_op_free( Operation *op, void *ctx ) 77{ 78 OperationBuffer *opbuf; 79 80 assert( LDAP_STAILQ_NEXT(op, o_next) == NULL ); 81 82 /* paranoia */ 83 op->o_abandon = 1; 84 85 if ( op->o_ber != NULL ) { 86 ber_free( op->o_ber, 1 ); 87 } 88 if ( !BER_BVISNULL( &op->o_dn ) ) { 89 ch_free( op->o_dn.bv_val ); 90 } 91 if ( !BER_BVISNULL( &op->o_ndn ) ) { 92 ch_free( op->o_ndn.bv_val ); 93 } 94 if ( !BER_BVISNULL( &op->o_authmech ) ) { 95 ch_free( op->o_authmech.bv_val ); 96 } 97 if ( op->o_ctrls != NULL ) { 98 slap_free_ctrls( op, op->o_ctrls ); 99 } 100 101#ifdef LDAP_CONNECTIONLESS 102 if ( op->o_res_ber != NULL ) { 103 ber_free( op->o_res_ber, 1 ); 104 } 105#endif 106 107 if ( op->o_groups ) { 108 slap_op_groups_free( op ); 109 } 110 111#if defined( LDAP_SLAPI ) 112 if ( slapi_plugins_used ) { 113 slapi_int_free_object_extensions( SLAPI_X_EXT_OPERATION, op ); 114 } 115#endif /* defined( LDAP_SLAPI ) */ 116 117 if ( !BER_BVISNULL( &op->o_csn ) ) { 118 op->o_tmpfree( op->o_csn.bv_val, op->o_tmpmemctx ); 119 } 120 121 if ( op->o_pagedresults_state != NULL ) { 122 op->o_tmpfree( op->o_pagedresults_state, op->o_tmpmemctx ); 123 } 124 125 /* Selectively zero out the struct. Ignore fields that will 126 * get explicitly initialized later anyway. Keep o_abandon intact. 127 */ 128 opbuf = (OperationBuffer *) op; 129 op->o_bd = NULL; 130 BER_BVZERO( &op->o_req_dn ); 131 BER_BVZERO( &op->o_req_ndn ); 132 memset( &op->o_request, 0, sizeof( op->o_request )); 133 memset( &op->o_do_not_cache, 0, sizeof( Operation ) - offsetof( Operation, o_do_not_cache )); 134 memset( opbuf->ob_controls, 0, sizeof( opbuf->ob_controls )); 135 op->o_controls = opbuf->ob_controls; 136 137 if ( ctx ) { 138 Operation *op2 = NULL; 139 ldap_pvt_thread_pool_setkey( ctx, (void *)slap_op_free, 140 op, slap_op_q_destroy, (void **)&op2, NULL ); 141 LDAP_STAILQ_NEXT( op, o_next ) = op2; 142 if ( op2 ) { 143 op->o_tincr = op2->o_tincr + 1; 144 /* No more than 10 ops on per-thread free list */ 145 if ( op->o_tincr > 10 ) { 146 ldap_pvt_thread_pool_setkey( ctx, (void *)slap_op_free, 147 op2, slap_op_q_destroy, NULL, NULL ); 148 ber_memfree_x( op, NULL ); 149 } 150 } else { 151 op->o_tincr = 1; 152 } 153 } else { 154 ber_memfree_x( op, NULL ); 155 } 156} 157 158void 159slap_op_time(time_t *t, int *nop) 160{ 161 ldap_pvt_thread_mutex_lock( &slap_op_mutex ); 162 *t = slap_get_time(); 163 if ( *t == last_time ) { 164 *nop = ++last_incr; 165 } else { 166 last_time = *t; 167 last_incr = 0; 168 *nop = 0; 169 } 170 ldap_pvt_thread_mutex_unlock( &slap_op_mutex ); 171} 172 173Operation * 174slap_op_alloc( 175 BerElement *ber, 176 ber_int_t msgid, 177 ber_tag_t tag, 178 ber_int_t id, 179 void *ctx ) 180{ 181 Operation *op = NULL; 182 183 if ( ctx ) { 184 void *otmp = NULL; 185 ldap_pvt_thread_pool_getkey( ctx, (void *)slap_op_free, &otmp, NULL ); 186 if ( otmp ) { 187 op = otmp; 188 otmp = LDAP_STAILQ_NEXT( op, o_next ); 189 ldap_pvt_thread_pool_setkey( ctx, (void *)slap_op_free, 190 otmp, slap_op_q_destroy, NULL, NULL ); 191 op->o_abandon = 0; 192 op->o_cancel = 0; 193 } 194 } 195 if (!op) { 196 op = (Operation *) ch_calloc( 1, sizeof(OperationBuffer) ); 197 op->o_hdr = &((OperationBuffer *) op)->ob_hdr; 198 op->o_controls = ((OperationBuffer *) op)->ob_controls; 199 } 200 201 op->o_ber = ber; 202 op->o_msgid = msgid; 203 op->o_tag = tag; 204 205 slap_op_time( &op->o_time, &op->o_tincr ); 206 op->o_opid = id; 207 208#if defined( LDAP_SLAPI ) 209 if ( slapi_plugins_used ) { 210 slapi_int_create_object_extensions( SLAPI_X_EXT_OPERATION, op ); 211 } 212#endif /* defined( LDAP_SLAPI ) */ 213 214 return( op ); 215} 216 217slap_op_t 218slap_req2op( ber_tag_t tag ) 219{ 220 switch ( tag ) { 221 case LDAP_REQ_BIND: 222 return SLAP_OP_BIND; 223 case LDAP_REQ_UNBIND: 224 return SLAP_OP_UNBIND; 225 case LDAP_REQ_ADD: 226 return SLAP_OP_ADD; 227 case LDAP_REQ_DELETE: 228 return SLAP_OP_DELETE; 229 case LDAP_REQ_MODRDN: 230 return SLAP_OP_MODRDN; 231 case LDAP_REQ_MODIFY: 232 return SLAP_OP_MODIFY; 233 case LDAP_REQ_COMPARE: 234 return SLAP_OP_COMPARE; 235 case LDAP_REQ_SEARCH: 236 return SLAP_OP_SEARCH; 237 case LDAP_REQ_ABANDON: 238 return SLAP_OP_ABANDON; 239 case LDAP_REQ_EXTENDED: 240 return SLAP_OP_EXTENDED; 241 } 242 243 return SLAP_OP_LAST; 244} 245