]> git.sur5r.net Git - openldap/blobdiff - servers/slapd/result.c
ITS#6001 SID of queued CSN must match the one in the op
[openldap] / servers / slapd / result.c
index 4debc048faa269d99b0229827a2e28369085f064..0756260de04ab20c39dbb424b25379e2748c2ef1 100644 (file)
@@ -2,7 +2,7 @@
 /* $OpenLDAP$ */
 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
  *
- * Copyright 1998-2007 The OpenLDAP Foundation.
+ * Copyright 1998-2009 The OpenLDAP Foundation.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -137,28 +137,53 @@ static long send_ldap_ber(
        BerElement *ber )
 {
        ber_len_t bytes;
+       long ret = 0;
+       int closing = 0;
 
        ber_get_option( ber, LBER_OPT_BER_BYTES_TO_WRITE, &bytes );
 
        /* write only one pdu at a time - wait til it's our turn */
-       ldap_pvt_thread_mutex_lock( &conn->c_write_mutex );
+       ldap_pvt_thread_mutex_lock( &conn->c_write1_mutex );
+       if ( connection_state_closing( conn )) {
+               ldap_pvt_thread_mutex_unlock( &conn->c_write1_mutex );
+               return 0;
+       }
+       while ( conn->c_writers > 0 ) {
+               ldap_pvt_thread_cond_wait( &conn->c_write1_cv, &conn->c_write1_mutex );
+       }
+       /* connection was closed under us */
+       if ( conn->c_writers < 0 ) {
+               closing = 1;
+               /* we're the last waiter, let the closer continue */
+               if ( conn->c_writers == -1 )
+                       ldap_pvt_thread_cond_signal( &conn->c_write1_cv );
+       }
 
-       /* lock the connection */ 
-       ldap_pvt_thread_mutex_lock( &conn->c_mutex );
+       conn->c_writers++;
+
+       if ( closing ) {
+               ldap_pvt_thread_mutex_unlock( &conn->c_write1_mutex );
+               return 0;
+       }
 
        /* write the pdu */
        while( 1 ) {
                int err;
-               ber_socket_t    sd;
-
-               if ( connection_state_closing( conn ) ) {
-                       ldap_pvt_thread_mutex_unlock( &conn->c_mutex );
-                       ldap_pvt_thread_mutex_unlock( &conn->c_write_mutex );
 
-                       return 0;
+               /* lock the connection */ 
+               if ( ldap_pvt_thread_mutex_trylock( &conn->c_mutex )) {
+                       ldap_pvt_thread_mutex_unlock( &conn->c_write1_mutex );
+                       ldap_pvt_thread_mutex_lock( &conn->c_write1_mutex );
+                       if ( conn->c_writers < 0 ) {
+                               ret = 0;
+                               break;
+                       }
+                       continue;
                }
 
                if ( ber_flush2( conn->c_sb, ber, LBER_FLUSH_FREE_NEVER ) == 0 ) {
+                       ldap_pvt_thread_mutex_unlock( &conn->c_mutex );
+                       ret = bytes;
                        break;
                }
 
@@ -174,27 +199,42 @@ static long send_ldap_ber(
                    err, sock_errstr(err), 0 );
 
                if ( err != EWOULDBLOCK && err != EAGAIN ) {
+                       conn->c_writers--;
+                       ldap_pvt_thread_mutex_unlock( &conn->c_write1_mutex );
                        connection_closing( conn, "connection lost on write" );
 
                        ldap_pvt_thread_mutex_unlock( &conn->c_mutex );
-                       ldap_pvt_thread_mutex_unlock( &conn->c_write_mutex );
-
-                       return( -1 );
+                       return -1;
                }
 
                /* wait for socket to be write-ready */
+               ldap_pvt_thread_mutex_lock( &conn->c_write2_mutex );
                conn->c_writewaiter = 1;
-               ber_sockbuf_ctrl( conn->c_sb, LBER_SB_OPT_GET_FD, &sd );
-               slapd_set_write( sd, 1 );
+               slapd_set_write( conn->c_sd, 1 );
 
-               ldap_pvt_thread_cond_wait( &conn->c_write_cv, &conn->c_mutex );
+               ldap_pvt_thread_mutex_unlock( &conn->c_write1_mutex );
+               ldap_pvt_thread_mutex_unlock( &conn->c_mutex );
+               ldap_pvt_thread_cond_wait( &conn->c_write2_cv, &conn->c_write2_mutex );
                conn->c_writewaiter = 0;
+               ldap_pvt_thread_mutex_unlock( &conn->c_write2_mutex );
+               ldap_pvt_thread_mutex_lock( &conn->c_write1_mutex );
+               if ( conn->c_writers < 0 ) {
+                       ret = 0;
+                       break;
+               }
        }
 
-       ldap_pvt_thread_mutex_unlock( &conn->c_mutex );
-       ldap_pvt_thread_mutex_unlock( &conn->c_write_mutex );
+       if ( conn->c_writers < 0 ) {
+               conn->c_writers++;
+               if ( !conn->c_writers )
+                       ldap_pvt_thread_cond_signal( &conn->c_write1_cv );
+       } else {
+               conn->c_writers--;
+               ldap_pvt_thread_cond_signal( &conn->c_write1_cv );
+       }
+       ldap_pvt_thread_mutex_unlock( &conn->c_write1_mutex );
 
-       return bytes;
+       return ret;
 }
 
 static int
@@ -239,7 +279,7 @@ send_ldap_controls( Operation *o, BerElement *ber, LDAPControl **c )
                if( rc == -1 ) return rc;
        }
 
