]> git.sur5r.net Git - openldap/blobdiff - servers/slapd/result.c
ITS#3151 always reschedule consistency_check task
[openldap] / servers / slapd / result.c
index 0d84cc0576a2f07ab88a12696093d1d75885284e..af9510da362aa3dc943db83e1dd30c06dd66d322 100644 (file)
@@ -2,7 +2,7 @@
 /* $OpenLDAP$ */
 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
  *
- * Copyright 1998-2003 The OpenLDAP Foundation.
+ * Copyright 1998-2004 The OpenLDAP Foundation.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -38,7 +38,7 @@
 #include "slap.h"
 
 #ifdef LDAP_SLAPI
-#include "slapi.h"
+#include "slapi/slapi.h"
 #endif
 
 int slap_null_cb( Operation *op, SlapReply *rs )
@@ -46,6 +46,14 @@ int slap_null_cb( Operation *op, SlapReply *rs )
        return 0;
 }
 
+int slap_replog_cb( Operation *op, SlapReply *rs )
+{
+       if ( rs->sr_err == LDAP_SUCCESS ) {
+               replog( op );
+       }
+       return SLAP_CB_CONTINUE;
+}
+
 static char *v2ref( BerVarray ref, const char *text )
 {
        size_t len = 0, i = 0;
@@ -248,7 +256,7 @@ send_ldap_controls( Operation *o, BerElement *ber, LDAPControl **c )
         * plugin.
         */
 
-       if ( slapi_pblock_get( o->o_pb, SLAPI_RESCONTROLS, &sctrls ) != 0 ) {
+       if ( o->o_pb && slapi_pblock_get( o->o_pb, SLAPI_RESCONTROLS, &sctrls ) != 0 ) {
                sctrls = NULL;
        }
 
@@ -282,7 +290,7 @@ send_ldap_controls( Operation *o, BerElement *ber, LDAPControl **c )
        return rc;
 }
 
-void
+static int
 send_ldap_response(
        Operation *op,
        SlapReply *rs )
@@ -303,7 +311,7 @@ send_ldap_response(
                        op->o_callback = op->o_callback->sc_next;
                }
                op->o_callback = sc;
-               if ( rc != SLAP_CB_CONTINUE ) goto cleanup;
+               if ( rc != SLAP_CB_CONTINUE ) goto clean2;
        }
 
 #ifdef LDAP_CONNECTIONLESS
