From 8326ac21b1db201b88ff3bb7b2634bd26ce690e1 Mon Sep 17 00:00:00 2001 From: Pierangelo Masarati Date: Thu, 23 Nov 2006 23:50:36 +0000 Subject: [PATCH] add "report" to "onerr" modes: continue a search in case one target returns an error, and only propagate the error at the end --- doc/man/man5/slapd-meta.5 | 7 +++- servers/slapd/back-meta/back-meta.h | 7 +++- servers/slapd/back-meta/config.c | 9 ++-- servers/slapd/back-meta/search.c | 64 ++++++++++++++++++++++++++--- 4 files changed, 74 insertions(+), 13 deletions(-) diff --git a/doc/man/man5/slapd-meta.5 b/doc/man/man5/slapd-meta.5 index 02b8ce635b..fd15479b0c 100644 --- a/doc/man/man5/slapd-meta.5 +++ b/doc/man/man5/slapd-meta.5 @@ -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} diff --git a/servers/slapd/back-meta/back-meta.h b/servers/slapd/back-meta/back-meta.h index b7a8079d5b..4d367674fc 100644 --- a/servers/slapd/back-meta/back-meta.h +++ b/servers/slapd/back-meta/back-meta.h @@ -330,10 +330,13 @@ typedef struct metainfo_t { #define li_flags mi_flags /* uses flags as defined in */ #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 ) diff --git a/servers/slapd/back-meta/config.c b/servers/slapd/back-meta/config.c index 70d6a179a8..6ae4b3ba5f 100644 --- a/servers/slapd/back-meta/config.c +++ b/servers/slapd/back-meta/config.c @@ -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; } diff --git a/servers/slapd/back-meta/search.c b/servers/slapd/back-meta/search.c index c3c0eb01e1..39e886b822 100644 --- a/servers/slapd/back-meta/search.c +++ b/servers/slapd/back-meta/search.c @@ -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 );