-#ifdef SLAP_SORTED_RESULTS
+#ifdef SLAP_CONTROL_X_SORTEDRESULTS
        /* this is a hack to avoid having to modify op->s_ctrls */
        if( o->o_sortedresults ) {
                BerElementBuffer berbuf;
@@ -508,10 +548,10 @@ send_ldap_response(
                goto cleanup;
        }
 
-       ldap_pvt_thread_mutex_lock( &slap_counters.sc_sent_mutex );
-       ldap_pvt_mp_add_ulong( slap_counters.sc_pdu, 1 );
-       ldap_pvt_mp_add_ulong( slap_counters.sc_bytes, (unsigned long)bytes );
-       ldap_pvt_thread_mutex_unlock( &slap_counters.sc_sent_mutex );
+       ldap_pvt_thread_mutex_lock( &op->o_counters->sc_mutex );
+       ldap_pvt_mp_add_ulong( op->o_counters->sc_pdu, 1 );
+       ldap_pvt_mp_add_ulong( op->o_counters->sc_bytes, (unsigned long)bytes );
+       ldap_pvt_thread_mutex_unlock( &op->o_counters->sc_mutex );
 
 cleanup:;
        /* Tell caller that we did this for real, as opposed to being
@@ -524,14 +564,28 @@ clean2:;
                (void)slap_cleanup_play( op, rs );
        }
 
-       if ( rs->sr_matched && rs->sr_flags & REP_MATCHED_MUSTBEFREED ) {
-               free( (char *)rs->sr_matched );
-               rs->sr_matched = NULL;
+       if ( rs->sr_flags & REP_MATCHED_MUSTBEFREED ) {
+               rs->sr_flags ^= REP_MATCHED_MUSTBEFREED; /* paranoia */
+               if ( rs->sr_matched ) {
+                       free( (char *)rs->sr_matched );
+                       rs->sr_matched = NULL;
+               }
        }
 
