add "report" to "onerr" modes: continue a search in case one target returns an error, and only propagate the error at the end

This commit is contained in:
Pierangelo Masarati 2006-11-23 23:50:36 +00:00
parent a06fc9cb02
commit 8326ac21b1
4 changed files with 74 additions and 13 deletions

View File

@ -115,14 +115,17 @@ illustrated for the
directive.
.TP
.B onerr {CONTINUE|stop}
.B onerr {CONTINUE|report|stop}
This directive allows to select the behavior in case an error is returned
by one target during a search.
The default, \fBcontinue\fP, consists in continuing the operation,
trying to return as much data as possible.
If this statement is set to \fBstop\fP, the search is terminated as soon
If the value is set to \fBstop\fP, the search is terminated as soon
as an error is returned by one target, and the error is immediately
propagated to the client.
If the value is set to \fBreport\fP, the search is continuated to the end
but, in case at least one target returned an error code, the first
non-success error code is returned.
.TP
.B protocol\-version {0,2,3}

View File

@ -330,10 +330,13 @@ typedef struct metainfo_t {
#define li_flags mi_flags
/* uses flags as defined in <back-ldap/back-ldap.h> */
#define META_BACK_F_ONERR_STOP (0x00010000U)
#define META_BACK_F_DEFER_ROOTDN_BIND (0x00020000U)
#define META_BACK_F_ONERR_REPORT (0x00020000U)
#define META_BACK_F_ONERR_MASK (META_BACK_F_ONERR_STOP|META_BACK_F_ONERR_REPORT)
#define META_BACK_F_DEFER_ROOTDN_BIND (0x00040000U)
#define META_BACK_ONERR_STOP(mi) ( (mi)->mi_flags & META_BACK_F_ONERR_STOP )
#define META_BACK_ONERR_CONTINUE(mi) ( !META_BACK_ONERR_CONTINUE( (mi) ) )
#define META_BACK_ONERR_REPORT(mi) ( (mi)->mi_flags & META_BACK_F_ONERR_REPORT )
#define META_BACK_ONERR_CONTINUE(mi) ( !( (mi)->mi_flags & META_BACK_F_ONERR_MASK ) )
#define META_BACK_DEFER_ROOTDN_BIND(mi) ( (mi)->mi_flags & META_BACK_F_DEFER_ROOTDN_BIND )

View File

@ -769,20 +769,23 @@ meta_back_db_config(
} else if ( strcasecmp( argv[ 0 ], "onerr" ) == 0 ) {
if ( argc != 2 ) {
Debug( LDAP_DEBUG_ANY,
"%s: line %d: \"onerr {CONTINUE|stop}\" takes 1 argument\n",
"%s: line %d: \"onerr {CONTINUE|report|stop}\" takes 1 argument\n",
fname, lineno, 0 );
return( 1 );
}
if ( strcasecmp( argv[ 1 ], "continue" ) == 0 ) {
mi->mi_flags &= ~META_BACK_F_ONERR_STOP;
mi->mi_flags &= ~META_BACK_F_ONERR_MASK;
} else if ( strcasecmp( argv[ 1 ], "stop" ) == 0 ) {
mi->mi_flags |= META_BACK_F_ONERR_STOP;
} else if ( strcasecmp( argv[ 1 ], "report" ) == 0 ) {
mi->mi_flags |= META_BACK_F_ONERR_REPORT;
} else {
Debug( LDAP_DEBUG_ANY,
"%s: line %d: \"onerr {CONTINUE|stop}\": invalid arg \"%s\".\n",
"%s: line %d: \"onerr {CONTINUE|report|stop}\": invalid arg \"%s\".\n",
fname, lineno, argv[ 1 ] );
return 1;
}

View File

@ -277,6 +277,10 @@ other:;
retcode = META_SEARCH_ERR;
} else {
if ( META_BACK_ONERR_REPORT( mi ) ) {
candidates[ candidate ].sr_err = rc;
}
retcode = META_SEARCH_NOT_CANDIDATE;
}
candidates[ candidate ].sr_msgid = META_MSGID_IGNORE;
@ -322,6 +326,9 @@ meta_search_dobind_result(
meta_back_release_conn( op, mc );
*mcp = NULL;
retcode = META_SEARCH_ERR;
} else if ( META_BACK_ONERR_REPORT( mi ) ) {
candidates[ candidate ].sr_err = rc;
}
} else {
@ -377,6 +384,9 @@ meta_back_search_start(
if ( META_BACK_ONERR_STOP( mi ) ) {
return META_SEARCH_ERR;
}
if ( META_BACK_ONERR_REPORT( mi ) ) {
candidates[ candidate ].sr_err = LDAP_OTHER;
}
candidates[ candidate ].sr_msgid = META_MSGID_IGNORE;
return META_SEARCH_NOT_CANDIDATE;
}
@ -837,6 +847,9 @@ getconn:;
op->o_private = savepriv;
goto finish;
}
if ( META_BACK_ONERR_REPORT( mi ) ) {
candidates[ i ].sr_err = rs->sr_err;
}
/* fallthru */
case META_SEARCH_NOT_CANDIDATE:
@ -865,6 +878,9 @@ getconn:;
op->o_private = savepriv;
goto finish;
}
if ( META_BACK_ONERR_REPORT( mi ) ) {
candidates[ i ].sr_err = rs->sr_err;
}
/* fallthru */
case META_SEARCH_NOT_CANDIDATE:
@ -954,6 +970,9 @@ really_bad:;
op->o_private = savepriv;
goto finish;
}
if ( META_BACK_ONERR_REPORT( mi ) ) {
candidates[ i ].sr_err = rs->sr_err;
}
break;
case META_SEARCH_BINDING:
@ -975,6 +994,9 @@ really_bad:;
op->o_private = savepriv;
goto finish;
}
if ( META_BACK_ONERR_REPORT( mi ) ) {
candidates[ i ].sr_err = rs->sr_err;
}
}
/*
@ -1131,7 +1153,7 @@ really_bad:;
0 );
if ( rs->sr_err != LDAP_SUCCESS ) {
ldap_get_option( msc->msc_ld,
LDAP_OPT_RESULT_CODE,
LDAP_OPT_ERROR_NUMBER,
&rs->sr_err );
sres = slap_map_api2result( rs );
candidates[ i ].sr_type = REP_RESULT;
@ -1252,6 +1274,9 @@ really_bad:;
res = NULL;
goto finish;
}
if ( META_BACK_ONERR_REPORT( mi ) ) {
candidates[ i ].sr_err = rs->sr_err;
}
break;
default:
@ -1264,6 +1289,9 @@ really_bad:;
res = NULL;
goto finish;
}
if ( META_BACK_ONERR_REPORT( mi ) ) {
candidates[ i ].sr_err = rs->sr_err;
}
break;
}
@ -1305,6 +1333,9 @@ really_bad:;
res = NULL;
goto finish;
}
if ( META_BACK_ONERR_REPORT( mi ) ) {
candidates[ i ].sr_err = rs->sr_err;
}
break;
default:
@ -1526,14 +1557,35 @@ really_bad:;
/*
* In case we returned at least one entry, we return LDAP_SUCCESS
* otherwise, the latter error code we got
*
* FIXME: we should handle error codes and return the more
* important/reasonable
*/
if ( sres == LDAP_SUCCESS && rs->sr_v2ref ) {
sres = LDAP_REFERRAL;
if ( sres == LDAP_SUCCESS ) {
if ( rs->sr_v2ref ) {
sres = LDAP_REFERRAL;
}
if ( META_BACK_ONERR_REPORT( mi ) ) {
/*
* Report errors, if any
*
* FIXME: we should handle error codes and return the more
* important/reasonable
*/
for ( i = 0; i < mi->mi_ntargets; i++ ) {
if ( !META_IS_CANDIDATE( &candidates[ i ] ) ) {
continue;
}
if ( candidates[ i ].sr_err != LDAP_SUCCESS
&& candidates[ i ].sr_err != LDAP_NO_SUCH_OBJECT )
{
sres = candidates[ i ].sr_err;
break;
}
}
}
}
rs->sr_err = sres;
rs->sr_matched = matched;
rs->sr_ref = ( sres == LDAP_REFERRAL ? rs->sr_v2ref : NULL );