https://bugs.openldap.org/show_bug.cgi?id=10026
--- Comment #16 from Ondřej Kuzník ondra@mistotebe.net --- There are multiple ways this can go wrong, but the simplest one was encoded in the script, its setup is roughly as follows, but the script is the authority:
- the bundled server A (port 1389, sid=1) has 2 direct consumers (both are slapds, B: 2389 (sid=2) and C: 3389 (sid=3)), each of which is also a provider - Server C also replicates from B - the test also operates as a client, running 3 syncrepl sessions against server C: - searchA: starts straight away (and immediately turns into persist mode, as provider has same state (=empty)) this lets us monitor C's progress - searchB: see below, this is the session that C sends confused data (missing an entry) - searchC: at the end of the test we rerun a search to make sure the provider knows its actual contents
The script has complete control over the server A and the end clients (searchA/B/C), it uses that information to drive C's state: - lets B replicate some initial state - rejects C's syncrepl sessions until it has caught up with B's, at this point we know B->C is a live persist syncrepl session and we remember the cookie we got from the monitor (searchA) - C's syncrepl session to A is allowed to start, A sends the same entries plus some more but does not end the refresh yet(*) - we now send one entry to B and observe its new cookie - once that happens, start searchB with cookie above and let it progress - we let B advance by another entry, when monitor sees it land on C, finish the refresh in the A->C session and let searchB reach expected cookie as well - we rerun the syncrepl search again (searchC) to confirm C's state
You'll see that C accepts one of the entries but never sends it to searchB so searchB desyncs.
The script outlines other failure scenarios it does not try to trigger. They would diverge after stage 3 in the script (the point where you see the asterisk (*) above): ---- 8< ---- We enter stage 3 when sid=3 reports they got the next batch of entries from sid=1 (which is a refresh) After that we can do several things (all of which would expose issues): a) let sid=2 replicate another entry. From sid=3's view, it's a persist session, so while the entry is ignored, the cookie gets committed and si_dirty cleared (bad) and passed to its consumers b) stop sid=3's session to sid=1 while in the middle of the refresh and start it with another host. That might send entries in different order (the above was a refresh, order was never guaranteed), if a consumer connected before that, ignored entries might never be seen c) restart sid=3, si_dirty will get cleared, the refresh will get entries that get ignored and consumers might again miss them """