-       if ( rs->sr_ref && rs->sr_flags & REP_REF_MUSTBEFREED ) {
-               ber_bvarray_free( rs->sr_ref );
-               rs->sr_ref = NULL;
+       if ( rs->sr_flags & REP_REF_MUSTBEFREED ) {
+               rs->sr_flags ^= REP_REF_MUSTBEFREED; /* paranoia */
+               if ( rs->sr_ref ) {
+                       ber_bvarray_free( rs->sr_ref );
+                       rs->sr_ref = NULL;
+               }
+       }
+
+       if ( rs->sr_flags & REP_CTRLS_MUSTBEFREED ) {
+               rs->sr_flags ^= REP_CTRLS_MUSTBEFREED; /* paranoia */
+               if ( rs->sr_ctrls ) {
+                       slap_free_ctrls( op, rs->sr_ctrls );
+                       rs->sr_ctrls = NULL;
+               }
        }
 
        return rc;
@@ -562,7 +616,7 @@ send_ldap_disconnect( Operation     *op, SlapReply *rs )
        } else {
                rs->sr_rspoid = LDAP_NOTICE_DISCONNECT;
                rs->sr_tag = LDAP_RES_EXTENDED;
-               rs->sr_msgid = 0;
+               rs->sr_msgid = LDAP_RES_UNSOLICITED;
        }
 
        if ( send_ldap_response( op, rs ) == SLAP_CB_CONTINUE ) {
@@ -623,20 +677,24 @@ slap_send_ldap_result( Operation *op, SlapReply *rs )
                rs->sr_ref = NULL;
        }
 
+abandon:
        rs->sr_tag = slap_req2res( op->o_tag );
        rs->sr_msgid = (rs->sr_tag != LBER_SEQUENCE) ? op->o_msgid : 0;
 
