From 23c5c1b65de70763bc4340b83ccb1e471f92984b Mon Sep 17 00:00:00 2001 From: Nathan Kinder Date: Dec 13 2010 21:22:58 +0000 Subject: Bug 621008 - parsing purge RUV from changelog at startup fails The purge RUV contains a single CSN per vector representing the last change trimmed from the changelog from each master. At shutdown this RUV is flushed to the changelog to a special entry and it's read and deleted from the changelog at startup. _cl5ReadRUV() calls ruv_init_from_bervals() which uses get_ruvelement_from_berval() on each berval that was read from the changelog's purge RUV. The problem is that get_ruvelement_from_berval() rejects any vector that doesn't have two CSNs, a minimum and a maximum. Thus, a replica that starts up is always missing a purge vector until the next time trimming occurs and the in-memory purge vector is updated. This can cause replication to continue when changes that still need to be sent to a consumer have been trimmed from the changelog. This patch sets a dummy CSN in the purge RUV, which is parsed correctly. This will cause replication to halt instead of skipping changes that have been trimmed from the changelog, which is the proper thing to do. Thanks to Ulf for contributing this patch! --- diff --git a/ldap/servers/plugins/replication/cl5_api.c b/ldap/servers/plugins/replication/cl5_api.c index b7c7229..72ebaa0 100644 --- a/ldap/servers/plugins/replication/cl5_api.c +++ b/ldap/servers/plugins/replication/cl5_api.c @@ -33,6 +33,7 @@ * * Copyright (C) 2001 Sun Microsystems, Inc. Used by permission. * Copyright (C) 2005 Red Hat, Inc. + * Copyright (C) 2010 Hewlett-Packard Development Company, L.P. * All rights reserved. * END COPYRIGHT BLOCK **/ @@ -3425,6 +3426,13 @@ static int _cl5WriteRUV (CL5DBFile *file, PRBool purge) if (purge) { + /* Set the minimum CSN of each vector to a dummy CSN that contains + * just a replica ID, e.g. 00000000000000010000. + * The minimum CSN in a purge RUV is not used so the value doesn't + * matter, but it needs to be set to something so that it can be + * flushed to changelog at shutdown and parsed at startup with the + * regular string-to-RUV parsing routines. */ + ruv_insert_dummy_min_csn(file->purgeRUV); key.data = _cl5GetHelperEntryKey (PURGE_RUV_TIME, csnStr); rc = ruv_to_bervals(file->purgeRUV, &vals); } diff --git a/ldap/servers/plugins/replication/repl5_ruv.c b/ldap/servers/plugins/replication/repl5_ruv.c index d2917ac..02f9c1b 100644 --- a/ldap/servers/plugins/replication/repl5_ruv.c +++ b/ldap/servers/plugins/replication/repl5_ruv.c @@ -33,6 +33,7 @@ * * Copyright (C) 2001 Sun Microsystems, Inc. Used by permission. * Copyright (C) 2005 Red Hat, Inc. + * Copyright (C) 2010 Hewlett-Packard Development Company, L.P. * All rights reserved. * END COPYRIGHT BLOCK **/ @@ -1946,6 +1947,26 @@ ruv_force_csn_update (RUV *ruv, CSN *csn) } } +/* This routine is used to iterate the elements in a RUV and set each vector's ++ * minimal CSN to a dummy with just the rid set, e.g. 00000000000000010000 */ +void +ruv_insert_dummy_min_csn (RUV *ruv) +{ + RUVElement *r; + int cookie; + + for (r = dl_get_first (ruv->elements, &cookie); r; + r = dl_get_next (ruv->elements, &cookie)) { + if (r->csn && !r->min_csn) { + CSN *dummycsn = csn_new(); + csn_init(dummycsn); + csn_set_replicaid(dummycsn, csn_get_replicaid(r->csn)); + r->min_csn = dummycsn; + } + } +} + + #ifdef TESTING /* Some unit tests for code in this file */ static void diff --git a/ldap/servers/plugins/replication/repl5_ruv.h b/ldap/servers/plugins/replication/repl5_ruv.h index 688f944..0a0777e 100644 --- a/ldap/servers/plugins/replication/repl5_ruv.h +++ b/ldap/servers/plugins/replication/repl5_ruv.h @@ -33,6 +33,7 @@ * * Copyright (C) 2001 Sun Microsystems, Inc. Used by permission. * Copyright (C) 2005 Red Hat, Inc. + * Copyright (C) 2010 Hewlett-Packard Development Company, L.P. * All rights reserved. * END COPYRIGHT BLOCK **/ @@ -120,6 +121,7 @@ PRBool ruv_has_csns(const RUV *ruv); PRBool ruv_has_both_csns(const RUV *ruv); PRBool ruv_is_newer (Object *sruv, Object *cruv); void ruv_force_csn_update (RUV *ruv, CSN *csn); +void ruv_insert_dummy_min_csn (RUV *ruv); #ifdef __cplusplus } #endif