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}
#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 )
} 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;
}
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;
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 {
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;
}
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:
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:
op->o_private = savepriv;
goto finish;
}
+ if ( META_BACK_ONERR_REPORT( mi ) ) {
+ candidates[ i ].sr_err = rs->sr_err;
+ }
break;
case META_SEARCH_BINDING:
op->o_private = savepriv;
goto finish;
}
+ if ( META_BACK_ONERR_REPORT( mi ) ) {
+ candidates[ i ].sr_err = rs->sr_err;
+ }
}
/*
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;
res = NULL;
goto finish;
}
+ if ( META_BACK_ONERR_REPORT( mi ) ) {
+ candidates[ i ].sr_err = rs->sr_err;
+ }
break;
default:
res = NULL;
goto finish;
}
+ if ( META_BACK_ONERR_REPORT( mi ) ) {
+ candidates[ i ].sr_err = rs->sr_err;
+ }
break;
}
res = NULL;
goto finish;
}
+ if ( META_BACK_ONERR_REPORT( mi ) ) {
+ candidates[ i ].sr_err = rs->sr_err;
+ }
break;
default:
/*
* 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 );