-abandon:
+       if ( rs->sr_flags & REP_REF_MUSTBEFREED ) {
+               if ( rs->sr_ref == NULL ) {
+                       rs->sr_flags ^= REP_REF_MUSTBEFREED;
+                       ber_bvarray_free( oref );
+               }
+               oref = NULL; /* send_ldap_response() will free rs->sr_ref if != NULL */
+       }
+
        if ( send_ldap_response( op, rs ) == SLAP_CB_CONTINUE ) {
                if ( op->o_tag == LDAP_REQ_SEARCH ) {
-                       char nbuf[64];
-                       snprintf( nbuf, sizeof nbuf, "%d nentries=%d",
-                               rs->sr_err, rs->sr_nentries );
-
                        Statslog( LDAP_DEBUG_STATS,
-                       "%s SEARCH RESULT tag=%lu err=%s text=%s\n",
-                               op->o_log_prefix, rs->sr_tag, nbuf,
-                               rs->sr_text ? rs->sr_text : "", 0 );
+                               "%s SEARCH RESULT tag=%lu err=%d nentries=%d text=%s\n",
+                               op->o_log_prefix, rs->sr_tag, rs->sr_err,
+                               rs->sr_nentries, rs->sr_text ? rs->sr_text : "" );
                } else {
                        Statslog( LDAP_DEBUG_STATS,
                                "%s RESULT tag=%lu err=%d text=%s\n",
@@ -727,7 +785,6 @@ slap_send_search_entry( Operation *op, SlapReply *rs )
        BerElement      *ber = (BerElement *) &berbuf;
        Attribute       *a;
        int             i, j, rc = LDAP_UNAVAILABLE, bytes;
-       char            *edn;
        int             userattrs;
        AccessControlState acl_state = ACL_STATE_INIT;
        int                      attrsonly;
@@ -743,6 +800,13 @@ slap_send_search_entry( Operation *op, SlapReply *rs )
                return LDAP_SIZELIMIT_EXCEEDED;
        }
 
+       /* Every 64 entries, check for thread pool pause */
+       if ( ( ( rs->sr_nentries & 0x3f ) == 0x3f ) &&
+               ldap_pvt_thread_pool_pausing( &connection_pool ) > 0 )
+       {
+               return LDAP_BUSY;
+       }
+
        rs->sr_type = REP_SEARCH;
 
        /* eventually will loop through generated operational attribute types
@@ -783,8 +847,6 @@ slap_send_search_entry( Operation *op, SlapReply *rs )
                goto error_return;
        }
 
-       edn = rs->sr_entry->e_nname.bv_val;
-
        if ( op->o_res_ber ) {
                /* read back control or LDAP_CONNECTIONLESS */
            ber = op->o_res_ber;
@@ -892,12 +954,16 @@ slap_send_search_entry( Operation *op, SlapReply *rs )
                } else {
                        /* specific attrs requested */
                        if ( is_at_operational( desc->ad_type ) ) {
-                               if ( !SLAP_OPATTRS( rs->sr_attr_flags ) &&
-                                       !ad_inlist( desc, rs->sr_attrs ) )
-                               {
-                                       continue;
+                               /* if not explicitly requested */
+                               if ( !ad_inlist( desc, rs->sr_attrs )) {
+                                       /* if not all op attrs requested, skip */
+                                       if ( !SLAP_OPATTRS( rs->sr_attr_flags ))
+                                               continue;
+                                       /* if DSA-specific and replicating, skip */
+                                       if ( op->o_sync != SLAP_CONTROL_NONE &&
+                                               desc->ad_type->sat_usage == LDAP_SCHEMA_DSA_OPERATION )
+                                               continue;
                                }
-
                        } else {
                                if ( !userattrs && !ad_inlist( desc, rs->sr_attrs ) ) {
                                        continue;
@@ -1167,6 +1233,9 @@ slap_send_search_entry( Operation *op, SlapReply *rs )
                goto error_return;
        }
 
+       Statslog( LDAP_DEBUG_STATS2, "%s ENTRY dn=\"%s\"\n",
+           op->o_log_prefix, rs->sr_entry->e_nname.bv_val, 0, 0, 0 );
+
        if ( rs->sr_flags & REP_ENTRY_MUSTRELEASE ) {
                be_entry_release_rw( op, rs->sr_entry, 0 );
                rs->sr_flags ^= REP_ENTRY_MUSTRELEASE;
@@ -1187,16 +1256,13 @@ slap_send_search_entry( Operation *op, SlapReply *rs )
                }
                rs->sr_nentries++;
 
-               ldap_pvt_thread_mutex_lock( &slap_counters.sc_sent_mutex );
-               ldap_pvt_mp_add_ulong( slap_counters.sc_bytes, (unsigned long)bytes );
-               ldap_pvt_mp_add_ulong( slap_counters.sc_entries, 1 );
-               ldap_pvt_mp_add_ulong( slap_counters.sc_pdu, 1 );
-               ldap_pvt_thread_mutex_unlock( &slap_counters.sc_sent_mutex );
+               ldap_pvt_thread_mutex_lock( &op->o_counters->sc_mutex );
+               ldap_pvt_mp_add_ulong( op->o_counters->sc_bytes, (unsigned long)bytes );
+               ldap_pvt_mp_add_ulong( op->o_counters->sc_entries, 1 );
+               ldap_pvt_mp_add_ulong( op->o_counters->sc_pdu, 1 );
+               ldap_pvt_thread_mutex_unlock( &op->o_counters->sc_mutex );
        }
 
-       Statslog( LDAP_DEBUG_STATS2, "%s ENTRY dn=\"%s\"\n",
-           op->o_log_prefix, edn, 0, 0, 0 );
-
        Debug( LDAP_DEBUG_TRACE,
                "<= send_search_entry: conn %lu exit.\n", op->o_connid, 0, 0 );
 
@@ -1242,6 +1308,7 @@ slap_send_search_reference( Operation *op, SlapReply *rs )
        BerElement      *ber = (BerElement *) &berbuf;
        int rc = 0;
        int bytes;
+       char *edn = rs->sr_entry ? rs->sr_entry->e_name.bv_val : "(null)";
 
        AttributeDescription *ad_ref = slap_schema.si_ad_ref;
        AttributeDescription *ad_entry = slap_schema.si_ad_entry;
@@ -1256,7 +1323,7 @@ slap_send_search_reference( Operation *op, SlapReply *rs )
 
        Debug( LDAP_DEBUG_TRACE,
                "=> send_search_reference: dn=\"%s\"\n",
-               rs->sr_entry ? rs->sr_entry->e_name.bv_val : "(null)", 0, 0 );
+               edn, 0, 0 );
 
        if (  rs->sr_entry && ! access_allowed( op, rs->sr_entry,
                ad_entry, NULL, ACL_READ, NULL ) )
@@ -1282,7 +1349,7 @@ slap_send_search_reference( Operation *op, SlapReply *rs )
        if( op->o_domain_scope ) {
                Debug( LDAP_DEBUG_ANY,
                        "send_search_reference: domainScope control in (%s)\n", 
-                       rs->sr_entry->e_dn, 0, 0 );
+                       edn, 0, 0 );
                rc = 0;
                goto rel;
        }
