- /* Find the smallest CSN */
- mincsn = srs->sr_state.ctxcsn[0];
- for ( i=1; i<srs->sr_state.numcsns; i++ ) {
- if ( ber_bvcmp( &mincsn, &srs->sr_state.ctxcsn[i] ) > 0 )
- mincsn = srs->sr_state.ctxcsn[i];
- }
-
- /* If nothing has changed, shortcut it */
- if ( srs->sr_state.numcsns == numcsns ) {
- int i, j, newer;
- for ( i=0; i<srs->sr_state.numcsns; i++ ) {
- for ( j=0; j<numcsns; j++ ) {
- if ( srs->sr_state.sids[i] != sids[j] )
- continue;
- newer = ber_bvcmp( &srs->sr_state.ctxcsn[i], &ctxcsn[j] );
- /* If our state is newer, tell consumer about changes */
- if ( newer < 0 )
- changed = SS_CHANGED;
- else if ( newer > 0 ) {
- /* our state is older, tell consumer nothing */
- rs->sr_err = LDAP_SUCCESS;
+ if (srs->sr_state.numcsns != numcsns) {
+ /* consumer doesn't have the right number of CSNs */
+ changed = SS_CHANGED;
+ if ( srs->sr_state.ctxcsn ) {
+ ber_bvarray_free_x( srs->sr_state.ctxcsn, op->o_tmpmemctx );
+ srs->sr_state.ctxcsn = NULL;
+ }
+ if ( srs->sr_state.sids ) {
+ slap_sl_free( srs->sr_state.sids, op->o_tmpmemctx );
+ srs->sr_state.sids = NULL;
+ }
+ srs->sr_state.numcsns = 0;
+ goto shortcut;
+ }
+
+ /* Find the smallest CSN which differs from contextCSN */
+ mincsn.bv_len = 0;
+ maxcsn.bv_len = 0;
+ for ( i=0,j=0; i<srs->sr_state.numcsns; i++ ) {
+ int newer;
+ while ( srs->sr_state.sids[i] != sids[j] ) j++;
+ if ( BER_BVISEMPTY( &maxcsn ) || ber_bvcmp( &maxcsn,
+ &srs->sr_state.ctxcsn[i] ) < 0 ) {
+ maxcsn = srs->sr_state.ctxcsn[i];
+ maxsid = sids[j];
+ }
+ newer = ber_bvcmp( &srs->sr_state.ctxcsn[i], &ctxcsn[j] );
+ /* If our state is newer, tell consumer about changes */
+ if ( newer < 0) {
+ changed = SS_CHANGED;
+ if ( BER_BVISEMPTY( &mincsn ) || ber_bvcmp( &mincsn,
+ &srs->sr_state.ctxcsn[i] ) > 0 ) {
+ mincsn = srs->sr_state.ctxcsn[i];
+ minsid = sids[j];
+ }
+ } else if ( newer > 0 && sids[j] == slap_serverID ) {
+ /* our state is older, complain to consumer */
+ rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
+ rs->sr_text = "consumer state is newer than provider!";