@@ -343,7 +351,7 @@ send_ldap_response(
        if (op->o_conn && op->o_conn->c_is_udp &&
                op->o_protocol == LDAP_VERSION2 )
        {
-               rc = ber_printf( ber, "t{ess" /*"}}"*/,
+               rc = ber_printf( ber, "t{ess" /*"}"*/,
                        rs->sr_tag, rs->sr_err,
                rs->sr_matched == NULL ? "" : rs->sr_matched,
                rs->sr_text == NULL ? "" : rs->sr_text );
@@ -401,7 +409,9 @@ send_ldap_response(
        }
 
 #ifdef LDAP_CONNECTIONLESS
-       if( op->o_conn && op->o_conn->c_is_udp && op->o_protocol == LDAP_VERSION2 && rc != -1 ) {
+       if( op->o_conn && op->o_conn->c_is_udp && op->o_protocol == LDAP_VERSION2
+               && rc != -1 )
+       {
                rc = ber_printf( ber, /*"{"*/ "N}" );
        }
 #endif
@@ -418,7 +428,9 @@ send_ldap_response(
 #ifdef LDAP_CONNECTIONLESS
                if (!op->o_conn || op->o_conn->c_is_udp == 0)
 #endif
-               ber_free_buf( ber );
+               {
+                       ber_free_buf( ber );
+               }
                goto cleanup;
        }
 
@@ -427,7 +439,9 @@ send_ldap_response(
 #ifdef LDAP_CONNECTIONLESS
        if (!op->o_conn || op->o_conn->c_is_udp == 0)
 #endif
-       ber_free_buf( ber );
+       {
+               ber_free_buf( ber );
+       }
 
        if ( bytes < 0 ) {
 #ifdef NEW_LOGGING
@@ -446,7 +460,8 @@ send_ldap_response(
 #ifdef LDAP_SLAPI
        if ( op->o_pb ) {
                slapi_pblock_set( op->o_pb, SLAPI_RESULT_CODE, (void *)rs->sr_err );
-               slapi_pblock_set( op->o_pb, SLAPI_RESULT_MATCHED, (void *)rs->sr_matched );
+               slapi_pblock_set( op->o_pb, SLAPI_RESULT_MATCHED,
+                       (void *)rs->sr_matched );
                slapi_pblock_set( op->o_pb, SLAPI_RESULT_TEXT, (void *)rs->sr_text );
        }
 #endif /* LDAP_SLAPI */
@@ -456,12 +471,23 @@ send_ldap_response(
        num_pdu_sent++;
        ldap_pvt_thread_mutex_unlock( &num_sent_mutex );
 
-cleanup:;
+cleanup:
+       /* Tell caller that we did this for real, as opposed to being
+        * overridden by a callback
+        */
+       rc = SLAP_CB_CONTINUE;
+
        if ( rs->sr_matched && rs->sr_flags & REP_MATCHED_MUSTBEFREED ) {
                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;
+       }
+
+clean2:
        if (op->o_callback) {
                slap_callback *sc = op->o_callback;
                for ( ; op->o_callback; op->o_callback = op->o_callback->sc_next ) {
@@ -472,7 +498,7 @@ cleanup:;
                op->o_callback = sc;
        }
 
-       return;
+       return rc;
 }
 
 
@@ -510,11 +536,12 @@ send_ldap_disconnect( Operation   *op, SlapReply *rs )
                rs->sr_msgid = 0;
        }
 
-       send_ldap_response( op, rs );
-
-       Statslog( LDAP_DEBUG_STATS,
-           "conn=%lu op=%lu DISCONNECT tag=%lu err=%d text=%s\n",
-               op->o_connid, op->o_opid, rs->sr_tag, rs->sr_err, rs->sr_text ? rs->sr_text : "" );
+       if ( send_ldap_response( op, rs ) == SLAP_CB_CONTINUE ) {
+               Statslog( LDAP_DEBUG_STATS,
+                       "conn=%lu op=%lu DISCONNECT tag=%lu err=%d text=%s\n",
+                       op->o_connid, op->o_opid, rs->sr_tag, rs->sr_err,
+                       rs->sr_text ? rs->sr_text : "" );
+       }
 }
 
 void
@@ -526,11 +553,11 @@ slap_send_ldap_result( Operation *op, SlapReply *rs )
 
        rs->sr_type = REP_RESULT;
 
-       assert( !LDAP_API_ERROR( rs->sr_err ) && ( rs->sr_err >= 0 ));
+       assert( !LDAP_API_ERROR( rs->sr_err ));
 
 #ifdef NEW_LOGGING
        LDAP_LOG( OPERATION, ENTRY, 
-               "send_ldap_result: conn %lu op=%lu p=%d\n",
+               "send_ldap_result: conn=%lu op=%lu p=%d\n",
                op->o_connid, op->o_opid, op->o_protocol );
 #else
        Debug( LDAP_DEBUG_TRACE,
@@ -585,13 +612,13 @@ slap_send_ldap_result( Operation *op, SlapReply *rs )
         * should just set SLAPI_RESULT_CODE rather than sending a
         * result if they wish to change the result.
         */
-       if ( op->o_pb ) {
+       if ( op->o_pb != NULL ) {
                slapi_int_pblock_set_operation( op->o_pb, op );
                slapi_pblock_set( op->o_pb, SLAPI_RESULT_CODE, (void *)rs->sr_err );
                slapi_pblock_set( op->o_pb, SLAPI_RESULT_TEXT, (void *)rs->sr_text );
                slapi_pblock_set( op->o_pb, SLAPI_RESULT_MATCHED, (void *)rs->sr_matched );
 
-               (void) doPluginFNs( op->o_bd, SLAPI_PLUGIN_PRE_RESULT_FN, op->o_pb );
+               (void) slapi_int_call_plugins( op->o_bd, SLAPI_PLUGIN_PRE_RESULT_FN, op->o_pb );
        }
 #endif /* LDAP_SLAPI */
 
@@ -604,22 +631,22 @@ slap_send_ldap_result( Operation *op, SlapReply *rs )
        rs->sr_tag = req2res( op->o_tag );
        rs->sr_msgid = (rs->sr_tag != LBER_SEQUENCE) ? op->o_msgid : 0;
 
-       send_ldap_response( op, rs );
+       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 );
 
-       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,
-               "conn=%lu op=%lu SEARCH RESULT tag=%lu err=%s text=%s\n",
-                       op->o_connid, op->o_opid, rs->sr_tag, nbuf,
-                       rs->sr_text ? rs->sr_text : "" );
-       } else {
-               Statslog( LDAP_DEBUG_STATS,
-                       "conn=%lu op=%lu RESULT tag=%lu err=%d text=%s\n",
-                       op->o_connid, op->o_opid, rs->sr_tag, rs->sr_err,
-                       rs->sr_text ? rs->sr_text : "" );
+                       Statslog( LDAP_DEBUG_STATS,
+                       "conn=%lu op=%lu SEARCH RESULT tag=%lu err=%s text=%s\n",
+                               op->o_connid, op->o_opid, rs->sr_tag, nbuf,
+                               rs->sr_text ? rs->sr_text : "" );
+               } else {
+                       Statslog( LDAP_DEBUG_STATS,
+                               "conn=%lu op=%lu RESULT tag=%lu err=%d text=%s\n",
+                               op->o_connid, op->o_opid, rs->sr_tag, rs->sr_err,
+                               rs->sr_text ? rs->sr_text : "" );
+               }
        }
 
        if( tmp != NULL ) ch_free(tmp);
@@ -831,15 +858,15 @@ slap_send_search_entry( Operation *op, SlapReply *rs )
                size = i * sizeof(char *) + k;
                if ( size > 0 ) {
                        char    *a_flags;
-                       e_flags = sl_calloc ( 1, i * sizeof(char *) + k, op->o_tmpmemctx );
+                       e_flags = slap_sl_calloc ( 1, i * sizeof(char *) + k, op->o_tmpmemctx );
                        if( e_flags == NULL ) {
 #ifdef NEW_LOGGING
                                LDAP_LOG( OPERATION, ERR, 
-                                       "send_search_entry: conn %lu sl_calloc failed\n",
+                                       "send_search_entry: conn %lu slap_sl_calloc failed\n",
                                        op->o_connid ? op->o_connid : 0, 0, 0 );
 #else
                        Debug( LDAP_DEBUG_ANY, 
-                                       "send_search_entry: sl_calloc failed\n", 0, 0, 0 );
+                                       "send_search_entry: slap_sl_calloc failed\n", 0, 0, 0 );
 #endif
                                ber_free( ber, 1 );
        
@@ -874,6 +901,7 @@ slap_send_search_entry( Operation *op, SlapReply *rs )
 
        for ( a = rs->sr_entry->e_attrs, j = 0; a != NULL; a = a->a_next, j++ ) {
                AttributeDescription *desc = a->a_desc;
+               int finish = 0;
 
                if ( rs->sr_attrs == NULL ) {
                        /* all attrs request, skip operational attributes */
@@ -895,39 +923,42 @@ slap_send_search_entry( Operation *op, SlapReply *rs )
                        }
                }
 
-               if ( ! access_allowed( op, rs->sr_entry, desc, NULL,
-                       ACL_READ, &acl_state ) )
-               {
+               if ( op->ors_attrsonly ) {
+                       if ( ! access_allowed( op, rs->sr_entry, desc, NULL,
+                               ACL_READ, &acl_state ) )
+                       {
 #ifdef NEW_LOGGING
-                       LDAP_LOG( ACL, INFO, 
-                               "send_search_entry: conn %lu  access to attribute %s not "
-                               "allowed\n", op->o_connid, desc->ad_cname.bv_val, 0 );
+                               LDAP_LOG( ACL, INFO, 
+                                       "send_search_entry: conn %lu  access to attribute %s not "
+                                       "allowed\n", op->o_connid, desc->ad_cname.bv_val, 0 );
 #else
-                       Debug( LDAP_DEBUG_ACL, "acl: "
-                               "access to attribute %s not allowed\n",
-                           desc->ad_cname.bv_val, 0, 0 );
+                               Debug( LDAP_DEBUG_ACL, "acl: "
+                                       "access to attribute %s not allowed\n",
+                                   desc->ad_cname.bv_val, 0, 0 );
 #endif
-                       continue;
-               }
+                               continue;
+                       }
 
-               if (( rc = ber_printf( ber, "{O[" /*]}*/ , &desc->ad_cname )) == -1 ) {
+                       if (( rc = ber_printf( ber, "{O[" /*]}*/ , &desc->ad_cname )) == -1 ) {
 #ifdef NEW_LOGGING
-                       LDAP_LOG( OPERATION, ERR, 
-                               "send_search_entry: conn %lu  ber_printf failed\n", 
-                               op->o_connid, 0, 0 );
+                               LDAP_LOG( OPERATION, ERR, 
+                                       "send_search_entry: conn %lu  ber_printf failed\n", 
+                                       op->o_connid, 0, 0 );
 #else
-                       Debug( LDAP_DEBUG_ANY, "ber_printf failed\n", 0, 0, 0 );
+                               Debug( LDAP_DEBUG_ANY, "ber_printf failed\n", 0, 0, 0 );
 #endif
 
-                       if ( op->o_res_ber == NULL ) ber_free_buf( ber );
-                       send_ldap_error( op, rs, LDAP_OTHER, "encoding description error");
-                       goto error_return;
-               }
+                               if ( op->o_res_ber == NULL ) ber_free_buf( ber );
+                               send_ldap_error( op, rs, LDAP_OTHER, "encoding description error");
+                               goto error_return;
+                       }
+                       finish = 1;
 
-               if ( ! op->ors_attrsonly ) {
-                       for ( i = 0; a->a_vals[i].bv_val != NULL; i++ ) {
+               } else {
+                       int first = 1;
+                       for ( i = 0; a->a_nvals[i].bv_val != NULL; i++ ) {
                                if ( ! access_allowed( op, rs->sr_entry,
-                                       desc, &a->a_vals[i], ACL_READ, &acl_state ) )
+                                       desc, &a->a_nvals[i], ACL_READ, &acl_state ) )
                                {
 #ifdef NEW_LOGGING
                                        LDAP_LOG( ACL, INFO, 
@@ -948,6 +979,23 @@ slap_send_search_entry( Operation *op, SlapReply *rs )
                                        continue;
                                }
 
+                               if ( first ) {
+                                       first = 0;
+                                       finish = 1;
+                                       if (( rc = ber_printf( ber, "{O[" /*]}*/ , &desc->ad_cname )) == -1 ) {
+#ifdef NEW_LOGGING
+                                               LDAP_LOG( OPERATION, ERR, 
+                                                       "send_search_entry: conn %lu  ber_printf failed\n", 
+                                                       op->o_connid, 0, 0 );
+#else
+                                               Debug( LDAP_DEBUG_ANY, "ber_printf failed\n", 0, 0, 0 );
+#endif
+
+                                               if ( op->o_res_ber == NULL ) ber_free_buf( ber );
+                                               send_ldap_error( op, rs, LDAP_OTHER, "encoding description error");
+                                               goto error_return;
+                                       }
+                               }
                                if (( rc = ber_printf( ber, "O", &a->a_vals[i] )) == -1 ) {
 #ifdef NEW_LOGGING
                                        LDAP_LOG( OPERATION, ERR, 
@@ -966,7 +1014,7 @@ slap_send_search_entry( Operation *op, SlapReply *rs )
                        }
                }
 
-               if (( rc = ber_printf( ber, /*{[*/ "]N}" )) == -1 ) {
+               if ( finish && ( rc = ber_printf( ber, /*{[*/ "]N}" )) == -1 ) {
 #ifdef NEW_LOGGING
                        LDAP_LOG( OPERATION, ERR, 
                                "send_search_entry: conn %lu ber_printf failed\n", 
@@ -1001,7 +1049,7 @@ slap_send_search_entry( Operation *op, SlapReply *rs )
                         * Reuse previous memory - we likely need less space
                         * for operational attributes
                         */
-                       tmp = sl_realloc( e_flags, i * sizeof(char *) + k,
+                       tmp = slap_sl_realloc( e_flags, i * sizeof(char *) + k,
                                op->o_tmpmemctx );
                        if ( tmp == NULL ) {
 #ifdef NEW_LOGGING
@@ -1207,7 +1255,7 @@ slap_send_search_entry( Operation *op, SlapReply *rs )
 
        /* free e_flags */
        if ( e_flags ) {
-               sl_free( e_flags, op->o_tmpmemctx );
+               slap_sl_free( e_flags, op->o_tmpmemctx );
                e_flags = NULL;
        }
 
@@ -1247,7 +1295,7 @@ slap_send_search_entry( Operation *op, SlapReply *rs )
        }
 
        if ( op->o_res_ber == NULL ) {
-               bytes = op->o_noop ? 0 : send_ldap_ber( op->o_conn, ber );
+               bytes = send_ldap_ber( op->o_conn, ber );
                ber_free_buf( ber );
 
                if ( bytes < 0 ) {
@@ -1301,7 +1349,7 @@ error_return:;
                rs->sr_flags &= ~REP_ENTRY_MUSTBEFREED;
        }
 
-       if ( e_flags ) sl_free( e_flags, op->o_tmpmemctx );
+       if ( e_flags ) slap_sl_free( e_flags, op->o_tmpmemctx );
 
        if (op->o_callback) {
                slap_callback *sc = op->o_callback;
@@ -1468,7 +1516,7 @@ slap_send_search_reference( Operation *op, SlapReply *rs )
 #ifdef LDAP_CONNECTIONLESS
        if (!op->o_conn || op->o_conn->c_is_udp == 0) {
 #endif
-       bytes = op->o_noop ? 0 : send_ldap_ber( op->o_conn, ber );
+       bytes = send_ldap_ber( op->o_conn, ber );
        ber_free_buf( ber );
 
        ldap_pvt_thread_mutex_lock( &num_sent_mutex );
@@ -1616,7 +1664,54 @@ int slap_read_controls(
        c.ldctl_oid = oid->bv_val;
        c.ldctl_iscritical = 0;
 
-       *ctrl = sl_calloc( 1, sizeof(LDAPControl), NULL );
+       *ctrl = slap_sl_calloc( 1, sizeof(LDAPControl), NULL );
        **ctrl = c;
        return LDAP_SUCCESS;
 }
+
+/* Map API errors to protocol errors... */
+int
+slap_map_api2result( SlapReply *rs )
+{
+       switch(rs->sr_err) {
+       case LDAP_SERVER_DOWN:
+               return LDAP_UNAVAILABLE;
+       case LDAP_LOCAL_ERROR:
+               return LDAP_OTHER;
+       case LDAP_ENCODING_ERROR:
+       case LDAP_DECODING_ERROR:
+               return LDAP_PROTOCOL_ERROR;
+       case LDAP_TIMEOUT:
+               return LDAP_UNAVAILABLE;
+       case LDAP_AUTH_UNKNOWN:
+               return LDAP_AUTH_METHOD_NOT_SUPPORTED;
+       case LDAP_FILTER_ERROR:
+               rs->sr_text = "Filter error";
+               return LDAP_OTHER;
+       case LDAP_USER_CANCELLED:
+               rs->sr_text = "User cancelled";
+               return LDAP_OTHER;
+       case LDAP_PARAM_ERROR:
+               return LDAP_PROTOCOL_ERROR;
+       case LDAP_NO_MEMORY:
+               return LDAP_OTHER;
+       case LDAP_CONNECT_ERROR:
+               return LDAP_UNAVAILABLE;
+       case LDAP_NOT_SUPPORTED:
+               return LDAP_UNWILLING_TO_PERFORM;
+       case LDAP_CONTROL_NOT_FOUND:
+               return LDAP_PROTOCOL_ERROR;
+       case LDAP_NO_RESULTS_RETURNED:
+               return LDAP_NO_SUCH_OBJECT;
+       case LDAP_MORE_RESULTS_TO_RETURN:
+               rs->sr_text = "More results to return";
+               return LDAP_OTHER;
+       case LDAP_CLIENT_LOOP:
+       case LDAP_REFERRAL_LIMIT_EXCEEDED:
+               return LDAP_LOOP_DETECT;
+       default:
+               if ( LDAP_API_ERROR(rs->sr_err) ) return LDAP_OTHER;
+               return rs->sr_err;
+       }
+}
+