@@ -1290,7 +1357,7 @@ slap_send_search_reference( Operation *op, SlapReply *rs )
        if( rs->sr_ref == NULL ) {
                Debug( LDAP_DEBUG_ANY,
                        "send_search_reference: null ref in (%s)\n", 
-                       rs->sr_entry ? rs->sr_entry->e_dn : "(null)", 0, 0 );
+                       edn, 0, 0 );
                rc = 1;
                goto rel;
        }
@@ -1340,6 +1407,7 @@ slap_send_search_reference( Operation *op, SlapReply *rs )
 
        rc = 0;
        if ( rs->sr_flags & REP_ENTRY_MUSTRELEASE ) {
+               assert( rs->sr_entry != NULL );
                be_entry_release_rw( op, rs->sr_entry, 0 );
                rs->sr_flags ^= REP_ENTRY_MUSTRELEASE;
                rs->sr_entry = NULL;
@@ -1354,11 +1422,11 @@ slap_send_search_reference( Operation *op, SlapReply *rs )
        if ( bytes < 0 ) {
                rc = LDAP_UNAVAILABLE;
        } else {
-               ldap_pvt_thread_mutex_lock( &slap_counters.sc_sent_mutex );
-               ldap_pvt_mp_add_ulong( slap_counters.sc_bytes, (unsigned long)bytes );
-               ldap_pvt_mp_add_ulong( slap_counters.sc_refs, 1 );
-               ldap_pvt_mp_add_ulong( slap_counters.sc_pdu, 1 );
-               ldap_pvt_thread_mutex_unlock( &slap_counters.sc_sent_mutex );
+               ldap_pvt_thread_mutex_lock( &op->o_counters->sc_mutex );
+               ldap_pvt_mp_add_ulong( op->o_counters->sc_bytes, (unsigned long)bytes );
+               ldap_pvt_mp_add_ulong( op->o_counters->sc_refs, 1 );
+               ldap_pvt_mp_add_ulong( op->o_counters->sc_pdu, 1 );
+               ldap_pvt_thread_mutex_unlock( &op->o_counters->sc_mutex );
        }
 #ifdef LDAP_CONNECTIONLESS
        }
@@ -1489,8 +1557,8 @@ int slap_read_controls(
        LDAPControl c;
        Operation myop;
 
-       Debug( LDAP_DEBUG_ANY, "slap_read_controls: (%s) %s\n",
-               oid->bv_val, e->e_dn, 0 );
+       Debug( LDAP_DEBUG_ANY, "%s slap_read_controls: (%s) %s\n",
+               op->o_log_prefix, oid->bv_val, e->e_dn );
 
        rs->sr_entry = e;
        rs->sr_attrs = ( oid == &slap_pre_read_bv ) ?
@@ -1515,7 +1583,7 @@ int slap_read_controls(
 
        rc = ber_flatten2( ber, &c.ldctl_value, 0 );
 
-       if( rc == LBER_ERROR ) return LDAP_OTHER;
+       if( rc == -1 ) return LDAP_OTHER;
 
        c.ldctl_oid = oid->bv_val;
        c.ldctl_iscritical = 0;
@@ -1588,9 +1656,9 @@ slap_attr_flags( AttributeName *an )
                flags |= ( SLAP_OPATTRS_NO | SLAP_USERATTRS_YES );
 
        } else {
-               flags |= an_find( an, &AllOper )
+               flags |= an_find( an, slap_bv_all_operational_attrs )
                        ? SLAP_OPATTRS_YES : SLAP_OPATTRS_NO;
-               flags |= an_find( an, &AllUser )
+               flags |= an_find( an, slap_bv_all_user_attrs )
                        ? SLAP_USERATTRS_YES : SLAP_USERATTRS_NO;
        }