From c64e663518988afbe5c5414ebb1a06a1864cf414 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Ond=C5=99ej=20Kuzn=C3=ADk?= <ondra@mistotebe.net>
Date: Fri, 22 Apr 2022 14:14:16 +0100
Subject: [PATCH] ITS#9823 Check minCSN when setting up delta-log replay

---
 servers/slapd/overlays/syncprov.c | 59 ++++++++++++++++++++++++++-----
 1 file changed, 51 insertions(+), 8 deletions(-)

diff --git a/servers/slapd/overlays/syncprov.c b/servers/slapd/overlays/syncprov.c
index 4b6358fdd..f6ab09949 100644
--- a/servers/slapd/overlays/syncprov.c
+++ b/servers/slapd/overlays/syncprov.c
@@ -3342,7 +3336,55 @@ no_change:	if ( !(op->o_sync_mode & SLAP_SYNC_PERSIST) ) {
 					numcsns, sids, &mincsn, minsid ) ) {
 				do_present = SS_PRESENT;
 			}
+		} else if ( si->si_nopres && si->si_usehint ) {
+			/* We are instructed to trust minCSN if it exists. */
+			Entry *e;
+			Attribute *a = NULL;
+			int rc;
+
+			/*
+			 * ITS#9580 FIXME: when we've figured out and split the
+			 * sessionlog/deltalog tracking, use the appropriate attribute
+			 */
+			rc = overlay_entry_get_ov( op, &op->o_bd->be_nsuffix[0], NULL,
+					ad_minCSN, 0, &e, on );
+			if ( rc == LDAP_SUCCESS && e != NULL ) {
+				a = attr_find( e->e_attrs, ad_minCSN );
+			}
+
+			if ( a != NULL ) {
+				int *minsids;
+
+				minsids = slap_parse_csn_sids( a->a_vals, a->a_numvals, op->o_tmpmemctx );
+				slap_sort_csn_sids( a->a_vals, minsids, a->a_numvals, op->o_tmpmemctx );
+
+				for ( i=0, j=0; i < a->a_numvals; i++ ) {
+					while ( j < numcsns && minsids[i] > sids[j] ) j++;
+					if ( j < numcsns && minsids[i] == sids[j] &&
+							ber_bvcmp( &a->a_vals[i], &srs->sr_state.ctxcsn[j] ) <= 0 ) {
+						/* minCSN for this serverID is contained, keep going */
+						continue;
+					}
+					/*
+					 * Log DB's minCSN claims we can only replay from a certain
+					 * CSN for this serverID, but consumer's cookie hasn't met that
+					 * threshold: they need to refresh
+					 */
+					Debug( LDAP_DEBUG_SYNC, "%s syncprov_op_search: "
+						"consumer not within recorded mincsn for DB's mincsn=%s\n",
+						op->o_log_prefix, a->a_vals[i].bv_val );
+					rs->sr_err = LDAP_SYNC_REFRESH_REQUIRED;
+					rs->sr_text = "sync cookie is stale";
+					slap_sl_free( minsids, op->o_tmpmemctx );
+					overlay_entry_release_ov( op, e, 0, on );
+					goto bailout;
+				}
+				slap_sl_free( minsids, op->o_tmpmemctx );
+			}
+			if ( e != NULL )
+				overlay_entry_release_ov( op, e, 0, on );
 		}
+
 		/*
 		 * If sessionlog wasn't useful, see if we can find at least one entry
 		 * that hasn't changed based on the cookie.
@@ -3787,6 +3829,7 @@ sp_cf_gen(ConfigArgs *c)
 		break;
 	case SP_USEHINT:
 		si->si_usehint = c->value_int;
+		rc = syncprov_setup_accesslog();
 		break;
 	case SP_LOGDB:
 		if ( si->si_logs ) {
-- 
2.33.0

